X11Application.m revision 4642e01f
14642e01fSmrg/* X11Application.m -- subclass of NSApplication to multiplex events 24642e01fSmrg 34642e01fSmrg Copyright (c) 2002-2008 Apple Inc. 44642e01fSmrg 54642e01fSmrg Permission is hereby granted, free of charge, to any person 64642e01fSmrg obtaining a copy of this software and associated documentation files 74642e01fSmrg (the "Software"), to deal in the Software without restriction, 84642e01fSmrg including without limitation the rights to use, copy, modify, merge, 94642e01fSmrg publish, distribute, sublicense, and/or sell copies of the Software, 104642e01fSmrg and to permit persons to whom the Software is furnished to do so, 114642e01fSmrg subject to the following conditions: 124642e01fSmrg 134642e01fSmrg The above copyright notice and this permission notice shall be 144642e01fSmrg included in all copies or substantial portions of the Software. 154642e01fSmrg 164642e01fSmrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 174642e01fSmrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 184642e01fSmrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 194642e01fSmrg NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT 204642e01fSmrg HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 214642e01fSmrg WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 224642e01fSmrg OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 234642e01fSmrg DEALINGS IN THE SOFTWARE. 244642e01fSmrg 254642e01fSmrg Except as contained in this notice, the name(s) of the above 264642e01fSmrg copyright holders shall not be used in advertising or otherwise to 274642e01fSmrg promote the sale, use or other dealings in this Software without 284642e01fSmrg prior written authorization. */ 294642e01fSmrg 304642e01fSmrg#include "sanitizedCarbon.h" 314642e01fSmrg 324642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 334642e01fSmrg#include <dix-config.h> 344642e01fSmrg#endif 354642e01fSmrg 364642e01fSmrg#include "quartzCommon.h" 374642e01fSmrg 384642e01fSmrg#import "X11Application.h" 394642e01fSmrg 404642e01fSmrg#include "darwin.h" 414642e01fSmrg#include "darwinEvents.h" 424642e01fSmrg#include "quartzKeyboard.h" 434642e01fSmrg#include "quartz.h" 444642e01fSmrg#define _APPLEWM_SERVER_ 454642e01fSmrg#include "X11/extensions/applewm.h" 464642e01fSmrg#include "micmap.h" 474642e01fSmrg 484642e01fSmrg#include <mach/mach.h> 494642e01fSmrg#include <unistd.h> 504642e01fSmrg#include <AvailabilityMacros.h> 514642e01fSmrg 524642e01fSmrg#include <Xplugin.h> 534642e01fSmrg 544642e01fSmrg// pbproxy/pbproxy.h 554642e01fSmrgextern BOOL xpbproxy_init (void); 564642e01fSmrg 574642e01fSmrg#define DEFAULTS_FILE X11LIBDIR"/X11/xserver/Xquartz.plist" 584642e01fSmrg 594642e01fSmrg#ifndef XSERVER_VERSION 604642e01fSmrg#define XSERVER_VERSION "?" 614642e01fSmrg#endif 624642e01fSmrg 634642e01fSmrg#define ProximityIn 0 644642e01fSmrg#define ProximityOut 1 654642e01fSmrg 664642e01fSmrg/* Stuck modifier / button state... force release when we context switch */ 674642e01fSmrgstatic NSEventType keyState[NUM_KEYCODES]; 684642e01fSmrgstatic int modifierFlagsMask; 694642e01fSmrg 704642e01fSmrgint X11EnableKeyEquivalents = TRUE, quartzFullscreenMenu = FALSE; 714642e01fSmrgint quartzHasRoot = FALSE, quartzEnableRootless = TRUE; 724642e01fSmrg 734642e01fSmrgextern Bool noTestExtensions; 744642e01fSmrg 754642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 764642e01fSmrgstatic TISInputSourceRef last_key_layout; 774642e01fSmrg#else 784642e01fSmrgstatic KeyboardLayoutRef last_key_layout; 794642e01fSmrg#endif 804642e01fSmrg 814642e01fSmrgextern int darwinFakeButtons; 824642e01fSmrg 834642e01fSmrgX11Application *X11App; 844642e01fSmrg 854642e01fSmrgCFStringRef app_prefs_domain_cfstr = NULL; 864642e01fSmrg 874642e01fSmrg#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask) 884642e01fSmrg 894642e01fSmrg@interface X11Application (Private) 904642e01fSmrg- (void) sendX11NSEvent:(NSEvent *)e; 914642e01fSmrg@end 924642e01fSmrg 934642e01fSmrg@implementation X11Application 944642e01fSmrg 954642e01fSmrgtypedef struct message_struct message; 964642e01fSmrgstruct message_struct { 974642e01fSmrg mach_msg_header_t hdr; 984642e01fSmrg SEL selector; 994642e01fSmrg NSObject *arg; 1004642e01fSmrg}; 1014642e01fSmrg 1024642e01fSmrgstatic mach_port_t _port; 1034642e01fSmrg 1044642e01fSmrg/* Quartz mode initialization routine. This is often dynamically loaded 1054642e01fSmrg but is statically linked into this X server. */ 1064642e01fSmrgBool QuartzModeBundleInit(void); 1074642e01fSmrg 1084642e01fSmrgstatic void init_ports (void) { 1094642e01fSmrg kern_return_t r; 1104642e01fSmrg NSPort *p; 1114642e01fSmrg 1124642e01fSmrg if (_port != MACH_PORT_NULL) return; 1134642e01fSmrg 1144642e01fSmrg r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port); 1154642e01fSmrg if (r != KERN_SUCCESS) return; 1164642e01fSmrg 1174642e01fSmrg p = [NSMachPort portWithMachPort:_port]; 1184642e01fSmrg [p setDelegate:NSApp]; 1194642e01fSmrg [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 1204642e01fSmrg} 1214642e01fSmrg 1224642e01fSmrgstatic void message_kit_thread (SEL selector, NSObject *arg) { 1234642e01fSmrg message msg; 1244642e01fSmrg kern_return_t r; 1254642e01fSmrg 1264642e01fSmrg msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0); 1274642e01fSmrg msg.hdr.msgh_size = sizeof (msg); 1284642e01fSmrg msg.hdr.msgh_remote_port = _port; 1294642e01fSmrg msg.hdr.msgh_local_port = MACH_PORT_NULL; 1304642e01fSmrg msg.hdr.msgh_reserved = 0; 1314642e01fSmrg msg.hdr.msgh_id = 0; 1324642e01fSmrg 1334642e01fSmrg msg.selector = selector; 1344642e01fSmrg msg.arg = [arg retain]; 1354642e01fSmrg 1364642e01fSmrg r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size, 1374642e01fSmrg 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); 1384642e01fSmrg if (r != KERN_SUCCESS) 1394642e01fSmrg ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r); 1404642e01fSmrg} 1414642e01fSmrg 1424642e01fSmrg- (void) handleMachMessage:(void *)_msg { 1434642e01fSmrg message *msg = _msg; 1444642e01fSmrg 1454642e01fSmrg [self performSelector:msg->selector withObject:msg->arg]; 1464642e01fSmrg [msg->arg release]; 1474642e01fSmrg} 1484642e01fSmrg 1494642e01fSmrg- (void) set_controller:obj { 1504642e01fSmrg if (_controller == nil) _controller = [obj retain]; 1514642e01fSmrg} 1524642e01fSmrg 1534642e01fSmrg- (void) dealloc { 1544642e01fSmrg if (_controller != nil) [_controller release]; 1554642e01fSmrg 1564642e01fSmrg if (_port != MACH_PORT_NULL) 1574642e01fSmrg mach_port_deallocate (mach_task_self (), _port); 1584642e01fSmrg 1594642e01fSmrg [super dealloc]; 1604642e01fSmrg} 1614642e01fSmrg 1624642e01fSmrg- (void) orderFrontStandardAboutPanel: (id) sender { 1634642e01fSmrg NSMutableDictionary *dict; 1644642e01fSmrg NSDictionary *infoDict; 1654642e01fSmrg NSString *tem; 1664642e01fSmrg 1674642e01fSmrg dict = [NSMutableDictionary dictionaryWithCapacity:3]; 1684642e01fSmrg infoDict = [[NSBundle mainBundle] infoDictionary]; 1694642e01fSmrg 1704642e01fSmrg [dict setObject: NSLocalizedString (@"The X Window System", @"About panel") 1714642e01fSmrg forKey:@"ApplicationName"]; 1724642e01fSmrg 1734642e01fSmrg tem = [infoDict objectForKey:@"CFBundleShortVersionString"]; 1744642e01fSmrg 1754642e01fSmrg [dict setObject:[NSString stringWithFormat:@"XQuartz %@", tem] 1764642e01fSmrg forKey:@"ApplicationVersion"]; 1774642e01fSmrg 1784642e01fSmrg [dict setObject:[NSString stringWithFormat:@"xorg-server %s", XSERVER_VERSION] 1794642e01fSmrg forKey:@"Version"]; 1804642e01fSmrg 1814642e01fSmrg [self orderFrontStandardAboutPanelWithOptions: dict]; 1824642e01fSmrg} 1834642e01fSmrg 1844642e01fSmrg- (void) activateX:(OSX_BOOL)state { 1854642e01fSmrg /* Create a TSM document that supports full Unicode input, and 1864642e01fSmrg have it activated while X is active */ 1874642e01fSmrg static TSMDocumentID x11_document; 1884642e01fSmrg size_t i; 1894642e01fSmrg DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active) 1904642e01fSmrg if (state) { 1914642e01fSmrg DarwinSendDDXEvent(kXquartzActivate, 0); 1924642e01fSmrg 1934642e01fSmrg if (!_x_active) { 1944642e01fSmrg if (x11_document == 0) { 1954642e01fSmrg OSType types[1]; 1964642e01fSmrg types[0] = kUnicodeDocument; 1974642e01fSmrg NewTSMDocument (1, types, &x11_document, 0); 1984642e01fSmrg } 1994642e01fSmrg 2004642e01fSmrg if (x11_document != 0) ActivateTSMDocument (x11_document); 2014642e01fSmrg } 2024642e01fSmrg } else { 2034642e01fSmrg 2044642e01fSmrg if(darwin_modifier_flags) 2054642e01fSmrg DarwinUpdateModKeys(0); 2064642e01fSmrg for(i=0; i < NUM_KEYCODES; i++) { 2074642e01fSmrg if(keyState[i] == NSKeyDown) { 2084642e01fSmrg DarwinSendKeyboardEvents(KeyRelease, i); 2094642e01fSmrg keyState[i] = NSKeyUp; 2104642e01fSmrg } 2114642e01fSmrg } 2124642e01fSmrg 2134642e01fSmrg DarwinSendDDXEvent(kXquartzDeactivate, 0); 2144642e01fSmrg 2154642e01fSmrg if (_x_active && x11_document != 0) 2164642e01fSmrg DeactivateTSMDocument (x11_document); 2174642e01fSmrg } 2184642e01fSmrg 2194642e01fSmrg _x_active = state; 2204642e01fSmrg} 2214642e01fSmrg 2224642e01fSmrg- (void) became_key:(NSWindow *)win { 2234642e01fSmrg [self activateX:NO]; 2244642e01fSmrg} 2254642e01fSmrg 2264642e01fSmrg- (void) sendEvent:(NSEvent *)e { 2274642e01fSmrg OSX_BOOL for_appkit, for_x; 2284642e01fSmrg 2294642e01fSmrg /* By default pass down the responder chain and to X. */ 2304642e01fSmrg for_appkit = YES; 2314642e01fSmrg for_x = YES; 2324642e01fSmrg 2334642e01fSmrg switch ([e type]) { 2344642e01fSmrg case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: 2354642e01fSmrg case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: 2364642e01fSmrg if ([e window] != nil) { 2374642e01fSmrg /* Pointer event has an (AppKit) window. Probably something for the kit. */ 2384642e01fSmrg for_x = NO; 2394642e01fSmrg if (_x_active) [self activateX:NO]; 2404642e01fSmrg } else if ([self modalWindow] == nil) { 2414642e01fSmrg /* Must be an X window. Tell appkit it doesn't have focus. */ 2424642e01fSmrg for_appkit = NO; 2434642e01fSmrg 2444642e01fSmrg if ([self isActive]) { 2454642e01fSmrg [self deactivate]; 2464642e01fSmrg if (!_x_active && quartzProcs->IsX11Window([e window], 2474642e01fSmrg [e windowNumber])) 2484642e01fSmrg [self activateX:YES]; 2494642e01fSmrg } 2504642e01fSmrg } 2514642e01fSmrg 2524642e01fSmrg /* We want to force sending to appkit if we're over the menu bar */ 2534642e01fSmrg if(!for_appkit) { 2544642e01fSmrg NSPoint NSlocation = [e locationInWindow]; 2554642e01fSmrg NSWindow *window = [e window]; 2564642e01fSmrg 2574642e01fSmrg if (window != nil) { 2584642e01fSmrg NSRect frame = [window frame]; 2594642e01fSmrg NSlocation.x += frame.origin.x; 2604642e01fSmrg NSlocation.y += frame.origin.y; 2614642e01fSmrg } 2624642e01fSmrg 2634642e01fSmrg NSRect NSframe = [[NSScreen mainScreen] frame]; 2644642e01fSmrg NSRect NSvisibleFrame = [[NSScreen mainScreen] visibleFrame]; 2654642e01fSmrg 2664642e01fSmrg CGRect CGframe = CGRectMake(NSframe.origin.x, NSframe.origin.y, 2674642e01fSmrg NSframe.size.width, NSframe.size.height); 2684642e01fSmrg CGRect CGvisibleFrame = CGRectMake(NSvisibleFrame.origin.x, 2694642e01fSmrg NSvisibleFrame.origin.y, 2704642e01fSmrg NSvisibleFrame.size.width, 2714642e01fSmrg NSvisibleFrame.size.height); 2724642e01fSmrg CGPoint CGlocation = CGPointMake(NSlocation.x, NSlocation.y); 2734642e01fSmrg 2744642e01fSmrg if(CGRectContainsPoint(CGframe, CGlocation) && 2754642e01fSmrg !CGRectContainsPoint(CGvisibleFrame, CGlocation)) 2764642e01fSmrg for_appkit = YES; 2774642e01fSmrg } 2784642e01fSmrg 2794642e01fSmrg break; 2804642e01fSmrg 2814642e01fSmrg case NSKeyDown: case NSKeyUp: 2824642e01fSmrg 2834642e01fSmrg if(_x_active) { 2844642e01fSmrg static BOOL do_swallow = NO; 2854642e01fSmrg static int swallow_keycode; 2864642e01fSmrg 2874642e01fSmrg if([e type] == NSKeyDown) { 2884642e01fSmrg /* Before that though, see if there are any global 2894642e01fSmrg * shortcuts bound to it. */ 2904642e01fSmrg 2914642e01fSmrg if(darwinAppKitModMask & [e modifierFlags]) { 2924642e01fSmrg /* Override to force sending to Appkit */ 2934642e01fSmrg swallow_keycode = [e keyCode]; 2944642e01fSmrg do_swallow = YES; 2954642e01fSmrg for_x = NO; 2964642e01fSmrg#if XPLUGIN_VERSION >= 1 2974642e01fSmrg } else if(X11EnableKeyEquivalents && 2984642e01fSmrg xp_is_symbolic_hotkey_event([e eventRef])) { 2994642e01fSmrg swallow_keycode = [e keyCode]; 3004642e01fSmrg do_swallow = YES; 3014642e01fSmrg for_x = NO; 3024642e01fSmrg#endif 3034642e01fSmrg } else if(X11EnableKeyEquivalents && 3044642e01fSmrg [[self mainMenu] performKeyEquivalent:e]) { 3054642e01fSmrg swallow_keycode = [e keyCode]; 3064642e01fSmrg do_swallow = YES; 3074642e01fSmrg for_appkit = NO; 3084642e01fSmrg for_x = NO; 3094642e01fSmrg } else if(!quartzEnableRootless 3104642e01fSmrg && ([e modifierFlags] & ALL_KEY_MASKS) == (NSCommandKeyMask | NSAlternateKeyMask) 3114642e01fSmrg && ([e keyCode] == 0 /*a*/ || [e keyCode] == 53 /*Esc*/)) { 3124642e01fSmrg /* We have this here to force processing fullscreen 3134642e01fSmrg * toggle even if X11EnableKeyEquivalents is disabled */ 3144642e01fSmrg swallow_keycode = [e keyCode]; 3154642e01fSmrg do_swallow = YES; 3164642e01fSmrg for_x = NO; 3174642e01fSmrg for_appkit = NO; 3184642e01fSmrg DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); 3194642e01fSmrg } else { 3204642e01fSmrg /* No kit window is focused, so send it to X. */ 3214642e01fSmrg for_appkit = NO; 3224642e01fSmrg } 3234642e01fSmrg } else { /* KeyUp */ 3244642e01fSmrg /* If we saw a key equivalent on the down, don't pass 3254642e01fSmrg * the up through to X. */ 3264642e01fSmrg if (do_swallow && [e keyCode] == swallow_keycode) { 3274642e01fSmrg do_swallow = NO; 3284642e01fSmrg for_x = NO; 3294642e01fSmrg } 3304642e01fSmrg } 3314642e01fSmrg } else { /* !_x_active */ 3324642e01fSmrg for_x = NO; 3334642e01fSmrg } 3344642e01fSmrg break; 3354642e01fSmrg 3364642e01fSmrg case NSFlagsChanged: 3374642e01fSmrg /* Don't tell X11 about modifiers changing while it's not active */ 3384642e01fSmrg if (!_x_active) 3394642e01fSmrg for_x = NO; 3404642e01fSmrg break; 3414642e01fSmrg 3424642e01fSmrg case NSAppKitDefined: 3434642e01fSmrg switch ([e subtype]) { 3444642e01fSmrg case NSApplicationActivatedEventType: 3454642e01fSmrg for_x = NO; 3464642e01fSmrg if ([self modalWindow] == nil) { 3474642e01fSmrg for_appkit = NO; 3484642e01fSmrg 3494642e01fSmrg /* FIXME: hack to avoid having to pass the event to appkit, 3504642e01fSmrg which would cause it to raise one of its windows. */ 3514642e01fSmrg _appFlags._active = YES; 3524642e01fSmrg 3534642e01fSmrg [self activateX:YES]; 3544642e01fSmrg 3554642e01fSmrg /* Get the Spaces preference for SwitchOnActivate */ 3564642e01fSmrg (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); 3574642e01fSmrg BOOL switch_on_activate, ok; 3584642e01fSmrg switch_on_activate = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok); 3594642e01fSmrg if(!ok) 3604642e01fSmrg switch_on_activate = YES; 3614642e01fSmrg 3624642e01fSmrg if ([e data2] & 0x10 && switch_on_activate) 3634642e01fSmrg DarwinSendDDXEvent(kXquartzBringAllToFront, 0); 3644642e01fSmrg } 3654642e01fSmrg break; 3664642e01fSmrg 3674642e01fSmrg case 18: /* ApplicationDidReactivate */ 3684642e01fSmrg if (quartzHasRoot) for_appkit = NO; 3694642e01fSmrg break; 3704642e01fSmrg 3714642e01fSmrg case NSApplicationDeactivatedEventType: 3724642e01fSmrg for_x = NO; 3734642e01fSmrg [self activateX:NO]; 3744642e01fSmrg break; 3754642e01fSmrg } 3764642e01fSmrg break; 3774642e01fSmrg 3784642e01fSmrg default: break; /* for gcc */ 3794642e01fSmrg } 3804642e01fSmrg 3814642e01fSmrg if (for_appkit) [super sendEvent:e]; 3824642e01fSmrg 3834642e01fSmrg if (for_x) [self sendX11NSEvent:e]; 3844642e01fSmrg} 3854642e01fSmrg 3864642e01fSmrg- (void) set_window_menu:(NSArray *)list { 3874642e01fSmrg [_controller set_window_menu:list]; 3884642e01fSmrg} 3894642e01fSmrg 3904642e01fSmrg- (void) set_window_menu_check:(NSNumber *)n { 3914642e01fSmrg [_controller set_window_menu_check:n]; 3924642e01fSmrg} 3934642e01fSmrg 3944642e01fSmrg- (void) set_apps_menu:(NSArray *)list { 3954642e01fSmrg [_controller set_apps_menu:list]; 3964642e01fSmrg} 3974642e01fSmrg 3984642e01fSmrg- (void) set_front_process:unused { 3994642e01fSmrg [NSApp activateIgnoringOtherApps:YES]; 4004642e01fSmrg 4014642e01fSmrg if ([self modalWindow] == nil) 4024642e01fSmrg [self activateX:YES]; 4034642e01fSmrg} 4044642e01fSmrg 4054642e01fSmrg- (void) set_can_quit:(NSNumber *)state { 4064642e01fSmrg [_controller set_can_quit:[state boolValue]]; 4074642e01fSmrg} 4084642e01fSmrg 4094642e01fSmrg- (void) server_ready:unused { 4104642e01fSmrg [_controller server_ready]; 4114642e01fSmrg} 4124642e01fSmrg 4134642e01fSmrg- (void) show_hide_menubar:(NSNumber *)state { 4144642e01fSmrg /* Also shows/hides the dock */ 4154642e01fSmrg if ([state boolValue]) 4164642e01fSmrg SetSystemUIMode(kUIModeNormal, 0); 4174642e01fSmrg else 4184642e01fSmrg SetSystemUIMode(kUIModeAllHidden, quartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation" 4194642e01fSmrg} 4204642e01fSmrg 4214642e01fSmrg 4224642e01fSmrg/* user preferences */ 4234642e01fSmrg 4244642e01fSmrg/* Note that these functions only work for arrays whose elements 4254642e01fSmrg can be toll-free-bridged between NS and CF worlds. */ 4264642e01fSmrg 4274642e01fSmrgstatic const void *cfretain (CFAllocatorRef a, const void *b) { 4284642e01fSmrg return CFRetain (b); 4294642e01fSmrg} 4304642e01fSmrg 4314642e01fSmrgstatic void cfrelease (CFAllocatorRef a, const void *b) { 4324642e01fSmrg CFRelease (b); 4334642e01fSmrg} 4344642e01fSmrg 4354642e01fSmrgstatic CFMutableArrayRef nsarray_to_cfarray (NSArray *in) { 4364642e01fSmrg CFMutableArrayRef out; 4374642e01fSmrg CFArrayCallBacks cb; 4384642e01fSmrg NSObject *ns; 4394642e01fSmrg const CFTypeRef *cf; 4404642e01fSmrg int i, count; 4414642e01fSmrg 4424642e01fSmrg memset (&cb, 0, sizeof (cb)); 4434642e01fSmrg cb.version = 0; 4444642e01fSmrg cb.retain = cfretain; 4454642e01fSmrg cb.release = cfrelease; 4464642e01fSmrg 4474642e01fSmrg count = [in count]; 4484642e01fSmrg out = CFArrayCreateMutable (NULL, count, &cb); 4494642e01fSmrg 4504642e01fSmrg for (i = 0; i < count; i++) { 4514642e01fSmrg ns = [in objectAtIndex:i]; 4524642e01fSmrg 4534642e01fSmrg if ([ns isKindOfClass:[NSArray class]]) 4544642e01fSmrg cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns); 4554642e01fSmrg else 4564642e01fSmrg cf = CFRetain ((CFTypeRef) ns); 4574642e01fSmrg 4584642e01fSmrg CFArrayAppendValue (out, cf); 4594642e01fSmrg CFRelease (cf); 4604642e01fSmrg } 4614642e01fSmrg 4624642e01fSmrg return out; 4634642e01fSmrg} 4644642e01fSmrg 4654642e01fSmrgstatic NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { 4664642e01fSmrg NSMutableArray *out; 4674642e01fSmrg const CFTypeRef *cf; 4684642e01fSmrg NSObject *ns; 4694642e01fSmrg int i, count; 4704642e01fSmrg 4714642e01fSmrg count = CFArrayGetCount (in); 4724642e01fSmrg out = [[NSMutableArray alloc] initWithCapacity:count]; 4734642e01fSmrg 4744642e01fSmrg for (i = 0; i < count; i++) { 4754642e01fSmrg cf = CFArrayGetValueAtIndex (in, i); 4764642e01fSmrg 4774642e01fSmrg if (CFGetTypeID (cf) == CFArrayGetTypeID ()) 4784642e01fSmrg ns = cfarray_to_nsarray ((CFArrayRef) cf); 4794642e01fSmrg else 4804642e01fSmrg ns = [(id)cf retain]; 4814642e01fSmrg 4824642e01fSmrg [out addObject:ns]; 4834642e01fSmrg [ns release]; 4844642e01fSmrg } 4854642e01fSmrg 4864642e01fSmrg return out; 4874642e01fSmrg} 4884642e01fSmrg 4894642e01fSmrg- (CFPropertyListRef) prefs_get:(NSString *)key { 4904642e01fSmrg CFPropertyListRef value; 4914642e01fSmrg 4924642e01fSmrg value = CFPreferencesCopyAppValue ((CFStringRef) key, app_prefs_domain_cfstr); 4934642e01fSmrg 4944642e01fSmrg if (value == NULL) { 4954642e01fSmrg static CFDictionaryRef defaults; 4964642e01fSmrg 4974642e01fSmrg if (defaults == NULL) { 4984642e01fSmrg CFStringRef error = NULL; 4994642e01fSmrg CFDataRef data; 5004642e01fSmrg CFURLRef url; 5014642e01fSmrg SInt32 error_code; 5024642e01fSmrg 5034642e01fSmrg url = (CFURLCreateFromFileSystemRepresentation 5044642e01fSmrg (NULL, (unsigned char *)DEFAULTS_FILE, strlen (DEFAULTS_FILE), false)); 5054642e01fSmrg if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data, 5064642e01fSmrg NULL, NULL, &error_code)) { 5074642e01fSmrg defaults = (CFPropertyListCreateFromXMLData 5084642e01fSmrg (NULL, data, kCFPropertyListMutableContainersAndLeaves, &error)); 5094642e01fSmrg if (error != NULL) CFRelease (error); 5104642e01fSmrg CFRelease (data); 5114642e01fSmrg } 5124642e01fSmrg CFRelease (url); 5134642e01fSmrg 5144642e01fSmrg if (defaults != NULL) { 5154642e01fSmrg NSMutableArray *apps, *elt; 5164642e01fSmrg int count, i; 5174642e01fSmrg NSString *name, *nname; 5184642e01fSmrg 5194642e01fSmrg /* Localize the names in the default apps menu. */ 5204642e01fSmrg 5214642e01fSmrg apps = [(NSDictionary *)defaults objectForKey:@PREFS_APPSMENU]; 5224642e01fSmrg if (apps != nil) { 5234642e01fSmrg count = [apps count]; 5244642e01fSmrg for (i = 0; i < count; i++) { 5254642e01fSmrg elt = [apps objectAtIndex:i]; 5264642e01fSmrg if (elt != nil && [elt isKindOfClass:[NSArray class]]) { 5274642e01fSmrg name = [elt objectAtIndex:0]; 5284642e01fSmrg if (name != nil) { 5294642e01fSmrg nname = NSLocalizedString (name, nil); 5304642e01fSmrg if (nname != nil && nname != name) 5314642e01fSmrg [elt replaceObjectAtIndex:0 withObject:nname]; 5324642e01fSmrg } 5334642e01fSmrg } 5344642e01fSmrg } 5354642e01fSmrg } 5364642e01fSmrg } 5374642e01fSmrg } 5384642e01fSmrg 5394642e01fSmrg if (defaults != NULL) value = CFDictionaryGetValue (defaults, key); 5404642e01fSmrg if (value != NULL) CFRetain (value); 5414642e01fSmrg } 5424642e01fSmrg 5434642e01fSmrg return value; 5444642e01fSmrg} 5454642e01fSmrg 5464642e01fSmrg- (int) prefs_get_integer:(NSString *)key default:(int)def { 5474642e01fSmrg CFPropertyListRef value; 5484642e01fSmrg int ret; 5494642e01fSmrg 5504642e01fSmrg value = [self prefs_get:key]; 5514642e01fSmrg 5524642e01fSmrg if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ()) 5534642e01fSmrg CFNumberGetValue (value, kCFNumberIntType, &ret); 5544642e01fSmrg else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) 5554642e01fSmrg ret = CFStringGetIntValue (value); 5564642e01fSmrg else 5574642e01fSmrg ret = def; 5584642e01fSmrg 5594642e01fSmrg if (value != NULL) CFRelease (value); 5604642e01fSmrg 5614642e01fSmrg return ret; 5624642e01fSmrg} 5634642e01fSmrg 5644642e01fSmrg- (const char *) prefs_get_string:(NSString *)key default:(const char *)def { 5654642e01fSmrg CFPropertyListRef value; 5664642e01fSmrg const char *ret = NULL; 5674642e01fSmrg 5684642e01fSmrg value = [self prefs_get:key]; 5694642e01fSmrg 5704642e01fSmrg if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { 5714642e01fSmrg NSString *s = (NSString *) value; 5724642e01fSmrg 5734642e01fSmrg ret = [s UTF8String]; 5744642e01fSmrg } 5754642e01fSmrg 5764642e01fSmrg if (value != NULL) CFRelease (value); 5774642e01fSmrg 5784642e01fSmrg return ret != NULL ? ret : def; 5794642e01fSmrg} 5804642e01fSmrg 5814642e01fSmrg- (float) prefs_get_float:(NSString *)key default:(float)def { 5824642e01fSmrg CFPropertyListRef value; 5834642e01fSmrg float ret = def; 5844642e01fSmrg 5854642e01fSmrg value = [self prefs_get:key]; 5864642e01fSmrg 5874642e01fSmrg if (value != NULL 5884642e01fSmrg && CFGetTypeID (value) == CFNumberGetTypeID () 5894642e01fSmrg && CFNumberIsFloatType (value)) 5904642e01fSmrg CFNumberGetValue (value, kCFNumberFloatType, &ret); 5914642e01fSmrg else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) 5924642e01fSmrg ret = CFStringGetDoubleValue (value); 5934642e01fSmrg 5944642e01fSmrg if (value != NULL) CFRelease (value); 5954642e01fSmrg 5964642e01fSmrg return ret; 5974642e01fSmrg} 5984642e01fSmrg 5994642e01fSmrg- (int) prefs_get_boolean:(NSString *)key default:(int)def { 6004642e01fSmrg CFPropertyListRef value; 6014642e01fSmrg int ret = def; 6024642e01fSmrg 6034642e01fSmrg value = [self prefs_get:key]; 6044642e01fSmrg 6054642e01fSmrg if (value != NULL) { 6064642e01fSmrg if (CFGetTypeID (value) == CFNumberGetTypeID ()) 6074642e01fSmrg CFNumberGetValue (value, kCFNumberIntType, &ret); 6084642e01fSmrg else if (CFGetTypeID (value) == CFBooleanGetTypeID ()) 6094642e01fSmrg ret = CFBooleanGetValue (value); 6104642e01fSmrg else if (CFGetTypeID (value) == CFStringGetTypeID ()) { 6114642e01fSmrg const char *tem = [(NSString *) value UTF8String]; 6124642e01fSmrg if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0) 6134642e01fSmrg ret = YES; 6144642e01fSmrg else 6154642e01fSmrg ret = NO; 6164642e01fSmrg } 6174642e01fSmrg 6184642e01fSmrg CFRelease (value); 6194642e01fSmrg } 6204642e01fSmrg return ret; 6214642e01fSmrg} 6224642e01fSmrg 6234642e01fSmrg- (NSArray *) prefs_get_array:(NSString *)key { 6244642e01fSmrg NSArray *ret = nil; 6254642e01fSmrg CFPropertyListRef value; 6264642e01fSmrg 6274642e01fSmrg value = [self prefs_get:key]; 6284642e01fSmrg 6294642e01fSmrg if (value != NULL) { 6304642e01fSmrg if (CFGetTypeID (value) == CFArrayGetTypeID ()) 6314642e01fSmrg ret = [cfarray_to_nsarray (value) autorelease]; 6324642e01fSmrg 6334642e01fSmrg CFRelease (value); 6344642e01fSmrg } 6354642e01fSmrg 6364642e01fSmrg return ret; 6374642e01fSmrg} 6384642e01fSmrg 6394642e01fSmrg- (void) prefs_set_integer:(NSString *)key value:(int)value { 6404642e01fSmrg CFNumberRef x; 6414642e01fSmrg 6424642e01fSmrg x = CFNumberCreate (NULL, kCFNumberIntType, &value); 6434642e01fSmrg 6444642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, 6454642e01fSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 6464642e01fSmrg 6474642e01fSmrg CFRelease (x); 6484642e01fSmrg} 6494642e01fSmrg 6504642e01fSmrg- (void) prefs_set_float:(NSString *)key value:(float)value { 6514642e01fSmrg CFNumberRef x; 6524642e01fSmrg 6534642e01fSmrg x = CFNumberCreate (NULL, kCFNumberFloatType, &value); 6544642e01fSmrg 6554642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, 6564642e01fSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 6574642e01fSmrg 6584642e01fSmrg CFRelease (x); 6594642e01fSmrg} 6604642e01fSmrg 6614642e01fSmrg- (void) prefs_set_boolean:(NSString *)key value:(int)value { 6624642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, 6634642e01fSmrg (CFTypeRef) (value ? kCFBooleanTrue 6644642e01fSmrg : kCFBooleanFalse), app_prefs_domain_cfstr, 6654642e01fSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 6664642e01fSmrg 6674642e01fSmrg} 6684642e01fSmrg 6694642e01fSmrg- (void) prefs_set_array:(NSString *)key value:(NSArray *)value { 6704642e01fSmrg CFArrayRef cfarray; 6714642e01fSmrg 6724642e01fSmrg cfarray = nsarray_to_cfarray (value); 6734642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, 6744642e01fSmrg (CFTypeRef) cfarray, 6754642e01fSmrg app_prefs_domain_cfstr, 6764642e01fSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 6774642e01fSmrg CFRelease (cfarray); 6784642e01fSmrg} 6794642e01fSmrg 6804642e01fSmrg- (void) prefs_set_string:(NSString *)key value:(NSString *)value { 6814642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value, 6824642e01fSmrg app_prefs_domain_cfstr, kCFPreferencesCurrentUser, 6834642e01fSmrg kCFPreferencesAnyHost); 6844642e01fSmrg} 6854642e01fSmrg 6864642e01fSmrg- (void) prefs_synchronize { 6874642e01fSmrg CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication); 6884642e01fSmrg} 6894642e01fSmrg 6904642e01fSmrg- (void) read_defaults 6914642e01fSmrg{ 6924642e01fSmrg NSString *nsstr; 6934642e01fSmrg const char *tem; 6944642e01fSmrg 6954642e01fSmrg quartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP 6964642e01fSmrg default:quartzUseSysBeep]; 6974642e01fSmrg quartzEnableRootless = [self prefs_get_boolean:@PREFS_ROOTLESS 6984642e01fSmrg default:quartzEnableRootless]; 6994642e01fSmrg quartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU 7004642e01fSmrg default:quartzFullscreenMenu]; 7014642e01fSmrg quartzFullscreenDisableHotkeys = ![self prefs_get_boolean: 7024642e01fSmrg @PREFS_FULLSCREEN_HOTKEYS default:!quartzFullscreenDisableHotkeys]; 7034642e01fSmrg darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS 7044642e01fSmrg default:darwinFakeButtons]; 7054642e01fSmrg if (darwinFakeButtons) { 7064642e01fSmrg const char *fake2, *fake3; 7074642e01fSmrg 7084642e01fSmrg fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL]; 7094642e01fSmrg fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL]; 7104642e01fSmrg 7114642e01fSmrg if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList(fake2, TRUE); 7124642e01fSmrg if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList(fake3, TRUE); 7134642e01fSmrg } 7144642e01fSmrg 7154642e01fSmrg tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL]; 7164642e01fSmrg if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE); 7174642e01fSmrg 7184642e01fSmrg tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL]; 7194642e01fSmrg if (tem != NULL) { 7204642e01fSmrg windowItemModMask = DarwinParseModifierList(tem, FALSE); 7214642e01fSmrg } else { 7224642e01fSmrg nsstr = NSLocalizedString (@"window item modifiers", @"window item modifiers"); 7234642e01fSmrg if(nsstr != NULL) { 7244642e01fSmrg tem = [nsstr UTF8String]; 7254642e01fSmrg if((tem != NULL) && strcmp(tem, "window item modifiers")) { 7264642e01fSmrg windowItemModMask = DarwinParseModifierList(tem, FALSE); 7274642e01fSmrg } 7284642e01fSmrg } 7294642e01fSmrg } 7304642e01fSmrg 7314642e01fSmrg X11EnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS 7324642e01fSmrg default:X11EnableKeyEquivalents]; 7334642e01fSmrg 7344642e01fSmrg darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP 7354642e01fSmrg default:darwinSyncKeymap]; 7364642e01fSmrg 7374642e01fSmrg darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH 7384642e01fSmrg default:darwinDesiredDepth]; 7394642e01fSmrg 7404642e01fSmrg noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS 7414642e01fSmrg default:FALSE]; 7424642e01fSmrg} 7434642e01fSmrg 7444642e01fSmrg/* This will end up at the end of the responder chain. */ 7454642e01fSmrg- (void) copy:sender { 7464642e01fSmrg DarwinSendDDXEvent(kXquartzPasteboardNotify, 1, 7474642e01fSmrg AppleWMCopyToPasteboard); 7484642e01fSmrg} 7494642e01fSmrg 7504642e01fSmrg- (OSX_BOOL) x_active { 7514642e01fSmrg return _x_active; 7524642e01fSmrg} 7534642e01fSmrg 7544642e01fSmrg@end 7554642e01fSmrg 7564642e01fSmrgstatic NSArray * 7574642e01fSmrgarray_with_strings_and_numbers (int nitems, const char **items, 7584642e01fSmrg const char *numbers) { 7594642e01fSmrg NSMutableArray *array, *subarray; 7604642e01fSmrg NSString *string, *number; 7614642e01fSmrg int i; 7624642e01fSmrg 7634642e01fSmrg /* (Can't autorelease on the X server thread) */ 7644642e01fSmrg 7654642e01fSmrg array = [[NSMutableArray alloc] initWithCapacity:nitems]; 7664642e01fSmrg 7674642e01fSmrg for (i = 0; i < nitems; i++) { 7684642e01fSmrg subarray = [[NSMutableArray alloc] initWithCapacity:2]; 7694642e01fSmrg 7704642e01fSmrg string = [[NSString alloc] initWithUTF8String:items[i]]; 7714642e01fSmrg [subarray addObject:string]; 7724642e01fSmrg [string release]; 7734642e01fSmrg 7744642e01fSmrg if (numbers[i] != 0) { 7754642e01fSmrg number = [[NSString alloc] initWithFormat:@"%d", numbers[i]]; 7764642e01fSmrg [subarray addObject:number]; 7774642e01fSmrg [number release]; 7784642e01fSmrg } else 7794642e01fSmrg [subarray addObject:@""]; 7804642e01fSmrg 7814642e01fSmrg [array addObject:subarray]; 7824642e01fSmrg [subarray release]; 7834642e01fSmrg } 7844642e01fSmrg 7854642e01fSmrg return array; 7864642e01fSmrg} 7874642e01fSmrg 7884642e01fSmrgvoid X11ApplicationSetWindowMenu (int nitems, const char **items, 7894642e01fSmrg const char *shortcuts) { 7904642e01fSmrg NSArray *array; 7914642e01fSmrg array = array_with_strings_and_numbers (nitems, items, shortcuts); 7924642e01fSmrg 7934642e01fSmrg /* Send the array of strings over to the appkit thread */ 7944642e01fSmrg 7954642e01fSmrg message_kit_thread (@selector (set_window_menu:), array); 7964642e01fSmrg [array release]; 7974642e01fSmrg} 7984642e01fSmrg 7994642e01fSmrgvoid X11ApplicationSetWindowMenuCheck (int idx) { 8004642e01fSmrg NSNumber *n; 8014642e01fSmrg 8024642e01fSmrg n = [[NSNumber alloc] initWithInt:idx]; 8034642e01fSmrg 8044642e01fSmrg message_kit_thread (@selector (set_window_menu_check:), n); 8054642e01fSmrg 8064642e01fSmrg [n release]; 8074642e01fSmrg} 8084642e01fSmrg 8094642e01fSmrgvoid X11ApplicationSetFrontProcess (void) { 8104642e01fSmrg message_kit_thread (@selector (set_front_process:), nil); 8114642e01fSmrg} 8124642e01fSmrg 8134642e01fSmrgvoid X11ApplicationSetCanQuit (int state) { 8144642e01fSmrg NSNumber *n; 8154642e01fSmrg 8164642e01fSmrg n = [[NSNumber alloc] initWithBool:state]; 8174642e01fSmrg 8184642e01fSmrg message_kit_thread (@selector (set_can_quit:), n); 8194642e01fSmrg 8204642e01fSmrg [n release]; 8214642e01fSmrg} 8224642e01fSmrg 8234642e01fSmrgvoid X11ApplicationServerReady (void) { 8244642e01fSmrg message_kit_thread (@selector (server_ready:), nil); 8254642e01fSmrg} 8264642e01fSmrg 8274642e01fSmrgvoid X11ApplicationShowHideMenubar (int state) { 8284642e01fSmrg NSNumber *n; 8294642e01fSmrg 8304642e01fSmrg n = [[NSNumber alloc] initWithBool:state]; 8314642e01fSmrg 8324642e01fSmrg message_kit_thread (@selector (show_hide_menubar:), n); 8334642e01fSmrg 8344642e01fSmrg [n release]; 8354642e01fSmrg} 8364642e01fSmrg 8374642e01fSmrgstatic void check_xinitrc (void) { 8384642e01fSmrg char *tem, buf[1024]; 8394642e01fSmrg NSString *msg; 8404642e01fSmrg 8414642e01fSmrg if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO]) 8424642e01fSmrg return; 8434642e01fSmrg 8444642e01fSmrg tem = getenv ("HOME"); 8454642e01fSmrg if (tem == NULL) goto done; 8464642e01fSmrg 8474642e01fSmrg snprintf (buf, sizeof (buf), "%s/.xinitrc", tem); 8484642e01fSmrg if (access (buf, F_OK) != 0) 8494642e01fSmrg goto done; 8504642e01fSmrg 8514642e01fSmrg msg = NSLocalizedString (@"You have an existing ~/.xinitrc file.\n\n\ 8524642e01fSmrgWindows displayed by X11 applications may not have titlebars, or may look \ 8534642e01fSmrgdifferent to windows displayed by native applications.\n\n\ 8544642e01fSmrgWould you like to move aside the existing file and use the standard X11 \ 8554642e01fSmrgenvironment the next time you start X11?", @"Startup xinitrc dialog"); 8564642e01fSmrg 8574642e01fSmrg if(NSAlertDefaultReturn == NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""), 8584642e01fSmrg NSLocalizedString (@"No", @""), nil)) { 8594642e01fSmrg char buf2[1024]; 8604642e01fSmrg int i = -1; 8614642e01fSmrg 8624642e01fSmrg snprintf (buf2, sizeof (buf2), "%s.old", buf); 8634642e01fSmrg 8644642e01fSmrg for(i = 1; access (buf2, F_OK) == 0; i++) 8654642e01fSmrg snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i); 8664642e01fSmrg 8674642e01fSmrg rename (buf, buf2); 8684642e01fSmrg } 8694642e01fSmrg 8704642e01fSmrg done: 8714642e01fSmrg [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES]; 8724642e01fSmrg [X11App prefs_synchronize]; 8734642e01fSmrg} 8744642e01fSmrg 8754642e01fSmrgvoid X11ApplicationMain (int argc, char **argv, char **envp) { 8764642e01fSmrg NSAutoreleasePool *pool; 8774642e01fSmrg int *p; 8784642e01fSmrg 8794642e01fSmrg#ifdef DEBUG 8804642e01fSmrg while (access ("/tmp/x11-block", F_OK) == 0) sleep (1); 8814642e01fSmrg#endif 8824642e01fSmrg 8834642e01fSmrg pool = [[NSAutoreleasePool alloc] init]; 8844642e01fSmrg X11App = (X11Application *) [X11Application sharedApplication]; 8854642e01fSmrg init_ports (); 8864642e01fSmrg 8874642e01fSmrg app_prefs_domain_cfstr = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]; 8884642e01fSmrg 8894642e01fSmrg [NSApp read_defaults]; 8904642e01fSmrg [NSBundle loadNibNamed:@"main" owner:NSApp]; 8914642e01fSmrg [[NSNotificationCenter defaultCenter] addObserver:NSApp 8924642e01fSmrg selector:@selector (became_key:) 8934642e01fSmrg name:NSWindowDidBecomeKeyNotification object:nil]; 8944642e01fSmrg 8954642e01fSmrg /* 8964642e01fSmrg * The xpr Quartz mode is statically linked into this server. 8974642e01fSmrg * Initialize all the Quartz functions. 8984642e01fSmrg */ 8994642e01fSmrg QuartzModeBundleInit(); 9004642e01fSmrg 9014642e01fSmrg /* Calculate the height of the menubar so we can avoid it. */ 9024642e01fSmrg aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - 9034642e01fSmrg NSMaxY([[NSScreen mainScreen] visibleFrame]); 9044642e01fSmrg 9054642e01fSmrg /* Set the key layout seed before we start the server */ 9064642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 9074642e01fSmrg last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); 9084642e01fSmrg 9094642e01fSmrg if(!last_key_layout) 9104642e01fSmrg fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); 9114642e01fSmrg#else 9124642e01fSmrg KLGetCurrentKeyboardLayout(&last_key_layout); 9134642e01fSmrg if(!last_key_layout) 9144642e01fSmrg fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n"); 9154642e01fSmrg#endif 9164642e01fSmrg 9174642e01fSmrg memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); 9184642e01fSmrg if (!QuartzReadSystemKeymap(&keyInfo)) { 9194642e01fSmrg fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n"); 9204642e01fSmrg } 9214642e01fSmrg 9224642e01fSmrg for(p=darwin_modifier_mask_list, modifierFlagsMask=0; *p; p++) { 9234642e01fSmrg modifierFlagsMask |= *p; 9244642e01fSmrg } 9254642e01fSmrg 9264642e01fSmrg /* Tell the server thread that it can proceed */ 9274642e01fSmrg QuartzInitServer(argc, argv, envp); 9284642e01fSmrg 9294642e01fSmrg /* This must be done after QuartzInitServer because it can result in 9304642e01fSmrg * an mieqEnqueue() - <rdar://problem/6300249> 9314642e01fSmrg */ 9324642e01fSmrg check_xinitrc(); 9334642e01fSmrg 9344642e01fSmrg if(!xpbproxy_init()) 9354642e01fSmrg fprintf(stderr, "Error initializing xpbproxy\n"); 9364642e01fSmrg 9374642e01fSmrg [NSApp run]; 9384642e01fSmrg /* not reached */ 9394642e01fSmrg} 9404642e01fSmrg 9414642e01fSmrg@implementation X11Application (Private) 9424642e01fSmrg 9434642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK 9444642e01fSmrg/* This is to workaround a bug in the VNC server where we sometimes see the L 9454642e01fSmrg * modifier and sometimes see no "side" 9464642e01fSmrg */ 9474642e01fSmrgstatic inline int ensure_flag(int flags, int device_independent, int device_dependents, int device_dependent_default) { 9484642e01fSmrg if( (flags & device_independent) && 9494642e01fSmrg !(flags & device_dependents)) 9504642e01fSmrg flags |= device_dependent_default; 9514642e01fSmrg return flags; 9524642e01fSmrg} 9534642e01fSmrg#endif 9544642e01fSmrg 9554642e01fSmrg- (void) sendX11NSEvent:(NSEvent *)e { 9564642e01fSmrg NSRect screen; 9574642e01fSmrg NSPoint location; 9584642e01fSmrg NSWindow *window; 9594642e01fSmrg int ev_button, ev_type; 9604642e01fSmrg float pointer_x, pointer_y, pressure, tilt_x, tilt_y; 9614642e01fSmrg DeviceIntPtr pDev; 9624642e01fSmrg int modifierFlags; 9634642e01fSmrg 9644642e01fSmrg /* convert location to be relative to top-left of primary display */ 9654642e01fSmrg location = [e locationInWindow]; 9664642e01fSmrg window = [e window]; 9674642e01fSmrg screen = [[[NSScreen screens] objectAtIndex:0] frame]; 9684642e01fSmrg 9694642e01fSmrg if (window != nil) { 9704642e01fSmrg NSRect frame = [window frame]; 9714642e01fSmrg pointer_x = location.x + frame.origin.x; 9724642e01fSmrg pointer_y = (screen.origin.y + screen.size.height) 9734642e01fSmrg - (location.y + frame.origin.y); 9744642e01fSmrg } else { 9754642e01fSmrg pointer_x = location.x; 9764642e01fSmrg pointer_y = (screen.origin.y + screen.size.height) - location.y; 9774642e01fSmrg } 9784642e01fSmrg 9794642e01fSmrg /* Setup our valuators. These will range from 0 to 1 */ 9804642e01fSmrg pressure = 0; 9814642e01fSmrg tilt_x = 0; 9824642e01fSmrg tilt_y = 0; 9834642e01fSmrg 9844642e01fSmrg modifierFlags = [e modifierFlags]; 9854642e01fSmrg 9864642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK 9874642e01fSmrg /* This is to workaround a bug in the VNC server where we sometimes see the L 9884642e01fSmrg * modifier and sometimes see no "side" 9894642e01fSmrg */ 9904642e01fSmrg modifierFlags = ensure_flag(modifierFlags, NX_CONTROLMASK, NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK, NX_DEVICELCTLKEYMASK); 9914642e01fSmrg modifierFlags = ensure_flag(modifierFlags, NX_SHIFTMASK, NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK, NX_DEVICELSHIFTKEYMASK); 9924642e01fSmrg modifierFlags = ensure_flag(modifierFlags, NX_COMMANDMASK, NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK, NX_DEVICELCMDKEYMASK); 9934642e01fSmrg modifierFlags = ensure_flag(modifierFlags, NX_ALTERNATEMASK, NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK, NX_DEVICELALTKEYMASK); 9944642e01fSmrg#endif 9954642e01fSmrg 9964642e01fSmrg modifierFlags &= modifierFlagsMask; 9974642e01fSmrg 9984642e01fSmrg /* We don't receive modifier key events while out of focus, and 3button 9994642e01fSmrg * emulation mucks this up, so we need to check our modifier flag state 10004642e01fSmrg * on every event... ugg 10014642e01fSmrg */ 10024642e01fSmrg 10034642e01fSmrg if(darwin_modifier_flags != modifierFlags) 10044642e01fSmrg DarwinUpdateModKeys(modifierFlags); 10054642e01fSmrg 10064642e01fSmrg switch ([e type]) { 10074642e01fSmrg case NSLeftMouseDown: ev_button=1; ev_type=ButtonPress; goto handle_mouse; 10084642e01fSmrg case NSOtherMouseDown: ev_button=2; ev_type=ButtonPress; goto handle_mouse; 10094642e01fSmrg case NSRightMouseDown: ev_button=3; ev_type=ButtonPress; goto handle_mouse; 10104642e01fSmrg case NSLeftMouseUp: ev_button=1; ev_type=ButtonRelease; goto handle_mouse; 10114642e01fSmrg case NSOtherMouseUp: ev_button=2; ev_type=ButtonRelease; goto handle_mouse; 10124642e01fSmrg case NSRightMouseUp: ev_button=3; ev_type=ButtonRelease; goto handle_mouse; 10134642e01fSmrg case NSLeftMouseDragged: ev_button=1; ev_type=MotionNotify; goto handle_mouse; 10144642e01fSmrg case NSOtherMouseDragged: ev_button=2; ev_type=MotionNotify; goto handle_mouse; 10154642e01fSmrg case NSRightMouseDragged: ev_button=3; ev_type=MotionNotify; goto handle_mouse; 10164642e01fSmrg case NSMouseMoved: ev_button=0; ev_type=MotionNotify; goto handle_mouse; 10174642e01fSmrg case NSTabletPoint: ev_button=0; ev_type=MotionNotify; goto handle_mouse; 10184642e01fSmrg 10194642e01fSmrg handle_mouse: 10204642e01fSmrg pDev = darwinPointer; 10214642e01fSmrg 10224642e01fSmrg /* NSTabletPoint can have no subtype */ 10234642e01fSmrg if([e type] != NSTabletPoint && 10244642e01fSmrg [e subtype] == NSTabletProximityEventSubtype) { 10254642e01fSmrg switch([e pointingDeviceType]) { 10264642e01fSmrg case NSEraserPointingDevice: 10274642e01fSmrg darwinTabletCurrent=darwinTabletEraser; 10284642e01fSmrg break; 10294642e01fSmrg case NSPenPointingDevice: 10304642e01fSmrg darwinTabletCurrent=darwinTabletStylus; 10314642e01fSmrg break; 10324642e01fSmrg case NSCursorPointingDevice: 10334642e01fSmrg case NSUnknownPointingDevice: 10344642e01fSmrg default: 10354642e01fSmrg darwinTabletCurrent=darwinTabletCursor; 10364642e01fSmrg break; 10374642e01fSmrg } 10384642e01fSmrg 10394642e01fSmrg /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt 10404642e01fSmrg * So we just pretend the motion was caused by the mouse. Hopefully 10414642e01fSmrg * we'll have a better solution for this in the future (like maybe 10424642e01fSmrg * NSTabletProximityEventSubtype will come from NSTabletPoint 10434642e01fSmrg * rather than NSMouseMoved. 10444642e01fSmrg pressure = [e pressure]; 10454642e01fSmrg tilt_x = [e tilt].x; 10464642e01fSmrg tilt_y = [e tilt].y; 10474642e01fSmrg pDev = darwinTabletCurrent; 10484642e01fSmrg */ 10494642e01fSmrg 10504642e01fSmrg DarwinSendProximityEvents([e isEnteringProximity]?ProximityIn:ProximityOut, 10514642e01fSmrg pointer_x, pointer_y); 10524642e01fSmrg } 10534642e01fSmrg 10544642e01fSmrg if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) { 10554642e01fSmrg pressure = [e pressure]; 10564642e01fSmrg tilt_x = [e tilt].x; 10574642e01fSmrg tilt_y = [e tilt].y; 10584642e01fSmrg 10594642e01fSmrg pDev = darwinTabletCurrent; 10604642e01fSmrg } 10614642e01fSmrg 10624642e01fSmrg/* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */ 10634642e01fSmrg#ifdef XPLUGIN_VERSION 10644642e01fSmrg#if XPLUGIN_VERSION > 0 10654642e01fSmrg if(!quartzServerVisible) { 10664642e01fSmrg xp_window_id wid; 10674642e01fSmrg 10684642e01fSmrg /* Sigh. Need to check that we're really over one of 10694642e01fSmrg * our windows. (We need to receive pointer events while 10704642e01fSmrg * not in the foreground, but we don't want to receive them 10714642e01fSmrg * when another window is over us or we might show a tooltip) 10724642e01fSmrg */ 10734642e01fSmrg 10744642e01fSmrg wid = 0; 10754642e01fSmrg 10764642e01fSmrg if (xp_find_window(pointer_x, pointer_y, 0, &wid) == XP_Success && 10774642e01fSmrg wid == 0) 10784642e01fSmrg return; 10794642e01fSmrg } 10804642e01fSmrg#endif 10814642e01fSmrg#endif 10824642e01fSmrg 10834642e01fSmrg DarwinSendPointerEvents(pDev, ev_type, ev_button, pointer_x, pointer_y, 10844642e01fSmrg pressure, tilt_x, tilt_y); 10854642e01fSmrg 10864642e01fSmrg break; 10874642e01fSmrg 10884642e01fSmrg case NSTabletProximity: 10894642e01fSmrg switch([e pointingDeviceType]) { 10904642e01fSmrg case NSEraserPointingDevice: 10914642e01fSmrg darwinTabletCurrent=darwinTabletEraser; 10924642e01fSmrg break; 10934642e01fSmrg case NSPenPointingDevice: 10944642e01fSmrg darwinTabletCurrent=darwinTabletStylus; 10954642e01fSmrg break; 10964642e01fSmrg case NSCursorPointingDevice: 10974642e01fSmrg case NSUnknownPointingDevice: 10984642e01fSmrg default: 10994642e01fSmrg darwinTabletCurrent=darwinTabletCursor; 11004642e01fSmrg break; 11014642e01fSmrg } 11024642e01fSmrg 11034642e01fSmrg DarwinSendProximityEvents([e isEnteringProximity]?ProximityIn:ProximityOut, 11044642e01fSmrg pointer_x, pointer_y); 11054642e01fSmrg break; 11064642e01fSmrg 11074642e01fSmrg case NSScrollWheel: 11084642e01fSmrg DarwinSendScrollEvents([e deltaX], [e deltaY], pointer_x, pointer_y, 11094642e01fSmrg pressure, tilt_x, tilt_y); 11104642e01fSmrg break; 11114642e01fSmrg 11124642e01fSmrg case NSKeyDown: case NSKeyUp: 11134642e01fSmrg if(darwinSyncKeymap) { 11144642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 11154642e01fSmrg TISInputSourceRef key_layout = TISCopyCurrentKeyboardLayoutInputSource(); 11164642e01fSmrg TISInputSourceRef clear; 11174642e01fSmrg if (CFEqual(key_layout, last_key_layout)) { 11184642e01fSmrg CFRelease(key_layout); 11194642e01fSmrg } else { 11204642e01fSmrg /* Swap/free thread-safely */ 11214642e01fSmrg clear = last_key_layout; 11224642e01fSmrg last_key_layout = key_layout; 11234642e01fSmrg CFRelease(clear); 11244642e01fSmrg#else 11254642e01fSmrg KeyboardLayoutRef key_layout; 11264642e01fSmrg KLGetCurrentKeyboardLayout(&key_layout); 11274642e01fSmrg if(key_layout != last_key_layout) { 11284642e01fSmrg last_key_layout = key_layout; 11294642e01fSmrg#endif 11304642e01fSmrg 11314642e01fSmrg /* Update keyInfo */ 11324642e01fSmrg pthread_mutex_lock(&keyInfo_mutex); 11334642e01fSmrg memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); 11344642e01fSmrg if (!QuartzReadSystemKeymap(&keyInfo)) { 11354642e01fSmrg fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n"); 11364642e01fSmrg } 11374642e01fSmrg pthread_mutex_unlock(&keyInfo_mutex); 11384642e01fSmrg 11394642e01fSmrg /* Tell server thread to deal with new keyInfo */ 11404642e01fSmrg DarwinSendDDXEvent(kXquartzReloadKeymap, 0); 11414642e01fSmrg } 11424642e01fSmrg } 11434642e01fSmrg 11444642e01fSmrg /* Avoid stuck keys on context switch */ 11454642e01fSmrg if(keyState[[e keyCode]] == [e type]) 11464642e01fSmrg return; 11474642e01fSmrg keyState[[e keyCode]] = [e type]; 11484642e01fSmrg 11494642e01fSmrg DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]); 11504642e01fSmrg break; 11514642e01fSmrg 11524642e01fSmrg default: break; /* for gcc */ 11534642e01fSmrg } 11544642e01fSmrg} 11554642e01fSmrg@end 1156