winemac: Allow the user to attempt to resize a maximized window and try to restore it if they do.

OS X doesn't have the same concept of maximized windows as Windows does.
There's no mode that prevents a normally-resizable window from being resized.
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 resize a window that's
maximized.

To get similar behavior while still respecting Win32 semantics, we now let the
user try to resize maximized windows.  (The resize cursors are shown at the
edges of the window frame.)  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 change its size.

The user expects to resize 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:
Ken Thomases 2015-03-23 18:58:06 -05:00 committed by Alexandre Julliard
parent 0a92329914
commit 8d581d0e48
5 changed files with 64 additions and 12 deletions

View File

@ -650,7 +650,7 @@ - (void) dealloc
- (BOOL) preventResizing
{
BOOL preventForClipping = cursor_clipping_locks_windows && [[WineApplicationController sharedController] clippingCursor];
return ([self styleMask] & NSResizableWindowMask) && (disabled || !resizable || maximized || preventForClipping);
return ([self styleMask] & NSResizableWindowMask) && (disabled || !resizable || preventForClipping);
}
- (void) adjustFeaturesForState
@ -814,6 +814,16 @@ - (void) postDidUnminimizeEvent
macdrv_release_event(event);
}
- (void) sendResizeStartQuery
{
macdrv_query* query = macdrv_create_query();
query->type = QUERY_RESIZE_START;
query->window = (macdrv_window)[self retain];
[self.queue query:query timeout:0.3];
macdrv_release_query(query);
}
- (void) setMacDrvState:(const struct macdrv_window_state*)state
{
NSWindowCollectionBehavior behavior;
@ -892,6 +902,9 @@ - (void) setMacDrvState:(const struct macdrv_window_state*)state
{
maximized = state->maximized;
[self adjustFeaturesForState];
if (!maximized && [self inLiveResize])
[self sendResizeStartQuery];
}
behavior = NSWindowCollectionBehaviorDefault;
@ -1797,9 +1810,12 @@ - (void)windowDidDeminiaturize:(NSNotification *)notification
- (void) windowDidEndLiveResize:(NSNotification *)notification
{
macdrv_event* event = macdrv_create_event(WINDOW_RESIZE_ENDED, self);
[queue postEvent:event];
macdrv_release_event(event);
if (!maximized)
{
macdrv_event* event = macdrv_create_event(WINDOW_RESIZE_ENDED, self);
[queue postEvent:event];
macdrv_release_event(event);
}
self.liveResizeDisplayTimer = nil;
}
@ -1958,6 +1974,9 @@ - (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize
{
if ([self inLiveResize])
{
if (maximized)
return self.frame.size;
NSRect rect;
macdrv_query* query;
@ -1992,12 +2011,21 @@ - (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize
- (void) windowWillStartLiveResize:(NSNotification *)notification
{
macdrv_query* query = macdrv_create_query();
query->type = QUERY_RESIZE_START;
query->window = (macdrv_window)[self retain];
if (maximized)
{
macdrv_event* event;
NSRect frame = [self contentRectForFrameRect:self.frame];
[self.queue query:query timeout:0.3];
macdrv_release_query(query);
[[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);
}
else
[self sendResizeStartQuery];
frameAtResizeStart = [self frame];
resizingFromLeft = resizingFromTop = FALSE;

View File

@ -280,7 +280,7 @@ void macdrv_handle_event(const macdrv_event *event)
macdrv_window_resize_ended(hwnd);
break;
case WINDOW_RESTORE_REQUESTED:
macdrv_window_restore_requested(hwnd);
macdrv_window_restore_requested(hwnd, event);
break;
default:
TRACE(" ignoring\n");

View File

@ -172,7 +172,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect)
extern void macdrv_window_did_unminimize(HWND hwnd) DECLSPEC_HIDDEN;
extern void macdrv_window_brought_forward(HWND hwnd) DECLSPEC_HIDDEN;
extern void macdrv_window_resize_ended(HWND hwnd) DECLSPEC_HIDDEN;
extern void macdrv_window_restore_requested(HWND hwnd) DECLSPEC_HIDDEN;
extern void macdrv_window_restore_requested(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN;
extern void macdrv_window_drag_begin(HWND hwnd) DECLSPEC_HIDDEN;
extern void macdrv_window_drag_end(HWND hwnd) DECLSPEC_HIDDEN;
extern BOOL query_resize_size(HWND hwnd, macdrv_query *query) DECLSPEC_HIDDEN;

View File

@ -291,6 +291,10 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
unsigned long serial;
void *tried_windows;
} window_got_focus;
struct {
int keep_frame;
CGRect frame;
} window_restore_requested;
};
} macdrv_event;

View File

@ -2139,8 +2139,28 @@ void macdrv_window_resize_ended(HWND hwnd)
* Handler for WINDOW_RESTORE_REQUESTED events. This is specifically
* for restoring from maximized, not from minimized.
*/
void macdrv_window_restore_requested(HWND hwnd)
void macdrv_window_restore_requested(HWND hwnd, const macdrv_event *event)
{
if (event->window_restore_requested.keep_frame && hwnd)
{
DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
struct macdrv_win_data *data;
if ((style & WS_MAXIMIZE) && (style & WS_VISIBLE) && (data = get_win_data(hwnd)))
{
RECT rect;
HWND parent = GetAncestor(hwnd, GA_PARENT);
rect = rect_from_cgrect(event->window_restore_requested.frame);
macdrv_mac_to_window_rect(data, &rect);
MapWindowPoints(0, parent, (POINT *)&rect, 2);
release_win_data(data);
SetInternalWindowPos(hwnd, SW_SHOW, &rect, NULL);
}
}
perform_window_command(hwnd, WS_MAXIMIZE, 0, SC_RESTORE, HTMAXBUTTON);
}