Module: wine Branch: master Commit: bd269786a505931c82f7fe93c6cc6d76102daac1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=bd269786a505931c82f7fe93c6...
Author: Ken Thomases ken@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); +}