Module: wine
Branch: master
Commit: 35319684d3eb0a06a94d474558d91228912d3012
URL: http://source.winehq.org/git/wine.git/?a=commit;h=35319684d3eb0a06a94d47455…
Author: Ken Thomases <ken(a)codeweavers.com>
Date: Mon Jan 7 14:44:36 2013 -0600
winemac: Convert main thread to Cocoa main loop on process attach.
---
dlls/winemac.drv/Makefile.in | 3 +-
dlls/winemac.drv/cocoa_main.m | 122 +++++++++++++++++++++++++++++++++++++++
dlls/winemac.drv/macdrv_cocoa.h | 6 ++-
dlls/winemac.drv/macdrv_main.c | 14 +++--
4 files changed, 138 insertions(+), 7 deletions(-)
diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in
index 38d8f7e..a388b9b 100644
--- a/dlls/winemac.drv/Makefile.in
+++ b/dlls/winemac.drv/Makefile.in
@@ -10,6 +10,7 @@ C_SRCS = \
OBJC_SRCS = \
cocoa_app.m \
- cocoa_display.m
+ cocoa_display.m \
+ cocoa_main.m
@MAKE_DLL_RULES@
diff --git a/dlls/winemac.drv/cocoa_main.m b/dlls/winemac.drv/cocoa_main.m
new file mode 100644
index 0000000..d920036
--- /dev/null
+++ b/dlls/winemac.drv/cocoa_main.m
@@ -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;
+}
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 720073e..932aa90 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -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 @@ struct macdrv_display {
};
+/* 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;
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c
index 17aebf6..9ee249d 100644
--- a/dlls/winemac.drv/macdrv_main.c
+++ b/dlls/winemac.drv/macdrv_main.c
@@ -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 */
Module: wine
Branch: master
Commit: daf0fd75e638729240f874a39ed7a28830ff02ec
URL: http://source.winehq.org/git/wine.git/?a=commit;h=daf0fd75e638729240f874a39…
Author: Ken Thomases <ken(a)codeweavers.com>
Date: Mon Jan 7 14:44:31 2013 -0600
winemac: Add a custom NSApplication subclass, WineApplication.
---
dlls/winemac.drv/Makefile.in | 1 +
dlls/winemac.drv/cocoa_app.h | 30 +++++++++++++++++++++
dlls/winemac.drv/cocoa_app.m | 58 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 0 deletions(-)
diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in
index 2082b37..38d8f7e 100644
--- a/dlls/winemac.drv/Makefile.in
+++ b/dlls/winemac.drv/Makefile.in
@@ -9,6 +9,7 @@ C_SRCS = \
window.c
OBJC_SRCS = \
+ cocoa_app.m \
cocoa_display.m
@MAKE_DLL_RULES@
diff --git a/dlls/winemac.drv/cocoa_app.h b/dlls/winemac.drv/cocoa_app.h
new file mode 100644
index 0000000..cc3ede3
--- /dev/null
+++ b/dlls/winemac.drv/cocoa_app.h
@@ -0,0 +1,30 @@
+/*
+ * MACDRV Cocoa application class declaration
+ *
+ * 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"
+
+
+@interface WineApplication : NSApplication <NSApplicationDelegate>
+
+ - (void) transformProcessToForeground;
+
+@end
diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
new file mode 100644
index 0000000..ee7e2f8
--- /dev/null
+++ b/dlls/winemac.drv/cocoa_app.m
@@ -0,0 +1,58 @@
+/*
+ * MACDRV Cocoa application class
+ *
+ * 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 "cocoa_app.h"
+
+
+@implementation WineApplication
+
+ - (void) transformProcessToForeground
+ {
+ if ([self activationPolicy] != NSApplicationActivationPolicyRegular)
+ {
+ NSMenu* mainMenu;
+ NSMenu* submenu;
+ NSString* bundleName;
+ NSString* title;
+ NSMenuItem* item;
+
+ [self setActivationPolicy:NSApplicationActivationPolicyRegular];
+ [self activateIgnoringOtherApps:YES];
+
+ mainMenu = [[[NSMenu alloc] init] autorelease];
+
+ submenu = [[[NSMenu alloc] initWithTitle:@"Wine"] autorelease];
+ bundleName = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString*)kCFBundleNameKey];
+ if ([bundleName length])
+ title = [NSString stringWithFormat:@"Quit %@", bundleName];
+ else
+ title = @"Quit";
+ item = [submenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
+ [item setKeyEquivalentModifierMask:NSCommandKeyMask | NSAlternateKeyMask];
+ item = [[[NSMenuItem alloc] init] autorelease];
+ [item setTitle:@"Wine"];
+ [item setSubmenu:submenu];
+ [mainMenu addItem:item];
+
+ [self setMainMenu:mainMenu];
+ }
+ }
+
+@end