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@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b5e17b669a
commit
bb28d54d08
|
@ -131,6 +131,7 @@ @interface WineApplicationController : NSObject <NSApplicationDelegate>
|
||||||
BOOL beenActive;
|
BOOL beenActive;
|
||||||
|
|
||||||
NSMutableSet* windowsBeingDragged;
|
NSMutableSet* windowsBeingDragged;
|
||||||
|
BOOL useDragNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic) CGEventSourceKeyboardType keyboardType;
|
@property (nonatomic) CGEventSourceKeyboardType keyboardType;
|
||||||
|
|
|
@ -27,6 +27,12 @@
|
||||||
|
|
||||||
static NSString* const WineAppWaitQueryResponseMode = @"WineAppWaitQueryResponseMode";
|
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;
|
int macdrv_err_on;
|
||||||
|
|
||||||
|
@ -181,6 +187,15 @@ - (id) init
|
||||||
|
|
||||||
windowsBeingDragged = [[NSMutableSet alloc] init];
|
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 ||
|
if (!requests || !requestsManipQueue || !eventQueues || !eventQueuesLock ||
|
||||||
!keyWindows || !originalDisplayModes || !latentDisplayModes || !warpRecords)
|
!keyWindows || !originalDisplayModes || !latentDisplayModes || !warpRecords)
|
||||||
{
|
{
|
||||||
|
@ -1554,10 +1569,7 @@ - (void) windowWillOrderOut:(WineWindow*)window
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (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;
|
macdrv_event* event;
|
||||||
int eventType;
|
int eventType;
|
||||||
|
@ -1580,7 +1592,6 @@ - (void) handleWindowDrag:(NSEvent*)anEvent begin:(BOOL)begin
|
||||||
[window.queue postEvent:event];
|
[window.queue postEvent:event];
|
||||||
macdrv_release_event(event);
|
macdrv_release_event(event);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
- (void) handleMouseMove:(NSEvent*)anEvent
|
- (void) handleMouseMove:(NSEvent*)anEvent
|
||||||
{
|
{
|
||||||
|
@ -1736,8 +1747,13 @@ - (void) handleMouseButton:(NSEvent*)theEvent
|
||||||
WineWindow* windowBroughtForward = nil;
|
WineWindow* windowBroughtForward = nil;
|
||||||
BOOL process = FALSE;
|
BOOL process = FALSE;
|
||||||
|
|
||||||
if (type == NSEventTypeLeftMouseUp && [windowsBeingDragged count])
|
if (!useDragNotifications &&
|
||||||
[self handleWindowDrag:theEvent begin:NO];
|
type == NSEventTypeLeftMouseUp &&
|
||||||
|
[windowsBeingDragged count] &&
|
||||||
|
[window isKindOfClass:[WineWindow class]])
|
||||||
|
{
|
||||||
|
[self handleWindowDrag:window begin:NO];
|
||||||
|
}
|
||||||
|
|
||||||
if ([window isKindOfClass:[WineWindow class]] &&
|
if ([window isKindOfClass:[WineWindow class]] &&
|
||||||
type == NSEventTypeLeftMouseDown &&
|
type == NSEventTypeLeftMouseDown &&
|
||||||
|
@ -2085,15 +2101,16 @@ - (BOOL) handleEvent:(NSEvent*)anEvent
|
||||||
[window postKeyEvent:anEvent];
|
[window postKeyEvent:anEvent];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == NSEventTypeAppKitDefined)
|
else if (!useDragNotifications && type == NSEventTypeAppKitDefined)
|
||||||
{
|
{
|
||||||
|
WineWindow *window = (WineWindow *)[anEvent window];
|
||||||
short subtype = [anEvent subtype];
|
short subtype = [anEvent subtype];
|
||||||
|
|
||||||
// These subtypes are not documented but they appear to mean
|
// These subtypes are not documented but they appear to mean
|
||||||
// "a window is being dragged" and "a window is no longer being
|
// "a window is being dragged" and "a window is no longer being
|
||||||
// dragged", respectively.
|
// dragged", respectively.
|
||||||
if (subtype == 20 || subtype == 21)
|
if ((subtype == 20 || subtype == 21) && [window isKindOfClass:[WineWindow class]])
|
||||||
[self handleWindowDrag:anEvent begin:(subtype == 20)];
|
[self handleWindowDrag:window begin:(subtype == 20)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2155,6 +2172,26 @@ - (void) setupObservations
|
||||||
[self updateCursorClippingState];
|
[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
|
[nc addObserver:self
|
||||||
selector:@selector(keyboardSelectionDidChange)
|
selector:@selector(keyboardSelectionDidChange)
|
||||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||||
|
|
Loading…
Reference in New Issue