diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index ff20a79ed..c35cf3063 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -22,11 +22,13 @@ /* General mouse handling code for SDL */ +#include "SDL_assert.h" #include "SDL_events.h" #include "SDL_events_c.h" #include "default_cursor.h" #include "../video/SDL_sysvideo.h" +/*#define DEBUG_MOUSE*/ /* The mouse state */ static SDL_Mouse SDL_mouse; @@ -68,6 +70,23 @@ SDL_GetMouseFocus(void) return mouse->focus; } +void +SDL_ResetMouse(void) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + Uint8 i; + +#ifdef DEBUG_MOUSE + printf("Resetting mouse\n"); +#endif + for (i = 1; i <= sizeof(mouse->buttonstate)*8; ++i) { + if (mouse->buttonstate & SDL_BUTTON(i)) { + SDL_SendMouseButton(mouse->focus, SDL_RELEASED, i); + } + } + SDL_assert(mouse->buttonstate == 0); +} + void SDL_SetMouseFocus(SDL_Window * window) { @@ -77,6 +96,11 @@ SDL_SetMouseFocus(SDL_Window * window) return; } + if (mouse->focus && !window) { + /* We won't get anymore mouse messages, so reset mouse state */ + SDL_ResetMouse(); + } + /* See if the current window has lost focus */ if (mouse->focus) { SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0); @@ -87,6 +111,45 @@ SDL_SetMouseFocus(SDL_Window * window) if (mouse->focus) { SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0); } + + /* Update cursor visibility */ + SDL_SetCursor(NULL); +} + +/* Check to see if we need to synthesize focus events */ +static SDL_bool +SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint8 buttonstate) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + int w, h; + SDL_bool inWindow; + + SDL_GetWindowSize(window, &w, &h); + if (x < 0 || y < 0 || x >= w || y >= h) { + inWindow = SDL_FALSE; + } else { + inWindow = SDL_TRUE; + } + if (!inWindow && !buttonstate) { + if (window == mouse->focus) { +#ifdef DEBUG_MOUSE + printf("Mouse left window, synthesizing focus lost event\n"); +#endif + SDL_SetMouseFocus(NULL); + } + return SDL_FALSE; + } + + if (window != mouse->focus) { + mouse->last_x = x; + mouse->last_y = y; + +#ifdef DEBUG_MOUSE + printf("Mouse entered window, synthesizing focus gain event\n"); +#endif + SDL_SetMouseFocus(window); + } + return SDL_TRUE; } int @@ -98,11 +161,13 @@ SDL_SendMouseMotion(SDL_Window * window, int relative, int x, int y) int yrel; int x_max = 0, y_max = 0; - if (window) { - SDL_SetMouseFocus(window); + if (window && !relative) { + if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) { + return 0; + } } - /* the relative motion is calculated regarding the system cursor last position */ + /* relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; yrel = y; @@ -115,7 +180,7 @@ SDL_SendMouseMotion(SDL_Window * window, int relative, int x, int y) /* Drop events that don't change state */ if (!xrel && !yrel) { -#if 0 +#ifdef DEBUG_MOUSE printf("Mouse event didn't change state - dropped!\n"); #endif return 0; @@ -135,7 +200,6 @@ SDL_SendMouseMotion(SDL_Window * window, int relative, int x, int y) --y_max; /* make sure that the pointers find themselves inside the windows */ - /* only check if mouse->xmax is set ! */ if (mouse->x > x_max) { mouse->x = x_max; } @@ -174,8 +238,9 @@ SDL_SendMouseMotion(SDL_Window * window, int relative, int x, int y) event.motion.yrel = yrel; posted = (SDL_PushEvent(&event) > 0); } - mouse->last_x = mouse->x; - mouse->last_y = mouse->y; + /* Use unclamped values if we're getting events outside the window */ + mouse->last_x = x; + mouse->last_y = y; return posted; } @@ -185,34 +250,34 @@ SDL_SendMouseButton(SDL_Window * window, Uint8 state, Uint8 button) SDL_Mouse *mouse = SDL_GetMouse(); int posted; Uint32 type; - - if (window) { - SDL_SetMouseFocus(window); - } + Uint8 buttonstate = mouse->buttonstate; /* Figure out which event to perform */ switch (state) { case SDL_PRESSED: - if (mouse->buttonstate & SDL_BUTTON(button)) { - /* Ignore this event, no state change */ - return 0; - } type = SDL_MOUSEBUTTONDOWN; - mouse->buttonstate |= SDL_BUTTON(button); + buttonstate |= SDL_BUTTON(button); break; case SDL_RELEASED: - if (!(mouse->buttonstate & SDL_BUTTON(button))) { - /* Ignore this event, no state change */ - return 0; - } type = SDL_MOUSEBUTTONUP; - mouse->buttonstate &= ~SDL_BUTTON(button); + buttonstate &= ~SDL_BUTTON(button); break; default: /* Invalid state -- bail */ return 0; } + /* We do this after calculating buttonstate so button presses gain focus */ + if (window && state == SDL_PRESSED) { + SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate); + } + + if (buttonstate == mouse->buttonstate) { + /* Ignore this event, no state change */ + return 0; + } + mouse->buttonstate = buttonstate; + /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(type) == SDL_ENABLE) { @@ -225,6 +290,12 @@ SDL_SendMouseButton(SDL_Window * window, Uint8 state, Uint8 button) event.button.windowID = mouse->focus ? mouse->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } + + /* We do this after dispatching event so button releases can lose focus */ + if (window && state == SDL_RELEASED) { + SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate); + } + return posted; } diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index f4a7f6140..9103fa95f 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -51,7 +51,7 @@ SDL_Surface * SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) { SDL_bool was_error; - long fp_offset = 0; + Sint64 fp_offset = 0; int bmpPitch; int i, pad; SDL_Surface *surface; @@ -371,7 +371,7 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) int SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst) { - long fp_offset; + Sint64 fp_offset; int i, pad; SDL_Surface *surface; Uint8 *bits; @@ -515,7 +515,7 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst) } /* Write the bitmap offset */ - bfOffBits = SDL_RWtell(dst) - fp_offset; + bfOffBits = (Uint32)(SDL_RWtell(dst) - fp_offset); if (SDL_RWseek(dst, fp_offset + 10, RW_SEEK_SET) < 0) { SDL_Error(SDL_EFSEEK); } @@ -542,7 +542,7 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst) } /* Write the BMP file size */ - bfSize = SDL_RWtell(dst) - fp_offset; + bfSize = (Uint32)(SDL_RWtell(dst) - fp_offset); if (SDL_RWseek(dst, fp_offset + 2, RW_SEEK_SET) < 0) { SDL_Error(SDL_EFSEEK); } diff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h index 427356149..d17604d71 100644 --- a/src/video/cocoa/SDL_cocoawindow.h +++ b/src/video/cocoa/SDL_cocoawindow.h @@ -56,8 +56,6 @@ typedef struct SDL_WindowData SDL_WindowData; -(void) mouseUp:(NSEvent *) theEvent; -(void) rightMouseUp:(NSEvent *) theEvent; -(void) otherMouseUp:(NSEvent *) theEvent; --(void) mouseEntered:(NSEvent *)theEvent; --(void) mouseExited:(NSEvent *)theEvent; -(void) mouseMoved:(NSEvent *) theEvent; -(void) mouseDragged:(NSEvent *) theEvent; -(void) rightMouseDragged:(NSEvent *) theEvent; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index 2d9b5a957..dc1a85096 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -200,10 +200,8 @@ static __inline__ void ConvertNSRect(NSRect *r) y = (int)(window->h - point.y); if (x >= 0 && x < window->w && y >= 0 && y < window->h) { - if (SDL_GetMouseFocus() != window) { - [self mouseEntered:nil]; - } SDL_SendMouseMotion(window, 0, x, y); + SDL_SetCursor(NULL); } } @@ -309,38 +307,6 @@ static __inline__ void ConvertNSRect(NSRect *r) [self mouseUp:theEvent]; } -- (void)mouseEntered:(NSEvent *)theEvent -{ - SDL_SetMouseFocus(_data->window); - - SDL_SetCursor(NULL); -} - -- (void)mouseExited:(NSEvent *)theEvent -{ - SDL_Window *window = _data->window; - - if (SDL_GetMouseFocus() == window) { - if (window->flags & SDL_WINDOW_INPUT_GRABBED) { - int x, y; - NSPoint point; - CGPoint cgpoint; - - point = [theEvent locationInWindow]; - point.y = window->h - point.y; - - SDL_SendMouseMotion(window, 0, (int)point.x, (int)point.y); - SDL_GetMouseState(&x, &y); - cgpoint.x = window->x + x; - cgpoint.y = window->y + y; - CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint); - } else { - SDL_SetMouseFocus(NULL); - SDL_SetCursor(NULL); - } - } -} - - (void)mouseMoved:(NSEvent *)theEvent { SDL_Mouse *mouse = SDL_GetMouse(); @@ -357,15 +323,26 @@ static __inline__ void ConvertNSRect(NSRect *r) y = (int)(window->h - point.y); if (x < 0 || x >= window->w || y < 0 || y >= window->h) { - if (SDL_GetMouseFocus() == window) { - [self mouseExited:theEvent]; + if (window->flags & SDL_WINDOW_INPUT_GRABBED) { + CGPoint cgpoint; + + if (x < 0) { + x = 0; + } else if (x >= window->w) { + x = window->w - 1; + } + if (y < 0) { + y = 0; + } else if (y >= window->h) { + y = window->h - 1; + } + + cgpoint.x = window->x + x; + cgpoint.y = window->y + y; + CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint); } - } else { - if (SDL_GetMouseFocus() != window) { - [self mouseEntered:theEvent]; - } - SDL_SendMouseMotion(window, 0, x, y); } + SDL_SendMouseMotion(window, 0, x, y); } - (void)mouseDragged:(NSEvent *)theEvent