winemac: Implement SetCapture().

This commit is contained in:
Ken Thomases 2013-05-07 03:00:55 -05:00 committed by Alexandre Julliard
parent 3eee56668a
commit 1a697e15b9
6 changed files with 125 additions and 57 deletions

View File

@ -60,6 +60,7 @@ @interface WineApplicationController : NSObject <NSApplicationDelegate>
NSMutableData* screenFrameCGRects; NSMutableData* screenFrameCGRects;
WineWindow* lastTargetWindow; WineWindow* lastTargetWindow;
WineWindow* mouseCaptureWindow;
BOOL forceNextMouseMoveAbsolute; BOOL forceNextMouseMoveAbsolute;
double mouseMoveDeltaX, mouseMoveDeltaY; double mouseMoveDeltaX, mouseMoveDeltaY;
NSUInteger unmatchedMouseDowns; NSUInteger unmatchedMouseDowns;

View File

@ -82,6 +82,7 @@ @interface WineApplicationController ()
@property (retain, nonatomic) NSTimer* cursorTimer; @property (retain, nonatomic) NSTimer* cursorTimer;
@property (retain, nonatomic) NSImage* applicationIcon; @property (retain, nonatomic) NSImage* applicationIcon;
@property (readonly, nonatomic) BOOL inputSourceIsInputMethod; @property (readonly, nonatomic) BOOL inputSourceIsInputMethod;
@property (retain, nonatomic) WineWindow* mouseCaptureWindow;
- (void) setupObservations; - (void) setupObservations;
- (void) applicationDidBecomeActive:(NSNotification *)notification; - (void) applicationDidBecomeActive:(NSNotification *)notification;
@ -96,6 +97,7 @@ @implementation WineApplicationController
@synthesize keyboardType, lastFlagsChanged; @synthesize keyboardType, lastFlagsChanged;
@synthesize orderedWineWindows, applicationIcon; @synthesize orderedWineWindows, applicationIcon;
@synthesize cursorFrames, cursorTimer; @synthesize cursorFrames, cursorTimer;
@synthesize mouseCaptureWindow;
+ (void) initialize + (void) initialize
{ {
@ -1159,12 +1161,16 @@ - (void) handleMouseMove:(NSEvent*)anEvent
WineWindow* targetWindow; WineWindow* targetWindow;
BOOL drag = [anEvent type] != NSMouseMoved; BOOL drag = [anEvent type] != NSMouseMoved;
/* Because of the way -[NSWindow setAcceptsMouseMovedEvents:] works, the if (mouseCaptureWindow)
event indicates its window is the main window, even if the cursor is targetWindow = mouseCaptureWindow;
over a different window. Find the actual WineWindow that is under the else if (drag)
cursor and post the event as being for that window. */ targetWindow = (WineWindow*)[anEvent window];
if (!drag) 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]); CGPoint cgpoint = CGEventGetLocation([anEvent CGEvent]);
NSPoint point = [self flippedMouseLocation:NSPointFromCGPoint(cgpoint)]; NSPoint point = [self flippedMouseLocation:NSPointFromCGPoint(cgpoint)];
NSInteger windowUnderNumber; NSInteger windowUnderNumber;
@ -1173,8 +1179,6 @@ - (void) handleMouseMove:(NSEvent*)anEvent
belowWindowWithWindowNumber:0]; belowWindowWithWindowNumber:0];
targetWindow = (WineWindow*)[NSApp windowWithWindowNumber:windowUnderNumber]; targetWindow = (WineWindow*)[NSApp windowWithWindowNumber:windowUnderNumber];
} }
else
targetWindow = (WineWindow*)[anEvent window];
if ([targetWindow isKindOfClass:[WineWindow class]]) if ([targetWindow isKindOfClass:[WineWindow class]])
{ {
@ -1296,7 +1300,12 @@ - (void) handleMouseMove:(NSEvent*)anEvent
- (void) handleMouseButton:(NSEvent*)theEvent - (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]]) if ([window isKindOfClass:[WineWindow class]])
{ {
@ -1310,33 +1319,38 @@ - (void) handleMouseButton:(NSEvent*)theEvent
if (pressed) if (pressed)
{ {
// Test if the click was in the window's content area. if (mouseCaptureWindow)
NSPoint nspoint = [self flippedMouseLocation:NSPointFromCGPoint(pt)]; process = TRUE;
NSRect contentRect = [window contentRectForFrameRect:[window frame]]; else
process = NSPointInRect(nspoint, contentRect);
if (process && [window styleMask] & NSResizableWindowMask)
{ {
// Ignore clicks in the grow box (resize widget). // Test if the click was in the window's content area.
HIPoint origin = { 0, 0 }; NSPoint nspoint = [self flippedMouseLocation:NSPointFromCGPoint(pt)];
HIThemeGrowBoxDrawInfo info = { 0 }; NSRect contentRect = [window contentRectForFrameRect:[window frame]];
HIRect bounds; process = NSPointInRect(nspoint, contentRect);
OSStatus status; if (process && [window styleMask] & NSResizableWindowMask)
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, // Ignore clicks in the grow box (resize widget).
NSMinY(contentRect), HIPoint origin = { 0, 0 };
bounds.size.width, HIThemeGrowBoxDrawInfo info = { 0 };
bounds.size.height); HIRect bounds;
process = !NSPointInRect(nspoint, growBox); 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) if (process)
@ -1380,23 +1394,33 @@ - (void) handleMouseButton:(NSEvent*)theEvent
- (void) handleScrollWheel:(NSEvent*)theEvent - (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]]) if ([window isKindOfClass:[WineWindow class]])
{ {
CGEventRef cgevent = [theEvent CGEvent]; CGEventRef cgevent = [theEvent CGEvent];
CGPoint pt = CGEventGetLocation(cgevent); CGPoint pt = CGEventGetLocation(cgevent);
NSPoint nspoint; BOOL process;
NSRect contentRect;
if (clippingCursor) if (clippingCursor)
[self clipCursorLocation:&pt]; [self clipCursorLocation:&pt];
nspoint = [self flippedMouseLocation:NSPointFromCGPoint(pt)]; if (mouseCaptureWindow)
contentRect = [window contentRectForFrameRect:[window frame]]; 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 (process)
if (NSPointInRect(nspoint, contentRect))
{ {
macdrv_event* event; macdrv_event* event;
CGFloat x, y; CGFloat x, y;
@ -1482,31 +1506,38 @@ - (void) handleScrollWheel:(NSEvent*)theEvent
// then call -didSendEvent:. // then call -didSendEvent:.
- (BOOL) handleEvent:(NSEvent*)anEvent - (BOOL) handleEvent:(NSEvent*)anEvent
{ {
if ([anEvent type] == NSFlagsChanged) BOOL ret = FALSE;
self.lastFlagsChanged = anEvent;
return FALSE;
}
- (void) didSendEvent:(NSEvent*)anEvent
{
NSEventType type = [anEvent type]; NSEventType type = [anEvent type];
if (type == NSMouseMoved || type == NSLeftMouseDragged || if (type == NSFlagsChanged)
type == NSRightMouseDragged || type == NSOtherMouseDragged) self.lastFlagsChanged = anEvent;
else if (type == NSMouseMoved || type == NSLeftMouseDragged ||
type == NSRightMouseDragged || type == NSOtherMouseDragged)
{ {
[self handleMouseMove:anEvent]; [self handleMouseMove:anEvent];
ret = mouseCaptureWindow != nil;
} }
else if (type == NSLeftMouseDown || type == NSLeftMouseUp || else if (type == NSLeftMouseDown || type == NSLeftMouseUp ||
type == NSRightMouseDown || type == NSRightMouseUp || type == NSRightMouseDown || type == NSRightMouseUp ||
type == NSOtherMouseDown || type == NSOtherMouseUp) type == NSOtherMouseDown || type == NSOtherMouseUp)
{ {
[self handleMouseButton:anEvent]; [self handleMouseButton:anEvent];
ret = mouseCaptureWindow != nil;
} }
else if (type == NSScrollWheel) else if (type == NSScrollWheel)
{ {
[self handleScrollWheel:anEvent]; [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]; NSUInteger modifiers = [anEvent modifierFlags];
if ((modifiers & NSCommandKeyMask) && if ((modifiers & NSCommandKeyMask) &&
@ -1543,6 +1574,8 @@ - (void) setupObservations
[orderedWineWindows removeObjectIdenticalTo:window]; [orderedWineWindows removeObjectIdenticalTo:window];
if (window == lastTargetWindow) if (window == lastTargetWindow)
lastTargetWindow = nil; lastTargetWindow = nil;
if (window == self.mouseCaptureWindow)
self.mouseCaptureWindow = nil;
}]; }];
[nc addObserver:self [nc addObserver:self
@ -2007,3 +2040,15 @@ int macdrv_using_input_method(void)
return ret; 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];
});
}

View File

@ -95,6 +95,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect)
{ {
macdrv_event_queue queue; macdrv_event_queue queue;
const macdrv_event *current_event; const macdrv_event *current_event;
macdrv_window capture_window;
CFDataRef keyboard_layout_uchr; CFDataRef keyboard_layout_uchr;
CGEventSourceKeyboardType keyboard_type; CGEventSourceKeyboardType keyboard_type;
int iso_keyboard; int iso_keyboard;

View File

@ -136,6 +136,7 @@
extern void macdrv_set_application_icon(CFArrayRef images) DECLSPEC_HIDDEN; extern void macdrv_set_application_icon(CFArrayRef images) DECLSPEC_HIDDEN;
extern void macdrv_quit_reply(int reply) DECLSPEC_HIDDEN; extern void macdrv_quit_reply(int reply) DECLSPEC_HIDDEN;
extern int macdrv_using_input_method(void) DECLSPEC_HIDDEN; extern int macdrv_using_input_method(void) DECLSPEC_HIDDEN;
extern void macdrv_set_mouse_capture_window(macdrv_window window) DECLSPEC_HIDDEN;
/* cursor */ /* cursor */

View File

@ -133,7 +133,7 @@ static const CFStringRef cocoa_cursor_names[] =
* *
* Update the various window states on a mouse event. * 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) DWORD mouse_data, BOOL drag, unsigned long time)
{ {
INPUT input; 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); 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; RECT rect;
@ -703,6 +704,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.@) * SetCursor (MACDRV.@)
*/ */
@ -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, event->mouse_button.x, event->mouse_button.y,
data, FALSE, event->mouse_button.time_ms); 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) if (event->type == MOUSE_MOVED_ABSOLUTE)
flags |= MOUSEEVENTF_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); 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.x, event->mouse_scroll.y,
event->mouse_scroll.time_ms, (GetTickCount() - event->mouse_scroll.time_ms)); 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.x, event->mouse_scroll.y,
event->mouse_scroll.y_scroll, FALSE, event->mouse_scroll.time_ms); 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, event->mouse_scroll.y,
event->mouse_scroll.x_scroll, FALSE, event->mouse_scroll.time_ms); event->mouse_scroll.x_scroll, FALSE, event->mouse_scroll.time_ms);
} }

View File

@ -28,6 +28,7 @@
@ cdecl IsClipboardFormatAvailable(long) macdrv_IsClipboardFormatAvailable @ cdecl IsClipboardFormatAvailable(long) macdrv_IsClipboardFormatAvailable
@ cdecl MapVirtualKeyEx(long long long) macdrv_MapVirtualKeyEx @ cdecl MapVirtualKeyEx(long long long) macdrv_MapVirtualKeyEx
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx
@ cdecl SetCapture(long long) macdrv_SetCapture
@ cdecl SetClipboardData(long long long) macdrv_SetClipboardData @ cdecl SetClipboardData(long long long) macdrv_SetClipboardData
@ cdecl SetCursor(long) macdrv_SetCursor @ cdecl SetCursor(long) macdrv_SetCursor
@ cdecl SetCursorPos(long long) macdrv_SetCursorPos @ cdecl SetCursorPos(long long) macdrv_SetCursorPos
@ -39,13 +40,13 @@
@ cdecl SetWindowText(long wstr) macdrv_SetWindowText @ cdecl SetWindowText(long wstr) macdrv_SetWindowText
@ cdecl ShowWindow(long long ptr long) macdrv_ShowWindow @ cdecl ShowWindow(long long ptr long) macdrv_ShowWindow
@ cdecl SysCommand(long long long) macdrv_SysCommand @ 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 ToUnicodeEx(long long ptr ptr long long long) macdrv_ToUnicodeEx
@ cdecl UpdateLayeredWindow(long ptr ptr) macdrv_UpdateLayeredWindow @ cdecl UpdateLayeredWindow(long ptr ptr) macdrv_UpdateLayeredWindow
@ cdecl VkKeyScanEx(long long) macdrv_VkKeyScanEx @ cdecl VkKeyScanEx(long long) macdrv_VkKeyScanEx
@ cdecl WindowMessage(long long long long) macdrv_WindowMessage @ cdecl WindowMessage(long long long long) macdrv_WindowMessage
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) macdrv_WindowPosChanged @ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) macdrv_WindowPosChanged
@ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) macdrv_WindowPosChanging @ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) macdrv_WindowPosChanging
@ cdecl SystemParametersInfo(long long ptr long) macdrv_SystemParametersInfo
# System tray # System tray
@ cdecl wine_notify_icon(long ptr) @ cdecl wine_notify_icon(long ptr)