From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/ntdll/unix/thread.c | 19 +++++++++++++++++++ dlls/winemac.drv/cocoa_main.m | 14 ++++++++------ dlls/winemac.drv/macdrv_cocoa.h | 1 + dlls/winemac.drv/macdrv_main.c | 11 +++++++++++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 3ab7cb9c283..c5468039ecb 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -64,6 +64,7 @@ #ifdef __APPLE__ #include <mach/mach.h> +#include <CoreFoundation/CoreFoundation.h> #endif #ifdef __FreeBSD__ #include <sys/thr.h> @@ -1316,6 +1317,24 @@ static NTSTATUS spawn_thread( struct thread_data *data ) pthread_attr_t attr; NTSTATUS status = STATUS_SUCCESS; +#ifdef __APPLE__ + if (data->start == CFRunLoopRun) + { + CFRunLoopSourceContext context = { .perform = (void *)server_init_thread, .info = data }; + CFRunLoopSourceRef source; + + if (!(source = CFRunLoopSourceCreate( NULL, 0, &context ))) return STATUS_NO_MEMORY; + + InterlockedIncrement( &nb_threads ); + CFRunLoopAddSource( CFRunLoopGetMain(), source, kCFRunLoopCommonModes ); + CFRunLoopSourceSignal( source ); + CFRunLoopWakeUp( CFRunLoopGetMain() ); + CFRelease( source ); + + return STATUS_SUCCESS; + } +#endif /* __APPLE__ */ + pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset ); pthread_attr_init( &attr ); pthread_attr_setstack( &attr, get_kernel_stack( data ), kernel_stack_size ); diff --git a/dlls/winemac.drv/cocoa_main.m b/dlls/winemac.drv/cocoa_main.m index b3190d80e2a..29db337607b 100644 --- a/dlls/winemac.drv/cocoa_main.m +++ b/dlls/winemac.drv/cocoa_main.m @@ -100,6 +100,14 @@ static void run_cocoa_app(void* info) } } +void macdrv_init_cocoa_threads(void) +{ + /* Make sure Cocoa is in multi-threading mode by detaching a + do-nothing thread. */ + [NSThread detachNewThreadSelector:@selector(self) + toTarget:[NSThread class] + withObject:nil]; +} /*********************************************************************** * macdrv_start_cocoa_app @@ -120,12 +128,6 @@ int macdrv_start_cocoa_app(unsigned long long tickcount) NSDate* timeLimit; CFRunLoopSourceContext source_context = { 0 }; - /* Make sure Cocoa is in multi-threading mode by detaching a - do-nothing thread. */ - [NSThread detachNewThreadSelector:@selector(self) - toTarget:[NSThread class] - withObject:nil]; - if (!(timeLimit = [NSDate dateWithTimeIntervalSinceNow:5])) return -1; if (!(startup_info.lock = [[NSConditionLock alloc] initWithCondition:COCOA_APP_NOT_RUNNING])) return -1; diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 9a91edbe8e3..6026b53054a 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -200,6 +200,7 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point) return point; } +extern void macdrv_init_cocoa_threads(void); extern int macdrv_start_cocoa_app(unsigned long long tickcount); extern void macdrv_window_rejected_focus(const struct macdrv_event *event); extern void macdrv_beep(void); diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index 96168242cc2..39d3efbc577 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -428,6 +428,7 @@ static NTSTATUS macdrv_init(void *arg) struct init_params *params = arg; SessionAttributeBits attributes; OSStatus status; + HANDLE thread; app_icon_callback = params->app_icon_callback; app_quit_request_callback = params->app_quit_request_callback; @@ -442,6 +443,16 @@ static NTSTATUS macdrv_init(void *arg) setup_options(); load_strings(params->strings); + macdrv_init_cocoa_threads(); + + /* convert the main thread to a Wine thread */ + if ((status = PsCreateSystemThread(&thread, THREAD_ALL_ACCESS, NULL, 0, NULL, (void *)CFRunLoopRun, NULL))) + { + ERR("Failed to spawn main thread, status %#x\n", status); + return STATUS_UNSUCCESSFUL; + } + NtClose(thread); + macdrv_err_on = ERR_ON(macdrv); if (macdrv_start_cocoa_app(NtGetTickCount())) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11333