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