winemac: Convert main thread to Cocoa main loop on process attach.

This commit is contained in:
Ken Thomases 2013-01-07 14:44:36 -06:00 committed by Alexandre Julliard
parent daf0fd75e6
commit 35319684d3
4 changed files with 138 additions and 7 deletions

View file

@ -10,6 +10,7 @@ C_SRCS = \
OBJC_SRCS = \
cocoa_app.m \
cocoa_display.m
cocoa_display.m \
cocoa_main.m
@MAKE_DLL_RULES@

View file

@ -0,0 +1,122 @@
/*
* MACDRV Cocoa initialization code
*
* Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#import <AppKit/AppKit.h>
#include "macdrv_cocoa.h"
#import "cocoa_app.h"
/* Condition values for an NSConditionLock. Used to signal between run_cocoa_app
and macdrv_start_cocoa_app so the latter knows when the former is running
the application event loop. */
enum {
COCOA_APP_NOT_RUNNING,
COCOA_APP_RUNNING,
};
/***********************************************************************
* run_cocoa_app
*
* Transforms the main thread from merely idling in its run loop to
* being a Cocoa application running its event loop.
*
* This will be the perform callback of a custom run loop source that
* will be scheduled in the main thread's run loop from a secondary
* thread by macdrv_start_cocoa_app. This function communicates that
* it has successfully started the application by changing the condition
* of a shared NSConditionLock, passed in via the info parameter.
*
* This function never returns. It's the new permanent home of the
* main thread.
*/
static void run_cocoa_app(void* info)
{
NSConditionLock* lock = info;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[WineApplication sharedApplication];
[NSApp setDelegate:(WineApplication*)NSApp];
/* Retain the lock while we're using it, so macdrv_start_cocoa_app()
doesn't deallocate it in the middle of us unlocking it. */
[lock retain];
[lock lock];
[lock unlockWithCondition:COCOA_APP_RUNNING];
[lock release];
[pool release];
/* Never returns */
[NSApp run];
}
/***********************************************************************
* macdrv_start_cocoa_app
*
* Tells the main thread to transform itself into a Cocoa application.
*
* Returns 0 on success, non-zero on failure.
*/
int macdrv_start_cocoa_app(void)
{
int ret = -1;
CFRunLoopSourceRef source;
NSConditionLock* lock;
NSDate* timeLimit;
CFRunLoopSourceContext source_context = { 0 };
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/* Make sure Cocoa is in multi-threading mode by detaching a
do-nothing thread. */
[NSThread detachNewThreadSelector:@selector(self)
toTarget:[NSThread class]
withObject:nil];
lock = [[NSConditionLock alloc] initWithCondition:COCOA_APP_NOT_RUNNING];
timeLimit = [NSDate dateWithTimeIntervalSinceNow:5];
source_context.info = lock;
source_context.perform = run_cocoa_app;
source = CFRunLoopSourceCreate(NULL, 0, &source_context);
if (source && lock && timeLimit)
{
CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopCommonModes);
CFRunLoopSourceSignal(source);
CFRunLoopWakeUp(CFRunLoopGetMain());
if ([lock lockWhenCondition:COCOA_APP_RUNNING beforeDate:timeLimit])
{
[lock unlock];
ret = 0;
}
}
if (source)
CFRelease(source);
[lock release];
[pool release];
return ret;
}

View file

@ -1,7 +1,7 @@
/*
* MACDRV Cocoa interface declarations
*
* Copyright 2011, 2012 Ken Thomases for CodeWeavers Inc.
* Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -104,6 +104,10 @@
};
/* main */
extern int macdrv_start_cocoa_app(void) DECLSPEC_HIDDEN;
/* display */
extern int macdrv_get_displays(struct macdrv_display** displays, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDEN;

View file

@ -3,6 +3,7 @@
*
* Copyright 1998 Patrik Stridvall
* Copyright 2000 Alexandre Julliard
* Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,11 +21,10 @@
*/
#include "config.h"
#include <stdarg.h>
#include "macdrv.h"
WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
/***********************************************************************
* MACDRV initialisation routine
@ -36,7 +36,11 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
switch(reason)
{
case DLL_PROCESS_ATTACH:
/* Do attach */
if (macdrv_start_cocoa_app())
{
ERR("Failed to start Cocoa app main loop\n");
ret = FALSE;
}
break;
case DLL_THREAD_DETACH:
/* do thread detach */