Tim Clem : winemac.drv: Use window drag notifications when available.
Alexandre Julliard
julliard at winehq.org
Wed Sep 15 16:21:29 CDT 2021
Module: wine
Branch: master
Commit: bb28d54d08023f6cea7be2c2c52545ab7f61e30b
URL: https://source.winehq.org/git/wine.git/?a=commit;h=bb28d54d08023f6cea7be2c2c52545ab7f61e30b
Author: Tim Clem <tclem at codeweavers.com>
Date: Tue Sep 14 13:22:45 2021 -0700
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: Tim Clem <tclem at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/winemac.drv/cocoa_app.h | 1 +
dlls/winemac.drv/cocoa_app.m | 93 +++++++++++++++++++++++++++++++-------------
2 files changed, 66 insertions(+), 28 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_app.h b/dlls/winemac.drv/cocoa_app.h
index 7abea0990e9..0b70a2fd55b 100644
--- a/dlls/winemac.drv/cocoa_app.h
+++ b/dlls/winemac.drv/cocoa_app.h
@@ -131,6 +131,7 @@ enum {
BOOL beenActive;
NSMutableSet* windowsBeingDragged;
+ BOOL useDragNotifications;
}
@property (nonatomic) CGEventSourceKeyboardType keyboardType;
diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
index e296d4b4af0..fe10ee8c41d 100644
--- a/dlls/winemac.drv/cocoa_app.m
+++ b/dlls/winemac.drv/cocoa_app.m
@@ -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
More information about the wine-cvs
mailing list