From 61f75b50f5e14eb6567973a90be916d93266ec74 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 19 Aug 2001 23:57:39 +0000 Subject: [PATCH] Date: Thu, 16 Aug 2001 21:50:51 -0500 (EST) From: Darrell Walisser Subject: Patch for video bugs + Max's additions I've attached a patch for today's CVS that includes Max's virtual mouse button fix as well as some other changes: -building mode list correctly now (had duplicate entries, was unsorted) -switching modes correctly now (wasn't destroying previous mode) -releasing memory correctly in event loop --- src/video/maccommon/SDL_macevents.c | 39 ++++++------ src/video/quartz/SDL_QuartzEvents.m | 33 ++++++---- src/video/quartz/SDL_QuartzVideo.h | 4 +- src/video/quartz/SDL_QuartzVideo.m | 94 +++++++++++++++++++++-------- 4 files changed, 110 insertions(+), 60 deletions(-) diff --git a/src/video/maccommon/SDL_macevents.c b/src/video/maccommon/SDL_macevents.c index 362081e13..ca72d96d5 100644 --- a/src/video/maccommon/SDL_macevents.c +++ b/src/video/maccommon/SDL_macevents.c @@ -107,6 +107,7 @@ static void myGlobalToLocal(_THIS, Point *pt) /* The main MacOS event handler */ static int Mac_HandleEvents(_THIS, int wait4it) { + static int mouse_button = 1; int i; EventRecord event; @@ -148,7 +149,7 @@ static int Mac_HandleEvents(_THIS, int wait4it) /* for some reason, event.where isn't set ? */ GetGlobalMouse ( &event.where ); #endif - + /* Check for mouse motion */ if ( (event.where.h != last_where.h) || (event.where.v != last_where.v) ) { @@ -282,16 +283,14 @@ static int Mac_HandleEvents(_THIS, int wait4it) myGlobalToLocal(this, &event.where); /* Treat command-click as right mouse button */ if ( event.modifiers & optionKey ) { - SDL_PrivateMouseButton(SDL_PRESSED, - 2,event.where.h,event.where.v); - } - else if ( event.modifiers & cmdKey ) { - SDL_PrivateMouseButton(SDL_PRESSED, - 3,event.where.h,event.where.v); + mouse_button = 2; + } else if ( event.modifiers & cmdKey ) { + mouse_button = 3; } else { - SDL_PrivateMouseButton(SDL_PRESSED, - 1,event.where.h,event.where.v); + mouse_button = 1; } + SDL_PrivateMouseButton(SDL_PRESSED, + mouse_button, event.where.h, event.where.v); break; case inGrow: { int newSize; @@ -336,7 +335,7 @@ static int Mac_HandleEvents(_THIS, int wait4it) if ( TrackBox (win, event.where, area )) { if ( IsWindowCollapsable(win) ) { CollapseWindow (win, !IsWindowCollapsed(win)); - // There should be something done like in inGrow case, but... + /* There should be something done like in inGrow case, but... */ } } break; @@ -355,18 +354,14 @@ static int Mac_HandleEvents(_THIS, int wait4it) break; case mouseUp: { myGlobalToLocal(this, &event.where); - /* Treat command-click as right mouse button */ - if ( event.modifiers & cmdKey ) { - SDL_PrivateMouseButton(SDL_RELEASED, - 3, event.where.h, event.where.v); - } - else if ( event.modifiers & optionKey ) { - SDL_PrivateMouseButton(SDL_RELEASED, - 2,event.where.h,event.where.v); - } else { - SDL_PrivateMouseButton(SDL_RELEASED, - 1, event.where.h, event.where.v); - } + /* Release the mouse button we simulated in the last press. + The drawback of this methos is we cannot press more than + one button. However, this doesn't matter, since there is + only a single logical mouse button, even if you have a + multi-button mouse, this doesn't matter at all. + */ + SDL_PrivateMouseButton(SDL_RELEASED, + mouse_button, event.where.h, event.where.v); } break; #if 0 /* Handled above the switch statement */ diff --git a/src/video/quartz/SDL_QuartzEvents.m b/src/video/quartz/SDL_QuartzEvents.m index 4f99362cf..4a2f17d14 100644 --- a/src/video/quartz/SDL_QuartzEvents.m +++ b/src/video/quartz/SDL_QuartzEvents.m @@ -22,6 +22,8 @@ #include "SDL_QuartzKeys.h" +static int last_virtual_button = 0; // Last virtual mouse button pressed + static void QZ_InitOSKeymap (_THIS) { int i; @@ -222,12 +224,16 @@ static void QZ_DoDeactivate (_THIS) { static void QZ_PumpEvents (_THIS) { - NSDate *distantPast = [ NSDate distantPast ]; - + NSDate *distantPast; NSEvent *event; NSRect winRect; NSRect titleBarRect; - + NSAutoreleasePool *pool; + + distantPast = [ [ NSDate distantPast ] retain ]; + + pool = [ [ NSAutoreleasePool alloc ] init ]; + winRect = NSMakeRect (0, 0, SDL_VideoSurface->w + 1, SDL_VideoSurface->h + 1); titleBarRect = NSMakeRect ( 0, SDL_VideoSurface->h, SDL_VideoSurface->w, SDL_VideoSurface->h + 22 ); @@ -266,9 +272,11 @@ static void QZ_PumpEvents (_THIS) case NSLeftMouseDown: if ( NSCommandKeyMask & currentMods ) { - DO_MOUSE_DOWN (3, 0); + last_virtual_button = 3; + DO_MOUSE_DOWN (3, 0); } else if ( NSAlternateKeyMask & currentMods ) { + last_virtual_button = 2; DO_MOUSE_DOWN (2, 0); } else { @@ -278,14 +286,14 @@ static void QZ_PumpEvents (_THIS) case 25: DO_MOUSE_DOWN (2, 0); break; case NSRightMouseDown: DO_MOUSE_DOWN (3, 0); break; case NSLeftMouseUp: - if ( NSCommandKeyMask & currentMods ) { - DO_MOUSE_UP (3, 0); - } - else if ( NSAlternateKeyMask & currentMods ) { - DO_MOUSE_UP (2, 0); - } - else + + if ( last_virtual_button != 0 ) { + DO_MOUSE_UP (last_virtual_button, 0); + last_virtual_button = 0; + } + else { DO_MOUSE_UP (1, 1); + } break; case 26: DO_MOUSE_UP (2, 0); break; case NSRightMouseUp: DO_MOUSE_UP (3, 0); break; @@ -364,5 +372,8 @@ static void QZ_PumpEvents (_THIS) } } } while (event != nil); + + [ pool release ]; + [ distantPast release ]; } diff --git a/src/video/quartz/SDL_QuartzVideo.h b/src/video/quartz/SDL_QuartzVideo.h index f0529b688..daf73aef2 100644 --- a/src/video/quartz/SDL_QuartzVideo.h +++ b/src/video/quartz/SDL_QuartzVideo.h @@ -83,8 +83,9 @@ typedef struct SDL_PrivateVideoData { CFArrayRef mode_list; CGDirectPaletteRef palette; NSOpenGLContext *gl_context; - int width, height, bpp; + Uint32 width, height, bpp; Uint32 flags; + SDL_bool video_is_set; /* tell if the video mode was set */ /* Window-only fields */ NSWindow *window; @@ -105,6 +106,7 @@ typedef struct SDL_PrivateVideoData { #define device_height (this->hidden->height) #define device_bpp (this->hidden->bpp) #define mode_flags (this->hidden->flags) +#define video_set (this->hidden->video_is_set) #define window (this->hidden->window) #define windowView (this->hidden->view) diff --git a/src/video/quartz/SDL_QuartzVideo.m b/src/video/quartz/SDL_QuartzVideo.m index 7279098c2..c596b9d07 100644 --- a/src/video/quartz/SDL_QuartzVideo.m +++ b/src/video/quartz/SDL_QuartzVideo.m @@ -27,14 +27,13 @@ static BOOL inForeground = YES; static SDLKey keymap[256]; static unsigned int currentMods = 0; /* Current keyboard modifiers, to track modifier state */ +static char QZ_Error[255]; /* Global error buffer to temporarily store more informative error messages */ /* Include files into one compile unit...break apart eventually */ #include "SDL_QuartzWM.m" #include "SDL_QuartzEvents.m" #include "SDL_QuartzWindow.m" -char QZ_Error[255]; /* Global error buffer to temporarily store more informative error messages */ - /* Bootstrap binding, enables entry point into the driver */ VideoBootStrap QZ_bootstrap = { "Quartz", "MacOS X CoreGraphics", QZ_Available, QZ_CreateDevice @@ -143,7 +142,7 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { static SDL_Rect **list = NULL; int list_size = 0; - + /* Any windowed mode is acceptable */ if ( (flags & SDL_FULLSCREEN) == 0 ) return (SDL_Rect**)-1; @@ -151,7 +150,7 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { /* Free memory from previous call, if any */ if ( list != NULL ) { - int i = 0; + int i; for (i = 0; list[i] != NULL; i++) free (list[i]); @@ -159,23 +158,24 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { free (list); list = NULL; } - + /* Build list of modes with the requested bpp */ - for (i = num_modes-1; i >= 0; i--) { + for (i = 0; i < num_modes; i++) { - CFDictionaryRef onemode = CFArrayGetValueAtIndex (mode_list, i); - CFNumberRef number; + CFDictionaryRef onemode; + CFNumberRef number; int bpp; + onemode = CFArrayGetValueAtIndex (mode_list, i); number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel); CFNumberGetValue (number, kCFNumberSInt32Type, &bpp); if (bpp == format->BitsPerPixel) { - int intvalue; - SDL_Rect *rect; - int lastwidth = 0, lastheight = 0, width, height; - + int intvalue; + int hasMode; + int width, height; + number = CFDictionaryGetValue (onemode, kCGDisplayWidth); CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); width = (Uint16) intvalue; @@ -184,12 +184,23 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); height = (Uint16) intvalue; - /* We'll get a lot of modes with the same size, so ignore them */ - if ( width != lastwidth && height != lastheight ) { - - lastwidth = width; - lastheight = height; + /* Check if mode is already in the list */ + { + int i; + hasMode = SDL_FALSE; + for (i = 0; i < list_size; i++) { + if (list[i]->w == width && list[i]->h == height) { + hasMode = SDL_TRUE; + break; + } + } + } + + /* Grow the list and add mode to the list */ + if ( ! hasMode ) { + SDL_Rect *rect; + list_size++; if ( list == NULL) @@ -211,14 +222,29 @@ static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { } } + /* Sort list largest to smallest (by area) */ + { + int i, j; + for (i = 0; i < list_size; i++) { + for (j = 0; j < list_size-1; j++) { + + int area1, area2; + area1 = list[j]->w * list[j]->h; + area2 = list[j+1]->w * list[j+1]->h; + + if (area1 < area2) { + SDL_Rect *tmp = list[j]; + list[j] = list[j+1]; + list[j+1] = tmp; + } + } + } + } return list; } static void QZ_UnsetVideoMode (_THIS) { - if ( mode_flags & SDL_OPENGL ) - QZ_TearDownOpenGL (this); - /* Reset values that may change between switches */ this->info.blit_fill = 0; this->FillHWRect = NULL; @@ -229,9 +255,11 @@ static void QZ_UnsetVideoMode (_THIS) { /* Restore original screen resolution */ if ( mode_flags & SDL_FULLSCREEN ) { + if (mode_flags & SDL_OPENGL) + CGLSetFullScreen(NULL); + CGDisplaySwitchToMode (display_id, save_mode); CGDisplayRelease (display_id); - this->screen->pixels = NULL; } /* Release window mode data structures */ else { @@ -240,13 +268,24 @@ static void QZ_UnsetVideoMode (_THIS) { [ windowView release ]; } [ window setContentView:nil ]; + [ window setDelegate:nil ]; [ window close ]; - [ window release ]; } + /* Set pixels to null (so other code doesn't try to free it) */ + if (this->screen != NULL) + this->screen->pixels = NULL; + + /* Release the OpenGL context */ + if ( mode_flags & SDL_OPENGL ) + QZ_TearDownOpenGL (this); + /* Ensure the cursor will be visible and working when we quit */ CGDisplayShowCursor (display_id); CGAssociateMouseAndMouseCursorPosition (1); + + /* Signal successful teardown */ + video_set = SDL_FALSE; } static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width, @@ -263,7 +302,7 @@ static void QZ_UnsetVideoMode (_THIS) { SDL_SetError (QZ_Error); goto ERR_NO_MATCH; } - + /* Put up the blanking window (a window above all other windows) */ if ( CGDisplayNoErr != CGDisplayCapture (display_id) ) { SDL_SetError ("Failed capturing display"); @@ -370,7 +409,7 @@ static void QZ_UnsetVideoMode (_THIS) { /* Manually create a window, avoids having a nib file resource */ window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect - styleMask:style backing:NSBackingStoreRetained defer:NO ]; + styleMask:style backing:NSBackingStoreBuffered defer:NO ]; if (window == nil) { SDL_SetError ("Could not create the Cocoa window"); return NULL; @@ -431,7 +470,7 @@ static void QZ_UnsetVideoMode (_THIS) { static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) { - if (SDL_VideoSurface != NULL) + if (video_set == SDL_TRUE) QZ_UnsetVideoMode (this); current->flags = 0; @@ -469,7 +508,7 @@ static void QZ_UnsetVideoMode (_THIS) { SDL_SetError ("24bpp is not available"); return NULL; case 32: /* (8)-8-8-8 ARGB */ - amask = 0x00000000; /* These are the correct semantics */ + amask = 0x00000000; rmask = 0x00FF0000; gmask = 0x0000FF00; bmask = 0x000000FF; @@ -486,6 +525,9 @@ static void QZ_UnsetVideoMode (_THIS) { /* Warp mouse to origin in order to get passive mouse motion events started correctly */ QZ_PrivateWarpCursor (this, current->flags & SDL_FULLSCREEN, height, 0, 0); + /* Signal successful completion */ + video_set = SDL_TRUE; + return current; }