winemac: Restore a maximized window if a user tries to move it by dragging its title bar.
OS X doesn't have the same concept of maximized windows as Windows does. There's no mode that prevents a normally-movable window from being moved. If a window is "zoomed", it mostly fills the screen but the user can still move or resize it, at which point it ceases to be in the zoomed state. So, users are confused and frustrated when they can't move a window that's maximized. To get similar behavior while still respecting Win32 semantics, we detect when the user tries to move a maximized window. When they start, a request is submitted to the app to restore the window. Unless and until the window is restored, we don't actually allow the window to move. The user expects to move the window from its current (maximized) position. It should not jump to its normal position upon being restored. So, we set the window's normal position to its current position before restoring it.
This commit is contained in:
parent
8d581d0e48
commit
792b47ad3b
|
@ -119,6 +119,8 @@ - (BOOL) waitUntilQueryDone:(int*)done timeout:(NSDate*)timeout processEvents:(B
|
|||
- (void) keyboardSelectionDidChange;
|
||||
- (void) noteKey:(uint16_t)keyCode pressed:(BOOL)pressed;
|
||||
|
||||
- (void) window:(WineWindow*)window isBeingDragged:(BOOL)dragged;
|
||||
|
||||
- (void) flipRect:(NSRect*)rect;
|
||||
|
||||
- (WineWindow*) frontWineWindow;
|
||||
|
|
|
@ -1436,6 +1436,15 @@ - (void) noteKey:(uint16_t)keyCode pressed:(BOOL)pressed
|
|||
pressedKeyCodes[index] &= ~mask;
|
||||
}
|
||||
|
||||
- (void) window:(WineWindow*)window isBeingDragged:(BOOL)dragged
|
||||
{
|
||||
if (dragged)
|
||||
[windowsBeingDragged addObject:window];
|
||||
else
|
||||
[windowsBeingDragged removeObject:window];
|
||||
[self updateCursorClippingState];
|
||||
}
|
||||
|
||||
- (void) handleMouseMove:(NSEvent*)anEvent
|
||||
{
|
||||
WineWindow* targetWindow;
|
||||
|
|
|
@ -69,6 +69,10 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
|||
NSRect nonFullscreenFrame;
|
||||
NSTimeInterval enteredFullScreenTime;
|
||||
|
||||
int draggingPhase;
|
||||
NSPoint dragStartPosition;
|
||||
NSPoint dragWindowStartPosition;
|
||||
|
||||
BOOL ignore_windowDeminiaturize;
|
||||
BOOL ignore_windowResize;
|
||||
BOOL fakingClose;
|
||||
|
|
|
@ -653,6 +653,16 @@ - (BOOL) preventResizing
|
|||
return ([self styleMask] & NSResizableWindowMask) && (disabled || !resizable || preventForClipping);
|
||||
}
|
||||
|
||||
- (BOOL) allowsMovingWithMaximized:(BOOL)inMaximized
|
||||
{
|
||||
if (allow_immovable_windows && (disabled || inMaximized))
|
||||
return NO;
|
||||
else if (cursor_clipping_locks_windows && [[WineApplicationController sharedController] clippingCursor])
|
||||
return NO;
|
||||
else
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) adjustFeaturesForState
|
||||
{
|
||||
NSUInteger style = [self styleMask];
|
||||
|
@ -682,14 +692,7 @@ - (void) adjustFeaturesForState
|
|||
}
|
||||
|
||||
if (allow_immovable_windows || cursor_clipping_locks_windows)
|
||||
{
|
||||
if (allow_immovable_windows && (disabled || maximized))
|
||||
[self setMovable:NO];
|
||||
else if (cursor_clipping_locks_windows && [[WineApplicationController sharedController] clippingCursor])
|
||||
[self setMovable:NO];
|
||||
else
|
||||
[self setMovable:YES];
|
||||
}
|
||||
[self setMovable:[self allowsMovingWithMaximized:maximized]];
|
||||
}
|
||||
|
||||
- (void) adjustFullScreenBehavior:(NSWindowCollectionBehavior)behavior
|
||||
|
@ -1543,6 +1546,22 @@ - (void) updateForCursorClipping
|
|||
[self adjustFeaturesForState];
|
||||
}
|
||||
|
||||
- (void) endWindowDragging
|
||||
{
|
||||
if (draggingPhase)
|
||||
{
|
||||
if (draggingPhase == 3)
|
||||
{
|
||||
macdrv_event* event = macdrv_create_event(WINDOW_DRAG_END, self);
|
||||
[queue postEvent:event];
|
||||
macdrv_release_event(event);
|
||||
}
|
||||
|
||||
draggingPhase = 0;
|
||||
[[WineApplicationController sharedController] window:self isBeingDragged:NO];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ---------- NSWindow method overrides ----------
|
||||
|
@ -1603,14 +1622,104 @@ - (void) makeKeyAndOrderFront:(id)sender
|
|||
|
||||
- (void) sendEvent:(NSEvent*)event
|
||||
{
|
||||
NSEventType type = event.type;
|
||||
|
||||
/* NSWindow consumes certain key-down events as part of Cocoa's keyboard
|
||||
interface control. For example, Control-Tab switches focus among
|
||||
views. We want to bypass that feature, so directly route key-down
|
||||
events to -keyDown:. */
|
||||
if ([event type] == NSKeyDown)
|
||||
if (type == NSKeyDown)
|
||||
[[self firstResponder] keyDown:event];
|
||||
else
|
||||
{
|
||||
if (!draggingPhase && maximized && ![self isMovable] &&
|
||||
![self allowsMovingWithMaximized:YES] && [self allowsMovingWithMaximized:NO] &&
|
||||
type == NSLeftMouseDown && (self.styleMask & NSTitledWindowMask))
|
||||
{
|
||||
NSRect titleBar = self.frame;
|
||||
NSRect contentRect = [self contentRectForFrameRect:titleBar];
|
||||
titleBar.size.height = NSMaxY(titleBar) - NSMaxY(contentRect);
|
||||
titleBar.origin.y = NSMaxY(contentRect);
|
||||
|
||||
dragStartPosition = [self convertBaseToScreen:event.locationInWindow];
|
||||
|
||||
if (NSMouseInRect(dragStartPosition, titleBar, NO))
|
||||
{
|
||||
static const NSWindowButton buttons[] = {
|
||||
NSWindowCloseButton,
|
||||
NSWindowMiniaturizeButton,
|
||||
NSWindowZoomButton,
|
||||
NSWindowFullScreenButton,
|
||||
};
|
||||
BOOL hitButton = NO;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(buttons) / sizeof(buttons[0]); i++)
|
||||
{
|
||||
NSButton* button;
|
||||
|
||||
if (buttons[i] == NSWindowFullScreenButton && ![self respondsToSelector:@selector(toggleFullScreen:)])
|
||||
continue;
|
||||
|
||||
button = [self standardWindowButton:buttons[i]];
|
||||
if ([button hitTest:[button.superview convertPoint:event.locationInWindow fromView:nil]])
|
||||
{
|
||||
hitButton = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hitButton)
|
||||
{
|
||||
draggingPhase = 1;
|
||||
dragWindowStartPosition = NSMakePoint(NSMinX(titleBar), NSMaxY(titleBar));
|
||||
[[WineApplicationController sharedController] window:self isBeingDragged:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (draggingPhase && (type == NSLeftMouseDragged || type == NSLeftMouseUp))
|
||||
{
|
||||
if ([self isMovable])
|
||||
{
|
||||
NSPoint point = [self convertBaseToScreen:event.locationInWindow];
|
||||
NSPoint newTopLeft = dragWindowStartPosition;
|
||||
|
||||
newTopLeft.x += point.x - dragStartPosition.x;
|
||||
newTopLeft.y += point.y - dragStartPosition.y;
|
||||
|
||||
if (draggingPhase == 2)
|
||||
{
|
||||
macdrv_event* event = macdrv_create_event(WINDOW_DRAG_BEGIN, self);
|
||||
[queue postEvent:event];
|
||||
macdrv_release_event(event);
|
||||
|
||||
draggingPhase = 3;
|
||||
}
|
||||
|
||||
[self setFrameTopLeftPoint:newTopLeft];
|
||||
}
|
||||
else if (draggingPhase == 1 && type == NSLeftMouseDragged)
|
||||
{
|
||||
macdrv_event* event;
|
||||
NSRect frame = [self contentRectForFrameRect:self.frame];
|
||||
|
||||
[[WineApplicationController sharedController] flipRect:&frame];
|
||||
|
||||
event = macdrv_create_event(WINDOW_RESTORE_REQUESTED, self);
|
||||
event->window_restore_requested.keep_frame = TRUE;
|
||||
event->window_restore_requested.frame = NSRectToCGRect(frame);
|
||||
[queue postEvent:event];
|
||||
macdrv_release_event(event);
|
||||
|
||||
draggingPhase = 2;
|
||||
}
|
||||
|
||||
if (type == NSLeftMouseUp)
|
||||
[self endWindowDragging];
|
||||
}
|
||||
|
||||
[super sendEvent:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) miniaturize:(id)sender
|
||||
|
@ -2011,6 +2120,8 @@ - (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize
|
|||
|
||||
- (void) windowWillStartLiveResize:(NSNotification *)notification
|
||||
{
|
||||
[self endWindowDragging];
|
||||
|
||||
if (maximized)
|
||||
{
|
||||
macdrv_event* event;
|
||||
|
|
Loading…
Reference in New Issue