aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xorg-server/dix/getevents.c21
-rw-r--r--xorg-server/dix/window.c2
-rw-r--r--xorg-server/hw/xquartz/X11Application.m2542
-rw-r--r--xorg-server/hw/xquartz/darwinEvents.c4
-rw-r--r--xorg-server/hw/xquartz/quartz.c4
-rw-r--r--xorg-server/hw/xquartz/xpr/xprEvent.c162
-rw-r--r--xorg-server/hw/xquartz/xpr/xprFrame.c10
-rw-r--r--xorg-server/miext/rootless/rootless.h900
-rw-r--r--xorg-server/miext/rootless/rootlessWindow.c12
9 files changed, 1849 insertions, 1808 deletions
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index 92e96b0bb..171868e26 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -927,17 +927,19 @@ GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code)
int
GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
int key_code, int first_valuator,
- int num_valuators, int *valuators) {
+ int num_valuators, int *valuators_in) {
int num_events = 0;
CARD32 ms = 0;
DeviceEvent *event;
RawDeviceEvent *raw;
+ int valuators[MAX_VALUATORS];
/* refuse events from disabled devices */
if (!pDev || !pDev->enabled)
return 0;
if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
+ num_valuators > MAX_VALUATORS ||
(type != KeyPress && type != KeyRelease) ||
(key_code < 8 || key_code > 255))
return 0;
@@ -962,6 +964,8 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
events++;
num_events++;
+ memcpy(valuators, valuators_in, num_valuators * sizeof(int));
+
init_raw(pDev, raw, ms, type, key_code);
set_raw_valuators(raw, first_valuator, num_valuators, valuators,
raw->valuators.data_raw);
@@ -1082,7 +1086,7 @@ transformAbsolute(DeviceIntPtr dev, int v[MAX_VALUATORS])
int
GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
int flags, int first_valuator, int num_valuators,
- int *valuators) {
+ int *valuators_in) {
int num_events = 1;
CARD32 ms;
DeviceEvent *event;
@@ -1091,6 +1095,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
cx, cy; /* only screen coordinates */
float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
ScreenPtr scr = miPointerGetScreen(pDev);
+ int valuators[MAX_VALUATORS];
/* refuse events from disabled devices */
if (!pDev->enabled)
@@ -1099,6 +1104,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
ms = GetTimeInMillis(); /* before pointer update to help precision */
if (!scr || !pDev->valuator || first_valuator < 0 ||
+ num_valuators > MAX_VALUATORS ||
((num_valuators + first_valuator) > pDev->valuator->numAxes) ||
(type != MotionNotify && type != ButtonPress && type != ButtonRelease) ||
(type != MotionNotify && !pDev->button) ||
@@ -1112,6 +1118,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
events++;
num_events++;
+ memcpy(valuators, valuators_in, num_valuators * sizeof(int));
+
init_raw(pDev, raw, ms, type, buttons);
set_raw_valuators(raw, first_valuator, num_valuators, valuators,
raw->valuators.data_raw);
@@ -1198,10 +1206,11 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
*/
int
GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
- int first_valuator, int num_valuators, int *valuators)
+ int first_valuator, int num_valuators, int *valuators_in)
{
int num_events = 1;
DeviceEvent *event;
+ int valuators[MAX_VALUATORS];
/* refuse events from disabled devices */
if (!pDev->enabled)
@@ -1217,7 +1226,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
num_valuators = 0;
/* You fail. */
- if (first_valuator < 0 ||
+ if (first_valuator < 0 || num_valuators > MAX_VALUATORS ||
(num_valuators + first_valuator) > pDev->valuator->numAxes)
return 0;
@@ -1227,8 +1236,10 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
init_event(pDev, event, GetTimeInMillis());
event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
- if (num_valuators)
+ if (num_valuators) {
+ memcpy(valuators, valuators_in, num_valuators * sizeof(int));
clipValuators(pDev, first_valuator, num_valuators, valuators);
+ }
set_valuators(pDev, event, first_valuator, num_valuators, valuators);
diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c
index 62f790c08..f4d6ca5d8 100644
--- a/xorg-server/dix/window.c
+++ b/xorg-server/dix/window.c
@@ -921,6 +921,8 @@ DeleteWindow(pointer value, XID wid)
if (pWin->prevSib)
pWin->prevSib->nextSib = pWin->nextSib;
}
+ else
+ pWin->drawable.pScreen->root = NULL;
dixFreeObjectWithPrivates(pWin, PRIVATE_WINDOW);
return Success;
}
diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m
index 805ed9933..fcd6b3eef 100644
--- a/xorg-server/hw/xquartz/X11Application.m
+++ b/xorg-server/hw/xquartz/X11Application.m
@@ -1,1264 +1,1278 @@
-/* X11Application.m -- subclass of NSApplication to multiplex events
-
- Copyright (c) 2002-2008 Apple Inc.
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation files
- (the "Software"), to deal in the Software without restriction,
- including without limitation the rights to use, copy, modify, merge,
- publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
- HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
-
- Except as contained in this notice, the name(s) of the above
- copyright holders shall not be used in advertising or otherwise to
- promote the sale, use or other dealings in this Software without
- prior written authorization. */
-
-#include "sanitizedCarbon.h"
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "quartzCommon.h"
-
-#import "X11Application.h"
-
-#include "darwin.h"
-#include "darwinEvents.h"
-#include "quartzKeyboard.h"
-#include "quartz.h"
-#include <X11/extensions/applewmconst.h>
-#include "micmap.h"
-#include "exglobals.h"
-
-#include <mach/mach.h>
-#include <unistd.h>
-#include <AvailabilityMacros.h>
-
-#include <Xplugin.h>
-
-// pbproxy/pbproxy.h
-extern int xpbproxy_run (void);
-
-#define DEFAULTS_FILE X11LIBDIR"/X11/xserver/Xquartz.plist"
-
-#ifndef XSERVER_VERSION
-#define XSERVER_VERSION "?"
-#endif
-
-/* Stuck modifier / button state... force release when we context switch */
-static NSEventType keyState[NUM_KEYCODES];
-
-int X11EnableKeyEquivalents = TRUE, quartzFullscreenMenu = FALSE;
-int quartzHasRoot = FALSE, quartzEnableRootless = TRUE;
-
-extern Bool noTestExtensions;
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
-static TISInputSourceRef last_key_layout;
-#else
-static KeyboardLayoutRef last_key_layout;
-#endif
-
-extern int darwinFakeButtons;
-
-/* Store the mouse location while in the background, and update X11's pointer
- * location when we become the foreground application
- */
-static NSPoint bgMouseLocation;
-static BOOL bgMouseLocationUpdated = FALSE;
-
-X11Application *X11App;
-
-CFStringRef app_prefs_domain_cfstr = NULL;
-
-#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask)
-
-@interface X11Application (Private)
-- (void) sendX11NSEvent:(NSEvent *)e;
-@end
-
-@implementation X11Application
-
-typedef struct message_struct message;
-struct message_struct {
- mach_msg_header_t hdr;
- SEL selector;
- NSObject *arg;
-};
-
-static mach_port_t _port;
-
-/* Quartz mode initialization routine. This is often dynamically loaded
- but is statically linked into this X server. */
-Bool QuartzModeBundleInit(void);
-
-static void init_ports (void) {
- kern_return_t r;
- NSPort *p;
-
- if (_port != MACH_PORT_NULL) return;
-
- r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port);
- if (r != KERN_SUCCESS) return;
-
- p = [NSMachPort portWithMachPort:_port];
- [p setDelegate:NSApp];
- [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
-}
-
-static void message_kit_thread (SEL selector, NSObject *arg) {
- message msg;
- kern_return_t r;
-
- msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
- msg.hdr.msgh_size = sizeof (msg);
- msg.hdr.msgh_remote_port = _port;
- msg.hdr.msgh_local_port = MACH_PORT_NULL;
- msg.hdr.msgh_reserved = 0;
- msg.hdr.msgh_id = 0;
-
- msg.selector = selector;
- msg.arg = [arg retain];
-
- r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size,
- 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
- if (r != KERN_SUCCESS)
- ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r);
-}
-
-- (void) handleMachMessage:(void *)_msg {
- message *msg = _msg;
-
- [self performSelector:msg->selector withObject:msg->arg];
- [msg->arg release];
-}
-
-- (void) set_controller:obj {
- if (_controller == nil) _controller = [obj retain];
-}
-
-- (void) dealloc {
- if (_controller != nil) [_controller release];
-
- if (_port != MACH_PORT_NULL)
- mach_port_deallocate (mach_task_self (), _port);
-
- [super dealloc];
-}
-
-- (void) orderFrontStandardAboutPanel: (id) sender {
- NSMutableDictionary *dict;
- NSDictionary *infoDict;
- NSString *tem;
-
- dict = [NSMutableDictionary dictionaryWithCapacity:3];
- infoDict = [[NSBundle mainBundle] infoDictionary];
-
- [dict setObject: NSLocalizedString (@"The X Window System", @"About panel")
- forKey:@"ApplicationName"];
-
- tem = [infoDict objectForKey:@"CFBundleShortVersionString"];
-
- [dict setObject:[NSString stringWithFormat:@"XQuartz %@", tem]
- forKey:@"ApplicationVersion"];
-
- [dict setObject:[NSString stringWithFormat:@"xorg-server %s", XSERVER_VERSION]
- forKey:@"Version"];
-
- [self orderFrontStandardAboutPanelWithOptions: dict];
-}
-
-- (void) activateX:(OSX_BOOL)state {
- size_t i;
- DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active)
- if (state) {
- if(bgMouseLocationUpdated) {
- DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, bgMouseLocation.x, bgMouseLocation.y, 0.0, 0.0, 0.0);
- bgMouseLocationUpdated = FALSE;
- }
- DarwinSendDDXEvent(kXquartzActivate, 0);
- } else {
-
- if(darwin_all_modifier_flags)
- DarwinUpdateModKeys(0);
- for(i=0; i < NUM_KEYCODES; i++) {
- if(keyState[i] == NSKeyDown) {
- DarwinSendKeyboardEvents(KeyRelease, i);
- keyState[i] = NSKeyUp;
- }
- }
-
- DarwinSendDDXEvent(kXquartzDeactivate, 0);
- }
-
- _x_active = state;
-}
-
-- (void) became_key:(NSWindow *)win {
- [self activateX:NO];
-}
-
-- (void) sendEvent:(NSEvent *)e {
- OSX_BOOL for_appkit, for_x;
-
- /* By default pass down the responder chain and to X. */
- for_appkit = YES;
- for_x = YES;
-
- switch ([e type]) {
- case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown:
- case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp:
- if ([e window] != nil) {
- /* Pointer event has an (AppKit) window. Probably something for the kit. */
- for_x = NO;
- if (_x_active) [self activateX:NO];
- } else if ([self modalWindow] == nil) {
- /* Must be an X window. Tell appkit it doesn't have focus. */
- for_appkit = NO;
-
- if ([self isActive]) {
- [self deactivate];
- if (!_x_active && quartzProcs->IsX11Window([e window],
- [e windowNumber]))
- [self activateX:YES];
- }
- }
-
- /* We want to force sending to appkit if we're over the menu bar */
- if(!for_appkit) {
- NSPoint NSlocation = [e locationInWindow];
- NSWindow *window = [e window];
- NSRect NSframe, NSvisibleFrame;
- CGRect CGframe, CGvisibleFrame;
- CGPoint CGlocation;
-
- if (window != nil) {
- NSRect frame = [window frame];
- NSlocation.x += frame.origin.x;
- NSlocation.y += frame.origin.y;
- }
-
- NSframe = [[NSScreen mainScreen] frame];
- NSvisibleFrame = [[NSScreen mainScreen] visibleFrame];
-
- CGframe = CGRectMake(NSframe.origin.x, NSframe.origin.y,
- NSframe.size.width, NSframe.size.height);
- CGvisibleFrame = CGRectMake(NSvisibleFrame.origin.x,
- NSvisibleFrame.origin.y,
- NSvisibleFrame.size.width,
- NSvisibleFrame.size.height);
- CGlocation = CGPointMake(NSlocation.x, NSlocation.y);
-
- if(CGRectContainsPoint(CGframe, CGlocation) &&
- !CGRectContainsPoint(CGvisibleFrame, CGlocation))
- for_appkit = YES;
- }
-
- break;
-
- case NSKeyDown: case NSKeyUp:
-
- if(_x_active) {
- static BOOL do_swallow = NO;
- static int swallow_keycode;
-
- if([e type] == NSKeyDown) {
- /* Before that though, see if there are any global
- * shortcuts bound to it. */
-
- if(darwinAppKitModMask & [e modifierFlags]) {
- /* Override to force sending to Appkit */
- swallow_keycode = [e keyCode];
- do_swallow = YES;
- for_x = NO;
-#if XPLUGIN_VERSION >= 1
- } else if(X11EnableKeyEquivalents &&
- xp_is_symbolic_hotkey_event([e eventRef])) {
- swallow_keycode = [e keyCode];
- do_swallow = YES;
- for_x = NO;
-#endif
- } else if(X11EnableKeyEquivalents &&
- [[self mainMenu] performKeyEquivalent:e]) {
- swallow_keycode = [e keyCode];
- do_swallow = YES;
- for_appkit = NO;
- for_x = NO;
- } else if(!quartzEnableRootless
- && ([e modifierFlags] & ALL_KEY_MASKS) == (NSCommandKeyMask | NSAlternateKeyMask)
- && ([e keyCode] == 0 /*a*/ || [e keyCode] == 53 /*Esc*/)) {
- /* We have this here to force processing fullscreen
- * toggle even if X11EnableKeyEquivalents is disabled */
- swallow_keycode = [e keyCode];
- do_swallow = YES;
- for_x = NO;
- for_appkit = NO;
- DarwinSendDDXEvent(kXquartzToggleFullscreen, 0);
- } else {
- /* No kit window is focused, so send it to X. */
- for_appkit = NO;
- }
- } else { /* KeyUp */
- /* If we saw a key equivalent on the down, don't pass
- * the up through to X. */
- if (do_swallow && [e keyCode] == swallow_keycode) {
- do_swallow = NO;
- for_x = NO;
- }
- }
- } else { /* !_x_active */
- for_x = NO;
- }
- break;
-
- case NSFlagsChanged:
- /* Don't tell X11 about modifiers changing while it's not active */
- if (!_x_active)
- for_x = NO;
- break;
-
- case NSAppKitDefined:
- switch ([e subtype]) {
- case NSApplicationActivatedEventType:
- for_x = NO;
- if ([self modalWindow] == nil) {
- BOOL switch_on_activate, ok;
- for_appkit = NO;
-
- /* FIXME: hack to avoid having to pass the event to appkit,
- which would cause it to raise one of its windows. */
- _appFlags._active = YES;
-
- [self activateX:YES];
-
- /* Get the Spaces preference for SwitchOnActivate */
- (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences"));
- switch_on_activate = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok);
- if(!ok)
- switch_on_activate = YES;
-
- if ([e data2] & 0x10 && switch_on_activate) // 0x10 is set when we use cmd-tab or the dock icon
- DarwinSendDDXEvent(kXquartzBringAllToFront, 0);
- }
- break;
-
- case 18: /* ApplicationDidReactivate */
- if (quartzHasRoot) for_appkit = NO;
- break;
-
- case NSApplicationDeactivatedEventType:
- for_x = NO;
- [self activateX:NO];
- break;
- }
- break;
-
- default: break; /* for gcc */
- }
-
- if (for_appkit) [super sendEvent:e];
-
- if (for_x) [self sendX11NSEvent:e];
-}
-
-- (void) set_window_menu:(NSArray *)list {
- [_controller set_window_menu:list];
-}
-
-- (void) set_window_menu_check:(NSNumber *)n {
- [_controller set_window_menu_check:n];
-}
-
-- (void) set_apps_menu:(NSArray *)list {
- [_controller set_apps_menu:list];
-}
-
-- (void) set_front_process:unused {
- [NSApp activateIgnoringOtherApps:YES];
-
- if ([self modalWindow] == nil)
- [self activateX:YES];
-}
-
-- (void) set_can_quit:(NSNumber *)state {
- [_controller set_can_quit:[state boolValue]];
-}
-
-- (void) server_ready:unused {
- [_controller server_ready];
-}
-
-- (void) show_hide_menubar:(NSNumber *)state {
- /* Also shows/hides the dock */
- if ([state boolValue])
- SetSystemUIMode(kUIModeNormal, 0);
- else
- SetSystemUIMode(kUIModeAllHidden, quartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation"
-}
-
-- (void) launch_client:(NSString *)cmd {
- (void)[_controller application:self openFile:cmd];
-}
-
-/* user preferences */
-
-/* Note that these functions only work for arrays whose elements
- can be toll-free-bridged between NS and CF worlds. */
-
-static const void *cfretain (CFAllocatorRef a, const void *b) {
- return CFRetain (b);
-}
-
-static void cfrelease (CFAllocatorRef a, const void *b) {
- CFRelease (b);
-}
-
-static CFMutableArrayRef nsarray_to_cfarray (NSArray *in) {
- CFMutableArrayRef out;
- CFArrayCallBacks cb;
- NSObject *ns;
- const CFTypeRef *cf;
- int i, count;
-
- memset (&cb, 0, sizeof (cb));
- cb.version = 0;
- cb.retain = cfretain;
- cb.release = cfrelease;
-
- count = [in count];
- out = CFArrayCreateMutable (NULL, count, &cb);
-
- for (i = 0; i < count; i++) {
- ns = [in objectAtIndex:i];
-
- if ([ns isKindOfClass:[NSArray class]])
- cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns);
- else
- cf = CFRetain ((CFTypeRef) ns);
-
- CFArrayAppendValue (out, cf);
- CFRelease (cf);
- }
-
- return out;
-}
-
-static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) {
- NSMutableArray *out;
- const CFTypeRef *cf;
- NSObject *ns;
- int i, count;
-
- count = CFArrayGetCount (in);
- out = [[NSMutableArray alloc] initWithCapacity:count];
-
- for (i = 0; i < count; i++) {
- cf = CFArrayGetValueAtIndex (in, i);
-
- if (CFGetTypeID (cf) == CFArrayGetTypeID ())
- ns = cfarray_to_nsarray ((CFArrayRef) cf);
- else
- ns = [(id)cf retain];
-
- [out addObject:ns];
- [ns release];
- }
-
- return out;
-}
-
-- (CFPropertyListRef) prefs_get_copy:(NSString *)key {
- CFPropertyListRef value;
-
- value = CFPreferencesCopyAppValue ((CFStringRef) key, app_prefs_domain_cfstr);
-
- if (value == NULL) {
- static CFDictionaryRef defaults;
-
- if (defaults == NULL) {
- CFStringRef error = NULL;
- CFDataRef data;
- CFURLRef url;
- SInt32 error_code;
-
- url = (CFURLCreateFromFileSystemRepresentation
- (NULL, (unsigned char *)DEFAULTS_FILE, strlen (DEFAULTS_FILE), false));
- if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data,
- NULL, NULL, &error_code)) {
- defaults = (CFPropertyListCreateFromXMLData
- (NULL, data, kCFPropertyListMutableContainersAndLeaves, &error));
- if (error != NULL) CFRelease (error);
- CFRelease (data);
- }
- CFRelease (url);
-
- if (defaults != NULL) {
- NSMutableArray *apps, *elt;
- int count, i;
- NSString *name, *nname;
-
- /* Localize the names in the default apps menu. */
-
- apps = [(NSDictionary *)defaults objectForKey:@PREFS_APPSMENU];
- if (apps != nil) {
- count = [apps count];
- for (i = 0; i < count; i++) {
- elt = [apps objectAtIndex:i];
- if (elt != nil && [elt isKindOfClass:[NSArray class]]) {
- name = [elt objectAtIndex:0];
- if (name != nil) {
- nname = NSLocalizedString (name, nil);
- if (nname != nil && nname != name)
- [elt replaceObjectAtIndex:0 withObject:nname];
- }
- }
- }
- }
- }
- }
-
- if (defaults != NULL) value = CFDictionaryGetValue (defaults, key);
- if (value != NULL) CFRetain (value);
- }
-
- return value;
-}
-
-- (int) prefs_get_integer:(NSString *)key default:(int)def {
- CFPropertyListRef value;
- int ret;
-
- value = [self prefs_get_copy:key];
-
- if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ())
- CFNumberGetValue (value, kCFNumberIntType, &ret);
- else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
- ret = CFStringGetIntValue (value);
- else
- ret = def;
-
- if (value != NULL) CFRelease (value);
-
- return ret;
-}
-
-- (const char *) prefs_get_string:(NSString *)key default:(const char *)def {
- CFPropertyListRef value;
- const char *ret = NULL;
-
- value = [self prefs_get_copy:key];
-
- if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) {
- NSString *s = (NSString *) value;
-
- ret = [s UTF8String];
- }
-
- if (value != NULL) CFRelease (value);
-
- return ret != NULL ? ret : def;
-}
-
-- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def {
- CFPropertyListRef value;
- NSURL *ret = NULL;
-
- value = [self prefs_get_copy:key];
-
- if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) {
- NSString *s = (NSString *) value;
-
- ret = [NSURL URLWithString:s];
- [ret retain];
- }
-
- if (value != NULL) CFRelease (value);
-
- return ret != NULL ? ret : def;
-}
-
-- (float) prefs_get_float:(NSString *)key default:(float)def {
- CFPropertyListRef value;
- float ret = def;
-
- value = [self prefs_get_copy:key];
-
- if (value != NULL
- && CFGetTypeID (value) == CFNumberGetTypeID ()
- && CFNumberIsFloatType (value))
- CFNumberGetValue (value, kCFNumberFloatType, &ret);
- else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
- ret = CFStringGetDoubleValue (value);
-
- if (value != NULL) CFRelease (value);
-
- return ret;
-}
-
-- (int) prefs_get_boolean:(NSString *)key default:(int)def {
- CFPropertyListRef value;
- int ret = def;
-
- value = [self prefs_get_copy:key];
-
- if (value != NULL) {
- if (CFGetTypeID (value) == CFNumberGetTypeID ())
- CFNumberGetValue (value, kCFNumberIntType, &ret);
- else if (CFGetTypeID (value) == CFBooleanGetTypeID ())
- ret = CFBooleanGetValue (value);
- else if (CFGetTypeID (value) == CFStringGetTypeID ()) {
- const char *tem = [(NSString *) value UTF8String];
- if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0)
- ret = YES;
- else
- ret = NO;
- }
-
- CFRelease (value);
- }
- return ret;
-}
-
-- (NSArray *) prefs_get_array:(NSString *)key {
- NSArray *ret = nil;
- CFPropertyListRef value;
-
- value = [self prefs_get_copy:key];
-
- if (value != NULL) {
- if (CFGetTypeID (value) == CFArrayGetTypeID ())
- ret = [cfarray_to_nsarray (value) autorelease];
-
- CFRelease (value);
- }
-
- return ret;
-}
-
-- (void) prefs_set_integer:(NSString *)key value:(int)value {
- CFNumberRef x;
-
- x = CFNumberCreate (NULL, kCFNumberIntType, &value);
-
- CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr,
- kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
-
- CFRelease (x);
-}
-
-- (void) prefs_set_float:(NSString *)key value:(float)value {
- CFNumberRef x;
-
- x = CFNumberCreate (NULL, kCFNumberFloatType, &value);
-
- CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr,
- kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
-
- CFRelease (x);
-}
-
-- (void) prefs_set_boolean:(NSString *)key value:(int)value {
- CFPreferencesSetValue ((CFStringRef) key,
- (CFTypeRef) (value ? kCFBooleanTrue
- : kCFBooleanFalse), app_prefs_domain_cfstr,
- kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
-
-}
-
-- (void) prefs_set_array:(NSString *)key value:(NSArray *)value {
- CFArrayRef cfarray;
-
- cfarray = nsarray_to_cfarray (value);
- CFPreferencesSetValue ((CFStringRef) key,
- (CFTypeRef) cfarray,
- app_prefs_domain_cfstr,
- kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
- CFRelease (cfarray);
-}
-
-- (void) prefs_set_string:(NSString *)key value:(NSString *)value {
- CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value,
- app_prefs_domain_cfstr, kCFPreferencesCurrentUser,
- kCFPreferencesAnyHost);
-}
-
-- (void) prefs_synchronize {
- CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication);
-}
-
-- (void) read_defaults
-{
- NSString *nsstr;
- const char *tem;
-
- quartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP
- default:quartzUseSysBeep];
- quartzEnableRootless = [self prefs_get_boolean:@PREFS_ROOTLESS
- default:quartzEnableRootless];
- quartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU
- default:quartzFullscreenMenu];
- quartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS
- default:!quartzFullscreenDisableHotkeys];
- darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS
- default:darwinFakeButtons];
- quartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT
- default:quartzOptionSendsAlt];
-
- if (darwinFakeButtons) {
- const char *fake2, *fake3;
-
- fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL];
- fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL];
-
- if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList(fake2, TRUE);
- if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList(fake3, TRUE);
- }
-
- tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL];
- if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE);
-
- tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL];
- if (tem != NULL) {
- windowItemModMask = DarwinParseModifierList(tem, FALSE);
- } else {
- nsstr = NSLocalizedString (@"window item modifiers", @"window item modifiers");
- if(nsstr != NULL) {
- tem = [nsstr UTF8String];
- if((tem != NULL) && strcmp(tem, "window item modifiers")) {
- windowItemModMask = DarwinParseModifierList(tem, FALSE);
- }
- }
- }
-
- X11EnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS
- default:X11EnableKeyEquivalents];
-
- darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP
- default:darwinSyncKeymap];
-
- darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH
- default:darwinDesiredDepth];
-
- noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS
- default:FALSE];
-
-#if XQUARTZ_SPARKLE
- NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil];
- if(url) {
- [[SUUpdater sharedUpdater] setFeedURL:url];
- [url release];
- }
-#endif
-}
-
-/* This will end up at the end of the responder chain. */
-- (void) copy:sender {
- DarwinSendDDXEvent(kXquartzPasteboardNotify, 1,
- AppleWMCopyToPasteboard);
-}
-
-- (X11Controller *) controller {
- return _controller;
-}
-
-- (OSX_BOOL) x_active {
- return _x_active;
-}
-
-@end
-
-static NSArray *
-array_with_strings_and_numbers (int nitems, const char **items,
- const char *numbers) {
- NSMutableArray *array, *subarray;
- NSString *string, *number;
- int i;
-
- /* (Can't autorelease on the X server thread) */
-
- array = [[NSMutableArray alloc] initWithCapacity:nitems];
-
- for (i = 0; i < nitems; i++) {
- subarray = [[NSMutableArray alloc] initWithCapacity:2];
-
- string = [[NSString alloc] initWithUTF8String:items[i]];
- [subarray addObject:string];
- [string release];
-
- if (numbers[i] != 0) {
- number = [[NSString alloc] initWithFormat:@"%d", numbers[i]];
- [subarray addObject:number];
- [number release];
- } else
- [subarray addObject:@""];
-
- [array addObject:subarray];
- [subarray release];
- }
-
- return array;
-}
-
-void X11ApplicationSetWindowMenu (int nitems, const char **items,
- const char *shortcuts) {
- NSArray *array;
- array = array_with_strings_and_numbers (nitems, items, shortcuts);
-
- /* Send the array of strings over to the appkit thread */
-
- message_kit_thread (@selector (set_window_menu:), array);
- [array release];
-}
-
-void X11ApplicationSetWindowMenuCheck (int idx) {
- NSNumber *n;
-
- n = [[NSNumber alloc] initWithInt:idx];
-
- message_kit_thread (@selector (set_window_menu_check:), n);
-
- [n release];
-}
-
-void X11ApplicationSetFrontProcess (void) {
- message_kit_thread (@selector (set_front_process:), nil);
-}
-
-void X11ApplicationSetCanQuit (int state) {
- NSNumber *n;
-
- n = [[NSNumber alloc] initWithBool:state];
-
- message_kit_thread (@selector (set_can_quit:), n);
-
- [n release];
-}
-
-void X11ApplicationServerReady (void) {
- message_kit_thread (@selector (server_ready:), nil);
-}
-
-void X11ApplicationShowHideMenubar (int state) {
- NSNumber *n;
-
- n = [[NSNumber alloc] initWithBool:state];
-
- message_kit_thread (@selector (show_hide_menubar:), n);
-
- [n release];
-}
-
-void X11ApplicationLaunchClient (const char *cmd) {
- NSString *string;
-
- string = [[NSString alloc] initWithUTF8String:cmd];
-
- message_kit_thread (@selector (launch_client:), string);
-
- [string release];
-}
-
-static void check_xinitrc (void) {
- char *tem, buf[1024];
- NSString *msg;
-
- if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO])
- return;
-
- tem = getenv ("HOME");
- if (tem == NULL) goto done;
-
- snprintf (buf, sizeof (buf), "%s/.xinitrc", tem);
- if (access (buf, F_OK) != 0)
- goto done;
-
- msg = NSLocalizedString (@"You have an existing ~/.xinitrc file.\n\n\
-Windows displayed by X11 applications may not have titlebars, or may look \
-different to windows displayed by native applications.\n\n\
-Would you like to move aside the existing file and use the standard X11 \
-environment the next time you start X11?", @"Startup xinitrc dialog");
-
- if(NSAlertDefaultReturn == NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""),
- NSLocalizedString (@"No", @""), nil)) {
- char buf2[1024];
- int i = -1;
-
- snprintf (buf2, sizeof (buf2), "%s.old", buf);
-
- for(i = 1; access (buf2, F_OK) == 0; i++)
- snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i);
-
- rename (buf, buf2);
- }
-
- done:
- [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES];
- [X11App prefs_synchronize];
-}
-
-static inline pthread_t create_thread(void *func, void *arg) {
- pthread_attr_t attr;
- pthread_t tid;
-
- pthread_attr_init(&attr);
- pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_create(&tid, &attr, func, arg);
- pthread_attr_destroy(&attr);
-
- return tid;
-}
-
-static void *xpbproxy_x_thread(void *args) {
- xpbproxy_run();
-
- fprintf(stderr, "xpbproxy thread is terminating unexpectedly.\n");
- return NULL;
-}
-
-void X11ApplicationMain (int argc, char **argv, char **envp) {
- NSAutoreleasePool *pool;
-
-#ifdef DEBUG
- while (access ("/tmp/x11-block", F_OK) == 0) sleep (1);
-#endif
-
- pool = [[NSAutoreleasePool alloc] init];
- X11App = (X11Application *) [X11Application sharedApplication];
- init_ports ();
-
- app_prefs_domain_cfstr = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier];
-
- [NSApp read_defaults];
- [NSBundle loadNibNamed:@"main" owner:NSApp];
- [[NSNotificationCenter defaultCenter] addObserver:NSApp
- selector:@selector (became_key:)
- name:NSWindowDidBecomeKeyNotification object:nil];
-
- /*
- * The xpr Quartz mode is statically linked into this server.
- * Initialize all the Quartz functions.
- */
- QuartzModeBundleInit();
-
- /* Calculate the height of the menubar so we can avoid it. */
- aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) -
- NSMaxY([[NSScreen mainScreen] visibleFrame]);
-
- /* Set the key layout seed before we start the server */
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- last_key_layout = TISCopyCurrentKeyboardLayoutInputSource();
-
- if(!last_key_layout)
- fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n");
-#else
- KLGetCurrentKeyboardLayout(&last_key_layout);
- if(!last_key_layout)
- fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n");
-#endif
-
- if (!QuartsResyncKeymap(FALSE)) {
- fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n");
- }
-
- /* Tell the server thread that it can proceed */
- QuartzInitServer(argc, argv, envp);
-
- /* This must be done after QuartzInitServer because it can result in
- * an mieqEnqueue() - <rdar://problem/6300249>
- */
- check_xinitrc();
-
- create_thread(xpbproxy_x_thread, NULL);
-
-#if XQUARTZ_SPARKLE
- [[X11App controller] setup_sparkle];
- [[SUUpdater sharedUpdater] resetUpdateCycle];
-// [[SUUpdater sharedUpdater] checkForUpdates:X11App];
-#endif
-
- [pool release];
- [NSApp run];
- /* not reached */
-}
-
-@implementation X11Application (Private)
-
-#ifdef NX_DEVICELCMDKEYMASK
-/* This is to workaround a bug in the VNC server where we sometimes see the L
- * modifier and sometimes see no "side"
- */
-static inline int ensure_flag(int flags, int device_independent, int device_dependents, int device_dependent_default) {
- if( (flags & device_independent) &&
- !(flags & device_dependents))
- flags |= device_dependent_default;
- return flags;
-}
-#endif
-
-- (void) sendX11NSEvent:(NSEvent *)e {
- NSPoint location = NSZeroPoint, tilt = NSZeroPoint;
- int ev_button, ev_type;
- float pressure = 0.0;
- DeviceIntPtr pDev;
- int modifierFlags;
- BOOL isMouseOrTabletEvent, isTabletEvent;
-
- isMouseOrTabletEvent = [e type] == NSLeftMouseDown || [e type] == NSOtherMouseDown || [e type] == NSRightMouseDown ||
- [e type] == NSLeftMouseUp || [e type] == NSOtherMouseUp || [e type] == NSRightMouseUp ||
- [e type] == NSLeftMouseDragged || [e type] == NSOtherMouseDragged || [e type] == NSRightMouseDragged ||
- [e type] == NSMouseMoved || [e type] == NSTabletPoint || [e type] == NSScrollWheel;
-
- isTabletEvent = ([e type] == NSTabletPoint) ||
- (isMouseOrTabletEvent && ([e subtype] == NSTabletPointEventSubtype || [e subtype] == NSTabletProximityEventSubtype));
-
- if(isMouseOrTabletEvent) {
- static NSPoint lastpt;
- NSWindow *window = [e window];
- NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame];
- BOOL hasUntrustedPointerDelta;
-
- // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that
- // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets
- // are not normally used in cases where that bug would present itself, so this is a fair tradeoff
- // <rdar://problem/7111003> deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype
- // http://xquartz.macosforge.org/trac/ticket/288
- hasUntrustedPointerDelta = isTabletEvent;
-
- // The deltaXY for middle click events also appear erroneous after fast user switching
- // <rdar://problem/7979468> deltaX and deltaY are incorrect for NSOtherMouseDown and NSOtherMouseUp after FUS
- // http://xquartz.macosforge.org/trac/ticket/389
- hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSOtherMouseDown || [e type] == NSOtherMouseUp;
-
- // The deltaXY for scroll events correspond to the scroll delta, not the pointer delta
- // <rdar://problem/7989690> deltaXY for wheel events are being sent as mouse movement
- hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSScrollWheel;
-
- if (window != nil) {
- NSRect frame = [window frame];
- location = [e locationInWindow];
- location.x += frame.origin.x;
- location.y += frame.origin.y;
- lastpt = location;
- } else if(hasUntrustedPointerDelta) {
- location = [e locationInWindow];
- lastpt = location;
- } else {
- location.x = lastpt.x + [e deltaX];
- location.y = lastpt.y - [e deltaY];
- lastpt = [e locationInWindow];
- }
-
- /* Convert coordinate system */
- location.y = (screen.origin.y + screen.size.height) - location.y;
- }
-
- modifierFlags = [e modifierFlags];
-
-#ifdef NX_DEVICELCMDKEYMASK
- /* This is to workaround a bug in the VNC server where we sometimes see the L
- * modifier and sometimes see no "side"
- */
- modifierFlags = ensure_flag(modifierFlags, NX_CONTROLMASK, NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK, NX_DEVICELCTLKEYMASK);
- modifierFlags = ensure_flag(modifierFlags, NX_SHIFTMASK, NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK, NX_DEVICELSHIFTKEYMASK);
- modifierFlags = ensure_flag(modifierFlags, NX_COMMANDMASK, NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK, NX_DEVICELCMDKEYMASK);
- modifierFlags = ensure_flag(modifierFlags, NX_ALTERNATEMASK, NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK, NX_DEVICELALTKEYMASK);
-#endif
-
- modifierFlags &= darwin_all_modifier_mask;
-
- /* We don't receive modifier key events while out of focus, and 3button
- * emulation mucks this up, so we need to check our modifier flag state
- * on every event... ugg
- */
-
- if(darwin_all_modifier_flags != modifierFlags)
- DarwinUpdateModKeys(modifierFlags);
-
- switch ([e type]) {
- case NSLeftMouseDown: ev_button=1; ev_type=ButtonPress; goto handle_mouse;
- case NSOtherMouseDown: ev_button=2; ev_type=ButtonPress; goto handle_mouse;
- case NSRightMouseDown: ev_button=3; ev_type=ButtonPress; goto handle_mouse;
- case NSLeftMouseUp: ev_button=1; ev_type=ButtonRelease; goto handle_mouse;
- case NSOtherMouseUp: ev_button=2; ev_type=ButtonRelease; goto handle_mouse;
- case NSRightMouseUp: ev_button=3; ev_type=ButtonRelease; goto handle_mouse;
- case NSLeftMouseDragged: ev_button=1; ev_type=MotionNotify; goto handle_mouse;
- case NSOtherMouseDragged: ev_button=2; ev_type=MotionNotify; goto handle_mouse;
- case NSRightMouseDragged: ev_button=3; ev_type=MotionNotify; goto handle_mouse;
- case NSMouseMoved: ev_button=0; ev_type=MotionNotify; goto handle_mouse;
- case NSTabletPoint: ev_button=0; ev_type=MotionNotify; goto handle_mouse;
-
- handle_mouse:
- pDev = darwinPointer;
-
- /* NSTabletPoint can have no subtype */
- if([e type] != NSTabletPoint &&
- [e subtype] == NSTabletProximityEventSubtype) {
- switch([e pointingDeviceType]) {
- case NSEraserPointingDevice:
- darwinTabletCurrent=darwinTabletEraser;
- break;
- case NSPenPointingDevice:
- darwinTabletCurrent=darwinTabletStylus;
- break;
- case NSCursorPointingDevice:
- case NSUnknownPointingDevice:
- default:
- darwinTabletCurrent=darwinTabletCursor;
- break;
- }
-
- /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt
- * So we just pretend the motion was caused by the mouse. Hopefully
- * we'll have a better solution for this in the future (like maybe
- * NSTabletProximityEventSubtype will come from NSTabletPoint
- * rather than NSMouseMoved.
- pressure = [e pressure];
- tilt = [e tilt];
- pDev = darwinTabletCurrent;
- */
-
- DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut,
- location.x, location.y);
- }
-
- if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) {
- pressure = [e pressure];
- tilt = [e tilt];
-
- pDev = darwinTabletCurrent;
- }
-
- if(!quartzServerVisible && noTestExtensions) {
-#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0
-/* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */
- xp_window_id wid = 0;
- xp_error e;
-
- /* Sigh. Need to check that we're really over one of
- * our windows. (We need to receive pointer events while
- * not in the foreground, but we don't want to receive them
- * when another window is over us or we might show a tooltip)
- */
-
- e = xp_find_window(location.x, location.y, 0, &wid);
-
- if (e != XP_Success || (e == XP_Success && wid == 0))
-#endif
- {
- bgMouseLocation = location;
- bgMouseLocationUpdated = TRUE;
- return;
- }
- }
-
- if(bgMouseLocationUpdated) {
- if(!(ev_type == MotionNotify && ev_button == 0)) {
- DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x,
- location.y, pressure, tilt.x, tilt.y);
- }
- bgMouseLocationUpdated = FALSE;
- }
-
- DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x, location.y,
- pressure, tilt.x, tilt.y);
-
- break;
-
- case NSTabletProximity:
- switch([e pointingDeviceType]) {
- case NSEraserPointingDevice:
- darwinTabletCurrent=darwinTabletEraser;
- break;
- case NSPenPointingDevice:
- darwinTabletCurrent=darwinTabletStylus;
- break;
- case NSCursorPointingDevice:
- case NSUnknownPointingDevice:
- default:
- darwinTabletCurrent=darwinTabletCursor;
- break;
- }
-
- DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut,
- location.x, location.y);
- break;
-
- case NSScrollWheel:
-#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0
- /* If we're in the background, we need to send a MotionNotify event
- * first, since we aren't getting them on background mouse motion
- */
- if(!quartzServerVisible && noTestExtensions) {
- bgMouseLocationUpdated = FALSE;
- DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, location.x,
- location.y, pressure, tilt.x, tilt.y);
- }
-#endif
- DarwinSendScrollEvents([e deltaX], [e deltaY], location.x, location.y,
- pressure, tilt.x, tilt.y);
- break;
-
- case NSKeyDown: case NSKeyUp:
- {
- /* XKB clobbers our keymap at startup, so we need to force it on the first keypress.
- * TODO: Make this less of a kludge.
- */
- static int force_resync_keymap = YES;
- if(force_resync_keymap) {
- DarwinSendDDXEvent(kXquartzReloadKeymap, 0);
- force_resync_keymap = NO;
- }
- }
-
- if(darwinSyncKeymap) {
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- TISInputSourceRef key_layout = TISCopyCurrentKeyboardLayoutInputSource();
- TISInputSourceRef clear;
- if (CFEqual(key_layout, last_key_layout)) {
- CFRelease(key_layout);
- } else {
- /* Swap/free thread-safely */
- clear = last_key_layout;
- last_key_layout = key_layout;
- CFRelease(clear);
-#else
- KeyboardLayoutRef key_layout;
- KLGetCurrentKeyboardLayout(&key_layout);
- if(key_layout != last_key_layout) {
- last_key_layout = key_layout;
-#endif
- /* Update keyInfo */
- if (!QuartsResyncKeymap(TRUE)) {
- fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n");
- }
- }
- }
-
- /* Avoid stuck keys on context switch */
- if(keyState[[e keyCode]] == [e type])
- return;
- keyState[[e keyCode]] = [e type];
-
- DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]);
- break;
-
- default: break; /* for gcc */
- }
-}
-@end
+/* X11Application.m -- subclass of NSApplication to multiplex events
+
+ Copyright (c) 2002-2008 Apple Inc.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name(s) of the above
+ copyright holders shall not be used in advertising or otherwise to
+ promote the sale, use or other dealings in this Software without
+ prior written authorization. */
+
+#include "sanitizedCarbon.h"
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "quartzCommon.h"
+
+#import "X11Application.h"
+
+#include "darwin.h"
+#include "darwinEvents.h"
+#include "quartzKeyboard.h"
+#include "quartz.h"
+#include <X11/extensions/applewmconst.h>
+#include "micmap.h"
+#include "exglobals.h"
+
+#include <mach/mach.h>
+#include <unistd.h>
+#include <AvailabilityMacros.h>
+
+#include <Xplugin.h>
+
+// pbproxy/pbproxy.h
+extern int xpbproxy_run (void);
+
+#define DEFAULTS_FILE X11LIBDIR"/X11/xserver/Xquartz.plist"
+
+#ifndef XSERVER_VERSION
+#define XSERVER_VERSION "?"
+#endif
+
+/* Stuck modifier / button state... force release when we context switch */
+static NSEventType keyState[NUM_KEYCODES];
+
+int X11EnableKeyEquivalents = TRUE, quartzFullscreenMenu = FALSE;
+int quartzHasRoot = FALSE, quartzEnableRootless = TRUE;
+
+extern Bool noTestExtensions;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+static TISInputSourceRef last_key_layout;
+#else
+static KeyboardLayoutRef last_key_layout;
+#endif
+
+extern int darwinFakeButtons;
+
+/* Store the mouse location while in the background, and update X11's pointer
+ * location when we become the foreground application
+ */
+static NSPoint bgMouseLocation;
+static BOOL bgMouseLocationUpdated = FALSE;
+
+X11Application *X11App;
+
+CFStringRef app_prefs_domain_cfstr = NULL;
+
+#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask)
+
+@interface X11Application (Private)
+- (void) sendX11NSEvent:(NSEvent *)e;
+@end
+
+@implementation X11Application
+
+typedef struct message_struct message;
+struct message_struct {
+ mach_msg_header_t hdr;
+ SEL selector;
+ NSObject *arg;
+};
+
+static mach_port_t _port;
+
+/* Quartz mode initialization routine. This is often dynamically loaded
+ but is statically linked into this X server. */
+Bool QuartzModeBundleInit(void);
+
+static void init_ports (void) {
+ kern_return_t r;
+ NSPort *p;
+
+ if (_port != MACH_PORT_NULL) return;
+
+ r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port);
+ if (r != KERN_SUCCESS) return;
+
+ p = [NSMachPort portWithMachPort:_port];
+ [p setDelegate:NSApp];
+ [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+}
+
+static void message_kit_thread (SEL selector, NSObject *arg) {
+ message msg;
+ kern_return_t r;
+
+ msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
+ msg.hdr.msgh_size = sizeof (msg);
+ msg.hdr.msgh_remote_port = _port;
+ msg.hdr.msgh_local_port = MACH_PORT_NULL;
+ msg.hdr.msgh_reserved = 0;
+ msg.hdr.msgh_id = 0;
+
+ msg.selector = selector;
+ msg.arg = [arg retain];
+
+ r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size,
+ 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
+ if (r != KERN_SUCCESS)
+ ErrorF("%s: mach_msg failed: %x\n", __FUNCTION__, r);
+}
+
+- (void) handleMachMessage:(void *)_msg {
+ message *msg = _msg;
+
+ [self performSelector:msg->selector withObject:msg->arg];
+ [msg->arg release];
+}
+
+- (void) set_controller:obj {
+ if (_controller == nil) _controller = [obj retain];
+}
+
+- (void) dealloc {
+ if (_controller != nil) [_controller release];
+
+ if (_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), _port);
+
+ [super dealloc];
+}
+
+- (void) orderFrontStandardAboutPanel: (id) sender {
+ NSMutableDictionary *dict;
+ NSDictionary *infoDict;
+ NSString *tem;
+
+ dict = [NSMutableDictionary dictionaryWithCapacity:3];
+ infoDict = [[NSBundle mainBundle] infoDictionary];
+
+ [dict setObject: NSLocalizedString (@"The X Window System", @"About panel")
+ forKey:@"ApplicationName"];
+
+ tem = [infoDict objectForKey:@"CFBundleShortVersionString"];
+
+ [dict setObject:[NSString stringWithFormat:@"XQuartz %@", tem]
+ forKey:@"ApplicationVersion"];
+
+ [dict setObject:[NSString stringWithFormat:@"xorg-server %s", XSERVER_VERSION]
+ forKey:@"Version"];
+
+ [self orderFrontStandardAboutPanelWithOptions: dict];
+}
+
+- (void) activateX:(OSX_BOOL)state {
+ size_t i;
+ DEBUG_LOG("state=%d, _x_active=%d, \n", state, _x_active)
+ if (state) {
+ if(bgMouseLocationUpdated) {
+ DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, bgMouseLocation.x, bgMouseLocation.y, 0.0, 0.0, 0.0);
+ bgMouseLocationUpdated = FALSE;
+ }
+ DarwinSendDDXEvent(kXquartzActivate, 0);
+ } else {
+
+ if(darwin_all_modifier_flags)
+ DarwinUpdateModKeys(0);
+ for(i=0; i < NUM_KEYCODES; i++) {
+ if(keyState[i] == NSKeyDown) {
+ DarwinSendKeyboardEvents(KeyRelease, i);
+ keyState[i] = NSKeyUp;
+ }
+ }
+
+ DarwinSendDDXEvent(kXquartzDeactivate, 0);
+ }
+
+ _x_active = state;
+}
+
+- (void) became_key:(NSWindow *)win {
+ [self activateX:NO];
+}
+
+- (void) sendEvent:(NSEvent *)e {
+ OSX_BOOL for_appkit, for_x;
+
+ /* By default pass down the responder chain and to X. */
+ for_appkit = YES;
+ for_x = YES;
+
+ switch ([e type]) {
+ case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown:
+ case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp:
+ if ([e window] != nil) {
+ /* Pointer event has an (AppKit) window. Probably something for the kit. */
+ for_x = NO;
+ if (_x_active) [self activateX:NO];
+ } else if ([self modalWindow] == nil) {
+ /* Must be an X window. Tell appkit it doesn't have focus. */
+ for_appkit = NO;
+
+ if ([self isActive]) {
+ [self deactivate];
+ if (!_x_active && quartzProcs->IsX11Window([e window],
+ [e windowNumber]))
+ [self activateX:YES];
+ }
+ }
+
+ /* We want to force sending to appkit if we're over the menu bar */
+ if(!for_appkit) {
+ NSPoint NSlocation = [e locationInWindow];
+ NSWindow *window = [e window];
+ NSRect NSframe, NSvisibleFrame;
+ CGRect CGframe, CGvisibleFrame;
+ CGPoint CGlocation;
+
+ if (window != nil) {
+ NSRect frame = [window frame];
+ NSlocation.x += frame.origin.x;
+ NSlocation.y += frame.origin.y;
+ }
+
+ NSframe = [[NSScreen mainScreen] frame];
+ NSvisibleFrame = [[NSScreen mainScreen] visibleFrame];
+
+ CGframe = CGRectMake(NSframe.origin.x, NSframe.origin.y,
+ NSframe.size.width, NSframe.size.height);
+ CGvisibleFrame = CGRectMake(NSvisibleFrame.origin.x,
+ NSvisibleFrame.origin.y,
+ NSvisibleFrame.size.width,
+ NSvisibleFrame.size.height);
+ CGlocation = CGPointMake(NSlocation.x, NSlocation.y);
+
+ if(CGRectContainsPoint(CGframe, CGlocation) &&
+ !CGRectContainsPoint(CGvisibleFrame, CGlocation))
+ for_appkit = YES;
+ }
+
+ break;
+
+ case NSKeyDown: case NSKeyUp:
+
+ if(_x_active) {
+ static BOOL do_swallow = NO;
+ static int swallow_keycode;
+
+ if([e type] == NSKeyDown) {
+ /* Before that though, see if there are any global
+ * shortcuts bound to it. */
+
+ if(darwinAppKitModMask & [e modifierFlags]) {
+ /* Override to force sending to Appkit */
+ swallow_keycode = [e keyCode];
+ do_swallow = YES;
+ for_x = NO;
+#if XPLUGIN_VERSION >= 1
+ } else if(X11EnableKeyEquivalents &&
+ xp_is_symbolic_hotkey_event([e eventRef])) {
+ swallow_keycode = [e keyCode];
+ do_swallow = YES;
+ for_x = NO;
+#endif
+ } else if(X11EnableKeyEquivalents &&
+ [[self mainMenu] performKeyEquivalent:e]) {
+ swallow_keycode = [e keyCode];
+ do_swallow = YES;
+ for_appkit = NO;
+ for_x = NO;
+ } else if(!quartzEnableRootless
+ && ([e modifierFlags] & ALL_KEY_MASKS) == (NSCommandKeyMask | NSAlternateKeyMask)
+ && ([e keyCode] == 0 /*a*/ || [e keyCode] == 53 /*Esc*/)) {
+ /* We have this here to force processing fullscreen
+ * toggle even if X11EnableKeyEquivalents is disabled */
+ swallow_keycode = [e keyCode];
+ do_swallow = YES;
+ for_x = NO;
+ for_appkit = NO;
+ DarwinSendDDXEvent(kXquartzToggleFullscreen, 0);
+ } else {
+ /* No kit window is focused, so send it to X. */
+ for_appkit = NO;
+ }
+ } else { /* KeyUp */
+ /* If we saw a key equivalent on the down, don't pass
+ * the up through to X. */
+ if (do_swallow && [e keyCode] == swallow_keycode) {
+ do_swallow = NO;
+ for_x = NO;
+ }
+ }
+ } else { /* !_x_active */
+ for_x = NO;
+ }
+ break;
+
+ case NSFlagsChanged:
+ /* Don't tell X11 about modifiers changing while it's not active */
+ if (!_x_active)
+ for_x = NO;
+ break;
+
+ case NSAppKitDefined:
+ switch ([e subtype]) {
+ case NSApplicationActivatedEventType:
+ for_x = NO;
+ if ([self modalWindow] == nil) {
+ BOOL order_all_windows = YES, workspaces, ok;
+ for_appkit = NO;
+
+ /* FIXME: hack to avoid having to pass the event to appkit,
+ which would cause it to raise one of its windows. */
+ _appFlags._active = YES;
+
+ [self activateX:YES];
+
+ /* Get the Spaces preference for SwitchOnActivate */
+ (void)CFPreferencesAppSynchronize(CFSTR("com.apple.dock"));
+ workspaces = CFPreferencesGetAppBooleanValue(CFSTR("workspaces"), CFSTR("com.apple.dock"), &ok);
+ if (!ok)
+ workspaces = NO;
+
+ if (workspaces) {
+ (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences"));
+ order_all_windows = CFPreferencesGetAppBooleanValue(CFSTR("AppleSpacesSwitchOnActivate"), CFSTR(".GlobalPreferences"), &ok);
+ if (!ok)
+ order_all_windows = YES;
+ }
+
+ /* TODO: In the workspaces && !AppleSpacesSwitchOnActivate case, the windows are ordered
+ * correctly, but we need to activate the top window on this space if there is
+ * none active.
+ *
+ * If there are no active windows, and there are minimized windows, we should
+ * be restoring one of them.
+ */
+ if ([e data2] & 0x10) // 0x10 is set when we use cmd-tab or the dock icon
+ DarwinSendDDXEvent(kXquartzBringAllToFront, 1, order_all_windows);
+ }
+ break;
+
+ case 18: /* ApplicationDidReactivate */
+ if (quartzHasRoot) for_appkit = NO;
+ break;
+
+ case NSApplicationDeactivatedEventType:
+ for_x = NO;
+ [self activateX:NO];
+ break;
+ }
+ break;
+
+ default: break; /* for gcc */
+ }
+
+ if (for_appkit) [super sendEvent:e];
+
+ if (for_x) [self sendX11NSEvent:e];
+}
+
+- (void) set_window_menu:(NSArray *)list {
+ [_controller set_window_menu:list];
+}
+
+- (void) set_window_menu_check:(NSNumber *)n {
+ [_controller set_window_menu_check:n];
+}
+
+- (void) set_apps_menu:(NSArray *)list {
+ [_controller set_apps_menu:list];
+}
+
+- (void) set_front_process:unused {
+ [NSApp activateIgnoringOtherApps:YES];
+
+ if ([self modalWindow] == nil)
+ [self activateX:YES];
+}
+
+- (void) set_can_quit:(NSNumber *)state {
+ [_controller set_can_quit:[state boolValue]];
+}
+
+- (void) server_ready:unused {
+ [_controller server_ready];
+}
+
+- (void) show_hide_menubar:(NSNumber *)state {
+ /* Also shows/hides the dock */
+ if ([state boolValue])
+ SetSystemUIMode(kUIModeNormal, 0);
+ else
+ SetSystemUIMode(kUIModeAllHidden, quartzFullscreenMenu ? kUIOptionAutoShowMenuBar : 0); // kUIModeAllSuppressed or kUIOptionAutoShowMenuBar can be used to allow "mouse-activation"
+}
+
+- (void) launch_client:(NSString *)cmd {
+ (void)[_controller application:self openFile:cmd];
+}
+
+/* user preferences */
+
+/* Note that these functions only work for arrays whose elements
+ can be toll-free-bridged between NS and CF worlds. */
+
+static const void *cfretain (CFAllocatorRef a, const void *b) {
+ return CFRetain (b);
+}
+
+static void cfrelease (CFAllocatorRef a, const void *b) {
+ CFRelease (b);
+}
+
+static CFMutableArrayRef nsarray_to_cfarray (NSArray *in) {
+ CFMutableArrayRef out;
+ CFArrayCallBacks cb;
+ NSObject *ns;
+ const CFTypeRef *cf;
+ int i, count;
+
+ memset (&cb, 0, sizeof (cb));
+ cb.version = 0;
+ cb.retain = cfretain;
+ cb.release = cfrelease;
+
+ count = [in count];
+ out = CFArrayCreateMutable (NULL, count, &cb);
+
+ for (i = 0; i < count; i++) {
+ ns = [in objectAtIndex:i];
+
+ if ([ns isKindOfClass:[NSArray class]])
+ cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns);
+ else
+ cf = CFRetain ((CFTypeRef) ns);
+
+ CFArrayAppendValue (out, cf);
+ CFRelease (cf);
+ }
+
+ return out;
+}
+
+static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) {
+ NSMutableArray *out;
+ const CFTypeRef *cf;
+ NSObject *ns;
+ int i, count;
+
+ count = CFArrayGetCount (in);
+ out = [[NSMutableArray alloc] initWithCapacity:count];
+
+ for (i = 0; i < count; i++) {
+ cf = CFArrayGetValueAtIndex (in, i);
+
+ if (CFGetTypeID (cf) == CFArrayGetTypeID ())
+ ns = cfarray_to_nsarray ((CFArrayRef) cf);
+ else
+ ns = [(id)cf retain];
+
+ [out addObject:ns];
+ [ns release];
+ }
+
+ return out;
+}
+
+- (CFPropertyListRef) prefs_get_copy:(NSString *)key {
+ CFPropertyListRef value;
+
+ value = CFPreferencesCopyAppValue ((CFStringRef) key, app_prefs_domain_cfstr);
+
+ if (value == NULL) {
+ static CFDictionaryRef defaults;
+
+ if (defaults == NULL) {
+ CFStringRef error = NULL;
+ CFDataRef data;
+ CFURLRef url;
+ SInt32 error_code;
+
+ url = (CFURLCreateFromFileSystemRepresentation
+ (NULL, (unsigned char *)DEFAULTS_FILE, strlen (DEFAULTS_FILE), false));
+ if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data,
+ NULL, NULL, &error_code)) {
+ defaults = (CFPropertyListCreateFromXMLData
+ (NULL, data, kCFPropertyListMutableContainersAndLeaves, &error));
+ if (error != NULL) CFRelease (error);
+ CFRelease (data);
+ }
+ CFRelease (url);
+
+ if (defaults != NULL) {
+ NSMutableArray *apps, *elt;
+ int count, i;
+ NSString *name, *nname;
+
+ /* Localize the names in the default apps menu. */
+
+ apps = [(NSDictionary *)defaults objectForKey:@PREFS_APPSMENU];
+ if (apps != nil) {
+ count = [apps count];
+ for (i = 0; i < count; i++) {
+ elt = [apps objectAtIndex:i];
+ if (elt != nil && [elt isKindOfClass:[NSArray class]]) {
+ name = [elt objectAtIndex:0];
+ if (name != nil) {
+ nname = NSLocalizedString (name, nil);
+ if (nname != nil && nname != name)
+ [elt replaceObjectAtIndex:0 withObject:nname];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (defaults != NULL) value = CFDictionaryGetValue (defaults, key);
+ if (value != NULL) CFRetain (value);
+ }
+
+ return value;
+}
+
+- (int) prefs_get_integer:(NSString *)key default:(int)def {
+ CFPropertyListRef value;
+ int ret;
+
+ value = [self prefs_get_copy:key];
+
+ if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ())
+ CFNumberGetValue (value, kCFNumberIntType, &ret);
+ else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
+ ret = CFStringGetIntValue (value);
+ else
+ ret = def;
+
+ if (value != NULL) CFRelease (value);
+
+ return ret;
+}
+
+- (const char *) prefs_get_string:(NSString *)key default:(const char *)def {
+ CFPropertyListRef value;
+ const char *ret = NULL;
+
+ value = [self prefs_get_copy:key];
+
+ if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) {
+ NSString *s = (NSString *) value;
+
+ ret = [s UTF8String];
+ }
+
+ if (value != NULL) CFRelease (value);
+
+ return ret != NULL ? ret : def;
+}
+
+- (NSURL *) prefs_copy_url:(NSString *)key default:(NSURL *)def {
+ CFPropertyListRef value;
+ NSURL *ret = NULL;
+
+ value = [self prefs_get_copy:key];
+
+ if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ()) {
+ NSString *s = (NSString *) value;
+
+ ret = [NSURL URLWithString:s];
+ [ret retain];
+ }
+
+ if (value != NULL) CFRelease (value);
+
+ return ret != NULL ? ret : def;
+}
+
+- (float) prefs_get_float:(NSString *)key default:(float)def {
+ CFPropertyListRef value;
+ float ret = def;
+
+ value = [self prefs_get_copy:key];
+
+ if (value != NULL
+ && CFGetTypeID (value) == CFNumberGetTypeID ()
+ && CFNumberIsFloatType (value))
+ CFNumberGetValue (value, kCFNumberFloatType, &ret);
+ else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
+ ret = CFStringGetDoubleValue (value);
+
+ if (value != NULL) CFRelease (value);
+
+ return ret;
+}
+
+- (int) prefs_get_boolean:(NSString *)key default:(int)def {
+ CFPropertyListRef value;
+ int ret = def;
+
+ value = [self prefs_get_copy:key];
+
+ if (value != NULL) {
+ if (CFGetTypeID (value) == CFNumberGetTypeID ())
+ CFNumberGetValue (value, kCFNumberIntType, &ret);
+ else if (CFGetTypeID (value) == CFBooleanGetTypeID ())
+ ret = CFBooleanGetValue (value);
+ else if (CFGetTypeID (value) == CFStringGetTypeID ()) {
+ const char *tem = [(NSString *) value UTF8String];
+ if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0)
+ ret = YES;
+ else
+ ret = NO;
+ }
+
+ CFRelease (value);
+ }
+ return ret;
+}
+
+- (NSArray *) prefs_get_array:(NSString *)key {
+ NSArray *ret = nil;
+ CFPropertyListRef value;
+
+ value = [self prefs_get_copy:key];
+
+ if (value != NULL) {
+ if (CFGetTypeID (value) == CFArrayGetTypeID ())
+ ret = [cfarray_to_nsarray (value) autorelease];
+
+ CFRelease (value);
+ }
+
+ return ret;
+}
+
+- (void) prefs_set_integer:(NSString *)key value:(int)value {
+ CFNumberRef x;
+
+ x = CFNumberCreate (NULL, kCFNumberIntType, &value);
+
+ CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr,
+ kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+
+ CFRelease (x);
+}
+
+- (void) prefs_set_float:(NSString *)key value:(float)value {
+ CFNumberRef x;
+
+ x = CFNumberCreate (NULL, kCFNumberFloatType, &value);
+
+ CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, app_prefs_domain_cfstr,
+ kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+
+ CFRelease (x);
+}
+
+- (void) prefs_set_boolean:(NSString *)key value:(int)value {
+ CFPreferencesSetValue ((CFStringRef) key,
+ (CFTypeRef) (value ? kCFBooleanTrue
+ : kCFBooleanFalse), app_prefs_domain_cfstr,
+ kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+
+}
+
+- (void) prefs_set_array:(NSString *)key value:(NSArray *)value {
+ CFArrayRef cfarray;
+
+ cfarray = nsarray_to_cfarray (value);
+ CFPreferencesSetValue ((CFStringRef) key,
+ (CFTypeRef) cfarray,
+ app_prefs_domain_cfstr,
+ kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
+ CFRelease (cfarray);
+}
+
+- (void) prefs_set_string:(NSString *)key value:(NSString *)value {
+ CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value,
+ app_prefs_domain_cfstr, kCFPreferencesCurrentUser,
+ kCFPreferencesAnyHost);
+}
+
+- (void) prefs_synchronize {
+ CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication);
+}
+
+- (void) read_defaults
+{
+ NSString *nsstr;
+ const char *tem;
+
+ quartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP
+ default:quartzUseSysBeep];
+ quartzEnableRootless = [self prefs_get_boolean:@PREFS_ROOTLESS
+ default:quartzEnableRootless];
+ quartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU
+ default:quartzFullscreenMenu];
+ quartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS
+ default:!quartzFullscreenDisableHotkeys];
+ darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS
+ default:darwinFakeButtons];
+ quartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT
+ default:quartzOptionSendsAlt];
+
+ if (darwinFakeButtons) {
+ const char *fake2, *fake3;
+
+ fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL];
+ fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL];
+
+ if (fake2 != NULL) darwinFakeMouse2Mask = DarwinParseModifierList(fake2, TRUE);
+ if (fake3 != NULL) darwinFakeMouse3Mask = DarwinParseModifierList(fake3, TRUE);
+ }
+
+ tem = [self prefs_get_string:@PREFS_APPKIT_MODIFIERS default:NULL];
+ if (tem != NULL) darwinAppKitModMask = DarwinParseModifierList(tem, TRUE);
+
+ tem = [self prefs_get_string:@PREFS_WINDOW_ITEM_MODIFIERS default:NULL];
+ if (tem != NULL) {
+ windowItemModMask = DarwinParseModifierList(tem, FALSE);
+ } else {
+ nsstr = NSLocalizedString (@"window item modifiers", @"window item modifiers");
+ if(nsstr != NULL) {
+ tem = [nsstr UTF8String];
+ if((tem != NULL) && strcmp(tem, "window item modifiers")) {
+ windowItemModMask = DarwinParseModifierList(tem, FALSE);
+ }
+ }
+ }
+
+ X11EnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS
+ default:X11EnableKeyEquivalents];
+
+ darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP
+ default:darwinSyncKeymap];
+
+ darwinDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH
+ default:darwinDesiredDepth];
+
+ noTestExtensions = ![self prefs_get_boolean:@PREFS_TEST_EXTENSIONS
+ default:FALSE];
+
+#if XQUARTZ_SPARKLE
+ NSURL *url = [self prefs_copy_url:@PREFS_UPDATE_FEED default:nil];
+ if(url) {
+ [[SUUpdater sharedUpdater] setFeedURL:url];
+ [url release];
+ }
+#endif
+}
+
+/* This will end up at the end of the responder chain. */
+- (void) copy:sender {
+ DarwinSendDDXEvent(kXquartzPasteboardNotify, 1,
+ AppleWMCopyToPasteboard);
+}
+
+- (X11Controller *) controller {
+ return _controller;
+}
+
+- (OSX_BOOL) x_active {
+ return _x_active;
+}
+
+@end
+
+static NSArray *
+array_with_strings_and_numbers (int nitems, const char **items,
+ const char *numbers) {
+ NSMutableArray *array, *subarray;
+ NSString *string, *number;
+ int i;
+
+ /* (Can't autorelease on the X server thread) */
+
+ array = [[NSMutableArray alloc] initWithCapacity:nitems];
+
+ for (i = 0; i < nitems; i++) {
+ subarray = [[NSMutableArray alloc] initWithCapacity:2];
+
+ string = [[NSString alloc] initWithUTF8String:items[i]];
+ [subarray addObject:string];
+ [string release];
+
+ if (numbers[i] != 0) {
+ number = [[NSString alloc] initWithFormat:@"%d", numbers[i]];
+ [subarray addObject:number];
+ [number release];
+ } else
+ [subarray addObject:@""];
+
+ [array addObject:subarray];
+ [subarray release];
+ }
+
+ return array;
+}
+
+void X11ApplicationSetWindowMenu (int nitems, const char **items,
+ const char *shortcuts) {
+ NSArray *array;
+ array = array_with_strings_and_numbers (nitems, items, shortcuts);
+
+ /* Send the array of strings over to the appkit thread */
+
+ message_kit_thread (@selector (set_window_menu:), array);
+ [array release];
+}
+
+void X11ApplicationSetWindowMenuCheck (int idx) {
+ NSNumber *n;
+
+ n = [[NSNumber alloc] initWithInt:idx];
+
+ message_kit_thread (@selector (set_window_menu_check:), n);
+
+ [n release];
+}
+
+void X11ApplicationSetFrontProcess (void) {
+ message_kit_thread (@selector (set_front_process:), nil);
+}
+
+void X11ApplicationSetCanQuit (int state) {
+ NSNumber *n;
+
+ n = [[NSNumber alloc] initWithBool:state];
+
+ message_kit_thread (@selector (set_can_quit:), n);
+
+ [n release];
+}
+
+void X11ApplicationServerReady (void) {
+ message_kit_thread (@selector (server_ready:), nil);
+}
+
+void X11ApplicationShowHideMenubar (int state) {
+ NSNumber *n;
+
+ n = [[NSNumber alloc] initWithBool:state];
+
+ message_kit_thread (@selector (show_hide_menubar:), n);
+
+ [n release];
+}
+
+void X11ApplicationLaunchClient (const char *cmd) {
+ NSString *string;
+
+ string = [[NSString alloc] initWithUTF8String:cmd];
+
+ message_kit_thread (@selector (launch_client:), string);
+
+ [string release];
+}
+
+static void check_xinitrc (void) {
+ char *tem, buf[1024];
+ NSString *msg;
+
+ if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO])
+ return;
+
+ tem = getenv ("HOME");
+ if (tem == NULL) goto done;
+
+ snprintf (buf, sizeof (buf), "%s/.xinitrc", tem);
+ if (access (buf, F_OK) != 0)
+ goto done;
+
+ msg = NSLocalizedString (@"You have an existing ~/.xinitrc file.\n\n\
+Windows displayed by X11 applications may not have titlebars, or may look \
+different to windows displayed by native applications.\n\n\
+Would you like to move aside the existing file and use the standard X11 \
+environment the next time you start X11?", @"Startup xinitrc dialog");
+
+ if(NSAlertDefaultReturn == NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""),
+ NSLocalizedString (@"No", @""), nil)) {
+ char buf2[1024];
+ int i = -1;
+
+ snprintf (buf2, sizeof (buf2), "%s.old", buf);
+
+ for(i = 1; access (buf2, F_OK) == 0; i++)
+ snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i);
+
+ rename (buf, buf2);
+ }
+
+ done:
+ [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES];
+ [X11App prefs_synchronize];
+}
+
+static inline pthread_t create_thread(void *func, void *arg) {
+ pthread_attr_t attr;
+ pthread_t tid;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&tid, &attr, func, arg);
+ pthread_attr_destroy(&attr);
+
+ return tid;
+}
+
+static void *xpbproxy_x_thread(void *args) {
+ xpbproxy_run();
+
+ fprintf(stderr, "xpbproxy thread is terminating unexpectedly.\n");
+ return NULL;
+}
+
+void X11ApplicationMain (int argc, char **argv, char **envp) {
+ NSAutoreleasePool *pool;
+
+#ifdef DEBUG
+ while (access ("/tmp/x11-block", F_OK) == 0) sleep (1);
+#endif
+
+ pool = [[NSAutoreleasePool alloc] init];
+ X11App = (X11Application *) [X11Application sharedApplication];
+ init_ports ();
+
+ app_prefs_domain_cfstr = (CFStringRef)[[NSBundle mainBundle] bundleIdentifier];
+
+ [NSApp read_defaults];
+ [NSBundle loadNibNamed:@"main" owner:NSApp];
+ [[NSNotificationCenter defaultCenter] addObserver:NSApp
+ selector:@selector (became_key:)
+ name:NSWindowDidBecomeKeyNotification object:nil];
+
+ /*
+ * The xpr Quartz mode is statically linked into this server.
+ * Initialize all the Quartz functions.
+ */
+ QuartzModeBundleInit();
+
+ /* Calculate the height of the menubar so we can avoid it. */
+ aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) -
+ NSMaxY([[NSScreen mainScreen] visibleFrame]);
+
+ /* Set the key layout seed before we start the server */
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ last_key_layout = TISCopyCurrentKeyboardLayoutInputSource();
+
+ if(!last_key_layout)
+ fprintf(stderr, "X11ApplicationMain: Unable to determine TISCopyCurrentKeyboardLayoutInputSource() at startup.\n");
+#else
+ KLGetCurrentKeyboardLayout(&last_key_layout);
+ if(!last_key_layout)
+ fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n");
+#endif
+
+ if (!QuartsResyncKeymap(FALSE)) {
+ fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n");
+ }
+
+ /* Tell the server thread that it can proceed */
+ QuartzInitServer(argc, argv, envp);
+
+ /* This must be done after QuartzInitServer because it can result in
+ * an mieqEnqueue() - <rdar://problem/6300249>
+ */
+ check_xinitrc();
+
+ create_thread(xpbproxy_x_thread, NULL);
+
+#if XQUARTZ_SPARKLE
+ [[X11App controller] setup_sparkle];
+ [[SUUpdater sharedUpdater] resetUpdateCycle];
+// [[SUUpdater sharedUpdater] checkForUpdates:X11App];
+#endif
+
+ [pool release];
+ [NSApp run];
+ /* not reached */
+}
+
+@implementation X11Application (Private)
+
+#ifdef NX_DEVICELCMDKEYMASK
+/* This is to workaround a bug in the VNC server where we sometimes see the L
+ * modifier and sometimes see no "side"
+ */
+static inline int ensure_flag(int flags, int device_independent, int device_dependents, int device_dependent_default) {
+ if( (flags & device_independent) &&
+ !(flags & device_dependents))
+ flags |= device_dependent_default;
+ return flags;
+}
+#endif
+
+- (void) sendX11NSEvent:(NSEvent *)e {
+ NSPoint location = NSZeroPoint, tilt = NSZeroPoint;
+ int ev_button, ev_type;
+ float pressure = 0.0;
+ DeviceIntPtr pDev;
+ int modifierFlags;
+ BOOL isMouseOrTabletEvent, isTabletEvent;
+
+ isMouseOrTabletEvent = [e type] == NSLeftMouseDown || [e type] == NSOtherMouseDown || [e type] == NSRightMouseDown ||
+ [e type] == NSLeftMouseUp || [e type] == NSOtherMouseUp || [e type] == NSRightMouseUp ||
+ [e type] == NSLeftMouseDragged || [e type] == NSOtherMouseDragged || [e type] == NSRightMouseDragged ||
+ [e type] == NSMouseMoved || [e type] == NSTabletPoint || [e type] == NSScrollWheel;
+
+ isTabletEvent = ([e type] == NSTabletPoint) ||
+ (isMouseOrTabletEvent && ([e subtype] == NSTabletPointEventSubtype || [e subtype] == NSTabletProximityEventSubtype));
+
+ if(isMouseOrTabletEvent) {
+ static NSPoint lastpt;
+ NSWindow *window = [e window];
+ NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame];
+ BOOL hasUntrustedPointerDelta;
+
+ // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that
+ // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets
+ // are not normally used in cases where that bug would present itself, so this is a fair tradeoff
+ // <rdar://problem/7111003> deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype
+ // http://xquartz.macosforge.org/trac/ticket/288
+ hasUntrustedPointerDelta = isTabletEvent;
+
+ // The deltaXY for middle click events also appear erroneous after fast user switching
+ // <rdar://problem/7979468> deltaX and deltaY are incorrect for NSOtherMouseDown and NSOtherMouseUp after FUS
+ // http://xquartz.macosforge.org/trac/ticket/389
+ hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSOtherMouseDown || [e type] == NSOtherMouseUp;
+
+ // The deltaXY for scroll events correspond to the scroll delta, not the pointer delta
+ // <rdar://problem/7989690> deltaXY for wheel events are being sent as mouse movement
+ hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSScrollWheel;
+
+ if (window != nil) {
+ NSRect frame = [window frame];
+ location = [e locationInWindow];
+ location.x += frame.origin.x;
+ location.y += frame.origin.y;
+ lastpt = location;
+ } else if(hasUntrustedPointerDelta) {
+ location = [e locationInWindow];
+ lastpt = location;
+ } else {
+ location.x = lastpt.x + [e deltaX];
+ location.y = lastpt.y - [e deltaY];
+ lastpt = [e locationInWindow];
+ }
+
+ /* Convert coordinate system */
+ location.y = (screen.origin.y + screen.size.height) - location.y;
+ }
+
+ modifierFlags = [e modifierFlags];
+
+#ifdef NX_DEVICELCMDKEYMASK
+ /* This is to workaround a bug in the VNC server where we sometimes see the L
+ * modifier and sometimes see no "side"
+ */
+ modifierFlags = ensure_flag(modifierFlags, NX_CONTROLMASK, NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK, NX_DEVICELCTLKEYMASK);
+ modifierFlags = ensure_flag(modifierFlags, NX_SHIFTMASK, NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK, NX_DEVICELSHIFTKEYMASK);
+ modifierFlags = ensure_flag(modifierFlags, NX_COMMANDMASK, NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK, NX_DEVICELCMDKEYMASK);
+ modifierFlags = ensure_flag(modifierFlags, NX_ALTERNATEMASK, NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK, NX_DEVICELALTKEYMASK);
+#endif
+
+ modifierFlags &= darwin_all_modifier_mask;
+
+ /* We don't receive modifier key events while out of focus, and 3button
+ * emulation mucks this up, so we need to check our modifier flag state
+ * on every event... ugg
+ */
+
+ if(darwin_all_modifier_flags != modifierFlags)
+ DarwinUpdateModKeys(modifierFlags);
+
+ switch ([e type]) {
+ case NSLeftMouseDown: ev_button=1; ev_type=ButtonPress; goto handle_mouse;
+ case NSOtherMouseDown: ev_button=2; ev_type=ButtonPress; goto handle_mouse;
+ case NSRightMouseDown: ev_button=3; ev_type=ButtonPress; goto handle_mouse;
+ case NSLeftMouseUp: ev_button=1; ev_type=ButtonRelease; goto handle_mouse;
+ case NSOtherMouseUp: ev_button=2; ev_type=ButtonRelease; goto handle_mouse;
+ case NSRightMouseUp: ev_button=3; ev_type=ButtonRelease; goto handle_mouse;
+ case NSLeftMouseDragged: ev_button=1; ev_type=MotionNotify; goto handle_mouse;
+ case NSOtherMouseDragged: ev_button=2; ev_type=MotionNotify; goto handle_mouse;
+ case NSRightMouseDragged: ev_button=3; ev_type=MotionNotify; goto handle_mouse;
+ case NSMouseMoved: ev_button=0; ev_type=MotionNotify; goto handle_mouse;
+ case NSTabletPoint: ev_button=0; ev_type=MotionNotify; goto handle_mouse;
+
+ handle_mouse:
+ pDev = darwinPointer;
+
+ /* NSTabletPoint can have no subtype */
+ if([e type] != NSTabletPoint &&
+ [e subtype] == NSTabletProximityEventSubtype) {
+ switch([e pointingDeviceType]) {
+ case NSEraserPointingDevice:
+ darwinTabletCurrent=darwinTabletEraser;
+ break;
+ case NSPenPointingDevice:
+ darwinTabletCurrent=darwinTabletStylus;
+ break;
+ case NSCursorPointingDevice:
+ case NSUnknownPointingDevice:
+ default:
+ darwinTabletCurrent=darwinTabletCursor;
+ break;
+ }
+
+ /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt
+ * So we just pretend the motion was caused by the mouse. Hopefully
+ * we'll have a better solution for this in the future (like maybe
+ * NSTabletProximityEventSubtype will come from NSTabletPoint
+ * rather than NSMouseMoved.
+ pressure = [e pressure];
+ tilt = [e tilt];
+ pDev = darwinTabletCurrent;
+ */
+
+ DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut,
+ location.x, location.y);
+ }
+
+ if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) {
+ pressure = [e pressure];
+ tilt = [e tilt];
+
+ pDev = darwinTabletCurrent;
+ }
+
+ if(!quartzServerVisible && noTestExtensions) {
+#if defined(XPLUGIN_VERSION) && XPLUGIN_VERSION > 0
+/* Older libXplugin (Tiger/"Stock" Leopard) aren't thread safe, so we can't call xp_find_window from the Appkit thread */
+ xp_window_id wid = 0;
+ xp_error e;
+
+ /* Sigh. Need to check that we're really over one of
+ * our windows. (We need to receive pointer events while
+ * not in the foreground, but we don't want to receive them
+ * when another window is over us or we might show a tooltip)
+ */
+
+ e = xp_find_window(location.x, location.y, 0, &wid);
+
+ if (e != XP_Success || (e == XP_Success && wid == 0))
+#endif
+ {
+ bgMouseLocation = location;
+ bgMouseLocationUpdated = TRUE;
+ return;
+ }
+ }
+
+ if(bgMouseLocationUpdated) {
+ if(!(ev_type == MotionNotify && ev_button == 0)) {
+ DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x,
+ location.y, pressure, tilt.x, tilt.y);
+ }
+ bgMouseLocationUpdated = FALSE;
+ }
+
+ DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x, location.y,
+ pressure, tilt.x, tilt.y);
+
+ break;
+
+ case NSTabletProximity:
+ switch([e pointingDeviceType]) {
+ case NSEraserPointingDevice:
+ darwinTabletCurrent=darwinTabletEraser;
+ break;
+ case NSPenPointingDevice:
+ darwinTabletCurrent=darwinTabletStylus;
+ break;
+ case NSCursorPointingDevice:
+ case NSUnknownPointingDevice:
+ default:
+ darwinTabletCurrent=darwinTabletCursor;
+ break;
+ }
+
+ DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut,
+ location.x, location.y);
+ break;
+
+ case NSScrollWheel:
+#if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0
+ /* If we're in the background, we need to send a MotionNotify event
+ * first, since we aren't getting them on background mouse motion
+ */
+ if(!quartzServerVisible && noTestExtensions) {
+ bgMouseLocationUpdated = FALSE;
+ DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, location.x,
+ location.y, pressure, tilt.x, tilt.y);
+ }
+#endif
+ DarwinSendScrollEvents([e deltaX], [e deltaY], location.x, location.y,
+ pressure, tilt.x, tilt.y);
+ break;
+
+ case NSKeyDown: case NSKeyUp:
+ {
+ /* XKB clobbers our keymap at startup, so we need to force it on the first keypress.
+ * TODO: Make this less of a kludge.
+ */
+ static int force_resync_keymap = YES;
+ if(force_resync_keymap) {
+ DarwinSendDDXEvent(kXquartzReloadKeymap, 0);
+ force_resync_keymap = NO;
+ }
+ }
+
+ if(darwinSyncKeymap) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ TISInputSourceRef key_layout = TISCopyCurrentKeyboardLayoutInputSource();
+ TISInputSourceRef clear;
+ if (CFEqual(key_layout, last_key_layout)) {
+ CFRelease(key_layout);
+ } else {
+ /* Swap/free thread-safely */
+ clear = last_key_layout;
+ last_key_layout = key_layout;
+ CFRelease(clear);
+#else
+ KeyboardLayoutRef key_layout;
+ KLGetCurrentKeyboardLayout(&key_layout);
+ if(key_layout != last_key_layout) {
+ last_key_layout = key_layout;
+#endif
+ /* Update keyInfo */
+ if (!QuartsResyncKeymap(TRUE)) {
+ fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n");
+ }
+ }
+ }
+
+ /* Avoid stuck keys on context switch */
+ if(keyState[[e keyCode]] == [e type])
+ return;
+ keyState[[e keyCode]] = [e type];
+
+ DarwinSendKeyboardEvents(([e type] == NSKeyDown) ? KeyPress : KeyRelease, [e keyCode]);
+ break;
+
+ default: break; /* for gcc */
+ }
+}
+@end
diff --git a/xorg-server/hw/xquartz/darwinEvents.c b/xorg-server/hw/xquartz/darwinEvents.c
index db3f5b24e..663087d74 100644
--- a/xorg-server/hw/xquartz/darwinEvents.c
+++ b/xorg-server/hw/xquartz/darwinEvents.c
@@ -238,8 +238,8 @@ static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr de
case kXquartzToggleFullscreen:
DEBUG_LOG("kXquartzToggleFullscreen\n");
- if (quartzEnableRootless)
- QuartzSetFullscreen(!quartzHasRoot);
+ if(quartzEnableRootless)
+ ErrorF("Ignoring kXquartzToggleFullscreen because of rootless mode.");
else if (quartzHasRoot)
QuartzHide();
else
diff --git a/xorg-server/hw/xquartz/quartz.c b/xorg-server/hw/xquartz/quartz.c
index de54290ab..3aa234e09 100644
--- a/xorg-server/hw/xquartz/quartz.c
+++ b/xorg-server/hw/xquartz/quartz.c
@@ -265,7 +265,6 @@ void QuartzUpdateScreens(void) {
pScreen->height = height;
DarwinAdjustScreenOrigins(&screenInfo);
- quartzProcs->UpdateScreen(pScreen);
/* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y,
* so use it rather than x/y
@@ -277,6 +276,7 @@ void QuartzUpdateScreens(void) {
pRoot = pScreen->root;
AppleWMSetScreenOrigin(pRoot);
pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL);
+
miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
/* <rdar://problem/7770779> pointer events are clipped to old display region after display reconfiguration
@@ -303,6 +303,8 @@ void QuartzUpdateScreens(void) {
e.u.configureNotify.borderWidth = wBorderWidth(pRoot);
e.u.configureNotify.override = pRoot->overrideRedirect;
DeliverEvents(pRoot, &e, 1, NullWindow);
+
+ quartzProcs->UpdateScreen(pScreen);
#ifdef FAKE_RANDR
RREditConnectionInfo(pScreen);
diff --git a/xorg-server/hw/xquartz/xpr/xprEvent.c b/xorg-server/hw/xquartz/xpr/xprEvent.c
index 6245cce42..38952b091 100644
--- a/xorg-server/hw/xquartz/xpr/xprEvent.c
+++ b/xorg-server/hw/xquartz/xpr/xprEvent.c
@@ -1,81 +1,81 @@
-/* Copyright (c) 2008 Apple Inc.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
- * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above
- * copyright holders shall not be used in advertising or otherwise to
- * promote the sale, use or other dealings in this Software without
- * prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "xpr.h"
-
-#include <X11/X.h>
-#include <X11/Xmd.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "windowstr.h"
-#include "pixmapstr.h"
-#include "inputstr.h"
-#include "eventstr.h"
-#include "mi.h"
-#include "scrnintstr.h"
-#include "mipointer.h"
-
-#include "darwin.h"
-#include "quartz.h"
-#include "quartzKeyboard.h"
-#include "darwinEvents.h"
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-#include "rootlessWindow.h"
-#include "xprEvent.h"
-
-Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev) {
- TA_SERVER();
-
- switch(e->subtype) {
- case kXquartzWindowState:
- DEBUG_LOG("kXquartzWindowState\n");
- RootlessNativeWindowStateChanged(xprGetXWindow(e->data[0]),
- e->data[1]);
- return TRUE;
-
- case kXquartzWindowMoved:
- DEBUG_LOG("kXquartzWindowMoved\n");
- RootlessNativeWindowMoved(xprGetXWindow(e->data[0]));
- return TRUE;
-
- case kXquartzBringAllToFront:
- DEBUG_LOG("kXquartzBringAllToFront\n");
- RootlessOrderAllWindows();
- return TRUE;
- default:
- return FALSE;
- }
-}
+/* Copyright (c) 2008 Apple Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above
+ * copyright holders shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without
+ * prior written authorization.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "xpr.h"
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "inputstr.h"
+#include "eventstr.h"
+#include "mi.h"
+#include "scrnintstr.h"
+#include "mipointer.h"
+
+#include "darwin.h"
+#include "quartz.h"
+#include "quartzKeyboard.h"
+#include "darwinEvents.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include "rootlessWindow.h"
+#include "xprEvent.h"
+
+Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev) {
+ TA_SERVER();
+
+ switch(e->subtype) {
+ case kXquartzWindowState:
+ DEBUG_LOG("kXquartzWindowState\n");
+ RootlessNativeWindowStateChanged(xprGetXWindow(e->data[0]),
+ e->data[1]);
+ return TRUE;
+
+ case kXquartzWindowMoved:
+ DEBUG_LOG("kXquartzWindowMoved\n");
+ RootlessNativeWindowMoved(xprGetXWindow(e->data[0]));
+ return TRUE;
+
+ case kXquartzBringAllToFront:
+ DEBUG_LOG("kXquartzBringAllToFront\n");
+ RootlessOrderAllWindows(e->data[0]);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
diff --git a/xorg-server/hw/xquartz/xpr/xprFrame.c b/xorg-server/hw/xquartz/xpr/xprFrame.c
index 52925339f..5a40cbf41 100644
--- a/xorg-server/hw/xquartz/xpr/xprFrame.c
+++ b/xorg-server/hw/xquartz/xpr/xprFrame.c
@@ -206,13 +206,16 @@ xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
static void
xprDestroyFrame(RootlessFrameID wid)
{
+ xp_error err;
TA_SERVER();
pthread_mutex_lock(&window_hash_mutex);
x_hash_table_remove(window_hash, wid);
pthread_mutex_unlock(&window_hash_mutex);
- xp_destroy_window(x_cvt_vptr_to_uint(wid));
+ err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
+ if (err != Success)
+ FatalError("Could not destroy window %i.", (int)x_cvt_vptr_to_uint(wid));
}
@@ -366,9 +369,12 @@ xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
static void
xprStopDrawing(RootlessFrameID wid, Bool flush)
{
+ xp_error err;
TA_SERVER();
- xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
+ err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
+ if(err != Success)
+ FatalError("Could not unlock window %i after drawing.", (int)x_cvt_vptr_to_uint(wid));
}
diff --git a/xorg-server/miext/rootless/rootless.h b/xorg-server/miext/rootless/rootless.h
index 00eac4e8a..1046657c4 100644
--- a/xorg-server/miext/rootless/rootless.h
+++ b/xorg-server/miext/rootless/rootless.h
@@ -1,450 +1,450 @@
-/*
- * External interface to generic rootless mode
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef _ROOTLESS_H
-#define _ROOTLESS_H
-
-#include "rootlessConfig.h"
-#include "mi.h"
-#include "gcstruct.h"
-
-/*
- Each top-level rootless window has a one-to-one correspondence to a physical
- on-screen window. The physical window is refered to as a "frame".
- */
-
-typedef void * RootlessFrameID;
-
-/*
- * RootlessWindowRec
- * This structure stores the per-frame data used by the rootless code.
- * Each top-level X window has one RootlessWindowRec associated with it.
- */
-typedef struct _RootlessWindowRec {
- // Position and size includes the window border
- // Position is in per-screen coordinates
- int x, y;
- unsigned int width, height;
- unsigned int borderWidth;
- int level;
-
- RootlessFrameID wid; // implementation specific frame id
- WindowPtr win; // underlying X window
-
- // Valid only when drawing (ie. is_drawing is set)
- char *pixelData;
- int bytesPerRow;
-
- PixmapPtr pixmap;
-
-#ifdef ROOTLESS_TRACK_DAMAGE
- RegionRec damage;
-#endif
-
- unsigned int is_drawing :1; // Currently drawing?
- unsigned int is_reorder_pending :1;
- unsigned int is_offscreen :1;
- unsigned int is_obscured :1;
-} RootlessWindowRec, *RootlessWindowPtr;
-
-
-/* Offset for screen-local to global coordinate transforms */
-#ifdef ROOTLESS_GLOBAL_COORDS
-extern int rootlessGlobalOffsetX;
-extern int rootlessGlobalOffsetY;
-#endif
-
-/* The minimum number of bytes or pixels for which to use the
- implementation's accelerated functions. */
-extern unsigned int rootless_CopyBytes_threshold;
-extern unsigned int rootless_FillBytes_threshold;
-extern unsigned int rootless_CompositePixels_threshold;
-extern unsigned int rootless_CopyWindow_threshold;
-
-/* Operations used by CompositePixels */
-enum rl_composite_op_enum {
- RL_COMPOSITE_SRC = 0,
- RL_COMPOSITE_OVER,
-};
-
-/* Data formats for depth field and composite functions */
-enum rl_depth_enum {
- RL_DEPTH_NIL = 0, /* null source when compositing */
- RL_DEPTH_ARGB8888,
- RL_DEPTH_RGB555,
- RL_DEPTH_A8, /* for masks when compositing */
- RL_DEPTH_INDEX8,
-};
-
-/* Macro to form the composite function for CompositePixels */
-#define RL_COMPOSITE_FUNCTION(op, src_depth, mask_depth, dest_depth) \
- (((op) << 24) | ((src_depth) << 16) \
- | ((mask_depth) << 8) | ((dest_depth) << 0))
-
-/* Gravity for window contents during resizing */
-enum rl_gravity_enum {
- RL_GRAVITY_NONE = 0, /* no gravity, fill everything */
- RL_GRAVITY_NORTH_WEST = 1, /* anchor to top-left corner */
- RL_GRAVITY_NORTH_EAST = 2, /* anchor to top-right corner */
- RL_GRAVITY_SOUTH_EAST = 3, /* anchor to bottom-right corner */
- RL_GRAVITY_SOUTH_WEST = 4, /* anchor to bottom-left corner */
-};
-
-
-/*------------------------------------------
- Rootless Implementation Functions
- ------------------------------------------*/
-
-/*
- * Create a new frame.
- * The frame is created unmapped.
- *
- * pFrame RootlessWindowPtr for this frame should be completely
- * initialized before calling except for pFrame->wid, which
- * is set by this function.
- * pScreen Screen on which to place the new frame
- * newX, newY Position of the frame. These will be identical to pFrame-x,
- * pFrame->y unless ROOTLESS_GLOBAL_COORDS is set.
- * pNewShape Shape for the frame (in frame-local coordinates). NULL for
- * unshaped frames.
- */
-typedef Bool (*RootlessCreateFrameProc)
- (RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY,
- RegionPtr pNewShape);
-
-/*
- * Destroy a frame.
- * Drawing is stopped and all updates are flushed before this is called.
- *
- * wid Frame id
- */
-typedef void (*RootlessDestroyFrameProc)
- (RootlessFrameID wid);
-
-/*
- * Move a frame on screen.
- * Drawing is stopped and all updates are flushed before this is called.
- *
- * wid Frame id
- * pScreen Screen to move the new frame to
- * newX, newY New position of the frame
- */
-typedef void (*RootlessMoveFrameProc)
- (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
-
-/*
- * Resize and move a frame.
- * Drawing is stopped and all updates are flushed before this is called.
- *
- * wid Frame id
- * pScreen Screen to move the new frame to
- * newX, newY New position of the frame
- * newW, newH New size of the frame
- * gravity Gravity for window contents (rl_gravity_enum). This is always
- * RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set.
- */
-typedef void (*RootlessResizeFrameProc)
- (RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity);
-
-/*
- * Change frame ordering (AKA stacking, layering).
- * Drawing is stopped before this is called. Unmapped frames are mapped by
- * setting their ordering.
- *
- * wid Frame id
- * nextWid Frame id of frame that is now above this one or NULL if this
- * frame is at the top.
- */
-typedef void (*RootlessRestackFrameProc)
- (RootlessFrameID wid, RootlessFrameID nextWid);
-
-/*
- * Change frame's shape.
- * Drawing is stopped before this is called.
- *
- * wid Frame id
- * pNewShape New shape for the frame (in frame-local coordinates)
- * or NULL if now unshaped.
- */
-typedef void (*RootlessReshapeFrameProc)
- (RootlessFrameID wid, RegionPtr pNewShape);
-
-/*
- * Unmap a frame.
- *
- * wid Frame id
- */
-typedef void (*RootlessUnmapFrameProc)
- (RootlessFrameID wid);
-
-/*
- * Start drawing to a frame.
- * Prepare a frame for direct access to its backing buffer.
- *
- * wid Frame id
- * pixelData Address of the backing buffer (returned)
- * bytesPerRow Width in bytes of the backing buffer (returned)
- */
-typedef void (*RootlessStartDrawingProc)
- (RootlessFrameID wid, char **pixelData, int *bytesPerRow);
-
-/*
- * Stop drawing to a frame.
- * No drawing to the frame's backing buffer will occur until drawing
- * is started again.
- *
- * wid Frame id
- * flush Flush drawing updates for this frame to the screen. This
- * will always be FALSE if ROOTLESS_TRACK_DAMAGE is set.
- */
-typedef void (*RootlessStopDrawingProc)
- (RootlessFrameID wid, Bool flush);
-
-/*
- * Flush drawing updates to the screen.
- * Drawing is stopped before this is called.
- *
- * wid Frame id
- * pDamage Region containing all the changed pixels in frame-lcoal
- * coordinates. This is clipped to the window's clip. This
- * will be NULL if ROOTLESS_TRACK_DAMAGE is not set.
- */
-typedef void (*RootlessUpdateRegionProc)
- (RootlessFrameID wid, RegionPtr pDamage);
-
-/*
- * Mark damaged rectangles as requiring redisplay to screen.
- * This will only be called if ROOTLESS_TRACK_DAMAGE is not set.
- *
- * wid Frame id
- * nrects Number of damaged rectangles
- * rects Array of damaged rectangles in frame-local coordinates
- * shift_x, Vector to shift rectangles by
- * shift_y
- */
-typedef void (*RootlessDamageRectsProc)
- (RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y);
-
-/*
- * Switch the window associated with a frame. (Optional)
- * When a framed window is reparented, the frame is resized and set to
- * use the new top-level parent. If defined this function will be called
- * afterwards for implementation specific bookkeeping.
- *
- * pFrame Frame whose window has switched
- * oldWin Previous window wrapped by this frame
- */
-typedef void (*RootlessSwitchWindowProc)
- (RootlessWindowPtr pFrame, WindowPtr oldWin);
-
-/*
- * Check if window should be reordered. (Optional)
- * The underlying window system may animate windows being ordered in.
- * We want them to be mapped but remain ordered out until the animation
- * completes. If defined this function will be called to check if a
- * framed window should be reordered now. If this function returns
- * FALSE, the window will still be mapped from the X11 perspective, but
- * the RestackFrame function will not be called for its frame.
- *
- * pFrame Frame to reorder
- */
-typedef Bool (*RootlessDoReorderWindowProc)
- (RootlessWindowPtr pFrame);
-
-/*
- * Copy bytes. (Optional)
- * Source and destinate may overlap and the right thing should happen.
- *
- * width Bytes to copy per row
- * height Number of rows
- * src Source data
- * srcRowBytes Width of source in bytes
- * dst Destination data
- * dstRowBytes Width of destination in bytes
- */
-typedef void (*RootlessCopyBytesProc)
- (unsigned int width, unsigned int height,
- const void *src, unsigned int srcRowBytes,
- void *dst, unsigned int dstRowBytes);
-
-/*
- * Fill memory with 32-bit pattern. (Optional)
- *
- * width Bytes to fill per row
- * height Number of rows
- * value 32-bit pattern to fill with
- * dst Destination data
- * dstRowBytes Width of destination in bytes
- */
-typedef void (*RootlessFillBytesProc)
- (unsigned int width, unsigned int height, unsigned int value,
- void *dst, unsigned int dstRowBytes);
-
-/*
- * Composite pixels from source and mask to destination. (Optional)
- *
- * width, height Size of area to composite to in pizels
- * function Composite function built with RL_COMPOSITE_FUNCTION
- * src Source data
- * srcRowBytes Width of source in bytes (Passing NULL means source
- * is a single pixel.
- * mask Mask data
- * maskRowBytes Width of mask in bytes
- * dst Destination data
- * dstRowBytes Width of destination in bytes
- *
- * For src and dst, the first element of the array is the color data. If
- * the second element is non-null it implies there is alpha data (which
- * may be meshed or planar). Data without alpha is assumed to be opaque.
- *
- * An X11 error code is returned.
- */
-typedef int (*RootlessCompositePixelsProc)
- (unsigned int width, unsigned int height, unsigned int function,
- void *src[2], unsigned int srcRowBytes[2],
- void *mask, unsigned int maskRowBytes,
- void *dst[2], unsigned int dstRowBytes[2]);
-
-/*
- * Copy area in frame to another part of frame. (Optional)
- *
- * wid Frame id
- * dstNrects Number of rectangles to copy
- * dstRects Array of rectangles to copy
- * dx, dy Number of pixels away to copy area
- */
-typedef void (*RootlessCopyWindowProc)
- (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy);
-
-
-typedef void (*RootlessHideWindowProc)
- (RootlessFrameID wid);
-
-typedef void (*RootlessUpdateColormapProc)
- (RootlessFrameID wid, ScreenPtr pScreen);
-
-/*
- * Rootless implementation function list
- */
-typedef struct _RootlessFrameProcs {
- RootlessCreateFrameProc CreateFrame;
- RootlessDestroyFrameProc DestroyFrame;
-
- RootlessMoveFrameProc MoveFrame;
- RootlessResizeFrameProc ResizeFrame;
- RootlessRestackFrameProc RestackFrame;
- RootlessReshapeFrameProc ReshapeFrame;
- RootlessUnmapFrameProc UnmapFrame;
-
- RootlessStartDrawingProc StartDrawing;
- RootlessStopDrawingProc StopDrawing;
- RootlessUpdateRegionProc UpdateRegion;
-#ifndef ROOTLESS_TRACK_DAMAGE
- RootlessDamageRectsProc DamageRects;
-#endif
-
- /* Optional frame functions */
- RootlessSwitchWindowProc SwitchWindow;
- RootlessDoReorderWindowProc DoReorderWindow;
- RootlessHideWindowProc HideWindow;
- RootlessUpdateColormapProc UpdateColormap;
-
- /* Optional acceleration functions */
- RootlessCopyBytesProc CopyBytes;
- RootlessFillBytesProc FillBytes;
- RootlessCompositePixelsProc CompositePixels;
- RootlessCopyWindowProc CopyWindow;
-} RootlessFrameProcsRec, *RootlessFrameProcsPtr;
-
-
-/*
- * Initialize rootless mode on the given screen.
- */
-Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs);
-
-/*
- * Initialize acceleration for rootless mode on a given screen.
- * Note: RootlessAccelInit() must be called before DamageSetup()
- * and RootlessInit() must be called afterwards.
- */
-Bool RootlessAccelInit(ScreenPtr pScreen);
-
-/*
- * Return the frame ID for the physical window displaying the given window.
- *
- * create If true and the window has no frame, attempt to create one
- */
-RootlessFrameID RootlessFrameForWindow(WindowPtr pWin, Bool create);
-
-/*
- * Return the top-level parent of a window.
- * The root is the top-level parent of itself, even though the root is
- * not otherwise considered to be a top-level window.
- */
-WindowPtr TopLevelParent(WindowPtr pWindow);
-
-/*
- * Prepare a window for direct access to its backing buffer.
- */
-void RootlessStartDrawing(WindowPtr pWindow);
-
-/*
- * Finish drawing to a window's backing buffer.
- *
- * flush If true and ROOTLESS_TRACK_DAMAGE is set, damaged areas
- * are flushed to the screen.
- */
-void RootlessStopDrawing(WindowPtr pWindow, Bool flush);
-
-/*
- * Alocate a new screen pixmap.
- * miCreateScreenResources does not do this properly with a null
- * framebuffer pointer.
- */
-void RootlessUpdateScreenPixmap(ScreenPtr pScreen);
-
-/*
- * Reposition all windows on a screen to their correct positions.
- */
-void RootlessRepositionWindows(ScreenPtr pScreen);
-
-/*
- * Bring all windows to the front of the Aqua stack
- */
-void RootlessOrderAllWindows (void);
-#endif /* _ROOTLESS_H */
+/*
+ * External interface to generic rootless mode
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _ROOTLESS_H
+#define _ROOTLESS_H
+
+#include "rootlessConfig.h"
+#include "mi.h"
+#include "gcstruct.h"
+
+/*
+ Each top-level rootless window has a one-to-one correspondence to a physical
+ on-screen window. The physical window is refered to as a "frame".
+ */
+
+typedef void * RootlessFrameID;
+
+/*
+ * RootlessWindowRec
+ * This structure stores the per-frame data used by the rootless code.
+ * Each top-level X window has one RootlessWindowRec associated with it.
+ */
+typedef struct _RootlessWindowRec {
+ // Position and size includes the window border
+ // Position is in per-screen coordinates
+ int x, y;
+ unsigned int width, height;
+ unsigned int borderWidth;
+ int level;
+
+ RootlessFrameID wid; // implementation specific frame id
+ WindowPtr win; // underlying X window
+
+ // Valid only when drawing (ie. is_drawing is set)
+ char *pixelData;
+ int bytesPerRow;
+
+ PixmapPtr pixmap;
+
+#ifdef ROOTLESS_TRACK_DAMAGE
+ RegionRec damage;
+#endif
+
+ unsigned int is_drawing :1; // Currently drawing?
+ unsigned int is_reorder_pending :1;
+ unsigned int is_offscreen :1;
+ unsigned int is_obscured :1;
+} RootlessWindowRec, *RootlessWindowPtr;
+
+
+/* Offset for screen-local to global coordinate transforms */
+#ifdef ROOTLESS_GLOBAL_COORDS
+extern int rootlessGlobalOffsetX;
+extern int rootlessGlobalOffsetY;
+#endif
+
+/* The minimum number of bytes or pixels for which to use the
+ implementation's accelerated functions. */
+extern unsigned int rootless_CopyBytes_threshold;
+extern unsigned int rootless_FillBytes_threshold;
+extern unsigned int rootless_CompositePixels_threshold;
+extern unsigned int rootless_CopyWindow_threshold;
+
+/* Operations used by CompositePixels */
+enum rl_composite_op_enum {
+ RL_COMPOSITE_SRC = 0,
+ RL_COMPOSITE_OVER,
+};
+
+/* Data formats for depth field and composite functions */
+enum rl_depth_enum {
+ RL_DEPTH_NIL = 0, /* null source when compositing */
+ RL_DEPTH_ARGB8888,
+ RL_DEPTH_RGB555,
+ RL_DEPTH_A8, /* for masks when compositing */
+ RL_DEPTH_INDEX8,
+};
+
+/* Macro to form the composite function for CompositePixels */
+#define RL_COMPOSITE_FUNCTION(op, src_depth, mask_depth, dest_depth) \
+ (((op) << 24) | ((src_depth) << 16) \
+ | ((mask_depth) << 8) | ((dest_depth) << 0))
+
+/* Gravity for window contents during resizing */
+enum rl_gravity_enum {
+ RL_GRAVITY_NONE = 0, /* no gravity, fill everything */
+ RL_GRAVITY_NORTH_WEST = 1, /* anchor to top-left corner */
+ RL_GRAVITY_NORTH_EAST = 2, /* anchor to top-right corner */
+ RL_GRAVITY_SOUTH_EAST = 3, /* anchor to bottom-right corner */
+ RL_GRAVITY_SOUTH_WEST = 4, /* anchor to bottom-left corner */
+};
+
+
+/*------------------------------------------
+ Rootless Implementation Functions
+ ------------------------------------------*/
+
+/*
+ * Create a new frame.
+ * The frame is created unmapped.
+ *
+ * pFrame RootlessWindowPtr for this frame should be completely
+ * initialized before calling except for pFrame->wid, which
+ * is set by this function.
+ * pScreen Screen on which to place the new frame
+ * newX, newY Position of the frame. These will be identical to pFrame-x,
+ * pFrame->y unless ROOTLESS_GLOBAL_COORDS is set.
+ * pNewShape Shape for the frame (in frame-local coordinates). NULL for
+ * unshaped frames.
+ */
+typedef Bool (*RootlessCreateFrameProc)
+ (RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY,
+ RegionPtr pNewShape);
+
+/*
+ * Destroy a frame.
+ * Drawing is stopped and all updates are flushed before this is called.
+ *
+ * wid Frame id
+ */
+typedef void (*RootlessDestroyFrameProc)
+ (RootlessFrameID wid);
+
+/*
+ * Move a frame on screen.
+ * Drawing is stopped and all updates are flushed before this is called.
+ *
+ * wid Frame id
+ * pScreen Screen to move the new frame to
+ * newX, newY New position of the frame
+ */
+typedef void (*RootlessMoveFrameProc)
+ (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
+
+/*
+ * Resize and move a frame.
+ * Drawing is stopped and all updates are flushed before this is called.
+ *
+ * wid Frame id
+ * pScreen Screen to move the new frame to
+ * newX, newY New position of the frame
+ * newW, newH New size of the frame
+ * gravity Gravity for window contents (rl_gravity_enum). This is always
+ * RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set.
+ */
+typedef void (*RootlessResizeFrameProc)
+ (RootlessFrameID wid, ScreenPtr pScreen,
+ int newX, int newY, unsigned int newW, unsigned int newH,
+ unsigned int gravity);
+
+/*
+ * Change frame ordering (AKA stacking, layering).
+ * Drawing is stopped before this is called. Unmapped frames are mapped by
+ * setting their ordering.
+ *
+ * wid Frame id
+ * nextWid Frame id of frame that is now above this one or NULL if this
+ * frame is at the top.
+ */
+typedef void (*RootlessRestackFrameProc)
+ (RootlessFrameID wid, RootlessFrameID nextWid);
+
+/*
+ * Change frame's shape.
+ * Drawing is stopped before this is called.
+ *
+ * wid Frame id
+ * pNewShape New shape for the frame (in frame-local coordinates)
+ * or NULL if now unshaped.
+ */
+typedef void (*RootlessReshapeFrameProc)
+ (RootlessFrameID wid, RegionPtr pNewShape);
+
+/*
+ * Unmap a frame.
+ *
+ * wid Frame id
+ */
+typedef void (*RootlessUnmapFrameProc)
+ (RootlessFrameID wid);
+
+/*
+ * Start drawing to a frame.
+ * Prepare a frame for direct access to its backing buffer.
+ *
+ * wid Frame id
+ * pixelData Address of the backing buffer (returned)
+ * bytesPerRow Width in bytes of the backing buffer (returned)
+ */
+typedef void (*RootlessStartDrawingProc)
+ (RootlessFrameID wid, char **pixelData, int *bytesPerRow);
+
+/*
+ * Stop drawing to a frame.
+ * No drawing to the frame's backing buffer will occur until drawing
+ * is started again.
+ *
+ * wid Frame id
+ * flush Flush drawing updates for this frame to the screen. This
+ * will always be FALSE if ROOTLESS_TRACK_DAMAGE is set.
+ */
+typedef void (*RootlessStopDrawingProc)
+ (RootlessFrameID wid, Bool flush);
+
+/*
+ * Flush drawing updates to the screen.
+ * Drawing is stopped before this is called.
+ *
+ * wid Frame id
+ * pDamage Region containing all the changed pixels in frame-lcoal
+ * coordinates. This is clipped to the window's clip. This
+ * will be NULL if ROOTLESS_TRACK_DAMAGE is not set.
+ */
+typedef void (*RootlessUpdateRegionProc)
+ (RootlessFrameID wid, RegionPtr pDamage);
+
+/*
+ * Mark damaged rectangles as requiring redisplay to screen.
+ * This will only be called if ROOTLESS_TRACK_DAMAGE is not set.
+ *
+ * wid Frame id
+ * nrects Number of damaged rectangles
+ * rects Array of damaged rectangles in frame-local coordinates
+ * shift_x, Vector to shift rectangles by
+ * shift_y
+ */
+typedef void (*RootlessDamageRectsProc)
+ (RootlessFrameID wid, int nrects, const BoxRec *rects,
+ int shift_x, int shift_y);
+
+/*
+ * Switch the window associated with a frame. (Optional)
+ * When a framed window is reparented, the frame is resized and set to
+ * use the new top-level parent. If defined this function will be called
+ * afterwards for implementation specific bookkeeping.
+ *
+ * pFrame Frame whose window has switched
+ * oldWin Previous window wrapped by this frame
+ */
+typedef void (*RootlessSwitchWindowProc)
+ (RootlessWindowPtr pFrame, WindowPtr oldWin);
+
+/*
+ * Check if window should be reordered. (Optional)
+ * The underlying window system may animate windows being ordered in.
+ * We want them to be mapped but remain ordered out until the animation
+ * completes. If defined this function will be called to check if a
+ * framed window should be reordered now. If this function returns
+ * FALSE, the window will still be mapped from the X11 perspective, but
+ * the RestackFrame function will not be called for its frame.
+ *
+ * pFrame Frame to reorder
+ */
+typedef Bool (*RootlessDoReorderWindowProc)
+ (RootlessWindowPtr pFrame);
+
+/*
+ * Copy bytes. (Optional)
+ * Source and destinate may overlap and the right thing should happen.
+ *
+ * width Bytes to copy per row
+ * height Number of rows
+ * src Source data
+ * srcRowBytes Width of source in bytes
+ * dst Destination data
+ * dstRowBytes Width of destination in bytes
+ */
+typedef void (*RootlessCopyBytesProc)
+ (unsigned int width, unsigned int height,
+ const void *src, unsigned int srcRowBytes,
+ void *dst, unsigned int dstRowBytes);
+
+/*
+ * Fill memory with 32-bit pattern. (Optional)
+ *
+ * width Bytes to fill per row
+ * height Number of rows
+ * value 32-bit pattern to fill with
+ * dst Destination data
+ * dstRowBytes Width of destination in bytes
+ */
+typedef void (*RootlessFillBytesProc)
+ (unsigned int width, unsigned int height, unsigned int value,
+ void *dst, unsigned int dstRowBytes);
+
+/*
+ * Composite pixels from source and mask to destination. (Optional)
+ *
+ * width, height Size of area to composite to in pizels
+ * function Composite function built with RL_COMPOSITE_FUNCTION
+ * src Source data
+ * srcRowBytes Width of source in bytes (Passing NULL means source
+ * is a single pixel.
+ * mask Mask data
+ * maskRowBytes Width of mask in bytes
+ * dst Destination data
+ * dstRowBytes Width of destination in bytes
+ *
+ * For src and dst, the first element of the array is the color data. If
+ * the second element is non-null it implies there is alpha data (which
+ * may be meshed or planar). Data without alpha is assumed to be opaque.
+ *
+ * An X11 error code is returned.
+ */
+typedef int (*RootlessCompositePixelsProc)
+ (unsigned int width, unsigned int height, unsigned int function,
+ void *src[2], unsigned int srcRowBytes[2],
+ void *mask, unsigned int maskRowBytes,
+ void *dst[2], unsigned int dstRowBytes[2]);
+
+/*
+ * Copy area in frame to another part of frame. (Optional)
+ *
+ * wid Frame id
+ * dstNrects Number of rectangles to copy
+ * dstRects Array of rectangles to copy
+ * dx, dy Number of pixels away to copy area
+ */
+typedef void (*RootlessCopyWindowProc)
+ (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
+ int dx, int dy);
+
+
+typedef void (*RootlessHideWindowProc)
+ (RootlessFrameID wid);
+
+typedef void (*RootlessUpdateColormapProc)
+ (RootlessFrameID wid, ScreenPtr pScreen);
+
+/*
+ * Rootless implementation function list
+ */
+typedef struct _RootlessFrameProcs {
+ RootlessCreateFrameProc CreateFrame;
+ RootlessDestroyFrameProc DestroyFrame;
+
+ RootlessMoveFrameProc MoveFrame;
+ RootlessResizeFrameProc ResizeFrame;
+ RootlessRestackFrameProc RestackFrame;
+ RootlessReshapeFrameProc ReshapeFrame;
+ RootlessUnmapFrameProc UnmapFrame;
+
+ RootlessStartDrawingProc StartDrawing;
+ RootlessStopDrawingProc StopDrawing;
+ RootlessUpdateRegionProc UpdateRegion;
+#ifndef ROOTLESS_TRACK_DAMAGE
+ RootlessDamageRectsProc DamageRects;
+#endif
+
+ /* Optional frame functions */
+ RootlessSwitchWindowProc SwitchWindow;
+ RootlessDoReorderWindowProc DoReorderWindow;
+ RootlessHideWindowProc HideWindow;
+ RootlessUpdateColormapProc UpdateColormap;
+
+ /* Optional acceleration functions */
+ RootlessCopyBytesProc CopyBytes;
+ RootlessFillBytesProc FillBytes;
+ RootlessCompositePixelsProc CompositePixels;
+ RootlessCopyWindowProc CopyWindow;
+} RootlessFrameProcsRec, *RootlessFrameProcsPtr;
+
+
+/*
+ * Initialize rootless mode on the given screen.
+ */
+Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs);
+
+/*
+ * Initialize acceleration for rootless mode on a given screen.
+ * Note: RootlessAccelInit() must be called before DamageSetup()
+ * and RootlessInit() must be called afterwards.
+ */
+Bool RootlessAccelInit(ScreenPtr pScreen);
+
+/*
+ * Return the frame ID for the physical window displaying the given window.
+ *
+ * create If true and the window has no frame, attempt to create one
+ */
+RootlessFrameID RootlessFrameForWindow(WindowPtr pWin, Bool create);
+
+/*
+ * Return the top-level parent of a window.
+ * The root is the top-level parent of itself, even though the root is
+ * not otherwise considered to be a top-level window.
+ */
+WindowPtr TopLevelParent(WindowPtr pWindow);
+
+/*
+ * Prepare a window for direct access to its backing buffer.
+ */
+void RootlessStartDrawing(WindowPtr pWindow);
+
+/*
+ * Finish drawing to a window's backing buffer.
+ *
+ * flush If true and ROOTLESS_TRACK_DAMAGE is set, damaged areas
+ * are flushed to the screen.
+ */
+void RootlessStopDrawing(WindowPtr pWindow, Bool flush);
+
+/*
+ * Alocate a new screen pixmap.
+ * miCreateScreenResources does not do this properly with a null
+ * framebuffer pointer.
+ */
+void RootlessUpdateScreenPixmap(ScreenPtr pScreen);
+
+/*
+ * Reposition all windows on a screen to their correct positions.
+ */
+void RootlessRepositionWindows(ScreenPtr pScreen);
+
+/*
+ * Bring all windows to the front of the native stack
+ */
+void RootlessOrderAllWindows (Bool include_unhitable);
+#endif /* _ROOTLESS_H */
diff --git a/xorg-server/miext/rootless/rootlessWindow.c b/xorg-server/miext/rootless/rootlessWindow.c
index 8967602d5..a9cecd2e3 100644
--- a/xorg-server/miext/rootless/rootlessWindow.c
+++ b/xorg-server/miext/rootless/rootlessWindow.c
@@ -587,10 +587,15 @@ RootlessReorderWindow(WindowPtr pWin)
RootlessStopDrawing(pWin, FALSE);
- /* Find the next window above this one that has a mapped frame. */
+ /* Find the next window above this one that has a mapped frame.
+ * Only include cases where the windows are in the same category of
+ * hittability to ensure offscreen windows dont get restacked
+ * relative to onscreen ones (but that the offscreen ones maintain
+ * their stacking order if they are explicitly asked to Reorder
+ */
newPrevW = pWin->prevSib;
- while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized))
+ while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable))
newPrevW = newPrevW->prevSib;
newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL;
@@ -1508,7 +1513,7 @@ RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
* (i.e in front of Aqua windows) -- called when X11.app is given focus
*/
void
-RootlessOrderAllWindows (void)
+RootlessOrderAllWindows (Bool include_unhitable)
{
int i;
WindowPtr pWin;
@@ -1525,6 +1530,7 @@ RootlessOrderAllWindows (void)
for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
if (!pWin->realized) continue;
if (RootlessEnsureFrame(pWin) == NULL) continue;
+ if (!include_unhitable && pWin->rootlessUnhittable) continue;
RootlessReorderWindow (pWin);
}
}