From ed367c504df4703677abfa42dc7620cc58a55d5f Mon Sep 17 00:00:00 2001 From: Ken Thomases Date: Mon, 21 Jan 2013 00:08:12 -0600 Subject: [PATCH] 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 deletion(-) diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index e647cd02eb2..36bd600b299 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -437,6 +437,10 @@ - (BOOL) validateMenuItem:(NSMenuItem *)menuItem */ - (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 fcef5500829..effaa9239d8 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 7fe41095f2c..524408f79f1 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -117,4 +117,6 @@ static inline RECT rect_from_cgrect(CGRect cgrect) 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 31bbb2d0b10..f7f2f1d38e5 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -121,6 +121,11 @@ /* 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 4776dd31452..2a9e0ac3255 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 cd7be9e670c..e22a155c941 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); + } +}