X11Application.m revision 1b5d61b8
14642e01fSmrg/* X11Application.m -- subclass of NSApplication to multiplex events 235c4bbdfSmrg * 335c4bbdfSmrg * Copyright (c) 2002-2012 Apple Inc. All rights reserved. 435c4bbdfSmrg * 535c4bbdfSmrg * Permission is hereby granted, free of charge, to any person 635c4bbdfSmrg * obtaining a copy of this software and associated documentation files 735c4bbdfSmrg * (the "Software"), to deal in the Software without restriction, 835c4bbdfSmrg * including without limitation the rights to use, copy, modify, merge, 935c4bbdfSmrg * publish, distribute, sublicense, and/or sell copies of the Software, 1035c4bbdfSmrg * and to permit persons to whom the Software is furnished to do so, 1135c4bbdfSmrg * subject to the following conditions: 1235c4bbdfSmrg * 1335c4bbdfSmrg * The above copyright notice and this permission notice shall be 1435c4bbdfSmrg * included in all copies or substantial portions of the Software. 1535c4bbdfSmrg * 1635c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1735c4bbdfSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1835c4bbdfSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1935c4bbdfSmrg * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT 2035c4bbdfSmrg * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 2135c4bbdfSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2235c4bbdfSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2335c4bbdfSmrg * DEALINGS IN THE SOFTWARE. 2435c4bbdfSmrg * 2535c4bbdfSmrg * Except as contained in this notice, the name(s) of the above 2635c4bbdfSmrg * copyright holders shall not be used in advertising or otherwise to 2735c4bbdfSmrg * promote the sale, use or other dealings in this Software without 2835c4bbdfSmrg * prior written authorization. 2935c4bbdfSmrg */ 304642e01fSmrg 314642e01fSmrg#include "sanitizedCarbon.h" 324642e01fSmrg 334642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 344642e01fSmrg#include <dix-config.h> 354642e01fSmrg#endif 364642e01fSmrg 374642e01fSmrg#include "quartzCommon.h" 384642e01fSmrg 394642e01fSmrg#import "X11Application.h" 404642e01fSmrg 414642e01fSmrg#include "darwin.h" 426747b715Smrg#include "quartz.h" 434642e01fSmrg#include "darwinEvents.h" 444642e01fSmrg#include "quartzKeyboard.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 5835c4bbdfSmrgextern int 5935c4bbdfSmrgxpbproxy_run(void); 604642e01fSmrg 6135c4bbdfSmrg#define DEFAULTS_FILE X11LIBDIR "/X11/xserver/Xquartz.plist" 624642e01fSmrg 634642e01fSmrg#ifndef XSERVER_VERSION 644642e01fSmrg#define XSERVER_VERSION "?" 654642e01fSmrg#endif 664642e01fSmrg 6735c4bbdfSmrg#ifdef HAVE_LIBDISPATCH 6835c4bbdfSmrg#include <dispatch/dispatch.h> 6935c4bbdfSmrg 7035c4bbdfSmrgstatic dispatch_queue_t eventTranslationQueue; 7135c4bbdfSmrg#endif 7235c4bbdfSmrg 7335c4bbdfSmrg#ifndef __has_feature 7435c4bbdfSmrg#define __has_feature(x) 0 7535c4bbdfSmrg#endif 7635c4bbdfSmrg 7735c4bbdfSmrg#ifndef CF_RETURNS_RETAINED 7835c4bbdfSmrg#if __has_feature(attribute_cf_returns_retained) 7935c4bbdfSmrg#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) 8035c4bbdfSmrg#else 8135c4bbdfSmrg#define CF_RETURNS_RETAINED 8235c4bbdfSmrg#endif 8335c4bbdfSmrg#endif 844642e01fSmrg 854642e01fSmrgextern Bool noTestExtensions; 8635c4bbdfSmrgextern Bool noRenderExtension; 874642e01fSmrg 884642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 894642e01fSmrgstatic TISInputSourceRef last_key_layout; 904642e01fSmrg#else 914642e01fSmrgstatic KeyboardLayoutRef last_key_layout; 924642e01fSmrg#endif 934642e01fSmrg 94475c125cSmrg/* This preference is only tested on Lion or later as it's not relevant to 95475c125cSmrg * earlier OS versions. 96475c125cSmrg */ 97475c125cSmrgBool XQuartzScrollInDeviceDirection = FALSE; 98475c125cSmrg 994642e01fSmrgextern int darwinFakeButtons; 1004642e01fSmrg 1016747b715Smrg/* Store the mouse location while in the background, and update X11's pointer 1026747b715Smrg * location when we become the foreground application 1036747b715Smrg */ 1046747b715Smrgstatic NSPoint bgMouseLocation; 1056747b715Smrgstatic BOOL bgMouseLocationUpdated = FALSE; 1066747b715Smrg 1074642e01fSmrgX11Application *X11App; 1084642e01fSmrg 1094642e01fSmrgCFStringRef app_prefs_domain_cfstr = NULL; 1104642e01fSmrg 11135c4bbdfSmrg#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | \ 11235c4bbdfSmrg NSAlternateKeyMask | NSCommandKeyMask) 1134642e01fSmrg 1144642e01fSmrg@interface X11Application (Private) 1154642e01fSmrg- (void) sendX11NSEvent:(NSEvent *)e; 1164642e01fSmrg@end 1174642e01fSmrg 1184642e01fSmrg@implementation X11Application 1194642e01fSmrg 1204642e01fSmrgtypedef struct message_struct message; 1214642e01fSmrgstruct message_struct { 1224642e01fSmrg mach_msg_header_t hdr; 1234642e01fSmrg SEL selector; 1244642e01fSmrg NSObject *arg; 1254642e01fSmrg}; 1264642e01fSmrg 1274642e01fSmrgstatic mach_port_t _port; 1284642e01fSmrg 1294642e01fSmrg/* Quartz mode initialization routine. This is often dynamically loaded 1304642e01fSmrg but is statically linked into this X server. */ 13135c4bbdfSmrgBool 13235c4bbdfSmrgQuartzModeBundleInit(void); 1334642e01fSmrg 13435c4bbdfSmrgstatic void 13535c4bbdfSmrginit_ports(void) 13635c4bbdfSmrg{ 1374642e01fSmrg kern_return_t r; 1384642e01fSmrg NSPort *p; 13935c4bbdfSmrg 1404642e01fSmrg if (_port != MACH_PORT_NULL) return; 14135c4bbdfSmrg 14235c4bbdfSmrg r = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &_port); 1434642e01fSmrg if (r != KERN_SUCCESS) return; 14435c4bbdfSmrg 1454642e01fSmrg p = [NSMachPort portWithMachPort:_port]; 1464642e01fSmrg [p setDelegate:NSApp]; 14735c4bbdfSmrg [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode: 14835c4bbdfSmrg NSDefaultRunLoopMode]; 1494642e01fSmrg} 1504642e01fSmrg 15135c4bbdfSmrgstatic void 15235c4bbdfSmrgmessage_kit_thread(SEL selector, NSObject *arg) 15335c4bbdfSmrg{ 1544642e01fSmrg message msg; 1554642e01fSmrg kern_return_t r; 15635c4bbdfSmrg 15735c4bbdfSmrg msg.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0); 15835c4bbdfSmrg msg.hdr.msgh_size = sizeof(msg); 1594642e01fSmrg msg.hdr.msgh_remote_port = _port; 1604642e01fSmrg msg.hdr.msgh_local_port = MACH_PORT_NULL; 1614642e01fSmrg msg.hdr.msgh_reserved = 0; 1624642e01fSmrg msg.hdr.msgh_id = 0; 16335c4bbdfSmrg 1644642e01fSmrg msg.selector = selector; 1654642e01fSmrg msg.arg = [arg retain]; 16635c4bbdfSmrg 16735c4bbdfSmrg r = mach_msg(&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size, 16835c4bbdfSmrg 0, MACH_PORT_NULL, 0, MACH_PORT_NULL); 1694642e01fSmrg if (r != KERN_SUCCESS) 17035c4bbdfSmrg ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r); 1714642e01fSmrg} 1724642e01fSmrg 17335c4bbdfSmrg- (void) handleMachMessage:(void *)_msg 17435c4bbdfSmrg{ 1754642e01fSmrg message *msg = _msg; 17635c4bbdfSmrg 1774642e01fSmrg [self performSelector:msg->selector withObject:msg->arg]; 1784642e01fSmrg [msg->arg release]; 1794642e01fSmrg} 1804642e01fSmrg 18135c4bbdfSmrg- (void) set_controller:obj 18235c4bbdfSmrg{ 1834642e01fSmrg if (_controller == nil) _controller = [obj retain]; 1844642e01fSmrg} 1854642e01fSmrg 18635c4bbdfSmrg- (void) dealloc 18735c4bbdfSmrg{ 1884642e01fSmrg if (_controller != nil) [_controller release]; 18935c4bbdfSmrg 1904642e01fSmrg if (_port != MACH_PORT_NULL) 19135c4bbdfSmrg mach_port_deallocate(mach_task_self(), _port); 19235c4bbdfSmrg 1934642e01fSmrg [super dealloc]; 1944642e01fSmrg} 1954642e01fSmrg 19635c4bbdfSmrg- (void) orderFrontStandardAboutPanel: (id) sender 19735c4bbdfSmrg{ 1984642e01fSmrg NSMutableDictionary *dict; 1994642e01fSmrg NSDictionary *infoDict; 2004642e01fSmrg NSString *tem; 20135c4bbdfSmrg 2024642e01fSmrg dict = [NSMutableDictionary dictionaryWithCapacity:3]; 2034642e01fSmrg infoDict = [[NSBundle mainBundle] infoDictionary]; 20435c4bbdfSmrg 20535c4bbdfSmrg [dict setObject: NSLocalizedString(@"The X Window System", @"About panel") 20635c4bbdfSmrg forKey:@"ApplicationName"]; 20735c4bbdfSmrg 2084642e01fSmrg tem = [infoDict objectForKey:@"CFBundleShortVersionString"]; 20935c4bbdfSmrg 2104642e01fSmrg [dict setObject:[NSString stringWithFormat:@"XQuartz %@", tem] 21135c4bbdfSmrg forKey:@"ApplicationVersion"]; 21235c4bbdfSmrg 21335c4bbdfSmrg [dict setObject:[NSString stringWithFormat:@"xorg-server %s", 21435c4bbdfSmrg XSERVER_VERSION] 21535c4bbdfSmrg forKey:@"Version"]; 2164642e01fSmrg 2174642e01fSmrg [self orderFrontStandardAboutPanelWithOptions: dict]; 2184642e01fSmrg} 2194642e01fSmrg 22035c4bbdfSmrg- (void) activateX:(OSX_BOOL)state 22135c4bbdfSmrg{ 22235c4bbdfSmrg if (_x_active == state) 22335c4bbdfSmrg return; 22435c4bbdfSmrg 22535c4bbdfSmrg DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active); 2264642e01fSmrg if (state) { 22735c4bbdfSmrg if (bgMouseLocationUpdated) { 22835c4bbdfSmrg DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, 22935c4bbdfSmrg bgMouseLocation.x, bgMouseLocation.y, 23035c4bbdfSmrg 0.0, 0.0); 2316747b715Smrg bgMouseLocationUpdated = FALSE; 2324642e01fSmrg } 2336747b715Smrg DarwinSendDDXEvent(kXquartzActivate, 0); 23435c4bbdfSmrg } 23535c4bbdfSmrg else { 2364642e01fSmrg 23735c4bbdfSmrg if (darwin_all_modifier_flags) 2384642e01fSmrg DarwinUpdateModKeys(0); 23935c4bbdfSmrg 24035c4bbdfSmrg DarwinInputReleaseButtonsAndKeys(darwinKeyboard); 24135c4bbdfSmrg DarwinInputReleaseButtonsAndKeys(darwinPointer); 24235c4bbdfSmrg DarwinInputReleaseButtonsAndKeys(darwinTabletCursor); 24335c4bbdfSmrg DarwinInputReleaseButtonsAndKeys(darwinTabletStylus); 24435c4bbdfSmrg DarwinInputReleaseButtonsAndKeys(darwinTabletEraser); 24535c4bbdfSmrg 2464642e01fSmrg DarwinSendDDXEvent(kXquartzDeactivate, 0); 2474642e01fSmrg } 2484642e01fSmrg 2494642e01fSmrg _x_active = state; 2504642e01fSmrg} 2514642e01fSmrg 25235c4bbdfSmrg- (void) became_key:(NSWindow *)win 25335c4bbdfSmrg{ 25435c4bbdfSmrg [self activateX:NO]; 2554642e01fSmrg} 2564642e01fSmrg 25735c4bbdfSmrg- (void) sendEvent:(NSEvent *)e 25835c4bbdfSmrg{ 2594642e01fSmrg OSX_BOOL for_appkit, for_x; 26035c4bbdfSmrg 2614642e01fSmrg /* By default pass down the responder chain and to X. */ 2624642e01fSmrg for_appkit = YES; 2634642e01fSmrg for_x = YES; 26435c4bbdfSmrg 2654642e01fSmrg switch ([e type]) { 26635c4bbdfSmrg case NSLeftMouseDown: 26735c4bbdfSmrg case NSRightMouseDown: 26835c4bbdfSmrg case NSOtherMouseDown: 26935c4bbdfSmrg case NSLeftMouseUp: 27035c4bbdfSmrg case NSRightMouseUp: 27135c4bbdfSmrg case NSOtherMouseUp: 27235c4bbdfSmrg if ([e window] != nil) { 27335c4bbdfSmrg /* Pointer event has an (AppKit) window. Probably something for the kit. */ 27435c4bbdfSmrg for_x = NO; 27535c4bbdfSmrg if (_x_active) [self activateX:NO]; 27635c4bbdfSmrg } 27735c4bbdfSmrg else if ([self modalWindow] == nil) { 2781b5d61b8Smrg /* Must be an X window. Tell appkit windows to resign main/key */ 27935c4bbdfSmrg for_appkit = NO; 28035c4bbdfSmrg 2811b5d61b8Smrg if (!_x_active && quartzProcs->IsX11Window([e windowNumber])) { 2821b5d61b8Smrg if ([self respondsToSelector:@selector(_setKeyWindow:)] && [self respondsToSelector:@selector(_setMainWindow:)]) { 2831b5d61b8Smrg NSWindow *keyWindow = [self keyWindow]; 2841b5d61b8Smrg if (keyWindow) { 2851b5d61b8Smrg [self _setKeyWindow:nil]; 2861b5d61b8Smrg [keyWindow resignKeyWindow]; 2871b5d61b8Smrg } 2881b5d61b8Smrg 2891b5d61b8Smrg NSWindow *mainWindow = [self mainWindow]; 2901b5d61b8Smrg if (mainWindow) { 2911b5d61b8Smrg [self _setMainWindow:nil]; 2921b5d61b8Smrg [mainWindow resignMainWindow]; 2931b5d61b8Smrg } 2941b5d61b8Smrg } else { 2951b5d61b8Smrg /* This has a side effect of causing background apps to steal focus from XQuartz. 2961b5d61b8Smrg * Unfortunately, there is no public and stable API to do what we want, but this 2971b5d61b8Smrg * is a decent fallback in the off chance that the above selectors get dropped 2981b5d61b8Smrg * in the future. 2991b5d61b8Smrg */ 3001b5d61b8Smrg [self deactivate]; 3011b5d61b8Smrg } 3021b5d61b8Smrg 3031b5d61b8Smrg [self activateX:YES]; 3044642e01fSmrg } 30535c4bbdfSmrg } 3064642e01fSmrg 30735c4bbdfSmrg /* We want to force sending to appkit if we're over the menu bar */ 30835c4bbdfSmrg if (!for_appkit) { 30935c4bbdfSmrg NSPoint NSlocation = [e locationInWindow]; 31035c4bbdfSmrg NSWindow *window = [e window]; 31135c4bbdfSmrg NSRect NSframe, NSvisibleFrame; 31235c4bbdfSmrg CGRect CGframe, CGvisibleFrame; 31335c4bbdfSmrg CGPoint CGlocation; 31435c4bbdfSmrg 31535c4bbdfSmrg if (window != nil) { 31635c4bbdfSmrg NSRect frame = [window frame]; 31735c4bbdfSmrg NSlocation.x += frame.origin.x; 31835c4bbdfSmrg NSlocation.y += frame.origin.y; 3194642e01fSmrg } 32035c4bbdfSmrg 32135c4bbdfSmrg NSframe = [[NSScreen mainScreen] frame]; 32235c4bbdfSmrg NSvisibleFrame = [[NSScreen mainScreen] visibleFrame]; 32335c4bbdfSmrg 32435c4bbdfSmrg CGframe = CGRectMake(NSframe.origin.x, NSframe.origin.y, 32535c4bbdfSmrg NSframe.size.width, NSframe.size.height); 32635c4bbdfSmrg CGvisibleFrame = CGRectMake(NSvisibleFrame.origin.x, 32735c4bbdfSmrg NSvisibleFrame.origin.y, 32835c4bbdfSmrg NSvisibleFrame.size.width, 32935c4bbdfSmrg NSvisibleFrame.size.height); 33035c4bbdfSmrg CGlocation = CGPointMake(NSlocation.x, NSlocation.y); 33135c4bbdfSmrg 33235c4bbdfSmrg if (CGRectContainsPoint(CGframe, CGlocation) && 33335c4bbdfSmrg !CGRectContainsPoint(CGvisibleFrame, CGlocation)) 33435c4bbdfSmrg for_appkit = YES; 33535c4bbdfSmrg } 33635c4bbdfSmrg 33735c4bbdfSmrg break; 33835c4bbdfSmrg 33935c4bbdfSmrg case NSKeyDown: 34035c4bbdfSmrg case NSKeyUp: 34135c4bbdfSmrg 34235c4bbdfSmrg if (_x_active) { 34335c4bbdfSmrg static BOOL do_swallow = NO; 34435c4bbdfSmrg static int swallow_keycode; 34535c4bbdfSmrg 34635c4bbdfSmrg if ([e type] == NSKeyDown) { 34735c4bbdfSmrg /* Before that though, see if there are any global 34835c4bbdfSmrg * shortcuts bound to it. */ 34935c4bbdfSmrg 35035c4bbdfSmrg if (darwinAppKitModMask &[e modifierFlags]) { 35135c4bbdfSmrg /* Override to force sending to Appkit */ 35235c4bbdfSmrg swallow_keycode = [e keyCode]; 35335c4bbdfSmrg do_swallow = YES; 35435c4bbdfSmrg for_x = NO; 3554642e01fSmrg#if XPLUGIN_VERSION >= 1 35635c4bbdfSmrg } 35735c4bbdfSmrg else if (XQuartzEnableKeyEquivalents && 35835c4bbdfSmrg xp_is_symbolic_hotkey_event([e eventRef])) { 35935c4bbdfSmrg swallow_keycode = [e keyCode]; 36035c4bbdfSmrg do_swallow = YES; 36135c4bbdfSmrg for_x = NO; 3624642e01fSmrg#endif 3634642e01fSmrg } 36435c4bbdfSmrg else if (XQuartzEnableKeyEquivalents && 36535c4bbdfSmrg [[self mainMenu] performKeyEquivalent:e]) { 36635c4bbdfSmrg swallow_keycode = [e keyCode]; 36735c4bbdfSmrg do_swallow = YES; 36835c4bbdfSmrg for_appkit = NO; 36935c4bbdfSmrg for_x = NO; 37035c4bbdfSmrg } 37135c4bbdfSmrg else if (!XQuartzIsRootless 37235c4bbdfSmrg && ([e modifierFlags] & ALL_KEY_MASKS) == 37335c4bbdfSmrg (NSCommandKeyMask | NSAlternateKeyMask) 37435c4bbdfSmrg && ([e keyCode] == 0 /*a*/ || [e keyCode] == 37535c4bbdfSmrg 53 /*Esc*/)) { 37635c4bbdfSmrg /* We have this here to force processing fullscreen 37735c4bbdfSmrg * toggle even if XQuartzEnableKeyEquivalents is disabled */ 37835c4bbdfSmrg swallow_keycode = [e keyCode]; 37935c4bbdfSmrg do_swallow = YES; 38035c4bbdfSmrg for_x = NO; 38135c4bbdfSmrg for_appkit = NO; 38235c4bbdfSmrg DarwinSendDDXEvent(kXquartzToggleFullscreen, 0); 38335c4bbdfSmrg } 38435c4bbdfSmrg else { 38535c4bbdfSmrg /* No kit window is focused, so send it to X. */ 38635c4bbdfSmrg for_appkit = NO; 3871b5d61b8Smrg 3881b5d61b8Smrg /* Reset our swallow state if we're seeing the same keyCode again. 3891b5d61b8Smrg * This can happen if we become !_x_active when the keyCode we 3901b5d61b8Smrg * intended to swallow is delivered. See: 3911b5d61b8Smrg * https://bugs.freedesktop.org/show_bug.cgi?id=92648 3921b5d61b8Smrg */ 3931b5d61b8Smrg if ([e keyCode] == swallow_keycode) { 3941b5d61b8Smrg do_swallow = NO; 3951b5d61b8Smrg } 39635c4bbdfSmrg } 39735c4bbdfSmrg } 39835c4bbdfSmrg else { /* KeyUp */ 39935c4bbdfSmrg /* If we saw a key equivalent on the down, don't pass 40035c4bbdfSmrg * the up through to X. */ 40135c4bbdfSmrg if (do_swallow && [e keyCode] == swallow_keycode) { 40235c4bbdfSmrg do_swallow = NO; 40335c4bbdfSmrg for_x = NO; 40435c4bbdfSmrg } 40535c4bbdfSmrg } 40635c4bbdfSmrg } 40735c4bbdfSmrg else { /* !_x_active */ 40835c4bbdfSmrg for_x = NO; 40935c4bbdfSmrg } 41035c4bbdfSmrg break; 41135c4bbdfSmrg 41235c4bbdfSmrg case NSFlagsChanged: 41335c4bbdfSmrg /* Don't tell X11 about modifiers changing while it's not active */ 41435c4bbdfSmrg if (!_x_active) 41535c4bbdfSmrg for_x = NO; 41635c4bbdfSmrg break; 41735c4bbdfSmrg 41835c4bbdfSmrg case NSAppKitDefined: 41935c4bbdfSmrg switch ([e subtype]) { 42035c4bbdfSmrg static BOOL x_was_active = NO; 42135c4bbdfSmrg 42235c4bbdfSmrg case NSApplicationActivatedEventType: 42335c4bbdfSmrg for_x = NO; 42435c4bbdfSmrg if ([e window] == nil && x_was_active) { 42535c4bbdfSmrg BOOL order_all_windows = YES, workspaces, ok; 42635c4bbdfSmrg for_appkit = NO; 42735c4bbdfSmrg 42835c4bbdfSmrg /* FIXME: This is a hack to avoid passing the event to AppKit which 42935c4bbdfSmrg * would result in it raising one of its windows. 43035c4bbdfSmrg */ 43135c4bbdfSmrg _appFlags._active = YES; 43235c4bbdfSmrg 43335c4bbdfSmrg [self set_front_process:nil]; 43435c4bbdfSmrg 43535c4bbdfSmrg /* Get the Spaces preference for SwitchOnActivate */ 43635c4bbdfSmrg (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock")); 43735c4bbdfSmrg workspaces = 43835c4bbdfSmrg CFPreferencesGetAppBooleanValue(CFSTR("workspaces"), 43935c4bbdfSmrg CFSTR( 44035c4bbdfSmrg "com.apple.dock"), 44135c4bbdfSmrg &ok); 44235c4bbdfSmrg if (!ok) 44335c4bbdfSmrg workspaces = NO; 44435c4bbdfSmrg 44535c4bbdfSmrg if (workspaces) { 44635c4bbdfSmrg (void)CFPreferencesAppSynchronize(CFSTR( 44735c4bbdfSmrg ".GlobalPreferences")); 44835c4bbdfSmrg order_all_windows = 44935c4bbdfSmrg CFPreferencesGetAppBooleanValue(CFSTR( 45035c4bbdfSmrg "AppleSpacesSwitchOnActivate"), 45135c4bbdfSmrg CFSTR( 45235c4bbdfSmrg ".GlobalPreferences"), 45335c4bbdfSmrg &ok); 45435c4bbdfSmrg if (!ok) 45535c4bbdfSmrg order_all_windows = YES; 45635c4bbdfSmrg } 45735c4bbdfSmrg 45835c4bbdfSmrg /* TODO: In the workspaces && !AppleSpacesSwitchOnActivate case, the windows are ordered 45935c4bbdfSmrg * correctly, but we need to activate the top window on this space if there is 46035c4bbdfSmrg * none active. 46135c4bbdfSmrg * 46235c4bbdfSmrg * If there are no active windows, and there are minimized windows, we should 46335c4bbdfSmrg * be restoring one of them. 46435c4bbdfSmrg */ 46535c4bbdfSmrg if ([e data2] & 0x10) { // 0x10 (bfCPSOrderAllWindowsForward) is set when we use cmd-tab or the dock icon 46635c4bbdfSmrg DarwinSendDDXEvent(kXquartzBringAllToFront, 1, 46735c4bbdfSmrg order_all_windows); 46835c4bbdfSmrg } 4694642e01fSmrg } 4704642e01fSmrg break; 47135c4bbdfSmrg 47235c4bbdfSmrg case 18: /* ApplicationDidReactivate */ 47335c4bbdfSmrg if (XQuartzFullscreenVisible) for_appkit = NO; 4744642e01fSmrg break; 4759ace9065Smrg 47635c4bbdfSmrg case NSApplicationDeactivatedEventType: 47735c4bbdfSmrg for_x = NO; 4789ace9065Smrg 47935c4bbdfSmrg x_was_active = _x_active; 48035c4bbdfSmrg if (_x_active) 48135c4bbdfSmrg [self activateX:NO]; 4824642e01fSmrg break; 48335c4bbdfSmrg } 48435c4bbdfSmrg break; 48535c4bbdfSmrg 48635c4bbdfSmrg default: 48735c4bbdfSmrg break; /* for gcc */ 4884642e01fSmrg } 48935c4bbdfSmrg 4904642e01fSmrg if (for_appkit) [super sendEvent:e]; 49135c4bbdfSmrg 49235c4bbdfSmrg if (for_x) { 49335c4bbdfSmrg#ifdef HAVE_LIBDISPATCH 49435c4bbdfSmrg dispatch_async(eventTranslationQueue, ^{ 49535c4bbdfSmrg [self sendX11NSEvent:e]; 49635c4bbdfSmrg }); 49735c4bbdfSmrg#else 49835c4bbdfSmrg [self sendX11NSEvent:e]; 49935c4bbdfSmrg#endif 50035c4bbdfSmrg } 5014642e01fSmrg} 5024642e01fSmrg 50335c4bbdfSmrg- (void) set_window_menu:(NSArray *)list 50435c4bbdfSmrg{ 50535c4bbdfSmrg [_controller set_window_menu:list]; 5064642e01fSmrg} 5074642e01fSmrg 50835c4bbdfSmrg- (void) set_window_menu_check:(NSNumber *)n 50935c4bbdfSmrg{ 51035c4bbdfSmrg [_controller set_window_menu_check:n]; 5114642e01fSmrg} 5124642e01fSmrg 51335c4bbdfSmrg- (void) set_apps_menu:(NSArray *)list 51435c4bbdfSmrg{ 51535c4bbdfSmrg [_controller set_apps_menu:list]; 5164642e01fSmrg} 5174642e01fSmrg 51835c4bbdfSmrg- (void) set_front_process:unused 51935c4bbdfSmrg{ 52035c4bbdfSmrg [NSApp activateIgnoringOtherApps:YES]; 5214642e01fSmrg 52235c4bbdfSmrg if ([self modalWindow] == nil) 52335c4bbdfSmrg [self activateX:YES]; 5244642e01fSmrg} 5254642e01fSmrg 52635c4bbdfSmrg- (void) set_can_quit:(NSNumber *)state 52735c4bbdfSmrg{ 52835c4bbdfSmrg [_controller set_can_quit:[state boolValue]]; 5294642e01fSmrg} 5304642e01fSmrg 53135c4bbdfSmrg- (void) server_ready:unused 53235c4bbdfSmrg{ 53335c4bbdfSmrg [_controller server_ready]; 5344642e01fSmrg} 5354642e01fSmrg 53635c4bbdfSmrg- (void) show_hide_menubar:(NSNumber *)state 53735c4bbdfSmrg{ 5384642e01fSmrg /* Also shows/hides the dock */ 5394642e01fSmrg if ([state boolValue]) 54035c4bbdfSmrg SetSystemUIMode(kUIModeNormal, 0); 5414642e01fSmrg else 54235c4bbdfSmrg SetSystemUIMode(kUIModeAllHidden, 54335c4bbdfSmrg XQuartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation" 5444642e01fSmrg} 5454642e01fSmrg 54635c4bbdfSmrg- (void) launch_client:(NSString *)cmd 54735c4bbdfSmrg{ 5486747b715Smrg (void)[_controller application:self openFile:cmd]; 5496747b715Smrg} 5504642e01fSmrg 5514642e01fSmrg/* user preferences */ 5524642e01fSmrg 5534642e01fSmrg/* Note that these functions only work for arrays whose elements 55435c4bbdfSmrg can be toll-free-bridged between NS and CF worlds. */ 5554642e01fSmrg 55635c4bbdfSmrgstatic const void * 55735c4bbdfSmrgcfretain(CFAllocatorRef a, const void *b) 55835c4bbdfSmrg{ 55935c4bbdfSmrg return CFRetain(b); 5604642e01fSmrg} 5614642e01fSmrg 56235c4bbdfSmrgstatic void 56335c4bbdfSmrgcfrelease(CFAllocatorRef a, const void *b) 56435c4bbdfSmrg{ 56535c4bbdfSmrg CFRelease(b); 5664642e01fSmrg} 5674642e01fSmrg 56835c4bbdfSmrgCF_RETURNS_RETAINED 56935c4bbdfSmrgstatic CFMutableArrayRef 57035c4bbdfSmrgnsarray_to_cfarray(NSArray *in) 57135c4bbdfSmrg{ 57235c4bbdfSmrg CFMutableArrayRef out; 57335c4bbdfSmrg CFArrayCallBacks cb; 57435c4bbdfSmrg NSObject *ns; 57535c4bbdfSmrg const CFTypeRef *cf; 57635c4bbdfSmrg int i, count; 57735c4bbdfSmrg 57835c4bbdfSmrg memset(&cb, 0, sizeof(cb)); 57935c4bbdfSmrg cb.version = 0; 58035c4bbdfSmrg cb.retain = cfretain; 58135c4bbdfSmrg cb.release = cfrelease; 58235c4bbdfSmrg 58335c4bbdfSmrg count = [in count]; 58435c4bbdfSmrg out = CFArrayCreateMutable(NULL, count, &cb); 58535c4bbdfSmrg 58635c4bbdfSmrg for (i = 0; i < count; i++) { 58735c4bbdfSmrg ns = [in objectAtIndex:i]; 58835c4bbdfSmrg 58935c4bbdfSmrg if ([ns isKindOfClass:[NSArray class]]) 59035c4bbdfSmrg cf = (CFTypeRef)nsarray_to_cfarray((NSArray *)ns); 59135c4bbdfSmrg else 59235c4bbdfSmrg cf = CFRetain((CFTypeRef)ns); 59335c4bbdfSmrg 59435c4bbdfSmrg CFArrayAppendValue(out, cf); 59535c4bbdfSmrg CFRelease(cf); 59635c4bbdfSmrg } 59735c4bbdfSmrg 59835c4bbdfSmrg return out; 59935c4bbdfSmrg} 6004642e01fSmrg 60135c4bbdfSmrgstatic NSMutableArray * 60235c4bbdfSmrgcfarray_to_nsarray(CFArrayRef in) 60335c4bbdfSmrg{ 60435c4bbdfSmrg NSMutableArray *out; 60535c4bbdfSmrg const CFTypeRef *cf; 60635c4bbdfSmrg NSObject *ns; 60735c4bbdfSmrg int i, count; 6084642e01fSmrg 60935c4bbdfSmrg count = CFArrayGetCount(in); 61035c4bbdfSmrg out = [[NSMutableArray alloc] initWithCapacity:count]; 6114642e01fSmrg 61235c4bbdfSmrg for (i = 0; i < count; i++) { 61335c4bbdfSmrg cf = CFArrayGetValueAtIndex(in, i); 6144642e01fSmrg 61535c4bbdfSmrg if (CFGetTypeID(cf) == CFArrayGetTypeID()) 61635c4bbdfSmrg ns = cfarray_to_nsarray((CFArrayRef)cf); 61735c4bbdfSmrg else 61835c4bbdfSmrg ns = [(id) cf retain]; 6194642e01fSmrg 62035c4bbdfSmrg [out addObject:ns]; 62135c4bbdfSmrg [ns release]; 62235c4bbdfSmrg } 6234642e01fSmrg 62435c4bbdfSmrg return out; 6254642e01fSmrg} 6264642e01fSmrg 62735c4bbdfSmrg- (CFPropertyListRef) prefs_get_copy:(NSString *)key 62835c4bbdfSmrg{ 62935c4bbdfSmrg CFPropertyListRef value; 63035c4bbdfSmrg 63135c4bbdfSmrg value = CFPreferencesCopyAppValue((CFStringRef)key, 63235c4bbdfSmrg app_prefs_domain_cfstr); 63335c4bbdfSmrg 63435c4bbdfSmrg if (value == NULL) { 63535c4bbdfSmrg static CFDictionaryRef defaults; 63635c4bbdfSmrg 63735c4bbdfSmrg if (defaults == NULL) { 63835c4bbdfSmrg CFStringRef error = NULL; 63935c4bbdfSmrg CFDataRef data; 64035c4bbdfSmrg CFURLRef url; 64135c4bbdfSmrg SInt32 error_code; 64235c4bbdfSmrg 64335c4bbdfSmrg url = (CFURLCreateFromFileSystemRepresentation 64435c4bbdfSmrg (NULL, (unsigned char *)DEFAULTS_FILE, 64535c4bbdfSmrg strlen(DEFAULTS_FILE), false)); 64635c4bbdfSmrg if (CFURLCreateDataAndPropertiesFromResource(NULL, url, &data, 64735c4bbdfSmrg NULL, NULL, 64835c4bbdfSmrg &error_code)) { 64935c4bbdfSmrg defaults = (CFPropertyListCreateFromXMLData 65035c4bbdfSmrg (NULL, data, 65135c4bbdfSmrg kCFPropertyListMutableContainersAndLeaves, 65235c4bbdfSmrg &error)); 65335c4bbdfSmrg if (error != NULL) CFRelease(error); 65435c4bbdfSmrg CFRelease(data); 65535c4bbdfSmrg } 65635c4bbdfSmrg CFRelease(url); 65735c4bbdfSmrg 65835c4bbdfSmrg if (defaults != NULL) { 65935c4bbdfSmrg NSMutableArray *apps, *elt; 66035c4bbdfSmrg int count, i; 66135c4bbdfSmrg NSString *name, *nname; 66235c4bbdfSmrg 66335c4bbdfSmrg /* Localize the names in the default apps menu. */ 66435c4bbdfSmrg 66535c4bbdfSmrg apps = 66635c4bbdfSmrg [(NSDictionary *) defaults objectForKey:@PREFS_APPSMENU]; 66735c4bbdfSmrg if (apps != nil) { 66835c4bbdfSmrg count = [apps count]; 66935c4bbdfSmrg for (i = 0; i < count; i++) { 67035c4bbdfSmrg elt = [apps objectAtIndex:i]; 67135c4bbdfSmrg if (elt != nil && 67235c4bbdfSmrg [elt isKindOfClass:[NSArray class]]) { 67335c4bbdfSmrg name = [elt objectAtIndex:0]; 67435c4bbdfSmrg if (name != nil) { 67535c4bbdfSmrg nname = NSLocalizedString(name, nil); 67635c4bbdfSmrg if (nname != nil && nname != name) 67735c4bbdfSmrg [elt replaceObjectAtIndex:0 withObject: 67835c4bbdfSmrg nname]; 67935c4bbdfSmrg } 68035c4bbdfSmrg } 68135c4bbdfSmrg } 68235c4bbdfSmrg } 68335c4bbdfSmrg } 68435c4bbdfSmrg } 68535c4bbdfSmrg 68635c4bbdfSmrg if (defaults != NULL) value = CFDictionaryGetValue(defaults, key); 68735c4bbdfSmrg if (value != NULL) CFRetain(value); 68835c4bbdfSmrg } 6894642e01fSmrg 69035c4bbdfSmrg return value; 69135c4bbdfSmrg} 6924642e01fSmrg 69335c4bbdfSmrg- (int) prefs_get_integer:(NSString *)key default:(int)def 69435c4bbdfSmrg{ 69535c4bbdfSmrg CFPropertyListRef value; 69635c4bbdfSmrg int ret; 6974642e01fSmrg 69835c4bbdfSmrg value = [self prefs_get_copy:key]; 6994642e01fSmrg 70035c4bbdfSmrg if (value != NULL && CFGetTypeID(value) == CFNumberGetTypeID()) 70135c4bbdfSmrg CFNumberGetValue(value, kCFNumberIntType, &ret); 70235c4bbdfSmrg else if (value != NULL && CFGetTypeID(value) == CFStringGetTypeID()) 70335c4bbdfSmrg ret = CFStringGetIntValue(value); 70435c4bbdfSmrg else 70535c4bbdfSmrg ret = def; 7064642e01fSmrg 70735c4bbdfSmrg if (value != NULL) CFRelease(value); 70835c4bbdfSmrg 70935c4bbdfSmrg return ret; 7104642e01fSmrg} 7114642e01fSmrg 71235c4bbdfSmrg- (const char *) prefs_get_string:(NSString *)key default:(const char *)def 71335c4bbdfSmrg{ 7144642e01fSmrg CFPropertyListRef value; 71535c4bbdfSmrg const char *ret = NULL; 71635c4bbdfSmrg 71735c4bbdfSmrg value = [self prefs_get_copy:key]; 71835c4bbdfSmrg 71935c4bbdfSmrg if (value != NULL && CFGetTypeID(value) == CFStringGetTypeID()) { 72035c4bbdfSmrg NSString *s = (NSString *)value; 72135c4bbdfSmrg 72235c4bbdfSmrg ret = [s UTF8String]; 7234642e01fSmrg } 7244642e01fSmrg 72535c4bbdfSmrg if (value != NULL) CFRelease(value); 7264642e01fSmrg 72735c4bbdfSmrg return ret != NULL ? ret : def; 7284642e01fSmrg} 7294642e01fSmrg 73035c4bbdfSmrg- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def 73135c4bbdfSmrg{ 7326747b715Smrg CFPropertyListRef value; 7336747b715Smrg NSURL *ret = NULL; 73435c4bbdfSmrg 7356747b715Smrg value = [self prefs_get_copy:key]; 73635c4bbdfSmrg 73735c4bbdfSmrg if (value != NULL && CFGetTypeID(value) == CFStringGetTypeID()) { 73835c4bbdfSmrg NSString *s = (NSString *)value; 7396747b715Smrg 7406747b715Smrg ret = [NSURL URLWithString:s]; 7416747b715Smrg [ret retain]; 7426747b715Smrg } 74335c4bbdfSmrg 74435c4bbdfSmrg if (value != NULL) CFRelease(value); 74535c4bbdfSmrg 7466747b715Smrg return ret != NULL ? ret : def; 7476747b715Smrg} 7486747b715Smrg 74935c4bbdfSmrg- (float) prefs_get_float:(NSString *)key default:(float)def 75035c4bbdfSmrg{ 75135c4bbdfSmrg CFPropertyListRef value; 75235c4bbdfSmrg float ret = def; 75335c4bbdfSmrg 75435c4bbdfSmrg value = [self prefs_get_copy:key]; 75535c4bbdfSmrg 75635c4bbdfSmrg if (value != NULL 75735c4bbdfSmrg && CFGetTypeID(value) == CFNumberGetTypeID() 75835c4bbdfSmrg && CFNumberIsFloatType(value)) 75935c4bbdfSmrg CFNumberGetValue(value, kCFNumberFloatType, &ret); 76035c4bbdfSmrg else if (value != NULL && CFGetTypeID(value) == CFStringGetTypeID()) 76135c4bbdfSmrg ret = CFStringGetDoubleValue(value); 76235c4bbdfSmrg 76335c4bbdfSmrg if (value != NULL) CFRelease(value); 76435c4bbdfSmrg 76535c4bbdfSmrg return ret; 7664642e01fSmrg} 7674642e01fSmrg 76835c4bbdfSmrg- (int) prefs_get_boolean:(NSString *)key default:(int)def 76935c4bbdfSmrg{ 77035c4bbdfSmrg CFPropertyListRef value; 77135c4bbdfSmrg int ret = def; 77235c4bbdfSmrg 77335c4bbdfSmrg value = [self prefs_get_copy:key]; 77435c4bbdfSmrg 77535c4bbdfSmrg if (value != NULL) { 77635c4bbdfSmrg if (CFGetTypeID(value) == CFNumberGetTypeID()) 77735c4bbdfSmrg CFNumberGetValue(value, kCFNumberIntType, &ret); 77835c4bbdfSmrg else if (CFGetTypeID(value) == CFBooleanGetTypeID()) 77935c4bbdfSmrg ret = CFBooleanGetValue(value); 78035c4bbdfSmrg else if (CFGetTypeID(value) == CFStringGetTypeID()) { 78135c4bbdfSmrg const char *tem = [(NSString *) value UTF8String]; 78235c4bbdfSmrg if (strcasecmp(tem, "true") == 0 || strcasecmp(tem, "yes") == 0) 78335c4bbdfSmrg ret = YES; 78435c4bbdfSmrg else 78535c4bbdfSmrg ret = NO; 78635c4bbdfSmrg } 78735c4bbdfSmrg 78835c4bbdfSmrg CFRelease(value); 7894642e01fSmrg } 79035c4bbdfSmrg return ret; 7914642e01fSmrg} 7924642e01fSmrg 79335c4bbdfSmrg- (NSArray *) prefs_get_array:(NSString *)key 79435c4bbdfSmrg{ 79535c4bbdfSmrg NSArray *ret = nil; 79635c4bbdfSmrg CFPropertyListRef value; 79735c4bbdfSmrg 79835c4bbdfSmrg value = [self prefs_get_copy:key]; 79935c4bbdfSmrg 80035c4bbdfSmrg if (value != NULL) { 80135c4bbdfSmrg if (CFGetTypeID(value) == CFArrayGetTypeID()) 80235c4bbdfSmrg ret = [cfarray_to_nsarray (value)autorelease]; 80335c4bbdfSmrg 80435c4bbdfSmrg CFRelease(value); 80535c4bbdfSmrg } 80635c4bbdfSmrg 80735c4bbdfSmrg return ret; 8084642e01fSmrg} 8094642e01fSmrg 81035c4bbdfSmrg- (void) prefs_set_integer:(NSString *)key value:(int)value 81135c4bbdfSmrg{ 8124642e01fSmrg CFNumberRef x; 81335c4bbdfSmrg 81435c4bbdfSmrg x = CFNumberCreate(NULL, kCFNumberIntType, &value); 81535c4bbdfSmrg 81635c4bbdfSmrg CFPreferencesSetValue((CFStringRef)key, (CFTypeRef)x, 81735c4bbdfSmrg app_prefs_domain_cfstr, 81835c4bbdfSmrg kCFPreferencesCurrentUser, 81935c4bbdfSmrg kCFPreferencesAnyHost); 82035c4bbdfSmrg 82135c4bbdfSmrg CFRelease(x); 8224642e01fSmrg} 8234642e01fSmrg 82435c4bbdfSmrg- (void) prefs_set_float:(NSString *)key value:(float)value 82535c4bbdfSmrg{ 8264642e01fSmrg CFNumberRef x; 82735c4bbdfSmrg 82835c4bbdfSmrg x = CFNumberCreate(NULL, kCFNumberFloatType, &value); 82935c4bbdfSmrg 83035c4bbdfSmrg CFPreferencesSetValue((CFStringRef)key, (CFTypeRef)x, 83135c4bbdfSmrg app_prefs_domain_cfstr, 83235c4bbdfSmrg kCFPreferencesCurrentUser, 83335c4bbdfSmrg kCFPreferencesAnyHost); 83435c4bbdfSmrg 83535c4bbdfSmrg CFRelease(x); 8364642e01fSmrg} 8374642e01fSmrg 83835c4bbdfSmrg- (void) prefs_set_boolean:(NSString *)key value:(int)value 83935c4bbdfSmrg{ 84035c4bbdfSmrg CFPreferencesSetValue( 84135c4bbdfSmrg (CFStringRef)key, 84235c4bbdfSmrg (CFTypeRef)(value ? kCFBooleanTrue 84335c4bbdfSmrg : kCFBooleanFalse), 84435c4bbdfSmrg app_prefs_domain_cfstr, 84535c4bbdfSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 84635c4bbdfSmrg 8474642e01fSmrg} 8484642e01fSmrg 84935c4bbdfSmrg- (void) prefs_set_array:(NSString *)key value:(NSArray *)value 85035c4bbdfSmrg{ 85135c4bbdfSmrg CFArrayRef cfarray; 85235c4bbdfSmrg 85335c4bbdfSmrg cfarray = nsarray_to_cfarray(value); 85435c4bbdfSmrg CFPreferencesSetValue((CFStringRef)key, 85535c4bbdfSmrg (CFTypeRef)cfarray, 85635c4bbdfSmrg app_prefs_domain_cfstr, 85735c4bbdfSmrg kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 85835c4bbdfSmrg CFRelease(cfarray); 8594642e01fSmrg} 8604642e01fSmrg 86135c4bbdfSmrg- (void) prefs_set_string:(NSString *)key value:(NSString *)value 86235c4bbdfSmrg{ 86335c4bbdfSmrg CFPreferencesSetValue((CFStringRef)key, (CFTypeRef)value, 86435c4bbdfSmrg app_prefs_domain_cfstr, kCFPreferencesCurrentUser, 86535c4bbdfSmrg kCFPreferencesAnyHost); 8664642e01fSmrg} 8674642e01fSmrg 86835c4bbdfSmrg- (void) prefs_synchronize 86935c4bbdfSmrg{ 87035c4bbdfSmrg CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); 8714642e01fSmrg} 8724642e01fSmrg 8734642e01fSmrg- (void) read_defaults 8744642e01fSmrg{ 8754642e01fSmrg NSString *nsstr; 8764642e01fSmrg const char *tem; 87735c4bbdfSmrg 8786747b715Smrg XQuartzRootlessDefault = [self prefs_get_boolean:@PREFS_ROOTLESS 87935c4bbdfSmrg default :XQuartzRootlessDefault]; 8806747b715Smrg XQuartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU 88135c4bbdfSmrg default :XQuartzFullscreenMenu]; 88235c4bbdfSmrg XQuartzFullscreenDisableHotkeys = 88335c4bbdfSmrg ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS 88435c4bbdfSmrg default :! 88535c4bbdfSmrg XQuartzFullscreenDisableHotkeys]; 8864642e01fSmrg darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS 88735c4bbdfSmrg default :darwinFakeButtons]; 8886747b715Smrg XQuartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT 88935c4bbdfSmrg default :XQuartzOptionSendsAlt]; 8906747b715Smrg 8914642e01fSmrg if (darwinFakeButtons) { 8924642e01fSmrg const char *fake2, *fake3; 8934642e01fSmrg 8944642e01fSmrg fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL]; 8954642e01fSmrg fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL]; 8964642e01fSmrg 89735c4bbdfSmrg if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList( 89835c4bbdfSmrg fake2, TRUE); 89935c4bbdfSmrg if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList( 90035c4bbdfSmrg fake3, TRUE); 9014642e01fSmrg } 9024642e01fSmrg 9034642e01fSmrg tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL]; 9044642e01fSmrg if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE); 90535c4bbdfSmrg 9064642e01fSmrg tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL]; 9074642e01fSmrg if (tem != NULL) { 9084642e01fSmrg windowItemModMask = DarwinParseModifierList(tem, FALSE); 90935c4bbdfSmrg } 91035c4bbdfSmrg else { 91135c4bbdfSmrg nsstr = NSLocalizedString(@"window item modifiers", 91235c4bbdfSmrg @"window item modifiers"); 91335c4bbdfSmrg if (nsstr != NULL) { 9144642e01fSmrg tem = [nsstr UTF8String]; 91535c4bbdfSmrg if ((tem != NULL) && strcmp(tem, "window item modifiers")) { 9164642e01fSmrg windowItemModMask = DarwinParseModifierList(tem, FALSE); 9174642e01fSmrg } 9184642e01fSmrg } 9194642e01fSmrg } 9204642e01fSmrg 9216747b715Smrg XQuartzEnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS 92235c4bbdfSmrg default : 92335c4bbdfSmrg XQuartzEnableKeyEquivalents]; 92435c4bbdfSmrg 9254642e01fSmrg darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP 92635c4bbdfSmrg default :darwinSyncKeymap]; 92735c4bbdfSmrg 9284642e01fSmrg darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH 92935c4bbdfSmrg default :darwinDesiredDepth]; 93035c4bbdfSmrg 9314642e01fSmrg noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS 93235c4bbdfSmrg default :FALSE]; 93335c4bbdfSmrg 93435c4bbdfSmrg noRenderExtension = ![self prefs_get_boolean:@PREFS_RENDER_EXTENSION 93535c4bbdfSmrg default :TRUE]; 93635c4bbdfSmrg 93735c4bbdfSmrg XQuartzScrollInDeviceDirection = 93835c4bbdfSmrg [self prefs_get_boolean:@PREFS_SCROLL_IN_DEV_DIRECTION 93935c4bbdfSmrg default : 94035c4bbdfSmrg XQuartzScrollInDeviceDirection]; 9416747b715Smrg 9426747b715Smrg#if XQUARTZ_SPARKLE 94335c4bbdfSmrg NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil]; 94435c4bbdfSmrg if (url) { 9456747b715Smrg [[SUUpdater sharedUpdater] setFeedURL:url]; 9466747b715Smrg [url release]; 9476747b715Smrg } 9486747b715Smrg#endif 9494642e01fSmrg} 9504642e01fSmrg 9514642e01fSmrg/* This will end up at the end of the responder chain. */ 95235c4bbdfSmrg- (void) copy:sender 95335c4bbdfSmrg{ 95435c4bbdfSmrg DarwinSendDDXEvent(kXquartzPasteboardNotify, 1, 95535c4bbdfSmrg AppleWMCopyToPasteboard); 9564642e01fSmrg} 9574642e01fSmrg 95835c4bbdfSmrg- (X11Controller *) controller 95935c4bbdfSmrg{ 9606747b715Smrg return _controller; 9616747b715Smrg} 9626747b715Smrg 96335c4bbdfSmrg- (OSX_BOOL) x_active 96435c4bbdfSmrg{ 9654642e01fSmrg return _x_active; 9664642e01fSmrg} 9674642e01fSmrg 9684642e01fSmrg@end 9694642e01fSmrg 9704642e01fSmrgstatic NSArray * 97135c4bbdfSmrgarray_with_strings_and_numbers(int nitems, const char **items, 97235c4bbdfSmrg const char *numbers) 97335c4bbdfSmrg{ 97435c4bbdfSmrg NSMutableArray *array, *subarray; 97535c4bbdfSmrg NSString *string, *number; 97635c4bbdfSmrg int i; 97735c4bbdfSmrg 97835c4bbdfSmrg /* (Can't autorelease on the X server thread) */ 97935c4bbdfSmrg 98035c4bbdfSmrg array = [[NSMutableArray alloc] initWithCapacity:nitems]; 98135c4bbdfSmrg 98235c4bbdfSmrg for (i = 0; i < nitems; i++) { 98335c4bbdfSmrg subarray = [[NSMutableArray alloc] initWithCapacity:2]; 98435c4bbdfSmrg 98535c4bbdfSmrg string = [[NSString alloc] initWithUTF8String:items[i]]; 98635c4bbdfSmrg [subarray addObject:string]; 98735c4bbdfSmrg [string release]; 98835c4bbdfSmrg 98935c4bbdfSmrg if (numbers[i] != 0) { 99035c4bbdfSmrg number = [[NSString alloc] initWithFormat:@"%d", numbers[i]]; 99135c4bbdfSmrg [subarray addObject:number]; 99235c4bbdfSmrg [number release]; 99335c4bbdfSmrg } 99435c4bbdfSmrg else 99535c4bbdfSmrg [subarray addObject:@""]; 99635c4bbdfSmrg 99735c4bbdfSmrg [array addObject:subarray]; 99835c4bbdfSmrg [subarray release]; 99935c4bbdfSmrg } 100035c4bbdfSmrg 100135c4bbdfSmrg return array; 10024642e01fSmrg} 10034642e01fSmrg 100435c4bbdfSmrgvoid 100535c4bbdfSmrgX11ApplicationSetWindowMenu(int nitems, const char **items, 100635c4bbdfSmrg const char *shortcuts) 100735c4bbdfSmrg{ 100835c4bbdfSmrg NSArray *array; 100935c4bbdfSmrg array = array_with_strings_and_numbers(nitems, items, shortcuts); 101035c4bbdfSmrg 101135c4bbdfSmrg /* Send the array of strings over to the appkit thread */ 101235c4bbdfSmrg 101335c4bbdfSmrg message_kit_thread(@selector (set_window_menu:), array); 101435c4bbdfSmrg [array release]; 10154642e01fSmrg} 10164642e01fSmrg 101735c4bbdfSmrgvoid 101835c4bbdfSmrgX11ApplicationSetWindowMenuCheck(int idx) 101935c4bbdfSmrg{ 102035c4bbdfSmrg NSNumber *n; 102135c4bbdfSmrg 102235c4bbdfSmrg n = [[NSNumber alloc] initWithInt:idx]; 102335c4bbdfSmrg 102435c4bbdfSmrg message_kit_thread(@selector (set_window_menu_check:), n); 102535c4bbdfSmrg 102635c4bbdfSmrg [n release]; 10274642e01fSmrg} 10284642e01fSmrg 102935c4bbdfSmrgvoid 103035c4bbdfSmrgX11ApplicationSetFrontProcess(void) 103135c4bbdfSmrg{ 103235c4bbdfSmrg message_kit_thread(@selector (set_front_process:), nil); 10334642e01fSmrg} 10344642e01fSmrg 103535c4bbdfSmrgvoid 103635c4bbdfSmrgX11ApplicationSetCanQuit(int state) 103735c4bbdfSmrg{ 10384642e01fSmrg NSNumber *n; 103935c4bbdfSmrg 10404642e01fSmrg n = [[NSNumber alloc] initWithBool:state]; 104135c4bbdfSmrg 104235c4bbdfSmrg message_kit_thread(@selector (set_can_quit:), n); 104335c4bbdfSmrg 10444642e01fSmrg [n release]; 10454642e01fSmrg} 10464642e01fSmrg 104735c4bbdfSmrgvoid 104835c4bbdfSmrgX11ApplicationServerReady(void) 104935c4bbdfSmrg{ 105035c4bbdfSmrg message_kit_thread(@selector (server_ready:), nil); 10514642e01fSmrg} 10524642e01fSmrg 105335c4bbdfSmrgvoid 105435c4bbdfSmrgX11ApplicationShowHideMenubar(int state) 105535c4bbdfSmrg{ 10564642e01fSmrg NSNumber *n; 105735c4bbdfSmrg 10584642e01fSmrg n = [[NSNumber alloc] initWithBool:state]; 105935c4bbdfSmrg 106035c4bbdfSmrg message_kit_thread(@selector (show_hide_menubar:), n); 106135c4bbdfSmrg 10624642e01fSmrg [n release]; 10634642e01fSmrg} 10644642e01fSmrg 106535c4bbdfSmrgvoid 106635c4bbdfSmrgX11ApplicationLaunchClient(const char *cmd) 106735c4bbdfSmrg{ 10686747b715Smrg NSString *string; 106935c4bbdfSmrg 10706747b715Smrg string = [[NSString alloc] initWithUTF8String:cmd]; 107135c4bbdfSmrg 107235c4bbdfSmrg message_kit_thread(@selector (launch_client:), string); 107335c4bbdfSmrg 10746747b715Smrg [string release]; 10756747b715Smrg} 10766747b715Smrg 10778223e2f2Smrg/* This is a special function in that it is run from the *SERVER* thread and 10788223e2f2Smrg * not the AppKit thread. We want to block entering a screen-capturing RandR 10798223e2f2Smrg * mode until we notify the user about how to get out if the X11 client crashes. 10808223e2f2Smrg */ 108135c4bbdfSmrgBool 108235c4bbdfSmrgX11ApplicationCanEnterRandR(void) 108335c4bbdfSmrg{ 10848223e2f2Smrg NSString *title, *msg; 108535c4bbdfSmrg 108635c4bbdfSmrg if ([X11App prefs_get_boolean:@PREFS_NO_RANDR_ALERT default:NO] || 108735c4bbdfSmrg XQuartzShieldingWindowLevel != 0) 10888223e2f2Smrg return TRUE; 10898223e2f2Smrg 109035c4bbdfSmrg title = NSLocalizedString(@"Enter RandR mode?", 109135c4bbdfSmrg @"Dialog title when switching to RandR"); 109235c4bbdfSmrg msg = NSLocalizedString( 109335c4bbdfSmrg @"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.", 109435c4bbdfSmrg @"Dialog when switching to RandR"); 109535c4bbdfSmrg 109635c4bbdfSmrg if (!XQuartzIsRootless) 10978223e2f2Smrg QuartzShowFullscreen(FALSE); 10988223e2f2Smrg 109935c4bbdfSmrg switch (NSRunAlertPanel(title, @"%@", 110035c4bbdfSmrg NSLocalizedString(@"Allow", 110135c4bbdfSmrg @""), 110235c4bbdfSmrg NSLocalizedString(@"Cancel", 110335c4bbdfSmrg @""), 110435c4bbdfSmrg NSLocalizedString(@"Always Allow", @""), msg)) { 110535c4bbdfSmrg case NSAlertOtherReturn: 110635c4bbdfSmrg [X11App prefs_set_boolean:@PREFS_NO_RANDR_ALERT value:YES]; 110735c4bbdfSmrg [X11App prefs_synchronize]; 110835c4bbdfSmrg 110935c4bbdfSmrg case NSAlertDefaultReturn: 111035c4bbdfSmrg return YES; 111135c4bbdfSmrg 111235c4bbdfSmrg default: 111335c4bbdfSmrg return NO; 11148223e2f2Smrg } 11158223e2f2Smrg} 11168223e2f2Smrg 111735c4bbdfSmrgstatic void 111835c4bbdfSmrgcheck_xinitrc(void) 111935c4bbdfSmrg{ 11204642e01fSmrg char *tem, buf[1024]; 11214642e01fSmrg NSString *msg; 112235c4bbdfSmrg 11234642e01fSmrg if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO]) 112435c4bbdfSmrg return; 112535c4bbdfSmrg 112635c4bbdfSmrg tem = getenv("HOME"); 11274642e01fSmrg if (tem == NULL) goto done; 112835c4bbdfSmrg 112935c4bbdfSmrg snprintf(buf, sizeof(buf), "%s/.xinitrc", tem); 113035c4bbdfSmrg if (access(buf, F_OK) != 0) 113135c4bbdfSmrg goto done; 113235c4bbdfSmrg 113335c4bbdfSmrg msg = 113435c4bbdfSmrg NSLocalizedString( 113535c4bbdfSmrg @"You have an existing ~/.xinitrc file.\n\n\ 113635c4bbdfSmrg Windows displayed by X11 applications may not have titlebars, or may look \ 113735c4bbdfSmrg different to windows displayed by native applications.\n\n\ 113835c4bbdfSmrg Would you like to move aside the existing file and use the standard X11 \ 113935c4bbdfSmrg environment the next time you start X11?" , 114035c4bbdfSmrg @"Startup xinitrc dialog"); 114135c4bbdfSmrg 114235c4bbdfSmrg if (NSAlertDefaultReturn == 114335c4bbdfSmrg NSRunAlertPanel(nil, @"%@", NSLocalizedString(@"Yes", @""), 114435c4bbdfSmrg NSLocalizedString(@"No", @""), nil, msg)) { 11454642e01fSmrg char buf2[1024]; 11464642e01fSmrg int i = -1; 11474642e01fSmrg 114835c4bbdfSmrg snprintf(buf2, sizeof(buf2), "%s.old", buf); 114935c4bbdfSmrg 115035c4bbdfSmrg for (i = 1; access(buf2, F_OK) == 0; i++) 115135c4bbdfSmrg snprintf(buf2, sizeof(buf2), "%s.old.%d", buf, i); 115235c4bbdfSmrg 115335c4bbdfSmrg rename(buf, buf2); 11544642e01fSmrg } 115535c4bbdfSmrg 115635c4bbdfSmrgdone: 11574642e01fSmrg [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES]; 11584642e01fSmrg [X11App prefs_synchronize]; 11594642e01fSmrg} 11604642e01fSmrg 116135c4bbdfSmrgstatic inline pthread_t 116235c4bbdfSmrgcreate_thread(void *(*func)(void *), void *arg) 116335c4bbdfSmrg{ 11646747b715Smrg pthread_attr_t attr; 11656747b715Smrg pthread_t tid; 116635c4bbdfSmrg 11676747b715Smrg pthread_attr_init(&attr); 11686747b715Smrg pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 11696747b715Smrg pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 11706747b715Smrg pthread_create(&tid, &attr, func, arg); 11716747b715Smrg pthread_attr_destroy(&attr); 117235c4bbdfSmrg 11736747b715Smrg return tid; 11746747b715Smrg} 11756747b715Smrg 117635c4bbdfSmrgstatic void * 117735c4bbdfSmrgxpbproxy_x_thread(void *args) 117835c4bbdfSmrg{ 11796747b715Smrg xpbproxy_run(); 11806747b715Smrg 118135c4bbdfSmrg ErrorF("xpbproxy thread is terminating unexpectedly.\n"); 11826747b715Smrg return NULL; 11836747b715Smrg} 11846747b715Smrg 118535c4bbdfSmrgvoid 118635c4bbdfSmrgX11ApplicationMain(int argc, char **argv, char **envp) 118735c4bbdfSmrg{ 11884642e01fSmrg NSAutoreleasePool *pool; 11894642e01fSmrg 11904642e01fSmrg#ifdef DEBUG 119135c4bbdfSmrg while (access("/tmp/x11-block", F_OK) == 0) sleep(1); 11924642e01fSmrg#endif 119335c4bbdfSmrg 11944642e01fSmrg pool = [[NSAutoreleasePool alloc] init]; 119535c4bbdfSmrg X11App = (X11Application *)[X11Application sharedApplication]; 119635c4bbdfSmrg init_ports(); 119735c4bbdfSmrg 119835c4bbdfSmrg app_prefs_domain_cfstr = 119935c4bbdfSmrg (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]; 12004642e01fSmrg 1201475c125cSmrg if (app_prefs_domain_cfstr == NULL) { 120235c4bbdfSmrg ErrorF( 120335c4bbdfSmrg "X11ApplicationMain: Unable to determine bundle identifier. Your installation of XQuartz may be broken.\n"); 120435c4bbdfSmrg app_prefs_domain_cfstr = CFSTR(BUNDLE_ID_PREFIX ".X11"); 1205475c125cSmrg } 1206475c125cSmrg 12074642e01fSmrg [NSApp read_defaults]; 12084642e01fSmrg [NSBundle loadNibNamed:@"main" owner:NSApp]; 12094642e01fSmrg [[NSNotificationCenter defaultCenter] addObserver:NSApp 121035c4bbdfSmrg selector:@selector (became_key:) 121135c4bbdfSmrg name: 121235c4bbdfSmrg NSWindowDidBecomeKeyNotification object:nil]; 12134642e01fSmrg 12144642e01fSmrg /* 12154642e01fSmrg * The xpr Quartz mode is statically linked into this server. 12164642e01fSmrg * Initialize all the Quartz functions. 12174642e01fSmrg */ 12184642e01fSmrg QuartzModeBundleInit(); 12194642e01fSmrg 12204642e01fSmrg /* Calculate the height of the menubar so we can avoid it. */ 122135c4bbdfSmrg aquaMenuBarHeight = [[NSApp mainMenu] menuBarHeight]; 122235c4bbdfSmrg#if ! __LP64__ 122335c4bbdfSmrg if (!aquaMenuBarHeight) { 122435c4bbdfSmrg aquaMenuBarHeight = [NSMenuView menuBarHeight]; 122535c4bbdfSmrg } 122635c4bbdfSmrg#endif 122735c4bbdfSmrg if (!aquaMenuBarHeight) { 122835c4bbdfSmrg NSScreen* primaryScreen = [[NSScreen screens] objectAtIndex:0]; 122935c4bbdfSmrg aquaMenuBarHeight = NSHeight([primaryScreen frame]) - NSMaxY([primaryScreen visibleFrame]); 123035c4bbdfSmrg } 123135c4bbdfSmrg 123235c4bbdfSmrg#ifdef HAVE_LIBDISPATCH 123335c4bbdfSmrg eventTranslationQueue = dispatch_queue_create( 123435c4bbdfSmrg BUNDLE_ID_PREFIX ".X11.NSEventsToX11EventsQueue", NULL); 123535c4bbdfSmrg assert(eventTranslationQueue != NULL); 123635c4bbdfSmrg#endif 12374642e01fSmrg 12384642e01fSmrg /* Set the key layout seed before we start the server */ 12394642e01fSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 124035c4bbdfSmrg last_key_layout = TISCopyCurrentKeyboardLayoutInputSource(); 12414642e01fSmrg 124235c4bbdfSmrg if (!last_key_layout) 124335c4bbdfSmrg ErrorF( 124435c4bbdfSmrg "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n"); 12454642e01fSmrg#else 12464642e01fSmrg KLGetCurrentKeyboardLayout(&last_key_layout); 124735c4bbdfSmrg if (!last_key_layout) 124835c4bbdfSmrg ErrorF( 124935c4bbdfSmrg "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n"); 12504642e01fSmrg#endif 12514642e01fSmrg 12526747b715Smrg if (!QuartsResyncKeymap(FALSE)) { 125335c4bbdfSmrg ErrorF("X11ApplicationMain: Could not build a valid keymap.\n"); 12544642e01fSmrg } 12554642e01fSmrg 12564642e01fSmrg /* Tell the server thread that it can proceed */ 12574642e01fSmrg QuartzInitServer(argc, argv, envp); 125835c4bbdfSmrg 12594642e01fSmrg /* This must be done after QuartzInitServer because it can result in 12604642e01fSmrg * an mieqEnqueue() - <rdar://problem/6300249> 12614642e01fSmrg */ 12624642e01fSmrg check_xinitrc(); 126335c4bbdfSmrg 12646747b715Smrg create_thread(xpbproxy_x_thread, NULL); 12656747b715Smrg 12666747b715Smrg#if XQUARTZ_SPARKLE 12676747b715Smrg [[X11App controller] setup_sparkle]; 12686747b715Smrg [[SUUpdater sharedUpdater] resetUpdateCycle]; 126935c4bbdfSmrg // [[SUUpdater sharedUpdater] checkForUpdates:X11App]; 12706747b715Smrg#endif 12716747b715Smrg 12726747b715Smrg [pool release]; 12734642e01fSmrg [NSApp run]; 12744642e01fSmrg /* not reached */ 12754642e01fSmrg} 12764642e01fSmrg 12774642e01fSmrg@implementation X11Application (Private) 12784642e01fSmrg 12794642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK 12804642e01fSmrg/* This is to workaround a bug in the VNC server where we sometimes see the L 12814642e01fSmrg * modifier and sometimes see no "side" 12824642e01fSmrg */ 128335c4bbdfSmrgstatic inline int 128435c4bbdfSmrgensure_flag(int flags, int device_independent, int device_dependents, 128535c4bbdfSmrg int device_dependent_default) 128635c4bbdfSmrg{ 128735c4bbdfSmrg if ((flags & device_independent) && 128835c4bbdfSmrg !(flags & device_dependents)) 12894642e01fSmrg flags |= device_dependent_default; 12904642e01fSmrg return flags; 12914642e01fSmrg} 12924642e01fSmrg#endif 12934642e01fSmrg 12949ace9065Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 129535c4bbdfSmrgstatic const char * 129635c4bbdfSmrguntrusted_str(NSEvent *e) 129735c4bbdfSmrg{ 129835c4bbdfSmrg switch ([e type]) { 129935c4bbdfSmrg case NSScrollWheel: 130035c4bbdfSmrg return "NSScrollWheel"; 130135c4bbdfSmrg 130235c4bbdfSmrg case NSTabletPoint: 130335c4bbdfSmrg return "NSTabletPoint"; 130435c4bbdfSmrg 130535c4bbdfSmrg case NSOtherMouseDown: 130635c4bbdfSmrg return "NSOtherMouseDown"; 130735c4bbdfSmrg 130835c4bbdfSmrg case NSOtherMouseUp: 130935c4bbdfSmrg return "NSOtherMouseUp"; 131035c4bbdfSmrg 131135c4bbdfSmrg case NSLeftMouseDown: 131235c4bbdfSmrg return "NSLeftMouseDown"; 131335c4bbdfSmrg 131435c4bbdfSmrg case NSLeftMouseUp: 131535c4bbdfSmrg return "NSLeftMouseUp"; 131635c4bbdfSmrg 131735c4bbdfSmrg default: 131835c4bbdfSmrg switch ([e subtype]) { 131935c4bbdfSmrg case NSTabletPointEventSubtype: 132035c4bbdfSmrg return "NSTabletPointEventSubtype"; 132135c4bbdfSmrg 132235c4bbdfSmrg case NSTabletProximityEventSubtype: 132335c4bbdfSmrg return "NSTabletProximityEventSubtype"; 132435c4bbdfSmrg 13259ace9065Smrg default: 132635c4bbdfSmrg return "Other"; 132735c4bbdfSmrg } 13289ace9065Smrg } 13299ace9065Smrg} 13309ace9065Smrg#endif 13319ace9065Smrg 133235c4bbdfSmrgextern void 13331b5d61b8Smrgwait_for_mieq_init(void); 133435c4bbdfSmrg 133535c4bbdfSmrg- (void) sendX11NSEvent:(NSEvent *)e 133635c4bbdfSmrg{ 133735c4bbdfSmrg NSPoint location = NSZeroPoint; 13384642e01fSmrg int ev_button, ev_type; 133935c4bbdfSmrg static float pressure = 0.0; // static so ProximityOut will have the value from the previous tablet event 134035c4bbdfSmrg static NSPoint tilt; // static so ProximityOut will have the value from the previous tablet event 134135c4bbdfSmrg static DeviceIntPtr darwinTabletCurrent = NULL; 134235c4bbdfSmrg static BOOL needsProximityIn = NO; // Do we do need to handle a pending ProximityIn once we have pressure/tilt? 13434642e01fSmrg DeviceIntPtr pDev; 13444642e01fSmrg int modifierFlags; 13456747b715Smrg BOOL isMouseOrTabletEvent, isTabletEvent; 13464642e01fSmrg 134735c4bbdfSmrg if (!darwinTabletCurrent) { 134835c4bbdfSmrg /* Ensure that the event system is initialized */ 13491b5d61b8Smrg wait_for_mieq_init(); 135035c4bbdfSmrg assert(darwinTabletStylus); 135135c4bbdfSmrg 135235c4bbdfSmrg tilt = NSZeroPoint; 135335c4bbdfSmrg darwinTabletCurrent = darwinTabletStylus; 135435c4bbdfSmrg } 135535c4bbdfSmrg 135635c4bbdfSmrg isMouseOrTabletEvent = [e type] == NSLeftMouseDown || 135735c4bbdfSmrg [e type] == NSOtherMouseDown || 135835c4bbdfSmrg [e type] == NSRightMouseDown || 135935c4bbdfSmrg [e type] == NSLeftMouseUp || 136035c4bbdfSmrg [e type] == NSOtherMouseUp || 136135c4bbdfSmrg [e type] == NSRightMouseUp || 136235c4bbdfSmrg [e type] == NSLeftMouseDragged || 136335c4bbdfSmrg [e type] == NSOtherMouseDragged || 136435c4bbdfSmrg [e type] == NSRightMouseDragged || 136535c4bbdfSmrg [e type] == NSMouseMoved || 136635c4bbdfSmrg [e type] == NSTabletPoint || 136735c4bbdfSmrg [e type] == NSScrollWheel; 13684642e01fSmrg 13696747b715Smrg isTabletEvent = ([e type] == NSTabletPoint) || 137035c4bbdfSmrg (isMouseOrTabletEvent && 137135c4bbdfSmrg ([e subtype] == NSTabletPointEventSubtype || 137235c4bbdfSmrg [e subtype] == NSTabletProximityEventSubtype)); 13734642e01fSmrg 137435c4bbdfSmrg if (isMouseOrTabletEvent) { 13756747b715Smrg static NSPoint lastpt; 13766747b715Smrg NSWindow *window = [e window]; 13776747b715Smrg NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame]; 137835c4bbdfSmrg BOOL hasUntrustedPointerDelta; 137935c4bbdfSmrg 13806747b715Smrg // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that 13816747b715Smrg // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets 13826747b715Smrg // are not normally used in cases where that bug would present itself, so this is a fair tradeoff 13836747b715Smrg // <rdar://problem/7111003> deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype 13846747b715Smrg // http://xquartz.macosforge.org/trac/ticket/288 13856747b715Smrg hasUntrustedPointerDelta = isTabletEvent; 138635c4bbdfSmrg 13876747b715Smrg // The deltaXY for middle click events also appear erroneous after fast user switching 13886747b715Smrg // <rdar://problem/7979468> deltaX and deltaY are incorrect for NSOtherMouseDown and NSOtherMouseUp after FUS 13896747b715Smrg // http://xquartz.macosforge.org/trac/ticket/389 139035c4bbdfSmrg hasUntrustedPointerDelta |= [e type] == NSOtherMouseDown || 139135c4bbdfSmrg [e type] == NSOtherMouseUp; 13926747b715Smrg 13936747b715Smrg // The deltaXY for scroll events correspond to the scroll delta, not the pointer delta 13946747b715Smrg // <rdar://problem/7989690> deltaXY for wheel events are being sent as mouse movement 139535c4bbdfSmrg hasUntrustedPointerDelta |= [e type] == NSScrollWheel; 13969ace9065Smrg 13979ace9065Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 139835c4bbdfSmrg hasUntrustedPointerDelta |= [e type] == NSLeftMouseDown || 139935c4bbdfSmrg [e type] == NSLeftMouseUp; 14009ace9065Smrg#endif 140135c4bbdfSmrg 140235c4bbdfSmrg if (window != nil) { 14036747b715Smrg NSRect frame = [window frame]; 14046747b715Smrg location = [e locationInWindow]; 14056747b715Smrg location.x += frame.origin.x; 14066747b715Smrg location.y += frame.origin.y; 14076747b715Smrg lastpt = location; 140835c4bbdfSmrg } 140935c4bbdfSmrg else if (hasUntrustedPointerDelta) { 14109ace9065Smrg#ifdef DEBUG_UNTRUSTED_POINTER_DELTA 14119ace9065Smrg ErrorF("--- Begin Event Debug ---\n"); 14129ace9065Smrg ErrorF("Event type: %s\n", untrusted_str(e)); 14139ace9065Smrg ErrorF("old lastpt: (%0.2f, %0.2f)\n", lastpt.x, lastpt.y); 14149ace9065Smrg ErrorF(" delta: (%0.2f, %0.2f)\n", [e deltaX], -[e deltaY]); 141535c4bbdfSmrg ErrorF(" location: (%0.2f, %0.2f)\n", lastpt.x + [e deltaX], 141635c4bbdfSmrg lastpt.y - [e deltaY]); 141735c4bbdfSmrg ErrorF("workaround: (%0.2f, %0.2f)\n", [e locationInWindow].x, 141835c4bbdfSmrg [e locationInWindow].y); 14199ace9065Smrg ErrorF("--- End Event Debug ---\n"); 14209ace9065Smrg 14219ace9065Smrg location.x = lastpt.x + [e deltaX]; 14229ace9065Smrg location.y = lastpt.y - [e deltaY]; 14239ace9065Smrg lastpt = [e locationInWindow]; 14249ace9065Smrg#else 14256747b715Smrg location = [e locationInWindow]; 14266747b715Smrg lastpt = location; 14279ace9065Smrg#endif 142835c4bbdfSmrg } 142935c4bbdfSmrg else { 14306747b715Smrg location.x = lastpt.x + [e deltaX]; 14316747b715Smrg location.y = lastpt.y - [e deltaY]; 14326747b715Smrg lastpt = [e locationInWindow]; 14336747b715Smrg } 143435c4bbdfSmrg 14356747b715Smrg /* Convert coordinate system */ 14366747b715Smrg location.y = (screen.origin.y + screen.size.height) - location.y; 14376747b715Smrg } 143835c4bbdfSmrg 14394642e01fSmrg modifierFlags = [e modifierFlags]; 144035c4bbdfSmrg 14414642e01fSmrg#ifdef NX_DEVICELCMDKEYMASK 14424642e01fSmrg /* This is to workaround a bug in the VNC server where we sometimes see the L 14434642e01fSmrg * modifier and sometimes see no "side" 14444642e01fSmrg */ 144535c4bbdfSmrg modifierFlags = ensure_flag(modifierFlags, NX_CONTROLMASK, 144635c4bbdfSmrg NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK, 144735c4bbdfSmrg NX_DEVICELCTLKEYMASK); 144835c4bbdfSmrg modifierFlags = ensure_flag(modifierFlags, NX_SHIFTMASK, 144935c4bbdfSmrg NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK, 145035c4bbdfSmrg NX_DEVICELSHIFTKEYMASK); 145135c4bbdfSmrg modifierFlags = ensure_flag(modifierFlags, NX_COMMANDMASK, 145235c4bbdfSmrg NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK, 145335c4bbdfSmrg NX_DEVICELCMDKEYMASK); 145435c4bbdfSmrg modifierFlags = ensure_flag(modifierFlags, NX_ALTERNATEMASK, 145535c4bbdfSmrg NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK, 145635c4bbdfSmrg NX_DEVICELALTKEYMASK); 14574642e01fSmrg#endif 14584642e01fSmrg 14596747b715Smrg modifierFlags &= darwin_all_modifier_mask; 14604642e01fSmrg 14614642e01fSmrg /* We don't receive modifier key events while out of focus, and 3button 14624642e01fSmrg * emulation mucks this up, so we need to check our modifier flag state 14634642e01fSmrg * on every event... ugg 14644642e01fSmrg */ 146535c4bbdfSmrg 146635c4bbdfSmrg if (darwin_all_modifier_flags != modifierFlags) 14674642e01fSmrg DarwinUpdateModKeys(modifierFlags); 14684642e01fSmrg 146935c4bbdfSmrg switch ([e type]) { 147035c4bbdfSmrg case NSLeftMouseDown: 147135c4bbdfSmrg ev_button = 1; 147235c4bbdfSmrg ev_type = ButtonPress; 147335c4bbdfSmrg goto handle_mouse; 147435c4bbdfSmrg 147535c4bbdfSmrg case NSOtherMouseDown: 147635c4bbdfSmrg ev_button = 2; 147735c4bbdfSmrg ev_type = ButtonPress; 147835c4bbdfSmrg goto handle_mouse; 147935c4bbdfSmrg 148035c4bbdfSmrg case NSRightMouseDown: 148135c4bbdfSmrg ev_button = 3; 148235c4bbdfSmrg ev_type = ButtonPress; 148335c4bbdfSmrg goto handle_mouse; 148435c4bbdfSmrg 148535c4bbdfSmrg case NSLeftMouseUp: 148635c4bbdfSmrg ev_button = 1; 148735c4bbdfSmrg ev_type = ButtonRelease; 148835c4bbdfSmrg goto handle_mouse; 148935c4bbdfSmrg 149035c4bbdfSmrg case NSOtherMouseUp: 149135c4bbdfSmrg ev_button = 2; 149235c4bbdfSmrg ev_type = ButtonRelease; 149335c4bbdfSmrg goto handle_mouse; 149435c4bbdfSmrg 149535c4bbdfSmrg case NSRightMouseUp: 149635c4bbdfSmrg ev_button = 3; 149735c4bbdfSmrg ev_type = ButtonRelease; 149835c4bbdfSmrg goto handle_mouse; 149935c4bbdfSmrg 150035c4bbdfSmrg case NSLeftMouseDragged: 150135c4bbdfSmrg ev_button = 1; 150235c4bbdfSmrg ev_type = MotionNotify; 150335c4bbdfSmrg goto handle_mouse; 150435c4bbdfSmrg 150535c4bbdfSmrg case NSOtherMouseDragged: 150635c4bbdfSmrg ev_button = 2; 150735c4bbdfSmrg ev_type = MotionNotify; 150835c4bbdfSmrg goto handle_mouse; 150935c4bbdfSmrg 151035c4bbdfSmrg case NSRightMouseDragged: 151135c4bbdfSmrg ev_button = 3; 151235c4bbdfSmrg ev_type = MotionNotify; 151335c4bbdfSmrg goto handle_mouse; 151435c4bbdfSmrg 151535c4bbdfSmrg case NSMouseMoved: 151635c4bbdfSmrg ev_button = 0; 151735c4bbdfSmrg ev_type = MotionNotify; 151835c4bbdfSmrg goto handle_mouse; 151935c4bbdfSmrg 152035c4bbdfSmrg case NSTabletPoint: 152135c4bbdfSmrg ev_button = 0; 152235c4bbdfSmrg ev_type = MotionNotify; 152335c4bbdfSmrg goto handle_mouse; 152435c4bbdfSmrg 152535c4bbdfSmrghandle_mouse: 152635c4bbdfSmrg pDev = darwinPointer; 152735c4bbdfSmrg 152835c4bbdfSmrg /* NSTabletPoint can have no subtype */ 152935c4bbdfSmrg if ([e type] != NSTabletPoint && 153035c4bbdfSmrg [e subtype] == NSTabletProximityEventSubtype) { 153135c4bbdfSmrg switch ([e pointingDeviceType]) { 153235c4bbdfSmrg case NSEraserPointingDevice: 153335c4bbdfSmrg darwinTabletCurrent = darwinTabletEraser; 153435c4bbdfSmrg break; 153535c4bbdfSmrg 153635c4bbdfSmrg case NSPenPointingDevice: 153735c4bbdfSmrg darwinTabletCurrent = darwinTabletStylus; 153835c4bbdfSmrg break; 153935c4bbdfSmrg 154035c4bbdfSmrg case NSCursorPointingDevice: 154135c4bbdfSmrg case NSUnknownPointingDevice: 154235c4bbdfSmrg default: 154335c4bbdfSmrg darwinTabletCurrent = darwinTabletCursor; 154435c4bbdfSmrg break; 15454642e01fSmrg } 15464642e01fSmrg 154735c4bbdfSmrg if ([e isEnteringProximity]) 154835c4bbdfSmrg needsProximityIn = YES; 154935c4bbdfSmrg else 155035c4bbdfSmrg DarwinSendTabletEvents(darwinTabletCurrent, ProximityOut, 0, 155135c4bbdfSmrg location.x, location.y, pressure, 155235c4bbdfSmrg tilt.x, tilt.y); 155335c4bbdfSmrg return; 155435c4bbdfSmrg } 155535c4bbdfSmrg 155635c4bbdfSmrg if ([e type] == NSTabletPoint || 155735c4bbdfSmrg [e subtype] == NSTabletPointEventSubtype) { 155835c4bbdfSmrg pressure = [e pressure]; 155935c4bbdfSmrg tilt = [e tilt]; 156035c4bbdfSmrg 156135c4bbdfSmrg pDev = darwinTabletCurrent; 156235c4bbdfSmrg 156335c4bbdfSmrg if (needsProximityIn) { 156435c4bbdfSmrg DarwinSendTabletEvents(darwinTabletCurrent, ProximityIn, 0, 156535c4bbdfSmrg location.x, location.y, pressure, 156635c4bbdfSmrg tilt.x, tilt.y); 156735c4bbdfSmrg 156835c4bbdfSmrg needsProximityIn = NO; 15694642e01fSmrg } 157035c4bbdfSmrg } 15714642e01fSmrg 157235c4bbdfSmrg if (!XQuartzServerVisible && noTestExtensions) { 15736747b715Smrg#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0 157435c4bbdfSmrg /* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */ 157535c4bbdfSmrg xp_window_id wid = 0; 157635c4bbdfSmrg xp_error err; 157735c4bbdfSmrg 157835c4bbdfSmrg /* Sigh. Need to check that we're really over one of 157935c4bbdfSmrg * our windows. (We need to receive pointer events while 158035c4bbdfSmrg * not in the foreground, but we don't want to receive them 158135c4bbdfSmrg * when another window is over us or we might show a tooltip) 158235c4bbdfSmrg */ 15836747b715Smrg 158435c4bbdfSmrg err = xp_find_window(location.x, location.y, 0, &wid); 15856747b715Smrg 158635c4bbdfSmrg if (err != XP_Success || (err == XP_Success && wid == 0)) 15874642e01fSmrg#endif 158835c4bbdfSmrg { 158935c4bbdfSmrg bgMouseLocation = location; 159035c4bbdfSmrg bgMouseLocationUpdated = TRUE; 159135c4bbdfSmrg return; 15926747b715Smrg } 159335c4bbdfSmrg } 159435c4bbdfSmrg 159535c4bbdfSmrg if (bgMouseLocationUpdated) { 159635c4bbdfSmrg if (!(ev_type == MotionNotify && ev_button == 0)) { 159735c4bbdfSmrg DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, 159835c4bbdfSmrg location.x, location.y, 159935c4bbdfSmrg 0.0, 0.0); 16006747b715Smrg } 160135c4bbdfSmrg bgMouseLocationUpdated = FALSE; 160235c4bbdfSmrg } 16036747b715Smrg 160435c4bbdfSmrg if (pDev == darwinPointer) { 160535c4bbdfSmrg DarwinSendPointerEvents(pDev, ev_type, ev_button, 160635c4bbdfSmrg location.x, location.y, 160735c4bbdfSmrg [e deltaX], [e deltaY]); 160835c4bbdfSmrg } else { 160935c4bbdfSmrg DarwinSendTabletEvents(pDev, ev_type, ev_button, 161035c4bbdfSmrg location.x, location.y, pressure, 161135c4bbdfSmrg tilt.x, tilt.y); 161235c4bbdfSmrg } 161335c4bbdfSmrg 161435c4bbdfSmrg break; 161535c4bbdfSmrg 161635c4bbdfSmrg case NSTabletProximity: 161735c4bbdfSmrg switch ([e pointingDeviceType]) { 161835c4bbdfSmrg case NSEraserPointingDevice: 161935c4bbdfSmrg darwinTabletCurrent = darwinTabletEraser; 16204642e01fSmrg break; 162135c4bbdfSmrg 162235c4bbdfSmrg case NSPenPointingDevice: 162335c4bbdfSmrg darwinTabletCurrent = darwinTabletStylus; 162435c4bbdfSmrg break; 162535c4bbdfSmrg 162635c4bbdfSmrg case NSCursorPointingDevice: 162735c4bbdfSmrg case NSUnknownPointingDevice: 162835c4bbdfSmrg default: 162935c4bbdfSmrg darwinTabletCurrent = darwinTabletCursor; 16304642e01fSmrg break; 163135c4bbdfSmrg } 163235c4bbdfSmrg 163335c4bbdfSmrg if ([e isEnteringProximity]) 163435c4bbdfSmrg needsProximityIn = YES; 163535c4bbdfSmrg else 163635c4bbdfSmrg DarwinSendTabletEvents(darwinTabletCurrent, ProximityOut, 0, 163735c4bbdfSmrg location.x, location.y, pressure, 163835c4bbdfSmrg tilt.x, tilt.y); 163935c4bbdfSmrg break; 164035c4bbdfSmrg 164135c4bbdfSmrg case NSScrollWheel: 164235c4bbdfSmrg { 164335c4bbdfSmrg#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 164435c4bbdfSmrg float deltaX = [e deltaX]; 164535c4bbdfSmrg float deltaY = [e deltaY]; 164635c4bbdfSmrg BOOL isContinuous = NO; 164735c4bbdfSmrg#else 164835c4bbdfSmrg CGFloat deltaX = [e deltaX]; 164935c4bbdfSmrg CGFloat deltaY = [e deltaY]; 165035c4bbdfSmrg CGEventRef cge = [e CGEvent]; 165135c4bbdfSmrg BOOL isContinuous = 165235c4bbdfSmrg CGEventGetIntegerValueField(cge, kCGScrollWheelEventIsContinuous); 165335c4bbdfSmrg 165435c4bbdfSmrg#if 0 165535c4bbdfSmrg /* Scale the scroll value by line height */ 165635c4bbdfSmrg CGEventSourceRef source = CGEventCreateSourceFromEvent(cge); 165735c4bbdfSmrg if (source) { 165835c4bbdfSmrg double lineHeight = CGEventSourceGetPixelsPerLine(source); 165935c4bbdfSmrg CFRelease(source); 16604642e01fSmrg 166135c4bbdfSmrg /* There's no real reason for the 1/5 ratio here other than that 166235c4bbdfSmrg * it feels like a good ratio after some testing. 166335c4bbdfSmrg */ 166435c4bbdfSmrg 166535c4bbdfSmrg deltaX *= lineHeight / 5.0; 166635c4bbdfSmrg deltaY *= lineHeight / 5.0; 166735c4bbdfSmrg } 166835c4bbdfSmrg#endif 166935c4bbdfSmrg#endif 167035c4bbdfSmrg 16716747b715Smrg#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0 167235c4bbdfSmrg /* If we're in the background, we need to send a MotionNotify event 167335c4bbdfSmrg * first, since we aren't getting them on background mouse motion 167435c4bbdfSmrg */ 167535c4bbdfSmrg if (!XQuartzServerVisible && noTestExtensions) { 167635c4bbdfSmrg bgMouseLocationUpdated = FALSE; 167735c4bbdfSmrg DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, 167835c4bbdfSmrg location.x, location.y, 167935c4bbdfSmrg 0.0, 0.0); 168035c4bbdfSmrg } 16816747b715Smrg#endif 1682475c125cSmrg#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 168335c4bbdfSmrg // TODO: Change 1117 to NSAppKitVersionNumber10_7 when it is defined 168435c4bbdfSmrg if (NSAppKitVersionNumber >= 1117 && 168535c4bbdfSmrg XQuartzScrollInDeviceDirection && 168635c4bbdfSmrg [e isDirectionInvertedFromDevice]) { 168735c4bbdfSmrg deltaX *= -1; 168835c4bbdfSmrg deltaY *= -1; 168935c4bbdfSmrg } 1690475c125cSmrg#endif 169135c4bbdfSmrg /* This hack is in place to better deal with "clicky" scroll wheels: 169235c4bbdfSmrg * http://xquartz.macosforge.org/trac/ticket/562 169335c4bbdfSmrg */ 169435c4bbdfSmrg if (!isContinuous) { 169535c4bbdfSmrg static NSTimeInterval lastScrollTime = 0.0; 169635c4bbdfSmrg 169735c4bbdfSmrg /* These store how much extra we have already scrolled. 169835c4bbdfSmrg * ie, this is how much we ignore on the next event. 169935c4bbdfSmrg */ 170035c4bbdfSmrg static double deficit_x = 0.0; 170135c4bbdfSmrg static double deficit_y = 0.0; 170235c4bbdfSmrg 170335c4bbdfSmrg /* If we have past a second since the last scroll, wipe the slate 170435c4bbdfSmrg * clean 170535c4bbdfSmrg */ 170635c4bbdfSmrg if ([e timestamp] - lastScrollTime > 1.0) { 170735c4bbdfSmrg deficit_x = deficit_y = 0.0; 1708475c125cSmrg } 170935c4bbdfSmrg lastScrollTime = [e timestamp]; 171035c4bbdfSmrg 171135c4bbdfSmrg if (deltaX != 0.0) { 171235c4bbdfSmrg /* If we changed directions, wipe the slate clean */ 171335c4bbdfSmrg if ((deficit_x < 0.0 && deltaX > 0.0) || 171435c4bbdfSmrg (deficit_x > 0.0 && deltaX < 0.0)) { 171535c4bbdfSmrg deficit_x = 0.0; 171635c4bbdfSmrg } 171735c4bbdfSmrg 171835c4bbdfSmrg /* Eat up the deficit, but ensure that something is 171935c4bbdfSmrg * always sent 17206747b715Smrg */ 172135c4bbdfSmrg if (fabs(deltaX) > fabs(deficit_x)) { 172235c4bbdfSmrg deltaX -= deficit_x; 172335c4bbdfSmrg 172435c4bbdfSmrg if (deltaX > 0.0) { 172535c4bbdfSmrg deficit_x = ceil(deltaX) - deltaX; 172635c4bbdfSmrg deltaX = ceil(deltaX); 172735c4bbdfSmrg } else { 172835c4bbdfSmrg deficit_x = floor(deltaX) - deltaX; 172935c4bbdfSmrg deltaX = floor(deltaX); 173035c4bbdfSmrg } 173135c4bbdfSmrg } else { 173235c4bbdfSmrg deficit_x -= deltaX; 173335c4bbdfSmrg 173435c4bbdfSmrg if (deltaX > 0.0) { 173535c4bbdfSmrg deltaX = 1.0; 173635c4bbdfSmrg } else { 173735c4bbdfSmrg deltaX = -1.0; 173835c4bbdfSmrg } 173935c4bbdfSmrg 174035c4bbdfSmrg deficit_x += deltaX; 17416747b715Smrg } 17426747b715Smrg } 17436747b715Smrg 174435c4bbdfSmrg if (deltaY != 0.0) { 174535c4bbdfSmrg /* If we changed directions, wipe the slate clean */ 174635c4bbdfSmrg if ((deficit_y < 0.0 && deltaY > 0.0) || 174735c4bbdfSmrg (deficit_y > 0.0 && deltaY < 0.0)) { 174835c4bbdfSmrg deficit_y = 0.0; 174935c4bbdfSmrg } 175035c4bbdfSmrg 175135c4bbdfSmrg /* Eat up the deficit, but ensure that something is 175235c4bbdfSmrg * always sent 175335c4bbdfSmrg */ 175435c4bbdfSmrg if (fabs(deltaY) > fabs(deficit_y)) { 175535c4bbdfSmrg deltaY -= deficit_y; 175635c4bbdfSmrg 175735c4bbdfSmrg if (deltaY > 0.0) { 175835c4bbdfSmrg deficit_y = ceil(deltaY) - deltaY; 175935c4bbdfSmrg deltaY = ceil(deltaY); 176035c4bbdfSmrg } else { 176135c4bbdfSmrg deficit_y = floor(deltaY) - deltaY; 176235c4bbdfSmrg deltaY = floor(deltaY); 176335c4bbdfSmrg } 17644642e01fSmrg } else { 176535c4bbdfSmrg deficit_y -= deltaY; 176635c4bbdfSmrg 176735c4bbdfSmrg if (deltaY > 0.0) { 176835c4bbdfSmrg deltaY = 1.0; 176935c4bbdfSmrg } else { 177035c4bbdfSmrg deltaY = -1.0; 177135c4bbdfSmrg } 177235c4bbdfSmrg 177335c4bbdfSmrg deficit_y += deltaY; 177435c4bbdfSmrg } 177535c4bbdfSmrg } 177635c4bbdfSmrg } 177735c4bbdfSmrg 177835c4bbdfSmrg DarwinSendScrollEvents(deltaX, deltaY); 177935c4bbdfSmrg break; 178035c4bbdfSmrg } 178135c4bbdfSmrg 178235c4bbdfSmrg case NSKeyDown: 178335c4bbdfSmrg case NSKeyUp: 178435c4bbdfSmrg { 178535c4bbdfSmrg /* XKB clobbers our keymap at startup, so we need to force it on the first keypress. 178635c4bbdfSmrg * TODO: Make this less of a kludge. 178735c4bbdfSmrg */ 178835c4bbdfSmrg static int force_resync_keymap = YES; 178935c4bbdfSmrg if (force_resync_keymap) { 179035c4bbdfSmrg DarwinSendDDXEvent(kXquartzReloadKeymap, 0); 179135c4bbdfSmrg force_resync_keymap = NO; 179235c4bbdfSmrg } 179335c4bbdfSmrg } 179435c4bbdfSmrg 179535c4bbdfSmrg if (darwinSyncKeymap) { 179635c4bbdfSmrg#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 179735c4bbdfSmrg TISInputSourceRef key_layout = 179835c4bbdfSmrg TISCopyCurrentKeyboardLayoutInputSource(); 179935c4bbdfSmrg TISInputSourceRef clear; 180035c4bbdfSmrg if (CFEqual(key_layout, last_key_layout)) { 180135c4bbdfSmrg CFRelease(key_layout); 180235c4bbdfSmrg } 180335c4bbdfSmrg else { 180435c4bbdfSmrg /* Swap/free thread-safely */ 180535c4bbdfSmrg clear = last_key_layout; 180635c4bbdfSmrg last_key_layout = key_layout; 180735c4bbdfSmrg CFRelease(clear); 18084642e01fSmrg#else 180935c4bbdfSmrg KeyboardLayoutRef key_layout; 181035c4bbdfSmrg KLGetCurrentKeyboardLayout(&key_layout); 181135c4bbdfSmrg if (key_layout != last_key_layout) { 181235c4bbdfSmrg last_key_layout = key_layout; 18134642e01fSmrg#endif 181435c4bbdfSmrg /* Update keyInfo */ 181535c4bbdfSmrg if (!QuartsResyncKeymap(TRUE)) { 181635c4bbdfSmrg ErrorF( 181735c4bbdfSmrg "sendX11NSEvent: Could not build a valid keymap.\n"); 18184642e01fSmrg } 18194642e01fSmrg } 182035c4bbdfSmrg } 18214642e01fSmrg 182235c4bbdfSmrg ev_type = ([e type] == NSKeyDown) ? KeyPress : KeyRelease; 182335c4bbdfSmrg DarwinSendKeyboardEvents(ev_type, [e keyCode]); 182435c4bbdfSmrg break; 18254642e01fSmrg 182635c4bbdfSmrg default: 182735c4bbdfSmrg break; /* for gcc */ 182835c4bbdfSmrg } 18294642e01fSmrg} 18304642e01fSmrg@end 1831