Fixed mouse events for fullscreen windows on Mac OS X
authorSam Lantinga <slouken@libsdl.org>
Thu, 03 Dec 2009 08:33:39 +0000
changeset 3517 e7eec78e4b92
parent 3516 72e70a8c30d5
child 3518 abefdc334970
Fixed mouse events for fullscreen windows on Mac OS X
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/cocoa/SDL_cocoaevents.m
src/video/cocoa/SDL_cocoamouse.h
src/video/cocoa/SDL_cocoamouse.m
src/video/cocoa/SDL_cocoawindow.m
--- a/src/video/SDL_sysvideo.h	Thu Dec 03 05:05:26 2009 +0000
+++ b/src/video/SDL_sysvideo.h	Thu Dec 03 08:33:39 2009 +0000
@@ -171,6 +171,7 @@
 
     int num_windows;
     SDL_Window *windows;
+    SDL_Window *fullscreen_window;
 
     SDL_Renderer *current_renderer;
 
--- a/src/video/SDL_video.c	Thu Dec 03 05:05:26 2009 +0000
+++ b/src/video/SDL_video.c	Thu Dec 03 08:33:39 2009 +0000
@@ -768,6 +768,7 @@
             SDL_DisplayMode fullscreen_mode;
             if (SDL_GetWindowDisplayMode(window->id, &fullscreen_mode) == 0) {
                 SDL_SetDisplayModeForDisplay(display, &fullscreen_mode);
+                display->fullscreen_window = window;
                 return;
             }
         }
@@ -775,6 +776,7 @@
 
     /* Nope, restore the desktop mode */
     SDL_SetDisplayModeForDisplay(display, NULL);
+    display->fullscreen_window = NULL;
 }
 
 int
--- a/src/video/cocoa/SDL_cocoaevents.m	Thu Dec 03 05:05:26 2009 +0000
+++ b/src/video/cocoa/SDL_cocoaevents.m	Thu Dec 03 08:33:39 2009 +0000
@@ -187,6 +187,20 @@
             break;
         }
         switch ([event type]) {
+        case NSLeftMouseDown:
+        case NSOtherMouseDown:
+        case NSRightMouseDown:
+        case NSLeftMouseUp:
+        case NSOtherMouseUp:
+        case NSRightMouseUp:
+        case NSLeftMouseDragged:
+        case NSRightMouseDragged:
+        case NSOtherMouseDragged: /* usually middle mouse dragged */
+        case NSMouseMoved:
+            Cocoa_HandleMouseEvent(_this, event);
+            /* Pass through to NSApp to make sure everything stays in sync */
+            [NSApp sendEvent:event];
+            break;
         case NSKeyDown:
         case NSKeyUp:
         case NSFlagsChanged:
--- a/src/video/cocoa/SDL_cocoamouse.h	Thu Dec 03 05:05:26 2009 +0000
+++ b/src/video/cocoa/SDL_cocoamouse.h	Thu Dec 03 08:33:39 2009 +0000
@@ -25,6 +25,7 @@
 #define _SDL_cocoamouse_h
 
 extern void Cocoa_InitMouse(_THIS);
+extern void Cocoa_HandleMouseEvent(_THIS, NSEvent * event);
 extern void Cocoa_QuitMouse(_THIS);
 
 #endif /* _SDL_cocoamouse_h */
--- a/src/video/cocoa/SDL_cocoamouse.m	Thu Dec 03 05:05:26 2009 +0000
+++ b/src/video/cocoa/SDL_cocoamouse.m	Thu Dec 03 08:33:39 2009 +0000
@@ -21,6 +21,7 @@
 */
 #include "SDL_config.h"
 
+#include "SDL_events.h"
 #include "SDL_cocoavideo.h"
 
 #include "../../events/SDL_mouse_c.h"
@@ -35,6 +36,87 @@
     data->mouse = SDL_AddMouse(&mouse, "Mouse", 0, 0, 1);
 }
 
+static int
+ConvertMouseButtonToSDL(int button)
+{
+    switch (button)
+    {
+        case 0:
+            return(SDL_BUTTON_LEFT);   /* 1 */
+        case 1:
+            return(SDL_BUTTON_RIGHT);  /* 3 */
+        case 2:
+            return(SDL_BUTTON_MIDDLE); /* 2 */
+    }
+    return button;
+}
+
+void
+Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
+{
+    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+    SDL_Mouse *mouse = SDL_GetMouse(data->mouse);
+    int i;
+    NSPoint point;
+    SDL_Window *window;
+
+    /* See if there are any fullscreen windows that might handle this event */
+    window = NULL;
+    for (i = 0; i < _this->num_displays; ++i) {
+        SDL_VideoDisplay *display = &_this->displays[i];
+        SDL_Window *candidate = display->fullscreen_window;
+
+        if (candidate) {
+            SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
+            NSRect rect = CGDisplayBounds(displaydata->display);
+
+            point = [NSEvent mouseLocation];
+            point.x = point.x - rect.origin.x;
+            point.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - point.y - rect.origin.y;
+            if (point.x < 0 || point.x >= candidate->w ||
+                point.y < 0 || point.y >= candidate->h) {
+                /* The mouse is out of this fullscreen display */
+                if (mouse->focus == candidate->id) {
+                    SDL_SetMouseFocus(data->mouse, 0);
+                }
+            } else {
+                /* This is it! */
+                window = candidate;
+                break;
+            }
+        }
+    }
+    if (!window) {
+        return;
+    }
+
+    /* Set the focus appropriately */
+    if (mouse->focus != window->id) {
+        SDL_SetMouseFocus(data->mouse, window->id);
+    }
+
+    switch ([event type]) {
+    case NSLeftMouseDown:
+    case NSOtherMouseDown:
+    case NSRightMouseDown:
+        SDL_SendMouseButton(data->mouse, SDL_PRESSED, ConvertMouseButtonToSDL([event buttonNumber]));
+        break;
+    case NSLeftMouseUp:
+    case NSOtherMouseUp:
+    case NSRightMouseUp:
+        SDL_SendMouseButton(data->mouse, SDL_RELEASED, ConvertMouseButtonToSDL([event buttonNumber]));
+        break;
+    case NSLeftMouseDragged:
+    case NSRightMouseDragged:
+    case NSOtherMouseDragged: /* usually middle mouse dragged */
+    case NSMouseMoved:
+        SDL_SendMouseMotion(data->mouse, 0, (int)point.x, (int)point.y, 0);
+        break;
+    default: /* just to avoid compiler warnings */
+        break;
+    }
+}
+
 void
 Cocoa_QuitMouse(_THIS)
 {
--- a/src/video/cocoa/SDL_cocoawindow.m	Thu Dec 03 05:05:26 2009 +0000
+++ b/src/video/cocoa/SDL_cocoawindow.m	Thu Dec 03 08:33:39 2009 +0000
@@ -235,17 +235,8 @@
 
     index = _data->videodata->mouse;
     mouse = SDL_GetMouse(index);
-
-    point = [NSEvent mouseLocation];
-    if ( (window->flags & SDL_WINDOW_FULLSCREEN) ) {
-        NSRect rect = CGDisplayBounds(_data->display);
-
-        point.x = point.x - rect.origin.x;
-        point.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - point.y - rect.origin.y;
-    } else {
-        point.x = point.x - window->x;
-        point.y = CGDisplayPixelsHigh(kCGDirectMainDisplay) - point.y - window->y;
-    }
+    point = [theEvent locationInWindow];
+    point.y = window->h - point.y;
     if ( point.x < 0 || point.x >= window->w ||
          point.y < 0 || point.y >= window->h ) {
         if (mouse->focus != 0) {