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;
|
||||
|
||||
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 @@ - (id) 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 ||
|
||||
!keyWindows || !originalDisplayModes || !latentDisplayModes || !warpRecords)
|
||||
{
|
||||
|
@ -1554,32 +1569,28 @@ - (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;
|
||||
int eventType;
|
||||
|
||||
if (begin)
|
||||
{
|
||||
macdrv_event* event;
|
||||
int eventType;
|
||||
|
||||
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);
|
||||
[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 @@ - (void) handleMouseButton:(NSEvent*)theEvent
|
|||
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 @@ - (BOOL) handleEvent:(NSEvent*)anEvent
|
|||
[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 @@ - (void) setupObservations
|
|||
[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
|
||||
|
|
Loading…
Reference in New Issue