Implemented mouse relative mode for iOS 14.1 and newer

This commit is contained in:
Sam Lantinga 2021-07-08 07:23:29 -07:00
parent 3433f3c4cc
commit 46f19c311d
9 changed files with 80 additions and 23 deletions

0
Xcode/SDL/SDL.xcodeproj/project.pbxproj Normal file → Executable file
View File

0
build-scripts/config.guess vendored Executable file → Normal file
View File

0
build-scripts/config.sub vendored Executable file → Normal file
View File

View File

@ -31,6 +31,7 @@ extern void SDL_QuitGCKeyboard(void);
extern void SDL_InitGCMouse(void); extern void SDL_InitGCMouse(void);
extern SDL_bool SDL_HasGCMouse(void); extern SDL_bool SDL_HasGCMouse(void);
extern SDL_bool SDL_GCMouseRelativeMode(void);
extern void SDL_QuitGCMouse(void); extern void SDL_QuitGCMouse(void);
#endif /* SDL_uikitevents_h_ */ #endif /* SDL_uikitevents_h_ */

View File

@ -91,9 +91,9 @@ static void OnGCKeyboardConnected(GCKeyboard *keyboard) API_AVAILABLE(macos(11.0
SDL_SendKeyboardKey(pressed ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)keyCode); SDL_SendKeyboardKey(pressed ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)keyCode);
}; };
dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.keyboard", DISPATCH_QUEUE_SERIAL ); dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.keyboard", DISPATCH_QUEUE_SERIAL );
dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) ); dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
keyboard.handlerQueue = queue; keyboard.handlerQueue = queue;
} }
static void OnGCKeyboardDisconnected(GCKeyboard *keyboard) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) static void OnGCKeyboardDisconnected(GCKeyboard *keyboard) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
@ -182,10 +182,22 @@ void SDL_QuitGCKeyboard(void)
static int mice_connected = 0; static int mice_connected = 0;
static id mouse_connect_observer = nil; static id mouse_connect_observer = nil;
static id mouse_disconnect_observer = nil; static id mouse_disconnect_observer = nil;
static bool mouse_relative_mode = SDL_FALSE;
static void UpdateMouseGrab()
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *window;
for (window = _this->windows; window != NULL; window = window->next) {
SDL_UpdateWindowGrab(window);
}
}
static int SetGCMouseRelativeMode(SDL_bool enabled) static int SetGCMouseRelativeMode(SDL_bool enabled)
{ {
/* We'll always send relative motion and we can't warp, so nothing to do here */ mouse_relative_mode = enabled;
UpdateMouseGrab();
return 0; return 0;
} }
@ -222,14 +234,16 @@ static void OnGCMouseConnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14
mouse.mouseInput.mouseMovedHandler = ^(GCMouseInput *mouse, float deltaX, float deltaY) mouse.mouseInput.mouseMovedHandler = ^(GCMouseInput *mouse, float deltaX, float deltaY)
{ {
SDL_SendMouseMotion(SDL_GetMouseFocus(), mouseID, SDL_TRUE, (int)deltaX, -(int)deltaY); SDL_SendMouseMotion(SDL_GetMouseFocus(), mouseID, SDL_TRUE, (int)deltaX, -(int)deltaY);
}; };
dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.mouse", DISPATCH_QUEUE_SERIAL ); dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.mouse", DISPATCH_QUEUE_SERIAL );
dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) ); dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
mouse.handlerQueue = queue; mouse.handlerQueue = queue;
++mice_connected; ++mice_connected;
UpdateMouseGrab();
} }
static void OnGCMouseDisconnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) static void OnGCMouseDisconnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
@ -245,12 +259,14 @@ static void OnGCMouseDisconnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios
for (GCControllerButtonInput *button in mouse.mouseInput.auxiliaryButtons) { for (GCControllerButtonInput *button in mouse.mouseInput.auxiliaryButtons) {
button.pressedChangedHandler = nil; button.pressedChangedHandler = nil;
} }
UpdateMouseGrab();
} }
void SDL_InitGCMouse(void) void SDL_InitGCMouse(void)
{ {
@autoreleasepool { @autoreleasepool {
/* There is a bug where mouse accumulates duplicate deltas over time in iOS 14.0 */ /* There is a bug where mouse accumulates duplicate deltas over time in iOS 14.0 */
if (@available(iOS 14.1, tvOS 14.1, *)) { if (@available(iOS 14.1, tvOS 14.1, *)) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
@ -284,6 +300,11 @@ SDL_bool SDL_HasGCMouse(void)
return (mice_connected > 0); return (mice_connected > 0);
} }
SDL_bool SDL_GCMouseRelativeMode(void)
{
return mouse_relative_mode;
}
void SDL_QuitGCMouse(void) void SDL_QuitGCMouse(void)
{ {
@autoreleasepool { @autoreleasepool {
@ -320,6 +341,11 @@ SDL_bool SDL_HasGCMouse(void)
return SDL_FALSE; return SDL_FALSE;
} }
SDL_bool SDL_GCMouseRelativeMode(void)
{
return SDL_FALSE;
}
void SDL_QuitGCMouse(void) void SDL_QuitGCMouse(void)
{ {
} }

View File

@ -93,6 +93,7 @@ UIKit_CreateDevice(int devindex)
device->RaiseWindow = UIKit_RaiseWindow; device->RaiseWindow = UIKit_RaiseWindow;
device->SetWindowBordered = UIKit_SetWindowBordered; device->SetWindowBordered = UIKit_SetWindowBordered;
device->SetWindowFullscreen = UIKit_SetWindowFullscreen; device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
device->SetWindowMouseGrab = UIKit_SetWindowMouseGrab;
device->DestroyWindow = UIKit_DestroyWindow; device->DestroyWindow = UIKit_DestroyWindow;
device->GetWindowWMInfo = UIKit_GetWindowWMInfo; device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds; device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;
@ -159,8 +160,8 @@ UIKit_VideoInit(_THIS)
return -1; return -1;
} }
SDL_InitGCKeyboard(); SDL_InitGCKeyboard();
SDL_InitGCMouse(); SDL_InitGCMouse();
return 0; return 0;
} }
@ -168,8 +169,8 @@ UIKit_VideoInit(_THIS)
void void
UIKit_VideoQuit(_THIS) UIKit_VideoQuit(_THIS)
{ {
SDL_QuitGCKeyboard(); SDL_QuitGCKeyboard();
SDL_QuitGCMouse(); SDL_QuitGCMouse();
UIKit_QuitModes(_this); UIKit_QuitModes(_this);
} }

View File

@ -27,8 +27,9 @@
#include "../SDL_sysvideo.h" #include "../SDL_sysvideo.h"
#include "../../events/SDL_events_c.h" #include "../../events/SDL_events_c.h"
#import "SDL_uikitviewcontroller.h" #include "SDL_uikitviewcontroller.h"
#import "SDL_uikitmessagebox.h" #include "SDL_uikitmessagebox.h"
#include "SDL_uikitevents.h"
#include "SDL_uikitvideo.h" #include "SDL_uikitvideo.h"
#include "SDL_uikitmodes.h" #include "SDL_uikitmodes.h"
#include "SDL_uikitwindow.h" #include "SDL_uikitwindow.h"
@ -246,7 +247,20 @@ SDL_HideHomeIndicatorHintChanged(void *userdata, const char *name, const char *o
return UIRectEdgeNone; return UIRectEdgeNone;
} }
} }
#endif
- (BOOL)prefersPointerLocked
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (SDL_HasGCMouse() &&
(SDL_GCMouseRelativeMode() || _this->grabbed_window == window)) {
return YES;
} else {
return NO;
}
}
#endif /* !TARGET_OS_TV */
/* /*
---- Keyboard related functionality below this line ---- ---- Keyboard related functionality below this line ----

View File

@ -33,6 +33,7 @@ extern void UIKit_HideWindow(_THIS, SDL_Window * window);
extern void UIKit_RaiseWindow(_THIS, SDL_Window * window); extern void UIKit_RaiseWindow(_THIS, SDL_Window * window);
extern void UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered); extern void UIKit_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
extern void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen); extern void UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
extern void UIKit_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
extern void UIKit_DestroyWindow(_THIS, SDL_Window * window); extern void UIKit_DestroyWindow(_THIS, SDL_Window * window);
extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, extern SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo * info); struct SDL_SysWMinfo * info);

View File

@ -161,14 +161,14 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
@autoreleasepool { @autoreleasepool {
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata; SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
SDL_Window *other; SDL_Window *other;
/* We currently only handle a single window per display on iOS */ /* We currently only handle a single window per display on iOS */
for (other = _this->windows; other; other = other->next) { for (other = _this->windows; other; other = other->next) {
if (other != window && SDL_GetDisplayForWindow(other) == display) { if (other != window && SDL_GetDisplayForWindow(other) == display) {
return SDL_SetError("Only one window allowed per display."); return SDL_SetError("Only one window allowed per display.");
} }
} }
/* If monitor has a resolution of 0x0 (hasn't been explicitly set by the /* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
* user, so it's in standby), try to force the display to a resolution * user, so it's in standby), try to force the display to a resolution
@ -320,6 +320,20 @@ UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
} }
} }
void
UIKit_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
#if !TARGET_OS_TV
@autoreleasepool {
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
SDL_uikitviewcontroller *viewcontroller = data.viewcontroller;
if (@available(iOS 14.0, *)) {
[viewcontroller setNeedsUpdateOfPrefersPointerLocked];
}
}
#endif /* !TARGET_OS_TV */
}
void void
UIKit_DestroyWindow(_THIS, SDL_Window * window) UIKit_DestroyWindow(_THIS, SDL_Window * window)
{ {