From 1a697e15b9c156a9e7586a8620dd4e2141f780e3 Mon Sep 17 00:00:00 2001 From: Ken Thomases Date: Tue, 7 May 2013 03:00:55 -0500 Subject: [PATCH] winemac: Implement SetCapture(). --- dlls/winemac.drv/cocoa_app.h | 1 + dlls/winemac.drv/cocoa_app.m | 145 +++++++++++++++++++++++++------------- dlls/winemac.drv/macdrv.h | 1 + dlls/winemac.drv/macdrv_cocoa.h | 1 + dlls/winemac.drv/mouse.c | 31 ++++++-- dlls/winemac.drv/winemac.drv.spec | 3 +- 6 files changed, 125 insertions(+), 57 deletions(-) diff --git a/dlls/winemac.drv/cocoa_app.h b/dlls/winemac.drv/cocoa_app.h index 3ce8a83ccb9..8ed97636a21 100644 --- a/dlls/winemac.drv/cocoa_app.h +++ b/dlls/winemac.drv/cocoa_app.h @@ -60,6 +60,7 @@ enum { NSMutableData* screenFrameCGRects; WineWindow* lastTargetWindow; + WineWindow* mouseCaptureWindow; BOOL forceNextMouseMoveAbsolute; double mouseMoveDeltaX, mouseMoveDeltaY; NSUInteger unmatchedMouseDowns; diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m index 52b6f2d5b4a..4e7cecc3f34 100644 --- a/dlls/winemac.drv/cocoa_app.m +++ b/dlls/winemac.drv/cocoa_app.m @@ -82,6 +82,7 @@ int macdrv_err_on; @property (retain, nonatomic) NSTimer* cursorTimer; @property (retain, nonatomic) NSImage* applicationIcon; @property (readonly, nonatomic) BOOL inputSourceIsInputMethod; +@property (retain, nonatomic) WineWindow* mouseCaptureWindow; - (void) setupObservations; - (void) applicationDidBecomeActive:(NSNotification *)notification; @@ -96,6 +97,7 @@ int macdrv_err_on; @synthesize keyboardType, lastFlagsChanged; @synthesize orderedWineWindows, applicationIcon; @synthesize cursorFrames, cursorTimer; + @synthesize mouseCaptureWindow; + (void) initialize { @@ -1159,12 +1161,16 @@ int macdrv_err_on; WineWindow* targetWindow; BOOL drag = [anEvent type] != NSMouseMoved; - /* Because of the way -[NSWindow setAcceptsMouseMovedEvents:] works, the - event indicates its window is the main window, even if the cursor is - over a different window. Find the actual WineWindow that is under the - cursor and post the event as being for that window. */ - if (!drag) + if (mouseCaptureWindow) + targetWindow = mouseCaptureWindow; + else if (drag) + targetWindow = (WineWindow*)[anEvent window]; + else { + /* Because of the way -[NSWindow setAcceptsMouseMovedEvents:] works, the + event indicates its window is the main window, even if the cursor is + over a different window. Find the actual WineWindow that is under the + cursor and post the event as being for that window. */ CGPoint cgpoint = CGEventGetLocation([anEvent CGEvent]); NSPoint point = [self flippedMouseLocation:NSPointFromCGPoint(cgpoint)]; NSInteger windowUnderNumber; @@ -1173,8 +1179,6 @@ int macdrv_err_on; belowWindowWithWindowNumber:0]; targetWindow = (WineWindow*)[NSApp windowWithWindowNumber:windowUnderNumber]; } - else - targetWindow = (WineWindow*)[anEvent window]; if ([targetWindow isKindOfClass:[WineWindow class]]) { @@ -1296,7 +1300,12 @@ int macdrv_err_on; - (void) handleMouseButton:(NSEvent*)theEvent { - WineWindow* window = (WineWindow*)[theEvent window]; + WineWindow* window; + + if (mouseCaptureWindow) + window = mouseCaptureWindow; + else + window = (WineWindow*)[theEvent window]; if ([window isKindOfClass:[WineWindow class]]) { @@ -1310,33 +1319,38 @@ int macdrv_err_on; if (pressed) { - // Test if the click was in the window's content area. - NSPoint nspoint = [self flippedMouseLocation:NSPointFromCGPoint(pt)]; - NSRect contentRect = [window contentRectForFrameRect:[window frame]]; - process = NSPointInRect(nspoint, contentRect); - if (process && [window styleMask] & NSResizableWindowMask) + if (mouseCaptureWindow) + process = TRUE; + else { - // Ignore clicks in the grow box (resize widget). - HIPoint origin = { 0, 0 }; - HIThemeGrowBoxDrawInfo info = { 0 }; - HIRect bounds; - OSStatus status; - - info.kind = kHIThemeGrowBoxKindNormal; - info.direction = kThemeGrowRight | kThemeGrowDown; - if ([window styleMask] & NSUtilityWindowMask) - info.size = kHIThemeGrowBoxSizeSmall; - else - info.size = kHIThemeGrowBoxSizeNormal; - - status = HIThemeGetGrowBoxBounds(&origin, &info, &bounds); - if (status == noErr) + // Test if the click was in the window's content area. + NSPoint nspoint = [self flippedMouseLocation:NSPointFromCGPoint(pt)]; + NSRect contentRect = [window contentRectForFrameRect:[window frame]]; + process = NSPointInRect(nspoint, contentRect); + if (process && [window styleMask] & NSResizableWindowMask) { - NSRect growBox = NSMakeRect(NSMaxX(contentRect) - bounds.size.width, - NSMinY(contentRect), - bounds.size.width, - bounds.size.height); - process = !NSPointInRect(nspoint, growBox); + // Ignore clicks in the grow box (resize widget). + HIPoint origin = { 0, 0 }; + HIThemeGrowBoxDrawInfo info = { 0 }; + HIRect bounds; + OSStatus status; + + info.kind = kHIThemeGrowBoxKindNormal; + info.direction = kThemeGrowRight | kThemeGrowDown; + if ([window styleMask] & NSUtilityWindowMask) + info.size = kHIThemeGrowBoxSizeSmall; + else + info.size = kHIThemeGrowBoxSizeNormal; + + status = HIThemeGetGrowBoxBounds(&origin, &info, &bounds); + if (status == noErr) + { + NSRect growBox = NSMakeRect(NSMaxX(contentRect) - bounds.size.width, + NSMinY(contentRect), + bounds.size.width, + bounds.size.height); + process = !NSPointInRect(nspoint, growBox); + } } } if (process) @@ -1380,23 +1394,33 @@ int macdrv_err_on; - (void) handleScrollWheel:(NSEvent*)theEvent { - WineWindow* window = (WineWindow*)[theEvent window]; + WineWindow* window; + + if (mouseCaptureWindow) + window = mouseCaptureWindow; + else + window = (WineWindow*)[theEvent window]; if ([window isKindOfClass:[WineWindow class]]) { CGEventRef cgevent = [theEvent CGEvent]; CGPoint pt = CGEventGetLocation(cgevent); - NSPoint nspoint; - NSRect contentRect; + BOOL process; if (clippingCursor) [self clipCursorLocation:&pt]; - nspoint = [self flippedMouseLocation:NSPointFromCGPoint(pt)]; - contentRect = [window contentRectForFrameRect:[window frame]]; + if (mouseCaptureWindow) + process = TRUE; + else + { + // Only process the event if it was in the window's content area. + NSPoint nspoint = [self flippedMouseLocation:NSPointFromCGPoint(pt)]; + NSRect contentRect = [window contentRectForFrameRect:[window frame]]; + process = NSPointInRect(nspoint, contentRect); + } - // Only process the event if it was in the window's content area. - if (NSPointInRect(nspoint, contentRect)) + if (process) { macdrv_event* event; CGFloat x, y; @@ -1482,31 +1506,38 @@ int macdrv_err_on; // then call -didSendEvent:. - (BOOL) handleEvent:(NSEvent*)anEvent { - if ([anEvent type] == NSFlagsChanged) - self.lastFlagsChanged = anEvent; - return FALSE; - } - - - (void) didSendEvent:(NSEvent*)anEvent - { + BOOL ret = FALSE; NSEventType type = [anEvent type]; - if (type == NSMouseMoved || type == NSLeftMouseDragged || - type == NSRightMouseDragged || type == NSOtherMouseDragged) + if (type == NSFlagsChanged) + self.lastFlagsChanged = anEvent; + else if (type == NSMouseMoved || type == NSLeftMouseDragged || + type == NSRightMouseDragged || type == NSOtherMouseDragged) { [self handleMouseMove:anEvent]; + ret = mouseCaptureWindow != nil; } else if (type == NSLeftMouseDown || type == NSLeftMouseUp || type == NSRightMouseDown || type == NSRightMouseUp || type == NSOtherMouseDown || type == NSOtherMouseUp) { [self handleMouseButton:anEvent]; + ret = mouseCaptureWindow != nil; } else if (type == NSScrollWheel) { [self handleScrollWheel:anEvent]; + ret = mouseCaptureWindow != nil; } - else if (type == NSKeyDown && ![anEvent isARepeat] && [anEvent keyCode] == kVK_Tab) + + return ret; + } + + - (void) didSendEvent:(NSEvent*)anEvent + { + NSEventType type = [anEvent type]; + + if (type == NSKeyDown && ![anEvent isARepeat] && [anEvent keyCode] == kVK_Tab) { NSUInteger modifiers = [anEvent modifierFlags]; if ((modifiers & NSCommandKeyMask) && @@ -1543,6 +1574,8 @@ int macdrv_err_on; [orderedWineWindows removeObjectIdenticalTo:window]; if (window == lastTargetWindow) lastTargetWindow = nil; + if (window == self.mouseCaptureWindow) + self.mouseCaptureWindow = nil; }]; [nc addObserver:self @@ -2007,3 +2040,15 @@ int macdrv_using_input_method(void) return ret; } + +/*********************************************************************** + * macdrv_set_mouse_capture_window + */ +void macdrv_set_mouse_capture_window(macdrv_window window) +{ + WineWindow* w = (WineWindow*)window; + + OnMainThread(^{ + [[WineApplicationController sharedController] setMouseCaptureWindow:w]; + }); +} diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index aec7a026352..fed1d475bab 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -95,6 +95,7 @@ struct macdrv_thread_data { macdrv_event_queue queue; const macdrv_event *current_event; + macdrv_window capture_window; CFDataRef keyboard_layout_uchr; CGEventSourceKeyboardType keyboard_type; int iso_keyboard; diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index eb3ed882f77..84dfd8732ad 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -136,6 +136,7 @@ extern void macdrv_beep(void) DECLSPEC_HIDDEN; extern void macdrv_set_application_icon(CFArrayRef images) DECLSPEC_HIDDEN; extern void macdrv_quit_reply(int reply) DECLSPEC_HIDDEN; extern int macdrv_using_input_method(void) DECLSPEC_HIDDEN; +extern void macdrv_set_mouse_capture_window(macdrv_window window) DECLSPEC_HIDDEN; /* cursor */ diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c index 248684d118f..2e49909bd0d 100644 --- a/dlls/winemac.drv/mouse.c +++ b/dlls/winemac.drv/mouse.c @@ -133,7 +133,7 @@ static const CFStringRef cocoa_cursor_names[] = * * Update the various window states on a mouse event. */ -static void send_mouse_input(HWND hwnd, UINT flags, int x, int y, +static void send_mouse_input(HWND hwnd, macdrv_window cocoa_window, UINT flags, int x, int y, DWORD mouse_data, BOOL drag, unsigned long time) { INPUT input; @@ -141,7 +141,8 @@ static void send_mouse_input(HWND hwnd, UINT flags, int x, int y, top_level_hwnd = GetAncestor(hwnd, GA_ROOT); - if ((flags & MOUSEEVENTF_MOVE) && (flags & MOUSEEVENTF_ABSOLUTE) && !drag) + if ((flags & MOUSEEVENTF_MOVE) && (flags & MOUSEEVENTF_ABSOLUTE) && !drag && + cocoa_window != macdrv_thread_data()->capture_window) { RECT rect; @@ -704,6 +705,24 @@ BOOL CDECL macdrv_GetCursorPos(LPPOINT pos) /*********************************************************************** + * SetCapture (MACDRV.@) + */ + void CDECL macdrv_SetCapture(HWND hwnd, UINT flags) +{ + struct macdrv_thread_data *thread_data = macdrv_thread_data(); + HWND top = GetAncestor(hwnd, GA_ROOT); + macdrv_window cocoa_window = macdrv_get_cocoa_window(top, FALSE); + + TRACE("hwnd %p top %p/%p flags 0x%08x\n", hwnd, top, cocoa_window, flags); + + if (!thread_data) return; + + thread_data->capture_window = cocoa_window; + macdrv_set_mouse_capture_window(cocoa_window); +} + + +/*********************************************************************** * SetCursor (MACDRV.@) */ void CDECL macdrv_SetCursor(HCURSOR cursor) @@ -852,7 +871,7 @@ void macdrv_mouse_button(HWND hwnd, const macdrv_event *event) } } - send_mouse_input(hwnd, flags | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, + send_mouse_input(hwnd, event->window, flags | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, event->mouse_button.x, event->mouse_button.y, data, FALSE, event->mouse_button.time_ms); } @@ -875,7 +894,7 @@ void macdrv_mouse_moved(HWND hwnd, const macdrv_event *event) if (event->type == MOUSE_MOVED_ABSOLUTE) flags |= MOUSEEVENTF_ABSOLUTE; - send_mouse_input(hwnd, flags, event->mouse_moved.x, event->mouse_moved.y, + send_mouse_input(hwnd, event->window, flags, event->mouse_moved.x, event->mouse_moved.y, 0, event->mouse_moved.drag, event->mouse_moved.time_ms); } @@ -892,10 +911,10 @@ void macdrv_mouse_scroll(HWND hwnd, const macdrv_event *event) 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, + send_mouse_input(hwnd, event->window, MOUSEEVENTF_WHEEL | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, event->mouse_scroll.x, event->mouse_scroll.y, event->mouse_scroll.y_scroll, FALSE, event->mouse_scroll.time_ms); - send_mouse_input(hwnd, MOUSEEVENTF_HWHEEL | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, + send_mouse_input(hwnd, event->window, MOUSEEVENTF_HWHEEL | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, event->mouse_scroll.x, event->mouse_scroll.y, event->mouse_scroll.x_scroll, FALSE, event->mouse_scroll.time_ms); } diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec index 29659b3a946..a51c831c1a3 100644 --- a/dlls/winemac.drv/winemac.drv.spec +++ b/dlls/winemac.drv/winemac.drv.spec @@ -28,6 +28,7 @@ @ cdecl IsClipboardFormatAvailable(long) macdrv_IsClipboardFormatAvailable @ cdecl MapVirtualKeyEx(long long long) macdrv_MapVirtualKeyEx @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx +@ cdecl SetCapture(long long) macdrv_SetCapture @ cdecl SetClipboardData(long long long) macdrv_SetClipboardData @ cdecl SetCursor(long) macdrv_SetCursor @ cdecl SetCursorPos(long long) macdrv_SetCursorPos @@ -39,13 +40,13 @@ @ cdecl SetWindowText(long wstr) macdrv_SetWindowText @ cdecl ShowWindow(long long ptr long) macdrv_ShowWindow @ cdecl SysCommand(long long long) macdrv_SysCommand +@ cdecl SystemParametersInfo(long long ptr long) macdrv_SystemParametersInfo @ cdecl ToUnicodeEx(long long ptr ptr long long long) macdrv_ToUnicodeEx @ cdecl UpdateLayeredWindow(long ptr ptr) macdrv_UpdateLayeredWindow @ cdecl VkKeyScanEx(long long) macdrv_VkKeyScanEx @ cdecl WindowMessage(long long long long) macdrv_WindowMessage @ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) macdrv_WindowPosChanged @ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) macdrv_WindowPosChanging -@ cdecl SystemParametersInfo(long long ptr long) macdrv_SystemParametersInfo # System tray @ cdecl wine_notify_icon(long ptr) -- 2.11.4.GIT