diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h index d7ad62e2ea2..e1e59f477b0 100644 --- a/dlls/winemac.drv/cocoa_window.h +++ b/dlls/winemac.drv/cocoa_window.h @@ -21,6 +21,9 @@ #import +@class WineEventQueue; + + @interface WineWindow : NSPanel { NSUInteger normalStyleMask; @@ -29,6 +32,8 @@ @interface WineWindow : NSPanel BOOL floating; WineWindow* latentParentWindow; + WineEventQueue* queue; + void* surface; pthread_mutex_t* surface_mutex; diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 7f073a82d1e..4ca7a092b3e 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -22,6 +22,7 @@ #include "macdrv_cocoa.h" #import "cocoa_app.h" +#import "cocoa_event.h" static NSUInteger style_mask_for_features(const struct macdrv_window_features* wf) @@ -65,6 +66,8 @@ @interface WineWindow () @property (nonatomic) BOOL floating; @property (retain, nonatomic) NSWindow* latentParentWindow; +@property (retain, nonatomic) WineEventQueue* queue; + @property (nonatomic) void* surface; @property (nonatomic) pthread_mutex_t* surface_mutex; @@ -159,7 +162,7 @@ - (void) drawRect:(NSRect)rect @implementation WineWindow - @synthesize disabled, noActivate, floating, latentParentWindow; + @synthesize disabled, noActivate, floating, latentParentWindow, queue; @synthesize surface, surface_mutex; @synthesize shape, shapeChangedSinceLastDraw; @synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue; @@ -167,6 +170,7 @@ @implementation WineWindow + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)wf windowFrame:(NSRect)window_frame + queue:(WineEventQueue*)queue { WineWindow* window; WineContentView* contentView; @@ -191,6 +195,7 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w [window setHasShadow:wf->shadow]; [window setColorSpace:[NSColorSpace genericRGBColorSpace]]; [window setDelegate:window]; + window.queue = queue; contentView = [[[WineContentView alloc] initWithFrame:NSZeroRect] autorelease]; if (!contentView) @@ -204,6 +209,7 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w - (void) dealloc { + [queue release]; [latentParentWindow release]; [shape release]; [super dealloc]; @@ -441,13 +447,14 @@ - (BOOL)windowShouldClose:(id)sender * title bar, close box, etc.). */ macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf, - CGRect frame) + CGRect frame, macdrv_event_queue queue) { __block WineWindow* window; OnMainThread(^{ window = [[WineWindow createWindowWithFeatures:wf - windowFrame:NSRectFromCGRect(frame)] retain]; + windowFrame:NSRectFromCGRect(frame) + queue:(WineEventQueue*)queue] retain]; }); return (macdrv_window)window; @@ -463,6 +470,7 @@ void macdrv_destroy_cocoa_window(macdrv_window w) NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; WineWindow* window = (WineWindow*)w; + [window.queue discardEventsMatchingMask:-1 forWindow:window]; [window close]; [window release]; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 15e4062b198..dee2fd8d210 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -80,6 +80,21 @@ static inline RECT rect_from_cgrect(CGRect cgrect) WM_MACDRV_SET_WIN_REGION = 0x80001000, }; +struct macdrv_thread_data +{ + macdrv_event_queue queue; +}; + +extern DWORD thread_data_tls_index DECLSPEC_HIDDEN; + +extern struct macdrv_thread_data *macdrv_init_thread_data(void) DECLSPEC_HIDDEN; + +static inline struct macdrv_thread_data *macdrv_thread_data(void) +{ + return TlsGetValue(thread_data_tls_index); +} + + /* macdrv private window data */ struct macdrv_win_data { diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 2118bacb614..71b4c3295cc 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -161,8 +161,9 @@ extern int macdrv_get_event_from_queue(macdrv_event_queue queue, }; extern macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf, - CGRect frame) DECLSPEC_HIDDEN; + CGRect frame, macdrv_event_queue queue) DECLSPEC_HIDDEN; extern void macdrv_destroy_cocoa_window(macdrv_window w) DECLSPEC_HIDDEN; +extern void* macdrv_get_window_hwnd(macdrv_window w) DECLSPEC_HIDDEN; extern void macdrv_set_cocoa_window_features(macdrv_window w, const struct macdrv_window_features* wf) DECLSPEC_HIDDEN; extern void macdrv_set_cocoa_window_state(macdrv_window w, diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index e209f3d6127..4776dd31452 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -22,32 +22,119 @@ #include "config.h" #include "macdrv.h" +#include "wine/server.h" WINE_DEFAULT_DEBUG_CHANNEL(macdrv); +DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES; + + /*********************************************************************** - * MACDRV initialisation routine + * process_attach */ -BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) +static BOOL process_attach(void) +{ + if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; + + macdrv_err_on = ERR_ON(macdrv); + if (macdrv_start_cocoa_app()) + { + ERR("Failed to start Cocoa app main loop\n"); + return FALSE; + } + + return TRUE; +} + + +/*********************************************************************** + * thread_detach + */ +static void thread_detach(void) +{ + struct macdrv_thread_data *data = macdrv_thread_data(); + + if (data) + { + macdrv_destroy_event_queue(data->queue); + HeapFree(GetProcessHeap(), 0, data); + } +} + + +/*********************************************************************** + * set_queue_display_fd + * + * Store the event queue fd into the message queue + */ +static void set_queue_display_fd(int fd) +{ + HANDLE handle; + int ret; + + if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle)) + { + MESSAGE("macdrv: Can't allocate handle for event queue fd\n"); + ExitProcess(1); + } + SERVER_START_REQ(set_queue_fd) + { + req->handle = wine_server_obj_handle(handle); + ret = wine_server_call(req); + } + SERVER_END_REQ; + if (ret) + { + MESSAGE("macdrv: Can't store handle for event queue fd\n"); + ExitProcess(1); + } + CloseHandle(handle); +} + + +/*********************************************************************** + * macdrv_init_thread_data + */ +struct macdrv_thread_data *macdrv_init_thread_data(void) +{ + struct macdrv_thread_data *data = macdrv_thread_data(); + + if (data) return data; + + if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data)))) + { + ERR("could not create data\n"); + ExitProcess(1); + } + + if (!(data->queue = macdrv_create_event_queue())) + { + ERR("macdrv: Can't create event queue.\n"); + ExitProcess(1); + } + + set_queue_display_fd(macdrv_get_event_queue_fd(data->queue)); + TlsSetValue(thread_data_tls_index, data); + + return data; +} + + +/*********************************************************************** + * DllMain + */ +BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) { BOOL ret = TRUE; switch(reason) { case DLL_PROCESS_ATTACH: - macdrv_err_on = ERR_ON(macdrv); - if (macdrv_start_cocoa_app()) - { - ERR("Failed to start Cocoa app main loop\n"); - ret = FALSE; - } + ret = process_attach(); break; case DLL_THREAD_DETACH: - /* do thread detach */ - break; - case DLL_PROCESS_DETACH: - /* do detach */ + thread_detach(); break; } return ret; diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 75f68d72d5e..26dedf4ad2c 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -478,6 +478,7 @@ static void sync_window_opacity(struct macdrv_win_data *data, COLORREF key, BYTE */ static void create_cocoa_window(struct macdrv_win_data *data) { + struct macdrv_thread_data *thread_data = macdrv_init_thread_data(); WCHAR text[1024]; struct macdrv_window_features wf; CGRect frame; @@ -510,7 +511,7 @@ static void create_cocoa_window(struct macdrv_win_data *data) TRACE("creating %p window %s whole %s client %s\n", data->hwnd, wine_dbgstr_rect(&data->window_rect), wine_dbgstr_rect(&data->whole_rect), wine_dbgstr_rect(&data->client_rect)); - data->cocoa_window = macdrv_create_cocoa_window(&wf, frame); + data->cocoa_window = macdrv_create_cocoa_window(&wf, frame, thread_data->queue); if (!data->cocoa_window) goto done; set_cocoa_window_properties(data); @@ -565,7 +566,10 @@ static struct macdrv_win_data *macdrv_create_win_data(HWND hwnd, const RECT *win if (GetWindowThreadProcessId(hwnd, NULL) != GetCurrentThreadId()) return NULL; if (!(parent = GetAncestor(hwnd, GA_PARENT))) /* desktop */ + { + macdrv_init_thread_data(); return NULL; + } /* don't create win data for HWND_MESSAGE windows */ if (parent != GetDesktopWindow() && !GetAncestor(parent, GA_PARENT)) return NULL;