From b9b3b0288237c2337cff87f48de94eb1274ed004 Mon Sep 17 00:00:00 2001 From: David Capello Date: Sat, 1 Nov 2014 11:36:51 -0300 Subject: [PATCH] Fix mouse issues on OS X (fix #458) Now we generate she::Event::MouseEnter/Leave events correctly when the mouse leaves or enters into the window to show the native cursor again when necessary. Close #466 --- .../include/allegro/platform/aintosx.h | 8 +++-- src/allegro/src/macosx/qzmouse.m | 13 +++++--- src/allegro/src/macosx/system.m | 8 +++++ src/she/alleg4/she_alleg4.cpp | 33 ++++++++++++++++++- src/ui/cursor_type.h | 2 ++ src/ui/manager.cpp | 16 +++++---- src/ui/system.cpp | 11 +++++-- 7 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/allegro/include/allegro/platform/aintosx.h b/src/allegro/include/allegro/platform/aintosx.h index 492cc2896..8f4191082 100644 --- a/src/allegro/include/allegro/platform/aintosx.h +++ b/src/allegro/include/allegro/platform/aintosx.h @@ -181,12 +181,14 @@ AL_VAR(int, osx_mouse_warped); AL_VAR(int, osx_skip_mouse_move); AL_VAR(int, osx_emulate_mouse_buttons); AL_VAR(NSTrackingRectTag, osx_mouse_tracking_rect); -extern AL_METHOD(void, osx_window_close_hook, (void)); -extern AL_METHOD(void, osx_resize_callback, (RESIZE_DISPLAY_EVENT *ev)); - #endif +extern AL_METHOD(void, osx_window_close_hook, (void)); +extern AL_METHOD(void, osx_resize_callback, (RESIZE_DISPLAY_EVENT *ev)); +extern AL_METHOD(void, osx_mouse_enter_callback, (void)); +extern AL_METHOD(void, osx_mouse_leave_callback, (void)); + #endif /* Local variables: */ diff --git a/src/allegro/src/macosx/qzmouse.m b/src/allegro/src/macosx/qzmouse.m index 2db42089e..cb6fd1438 100644 --- a/src/allegro/src/macosx/qzmouse.m +++ b/src/allegro/src/macosx/qzmouse.m @@ -255,7 +255,12 @@ static void osx_mouse_set_range(int x1, int y1, int x2, int y2) mouse_maxx = x2; mouse_maxy = y2; - osx_mouse_position(CLAMP(mouse_minx, _mouse_x, mouse_maxx), CLAMP(mouse_miny, _mouse_y, mouse_maxy)); + // Do not change the position of the mouse inside the + // range to avoid changing the position to 0,0 when + // the program starts. + //osx_mouse_position( + // CLAMP(mouse_minx, _mouse_x, mouse_maxx), + // CLAMP(mouse_miny, _mouse_y, mouse_maxy)); } @@ -418,13 +423,13 @@ static int osx_select_system_cursor(AL_CONST int cursor) requested_cursor = [NSCursor operationNotAllowedCursor]; break; case MOUSE_CURSOR_SIZE_N: - requested_cursor = [NSCursor resizeUpCursor]; break; + requested_cursor = [NSCursor resizeUpCursor]; break; case MOUSE_CURSOR_SIZE_S: - requested_cursor = [NSCursor resizeDownCursor]; break; + requested_cursor = [NSCursor resizeDownCursor]; break; case MOUSE_CURSOR_SIZE_NS: - requested_cursor = [NSCursor resizeUpDownCursor]; break; + requested_cursor = [NSCursor resizeUpDownCursor]; break; case MOUSE_CURSOR_SIZE_W: requested_cursor = [NSCursor resizeLeftCursor]; diff --git a/src/allegro/src/macosx/system.m b/src/allegro/src/macosx/system.m index 7e890f895..113cf5c15 100644 --- a/src/allegro/src/macosx/system.m +++ b/src/allegro/src/macosx/system.m @@ -69,6 +69,8 @@ AllegroWindow *osx_window = NULL; char osx_window_title[ALLEGRO_MESSAGE_SIZE]; void (*osx_window_close_hook)(void) = NULL; void (*osx_resize_callback)(RESIZE_DISPLAY_EVENT *ev) = NULL; +void (*osx_mouse_enter_callback)() = NULL; +void (*osx_mouse_leave_callback)() = NULL; int osx_gfx_mode = OSX_GFX_NONE; int osx_emulate_mouse_buttons = FALSE; int osx_window_first_expose = FALSE; @@ -295,6 +297,9 @@ void osx_event_handler() _mouse_on = TRUE; osx_hide_native_mouse(); } + + if (osx_mouse_enter_callback) + osx_mouse_enter_callback(); } } [NSApp sendEvent: event]; @@ -308,6 +313,9 @@ void osx_event_handler() _mouse_on = FALSE; osx_show_native_mouse(); } + + if (osx_mouse_leave_callback) + osx_mouse_leave_callback(); } } [NSApp sendEvent: event]; diff --git a/src/she/alleg4/she_alleg4.cpp b/src/she/alleg4/she_alleg4.cpp index 7f11b6d29..1610f92b7 100644 --- a/src/she/alleg4/she_alleg4.cpp +++ b/src/she/alleg4/she_alleg4.cpp @@ -35,7 +35,9 @@ #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E #endif + #elif defined(ALLEGRO_UNIX) + #include #ifdef None #undef None @@ -50,6 +52,10 @@ #include "she/clipboard_simple.h" #endif +#ifdef __APPLE__ + #include +#endif + #include "loadpng.h" #include @@ -407,7 +413,27 @@ void unsubclass_hwnd(HWND hwnd) base_wndproc = NULL; } -#endif +#endif // WIN32 + +#if __APPLE__ + +void osx_mouser_enter_she_callback() +{ + Event ev; + ev.setPosition(gfx::Point(0, 0)); + ev.setType(Event::MouseEnter); + queue_event(ev); +} + +void osx_mouser_leave_she_callback() +{ + Event ev; + ev.setType(Event::MouseLeave); + queue_event(ev); +} + +#endif // __APPLE__ + } // anonymous namespace class Alleg4Display : public Display { @@ -417,6 +443,11 @@ public: , m_scale(0) { unique_display = this; +#ifdef __APPLE__ + osx_mouse_enter_callback = osx_mouser_enter_she_callback; + osx_mouse_leave_callback = osx_mouser_leave_she_callback; +#endif + if (install_mouse() < 0) throw DisplayCreationException(allegro_error); if (install_keyboard() < 0) throw DisplayCreationException(allegro_error); diff --git a/src/ui/cursor_type.h b/src/ui/cursor_type.h index ed8b74671..e1625ad9e 100644 --- a/src/ui/cursor_type.h +++ b/src/ui/cursor_type.h @@ -11,6 +11,8 @@ namespace ui { enum CursorType { + kOutsideDisplay = -1, + kFirstCursorType = 0, kNoCursor = 0, kArrowCursor, diff --git a/src/ui/manager.cpp b/src/ui/manager.cpp index 49d5b9eb6..ad13712a3 100644 --- a/src/ui/manager.cpp +++ b/src/ui/manager.cpp @@ -102,6 +102,9 @@ static char old_readed_key[KEY_MAX]; /* keyboard status of previous static unsigned key_repeated[KEY_MAX]; +// Flag to block all the generation of mouse messages from polling. +static bool mouse_left = false; + /* keyboard focus movement stuff */ static bool move_focus(Manager* manager, Message* msg); static int count_widgets_accept_focus(Widget* widget); @@ -288,6 +291,9 @@ bool Manager::generateMessages() void Manager::generateMouseMessages() { + if (mouse_left) + return; + // Update mouse status bool mousemove = _internal_poll_mouse(); @@ -469,18 +475,14 @@ void Manager::generateMessagesFromSheEvents() } case she::Event::MouseEnter: { - if (!mouse_events_from_she) - continue; - + mouse_left = false; jmouse_set_cursor(kArrowCursor); break; } case she::Event::MouseLeave: { - if (!mouse_events_from_she) - continue; - - jmouse_set_cursor(kNoCursor); + mouse_left = true; + jmouse_set_cursor(kOutsideDisplay); setMouse(NULL); _internal_no_mouse_position(); diff --git a/src/ui/system.cpp b/src/ui/system.cpp index cfea56edf..6b5648af2 100644 --- a/src/ui/system.cpp +++ b/src/ui/system.cpp @@ -98,11 +98,14 @@ static void update_mouse_cursor() // Use native cursor when it's possible/available/configured to do so. bool native_cursor_available = false; - if (use_native_mouse_cursor) { + if (use_native_mouse_cursor || mouse_cursor_type == kOutsideDisplay) { she::NativeCursor nativeCursor = she::kNoCursor; native_cursor_available = true; switch (mouse_cursor_type) { + case ui::kOutsideDisplay: + nativeCursor = she::kArrowCursor; + break; case ui::kNoCursor: break; case ui::kArrowCursor: case ui::kArrowPlusCursor: @@ -151,10 +154,12 @@ static void update_mouse_cursor() // Use a software cursor with the overlay. if (!native_cursor_set) { - if (mouse_cursor_type == ui::kNoCursor) + if (mouse_cursor_type == ui::kNoCursor) { update_mouse_overlay(NULL); - else + } + else { update_mouse_overlay(CurrentTheme::get()->getCursor(mouse_cursor_type)); + } } else { // Hide the overlay if we are using a native cursor.