From 5f10f6b123c3aa94e19d0ef0e5887945b33d6e35 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Fri, 30 May 2025 01:07:10 +0800 Subject: [PATCH 1/9] hw/xquartz: replace sources with working 1.20-legacy --- hw/xquartz/GL/indirect.c | 2 + hw/xquartz/NSUserDefaults+XQuartzDefaults.h | 49 -- hw/xquartz/NSUserDefaults+XQuartzDefaults.m | 148 ---- hw/xquartz/X11Application.h | 63 +- hw/xquartz/X11Application.m | 888 ++++++++++++++++---- hw/xquartz/X11Controller.h | 108 ++- hw/xquartz/X11Controller.m | 584 +++++++------ hw/xquartz/applewm.c | 2 +- hw/xquartz/applewmExt.h | 6 + hw/xquartz/bundle/Info.plist.cpp | 33 +- hw/xquartz/console_redirect.c | 482 +++++++++++ hw/xquartz/console_redirect.h | 46 + hw/xquartz/darwin.c | 33 + hw/xquartz/darwinEvents.c | 3 - hw/xquartz/mach-startup/bundle-main.c | 89 +- hw/xquartz/mach-startup/stub.c | 126 ++- hw/xquartz/man/Xquartz.man | 2 +- hw/xquartz/pbproxy/app-main.m | 40 + hw/xquartz/pbproxy/main.m | 66 +- hw/xquartz/pbproxy/pbproxy.h | 11 + hw/xquartz/pbproxy/x-input.m | 13 +- hw/xquartz/pbproxy/x-selection.m | 73 +- hw/xquartz/quartz.c | 54 +- hw/xquartz/quartz.h | 11 - hw/xquartz/quartzCocoa.m | 66 ++ hw/xquartz/quartzCommon.h | 55 ++ hw/xquartz/quartzKeyboard.c | 182 +++- hw/xquartz/quartzRandR.c | 153 ++++ hw/xquartz/quartzStartup.c | 4 +- hw/xquartz/xpr/appledristr.h | 160 ++-- hw/xquartz/xpr/dri.c | 2 + hw/xquartz/xpr/x-list.c | 3 +- hw/xquartz/xpr/xprAppleWM.c | 10 + hw/xquartz/xpr/xprEvent.c | 23 +- hw/xquartz/xpr/xprFrame.c | 65 +- hw/xquartz/xpr/xprScreen.c | 32 +- 36 files changed, 2701 insertions(+), 986 deletions(-) delete mode 100644 hw/xquartz/NSUserDefaults+XQuartzDefaults.h delete mode 100644 hw/xquartz/NSUserDefaults+XQuartzDefaults.m create mode 100644 hw/xquartz/console_redirect.c create mode 100644 hw/xquartz/console_redirect.h create mode 100644 hw/xquartz/quartzCocoa.m create mode 100644 hw/xquartz/quartzCommon.h diff --git a/hw/xquartz/GL/indirect.c b/hw/xquartz/GL/indirect.c index a8ccfc8ee..6738946ff 100644 --- a/hw/xquartz/GL/indirect.c +++ b/hw/xquartz/GL/indirect.c @@ -35,6 +35,8 @@ #include #endif +#include + #include #include diff --git a/hw/xquartz/NSUserDefaults+XQuartzDefaults.h b/hw/xquartz/NSUserDefaults+XQuartzDefaults.h deleted file mode 100644 index 2f180b241..000000000 --- a/hw/xquartz/NSUserDefaults+XQuartzDefaults.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// NSUserDefaults+XQuartzDefaults.h -// XQuartz -// -// Created by Jeremy Huddleston Sequoia on 2021.02.19. -// Copyright (c) 2021 Apple Inc. All rights reserved. -// - -#import - -extern NSString * const XQuartzPrefKeyAppsMenu; -extern NSString * const XQuartzPrefKeyFakeButtons; -extern NSString * const XQuartzPrefKeyFakeButton2; -extern NSString * const XQuartzPrefKeyFakeButton3; -extern NSString * const XQuartzPrefKeyKeyEquivs; -extern NSString * const XQuartzPrefKeyFullscreenHotkeys; -extern NSString * const XQuartzPrefKeyFullscreenMenu; -extern NSString * const XQuartzPrefKeySyncKeymap; -extern NSString * const XQuartzPrefKeyDepth; -extern NSString * const XQuartzPrefKeyNoAuth; -extern NSString * const XQuartzPrefKeyNoTCP; -extern NSString * const XQuartzPrefKeyDoneXinitCheck; -extern NSString * const XQuartzPrefKeyNoQuitAlert; -extern NSString * const XQuartzPrefKeyNoRANDRAlert; -extern NSString * const XQuartzPrefKeyOptionSendsAlt; -extern NSString * const XQuartzPrefKeyAppKitModifiers; -extern NSString * const XQuartzPrefKeyWindowItemModifiers; -extern NSString * const XQuartzPrefKeyRootless; -extern NSString * const XQuartzPrefKeyRENDERExtension; -extern NSString * const XQuartzPrefKeyTESTExtension; -extern NSString * const XQuartzPrefKeyLoginShell; -extern NSString * const XQuartzPrefKeyClickThrough; -extern NSString * const XQuartzPrefKeyFocusFollowsMouse; -extern NSString * const XQuartzPrefKeyFocusOnNewWindow; - -extern NSString * const XQuartzPrefKeyScrollInDeviceDirection; -extern NSString * const XQuartzPrefKeySyncPasteboard; -extern NSString * const XQuartzPrefKeySyncPasteboardToClipboard; -extern NSString * const XQuartzPrefKeySyncPasteboardToPrimary; -extern NSString * const XQuartzPrefKeySyncClipboardToPasteBoard; -extern NSString * const XQuartzPrefKeySyncPrimaryOnSelect; - -@interface NSUserDefaults (XQuartzDefaults) - -+ (NSUserDefaults *)globalDefaults; -+ (NSUserDefaults *)dockDefaults; -+ (NSUserDefaults *)xquartzDefaults; - -@end diff --git a/hw/xquartz/NSUserDefaults+XQuartzDefaults.m b/hw/xquartz/NSUserDefaults+XQuartzDefaults.m deleted file mode 100644 index ecc192197..000000000 --- a/hw/xquartz/NSUserDefaults+XQuartzDefaults.m +++ /dev/null @@ -1,148 +0,0 @@ -// -// NSUserDefaults+XQuartzDefaults.m -// XQuartz -// -// Created by Jeremy Huddleston Sequoia on 2021.02.19. -// Copyright (c) 2021 Apple Inc. All rights reserved. -// - -#import "NSUserDefaults+XQuartzDefaults.h" -#import - -NSString * const XQuartzPrefKeyAppsMenu = @"apps_menu"; -NSString * const XQuartzPrefKeyFakeButtons = @"enable_fake_buttons"; -NSString * const XQuartzPrefKeyFakeButton2 = @"fake_button2"; -NSString * const XQuartzPrefKeyFakeButton3 = @"fake_button3"; -NSString * const XQuartzPrefKeyKeyEquivs = @"enable_key_equivalents"; -NSString * const XQuartzPrefKeyFullscreenHotkeys = @"fullscreen_hotkeys"; -NSString * const XQuartzPrefKeyFullscreenMenu = @"fullscreen_menu"; -NSString * const XQuartzPrefKeySyncKeymap = @"sync_keymap"; -NSString * const XQuartzPrefKeyDepth = @"depth"; -NSString * const XQuartzPrefKeyNoAuth = @"no_auth"; -NSString * const XQuartzPrefKeyNoTCP = @"nolisten_tcp"; -NSString * const XQuartzPrefKeyDoneXinitCheck = @"done_xinit_check"; -NSString * const XQuartzPrefKeyNoQuitAlert = @"no_quit_alert"; -NSString * const XQuartzPrefKeyNoRANDRAlert = @"no_randr_alert"; -NSString * const XQuartzPrefKeyOptionSendsAlt = @"option_sends_alt"; -NSString * const XQuartzPrefKeyAppKitModifiers = @"appkit_modifiers"; -NSString * const XQuartzPrefKeyWindowItemModifiers = @"window_item_modifiers"; -NSString * const XQuartzPrefKeyRootless = @"rootless"; -NSString * const XQuartzPrefKeyRENDERExtension = @"enable_render_extension"; -NSString * const XQuartzPrefKeyTESTExtension = @"enable_test_extensions"; -NSString * const XQuartzPrefKeyLoginShell = @"login_shell"; -NSString * const XQuartzPrefKeyUpdateFeed = @"update_feed"; -NSString * const XQuartzPrefKeyClickThrough = @"wm_click_through"; -NSString * const XQuartzPrefKeyFocusFollowsMouse = @"wm_ffm"; -NSString * const XQuartzPrefKeyFocusOnNewWindow = @"wm_focus_on_new_window"; - -NSString * const XQuartzPrefKeyScrollInDeviceDirection = @"scroll_in_device_direction"; -NSString * const XQuartzPrefKeySyncPasteboard = @"sync_pasteboard"; -NSString * const XQuartzPrefKeySyncPasteboardToClipboard = @"sync_pasteboard_to_clipboard"; -NSString * const XQuartzPrefKeySyncPasteboardToPrimary = @"sync_pasteboard_to_primary"; -NSString * const XQuartzPrefKeySyncClipboardToPasteBoard = @"sync_clipboard_to_pasteboard"; -NSString * const XQuartzPrefKeySyncPrimaryOnSelect = @"sync_primary_on_select"; - -@implementation NSUserDefaults (XQuartzDefaults) - -+ (NSUserDefaults *)globalDefaults -{ - static dispatch_once_t once; - static NSUserDefaults *defaults; - - dispatch_once(&once, ^{ - NSString * const defaultsDomain = @".GlobalPreferences"; - defaults = [[[NSUserDefaults alloc] initWithSuiteName:defaultsDomain] retain]; - - NSDictionary * const defaultDefaultsDict = @{ - @"AppleSpacesSwitchOnActivate" : @(YES), - }; - - [defaults registerDefaults:defaultDefaultsDict]; - }); - - return defaults; -} - -+ (NSUserDefaults *)dockDefaults -{ - static dispatch_once_t once; - static NSUserDefaults *defaults; - - dispatch_once(&once, ^{ - NSString * const defaultsDomain = @"com.apple.dock"; - defaults = [[[NSUserDefaults alloc] initWithSuiteName:defaultsDomain] retain]; - - NSDictionary * const defaultDefaultsDict = @{ - @"workspaces" : @(NO), - }; - - [defaults registerDefaults:defaultDefaultsDict]; - }); - - return defaults; -} - -+ (NSUserDefaults *)xquartzDefaults -{ - static dispatch_once_t once; - static NSUserDefaults *defaults; - - dispatch_once(&once, ^{ - NSString * const defaultsDomain = @(BUNDLE_ID_PREFIX ".X11"); - NSString * const defaultDefaultsDomain = NSBundle.mainBundle.bundleIdentifier; - if ([defaultsDomain isEqualToString:defaultDefaultsDomain]) { - defaults = [NSUserDefaults.standardUserDefaults retain]; - } else { - defaults = [[[NSUserDefaults alloc] initWithSuiteName:defaultsDomain] retain]; - } - - NSString *defaultWindowItemModifiers = @"command"; - NSString * const defaultWindowItemModifiersLocalized = NSLocalizedString(@"window item modifiers", @"window item modifiers"); - if (![defaultWindowItemModifiersLocalized isEqualToString:@"window item modifiers"]) { - defaultWindowItemModifiers = defaultWindowItemModifiersLocalized; - } - - NSDictionary * const defaultDefaultsDict = @{ - XQuartzPrefKeyFakeButtons : @(NO), - // XQuartzPrefKeyFakeButton2 nil default - // XQuartzPrefKeyFakeButton3 nil default - XQuartzPrefKeyKeyEquivs : @(YES), - XQuartzPrefKeyFullscreenHotkeys : @(NO), - XQuartzPrefKeyFullscreenMenu : @(NO), - XQuartzPrefKeySyncKeymap : @(NO), - XQuartzPrefKeyDepth : @(-1), - XQuartzPrefKeyNoAuth : @(NO), - XQuartzPrefKeyNoTCP : @(NO), - XQuartzPrefKeyDoneXinitCheck : @(NO), - XQuartzPrefKeyNoQuitAlert : @(NO), - XQuartzPrefKeyNoRANDRAlert : @(NO), - XQuartzPrefKeyOptionSendsAlt : @(NO), - // XQuartzPrefKeyAppKitModifiers nil default - XQuartzPrefKeyWindowItemModifiers : defaultWindowItemModifiers, - XQuartzPrefKeyRootless : @(YES), - XQuartzPrefKeyRENDERExtension : @(YES), - XQuartzPrefKeyTESTExtension : @(NO), - XQuartzPrefKeyLoginShell : @"/bin/sh", - XQuartzPrefKeyClickThrough : @(NO), - XQuartzPrefKeyFocusFollowsMouse : @(NO), - XQuartzPrefKeyFocusOnNewWindow : @(YES), - - XQuartzPrefKeyScrollInDeviceDirection : @(NO), - XQuartzPrefKeySyncPasteboard : @(YES), - XQuartzPrefKeySyncPasteboardToClipboard : @(YES), - XQuartzPrefKeySyncPasteboardToPrimary : @(YES), - XQuartzPrefKeySyncClipboardToPasteBoard : @(YES), - XQuartzPrefKeySyncPrimaryOnSelect : @(NO), - }; - - [defaults registerDefaults:defaultDefaultsDict]; - - NSString * const systemDefaultsPlistPath = [@(XQUARTZ_DATA_DIR) stringByAppendingPathComponent:@"defaults.plist"]; - NSDictionary * const systemDefaultsDict = [NSDictionary dictionaryWithContentsOfFile:systemDefaultsPlistPath]; - [defaults registerDefaults:systemDefaultsDict]; - }); - - return defaults; -} - -@end diff --git a/hw/xquartz/X11Application.h b/hw/xquartz/X11Application.h index 1ef98bee3..740a8070a 100644 --- a/hw/xquartz/X11Application.h +++ b/hw/xquartz/X11Application.h @@ -31,17 +31,36 @@ #ifndef X11APPLICATION_H #define X11APPLICATION_H 1 -#include - #if __OBJC__ #import "X11Controller.h" -@interface X11Application : NSApplication +@interface X11Application : NSApplication { + X11Controller *_controller; + + unsigned int _x_active : 1; +} + +- (void)set_controller:controller; +- (void)set_window_menu:(NSArray *)list; -@property (nonatomic, readwrite, strong) X11Controller *controller; -@property (nonatomic, readonly, assign) OSX_BOOL x_active; +- (CFPropertyListRef)prefs_get_copy:(NSString *)key CF_RETURNS_RETAINED; +- (int)prefs_get_integer:(NSString *)key default:(int)def; +- (const char *)prefs_get_string:(NSString *)key default:(const char *)def; +- (float)prefs_get_float:(NSString *)key default:(float)def; +- (int)prefs_get_boolean:(NSString *)key default:(int)def; +- (NSURL *)prefs_copy_url:(NSString *)key default:(NSURL *)def + NS_RETURNS_RETAINED; +- (NSArray *)prefs_get_array:(NSString *)key; +- (void)prefs_set_integer:(NSString *)key value:(int)value; +- (void)prefs_set_float:(NSString *)key value:(float)value; +- (void)prefs_set_boolean:(NSString *)key value:(int)value; +- (void)prefs_set_array:(NSString *)key value:(NSArray *)value; +- (void)prefs_set_string:(NSString *)key value:(NSString *)value; +- (void)prefs_synchronize; +- (X11Controller *)controller; +- (OSX_BOOL)x_active; @end extern X11Application * X11App; @@ -70,6 +89,40 @@ X11ApplicationCanEnterRandR(void); void X11ApplicationMain(int argc, char **argv, char **envp); +#define PREFS_APPSMENU "apps_menu" +#define PREFS_FAKEBUTTONS "enable_fake_buttons" +#define PREFS_KEYEQUIVS "enable_key_equivalents" +#define PREFS_FULLSCREEN_HOTKEYS "fullscreen_hotkeys" +#define PREFS_FULLSCREEN_MENU "fullscreen_menu" +#define PREFS_SYNC_KEYMAP "sync_keymap" +#define PREFS_DEPTH "depth" +#define PREFS_NO_AUTH "no_auth" +#define PREFS_NO_TCP "nolisten_tcp" +#define PREFS_DONE_XINIT_CHECK "done_xinit_check" +#define PREFS_NO_QUIT_ALERT "no_quit_alert" +#define PREFS_NO_RANDR_ALERT "no_randr_alert" +#define PREFS_OPTION_SENDS_ALT "option_sends_alt" +#define PREFS_FAKE_BUTTON2 "fake_button2" +#define PREFS_FAKE_BUTTON3 "fake_button3" +#define PREFS_APPKIT_MODIFIERS "appkit_modifiers" +#define PREFS_WINDOW_ITEM_MODIFIERS "window_item_modifiers" +#define PREFS_ROOTLESS "rootless" +#define PREFS_RENDER_EXTENSION "enable_render_extension" +#define PREFS_TEST_EXTENSIONS "enable_test_extensions" +#define PREFS_XP_OPTIONS "xp_options" +#define PREFS_LOGIN_SHELL "login_shell" +#define PREFS_UPDATE_FEED "update_feed" +#define PREFS_CLICK_THROUGH "wm_click_through" +#define PREFS_FFM "wm_ffm" +#define PREFS_FOCUS_ON_NEW_WINDOW "wm_focus_on_new_window" + +#define PREFS_SCROLL_IN_DEV_DIRECTION "scroll_in_device_direction" extern Bool XQuartzScrollInDeviceDirection; +#define PREFS_SYNC_PB "sync_pasteboard" +#define PREFS_SYNC_PB_TO_CLIPBOARD "sync_pasteboard_to_clipboard" +#define PREFS_SYNC_PB_TO_PRIMARY "sync_pasteboard_to_primary" +#define PREFS_SYNC_CLIPBOARD_TO_PB "sync_clipboard_to_pasteboard" +#define PREFS_SYNC_PRIMARY_ON_SELECT "sync_primary_on_select" + #endif /* X11APPLICATION_H */ diff --git a/hw/xquartz/X11Application.m b/hw/xquartz/X11Application.m index 752ddc3f6..0b1335553 100644 --- a/hw/xquartz/X11Application.m +++ b/hw/xquartz/X11Application.m @@ -34,8 +34,9 @@ #include #endif +#include "quartzCommon.h" + #import "X11Application.h" -#import "NSUserDefaults+XQuartzDefaults.h" #include "darwin.h" #include "quartz.h" @@ -47,6 +48,7 @@ #include #include +#include #include @@ -56,13 +58,17 @@ extern int xpbproxy_run(void); +#define DEFAULTS_FILE X11LIBDIR "/X11/xserver/Xquartz.plist" + #ifndef XSERVER_VERSION #define XSERVER_VERSION "?" #endif +#ifdef HAVE_LIBDISPATCH #include static dispatch_queue_t eventTranslationQueue; +#endif #ifndef __has_feature #define __has_feature(x) 0 @@ -83,7 +89,11 @@ extern Bool noTestExtensions; extern Bool noRenderExtension; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 static TISInputSourceRef last_key_layout; +#else +static KeyboardLayoutRef last_key_layout; +#endif /* This preference is only tested on Lion or later as it's not relevant to * earlier OS versions. @@ -100,6 +110,8 @@ X11Application *X11App; +CFStringRef app_prefs_domain_cfstr = NULL; + #define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | \ NSAlternateKeyMask | NSCommandKeyMask) @@ -156,10 +168,6 @@ @interface X11Application (Private) - (void) sendX11NSEvent:(NSEvent *)e; @end -@interface X11Application () -@property (nonatomic, readwrite, assign) OSX_BOOL x_active; -@end - @implementation X11Application typedef struct message_struct message; @@ -169,14 +177,72 @@ @implementation X11Application NSObject *arg; }; +static mach_port_t _port; + /* Quartz mode initialization routine. This is often dynamically loaded but is statically linked into this X server. */ Bool QuartzModeBundleInit(void); +static void +init_ports(void) +{ + kern_return_t r; + NSPort *p; + + if (_port != MACH_PORT_NULL) return; + + r = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &_port); + if (r != KERN_SUCCESS) return; + + p = [NSMachPort portWithMachPort:_port]; + [p setDelegate:NSApp]; + [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode: + NSDefaultRunLoopMode]; +} + +static void +message_kit_thread(SEL selector, NSObject *arg) +{ + message msg; + kern_return_t r; + + msg.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); + msg.hdr.msgh_size = sizeof(msg); + msg.hdr.msgh_remote_port = _port; + msg.hdr.msgh_local_port = MACH_PORT_NULL; + msg.hdr.msgh_reserved = 0; + msg.hdr.msgh_id = 0; + + msg.selector = selector; + msg.arg = [arg retain]; + + r = mach_msg(&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size, + 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); + if (r != KERN_SUCCESS) + ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r); +} + +- (void) handleMachMessage:(void *)_msg +{ + message *msg = _msg; + + [self performSelector:msg->selector withObject:msg->arg]; + [msg->arg release]; +} + +- (void) set_controller:obj +{ + if (_controller == nil) _controller = [obj retain]; +} + - (void) dealloc { - self.controller = nil; + if (_controller != nil) [_controller release]; + + if (_port != MACH_PORT_NULL) + mach_port_deallocate(mach_task_self(), _port); + [super dealloc]; } @@ -206,12 +272,10 @@ - (void) orderFrontStandardAboutPanel: (id) sender - (void) activateX:(OSX_BOOL)state { - OSX_BOOL const x_active = self.x_active; - - if (x_active == state) + if (_x_active == state) return; - DEBUG_LOG("state=%d, x_active=%d, \n", state, x_active); + DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active); if (state) { if (bgMouseLocationUpdated) { DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, @@ -235,7 +299,7 @@ - (void) activateX:(OSX_BOOL)state DarwinSendDDXEvent(kXquartzDeactivate, 0); } - self.x_active = state; + _x_active = state; } - (void) became_key:(NSWindow *)win @@ -247,14 +311,14 @@ - (void) sendEvent:(NSEvent *)e { /* Don't try sending to X if we haven't initialized. This can happen if AppKit takes over * (eg: uncaught exception) early in launch. + * aquaMenuBarHeight is just a proxy for initialization. */ - if (!eventTranslationQueue) { + if (!aquaMenuBarHeight) { [super sendEvent:e]; return; } OSX_BOOL for_appkit, for_x; - OSX_BOOL const x_active = self.x_active; /* By default pass down the responder chain and to X. */ for_appkit = YES; @@ -267,18 +331,16 @@ - (void) sendEvent:(NSEvent *)e case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: - case NSScrollWheel: - if ([e window] != nil) { /* Pointer event has an (AppKit) window. Probably something for the kit. */ for_x = NO; - if (x_active) [self activateX:NO]; + if (_x_active) [self activateX:NO]; } else if ([self modalWindow] == nil) { /* Must be an X window. Tell appkit windows to resign main/key */ for_appkit = NO; - if (!x_active && quartzProcs->IsX11Window([e windowNumber])) { + if (!_x_active && quartzProcs->IsX11Window([e windowNumber])) { if ([self respondsToSelector:@selector(_setKeyWindow:)] && [self respondsToSelector:@selector(_setMainWindow:)]) { NSWindow *keyWindow = [self keyWindow]; if (keyWindow) { @@ -352,11 +414,14 @@ - (void) sendEvent:(NSEvent *)e swallow_keycode = [e keyCode]; do_swallow = YES; for_x = NO; - } else if (XQuartzEnableKeyEquivalents && +#if XPLUGIN_VERSION >= 1 + } + else if (XQuartzEnableKeyEquivalents && xp_is_symbolic_hotkey_event([e eventRef])) { swallow_keycode = [e keyCode]; do_swallow = YES; for_x = NO; +#endif } else if (XQuartzEnableKeyEquivalents && [[self mainMenu] performKeyEquivalent:e]) { @@ -419,7 +484,7 @@ - (void) sendEvent:(NSEvent *)e case NSApplicationActivatedEventType: for_x = NO; if ([e window] == nil && x_was_active) { - BOOL order_all_windows = YES; + BOOL order_all_windows = YES, workspaces, ok; for_appkit = NO; #if APPKIT_APPFLAGS_HACK @@ -432,9 +497,26 @@ - (void) sendEvent:(NSEvent *)e [self set_front_process:nil]; /* Get the Spaces preference for SwitchOnActivate */ - BOOL const workspaces = [NSUserDefaults.dockDefaults boolForKey:@"workspaces"]; + (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock")); + workspaces = + CFPreferencesGetAppBooleanValue(CFSTR("workspaces"), + CFSTR( + "com.apple.dock"), + &ok); + if (!ok) + workspaces = NO; + if (workspaces) { - order_all_windows = [NSUserDefaults.globalDefaults boolForKey:@"AppleSpacesSwitchOnActivate"]; + (void)CFPreferencesAppSynchronize(CFSTR( + ".GlobalPreferences")); + order_all_windows = + CFPreferencesGetAppBooleanValue(CFSTR( + "AppleSpacesSwitchOnActivate"), + CFSTR( + ".GlobalPreferences"), + &ok); + if (!ok) + order_all_windows = YES; } /* TODO: In the workspaces && !AppleSpacesSwitchOnActivate case, the windows are ordered @@ -445,7 +527,8 @@ - (void) sendEvent:(NSEvent *)e * be restoring one of them. */ if ([e data2] & 0x10) { // 0x10 (bfCPSOrderAllWindowsForward) is set when we use cmd-tab or the dock icon - DarwinSendDDXEvent(kXquartzBringAllToFront, 1, order_all_windows); + DarwinSendDDXEvent(kXquartzBringAllToFront, 1, + order_all_windows); } } break; @@ -468,20 +551,32 @@ - (void) sendEvent:(NSEvent *)e break; /* for gcc */ } - if (for_appkit) { - [super sendEvent:e]; - } + if (for_appkit) [super sendEvent:e]; if (for_x) { +#ifdef HAVE_LIBDISPATCH dispatch_async(eventTranslationQueue, ^{ - [self sendX11NSEvent:e]; - }); + [self sendX11NSEvent:e]; + }); +#else + [self sendX11NSEvent:e]; +#endif } } +- (void) set_window_menu:(NSArray *)list +{ + [_controller set_window_menu:list]; +} + +- (void) set_window_menu_check:(NSNumber *)n +{ + [_controller set_window_menu_check:n]; +} + - (void) set_apps_menu:(NSArray *)list { - [self.controller set_apps_menu:list]; + [_controller set_apps_menu:list]; } - (void) set_front_process:unused @@ -492,6 +587,16 @@ - (void) set_front_process:unused [self activateX:YES]; } +- (void) set_can_quit:(NSNumber *)state +{ + [_controller set_can_quit:[state boolValue]]; +} + +- (void) server_ready:unused +{ + [_controller server_ready]; +} + - (void) show_hide_menubar:(NSNumber *)state { /* Also shows/hides the dock */ @@ -504,53 +609,407 @@ - (void) show_hide_menubar:(NSNumber *)state - (void) launch_client:(NSString *)cmd { - (void)[self.controller application:self openFile:cmd]; + (void)[_controller application:self openFile:cmd]; } +/* user preferences */ -- (void) read_defaults +/* Note that these functions only work for arrays whose elements + can be toll-free-bridged between NS and CF worlds. */ + +static const void * +cfretain(CFAllocatorRef a, const void *b) { - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; + return CFRetain(b); +} - XQuartzRootlessDefault = [defaults boolForKey:XQuartzPrefKeyRootless]; - XQuartzFullscreenMenu = [defaults boolForKey:XQuartzPrefKeyFullscreenMenu]; - XQuartzFullscreenDisableHotkeys = ![defaults boolForKey:XQuartzPrefKeyFullscreenHotkeys]; +static void +cfrelease(CFAllocatorRef a, const void *b) +{ + CFRelease(b); +} - darwinFakeButtons = [defaults boolForKey:XQuartzPrefKeyFakeButtons]; - XQuartzOptionSendsAlt = [defaults boolForKey:XQuartzPrefKeyOptionSendsAlt]; +CF_RETURNS_RETAINED +static CFMutableArrayRef +nsarray_to_cfarray(NSArray *in) +{ + CFMutableArrayRef out; + CFArrayCallBacks cb; + NSObject *ns; + const CFTypeRef *cf; + int i, count; - if (darwinFakeButtons) { - NSString * const fake2 = [defaults stringForKey:XQuartzPrefKeyFakeButton2]; - if (fake2) { - darwinFakeMouse2Mask = DarwinParseModifierList(fake2.UTF8String, TRUE); + memset(&cb, 0, sizeof(cb)); + cb.version = 0; + cb.retain = cfretain; + cb.release = cfrelease; + + count = [in count]; + out = CFArrayCreateMutable(NULL, count, &cb); + + for (i = 0; i < count; i++) { + ns = [in objectAtIndex:i]; + + if ([ns isKindOfClass:[NSArray class]]) + cf = (CFTypeRef)nsarray_to_cfarray((NSArray *)ns); + else + cf = CFRetain((CFTypeRef)ns); + + CFArrayAppendValue(out, cf); + CFRelease(cf); + } + + return out; +} + +static NSMutableArray * +cfarray_to_nsarray(CFArrayRef in) +{ + NSMutableArray *out; + const CFTypeRef *cf; + NSObject *ns; + int i, count; + + count = CFArrayGetCount(in); + out = [[NSMutableArray alloc] initWithCapacity:count]; + + for (i = 0; i < count; i++) { + cf = CFArrayGetValueAtIndex(in, i); + + if (CFGetTypeID(cf) == CFArrayGetTypeID()) + ns = cfarray_to_nsarray((CFArrayRef)cf); + else + ns = [(id) cf retain]; + + [out addObject:ns]; + [ns release]; + } + + return out; +} + +- (CFPropertyListRef) prefs_get_copy:(NSString *)key +{ + CFPropertyListRef value; + + value = CFPreferencesCopyAppValue((CFStringRef)key, + app_prefs_domain_cfstr); + + if (value == NULL) { + static CFDictionaryRef defaults; + + if (defaults == NULL) { + CFStringRef error = NULL; + CFDataRef data; + CFURLRef url; + SInt32 error_code; + + url = (CFURLCreateFromFileSystemRepresentation + (NULL, (unsigned char *)DEFAULTS_FILE, + strlen(DEFAULTS_FILE), false)); + if (CFURLCreateDataAndPropertiesFromResource(NULL, url, &data, + NULL, NULL, + &error_code)) { + defaults = (CFPropertyListCreateFromXMLData + (NULL, data, + kCFPropertyListMutableContainersAndLeaves, + &error)); + if (error != NULL) CFRelease(error); + CFRelease(data); + } + CFRelease(url); + + if (defaults != NULL) { + NSMutableArray *apps, *elt; + int count, i; + NSString *name, *nname; + + /* Localize the names in the default apps menu. */ + + apps = + [(NSDictionary *) defaults objectForKey:@PREFS_APPSMENU]; + if (apps != nil) { + count = [apps count]; + for (i = 0; i < count; i++) { + elt = [apps objectAtIndex:i]; + if (elt != nil && + [elt isKindOfClass:[NSArray class]]) { + name = [elt objectAtIndex:0]; + if (name != nil) { + nname = NSLocalizedString(name, nil); + if (nname != nil && nname != name) + [elt replaceObjectAtIndex:0 withObject: + nname]; + } + } + } + } + } } - NSString * const fake3 = [defaults stringForKey:XQuartzPrefKeyFakeButton3]; - if (fake3) { - darwinFakeMouse3Mask = DarwinParseModifierList(fake3.UTF8String, TRUE); + if (defaults != NULL) value = CFDictionaryGetValue(defaults, key); + if (value != NULL) CFRetain(value); + } + + return value; +} + +- (int) prefs_get_integer:(NSString *)key default:(int)def +{ + CFPropertyListRef value; + int ret; + + value = [self prefs_get_copy:key]; + + if (value != NULL && CFGetTypeID(value) == CFNumberGetTypeID()) + CFNumberGetValue(value, kCFNumberIntType, &ret); + else if (value != NULL && CFGetTypeID(value) == CFStringGetTypeID()) + ret = CFStringGetIntValue(value); + else + ret = def; + + if (value != NULL) CFRelease(value); + + return ret; +} + +- (const char *) prefs_get_string:(NSString *)key default:(const char *)def +{ + CFPropertyListRef value; + const char *ret = NULL; + + value = [self prefs_get_copy:key]; + + if (value != NULL && CFGetTypeID(value) == CFStringGetTypeID()) { + NSString *s = (NSString *)value; + + ret = [s UTF8String]; + } + + if (value != NULL) CFRelease(value); + + return ret != NULL ? ret : def; +} + +- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def +{ + CFPropertyListRef value; + NSURL *ret = NULL; + + value = [self prefs_get_copy:key]; + + if (value != NULL && CFGetTypeID(value) == CFStringGetTypeID()) { + NSString *s = (NSString *)value; + + ret = [NSURL URLWithString:s]; + [ret retain]; + } + + if (value != NULL) CFRelease(value); + + return ret != NULL ? ret : def; +} + +- (float) prefs_get_float:(NSString *)key default:(float)def +{ + CFPropertyListRef value; + float ret = def; + + value = [self prefs_get_copy:key]; + + if (value != NULL + && CFGetTypeID(value) == CFNumberGetTypeID() + && CFNumberIsFloatType(value)) + CFNumberGetValue(value, kCFNumberFloatType, &ret); + else if (value != NULL && CFGetTypeID(value) == CFStringGetTypeID()) + ret = CFStringGetDoubleValue(value); + + if (value != NULL) CFRelease(value); + + return ret; +} + +- (int) prefs_get_boolean:(NSString *)key default:(int)def +{ + CFPropertyListRef value; + int ret = def; + + value = [self prefs_get_copy:key]; + + if (value != NULL) { + if (CFGetTypeID(value) == CFNumberGetTypeID()) + CFNumberGetValue(value, kCFNumberIntType, &ret); + else if (CFGetTypeID(value) == CFBooleanGetTypeID()) + ret = CFBooleanGetValue(value); + else if (CFGetTypeID(value) == CFStringGetTypeID()) { + const char *tem = [(NSString *) value UTF8String]; + if (strcasecmp(tem, "true") == 0 || strcasecmp(tem, "yes") == 0) + ret = YES; + else + ret = NO; } + + CFRelease(value); } + return ret; +} - NSString * const appKitModifiers = [defaults stringForKey:XQuartzPrefKeyAppKitModifiers]; - if (appKitModifiers) { - darwinAppKitModMask = DarwinParseModifierList(appKitModifiers.UTF8String, TRUE); +- (NSArray *) prefs_get_array:(NSString *)key +{ + NSArray *ret = nil; + CFPropertyListRef value; + + value = [self prefs_get_copy:key]; + + if (value != NULL) { + if (CFGetTypeID(value) == CFArrayGetTypeID()) + ret = [cfarray_to_nsarray (value)autorelease]; + + CFRelease(value); } - NSString * const windowItemModifiers = [defaults stringForKey:XQuartzPrefKeyWindowItemModifiers]; - if (windowItemModifiers) { - windowItemModMask = DarwinParseModifierList(windowItemModifiers.UTF8String, FALSE); + return ret; +} + +- (void) prefs_set_integer:(NSString *)key value:(int)value +{ + CFNumberRef x; + + x = CFNumberCreate(NULL, kCFNumberIntType, &value); + + CFPreferencesSetValue((CFStringRef)key, (CFTypeRef)x, + app_prefs_domain_cfstr, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + + CFRelease(x); +} + +- (void) prefs_set_float:(NSString *)key value:(float)value +{ + CFNumberRef x; + + x = CFNumberCreate(NULL, kCFNumberFloatType, &value); + + CFPreferencesSetValue((CFStringRef)key, (CFTypeRef)x, + app_prefs_domain_cfstr, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + + CFRelease(x); +} + +- (void) prefs_set_boolean:(NSString *)key value:(int)value +{ + CFPreferencesSetValue( + (CFStringRef)key, + (CFTypeRef)(value ? kCFBooleanTrue + : kCFBooleanFalse), + app_prefs_domain_cfstr, + kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + +} + +- (void) prefs_set_array:(NSString *)key value:(NSArray *)value +{ + CFArrayRef cfarray; + + cfarray = nsarray_to_cfarray(value); + CFPreferencesSetValue((CFStringRef)key, + (CFTypeRef)cfarray, + app_prefs_domain_cfstr, + kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + CFRelease(cfarray); +} + +- (void) prefs_set_string:(NSString *)key value:(NSString *)value +{ + CFPreferencesSetValue((CFStringRef)key, (CFTypeRef)value, + app_prefs_domain_cfstr, kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); +} + +- (void) prefs_synchronize +{ + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); +} + +- (void) read_defaults +{ + NSString *nsstr; + const char *tem; + + XQuartzRootlessDefault = [self prefs_get_boolean:@PREFS_ROOTLESS + default :XQuartzRootlessDefault]; + XQuartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU + default :XQuartzFullscreenMenu]; + XQuartzFullscreenDisableHotkeys = + ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS + default :! + XQuartzFullscreenDisableHotkeys]; + darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS + default :darwinFakeButtons]; + XQuartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT + default :XQuartzOptionSendsAlt]; + + if (darwinFakeButtons) { + const char *fake2, *fake3; + + fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL]; + fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL]; + + if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList( + fake2, TRUE); + if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList( + fake3, TRUE); + } + + tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL]; + if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE); + + tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL]; + if (tem != NULL) { + windowItemModMask = DarwinParseModifierList(tem, FALSE); + } + else { + nsstr = NSLocalizedString(@"window item modifiers", + @"window item modifiers"); + if (nsstr != NULL) { + tem = [nsstr UTF8String]; + if ((tem != NULL) && strcmp(tem, "window item modifiers")) { + windowItemModMask = DarwinParseModifierList(tem, FALSE); + } + } } - XQuartzEnableKeyEquivalents = [defaults boolForKey:XQuartzPrefKeyKeyEquivs]; + XQuartzEnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS + default : + XQuartzEnableKeyEquivalents]; + + darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP + default :darwinSyncKeymap]; - darwinSyncKeymap = [defaults boolForKey:XQuartzPrefKeySyncKeymap]; + darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH + default :darwinDesiredDepth]; - darwinDesiredDepth = [defaults integerForKey:XQuartzPrefKeyDepth]; + noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS + default :FALSE]; - noTestExtensions = ![defaults boolForKey:XQuartzPrefKeyTESTExtension]; - noRenderExtension = ![defaults boolForKey:XQuartzPrefKeyRENDERExtension]; + noRenderExtension = ![self prefs_get_boolean:@PREFS_RENDER_EXTENSION + default :TRUE]; - XQuartzScrollInDeviceDirection = [defaults boolForKey:XQuartzPrefKeyScrollInDeviceDirection]; + XQuartzScrollInDeviceDirection = + [self prefs_get_boolean:@PREFS_SCROLL_IN_DEV_DIRECTION + default : + XQuartzScrollInDeviceDirection]; + +#if XQUARTZ_SPARKLE + NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil]; + if (url) { + [[SUUpdater sharedUpdater] setFeedURL:url]; + [url release]; + } +#endif } /* This will end up at the end of the responder chain. */ @@ -560,83 +1019,123 @@ - (void) copy:sender AppleWMCopyToPasteboard); } +- (X11Controller *) controller +{ + return _controller; +} + +- (OSX_BOOL) x_active +{ + return _x_active; +} + @end -void -X11ApplicationSetWindowMenu(int nitems, const char **items, - const char *shortcuts) +static NSArray * +array_with_strings_and_numbers(int nitems, const char **items, + const char *numbers) { - @autoreleasepool { - NSMutableArray *> * const allMenuItems = [NSMutableArray array]; + NSMutableArray *array, *subarray; + NSString *string, *number; + int i; - for (int i = 0; i < nitems; i++) { - NSMutableArray * const menuItem = [NSMutableArray array]; - [menuItem addObject:@(items[i])]; + /* (Can't autorelease on the X server thread) */ - if (shortcuts[i] == 0) { - [menuItem addObject:@""]; - } else { - [menuItem addObject:[NSString stringWithFormat:@"%d", shortcuts[i]]]; - } + array = [[NSMutableArray alloc] initWithCapacity:nitems]; + + for (i = 0; i < nitems; i++) { + subarray = [[NSMutableArray alloc] initWithCapacity:2]; + + string = [[NSString alloc] initWithUTF8String:items[i]]; + [subarray addObject:string]; + [string release]; - [allMenuItems addObject:menuItem]; + if (numbers[i] != 0) { + number = [[NSString alloc] initWithFormat:@"%d", numbers[i]]; + [subarray addObject:number]; + [number release]; } + else + [subarray addObject:@""]; - dispatch_async(dispatch_get_main_queue(), ^{ - [X11App.controller set_window_menu:allMenuItems]; - }); + [array addObject:subarray]; + [subarray release]; } + + return array; +} + +void +X11ApplicationSetWindowMenu(int nitems, const char **items, + const char *shortcuts) +{ + NSArray *array; + array = array_with_strings_and_numbers(nitems, items, shortcuts); + + /* Send the array of strings over to the appkit thread */ + + message_kit_thread(@selector (set_window_menu:), array); + [array release]; } void X11ApplicationSetWindowMenuCheck(int idx) { - dispatch_async(dispatch_get_main_queue(), ^{ - [X11App.controller set_window_menu_check:@(idx)]; - }); + NSNumber *n; + + n = [[NSNumber alloc] initWithInt:idx]; + + message_kit_thread(@selector (set_window_menu_check:), n); + + [n release]; } void X11ApplicationSetFrontProcess(void) { - dispatch_async(dispatch_get_main_queue(), ^{ - [X11App set_front_process:nil]; - }); + message_kit_thread(@selector (set_front_process:), nil); } void X11ApplicationSetCanQuit(int state) { - dispatch_async(dispatch_get_main_queue(), ^{ - X11App.controller.can_quit = !!state; - }); + NSNumber *n; + + n = [[NSNumber alloc] initWithBool:state]; + + message_kit_thread(@selector (set_can_quit:), n); + + [n release]; } void X11ApplicationServerReady(void) { - dispatch_async(dispatch_get_main_queue(), ^{ - [X11App.controller server_ready]; - }); + message_kit_thread(@selector (server_ready:), nil); } void X11ApplicationShowHideMenubar(int state) { - dispatch_async(dispatch_get_main_queue(), ^{ - [X11App show_hide_menubar:@(state)]; - }); + NSNumber *n; + + n = [[NSNumber alloc] initWithBool:state]; + + message_kit_thread(@selector (show_hide_menubar:), n); + + [n release]; } void X11ApplicationLaunchClient(const char *cmd) { - @autoreleasepool { - NSString *string = @(cmd); - dispatch_async(dispatch_get_main_queue(), ^{ - [X11App launch_client:string]; - }); - } + NSString *string; + + string = [[NSString alloc] initWithUTF8String:cmd]; + + message_kit_thread(@selector (launch_client:), string); + + [string release]; } /* This is a special function in that it is run from the *SERVER* thread and @@ -647,9 +1146,8 @@ - (void) copy:sender X11ApplicationCanEnterRandR(void) { NSString *title, *msg; - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - if ([defaults boolForKey:XQuartzPrefKeyNoRANDRAlert] || + if ([X11App prefs_get_boolean:@PREFS_NO_RANDR_ALERT default:NO] || XQuartzShieldingWindowLevel != 0) return TRUE; @@ -662,17 +1160,15 @@ - (void) copy:sender if (!XQuartzIsRootless) QuartzShowFullscreen(FALSE); - NSInteger __block alert_result; - dispatch_sync(dispatch_get_main_queue(), ^{ - alert_result = NSRunAlertPanel(title, @"%@", - NSLocalizedString(@"Allow", @""), - NSLocalizedString(@"Cancel", @""), - NSLocalizedString(@"Always Allow", @""), msg); - }); - - switch (alert_result) { + switch (NSRunAlertPanel(title, @"%@", + NSLocalizedString(@"Allow", + @""), + NSLocalizedString(@"Cancel", + @""), + NSLocalizedString(@"Always Allow", @""), msg)) { case NSAlertOtherReturn: - [defaults setBool:YES forKey:XQuartzPrefKeyNoRANDRAlert]; + [X11App prefs_set_boolean:@PREFS_NO_RANDR_ALERT value:YES]; + [X11App prefs_synchronize]; case NSAlertDefaultReturn: return YES; @@ -687,9 +1183,8 @@ - (void) copy:sender { char *tem, buf[1024]; NSString *msg; - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - if ([defaults boolForKey:XQuartzPrefKeyDoneXinitCheck]) + if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO]) return; tem = getenv("HOME"); @@ -723,7 +1218,8 @@ - (void) copy:sender } done: - [defaults setBool:YES forKey:XQuartzPrefKeyDoneXinitCheck]; + [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES]; + [X11App prefs_synchronize]; } static inline pthread_t @@ -735,9 +1231,6 @@ - (void) copy:sender pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (&pthread_attr_set_qos_class_np) { - pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INITIATED, 0); - } pthread_create(&tid, &attr, func, arg); pthread_attr_destroy(&attr); @@ -756,64 +1249,91 @@ - (void) copy:sender void X11ApplicationMain(int argc, char **argv, char **envp) { + NSAutoreleasePool *pool; + #ifdef DEBUG while (access("/tmp/x11-block", F_OK) == 0) sleep(1); #endif - @autoreleasepool { - X11App = (X11Application *)[X11Application sharedApplication]; - [X11App read_defaults]; + pool = [[NSAutoreleasePool alloc] init]; + X11App = (X11Application *)[X11Application sharedApplication]; + init_ports(); - [NSBundle loadNibNamed:@"main" owner:NSApp]; - [NSNotificationCenter.defaultCenter addObserver:NSApp - selector:@selector (became_key:) - name:NSWindowDidBecomeKeyNotification - object:nil]; + app_prefs_domain_cfstr = + (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]; - /* - * The xpr Quartz mode is statically linked into this server. - * Initialize all the Quartz functions. - */ - QuartzModeBundleInit(); + if (app_prefs_domain_cfstr == NULL) { + ErrorF( + "X11ApplicationMain: Unable to determine bundle identifier. Your installation of XQuartz may be broken.\n"); + app_prefs_domain_cfstr = CFSTR(BUNDLE_ID_PREFIX ".X11"); + } - /* Calculate the height of the menubar so we can avoid it. */ - aquaMenuBarHeight = NSApp.mainMenu.menuBarHeight; - if (!aquaMenuBarHeight) { - NSScreen* primaryScreen = NSScreen.screens[0]; - aquaMenuBarHeight = NSHeight(primaryScreen.frame) - NSMaxY(primaryScreen.visibleFrame); - } + [NSApp read_defaults]; + [NSBundle loadNibNamed:@"main" owner:NSApp]; + [[NSNotificationCenter defaultCenter] addObserver:NSApp + selector:@selector (became_key:) + name: + NSWindowDidBecomeKeyNotification object:nil]; - eventTranslationQueue = dispatch_queue_create(BUNDLE_ID_PREFIX ".X11.NSEventsToX11EventsQueue", NULL); - assert(eventTranslationQueue != NULL); + /* + * The xpr Quartz mode is statically linked into this server. + * Initialize all the Quartz functions. + */ + QuartzModeBundleInit(); - /* Set the key layout seed before we start the server */ - last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); + /* Calculate the height of the menubar so we can avoid it. */ + aquaMenuBarHeight = [[NSApp mainMenu] menuBarHeight]; +#if ! __LP64__ + if (!aquaMenuBarHeight) { + aquaMenuBarHeight = [NSMenuView menuBarHeight]; + } +#endif + if (!aquaMenuBarHeight) { + NSScreen* primaryScreen = [[NSScreen screens] objectAtIndex:0]; + aquaMenuBarHeight = NSHeight([primaryScreen frame]) - NSMaxY([primaryScreen visibleFrame]); + } - if (!last_key_layout) { - ErrorF("X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); - } +#ifdef HAVE_LIBDISPATCH + eventTranslationQueue = dispatch_queue_create( + BUNDLE_ID_PREFIX ".X11.NSEventsToX11EventsQueue", NULL); + assert(eventTranslationQueue != NULL); +#endif - if (!QuartsResyncKeymap(FALSE)) { - ErrorF("X11ApplicationMain: Could not build a valid keymap.\n"); - } + /* Set the key layout seed before we start the server */ +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); + + if (!last_key_layout) + ErrorF( + "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); +#else + KLGetCurrentKeyboardLayout(&last_key_layout); + if (!last_key_layout) + ErrorF( + "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n"); +#endif + + if (!QuartsResyncKeymap(FALSE)) { + ErrorF("X11ApplicationMain: Could not build a valid keymap.\n"); + } - /* Tell the server thread that it can proceed */ - QuartzInitServer(argc, argv, envp); + /* Tell the server thread that it can proceed */ + QuartzInitServer(argc, argv, envp); - /* This must be done after QuartzInitServer because it can result in - * an mieqEnqueue() - - */ - check_xinitrc(); + /* This must be done after QuartzInitServer because it can result in + * an mieqEnqueue() - + */ + check_xinitrc(); - create_thread(xpbproxy_x_thread, NULL); + create_thread(xpbproxy_x_thread, NULL); #if XQUARTZ_SPARKLE - [[X11App controller] setup_sparkle]; - [[SUUpdater sharedUpdater] resetUpdateCycle]; - // [[SUUpdater sharedUpdater] checkForUpdates:X11App]; + [[X11App controller] setup_sparkle]; + [[SUUpdater sharedUpdater] resetUpdateCycle]; + // [[SUUpdater sharedUpdater] checkForUpdates:X11App]; #endif - } + [pool release]; [NSApp run]; /* not reached */ } @@ -1017,16 +1537,7 @@ - (void) sendX11NSEvent:(NSEvent *)e goto handle_mouse; case NSOtherMouseDown: - // Get the AppKit button number, and convert it from 0-based to 1-based - ev_button = [e buttonNumber] + 1; - - /* Translate middle mouse button (3 in AppKit) to button 2 in X11, - * and translate additional mouse buttons (4 and higher in AppKit) - * to buttons 8 and higher in X11, to match default behavior of X11 - * on other platforms - */ - ev_button = (ev_button == 3) ? 2 : (ev_button + 4); - + ev_button = 2; ev_type = ButtonPress; goto handle_mouse; @@ -1041,9 +1552,7 @@ - (void) sendX11NSEvent:(NSEvent *)e goto handle_mouse; case NSOtherMouseUp: - // See above comments for NSOtherMouseDown - ev_button = [e buttonNumber] + 1; - ev_button = (ev_button == 3) ? 2 : (ev_button + 4); + ev_button = 2; ev_type = ButtonRelease; goto handle_mouse; @@ -1058,9 +1567,7 @@ - (void) sendX11NSEvent:(NSEvent *)e goto handle_mouse; case NSOtherMouseDragged: - // See above comments for NSOtherMouseDown - ev_button = [e buttonNumber] + 1; - ev_button = (ev_button == 3) ? 2 : (ev_button + 4); + ev_button = 2; ev_type = MotionNotify; goto handle_mouse; @@ -1127,6 +1634,8 @@ - (void) sendX11NSEvent:(NSEvent *)e } if (!XQuartzServerVisible && noTestExtensions) { +#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0 + /* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */ xp_window_id wid = 0; xp_error err; @@ -1139,6 +1648,7 @@ - (void) sendX11NSEvent:(NSEvent *)e err = xp_find_window(location.x, location.y, 0, &wid); if (err != XP_Success || (err == XP_Success && wid == 0)) +#endif { bgMouseLocation = location; bgMouseLocationUpdated = TRUE; @@ -1194,6 +1704,11 @@ - (void) sendX11NSEvent:(NSEvent *)e case NSScrollWheel: { +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 + float deltaX = [e deltaX]; + float deltaY = [e deltaY]; + BOOL isContinuous = NO; +#else CGFloat deltaX = [e deltaX]; CGFloat deltaY = [e deltaY]; CGEventRef cge = [e CGEvent]; @@ -1215,12 +1730,28 @@ - (void) sendX11NSEvent:(NSEvent *)e deltaY *= lineHeight / 5.0; } #endif +#endif - if (XQuartzScrollInDeviceDirection && +#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0 + /* If we're in the background, we need to send a MotionNotify event + * first, since we aren't getting them on background mouse motion + */ + if (!XQuartzServerVisible && noTestExtensions) { + bgMouseLocationUpdated = FALSE; + DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, + location.x, location.y, + 0.0, 0.0); + } +#endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + // TODO: Change 1117 to NSAppKitVersionNumber10_7 when it is defined + if (NSAppKitVersionNumber >= 1117 && + XQuartzScrollInDeviceDirection && [e isDirectionInvertedFromDevice]) { deltaX *= -1; deltaY *= -1; } +#endif /* This hack is in place to better deal with "clicky" scroll wheels: * http://xquartz.macosforge.org/trac/ticket/562 */ @@ -1326,17 +1857,9 @@ - (void) sendX11NSEvent:(NSEvent *)e } if (darwinSyncKeymap) { - __block TISInputSourceRef key_layout; - dispatch_block_t copyCurrentKeyboardLayoutInputSource = ^{ - key_layout = TISCopyCurrentKeyboardLayoutInputSource(); - }; - /* This is an ugly ant-pattern, but it is more expedient to address the problem right now. */ - if (pthread_main_np()) { - copyCurrentKeyboardLayoutInputSource(); - } else { - dispatch_sync(dispatch_get_main_queue(), copyCurrentKeyboardLayoutInputSource); - } - +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + TISInputSourceRef key_layout = + TISCopyCurrentKeyboardLayoutInputSource(); TISInputSourceRef clear; if (CFEqual(key_layout, last_key_layout)) { CFRelease(key_layout); @@ -1346,7 +1869,12 @@ - (void) sendX11NSEvent:(NSEvent *)e clear = last_key_layout; last_key_layout = key_layout; CFRelease(clear); - +#else + KeyboardLayoutRef key_layout; + KLGetCurrentKeyboardLayout(&key_layout); + if (key_layout != last_key_layout) { + last_key_layout = key_layout; +#endif /* Update keyInfo */ if (!QuartsResyncKeymap(TRUE)) { ErrorF( diff --git a/hw/xquartz/X11Controller.h b/hw/xquartz/X11Controller.h index d5be0e8b6..c8b501831 100644 --- a/hw/xquartz/X11Controller.h +++ b/hw/xquartz/X11Controller.h @@ -46,43 +46,76 @@ #undef BOOL #endif -@interface X11Controller : NSObject -@property (nonatomic, readwrite, strong) IBOutlet NSPanel *prefs_panel; - -@property (nonatomic, readwrite, strong) IBOutlet NSButton *fake_buttons; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *enable_fullscreen; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *enable_fullscreen_menu; -@property (nonatomic, readwrite, strong) IBOutlet NSTextField *enable_fullscreen_menu_text; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *enable_keyequivs; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *sync_keymap; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *option_sends_alt; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *scroll_in_device_direction; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *click_through; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *focus_follows_mouse; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *focus_on_new_window; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *enable_auth; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *enable_tcp; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *sync_pasteboard; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *sync_pasteboard_to_clipboard; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *sync_pasteboard_to_primary; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *sync_clipboard_to_pasteboard; -@property (nonatomic, readwrite, strong) IBOutlet NSButton *sync_primary_immediately; -@property (nonatomic, readwrite, strong) IBOutlet NSTextField *sync_text1; -@property (nonatomic, readwrite, strong) IBOutlet NSTextField *sync_text2; -@property (nonatomic, readwrite, strong) IBOutlet NSPopUpButton *depth; - -@property (nonatomic, readwrite, strong) IBOutlet NSMenuItem *x11_about_item; -@property (nonatomic, readwrite, strong) IBOutlet NSMenuItem *dock_window_separator; -@property (nonatomic, readwrite, strong) IBOutlet NSMenuItem *apps_separator; -@property (nonatomic, readwrite, strong) IBOutlet NSMenuItem *toggle_fullscreen_item; - -@property (nonatomic, readwrite, strong) IBOutlet NSMenuItem *copy_menu_item; -@property (nonatomic, readwrite, strong) IBOutlet NSMenu *dock_apps_menu; -@property (nonatomic, readwrite, strong) IBOutlet NSTableView *apps_table; - -@property (nonatomic, readwrite, strong) IBOutlet NSMenu *dock_menu; - -@property (nonatomic, readwrite, assign) OSX_BOOL can_quit; +#ifndef NSINTEGER_DEFINED +#if __LP64__ || NS_BUILD_32_LIKE_64 +typedef long NSInteger; +typedef unsigned long NSUInteger; +#else +typedef int NSInteger; +typedef unsigned int NSUInteger; +#endif +#endif + +@interface X11Controller : NSObject +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 + +#endif +{ + IBOutlet NSPanel *prefs_panel; + + IBOutlet NSButton *fake_buttons; + IBOutlet NSButton *enable_fullscreen; + IBOutlet NSButton *enable_fullscreen_menu; + IBOutlet NSTextField *enable_fullscreen_menu_text; + IBOutlet NSButton *enable_keyequivs; + IBOutlet NSButton *sync_keymap; + IBOutlet NSButton *option_sends_alt; + IBOutlet NSButton *scroll_in_device_direction; + IBOutlet NSButton *click_through; + IBOutlet NSButton *focus_follows_mouse; + IBOutlet NSButton *focus_on_new_window; + IBOutlet NSButton *enable_auth; + IBOutlet NSButton *enable_tcp; + IBOutlet NSButton *sync_pasteboard; + IBOutlet NSButton *sync_pasteboard_to_clipboard; + IBOutlet NSButton *sync_pasteboard_to_primary; + IBOutlet NSButton *sync_clipboard_to_pasteboard; + IBOutlet NSButton *sync_primary_immediately; + IBOutlet NSTextField *sync_text1; + IBOutlet NSTextField *sync_text2; + IBOutlet NSPopUpButton *depth; + + IBOutlet NSMenuItem *window_separator; + // window_separator is DEPRECATED due to this radar: + // NSApplication releases the separator in the Windows menu even though it's an IBOutlet + // It is kept around for localization compatibility and is subject to removal "eventually" + // If it is !NULL (meaning it is in the nib), it is removed from the menu and released + + IBOutlet NSMenuItem *x11_about_item; + IBOutlet NSMenuItem *dock_window_separator; + IBOutlet NSMenuItem *apps_separator; + IBOutlet NSMenuItem *toggle_fullscreen_item; +#ifdef XQUARTZ_SPARKLE + NSMenuItem *check_for_updates_item; // Programmatically enabled +#endif + IBOutlet NSMenuItem *copy_menu_item; + IBOutlet NSMenu *dock_apps_menu; + IBOutlet NSTableView *apps_table; + + NSArray *apps; + NSMutableArray *table_apps; + + IBOutlet NSMenu *dock_menu; + + // This is where in the Windows menu we'll start (this will be the index of the separator) + NSInteger windows_menu_start; + + int checked_window_item; + x_list *pending_apps; + + OSX_BOOL finished_launching; + OSX_BOOL can_quit; +} - (void)set_window_menu:(NSArray *)list; - (void)set_window_menu_check:(NSNumber *)n; @@ -92,6 +125,7 @@ - (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *) update; #endif +- (void)set_can_quit:(OSX_BOOL)state; - (void)server_ready; - (OSX_BOOL)application:(NSApplication *)app openFile:(NSString *)filename; diff --git a/hw/xquartz/X11Controller.m b/hw/xquartz/X11Controller.m index e21aed0d3..c75493c42 100644 --- a/hw/xquartz/X11Controller.m +++ b/hw/xquartz/X11Controller.m @@ -29,14 +29,16 @@ */ #include "sanitizedCarbon.h" +#include #ifdef HAVE_DIX_CONFIG_H #include #endif +#include "quartzCommon.h" + #import "X11Controller.h" #import "X11Application.h" -#import "NSUserDefaults+XQuartzDefaults.h" #include "opaque.h" #include "darwin.h" @@ -57,37 +59,26 @@ extern aslclient aslc; extern char *bundle_id_prefix; -@interface X11Controller () -#ifdef XQUARTZ_SPARKLE -@property (nonatomic, readwrite, strong) NSMenuItem *check_for_updates_item; // Programatically enabled -#endif - -@property (nonatomic, readwrite, strong) NSArray *> *apps; -@property (nonatomic, readwrite, strong) NSMutableArray *> *table_apps; -@property (nonatomic, readwrite, assign) NSInteger windows_menu_nitems; -@property (nonatomic, readwrite, assign) int checked_window_item; -@property (nonatomic, readwrite, assign) x_list *pending_apps; -@property (nonatomic, readwrite, assign) OSX_BOOL finished_launching; -@end - @implementation X11Controller - (void) awakeFromNib { X11Application *xapp = NSApp; + NSArray *array; /* Point X11Application at ourself. */ - xapp.controller = self; - - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - NSArray *appsMenu = [defaults arrayForKey:XQuartzPrefKeyAppsMenu]; + [xapp set_controller:self]; - if (appsMenu) { - int count = appsMenu.count; + array = [xapp prefs_get_array:@PREFS_APPSMENU]; + if (array != nil) { + int count; /* convert from [TITLE1 COMMAND1 TITLE2 COMMAND2 ...] to [[TITLE1 COMMAND1] [TITLE2 COMMAND2] ...] format. */ - if (count > 0 && ![appsMenu[0] isKindOfClass:NSArray.class]) { + + count = [array count]; + if (count > 0 + && ![[array objectAtIndex:0] isKindOfClass:[NSArray class]]) { int i; NSMutableArray *copy, *sub; @@ -95,24 +86,32 @@ - (void) awakeFromNib for (i = 0; i < count / 2; i++) { sub = [[NSMutableArray alloc] initWithCapacity:3]; - [sub addObject:appsMenu[i * 2]]; - [sub addObject:appsMenu[i * 2 + 1]]; + [sub addObject:[array objectAtIndex:i * 2]]; + [sub addObject:[array objectAtIndex:i * 2 + 1]]; [sub addObject:@""]; [copy addObject:sub]; [sub release]; } - appsMenu = copy; - [defaults setObject:appsMenu forKey:XQuartzPrefKeyAppsMenu]; + array = copy; } - [self set_apps_menu:appsMenu]; + [self set_apps_menu:array]; + } + + [[NSNotificationCenter defaultCenter] + addObserver: self + selector: @selector(apps_table_done:) + name: NSWindowWillCloseNotification + object: [apps_table window]]; + + // Setup data about our Windows menu + if (window_separator) { + [[window_separator menu] removeItem:window_separator]; + window_separator = nil; } - [NSNotificationCenter.defaultCenter addObserver:self - selector:@selector(apps_table_done:) - name:NSWindowWillCloseNotification - object:self.apps_table.window]; + windows_menu_start = [[X11App windowsMenu] numberOfItems]; } - (void) item_selected:sender @@ -123,16 +122,80 @@ - (void) item_selected:sender AppleWMWindowMenuItem, [sender tag]); } +- (void) remove_window_menu +{ + NSMenu *menu; + int count, i; + + /* Work backwards so we don't mess up the indices */ + menu = [X11App windowsMenu]; + count = [menu numberOfItems]; + for (i = count - 1; i >= windows_menu_start; i--) + [menu removeItemAtIndex:i]; + + count = [dock_menu indexOfItem:dock_window_separator]; + for (i = 0; i < count; i++) + [dock_menu removeItemAtIndex:0]; +} + +- (void) install_window_menu:(NSArray *)list +{ + NSMenu *menu; + NSMenuItem *item; + int first, count, i; + + menu = [X11App windowsMenu]; + first = windows_menu_start + 1; + count = [list count]; + + // Push a Separator + if (count) { + [menu addItem:[NSMenuItem separatorItem]]; + } + + for (i = 0; i < count; i++) { + NSString *name, *shortcut; + + name = [[list objectAtIndex:i] objectAtIndex:0]; + shortcut = [[list objectAtIndex:i] objectAtIndex:1]; + + if (windowItemModMask == 0 || windowItemModMask == -1) + shortcut = @""; + + item = + (NSMenuItem *)[menu addItemWithTitle:name action: + @selector + (item_selected:) keyEquivalent:shortcut]; + [item setKeyEquivalentModifierMask:(NSUInteger)windowItemModMask]; + [item setTarget:self]; + [item setTag:i]; + [item setEnabled:YES]; + + item = (NSMenuItem *)[dock_menu insertItemWithTitle:name + action:@selector + (item_selected:) keyEquivalent:shortcut + atIndex:i]; + [item setKeyEquivalentModifierMask:(NSUInteger)windowItemModMask]; + [item setTarget:self]; + [item setTag:i]; + [item setEnabled:YES]; + } + + if (checked_window_item >= 0 && checked_window_item < count) { + item = (NSMenuItem *)[menu itemAtIndex:first + checked_window_item]; + [item setState:NSOnState]; + item = (NSMenuItem *)[dock_menu itemAtIndex:checked_window_item]; + [item setState:NSOnState]; + } +} + - (void) remove_apps_menu { NSMenu *menu; NSMenuItem *item; int i; - NSMenuItem * const apps_separator = self.apps_separator; - NSMenu * const dock_apps_menu = self.dock_apps_menu; - - if (self.apps == nil || apps_separator == nil) return; + if (apps == nil || apps_separator == nil) return; menu = [apps_separator menu]; @@ -152,13 +215,14 @@ - (void) remove_apps_menu } } - self.apps = nil; + [apps release]; + apps = nil; } -- (void) prepend_apps_item:(NSArray *> *)list index:(int)i menu:(NSMenu *)menu +- (void) prepend_apps_item:(NSArray *)list index:(int)i menu:(NSMenu *)menu { NSString *title, *shortcut = @""; - NSArray *group; + NSArray *group; NSMenuItem *item; group = [list objectAtIndex:i]; @@ -182,16 +246,13 @@ - (void) prepend_apps_item:(NSArray *> *)list index:(int)i [item setTag:i + 1]; /* can't be zero, so add one */ } -- (void) install_apps_menu:(NSArray *> *)list +- (void) install_apps_menu:(NSArray *)list { NSMenu *menu; int i, count; count = [list count]; - NSMenuItem * const apps_separator = self.apps_separator; - NSMenu * const dock_apps_menu = self.dock_apps_menu; - if (count == 0 || apps_separator == nil) return; menu = [apps_separator menu]; @@ -203,89 +264,28 @@ - (void) install_apps_menu:(NSArray *> *)list [self prepend_apps_item:list index:i menu:dock_apps_menu]; } - self.apps = list; + apps = [list retain]; } -- (void) set_window_menu:(NSArray *> *)list +- (void) set_window_menu:(NSArray *)list { - NSMenu * const menu = X11App.windowsMenu; - NSMenu * const dock_menu = self.dock_menu; - - /* First, remove the existing items from the Window Menu */ - NSInteger itemsToRemove = self.windows_menu_nitems; - if (itemsToRemove > 0) { - NSInteger indexForRemoval = menu.numberOfItems - itemsToRemove - 1; /* we also want to remove the separator */ - - for (NSInteger i = 0 ; i < itemsToRemove + 1 ; i++) { - [menu removeItemAtIndex:indexForRemoval]; - } - - for (NSInteger i = 0 ; i < itemsToRemove; i++) { - [dock_menu removeItemAtIndex:0]; - } - } - - NSInteger const itemsToAdd = list.count; - self.windows_menu_nitems = itemsToAdd; + [self remove_window_menu]; + [self install_window_menu:list]; - if (itemsToAdd > 0) { - NSMenuItem *item; - - // Push a Separator - [menu addItem:[NSMenuItem separatorItem]]; - - for (NSInteger i = 0; i < itemsToAdd; i++) { - NSString *name, *shortcut; - - name = list[i][0]; - shortcut = list[i][1]; - - if (windowItemModMask == 0 || windowItemModMask == -1) - shortcut = @""; - - item = (NSMenuItem *)[menu addItemWithTitle:name - action:@selector(item_selected:) - keyEquivalent:shortcut]; - [item setKeyEquivalentModifierMask:(NSUInteger)windowItemModMask]; - [item setTarget:self]; - [item setTag:i]; - [item setEnabled:YES]; - - item = (NSMenuItem *)[dock_menu insertItemWithTitle:name - action:@selector(item_selected:) - keyEquivalent:shortcut - atIndex:i]; - [item setKeyEquivalentModifierMask:(NSUInteger)windowItemModMask]; - [item setTarget:self]; - [item setTag:i]; - [item setEnabled:YES]; - } - - int const checked_window_item = self.checked_window_item; - if (checked_window_item >= 0 && checked_window_item < itemsToAdd) { - NSInteger first = menu.numberOfItems - itemsToAdd; - item = (NSMenuItem *)[menu itemAtIndex:first + checked_window_item]; - [item setState:NSOnState]; - - item = (NSMenuItem *)[dock_menu itemAtIndex:checked_window_item]; - [item setState:NSOnState]; - } - } - - DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMWindowMenuNotify); + DarwinSendDDXEvent(kXquartzControllerNotify, 1, + AppleWMWindowMenuNotify); } - (void) set_window_menu_check:(NSNumber *)nn { - NSMenu * const menu = X11App.windowsMenu; - NSMenu * const dock_menu = self.dock_menu; + NSMenu *menu; NSMenuItem *item; - int n = nn.intValue; - - NSInteger const count = self.windows_menu_nitems; - NSInteger const first = menu.numberOfItems - count; + int first, count; + int n = [nn intValue]; - int const checked_window_item = self.checked_window_item; + menu = [X11App windowsMenu]; + first = windows_menu_start + 1; + count = [menu numberOfItems] - first; if (checked_window_item >= 0 && checked_window_item < count) { item = (NSMenuItem *)[menu itemAtIndex:first + checked_window_item]; @@ -299,10 +299,10 @@ - (void) set_window_menu_check:(NSNumber *)nn item = (NSMenuItem *)[dock_menu itemAtIndex:n]; [item setState:NSOnState]; } - self.checked_window_item = n; + checked_window_item = n; } -- (void) set_apps_menu:(NSArray *> *)list +- (void) set_apps_menu:(NSArray *)list { [self remove_apps_menu]; [self install_apps_menu:list]; @@ -311,29 +311,31 @@ - (void) set_apps_menu:(NSArray *> *)list #ifdef XQUARTZ_SPARKLE - (void) setup_sparkle { - if (self.check_for_updates_item) + if (check_for_updates_item) return; // already did it... - NSMenu *menu = [self.x11_about_item menu]; + NSMenu *menu = [x11_about_item menu]; - NSMenuItem * const check_for_updates_item = - [menu insertItemWithTitle:NSLocalizedString(@"Check for X11 Updates...", @"Check for X11 Updates...") - action:@selector(checkForUpdates:) - keyEquivalent:@"" - atIndex:1]; + check_for_updates_item = + [menu insertItemWithTitle:NSLocalizedString( + @"Check for X11 Updates...", + @"Check for X11 Updates...") + action:@selector ( + checkForUpdates:) + keyEquivalent:@"" + atIndex:1]; [check_for_updates_item setTarget:[SUUpdater sharedUpdater]]; [check_for_updates_item setEnabled:YES]; - self.check_for_updates_item = check_for_updates_item; - // Set X11Controller as the delegate for the updater. [[SUUpdater sharedUpdater] setDelegate:self]; } // Sent immediately before installing the specified update. -- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update +- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *) + update { - //self.can_quit = YES; + //[self set_can_quit:YES]; } #endif @@ -345,15 +347,14 @@ - (void) launch_client:(NSString *)filename const char *newargv[4]; char buf[128]; char *s; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 int stdout_pipe[2]; int stderr_pipe[2]; +#endif - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - NSString * const shell = [defaults stringForKey:XQuartzPrefKeyLoginShell]; - - newargv[0] = shell.fileSystemRepresentation; + newargv[0] = [X11App prefs_get_string:@PREFS_LOGIN_SHELL default:"/bin/sh"]; newargv[1] = "-c"; - newargv[2] = filename.fileSystemRepresentation; + newargv[2] = [filename UTF8String]; newargv[3] = NULL; s = getenv("DISPLAY"); @@ -362,6 +363,7 @@ - (void) launch_client:(NSString *)filename setenv("DISPLAY", buf, TRUE); } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 if (&asl_log_descriptor) { char *asl_sender; aslmsg amsg = asl_new(ASL_TYPE_MSG); @@ -393,6 +395,7 @@ - (void) launch_client:(NSString *)filename asl_free(amsg); } +#endif /* Do the fork-twice trick to avoid having to reap zombies */ child1 = fork(); @@ -410,11 +413,13 @@ - (void) launch_client:(NSString *)filename _exit(1); case 0: /* child2 */ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 if (&asl_log_descriptor) { /* Replace our stdout/stderr */ dup2(stdout_pipe[1], STDOUT_FILENO); dup2(stderr_pipe[1], STDERR_FILENO); } +#endif /* close all open files except for standard streams */ max_files = sysconf(_SC_OPEN_MAX); @@ -437,18 +442,19 @@ - (void) launch_client:(NSString *)filename waitpid(child1, &status, 0); } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 if (&asl_log_descriptor) { /* Close the write ends of the pipe */ close(stdout_pipe[1]); close(stderr_pipe[1]); } +#endif } - (void) app_selected:sender { int tag; NSString *item; - NSArray *> * const apps = self.apps; tag = [sender tag] - 1; if (apps == nil || tag < 0 || tag >= [apps count]) @@ -462,18 +468,14 @@ - (void) app_selected:sender - (IBAction) apps_table_show:sender { NSArray *columns; - NSMutableArray *> * const oldapps = self.table_apps; - NSTableView * const apps_table = self.apps_table; + NSMutableArray *oldapps = nil; - NSMutableArray *> * const table_apps = [[NSMutableArray alloc] initWithCapacity:1]; - self.table_apps = table_apps; + if (table_apps != nil) + oldapps = table_apps; - NSArray *> * const apps = self.apps; - if (apps != nil) { - for (NSArray * row in apps) { - [table_apps addObject:row.mutableCopy]; - } - } + table_apps = [[NSMutableArray alloc] initWithCapacity:1]; + if (apps != nil) + [table_apps addObjectsFromArray:apps]; columns = [apps_table tableColumns]; [[columns objectAtIndex:0] setIdentifier:@"0"]; @@ -492,26 +494,23 @@ - (IBAction) apps_table_show:sender - (IBAction) apps_table_done:sender { - NSMutableArray *> * const table_apps = self.table_apps; - NSTableView * const apps_table = self.apps_table; [apps_table deselectAll:sender]; /* flush edits? */ [self remove_apps_menu]; [self install_apps_menu:table_apps]; - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - [defaults setObject:table_apps forKey:XQuartzPrefKeyAppsMenu]; + [NSApp prefs_set_array:@PREFS_APPSMENU value:table_apps]; + [NSApp prefs_synchronize]; [[apps_table window] orderOut:sender]; - self.table_apps = nil; + [table_apps release]; + table_apps = nil; } - (IBAction) apps_table_new:sender { NSMutableArray *item; - NSMutableArray *> * const table_apps = self.table_apps; - NSTableView * const apps_table = self.apps_table; int row = [apps_table selectedRow], i; @@ -539,10 +538,8 @@ - (IBAction) apps_table_new:sender - (IBAction) apps_table_duplicate:sender { - NSMutableArray *> * const table_apps = self.table_apps; - NSTableView * const apps_table = self.apps_table; int row = [apps_table selectedRow], i; - NSMutableArray *item; + NSObject *item; if (row < 0) { [self apps_table_new:sender]; @@ -565,8 +562,6 @@ - (IBAction) apps_table_duplicate:sender - (IBAction) apps_table_delete:sender { - NSMutableArray *> * const table_apps = self.table_apps; - NSTableView * const apps_table = self.apps_table; int row = [apps_table selectedRow]; if (row >= 0) { @@ -589,7 +584,6 @@ - (IBAction) apps_table_delete:sender - (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView { - NSMutableArray *> * const table_apps = self.table_apps; if (table_apps == nil) return 0; return [table_apps count]; @@ -598,7 +592,6 @@ - (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView - (id) tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { - NSMutableArray *> * const table_apps = self.table_apps; NSArray *item; int col; @@ -616,8 +609,7 @@ - (id) tableView:(NSTableView *)tableView - (void) tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { - NSMutableArray *> * const table_apps = self.table_apps; - NSMutableArray *item; + NSMutableArray *item; int col; if (table_apps == nil) return; @@ -677,15 +669,16 @@ - (IBAction) previous_window:sender - (IBAction) enable_fullscreen_changed:sender { - XQuartzRootlessDefault = !self.enable_fullscreen.state; + XQuartzRootlessDefault = ![enable_fullscreen intValue]; - [self.enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault]; - [self.enable_fullscreen_menu_text setTextColor:XQuartzRootlessDefault ? NSColor.disabledControlTextColor : NSColor.controlTextColor]; + [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault]; + [enable_fullscreen_menu_text setTextColor:XQuartzRootlessDefault ?[ + NSColor disabledControlTextColor] : [NSColor controlTextColor]]; DarwinSendDDXEvent(kXquartzSetRootless, 1, XQuartzRootlessDefault); - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - [defaults setBool:XQuartzRootlessDefault forKey:XQuartzPrefKeyRootless]; + [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:XQuartzRootlessDefault]; + [NSApp prefs_synchronize]; } - (IBAction) toggle_fullscreen:sender @@ -693,115 +686,179 @@ - (IBAction) toggle_fullscreen:sender DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); } +- (void) set_can_quit:(OSX_BOOL)state +{ + can_quit = state; +} + - (IBAction)prefs_changed:sender { if (!sender) return; - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - - if (sender == self.fake_buttons) { - darwinFakeButtons = !!self.fake_buttons.state; - [defaults setBool:darwinFakeButtons forKey:XQuartzPrefKeyFakeButtons]; - } else if (sender == self.enable_keyequivs) { - XQuartzEnableKeyEquivalents = !!self.enable_keyequivs.state; - [defaults setBool:XQuartzEnableKeyEquivalents forKey:XQuartzPrefKeyKeyEquivs]; - } else if (sender == self.sync_keymap) { - darwinSyncKeymap = !!self.sync_keymap.state; - [defaults setBool:darwinSyncKeymap forKey:XQuartzPrefKeySyncKeymap]; - } else if (sender == self.enable_fullscreen_menu) { - XQuartzFullscreenMenu = !!self.enable_fullscreen_menu.state; - [defaults setBool:XQuartzFullscreenMenu forKey:XQuartzPrefKeyFullscreenMenu]; - } else if (sender == self.option_sends_alt) { + if (sender == fake_buttons) { + darwinFakeButtons = [fake_buttons intValue]; + [NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons]; + } + else if (sender == enable_keyequivs) { + XQuartzEnableKeyEquivalents = [enable_keyequivs intValue]; + [NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value: + XQuartzEnableKeyEquivalents]; + } + else if (sender == sync_keymap) { + darwinSyncKeymap = [sync_keymap intValue]; + [NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap]; + } + else if (sender == enable_fullscreen_menu) { + XQuartzFullscreenMenu = [enable_fullscreen_menu intValue]; + [NSApp prefs_set_boolean:@PREFS_FULLSCREEN_MENU value: + XQuartzFullscreenMenu]; + } + else if (sender == option_sends_alt) { BOOL prev_opt_sends_alt = XQuartzOptionSendsAlt; - XQuartzOptionSendsAlt = !!self.option_sends_alt.state; - [defaults setBool:XQuartzOptionSendsAlt forKey:XQuartzPrefKeyOptionSendsAlt]; + XQuartzOptionSendsAlt = [option_sends_alt intValue]; + [NSApp prefs_set_boolean:@PREFS_OPTION_SENDS_ALT value: + XQuartzOptionSendsAlt]; if (prev_opt_sends_alt != XQuartzOptionSendsAlt) QuartsResyncKeymap(TRUE); - } else if (sender == self.click_through) { - [defaults setBool:!!self.click_through.state forKey:XQuartzPrefKeyClickThrough]; - } else if (sender == self.focus_follows_mouse) { - [defaults setBool:!!self.focus_follows_mouse.state forKey:XQuartzPrefKeyFocusFollowsMouse]; - } else if (sender == self.focus_on_new_window) { - [defaults setBool:!!self.focus_on_new_window.state forKey:XQuartzPrefKeyFocusOnNewWindow]; - } else if (sender == self.enable_auth) { - [defaults setBool:!self.enable_auth.state forKey:XQuartzPrefKeyNoAuth]; - } else if (sender == self.enable_tcp) { - [defaults setBool:!self.enable_tcp.state forKey:XQuartzPrefKeyNoTCP]; - } else if (sender == self.depth) { - [defaults setInteger:self.depth.selectedTag forKey:XQuartzPrefKeyDepth]; - } else if (sender == self.sync_pasteboard) { - BOOL pbproxy_active = self.sync_pasteboard.intValue; - [defaults setBool:pbproxy_active forKey:XQuartzPrefKeySyncPasteboard]; - - [self.sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; - [self.sync_pasteboard_to_primary setEnabled:pbproxy_active]; - [self.sync_clipboard_to_pasteboard setEnabled:pbproxy_active]; - [self.sync_primary_immediately setEnabled:pbproxy_active]; + } + else if (sender == click_through) { + [NSApp prefs_set_boolean:@PREFS_CLICK_THROUGH value:[click_through + intValue]]; + } + else if (sender == focus_follows_mouse) { + [NSApp prefs_set_boolean:@PREFS_FFM value:[focus_follows_mouse + intValue]]; + } + else if (sender == focus_on_new_window) { + [NSApp prefs_set_boolean:@PREFS_FOCUS_ON_NEW_WINDOW value:[ + focus_on_new_window intValue]]; + } + else if (sender == enable_auth) { + [NSApp prefs_set_boolean:@PREFS_NO_AUTH value:![enable_auth intValue] + ]; + } + else if (sender == enable_tcp) { + [NSApp prefs_set_boolean:@PREFS_NO_TCP value:![enable_tcp intValue]]; + } + else if (sender == depth) { + [NSApp prefs_set_integer:@PREFS_DEPTH value:[depth selectedTag]]; + } + else if (sender == sync_pasteboard) { + BOOL pbproxy_active = [sync_pasteboard intValue]; + [NSApp prefs_set_boolean:@PREFS_SYNC_PB value:pbproxy_active]; + + [sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; + [sync_pasteboard_to_primary setEnabled:pbproxy_active]; + [sync_clipboard_to_pasteboard setEnabled:pbproxy_active]; + [sync_primary_immediately setEnabled:pbproxy_active]; // setEnabled doesn't do this... - [self.sync_text1 setTextColor:pbproxy_active ? NSColor.controlTextColor : NSColor.disabledControlTextColor]; - [self.sync_text2 setTextColor:pbproxy_active ? NSColor.controlTextColor : NSColor.disabledControlTextColor]; - } else if (sender == self.sync_pasteboard_to_clipboard) { - [defaults setBool:!!self.sync_pasteboard_to_clipboard.state forKey:XQuartzPrefKeySyncPasteboardToClipboard]; - } else if (sender == self.sync_pasteboard_to_primary) { - [defaults setBool:!!self.sync_pasteboard_to_primary.state forKey:XQuartzPrefKeySyncPasteboardToPrimary]; - } else if (sender == self.sync_clipboard_to_pasteboard) { - [defaults setBool:!!self.sync_clipboard_to_pasteboard.state forKey:XQuartzPrefKeySyncClipboardToPasteBoard]; - } else if (sender == self.sync_primary_immediately) { - [defaults setBool:!!self.sync_primary_immediately.state forKey:XQuartzPrefKeySyncPrimaryOnSelect]; - } else if (sender == self.scroll_in_device_direction) { - XQuartzScrollInDeviceDirection = !!self.scroll_in_device_direction.state; - [defaults setBool:XQuartzScrollInDeviceDirection forKey:XQuartzPrefKeyScrollInDeviceDirection]; + [sync_text1 setTextColor:pbproxy_active ?[NSColor controlTextColor] : + [NSColor disabledControlTextColor]]; + [sync_text2 setTextColor:pbproxy_active ?[NSColor controlTextColor] : + [NSColor disabledControlTextColor]]; + } + else if (sender == sync_pasteboard_to_clipboard) { + [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_CLIPBOARD value:[ + sync_pasteboard_to_clipboard intValue]]; + } + else if (sender == sync_pasteboard_to_primary) { + [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_PRIMARY value:[ + sync_pasteboard_to_primary intValue]]; + } + else if (sender == sync_clipboard_to_pasteboard) { + [NSApp prefs_set_boolean:@PREFS_SYNC_CLIPBOARD_TO_PB value:[ + sync_clipboard_to_pasteboard intValue]]; + } + else if (sender == sync_primary_immediately) { + [NSApp prefs_set_boolean:@PREFS_SYNC_PRIMARY_ON_SELECT value:[ + sync_primary_immediately intValue]]; + } + else if (sender == scroll_in_device_direction) { + XQuartzScrollInDeviceDirection = + [scroll_in_device_direction intValue]; + [NSApp prefs_set_boolean:@PREFS_SCROLL_IN_DEV_DIRECTION value: + XQuartzScrollInDeviceDirection]; } + [NSApp prefs_synchronize]; + DarwinSendDDXEvent(kXquartzReloadPreferences, 0); } - (IBAction) prefs_show:sender { - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - - BOOL pbproxy_active = [defaults boolForKey:XQuartzPrefKeySyncPasteboard]; - - [self.scroll_in_device_direction setIntValue:XQuartzScrollInDeviceDirection]; - - [self.fake_buttons setIntValue:darwinFakeButtons]; - [self.enable_keyequivs setIntValue:XQuartzEnableKeyEquivalents]; - [self.sync_keymap setIntValue:darwinSyncKeymap]; - [self.option_sends_alt setIntValue:XQuartzOptionSendsAlt]; - [self.click_through setIntValue:[defaults boolForKey:XQuartzPrefKeyClickThrough]]; - [self.focus_follows_mouse setIntValue:[defaults boolForKey:XQuartzPrefKeyFocusFollowsMouse]]; - [self.focus_on_new_window setIntValue:[defaults boolForKey:XQuartzPrefKeyFocusOnNewWindow]]; + BOOL pbproxy_active = + [NSApp prefs_get_boolean:@PREFS_SYNC_PB default:YES]; - [self.enable_auth setIntValue:![defaults boolForKey:XQuartzPrefKeyNoAuth]]; - [self.enable_tcp setIntValue:![defaults boolForKey:XQuartzPrefKeyNoTCP]]; - - [self.depth selectItemAtIndex:[self.depth indexOfItemWithTag:[defaults integerForKey:XQuartzPrefKeyDepth]]]; - - [self.sync_pasteboard setIntValue:pbproxy_active]; - [self.sync_pasteboard_to_clipboard setIntValue:[defaults boolForKey:XQuartzPrefKeySyncPasteboardToClipboard]]; - [self.sync_pasteboard_to_primary setIntValue:[defaults boolForKey:XQuartzPrefKeySyncPasteboardToPrimary]]; - [self.sync_clipboard_to_pasteboard setIntValue:[defaults boolForKey:XQuartzPrefKeySyncClipboardToPasteBoard]]; - [self.sync_primary_immediately setIntValue:[defaults boolForKey:XQuartzPrefKeySyncPrimaryOnSelect]]; + // Remove preferences from the GUI which are not supported + // TODO: Change 1117 to NSAppKitVersionNumber10_7 when it is defined + if (scroll_in_device_direction && NSAppKitVersionNumber < 1117) { + [scroll_in_device_direction removeFromSuperview]; + scroll_in_device_direction = nil; + } + else { + [scroll_in_device_direction setIntValue: + XQuartzScrollInDeviceDirection]; + } - [self.sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; - [self.sync_pasteboard_to_primary setEnabled:pbproxy_active]; - [self.sync_clipboard_to_pasteboard setEnabled:pbproxy_active]; - [self.sync_primary_immediately setEnabled:pbproxy_active]; + [fake_buttons setIntValue:darwinFakeButtons]; + [enable_keyequivs setIntValue:XQuartzEnableKeyEquivalents]; + [sync_keymap setIntValue:darwinSyncKeymap]; + [option_sends_alt setIntValue:XQuartzOptionSendsAlt]; + [click_through setIntValue:[NSApp prefs_get_boolean:@PREFS_CLICK_THROUGH + default:NO]]; + [focus_follows_mouse setIntValue:[NSApp prefs_get_boolean:@PREFS_FFM + default:NO]]; + [focus_on_new_window setIntValue:[NSApp prefs_get_boolean: + @PREFS_FOCUS_ON_NEW_WINDOW default:YES] + ]; + + [enable_auth setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_AUTH default + :NO]]; + [enable_tcp setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_TCP default: + NO]]; + + [depth selectItemAtIndex:[depth indexOfItemWithTag:[NSApp + prefs_get_integer: + @PREFS_DEPTH default: + -1]]]; + + [sync_pasteboard setIntValue:pbproxy_active]; + [sync_pasteboard_to_clipboard setIntValue:[NSApp prefs_get_boolean: + @PREFS_SYNC_PB_TO_CLIPBOARD + default:YES]]; + [sync_pasteboard_to_primary setIntValue:[NSApp prefs_get_boolean: + @PREFS_SYNC_PB_TO_PRIMARY + default:YES]]; + [sync_clipboard_to_pasteboard setIntValue:[NSApp prefs_get_boolean: + @PREFS_SYNC_CLIPBOARD_TO_PB + default:YES]]; + [sync_primary_immediately setIntValue:[NSApp prefs_get_boolean: + @PREFS_SYNC_PRIMARY_ON_SELECT + default:NO]]; + + [sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; + [sync_pasteboard_to_primary setEnabled:pbproxy_active]; + [sync_clipboard_to_pasteboard setEnabled:pbproxy_active]; + [sync_primary_immediately setEnabled:pbproxy_active]; // setEnabled doesn't do this... - [self.sync_text1 setTextColor:pbproxy_active ? NSColor.controlTextColor : NSColor.disabledControlTextColor]; - [self.sync_text2 setTextColor:pbproxy_active ? NSColor.controlTextColor : NSColor.disabledControlTextColor]; + [sync_text1 setTextColor:pbproxy_active ?[NSColor controlTextColor] : [ + NSColor disabledControlTextColor]]; + [sync_text2 setTextColor:pbproxy_active ?[NSColor controlTextColor] : [ + NSColor disabledControlTextColor]]; - [self.enable_fullscreen setIntValue:!XQuartzRootlessDefault]; - [self.enable_fullscreen_menu setIntValue:XQuartzFullscreenMenu]; - [self.enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault]; - [self.enable_fullscreen_menu_text setTextColor:XQuartzRootlessDefault ? NSColor.disabledControlTextColor : NSColor.controlTextColor]; + [enable_fullscreen setIntValue:!XQuartzRootlessDefault]; + [enable_fullscreen_menu setIntValue:XQuartzFullscreenMenu]; + [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault]; + [enable_fullscreen_menu_text setTextColor:XQuartzRootlessDefault ?[ + NSColor disabledControlTextColor] : [NSColor controlTextColor]]; - [self.prefs_panel makeKeyAndOrderFront:sender]; + [prefs_panel makeKeyAndOrderFront:sender]; } - (IBAction) quit:sender @@ -811,18 +868,23 @@ - (IBAction) quit:sender - (IBAction) x11_help:sender { +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + AHLookupAnchor((CFStringRef)NSLocalizedString(@"Mac Help", + no comment), + CFSTR("mchlp2276")); +#else AHLookupAnchor(CFSTR("com.apple.machelp"), CFSTR("mchlp2276")); +#endif } - (OSX_BOOL) validateMenuItem:(NSMenuItem *)item { NSMenu *menu = [item menu]; - NSMenu * const dock_menu = self.dock_menu; - if (item == self.toggle_fullscreen_item) + if (item == toggle_fullscreen_item) return !XQuartzIsRootless; else if (menu == [X11App windowsMenu] || menu == dock_menu - || (menu == [self.x11_about_item menu] && [item tag] == 42)) + || (menu == [x11_about_item menu] && [item tag] == 42)) return (AppleWMSelectedEvents() & AppleWMControllerNotifyMask) != 0; else return TRUE; @@ -850,11 +912,9 @@ - (NSApplicationTerminateReply) applicationShouldTerminate:sender NSString *msg; NSString *title; - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - - if (self.can_quit || [defaults boolForKey:XQuartzPrefKeyNoQuitAlert]) { + if (can_quit || + [X11App prefs_get_boolean:@PREFS_NO_QUIT_ALERT default:NO]) return NSTerminateNow; - } /* Make sure we're frontmost. */ [NSApp activateIgnoringOtherApps:YES]; @@ -876,6 +936,8 @@ - (NSApplicationTerminateReply) applicationShouldTerminate:sender - (void) applicationWillTerminate:(NSNotification *)aNotification _X_NORETURN { + [X11App prefs_synchronize]; + /* shutdown the X server, it will exit () for us. */ DarwinSendDDXEvent(kXquartzQuit, 0); @@ -889,26 +951,26 @@ - (void) server_ready { x_list *node; - self.finished_launching = YES; + finished_launching = YES; - for (node = self.pending_apps; node != NULL; node = node->next) { + for (node = pending_apps; node != NULL; node = node->next) { NSString *filename = node->data; [self launch_client:filename]; [filename release]; } - x_list_free(self.pending_apps); - self.pending_apps = NULL; + x_list_free(pending_apps); + pending_apps = NULL; } - (OSX_BOOL) application:(NSApplication *)app openFile:(NSString *)filename { const char *name = [filename UTF8String]; - if (self.finished_launching) + if (finished_launching) [self launch_client:filename]; else if (name[0] != ':') /* ignore display names */ - self.pending_apps = x_list_prepend(self.pending_apps, [filename retain]); + pending_apps = x_list_prepend(pending_apps, [filename retain]); /* FIXME: report failures. */ return YES; diff --git a/hw/xquartz/applewm.c b/hw/xquartz/applewm.c index e743a861e..cc91c9608 100644 --- a/hw/xquartz/applewm.c +++ b/hw/xquartz/applewm.c @@ -34,7 +34,7 @@ #include #endif -#include "quartz.h" +#include "quartzCommon.h" #include "misc.h" #include "dixstruct.h" diff --git a/hw/xquartz/applewmExt.h b/hw/xquartz/applewmExt.h index 9a8b8d639..14c77214a 100644 --- a/hw/xquartz/applewmExt.h +++ b/hw/xquartz/applewmExt.h @@ -35,6 +35,12 @@ #include "window.h" #include +#if XPLUGIN_VERSION < 4 +typedef int xp_frame_attr; +typedef int xp_frame_class; +typedef int xp_frame_rect; +#endif + typedef int (*DisableUpdateProc)(void); typedef int (*EnableUpdateProc)(void); typedef int (*SetWindowLevelProc)(WindowPtr pWin, int level); diff --git a/hw/xquartz/bundle/Info.plist.cpp b/hw/xquartz/bundle/Info.plist.cpp index f576f7eb5..6314c7181 100644 --- a/hw/xquartz/bundle/Info.plist.cpp +++ b/hw/xquartz/bundle/Info.plist.cpp @@ -28,45 +28,20 @@ NSSupportsAutomaticGraphicsSwitching - - - NSAppleEventsUsageDescription - A process launched by APPLE_APPLICATION_NAME wants to use AppleScript. - NSCalendarsUsageDescription - A process launched by APPLE_APPLICATION_NAME wants access to your calendar data. - NSCameraUsageDescription - A process launched by APPLE_APPLICATION_NAME wants access to your camera. - NSContactsUsageDescription - A process launched by APPLE_APPLICATION_NAME wants access to your contacts. - NSLocationAlwaysUsageDescription - A process launched by APPLE_APPLICATION_NAME wants access to your location information, even when not in use. - NSLocationUsageDescription - A process launched by APPLE_APPLICATION_NAME wants access to your location information. - NSLocationWhenInUseUsageDescription - A process launched by APPLE_APPLICATION_NAME wants access to your location information when in use. - NSMicrophoneUsageDescription - A process launched by APPLE_APPLICATION_NAME wants access to your microphone. - NSRemindersUsageDescription - A process launched by APPLE_APPLICATION_NAME wants access to your reminders. - NSSystemAdministrationUsageDescription - A process launched by APPLE_APPLICATION_NAME wants admin privileges. - #ifdef XQUARTZ_SPARKLE SUEnableAutomaticChecks - SUPublicEDKey - XQUARTZ_SPARKLE_PUBLIC_EDKEY + SUPublicDSAKeyFile + sparkle.pem SUFeedURL XQUARTZ_SPARKLE_FEED_URL #endif LSApplicationCategoryType public.app-category.utilities NSHumanReadableCopyright - © 2003-2023 Apple Inc. + © 2003-2021 Apple Inc. © 2003 XFree86 Project, Inc. -© 2003-2023 X.org Foundation, Inc. +© 2003-2021 X.org Foundation, Inc. NSMainNibFile main diff --git a/hw/xquartz/console_redirect.c b/hw/xquartz/console_redirect.c new file mode 100644 index 000000000..8fdce4699 --- /dev/null +++ b/hw/xquartz/console_redirect.c @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2011-2012 Apple Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT + * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above + * copyright holders shall not be used in advertising or otherwise to + * promote the sale, use or other dealings in this Software without + * prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#else +#define DEBUG_CONSOLE_REDIRECT 1 +#define HAVE_LIBDISPATCH 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "console_redirect.h" + +#define BUF_SIZE 512 + +#ifdef HAVE_LIBDISPATCH +#include + +static dispatch_queue_t redirect_serial_q; +static dispatch_group_t read_source_group; +#else +#include + +static pthread_t redirect_pthread; +static pthread_mutex_t redirect_fds_lock = PTHREAD_MUTEX_INITIALIZER; + +static int kq; + +/* Notifications to our reader thread */ +#define ASL_REDIRECT_TERMINATE ((void *)(uintptr_t)1) +#endif + +typedef struct { + int level; + aslclient asl; + aslmsg msg; + + /* Buffered reading */ + char *buf; + char *w; + +#ifdef HAVE_LIBDISPATCH + dispatch_source_t read_source; +#endif +} asl_redirect; + +static asl_redirect *redirect_fds = NULL; +static int n_redirect_fds = 0; + +/* Read from the FD until there is no more to read and redirect to ASL. + * Preconditions: + * 1: pthread_mutex_lock lock is held (pthreads) or called + * from the appropriate serial queue for operating on + * redirect_fds + * 2: fd corresponds to a valid entry in redirect_fds + * + * Return values: + * If the pipe is closed, EOF is returned regardless of how many bytes + * were processed. If the pipe is still open, the number of read bytes + * is returned. + */ +static inline int +_read_redirect(int fd, int flush) +{ + int total_read = 0; + int nbytes; + asl_redirect *aslr = &redirect_fds[fd]; + + while ((nbytes = + read(fd, aslr->w, + BUF_SIZE - (aslr->w - aslr->buf) - 1)) > 0) { + char *s, *p; + + /* Increment our returned number read */ + total_read += nbytes; + + /* Increment our write location */ + aslr->w += nbytes; + aslr->w[0] = '\0'; + + /* One line at a time */ + for (p = aslr->buf; p < aslr->w; p = s + 1) { + // Find null or \n + for (s = p; *s && *s != '\n'; s++) ; + if (*s == '\n') { + *s = '\0'; + } + + if (s < aslr->w || aslr->buf == p) { + /* Either the first of multiple messages or one message which is larger than our buffer */ + asl_log(aslr->asl, aslr->msg, aslr->level, "%s", p); + } + else { + /* We reached the end of the buffer, move this chunk to the start. */ + memmove(aslr->buf, p, BUF_SIZE - (p - aslr->buf)); + aslr->w = aslr->buf + (s - p); + break; + } + } + + if (p == aslr->w) { + /* Start writing at the beginning in the case where we flushed */ + aslr->w = aslr->buf; + } + } + + /* Flush if requested or we're at EOF */ + if (flush || nbytes == 0) { + if (aslr->w > aslr->buf) { + *aslr->w = '\0'; + asl_log(aslr->asl, aslr->msg, aslr->level, "%s", aslr->buf); + } + } + + if (nbytes == 0) + return EOF; + return total_read; +} + +#ifdef HAVE_LIBDISPATCH +static void +read_from_source(void *_source) +{ + dispatch_source_t source = (dispatch_source_t)_source; + int fd = dispatch_source_get_handle(source); + if (_read_redirect(fd, 0) == EOF) { + dispatch_source_cancel(source); + } +} + +static void +cancel_source(void *_source) +{ + dispatch_source_t source = (dispatch_source_t)_source; + int fd = dispatch_source_get_handle(source); + asl_redirect *aslr = &redirect_fds[fd]; + + /* Flush the buffer */ + _read_redirect(fd, 1); + + close(fd); + free(aslr->buf); + memset(aslr, 0, sizeof(*aslr)); + dispatch_release(source); + dispatch_group_leave(read_source_group); +} + +#else /* !HAVE_LIBDISPATCH */ +static void * +redirect_thread(void *ctx __unused) +{ + struct kevent ev; + int n; + + while (1) { + n = kevent(kq, NULL, 0, &ev, 1, NULL); + + /* Bail on errors */ + if (n < 0) { + asl_log(NULL, NULL, ASL_LEVEL_ERR, "kevent failure: %s", + strerror(errno)); + break; + } + + /* This should not happen */ + if (n == 0) + continue; + + switch (ev.filter) { + case EVFILT_READ: + pthread_mutex_lock(&redirect_fds_lock); + { + int fd = ev.ident; + int close_fd = 0; + asl_redirect *aslr = &redirect_fds[fd]; + + if (fd < 0 || fd >= n_redirect_fds || aslr->buf == NULL) { + asl_log(NULL, NULL, ASL_LEVEL_ERR, + "Unexpected file descriptor: %d", + fd); + goto next; + } + + if (ev.flags & EV_EOF) { + close_fd = 1; + if (EOF != _read_redirect(fd, 1)) { + asl_log( + NULL, NULL, ASL_LEVEL_ERR, + "kevent reported EOF on %d, but read doesn't concur.", + fd); + } + } + else { + close_fd = (EOF == _read_redirect(fd, 0)); + } + + if (close_fd) { + EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0); + kevent(kq, &ev, 1, NULL, 0, NULL); + close(fd); + free(aslr->buf); + memset(aslr, 0, sizeof(*aslr)); + } + } +next: + pthread_mutex_unlock(&redirect_fds_lock); + + case EVFILT_TIMER: + if (ev.udata == ASL_REDIRECT_TERMINATE) + return NULL; + + default: + ; + ; + } + } + + return NULL; +} +#endif + +static void +redirect_atexit(void) +{ + /* stdout is linebuffered, so flush the buffer */ + if (redirect_fds[STDOUT_FILENO].buf) + fflush(stdout); + +#ifdef HAVE_LIBDISPATCH + { + int i; + + /* Cancel all of our dispatch sources, so they flush to ASL */ + for (i = 0; i < n_redirect_fds; i++) + if (redirect_fds[i].read_source) + dispatch_source_cancel(redirect_fds[i].read_source); + + /* Wait at least three seconds for our sources to flush to ASL */ + dispatch_group_wait(read_source_group, + dispatch_time(DISPATCH_TIME_NOW, 3LL * + NSEC_PER_SEC)); + } +#else + { + struct kevent ev; + + /* Tell our reader thread it is time to pack up and go home */ + EV_SET(&ev, 0, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 0, + ASL_REDIRECT_TERMINATE); + kevent(kq, &ev, 1, NULL, 0, NULL); + + pthread_join(redirect_pthread, NULL); + } +#endif +} + +#ifdef HAVE_LIBDISPATCH +static void +xq_asl_init(void *ctx __unused) +#else +static void +xq_asl_init(void) +#endif +{ + assert((redirect_fds = calloc(16, sizeof(*redirect_fds))) != NULL); + n_redirect_fds = 16; + +#ifdef HAVE_LIBDISPATCH + redirect_serial_q = dispatch_queue_create("com.apple.asl-redirect", NULL); + assert(redirect_serial_q != NULL); + + read_source_group = dispatch_group_create(); + assert(read_source_group != NULL); +#else + assert((kq = kqueue()) != -1); + assert(pthread_create(&redirect_pthread, NULL, redirect_thread, + NULL) == 0); +#endif + + atexit(redirect_atexit); +} + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 +#define fls(v) xq_fls(v) + +static inline int fls(int value) { + unsigned int b, v; + + v = *((unsigned int *)&value); + + for(b=0 ; v ; v >>= 1 , b++); + + return b; +} +#endif + +int +xq_asl_log_fd(aslclient asl, aslmsg msg, int level, int fd) +{ +#ifdef HAVE_LIBDISPATCH + int err __block = 0; + static dispatch_once_t once_control; + dispatch_once_f(&once_control, NULL, xq_asl_init); +#else + int err = 0; + static pthread_once_t once_control = PTHREAD_ONCE_INIT; + assert(pthread_once(&once_control, xq_asl_init) == 0); +#endif + + if (fd < 0) + return EBADF; + +#ifdef HAVE_LIBDISPATCH +#define BLOCK_DONE return + dispatch_sync(redirect_serial_q, ^ +#else +#define BLOCK_DONE goto done + assert(pthread_mutex_lock(&redirect_fds_lock) == 0); +#endif + { + /* Reallocate if we need more space */ + if (fd >= n_redirect_fds) { + size_t new_n = 1 << (fls(fd) + 1); + asl_redirect *new_array = + realloc(redirect_fds, new_n * + sizeof(*redirect_fds)); + if (!new_array) { + err = errno; + BLOCK_DONE; + } + redirect_fds = new_array; + memset(redirect_fds + n_redirect_fds, 0, (new_n - + n_redirect_fds) * sizeof(*redirect_fds)); + n_redirect_fds = new_n; + } + + /* If we're already listening on it, return error. */ + if (redirect_fds[fd].buf != NULL) { + err = EBADF; + BLOCK_DONE; + } + + /* Initialize our buffer */ + redirect_fds[fd].buf = (char *)malloc(BUF_SIZE); + if (redirect_fds[fd].buf == NULL) { + err = errno; + BLOCK_DONE; + } + redirect_fds[fd].w = redirect_fds[fd].buf; + + /* Store our ASL settings */ + redirect_fds[fd].level = level; + redirect_fds[fd].asl = asl; + redirect_fds[fd].msg = msg; + + /* Don't block on reads from this fd */ + fcntl(fd, F_SETFL, + O_NONBLOCK); + + /* Start listening */ +#ifdef HAVE_LIBDISPATCH + { + dispatch_source_t read_source = + dispatch_source_create( + DISPATCH_SOURCE_TYPE_READ, fd, 0, + redirect_serial_q); + redirect_fds[fd].read_source = read_source; + dispatch_set_context(read_source, read_source); + dispatch_source_set_event_handler_f(read_source, + read_from_source); + dispatch_source_set_cancel_handler_f(read_source, + cancel_source); + dispatch_group_enter(read_source_group); + dispatch_resume(read_source); + } +#else + { + struct kevent ev; + EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0); + kevent(kq, &ev, 1, NULL, 0, NULL); + } +#endif + } +#ifdef HAVE_LIBDISPATCH + ); +#else +done: + assert(pthread_mutex_unlock(&redirect_fds_lock) == 0); +#endif +#undef BLOCK_DONE + + return err; +} + +int +xq_asl_capture_fd(aslclient asl, aslmsg msg, int level, int fd) +{ + int pipepair[2]; + + /* Create pipe */ + if (pipe(pipepair) == -1) + return errno; + + /* Close the read fd but not the write fd on exec */ + if (fcntl(pipepair[0], F_SETFD, FD_CLOEXEC) == -1) + return errno; + + /* Replace the existing fd */ + if (dup2(pipepair[1], fd) == -1) { + close(pipepair[0]); + close(pipepair[1]); + return errno; + } + + /* If we capture STDOUT_FILENO, make sure we linebuffer stdout */ + if (fd == STDOUT_FILENO) + setlinebuf(stdout); + + /* Close the duplicate fds since they've been reassigned */ + close(pipepair[1]); + + /* Hand off the read end of our pipe to xq_asl_log_fd */ + return xq_asl_log_fd(asl, msg, level, pipepair[0]); +} + +#ifdef DEBUG_CONSOLE_REDIRECT +int +main(int argc __unused, char * *argv __unused) +{ + xq_asl_capture_fd(NULL, NULL, ASL_LEVEL_NOTICE, STDOUT_FILENO); + xq_asl_capture_fd(NULL, NULL, ASL_LEVEL_ERR, STDERR_FILENO); + + fprintf(stderr, "TEST ERR1\n"); + fprintf(stdout, "TEST OUT1\n"); + fprintf(stderr, "TEST ERR2\n"); + fprintf(stdout, "TEST OUT2\n"); + system("/bin/echo SYST OUT"); + system("/bin/echo SYST ERR >&2"); + fprintf(stdout, "TEST OUT3\n"); + fprintf(stdout, "TEST OUT4\n"); + fprintf(stderr, "TEST ERR3\n"); + fprintf(stderr, "TEST ERR4\n"); + + exit(0); +} +#endif diff --git a/hw/xquartz/console_redirect.h b/hw/xquartz/console_redirect.h new file mode 100644 index 000000000..7b80de405 --- /dev/null +++ b/hw/xquartz/console_redirect.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2011-2012 Apple Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT + * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above + * copyright holders shall not be used in advertising or otherwise to + * promote the sale, use or other dealings in this Software without + * prior written authorization. + */ + +#ifndef _XQUARTZ_CONSOLE_REDIRECT_H_ +#define _XQUARTZ_CONSOLE_REDIRECT_H_ + +#include + +/* The given fd is replaced with a pipe. Anything written to it will will be + * logged to ASL. + */ +int +xq_asl_capture_fd(aslclient asl, aslmsg msg, int level, int fd); + +/* The given fd is read from and passed along to ASL until all write ends of the + * pipe are closed. Once the last writer has closed the pipe, we close our end. + */ +int +xq_asl_log_fd(aslclient asl, aslmsg msg, int level, int fd); + +#endif diff --git a/hw/xquartz/darwin.c b/hw/xquartz/darwin.c index e34994673..d72da093b 100644 --- a/hw/xquartz/darwin.c +++ b/hw/xquartz/darwin.c @@ -41,6 +41,7 @@ #include "mipointer.h" // mi software cursor #include "micmap.h" // mi colormap code #include "fb.h" // fb framebuffer code +#include "site.h" #include "globals.h" #include "dix.h" #include "xkbsrv.h" @@ -167,6 +168,21 @@ DarwinPrintBanner(void) { ErrorF("Xquartz starting:\n"); ErrorF("X.Org X Server %s\n", XSERVER_VERSION); + ErrorF("Build Date: %s\n", BUILD_DATE); +} + +/* + * DarwinSaveScreen + * X screensaver support. Not implemented. + */ +static Bool +DarwinSaveScreen(ScreenPtr pScreen, int on) +{ + // FIXME + if (on == SCREEN_SAVER_FORCER) {} + else if (on == SCREEN_SAVER_ON) {} + else {} + return TRUE; } /* @@ -255,6 +271,9 @@ DarwinScreenInit(ScreenPtr pScreen, int argc, char **argv) ShmRegisterFbFuncs(pScreen); #endif + // this must be initialized (why doesn't X have a default?) + pScreen->SaveScreen = DarwinSaveScreen; + // finish mode dependent screen setup including cursor support if (!QuartzSetupScreen(pScreen->myNum, pScreen)) { return FALSE; @@ -825,6 +844,20 @@ ddxGiveUp(enum ExitCode error) LogClose(error); } +/* + * AbortDDX -- + * DDX - specific abort routine. Called by AbortServer(). The attempt is + * made to restore all original setting of the displays. Also all devices + * are closed. + */ +_X_NORETURN +void +AbortDDX(enum ExitCode error) +{ + ErrorF(" AbortDDX\n"); + OsAbort(); +} + #if INPUTTHREAD /** This function is called in Xserver/os/inputthread.c when starting the input thread. */ diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c index 15c1bc5d8..fd87e968b 100644 --- a/hw/xquartz/darwinEvents.c +++ b/hw/xquartz/darwinEvents.c @@ -129,9 +129,6 @@ create_thread(void *(*func)(void *), void *arg) pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (&pthread_attr_set_qos_class_np) { - pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INITIATED, 0); - } pthread_create(&tid, &attr, func, arg); pthread_attr_destroy(&attr); diff --git a/hw/xquartz/mach-startup/bundle-main.c b/hw/xquartz/mach-startup/bundle-main.c index de82e2280..b40366244 100644 --- a/hw/xquartz/mach-startup/bundle-main.c +++ b/hw/xquartz/mach-startup/bundle-main.c @@ -29,6 +29,7 @@ */ #include +#include #ifdef HAVE_DIX_CONFIG_H #include @@ -43,7 +44,11 @@ #include #include +#ifdef HAVE_LIBDISPATCH #include +#else +#include +#endif #include #include @@ -56,7 +61,7 @@ #include "mach_startup.h" #include "mach_startupServer.h" -#include +#include "console_redirect.h" /* From darwinEvents.c ... but don't want to pull in all the server cruft */ void @@ -72,17 +77,13 @@ FatalError(const char *f, ...) _X_ATTRIBUTE_PRINTF(1, 2) _X_NORETURN; extern int noPanoramiXExtension; -#ifdef COMPOSITE -extern Bool noCompositeExtension; -#endif - #define DEFAULT_CLIENT X11BINDIR "/xterm" #define DEFAULT_STARTX X11BINDIR "/startx -- " X11BINDIR "/Xquartz" #define DEFAULT_SHELL "/bin/sh" -#define _STRINGIZE(s) #s -#define STRINGIZE(s) _STRINGIZE(s) - +#ifndef BUILD_DATE +#define BUILD_DATE "" +#endif #ifndef XSERVER_VERSION #define XSERVER_VERSION "?" #endif @@ -90,11 +91,15 @@ extern Bool noCompositeExtension; static char __crashreporter_info_buff__[4096] = { 0 }; static const char *__crashreporter_info__ __attribute__((__used__)) = &__crashreporter_info_buff__[0]; -// This line just tells the linker to never strip this symbol (such as for space optimization) +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 +// This is actually a toolchain requirement, but I'm not sure the correct check, +// but it should be fine to just only include it for Leopard and later. This line +// just tells the linker to never strip this symbol (such as for space optimization) asm (".desc ___crashreporter_info__, 0x10"); +#endif static const char *__crashreporter_info__base = - "X.Org X Server " XSERVER_VERSION; + "X.Org X Server " XSERVER_VERSION " Build Date: " BUILD_DATE; char *bundle_id_prefix = NULL; static char *server_bootstrap_name = NULL; @@ -114,6 +119,23 @@ static char *pref_app_to_run; static char *pref_login_shell; static char *pref_startx_script; +#ifndef HAVE_LIBDISPATCH +/*** Pthread Magics ***/ +static pthread_t +create_thread(void *(*func)(void *), void *arg) +{ + pthread_attr_t attr; + pthread_t tid; + + pthread_attr_init(&attr); + pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&tid, &attr, func, arg); + pthread_attr_destroy(&attr); + + return tid; +} +#endif /*** Mach-O IPC Stuffs ***/ @@ -221,9 +243,16 @@ typedef struct { /* This thread accepts an incoming connection and hands off the file * descriptor for the new connection to accept_fd_handoff() */ +#ifdef HAVE_LIBDISPATCH static void socket_handoff(socket_handoff_t *handoff_data) { +#else +static void * +socket_handoff_thread(void *arg) +{ + socket_handoff_t *handoff_data = (socket_handoff_t *)arg; +#endif int launchd_fd = -1; int connected_fd; @@ -258,6 +287,9 @@ socket_handoff(socket_handoff_t *handoff_data) launchd_fd); DarwinListenOnOpenFD(launchd_fd); +#ifndef HAVE_LIBDISPATCH + return NULL; +#endif } static int @@ -341,10 +373,14 @@ do_request_fd_handoff_socket(mach_port_t port, string_t filename) strlcpy(filename, handoff_data->filename, STRING_T_SIZE); +#ifdef HAVE_LIBDISPATCH dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ { socket_handoff(handoff_data); }); +#else + create_thread(socket_handoff_thread, handoff_data); +#endif #ifdef DEBUG ErrorF( @@ -441,9 +477,14 @@ startup_trigger(int argc, char **argv, char **envp) kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp); if (kr != KERN_SUCCESS) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 ErrorF("bootstrap_look_up(%s): %s\n", server_bootstrap_name, bootstrap_strerror( kr)); +#else + ErrorF("bootstrap_look_up(%s): %ul\n", server_bootstrap_name, + (unsigned long)kr); +#endif exit(EXIT_FAILURE); } @@ -523,8 +564,24 @@ setup_console_redirect(const char *bundle_id) asl_set_filter(aslc, ASL_FILTER_MASK_UPTO(ASL_LEVEL_WARNING)); - asl_log_descriptor(aslc, NULL, ASL_LEVEL_INFO, STDOUT_FILENO, ASL_LOG_DESCRIPTOR_WRITE); - asl_log_descriptor(aslc, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO, ASL_LOG_DESCRIPTOR_WRITE); +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 +# if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 + if (asl_log_descriptor) +# endif + { + asl_log_descriptor(aslc, NULL, ASL_LEVEL_INFO, STDOUT_FILENO, ASL_LOG_DESCRIPTOR_WRITE); + asl_log_descriptor(aslc, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO, ASL_LOG_DESCRIPTOR_WRITE); + } +# if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 + else { + xq_asl_capture_fd(aslc, NULL, ASL_LEVEL_INFO, STDOUT_FILENO); + xq_asl_capture_fd(aslc, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO); + } +# endif +#else + xq_asl_capture_fd(aslc, NULL, ASL_LEVEL_INFO, STDOUT_FILENO); + xq_asl_capture_fd(aslc, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO); +#endif } static void @@ -630,20 +687,12 @@ main(int argc, char **argv, char **envp) mach_port_t mp; kern_return_t kr; - /* Ignore SIGPIPE */ - signal(SIGPIPE, SIG_IGN); - /* Setup our environment for our children */ setup_env(); /* The server must not run the PanoramiX operations. */ noPanoramiXExtension = TRUE; -#ifdef COMPOSITE - /* https://gitlab.freedesktop.org/xorg/xserver/-/issues/1409 */ - noCompositeExtension = TRUE; -#endif - /* Setup the initial crasherporter info */ strlcpy(__crashreporter_info_buff__, __crashreporter_info__base, sizeof(__crashreporter_info_buff__)); diff --git a/hw/xquartz/mach-startup/stub.c b/hw/xquartz/mach-startup/stub.c index 83252e805..756e4ef2d 100644 --- a/hw/xquartz/mach-startup/stub.c +++ b/hw/xquartz/mach-startup/stub.c @@ -50,27 +50,45 @@ #include +#include + #include "launchd_fd.h" -static CFURLRef x11appURL; -static FSRef x11_appRef; +static char x11_path[PATH_MAX + 1]; static pid_t x11app_pid = 0; aslclient aslc; static void set_x11_path(void) { - OSStatus osstatus = LSFindApplicationForInfo(kLSUnknownCreator, CFSTR(kX11AppBundleId), - nil, &x11_appRef, &x11appURL); +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + + CFURLRef appURL = NULL; + OSStatus osstatus = + LSFindApplicationForInfo(kLSUnknownCreator, CFSTR( + kX11AppBundleId), nil, nil, &appURL); switch (osstatus) { case noErr: - if (x11appURL == NULL) { + if (appURL == NULL) { + asl_log( + aslc, NULL, ASL_LEVEL_ERR, + "Xquartz: Invalid response from LSFindApplicationForInfo(%s)", + kX11AppBundleId); + exit(1); + } + + if (!CFURLGetFileSystemRepresentation(appURL, true, + (unsigned char *)x11_path, + sizeof(x11_path))) { asl_log(aslc, NULL, ASL_LEVEL_ERR, - "Xquartz: Invalid response from LSFindApplicationForInfo(%s)", + "Xquartz: Error resolving URL for %s", kX11AppBundleId); - exit(1); + exit(3); } + + strlcat(x11_path, kX11AppBundlePath, sizeof(x11_path)); + asl_log(aslc, NULL, ASL_LEVEL_INFO, "Xquartz: X11.app = %s", x11_path); break; case kLSApplicationNotFoundErr: @@ -82,9 +100,15 @@ set_x11_path(void) default: asl_log(aslc, NULL, ASL_LEVEL_ERR, "Xquartz: Unable to find application for %s, error code = %d", - kX11AppBundleId, (int)osstatus); + kX11AppBundleId, + (int)osstatus); exit(11); } +#else + /* TODO: Make Tiger smarter... but TBH, this should never get called on Tiger... */ + strlcpy(x11_path, "/Applications/Utilities/X11.app/Contents/MacOS/X11", + sizeof(x11_path)); +#endif } static int @@ -107,15 +131,18 @@ connect_to_socket(const char *filename) ret_fd = socket(PF_UNIX, SOCK_STREAM, 0); if (ret_fd == -1) { asl_log(aslc, NULL, ASL_LEVEL_ERR, - "Xquartz: Failed to create socket: %s - %d - %s", - filename, errno, strerror(errno)); + "Xquartz: Failed to create socket: %s - %s", filename, + strerror( + errno)); return -1; } if (connect(ret_fd, servaddr, servaddr_len) < 0) { asl_log(aslc, NULL, ASL_LEVEL_ERR, "Xquartz: Failed to connect to socket: %s - %d - %s", - filename, errno, strerror(errno)); + filename, errno, + strerror( + errno)); close(ret_fd); return -1; } @@ -158,9 +185,10 @@ send_fd_handoff(int connected_fd, int launchd_fd) *((int *)CMSG_DATA(cmsg)) = launchd_fd; if (sendmsg(connected_fd, &msg, 0) < 0) { - asl_log(aslc, NULL, ASL_LEVEL_ERR, - "Xquartz: Error sending $DISPLAY file descriptor over fd %d: %d -- %s", - connected_fd, errno, strerror(errno)); + asl_log( + aslc, NULL, ASL_LEVEL_ERR, + "Xquartz: Error sending $DISPLAY file descriptor over fd %d: %d -- %s", + connected_fd, errno, strerror(errno)); return; } @@ -234,25 +262,26 @@ main(int argc, char **argv, char **envp) server_bootstrap_name); set_x11_path(); - char *listenOnlyArg = "--listenonly"; - CFStringRef silentLaunchArg = CFStringCreateWithCString(NULL, listenOnlyArg, kCFStringEncodingUTF8); - CFStringRef args[] = { silentLaunchArg }; - CFArrayRef passArgv = CFArrayCreate(NULL, (const void**) args, 1, NULL); - LSApplicationParameters params = { 0, /* CFIndex version == 0 */ - kLSLaunchDefaults, /* LSLaunchFlags flags */ - &x11_appRef, /* FSRef application */ - NULL, /* void* asyncLaunchRefCon*/ - NULL, /* CFDictionaryRef environment */ - passArgv, /* CFArrayRef arguments */ - NULL /* AppleEvent* initialEvent */ - }; - - OSStatus status = LSOpenApplication(¶ms, NULL); - if (status != noErr) { - asl_log(aslc, NULL, ASL_LEVEL_ERR, "Xquartz: Unable to launch: %d", (int)status); + /* This forking is ugly and will be cleaned up later */ + child = fork(); + if (child == -1) { + asl_log(aslc, NULL, ASL_LEVEL_ERR, "Xquartz: Could not fork: %s", + strerror( + errno)); return EXIT_FAILURE; } + if (child == 0) { + char *_argv[3]; + _argv[0] = x11_path; + _argv[1] = "--listenonly"; + _argv[2] = NULL; + asl_log(aslc, NULL, ASL_LEVEL_NOTICE, + "Xquartz: Starting X server: %s --listenonly", + x11_path); + return execvp(x11_path, _argv); + } + /* Try connecting for 10 seconds */ for (i = 0; i < 80; i++) { usleep(250000); @@ -262,8 +291,15 @@ main(int argc, char **argv, char **envp) } if (kr != KERN_SUCCESS) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 asl_log(aslc, NULL, ASL_LEVEL_ERR, - "Xquartz: bootstrap_look_up(): %s", bootstrap_strerror(kr)); + "Xquartz: bootstrap_look_up(): %s", bootstrap_strerror( + kr)); +#else + asl_log(aslc, NULL, ASL_LEVEL_ERR, + "Xquartz: bootstrap_look_up(): %ul", + (unsigned long)kr); +#endif return EXIT_FAILURE; } } @@ -277,10 +313,13 @@ main(int argc, char **argv, char **envp) int handoff_fd = -1; for (try = 0, try_max = 5; try < try_max; try++) { - if (request_fd_handoff_socket(mp, handoff_socket_filename) != KERN_SUCCESS) { - asl_log(aslc, NULL, ASL_LEVEL_INFO, - "Xquartz: Failed to request a socket from the server to send the $DISPLAY fd over (try %d of %d)", - (int)try + 1, (int)try_max); + if (request_fd_handoff_socket(mp, + handoff_socket_filename) != + KERN_SUCCESS) { + asl_log( + aslc, NULL, ASL_LEVEL_INFO, + "Xquartz: Failed to request a socket from the server to send the $DISPLAY fd over (try %d of %d)", + (int)try + 1, (int)try_max); continue; } @@ -288,13 +327,16 @@ main(int argc, char **argv, char **envp) if (handoff_fd == -1) { asl_log(aslc, NULL, ASL_LEVEL_ERR, "Xquartz: Failed to connect to socket (try %d of %d)", - (int)try + 1, (int)try_max); + (int)try + 1, + (int)try_max); continue; } - asl_log(aslc, NULL, ASL_LEVEL_INFO, - "Xquartz: Handoff connection established (try %d of %d) on fd %d, \"%s\". Sending message.", - (int)try + 1, (int)try_max, handoff_fd, handoff_socket_filename); + asl_log( + aslc, NULL, ASL_LEVEL_INFO, + "Xquartz: Handoff connection established (try %d of %d) on fd %d, \"%s\". Sending message.", + (int)try + 1, (int)try_max, handoff_fd, + handoff_socket_filename); send_fd_handoff(handoff_fd, launchd_fd); close(handoff_fd); break; @@ -315,7 +357,8 @@ main(int argc, char **argv, char **envp) free(newargv); free(newenvp); - asl_log(aslc, NULL, ASL_LEVEL_ERR, "Xquartz: Memory allocation failure"); + asl_log(aslc, NULL, ASL_LEVEL_ERR, + "Xquartz: Memory allocation failure"); return EXIT_FAILURE; } @@ -333,7 +376,8 @@ main(int argc, char **argv, char **envp) if (kr != KERN_SUCCESS) { asl_log(aslc, NULL, ASL_LEVEL_ERR, "Xquartz: start_x11_server: %s", - mach_error_string(kr)); + mach_error_string( + kr)); return EXIT_FAILURE; } return EXIT_SUCCESS; diff --git a/hw/xquartz/man/Xquartz.man b/hw/xquartz/man/Xquartz.man index 643bea9df..056086884 100644 --- a/hw/xquartz/man/Xquartz.man +++ b/hw/xquartz/man/Xquartz.man @@ -84,7 +84,7 @@ This option defaults to false and is provided only "for experts." It updates th .B defaults write @bundle_id_prefix@.X11 enable_test_extensions -boolean true This option defaults to false and is only accessible through the command line. Enable this option to turn on the DEC-XTRAP, RECORD, and XTEST extensions in the server. .TP 8 -.B defaults write @bundle_id_prefix@.X11 scroll_in_device_direction -boolean true +.B defaults write @laucnd_id_prefix@.X11 scroll_in_device_direction -boolean true This option defaults to false. Enable this option to ensure that X11 scroll events are always in the direction of the device. This overrides the related option in the Mouse/Trackpad section of System Preferences. .SH OPTIONS .PP diff --git a/hw/xquartz/pbproxy/app-main.m b/hw/xquartz/pbproxy/app-main.m index 825980caf..eda9a9e67 100644 --- a/hw/xquartz/pbproxy/app-main.m +++ b/hw/xquartz/pbproxy/app-main.m @@ -31,6 +31,13 @@ #include "pbproxy.h" #import "x-selection.h" +#include +#include /*for getpid*/ +#include + +static const char *app_prefs_domain = BUNDLE_ID_PREFIX ".xpbproxy"; +CFStringRef app_prefs_domain_cfstr; + /* Stubs */ char *display = NULL; @@ -75,8 +82,41 @@ int main(int argc, const char *argv[]) { + const char *s; + int i; + +#ifdef DEBUG + ErrorF("pid: %u\n", getpid()); +#endif + xpbproxy_is_standalone = YES; + if ((s = getenv("X11_PREFS_DOMAIN"))) + app_prefs_domain = s; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--prefs-domain") == 0 && i + 1 < argc) { + app_prefs_domain = argv[++i]; + } + else if (strcmp(argv[i], "--help") == 0) { + ErrorF( + "usage: xpbproxy OPTIONS\n" + "Pasteboard proxying for X11.\n\n" + "--prefs-domain Change the domain used for reading preferences\n" + " (default: %s)\n", + app_prefs_domain); + return 0; + } + else { + ErrorF("usage: xpbproxy OPTIONS...\n" + "Try 'xpbproxy --help' for more information.\n"); + return 1; + } + } + + app_prefs_domain_cfstr = CFStringCreateWithCString(NULL, app_prefs_domain, + kCFStringEncodingUTF8); + signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); diff --git a/hw/xquartz/pbproxy/main.m b/hw/xquartz/pbproxy/main.m index 92cde0437..2d2f76108 100644 --- a/hw/xquartz/pbproxy/main.m +++ b/hw/xquartz/pbproxy/main.m @@ -78,49 +78,55 @@ int xpbproxy_run(void) { - @autoreleasepool { - size_t i; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + size_t i; - for (i = 0, xpbproxy_dpy = NULL; !xpbproxy_dpy && i < 5; i++) { - xpbproxy_dpy = XOpenDisplay(NULL); + for (i = 0, xpbproxy_dpy = NULL; !xpbproxy_dpy && i < 5; i++) { + xpbproxy_dpy = XOpenDisplay(NULL); - if (!xpbproxy_dpy && display) { - char _display[32]; - snprintf(_display, sizeof(_display), ":%s", display); - setenv("DISPLAY", _display, TRUE); + if (!xpbproxy_dpy && display) { + char _display[32]; + snprintf(_display, sizeof(_display), ":%s", display); + setenv("DISPLAY", _display, TRUE); - xpbproxy_dpy = XOpenDisplay(_display); - } - if (!xpbproxy_dpy) - sleep(1); + xpbproxy_dpy = XOpenDisplay(_display); } + if (!xpbproxy_dpy) + sleep(1); + } - if (xpbproxy_dpy == NULL) { - ErrorF("xpbproxy: can't open default display\n"); - return EXIT_FAILURE; - } + if (xpbproxy_dpy == NULL) { + ErrorF("xpbproxy: can't open default display\n"); + [pool release]; + return EXIT_FAILURE; + } - XSetIOErrorHandler(x_io_error_handler); - XSetErrorHandler(x_error_handler); + XSetIOErrorHandler(x_io_error_handler); + XSetErrorHandler(x_error_handler); - if (!XAppleWMQueryExtension(xpbproxy_dpy, &xpbproxy_apple_wm_event_base, - &xpbproxy_apple_wm_error_base)) { - ErrorF("xpbproxy: can't open AppleWM server extension\n"); - return EXIT_FAILURE; - } + if (!XAppleWMQueryExtension(xpbproxy_dpy, &xpbproxy_apple_wm_event_base, + &xpbproxy_apple_wm_error_base)) { + ErrorF("xpbproxy: can't open AppleWM server extension\n"); + [pool release]; + return EXIT_FAILURE; + } - xpbproxy_have_xfixes = XFixesQueryExtension(xpbproxy_dpy, &xpbproxy_xfixes_event_base, - &xpbproxy_xfixes_error_base); + xpbproxy_have_xfixes = + XFixesQueryExtension(xpbproxy_dpy, &xpbproxy_xfixes_event_base, + &xpbproxy_xfixes_error_base); - XAppleWMSelectInput(xpbproxy_dpy, AppleWMActivationNotifyMask | AppleWMPasteboardNotifyMask); + XAppleWMSelectInput(xpbproxy_dpy, AppleWMActivationNotifyMask | + AppleWMPasteboardNotifyMask); - _selection_object = [x_selection new]; + _selection_object = [[x_selection alloc] init]; - if (!xpbproxy_input_register()) { - return EXIT_FAILURE; - } + if (!xpbproxy_input_register()) { + [pool release]; + return EXIT_FAILURE; } + [pool release]; + CFRunLoopRun(); return EXIT_SUCCESS; diff --git a/hw/xquartz/pbproxy/pbproxy.h b/hw/xquartz/pbproxy/pbproxy.h index 482f95ea6..c5a07f2d0 100644 --- a/hw/xquartz/pbproxy/pbproxy.h +++ b/hw/xquartz/pbproxy/pbproxy.h @@ -35,6 +35,17 @@ #include +#include +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 +#if __LP64__ || NS_BUILD_32_LIKE_64 +typedef long NSInteger; +typedef unsigned long NSUInteger; +#else +typedef int NSInteger; +typedef unsigned int NSUInteger; +#endif +#endif + #define Cursor X_Cursor #undef _SHAPE_H_ #include diff --git a/hw/xquartz/pbproxy/x-input.m b/hw/xquartz/pbproxy/x-input.m index 3be9ce407..71b46a8b3 100644 --- a/hw/xquartz/pbproxy/x-input.m +++ b/hw/xquartz/pbproxy/x-input.m @@ -89,7 +89,14 @@ static void xpbproxy_process_xevents(void) { - while (XPending(xpbproxy_dpy) != 0) { @autoreleasepool { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + if (pool == nil) { + ErrorF("unable to allocate/init auto release pool!\n"); + return; + } + + while (XPending(xpbproxy_dpy) != 0) { XEvent e; XNextEvent(xpbproxy_dpy, &e); @@ -127,7 +134,9 @@ } XFlush(xpbproxy_dpy); - }} + } + + [pool release]; } static BOOL diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m index f4f2b9a6b..b89a5760e 100644 --- a/hw/xquartz/pbproxy/x-selection.m +++ b/hw/xquartz/pbproxy/x-selection.m @@ -38,8 +38,6 @@ #import #import -#import "NSUserDefaults+XQuartzDefaults.h" - /* * The basic design of the pbproxy code is as follows. * @@ -101,6 +99,18 @@ @implementation x_selection } #endif +extern CFStringRef app_prefs_domain_cfstr; + +static BOOL +prefs_get_bool(CFStringRef key, BOOL defaultValue) +{ + Boolean value, ok; + + value = CFPreferencesGetAppBooleanValue(key, app_prefs_domain_cfstr, &ok); + + return ok ? (BOOL)value : defaultValue; +} + static void init_propdata(struct propdata *pdata) { @@ -663,8 +673,13 @@ - (void) send_string:(XSelectionRequestEvent *)e utf8:(BOOL)utf8 pasteboard:( return; } +#ifdef __LP64__ DebugF("pbtypes retainCount after containsObject: %lu\n", [pbtypes retainCount]); +#else + DebugF("pbtypes retainCount after containsObject: %u\n", + [pbtypes retainCount]); +#endif data = [pb stringForType:NSStringPboardType]; @@ -683,7 +698,11 @@ - (void) send_string:(XSelectionRequestEvent *)e utf8:(BOOL)utf8 pasteboard:( if (length < 50) { DebugF("UTF-8: %s\n", bytes); +#ifdef __LP64__ DebugF("UTF-8 length: %lu\n", length); +#else + DebugF("UTF-8 length: %u\n", length); +#endif } } else { @@ -1177,8 +1196,13 @@ - (void) handle_image: (struct propdata *)pdata pasteboard:(NSPasteboard *)pb return; } +#ifdef __LP64__ DebugF("data retainCount before NSBitmapImageRep initWithData: %lu\n", [data retainCount]); +#else + DebugF("data retainCount before NSBitmapImageRep initWithData: %u\n", + [data retainCount]); +#endif bmimage = [[NSBitmapImageRep alloc] initWithData:data]; @@ -1188,8 +1212,13 @@ - (void) handle_image: (struct propdata *)pdata pasteboard:(NSPasteboard *)pb return; } +#ifdef __LP64__ DebugF("data retainCount after NSBitmapImageRep initWithData: %lu\n", [data retainCount]); +#else + DebugF("data retainCount after NSBitmapImageRep initWithData: %u\n", + [data retainCount]); +#endif @try { @@ -1204,8 +1233,13 @@ - (void) handle_image: (struct propdata *)pdata pasteboard:(NSPasteboard *)pb return; } +#ifdef __LP64__ DebugF("bmimage retainCount after TIFFRepresentation %lu\n", [bmimage retainCount]); +#else + DebugF("bmimage retainCount after TIFFRepresentation %u\n", + [bmimage retainCount]); +#endif pbtypes = [NSArray arrayWithObjects:NSTIFFPboardType, nil]; @@ -1222,7 +1256,11 @@ - (void) handle_image: (struct propdata *)pdata pasteboard:(NSPasteboard *)pb [data autorelease]; +#ifdef __LP64__ DebugF("bmimage retainCount before release %lu\n", [bmimage retainCount]); +#else + DebugF("bmimage retainCount before release %u\n", [bmimage retainCount]); +#endif [bmimage autorelease]; } @@ -1384,18 +1422,35 @@ - (void) copy_completed:(Atom)selection - (void) reload_preferences { - NSUserDefaults * const defaults = NSUserDefaults.xquartzDefaults; - + /* + * It's uncertain how we could handle the synchronization failing, so cast to void. + * The prefs_get_bool should fall back to defaults if the org.x.X11 plist doesn't exist or is invalid. + */ + (void)CFPreferencesAppSynchronize(app_prefs_domain_cfstr); #ifdef STANDALONE_XPBPROXY if (xpbproxy_is_standalone) pbproxy_prefs.active = YES; else #endif - pbproxy_prefs.active = [defaults boolForKey:XQuartzPrefKeySyncPasteboard]; - pbproxy_prefs.primary_on_grab = [defaults boolForKey:XQuartzPrefKeySyncPrimaryOnSelect]; - pbproxy_prefs.clipboard_to_pasteboard = [defaults boolForKey:XQuartzPrefKeySyncClipboardToPasteBoard]; - pbproxy_prefs.pasteboard_to_primary = [defaults boolForKey:XQuartzPrefKeySyncPasteboardToPrimary]; - pbproxy_prefs.pasteboard_to_clipboard = [defaults boolForKey:XQuartzPrefKeySyncPasteboardToClipboard]; + pbproxy_prefs.active = prefs_get_bool(CFSTR( + "sync_pasteboard"), + pbproxy_prefs.active); + pbproxy_prefs.primary_on_grab = + prefs_get_bool(CFSTR( + "sync_primary_on_select"), + pbproxy_prefs.primary_on_grab); + pbproxy_prefs.clipboard_to_pasteboard = + prefs_get_bool(CFSTR( + "sync_clipboard_to_pasteboard"), + pbproxy_prefs.clipboard_to_pasteboard); + pbproxy_prefs.pasteboard_to_primary = + prefs_get_bool(CFSTR( + "sync_pasteboard_to_primary"), + pbproxy_prefs.pasteboard_to_primary); + pbproxy_prefs.pasteboard_to_clipboard = + prefs_get_bool(CFSTR( + "sync_pasteboard_to_clipboard"), + pbproxy_prefs.pasteboard_to_clipboard); /* This is used for debugging. */ //dump_prefs(); diff --git a/hw/xquartz/quartz.c b/hw/xquartz/quartz.c index 4bbe56b93..b0dfcbe68 100644 --- a/hw/xquartz/quartz.c +++ b/hw/xquartz/quartz.c @@ -35,6 +35,7 @@ #include #endif +#include "quartzCommon.h" #include "quartzRandR.h" #include "inputstr.h" #include "quartz.h" @@ -71,30 +72,25 @@ #include #include -// These are vended by the Objective-C runtime, but they are unfortunately -// not available as API in the macOS SDK. We are following suit with swift -// and clang in declaring them inline here. They canot be removed or changed -// in the OS without major bincompat ramifications. -// -// These were added in macOS 10.7. -void * _Nonnull objc_autoreleasePoolPush(void); -void objc_autoreleasePoolPop(void * _Nonnull context); +/* Work around a bug on Leopard's headers */ +#if defined (__LP64__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 && MAC_OS_X_VERSION_MAX_ALLOWED < 1060 +extern OSErr UpdateSystemActivity(UInt8 activity); +#define OverallAct 0 +#endif DevPrivateKeyRec quartzScreenKeyRec; int aquaMenuBarHeight = 0; QuartzModeProcsPtr quartzProcs = NULL; const char *quartzOpenGLBundle = NULL; -/* These are initialized by X11Application with default values set in NSUserDefaults+XQuartzDefaults */ -Bool XQuartzFullscreenDisableHotkeys; -Bool XQuartzOptionSendsAlt; -Bool XQuartzEnableKeyEquivalents; -Bool XQuartzFullscreenMenu; -Bool XQuartzRootlessDefault; - +Bool XQuartzFullscreenDisableHotkeys = TRUE; +Bool XQuartzOptionSendsAlt = FALSE; +Bool XQuartzEnableKeyEquivalents = TRUE; Bool XQuartzFullscreenVisible = FALSE; +Bool XQuartzRootlessDefault = TRUE; Bool XQuartzIsRootless = TRUE; Bool XQuartzServerVisible = FALSE; +Bool XQuartzFullscreenMenu = FALSE; int32_t XQuartzShieldingWindowLevel = 0; @@ -153,30 +149,6 @@ QuartzSetupScreen(int index, return TRUE; } -/* - * QuartzBlockHandler - * Clean out any autoreleased objects. - */ -static void -QuartzBlockHandler(void *blockData, void *pTimeout) -{ - static void *poolToken = NULL; - - if (poolToken) { - objc_autoreleasePoolPop(poolToken); - } - poolToken = objc_autoreleasePoolPush(); -} - -/* - * QuartzWakeupHandler - */ -static void -QuartzWakeupHandler(void *blockData, int result) -{ - /* nothing here */ -} - /* * QuartzInitOutput * Quartz display initialization. @@ -308,8 +280,8 @@ QuartzUpdateScreens(void) quartzProcs->UpdateScreen(pScreen); - /* PaintWindow needs to be called after RootlessUpdateScreenPixmap (from xprUpdateScreen) */ - pScreen->PaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); + /* miPaintWindow needs to be called after RootlessUpdateScreenPixmap (from xprUpdateScreen) */ + miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); /* Tell RandR about the new size, so new connections get the correct info */ RRScreenSizeNotify(pScreen); diff --git a/hw/xquartz/quartz.h b/hw/xquartz/quartz.h index 3a456f573..ddbf2e780 100644 --- a/hw/xquartz/quartz.h +++ b/hw/xquartz/quartz.h @@ -34,9 +34,6 @@ #ifndef _QUARTZ_H #define _QUARTZ_H -#include -#include "privates.h" - #include "screenint.h" #include "window.h" #include "pixmap.h" @@ -130,14 +127,6 @@ extern Bool XQuartzOptionSendsAlt; /* Alt or Mode_switch? */ extern int32_t XQuartzShieldingWindowLevel; /* CGShieldingWindowLevel() or 0 */ -// Other shared data -extern DevPrivateKeyRec quartzScreenKeyRec; -#define quartzScreenKey (&quartzScreenKeyRec) -extern int aquaMenuBarHeight; - -// Name of GLX bundle for native OpenGL -extern const char *quartzOpenGLBundle; - Bool QuartzAddScreen(int index, ScreenPtr pScreen); Bool diff --git a/hw/xquartz/quartzCocoa.m b/hw/xquartz/quartzCocoa.m new file mode 100644 index 000000000..ac6f67e2b --- /dev/null +++ b/hw/xquartz/quartzCocoa.m @@ -0,0 +1,66 @@ +/************************************************************** + * + * Quartz-specific support for the Darwin X Server + * that requires Cocoa and Objective-C. + * + * This file is separate from the parts of Quartz support + * that use X include files to avoid symbol collisions. + * + * Copyright (c) 2001-2004 Torrey T. Lyons and Greg Parker. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#include "sanitizedCocoa.h" + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "quartzCommon.h" +#include "inputstr.h" + +#include "darwin.h" + +/* + * QuartzBlockHandler + * Clean out any autoreleased objects. + */ +void +QuartzBlockHandler(void *blockData, void *pTimeout) +{ + static NSAutoreleasePool *aPool = nil; + + [aPool release]; + aPool = [[NSAutoreleasePool alloc] init]; +} + +/* + * QuartzWakeupHandler + */ +void +QuartzWakeupHandler(void *blockData, int result) +{ + // nothing here +} diff --git a/hw/xquartz/quartzCommon.h b/hw/xquartz/quartzCommon.h new file mode 100644 index 000000000..721886b87 --- /dev/null +++ b/hw/xquartz/quartzCommon.h @@ -0,0 +1,55 @@ +/* + * quartzCommon.h + * + * Common definitions used internally by all Quartz modes + * + * This file should be included before any X11 or IOKit headers + * so that it can avoid symbol conflicts. + * + * Copyright (c) 2001-2004 Torrey T. Lyons and Greg Parker. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifndef _QUARTZCOMMON_H +#define _QUARTZCOMMON_H + +#include +#include "privates.h" + +// Other shared data +extern DevPrivateKeyRec quartzScreenKeyRec; +#define quartzScreenKey (&quartzScreenKeyRec) +extern int aquaMenuBarHeight; + +// Name of GLX bundle for native OpenGL +extern const char *quartzOpenGLBundle; + +void +QuartzBlockHandler(void *blockData, void *pTimeout); + +void +QuartzWakeupHandler(void *blockData, int result); + +#endif /* _QUARTZCOMMON_H */ diff --git a/hw/xquartz/quartzKeyboard.c b/hw/xquartz/quartzKeyboard.c index c35a2d15d..d2b7f422f 100644 --- a/hw/xquartz/quartzKeyboard.c +++ b/hw/xquartz/quartzKeyboard.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "quartz.h" #include "darwin.h" @@ -732,6 +733,65 @@ DarwinModifierStringToNXMask(const char *str, int separatelr) return 0; } +/* + * LegalModifier + * This allows the ddx layer to prevent some keys from being remapped + * as modifier keys. + */ +Bool +LegalModifier(unsigned int key, DeviceIntPtr pDev) +{ + return 1; +} + +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 +static inline UniChar +macroman2ucs(unsigned char c) +{ + /* Precalculated table mapping MacRoman-128 to Unicode. Generated + by creating single element CFStringRefs then extracting the + first character. */ + + static const unsigned short table[128] = { + 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, + 0xe1, + 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, + 0xe8, + 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, + 0xf3, + 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, + 0xfc, + 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, + 0xdf, + 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, + 0xd8, + 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, + 0x2211, + 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, + 0xf8, + 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, + 0xab, + 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, + 0x153, + 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, + 0x25ca, + 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, + 0xfb02, + 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, + 0xc1, + 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, + 0xd4, + 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, + 0x2dc, + 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, + 0x2c7, + }; + + if (c < 128) return c; + else return table[c - 128]; +} +#endif + static KeySym make_dead_key(KeySym in) { @@ -746,34 +806,83 @@ make_dead_key(KeySym in) static Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) { - __block const void *chr_data = NULL; +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + KeyboardLayoutRef key_layout; + int is_uchr = 1; +#endif + const void *chr_data = NULL; int num_keycodes = NUM_KEYCODES; - __block UInt32 keyboard_type; + UInt32 keyboard_type = LMGetKbdType(); int i, j; OSStatus err; KeySym *k; + CFDataRef currentKeyLayoutDataRef = NULL; - dispatch_block_t getKeyboardData = ^{ - keyboard_type = LMGetKbdType(); +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + TISInputSourceRef currentKeyLayoutRef = + TISCopyCurrentKeyboardLayoutInputSource(); - TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource(); + if (currentKeyLayoutRef) { + currentKeyLayoutDataRef = (CFDataRef)TISGetInputSourceProperty( + currentKeyLayoutRef, kTISPropertyUnicodeKeyLayoutData); + if (currentKeyLayoutDataRef) + chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef); + } +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" // KLGetCurrentKeyboardLayout, KLGetKeyboardLayoutProperty +#endif + +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + if (chr_data == NULL) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + ErrorF( + "X11.app: Error detected in determining keyboard layout. If you are using an Apple-provided keyboard layout, please report this error at http://xquartz.macosforge.org and http://bugreport.apple.com\n"); + ErrorF( + "X11.app: Debug Info: keyboard_type=%u, currentKeyLayoutRef=%p, currentKeyLayoutDataRef=%p, chr_data=%p\n", + (unsigned)keyboard_type, currentKeyLayoutRef, + currentKeyLayoutDataRef, chr_data); +#endif - if (currentKeyLayoutRef) { - CFDataRef currentKeyLayoutDataRef = (CFDataRef)TISGetInputSourceProperty(currentKeyLayoutRef, - kTISPropertyUnicodeKeyLayoutData); - if (currentKeyLayoutDataRef) - chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef); + KLGetCurrentKeyboardLayout(&key_layout); + KLGetKeyboardLayoutProperty(key_layout, kKLuchrData, &chr_data); - CFRelease(currentKeyLayoutRef); +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + if (chr_data != NULL) { + ErrorF( + "X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); } - }; +#endif + } - /* This is an ugly ant-pattern, but it is more expedient to address the problem right now. */ - if (pthread_main_np()) { - getKeyboardData(); - } else { - dispatch_sync(dispatch_get_main_queue(), getKeyboardData); + if (chr_data == NULL) { + ErrorF( + "X11.app: Debug Info: kKLuchrData failed, trying kKLKCHRData.\n"); + ErrorF( + "If you are using a 3rd party keyboard layout, please see http://xquartz.macosforge.org/trac/ticket/154\n"); + KLGetKeyboardLayoutProperty(key_layout, kKLKCHRData, &chr_data); + is_uchr = 0; + num_keycodes = 128; + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + if (chr_data != NULL) { + ErrorF( + "X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n"); + } +#endif } +#endif + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + if (currentKeyLayoutRef) + CFRelease(currentKeyLayoutRef); +#endif if (chr_data == NULL) { ErrorF("Couldn't get uchr or kchr resource\n"); @@ -797,6 +906,9 @@ QuartzReadSystemKeymap(darwinKeyboardInfo *info) k = info->keyMap + i * GLYPHS_PER_KEY; for (j = 0; j < 4; j++) { +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + if (is_uchr) { +#endif UniChar s[8]; UniCharCount len; UInt32 dead_key_state = 0, extra_dead = 0; @@ -823,6 +935,42 @@ QuartzReadSystemKeymap(darwinKeyboardInfo *info) k[j] = ucs2keysym(s[0]); if (dead_key_state != 0) k[j] = make_dead_key(k[j]); } +#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 + } + else { // kchr + UInt32 c, state = 0, state2 = 0; + UInt16 code; + + code = i | mods[j]; + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" // KeyTranslate +#endif + + c = KeyTranslate(chr_data, code, &state); + + /* Dead keys are only processed on key-down, so ask + to translate those events. When we find a dead key, + translating the matching key up event will give + us the actual dead character. */ + + if (state != 0) + c = KeyTranslate(chr_data, code | 128, &state2); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + /* Characters seem to be in MacRoman encoding. */ + + if (c != 0 && c != 0x0010) { + k[j] = ucs2keysym(macroman2ucs(c & 255)); + + if (state != 0) k[j] = make_dead_key(k[j]); + } + } +#endif } if (k[3] == k[2]) k[3] = NoSymbol; diff --git a/hw/xquartz/quartzRandR.c b/hw/xquartz/quartzRandR.c index 3ecc0e771..cb470fa8e 100644 --- a/hw/xquartz/quartzRandR.c +++ b/hw/xquartz/quartzRandR.c @@ -35,12 +35,15 @@ #include #endif +#include "quartzCommon.h" #include "quartzRandR.h" #include "quartz.h" #include "darwin.h" #include "X11Application.h" +#include + #include #include #include @@ -63,6 +66,154 @@ static Bool ignore_next_fake_mode_update = FALSE; typedef int (*QuartzModeCallback) (ScreenPtr, QuartzModeInfoPtr, void *); +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + +static long +getDictLong(CFDictionaryRef dictRef, CFStringRef key) +{ + long value; + + CFNumberRef numRef = (CFNumberRef)CFDictionaryGetValue(dictRef, key); + if (!numRef) + return 0; + + if (!CFNumberGetValue(numRef, kCFNumberLongType, &value)) + return 0; + return value; +} + +static double +getDictDouble(CFDictionaryRef dictRef, CFStringRef key) +{ + double value; + + CFNumberRef numRef = (CFNumberRef)CFDictionaryGetValue(dictRef, key); + if (!numRef) + return 0.0; + + if (!CFNumberGetValue(numRef, kCFNumberDoubleType, &value)) + return 0.0; + return value; +} + +static void +QuartzRandRGetModeInfo(CFDictionaryRef modeRef, + QuartzModeInfoPtr pMode) +{ + pMode->width = (size_t)getDictLong(modeRef, kCGDisplayWidth); + pMode->height = (size_t)getDictLong(modeRef, kCGDisplayHeight); + pMode->refresh = + (int)(getDictDouble(modeRef, kCGDisplayRefreshRate) + 0.5); + if (pMode->refresh == 0) + pMode->refresh = DEFAULT_REFRESH; + pMode->ref = NULL; + pMode->pSize = NULL; +} + +static Bool +QuartzRandRCopyCurrentModeInfo(CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) +{ + CFDictionaryRef curModeRef = CGDisplayCurrentMode(screenId); + if (!curModeRef) + return FALSE; + + QuartzRandRGetModeInfo(curModeRef, pMode); + pMode->ref = (void *)curModeRef; + CFRetain(pMode->ref); + return TRUE; +} + +static Bool +QuartzRandRSetCGMode(CGDirectDisplayID screenId, + QuartzModeInfoPtr pMode) +{ + CFDictionaryRef modeRef = (CFDictionaryRef)pMode->ref; + return (CGDisplaySwitchToMode(screenId, modeRef) == kCGErrorSuccess); +} + +static Bool +QuartzRandREnumerateModes(ScreenPtr pScreen, + QuartzModeCallback callback, + void *data) +{ + Bool retval = FALSE; + QuartzScreenPtr pQuartzScreen = QUARTZ_PRIV(pScreen); + + /* Just an 800x600 fallback if we have no attached heads */ + if (pQuartzScreen->displayIDs) { + CFDictionaryRef curModeRef, modeRef; + long curBpp; + CFArrayRef modes; + QuartzModeInfo modeInfo; + int i; + CGDirectDisplayID screenId = pQuartzScreen->displayIDs[0]; + + curModeRef = CGDisplayCurrentMode(screenId); + if (!curModeRef) + return FALSE; + curBpp = getDictLong(curModeRef, kCGDisplayBitsPerPixel); + + modes = CGDisplayAvailableModes(screenId); + if (!modes) + return FALSE; + for (i = 0; i < CFArrayGetCount(modes); i++) { + int cb; + modeRef = (CFDictionaryRef)CFArrayGetValueAtIndex(modes, i); + + /* Skip modes that are not usable on the current display or have a + different pixel encoding than the current mode. */ + if (((unsigned long)getDictLong(modeRef, kCGDisplayIOFlags) & + kDisplayModeUsableFlags) != kDisplayModeUsableFlags) + continue; + if (getDictLong(modeRef, kCGDisplayBitsPerPixel) != curBpp) + continue; + + QuartzRandRGetModeInfo(modeRef, &modeInfo); + modeInfo.ref = (void *)modeRef; + cb = callback(pScreen, &modeInfo, data); + if (cb == CALLBACK_CONTINUE) + retval = TRUE; + else if (cb == CALLBACK_SUCCESS) + return TRUE; + else if (cb == CALLBACK_ERROR) + return FALSE; + } + } + + switch (callback(pScreen, &pQuartzScreen->rootlessMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + + case CALLBACK_ERROR: + return FALSE; + + case CALLBACK_CONTINUE: + retval = TRUE; + + default: + break; + } + + switch (callback(pScreen, &pQuartzScreen->fullscreenMode, data)) { + case CALLBACK_SUCCESS: + return TRUE; + + case CALLBACK_ERROR: + return FALSE; + + case CALLBACK_CONTINUE: + retval = TRUE; + + default: + break; + } + + return retval; +} + +#else /* we have the new CG APIs from Snow Leopard */ + static void QuartzRandRGetModeInfo(CGDisplayModeRef modeRef, QuartzModeInfoPtr pMode) @@ -199,6 +350,8 @@ QuartzRandREnumerateModes(ScreenPtr pScreen, return retval; } +#endif /* Snow Leopard CoreGraphics APIs */ + static Bool QuartzRandRModesEqual(QuartzModeInfoPtr pMode1, QuartzModeInfoPtr pMode2) diff --git a/hw/xquartz/quartzStartup.c b/hw/xquartz/quartzStartup.c index 9137edb66..bb92b6d3c 100644 --- a/hw/xquartz/quartzStartup.c +++ b/hw/xquartz/quartzStartup.c @@ -36,6 +36,7 @@ #include #include #include +#include "quartzCommon.h" #include "X11Controller.h" #include "darwin.h" #include "darwinEvents.h" @@ -74,9 +75,6 @@ create_thread(void *func, void *arg) pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (&pthread_attr_set_qos_class_np) { - pthread_attr_set_qos_class_np(&attr, QOS_CLASS_USER_INTERACTIVE, 0); - } pthread_create(&tid, &attr, func, arg); pthread_attr_destroy(&attr); diff --git a/hw/xquartz/xpr/appledristr.h b/hw/xquartz/xpr/appledristr.h index 341d72bb4..71346c428 100644 --- a/hw/xquartz/xpr/appledristr.h +++ b/hw/xquartz/xpr/appledristr.h @@ -50,126 +50,126 @@ typedef struct _AppleDRIQueryVersion { CARD8 reqType; /* always DRIReqCode */ CARD8 driReqType; /* always X_DRIQueryVersion */ - CARD16 length; + CARD16 length B16; } xAppleDRIQueryVersionReq; #define sz_xAppleDRIQueryVersionReq 4 typedef struct { BYTE type; /* X_Reply */ BOOL pad1; - CARD16 sequenceNumber; - CARD32 length; - CARD16 majorVersion; /* major version of DRI protocol */ - CARD16 minorVersion; /* minor version of DRI protocol */ - CARD32 patchVersion; /* patch version of DRI protocol */ - CARD32 pad3; - CARD32 pad4; - CARD32 pad5; - CARD32 pad6; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 majorVersion B16; /* major version of DRI protocol */ + CARD16 minorVersion B16; /* minor version of DRI protocol */ + CARD32 patchVersion B32; /* patch version of DRI protocol */ + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRIQueryVersionReply; #define sz_xAppleDRIQueryVersionReply 32 typedef struct _AppleDRIQueryDirectRenderingCapable { CARD8 reqType; /* always DRIReqCode */ CARD8 driReqType; /* X_DRIQueryDirectRenderingCapable */ - CARD16 length; - CARD32 screen; + CARD16 length B16; + CARD32 screen B32; } xAppleDRIQueryDirectRenderingCapableReq; #define sz_xAppleDRIQueryDirectRenderingCapableReq 8 typedef struct { BYTE type; /* X_Reply */ BOOL pad1; - CARD16 sequenceNumber; - CARD32 length; + CARD16 sequenceNumber B16; + CARD32 length B32; BOOL isCapable; BOOL pad2; BOOL pad3; BOOL pad4; - CARD32 pad5; - CARD32 pad6; - CARD32 pad7; - CARD32 pad8; - CARD32 pad9; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; + CARD32 pad8 B32; + CARD32 pad9 B32; } xAppleDRIQueryDirectRenderingCapableReply; #define sz_xAppleDRIQueryDirectRenderingCapableReply 32 typedef struct _AppleDRIAuthConnection { CARD8 reqType; /* always DRIReqCode */ CARD8 driReqType; /* always X_DRICloseConnection */ - CARD16 length; - CARD32 screen; - CARD32 magic; + CARD16 length B16; + CARD32 screen B32; + CARD32 magic B32; } xAppleDRIAuthConnectionReq; #define sz_xAppleDRIAuthConnectionReq 12 typedef struct { BYTE type; BOOL pad1; - CARD16 sequenceNumber; - CARD32 length; - CARD32 authenticated; - CARD32 pad2; - CARD32 pad3; - CARD32 pad4; - CARD32 pad5; - CARD32 pad6; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 authenticated B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRIAuthConnectionReply; #define zx_xAppleDRIAuthConnectionReply 32 typedef struct _AppleDRICreateSurface { CARD8 reqType; /* always DRIReqCode */ CARD8 driReqType; /* always X_DRICreateSurface */ - CARD16 length; - CARD32 screen; - CARD32 drawable; - CARD32 client_id; + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; + CARD32 client_id B32; } xAppleDRICreateSurfaceReq; #define sz_xAppleDRICreateSurfaceReq 16 typedef struct { BYTE type; /* X_Reply */ BOOL pad1; - CARD16 sequenceNumber; - CARD32 length; - CARD32 key_0; - CARD32 key_1; - CARD32 uid; - CARD32 pad4; - CARD32 pad5; - CARD32 pad6; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 key_0 B32; + CARD32 key_1 B32; + CARD32 uid B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRICreateSurfaceReply; #define sz_xAppleDRICreateSurfaceReply 32 typedef struct _AppleDRIDestroySurface { CARD8 reqType; /* always DRIReqCode */ CARD8 driReqType; /* always X_DRIDestroySurface */ - CARD16 length; - CARD32 screen; - CARD32 drawable; + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; } xAppleDRIDestroySurfaceReq; #define sz_xAppleDRIDestroySurfaceReq 12 typedef struct _AppleDRINotify { BYTE type; /* always eventBase + event type */ BYTE kind; - CARD16 sequenceNumber; - CARD32 time; /* time of change */ - CARD32 pad1; - CARD32 arg; - CARD32 pad3; - CARD32 pad4; - CARD32 pad5; - CARD32 pad6; + CARD16 sequenceNumber B16; + CARD32 time B32; /* time of change */ + CARD32 pad1 B32; + CARD32 arg B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; } xAppleDRINotifyEvent; #define sz_xAppleDRINotifyEvent 32 typedef struct { CARD8 reqType; CARD8 driReqType; - CARD16 length; - CARD32 screen; - CARD32 drawable; + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; BOOL doubleSwap; CARD8 pad1, pad2, pad3; } xAppleDRICreateSharedBufferReq; @@ -179,14 +179,14 @@ typedef struct { typedef struct { BYTE type; BYTE data1; - CARD16 sequenceNumber; - CARD32 length; - CARD32 stringLength; /* 0 on error */ - CARD32 width; - CARD32 height; - CARD32 pad1; - CARD32 pad2; - CARD32 pad3; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 stringLength B32; /* 0 on error */ + CARD32 width B32; + CARD32 height B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; } xAppleDRICreateSharedBufferReply; #define sz_xAppleDRICreateSharedBufferReply 32 @@ -194,9 +194,9 @@ typedef struct { typedef struct { CARD8 reqType; CARD8 driReqType; - CARD16 length; - CARD32 screen; - CARD32 drawable; + CARD16 length B16; + CARD32 screen B32; + CARD32 drawable B32; } xAppleDRISwapBuffersReq; #define sz_xAppleDRISwapBuffersReq 12 @@ -204,9 +204,9 @@ typedef struct { typedef struct { CARD8 reqType; /*1 */ CARD8 driReqType; /*2 */ - CARD16 length; /*4 */ - CARD32 screen; /*8 */ - CARD32 drawable; /*12 */ + CARD16 length B16; /*4 */ + CARD32 screen B32; /*8 */ + CARD32 drawable B32; /*12 */ } xAppleDRICreatePixmapReq; #define sz_xAppleDRICreatePixmapReq 12 @@ -214,14 +214,14 @@ typedef struct { typedef struct { BYTE type; /*1 */ BOOL pad1; /*2 */ - CARD16 sequenceNumber; /*4 */ - CARD32 length; /*8 */ - CARD32 width; /*12 */ - CARD32 height; /*16 */ - CARD32 pitch; /*20 */ - CARD32 bpp; /*24 */ - CARD32 size; /*28 */ - CARD32 stringLength; /*32 */ + CARD16 sequenceNumber B16; /*4 */ + CARD32 length B32; /*8 */ + CARD32 width B32; /*12 */ + CARD32 height B32; /*16 */ + CARD32 pitch B32; /*20 */ + CARD32 bpp B32; /*24 */ + CARD32 size B32; /*28 */ + CARD32 stringLength B32; /*32 */ } xAppleDRICreatePixmapReply; #define sz_xAppleDRICreatePixmapReply 32 @@ -229,8 +229,8 @@ typedef struct { typedef struct { CARD8 reqType; /*1 */ CARD8 driReqType; /*2 */ - CARD16 length; /*4 */ - CARD32 drawable; /*8 */ + CARD16 length B16; /*4 */ + CARD32 drawable B32; /*8 */ } xAppleDRIDestroyPixmapReq; #define sz_xAppleDRIDestroyPixmapReq 8 diff --git a/hw/xquartz/xpr/dri.c b/hw/xquartz/xpr/dri.c index 091418e19..67ea6a006 100644 --- a/hw/xquartz/xpr/dri.c +++ b/hw/xquartz/xpr/dri.c @@ -69,6 +69,8 @@ #include "x-hook.h" #include "driWrap.h" +#include + static DevPrivateKeyRec DRIScreenPrivKeyRec; #define DRIScreenPrivKey (&DRIScreenPrivKeyRec) static DevPrivateKeyRec DRIWindowPrivKeyRec; diff --git a/hw/xquartz/xpr/x-list.c b/hw/xquartz/xpr/x-list.c index 171657686..29543d4e0 100644 --- a/hw/xquartz/xpr/x-list.c +++ b/hw/xquartz/xpr/x-list.c @@ -281,8 +281,7 @@ list_sort_1(x_list *lst, int length, /* Then merge them back together. */ - assert(lst != NULL); - assert(mid != NULL); + assert(lst != NULL && mid != NULL); if ((*less)(mid->data, lst->data)) out = out_head = mid, mid = mid->next; diff --git a/hw/xquartz/xpr/xprAppleWM.c b/hw/xquartz/xpr/xprAppleWM.c index 126661766..8c4f5efb8 100644 --- a/hw/xquartz/xpr/xprAppleWM.c +++ b/hw/xquartz/xpr/xprAppleWM.c @@ -82,6 +82,7 @@ xprSetWindowLevel(WindowPtr pWin, int level) return Success; } +#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3 static int xprAttachTransient(WindowPtr pWinChild, WindowPtr pWinParent) { @@ -113,6 +114,7 @@ xprAttachTransient(WindowPtr pWinChild, WindowPtr pWinParent) return Success; } +#endif static int xprFrameDraw(WindowPtr pWin, @@ -144,8 +146,16 @@ static AppleWMProcsRec xprAppleWMProcs = { xp_frame_get_rect, xp_frame_hit_test, xprFrameDraw, +#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 3 xp_set_dock_proxy, xprAttachTransient +#elif defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 2 + xp_set_dock_proxy, + NULL +#else + NULL, + NULL +#endif }; void diff --git a/hw/xquartz/xpr/xprEvent.c b/hw/xquartz/xpr/xprEvent.c index eb321a52f..398177ca8 100644 --- a/hw/xquartz/xpr/xprEvent.c +++ b/hw/xquartz/xpr/xprEvent.c @@ -52,7 +52,9 @@ #include #include +#ifdef HAVE_LIBDISPATCH #include +#endif #include "rootlessWindow.h" #include "xprEvent.h" @@ -74,9 +76,24 @@ QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev) case kXquartzBringAllToFront: DEBUG_LOG("kXquartzBringAllToFront\n"); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - xp_window_bring_all_to_front(); - }); + /* There's no need to do xp_window_bring_all_to_front on Leopard, + * and we don't care about the result, so just do it async. + */ +#if defined(HAVE_LIBDISPATCH) && defined(XPLUGIN_VERSION) && XPLUGIN_VERSION >= 6 +# if defined(XPLUGIN_VERSION_MIN_REQUIRED) && XPLUGIN_VERSION_MIN_REQUIRED < 6 + if (&xp_window_bring_all_to_front) { +# endif + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + xp_window_bring_all_to_front(); + }); +# if defined(XPLUGIN_VERSION_MIN_REQUIRED) && XPLUGIN_VERSION_MIN_REQUIRED < 6 + } else { + RootlessOrderAllWindows(e->data[0]); + } +# endif +#else + RootlessOrderAllWindows(e->data[0]); +#endif return TRUE; diff --git a/hw/xquartz/xpr/xprFrame.c b/hw/xquartz/xpr/xprFrame.c index 57d16d42f..aad375b52 100644 --- a/hw/xquartz/xpr/xprFrame.c +++ b/hw/xquartz/xpr/xprFrame.c @@ -43,7 +43,15 @@ #include "windowstr.h" #include "quartz.h" +#ifdef HAVE_LIBDISPATCH #include +#else +#include +#endif + +#ifdef DEBUG_XP_LOCK_WINDOW +#include +#endif #define DEFINE_ATOM_HELPER(func, atom_name) \ static Atom func(void) { \ @@ -62,7 +70,11 @@ DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID") static x_hash_table * window_hash; /* Need to guard window_hash since xprIsX11Window can be called from any thread. */ +#ifdef HAVE_LIBDISPATCH static dispatch_queue_t window_hash_serial_q; +#else +static pthread_rwlock_t window_hash_rwlock; +#endif /* Prototypes for static functions */ static Bool @@ -197,9 +209,15 @@ xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, return FALSE; } +#ifdef HAVE_LIBDISPATCH dispatch_async(window_hash_serial_q, ^ { x_hash_table_insert(window_hash, pFrame->wid, pFrame); }); +#else + pthread_rwlock_wrlock(&window_hash_rwlock); + x_hash_table_insert(window_hash, pFrame->wid, pFrame); + pthread_rwlock_unlock(&window_hash_rwlock); +#endif xprSetNativeProperty(pFrame); @@ -214,9 +232,15 @@ xprDestroyFrame(RootlessFrameID wid) { xp_error err; +#ifdef HAVE_LIBDISPATCH dispatch_async(window_hash_serial_q, ^ { x_hash_table_remove(window_hash, wid); }); +#else + pthread_rwlock_wrlock(&window_hash_rwlock); + x_hash_table_remove(window_hash, wid); + pthread_rwlock_unlock(&window_hash_rwlock); +#endif err = xp_destroy_window(x_cvt_vptr_to_uint(wid)); if (err != Success) @@ -269,7 +293,9 @@ xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) { xp_window_changes wc; unsigned int mask = XP_STACKING; +#ifdef HAVE_LIBDISPATCH __block +#endif RootlessWindowRec * winRec; /* Stack frame below nextWid it if it exists, or raise @@ -284,9 +310,15 @@ xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) wc.sibling = x_cvt_vptr_to_uint(nextWid); } +#ifdef HAVE_LIBDISPATCH dispatch_sync(window_hash_serial_q, ^ { winRec = x_hash_table_lookup(window_hash, wid, NULL); }); +#else + pthread_rwlock_rdlock(&window_hash_rwlock); + winRec = x_hash_table_lookup(window_hash, wid, NULL); + pthread_rwlock_unlock(&window_hash_rwlock); +#endif if (winRec) { if (XQuartzIsRootless) @@ -349,8 +381,15 @@ xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) xp_error err; #ifdef DEBUG_XP_LOCK_WINDOW + void* callstack[128]; + int i, frames = backtrace(callstack, 128); + char** strs = backtrace_symbols(callstack, frames); + ErrorF("=== LOCK %d ===\n", (int)x_cvt_vptr_to_uint(wid)); - xorg_backtrace(); + for (i = 0; i < frames; ++i) { + ErrorF(" %s\n", strs[i]); + } + free(strs); #endif err = xp_lock_window(x_cvt_vptr_to_uint( @@ -360,10 +399,6 @@ xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow) (int)x_cvt_vptr_to_uint( wid), (int)err); -#ifdef DEBUG_XP_LOCK_WINDOW - ErrorF(" bits: %p\n", *data); -#endif - *pixelData = data[0]; *bytesPerRow = rowbytes[0]; } @@ -377,8 +412,15 @@ xprStopDrawing(RootlessFrameID wid, Bool flush) xp_error err; #ifdef DEBUG_XP_LOCK_WINDOW + void* callstack[128]; + int i, frames = backtrace(callstack, 128); + char** strs = backtrace_symbols(callstack, frames); + ErrorF("=== UNLOCK %d ===\n", (int)x_cvt_vptr_to_uint(wid)); - xorg_backtrace(); + for (i = 0; i < frames; ++i) { + ErrorF(" %s\n", strs[i]); + } + free(strs); #endif err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush); @@ -477,9 +519,13 @@ xprInit(ScreenPtr pScreen) rootless_CopyWindow_threshold = xp_scroll_area_threshold; assert((window_hash = x_hash_table_new(NULL, NULL, NULL, NULL))); +#ifdef HAVE_LIBDISPATCH assert((window_hash_serial_q = dispatch_queue_create(BUNDLE_ID_PREFIX ".X11.xpr_window_hash", NULL))); +#else + assert(0 == pthread_rwlock_init(&window_hash_rwlock, NULL)); +#endif return TRUE; } @@ -491,12 +537,19 @@ xprInit(ScreenPtr pScreen) WindowPtr xprGetXWindow(xp_window_id wid) { +#ifdef HAVE_LIBDISPATCH RootlessWindowRec *winRec __block; dispatch_sync(window_hash_serial_q, ^ { winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL); }); +#else + RootlessWindowRec *winRec; + pthread_rwlock_rdlock(&window_hash_rwlock); + winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL); + pthread_rwlock_unlock(&window_hash_rwlock); +#endif return winRec != NULL ? winRec->win : NULL; } diff --git a/hw/xquartz/xpr/xprScreen.c b/hw/xquartz/xpr/xprScreen.c index 562d6a0c3..1dc23211c 100644 --- a/hw/xquartz/xpr/xprScreen.c +++ b/hw/xquartz/xpr/xprScreen.c @@ -33,6 +33,7 @@ #include #endif +#include "quartzCommon.h" #include "inputstr.h" #include "quartz.h" #include "quartzRandR.h" @@ -55,6 +56,11 @@ #include "nonsdk_extinit.h" +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 +// From NSApplication.h +extern const double NSAppKitVersionNumber; +#endif + /* 10.4's deferred update makes X slower.. have to live with the tearing * for now.. */ #define XP_NO_DEFERRED_UPDATES 8 @@ -166,13 +172,18 @@ displayScreenBounds(CGDirectDisplayID id) (int)frame.origin.x, (int)frame.origin.y); Boolean spacePerDisplay = false; - Boolean ok; - (void)CFPreferencesAppSynchronize(CFSTR("com.apple.spaces")); - spacePerDisplay = ! CFPreferencesGetAppBooleanValue(CFSTR("spans-displays"), - CFSTR("com.apple.spaces"), - &ok); - if (!ok) - spacePerDisplay = true; +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 + if (NSAppKitVersionNumber >= 1265) +#endif + { + Boolean ok; + (void)CFPreferencesAppSynchronize(CFSTR("com.apple.spaces")); + spacePerDisplay = ! CFPreferencesGetAppBooleanValue(CFSTR("spans-displays"), + CFSTR("com.apple.spaces"), + &ok); + if (!ok) + spacePerDisplay = true; + } /* Remove menubar to help standard X11 window managers. * On Mavericks and later, the menu bar is on all displays when spans-displays is false or unset. @@ -322,6 +333,10 @@ xprAddScreen(int index, ScreenPtr pScreen) DEBUG_LOG("index=%d depth=%d\n", index, depth); if (depth == -1) { +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) * + CGDisplayBitsPerSample(kCGDirectMainDisplay); +#else CGDisplayModeRef modeRef; CFStringRef encStrRef; @@ -351,9 +366,12 @@ xprAddScreen(int index, ScreenPtr pScreen) } CFRelease(encStrRef); +#endif } +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 have_depth: +#endif switch (depth) { case 8: // pseudo-working dfb->visuals = PseudoColorMask; -- 2.24.3 (Apple Git-128)