winemac: Send WM_{ENTER, EXIT}SIZEMOVE before/after window dragging and run an internal event loop during.

This simulates some of what would happen if user32 were managing the drag.  The
click in the caption would cause WM_SYSCOMMAND/SC_MOVE.  The processing of that
message is synchronous and doesn't return until the move is complete.

Some games require that "blocking" in the internal event loop to prevent them
from misbehaving during the drag.
This commit is contained in:
Ken Thomases 2013-12-11 12:50:55 -06:00 committed by Alexandre Julliard
parent b3cc34e5b0
commit f068e329c1
5 changed files with 101 additions and 3 deletions

View File

@ -1882,11 +1882,24 @@ - (BOOL) handleEvent:(NSEvent*)anEvent
WineWindow* window = (WineWindow*)[anEvent window];
if ([window isKindOfClass:[WineWindow class]])
{
macdrv_event* event;
int eventType;
if (subtype == 20)
{
[windowsBeingDragged addObject:window];
eventType = WINDOW_DRAG_BEGIN;
}
else
{
[windowsBeingDragged removeObject:window];
eventType = WINDOW_DRAG_END;
}
[self updateCursorClippingState];
event = macdrv_create_event(eventType, window);
[window.queue postEvent:event];
macdrv_release_event(event);
}
}
}

View File

@ -51,6 +51,8 @@ static const char *dbgstr_event(int type)
"WINDOW_BROUGHT_FORWARD",
"WINDOW_CLOSE_REQUESTED",
"WINDOW_DID_UNMINIMIZE",
"WINDOW_DRAG_BEGIN",
"WINDOW_DRAG_END",
"WINDOW_FRAME_CHANGED",
"WINDOW_GOT_FOCUS",
"WINDOW_LOST_FOCUS",
@ -114,6 +116,8 @@ static macdrv_event_mask get_event_mask(DWORD mask)
event_mask |= event_mask_for_type(QUERY_EVENT);
event_mask |= event_mask_for_type(RELEASE_CAPTURE);
event_mask |= event_mask_for_type(WINDOW_BROUGHT_FORWARD);
event_mask |= event_mask_for_type(WINDOW_DRAG_BEGIN);
event_mask |= event_mask_for_type(WINDOW_DRAG_END);
event_mask |= event_mask_for_type(WINDOW_MINIMIZE_REQUESTED);
event_mask |= event_mask_for_type(WINDOW_RESIZE_ENDED);
}
@ -243,6 +247,12 @@ void macdrv_handle_event(const macdrv_event *event)
case WINDOW_DID_UNMINIMIZE:
macdrv_window_did_unminimize(hwnd);
break;
case WINDOW_DRAG_BEGIN:
macdrv_window_drag_begin(hwnd);
break;
case WINDOW_DRAG_END:
macdrv_window_drag_end(hwnd);
break;
case WINDOW_FRAME_CHANGED:
macdrv_window_frame_changed(hwnd, event);
break;
@ -307,7 +317,8 @@ DWORD CDECL macdrv_MsgWaitForMultipleObjectsEx(DWORD count, const HANDLE *handle
}
if (data->current_event && data->current_event->type != QUERY_EVENT &&
data->current_event->type != APP_QUIT_REQUESTED)
data->current_event->type != APP_QUIT_REQUESTED &&
data->current_event->type != WINDOW_DRAG_BEGIN)
event_mask = 0; /* don't process nested events */
if (process_events(data->queue, event_mask)) ret = count - 1;

View File

@ -140,6 +140,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect)
unsigned int ulw_layered : 1; /* has UpdateLayeredWindow() been called for window? */
unsigned int per_pixel_alpha : 1; /* is window using per-pixel alpha? */
unsigned int minimized : 1; /* is window minimized? */
unsigned int being_dragged : 1; /* is window being dragged under Cocoa's control? */
struct window_surface *surface;
struct window_surface *unminimized_surface;
};
@ -167,6 +168,8 @@ 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_drag_begin(HWND hwnd) DECLSPEC_HIDDEN;
extern void macdrv_window_drag_end(HWND hwnd) DECLSPEC_HIDDEN;
extern BOOL query_resize_start(HWND hwnd) DECLSPEC_HIDDEN;
extern BOOL query_min_max_info(HWND hwnd) DECLSPEC_HIDDEN;

View File

@ -191,6 +191,8 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
WINDOW_BROUGHT_FORWARD,
WINDOW_CLOSE_REQUESTED,
WINDOW_DID_UNMINIMIZE,
WINDOW_DRAG_BEGIN,
WINDOW_DRAG_END,
WINDOW_FRAME_CHANGED,
WINDOW_GOT_FOCUS,
WINDOW_LOST_FOCUS,

View File

@ -1681,6 +1681,7 @@ void macdrv_window_frame_changed(HWND hwnd, const macdrv_event *event)
HWND parent;
UINT flags = SWP_NOACTIVATE | SWP_NOZORDER;
int width, height;
BOOL being_dragged;
if (!hwnd) return;
if (!(data = get_win_data(hwnd))) return;
@ -1719,16 +1720,17 @@ void macdrv_window_frame_changed(HWND hwnd, const macdrv_event *event)
TRACE("%p resizing from (%dx%d) to (%dx%d)\n", hwnd, data->window_rect.right - data->window_rect.left,
data->window_rect.bottom - data->window_rect.top, width, height);
being_dragged = data->being_dragged;
release_win_data(data);
if (event->window_frame_changed.fullscreen)
flags |= SWP_NOSENDCHANGING;
if (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE))
{
if (!event->window_frame_changed.in_resize)
if (!event->window_frame_changed.in_resize && !being_dragged)
SendMessageW(hwnd, WM_ENTERSIZEMOVE, 0, 0);
SetWindowPos(hwnd, 0, rect.left, rect.top, width, height, flags);
if (!event->window_frame_changed.in_resize)
if (!event->window_frame_changed.in_resize && !being_dragged)
SendMessageW(hwnd, WM_EXITSIZEMOVE, 0, 0);
}
}
@ -1916,6 +1918,73 @@ void macdrv_window_resize_ended(HWND hwnd)
}
/***********************************************************************
* macdrv_window_drag_begin
*
* Handler for WINDOW_DRAG_BEGIN events.
*/
void macdrv_window_drag_begin(HWND hwnd)
{
struct macdrv_win_data *data;
MSG msg;
TRACE("win %p\n", hwnd);
if (!(data = get_win_data(hwnd))) return;
if (data->being_dragged) goto done;
data->being_dragged = 1;
release_win_data(data);
SendMessageW(hwnd, WM_ENTERSIZEMOVE, 0, 0);
while (GetMessageW(&msg, 0, 0, 0))
{
if (!CallMsgFilterW(&msg, MSGF_SIZE) && msg.message != WM_KEYDOWN &&
msg.message != WM_MOUSEMOVE && msg.message != WM_LBUTTONDOWN && msg.message != WM_LBUTTONUP)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
if (msg.message == WM_EXITSIZEMOVE) break;
}
TRACE("done\n");
if ((data = get_win_data(hwnd)))
data->being_dragged = 0;
done:
release_win_data(data);
}
/***********************************************************************
* macdrv_window_drag_end
*
* Handler for WINDOW_DRAG_END events.
*/
void macdrv_window_drag_end(HWND hwnd)
{
struct macdrv_win_data *data;
BOOL being_dragged;
TRACE("win %p\n", hwnd);
if (!(data = get_win_data(hwnd))) return;
being_dragged = data->being_dragged;
release_win_data(data);
if (being_dragged)
{
/* Post this rather than sending it, so that the message loop in
macdrv_window_drag_begin() will see it. */
PostMessageW(hwnd, WM_EXITSIZEMOVE, 0, 0);
}
}
struct quit_info {
HWND *wins;
UINT capacity;