Blame synfig-osx/launcher/X11Application.m

Carlos Lopez a09598
/* X11Application.m -- subclass of NSApplication to multiplex events
Carlos Lopez a09598
   $Id: X11Application.m,v 1.53 2003/09/13 02:00:46 jharper Exp $
Carlos Lopez a09598
Carlos Lopez a09598
   Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
Carlos Lopez a09598
Carlos Lopez a09598
   Permission is hereby granted, free of charge, to any person
Carlos Lopez a09598
   obtaining a copy of this software and associated documentation files
Carlos Lopez a09598
   (the "Software"), to deal in the Software without restriction,
Carlos Lopez a09598
   including without limitation the rights to use, copy, modify, merge,
Carlos Lopez a09598
   publish, distribute, sublicense, and/or sell copies of the Software,
Carlos Lopez a09598
   and to permit persons to whom the Software is furnished to do so,
Carlos Lopez a09598
   subject to the following conditions:
Carlos Lopez a09598
Carlos Lopez a09598
   The above copyright notice and this permission notice shall be
Carlos Lopez a09598
   included in all copies or substantial portions of the Software.
Carlos Lopez a09598
Carlos Lopez a09598
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Carlos Lopez a09598
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Carlos Lopez a09598
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Carlos Lopez a09598
   NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
Carlos Lopez a09598
   HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
Carlos Lopez a09598
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Carlos Lopez a09598
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Carlos Lopez a09598
   DEALINGS IN THE SOFTWARE.
Carlos Lopez a09598
Carlos Lopez a09598
   Except as contained in this notice, the name(s) of the above
Carlos Lopez a09598
   copyright holders shall not be used in advertising or otherwise to
Carlos Lopez a09598
   promote the sale, use or other dealings in this Software without
Carlos Lopez a09598
   prior written authorization. */
Carlos Lopez a09598
Carlos Lopez a09598
#import "X11Application.h"
Carlos Lopez a09598
#include <carbon carbon.h=""></carbon>
Carlos Lopez a09598
Carlos Lopez a09598
/* ouch! */
Carlos Lopez a09598
#define BOOL X_BOOL
Carlos Lopez a09598
# include "Xproto.h"
Carlos Lopez a09598
#define WindowPtr X_WindowPtr
Carlos Lopez a09598
#define Cursor X_Cursor
Carlos Lopez a09598
# include "quartz.h"
Carlos Lopez a09598
# define _APPLEWM_SERVER_
Carlos Lopez a09598
# include "applewm.h"
Carlos Lopez a09598
# include "X.h"
Carlos Lopez a09598
#undef Cursor
Carlos Lopez a09598
#undef WindowPtr
Carlos Lopez a09598
#undef BOOL
Carlos Lopez a09598
Carlos Lopez a09598
#include "xf86Version.h"
Carlos Lopez a09598
Carlos Lopez a09598
#include <mach mach.h=""></mach>
Carlos Lopez a09598
#include <unistd.h></unistd.h>
Carlos Lopez a09598
#include <pthread.h></pthread.h>
Carlos Lopez a09598
Carlos Lopez a09598
#define DEFAULTS_FILE "/etc/X11/xserver/Xquartz.plist"
Carlos Lopez a09598
Carlos Lopez a09598
int X11EnableKeyEquivalents = TRUE;
Carlos Lopez a09598
Carlos Lopez a09598
X11Application *X11App;
Carlos Lopez a09598
Carlos Lopez a09598
#define ALL_KEY_MASKS (NSShiftKeyMask | NSControlKeyMask \
Carlos Lopez a09598
		       | NSAlternateKeyMask | NSCommandKeyMask)
Carlos Lopez a09598
Carlos Lopez a09598
@implementation X11Application
Carlos Lopez a09598
Carlos Lopez a09598
typedef struct message_struct message;
Carlos Lopez a09598
struct message_struct {
Carlos Lopez a09598
    mach_msg_header_t hdr;
Carlos Lopez a09598
    SEL selector;
Carlos Lopez a09598
    NSObject *arg;
Carlos Lopez a09598
};
Carlos Lopez a09598
Carlos Lopez a09598
static mach_port_t _port;
Carlos Lopez a09598
Carlos Lopez a09598
static void send_nsevent (NSEventType type, NSEvent *e);
Carlos Lopez a09598
Carlos Lopez a09598
/* avoid header conflict hell */
Carlos Lopez a09598
extern int RootlessKnowsWindowNumber (int number);
Carlos Lopez a09598
extern void DarwinEnqueueEvent (const xEvent *e);
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
init_ports (void)
Carlos Lopez a09598
{
Carlos Lopez a09598
    kern_return_t r;
Carlos Lopez a09598
    NSPort *p;
Carlos Lopez a09598
Carlos Lopez a09598
    if (_port != MACH_PORT_NULL)
Carlos Lopez a09598
	return;
Carlos Lopez a09598
Carlos Lopez a09598
    r = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &_port);
Carlos Lopez a09598
    if (r != KERN_SUCCESS)
Carlos Lopez a09598
	return;
Carlos Lopez a09598
Carlos Lopez a09598
    p = [NSMachPort portWithMachPort:_port];
Carlos Lopez a09598
    [p setDelegate:NSApp];
Carlos Lopez a09598
    [p scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
message_kit_thread (SEL selector, NSObject *arg)
Carlos Lopez a09598
{
Carlos Lopez a09598
    message msg;
Carlos Lopez a09598
    kern_return_t r;
Carlos Lopez a09598
Carlos Lopez a09598
    msg.hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
Carlos Lopez a09598
    msg.hdr.msgh_size = sizeof (msg);
Carlos Lopez a09598
    msg.hdr.msgh_remote_port = _port;
Carlos Lopez a09598
    msg.hdr.msgh_local_port = MACH_PORT_NULL;
Carlos Lopez a09598
    msg.hdr.msgh_reserved = 0;
Carlos Lopez a09598
    msg.hdr.msgh_id = 0;
Carlos Lopez a09598
Carlos Lopez a09598
    msg.selector = selector;
Carlos Lopez a09598
    msg.arg = [arg retain];
Carlos Lopez a09598
Carlos Lopez a09598
    r = mach_msg (&msg.hdr, MACH_SEND_MSG, msg.hdr.msgh_size,
Carlos Lopez a09598
		  0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
Carlos Lopez a09598
    if (r != KERN_SUCCESS)
Carlos Lopez a09598
	fprintf (stderr, "%s: mach_msg failed: %x\n", __FUNCTION__, r);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) handleMachMessage:(void *)_msg
Carlos Lopez a09598
{
Carlos Lopez a09598
    message *msg = _msg;
Carlos Lopez a09598
Carlos Lopez a09598
    [self performSelector:msg->selector withObject:msg->arg];
Carlos Lopez a09598
    [msg->arg release];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) set_controller:obj
Carlos Lopez a09598
{
Carlos Lopez a09598
    if (_controller == nil)
Carlos Lopez a09598
	_controller = [obj retain];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) dealloc
Carlos Lopez a09598
{
Carlos Lopez a09598
    if (_controller != nil)
Carlos Lopez a09598
	[_controller release];
Carlos Lopez a09598
Carlos Lopez a09598
    if (_port != MACH_PORT_NULL)
Carlos Lopez a09598
	mach_port_deallocate (mach_task_self (), _port);
Carlos Lopez a09598
Carlos Lopez a09598
    [super dealloc];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) orderFrontStandardAboutPanel: (id) sender
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSMutableDictionary *dict;
Carlos Lopez a09598
    NSDictionary *infoDict;
Carlos Lopez a09598
    NSString *tem;
Carlos Lopez a09598
Carlos Lopez a09598
    dict = [NSMutableDictionary dictionaryWithCapacity:2];
Carlos Lopez a09598
    infoDict = [[NSBundle mainBundle] infoDictionary];
Carlos Lopez a09598
Carlos Lopez a09598
    [dict setObject: NSLocalizedString (@"The X Window System", @"About panel")
Carlos Lopez a09598
     forKey:@"ApplicationName"];
Carlos Lopez a09598
Carlos Lopez a09598
    tem = [infoDict objectForKey:@"CFBundleShortVersionString"];
Carlos Lopez a09598
Carlos Lopez a09598
    [dict setObject:[NSString stringWithFormat:@"X11 %@ - XFree86 %d.%d.%d",
Carlos Lopez a09598
		     tem, XF86_VERSION_MAJOR, XF86_VERSION_MINOR,
Carlos Lopez a09598
		     XF86_VERSION_PATCH] forKey:@"ApplicationVersion"];
Carlos Lopez a09598
Carlos Lopez a09598
    [self orderFrontStandardAboutPanelWithOptions: dict];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) activateX:(BOOL)state
Carlos Lopez a09598
{
Carlos Lopez a09598
    /* Create a TSM document that supports full Unicode input, and
Carlos Lopez a09598
       have it activated while X is active (unless using the old
Carlos Lopez a09598
       keymapping files) */
Carlos Lopez a09598
    static TSMDocumentID x11_document;
Carlos Lopez a09598
Carlos Lopez a09598
    if (state)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	QuartzMessageMainThread (kXquartzActivate, 0);
Carlos Lopez a09598
Carlos Lopez a09598
	if (!_x_active)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    if (x11_document == 0 && darwinKeymapFile == NULL)
Carlos Lopez a09598
	    {
Carlos Lopez a09598
		OSType types[1];
Carlos Lopez a09598
		types[0] = kUnicodeDocument;
Carlos Lopez a09598
		NewTSMDocument (1, types, &x11_document, 0);
Carlos Lopez a09598
	    }
Carlos Lopez a09598
Carlos Lopez a09598
	    if (x11_document != 0)
Carlos Lopez a09598
		ActivateTSMDocument (x11_document);
Carlos Lopez a09598
	}
Carlos Lopez a09598
    }
Carlos Lopez a09598
    else
Carlos Lopez a09598
    {
Carlos Lopez a09598
	QuartzMessageMainThread (kXquartzDeactivate, 0);
Carlos Lopez a09598
Carlos Lopez a09598
	if (_x_active)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    if (x11_document != 0)
Carlos Lopez a09598
		DeactivateTSMDocument (x11_document);
Carlos Lopez a09598
	}
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    _x_active = state;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) became_key:(NSWindow *)win
Carlos Lopez a09598
{
Carlos Lopez a09598
    [self activateX:NO];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) sendEvent:(NSEvent *)e
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSEventType type;
Carlos Lopez a09598
    BOOL for_appkit, for_x;
Carlos Lopez a09598
Carlos Lopez a09598
    type = [e type];
Carlos Lopez a09598
Carlos Lopez a09598
    /* By default pass down the responder chain and to X. */
Carlos Lopez a09598
    for_appkit = YES;
Carlos Lopez a09598
    for_x = YES;
Carlos Lopez a09598
Carlos Lopez a09598
    switch (type)
Carlos Lopez a09598
    {
Carlos Lopez a09598
    case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown:
Carlos Lopez a09598
    case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp:
Carlos Lopez a09598
	if ([e window] != nil)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    /* Pointer event has a window. Probably something for the kit. */
Carlos Lopez a09598
Carlos Lopez a09598
	    for_x = NO;
Carlos Lopez a09598
Carlos Lopez a09598
	    if (_x_active)
Carlos Lopez a09598
		[self activateX:NO];
Carlos Lopez a09598
	}
Carlos Lopez a09598
	else if ([self modalWindow] == nil)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    /* Must be an X window. Tell appkit it doesn't have focus. */
Carlos Lopez a09598
Carlos Lopez a09598
	    for_appkit = NO;
Carlos Lopez a09598
Carlos Lopez a09598
	    if ([self isActive])
Carlos Lopez a09598
	    {
Carlos Lopez a09598
		[self deactivate];
Carlos Lopez a09598
Carlos Lopez a09598
		if (!_x_active && RootlessKnowsWindowNumber ([e windowNumber]))
Carlos Lopez a09598
		    [self activateX:YES];
Carlos Lopez a09598
	    }
Carlos Lopez a09598
	}
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSKeyDown: case NSKeyUp:
Carlos Lopez a09598
	if (_x_active)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    static int swallow_up;
Carlos Lopez a09598
Carlos Lopez a09598
	    /* No kit window is focused, so send it to X. */
Carlos Lopez a09598
Carlos Lopez a09598
	    for_appkit = NO;
Carlos Lopez a09598
Carlos Lopez a09598
	    if (type == NSKeyDown)
Carlos Lopez a09598
	    {
Carlos Lopez a09598
		/* Before that though, see if there are any global
Carlos Lopez a09598
		   shortcuts bound to it. */
Carlos Lopez a09598
Carlos Lopez a09598
		if (X11EnableKeyEquivalents
Carlos Lopez a09598
		    && [[self mainMenu] performKeyEquivalent:e])
Carlos Lopez a09598
		{
Carlos Lopez a09598
		    swallow_up = [e keyCode];
Carlos Lopez a09598
		    for_x = NO;
Carlos Lopez a09598
		}
Carlos Lopez a09598
		else if (!quartzEnableRootless
Carlos Lopez a09598
			 && ([e modifierFlags] & ALL_KEY_MASKS)
Carlos Lopez a09598
			    == (NSCommandKeyMask | NSAlternateKeyMask)
Carlos Lopez a09598
			 && ([e keyCode] == 0 /*a*/
Carlos Lopez a09598
			     || [e keyCode] == 53 /*Esc*/))
Carlos Lopez a09598
		{
Carlos Lopez a09598
		    swallow_up = 0;
Carlos Lopez a09598
		    for_x = NO;
Carlos Lopez a09598
		    QuartzMessageMainThread (kXquartzToggleFullscreen, 0);
Carlos Lopez a09598
		}
Carlos Lopez a09598
	    }
Carlos Lopez a09598
	    else
Carlos Lopez a09598
	    {
Carlos Lopez a09598
		/* If we saw a key equivalent on the down, don't pass
Carlos Lopez a09598
		   the up through to X. */
Carlos Lopez a09598
Carlos Lopez a09598
		if (swallow_up != 0 && [e keyCode] == swallow_up)
Carlos Lopez a09598
		{
Carlos Lopez a09598
		    swallow_up = 0;
Carlos Lopez a09598
		    for_x = NO;
Carlos Lopez a09598
		}
Carlos Lopez a09598
	    }
Carlos Lopez a09598
	}
Carlos Lopez a09598
	else
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    for_x = NO;
Carlos Lopez a09598
	}
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSFlagsChanged:
Carlos Lopez a09598
	/* For the l33t X users who remap modifier keys to normal keysyms. */
Carlos Lopez a09598
	if (!_x_active)
Carlos Lopez a09598
	    for_x = NO;
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSAppKitDefined:
Carlos Lopez a09598
	switch ([e subtype])
Carlos Lopez a09598
	{
Carlos Lopez a09598
	case NSApplicationActivatedEventType:
Carlos Lopez a09598
	    for_x = NO;
Carlos Lopez a09598
	    if ([self modalWindow] == nil)
Carlos Lopez a09598
	    {
Carlos Lopez a09598
		for_appkit = NO;
Carlos Lopez a09598
	    
Carlos Lopez a09598
		/* FIXME: hack to avoid having to pass the event to appkit,
Carlos Lopez a09598
		   which would cause it to raise one of its windows. */
Carlos Lopez a09598
		_appFlags._active = YES;
Carlos Lopez a09598
Carlos Lopez a09598
		[self activateX:YES];
Carlos Lopez a09598
	    }
Carlos Lopez a09598
	    break;
Carlos Lopez a09598
Carlos Lopez a09598
	case 18: /* ApplicationDidReactivate */
Carlos Lopez a09598
	    if (quartzHasRoot)
Carlos Lopez a09598
		for_appkit = NO;
Carlos Lopez a09598
	    break;
Carlos Lopez a09598
Carlos Lopez a09598
	case NSApplicationDeactivatedEventType:
Carlos Lopez a09598
	    for_x = NO;
Carlos Lopez a09598
	    [self activateX:NO];
Carlos Lopez a09598
	    break;
Carlos Lopez a09598
	}
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    default: break; /* for gcc */
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (for_appkit)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	[super sendEvent:e];
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (for_x)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	send_nsevent (type, e);
Carlos Lopez a09598
    }
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) set_window_menu:(NSArray *)list
Carlos Lopez a09598
{
Carlos Lopez a09598
    [_controller set_window_menu:list];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) set_window_menu_check:(NSNumber *)n
Carlos Lopez a09598
{
Carlos Lopez a09598
    [_controller set_window_menu_check:n];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) set_apps_menu:(NSArray *)list
Carlos Lopez a09598
{
Carlos Lopez a09598
    [_controller set_apps_menu:list];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) set_front_process:unused
Carlos Lopez a09598
{
Carlos Lopez a09598
    [NSApp activateIgnoringOtherApps:YES];
Carlos Lopez a09598
Carlos Lopez a09598
    if ([self modalWindow] == nil)
Carlos Lopez a09598
	[self activateX:YES];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) set_can_quit:(NSNumber *)state
Carlos Lopez a09598
{
Carlos Lopez a09598
    [_controller set_can_quit:[state boolValue]];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) server_ready:unused
Carlos Lopez a09598
{
Carlos Lopez a09598
    [_controller server_ready];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) show_hide_menubar:(NSNumber *)state
Carlos Lopez a09598
{
Carlos Lopez a09598
    if ([state boolValue])
Carlos Lopez a09598
	ShowMenuBar ();
Carlos Lopez a09598
    else
Carlos Lopez a09598
	HideMenuBar ();
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598

Carlos Lopez a09598
/* user preferences */
Carlos Lopez a09598
Carlos Lopez a09598
/* Note that these functions only work for arrays whose elements
Carlos Lopez a09598
   can be toll-free-bridged between NS and CF worlds. */
Carlos Lopez a09598
Carlos Lopez a09598
static const void *cfretain (CFAllocatorRef a, const void *b) {
Carlos Lopez a09598
    return CFRetain (b);
Carlos Lopez a09598
}
Carlos Lopez a09598
static void cfrelease (CFAllocatorRef a, const void *b) {
Carlos Lopez a09598
    CFRelease (b);
Carlos Lopez a09598
}
Carlos Lopez a09598
static CFMutableArrayRef
Carlos Lopez a09598
nsarray_to_cfarray (NSArray *in)
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFMutableArrayRef out;
Carlos Lopez a09598
    CFArrayCallBacks cb;
Carlos Lopez a09598
    NSObject *ns;
Carlos Lopez a09598
    const CFTypeRef *cf;
Carlos Lopez a09598
    int i, count;
Carlos Lopez a09598
Carlos Lopez a09598
    memset (&cb, 0, sizeof (cb));
Carlos Lopez a09598
    cb.version = 0;
Carlos Lopez a09598
    cb.retain = cfretain;
Carlos Lopez a09598
    cb.release = cfrelease;
Carlos Lopez a09598
Carlos Lopez a09598
    count = [in count];
Carlos Lopez a09598
    out = CFArrayCreateMutable (NULL, count, &cb);
Carlos Lopez a09598
Carlos Lopez a09598
    for (i = 0; i < count; i++)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	ns = [in objectAtIndex:i];
Carlos Lopez a09598
Carlos Lopez a09598
	if ([ns isKindOfClass:[NSArray class]])
Carlos Lopez a09598
	    cf = (CFTypeRef) nsarray_to_cfarray ((NSArray *) ns);
Carlos Lopez a09598
	else
Carlos Lopez a09598
	    cf = CFRetain ((CFTypeRef) ns);
Carlos Lopez a09598
Carlos Lopez a09598
	CFArrayAppendValue (out, cf);
Carlos Lopez a09598
	CFRelease (cf);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return out;
Carlos Lopez a09598
}
Carlos Lopez a09598
static NSMutableArray *
Carlos Lopez a09598
cfarray_to_nsarray (CFArrayRef in)
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSMutableArray *out;
Carlos Lopez a09598
    const CFTypeRef *cf;
Carlos Lopez a09598
    NSObject *ns;
Carlos Lopez a09598
    int i, count;
Carlos Lopez a09598
Carlos Lopez a09598
    count = CFArrayGetCount (in);
Carlos Lopez a09598
    out = [[NSMutableArray alloc] initWithCapacity:count];
Carlos Lopez a09598
Carlos Lopez a09598
    for (i = 0; i < count; i++)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	cf = CFArrayGetValueAtIndex (in, i);
Carlos Lopez a09598
Carlos Lopez a09598
	if (CFGetTypeID (cf) == CFArrayGetTypeID ())
Carlos Lopez a09598
	    ns = cfarray_to_nsarray ((CFArrayRef) cf);
Carlos Lopez a09598
	else
Carlos Lopez a09598
	    ns = [(id)cf retain];
Carlos Lopez a09598
Carlos Lopez a09598
	[out addObject:ns];
Carlos Lopez a09598
	[ns release];
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return out;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (CFPropertyListRef) prefs_get:(NSString *)key
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFPropertyListRef value;
Carlos Lopez a09598
Carlos Lopez a09598
    value = CFPreferencesCopyAppValue ((CFStringRef) key, CFSTR (APP_PREFS));
Carlos Lopez a09598
Carlos Lopez a09598
    if (value == NULL)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	static CFDictionaryRef defaults;
Carlos Lopez a09598
Carlos Lopez a09598
	if (defaults == NULL)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    CFStringRef error = NULL;
Carlos Lopez a09598
	    CFDataRef data;
Carlos Lopez a09598
	    CFURLRef url;
Carlos Lopez a09598
	    SInt32 error_code;
Carlos Lopez a09598
Carlos Lopez a09598
	    url = (CFURLCreateFromFileSystemRepresentation
Carlos Lopez a09598
		   (NULL, DEFAULTS_FILE, strlen (DEFAULTS_FILE), false));
Carlos Lopez a09598
	    if (CFURLCreateDataAndPropertiesFromResource (NULL, url, &data,
Carlos Lopez a09598
							  NULL, NULL,
Carlos Lopez a09598
							  &error_code))
Carlos Lopez a09598
	    {
Carlos Lopez a09598
		defaults = (CFPropertyListCreateFromXMLData
Carlos Lopez a09598
			    (NULL, data, kCFPropertyListImmutable, &error));
Carlos Lopez a09598
		if (error != NULL)
Carlos Lopez a09598
		    CFRelease (error);
Carlos Lopez a09598
		CFRelease (data);
Carlos Lopez a09598
	    }
Carlos Lopez a09598
	    CFRelease (url);
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	if (defaults != NULL)
Carlos Lopez a09598
	    value = CFDictionaryGetValue (defaults, key);
Carlos Lopez a09598
Carlos Lopez a09598
	if (value != NULL)
Carlos Lopez a09598
	    CFRetain (value);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return value;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (int) prefs_get_integer:(NSString *)key default:(int)def
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFPropertyListRef value;
Carlos Lopez a09598
    int ret;
Carlos Lopez a09598
Carlos Lopez a09598
    value = [self prefs_get:key];
Carlos Lopez a09598
Carlos Lopez a09598
    if (value != NULL && CFGetTypeID (value) == CFNumberGetTypeID ())
Carlos Lopez a09598
	CFNumberGetValue (value, kCFNumberIntType, &ret);
Carlos Lopez a09598
    else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
Carlos Lopez a09598
	ret = CFStringGetIntValue (value);
Carlos Lopez a09598
    else
Carlos Lopez a09598
	ret = def;
Carlos Lopez a09598
Carlos Lopez a09598
    if (value != NULL)
Carlos Lopez a09598
	CFRelease (value);
Carlos Lopez a09598
Carlos Lopez a09598
    return ret;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (const char *) prefs_get_string:(NSString *)key default:(const char *)def
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFPropertyListRef value;
Carlos Lopez a09598
    const char *ret = NULL;
Carlos Lopez a09598
Carlos Lopez a09598
    value = [self prefs_get:key];
Carlos Lopez a09598
Carlos Lopez a09598
    if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
Carlos Lopez a09598
    {
Carlos Lopez a09598
	NSString *s = (NSString *) value;
Carlos Lopez a09598
Carlos Lopez a09598
	ret = [s UTF8String];
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (value != NULL)
Carlos Lopez a09598
	CFRelease (value);
Carlos Lopez a09598
Carlos Lopez a09598
    return ret != NULL ? ret : def;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (float) prefs_get_float:(NSString *)key default:(float)def
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFPropertyListRef value;
Carlos Lopez a09598
    float ret = def;
Carlos Lopez a09598
Carlos Lopez a09598
    value = [self prefs_get:key];
Carlos Lopez a09598
Carlos Lopez a09598
    if (value != NULL
Carlos Lopez a09598
	&& CFGetTypeID (value) == CFNumberGetTypeID ()
Carlos Lopez a09598
	&& CFNumberIsFloatType (value))
Carlos Lopez a09598
    {
Carlos Lopez a09598
	CFNumberGetValue (value, kCFNumberFloatType, &ret);
Carlos Lopez a09598
    }
Carlos Lopez a09598
    else if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
Carlos Lopez a09598
    {
Carlos Lopez a09598
	ret = CFStringGetDoubleValue (value);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (value != NULL)
Carlos Lopez a09598
	CFRelease (value);
Carlos Lopez a09598
Carlos Lopez a09598
    return ret;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (int) prefs_get_boolean:(NSString *)key default:(int)def
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFPropertyListRef value;
Carlos Lopez a09598
    int ret = def;
Carlos Lopez a09598
Carlos Lopez a09598
    value = [self prefs_get:key];
Carlos Lopez a09598
Carlos Lopez a09598
    if (value != NULL)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	if (CFGetTypeID (value) == CFNumberGetTypeID ())
Carlos Lopez a09598
	    CFNumberGetValue (value, kCFNumberIntType, &ret);
Carlos Lopez a09598
	else if (CFGetTypeID (value) == CFBooleanGetTypeID ())
Carlos Lopez a09598
	    ret = CFBooleanGetValue (value);
Carlos Lopez a09598
	else if (CFGetTypeID (value) == CFStringGetTypeID ())
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    const char *tem = [(NSString *) value lossyCString];
Carlos Lopez a09598
	    if (strcasecmp (tem, "true") == 0 || strcasecmp (tem, "yes") == 0)
Carlos Lopez a09598
		ret = YES;
Carlos Lopez a09598
	    else
Carlos Lopez a09598
		ret = NO;
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	CFRelease (value);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return ret;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (NSArray *) prefs_get_array:(NSString *)key
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSArray *ret = nil;
Carlos Lopez a09598
    CFPropertyListRef value;
Carlos Lopez a09598
Carlos Lopez a09598
    value = [self prefs_get:key];
Carlos Lopez a09598
Carlos Lopez a09598
    if (value != NULL)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	if (CFGetTypeID (value) == CFArrayGetTypeID ())
Carlos Lopez a09598
	    ret = [cfarray_to_nsarray (value) autorelease];
Carlos Lopez a09598
Carlos Lopez a09598
	CFRelease (value);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return ret;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) prefs_set_integer:(NSString *)key value:(int)value
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFNumberRef x;
Carlos Lopez a09598
Carlos Lopez a09598
    x = CFNumberCreate (NULL, kCFNumberIntType, &value);
Carlos Lopez a09598
Carlos Lopez a09598
    CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, CFSTR (APP_PREFS),
Carlos Lopez a09598
			   kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
Carlos Lopez a09598
Carlos Lopez a09598
    CFRelease (x);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) prefs_set_float:(NSString *)key value:(float)value
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFNumberRef x;
Carlos Lopez a09598
Carlos Lopez a09598
    x = CFNumberCreate (NULL, kCFNumberFloatType, &value);
Carlos Lopez a09598
Carlos Lopez a09598
    CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) x, CFSTR (APP_PREFS),
Carlos Lopez a09598
			   kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
Carlos Lopez a09598
Carlos Lopez a09598
    CFRelease (x);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) prefs_set_boolean:(NSString *)key value:(int)value
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFPreferencesSetValue ((CFStringRef) key,
Carlos Lopez a09598
			   (CFTypeRef) value ? kCFBooleanTrue
Carlos Lopez a09598
			   : kCFBooleanFalse, CFSTR (APP_PREFS),
Carlos Lopez a09598
			   kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
Carlos Lopez a09598
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) prefs_set_array:(NSString *)key value:(NSArray *)value
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFArrayRef cfarray;
Carlos Lopez a09598
Carlos Lopez a09598
    cfarray = nsarray_to_cfarray (value);
Carlos Lopez a09598
    CFPreferencesSetValue ((CFStringRef) key,
Carlos Lopez a09598
			   (CFTypeRef) cfarray,
Carlos Lopez a09598
			   CFSTR (APP_PREFS),
Carlos Lopez a09598
			   kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
Carlos Lopez a09598
    CFRelease (cfarray);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) prefs_set_string:(NSString *)key value:(NSString *)value
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFPreferencesSetValue ((CFStringRef) key, (CFTypeRef) value,
Carlos Lopez a09598
			   CFSTR (APP_PREFS), kCFPreferencesCurrentUser,
Carlos Lopez a09598
			   kCFPreferencesAnyHost);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) prefs_synchronize
Carlos Lopez a09598
{
Carlos Lopez a09598
    CFPreferencesAppSynchronize (kCFPreferencesCurrentApplication);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (void) read_defaults
Carlos Lopez a09598
{
Carlos Lopez a09598
    extern int darwinFakeButtons;
Carlos Lopez a09598
    const char *tem;
Carlos Lopez a09598
Carlos Lopez a09598
    quartzUseSysBeep = [self prefs_get_boolean:@PREFS_SYSBEEP
Carlos Lopez a09598
		        default:quartzUseSysBeep];
Carlos Lopez a09598
    quartzEnableRootless = [self prefs_get_boolean:@PREFS_ROOTLESS
Carlos Lopez a09598
			    default:quartzEnableRootless];
Carlos Lopez a09598
    quartzFullscreenDisableHotkeys = ![self prefs_get_boolean:
Carlos Lopez a09598
				       @PREFS_FULLSCREEN_HOTKEYS default:
Carlos Lopez a09598
				       !quartzFullscreenDisableHotkeys];
Carlos Lopez a09598
    quartzXpluginOptions = [self prefs_get_integer:@PREFS_XP_OPTIONS
Carlos Lopez a09598
			    default:quartzXpluginOptions];
Carlos Lopez a09598
Carlos Lopez a09598
    darwinSwapAltMeta = [self prefs_get_boolean:@PREFS_SWAP_ALT_META
Carlos Lopez a09598
			 default:darwinSwapAltMeta];
Carlos Lopez a09598
    darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS
Carlos Lopez a09598
		         default:darwinFakeButtons];
Carlos Lopez a09598
    if (darwinFakeButtons)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	const char *fake2, *fake3;
Carlos Lopez a09598
Carlos Lopez a09598
	fake2 = [self prefs_get_string:@PREFS_FAKE_BUTTON2 default:NULL];
Carlos Lopez a09598
	fake3 = [self prefs_get_string:@PREFS_FAKE_BUTTON3 default:NULL];
Carlos Lopez a09598
Carlos Lopez a09598
	DarwinSetFakeButtons (fake2, fake3);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    X11EnableKeyEquivalents = [self prefs_get_boolean:@PREFS_KEYEQUIVS
Carlos Lopez a09598
			       default:X11EnableKeyEquivalents];
Carlos Lopez a09598
Carlos Lopez a09598
    darwinSyncKeymap = [self prefs_get_boolean:@PREFS_SYNC_KEYMAP
Carlos Lopez a09598
		        default:darwinSyncKeymap];
Carlos Lopez a09598
Carlos Lopez a09598
    tem = [self prefs_get_string:@PREFS_KEYMAP_FILE default:NULL];
Carlos Lopez a09598
    if (tem != NULL)
Carlos Lopez a09598
	darwinKeymapFile = strdup (tem);
Carlos Lopez a09598
Carlos Lopez a09598
    quartzDesiredDepth = [self prefs_get_integer:@PREFS_DEPTH
Carlos Lopez a09598
			  default:quartzDesiredDepth];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* This will end up at the end of the responder chain. */
Carlos Lopez a09598
- (void) copy:sender
Carlos Lopez a09598
{
Carlos Lopez a09598
    QuartzMessageMainThread (kXquartzPasteboardNotify, 1,
Carlos Lopez a09598
			     AppleWMCopyToPasteboard);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
- (BOOL) x_active
Carlos Lopez a09598
{
Carlos Lopez a09598
    return _x_active;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
@end
Carlos Lopez a09598
Carlos Lopez a09598
static NSArray *
Carlos Lopez a09598
array_with_strings_and_numbers (int nitems, const char **items,
Carlos Lopez a09598
				const char *numbers)
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSMutableArray *array, *subarray;
Carlos Lopez a09598
    NSString *string;
Carlos Lopez a09598
    NSString *number;
Carlos Lopez a09598
    int i;
Carlos Lopez a09598
Carlos Lopez a09598
    /* (Can't autorelease on the X server thread) */
Carlos Lopez a09598
Carlos Lopez a09598
    array = [[NSMutableArray alloc] initWithCapacity:nitems];
Carlos Lopez a09598
Carlos Lopez a09598
    for (i = 0; i < nitems; i++)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	subarray = [[NSMutableArray alloc] initWithCapacity:2];
Carlos Lopez a09598
Carlos Lopez a09598
	string = [[NSString alloc] initWithUTF8String:items[i]];
Carlos Lopez a09598
	[subarray addObject:string];
Carlos Lopez a09598
	[string release];
Carlos Lopez a09598
Carlos Lopez a09598
	if (numbers[i] != 0)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    number = [[NSString alloc] initWithFormat:@"%d", numbers[i]];
Carlos Lopez a09598
	    [subarray addObject:number];
Carlos Lopez a09598
	    [number release];
Carlos Lopez a09598
	}
Carlos Lopez a09598
	else
Carlos Lopez a09598
	    [subarray addObject:@""];
Carlos Lopez a09598
Carlos Lopez a09598
	[array addObject:subarray];
Carlos Lopez a09598
	[subarray release];
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return array;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
X11ApplicationSetWindowMenu (int nitems, const char **items,
Carlos Lopez a09598
			     const char *shortcuts)
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSArray *array;
Carlos Lopez a09598
Carlos Lopez a09598
    array = array_with_strings_and_numbers (nitems, items, shortcuts);
Carlos Lopez a09598
Carlos Lopez a09598
    /* Send the array of strings over to the appkit thread */
Carlos Lopez a09598
Carlos Lopez a09598
    message_kit_thread (@selector (set_window_menu:), array);
Carlos Lopez a09598
    [array release];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
X11ApplicationSetWindowMenuCheck (int idx)
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSNumber *n;
Carlos Lopez a09598
Carlos Lopez a09598
    n = [[NSNumber alloc] initWithInt:idx];
Carlos Lopez a09598
Carlos Lopez a09598
    message_kit_thread (@selector (set_window_menu_check:), n);
Carlos Lopez a09598
Carlos Lopez a09598
    [n release];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
X11ApplicationSetFrontProcess (void)
Carlos Lopez a09598
{
Carlos Lopez a09598
    message_kit_thread (@selector (set_front_process:), nil);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
X11ApplicationSetCanQuit (int state)
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSNumber *n;
Carlos Lopez a09598
Carlos Lopez a09598
    n = [[NSNumber alloc] initWithBool:state];
Carlos Lopez a09598
Carlos Lopez a09598
    message_kit_thread (@selector (set_can_quit:), n);
Carlos Lopez a09598
Carlos Lopez a09598
    [n release];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
X11ApplicationServerReady (void)
Carlos Lopez a09598
{
Carlos Lopez a09598
    message_kit_thread (@selector (server_ready:), nil);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
X11ApplicationShowHideMenubar (int state)
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSNumber *n;
Carlos Lopez a09598
Carlos Lopez a09598
    n = [[NSNumber alloc] initWithBool:state];
Carlos Lopez a09598
Carlos Lopez a09598
    message_kit_thread (@selector (show_hide_menubar:), n);
Carlos Lopez a09598
Carlos Lopez a09598
    [n release];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void *
Carlos Lopez a09598
create_thread (void *func, void *arg)
Carlos Lopez a09598
{
Carlos Lopez a09598
    pthread_attr_t attr;
Carlos Lopez a09598
    pthread_t tid;
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_attr_init (&attr);
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
Carlos Lopez a09598
    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_create (&tid, &attr, func, arg);
Carlos Lopez a09598
Carlos Lopez a09598
    pthread_attr_destroy (&attr);
Carlos Lopez a09598
Carlos Lopez a09598
    return (void *) tid;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
check_xinitrc (void)
Carlos Lopez a09598
{
Carlos Lopez a09598
    char *tem, buf[1024];
Carlos Lopez a09598
    NSString *msg;
Carlos Lopez a09598
Carlos Lopez a09598
    if ([X11App prefs_get_boolean:@PREFS_DONE_XINIT_CHECK default:NO])
Carlos Lopez a09598
	return;
Carlos Lopez a09598
Carlos Lopez a09598
    tem = getenv ("HOME");
Carlos Lopez a09598
    if (tem == NULL)
Carlos Lopez a09598
	goto done;
Carlos Lopez a09598
Carlos Lopez a09598
    snprintf (buf, sizeof (buf), "%s/.xinitrc", tem);
Carlos Lopez a09598
    if (access (buf, F_OK) != 0)
Carlos Lopez a09598
	goto done;
Carlos Lopez a09598
Carlos Lopez a09598
    /* FIXME: put localized strings into Resources/English.lproj */
Carlos Lopez a09598
Carlos Lopez a09598
    msg = NSLocalizedString (
Carlos Lopez a09598
@"You have an existing ~/.xinitrc file.\n\n\
Carlos Lopez a09598
Windows displayed by X11 applications may not have titlebars, or may look \
Carlos Lopez a09598
different to windows displayed by native applications.\n\n\
Carlos Lopez a09598
Would you like to move aside the existing file and use the standard X11 \
Carlos Lopez a09598
environment?", @"");
Carlos Lopez a09598
Carlos Lopez a09598
    if (NSRunAlertPanel (nil, msg, NSLocalizedString (@"Yes", @""),
Carlos Lopez a09598
			 NSLocalizedString (@"No", @""), nil)
Carlos Lopez a09598
	== NSAlertDefaultReturn)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	char buf2[1024];
Carlos Lopez a09598
	int i = -1;
Carlos Lopez a09598
Carlos Lopez a09598
	snprintf (buf2, sizeof (buf2), "%s.old", buf);
Carlos Lopez a09598
Carlos Lopez a09598
	for (i = 1; access (buf2, F_OK) == 0; i++)
Carlos Lopez a09598
	     snprintf (buf2, sizeof (buf2), "%s.old.%d", buf, i);
Carlos Lopez a09598
Carlos Lopez a09598
	rename (buf, buf2);
Carlos Lopez a09598
    }
Carlos Lopez a09598
    
Carlos Lopez a09598
done:
Carlos Lopez a09598
    [X11App prefs_set_boolean:@PREFS_DONE_XINIT_CHECK value:YES];
Carlos Lopez a09598
    [X11App prefs_synchronize];
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
X11ApplicationMain (int argc, const char *argv[],
Carlos Lopez a09598
		    void (*server_thread) (void *), void *server_arg)
Carlos Lopez a09598
{
Carlos Lopez a09598
    NSAutoreleasePool *pool;
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef DEBUG
Carlos Lopez a09598
    while (access ("/tmp/x11-block", F_OK) == 0)
Carlos Lopez a09598
	sleep (1);
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
    pool = [[NSAutoreleasePool alloc] init];
Carlos Lopez a09598
Carlos Lopez a09598
    X11App = (X11Application *) [X11Application sharedApplication];
Carlos Lopez a09598
Carlos Lopez a09598
    init_ports ();
Carlos Lopez a09598
Carlos Lopez a09598
    [NSApp read_defaults];
Carlos Lopez a09598
Carlos Lopez a09598
    [NSBundle loadNibNamed:@"main" owner:NSApp];
Carlos Lopez a09598
Carlos Lopez a09598
    [[NSNotificationCenter defaultCenter] addObserver:NSApp
Carlos Lopez a09598
     selector:@selector (became_key:)
Carlos Lopez a09598
     name:NSWindowDidBecomeKeyNotification object:nil];
Carlos Lopez a09598
Carlos Lopez a09598
    check_xinitrc ();
Carlos Lopez a09598
Carlos Lopez a09598
    if (!create_thread (server_thread, server_arg))
Carlos Lopez a09598
    {
Carlos Lopez a09598
	fprintf (stderr, "can't create secondary thread\n");
Carlos Lopez a09598
	exit (1);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    [NSApp run];
Carlos Lopez a09598
Carlos Lopez a09598
    /* not reached */
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598

Carlos Lopez a09598
/* event conversion */
Carlos Lopez a09598
Carlos Lopez a09598
static inline unsigned short
Carlos Lopez a09598
convert_flags (unsigned int nsflags)
Carlos Lopez a09598
{
Carlos Lopez a09598
    unsigned int xflags;
Carlos Lopez a09598
Carlos Lopez a09598
    if (nsflags == ~0)
Carlos Lopez a09598
	return 0xffff;
Carlos Lopez a09598
Carlos Lopez a09598
    xflags = 0;
Carlos Lopez a09598
Carlos Lopez a09598
    if (nsflags & NSAlphaShiftKeyMask)
Carlos Lopez a09598
	xflags |= LockMask;
Carlos Lopez a09598
    if (nsflags & NSShiftKeyMask)
Carlos Lopez a09598
	xflags |= ShiftMask;
Carlos Lopez a09598
    if (nsflags & NSControlKeyMask)
Carlos Lopez a09598
	xflags |= ControlMask;
Carlos Lopez a09598
    if (nsflags & NSAlternateKeyMask)
Carlos Lopez a09598
	xflags |= Mod1Mask;
Carlos Lopez a09598
    if (nsflags & NSCommandKeyMask)
Carlos Lopez a09598
	xflags |= Mod2Mask;
Carlos Lopez a09598
    /* FIXME: secondaryfn? */
Carlos Lopez a09598
Carlos Lopez a09598
    return xflags;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
send_nsevent (NSEventType type, NSEvent *e)
Carlos Lopez a09598
{
Carlos Lopez a09598
    static unsigned int button_state = 0;
Carlos Lopez a09598
Carlos Lopez a09598
    xEvent xe;
Carlos Lopez a09598
Carlos Lopez a09598
    memset (&xe, 0, sizeof (xe));
Carlos Lopez a09598
Carlos Lopez a09598
    switch (type)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	NSRect screen;
Carlos Lopez a09598
	NSPoint location;
Carlos Lopez a09598
	NSWindow *window;
Carlos Lopez a09598
	int pointer_x, pointer_y, count;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSLeftMouseDown:
Carlos Lopez a09598
	xe.u.u.type = ButtonPress;
Carlos Lopez a09598
	xe.u.u.detail = 1;
Carlos Lopez a09598
	goto do_press_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSRightMouseDown:
Carlos Lopez a09598
	xe.u.u.type = ButtonPress;
Carlos Lopez a09598
	xe.u.u.detail = 3;
Carlos Lopez a09598
	goto do_press_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSOtherMouseDown:
Carlos Lopez a09598
	xe.u.u.type = ButtonPress;
Carlos Lopez a09598
	xe.u.u.detail = 2; /* FIXME? */
Carlos Lopez a09598
	goto do_press_event;
Carlos Lopez a09598
Carlos Lopez a09598
    do_press_event:
Carlos Lopez a09598
	if (RootlessKnowsWindowNumber ([e windowNumber]) == NULL)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    /* X server doesn't grok this window, drop the event.
Carlos Lopez a09598
Carlos Lopez a09598
	       Note: theoretically this isn't necessary, but if I click
Carlos Lopez a09598
	       on the menubar, we get sent a LeftMouseDown when the
Carlos Lopez a09598
	       release happens, but no LeftMouseUp is ever seen! */
Carlos Lopez a09598
Carlos Lopez a09598
	    break;
Carlos Lopez a09598
	}
Carlos Lopez a09598
	goto do_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSLeftMouseUp:
Carlos Lopez a09598
	xe.u.u.type = ButtonRelease;
Carlos Lopez a09598
	xe.u.u.detail = 1;
Carlos Lopez a09598
	goto do_release_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSRightMouseUp:
Carlos Lopez a09598
	xe.u.u.type = ButtonRelease;
Carlos Lopez a09598
	xe.u.u.detail = 3;
Carlos Lopez a09598
	goto do_release_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSOtherMouseUp:
Carlos Lopez a09598
	xe.u.u.type = ButtonRelease;
Carlos Lopez a09598
	xe.u.u.detail = 2; /* FIXME? */
Carlos Lopez a09598
	goto do_release_event;
Carlos Lopez a09598
Carlos Lopez a09598
    do_release_event:
Carlos Lopez a09598
	if ((button_state & (1 << xe.u.u.detail)) == 0)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    /* X didn't see the button press for this release, so skip it */
Carlos Lopez a09598
	    break;
Carlos Lopez a09598
	}
Carlos Lopez a09598
	goto do_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSMouseMoved:
Carlos Lopez a09598
    case NSLeftMouseDragged:
Carlos Lopez a09598
    case NSRightMouseDragged:
Carlos Lopez a09598
    case NSOtherMouseDragged:
Carlos Lopez a09598
	/* convert location to global top-left coordinates */
Carlos Lopez a09598
Carlos Lopez a09598
	location = [e locationInWindow];
Carlos Lopez a09598
	window = [e window];
Carlos Lopez a09598
	screen = [[[NSScreen screens] objectAtIndex:0] frame];
Carlos Lopez a09598
Carlos Lopez a09598
	if (window != nil)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    NSRect frame = [window frame];
Carlos Lopez a09598
	    pointer_x = location.x + frame.origin.x;
Carlos Lopez a09598
	    pointer_y = (((screen.origin.y + screen.size.height)
Carlos Lopez a09598
			  - location.y) - frame.origin.y);
Carlos Lopez a09598
	}
Carlos Lopez a09598
	else
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    pointer_x = location.x;
Carlos Lopez a09598
	    pointer_y = (screen.origin.y + screen.size.height) - location.y;
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	xe.u.keyButtonPointer.rootX = pointer_x;
Carlos Lopez a09598
	xe.u.keyButtonPointer.rootY = pointer_y;
Carlos Lopez a09598
	xe.u.u.type = MotionNotify;
Carlos Lopez a09598
	goto do_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSKeyDown:
Carlos Lopez a09598
	xe.u.u.type = KeyPress;
Carlos Lopez a09598
	xe.u.u.detail = [e keyCode];
Carlos Lopez a09598
	goto do_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSKeyUp:
Carlos Lopez a09598
	xe.u.u.type = KeyRelease;
Carlos Lopez a09598
	xe.u.u.detail = [e keyCode];
Carlos Lopez a09598
	goto do_event;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSScrollWheel:
Carlos Lopez a09598
	xe.u.keyButtonPointer.state = convert_flags ([e modifierFlags]);
Carlos Lopez a09598
	count = [e deltaY];
Carlos Lopez a09598
	xe.u.u.detail = count > 0 ? 4 : 5;
Carlos Lopez a09598
	for (count = abs (count); count-- > 0;)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    xe.u.u.type = ButtonPress;
Carlos Lopez a09598
	    DarwinEnqueueEvent (&xe);
Carlos Lopez a09598
	    xe.u.u.type = ButtonRelease;
Carlos Lopez a09598
	    DarwinEnqueueEvent (&xe);
Carlos Lopez a09598
	}
Carlos Lopez a09598
	xe.u.u.type = 0;
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case NSFlagsChanged:
Carlos Lopez a09598
    do_event:
Carlos Lopez a09598
	xe.u.keyButtonPointer.state = convert_flags ([e modifierFlags]);
Carlos Lopez a09598
	DarwinEnqueueEvent (&xe);
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    default: break; /* for gcc */
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (xe.u.u.type == ButtonPress)
Carlos Lopez a09598
	button_state |= (1 << xe.u.u.detail);
Carlos Lopez a09598
    else if (xe.u.u.type == ButtonRelease)
Carlos Lopez a09598
	button_state &= ~(1 << xe.u.u.detail);
Carlos Lopez a09598
}