Ken Thomases : winemac: Implement a WINDOW_CLOSE_REQUESTED event to allow closing windows.

Alexandre Julliard julliard at winehq.org
Mon Jan 21 13:52:23 CST 2013


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

Author: Ken Thomases <ken at codeweavers.com>
Date:   Mon Jan 21 00:08:12 2013 -0600

winemac: Implement a WINDOW_CLOSE_REQUESTED event to allow closing windows.

---

 dlls/winemac.drv/cocoa_window.m |    4 +++
 dlls/winemac.drv/event.c        |   16 ++++++++++++-
 dlls/winemac.drv/macdrv.h       |    2 +
 dlls/winemac.drv/macdrv_cocoa.h |    5 ++++
 dlls/winemac.drv/macdrv_main.c  |    2 +
 dlls/winemac.drv/window.c       |   49 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 77 insertions(+), 1 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index e647cd0..36bd600 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -437,6 +437,10 @@ static BOOL frame_intersects_screens(NSRect frame, NSArray* screens)
      */
     - (BOOL)windowShouldClose:(id)sender
     {
+        macdrv_event event;
+        event.type = WINDOW_CLOSE_REQUESTED;
+        event.window = (macdrv_window)[self retain];
+        [queue postEvent:&event];
         return NO;
     }
 
diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c
index fcef550..effaa92 100644
--- a/dlls/winemac.drv/event.c
+++ b/dlls/winemac.drv/event.c
@@ -31,6 +31,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(event);
 /* return the name of an Mac event */
 static const char *dbgstr_event(int type)
 {
+    static const char * const event_names[] = {
+        "WINDOW_CLOSE_REQUESTED",
+    };
+
+    if (0 <= type && type < NUM_EVENT_TYPES) return event_names[type];
     return wine_dbg_sprintf("Unknown event %d", type);
 }
 
@@ -40,8 +45,14 @@ static const char *dbgstr_event(int type)
  */
 static macdrv_event_mask get_event_mask(DWORD mask)
 {
+    macdrv_event_mask event_mask = 0;
+
     if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return -1;
-    return 0;
+
+    if (mask & QS_POSTMESSAGE)
+        event_mask |= event_mask_for_type(WINDOW_CLOSE_REQUESTED);
+
+    return event_mask;
 }
 
 
@@ -62,6 +73,9 @@ void macdrv_handle_event(macdrv_event *event)
 
     switch (event->type)
     {
+    case WINDOW_CLOSE_REQUESTED:
+        macdrv_window_close_requested(hwnd);
+        break;
     default:
         TRACE("    ignoring\n");
         break;
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index 7fe4109..524408f 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -117,4 +117,6 @@ extern struct window_surface *create_surface(macdrv_window window, const RECT *r
 extern void set_window_surface(macdrv_window window, struct window_surface *window_surface) DECLSPEC_HIDDEN;
 extern void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha) DECLSPEC_HIDDEN;
 
+extern void macdrv_window_close_requested(HWND hwnd) DECLSPEC_HIDDEN;
+
 #endif  /* __WINE_MACDRV_H */
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 31bbb2d..f7f2f1d 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -121,6 +121,11 @@ extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDE
 
 
 /* event */
+enum {
+    WINDOW_CLOSE_REQUESTED,
+    NUM_EVENT_TYPES
+};
+
 typedef uint32_t macdrv_event_mask;
 
 typedef struct macdrv_event {
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c
index 4776dd3..2a9e0ac 100644
--- a/dlls/winemac.drv/macdrv_main.c
+++ b/dlls/winemac.drv/macdrv_main.c
@@ -35,6 +35,8 @@ DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
  */
 static BOOL process_attach(void)
 {
+    assert(NUM_EVENT_TYPES <= sizeof(macdrv_event_mask) * 8);
+
     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
 
     macdrv_err_on = ERR_ON(macdrv);
diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c
index cd7be9e..e22a155 100644
--- a/dlls/winemac.drv/window.c
+++ b/dlls/winemac.drv/window.c
@@ -1230,3 +1230,52 @@ void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
 done:
     release_win_data(data);
 }
+
+
+/***********************************************************************
+ *              macdrv_window_close_requested
+ *
+ * Handler for WINDOW_CLOSE_REQUESTED events.
+ */
+void macdrv_window_close_requested(HWND hwnd)
+{
+    /* Ignore the delete window request if the window has been disabled. This
+     * is to disallow applications from being closed while in a modal state.
+     */
+    if (IsWindowEnabled(hwnd))
+    {
+        HMENU hSysMenu;
+
+        if (GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) return;
+        hSysMenu = GetSystemMenu(hwnd, FALSE);
+        if (hSysMenu)
+        {
+            UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
+            if (state == 0xFFFFFFFF || (state & (MF_DISABLED | MF_GRAYED)))
+                return;
+        }
+        if (GetActiveWindow() != hwnd)
+        {
+            LRESULT ma = SendMessageW(hwnd, WM_MOUSEACTIVATE,
+                                      (WPARAM)GetAncestor(hwnd, GA_ROOT),
+                                      MAKELPARAM(HTCLOSE, WM_NCLBUTTONDOWN));
+            switch(ma)
+            {
+                case MA_NOACTIVATEANDEAT:
+                case MA_ACTIVATEANDEAT:
+                    return;
+                case MA_NOACTIVATE:
+                    break;
+                case MA_ACTIVATE:
+                case 0:
+                    SetActiveWindow(hwnd);
+                    break;
+                default:
+                    WARN("unknown WM_MOUSEACTIVATE code %d\n", (int) ma);
+                    break;
+            }
+        }
+
+        PostMessageW(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
+    }
+}




More information about the wine-cvs mailing list