Commit 9372af77 authored by Ken Thomases's avatar Ken Thomases Committed by Alexandre Julliard

winemac: Queue an event to reassert the WinAPI window position before Cocoa…

winemac: Queue an event to reassert the WinAPI window position before Cocoa adjusts its position for a display change. When the display mode changes such that the screen height changes, we'd like our windows to keep their position relative to the top-left of the primary screen. That's how WinAPI's coordinate system works and we want the WinAPI position of the window to not change just because the display mode changed. Unfortunately that's not achievable in Cocoa. Cocoa keeps the window stationary relative to the screen it's on, not necessarily the primary screen, and it's sometimes relative to the bottom-left and sometimes the top-left of that screen. So, what we do instead is queue an event to get the back end to reassert the WinAPI position of the window. This is queued before Cocoa can adjust the Cocoa position of the window which would queue a WINDOW_FRAME_CHANGED to the back end and mess up the WinAPI position. The back end's reassertion of the WinAPI position won't be processed by the Cocoa thread until after Cocoa has adjusted the position and will thus override it. It will also discard any wrong WINDOW_FRAME_CHANGED that may have been queued. Signed-off-by: 's avatarKen Thomases <ken@codeweavers.com>
parent 01a5e004
......@@ -150,6 +150,11 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
}
@interface NSWindow (WineAccessPrivateMethods)
- (id) _displayChanged;
@end
@interface WineContentView : NSView <NSTextInputClient>
{
NSMutableArray* glContexts;
......@@ -1593,6 +1598,38 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
return frameRect;
}
// This private method of NSWindow is called as Cocoa reacts to the display
// configuration changing. Among other things, it adjusts the window's
// frame based on how the screen(s) changed size. That tells Wine that the
// window has been moved. We don't want that. Rather, we want to make
// sure that the WinAPI notion of the window position is maintained/
// restored, possibly undoing or overriding Cocoa's adjustment.
//
// So, we queue a REASSERT_WINDOW_POSITION event to the back end before
// Cocoa has a chance to adjust the frame, thus preceding any resulting
// WINDOW_FRAME_CHANGED event that may get queued. The back end will
// reassert its notion of the position. That call won't get processed
// until after this method returns, so it will override whatever this
// method does to the window position. It will also discard any pending
// WINDOW_FRAME_CHANGED events.
//
// Unfortunately, the only way I've found to know when Cocoa is _about to_
// adjust the window's position due to a display change is to hook into
// this private method. This private method has remained stable from 10.6
// through 10.11. If it does change, the most likely thing is that it
// will be removed and no longer called and this fix will simply stop
// working. The only real danger would be if Apple changed the return type
// to a struct or floating-point type, which would change the calling
// convention.
- (id) _displayChanged
{
macdrv_event* event = macdrv_create_event(REASSERT_WINDOW_POSITION, self);
[queue postEvent:event];
macdrv_release_event(event);
return [super _displayChanged];
}
- (BOOL) isExcludedFromWindowsMenu
{
return !([self collectionBehavior] & NSWindowCollectionBehaviorParticipatesInCycle);
......
......@@ -45,6 +45,7 @@ static const char *dbgstr_event(int type)
"MOUSE_MOVED_ABSOLUTE",
"MOUSE_SCROLL",
"QUERY_EVENT",
"REASSERT_WINDOW_POSITION",
"RELEASE_CAPTURE",
"STATUS_ITEM_MOUSE_BUTTON",
"STATUS_ITEM_MOUSE_MOVE",
......@@ -115,6 +116,7 @@ static macdrv_event_mask get_event_mask(DWORD mask)
if (mask & QS_SENDMESSAGE)
{
event_mask |= event_mask_for_type(QUERY_EVENT);
event_mask |= event_mask_for_type(REASSERT_WINDOW_POSITION);
event_mask |= event_mask_for_type(RELEASE_CAPTURE);
event_mask |= event_mask_for_type(WINDOW_BROUGHT_FORWARD);
event_mask |= event_mask_for_type(WINDOW_CLOSE_REQUESTED);
......@@ -237,6 +239,9 @@ void macdrv_handle_event(const macdrv_event *event)
case QUERY_EVENT:
macdrv_query_event(hwnd, event);
break;
case REASSERT_WINDOW_POSITION:
macdrv_reassert_window_position(hwnd);
break;
case RELEASE_CAPTURE:
macdrv_release_capture(hwnd, event);
break;
......
......@@ -175,6 +175,7 @@ extern void macdrv_window_resize_ended(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 void macdrv_reassert_window_position(HWND hwnd) DECLSPEC_HIDDEN;
extern BOOL query_resize_size(HWND hwnd, macdrv_query *query) DECLSPEC_HIDDEN;
extern BOOL query_resize_start(HWND hwnd) DECLSPEC_HIDDEN;
extern BOOL query_min_max_info(HWND hwnd) DECLSPEC_HIDDEN;
......
......@@ -195,6 +195,7 @@ enum {
MOUSE_MOVED_ABSOLUTE,
MOUSE_SCROLL,
QUERY_EVENT,
REASSERT_WINDOW_POSITION,
RELEASE_CAPTURE,
STATUS_ITEM_MOUSE_BUTTON,
STATUS_ITEM_MOUSE_MOVE,
......
......@@ -1682,12 +1682,7 @@ LRESULT CDECL macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
macdrv_reset_device_metrics();
return 0;
case WM_MACDRV_DISPLAYCHANGE:
if ((data = get_win_data(hwnd)))
{
if (data->cocoa_window && data->on_screen)
sync_window_position(data, SWP_NOZORDER | SWP_NOACTIVATE, NULL, NULL);
release_win_data(data);
}
macdrv_reassert_window_position(hwnd);
SendMessageW(hwnd, WM_DISPLAYCHANGE, wp, lp);
return 0;
case WM_MACDRV_ACTIVATE_ON_FOLLOWING_FOCUS:
......@@ -2244,6 +2239,23 @@ void macdrv_window_drag_end(HWND hwnd)
}
/***********************************************************************
* macdrv_reassert_window_position
*
* Handler for REASSERT_WINDOW_POSITION events.
*/
void macdrv_reassert_window_position(HWND hwnd)
{
struct macdrv_win_data *data = get_win_data(hwnd);
if (data)
{
if (data->cocoa_window && data->on_screen)
sync_window_position(data, SWP_NOZORDER | SWP_NOACTIVATE, NULL, NULL);
release_win_data(data);
}
}
struct quit_info {
HWND *wins;
UINT capacity;
......
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