Commit 792b47ad authored by Ken Thomases's avatar Ken Thomases Committed by Alexandre Julliard

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.
parent 8d581d0e
......@@ -119,6 +119,8 @@ enum {
- (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 @@ int macdrv_err_on;
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 @@
NSRect nonFullscreenFrame;
NSTimeInterval enteredFullScreenTime;
int draggingPhase;
NSPoint dragStartPosition;
NSPoint dragWindowStartPosition;
BOOL ignore_windowDeminiaturize;
BOOL ignore_windowResize;
BOOL fakingClose;
......
......@@ -653,6 +653,16 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
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 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
}
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 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
[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 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
- (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 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
- (void) windowWillStartLiveResize:(NSNotification *)notification
{
[self endWindowDragging];
if (maximized)
{
macdrv_event* event;
......
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