From 3748c3930837dcdd93c01f19cf6992e359dc6720 Mon Sep 17 00:00:00 2001 From: Ken Thomases Date: Sun, 10 Feb 2013 19:09:12 -0600 Subject: [PATCH] winemac: Implement MOUSE_SCROLL events. --- dlls/winemac.drv/cocoa_window.m | 78 +++++++++++++++++++++++++++++++++ dlls/winemac.drv/event.c | 7 +++ dlls/winemac.drv/macdrv.h | 1 + dlls/winemac.drv/macdrv_cocoa.h | 8 ++++ dlls/winemac.drv/mouse.c | 21 +++++++++ 5 files changed, 115 insertions(+) diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index bd6f0869d6f..218ba3fdb7b 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -778,6 +778,84 @@ - (void) mouseDragged:(NSEvent *)theEvent { [self postMouseMovedEvent:theE - (void) rightMouseDragged:(NSEvent *)theEvent { [self postMouseMovedEvent:theEvent]; } - (void) otherMouseDragged:(NSEvent *)theEvent { [self postMouseMovedEvent:theEvent]; } + - (void) scrollWheel:(NSEvent *)theEvent + { + CGPoint pt; + macdrv_event event; + CGEventRef cgevent; + CGFloat x, y; + BOOL continuous = FALSE; + + cgevent = [theEvent CGEvent]; + pt = CGEventGetLocation(cgevent); + + event.type = MOUSE_SCROLL; + event.window = (macdrv_window)[self retain]; + event.mouse_scroll.x = pt.x; + event.mouse_scroll.y = pt.y; + event.mouse_scroll.time_ms = [NSApp ticksForEventTime:[theEvent timestamp]]; + + if (CGEventGetIntegerValueField(cgevent, kCGScrollWheelEventIsContinuous)) + { + continuous = TRUE; + + /* Continuous scroll wheel events come from high-precision scrolling + hardware like Apple's Magic Mouse, Mighty Mouse, and trackpads. + For these, we can get more precise data from the CGEvent API. */ + /* Axis 1 is vertical, axis 2 is horizontal. */ + x = CGEventGetDoubleValueField(cgevent, kCGScrollWheelEventPointDeltaAxis2); + y = CGEventGetDoubleValueField(cgevent, kCGScrollWheelEventPointDeltaAxis1); + } + else + { + double pixelsPerLine = 10; + CGEventSourceRef source; + + /* The non-continuous values are in units of "lines", not pixels. */ + if ((source = CGEventCreateSourceFromEvent(cgevent))) + { + pixelsPerLine = CGEventSourceGetPixelsPerLine(source); + CFRelease(source); + } + + x = pixelsPerLine * [theEvent deltaX]; + y = pixelsPerLine * [theEvent deltaY]; + } + + /* Mac: negative is right or down, positive is left or up. + Win32: negative is left or down, positive is right or up. + So, negate the X scroll value to translate. */ + x = -x; + + /* The x,y values so far are in pixels. Win32 expects to receive some + fraction of WHEEL_DELTA == 120. By my estimation, that's roughly + 6 times the pixel value. */ + event.mouse_scroll.x_scroll = 6 * x; + event.mouse_scroll.y_scroll = 6 * y; + + if (!continuous) + { + /* For non-continuous "clicky" wheels, if there was any motion, make + sure there was at least WHEEL_DELTA motion. This is so, at slow + speeds where the system's acceleration curve is actually reducing the + scroll distance, the user is sure to get some action out of each click. + For example, this is important for rotating though weapons in a + first-person shooter. */ + if (0 < event.mouse_scroll.x_scroll && event.mouse_scroll.x_scroll < 120) + event.mouse_scroll.x_scroll = 120; + else if (-120 < event.mouse_scroll.x_scroll && event.mouse_scroll.x_scroll < 0) + event.mouse_scroll.x_scroll = -120; + + if (0 < event.mouse_scroll.y_scroll && event.mouse_scroll.y_scroll < 120) + event.mouse_scroll.y_scroll = 120; + else if (-120 < event.mouse_scroll.y_scroll && event.mouse_scroll.y_scroll < 0) + event.mouse_scroll.y_scroll = -120; + } + + if (event.mouse_scroll.x_scroll || event.mouse_scroll.y_scroll) + [queue postEvent:&event]; + } + /* * ---------- NSWindowDelegate methods ---------- diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c index 1f90c0491a4..f03fef4cf6b 100644 --- a/dlls/winemac.drv/event.c +++ b/dlls/winemac.drv/event.c @@ -39,6 +39,7 @@ static const char *dbgstr_event(int type) "MOUSE_BUTTON", "MOUSE_MOVED", "MOUSE_MOVED_ABSOLUTE", + "MOUSE_SCROLL", "WINDOW_CLOSE_REQUESTED", "WINDOW_DID_MINIMIZE", "WINDOW_DID_UNMINIMIZE", @@ -69,7 +70,10 @@ static macdrv_event_mask get_event_mask(DWORD mask) } if (mask & QS_MOUSEBUTTON) + { event_mask |= event_mask_for_type(MOUSE_BUTTON); + event_mask |= event_mask_for_type(MOUSE_SCROLL); + } if (mask & QS_MOUSEMOVE) { @@ -126,6 +130,9 @@ void macdrv_handle_event(macdrv_event *event) case MOUSE_MOVED_ABSOLUTE: macdrv_mouse_moved(hwnd, event); break; + case MOUSE_SCROLL: + macdrv_mouse_scroll(hwnd, event); + break; case WINDOW_CLOSE_REQUESTED: macdrv_window_close_requested(hwnd); break; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 5cfcb8b1fe0..8c4ce549937 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -136,6 +136,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect) extern void macdrv_mouse_button(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_mouse_moved(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN; +extern void macdrv_mouse_scroll(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_compute_keyboard_layout(struct macdrv_thread_data *thread_data) DECLSPEC_HIDDEN; extern void macdrv_keyboard_changed(const macdrv_event *event) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 388ffb734f2..23f0edf0bfa 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -132,6 +132,7 @@ MOUSE_BUTTON, MOUSE_MOVED, MOUSE_MOVED_ABSOLUTE, + MOUSE_SCROLL, WINDOW_CLOSE_REQUESTED, WINDOW_DID_MINIMIZE, WINDOW_DID_UNMINIMIZE, @@ -169,6 +170,13 @@ int y; unsigned long time_ms; } mouse_moved; + struct { + int x_scroll; + int y_scroll; + int x; + int y; + unsigned long time_ms; + } mouse_scroll; struct { CGRect frame; } window_frame_changed; diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c index 4742e376bac..d251808cfce 100644 --- a/dlls/winemac.drv/mouse.c +++ b/dlls/winemac.drv/mouse.c @@ -142,3 +142,24 @@ void macdrv_mouse_moved(HWND hwnd, const macdrv_event *event) send_mouse_input(hwnd, flags, event->mouse_moved.x, event->mouse_moved.y, 0, event->mouse_moved.time_ms); } + + +/*********************************************************************** + * macdrv_mouse_scroll + * + * Handler for MOUSE_SCROLL events. + */ +void macdrv_mouse_scroll(HWND hwnd, const macdrv_event *event) +{ + TRACE("win %p/%p scroll (%d,%d) at (%d,%d) time %lu (%lu ticks ago)\n", hwnd, + event->window, event->mouse_scroll.x_scroll, event->mouse_scroll.y_scroll, + event->mouse_scroll.x, event->mouse_scroll.y, + event->mouse_scroll.time_ms, (GetTickCount() - event->mouse_scroll.time_ms)); + + send_mouse_input(hwnd, MOUSEEVENTF_WHEEL | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, + event->mouse_scroll.x, event->mouse_scroll.y, + event->mouse_scroll.y_scroll, event->mouse_scroll.time_ms); + send_mouse_input(hwnd, MOUSEEVENTF_HWHEEL | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, + event->mouse_scroll.x, event->mouse_scroll.y, + event->mouse_scroll.x_scroll, event->mouse_scroll.time_ms); +}