Ken Thomases : winemac: Implement MOUSE_SCROLL events.

Alexandre Julliard julliard at winehq.org
Mon Feb 11 13:06:31 CST 2013


Module: wine
Branch: master
Commit: 3748c3930837dcdd93c01f19cf6992e359dc6720
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3748c3930837dcdd93c01f19cf6992e359dc6720

Author: Ken Thomases <ken at codeweavers.com>
Date:   Sun Feb 10 19:09:12 2013 -0600

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(+), 0 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index bd6f086..218ba3f 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -778,6 +778,84 @@ static inline void fix_generic_modifiers_by_device(NSUInteger* modifiers)
     - (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 1f90c04..f03fef4 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 5cfcb8b..8c4ce54 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -136,6 +136,7 @@ extern void macdrv_window_did_unminimize(HWND hwnd) DECLSPEC_HIDDEN;
 
 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 388ffb7..23f0edf 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -132,6 +132,7 @@ enum {
     MOUSE_BUTTON,
     MOUSE_MOVED,
     MOUSE_MOVED_ABSOLUTE,
+    MOUSE_SCROLL,
     WINDOW_CLOSE_REQUESTED,
     WINDOW_DID_MINIMIZE,
     WINDOW_DID_UNMINIMIZE,
@@ -170,6 +171,13 @@ typedef struct macdrv_event {
             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;
         struct {
diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c
index 4742e37..d251808 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);
+}




More information about the wine-cvs mailing list