mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 11:43:31 +00:00
winemac: Add support for "query" events which wait for synchronous responses.
This commit is contained in:
parent
bf824ed38c
commit
69e631e04e
10 changed files with 314 additions and 20 deletions
|
@ -32,6 +32,10 @@
|
|||
|
||||
@interface WineApplication : NSApplication <NSApplicationDelegate>
|
||||
{
|
||||
CFRunLoopSourceRef requestSource;
|
||||
NSMutableArray* requests;
|
||||
dispatch_queue_t requestsManipQueue;
|
||||
|
||||
NSMutableArray* eventQueues;
|
||||
NSLock* eventQueuesLock;
|
||||
|
||||
|
@ -83,6 +87,8 @@ - (double) ticksForEventTime:(NSTimeInterval)eventTime;
|
|||
|
||||
- (void) windowGotFocus:(WineWindow*)window;
|
||||
|
||||
- (BOOL) waitUntilQueryDone:(int*)done timeout:(NSDate*)timeout;
|
||||
|
||||
- (void) keyboardSelectionDidChange;
|
||||
|
||||
- (void) flipRect:(NSRect*)rect;
|
||||
|
@ -93,7 +99,6 @@ - (void) wineWindow:(WineWindow*)window
|
|||
|
||||
@end
|
||||
|
||||
void OnMainThread(dispatch_block_t block);
|
||||
void OnMainThreadAsync(dispatch_block_t block);
|
||||
|
||||
void LogError(const char* func, NSString* format, ...);
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#import "cocoa_window.h"
|
||||
|
||||
|
||||
static NSString* const WineAppWaitQueryResponseMode = @"WineAppWaitQueryResponseMode";
|
||||
|
||||
|
||||
int macdrv_err_on;
|
||||
|
||||
|
||||
|
@ -56,6 +59,8 @@ @interface WineApplication ()
|
|||
@property (copy, nonatomic) NSArray* cursorFrames;
|
||||
@property (retain, nonatomic) NSTimer* cursorTimer;
|
||||
|
||||
static void PerformRequest(void *info);
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -70,6 +75,20 @@ - (id) init
|
|||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
CFRunLoopSourceContext context = { 0 };
|
||||
context.perform = PerformRequest;
|
||||
requestSource = CFRunLoopSourceCreate(NULL, 0, &context);
|
||||
if (!requestSource)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
CFRunLoopAddSource(CFRunLoopGetMain(), requestSource, kCFRunLoopCommonModes);
|
||||
CFRunLoopAddSource(CFRunLoopGetMain(), requestSource, (CFStringRef)WineAppWaitQueryResponseMode);
|
||||
|
||||
requests = [[NSMutableArray alloc] init];
|
||||
requestsManipQueue = dispatch_queue_create("org.winehq.WineAppRequestManipQueue", NULL);
|
||||
|
||||
eventQueues = [[NSMutableArray alloc] init];
|
||||
eventQueuesLock = [[NSLock alloc] init];
|
||||
|
||||
|
@ -80,8 +99,8 @@ - (id) init
|
|||
|
||||
warpRecords = [[NSMutableArray alloc] init];
|
||||
|
||||
if (!eventQueues || !eventQueuesLock || !keyWindows || !orderedWineWindows ||
|
||||
!originalDisplayModes || !warpRecords)
|
||||
if (!requests || !requestsManipQueue || !eventQueues || !eventQueuesLock ||
|
||||
!keyWindows || !orderedWineWindows || !originalDisplayModes || !warpRecords)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
|
@ -100,6 +119,13 @@ - (void) dealloc
|
|||
[keyWindows release];
|
||||
[eventQueues release];
|
||||
[eventQueuesLock release];
|
||||
if (requestsManipQueue) dispatch_release(requestsManipQueue);
|
||||
[requests release];
|
||||
if (requestSource)
|
||||
{
|
||||
CFRunLoopSourceInvalidate(requestSource);
|
||||
CFRelease(requestSource);
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -146,6 +172,18 @@ - (void) transformProcessToForeground
|
|||
}
|
||||
}
|
||||
|
||||
- (BOOL) waitUntilQueryDone:(int*)done timeout:(NSDate*)timeout
|
||||
{
|
||||
PerformRequest(NULL);
|
||||
|
||||
do
|
||||
{
|
||||
[[NSRunLoop currentRunLoop] runMode:WineAppWaitQueryResponseMode beforeDate:timeout];
|
||||
} while (!*done && [timeout timeIntervalSinceNow] >= 0);
|
||||
|
||||
return *done;
|
||||
}
|
||||
|
||||
- (BOOL) registerEventQueue:(WineEventQueue*)queue
|
||||
{
|
||||
[eventQueuesLock lock];
|
||||
|
@ -1102,16 +1140,36 @@ - (void)applicationWillResignActive:(NSNotification *)notification
|
|||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/***********************************************************************
|
||||
* OnMainThread
|
||||
* PerformRequest
|
||||
*
|
||||
* Run a block on the main thread synchronously.
|
||||
* Run-loop-source perform callback. Pull request blocks from the
|
||||
* array of queued requests and invoke them.
|
||||
*/
|
||||
void OnMainThread(dispatch_block_t block)
|
||||
static void PerformRequest(void *info)
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), block);
|
||||
WineApplication* app = (WineApplication*)NSApp;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
__block dispatch_block_t block;
|
||||
|
||||
dispatch_sync(app->requestsManipQueue, ^{
|
||||
if ([app->requests count])
|
||||
{
|
||||
block = (dispatch_block_t)[[app->requests objectAtIndex:0] retain];
|
||||
[app->requests removeObjectAtIndex:0];
|
||||
}
|
||||
else
|
||||
block = nil;
|
||||
});
|
||||
|
||||
if (!block)
|
||||
break;
|
||||
|
||||
block();
|
||||
[block release];
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1121,9 +1179,19 @@ void OnMainThread(dispatch_block_t block)
|
|||
*/
|
||||
void OnMainThreadAsync(dispatch_block_t block)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), block);
|
||||
WineApplication* app = (WineApplication*)NSApp;
|
||||
|
||||
block = [block copy];
|
||||
dispatch_sync(app->requestsManipQueue, ^{
|
||||
[app->requests addObject:block];
|
||||
});
|
||||
[block release];
|
||||
CFRunLoopSourceSignal(app->requestSource);
|
||||
CFRunLoopWakeUp(CFRunLoopGetMain());
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/***********************************************************************
|
||||
* LogError
|
||||
*/
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "macdrv_cocoa.h"
|
||||
#import "cocoa_app.h"
|
||||
#import "cocoa_event.h"
|
||||
|
||||
|
||||
static int owned_change_count = -1;
|
||||
|
|
|
@ -28,9 +28,16 @@ @interface WineEventQueue : NSObject
|
|||
NSLock* eventsLock;
|
||||
|
||||
int fds[2]; /* Pipe signaling when there are events queued. */
|
||||
int kq; /* kqueue for waiting in OnMainThread(). */
|
||||
|
||||
macdrv_event_handler event_handler;
|
||||
}
|
||||
|
||||
- (void) postEvent:(const macdrv_event*)inEvent;
|
||||
- (void) discardEventsMatchingMask:(macdrv_event_mask)mask forWindow:(NSWindow*)window;
|
||||
|
||||
- (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout;
|
||||
|
||||
@end
|
||||
|
||||
void OnMainThread(dispatch_block_t block);
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#import "cocoa_window.h"
|
||||
|
||||
|
||||
static NSString* const WineEventQueueThreadDictionaryKey = @"WineEventQueueThreadDictionaryKey";
|
||||
|
||||
|
||||
@interface MacDrvEvent : NSObject
|
||||
{
|
||||
@public
|
||||
|
@ -58,11 +61,24 @@ @implementation WineEventQueue
|
|||
|
||||
- (id) init
|
||||
{
|
||||
[self doesNotRecognizeSelector:_cmd];
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id) initWithEventHandler:(macdrv_event_handler)handler
|
||||
{
|
||||
NSParameterAssert(handler != nil);
|
||||
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
{
|
||||
fds[0] = fds[1] = -1;
|
||||
struct kevent kev;
|
||||
int rc;
|
||||
|
||||
fds[0] = fds[1] = kq = -1;
|
||||
|
||||
event_handler = handler;
|
||||
events = [[NSMutableArray alloc] init];
|
||||
eventsLock = [[NSLock alloc] init];
|
||||
|
||||
|
@ -81,6 +97,24 @@ - (id) init
|
|||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
kq = kqueue();
|
||||
if (kq < 0)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
EV_SET(&kev, fds[0], EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
|
||||
do
|
||||
{
|
||||
rc = kevent(kq, &kev, 1, NULL, 0, NULL);
|
||||
} while (rc == -1 && errno == EINTR);
|
||||
if (rc == -1)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -90,6 +124,7 @@ - (void) dealloc
|
|||
[events release];
|
||||
[eventsLock release];
|
||||
|
||||
if (kq != -1) close(kq);
|
||||
if (fds[0] != -1) close(fds[0]);
|
||||
if (fds[1] != -1) close(fds[1]);
|
||||
|
||||
|
@ -217,6 +252,69 @@ - (void) discardEventsMatchingMask:(macdrv_event_mask)mask forWindow:(NSWindow*)
|
|||
[eventsLock unlock];
|
||||
}
|
||||
|
||||
- (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout
|
||||
{
|
||||
macdrv_event event;
|
||||
NSDate* timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout];
|
||||
BOOL timedout;
|
||||
|
||||
event.type = QUERY_EVENT;
|
||||
event.window = (macdrv_window)[(WineWindow*)query->window retain];
|
||||
event.query_event.query = macdrv_retain_query(query);
|
||||
query->done = FALSE;
|
||||
|
||||
[self postEvent:&event];
|
||||
timedout = ![NSApp waitUntilQueryDone:&query->done timeout:timeoutDate];
|
||||
return !timedout && query->status;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* OnMainThread
|
||||
*
|
||||
* Run a block on the main thread synchronously.
|
||||
*/
|
||||
void OnMainThread(dispatch_block_t block)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];
|
||||
WineEventQueue* queue = [threadDict objectForKey:WineEventQueueThreadDictionaryKey];
|
||||
__block BOOL finished;
|
||||
|
||||
if (!queue)
|
||||
{
|
||||
/* Fall back to synchronous dispatch without handling query events. */
|
||||
dispatch_sync(dispatch_get_main_queue(), block);
|
||||
[pool release];
|
||||
return;
|
||||
}
|
||||
|
||||
finished = FALSE;
|
||||
OnMainThreadAsync(^{
|
||||
block();
|
||||
finished = TRUE;
|
||||
[queue signalEventAvailable];
|
||||
});
|
||||
|
||||
while (!finished)
|
||||
{
|
||||
MacDrvEvent* macDrvEvent;
|
||||
struct kevent kev;
|
||||
|
||||
while (!finished &&
|
||||
(macDrvEvent = [queue getEventMatchingMask:event_mask_for_type(QUERY_EVENT)]))
|
||||
{
|
||||
queue->event_handler(&macDrvEvent->event);
|
||||
macdrv_cleanup_event(&macDrvEvent->event);
|
||||
}
|
||||
|
||||
if (!finished)
|
||||
kevent(queue->kq, NULL, 0, &kev, 1, NULL);
|
||||
}
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_create_event_queue
|
||||
|
@ -224,15 +322,22 @@ - (void) discardEventsMatchingMask:(macdrv_event_mask)mask forWindow:(NSWindow*)
|
|||
* Register this thread with the application on the main thread, and set
|
||||
* up an event queue on which it can deliver events to this thread.
|
||||
*/
|
||||
macdrv_event_queue macdrv_create_event_queue(void)
|
||||
macdrv_event_queue macdrv_create_event_queue(macdrv_event_handler handler)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];
|
||||
|
||||
WineEventQueue* queue = [[WineEventQueue alloc] init];
|
||||
if (queue && ![NSApp registerEventQueue:queue])
|
||||
WineEventQueue* queue = [threadDict objectForKey:WineEventQueueThreadDictionaryKey];
|
||||
if (!queue)
|
||||
{
|
||||
[queue release];
|
||||
queue = nil;
|
||||
queue = [[[WineEventQueue alloc] initWithEventHandler:handler] autorelease];
|
||||
if (queue)
|
||||
{
|
||||
if ([NSApp registerEventQueue:queue])
|
||||
[threadDict setObject:queue forKey:WineEventQueueThreadDictionaryKey];
|
||||
else
|
||||
queue = nil;
|
||||
}
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
@ -249,9 +354,10 @@ void macdrv_destroy_event_queue(macdrv_event_queue queue)
|
|||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
WineEventQueue* q = (WineEventQueue*)queue;
|
||||
NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];
|
||||
|
||||
[NSApp unregisterEventQueue:q];
|
||||
[q release];
|
||||
[threadDict removeObjectForKey:WineEventQueueThreadDictionaryKey];
|
||||
|
||||
[pool release];
|
||||
}
|
||||
|
@ -308,6 +414,9 @@ void macdrv_cleanup_event(macdrv_event *event)
|
|||
case KEYBOARD_CHANGED:
|
||||
CFRelease(event->keyboard_changed.uchr);
|
||||
break;
|
||||
case QUERY_EVENT:
|
||||
macdrv_release_query(event->query_event.query);
|
||||
break;
|
||||
case WINDOW_GOT_FOCUS:
|
||||
[(NSMutableSet*)event->window_got_focus.tried_windows release];
|
||||
break;
|
||||
|
@ -318,4 +427,50 @@ void macdrv_cleanup_event(macdrv_event *event)
|
|||
[pool release];
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_create_query
|
||||
*/
|
||||
macdrv_query* macdrv_create_query(void)
|
||||
{
|
||||
macdrv_query *query;
|
||||
|
||||
query = calloc(1, sizeof(*query));
|
||||
query->refs = 1;
|
||||
return query;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_retain_query
|
||||
*/
|
||||
macdrv_query* macdrv_retain_query(macdrv_query *query)
|
||||
{
|
||||
OSAtomicIncrement32Barrier(&query->refs);
|
||||
return query;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_release_query
|
||||
*/
|
||||
void macdrv_release_query(macdrv_query *query)
|
||||
{
|
||||
if (OSAtomicDecrement32Barrier(&query->refs) <= 0)
|
||||
{
|
||||
[(WineWindow*)query->window release];
|
||||
free(query);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_set_query_done
|
||||
*/
|
||||
void macdrv_set_query_done(macdrv_query *query)
|
||||
{
|
||||
macdrv_retain_query(query);
|
||||
|
||||
OnMainThreadAsync(^{
|
||||
query->done = TRUE;
|
||||
macdrv_release_query(query);
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#import "cocoa_opengl.h"
|
||||
|
||||
#include "macdrv_cocoa.h"
|
||||
#include "cocoa_app.h"
|
||||
#include "cocoa_event.h"
|
||||
|
||||
|
||||
@interface WineOpenGLContext ()
|
||||
|
|
|
@ -41,6 +41,7 @@ static const char *dbgstr_event(int type)
|
|||
"MOUSE_MOVED",
|
||||
"MOUSE_MOVED_ABSOLUTE",
|
||||
"MOUSE_SCROLL",
|
||||
"QUERY_EVENT",
|
||||
"WINDOW_CLOSE_REQUESTED",
|
||||
"WINDOW_DID_MINIMIZE",
|
||||
"WINDOW_DID_UNMINIMIZE",
|
||||
|
@ -94,10 +95,38 @@ static macdrv_event_mask get_event_mask(DWORD mask)
|
|||
event_mask |= event_mask_for_type(WINDOW_LOST_FOCUS);
|
||||
}
|
||||
|
||||
if (mask & QS_SENDMESSAGE)
|
||||
{
|
||||
event_mask |= event_mask_for_type(QUERY_EVENT);
|
||||
}
|
||||
|
||||
return event_mask;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_query_event
|
||||
*
|
||||
* Handler for QUERY_EVENT queries.
|
||||
*/
|
||||
static void macdrv_query_event(HWND hwnd, macdrv_event *event)
|
||||
{
|
||||
BOOL success = FALSE;
|
||||
macdrv_query *query = event->query_event.query;
|
||||
|
||||
switch (query->type)
|
||||
{
|
||||
default:
|
||||
FIXME("unrecognized query type %d\n", query->type);
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE("success %d\n", success);
|
||||
query->status = success;
|
||||
macdrv_set_query_done(query);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* macdrv_handle_event
|
||||
*/
|
||||
|
@ -138,6 +167,9 @@ void macdrv_handle_event(macdrv_event *event)
|
|||
case MOUSE_SCROLL:
|
||||
macdrv_mouse_scroll(hwnd, event);
|
||||
break;
|
||||
case QUERY_EVENT:
|
||||
macdrv_query_event(hwnd, event);
|
||||
break;
|
||||
case WINDOW_CLOSE_REQUESTED:
|
||||
macdrv_window_close_requested(hwnd);
|
||||
break;
|
||||
|
|
|
@ -138,6 +138,8 @@ 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_handle_event(macdrv_event *event) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void macdrv_window_close_requested(HWND hwnd) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_window_frame_changed(HWND hwnd, CGRect frame) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_window_got_focus(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
typedef struct macdrv_opaque_view* macdrv_view;
|
||||
typedef struct macdrv_opaque_opengl_context* macdrv_opengl_context;
|
||||
struct macdrv_event;
|
||||
struct macdrv_query;
|
||||
|
||||
struct macdrv_display {
|
||||
CGDirectDisplayID displayID;
|
||||
|
@ -145,6 +146,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
|
|||
MOUSE_MOVED,
|
||||
MOUSE_MOVED_ABSOLUTE,
|
||||
MOUSE_SCROLL,
|
||||
QUERY_EVENT,
|
||||
WINDOW_CLOSE_REQUESTED,
|
||||
WINDOW_DID_MINIMIZE,
|
||||
WINDOW_DID_UNMINIMIZE,
|
||||
|
@ -192,6 +194,9 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
|
|||
int y;
|
||||
unsigned long time_ms;
|
||||
} mouse_scroll;
|
||||
struct {
|
||||
struct macdrv_query *query;
|
||||
} query_event;
|
||||
struct {
|
||||
CGRect frame;
|
||||
} window_frame_changed;
|
||||
|
@ -202,12 +207,26 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
|
|||
};
|
||||
} macdrv_event;
|
||||
|
||||
enum {
|
||||
NUM_QUERY_TYPES
|
||||
};
|
||||
|
||||
typedef struct macdrv_query {
|
||||
int refs;
|
||||
int type;
|
||||
macdrv_window window;
|
||||
int status;
|
||||
int done;
|
||||
} macdrv_query;
|
||||
|
||||
static inline macdrv_event_mask event_mask_for_type(int type)
|
||||
{
|
||||
return ((macdrv_event_mask)1 << type);
|
||||
}
|
||||
|
||||
extern macdrv_event_queue macdrv_create_event_queue(void) DECLSPEC_HIDDEN;
|
||||
typedef void (*macdrv_event_handler)(macdrv_event *event);
|
||||
|
||||
extern macdrv_event_queue macdrv_create_event_queue(macdrv_event_handler handler) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_destroy_event_queue(macdrv_event_queue queue) DECLSPEC_HIDDEN;
|
||||
extern int macdrv_get_event_queue_fd(macdrv_event_queue queue) DECLSPEC_HIDDEN;
|
||||
|
||||
|
@ -215,6 +234,11 @@ extern int macdrv_get_event_from_queue(macdrv_event_queue queue,
|
|||
macdrv_event_mask mask, macdrv_event *event) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_cleanup_event(macdrv_event *event) DECLSPEC_HIDDEN;
|
||||
|
||||
extern macdrv_query* macdrv_create_query(void) DECLSPEC_HIDDEN;
|
||||
extern macdrv_query* macdrv_retain_query(macdrv_query *query) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_release_query(macdrv_query *query) DECLSPEC_HIDDEN;
|
||||
extern void macdrv_set_query_done(macdrv_query *query) DECLSPEC_HIDDEN;
|
||||
|
||||
|
||||
/* window */
|
||||
struct macdrv_window_features {
|
||||
|
|
|
@ -157,7 +157,7 @@ struct macdrv_thread_data *macdrv_init_thread_data(void)
|
|||
ExitProcess(1);
|
||||
}
|
||||
|
||||
if (!(data->queue = macdrv_create_event_queue()))
|
||||
if (!(data->queue = macdrv_create_event_queue(macdrv_handle_event)))
|
||||
{
|
||||
ERR("macdrv: Can't create event queue.\n");
|
||||
ExitProcess(1);
|
||||
|
|
Loading…
Reference in a new issue