فهرست منبع

trigger chat message with pinch gesture

kambala-decapitator/vcmi#4
Andrey Filipenkov 4 سال پیش
والد
کامیت
123fd5933e
1فایلهای تغییر یافته به همراه75 افزوده شده و 8 حذف شده
  1. 75 8
      client/SDL_uikit_main.mm

+ 75 - 8
client/SDL_uikit_main.mm

@@ -10,24 +10,46 @@
 
 #include "../Global.h"
 #include "CMT.h"
+#include "CServerHandler.h"
 #include "CFocusableHelper.h"
 
 #import <UIKit/UIKit.h>
 
 
-@interface SDLViewObserver : NSObject
+static int watchReturnKey(void * userdata, SDL_Event * event);
+
+static void sendKeyEvent(SDL_KeyCode keyCode)
+{
+    SDL_Event keyEvent;
+    keyEvent.key = (SDL_KeyboardEvent){
+        .type = SDL_KEYDOWN,
+        .keysym.sym = keyCode,
+    };
+    SDL_PushEvent(&keyEvent);
+}
+
+
+@interface SDLViewObserver : NSObject <UIGestureRecognizerDelegate>
+@property (nonatomic) bool wasChatMessageSent;
 @end
 
 @implementation SDLViewObserver
 
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
-    __auto_type longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
+    UIView * view = [object valueForKey:keyPath];
+
+    auto longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
     longPress.minimumPressDuration = 0.1;
-    longPress.delaysTouchesBegan = YES; // prevent normal clicks by SDL
-    [(UIView *)[object valueForKey:keyPath] addGestureRecognizer:longPress];
+    [view addGestureRecognizer:longPress];
+
+    auto pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
+    [view addGestureRecognizer:pinch];
 }
 
+#pragma mark - Gestures
+
 - (void)handleLongPress:(UIGestureRecognizer *)gesture {
+    // send RMB click
     SDL_EventType mouseButtonType;
     switch (gesture.state)
     {
@@ -41,14 +63,14 @@
             return;
     }
 
-    __auto_type renderer = SDL_GetRenderer(mainWindow);
+    auto renderer = SDL_GetRenderer(mainWindow);
     float scaleX, scaleY;
     SDL_Rect viewport;
     SDL_RenderGetScale(renderer, &scaleX, &scaleY);
     SDL_RenderGetViewport(renderer, &viewport);
 
-    __auto_type touchedPoint = [gesture locationInView:gesture.view];
-    __auto_type screenScale = UIScreen.mainScreen.nativeScale;
+    auto touchedPoint = [gesture locationInView:gesture.view];
+    auto screenScale = UIScreen.mainScreen.nativeScale;
     Sint32 x = (int)touchedPoint.x * screenScale / scaleX - viewport.x;
     Sint32 y = (int)touchedPoint.y * screenScale / scaleY - viewport.y;
 
@@ -75,6 +97,40 @@
         });
 }
 
+- (void)handlePinch:(UIGestureRecognizer *)gesture {
+    if(gesture.state != UIGestureRecognizerStateBegan || CSH->state != EClientState::GAMEPLAY)
+        return;
+
+    // Tab triggers chat message input
+    self.wasChatMessageSent = false;
+    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleKeyboardDidShowForGameChat:) name:UIKeyboardDidShowNotification object:nil];
+    sendKeyEvent(SDLK_TAB);
+}
+
+#pragma mark - Notifications
+
+- (void)handleKeyboardDidShowForGameChat:(NSNotification *)n {
+    [NSNotificationCenter.defaultCenter removeObserver:self name:n.name object:nil];
+
+    // watch for pressing Return to ignore sending Escape key after keyboard is closed
+    SDL_AddEventWatch(watchReturnKey, (__bridge void *)self);
+    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleKeyboardDidHideForGameChat:) name:UIKeyboardDidHideNotification object:nil];
+}
+
+- (void)handleKeyboardDidHideForGameChat:(NSNotification *)n {
+    [NSNotificationCenter.defaultCenter removeObserver:self name:n.name object:nil];
+
+    // discard chat message
+    if(!self.wasChatMessageSent)
+        sendKeyEvent(SDLK_ESCAPE);
+}
+
+#pragma mark - UIGestureRecognizerDelegate
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
+    return [gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]];
+}
+
 @end
 
 
@@ -87,7 +143,7 @@ main(int argc, char *argv[])
 {
     @autoreleasepool
     {
-        __auto_type observer = [SDLViewObserver new];
+        auto observer = [SDLViewObserver new];
         [NSNotificationCenter.defaultCenter addObserverForName:UIWindowDidBecomeKeyNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
             [UIApplication.sharedApplication.keyWindow.rootViewController addObserver:observer forKeyPath:NSStringFromSelector(@selector(view)) options:NSKeyValueObservingOptionNew context:NULL];
         }];
@@ -97,3 +153,14 @@ main(int argc, char *argv[])
         return SDL_UIKitRunApp(argc, argv, SDL_main);
     }
 }
+
+static int watchReturnKey(void * userdata, SDL_Event * event)
+{
+    if(event->type == SDL_KEYDOWN && event->key.keysym.scancode == SDL_SCANCODE_RETURN)
+    {
+        auto self = (__bridge SDLViewObserver *)userdata;
+        self.wasChatMessageSent = true;
+        SDL_DelEventWatch(watchReturnKey, userdata);
+    }
+    return 1;
+}