X11Application.m revision 9ace9065
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" 416747b715Smrg#include "quartz.h" 424642e01fSmrg#include "darwinEvents.h" 434642e01fSmrg#include "quartzKeyboard.h" 444642e01fSmrg#include "quartz.h" 456747b715Smrg#include <X11/extensions/applewmconst.h> 464642e01fSmrg#include "micmap.h" 476747b715Smrg#include "exglobals.h" 484642e01fSmrg 494642e01fSmrg#include <mach/mach.h> 504642e01fSmrg#include <unistd.h> 514642e01fSmrg#include <AvailabilityMacros.h> 524642e01fSmrg 539ace9065Smrg#include <pthread.h> 549ace9065Smrg 554642e01fSmrg#include <Xplugin.h> 564642e01fSmrg 574642e01fSmrg// pbproxy/pbproxy.h 586747b715Smrgextern int xpbproxy_run (void); 594642e01fSmrg 604642e01fSmrg#define DEFAULTS_FILE X11LIBDIR"/X11/xserver/Xquartz.plist" 614642e01fSmrg 624642e01fSmrg#ifndef XSERVER_VERSION 634642e01fSmrg#define XSERVER_VERSION "?" 644642e01fSmrg#endif 654642e01fSmrg 664642e01fSmrg/* Stuck modifier / button state... force release when we context switch */ 674642e01fSmrgstatic NSEventType keyState[NUM_KEYCODES]; 684642e01fSmrg 694642e01fSmrgextern Bool noTestExtensions; 704642e01fSmrg 714642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 724642e01fSmrgstatic TISInputSourceRef last_key_layout; 734642e01fSmrg#else 744642e01fSmrgstatic KeyboardLayoutRef last_key_layout; 754642e01fSmrg#endif 764642e01fSmrg 774642e01fSmrgextern int darwinFakeButtons; 784642e01fSmrg 796747b715Smrg/* Store the mouse location while in the background, and update X11's pointer 806747b715Smrg * location when we become the foreground application 816747b715Smrg */ 826747b715Smrgstatic NSPoint bgMouseLocation; 836747b715Smrgstatic BOOL bgMouseLocationUpdated = FALSE; 846747b715Smrg 854642e01fSmrgX11Application *X11App; 864642e01fSmrg 874642e01fSmrgCFStringRef app_prefs_domain_cfstr = NULL; 884642e01fSmrg 894642e01fSmrg#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask) 904642e01fSmrg 914642e01fSmrg@interface X11Application (Private) 924642e01fSmrg- (void) sendX11NSEvent:(NSEvent *)e; 934642e01fSmrg@end 944642e01fSmrg 954642e01fSmrg@implementation X11Application 964642e01fSmrg 974642e01fSmrgtypedef struct message_struct message; 984642e01fSmrgstruct message_struct { 994642e01fSmrg mach_msg_header_t hdr; 1004642e01fSmrg SEL selector; 1014642e01fSmrg NSObject *arg; 1024642e01fSmrg}; 1034642e01fSmrg 1044642e01fSmrgstatic mach_port_t _port; 1054642e01fSmrg 1064642e01fSmrg/* Quartz mode initialization routine. This is often dynamically loaded 1074642e01fSmrg but is statically linked into this X server. */ 1084642e01fSmrgBool QuartzModeBundleInit(void); 1094642e01fSmrg 1104642e01fSmrgstatic void init_ports (void) { 1114642e01fSmrg kern_return_t r; 1124642e01fSmrg NSPort *p; 1134642e01fSmrg 1144642e01fSmrg if (_port != MACH_PORT_NULL) return; 1154642e01fSmrg 1164642e01fSmrg r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port); 1174642e01fSmrg if (r != KERN_SUCCESS) return; 1184642e01fSmrg 1194642e01fSmrg p = [NSMachPort portWithMachPort:_port]; 1204642e01fSmrg [p setDelegate:NSApp]; 1214642e01fSmrg [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 1224642e01fSmrg} 1234642e01fSmrg 1244642e01fSmrgstatic void message_kit_thread (SEL selector, NSObject *arg) { 1254642e01fSmrg message msg; 1264642e01fSmrg kern_return_t r; 1274642e01fSmrg 1284642e01fSmrg msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0); 1294642e01fSmrg msg.hdr.msgh_size = sizeof (msg); 1304642e01fSmrg msg.hdr.msgh_remote_port = _port; 1314642e01fSmrg msg.hdr.msgh_local_port = MACH_PORT_NULL; 1324642e01fSmrg msg.hdr.msgh_reserved = 0; 1334642e01fSmrg msg.hdr.msgh_id = 0; 1344642e01fSmrg 1354642e01fSmrg msg.selector = selector; 1364642e01fSmrg msg.arg = [arg retain]; 1374642e01fSmrg 1384642e01fSmrg r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size, 1394642e01fSmrg 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); 1404642e01fSmrg if (r != KERN_SUCCESS) 1414642e01fSmrg ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r); 1424642e01fSmrg} 1434642e01fSmrg 1444642e01fSmrg- (void) handleMachMessage:(void *)_msg { 1454642e01fSmrg message *msg = _msg; 1464642e01fSmrg 1474642e01fSmrg [self performSelector:msg->selector withObject:msg->arg]; 1484642e01fSmrg [msg->arg release]; 1494642e01fSmrg} 1504642e01fSmrg 1514642e01fSmrg- (void) set_controller:obj { 1524642e01fSmrg if (_controller == nil) _controller = [obj retain]; 1534642e01fSmrg} 1544642e01fSmrg 1554642e01fSmrg- (void) dealloc { 1564642e01fSmrg if (_controller != nil) [_controller release]; 1574642e01fSmrg 1584642e01fSmrg if (_port != MACH_PORT_NULL) 1594642e01fSmrg mach_port_deallocate (mach_task_self (), _port); 1604642e01fSmrg 1614642e01fSmrg [super dealloc]; 1624642e01fSmrg} 1634642e01fSmrg 1644642e01fSmrg- (void) orderFrontStandardAboutPanel: (id) sender { 1654642e01fSmrg NSMutableDictionary *dict; 1664642e01fSmrg NSDictionary *infoDict; 1674642e01fSmrg NSString *tem; 1684642e01fSmrg 1694642e01fSmrg dict = [NSMutableDictionary dictionaryWithCapacity:3]; 1704642e01fSmrg infoDict = [[NSBundle mainBundle] infoDictionary]; 1714642e01fSmrg 1724642e01fSmrg [dict setObject: NSLocalizedString (@"The X Window System", @"About panel") 1734642e01fSmrg forKey:@"ApplicationName"]; 1744642e01fSmrg 1754642e01fSmrg tem = [infoDict objectForKey:@"CFBundleShortVersionString"]; 1764642e01fSmrg 1774642e01fSmrg [dict setObject:[NSString stringWithFormat:@"XQuartz %@", tem] 1784642e01fSmrg forKey:@"ApplicationVersion"]; 1794642e01fSmrg 1804642e01fSmrg [dict setObject:[NSString stringWithFormat:@"xorg-server %s", XSERVER_VERSION] 1814642e01fSmrg forKey:@"Version"]; 1824642e01fSmrg 1834642e01fSmrg [self orderFrontStandardAboutPanelWithOptions: dict]; 1844642e01fSmrg} 1854642e01fSmrg 1864642e01fSmrg- (void) activateX:(OSX_BOOL)state { 1874642e01fSmrg size_t i; 1884642e01fSmrg DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active) 1894642e01fSmrg if (state) { 1906747b715Smrg if(bgMouseLocationUpdated) { 1916747b715Smrg DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, bgMouseLocation.x, bgMouseLocation.y, 0.0, 0.0, 0.0); 1926747b715Smrg bgMouseLocationUpdated = FALSE; 1934642e01fSmrg } 1946747b715Smrg DarwinSendDDXEvent(kXquartzActivate, 0); 1954642e01fSmrg } else { 1964642e01fSmrg 1976747b715Smrg if(darwin_all_modifier_flags) 1984642e01fSmrg DarwinUpdateModKeys(0); 1994642e01fSmrg for(i=0; i < NUM_KEYCODES; i++) { 2004642e01fSmrg if(keyState[i] == NSKeyDown) { 2014642e01fSmrg DarwinSendKeyboardEvents(KeyRelease, i); 2024642e01fSmrg keyState[i] = NSKeyUp; 2034642e01fSmrg } 2044642e01fSmrg } 2054642e01fSmrg 2064642e01fSmrg DarwinSendDDXEvent(kXquartzDeactivate, 0); 2074642e01fSmrg } 2084642e01fSmrg 2094642e01fSmrg _x_active = state; 2104642e01fSmrg} 2114642e01fSmrg 2124642e01fSmrg- (void) became_key:(NSWindow *)win { 2134642e01fSmrg [self activateX:NO]; 2144642e01fSmrg} 2154642e01fSmrg 2164642e01fSmrg- (void) sendEvent:(NSEvent *)e { 2174642e01fSmrg OSX_BOOL for_appkit, for_x; 2184642e01fSmrg 2194642e01fSmrg /* By default pass down the responder chain and to X. */ 2204642e01fSmrg for_appkit = YES; 2214642e01fSmrg for_x = YES; 2224642e01fSmrg 2234642e01fSmrg switch ([e type]) { 2244642e01fSmrg case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: 2254642e01fSmrg case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: 2264642e01fSmrg if ([e window] != nil) { 2274642e01fSmrg /* Pointer event has an (AppKit) window. Probably something for the kit. */ 2284642e01fSmrg for_x = NO; 2294642e01fSmrg if (_x_active) [self activateX:NO]; 2304642e01fSmrg } else if ([self modalWindow] == nil) { 2314642e01fSmrg /* Must be an X window. Tell appkit it doesn't have focus. */ 2324642e01fSmrg for_appkit = NO; 2334642e01fSmrg 2344642e01fSmrg if ([self isActive]) { 2354642e01fSmrg [self deactivate]; 2364642e01fSmrg if (!_x_active && quartzProcs->IsX11Window([e window], 2374642e01fSmrg [e windowNumber])) 2384642e01fSmrg [self activateX:YES]; 2394642e01fSmrg } 2404642e01fSmrg } 2414642e01fSmrg 2424642e01fSmrg /* We want to force sending to appkit if we're over the menu bar */ 2434642e01fSmrg if(!for_appkit) { 2444642e01fSmrg NSPoint NSlocation = [e locationInWindow]; 2454642e01fSmrg NSWindow *window = [e window]; 2466747b715Smrg NSRect NSframe, NSvisibleFrame; 2476747b715Smrg CGRect CGframe, CGvisibleFrame; 2486747b715Smrg CGPoint CGlocation; 2496747b715Smrg 2504642e01fSmrg if (window != nil) { 2514642e01fSmrg NSRect frame = [window frame]; 2524642e01fSmrg NSlocation.x += frame.origin.x; 2534642e01fSmrg NSlocation.y += frame.origin.y; 2544642e01fSmrg } 2554642e01fSmrg 2566747b715Smrg NSframe = [[NSScreen mainScreen] frame]; 2576747b715Smrg NSvisibleFrame = [[NSScreen mainScreen] visibleFrame]; 2584642e01fSmrg 2596747b715Smrg CGframe = CGRectMake(NSframe.origin.x, NSframe.origin.y, 2604642e01fSmrg NSframe.size.width, NSframe.size.height); 2616747b715Smrg CGvisibleFrame = CGRectMake(NSvisibleFrame.origin.x, 2624642e01fSmrg NSvisibleFrame.origin.y, 2634642e01fSmrg NSvisibleFrame.size.width, 2644642e01fSmrg NSvisibleFrame.size.height); 2656747b715Smrg CGlocation = CGPointMake(NSlocation.x, NSlocation.y); 2664642e01fSmrg 2674642e01fSmrg if(CGRectContainsPoint(CGframe, CGlocation) && 2684642e01fSmrg !CGRectContainsPoint(CGvisibleFrame, CGlocation)) 2694642e01fSmrg for_appkit = YES; 2704642e01fSmrg } 2714642e01fSmrg 2724642e01fSmrg break; 2734642e01fSmrg 2744642e01fSmrg case NSKeyDown: case NSKeyUp: 2754642e01fSmrg 2764642e01fSmrg if(_x_active) { 2774642e01fSmrg static BOOL do_swallow = NO; 2784642e01fSmrg static int swallow_keycode; 2794642e01fSmrg 2804642e01fSmrg if([e type] == NSKeyDown) { 2814642e01fSmrg /* Before that though, see if there are any global 2824642e01fSmrg * shortcuts bound to it. */ 2834642e01fSmrg 2844642e01fSmrg if(darwinAppKitModMask & [e modifierFlags]) { 2854642e01fSmrg /* Override to force sending to Appkit */ 2864642e01fSmrg swallow_keycode = [e keyCode]; 2874642e01fSmrg do_swallow = YES; 2884642e01fSmrg for_x = NO; 2894642e01fSmrg#if XPLUGIN_VERSION >= 1 2906747b715Smrg } else if(XQuartzEnableKeyEquivalents && 2914642e01fSmrg xp_is_symbolic_hotkey_event([e eventRef])) { 2924642e01fSmrg swallow_keycode = [e keyCode]; 2934642e01fSmrg do_swallow = YES; 2944642e01fSmrg for_x = NO; 2954642e01fSmrg#endif 2966747b715Smrg } else if(XQuartzEnableKeyEquivalents && 2974642e01fSmrg [[self mainMenu] performKeyEquivalent:e]) { 2984642e01fSmrg swallow_keycode = [e keyCode]; 2994642e01fSmrg do_swallow = YES; 3004642e01fSmrg for_appkit = NO; 3014642e01fSmrg for_x = NO; 3026747b715Smrg } else if(!XQuartzIsRootless 3034642e01fSmrg && ([e modifierFlags] & ALL_KEY_MASKS) == (NSCommandKeyMask | NSAlternateKeyMask) 3044642e01fSmrg && ([e keyCode] == 0 /*a*/ || [e keyCode] == 53 /*Esc*/)) { 3054642e01fSmrg /* We have this here to force processing fullscreen 3066747b715Smrg * toggle even if XQuartzEnableKeyEquivalents is disabled */ 3074642e01fSmrg swallow_keycode = [e keyCode]; 3084642e01fSmrg do_swallow = YES; 3094642e01fSmrg for_x = NO; 3104642e01fSmrg for_appkit = NO; 3114642e01fSmrg DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); 3124642e01fSmrg } else { 3134642e01fSmrg /* No kit window is focused, so send it to X. */ 3144642e01fSmrg for_appkit = NO; 3154642e01fSmrg } 3164642e01fSmrg } else { /* KeyUp */ 3174642e01fSmrg /* If we saw a key equivalent on the down, don't pass 3184642e01fSmrg * the up through to X. */ 3194642e01fSmrg if (do_swallow && [e keyCode] == swallow_keycode) { 3204642e01fSmrg do_swallow = NO; 3214642e01fSmrg for_x = NO; 3224642e01fSmrg } 3234642e01fSmrg } 3244642e01fSmrg } else { /* !_x_active */ 3254642e01fSmrg for_x = NO; 3264642e01fSmrg } 3274642e01fSmrg break; 3284642e01fSmrg 3294642e01fSmrg case NSFlagsChanged: 3304642e01fSmrg /* Don't tell X11 about modifiers changing while it's not active */ 3314642e01fSmrg if (!_x_active) 3324642e01fSmrg for_x = NO; 3334642e01fSmrg break; 3344642e01fSmrg 3354642e01fSmrg case NSAppKitDefined: 3364642e01fSmrg switch ([e subtype]) { 3379ace9065Smrg static BOOL x_was_active = NO; 3389ace9065Smrg 3394642e01fSmrg case NSApplicationActivatedEventType: 3404642e01fSmrg for_x = NO; 3419ace9065Smrg if ([e window] == nil && x_was_active) { 3426747b715Smrg BOOL order_all_windows = YES, workspaces, ok; 3434642e01fSmrg for_appkit = NO; 3449ace9065Smrg 3459ace9065Smrg /* FIXME: This is a hack to avoid passing the event to AppKit which 3469ace9065Smrg * would result in it raising one of its windows. 3479ace9065Smrg */ 3484642e01fSmrg _appFlags._active = YES; 3499ace9065Smrg 3509ace9065Smrg X11ApplicationSetFrontProcess(); 3519ace9065Smrg 3524642e01fSmrg /* Get the Spaces preference for SwitchOnActivate */ 3536747b715Smrg (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock")); 3546747b715Smrg workspaces = CFPreferencesGetAppBooleanValue(CFSTR("workspaces"), CFSTR("com.apple.dock"), &ok); 3556747b715Smrg if (!ok) 3566747b715Smrg workspaces = NO; 3576747b715Smrg 3586747b715Smrg if (workspaces) { 3596747b715Smrg (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); 3606747b715Smrg order_all_windows = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok); 3616747b715Smrg if (!ok) 3626747b715Smrg order_all_windows = YES; 3636747b715Smrg } 3644642e01fSmrg 3656747b715Smrg /* TODO: In the workspaces && !AppleSpacesSwitchOnActivate case, the windows are ordered 3666747b715Smrg * correctly, but we need to activate the top window on this space if there is 3676747b715Smrg * none active. 3686747b715Smrg * 3696747b715Smrg * If there are no active windows, and there are minimized windows, we should 3706747b715Smrg * be restoring one of them. 3716747b715Smrg */ 3729ace9065Smrg if ([e data2] & 0x10) { // 0x10 (bfCPSOrderAllWindowsForward) is set when we use cmd-tab or the dock icon 3736747b715Smrg DarwinSendDDXEvent(kXquartzBringAllToFront, 1, order_all_windows); 3749ace9065Smrg } 3754642e01fSmrg } 3764642e01fSmrg break; 3774642e01fSmrg 3784642e01fSmrg case 18: /* ApplicationDidReactivate */ 3796747b715Smrg if (XQuartzFullscreenVisible) for_appkit = NO; 3804642e01fSmrg break; 3814642e01fSmrg 3824642e01fSmrg case NSApplicationDeactivatedEventType: 3834642e01fSmrg for_x = NO; 3849ace9065Smrg 3859ace9065Smrg x_was_active = _x_active; 3869ace9065Smrg if(_x_active) 3879ace9065Smrg [self activateX:NO]; 3884642e01fSmrg break; 3894642e01fSmrg } 3904642e01fSmrg break; 3914642e01fSmrg 3924642e01fSmrg default: break; /* for gcc */ 3934642e01fSmrg } 3944642e01fSmrg 3954642e01fSmrg if (for_appkit) [super sendEvent:e]; 3964642e01fSmrg 3974642e01fSmrg if (for_x) [self sendX11NSEvent:e]; 3984642e01fSmrg} 3994642e01fSmrg 4004642e01fSmrg- (void) set_window_menu:(NSArray *)list { 4014642e01fSmrg [_controller set_window_menu:list]; 4024642e01fSmrg} 4034642e01fSmrg 4044642e01fSmrg- (void) set_window_menu_check:(NSNumber *)n { 4054642e01fSmrg [_controller set_window_menu_check:n]; 4064642e01fSmrg} 4074642e01fSmrg 4084642e01fSmrg- (void) set_apps_menu:(NSArray *)list { 4094642e01fSmrg [_controller set_apps_menu:list]; 4104642e01fSmrg} 4114642e01fSmrg 4124642e01fSmrg- (void) set_front_process:unused { 4134642e01fSmrg [NSApp activateIgnoringOtherApps:YES]; 4144642e01fSmrg 4154642e01fSmrg if ([self modalWindow] == nil) 4164642e01fSmrg [self activateX:YES]; 4174642e01fSmrg} 4184642e01fSmrg 4194642e01fSmrg- (void) set_can_quit:(NSNumber *)state { 4204642e01fSmrg [_controller set_can_quit:[state boolValue]]; 4214642e01fSmrg} 4224642e01fSmrg 4234642e01fSmrg- (void) server_ready:unused { 4244642e01fSmrg [_controller server_ready]; 4254642e01fSmrg} 4264642e01fSmrg 4274642e01fSmrg- (void) show_hide_menubar:(NSNumber *)state { 4284642e01fSmrg /* Also shows/hides the dock */ 4294642e01fSmrg if ([state boolValue]) 4304642e01fSmrg SetSystemUIMode(kUIModeNormal, 0); 4314642e01fSmrg else 4326747b715Smrg SetSystemUIMode(kUIModeAllHidden, XQuartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation" 4334642e01fSmrg} 4344642e01fSmrg 4356747b715Smrg- (void) launch_client:(NSString *)cmd { 4366747b715Smrg (void)[_controller application:self openFile:cmd]; 4376747b715Smrg} 4384642e01fSmrg 4394642e01fSmrg/* user preferences */ 4404642e01fSmrg 4414642e01fSmrg/* Note that these functions only work for arrays whose elements 4424642e01fSmrg can be toll-free-bridged between NS and CF worlds. */ 4434642e01fSmrg 4444642e01fSmrgstatic const void *cfretain (CFAllocatorRef a, const void *b) { 4454642e01fSmrg return CFRetain (b); 4464642e01fSmrg} 4474642e01fSmrg 4484642e01fSmrgstatic void cfrelease (CFAllocatorRef a, const void *b) { 4494642e01fSmrg CFRelease (b); 4504642e01fSmrg} 4514642e01fSmrg 4524642e01fSmrgstatic CFMutableArrayRef nsarray_to_cfarray (NSArray *in) { 4534642e01fSmrg CFMutableArrayRef out; 4544642e01fSmrg CFArrayCallBacks cb; 4554642e01fSmrg NSObject *ns; 4564642e01fSmrg const CFTypeRef *cf; 4574642e01fSmrg int i, count; 4584642e01fSmrg 4594642e01fSmrg memset (&cb, 0, sizeof (cb)); 4604642e01fSmrg cb.version = 0; 4614642e01fSmrg cb.retain = cfretain; 4624642e01fSmrg cb.release = cfrelease; 4634642e01fSmrg 4644642e01fSmrg count = [in count]; 4654642e01fSmrg out = CFArrayCreateMutable (NULL, count, &cb); 4664642e01fSmrg 4674642e01fSmrg for (i = 0; i < count; i++) { 4684642e01fSmrg ns = [in objectAtIndex:i]; 4694642e01fSmrg 4704642e01fSmrg if ([ns isKindOfClass:[NSArray class]]) 4714642e01fSmrg cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns); 4724642e01fSmrg else 4734642e01fSmrg cf = CFRetain ((CFTypeRef) ns); 4744642e01fSmrg 4754642e01fSmrg CFArrayAppendValue (out, cf); 4764642e01fSmrg CFRelease (cf); 4774642e01fSmrg } 4784642e01fSmrg 4794642e01fSmrg return out; 4804642e01fSmrg} 4814642e01fSmrg 4824642e01fSmrgstatic NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { 4834642e01fSmrg NSMutableArray *out; 4844642e01fSmrg const CFTypeRef *cf; 4854642e01fSmrg NSObject *ns; 4864642e01fSmrg int i, count; 4874642e01fSmrg 4884642e01fSmrg count = CFArrayGetCount (in); 4894642e01fSmrg out = [[NSMutableArray alloc] initWithCapacity:count]; 4904642e01fSmrg 4914642e01fSmrg for (i = 0; i < count; i++) { 4924642e01fSmrg cf = CFArrayGetValueAtIndex (in, i); 4934642e01fSmrg 4944642e01fSmrg if (CFGetTypeID (cf) == CFArrayGetTypeID ()) 4954642e01fSmrg ns = cfarray_to_nsarray ((CFArrayRef) cf); 4964642e01fSmrg else 4974642e01fSmrg ns = [(id)cf retain]; 4984642e01fSmrg 4994642e01fSmrg [out addObject:ns]; 5004642e01fSmrg [ns release]; 5014642e01fSmrg } 5024642e01fSmrg 5034642e01fSmrg return out; 5044642e01fSmrg} 5054642e01fSmrg 5066747b715Smrg- (CFPropertyListRef) prefs_get_copy:(NSString *)key { 5074642e01fSmrg CFPropertyListRef value; 5084642e01fSmrg 5094642e01fSmrg value = CFPreferencesCopyAppValue ((CFStringRef) key, app_prefs_domain_cfstr); 5104642e01fSmrg 5114642e01fSmrg if (value == NULL) { 5124642e01fSmrg static CFDictionaryRef defaults; 5134642e01fSmrg 5144642e01fSmrg if (defaults == NULL) { 5154642e01fSmrg CFStringRef error = NULL; 5164642e01fSmrg CFDataRef data; 5174642e01fSmrg CFURLRef url; 5184642e01fSmrg SInt32 error_code; 5194642e01fSmrg 5204642e01fSmrg url = (CFURLCreateFromFileSystemRepresentation 5214642e01fSmrg (NULL, (unsigned char *)DEFAULTS_FILE, strlen (DEFAULTS_FILE), false)); 5224642e01fSmrg if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data, 5234642e01fSmrg NULL, NULL, &error_code)) { 5244642e01fSmrg defaults = (CFPropertyListCreateFromXMLData 5254642e01fSmrg (NULL, data, kCFPropertyListMutableContainersAndLeaves, &error)); 5264642e01fSmrg if (error != NULL) CFRelease (error); 5274642e01fSmrg CFRelease (data); 5284642e01fSmrg } 5294642e01fSmrg CFRelease (url); 5304642e01fSmrg 5314642e01fSmrg if (defaults != NULL) { 5324642e01fSmrg NSMutableArray *apps, *elt; 5334642e01fSmrg int count, i; 5344642e01fSmrg NSString *name, *nname; 5354642e01fSmrg 5364642e01fSmrg /* Localize the names in the default apps menu. */ 5374642e01fSmrg 5384642e01fSmrg apps = [(NSDictionary *)defaults objectForKey:@PREFS_APPSMENU]; 5394642e01fSmrg if (apps != nil) { 5404642e01fSmrg count = [apps count]; 5414642e01fSmrg for (i = 0; i < count; i++) { 5424642e01fSmrg elt = [apps objectAtIndex:i]; 5434642e01fSmrg if (elt != nil && [elt isKindOfClass:[NSArray class]]) { 5444642e01fSmrg name = [elt objectAtIndex:0]; 5454642e01fSmrg if (name != nil) { 5464642e01fSmrg nname = NSLocalizedString (name, nil); 5474642e01fSmrg if (nname != nil && nname != name) 5484642e01fSmrg [elt replaceObjectAtIndex:0 withObject:nname]; 5494642e01fSmrg } 5504642e01fSmrg } 5514642e01fSmrg } 5524642e01fSmrg } 5534642e01fSmrg } 5544642e01fSmrg } 5554642e01fSmrg 5564642e01fSmrg if (defaults != NULL) value = CFDictionaryGetValue (defaults, key); 5574642e01fSmrg if (value != NULL) CFRetain (value); 5584642e01fSmrg } 5594642e01fSmrg 5604642e01fSmrg return value; 5614642e01fSmrg} 5624642e01fSmrg 5634642e01fSmrg- (int) prefs_get_integer:(NSString *)key default:(int)def { 5644642e01fSmrg CFPropertyListRef value; 5654642e01fSmrg int ret; 5664642e01fSmrg 5676747b715Smrg value = [self prefs_get_copy:key]; 5684642e01fSmrg 5694642e01fSmrg if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ()) 5704642e01fSmrg CFNumberGetValue (value, kCFNumberIntType, &ret); 5714642e01fSmrg else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) 5724642e01fSmrg ret = CFStringGetIntValue (value); 5734642e01fSmrg else 5744642e01fSmrg ret = def; 5754642e01fSmrg 5764642e01fSmrg if (value != NULL) CFRelease (value); 5774642e01fSmrg 5784642e01fSmrg return ret; 5794642e01fSmrg} 5804642e01fSmrg 5814642e01fSmrg- (const char *) prefs_get_string:(NSString *)key default:(const char *)def { 5824642e01fSmrg CFPropertyListRef value; 5834642e01fSmrg const char *ret = NULL; 5844642e01fSmrg 5856747b715Smrg value = [self prefs_get_copy:key]; 5864642e01fSmrg 5874642e01fSmrg if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { 5884642e01fSmrg NSString *s = (NSString *) value; 5894642e01fSmrg 5904642e01fSmrg ret = [s UTF8String]; 5914642e01fSmrg } 5924642e01fSmrg 5934642e01fSmrg if (value != NULL) CFRelease (value); 5944642e01fSmrg 5954642e01fSmrg return ret != NULL ? ret : def; 5964642e01fSmrg} 5974642e01fSmrg 5986747b715Smrg- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def { 5996747b715Smrg CFPropertyListRef value; 6006747b715Smrg NSURL *ret = NULL; 6016747b715Smrg 6026747b715Smrg value = [self prefs_get_copy:key]; 6036747b715Smrg 6046747b715Smrg if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { 6056747b715Smrg NSString *s = (NSString *) value; 6066747b715Smrg 6076747b715Smrg ret = [NSURL URLWithString:s]; 6086747b715Smrg [ret retain]; 6096747b715Smrg } 6106747b715Smrg 6116747b715Smrg if (value != NULL) CFRelease (value); 6126747b715Smrg 6136747b715Smrg return ret != NULL ? ret : def; 6146747b715Smrg} 6156747b715Smrg 6164642e01fSmrg- (float) prefs_get_float:(NSString *)key default:(float)def { 6174642e01fSmrg CFPropertyListRef value; 6184642e01fSmrg float ret = def; 6194642e01fSmrg 6206747b715Smrg value = [self prefs_get_copy:key]; 6214642e01fSmrg 6224642e01fSmrg if (value != NULL 6234642e01fSmrg && CFGetTypeID (value) == CFNumberGetTypeID () 6244642e01fSmrg && CFNumberIsFloatType (value)) 6254642e01fSmrg CFNumberGetValue (value, kCFNumberFloatType, &ret); 6264642e01fSmrg else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) 6274642e01fSmrg ret = CFStringGetDoubleValue (value); 6284642e01fSmrg 6294642e01fSmrg if (value != NULL) CFRelease (value); 6304642e01fSmrg 6314642e01fSmrg return ret; 6324642e01fSmrg} 6334642e01fSmrg 6344642e01fSmrg- (int) prefs_get_boolean:(NSString *)key default:(int)def { 6354642e01fSmrg CFPropertyListRef value; 6364642e01fSmrg int ret = def; 6374642e01fSmrg 6386747b715Smrg value = [self prefs_get_copy:key]; 6394642e01fSmrg 6404642e01fSmrg if (value != NULL) { 6414642e01fSmrg if (CFGetTypeID (value) == CFNumberGetTypeID ()) 6424642e01fSmrg CFNumberGetValue (value, kCFNumberIntType, &ret); 6434642e01fSmrg else if (CFGetTypeID (value) == CFBooleanGetTypeID ()) 6444642e01fSmrg ret = CFBooleanGetValue (value); 6454642e01fSmrg else if (CFGetTypeID (value) == CFStringGetTypeID ()) { 6464642e01fSmrg const char *tem = [(NSString *) value UTF8String]; 6474642e01fSmrg if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0) 6484642e01fSmrg ret = YES; 6494642e01fSmrg else 6504642e01fSmrg ret = NO; 6514642e01fSmrg } 6524642e01fSmrg 6534642e01fSmrg CFRelease (value); 6544642e01fSmrg } 6554642e01fSmrg return ret; 6564642e01fSmrg} 6574642e01fSmrg 6584642e01fSmrg- (NSArray *) prefs_get_array:(NSString *)key { 6594642e01fSmrg NSArray *ret = nil; 6604642e01fSmrg CFPropertyListRef value; 6614642e01fSmrg 6626747b715Smrg value = [self prefs_get_copy:key]; 6634642e01fSmrg 6644642e01fSmrg if (value != NULL) { 6654642e01fSmrg if (CFGetTypeID (value) == CFArrayGetTypeID ()) 6664642e01fSmrg ret = [cfarray_to_nsarray (value) autorelease]; 6674642e01fSmrg 6684642e01fSmrg CFRelease (value); 6694642e01fSmrg } 6704642e01fSmrg 6714642e01fSmrg return ret; 6724642e01fSmrg} 6734642e01fSmrg 6744642e01fSmrg- (void) prefs_set_integer:(NSString *)key value:(int)value { 6754642e01fSmrg CFNumberRef x; 6764642e01fSmrg 6774642e01fSmrg x = CFNumberCreate (NULL, kCFNumberIntType, &value); 6784642e01fSmrg 6794642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, 6804642e01fSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 6814642e01fSmrg 6824642e01fSmrg CFRelease (x); 6834642e01fSmrg} 6844642e01fSmrg 6854642e01fSmrg- (void) prefs_set_float:(NSString *)key value:(float)value { 6864642e01fSmrg CFNumberRef x; 6874642e01fSmrg 6884642e01fSmrg x = CFNumberCreate (NULL, kCFNumberFloatType, &value); 6894642e01fSmrg 6904642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, 6914642e01fSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 6924642e01fSmrg 6934642e01fSmrg CFRelease (x); 6944642e01fSmrg} 6954642e01fSmrg 6964642e01fSmrg- (void) prefs_set_boolean:(NSString *)key value:(int)value { 6974642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, 6984642e01fSmrg (CFTypeRef) (value ? kCFBooleanTrue 6994642e01fSmrg : kCFBooleanFalse), app_prefs_domain_cfstr, 7004642e01fSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 7014642e01fSmrg 7024642e01fSmrg} 7034642e01fSmrg 7044642e01fSmrg- (void) prefs_set_array:(NSString *)key value:(NSArray *)value { 7054642e01fSmrg CFArrayRef cfarray; 7064642e01fSmrg 7074642e01fSmrg cfarray = nsarray_to_cfarray (value); 7084642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, 7094642e01fSmrg (CFTypeRef) cfarray, 7104642e01fSmrg app_prefs_domain_cfstr, 7114642e01fSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 7124642e01fSmrg CFRelease (cfarray); 7134642e01fSmrg} 7144642e01fSmrg 7154642e01fSmrg- (void) prefs_set_string:(NSString *)key value:(NSString *)value { 7164642e01fSmrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value, 7174642e01fSmrg app_prefs_domain_cfstr, kCFPreferencesCurrentUser, 7184642e01fSmrg kCFPreferencesAnyHost); 7194642e01fSmrg} 7204642e01fSmrg 7214642e01fSmrg- (void) prefs_synchronize { 7224642e01fSmrg CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication); 7234642e01fSmrg} 7244642e01fSmrg 7254642e01fSmrg- (void) read_defaults 7264642e01fSmrg{ 7274642e01fSmrg NSString *nsstr; 7284642e01fSmrg const char *tem; 7294642e01fSmrg 7306747b715Smrg XQuartzRootlessDefault = [self prefs_get_boolean:@PREFS_ROOTLESS 7316747b715Smrg default:XQuartzRootlessDefault]; 7326747b715Smrg XQuartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU 7336747b715Smrg default:XQuartzFullscreenMenu]; 7346747b715Smrg XQuartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS 7356747b715Smrg default:!XQuartzFullscreenDisableHotkeys]; 7364642e01fSmrg darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS 7374642e01fSmrg default:darwinFakeButtons]; 7386747b715Smrg XQuartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT 7396747b715Smrg default:XQuartzOptionSendsAlt]; 7406747b715Smrg 7414642e01fSmrg if (darwinFakeButtons) { 7424642e01fSmrg const char *fake2, *fake3; 7434642e01fSmrg 7444642e01fSmrg fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL]; 7454642e01fSmrg fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL]; 7464642e01fSmrg 7474642e01fSmrg if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList(fake2, TRUE); 7484642e01fSmrg if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList(fake3, TRUE); 7494642e01fSmrg } 7504642e01fSmrg 7514642e01fSmrg tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL]; 7524642e01fSmrg if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE); 7534642e01fSmrg 7544642e01fSmrg tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL]; 7554642e01fSmrg if (tem != NULL) { 7564642e01fSmrg windowItemModMask = DarwinParseModifierList(tem, FALSE); 7574642e01fSmrg } else { 7584642e01fSmrg nsstr = NSLocalizedString (@"window item modifiers", @"window item modifiers"); 7594642e01fSmrg if(nsstr != NULL) { 7604642e01fSmrg tem = [nsstr UTF8String]; 7614642e01fSmrg if((tem != NULL) && strcmp(tem, "window item modifiers")) { 7624642e01fSmrg windowItemModMask = DarwinParseModifierList(tem, FALSE); 7634642e01fSmrg } 7644642e01fSmrg } 7654642e01fSmrg } 7664642e01fSmrg 7676747b715Smrg XQuartzEnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS 7686747b715Smrg default:XQuartzEnableKeyEquivalents]; 7694642e01fSmrg 7704642e01fSmrg darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP 7714642e01fSmrg default:darwinSyncKeymap]; 7724642e01fSmrg 7734642e01fSmrg darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH 7744642e01fSmrg default:darwinDesiredDepth]; 7754642e01fSmrg 7764642e01fSmrg noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS 7774642e01fSmrg default:FALSE]; 7786747b715Smrg 7796747b715Smrg#if XQUARTZ_SPARKLE 7806747b715Smrg NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil]; 7816747b715Smrg if(url) { 7826747b715Smrg [[SUUpdater sharedUpdater] setFeedURL:url]; 7836747b715Smrg [url release]; 7846747b715Smrg } 7856747b715Smrg#endif 7864642e01fSmrg} 7874642e01fSmrg 7884642e01fSmrg/* This will end up at the end of the responder chain. */ 7894642e01fSmrg- (void) copy:sender { 7904642e01fSmrg DarwinSendDDXEvent(kXquartzPasteboardNotify, 1, 7914642e01fSmrg AppleWMCopyToPasteboard); 7924642e01fSmrg} 7934642e01fSmrg 7946747b715Smrg- (X11Controller *) controller { 7956747b715Smrg return _controller; 7966747b715Smrg} 7976747b715Smrg 7984642e01fSmrg- (OSX_BOOL) x_active { 7994642e01fSmrg return _x_active; 8004642e01fSmrg} 8014642e01fSmrg 8024642e01fSmrg@end 8034642e01fSmrg 8044642e01fSmrgstatic NSArray * 8054642e01fSmrgarray_with_strings_and_numbers (int nitems, const char **items, 8064642e01fSmrg const char *numbers) { 8074642e01fSmrg NSMutableArray *array, *subarray; 8084642e01fSmrg NSString *string, *number; 8094642e01fSmrg int i; 8104642e01fSmrg 8114642e01fSmrg /* (Can't autorelease on the X server thread) */ 8124642e01fSmrg 8134642e01fSmrg array = [[NSMutableArray alloc] initWithCapacity:nitems]; 8144642e01fSmrg 8154642e01fSmrg for (i = 0; i < nitems; i++) { 8164642e01fSmrg subarray = [[NSMutableArray alloc] initWithCapacity:2]; 8174642e01fSmrg 8184642e01fSmrg string = [[NSString alloc] initWithUTF8String:items[i]]; 8194642e01fSmrg [subarray addObject:string]; 8204642e01fSmrg [string release]; 8214642e01fSmrg 8224642e01fSmrg if (numbers[i] != 0) { 8234642e01fSmrg number = [[NSString alloc] initWithFormat:@"%d", numbers[i]]; 8244642e01fSmrg [subarray addObject:number]; 8254642e01fSmrg [number release]; 8264642e01fSmrg } else 8274642e01fSmrg [subarray addObject:@""]; 8284642e01fSmrg 8294642e01fSmrg [array addObject:subarray]; 8304642e01fSmrg [subarray release]; 8314642e01fSmrg } 8324642e01fSmrg 8334642e01fSmrg return array; 8344642e01fSmrg} 8354642e01fSmrg 8364642e01fSmrgvoid X11ApplicationSetWindowMenu (int nitems, const char **items, 8374642e01fSmrg const char *shortcuts) { 8384642e01fSmrg NSArray *array; 8394642e01fSmrg array = array_with_strings_and_numbers (nitems, items, shortcuts); 8404642e01fSmrg 8414642e01fSmrg /* Send the array of strings over to the appkit thread */ 8424642e01fSmrg 8434642e01fSmrg message_kit_thread (@selector (set_window_menu:), array); 8444642e01fSmrg [array release]; 8454642e01fSmrg} 8464642e01fSmrg 8474642e01fSmrgvoid X11ApplicationSetWindowMenuCheck (int idx) { 8484642e01fSmrg NSNumber *n; 8494642e01fSmrg 8504642e01fSmrg n = [[NSNumber alloc] initWithInt:idx]; 8514642e01fSmrg 8524642e01fSmrg message_kit_thread (@selector (set_window_menu_check:), n); 8534642e01fSmrg 8544642e01fSmrg [n release]; 8554642e01fSmrg} 8564642e01fSmrg 8574642e01fSmrgvoid X11ApplicationSetFrontProcess (void) { 8584642e01fSmrg message_kit_thread (@selector (set_front_process:), nil); 8594642e01fSmrg} 8604642e01fSmrg 8614642e01fSmrgvoid X11ApplicationSetCanQuit (int state) { 8624642e01fSmrg NSNumber *n; 8634642e01fSmrg 8644642e01fSmrg n = [[NSNumber alloc] initWithBool:state]; 8654642e01fSmrg 8664642e01fSmrg message_kit_thread (@selector (set_can_quit:), n); 8674642e01fSmrg 8684642e01fSmrg [n release]; 8694642e01fSmrg} 8704642e01fSmrg 8714642e01fSmrgvoid X11ApplicationServerReady (void) { 8724642e01fSmrg message_kit_thread (@selector (server_ready:), nil); 8734642e01fSmrg} 8744642e01fSmrg 8754642e01fSmrgvoid X11ApplicationShowHideMenubar (int state) { 8764642e01fSmrg NSNumber *n; 8774642e01fSmrg 8784642e01fSmrg n = [[NSNumber alloc] initWithBool:state]; 8794642e01fSmrg 8804642e01fSmrg message_kit_thread (@selector (show_hide_menubar:), n); 8814642e01fSmrg 8824642e01fSmrg [n release]; 8834642e01fSmrg} 8844642e01fSmrg 8856747b715Smrgvoid X11ApplicationLaunchClient (const char *cmd) { 8866747b715Smrg NSString *string; 8876747b715Smrg 8886747b715Smrg string = [[NSString alloc] initWithUTF8String:cmd]; 8896747b715Smrg 8906747b715Smrg message_kit_thread (@selector (launch_client:), string); 8916747b715Smrg 8926747b715Smrg [string release]; 8936747b715Smrg} 8946747b715Smrg 8958223e2f2Smrg/* This is a special function in that it is run from the *SERVER* thread and 8968223e2f2Smrg * not the AppKit thread. We want to block entering a screen-capturing RandR 8978223e2f2Smrg * mode until we notify the user about how to get out if the X11 client crashes. 8988223e2f2Smrg */ 8998223e2f2SmrgBool X11ApplicationCanEnterRandR(void) { 9008223e2f2Smrg NSString *title, *msg; 9018223e2f2Smrg 9028223e2f2Smrg if([X11App prefs_get_boolean:@PREFS_NO_RANDR_ALERT default:NO] || XQuartzShieldingWindowLevel != 0) 9038223e2f2Smrg return TRUE; 9048223e2f2Smrg 9058223e2f2Smrg title = NSLocalizedString(@"Enter RandR mode?", @"Dialog title when switching to RandR"); 9068223e2f2Smrg msg = NSLocalizedString(@"An application has requested X11 to change the resolution of your display. X11 will restore the display to its previous state when the requesting application requests to return to the previous state. Alternatively, you can use the ⌥⌘A key sequence to force X11 to return to the previous state.", 9078223e2f2Smrg @"Dialog when switching to RandR"); 9088223e2f2Smrg 9098223e2f2Smrg if(!XQuartzIsRootless) 9108223e2f2Smrg QuartzShowFullscreen(FALSE); 9118223e2f2Smrg 9128223e2f2Smrg switch(NSRunAlertPanel(title, msg, NSLocalizedString(@"Allow", @""), NSLocalizedString (@"Cancel", @""), NSLocalizedString (@"Always Allow", @""))) { 9138223e2f2Smrg case NSAlertOtherReturn: 9148223e2f2Smrg [X11App prefs_set_boolean:@PREFS_NO_RANDR_ALERT value:YES]; 9158223e2f2Smrg [X11App prefs_synchronize]; 9168223e2f2Smrg case NSAlertDefaultReturn: 9178223e2f2Smrg return YES; 9188223e2f2Smrg 9198223e2f2Smrg default: 9208223e2f2Smrg return NO; 9218223e2f2Smrg } 9228223e2f2Smrg} 9238223e2f2Smrg 9244642e01fSmrgstatic void check_xinitrc (void) { 9254642e01fSmrg char *tem, buf[1024]; 9264642e01fSmrg NSString *msg; 9274642e01fSmrg 9284642e01fSmrg if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO]) 9294642e01fSmrg return; 9304642e01fSmrg 9314642e01fSmrg tem = getenv ("HOME"); 9324642e01fSmrg if (tem == NULL) goto done; 9334642e01fSmrg 9344642e01fSmrg snprintf (buf, sizeof (buf), "%s/.xinitrc", tem); 9354642e01fSmrg if (access (buf, F_OK) != 0) 9364642e01fSmrg goto done; 9374642e01fSmrg 9384642e01fSmrg msg = NSLocalizedString (@"You have an existing ~/.xinitrc file.\n\n\ 9394642e01fSmrgWindows displayed by X11 applications may not have titlebars, or may look \ 9404642e01fSmrgdifferent to windows displayed by native applications.\n\n\ 9414642e01fSmrgWould you like to move aside the existing file and use the standard X11 \ 9424642e01fSmrgenvironment the next time you start X11?", @"Startup xinitrc dialog"); 9434642e01fSmrg 9444642e01fSmrg if(NSAlertDefaultReturn == NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""), 9454642e01fSmrg NSLocalizedString (@"No", @""), nil)) { 9464642e01fSmrg char buf2[1024]; 9474642e01fSmrg int i = -1; 9484642e01fSmrg 9494642e01fSmrg snprintf (buf2, sizeof (buf2), "%s.old", buf); 9504642e01fSmrg 9514642e01fSmrg for(i = 1; access (buf2, F_OK) == 0; i++) 9524642e01fSmrg snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i); 9534642e01fSmrg 9544642e01fSmrg rename (buf, buf2); 9554642e01fSmrg } 9564642e01fSmrg 9574642e01fSmrg done: 9584642e01fSmrg [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES]; 9594642e01fSmrg [X11App prefs_synchronize]; 9604642e01fSmrg} 9614642e01fSmrg 9629ace9065Smrgstatic inline pthread_t create_thread(void *(*func)(void *), void *arg) { 9636747b715Smrg pthread_attr_t attr; 9646747b715Smrg pthread_t tid; 9656747b715Smrg 9666747b715Smrg pthread_attr_init(&attr); 9676747b715Smrg pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 9686747b715Smrg pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 9696747b715Smrg pthread_create(&tid, &attr, func, arg); 9706747b715Smrg pthread_attr_destroy(&attr); 9716747b715Smrg 9726747b715Smrg return tid; 9736747b715Smrg} 9746747b715Smrg 9756747b715Smrgstatic void *xpbproxy_x_thread(void *args) { 9766747b715Smrg xpbproxy_run(); 9776747b715Smrg 9786747b715Smrg fprintf(stderr, "xpbproxy thread is terminating unexpectedly.\n"); 9796747b715Smrg return NULL; 9806747b715Smrg} 9816747b715Smrg 9824642e01fSmrgvoid X11ApplicationMain (int argc, char **argv, char **envp) { 9834642e01fSmrg NSAutoreleasePool *pool; 9844642e01fSmrg 9854642e01fSmrg#ifdef DEBUG 9864642e01fSmrg while (access ("/tmp/x11-block", F_OK) == 0) sleep (1); 9874642e01fSmrg#endif 9884642e01fSmrg 9894642e01fSmrg pool = [[NSAutoreleasePool alloc] init]; 9904642e01fSmrg X11App = (X11Application *) [X11Application sharedApplication]; 9914642e01fSmrg init_ports (); 9924642e01fSmrg 9934642e01fSmrg app_prefs_domain_cfstr = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]; 9944642e01fSmrg 9954642e01fSmrg [NSApp read_defaults]; 9964642e01fSmrg [NSBundle loadNibNamed:@"main" owner:NSApp]; 9974642e01fSmrg [[NSNotificationCenter defaultCenter] addObserver:NSApp 9984642e01fSmrg selector:@selector (became_key:) 9994642e01fSmrg name:NSWindowDidBecomeKeyNotification object:nil]; 10004642e01fSmrg 10014642e01fSmrg /* 10024642e01fSmrg * The xpr Quartz mode is statically linked into this server. 10034642e01fSmrg * Initialize all the Quartz functions. 10044642e01fSmrg */ 10054642e01fSmrg QuartzModeBundleInit(); 10064642e01fSmrg 10074642e01fSmrg /* Calculate the height of the menubar so we can avoid it. */ 10084642e01fSmrg aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - 10094642e01fSmrg NSMaxY([[NSScreen mainScreen] visibleFrame]); 10104642e01fSmrg 10114642e01fSmrg /* Set the key layout seed before we start the server */ 10124642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 10134642e01fSmrg last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); 10144642e01fSmrg 10154642e01fSmrg if(!last_key_layout) 10164642e01fSmrg fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); 10174642e01fSmrg#else 10184642e01fSmrg KLGetCurrentKeyboardLayout(&last_key_layout); 10194642e01fSmrg if(!last_key_layout) 10204642e01fSmrg fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n"); 10214642e01fSmrg#endif 10224642e01fSmrg 10236747b715Smrg if (!QuartsResyncKeymap(FALSE)) { 10244642e01fSmrg fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n"); 10254642e01fSmrg } 10264642e01fSmrg 10274642e01fSmrg /* Tell the server thread that it can proceed */ 10284642e01fSmrg QuartzInitServer(argc, argv, envp); 10294642e01fSmrg 10304642e01fSmrg /* This must be done after QuartzInitServer because it can result in 10314642e01fSmrg * an mieqEnqueue() - <rdar://problem/6300249> 10324642e01fSmrg */ 10334642e01fSmrg check_xinitrc(); 10344642e01fSmrg 10356747b715Smrg create_thread(xpbproxy_x_thread, NULL); 10366747b715Smrg 10376747b715Smrg#if XQUARTZ_SPARKLE 10386747b715Smrg [[X11App controller] setup_sparkle]; 10396747b715Smrg [[SUUpdater sharedUpdater] resetUpdateCycle]; 10406747b715Smrg// [[SUUpdater sharedUpdater] checkForUpdates:X11App]; 10416747b715Smrg#endif 10426747b715Smrg 10436747b715Smrg [pool release]; 10444642e01fSmrg [NSApp run]; 10454642e01fSmrg /* not reached */ 10464642e01fSmrg} 10474642e01fSmrg 10484642e01fSmrg@implementation X11Application (Private) 10494642e01fSmrg 10504642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK 10514642e01fSmrg/* This is to workaround a bug in the VNC server where we sometimes see the L 10524642e01fSmrg * modifier and sometimes see no "side" 10534642e01fSmrg */ 10544642e01fSmrgstatic inline int ensure_flag(int flags, int device_independent, int device_dependents, int device_dependent_default) { 10554642e01fSmrg if( (flags & device_independent) && 10564642e01fSmrg !(flags & device_dependents)) 10574642e01fSmrg flags |= device_dependent_default; 10584642e01fSmrg return flags; 10594642e01fSmrg} 10604642e01fSmrg#endif 10614642e01fSmrg 10629ace9065Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 10639ace9065Smrgstatic const char *untrusted_str(NSEvent *e) { 10649ace9065Smrg switch([e type]) { 10659ace9065Smrg case NSScrollWheel: 10669ace9065Smrg return "NSScrollWheel"; 10679ace9065Smrg case NSTabletPoint: 10689ace9065Smrg return "NSTabletPoint"; 10699ace9065Smrg case NSOtherMouseDown: 10709ace9065Smrg return "NSOtherMouseDown"; 10719ace9065Smrg case NSOtherMouseUp: 10729ace9065Smrg return "NSOtherMouseUp"; 10739ace9065Smrg case NSLeftMouseDown: 10749ace9065Smrg return "NSLeftMouseDown"; 10759ace9065Smrg case NSLeftMouseUp: 10769ace9065Smrg return "NSLeftMouseUp"; 10779ace9065Smrg default: 10789ace9065Smrg switch([e subtype]) { 10799ace9065Smrg case NSTabletPointEventSubtype: 10809ace9065Smrg return "NSTabletPointEventSubtype"; 10819ace9065Smrg case NSTabletProximityEventSubtype: 10829ace9065Smrg return "NSTabletProximityEventSubtype"; 10839ace9065Smrg default: 10849ace9065Smrg return "Other"; 10859ace9065Smrg } 10869ace9065Smrg } 10879ace9065Smrg} 10889ace9065Smrg#endif 10899ace9065Smrg 10904642e01fSmrg- (void) sendX11NSEvent:(NSEvent *)e { 10916747b715Smrg NSPoint location = NSZeroPoint, tilt = NSZeroPoint; 10924642e01fSmrg int ev_button, ev_type; 10936747b715Smrg float pressure = 0.0; 10944642e01fSmrg DeviceIntPtr pDev; 10954642e01fSmrg int modifierFlags; 10966747b715Smrg BOOL isMouseOrTabletEvent, isTabletEvent; 10974642e01fSmrg 10986747b715Smrg isMouseOrTabletEvent = [e type] == NSLeftMouseDown || [e type] == NSOtherMouseDown || [e type] == NSRightMouseDown || 10996747b715Smrg [e type] == NSLeftMouseUp || [e type] == NSOtherMouseUp || [e type] == NSRightMouseUp || 11006747b715Smrg [e type] == NSLeftMouseDragged || [e type] == NSOtherMouseDragged || [e type] == NSRightMouseDragged || 11016747b715Smrg [e type] == NSMouseMoved || [e type] == NSTabletPoint || [e type] == NSScrollWheel; 11024642e01fSmrg 11036747b715Smrg isTabletEvent = ([e type] == NSTabletPoint) || 11046747b715Smrg (isMouseOrTabletEvent && ([e subtype] == NSTabletPointEventSubtype || [e subtype] == NSTabletProximityEventSubtype)); 11054642e01fSmrg 11066747b715Smrg if(isMouseOrTabletEvent) { 11076747b715Smrg static NSPoint lastpt; 11086747b715Smrg NSWindow *window = [e window]; 11096747b715Smrg NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame]; 11106747b715Smrg BOOL hasUntrustedPointerDelta; 11116747b715Smrg 11126747b715Smrg // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that 11136747b715Smrg // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets 11146747b715Smrg // are not normally used in cases where that bug would present itself, so this is a fair tradeoff 11156747b715Smrg // <rdar://problem/7111003> deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype 11166747b715Smrg // http://xquartz.macosforge.org/trac/ticket/288 11176747b715Smrg hasUntrustedPointerDelta = isTabletEvent; 11186747b715Smrg 11196747b715Smrg // The deltaXY for middle click events also appear erroneous after fast user switching 11206747b715Smrg // <rdar://problem/7979468> deltaX and deltaY are incorrect for NSOtherMouseDown and NSOtherMouseUp after FUS 11216747b715Smrg // http://xquartz.macosforge.org/trac/ticket/389 11226747b715Smrg hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSOtherMouseDown || [e type] == NSOtherMouseUp; 11236747b715Smrg 11246747b715Smrg // The deltaXY for scroll events correspond to the scroll delta, not the pointer delta 11256747b715Smrg // <rdar://problem/7989690> deltaXY for wheel events are being sent as mouse movement 11266747b715Smrg hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSScrollWheel; 11279ace9065Smrg 11289ace9065Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 11299ace9065Smrg hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSLeftMouseDown || [e type] == NSLeftMouseUp; 11309ace9065Smrg#endif 11316747b715Smrg 11326747b715Smrg if (window != nil) { 11336747b715Smrg NSRect frame = [window frame]; 11346747b715Smrg location = [e locationInWindow]; 11356747b715Smrg location.x += frame.origin.x; 11366747b715Smrg location.y += frame.origin.y; 11376747b715Smrg lastpt = location; 11386747b715Smrg } else if(hasUntrustedPointerDelta) { 11399ace9065Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 11409ace9065Smrg ErrorF("--- Begin Event Debug ---\n"); 11419ace9065Smrg ErrorF("Event type: %s\n", untrusted_str(e)); 11429ace9065Smrg ErrorF("old lastpt: (%0.2f, %0.2f)\n", lastpt.x, lastpt.y); 11439ace9065Smrg ErrorF(" delta: (%0.2f, %0.2f)\n", [e deltaX], -[e deltaY]); 11449ace9065Smrg ErrorF(" location: (%0.2f, %0.2f)\n", lastpt.x + [e deltaX], lastpt.y - [e deltaY]); 11459ace9065Smrg ErrorF("workaround: (%0.2f, %0.2f)\n", [e locationInWindow].x, [e locationInWindow].y); 11469ace9065Smrg ErrorF("--- End Event Debug ---\n"); 11479ace9065Smrg 11489ace9065Smrg location.x = lastpt.x + [e deltaX]; 11499ace9065Smrg location.y = lastpt.y - [e deltaY]; 11509ace9065Smrg lastpt = [e locationInWindow]; 11519ace9065Smrg#else 11526747b715Smrg location = [e locationInWindow]; 11536747b715Smrg lastpt = location; 11549ace9065Smrg#endif 11556747b715Smrg } else { 11566747b715Smrg location.x = lastpt.x + [e deltaX]; 11576747b715Smrg location.y = lastpt.y - [e deltaY]; 11586747b715Smrg lastpt = [e locationInWindow]; 11596747b715Smrg } 11606747b715Smrg 11616747b715Smrg /* Convert coordinate system */ 11626747b715Smrg location.y = (screen.origin.y + screen.size.height) - location.y; 11636747b715Smrg } 11644642e01fSmrg 11654642e01fSmrg modifierFlags = [e modifierFlags]; 11664642e01fSmrg 11674642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK 11684642e01fSmrg /* This is to workaround a bug in the VNC server where we sometimes see the L 11694642e01fSmrg * modifier and sometimes see no "side" 11704642e01fSmrg */ 11714642e01fSmrg modifierFlags = ensure_flag(modifierFlags, NX_CONTROLMASK, NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK, NX_DEVICELCTLKEYMASK); 11724642e01fSmrg modifierFlags = ensure_flag(modifierFlags, NX_SHIFTMASK, NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK, NX_DEVICELSHIFTKEYMASK); 11734642e01fSmrg modifierFlags = ensure_flag(modifierFlags, NX_COMMANDMASK, NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK, NX_DEVICELCMDKEYMASK); 11744642e01fSmrg modifierFlags = ensure_flag(modifierFlags, NX_ALTERNATEMASK, NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK, NX_DEVICELALTKEYMASK); 11754642e01fSmrg#endif 11764642e01fSmrg 11776747b715Smrg modifierFlags &= darwin_all_modifier_mask; 11784642e01fSmrg 11794642e01fSmrg /* We don't receive modifier key events while out of focus, and 3button 11804642e01fSmrg * emulation mucks this up, so we need to check our modifier flag state 11814642e01fSmrg * on every event... ugg 11824642e01fSmrg */ 11834642e01fSmrg 11846747b715Smrg if(darwin_all_modifier_flags != modifierFlags) 11854642e01fSmrg DarwinUpdateModKeys(modifierFlags); 11864642e01fSmrg 11874642e01fSmrg switch ([e type]) { 11884642e01fSmrg case NSLeftMouseDown: ev_button=1; ev_type=ButtonPress; goto handle_mouse; 11894642e01fSmrg case NSOtherMouseDown: ev_button=2; ev_type=ButtonPress; goto handle_mouse; 11904642e01fSmrg case NSRightMouseDown: ev_button=3; ev_type=ButtonPress; goto handle_mouse; 11914642e01fSmrg case NSLeftMouseUp: ev_button=1; ev_type=ButtonRelease; goto handle_mouse; 11924642e01fSmrg case NSOtherMouseUp: ev_button=2; ev_type=ButtonRelease; goto handle_mouse; 11934642e01fSmrg case NSRightMouseUp: ev_button=3; ev_type=ButtonRelease; goto handle_mouse; 11944642e01fSmrg case NSLeftMouseDragged: ev_button=1; ev_type=MotionNotify; goto handle_mouse; 11954642e01fSmrg case NSOtherMouseDragged: ev_button=2; ev_type=MotionNotify; goto handle_mouse; 11964642e01fSmrg case NSRightMouseDragged: ev_button=3; ev_type=MotionNotify; goto handle_mouse; 11974642e01fSmrg case NSMouseMoved: ev_button=0; ev_type=MotionNotify; goto handle_mouse; 11984642e01fSmrg case NSTabletPoint: ev_button=0; ev_type=MotionNotify; goto handle_mouse; 11994642e01fSmrg 12004642e01fSmrg handle_mouse: 12014642e01fSmrg pDev = darwinPointer; 12024642e01fSmrg 12034642e01fSmrg /* NSTabletPoint can have no subtype */ 12044642e01fSmrg if([e type] != NSTabletPoint && 12054642e01fSmrg [e subtype] == NSTabletProximityEventSubtype) { 12064642e01fSmrg switch([e pointingDeviceType]) { 12074642e01fSmrg case NSEraserPointingDevice: 12084642e01fSmrg darwinTabletCurrent=darwinTabletEraser; 12094642e01fSmrg break; 12104642e01fSmrg case NSPenPointingDevice: 12114642e01fSmrg darwinTabletCurrent=darwinTabletStylus; 12124642e01fSmrg break; 12134642e01fSmrg case NSCursorPointingDevice: 12144642e01fSmrg case NSUnknownPointingDevice: 12154642e01fSmrg default: 12164642e01fSmrg darwinTabletCurrent=darwinTabletCursor; 12174642e01fSmrg break; 12184642e01fSmrg } 12194642e01fSmrg 12204642e01fSmrg /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt 12214642e01fSmrg * So we just pretend the motion was caused by the mouse. Hopefully 12224642e01fSmrg * we'll have a better solution for this in the future (like maybe 12234642e01fSmrg * NSTabletProximityEventSubtype will come from NSTabletPoint 12244642e01fSmrg * rather than NSMouseMoved. 12254642e01fSmrg pressure = [e pressure]; 12266747b715Smrg tilt = [e tilt]; 12274642e01fSmrg pDev = darwinTabletCurrent; 12284642e01fSmrg */ 12294642e01fSmrg 12306747b715Smrg DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, 12316747b715Smrg location.x, location.y); 12324642e01fSmrg } 12334642e01fSmrg 12344642e01fSmrg if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) { 12354642e01fSmrg pressure = [e pressure]; 12366747b715Smrg tilt = [e tilt]; 12374642e01fSmrg 12384642e01fSmrg pDev = darwinTabletCurrent; 12394642e01fSmrg } 12404642e01fSmrg 12416747b715Smrg if(!XQuartzServerVisible && noTestExtensions) { 12426747b715Smrg#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0 12434642e01fSmrg/* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */ 12446747b715Smrg xp_window_id wid = 0; 12456747b715Smrg xp_error e; 12464642e01fSmrg 12474642e01fSmrg /* Sigh. Need to check that we're really over one of 12484642e01fSmrg * our windows. (We need to receive pointer events while 12494642e01fSmrg * not in the foreground, but we don't want to receive them 12504642e01fSmrg * when another window is over us or we might show a tooltip) 12514642e01fSmrg */ 12526747b715Smrg 12536747b715Smrg e = xp_find_window(location.x, location.y, 0, &wid); 12546747b715Smrg 12556747b715Smrg if (e != XP_Success || (e == XP_Success && wid == 0)) 12564642e01fSmrg#endif 12576747b715Smrg { 12586747b715Smrg bgMouseLocation = location; 12596747b715Smrg bgMouseLocationUpdated = TRUE; 12606747b715Smrg return; 12616747b715Smrg } 12626747b715Smrg } 12634642e01fSmrg 12646747b715Smrg if(bgMouseLocationUpdated) { 12656747b715Smrg if(!(ev_type == MotionNotify && ev_button == 0)) { 12666747b715Smrg DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x, 12676747b715Smrg location.y, pressure, tilt.x, tilt.y); 12686747b715Smrg } 12696747b715Smrg bgMouseLocationUpdated = FALSE; 12706747b715Smrg } 12716747b715Smrg 12726747b715Smrg DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x, location.y, 12736747b715Smrg pressure, tilt.x, tilt.y); 12744642e01fSmrg 12754642e01fSmrg break; 12764642e01fSmrg 12774642e01fSmrg case NSTabletProximity: 12784642e01fSmrg switch([e pointingDeviceType]) { 12794642e01fSmrg case NSEraserPointingDevice: 12804642e01fSmrg darwinTabletCurrent=darwinTabletEraser; 12814642e01fSmrg break; 12824642e01fSmrg case NSPenPointingDevice: 12834642e01fSmrg darwinTabletCurrent=darwinTabletStylus; 12844642e01fSmrg break; 12854642e01fSmrg case NSCursorPointingDevice: 12864642e01fSmrg case NSUnknownPointingDevice: 12874642e01fSmrg default: 12884642e01fSmrg darwinTabletCurrent=darwinTabletCursor; 12894642e01fSmrg break; 12904642e01fSmrg } 12914642e01fSmrg 12926747b715Smrg DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, 12936747b715Smrg location.x, location.y); 12944642e01fSmrg break; 12954642e01fSmrg 12964642e01fSmrg case NSScrollWheel: 12976747b715Smrg#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0 12986747b715Smrg /* If we're in the background, we need to send a MotionNotify event 12996747b715Smrg * first, since we aren't getting them on background mouse motion 13006747b715Smrg */ 13016747b715Smrg if(!XQuartzServerVisible && noTestExtensions) { 13026747b715Smrg bgMouseLocationUpdated = FALSE; 13036747b715Smrg DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, location.x, 13046747b715Smrg location.y, pressure, tilt.x, tilt.y); 13056747b715Smrg } 13066747b715Smrg#endif 13076747b715Smrg DarwinSendScrollEvents([e deltaX], [e deltaY], location.x, location.y, 13086747b715Smrg pressure, tilt.x, tilt.y); 13094642e01fSmrg break; 13104642e01fSmrg 13114642e01fSmrg case NSKeyDown: case NSKeyUp: 13126747b715Smrg { 13136747b715Smrg /* XKB clobbers our keymap at startup, so we need to force it on the first keypress. 13146747b715Smrg * TODO: Make this less of a kludge. 13156747b715Smrg */ 13166747b715Smrg static int force_resync_keymap = YES; 13176747b715Smrg if(force_resync_keymap) { 13186747b715Smrg DarwinSendDDXEvent(kXquartzReloadKeymap, 0); 13196747b715Smrg force_resync_keymap = NO; 13206747b715Smrg } 13216747b715Smrg } 13226747b715Smrg 13234642e01fSmrg if(darwinSyncKeymap) { 13244642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 13254642e01fSmrg TISInputSourceRef key_layout = TISCopyCurrentKeyboardLayoutInputSource(); 13264642e01fSmrg TISInputSourceRef clear; 13274642e01fSmrg if (CFEqual(key_layout, last_key_layout)) { 13284642e01fSmrg CFRelease(key_layout); 13294642e01fSmrg } else { 13304642e01fSmrg /* Swap/free thread-safely */ 13314642e01fSmrg clear = last_key_layout; 13324642e01fSmrg last_key_layout = key_layout; 13334642e01fSmrg CFRelease(clear); 13344642e01fSmrg#else 13354642e01fSmrg KeyboardLayoutRef key_layout; 13364642e01fSmrg KLGetCurrentKeyboardLayout(&key_layout); 13374642e01fSmrg if(key_layout != last_key_layout) { 13384642e01fSmrg last_key_layout = key_layout; 13394642e01fSmrg#endif 13404642e01fSmrg /* Update keyInfo */ 13416747b715Smrg if (!QuartsResyncKeymap(TRUE)) { 13424642e01fSmrg fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n"); 13434642e01fSmrg } 13444642e01fSmrg } 13454642e01fSmrg } 13464642e01fSmrg 13474642e01fSmrg /* Avoid stuck keys on context switch */ 13484642e01fSmrg if(keyState[[e keyCode]] == [e type]) 13494642e01fSmrg return; 13504642e01fSmrg keyState[[e keyCode]] = [e type]; 13514642e01fSmrg 13524642e01fSmrg DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]); 13534642e01fSmrg break; 13544642e01fSmrg 13554642e01fSmrg default: break; /* for gcc */ 13564642e01fSmrg } 13574642e01fSmrg} 13584642e01fSmrg@end 1359