From 83b9d5c682b21d88133f24da0f94dd56bd79e687 Mon Sep 17 00:00:00 2001
From: 单军华
Date: Thu, 19 Jul 2018 13:38:55 +0800
Subject: [PATCH] change

---
 screendisplay/Pods/YYText/YYText/Component/YYTextKeyboardManager.m |  521 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 521 insertions(+), 0 deletions(-)

diff --git a/screendisplay/Pods/YYText/YYText/Component/YYTextKeyboardManager.m b/screendisplay/Pods/YYText/YYText/Component/YYTextKeyboardManager.m
new file mode 100755
index 0000000..43467bb
--- /dev/null
+++ b/screendisplay/Pods/YYText/YYText/Component/YYTextKeyboardManager.m
@@ -0,0 +1,521 @@
+//
+//  YYTextKeyboardManager.m
+//  YYText <https://github.com/ibireme/YYText>
+//
+//  Created by ibireme on 15/6/3.
+//  Copyright (c) 2015 ibireme.
+//
+//  This source code is licensed under the MIT-style license found in the
+//  LICENSE file in the root directory of this source tree.
+//
+
+#import "YYTextKeyboardManager.h"
+#import "YYTextUtilities.h"
+#import <objc/runtime.h>
+
+
+static int _YYTextKeyboardViewFrameObserverKey;
+
+/// Observer for view's frame/bounds/center/transform
+@interface _YYTextKeyboardViewFrameObserver : NSObject
+@property (nonatomic, copy) void (^notifyBlock)(UIView *keyboard);
+- (void)addToKeyboardView:(UIView *)keyboardView;
++ (instancetype)observerForView:(UIView *)keyboardView;
+@end
+
+
+@implementation _YYTextKeyboardViewFrameObserver {
+    __unsafe_unretained UIView *_keyboardView;
+}
+- (void)addToKeyboardView:(UIView *)keyboardView {
+    if (_keyboardView == keyboardView) return;
+    if (_keyboardView) {
+        [self removeFrameObserver];
+        objc_setAssociatedObject(_keyboardView, &_YYTextKeyboardViewFrameObserverKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    }
+    _keyboardView = keyboardView;
+    if (keyboardView) {
+        [self addFrameObserver];
+    }
+    objc_setAssociatedObject(keyboardView, &_YYTextKeyboardViewFrameObserverKey, self, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (void)removeFrameObserver {
+    [_keyboardView removeObserver:self forKeyPath:@"frame"];
+    [_keyboardView removeObserver:self forKeyPath:@"center"];
+    [_keyboardView removeObserver:self forKeyPath:@"bounds"];
+    [_keyboardView removeObserver:self forKeyPath:@"transform"];
+    _keyboardView = nil;
+}
+
+- (void)addFrameObserver {
+    if (!_keyboardView) return;
+    [_keyboardView addObserver:self forKeyPath:@"frame" options:kNilOptions context:NULL];
+    [_keyboardView addObserver:self forKeyPath:@"center" options:kNilOptions context:NULL];
+    [_keyboardView addObserver:self forKeyPath:@"bounds" options:kNilOptions context:NULL];
+    [_keyboardView addObserver:self forKeyPath:@"transform" options:kNilOptions context:NULL];
+}
+
+- (void)dealloc {
+    [self removeFrameObserver];
+}
+
++ (instancetype)observerForView:(UIView *)keyboardView {
+    if (!keyboardView) return nil;
+    return objc_getAssociatedObject(keyboardView, &_YYTextKeyboardViewFrameObserverKey);
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
+    
+    BOOL isPrior = [[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue];
+    if (isPrior) return;
+    
+    NSKeyValueChange changeKind = [[change objectForKey:NSKeyValueChangeKindKey] integerValue];
+    if (changeKind != NSKeyValueChangeSetting) return;
+    
+    id newVal = [change objectForKey:NSKeyValueChangeNewKey];
+    if (newVal == [NSNull null]) newVal = nil;
+    
+    if (_notifyBlock) {
+        _notifyBlock(_keyboardView);
+    }
+}
+
+@end
+
+
+
+@implementation YYTextKeyboardManager {
+    NSHashTable *_observers;
+    
+    CGRect _fromFrame;
+    BOOL _fromVisible;
+    UIInterfaceOrientation _fromOrientation;
+    
+    CGRect _notificationFromFrame;
+    CGRect _notificationToFrame;
+    NSTimeInterval _notificationDuration;
+    UIViewAnimationCurve _notificationCurve;
+    BOOL _hasNotification;
+    
+    CGRect _observedToFrame;
+    BOOL _hasObservedChange;
+    
+    BOOL _lastIsNotification;
+}
+
+- (instancetype)init {
+    @throw [NSException exceptionWithName:@"YYTextKeyboardManager init error" reason:@"Use 'defaultManager' to get instance." userInfo:nil];
+    return [super init];
+}
+
+- (instancetype)_init {
+    self = [super init];
+    _observers = [[NSHashTable alloc] initWithOptions:NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0];
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(_keyboardFrameWillChangeNotification:)
+                                                 name:UIKeyboardWillChangeFrameNotification
+                                               object:nil];
+    // for iPad (iOS 9)
+    if ([UIDevice currentDevice].systemVersion.floatValue >= 9) {
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(_keyboardFrameDidChangeNotification:)
+                                                     name:UIKeyboardDidChangeFrameNotification
+                                                   object:nil];
+    }
+    return self;
+}
+
+- (void)_initFrameObserver {
+    UIView *keyboardView = self.keyboardView;
+    if (!keyboardView) return;
+    __weak typeof(self) _self = self;
+    _YYTextKeyboardViewFrameObserver *observer = [_YYTextKeyboardViewFrameObserver observerForView:keyboardView];
+    if (!observer) {
+        observer = [_YYTextKeyboardViewFrameObserver new];
+        observer.notifyBlock = ^(UIView *keyboard) {
+            [_self _keyboardFrameChanged:keyboard];
+        };
+        [observer addToKeyboardView:keyboardView];
+    }
+}
+
+- (void)dealloc {
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
++ (instancetype)defaultManager {
+    static YYTextKeyboardManager *mgr = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        if (!YYTextIsAppExtension()) {
+            mgr = [[self alloc] _init];
+        }
+    });
+    return mgr;
+}
+
++ (void)load {
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        [self defaultManager];
+    });
+}
+
+- (void)addObserver:(id<YYTextKeyboardObserver>)observer {
+    if (!observer) return;
+    [_observers addObject:observer];
+}
+
+- (void)removeObserver:(id<YYTextKeyboardObserver>)observer {
+    if (!observer) return;
+    [_observers removeObject:observer];
+}
+
+- (UIWindow *)keyboardWindow {
+    UIApplication *app = YYTextSharedApplication();
+    if (!app) return nil;
+    
+    UIWindow *window = nil;
+    for (window in app.windows) {
+        if ([self _getKeyboardViewFromWindow:window]) return window;
+    }
+    window = app.keyWindow;
+    if ([self _getKeyboardViewFromWindow:window]) return window;
+    
+    NSMutableArray *kbWindows = nil;
+    for (window in app.windows) {
+        NSString *windowName = NSStringFromClass(window.class);
+        if ([self _systemVersion] < 9) {
+            // UITextEffectsWindow
+            if (windowName.length == 19 &&
+                [windowName hasPrefix:@"UI"] &&
+                [windowName hasSuffix:@"TextEffectsWindow"]) {
+                if (!kbWindows) kbWindows = [NSMutableArray new];
+                [kbWindows addObject:window];
+            }
+        } else {
+            // UIRemoteKeyboardWindow
+            if (windowName.length == 22 &&
+                [windowName hasPrefix:@"UI"] &&
+                [windowName hasSuffix:@"RemoteKeyboardWindow"]) {
+                if (!kbWindows) kbWindows = [NSMutableArray new];
+                [kbWindows addObject:window];
+            }
+        }
+    }
+    
+    if (kbWindows.count == 1) {
+        return kbWindows.firstObject;
+    }
+    return nil;
+}
+
+- (UIView *)keyboardView {
+    UIApplication *app = YYTextSharedApplication();
+    if (!app) return nil;
+    
+    UIWindow *window = nil;
+    UIView *view = nil;
+    for (window in app.windows) {
+        view = [self _getKeyboardViewFromWindow:window];
+        if (view) return view;
+    }
+    window = app.keyWindow;
+    view = [self _getKeyboardViewFromWindow:window];
+    if (view) return view;
+    return nil;
+}
+
+- (BOOL)isKeyboardVisible {
+    UIWindow *window = self.keyboardWindow;
+    if (!window) return NO;
+    UIView *view = self.keyboardView;
+    if (!view) return NO;
+    CGRect rect = CGRectIntersection(window.bounds, view.frame);
+    if (CGRectIsNull(rect)) return NO;
+    if (CGRectIsInfinite(rect)) return NO;
+    return rect.size.width > 0 && rect.size.height > 0;
+}
+
+- (CGRect)keyboardFrame {
+    UIView *keyboard = [self keyboardView];
+    if (!keyboard) return CGRectNull;
+    
+    CGRect frame = CGRectNull;
+    UIWindow *window = keyboard.window;
+    if (window) {
+        frame = [window convertRect:keyboard.frame toWindow:nil];
+    } else {
+        frame = keyboard.frame;
+    }
+    return frame;
+}
+
+#pragma mark - private
+
+- (double)_systemVersion {
+    static double v;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        v = [UIDevice currentDevice].systemVersion.doubleValue;
+    });
+    return v;
+}
+
+- (UIView *)_getKeyboardViewFromWindow:(UIWindow *)window {
+    /*
+     iOS 6/7:
+     UITextEffectsWindow
+        UIPeripheralHostView << keyboard
+     
+     iOS 8:
+     UITextEffectsWindow
+        UIInputSetContainerView
+            UIInputSetHostView << keyboard
+     
+     iOS 9:
+     UIRemoteKeyboardWindow
+        UIInputSetContainerView
+            UIInputSetHostView << keyboard
+     */
+    if (!window) return nil;
+    
+    // Get the window
+    NSString *windowName = NSStringFromClass(window.class);
+    if ([self _systemVersion] < 9) {
+        // UITextEffectsWindow
+        if (windowName.length != 19) return nil;
+        if (![windowName hasPrefix:@"UI"]) return nil;
+        if (![windowName hasSuffix:@"TextEffectsWindow"]) return nil;
+    } else {
+        // UIRemoteKeyboardWindow
+        if (windowName.length != 22) return nil;
+        if (![windowName hasPrefix:@"UI"]) return nil;
+        if (![windowName hasSuffix:@"RemoteKeyboardWindow"]) return nil;
+    }
+    
+    // Get the view
+    if ([self _systemVersion] < 8) {
+        // UIPeripheralHostView
+        for (UIView *view in window.subviews) {
+            NSString *viewName = NSStringFromClass(view.class);
+            if (viewName.length != 20) continue;
+            if (![viewName hasPrefix:@"UI"]) continue;
+            if (![viewName hasSuffix:@"PeripheralHostView"]) continue;
+            return view;
+        }
+    } else {
+        // UIInputSetContainerView
+        for (UIView *view in window.subviews) {
+            NSString *viewName = NSStringFromClass(view.class);
+            if (viewName.length != 23) continue;
+            if (![viewName hasPrefix:@"UI"]) continue;
+            if (![viewName hasSuffix:@"InputSetContainerView"]) continue;
+            // UIInputSetHostView
+            for (UIView *subView in view.subviews) {
+                NSString *subViewName = NSStringFromClass(subView.class);
+                if (subViewName.length != 18) continue;
+                if (![subViewName hasPrefix:@"UI"]) continue;
+                if (![subViewName hasSuffix:@"InputSetHostView"]) continue;
+                return subView;
+            }
+        }
+    }
+    
+    return nil;
+}
+
+- (void)_keyboardFrameWillChangeNotification:(NSNotification *)notif {
+    if (![notif.name isEqualToString:UIKeyboardWillChangeFrameNotification]) return;
+    NSDictionary *info = notif.userInfo;
+    if (!info) return;
+    
+    [self _initFrameObserver];
+    
+    NSValue *beforeValue = info[UIKeyboardFrameBeginUserInfoKey];
+    NSValue *afterValue = info[UIKeyboardFrameEndUserInfoKey];
+    NSNumber *curveNumber = info[UIKeyboardAnimationCurveUserInfoKey];
+    NSNumber *durationNumber = info[UIKeyboardAnimationDurationUserInfoKey];
+    
+    CGRect before = beforeValue.CGRectValue;
+    CGRect after = afterValue.CGRectValue;
+    UIViewAnimationCurve curve = curveNumber.integerValue;
+    NSTimeInterval duration = durationNumber.doubleValue;
+    
+    // ignore zero end frame
+    if (after.size.width <= 0 && after.size.height <= 0) return;
+    
+    _notificationFromFrame = before;
+    _notificationToFrame = after;
+    _notificationCurve = curve;
+    _notificationDuration = duration;
+    _hasNotification = YES;
+    _lastIsNotification = YES;
+    
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_notifyAllObservers) object:nil];
+    if (duration == 0) {
+        [self performSelector:@selector(_notifyAllObservers) withObject:nil afterDelay:0 inModes:@[NSRunLoopCommonModes]];
+    } else {
+        [self _notifyAllObservers];
+    }
+}
+
+- (void)_keyboardFrameDidChangeNotification:(NSNotification *)notif {
+    if (![notif.name isEqualToString:UIKeyboardDidChangeFrameNotification]) return;
+    NSDictionary *info = notif.userInfo;
+    if (!info) return;
+    
+    [self _initFrameObserver];
+    
+    NSValue *afterValue = info[UIKeyboardFrameEndUserInfoKey];
+    CGRect after = afterValue.CGRectValue;
+    
+    // ignore zero end frame
+    if (after.size.width <= 0 && after.size.height <= 0) return;
+    
+    _notificationToFrame = after;
+    _notificationCurve = UIViewAnimationCurveEaseInOut;
+    _notificationDuration = 0;
+    _hasNotification = YES;
+    _lastIsNotification = YES;
+    
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_notifyAllObservers) object:nil];
+    [self performSelector:@selector(_notifyAllObservers) withObject:nil afterDelay:0 inModes:@[NSRunLoopCommonModes]];
+}
+
+- (void)_keyboardFrameChanged:(UIView *)keyboard {
+    if (keyboard != self.keyboardView) return;
+    
+    UIWindow *window = keyboard.window;
+    if (window) {
+        _observedToFrame = [window convertRect:keyboard.frame toWindow:nil];
+    } else {
+        _observedToFrame = keyboard.frame;
+    }
+    _hasObservedChange = YES;
+    _lastIsNotification = NO;
+    
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_notifyAllObservers) object:nil];
+    [self performSelector:@selector(_notifyAllObservers) withObject:nil afterDelay:0 inModes:@[NSRunLoopCommonModes]];
+}
+
+- (void)_notifyAllObservers {
+    UIApplication *app = YYTextSharedApplication();
+    if (!app) return;
+    
+    UIView *keyboard = self.keyboardView;
+    UIWindow *window = keyboard.window;
+    if (!window) {
+        window = app.keyWindow;
+    }
+    if (!window) {
+        window = app.windows.firstObject;
+    }
+    
+    YYTextKeyboardTransition trans = {0};
+    
+    // from
+    if (_fromFrame.size.width == 0 && _fromFrame.size.height == 0) { // first notify
+        _fromFrame.size.width = window.bounds.size.width;
+        _fromFrame.size.height = trans.toFrame.size.height;
+        _fromFrame.origin.x = trans.toFrame.origin.x;
+        _fromFrame.origin.y = window.bounds.size.height;
+    }
+    trans.fromFrame = _fromFrame;
+    trans.fromVisible = _fromVisible;
+    
+    // to
+    if (_lastIsNotification || (_hasObservedChange && CGRectEqualToRect(_observedToFrame, _notificationToFrame))) {
+        trans.toFrame = _notificationToFrame;
+        trans.animationDuration = _notificationDuration;
+        trans.animationCurve = _notificationCurve;
+        trans.animationOption = _notificationCurve << 16;
+        
+        // Fix iPad(iOS7) keyboard frame error after rorate device when the keyboard is not docked to bottom.
+        if (((int)[self _systemVersion]) == 7) {
+            UIInterfaceOrientation ori = app.statusBarOrientation;
+            if (_fromOrientation != UIInterfaceOrientationUnknown && _fromOrientation != ori) {
+                switch (ori) {
+                    case UIInterfaceOrientationPortrait: {
+                        if (CGRectGetMaxY(trans.toFrame) != window.frame.size.height) {
+                            trans.toFrame.origin.y -= trans.toFrame.size.height;
+                        }
+                    } break;
+                    case UIInterfaceOrientationPortraitUpsideDown: {
+                        if (CGRectGetMinY(trans.toFrame) != 0) {
+                            trans.toFrame.origin.y += trans.toFrame.size.height;
+                        }
+                    } break;
+                    case UIInterfaceOrientationLandscapeLeft: {
+                        if (CGRectGetMaxX(trans.toFrame) != window.frame.size.width) {
+                            trans.toFrame.origin.x -= trans.toFrame.size.width;
+                        }
+                    } break;
+                    case UIInterfaceOrientationLandscapeRight: {
+                        if (CGRectGetMinX(trans.toFrame) != 0) {
+                            trans.toFrame.origin.x += trans.toFrame.size.width;
+                        }
+                    } break;
+                    default: break;
+                }
+            }
+        }
+    } else {
+        trans.toFrame = _observedToFrame;
+    }
+    
+    if (window && trans.toFrame.size.width > 0 && trans.toFrame.size.height > 0) {
+        CGRect rect = CGRectIntersection(window.bounds, trans.toFrame);
+        if (!CGRectIsNull(rect) && !CGRectIsEmpty(rect)) {
+            trans.toVisible = YES;
+        }
+    }
+    
+    if (!CGRectEqualToRect(trans.toFrame, _fromFrame)) {
+        for (id<YYTextKeyboardObserver> observer in _observers.copy) {
+            if ([observer respondsToSelector:@selector(keyboardChangedWithTransition:)]) {
+                [observer keyboardChangedWithTransition:trans];
+            }
+        }
+    }
+    
+    _hasNotification = NO;
+    _hasObservedChange = NO;
+    _fromFrame = trans.toFrame;
+    _fromVisible = trans.toVisible;
+    _fromOrientation = app.statusBarOrientation;
+}
+
+- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view {
+    UIApplication *app = YYTextSharedApplication();
+    if (!app) return CGRectZero;
+    
+    if (CGRectIsNull(rect)) return rect;
+    if (CGRectIsInfinite(rect)) return rect;
+    
+    UIWindow *mainWindow = app.keyWindow;
+    if (!mainWindow) mainWindow = app.windows.firstObject;
+    if (!mainWindow) { // no window ?!
+        if (view) {
+            [view convertRect:rect fromView:nil];
+        } else {
+            return rect;
+        }
+    }
+    
+    rect = [mainWindow convertRect:rect fromWindow:nil];
+    if (!view) return [mainWindow convertRect:rect toWindow:nil];
+    if (view == mainWindow) return rect;
+    
+    UIWindow *toWindow = [view isKindOfClass:[UIWindow class]] ? (id)view : view.window;
+    if (!mainWindow || !toWindow) return [mainWindow convertRect:rect toView:view];
+    if (mainWindow == toWindow) return [mainWindow convertRect:rect toView:view];
+    
+    // in different window
+    rect = [mainWindow convertRect:rect toView:mainWindow];
+    rect = [toWindow convertRect:rect fromWindow:mainWindow];
+    rect = [view convertRect:rect fromView:toWindow];
+    return rect;
+}
+
+@end

--
Gitblit v1.8.0