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
This commit is contained in:
David Capello 2014-11-01 11:36:51 -03:00
parent 01c26e5a18
commit b9b3b02882
7 changed files with 73 additions and 18 deletions

View File

@ -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: */

View File

@ -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];

View File

@ -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];

View File

@ -35,7 +35,9 @@
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
#elif defined(ALLEGRO_UNIX)
#include <xalleg.h>
#ifdef None
#undef None
@ -50,6 +52,10 @@
#include "she/clipboard_simple.h"
#endif
#ifdef __APPLE__
#include <allegro/platform/aintosx.h>
#endif
#include "loadpng.h"
#include <cassert>
@ -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);

View File

@ -11,6 +11,8 @@
namespace ui {
enum CursorType {
kOutsideDisplay = -1,
kFirstCursorType = 0,
kNoCursor = 0,
kArrowCursor,

View File

@ -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();

View File

@ -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.