1706f2543Smrg/* X11Application.m -- subclass of NSApplication to multiplex events 2706f2543Smrg 3706f2543Smrg Copyright (c) 2002-2008 Apple Inc. 4706f2543Smrg 5706f2543Smrg Permission is hereby granted, free of charge, to any person 6706f2543Smrg obtaining a copy of this software and associated documentation files 7706f2543Smrg (the "Software"), to deal in the Software without restriction, 8706f2543Smrg including without limitation the rights to use, copy, modify, merge, 9706f2543Smrg publish, distribute, sublicense, and/or sell copies of the Software, 10706f2543Smrg and to permit persons to whom the Software is furnished to do so, 11706f2543Smrg subject to the following conditions: 12706f2543Smrg 13706f2543Smrg The above copyright notice and this permission notice shall be 14706f2543Smrg included in all copies or substantial portions of the Software. 15706f2543Smrg 16706f2543Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17706f2543Smrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18706f2543Smrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19706f2543Smrg NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT 20706f2543Smrg HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21706f2543Smrg WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22706f2543Smrg OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23706f2543Smrg DEALINGS IN THE SOFTWARE. 24706f2543Smrg 25706f2543Smrg Except as contained in this notice, the name(s) of the above 26706f2543Smrg copyright holders shall not be used in advertising or otherwise to 27706f2543Smrg promote the sale, use or other dealings in this Software without 28706f2543Smrg prior written authorization. */ 29706f2543Smrg 30706f2543Smrg#include "sanitizedCarbon.h" 31706f2543Smrg 32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 33706f2543Smrg#include <dix-config.h> 34706f2543Smrg#endif 35706f2543Smrg 36706f2543Smrg#include "quartzCommon.h" 37706f2543Smrg 38706f2543Smrg#import "X11Application.h" 39706f2543Smrg 40706f2543Smrg#include "darwin.h" 41706f2543Smrg#include "quartz.h" 42706f2543Smrg#include "darwinEvents.h" 43706f2543Smrg#include "quartzKeyboard.h" 44706f2543Smrg#include "quartz.h" 45706f2543Smrg#include <X11/extensions/applewmconst.h> 46706f2543Smrg#include "micmap.h" 47706f2543Smrg#include "exglobals.h" 48706f2543Smrg 49706f2543Smrg#include <mach/mach.h> 50706f2543Smrg#include <unistd.h> 51706f2543Smrg#include <AvailabilityMacros.h> 52706f2543Smrg 53706f2543Smrg#include <pthread.h> 54706f2543Smrg 55706f2543Smrg#include <Xplugin.h> 56706f2543Smrg 57706f2543Smrg// pbproxy/pbproxy.h 58706f2543Smrgextern int xpbproxy_run (void); 59706f2543Smrg 60706f2543Smrg#define DEFAULTS_FILE X11LIBDIR"/X11/xserver/Xquartz.plist" 61706f2543Smrg 62706f2543Smrg#ifndef XSERVER_VERSION 63706f2543Smrg#define XSERVER_VERSION "?" 64706f2543Smrg#endif 65706f2543Smrg 66706f2543Smrg/* Stuck modifier / button state... force release when we context switch */ 67706f2543Smrgstatic NSEventType keyState[NUM_KEYCODES]; 68706f2543Smrg 69706f2543Smrgextern Bool noTestExtensions; 70706f2543Smrg 71706f2543Smrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 72706f2543Smrgstatic TISInputSourceRef last_key_layout; 73706f2543Smrg#else 74706f2543Smrgstatic KeyboardLayoutRef last_key_layout; 75706f2543Smrg#endif 76706f2543Smrg 77706f2543Smrg/* This preference is only tested on Lion or later as it's not relevant to 78706f2543Smrg * earlier OS versions. 79706f2543Smrg */ 80706f2543SmrgBool XQuartzScrollInDeviceDirection = FALSE; 81706f2543Smrg 82706f2543Smrgextern int darwinFakeButtons; 83706f2543Smrg 84706f2543Smrg/* Store the mouse location while in the background, and update X11's pointer 85706f2543Smrg * location when we become the foreground application 86706f2543Smrg */ 87706f2543Smrgstatic NSPoint bgMouseLocation; 88706f2543Smrgstatic BOOL bgMouseLocationUpdated = FALSE; 89706f2543Smrg 90706f2543SmrgX11Application *X11App; 91706f2543Smrg 92706f2543SmrgCFStringRef app_prefs_domain_cfstr = NULL; 93706f2543Smrg 94706f2543Smrg#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask) 95706f2543Smrg 96706f2543Smrg@interface X11Application (Private) 97706f2543Smrg- (void) sendX11NSEvent:(NSEvent *)e; 98706f2543Smrg@end 99706f2543Smrg 100706f2543Smrg@implementation X11Application 101706f2543Smrg 102706f2543Smrgtypedef struct message_struct message; 103706f2543Smrgstruct message_struct { 104706f2543Smrg mach_msg_header_t hdr; 105706f2543Smrg SEL selector; 106706f2543Smrg NSObject *arg; 107706f2543Smrg}; 108706f2543Smrg 109706f2543Smrgstatic mach_port_t _port; 110706f2543Smrg 111706f2543Smrg/* Quartz mode initialization routine. This is often dynamically loaded 112706f2543Smrg but is statically linked into this X server. */ 113706f2543SmrgBool QuartzModeBundleInit(void); 114706f2543Smrg 115706f2543Smrgstatic void init_ports (void) { 116706f2543Smrg kern_return_t r; 117706f2543Smrg NSPort *p; 118706f2543Smrg 119706f2543Smrg if (_port != MACH_PORT_NULL) return; 120706f2543Smrg 121706f2543Smrg r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port); 122706f2543Smrg if (r != KERN_SUCCESS) return; 123706f2543Smrg 124706f2543Smrg p = [NSMachPort portWithMachPort:_port]; 125706f2543Smrg [p setDelegate:NSApp]; 126706f2543Smrg [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 127706f2543Smrg} 128706f2543Smrg 129706f2543Smrgstatic void message_kit_thread (SEL selector, NSObject *arg) { 130706f2543Smrg message msg; 131706f2543Smrg kern_return_t r; 132706f2543Smrg 133706f2543Smrg msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0); 134706f2543Smrg msg.hdr.msgh_size = sizeof (msg); 135706f2543Smrg msg.hdr.msgh_remote_port = _port; 136706f2543Smrg msg.hdr.msgh_local_port = MACH_PORT_NULL; 137706f2543Smrg msg.hdr.msgh_reserved = 0; 138706f2543Smrg msg.hdr.msgh_id = 0; 139706f2543Smrg 140706f2543Smrg msg.selector = selector; 141706f2543Smrg msg.arg = [arg retain]; 142706f2543Smrg 143706f2543Smrg r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size, 144706f2543Smrg 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); 145706f2543Smrg if (r != KERN_SUCCESS) 146706f2543Smrg ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r); 147706f2543Smrg} 148706f2543Smrg 149706f2543Smrg- (void) handleMachMessage:(void *)_msg { 150706f2543Smrg message *msg = _msg; 151706f2543Smrg 152706f2543Smrg [self performSelector:msg->selector withObject:msg->arg]; 153706f2543Smrg [msg->arg release]; 154706f2543Smrg} 155706f2543Smrg 156706f2543Smrg- (void) set_controller:obj { 157706f2543Smrg if (_controller == nil) _controller = [obj retain]; 158706f2543Smrg} 159706f2543Smrg 160706f2543Smrg- (void) dealloc { 161706f2543Smrg if (_controller != nil) [_controller release]; 162706f2543Smrg 163706f2543Smrg if (_port != MACH_PORT_NULL) 164706f2543Smrg mach_port_deallocate (mach_task_self (), _port); 165706f2543Smrg 166706f2543Smrg [super dealloc]; 167706f2543Smrg} 168706f2543Smrg 169706f2543Smrg- (void) orderFrontStandardAboutPanel: (id) sender { 170706f2543Smrg NSMutableDictionary *dict; 171706f2543Smrg NSDictionary *infoDict; 172706f2543Smrg NSString *tem; 173706f2543Smrg 174706f2543Smrg dict = [NSMutableDictionary dictionaryWithCapacity:3]; 175706f2543Smrg infoDict = [[NSBundle mainBundle] infoDictionary]; 176706f2543Smrg 177706f2543Smrg [dict setObject: NSLocalizedString (@"The X Window System", @"About panel") 178706f2543Smrg forKey:@"ApplicationName"]; 179706f2543Smrg 180706f2543Smrg tem = [infoDict objectForKey:@"CFBundleShortVersionString"]; 181706f2543Smrg 182706f2543Smrg [dict setObject:[NSString stringWithFormat:@"XQuartz %@", tem] 183706f2543Smrg forKey:@"ApplicationVersion"]; 184706f2543Smrg 185706f2543Smrg [dict setObject:[NSString stringWithFormat:@"xorg-server %s", XSERVER_VERSION] 186706f2543Smrg forKey:@"Version"]; 187706f2543Smrg 188706f2543Smrg [self orderFrontStandardAboutPanelWithOptions: dict]; 189706f2543Smrg} 190706f2543Smrg 191706f2543Smrg- (void) activateX:(OSX_BOOL)state { 192706f2543Smrg size_t i; 193706f2543Smrg DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active) 194706f2543Smrg if (state) { 195706f2543Smrg if(bgMouseLocationUpdated) { 196706f2543Smrg DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, bgMouseLocation.x, bgMouseLocation.y, 0.0, 0.0, 0.0); 197706f2543Smrg bgMouseLocationUpdated = FALSE; 198706f2543Smrg } 199706f2543Smrg DarwinSendDDXEvent(kXquartzActivate, 0); 200706f2543Smrg } else { 201706f2543Smrg 202706f2543Smrg if(darwin_all_modifier_flags) 203706f2543Smrg DarwinUpdateModKeys(0); 204706f2543Smrg for(i=0; i < NUM_KEYCODES; i++) { 205706f2543Smrg if(keyState[i] == NSKeyDown) { 206706f2543Smrg DarwinSendKeyboardEvents(KeyRelease, i); 207706f2543Smrg keyState[i] = NSKeyUp; 208706f2543Smrg } 209706f2543Smrg } 210706f2543Smrg 211706f2543Smrg DarwinSendDDXEvent(kXquartzDeactivate, 0); 212706f2543Smrg } 213706f2543Smrg 214706f2543Smrg _x_active = state; 215706f2543Smrg} 216706f2543Smrg 217706f2543Smrg- (void) became_key:(NSWindow *)win { 218706f2543Smrg [self activateX:NO]; 219706f2543Smrg} 220706f2543Smrg 221706f2543Smrg- (void) sendEvent:(NSEvent *)e { 222706f2543Smrg OSX_BOOL for_appkit, for_x; 223706f2543Smrg 224706f2543Smrg /* By default pass down the responder chain and to X. */ 225706f2543Smrg for_appkit = YES; 226706f2543Smrg for_x = YES; 227706f2543Smrg 228706f2543Smrg switch ([e type]) { 229706f2543Smrg case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: 230706f2543Smrg case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: 231706f2543Smrg if ([e window] != nil) { 232706f2543Smrg /* Pointer event has an (AppKit) window. Probably something for the kit. */ 233706f2543Smrg for_x = NO; 234706f2543Smrg if (_x_active) [self activateX:NO]; 235706f2543Smrg } else if ([self modalWindow] == nil) { 236706f2543Smrg /* Must be an X window. Tell appkit it doesn't have focus. */ 237706f2543Smrg for_appkit = NO; 238706f2543Smrg 239706f2543Smrg if ([self isActive]) { 240706f2543Smrg [self deactivate]; 241706f2543Smrg if (!_x_active && quartzProcs->IsX11Window([e window], 242706f2543Smrg [e windowNumber])) 243706f2543Smrg [self activateX:YES]; 244706f2543Smrg } 245706f2543Smrg } 246706f2543Smrg 247706f2543Smrg /* We want to force sending to appkit if we're over the menu bar */ 248706f2543Smrg if(!for_appkit) { 249706f2543Smrg NSPoint NSlocation = [e locationInWindow]; 250706f2543Smrg NSWindow *window = [e window]; 251706f2543Smrg NSRect NSframe, NSvisibleFrame; 252706f2543Smrg CGRect CGframe, CGvisibleFrame; 253706f2543Smrg CGPoint CGlocation; 254706f2543Smrg 255706f2543Smrg if (window != nil) { 256706f2543Smrg NSRect frame = [window frame]; 257706f2543Smrg NSlocation.x += frame.origin.x; 258706f2543Smrg NSlocation.y += frame.origin.y; 259706f2543Smrg } 260706f2543Smrg 261706f2543Smrg NSframe = [[NSScreen mainScreen] frame]; 262706f2543Smrg NSvisibleFrame = [[NSScreen mainScreen] visibleFrame]; 263706f2543Smrg 264706f2543Smrg CGframe = CGRectMake(NSframe.origin.x, NSframe.origin.y, 265706f2543Smrg NSframe.size.width, NSframe.size.height); 266706f2543Smrg CGvisibleFrame = CGRectMake(NSvisibleFrame.origin.x, 267706f2543Smrg NSvisibleFrame.origin.y, 268706f2543Smrg NSvisibleFrame.size.width, 269706f2543Smrg NSvisibleFrame.size.height); 270706f2543Smrg CGlocation = CGPointMake(NSlocation.x, NSlocation.y); 271706f2543Smrg 272706f2543Smrg if(CGRectContainsPoint(CGframe, CGlocation) && 273706f2543Smrg !CGRectContainsPoint(CGvisibleFrame, CGlocation)) 274706f2543Smrg for_appkit = YES; 275706f2543Smrg } 276706f2543Smrg 277706f2543Smrg break; 278706f2543Smrg 279706f2543Smrg case NSKeyDown: case NSKeyUp: 280706f2543Smrg 281706f2543Smrg if(_x_active) { 282706f2543Smrg static BOOL do_swallow = NO; 283706f2543Smrg static int swallow_keycode; 284706f2543Smrg 285706f2543Smrg if([e type] == NSKeyDown) { 286706f2543Smrg /* Before that though, see if there are any global 287706f2543Smrg * shortcuts bound to it. */ 288706f2543Smrg 289706f2543Smrg if(darwinAppKitModMask & [e modifierFlags]) { 290706f2543Smrg /* Override to force sending to Appkit */ 291706f2543Smrg swallow_keycode = [e keyCode]; 292706f2543Smrg do_swallow = YES; 293706f2543Smrg for_x = NO; 294706f2543Smrg#if XPLUGIN_VERSION >= 1 295706f2543Smrg } else if(XQuartzEnableKeyEquivalents && 296706f2543Smrg xp_is_symbolic_hotkey_event([e eventRef])) { 297706f2543Smrg swallow_keycode = [e keyCode]; 298706f2543Smrg do_swallow = YES; 299706f2543Smrg for_x = NO; 300706f2543Smrg#endif 301706f2543Smrg } else if(XQuartzEnableKeyEquivalents && 302706f2543Smrg [[self mainMenu] performKeyEquivalent:e]) { 303706f2543Smrg swallow_keycode = [e keyCode]; 304706f2543Smrg do_swallow = YES; 305706f2543Smrg for_appkit = NO; 306706f2543Smrg for_x = NO; 307706f2543Smrg } else if(!XQuartzIsRootless 308706f2543Smrg && ([e modifierFlags] & ALL_KEY_MASKS) == (NSCommandKeyMask | NSAlternateKeyMask) 309706f2543Smrg && ([e keyCode] == 0 /*a*/ || [e keyCode] == 53 /*Esc*/)) { 310706f2543Smrg /* We have this here to force processing fullscreen 311706f2543Smrg * toggle even if XQuartzEnableKeyEquivalents is disabled */ 312706f2543Smrg swallow_keycode = [e keyCode]; 313706f2543Smrg do_swallow = YES; 314706f2543Smrg for_x = NO; 315706f2543Smrg for_appkit = NO; 316706f2543Smrg DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); 317706f2543Smrg } else { 318706f2543Smrg /* No kit window is focused, so send it to X. */ 319706f2543Smrg for_appkit = NO; 320706f2543Smrg } 321706f2543Smrg } else { /* KeyUp */ 322706f2543Smrg /* If we saw a key equivalent on the down, don't pass 323706f2543Smrg * the up through to X. */ 324706f2543Smrg if (do_swallow && [e keyCode] == swallow_keycode) { 325706f2543Smrg do_swallow = NO; 326706f2543Smrg for_x = NO; 327706f2543Smrg } 328706f2543Smrg } 329706f2543Smrg } else { /* !_x_active */ 330706f2543Smrg for_x = NO; 331706f2543Smrg } 332706f2543Smrg break; 333706f2543Smrg 334706f2543Smrg case NSFlagsChanged: 335706f2543Smrg /* Don't tell X11 about modifiers changing while it's not active */ 336706f2543Smrg if (!_x_active) 337706f2543Smrg for_x = NO; 338706f2543Smrg break; 339706f2543Smrg 340706f2543Smrg case NSAppKitDefined: 341706f2543Smrg switch ([e subtype]) { 342706f2543Smrg static BOOL x_was_active = NO; 343706f2543Smrg 344706f2543Smrg case NSApplicationActivatedEventType: 345706f2543Smrg for_x = NO; 346706f2543Smrg if ([e window] == nil && x_was_active) { 347706f2543Smrg BOOL order_all_windows = YES, workspaces, ok; 348706f2543Smrg for_appkit = NO; 349706f2543Smrg 350706f2543Smrg /* FIXME: This is a hack to avoid passing the event to AppKit which 351706f2543Smrg * would result in it raising one of its windows. 352706f2543Smrg */ 353706f2543Smrg _appFlags._active = YES; 354706f2543Smrg 355706f2543Smrg [self set_front_process:nil]; 356706f2543Smrg 357706f2543Smrg /* Get the Spaces preference for SwitchOnActivate */ 358706f2543Smrg (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock")); 359706f2543Smrg workspaces = CFPreferencesGetAppBooleanValue(CFSTR("workspaces"), CFSTR("com.apple.dock"), &ok); 360706f2543Smrg if (!ok) 361706f2543Smrg workspaces = NO; 362706f2543Smrg 363706f2543Smrg if (workspaces) { 364706f2543Smrg (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences")); 365706f2543Smrg order_all_windows = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok); 366706f2543Smrg if (!ok) 367706f2543Smrg order_all_windows = YES; 368706f2543Smrg } 369706f2543Smrg 370706f2543Smrg /* TODO: In the workspaces && !AppleSpacesSwitchOnActivate case, the windows are ordered 371706f2543Smrg * correctly, but we need to activate the top window on this space if there is 372706f2543Smrg * none active. 373706f2543Smrg * 374706f2543Smrg * If there are no active windows, and there are minimized windows, we should 375706f2543Smrg * be restoring one of them. 376706f2543Smrg */ 377706f2543Smrg if ([e data2] & 0x10) { // 0x10 (bfCPSOrderAllWindowsForward) is set when we use cmd-tab or the dock icon 378706f2543Smrg DarwinSendDDXEvent(kXquartzBringAllToFront, 1, order_all_windows); 379706f2543Smrg } 380706f2543Smrg } 381706f2543Smrg break; 382706f2543Smrg 383706f2543Smrg case 18: /* ApplicationDidReactivate */ 384706f2543Smrg if (XQuartzFullscreenVisible) for_appkit = NO; 385706f2543Smrg break; 386706f2543Smrg 387706f2543Smrg case NSApplicationDeactivatedEventType: 388706f2543Smrg for_x = NO; 389706f2543Smrg 390706f2543Smrg x_was_active = _x_active; 391706f2543Smrg if(_x_active) 392706f2543Smrg [self activateX:NO]; 393706f2543Smrg break; 394706f2543Smrg } 395706f2543Smrg break; 396706f2543Smrg 397706f2543Smrg default: break; /* for gcc */ 398706f2543Smrg } 399706f2543Smrg 400706f2543Smrg if (for_appkit) [super sendEvent:e]; 401706f2543Smrg 402706f2543Smrg if (for_x) [self sendX11NSEvent:e]; 403706f2543Smrg} 404706f2543Smrg 405706f2543Smrg- (void) set_window_menu:(NSArray *)list { 406706f2543Smrg [_controller set_window_menu:list]; 407706f2543Smrg} 408706f2543Smrg 409706f2543Smrg- (void) set_window_menu_check:(NSNumber *)n { 410706f2543Smrg [_controller set_window_menu_check:n]; 411706f2543Smrg} 412706f2543Smrg 413706f2543Smrg- (void) set_apps_menu:(NSArray *)list { 414706f2543Smrg [_controller set_apps_menu:list]; 415706f2543Smrg} 416706f2543Smrg 417706f2543Smrg- (void) set_front_process:unused { 418706f2543Smrg [NSApp activateIgnoringOtherApps:YES]; 419706f2543Smrg 420706f2543Smrg if ([self modalWindow] == nil) 421706f2543Smrg [self activateX:YES]; 422706f2543Smrg} 423706f2543Smrg 424706f2543Smrg- (void) set_can_quit:(NSNumber *)state { 425706f2543Smrg [_controller set_can_quit:[state boolValue]]; 426706f2543Smrg} 427706f2543Smrg 428706f2543Smrg- (void) server_ready:unused { 429706f2543Smrg [_controller server_ready]; 430706f2543Smrg} 431706f2543Smrg 432706f2543Smrg- (void) show_hide_menubar:(NSNumber *)state { 433706f2543Smrg /* Also shows/hides the dock */ 434706f2543Smrg if ([state boolValue]) 435706f2543Smrg SetSystemUIMode(kUIModeNormal, 0); 436706f2543Smrg else 437706f2543Smrg SetSystemUIMode(kUIModeAllHidden, XQuartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation" 438706f2543Smrg} 439706f2543Smrg 440706f2543Smrg- (void) launch_client:(NSString *)cmd { 441706f2543Smrg (void)[_controller application:self openFile:cmd]; 442706f2543Smrg} 443706f2543Smrg 444706f2543Smrg/* user preferences */ 445706f2543Smrg 446706f2543Smrg/* Note that these functions only work for arrays whose elements 447706f2543Smrg can be toll-free-bridged between NS and CF worlds. */ 448706f2543Smrg 449706f2543Smrgstatic const void *cfretain (CFAllocatorRef a, const void *b) { 450706f2543Smrg return CFRetain (b); 451706f2543Smrg} 452706f2543Smrg 453706f2543Smrgstatic void cfrelease (CFAllocatorRef a, const void *b) { 454706f2543Smrg CFRelease (b); 455706f2543Smrg} 456706f2543Smrg 457706f2543Smrgstatic CFMutableArrayRef nsarray_to_cfarray (NSArray *in) { 458706f2543Smrg CFMutableArrayRef out; 459706f2543Smrg CFArrayCallBacks cb; 460706f2543Smrg NSObject *ns; 461706f2543Smrg const CFTypeRef *cf; 462706f2543Smrg int i, count; 463706f2543Smrg 464706f2543Smrg memset (&cb, 0, sizeof (cb)); 465706f2543Smrg cb.version = 0; 466706f2543Smrg cb.retain = cfretain; 467706f2543Smrg cb.release = cfrelease; 468706f2543Smrg 469706f2543Smrg count = [in count]; 470706f2543Smrg out = CFArrayCreateMutable (NULL, count, &cb); 471706f2543Smrg 472706f2543Smrg for (i = 0; i < count; i++) { 473706f2543Smrg ns = [in objectAtIndex:i]; 474706f2543Smrg 475706f2543Smrg if ([ns isKindOfClass:[NSArray class]]) 476706f2543Smrg cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns); 477706f2543Smrg else 478706f2543Smrg cf = CFRetain ((CFTypeRef) ns); 479706f2543Smrg 480706f2543Smrg CFArrayAppendValue (out, cf); 481706f2543Smrg CFRelease (cf); 482706f2543Smrg } 483706f2543Smrg 484706f2543Smrg return out; 485706f2543Smrg} 486706f2543Smrg 487706f2543Smrgstatic NSMutableArray * cfarray_to_nsarray (CFArrayRef in) { 488706f2543Smrg NSMutableArray *out; 489706f2543Smrg const CFTypeRef *cf; 490706f2543Smrg NSObject *ns; 491706f2543Smrg int i, count; 492706f2543Smrg 493706f2543Smrg count = CFArrayGetCount (in); 494706f2543Smrg out = [[NSMutableArray alloc] initWithCapacity:count]; 495706f2543Smrg 496706f2543Smrg for (i = 0; i < count; i++) { 497706f2543Smrg cf = CFArrayGetValueAtIndex (in, i); 498706f2543Smrg 499706f2543Smrg if (CFGetTypeID (cf) == CFArrayGetTypeID ()) 500706f2543Smrg ns = cfarray_to_nsarray ((CFArrayRef) cf); 501706f2543Smrg else 502706f2543Smrg ns = [(id)cf retain]; 503706f2543Smrg 504706f2543Smrg [out addObject:ns]; 505706f2543Smrg [ns release]; 506706f2543Smrg } 507706f2543Smrg 508706f2543Smrg return out; 509706f2543Smrg} 510706f2543Smrg 511706f2543Smrg- (CFPropertyListRef) prefs_get_copy:(NSString *)key { 512706f2543Smrg CFPropertyListRef value; 513706f2543Smrg 514706f2543Smrg value = CFPreferencesCopyAppValue ((CFStringRef) key, app_prefs_domain_cfstr); 515706f2543Smrg 516706f2543Smrg if (value == NULL) { 517706f2543Smrg static CFDictionaryRef defaults; 518706f2543Smrg 519706f2543Smrg if (defaults == NULL) { 520706f2543Smrg CFStringRef error = NULL; 521706f2543Smrg CFDataRef data; 522706f2543Smrg CFURLRef url; 523706f2543Smrg SInt32 error_code; 524706f2543Smrg 525706f2543Smrg url = (CFURLCreateFromFileSystemRepresentation 526706f2543Smrg (NULL, (unsigned char *)DEFAULTS_FILE, strlen (DEFAULTS_FILE), false)); 527706f2543Smrg if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data, 528706f2543Smrg NULL, NULL, &error_code)) { 529706f2543Smrg defaults = (CFPropertyListCreateFromXMLData 530706f2543Smrg (NULL, data, kCFPropertyListMutableContainersAndLeaves, &error)); 531706f2543Smrg if (error != NULL) CFRelease (error); 532706f2543Smrg CFRelease (data); 533706f2543Smrg } 534706f2543Smrg CFRelease (url); 535706f2543Smrg 536706f2543Smrg if (defaults != NULL) { 537706f2543Smrg NSMutableArray *apps, *elt; 538706f2543Smrg int count, i; 539706f2543Smrg NSString *name, *nname; 540706f2543Smrg 541706f2543Smrg /* Localize the names in the default apps menu. */ 542706f2543Smrg 543706f2543Smrg apps = [(NSDictionary *)defaults objectForKey:@PREFS_APPSMENU]; 544706f2543Smrg if (apps != nil) { 545706f2543Smrg count = [apps count]; 546706f2543Smrg for (i = 0; i < count; i++) { 547706f2543Smrg elt = [apps objectAtIndex:i]; 548706f2543Smrg if (elt != nil && [elt isKindOfClass:[NSArray class]]) { 549706f2543Smrg name = [elt objectAtIndex:0]; 550706f2543Smrg if (name != nil) { 551706f2543Smrg nname = NSLocalizedString (name, nil); 552706f2543Smrg if (nname != nil && nname != name) 553706f2543Smrg [elt replaceObjectAtIndex:0 withObject:nname]; 554706f2543Smrg } 555706f2543Smrg } 556706f2543Smrg } 557706f2543Smrg } 558706f2543Smrg } 559706f2543Smrg } 560706f2543Smrg 561706f2543Smrg if (defaults != NULL) value = CFDictionaryGetValue (defaults, key); 562706f2543Smrg if (value != NULL) CFRetain (value); 563706f2543Smrg } 564706f2543Smrg 565706f2543Smrg return value; 566706f2543Smrg} 567706f2543Smrg 568706f2543Smrg- (int) prefs_get_integer:(NSString *)key default:(int)def { 569706f2543Smrg CFPropertyListRef value; 570706f2543Smrg int ret; 571706f2543Smrg 572706f2543Smrg value = [self prefs_get_copy:key]; 573706f2543Smrg 574706f2543Smrg if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ()) 575706f2543Smrg CFNumberGetValue (value, kCFNumberIntType, &ret); 576706f2543Smrg else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) 577706f2543Smrg ret = CFStringGetIntValue (value); 578706f2543Smrg else 579706f2543Smrg ret = def; 580706f2543Smrg 581706f2543Smrg if (value != NULL) CFRelease (value); 582706f2543Smrg 583706f2543Smrg return ret; 584706f2543Smrg} 585706f2543Smrg 586706f2543Smrg- (const char *) prefs_get_string:(NSString *)key default:(const char *)def { 587706f2543Smrg CFPropertyListRef value; 588706f2543Smrg const char *ret = NULL; 589706f2543Smrg 590706f2543Smrg value = [self prefs_get_copy:key]; 591706f2543Smrg 592706f2543Smrg if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { 593706f2543Smrg NSString *s = (NSString *) value; 594706f2543Smrg 595706f2543Smrg ret = [s UTF8String]; 596706f2543Smrg } 597706f2543Smrg 598706f2543Smrg if (value != NULL) CFRelease (value); 599706f2543Smrg 600706f2543Smrg return ret != NULL ? ret : def; 601706f2543Smrg} 602706f2543Smrg 603706f2543Smrg- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def { 604706f2543Smrg CFPropertyListRef value; 605706f2543Smrg NSURL *ret = NULL; 606706f2543Smrg 607706f2543Smrg value = [self prefs_get_copy:key]; 608706f2543Smrg 609706f2543Smrg if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) { 610706f2543Smrg NSString *s = (NSString *) value; 611706f2543Smrg 612706f2543Smrg ret = [NSURL URLWithString:s]; 613706f2543Smrg [ret retain]; 614706f2543Smrg } 615706f2543Smrg 616706f2543Smrg if (value != NULL) CFRelease (value); 617706f2543Smrg 618706f2543Smrg return ret != NULL ? ret : def; 619706f2543Smrg} 620706f2543Smrg 621706f2543Smrg- (float) prefs_get_float:(NSString *)key default:(float)def { 622706f2543Smrg CFPropertyListRef value; 623706f2543Smrg float ret = def; 624706f2543Smrg 625706f2543Smrg value = [self prefs_get_copy:key]; 626706f2543Smrg 627706f2543Smrg if (value != NULL 628706f2543Smrg && CFGetTypeID (value) == CFNumberGetTypeID () 629706f2543Smrg && CFNumberIsFloatType (value)) 630706f2543Smrg CFNumberGetValue (value, kCFNumberFloatType, &ret); 631706f2543Smrg else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) 632706f2543Smrg ret = CFStringGetDoubleValue (value); 633706f2543Smrg 634706f2543Smrg if (value != NULL) CFRelease (value); 635706f2543Smrg 636706f2543Smrg return ret; 637706f2543Smrg} 638706f2543Smrg 639706f2543Smrg- (int) prefs_get_boolean:(NSString *)key default:(int)def { 640706f2543Smrg CFPropertyListRef value; 641706f2543Smrg int ret = def; 642706f2543Smrg 643706f2543Smrg value = [self prefs_get_copy:key]; 644706f2543Smrg 645706f2543Smrg if (value != NULL) { 646706f2543Smrg if (CFGetTypeID (value) == CFNumberGetTypeID ()) 647706f2543Smrg CFNumberGetValue (value, kCFNumberIntType, &ret); 648706f2543Smrg else if (CFGetTypeID (value) == CFBooleanGetTypeID ()) 649706f2543Smrg ret = CFBooleanGetValue (value); 650706f2543Smrg else if (CFGetTypeID (value) == CFStringGetTypeID ()) { 651706f2543Smrg const char *tem = [(NSString *) value UTF8String]; 652706f2543Smrg if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0) 653706f2543Smrg ret = YES; 654706f2543Smrg else 655706f2543Smrg ret = NO; 656706f2543Smrg } 657706f2543Smrg 658706f2543Smrg CFRelease (value); 659706f2543Smrg } 660706f2543Smrg return ret; 661706f2543Smrg} 662706f2543Smrg 663706f2543Smrg- (NSArray *) prefs_get_array:(NSString *)key { 664706f2543Smrg NSArray *ret = nil; 665706f2543Smrg CFPropertyListRef value; 666706f2543Smrg 667706f2543Smrg value = [self prefs_get_copy:key]; 668706f2543Smrg 669706f2543Smrg if (value != NULL) { 670706f2543Smrg if (CFGetTypeID (value) == CFArrayGetTypeID ()) 671706f2543Smrg ret = [cfarray_to_nsarray (value) autorelease]; 672706f2543Smrg 673706f2543Smrg CFRelease (value); 674706f2543Smrg } 675706f2543Smrg 676706f2543Smrg return ret; 677706f2543Smrg} 678706f2543Smrg 679706f2543Smrg- (void) prefs_set_integer:(NSString *)key value:(int)value { 680706f2543Smrg CFNumberRef x; 681706f2543Smrg 682706f2543Smrg x = CFNumberCreate (NULL, kCFNumberIntType, &value); 683706f2543Smrg 684706f2543Smrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, 685706f2543Smrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 686706f2543Smrg 687706f2543Smrg CFRelease (x); 688706f2543Smrg} 689706f2543Smrg 690706f2543Smrg- (void) prefs_set_float:(NSString *)key value:(float)value { 691706f2543Smrg CFNumberRef x; 692706f2543Smrg 693706f2543Smrg x = CFNumberCreate (NULL, kCFNumberFloatType, &value); 694706f2543Smrg 695706f2543Smrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr, 696706f2543Smrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 697706f2543Smrg 698706f2543Smrg CFRelease (x); 699706f2543Smrg} 700706f2543Smrg 701706f2543Smrg- (void) prefs_set_boolean:(NSString *)key value:(int)value { 702706f2543Smrg CFPreferencesSetValue ((CFStringRef) key, 703706f2543Smrg (CFTypeRef) (value ? kCFBooleanTrue 704706f2543Smrg : kCFBooleanFalse), app_prefs_domain_cfstr, 705706f2543Smrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 706706f2543Smrg 707706f2543Smrg} 708706f2543Smrg 709706f2543Smrg- (void) prefs_set_array:(NSString *)key value:(NSArray *)value { 710706f2543Smrg CFArrayRef cfarray; 711706f2543Smrg 712706f2543Smrg cfarray = nsarray_to_cfarray (value); 713706f2543Smrg CFPreferencesSetValue ((CFStringRef) key, 714706f2543Smrg (CFTypeRef) cfarray, 715706f2543Smrg app_prefs_domain_cfstr, 716706f2543Smrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 717706f2543Smrg CFRelease (cfarray); 718706f2543Smrg} 719706f2543Smrg 720706f2543Smrg- (void) prefs_set_string:(NSString *)key value:(NSString *)value { 721706f2543Smrg CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value, 722706f2543Smrg app_prefs_domain_cfstr, kCFPreferencesCurrentUser, 723706f2543Smrg kCFPreferencesAnyHost); 724706f2543Smrg} 725706f2543Smrg 726706f2543Smrg- (void) prefs_synchronize { 727706f2543Smrg CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication); 728706f2543Smrg} 729706f2543Smrg 730706f2543Smrg- (void) read_defaults 731706f2543Smrg{ 732706f2543Smrg NSString *nsstr; 733706f2543Smrg const char *tem; 734706f2543Smrg 735706f2543Smrg XQuartzRootlessDefault = [self prefs_get_boolean:@PREFS_ROOTLESS 736706f2543Smrg default:XQuartzRootlessDefault]; 737706f2543Smrg XQuartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU 738706f2543Smrg default:XQuartzFullscreenMenu]; 739706f2543Smrg XQuartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS 740706f2543Smrg default:!XQuartzFullscreenDisableHotkeys]; 741706f2543Smrg darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS 742706f2543Smrg default:darwinFakeButtons]; 743706f2543Smrg XQuartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT 744706f2543Smrg default:XQuartzOptionSendsAlt]; 745706f2543Smrg 746706f2543Smrg if (darwinFakeButtons) { 747706f2543Smrg const char *fake2, *fake3; 748706f2543Smrg 749706f2543Smrg fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL]; 750706f2543Smrg fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL]; 751706f2543Smrg 752706f2543Smrg if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList(fake2, TRUE); 753706f2543Smrg if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList(fake3, TRUE); 754706f2543Smrg } 755706f2543Smrg 756706f2543Smrg tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL]; 757706f2543Smrg if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE); 758706f2543Smrg 759706f2543Smrg tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL]; 760706f2543Smrg if (tem != NULL) { 761706f2543Smrg windowItemModMask = DarwinParseModifierList(tem, FALSE); 762706f2543Smrg } else { 763706f2543Smrg nsstr = NSLocalizedString (@"window item modifiers", @"window item modifiers"); 764706f2543Smrg if(nsstr != NULL) { 765706f2543Smrg tem = [nsstr UTF8String]; 766706f2543Smrg if((tem != NULL) && strcmp(tem, "window item modifiers")) { 767706f2543Smrg windowItemModMask = DarwinParseModifierList(tem, FALSE); 768706f2543Smrg } 769706f2543Smrg } 770706f2543Smrg } 771706f2543Smrg 772706f2543Smrg XQuartzEnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS 773706f2543Smrg default:XQuartzEnableKeyEquivalents]; 774706f2543Smrg 775706f2543Smrg darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP 776706f2543Smrg default:darwinSyncKeymap]; 777706f2543Smrg 778706f2543Smrg darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH 779706f2543Smrg default:darwinDesiredDepth]; 780706f2543Smrg 781706f2543Smrg noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS 782706f2543Smrg default:FALSE]; 783706f2543Smrg 784706f2543Smrg XQuartzScrollInDeviceDirection = [self prefs_get_boolean:@PREFS_SCROLL_IN_DEV_DIRECTION 785706f2543Smrg default:XQuartzScrollInDeviceDirection]; 786706f2543Smrg 787706f2543Smrg#if XQUARTZ_SPARKLE 788706f2543Smrg NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil]; 789706f2543Smrg if(url) { 790706f2543Smrg [[SUUpdater sharedUpdater] setFeedURL:url]; 791706f2543Smrg [url release]; 792706f2543Smrg } 793706f2543Smrg#endif 794706f2543Smrg} 795706f2543Smrg 796706f2543Smrg/* This will end up at the end of the responder chain. */ 797706f2543Smrg- (void) copy:sender { 798706f2543Smrg DarwinSendDDXEvent(kXquartzPasteboardNotify, 1, 799706f2543Smrg AppleWMCopyToPasteboard); 800706f2543Smrg} 801706f2543Smrg 802706f2543Smrg- (X11Controller *) controller { 803706f2543Smrg return _controller; 804706f2543Smrg} 805706f2543Smrg 806706f2543Smrg- (OSX_BOOL) x_active { 807706f2543Smrg return _x_active; 808706f2543Smrg} 809706f2543Smrg 810706f2543Smrg@end 811706f2543Smrg 812706f2543Smrgstatic NSArray * 813706f2543Smrgarray_with_strings_and_numbers (int nitems, const char **items, 814706f2543Smrg const char *numbers) { 815706f2543Smrg NSMutableArray *array, *subarray; 816706f2543Smrg NSString *string, *number; 817706f2543Smrg int i; 818706f2543Smrg 819706f2543Smrg /* (Can't autorelease on the X server thread) */ 820706f2543Smrg 821706f2543Smrg array = [[NSMutableArray alloc] initWithCapacity:nitems]; 822706f2543Smrg 823706f2543Smrg for (i = 0; i < nitems; i++) { 824706f2543Smrg subarray = [[NSMutableArray alloc] initWithCapacity:2]; 825706f2543Smrg 826706f2543Smrg string = [[NSString alloc] initWithUTF8String:items[i]]; 827706f2543Smrg [subarray addObject:string]; 828706f2543Smrg [string release]; 829706f2543Smrg 830706f2543Smrg if (numbers[i] != 0) { 831706f2543Smrg number = [[NSString alloc] initWithFormat:@"%d", numbers[i]]; 832706f2543Smrg [subarray addObject:number]; 833706f2543Smrg [number release]; 834706f2543Smrg } else 835706f2543Smrg [subarray addObject:@""]; 836706f2543Smrg 837706f2543Smrg [array addObject:subarray]; 838706f2543Smrg [subarray release]; 839706f2543Smrg } 840706f2543Smrg 841706f2543Smrg return array; 842706f2543Smrg} 843706f2543Smrg 844706f2543Smrgvoid X11ApplicationSetWindowMenu (int nitems, const char **items, 845706f2543Smrg const char *shortcuts) { 846706f2543Smrg NSArray *array; 847706f2543Smrg array = array_with_strings_and_numbers (nitems, items, shortcuts); 848706f2543Smrg 849706f2543Smrg /* Send the array of strings over to the appkit thread */ 850706f2543Smrg 851706f2543Smrg message_kit_thread (@selector (set_window_menu:), array); 852706f2543Smrg [array release]; 853706f2543Smrg} 854706f2543Smrg 855706f2543Smrgvoid X11ApplicationSetWindowMenuCheck (int idx) { 856706f2543Smrg NSNumber *n; 857706f2543Smrg 858706f2543Smrg n = [[NSNumber alloc] initWithInt:idx]; 859706f2543Smrg 860706f2543Smrg message_kit_thread (@selector (set_window_menu_check:), n); 861706f2543Smrg 862706f2543Smrg [n release]; 863706f2543Smrg} 864706f2543Smrg 865706f2543Smrgvoid X11ApplicationSetFrontProcess (void) { 866706f2543Smrg message_kit_thread (@selector (set_front_process:), nil); 867706f2543Smrg} 868706f2543Smrg 869706f2543Smrgvoid X11ApplicationSetCanQuit (int state) { 870706f2543Smrg NSNumber *n; 871706f2543Smrg 872706f2543Smrg n = [[NSNumber alloc] initWithBool:state]; 873706f2543Smrg 874706f2543Smrg message_kit_thread (@selector (set_can_quit:), n); 875706f2543Smrg 876706f2543Smrg [n release]; 877706f2543Smrg} 878706f2543Smrg 879706f2543Smrgvoid X11ApplicationServerReady (void) { 880706f2543Smrg message_kit_thread (@selector (server_ready:), nil); 881706f2543Smrg} 882706f2543Smrg 883706f2543Smrgvoid X11ApplicationShowHideMenubar (int state) { 884706f2543Smrg NSNumber *n; 885706f2543Smrg 886706f2543Smrg n = [[NSNumber alloc] initWithBool:state]; 887706f2543Smrg 888706f2543Smrg message_kit_thread (@selector (show_hide_menubar:), n); 889706f2543Smrg 890706f2543Smrg [n release]; 891706f2543Smrg} 892706f2543Smrg 893706f2543Smrgvoid X11ApplicationLaunchClient (const char *cmd) { 894706f2543Smrg NSString *string; 895706f2543Smrg 896706f2543Smrg string = [[NSString alloc] initWithUTF8String:cmd]; 897706f2543Smrg 898706f2543Smrg message_kit_thread (@selector (launch_client:), string); 899706f2543Smrg 900706f2543Smrg [string release]; 901706f2543Smrg} 902706f2543Smrg 903706f2543Smrg/* This is a special function in that it is run from the *SERVER* thread and 904706f2543Smrg * not the AppKit thread. We want to block entering a screen-capturing RandR 905706f2543Smrg * mode until we notify the user about how to get out if the X11 client crashes. 906706f2543Smrg */ 907706f2543SmrgBool X11ApplicationCanEnterRandR(void) { 908706f2543Smrg NSString *title, *msg; 909706f2543Smrg 910706f2543Smrg if([X11App prefs_get_boolean:@PREFS_NO_RANDR_ALERT default:NO] || XQuartzShieldingWindowLevel != 0) 911706f2543Smrg return TRUE; 912706f2543Smrg 913706f2543Smrg title = NSLocalizedString(@"Enter RandR mode?", @"Dialog title when switching to RandR"); 914706f2543Smrg 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.", 915706f2543Smrg @"Dialog when switching to RandR"); 916706f2543Smrg 917706f2543Smrg if(!XQuartzIsRootless) 918706f2543Smrg QuartzShowFullscreen(FALSE); 919706f2543Smrg 920706f2543Smrg switch(NSRunAlertPanel(title, msg, NSLocalizedString(@"Allow", @""), NSLocalizedString (@"Cancel", @""), NSLocalizedString (@"Always Allow", @""))) { 921706f2543Smrg case NSAlertOtherReturn: 922706f2543Smrg [X11App prefs_set_boolean:@PREFS_NO_RANDR_ALERT value:YES]; 923706f2543Smrg [X11App prefs_synchronize]; 924706f2543Smrg case NSAlertDefaultReturn: 925706f2543Smrg return YES; 926706f2543Smrg 927706f2543Smrg default: 928706f2543Smrg return NO; 929706f2543Smrg } 930706f2543Smrg} 931706f2543Smrg 932706f2543Smrgstatic void check_xinitrc (void) { 933706f2543Smrg char *tem, buf[1024]; 934706f2543Smrg NSString *msg; 935706f2543Smrg 936706f2543Smrg if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO]) 937706f2543Smrg return; 938706f2543Smrg 939706f2543Smrg tem = getenv ("HOME"); 940706f2543Smrg if (tem == NULL) goto done; 941706f2543Smrg 942706f2543Smrg snprintf (buf, sizeof (buf), "%s/.xinitrc", tem); 943706f2543Smrg if (access (buf, F_OK) != 0) 944706f2543Smrg goto done; 945706f2543Smrg 946706f2543Smrg msg = NSLocalizedString (@"You have an existing ~/.xinitrc file.\n\n\ 947706f2543SmrgWindows displayed by X11 applications may not have titlebars, or may look \ 948706f2543Smrgdifferent to windows displayed by native applications.\n\n\ 949706f2543SmrgWould you like to move aside the existing file and use the standard X11 \ 950706f2543Smrgenvironment the next time you start X11?", @"Startup xinitrc dialog"); 951706f2543Smrg 952706f2543Smrg if(NSAlertDefaultReturn == NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""), 953706f2543Smrg NSLocalizedString (@"No", @""), nil)) { 954706f2543Smrg char buf2[1024]; 955706f2543Smrg int i = -1; 956706f2543Smrg 957706f2543Smrg snprintf (buf2, sizeof (buf2), "%s.old", buf); 958706f2543Smrg 959706f2543Smrg for(i = 1; access (buf2, F_OK) == 0; i++) 960706f2543Smrg snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i); 961706f2543Smrg 962706f2543Smrg rename (buf, buf2); 963706f2543Smrg } 964706f2543Smrg 965706f2543Smrg done: 966706f2543Smrg [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES]; 967706f2543Smrg [X11App prefs_synchronize]; 968706f2543Smrg} 969706f2543Smrg 970706f2543Smrgstatic inline pthread_t create_thread(void *(*func)(void *), void *arg) { 971706f2543Smrg pthread_attr_t attr; 972706f2543Smrg pthread_t tid; 973706f2543Smrg 974706f2543Smrg pthread_attr_init(&attr); 975706f2543Smrg pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 976706f2543Smrg pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 977706f2543Smrg pthread_create(&tid, &attr, func, arg); 978706f2543Smrg pthread_attr_destroy(&attr); 979706f2543Smrg 980706f2543Smrg return tid; 981706f2543Smrg} 982706f2543Smrg 983706f2543Smrgstatic void *xpbproxy_x_thread(void *args) { 984706f2543Smrg xpbproxy_run(); 985706f2543Smrg 986706f2543Smrg fprintf(stderr, "xpbproxy thread is terminating unexpectedly.\n"); 987706f2543Smrg return NULL; 988706f2543Smrg} 989706f2543Smrg 990706f2543Smrgvoid X11ApplicationMain (int argc, char **argv, char **envp) { 991706f2543Smrg NSAutoreleasePool *pool; 992706f2543Smrg 993706f2543Smrg#ifdef DEBUG 994706f2543Smrg while (access ("/tmp/x11-block", F_OK) == 0) sleep (1); 995706f2543Smrg#endif 996706f2543Smrg 997706f2543Smrg pool = [[NSAutoreleasePool alloc] init]; 998706f2543Smrg X11App = (X11Application *) [X11Application sharedApplication]; 999706f2543Smrg init_ports (); 1000706f2543Smrg 1001706f2543Smrg app_prefs_domain_cfstr = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]; 1002706f2543Smrg 1003706f2543Smrg if (app_prefs_domain_cfstr == NULL) { 1004706f2543Smrg ErrorF("X11ApplicationMain: Unable to determine bundle identifier. Your installation of XQuartz may be broken.\n"); 1005706f2543Smrg app_prefs_domain_cfstr = CFSTR(LAUNCHD_ID_PREFIX".X11"); 1006706f2543Smrg } 1007706f2543Smrg 1008706f2543Smrg [NSApp read_defaults]; 1009706f2543Smrg [NSBundle loadNibNamed:@"main" owner:NSApp]; 1010706f2543Smrg [[NSNotificationCenter defaultCenter] addObserver:NSApp 1011706f2543Smrg selector:@selector (became_key:) 1012706f2543Smrg name:NSWindowDidBecomeKeyNotification object:nil]; 1013706f2543Smrg 1014706f2543Smrg /* 1015706f2543Smrg * The xpr Quartz mode is statically linked into this server. 1016706f2543Smrg * Initialize all the Quartz functions. 1017706f2543Smrg */ 1018706f2543Smrg QuartzModeBundleInit(); 1019706f2543Smrg 1020706f2543Smrg /* Calculate the height of the menubar so we can avoid it. */ 1021706f2543Smrg aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) - 1022706f2543Smrg NSMaxY([[NSScreen mainScreen] visibleFrame]); 1023706f2543Smrg 1024706f2543Smrg /* Set the key layout seed before we start the server */ 1025706f2543Smrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 1026706f2543Smrg last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); 1027706f2543Smrg 1028706f2543Smrg if(!last_key_layout) 1029706f2543Smrg fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); 1030706f2543Smrg#else 1031706f2543Smrg KLGetCurrentKeyboardLayout(&last_key_layout); 1032706f2543Smrg if(!last_key_layout) 1033706f2543Smrg fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n"); 1034706f2543Smrg#endif 1035706f2543Smrg 1036706f2543Smrg if (!QuartsResyncKeymap(FALSE)) { 1037706f2543Smrg fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n"); 1038706f2543Smrg } 1039706f2543Smrg 1040706f2543Smrg /* Tell the server thread that it can proceed */ 1041706f2543Smrg QuartzInitServer(argc, argv, envp); 1042706f2543Smrg 1043706f2543Smrg /* This must be done after QuartzInitServer because it can result in 1044706f2543Smrg * an mieqEnqueue() - <rdar://problem/6300249> 1045706f2543Smrg */ 1046706f2543Smrg check_xinitrc(); 1047706f2543Smrg 1048706f2543Smrg create_thread(xpbproxy_x_thread, NULL); 1049706f2543Smrg 1050706f2543Smrg#if XQUARTZ_SPARKLE 1051706f2543Smrg [[X11App controller] setup_sparkle]; 1052706f2543Smrg [[SUUpdater sharedUpdater] resetUpdateCycle]; 1053706f2543Smrg// [[SUUpdater sharedUpdater] checkForUpdates:X11App]; 1054706f2543Smrg#endif 1055706f2543Smrg 1056706f2543Smrg [pool release]; 1057706f2543Smrg [NSApp run]; 1058706f2543Smrg /* not reached */ 1059706f2543Smrg} 1060706f2543Smrg 1061706f2543Smrg@implementation X11Application (Private) 1062706f2543Smrg 1063706f2543Smrg#ifdef NX_DEVICELCMDKEYMASK 1064706f2543Smrg/* This is to workaround a bug in the VNC server where we sometimes see the L 1065706f2543Smrg * modifier and sometimes see no "side" 1066706f2543Smrg */ 1067706f2543Smrgstatic inline int ensure_flag(int flags, int device_independent, int device_dependents, int device_dependent_default) { 1068706f2543Smrg if( (flags & device_independent) && 1069706f2543Smrg !(flags & device_dependents)) 1070706f2543Smrg flags |= device_dependent_default; 1071706f2543Smrg return flags; 1072706f2543Smrg} 1073706f2543Smrg#endif 1074706f2543Smrg 1075706f2543Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 1076706f2543Smrgstatic const char *untrusted_str(NSEvent *e) { 1077706f2543Smrg switch([e type]) { 1078706f2543Smrg case NSScrollWheel: 1079706f2543Smrg return "NSScrollWheel"; 1080706f2543Smrg case NSTabletPoint: 1081706f2543Smrg return "NSTabletPoint"; 1082706f2543Smrg case NSOtherMouseDown: 1083706f2543Smrg return "NSOtherMouseDown"; 1084706f2543Smrg case NSOtherMouseUp: 1085706f2543Smrg return "NSOtherMouseUp"; 1086706f2543Smrg case NSLeftMouseDown: 1087706f2543Smrg return "NSLeftMouseDown"; 1088706f2543Smrg case NSLeftMouseUp: 1089706f2543Smrg return "NSLeftMouseUp"; 1090706f2543Smrg default: 1091706f2543Smrg switch([e subtype]) { 1092706f2543Smrg case NSTabletPointEventSubtype: 1093706f2543Smrg return "NSTabletPointEventSubtype"; 1094706f2543Smrg case NSTabletProximityEventSubtype: 1095706f2543Smrg return "NSTabletProximityEventSubtype"; 1096706f2543Smrg default: 1097706f2543Smrg return "Other"; 1098706f2543Smrg } 1099706f2543Smrg } 1100706f2543Smrg} 1101706f2543Smrg#endif 1102706f2543Smrg 1103706f2543Smrg- (void) sendX11NSEvent:(NSEvent *)e { 1104706f2543Smrg NSPoint location = NSZeroPoint, tilt = NSZeroPoint; 1105706f2543Smrg int ev_button, ev_type; 1106706f2543Smrg float pressure = 0.0; 1107706f2543Smrg DeviceIntPtr pDev; 1108706f2543Smrg int modifierFlags; 1109706f2543Smrg BOOL isMouseOrTabletEvent, isTabletEvent; 1110706f2543Smrg 1111706f2543Smrg isMouseOrTabletEvent = [e type] == NSLeftMouseDown || [e type] == NSOtherMouseDown || [e type] == NSRightMouseDown || 1112706f2543Smrg [e type] == NSLeftMouseUp || [e type] == NSOtherMouseUp || [e type] == NSRightMouseUp || 1113706f2543Smrg [e type] == NSLeftMouseDragged || [e type] == NSOtherMouseDragged || [e type] == NSRightMouseDragged || 1114706f2543Smrg [e type] == NSMouseMoved || [e type] == NSTabletPoint || [e type] == NSScrollWheel; 1115706f2543Smrg 1116706f2543Smrg isTabletEvent = ([e type] == NSTabletPoint) || 1117706f2543Smrg (isMouseOrTabletEvent && ([e subtype] == NSTabletPointEventSubtype || [e subtype] == NSTabletProximityEventSubtype)); 1118706f2543Smrg 1119706f2543Smrg if(isMouseOrTabletEvent) { 1120706f2543Smrg static NSPoint lastpt; 1121706f2543Smrg NSWindow *window = [e window]; 1122706f2543Smrg NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame]; 1123706f2543Smrg BOOL hasUntrustedPointerDelta; 1124706f2543Smrg 1125706f2543Smrg // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that 1126706f2543Smrg // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets 1127706f2543Smrg // are not normally used in cases where that bug would present itself, so this is a fair tradeoff 1128706f2543Smrg // <rdar://problem/7111003> deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype 1129706f2543Smrg // http://xquartz.macosforge.org/trac/ticket/288 1130706f2543Smrg hasUntrustedPointerDelta = isTabletEvent; 1131706f2543Smrg 1132706f2543Smrg // The deltaXY for middle click events also appear erroneous after fast user switching 1133706f2543Smrg // <rdar://problem/7979468> deltaX and deltaY are incorrect for NSOtherMouseDown and NSOtherMouseUp after FUS 1134706f2543Smrg // http://xquartz.macosforge.org/trac/ticket/389 1135706f2543Smrg hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSOtherMouseDown || [e type] == NSOtherMouseUp; 1136706f2543Smrg 1137706f2543Smrg // The deltaXY for scroll events correspond to the scroll delta, not the pointer delta 1138706f2543Smrg // <rdar://problem/7989690> deltaXY for wheel events are being sent as mouse movement 1139706f2543Smrg hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSScrollWheel; 1140706f2543Smrg 1141706f2543Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 1142706f2543Smrg hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSLeftMouseDown || [e type] == NSLeftMouseUp; 1143706f2543Smrg#endif 1144706f2543Smrg 1145706f2543Smrg if (window != nil) { 1146706f2543Smrg NSRect frame = [window frame]; 1147706f2543Smrg location = [e locationInWindow]; 1148706f2543Smrg location.x += frame.origin.x; 1149706f2543Smrg location.y += frame.origin.y; 1150706f2543Smrg lastpt = location; 1151706f2543Smrg } else if(hasUntrustedPointerDelta) { 1152706f2543Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 1153706f2543Smrg ErrorF("--- Begin Event Debug ---\n"); 1154706f2543Smrg ErrorF("Event type: %s\n", untrusted_str(e)); 1155706f2543Smrg ErrorF("old lastpt: (%0.2f, %0.2f)\n", lastpt.x, lastpt.y); 1156706f2543Smrg ErrorF(" delta: (%0.2f, %0.2f)\n", [e deltaX], -[e deltaY]); 1157706f2543Smrg ErrorF(" location: (%0.2f, %0.2f)\n", lastpt.x + [e deltaX], lastpt.y - [e deltaY]); 1158706f2543Smrg ErrorF("workaround: (%0.2f, %0.2f)\n", [e locationInWindow].x, [e locationInWindow].y); 1159706f2543Smrg ErrorF("--- End Event Debug ---\n"); 1160706f2543Smrg 1161706f2543Smrg location.x = lastpt.x + [e deltaX]; 1162706f2543Smrg location.y = lastpt.y - [e deltaY]; 1163706f2543Smrg lastpt = [e locationInWindow]; 1164706f2543Smrg#else 1165706f2543Smrg location = [e locationInWindow]; 1166706f2543Smrg lastpt = location; 1167706f2543Smrg#endif 1168706f2543Smrg } else { 1169706f2543Smrg location.x = lastpt.x + [e deltaX]; 1170706f2543Smrg location.y = lastpt.y - [e deltaY]; 1171706f2543Smrg lastpt = [e locationInWindow]; 1172706f2543Smrg } 1173706f2543Smrg 1174706f2543Smrg /* Convert coordinate system */ 1175706f2543Smrg location.y = (screen.origin.y + screen.size.height) - location.y; 1176706f2543Smrg } 1177706f2543Smrg 1178706f2543Smrg modifierFlags = [e modifierFlags]; 1179706f2543Smrg 1180706f2543Smrg#ifdef NX_DEVICELCMDKEYMASK 1181706f2543Smrg /* This is to workaround a bug in the VNC server where we sometimes see the L 1182706f2543Smrg * modifier and sometimes see no "side" 1183706f2543Smrg */ 1184706f2543Smrg modifierFlags = ensure_flag(modifierFlags, NX_CONTROLMASK, NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK, NX_DEVICELCTLKEYMASK); 1185706f2543Smrg modifierFlags = ensure_flag(modifierFlags, NX_SHIFTMASK, NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK, NX_DEVICELSHIFTKEYMASK); 1186706f2543Smrg modifierFlags = ensure_flag(modifierFlags, NX_COMMANDMASK, NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK, NX_DEVICELCMDKEYMASK); 1187706f2543Smrg modifierFlags = ensure_flag(modifierFlags, NX_ALTERNATEMASK, NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK, NX_DEVICELALTKEYMASK); 1188706f2543Smrg#endif 1189706f2543Smrg 1190706f2543Smrg modifierFlags &= darwin_all_modifier_mask; 1191706f2543Smrg 1192706f2543Smrg /* We don't receive modifier key events while out of focus, and 3button 1193706f2543Smrg * emulation mucks this up, so we need to check our modifier flag state 1194706f2543Smrg * on every event... ugg 1195706f2543Smrg */ 1196706f2543Smrg 1197706f2543Smrg if(darwin_all_modifier_flags != modifierFlags) 1198706f2543Smrg DarwinUpdateModKeys(modifierFlags); 1199706f2543Smrg 1200706f2543Smrg switch ([e type]) { 1201706f2543Smrg case NSLeftMouseDown: ev_button=1; ev_type=ButtonPress; goto handle_mouse; 1202706f2543Smrg case NSOtherMouseDown: ev_button=2; ev_type=ButtonPress; goto handle_mouse; 1203706f2543Smrg case NSRightMouseDown: ev_button=3; ev_type=ButtonPress; goto handle_mouse; 1204706f2543Smrg case NSLeftMouseUp: ev_button=1; ev_type=ButtonRelease; goto handle_mouse; 1205706f2543Smrg case NSOtherMouseUp: ev_button=2; ev_type=ButtonRelease; goto handle_mouse; 1206706f2543Smrg case NSRightMouseUp: ev_button=3; ev_type=ButtonRelease; goto handle_mouse; 1207706f2543Smrg case NSLeftMouseDragged: ev_button=1; ev_type=MotionNotify; goto handle_mouse; 1208706f2543Smrg case NSOtherMouseDragged: ev_button=2; ev_type=MotionNotify; goto handle_mouse; 1209706f2543Smrg case NSRightMouseDragged: ev_button=3; ev_type=MotionNotify; goto handle_mouse; 1210706f2543Smrg case NSMouseMoved: ev_button=0; ev_type=MotionNotify; goto handle_mouse; 1211706f2543Smrg case NSTabletPoint: ev_button=0; ev_type=MotionNotify; goto handle_mouse; 1212706f2543Smrg 1213706f2543Smrg handle_mouse: 1214706f2543Smrg pDev = darwinPointer; 1215706f2543Smrg 1216706f2543Smrg /* NSTabletPoint can have no subtype */ 1217706f2543Smrg if([e type] != NSTabletPoint && 1218706f2543Smrg [e subtype] == NSTabletProximityEventSubtype) { 1219706f2543Smrg switch([e pointingDeviceType]) { 1220706f2543Smrg case NSEraserPointingDevice: 1221706f2543Smrg darwinTabletCurrent=darwinTabletEraser; 1222706f2543Smrg break; 1223706f2543Smrg case NSPenPointingDevice: 1224706f2543Smrg darwinTabletCurrent=darwinTabletStylus; 1225706f2543Smrg break; 1226706f2543Smrg case NSCursorPointingDevice: 1227706f2543Smrg case NSUnknownPointingDevice: 1228706f2543Smrg default: 1229706f2543Smrg darwinTabletCurrent=darwinTabletCursor; 1230706f2543Smrg break; 1231706f2543Smrg } 1232706f2543Smrg 1233706f2543Smrg /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt 1234706f2543Smrg * So we just pretend the motion was caused by the mouse. Hopefully 1235706f2543Smrg * we'll have a better solution for this in the future (like maybe 1236706f2543Smrg * NSTabletProximityEventSubtype will come from NSTabletPoint 1237706f2543Smrg * rather than NSMouseMoved. 1238706f2543Smrg pressure = [e pressure]; 1239706f2543Smrg tilt = [e tilt]; 1240706f2543Smrg pDev = darwinTabletCurrent; 1241706f2543Smrg */ 1242706f2543Smrg 1243706f2543Smrg DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, 1244706f2543Smrg location.x, location.y); 1245706f2543Smrg } 1246706f2543Smrg 1247706f2543Smrg if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) { 1248706f2543Smrg pressure = [e pressure]; 1249706f2543Smrg tilt = [e tilt]; 1250706f2543Smrg 1251706f2543Smrg pDev = darwinTabletCurrent; 1252706f2543Smrg } 1253706f2543Smrg 1254706f2543Smrg if(!XQuartzServerVisible && noTestExtensions) { 1255706f2543Smrg#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0 1256706f2543Smrg/* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */ 1257706f2543Smrg xp_window_id wid = 0; 1258706f2543Smrg xp_error e; 1259706f2543Smrg 1260706f2543Smrg /* Sigh. Need to check that we're really over one of 1261706f2543Smrg * our windows. (We need to receive pointer events while 1262706f2543Smrg * not in the foreground, but we don't want to receive them 1263706f2543Smrg * when another window is over us or we might show a tooltip) 1264706f2543Smrg */ 1265706f2543Smrg 1266706f2543Smrg e = xp_find_window(location.x, location.y, 0, &wid); 1267706f2543Smrg 1268706f2543Smrg if (e != XP_Success || (e == XP_Success && wid == 0)) 1269706f2543Smrg#endif 1270706f2543Smrg { 1271706f2543Smrg bgMouseLocation = location; 1272706f2543Smrg bgMouseLocationUpdated = TRUE; 1273706f2543Smrg return; 1274706f2543Smrg } 1275706f2543Smrg } 1276706f2543Smrg 1277706f2543Smrg if(bgMouseLocationUpdated) { 1278706f2543Smrg if(!(ev_type == MotionNotify && ev_button == 0)) { 1279706f2543Smrg DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x, 1280706f2543Smrg location.y, pressure, tilt.x, tilt.y); 1281706f2543Smrg } 1282706f2543Smrg bgMouseLocationUpdated = FALSE; 1283706f2543Smrg } 1284706f2543Smrg 1285706f2543Smrg DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x, location.y, 1286706f2543Smrg pressure, tilt.x, tilt.y); 1287706f2543Smrg 1288706f2543Smrg break; 1289706f2543Smrg 1290706f2543Smrg case NSTabletProximity: 1291706f2543Smrg switch([e pointingDeviceType]) { 1292706f2543Smrg case NSEraserPointingDevice: 1293706f2543Smrg darwinTabletCurrent=darwinTabletEraser; 1294706f2543Smrg break; 1295706f2543Smrg case NSPenPointingDevice: 1296706f2543Smrg darwinTabletCurrent=darwinTabletStylus; 1297706f2543Smrg break; 1298706f2543Smrg case NSCursorPointingDevice: 1299706f2543Smrg case NSUnknownPointingDevice: 1300706f2543Smrg default: 1301706f2543Smrg darwinTabletCurrent=darwinTabletCursor; 1302706f2543Smrg break; 1303706f2543Smrg } 1304706f2543Smrg 1305706f2543Smrg DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut, 1306706f2543Smrg location.x, location.y); 1307706f2543Smrg break; 1308706f2543Smrg 1309706f2543Smrg case NSScrollWheel: 1310706f2543Smrg { 1311706f2543Smrg float deltaX = [e deltaX]; 1312706f2543Smrg float deltaY = [e deltaY]; 1313706f2543Smrg#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0 1314706f2543Smrg /* If we're in the background, we need to send a MotionNotify event 1315706f2543Smrg * first, since we aren't getting them on background mouse motion 1316706f2543Smrg */ 1317706f2543Smrg if(!XQuartzServerVisible && noTestExtensions) { 1318706f2543Smrg bgMouseLocationUpdated = FALSE; 1319706f2543Smrg DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, location.x, 1320706f2543Smrg location.y, pressure, tilt.x, tilt.y); 1321706f2543Smrg } 1322706f2543Smrg#endif 1323706f2543Smrg#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 1324706f2543Smrg // TODO: Change 1117 to NSAppKitVersionNumber10_7 when it is defined 1325706f2543Smrg if(NSAppKitVersionNumber >= 1117 && XQuartzScrollInDeviceDirection && [e isDirectionInvertedFromDevice]) { 1326706f2543Smrg deltaX *= -1; 1327706f2543Smrg deltaY *= -1; 1328706f2543Smrg } 1329706f2543Smrg#endif 1330706f2543Smrg DarwinSendScrollEvents(deltaX, deltaY, location.x, location.y, 1331706f2543Smrg pressure, tilt.x, tilt.y); 1332706f2543Smrg break; 1333706f2543Smrg } 1334706f2543Smrg case NSKeyDown: case NSKeyUp: 1335706f2543Smrg { 1336706f2543Smrg /* XKB clobbers our keymap at startup, so we need to force it on the first keypress. 1337706f2543Smrg * TODO: Make this less of a kludge. 1338706f2543Smrg */ 1339706f2543Smrg static int force_resync_keymap = YES; 1340706f2543Smrg if(force_resync_keymap) { 1341706f2543Smrg DarwinSendDDXEvent(kXquartzReloadKeymap, 0); 1342706f2543Smrg force_resync_keymap = NO; 1343706f2543Smrg } 1344706f2543Smrg } 1345706f2543Smrg 1346706f2543Smrg if(darwinSyncKeymap) { 1347706f2543Smrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 1348706f2543Smrg TISInputSourceRef key_layout = TISCopyCurrentKeyboardLayoutInputSource(); 1349706f2543Smrg TISInputSourceRef clear; 1350706f2543Smrg if (CFEqual(key_layout, last_key_layout)) { 1351706f2543Smrg CFRelease(key_layout); 1352706f2543Smrg } else { 1353706f2543Smrg /* Swap/free thread-safely */ 1354706f2543Smrg clear = last_key_layout; 1355706f2543Smrg last_key_layout = key_layout; 1356706f2543Smrg CFRelease(clear); 1357706f2543Smrg#else 1358706f2543Smrg KeyboardLayoutRef key_layout; 1359706f2543Smrg KLGetCurrentKeyboardLayout(&key_layout); 1360706f2543Smrg if(key_layout != last_key_layout) { 1361706f2543Smrg last_key_layout = key_layout; 1362706f2543Smrg#endif 1363706f2543Smrg /* Update keyInfo */ 1364706f2543Smrg if (!QuartsResyncKeymap(TRUE)) { 1365706f2543Smrg fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n"); 1366706f2543Smrg } 1367706f2543Smrg } 1368706f2543Smrg } 1369706f2543Smrg 1370706f2543Smrg /* Avoid stuck keys on context switch */ 1371706f2543Smrg if(keyState[[e keyCode]] == [e type]) 1372706f2543Smrg return; 1373706f2543Smrg keyState[[e keyCode]] = [e type]; 1374706f2543Smrg 1375706f2543Smrg DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]); 1376706f2543Smrg break; 1377706f2543Smrg 1378706f2543Smrg default: break; /* for gcc */ 1379706f2543Smrg } 1380706f2543Smrg} 1381706f2543Smrg@end 1382