Ken Thomases : winemac: Implement a MOUSE_BUTTON event for mouse clicks.

Alexandre Julliard julliard at winehq.org
Mon Jan 28 13:43:19 CST 2013


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

Author: Ken Thomases <ken at codeweavers.com>
Date:   Sun Jan 27 16:19:37 2013 -0600

winemac: Implement a MOUSE_BUTTON event for mouse clicks.

---

 dlls/winemac.drv/Makefile.in    |    1 +
 dlls/winemac.drv/cocoa_window.m |   35 +++++++++++
 dlls/winemac.drv/event.c        |    7 ++
 dlls/winemac.drv/macdrv.h       |    2 +
 dlls/winemac.drv/macdrv_cocoa.h |    8 +++
 dlls/winemac.drv/mouse.c        |  122 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 175 insertions(+), 0 deletions(-)

diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in
index 1de19ef..8484db8 100644
--- a/dlls/winemac.drv/Makefile.in
+++ b/dlls/winemac.drv/Makefile.in
@@ -7,6 +7,7 @@ C_SRCS = \
 	event.c \
 	gdi.c \
 	macdrv_main.c \
+	mouse.c \
 	surface.c \
 	window.c
 
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index c05adae..402db30 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -158,6 +158,13 @@ static BOOL frame_intersects_screens(NSRect frame, NSArray* screens)
         }
     }
 
+    /* By default, NSView will swallow right-clicks in an attempt to support contextual
+       menus.  We need to bypass that and allow the event to make it to the window. */
+    - (void) rightMouseDown:(NSEvent*)theEvent
+    {
+        [[self window] rightMouseDown:theEvent];
+    }
+
 @end
 
 
@@ -417,6 +424,22 @@ static BOOL frame_intersects_screens(NSRect frame, NSArray* screens)
         [self checkTransparency];
     }
 
+    - (void) postMouseButtonEvent:(NSEvent *)theEvent pressed:(int)pressed
+    {
+        CGPoint pt = CGEventGetLocation([theEvent CGEvent]);
+        macdrv_event event;
+
+        event.type = MOUSE_BUTTON;
+        event.window = (macdrv_window)[self retain];
+        event.mouse_button.button = [theEvent buttonNumber];
+        event.mouse_button.pressed = pressed;
+        event.mouse_button.x = pt.x;
+        event.mouse_button.y = pt.y;
+        event.mouse_button.time_ms = [NSApp ticksForEventTime:[theEvent timestamp]];
+
+        [queue postEvent:&event];
+    }
+
 
     /*
      * ---------- NSWindow method overrides ----------
@@ -446,6 +469,18 @@ static BOOL frame_intersects_screens(NSRect frame, NSArray* screens)
 
 
     /*
+     * ---------- NSResponder method overrides ----------
+     */
+    - (void) mouseDown:(NSEvent *)theEvent { [self postMouseButtonEvent:theEvent pressed:1]; }
+    - (void) rightMouseDown:(NSEvent *)theEvent { [self mouseDown:theEvent]; }
+    - (void) otherMouseDown:(NSEvent *)theEvent { [self mouseDown:theEvent]; }
+
+    - (void) mouseUp:(NSEvent *)theEvent { [self postMouseButtonEvent:theEvent pressed:0]; }
+    - (void) rightMouseUp:(NSEvent *)theEvent { [self mouseUp:theEvent]; }
+    - (void) otherMouseUp:(NSEvent *)theEvent { [self mouseUp:theEvent]; }
+
+
+    /*
      * ---------- NSWindowDelegate methods ----------
      */
     - (void)windowDidMove:(NSNotification *)notification
diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c
index da41884..4d35082 100644
--- a/dlls/winemac.drv/event.c
+++ b/dlls/winemac.drv/event.c
@@ -32,6 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(event);
 static const char *dbgstr_event(int type)
 {
     static const char * const event_names[] = {
+        "MOUSE_BUTTON",
         "WINDOW_CLOSE_REQUESTED",
         "WINDOW_FRAME_CHANGED",
     };
@@ -50,6 +51,9 @@ static macdrv_event_mask get_event_mask(DWORD mask)
 
     if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return -1;
 
+    if (mask & QS_MOUSEBUTTON)
+        event_mask |= event_mask_for_type(MOUSE_BUTTON);
+
     if (mask & QS_POSTMESSAGE)
     {
         event_mask |= event_mask_for_type(WINDOW_CLOSE_REQUESTED);
@@ -77,6 +81,9 @@ void macdrv_handle_event(macdrv_event *event)
 
     switch (event->type)
     {
+    case MOUSE_BUTTON:
+        macdrv_mouse_button(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 c40fb86..378b4ab 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -120,4 +120,6 @@ extern void set_surface_use_alpha(struct window_surface *window_surface, BOOL us
 extern void macdrv_window_close_requested(HWND hwnd) DECLSPEC_HIDDEN;
 extern void macdrv_window_frame_changed(HWND hwnd, CGRect frame) DECLSPEC_HIDDEN;
 
+extern void macdrv_mouse_button(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN;
+
 #endif  /* __WINE_MACDRV_H */
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 70be367..4827d40 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -122,6 +122,7 @@ extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDE
 
 /* event */
 enum {
+    MOUSE_BUTTON,
     WINDOW_CLOSE_REQUESTED,
     WINDOW_FRAME_CHANGED,
     NUM_EVENT_TYPES
@@ -134,6 +135,13 @@ typedef struct macdrv_event {
     macdrv_window       window;
     union {
         struct {
+            int             button;
+            int             pressed;
+            int             x;
+            int             y;
+            unsigned long   time_ms;
+        }                                           mouse_button;
+        struct {
             CGRect frame;
         }                                           window_frame_changed;
     };
diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c
new file mode 100644
index 0000000..31d3db0
--- /dev/null
+++ b/dlls/winemac.drv/mouse.c
@@ -0,0 +1,122 @@
+/*
+ * MACDRV mouse driver
+ *
+ * Copyright 1998 Ulrich Weigand
+ * Copyright 2007 Henri Verbeet
+ * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include "macdrv.h"
+#include "winuser.h"
+#include "wine/server.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(cursor);
+
+
+/***********************************************************************
+ *              send_mouse_input
+ *
+ * Update the various window states on a mouse event.
+ */
+static void send_mouse_input(HWND hwnd, UINT flags, int x, int y,
+                             DWORD mouse_data, unsigned long time)
+{
+    INPUT input;
+    HWND top_level_hwnd;
+
+    top_level_hwnd = GetAncestor(hwnd, GA_ROOT);
+
+    if ((flags & MOUSEEVENTF_MOVE) && (flags & MOUSEEVENTF_ABSOLUTE))
+    {
+        RECT rect;
+
+        /* update the wine server Z-order */
+        SetRect(&rect, x, y, x + 1, y + 1);
+        MapWindowPoints(0, top_level_hwnd, (POINT *)&rect, 2);
+
+        SERVER_START_REQ(update_window_zorder)
+        {
+            req->window      = wine_server_user_handle(top_level_hwnd);
+            req->rect.left   = rect.left;
+            req->rect.top    = rect.top;
+            req->rect.right  = rect.right;
+            req->rect.bottom = rect.bottom;
+            wine_server_call(req);
+        }
+        SERVER_END_REQ;
+    }
+
+    input.type              = INPUT_MOUSE;
+    input.mi.dx             = x;
+    input.mi.dy             = y;
+    input.mi.mouseData      = mouse_data;
+    input.mi.dwFlags        = flags;
+    input.mi.time           = time;
+    input.mi.dwExtraInfo    = 0;
+
+    __wine_send_input(top_level_hwnd, &input);
+}
+
+
+/***********************************************************************
+ *              macdrv_mouse_button
+ *
+ * Handler for MOUSE_BUTTON events.
+ */
+void macdrv_mouse_button(HWND hwnd, const macdrv_event *event)
+{
+    UINT flags = 0;
+    WORD data = 0;
+
+    TRACE("win %p button %d %s at (%d,%d) time %lu (%lu ticks ago)\n", hwnd, event->mouse_button.button,
+          (event->mouse_button.pressed ? "pressed" : "released"),
+          event->mouse_button.x, event->mouse_button.y,
+          event->mouse_button.time_ms, (GetTickCount() - event->mouse_button.time_ms));
+
+    if (event->mouse_button.pressed)
+    {
+        switch (event->mouse_button.button)
+        {
+        case 0: flags |= MOUSEEVENTF_LEFTDOWN; break;
+        case 1: flags |= MOUSEEVENTF_RIGHTDOWN; break;
+        case 2: flags |= MOUSEEVENTF_MIDDLEDOWN; break;
+        default:
+            flags |= MOUSEEVENTF_XDOWN;
+            data = 1 << (event->mouse_button.button - 3);
+            break;
+        }
+    }
+    else
+    {
+        switch (event->mouse_button.button)
+        {
+        case 0: flags |= MOUSEEVENTF_LEFTUP; break;
+        case 1: flags |= MOUSEEVENTF_RIGHTUP; break;
+        case 2: flags |= MOUSEEVENTF_MIDDLEUP; break;
+        default:
+            flags |= MOUSEEVENTF_XUP;
+            data = 1 << (event->mouse_button.button - 3);
+            break;
+        }
+    }
+
+    send_mouse_input(hwnd, flags | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,
+                     event->mouse_button.x, event->mouse_button.y,
+                     data, event->mouse_button.time_ms);
+}




More information about the wine-cvs mailing list