From e53dbbcc6b3648637a291cc529c6df8f9e06b203 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <vital.had@gmail.com>
Date: Thu, 28 May 2026 18:43:05 +0800
Subject: [PATCH 5/8] xquartz: X11Application.m: fallbacks to support < 10.6

---
 hw/xquartz/X11Application.m | 101 ++++++++++++++++++++++++++++++++++--
 1 file changed, 96 insertions(+), 5 deletions(-)

diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m
index a91f71894..4053452b8 100644
--- a/hw/xquartz/X11Application.m
+++ b/hw/xquartz/X11Application.m
@@ -159,6 +159,16 @@ X11Application *X11App;
 
 @interface X11Application (Private)
 - (void) sendX11NSEvent:(NSEvent *)e;
+#ifndef HAS_LIBDISPATCH
+- (void)setWindowMenuCompat:(NSArray *)items;
+- (void)setWindowMenuCheckCompat:(NSNumber *)idx;
+- (void)setFrontProcessCompat:(id)unused;
+- (void)setCanQuitCompat:(NSNumber *)state;
+- (void)serverReadyCompat:(id)unused;
+- (void)showHideMenubarCompat:(NSNumber *)state;
+- (void)launchClientCompat:(NSString *)cmd;
+- (void)runAlertPanelCompat:(NSMutableDictionary *)ctx;
+#endif
 @end
 
 @interface X11Application ()
@@ -492,6 +502,7 @@ sendX11NSEvent_fptr(void *e_ptr)
         NSEvent *event_copy = [e retain];
         dispatch_async_f(eventTranslationQueue, event_copy, sendX11NSEvent_fptr);
 #else
+        /* On 10.5, process events directly without async queue */
         [self sendX11NSEvent:e];
 #endif
     }
@@ -525,7 +536,6 @@ sendX11NSEvent_fptr(void *e_ptr)
     (void)[self.controller application:self openFile:cmd];
 }
 
-
 - (void) read_defaults
 {
     NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults;
@@ -614,9 +624,15 @@ X11ApplicationSetWindowMenu(int nitems, const char **items,
             [menuItem release];
         }
 
+#ifdef HAS_LIBDISPATCH
         dispatch_async_f(dispatch_get_main_queue(),
                          allMenuItems,
                          setWindowMenuOnMain_fptr);
+#else
+        [X11App performSelectorOnMainThread:@selector(setWindowMenuCompat:)
+                                  withObject:allMenuItems
+                               waitUntilDone:NO];
+#endif
     OBJC_AUTORELEASEPOOL_END
 }
 
@@ -632,10 +648,15 @@ void
 X11ApplicationSetWindowMenuCheck(int idx)
 {
     NSNumber *num = [[NSNumber alloc] initWithInt:idx];
+#ifdef HAS_LIBDISPATCH
     dispatch_async_f(dispatch_get_main_queue(), num, setWindowMenuCheck_fptr);
+#else
+    [X11App performSelectorOnMainThread:@selector(setWindowMenuCheckCompat:)
+                              withObject:num
+                           waitUntilDone:NO];
+#endif
 }
 
-
 static void
 appSetFrontProcess_fptr(void* unused)
 {
@@ -645,7 +666,13 @@ appSetFrontProcess_fptr(void* unused)
 void
 X11ApplicationSetFrontProcess(void)
 {
+#ifdef HAS_LIBDISPATCH
     dispatch_async_f(dispatch_get_main_queue(), NULL, appSetFrontProcess_fptr);
+#else
+    [X11App performSelectorOnMainThread:@selector(setFrontProcessCompat:)
+                              withObject:nil
+                           waitUntilDone:NO];
+#endif
 }
 
 static void
@@ -659,7 +686,13 @@ void
 X11ApplicationSetCanQuit(int state)
 {
     NSNumber *state_alloc = [[NSNumber alloc] initWithInt:state];
+#ifdef HAS_LIBDISPATCH
     dispatch_async_f(dispatch_get_main_queue(), state_alloc, appSetCanQuit_fptr);
+#else
+    [X11App performSelectorOnMainThread:@selector(setCanQuitCompat:)
+                              withObject:state_alloc
+                           waitUntilDone:NO];
+#endif
 }
 
 static void
@@ -671,7 +704,13 @@ appServerReady_fptr(void* unused)
 void
 X11ApplicationServerReady(void)
 {
+#ifdef HAS_LIBDISPATCH
     dispatch_async_f(dispatch_get_main_queue(), NULL, appServerReady_fptr);
+#else
+    [X11App performSelectorOnMainThread:@selector(serverReadyCompat:)
+                              withObject:nil
+                           waitUntilDone:NO];
+#endif
 }
 
 static void
@@ -685,7 +724,13 @@ void
 X11ApplicationShowHideMenubar(int state)
 {
     NSNumber *state_alloc = [[NSNumber alloc] initWithInt:state];
+#ifdef HAS_LIBDISPATCH
     dispatch_async_f(dispatch_get_main_queue(), state_alloc, appShowHideMenubar_fptr);
+#else
+    [X11App performSelectorOnMainThread:@selector(showHideMenubarCompat:)
+                              withObject:state_alloc
+                           waitUntilDone:NO];
+#endif
 }
 
 static void
@@ -700,11 +745,16 @@ X11ApplicationLaunchClient(const char *cmd)
 {
     OBJC_AUTORELEASEPOOL_BEGIN
         NSString *string_alloc = [[NSString alloc] initWithUTF8String:cmd];
+#ifdef HAS_LIBDISPATCH
         dispatch_async_f(dispatch_get_main_queue(), string_alloc, appLaunchClient_fptr);
+#else
+        [X11App performSelectorOnMainThread:@selector(launchClientCompat:)
+                                  withObject:string_alloc
+                               waitUntilDone:NO];
+#endif
     OBJC_AUTORELEASEPOOL_END
 }
 
-
 /* helper function for X11ApplicationCanEnterRandR(),
  * extracted from previous Apple block */
 static void
@@ -733,7 +783,7 @@ runAlertPanel(void *result_ptr)
 Bool
 X11ApplicationCanEnterRandR(void)
 {
-    
+
     NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults;
 
     if ([defaults boolForKey:XQuartzPrefKeyNoRANDRAlert] ||
@@ -744,7 +794,16 @@ X11ApplicationCanEnterRandR(void)
         QuartzShowFullscreen(FALSE);
 
     NSInteger alert_result;
+#ifdef HAS_LIBDISPATCH
     dispatch_sync_f(dispatch_get_main_queue(), &alert_result, runAlertPanel);
+#else
+    NSMutableDictionary *ctx = [[NSMutableDictionary alloc] init];
+    [ctx setObject:[NSValue valueWithPointer:&alert_result] forKey:@"result"];
+    [X11App performSelectorOnMainThread:@selector(runAlertPanelCompat:)
+                              withObject:ctx
+                           waitUntilDone:YES];
+    [ctx release];
+#endif
 
     switch (alert_result) {
     case NSAlertOtherReturn:
@@ -851,7 +910,7 @@ X11ApplicationMain(int argc, char **argv, char **envp)
 
         /* Calculate the height of the menubar so we can avoid it. */
         aquaMenuBarHeight = [[NSApp mainMenu] menuBarHeight];
-#if ! __LP64__
+#if !__LP64__
         if (!aquaMenuBarHeight) {
             aquaMenuBarHeight = [NSMenuView menuBarHeight];
         }
@@ -900,6 +959,34 @@ X11ApplicationMain(int argc, char **argv, char **envp)
 
 @implementation X11Application (Private)
 
+#ifndef HAS_LIBDISPATCH
+- (void)setWindowMenuCompat:(NSArray *)items {
+    setWindowMenuOnMain_fptr(items);
+}
+- (void)setWindowMenuCheckCompat:(NSNumber *)idx {
+    setWindowMenuCheck_fptr(idx);
+}
+- (void)setFrontProcessCompat:(id)unused {
+    appSetFrontProcess_fptr(NULL);
+}
+- (void)setCanQuitCompat:(NSNumber *)state {
+    appSetCanQuit_fptr(state);
+}
+- (void)serverReadyCompat:(id)unused {
+    appServerReady_fptr(NULL);
+}
+- (void)showHideMenubarCompat:(NSNumber *)state {
+    appShowHideMenubar_fptr(state);
+}
+- (void)launchClientCompat:(NSString *)cmd {
+    appLaunchClient_fptr(cmd);
+}
+- (void)runAlertPanelCompat:(NSMutableDictionary *)ctx {
+    NSInteger *result = [[ctx objectForKey:@"result"] pointerValue];
+    runAlertPanel(result);
+}
+#endif
+
 #ifdef NX_DEVICELCMDKEYMASK
 /* This is to workaround a bug in the VNC server where we sometimes see the L
  * modifier and sometimes see no "side"
@@ -1424,7 +1511,11 @@ handle_mouse:
             if (pthread_main_np()) {
                 copyKeyboardLayout_fptr(&ctx);
             } else {
+#ifdef HAS_LIBDISPATCH
                 dispatch_sync_f(dispatch_get_main_queue(), &ctx, copyKeyboardLayout_fptr);
+#else
+                copyKeyboardLayout_fptr(&ctx);
+#endif
             }
 
             TISInputSourceRef clear;
-- 
2.54.0

