diff --git a/main_sdl.m b/main_sdl.m
index db6daf9..93d6606 100644
--- a/main_sdl.m
+++ b/main_sdl.m
@@ -20,6 +20,12 @@ along with this program. If not, see .
*/
#include
+#include
+
+@interface DPPCResponder : NSResponder
+@end
+
+static DPPCResponder *dppcResponder;
/** @file SDL-specific main function additions for macOS hosts. */
@@ -37,4 +43,55 @@ void remap_appkit_menu_shortcuts(void) {
}
}
}
+
+ // Add a "Grab Mouse" commamand to the Window menu.
+ NSMenuItem *windowMenuItem = [[NSApp mainMenu] itemWithTitle:@"Window"];
+ if (windowMenuItem) {
+ NSMenu *windowMenu = [windowMenuItem submenu];
+ if (windowMenu) {
+ NSMenuItem *grabMouseMenuItem = [[NSMenuItem alloc] initWithTitle:@"Grab Mouse"
+ action:@selector(grabMouse:)
+ keyEquivalent:@"g"];
+ [grabMouseMenuItem setKeyEquivalentModifierMask:NSEventModifierFlagControl];
+ [windowMenu addItem:grabMouseMenuItem];
+ }
+ }
+
+ // Insert a responder in the chain to handle the command (SDL does not
+ // expose its NSAppDelegate implementation so we can't subclass it).
+ dppcResponder = [DPPCResponder new];
+ [dppcResponder setNextResponder:[NSApp nextResponder]];
+ [NSApp setNextResponder:dppcResponder];
}
+
+@implementation DPPCResponder
+
+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
+ if ([menuItem action] == @selector(grabMouse:)) {
+ [menuItem setState:SDL_GetRelativeMouseMode() ? NSControlStateValueOn : NSControlStateValueOff];
+ return YES;
+ }
+ return [super validateMenuItem:menuItem];
+}
+
+- (void)grabMouse:(id)sender {
+ NSWindow *mainWindow = NSApp.mainWindow;
+ if (mainWindow) {
+ // If we're about to grab the mouse, move the mouse to the middle of the
+ // window so that SDL knows that this window is what we want coordinates
+ // to be relative to.
+ if (!SDL_GetRelativeMouseMode()) {
+ NSRect frame = mainWindow.frame;
+ NSPoint center = NSMakePoint(frame.size.width/2, frame.size.height/2);
+ center = [mainWindow convertPointToScreen:center];
+ CGWarpMouseCursorPosition(center);
+ mainWindow.subtitle = @"Mouse grabbed";
+ } else {
+ mainWindow.subtitle = @"";
+ }
+ }
+
+ SDL_SetRelativeMouseMode(!SDL_GetRelativeMouseMode());
+}
+
+@end