From 632e5cfc379d66497f977efc51c15a3bb8eb5d99 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 15 Jul 2007 15:58:00 +0000 Subject: [PATCH] Patch from Christian Walther Yes, the idea to use a cursor rectangle instead of [NSCursor set] has occurred to me too, and it does seem to be the most elegant way. Here's my attempt at an implementation --- src/video/quartz/SDL_QuartzEvents.m | 31 +++++----------------- src/video/quartz/SDL_QuartzVideo.h | 2 -- src/video/quartz/SDL_QuartzVideo.m | 1 + src/video/quartz/SDL_QuartzWM.h | 27 +++++++++++++++++++ src/video/quartz/SDL_QuartzWM.m | 40 +++++++++++++++++------------ src/video/quartz/SDL_QuartzWindow.h | 4 +++ src/video/quartz/SDL_QuartzWindow.m | 13 ++++++++++ 7 files changed, 75 insertions(+), 43 deletions(-) create mode 100644 src/video/quartz/SDL_QuartzWM.h diff --git a/src/video/quartz/SDL_QuartzEvents.m b/src/video/quartz/SDL_QuartzEvents.m index 2c91d06c2..2e1296636 100644 --- a/src/video/quartz/SDL_QuartzEvents.m +++ b/src/video/quartz/SDL_QuartzEvents.m @@ -22,6 +22,7 @@ #include "SDL_config.h" #include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" #include /* For wake from sleep detection */ #include /* For wake from sleep detection */ @@ -623,22 +624,9 @@ static void QZ_GetMouseLocation (_THIS, NSPoint *p) { void QZ_DoActivate (_THIS) { - BOOL isInGameWin = QZ_IsMouseInWindow (this); + SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS | (QZ_IsMouseInWindow (this) ? SDL_APPMOUSEFOCUS : 0)); - SDL_PrivateAppActive (1, SDL_APPINPUTFOCUS | (isInGameWin ? SDL_APPMOUSEFOCUS : 0)); - - /* Reset the cursor state */ - /* FIXME: This doesn't currently work... - Apparently you can't set the cursor inside windowDidBecomeKey - */ - if ( isInGameWin ) { - if (cursor_should_be_visible) - SDL_SetCursor (NULL); - else - QZ_HideMouse (this); - } else { - QZ_ShowMouse (this, [NSCursor arrowCursor]); - } + QZ_UpdateCursor(this); /* Regrab input, only if it was previously grabbed */ if ( current_grab_mode == SDL_GRAB_ON ) { @@ -665,9 +653,7 @@ void QZ_DoDeactivate (_THIS) { /* Reassociate mouse and cursor */ CGAssociateMouseAndMouseCursorPosition (1); - /* Show the cursor if it was hidden by SDL_ShowCursor() */ - if (!cursor_should_be_visible) - QZ_ShowMouse (this, [NSCursor arrowCursor]); + QZ_UpdateCursor(this); } void QZ_SleepNotificationHandler (void * refcon, @@ -904,6 +890,7 @@ but not as a result of the warp (so it's in the right direction). if ( !isInGameWin && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS); + if (grab_state == QZ_INVISIBLE_GRAB) /*The cursor has left the window even though it is disassociated from the mouse (and therefore @@ -920,18 +907,14 @@ disassociated from the mouse (and therefore to the user that the grab is broken.*/ CGAssociateMouseAndMouseCursorPosition (1); - QZ_ShowMouse (this, [NSCursor arrowCursor]); + QZ_UpdateCursor(this); } else if ( isInGameWin && (SDL_GetAppState() & (SDL_APPMOUSEFOCUS | SDL_APPINPUTFOCUS)) == SDL_APPINPUTFOCUS ) { SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS); - if (cursor_should_be_visible) { - SDL_SetCursor (NULL); - } else { - QZ_HideMouse (this); - } + QZ_UpdateCursor(this); if (grab_state == QZ_INVISIBLE_GRAB) { /*see comment above*/ QZ_PrivateWarpCursor (this, SDL_VideoSurface->w / 2, SDL_VideoSurface->h / 2); diff --git a/src/video/quartz/SDL_QuartzVideo.h b/src/video/quartz/SDL_QuartzVideo.h index e480bfa50..44e25ef07 100644 --- a/src/video/quartz/SDL_QuartzVideo.h +++ b/src/video/quartz/SDL_QuartzVideo.h @@ -224,8 +224,6 @@ SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height, void QZ_PrivateWarpCursor (_THIS, int x, int y); void QZ_ChangeGrabState (_THIS, int action); void QZ_RegisterForSleepNotifications (_THIS); -void QZ_ShowMouse (_THIS, NSCursor *cursor); -void QZ_HideMouse (_THIS); void QZ_PrivateGlobalToLocal (_THIS, NSPoint *p); void QZ_PrivateCocoaToSDL (_THIS, NSPoint *p); BOOL QZ_IsMouseInWindow (_THIS); diff --git a/src/video/quartz/SDL_QuartzVideo.m b/src/video/quartz/SDL_QuartzVideo.m index 13acee0be..10d502830 100644 --- a/src/video/quartz/SDL_QuartzVideo.m +++ b/src/video/quartz/SDL_QuartzVideo.m @@ -756,6 +756,7 @@ other blitting while waiting on the VBL (and hence results in higher framerates) } [ qz_window setDelegate: [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ]; + [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ]; } /* We already have a window, just change its size */ else { diff --git a/src/video/quartz/SDL_QuartzWM.h b/src/video/quartz/SDL_QuartzWM.h new file mode 100644 index 000000000..e1ae17895 --- /dev/null +++ b/src/video/quartz/SDL_QuartzWM.h @@ -0,0 +1,27 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2003 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +struct WMcursor { + NSCursor *nscursor; +}; + +void QZ_UpdateCursor(_THIS); diff --git a/src/video/quartz/SDL_QuartzWM.m b/src/video/quartz/SDL_QuartzWM.m index eee652c53..f544dc975 100644 --- a/src/video/quartz/SDL_QuartzWM.m +++ b/src/video/quartz/SDL_QuartzWM.m @@ -22,12 +22,9 @@ #include "SDL_config.h" #include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" -struct WMcursor { - NSCursor *nscursor; -}; - void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { if ( cursor != NULL ) { @@ -90,18 +87,21 @@ void QZ_FreeWMCursor (_THIS, WMcursor *cursor) { return(NULL); } -void QZ_ShowMouse (_THIS, NSCursor *cursor) { - if (!cursor_visible) { - [ NSCursor unhide ]; - cursor_visible = YES; - } - [ cursor set ]; -} +void QZ_UpdateCursor (_THIS) { + BOOL state; -void QZ_HideMouse (_THIS) { - if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS) && cursor_visible) { - [ NSCursor hide ]; - cursor_visible = NO; + if (cursor_should_be_visible || !(SDL_GetAppState() & SDL_APPMOUSEFOCUS)) { + state = YES; + } else { + state = NO; + } + if (state != cursor_visible) { + if (state) { + [ NSCursor unhide ]; + } else { + [ NSCursor hide ]; + } + cursor_visible = state; } } @@ -117,18 +117,24 @@ BOOL QZ_IsMouseInWindow (_THIS) { int QZ_ShowWMCursor (_THIS, WMcursor *cursor) { if ( cursor == NULL) { - QZ_HideMouse (this); if ( cursor_should_be_visible ) { cursor_should_be_visible = NO; QZ_ChangeGrabState (this, QZ_HIDECURSOR); } + QZ_UpdateCursor(this); } else { - QZ_ShowMouse (this, cursor->nscursor); + if (qz_window ==nil || (mode_flags & SDL_FULLSCREEN)) { + [ cursor->nscursor set ]; + } + else { + [ qz_window invalidateCursorRectsForView: [ qz_window contentView ] ]; + } if ( ! cursor_should_be_visible ) { cursor_should_be_visible = YES; QZ_ChangeGrabState (this, QZ_SHOWCURSOR); } + QZ_UpdateCursor(this); } return 1; diff --git a/src/video/quartz/SDL_QuartzWindow.h b/src/video/quartz/SDL_QuartzWindow.h index 20077ee89..cdfdec47e 100644 --- a/src/video/quartz/SDL_QuartzWindow.h +++ b/src/video/quartz/SDL_QuartzWindow.h @@ -37,3 +37,7 @@ - (BOOL)windowShouldClose:(id)sender; @end +/* Subclass of NSView to set cursor rectangle */ +@interface SDL_QuartzView : NSView +- (void)resetCursorRects; +@end diff --git a/src/video/quartz/SDL_QuartzWindow.m b/src/video/quartz/SDL_QuartzWindow.m index ffbf1eadf..b56f9a701 100644 --- a/src/video/quartz/SDL_QuartzWindow.m +++ b/src/video/quartz/SDL_QuartzWindow.m @@ -22,6 +22,7 @@ #include "SDL_config.h" #include "SDL_QuartzVideo.h" +#include "SDL_QuartzWM.h" #include "SDL_QuartzWindow.h" /* @@ -217,3 +218,15 @@ - (void)windowDidResignKey:(NSNotification *)aNotification } @end + +@implementation SDL_QuartzView + +- (void)resetCursorRects +{ + SDL_Cursor *sdlc = SDL_GetCursor(); + if (sdlc != NULL && sdlc->wm_cursor != NULL) { + [self addCursorRect: [self visibleRect] cursor: sdlc->wm_cursor->nscursor]; + } +} + +@end