winemac: Associate an event queue with each thread that creates windows and with each window.
This commit is contained in:
parent
3c995bb682
commit
207c4d193f
|
@ -21,6 +21,9 @@
|
||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
|
||||||
|
@class WineEventQueue;
|
||||||
|
|
||||||
|
|
||||||
@interface WineWindow : NSPanel <NSWindowDelegate>
|
@interface WineWindow : NSPanel <NSWindowDelegate>
|
||||||
{
|
{
|
||||||
NSUInteger normalStyleMask;
|
NSUInteger normalStyleMask;
|
||||||
|
@ -29,6 +32,8 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
||||||
BOOL floating;
|
BOOL floating;
|
||||||
WineWindow* latentParentWindow;
|
WineWindow* latentParentWindow;
|
||||||
|
|
||||||
|
WineEventQueue* queue;
|
||||||
|
|
||||||
void* surface;
|
void* surface;
|
||||||
pthread_mutex_t* surface_mutex;
|
pthread_mutex_t* surface_mutex;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "macdrv_cocoa.h"
|
#include "macdrv_cocoa.h"
|
||||||
#import "cocoa_app.h"
|
#import "cocoa_app.h"
|
||||||
|
#import "cocoa_event.h"
|
||||||
|
|
||||||
|
|
||||||
static NSUInteger style_mask_for_features(const struct macdrv_window_features* wf)
|
static NSUInteger style_mask_for_features(const struct macdrv_window_features* wf)
|
||||||
|
@ -65,6 +66,8 @@ @interface WineWindow ()
|
||||||
@property (nonatomic) BOOL floating;
|
@property (nonatomic) BOOL floating;
|
||||||
@property (retain, nonatomic) NSWindow* latentParentWindow;
|
@property (retain, nonatomic) NSWindow* latentParentWindow;
|
||||||
|
|
||||||
|
@property (retain, nonatomic) WineEventQueue* queue;
|
||||||
|
|
||||||
@property (nonatomic) void* surface;
|
@property (nonatomic) void* surface;
|
||||||
@property (nonatomic) pthread_mutex_t* surface_mutex;
|
@property (nonatomic) pthread_mutex_t* surface_mutex;
|
||||||
|
|
||||||
|
@ -159,7 +162,7 @@ - (void) drawRect:(NSRect)rect
|
||||||
|
|
||||||
@implementation WineWindow
|
@implementation WineWindow
|
||||||
|
|
||||||
@synthesize disabled, noActivate, floating, latentParentWindow;
|
@synthesize disabled, noActivate, floating, latentParentWindow, queue;
|
||||||
@synthesize surface, surface_mutex;
|
@synthesize surface, surface_mutex;
|
||||||
@synthesize shape, shapeChangedSinceLastDraw;
|
@synthesize shape, shapeChangedSinceLastDraw;
|
||||||
@synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue;
|
@synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue;
|
||||||
|
@ -167,6 +170,7 @@ @implementation WineWindow
|
||||||
|
|
||||||
+ (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)wf
|
+ (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)wf
|
||||||
windowFrame:(NSRect)window_frame
|
windowFrame:(NSRect)window_frame
|
||||||
|
queue:(WineEventQueue*)queue
|
||||||
{
|
{
|
||||||
WineWindow* window;
|
WineWindow* window;
|
||||||
WineContentView* contentView;
|
WineContentView* contentView;
|
||||||
|
@ -191,6 +195,7 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
|
||||||
[window setHasShadow:wf->shadow];
|
[window setHasShadow:wf->shadow];
|
||||||
[window setColorSpace:[NSColorSpace genericRGBColorSpace]];
|
[window setColorSpace:[NSColorSpace genericRGBColorSpace]];
|
||||||
[window setDelegate:window];
|
[window setDelegate:window];
|
||||||
|
window.queue = queue;
|
||||||
|
|
||||||
contentView = [[[WineContentView alloc] initWithFrame:NSZeroRect] autorelease];
|
contentView = [[[WineContentView alloc] initWithFrame:NSZeroRect] autorelease];
|
||||||
if (!contentView)
|
if (!contentView)
|
||||||
|
@ -204,6 +209,7 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
|
[queue release];
|
||||||
[latentParentWindow release];
|
[latentParentWindow release];
|
||||||
[shape release];
|
[shape release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
|
@ -441,13 +447,14 @@ - (BOOL)windowShouldClose:(id)sender
|
||||||
* title bar, close box, etc.).
|
* title bar, close box, etc.).
|
||||||
*/
|
*/
|
||||||
macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf,
|
macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf,
|
||||||
CGRect frame)
|
CGRect frame, macdrv_event_queue queue)
|
||||||
{
|
{
|
||||||
__block WineWindow* window;
|
__block WineWindow* window;
|
||||||
|
|
||||||
OnMainThread(^{
|
OnMainThread(^{
|
||||||
window = [[WineWindow createWindowWithFeatures:wf
|
window = [[WineWindow createWindowWithFeatures:wf
|
||||||
windowFrame:NSRectFromCGRect(frame)] retain];
|
windowFrame:NSRectFromCGRect(frame)
|
||||||
|
queue:(WineEventQueue*)queue] retain];
|
||||||
});
|
});
|
||||||
|
|
||||||
return (macdrv_window)window;
|
return (macdrv_window)window;
|
||||||
|
@ -463,6 +470,7 @@ void macdrv_destroy_cocoa_window(macdrv_window w)
|
||||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||||
WineWindow* window = (WineWindow*)w;
|
WineWindow* window = (WineWindow*)w;
|
||||||
|
|
||||||
|
[window.queue discardEventsMatchingMask:-1 forWindow:window];
|
||||||
[window close];
|
[window close];
|
||||||
[window release];
|
[window release];
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,21 @@ static inline RECT rect_from_cgrect(CGRect cgrect)
|
||||||
WM_MACDRV_SET_WIN_REGION = 0x80001000,
|
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 */
|
/* macdrv private window data */
|
||||||
struct macdrv_win_data
|
struct macdrv_win_data
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
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_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,
|
extern void macdrv_set_cocoa_window_features(macdrv_window w,
|
||||||
const struct macdrv_window_features* wf) DECLSPEC_HIDDEN;
|
const struct macdrv_window_features* wf) DECLSPEC_HIDDEN;
|
||||||
extern void macdrv_set_cocoa_window_state(macdrv_window w,
|
extern void macdrv_set_cocoa_window_state(macdrv_window w,
|
||||||
|
|
|
@ -22,32 +22,119 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "macdrv.h"
|
#include "macdrv.h"
|
||||||
|
#include "wine/server.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
|
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;
|
BOOL ret = TRUE;
|
||||||
|
|
||||||
switch(reason)
|
switch(reason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
macdrv_err_on = ERR_ON(macdrv);
|
ret = process_attach();
|
||||||
if (macdrv_start_cocoa_app())
|
|
||||||
{
|
|
||||||
ERR("Failed to start Cocoa app main loop\n");
|
|
||||||
ret = FALSE;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case DLL_THREAD_DETACH:
|
case DLL_THREAD_DETACH:
|
||||||
/* do thread detach */
|
thread_detach();
|
||||||
break;
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
/* do detach */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -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)
|
static void create_cocoa_window(struct macdrv_win_data *data)
|
||||||
{
|
{
|
||||||
|
struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
|
||||||
WCHAR text[1024];
|
WCHAR text[1024];
|
||||||
struct macdrv_window_features wf;
|
struct macdrv_window_features wf;
|
||||||
CGRect frame;
|
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),
|
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));
|
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;
|
if (!data->cocoa_window) goto done;
|
||||||
|
|
||||||
set_cocoa_window_properties(data);
|
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 (GetWindowThreadProcessId(hwnd, NULL) != GetCurrentThreadId()) return NULL;
|
||||||
|
|
||||||
if (!(parent = GetAncestor(hwnd, GA_PARENT))) /* desktop */
|
if (!(parent = GetAncestor(hwnd, GA_PARENT))) /* desktop */
|
||||||
|
{
|
||||||
|
macdrv_init_thread_data();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* don't create win data for HWND_MESSAGE windows */
|
/* don't create win data for HWND_MESSAGE windows */
|
||||||
if (parent != GetDesktopWindow() && !GetAncestor(parent, GA_PARENT)) return NULL;
|
if (parent != GetDesktopWindow() && !GetAncestor(parent, GA_PARENT)) return NULL;
|
||||||
|
|
Loading…
Reference in New Issue