Cleaned up the iOS text input code, fixed the orientation of the view offset when the onscreen keyboard is shown in iOS 8+, and changed UIKit_SetTextInputRect to update the view offset if the keyboard is currently visible. iOS-improvements
authorAlex Szpakowski <slime73@gmail.com>
Sun, 23 Nov 2014 23:23:47 -0400
branchiOS-improvements
changeset 9527bbd9326ecacf
parent 9526 b1e51123fbea
child 9528 6915f7db6791
Cleaned up the iOS text input code, fixed the orientation of the view offset when the onscreen keyboard is shown in iOS 8+, and changed UIKit_SetTextInputRect to update the view offset if the keyboard is currently visible.
src/video/uikit/SDL_uikitview.h
src/video/uikit/SDL_uikitview.m
     1.1 --- a/src/video/uikit/SDL_uikitview.h	Fri Nov 21 10:03:02 2014 -0400
     1.2 +++ b/src/video/uikit/SDL_uikitview.h	Sun Nov 23 23:23:47 2014 -0400
     1.3 @@ -40,7 +40,13 @@
     1.4  #if SDL_IPHONE_KEYBOARD
     1.5  - (void)showKeyboard;
     1.6  - (void)hideKeyboard;
     1.7 -- (void)initializeKeyboard;
     1.8 +- (void)initKeyboard;
     1.9 +- (void)deinitKeyboard;
    1.10 +
    1.11 +- (void)keyboardWillShow:(NSNotification *)notification;
    1.12 +- (void)keyboardWillHide:(NSNotification *)notification;
    1.13 +
    1.14 +- (void)updateKeyboard;
    1.15  
    1.16  @property (nonatomic, assign, getter=isKeyboardVisible) BOOL keyboardVisible;
    1.17  @property (nonatomic, assign) SDL_Rect textInputRect;
     2.1 --- a/src/video/uikit/SDL_uikitview.m	Fri Nov 21 10:03:02 2014 -0400
     2.2 +++ b/src/video/uikit/SDL_uikitview.m	Sun Nov 23 23:23:47 2014 -0400
     2.3 @@ -35,8 +35,6 @@
     2.4  #include "SDL_uikitmodes.h"
     2.5  #include "SDL_uikitwindow.h"
     2.6  
     2.7 -void _uikit_keyboard_init();
     2.8 -
     2.9  @implementation SDL_uikitview {
    2.10  
    2.11      SDL_TouchID touchId;
    2.12 @@ -54,7 +52,7 @@
    2.13  {
    2.14      if (self = [super initWithFrame:frame]) {
    2.15  #if SDL_IPHONE_KEYBOARD
    2.16 -        [self initializeKeyboard];
    2.17 +        [self initKeyboard];
    2.18  #endif
    2.19  
    2.20          self.multipleTouchEnabled = YES;
    2.21 @@ -67,6 +65,13 @@
    2.22  
    2.23  }
    2.24  
    2.25 +- (void)dealloc
    2.26 +{
    2.27 +#if SDL_IPHONE_KEYBOARD
    2.28 +    [self deinitKeyboard];
    2.29 +#endif
    2.30 +}
    2.31 +
    2.32  - (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize
    2.33  {
    2.34      CGPoint point = [touch locationInView:self];
    2.35 @@ -152,7 +157,7 @@
    2.36  @synthesize keyboardVisible;
    2.37  
    2.38  /* Set ourselves up as a UITextFieldDelegate */
    2.39 -- (void)initializeKeyboard
    2.40 +- (void)initKeyboard
    2.41  {
    2.42      textField = [[UITextField alloc] initWithFrame:CGRectZero];
    2.43      textField.delegate = self;
    2.44 @@ -172,8 +177,17 @@
    2.45      keyboardVisible = NO;
    2.46      /* add the UITextField (hidden) to our view */
    2.47      [self addSubview:textField];
    2.48 -    
    2.49 -    _uikit_keyboard_init();
    2.50 +
    2.51 +    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    2.52 +    [center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    2.53 +    [center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    2.54 +}
    2.55 +
    2.56 +- (void)deinitKeyboard
    2.57 +{
    2.58 +    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    2.59 +    [center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    2.60 +    [center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
    2.61  }
    2.62  
    2.63  /* reveal onscreen virtual keyboard */
    2.64 @@ -190,6 +204,71 @@
    2.65      [textField resignFirstResponder];
    2.66  }
    2.67  
    2.68 +- (void)keyboardWillShow:(NSNotification *)notification
    2.69 +{
    2.70 +    CGRect kbrect = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    2.71 +    int height;
    2.72 +
    2.73 +    /* The keyboard rect is in the coordinate space of the screen, but we want
    2.74 +     * its height in the view's coordinate space.
    2.75 +     */
    2.76 +#ifdef __IPHONE_8_0
    2.77 +    if ([self respondsToSelector:@selector(convertRect:fromCoordinateSpace:)]) {
    2.78 +        UIScreen *screen = self.window.screen;
    2.79 +        kbrect = [self convertRect:kbrect fromCoordinateSpace:screen.coordinateSpace];
    2.80 +        height = kbrect.size.height;
    2.81 +    } else
    2.82 +#endif
    2.83 +    {
    2.84 +        /* In iOS 7 and below, the screen's coordinate space is never rotated. */
    2.85 +        if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
    2.86 +            height = kbrect.size.width;
    2.87 +        } else {
    2.88 +            height = kbrect.size.height;
    2.89 +        }
    2.90 +    }
    2.91 +
    2.92 +    [self setKeyboardHeight:height];
    2.93 +}
    2.94 +
    2.95 + - (void)keyboardWillHide:(NSNotification *)notification
    2.96 +{
    2.97 +    [self setKeyboardHeight:0];
    2.98 +}
    2.99 +
   2.100 +- (void)updateKeyboard
   2.101 +{
   2.102 +    SDL_Rect textrect = self.textInputRect;
   2.103 +    CGAffineTransform t = self.transform;
   2.104 +    CGPoint offset = CGPointMake(0.0, 0.0);
   2.105 +
   2.106 +    if (self.keyboardHeight) {
   2.107 +        int rectbottom = textrect.y + textrect.h;
   2.108 +        int kbottom = self.bounds.size.height - self.keyboardHeight;
   2.109 +        if (kbottom < rectbottom) {
   2.110 +            offset.y = kbottom - rectbottom;
   2.111 +        }
   2.112 +    }
   2.113 +
   2.114 +    /* Put the offset into the this view transform's coordinate space. */
   2.115 +    t.tx = 0.0;
   2.116 +    t.ty = 0.0;
   2.117 +    offset = CGPointApplyAffineTransform(offset, t);
   2.118 +
   2.119 +    t.tx = offset.x;
   2.120 +    t.ty = offset.y;
   2.121 +
   2.122 +    /* Move the view by applying the updated transform. */
   2.123 +    self.transform = t;
   2.124 +}
   2.125 +
   2.126 +- (void)setKeyboardHeight:(int)height
   2.127 +{
   2.128 +    keyboardVisible = height > 0;
   2.129 +    keyboardHeight = height;
   2.130 +    [self updateKeyboard];
   2.131 +}
   2.132 +
   2.133  /* UITextFieldDelegate method.  Invoked when user types something. */
   2.134  - (BOOL)textField:(UITextField *)_textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
   2.135  {
   2.136 @@ -255,7 +334,8 @@
   2.137  /* iPhone keyboard addition functions */
   2.138  #if SDL_IPHONE_KEYBOARD
   2.139  
   2.140 -static SDL_uikitview * getWindowView(SDL_Window * window)
   2.141 +static SDL_uikitview *
   2.142 +GetWindowView(SDL_Window * window)
   2.143  {
   2.144      if (window == NULL) {
   2.145          SDL_SetError("Window does not exist");
   2.146 @@ -272,117 +352,46 @@
   2.147      return view;
   2.148  }
   2.149  
   2.150 -SDL_bool UIKit_HasScreenKeyboardSupport(_THIS)
   2.151 +SDL_bool
   2.152 +UIKit_HasScreenKeyboardSupport(_THIS)
   2.153  {
   2.154      return SDL_TRUE;
   2.155  }
   2.156  
   2.157 -void UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
   2.158 +void
   2.159 +UIKit_ShowScreenKeyboard(_THIS, SDL_Window *window)
   2.160  {
   2.161      @autoreleasepool {
   2.162 -        SDL_uikitview *view = getWindowView(window);
   2.163 +        SDL_uikitview *view = GetWindowView(window);
   2.164          if (view != nil) {
   2.165              [view showKeyboard];
   2.166          }
   2.167      }
   2.168  }
   2.169  
   2.170 -void UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
   2.171 +void
   2.172 +UIKit_HideScreenKeyboard(_THIS, SDL_Window *window)
   2.173  {
   2.174      @autoreleasepool {
   2.175 -        SDL_uikitview *view = getWindowView(window);
   2.176 +        SDL_uikitview *view = GetWindowView(window);
   2.177          if (view != nil) {
   2.178              [view hideKeyboard];
   2.179          }
   2.180      }
   2.181  }
   2.182  
   2.183 -SDL_bool UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
   2.184 +SDL_bool
   2.185 +UIKit_IsScreenKeyboardShown(_THIS, SDL_Window *window)
   2.186  {
   2.187      @autoreleasepool {
   2.188 -        SDL_uikitview *view = getWindowView(window);
   2.189 -        if (view == nil) {
   2.190 -            return 0;
   2.191 +        SDL_uikitview *view = GetWindowView(window);
   2.192 +        if (view != nil) {
   2.193 +            return view.isKeyboardVisible;
   2.194          }
   2.195 -
   2.196 -        return view.isKeyboardVisible;
   2.197 +        return 0;
   2.198      }
   2.199  }
   2.200  
   2.201 -
   2.202 -void _uikit_keyboard_update() {
   2.203 -    SDL_Window *window = SDL_GetFocusWindow();
   2.204 -    if (!window) { return; }
   2.205 -    SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
   2.206 -    if (!data) { return; }
   2.207 -    SDL_uikitview *view = data.view;
   2.208 -    if (!view) { return; }
   2.209 -
   2.210 -    SDL_Rect r = view.textInputRect;
   2.211 -    int height = view.keyboardHeight;
   2.212 -    int offsetx = 0;
   2.213 -    int offsety = 0;
   2.214 -    if (height) {
   2.215 -        int sw,sh;
   2.216 -        SDL_GetWindowSize(window,&sw,&sh);
   2.217 -        int bottom = (r.y + r.h);
   2.218 -        int kbottom = sh - height;
   2.219 -        if (kbottom < bottom) {
   2.220 -            offsety = kbottom-bottom;
   2.221 -        }
   2.222 -    }
   2.223 -    UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
   2.224 -    if (ui_orient == UIInterfaceOrientationLandscapeLeft) {
   2.225 -        int tmp = offsetx; offsetx = offsety; offsety = tmp;
   2.226 -    }
   2.227 -    if (ui_orient == UIInterfaceOrientationLandscapeRight) {
   2.228 -        offsety = -offsety;
   2.229 -        int tmp = offsetx; offsetx = offsety; offsety = tmp;
   2.230 -    }
   2.231 -    if (ui_orient == UIInterfaceOrientationPortraitUpsideDown) {
   2.232 -        offsety = -offsety;
   2.233 -    }
   2.234 -
   2.235 -    view.frame = CGRectMake(offsetx,offsety,view.frame.size.width,view.frame.size.height);
   2.236 -}
   2.237 -
   2.238 -void _uikit_keyboard_set_height(int height) {
   2.239 -    SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
   2.240 -    if (view == nil) {
   2.241 -        return;
   2.242 -    }
   2.243 -
   2.244 -    view.keyboardVisible = height > 0;
   2.245 -    view.keyboardHeight = height;
   2.246 -    _uikit_keyboard_update();
   2.247 -}
   2.248 -
   2.249 -void _uikit_keyboard_init() {
   2.250 -    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
   2.251 -    NSOperationQueue *queue = [NSOperationQueue mainQueue];
   2.252 -    [center addObserverForName:UIKeyboardWillShowNotification
   2.253 -                        object:nil
   2.254 -                         queue:queue
   2.255 -                    usingBlock:^(NSNotification *notification) {
   2.256 -                        int height = 0;
   2.257 -                        CGSize keyboardSize = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
   2.258 -                        height = keyboardSize.height;
   2.259 -                        UIInterfaceOrientation ui_orient = [[UIApplication sharedApplication] statusBarOrientation];
   2.260 -                        if (ui_orient == UIInterfaceOrientationLandscapeRight || ui_orient == UIInterfaceOrientationLandscapeLeft) {
   2.261 -                            height = keyboardSize.width;
   2.262 -                        }
   2.263 -                        _uikit_keyboard_set_height(height);
   2.264 -                    }
   2.265 -     ];
   2.266 -    [center addObserverForName:UIKeyboardDidHideNotification
   2.267 -                        object:nil
   2.268 -                         queue:queue
   2.269 -                    usingBlock:^(NSNotification *notification) {
   2.270 -                        _uikit_keyboard_set_height(0);
   2.271 -                    }
   2.272 -     ];
   2.273 -}
   2.274 -
   2.275  void
   2.276  UIKit_SetTextInputRect(_THIS, SDL_Rect *rect)
   2.277  {
   2.278 @@ -392,12 +401,14 @@
   2.279      }
   2.280  
   2.281      @autoreleasepool {
   2.282 -        SDL_uikitview *view = getWindowView(SDL_GetFocusWindow());
   2.283 -        if (view == nil) {
   2.284 -            return;
   2.285 +        SDL_uikitview *view = GetWindowView(SDL_GetFocusWindow());
   2.286 +        if (view != nil) {
   2.287 +            view.textInputRect = *rect;
   2.288 +
   2.289 +            if (view.keyboardVisible) {
   2.290 +                [view updateKeyboard];
   2.291 +            }
   2.292          }
   2.293 -
   2.294 -        view.textInputRect = *rect;
   2.295      }
   2.296  }
   2.297