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

Alexandre Julliard julliard at winehq.org
Thu Dec 12 12:48:07 CST 2013


Module: wine
Branch: master
Commit: f068e329c1fe45a6a55c7a3ea013740dbb4f41db
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f068e329c1fe45a6a55c7a3ea013740dbb4f41db

Author: Ken Thomases <ken at codeweavers.com>
Date:   Wed Dec 11 12:50:55 2013 -0600

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.

---

 dlls/winemac.drv/cocoa_app.m    |   13 +++++++
 dlls/winemac.drv/event.c        |   13 ++++++-
 dlls/winemac.drv/macdrv.h       |    3 ++
 dlls/winemac.drv/macdrv_cocoa.h |    2 +
 dlls/winemac.drv/window.c       |   73 +++++++++++++++++++++++++++++++++++++-
 5 files changed, 101 insertions(+), 3 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
index 857c019..ce43e27 100644
--- a/dlls/winemac.drv/cocoa_app.m
+++ b/dlls/winemac.drv/cocoa_app.m
@@ -1882,11 +1882,24 @@ int macdrv_err_on;
                 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);
                 }
             }
         }
diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c
index 77df582..13f55f5 100644
--- a/dlls/winemac.drv/event.c
+++ b/dlls/winemac.drv/event.c
@@ -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;
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index 32a342b..2234cca 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -140,6 +140,7 @@ struct macdrv_win_data
     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 @@ extern void macdrv_window_minimize_requested(HWND hwnd) DECLSPEC_HIDDEN;
 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;
 
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index f7ffc50..5073db8 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -191,6 +191,8 @@ enum {
     WINDOW_BROUGHT_FORWARD,
     WINDOW_CLOSE_REQUESTED,
     WINDOW_DID_UNMINIMIZE,
+    WINDOW_DRAG_BEGIN,
+    WINDOW_DRAG_END,
     WINDOW_FRAME_CHANGED,
     WINDOW_GOT_FOCUS,
     WINDOW_LOST_FOCUS,
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c
index 6360c32..bd710ce 100644
--- a/dlls/winemac.drv/window.c
+++ b/dlls/winemac.drv/window.c
@@ -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;




More information about the wine-cvs mailing list