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