Commit bb28d54d authored by Tim Clem's avatar Tim Clem Committed by Alexandre Julliard

winemac.drv: Use window drag notifications when available.

When running on macOS 10.12+, there are private notification center messages we can use to reliably detect when a window is being dragged by its titlebar. These are less finicky than the current combination of an undocumented event subtype and a left mouse up. Signed-off-by: 's avatarTim Clem <tclem@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent b5e17b66
......@@ -131,6 +131,7 @@ enum {
BOOL beenActive;
NSMutableSet* windowsBeingDragged;
BOOL useDragNotifications;
}
@property (nonatomic) CGEventSourceKeyboardType keyboardType;
......
......@@ -27,6 +27,12 @@
static NSString* const WineAppWaitQueryResponseMode = @"WineAppWaitQueryResponseMode";
// Private notifications that are reliably dispatched when a window is moved by dragging its titlebar.
// The object of the notification is the window being dragged.
// Available in macOS 10.12+
static NSString* const NSWindowWillStartDraggingNotification = @"NSWindowWillStartDraggingNotification";
static NSString* const NSWindowDidEndDraggingNotification = @"NSWindowDidEndDraggingNotification";
int macdrv_err_on;
......@@ -181,6 +187,15 @@ static NSString* WineLocalizedString(unsigned int stringID)
windowsBeingDragged = [[NSMutableSet alloc] init];
// On macOS 10.12+, use notifications to more reliably detect when windows are being dragged.
if ([NSProcessInfo instancesRespondToSelector:@selector(isOperatingSystemAtLeastVersion:)])
{
NSOperatingSystemVersion requiredVersion = { 10, 12, 0 };
useDragNotifications = [[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:requiredVersion];
}
else
useDragNotifications = NO;
if (!requests || !requestsManipQueue || !eventQueues || !eventQueuesLock ||
!keyWindows || !originalDisplayModes || !latentDisplayModes || !warpRecords)
{
......@@ -1554,32 +1569,28 @@ static NSString* WineLocalizedString(unsigned int stringID)
}
}
- (void) handleWindowDrag:(NSEvent*)anEvent begin:(BOOL)begin
- (void) handleWindowDrag:(WineWindow*)window begin:(BOOL)begin
{
WineWindow* window = (WineWindow*)[anEvent window];
if ([window isKindOfClass:[WineWindow class]])
{
macdrv_event* event;
int eventType;
if (begin)
{
[windowsBeingDragged addObject:window];
eventType = WINDOW_DRAG_BEGIN;
}
else
{
[windowsBeingDragged removeObject:window];
eventType = WINDOW_DRAG_END;
}
[self updateCursorClippingState];
macdrv_event* event;
int eventType;
event = macdrv_create_event(eventType, window);
if (eventType == WINDOW_DRAG_BEGIN)
event->window_drag_begin.no_activate = [NSEvent wine_commandKeyDown];
[window.queue postEvent:event];
macdrv_release_event(event);
if (begin)
{
[windowsBeingDragged addObject:window];
eventType = WINDOW_DRAG_BEGIN;
}
else
{
[windowsBeingDragged removeObject:window];
eventType = WINDOW_DRAG_END;
}
[self updateCursorClippingState];
event = macdrv_create_event(eventType, window);
if (eventType == WINDOW_DRAG_BEGIN)
event->window_drag_begin.no_activate = [NSEvent wine_commandKeyDown];
[window.queue postEvent:event];
macdrv_release_event(event);
}
- (void) handleMouseMove:(NSEvent*)anEvent
......@@ -1736,8 +1747,13 @@ static NSString* WineLocalizedString(unsigned int stringID)
WineWindow* windowBroughtForward = nil;
BOOL process = FALSE;
if (type == NSEventTypeLeftMouseUp && [windowsBeingDragged count])
[self handleWindowDrag:theEvent begin:NO];
if (!useDragNotifications &&
type == NSEventTypeLeftMouseUp &&
[windowsBeingDragged count] &&
[window isKindOfClass:[WineWindow class]])
{
[self handleWindowDrag:window begin:NO];
}
if ([window isKindOfClass:[WineWindow class]] &&
type == NSEventTypeLeftMouseDown &&
......@@ -2085,15 +2101,16 @@ static NSString* WineLocalizedString(unsigned int stringID)
[window postKeyEvent:anEvent];
}
}
else if (type == NSEventTypeAppKitDefined)
else if (!useDragNotifications && type == NSEventTypeAppKitDefined)
{
WineWindow *window = (WineWindow *)[anEvent window];
short subtype = [anEvent subtype];
// These subtypes are not documented but they appear to mean
// "a window is being dragged" and "a window is no longer being
// dragged", respectively.
if (subtype == 20 || subtype == 21)
[self handleWindowDrag:anEvent begin:(subtype == 20)];
if ((subtype == 20 || subtype == 21) && [window isKindOfClass:[WineWindow class]])
[self handleWindowDrag:window begin:(subtype == 20)];
}
return ret;
......@@ -2155,6 +2172,26 @@ static NSString* WineLocalizedString(unsigned int stringID)
[self updateCursorClippingState];
}];
if (useDragNotifications) {
[nc addObserverForName:NSWindowWillStartDraggingNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note){
NSWindow* window = [note object];
if ([window isKindOfClass:[WineWindow class]])
[self handleWindowDrag:(WineWindow *)window begin:YES];
}];
[nc addObserverForName:NSWindowDidEndDraggingNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note){
NSWindow* window = [note object];
if ([window isKindOfClass:[WineWindow class]])
[self handleWindowDrag:(WineWindow *)window begin:NO];
}];
}
[nc addObserver:self
selector:@selector(keyboardSelectionDidChange)
name:NSTextInputContextKeyboardSelectionDidChangeNotification
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment