Blame synfig-osx/launcher/quartz.c

Carlos Lopez a09598
/**************************************************************
Carlos Lopez a09598
 *
Carlos Lopez a09598
 * Quartz-specific support for the Darwin X Server
Carlos Lopez a09598
 *
Carlos Lopez a09598
 **************************************************************/
Carlos Lopez a09598
/*
Carlos Lopez a09598
 * Copyright (c) 2001 Greg Parker and Torrey T. Lyons.
Carlos Lopez a09598
 * Copyright (c) 2002 Apple Computer, Inc.
Carlos Lopez a09598
 *                 All Rights Reserved.
Carlos Lopez a09598
 *
Carlos Lopez a09598
 * Permission is hereby granted, free of charge, to any person obtaining a
Carlos Lopez a09598
 * copy of this software and associated documentation files (the "Software"),
Carlos Lopez a09598
 * to deal in the Software without restriction, including without limitation
Carlos Lopez a09598
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
Carlos Lopez a09598
 * and/or sell copies of the Software, and to permit persons to whom the
Carlos Lopez a09598
 * Software is furnished to do so, subject to the following conditions:
Carlos Lopez a09598
 *
Carlos Lopez a09598
 * The above copyright notice and this permission notice shall be included in
Carlos Lopez a09598
 * 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, EXPRESS OR
Carlos Lopez a09598
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Carlos Lopez a09598
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Carlos Lopez a09598
 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
Carlos Lopez a09598
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
Carlos Lopez a09598
 * ARISING FROM, 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 copyright
Carlos Lopez a09598
 * holders shall not be used in advertising or otherwise to promote the sale,
Carlos Lopez a09598
 * use or other dealings in this Software without prior written authorization.
Carlos Lopez a09598
 */
Carlos Lopez a09598
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartz.c,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
Carlos Lopez a09598
Carlos Lopez a09598
#include "quartz.h"
Carlos Lopez a09598
#include "darwin.h"
Carlos Lopez a09598
#include "quartz-audio.h"
Carlos Lopez a09598
#include "quartz-cursor.h"
Carlos Lopez a09598
#include "rootless.h"
Carlos Lopez a09598
#include "rootless-window.h"
Carlos Lopez a09598
#include "pseudoramiX.h"
Carlos Lopez a09598
#include "globals.h"
Carlos Lopez a09598
#include "dri.h"
Carlos Lopez a09598
#define _APPLEWM_SERVER_
Carlos Lopez a09598
#include "applewmstr.h"
Carlos Lopez a09598
#include "X11Application.h"
Carlos Lopez a09598
Carlos Lopez a09598
#include "scrnintstr.h"
Carlos Lopez a09598
#include "colormapst.h"
Carlos Lopez a09598
Carlos Lopez a09598
#include <sys types.h=""></sys>
Carlos Lopez a09598
#include <sys stat.h=""></sys>
Carlos Lopez a09598
#include <fcntl.h></fcntl.h>
Carlos Lopez a09598
#include <unistd.h></unistd.h>
Carlos Lopez a09598
#include <sys wait.h=""></sys>
Carlos Lopez a09598
Carlos Lopez a09598
#include <availabilitymacros.h></availabilitymacros.h>
Carlos Lopez a09598
#include <coregraphics coregraphics.h=""></coregraphics>
Carlos Lopez a09598
Carlos Lopez a09598
/* Shared global variables for Quartz modes */
Carlos Lopez a09598
int quartzEventWriteFD = -1;
Carlos Lopez a09598
int quartzUseSysBeep = 1;
Carlos Lopez a09598
int quartzServerVisible = FALSE;
Carlos Lopez a09598
int quartzDesiredDepth = -1;
Carlos Lopez a09598
int quartzHasRoot = FALSE, quartzEnableRootless = TRUE;
Carlos Lopez a09598
int quartzFullscreenDisableHotkeys = TRUE;
Carlos Lopez a09598
int noPseudoramiXExtension = FALSE;
Carlos Lopez a09598
int quartzXpluginOptions = 0;
Carlos Lopez a09598
Carlos Lopez a09598
extern char *display;
Carlos Lopez a09598
Carlos Lopez a09598
static CGDirectDisplayID
Carlos Lopez a09598
display_at_index (int index)
Carlos Lopez a09598
{
Carlos Lopez a09598
    CGError err;
Carlos Lopez a09598
    CGDisplayCount cnt;
Carlos Lopez a09598
    CGDirectDisplayID dpy[index+1];
Carlos Lopez a09598
Carlos Lopez a09598
    err = CGGetActiveDisplayList (index + 1, dpy, &cnt);
Carlos Lopez a09598
    if (err == kCGErrorSuccess && (int) cnt == index + 1)
Carlos Lopez a09598
	return dpy[index];
Carlos Lopez a09598
    else
Carlos Lopez a09598
	return kCGNullDirectDisplay;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static CGRect
Carlos Lopez a09598
display_screen_bounds (CGDirectDisplayID id, Bool remove_menubar)
Carlos Lopez a09598
{
Carlos Lopez a09598
    CGRect frame;
Carlos Lopez a09598
Carlos Lopez a09598
    frame = CGDisplayBounds (id);
Carlos Lopez a09598
Carlos Lopez a09598
    if (remove_menubar && !quartzHasRoot
Carlos Lopez a09598
	&& frame.origin.x == 0 && frame.origin.y == 0)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	/* Remove Aqua menubar from display bounds. */
Carlos Lopez a09598
Carlos Lopez a09598
	frame.origin.y += 22;
Carlos Lopez a09598
	frame.size.height -= 22;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return frame;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
addPseudoramiXScreens (int *x, int *y, int *width, int *height)
Carlos Lopez a09598
{
Carlos Lopez a09598
    CGDisplayCount i, total = 16;	/* FIXME: hardcoded maximum */
Carlos Lopez a09598
    CGRect unionRect = CGRectNull, frame;
Carlos Lopez a09598
    CGDirectDisplayID screens[total];
Carlos Lopez a09598
	
Carlos Lopez a09598
    CGGetActiveDisplayList (total, screens, &total);
Carlos Lopez a09598
Carlos Lopez a09598
    /* Get the union of all screens */
Carlos Lopez a09598
    for (i = 0; i < total; i++)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	CGDirectDisplayID dpy = screens[i];
Carlos Lopez a09598
Carlos Lopez a09598
	/* we can't remove the menubar from the screen - doing so
Carlos Lopez a09598
	   would constrain the pointer to the screen, not allowing it
Carlos Lopez a09598
	   to reach the menubar.. */
Carlos Lopez a09598
Carlos Lopez a09598
	frame = display_screen_bounds (dpy, FALSE);
Carlos Lopez a09598
	unionRect = CGRectUnion (unionRect, frame);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    /* Use unionRect as the screen size for the X server. */
Carlos Lopez a09598
    *x = unionRect.origin.x;
Carlos Lopez a09598
    *y = unionRect.origin.y;
Carlos Lopez a09598
    *width = unionRect.size.width;
Carlos Lopez a09598
    *height = unionRect.size.height;
Carlos Lopez a09598
Carlos Lopez a09598
    /* Tell PseudoramiX about the real screens. */
Carlos Lopez a09598
    for (i = 0; i < total; i++)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	CGDirectDisplayID dpy = screens[i];
Carlos Lopez a09598
Carlos Lopez a09598
	frame = display_screen_bounds (dpy, TRUE);
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef DEBUG
Carlos Lopez a09598
	ErrorF("PseudoramiX screen %d added: %dx%d @ (%d,%d).\n", i,
Carlos Lopez a09598
	       (int)frame.size.width, (int)frame.size.height,
Carlos Lopez a09598
	       (int)frame.origin.x, (int)frame.origin.y);
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
	frame.origin.x -= unionRect.origin.x;
Carlos Lopez a09598
	frame.origin.y -= unionRect.origin.y;
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef DEBUG
Carlos Lopez a09598
	ErrorF("PseudoramiX screen %d placed at X11 coordinate (%d,%d).\n",
Carlos Lopez a09598
	       i, (int)frame.origin.x, (int)frame.origin.y);
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
	PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
Carlos Lopez a09598
			     frame.size.width, frame.size.height);
Carlos Lopez a09598
    }
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* Do mode dependent initialization of each screen for Quartz. */
Carlos Lopez a09598
Bool
Carlos Lopez a09598
QuartzAddScreen (int index, ScreenPtr pScreen)
Carlos Lopez a09598
{
Carlos Lopez a09598
    DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
Carlos Lopez a09598
Carlos Lopez a09598
    /* If no specific depth chosen, look for the depth of the main display.
Carlos Lopez a09598
       Else if 16bpp specified, use that. Else use 32bpp. */
Carlos Lopez a09598
Carlos Lopez a09598
    dfb->componentCount = 3;
Carlos Lopez a09598
    dfb->bitsPerComponent = 8;
Carlos Lopez a09598
    dfb->bitsPerPixel = 32;
Carlos Lopez a09598
Carlos Lopez a09598
    if (quartzDesiredDepth == -1)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	dfb->bitsPerComponent = CGDisplayBitsPerSample (kCGDirectMainDisplay);
Carlos Lopez a09598
	dfb->bitsPerPixel = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
Carlos Lopez a09598
    }
Carlos Lopez a09598
    else if (quartzDesiredDepth == 15)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	dfb->bitsPerComponent = 5;
Carlos Lopez a09598
	dfb->bitsPerPixel = 16;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    else if (quartzDesiredDepth == 8)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	dfb->bitsPerComponent = 8;
Carlos Lopez a09598
	dfb->bitsPerPixel = 8;
Carlos Lopez a09598
	dfb->componentCount = 1;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (noPseudoramiXExtension)
Carlos Lopez a09598
    {
Carlos Lopez a09598
        CGDirectDisplayID dpy;
Carlos Lopez a09598
        CGRect frame;
Carlos Lopez a09598
Carlos Lopez a09598
	dpy = display_at_index (index);
Carlos Lopez a09598
Carlos Lopez a09598
	frame = display_screen_bounds (dpy, TRUE);
Carlos Lopez a09598
Carlos Lopez a09598
        dfb->x = frame.origin.x;
Carlos Lopez a09598
        dfb->y = frame.origin.y;
Carlos Lopez a09598
        dfb->width =  frame.size.width;
Carlos Lopez a09598
        dfb->height = frame.size.height;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    else
Carlos Lopez a09598
    {
Carlos Lopez a09598
	addPseudoramiXScreens (&dfb->x, &dfb->y, &dfb->width, &dfb->height);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    dfb->colorBitsPerPixel = dfb->bitsPerComponent * dfb->componentCount;
Carlos Lopez a09598
Carlos Lopez a09598
    /* Passing zero width (pitch) makes miCreateScreenResources set the
Carlos Lopez a09598
       screen pixmap to the framebuffer pointer, i.e. null. We'll take
Carlos Lopez a09598
       it from there.. */
Carlos Lopez a09598
    dfb->pitch = 0;
Carlos Lopez a09598
    dfb->framebuffer = NULL;
Carlos Lopez a09598
Carlos Lopez a09598
    DRIScreenInit (pScreen);
Carlos Lopez a09598
Carlos Lopez a09598
    return TRUE;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* Finalize mode specific setup of each screen. */
Carlos Lopez a09598
Bool
Carlos Lopez a09598
QuartzSetupScreen (int index, ScreenPtr pScreen)
Carlos Lopez a09598
{
Carlos Lopez a09598
    // do full screen or rootless specific setup
Carlos Lopez a09598
    if (! RootlessSetupScreen(index, pScreen))
Carlos Lopez a09598
	return FALSE;
Carlos Lopez a09598
Carlos Lopez a09598
    // setup cursor support
Carlos Lopez a09598
    if (! QuartzInitCursor(pScreen))
Carlos Lopez a09598
        return FALSE;
Carlos Lopez a09598
Carlos Lopez a09598
    DRIFinishScreenInit (pScreen);
Carlos Lopez a09598
Carlos Lopez a09598
    return TRUE;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Carlos Lopez a09598
/* Quartz display initialization. */
Carlos Lopez a09598
void
Carlos Lopez a09598
QuartzInitOutput (int argc, char **argv)
Carlos Lopez a09598
{
Carlos Lopez a09598
    static int orig_noPanoramiXExtension;
Carlos Lopez a09598
    int total;
Carlos Lopez a09598
Carlos Lopez a09598
    if (serverGeneration == 1) {
Carlos Lopez a09598
	orig_noPanoramiXExtension = noPanoramiXExtension;
Carlos Lopez a09598
        QuartzAudioInit();
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    /* +xinerama option sets noPanoramiXExtension variable */
Carlos Lopez a09598
    noPseudoramiXExtension = orig_noPanoramiXExtension;
Carlos Lopez a09598
Carlos Lopez a09598
    total = 16;				/* FIXME: hardcoded maximum */
Carlos Lopez a09598
    if (total > 0)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	CGDirectDisplayID screens[total];
Carlos Lopez a09598
	CGGetActiveDisplayList (total, screens, &total);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (noPseudoramiXExtension)
Carlos Lopez a09598
	darwinScreensFound = total;
Carlos Lopez a09598
    else
Carlos Lopez a09598
        darwinScreensFound =  1; // only PseudoramiX knows about the rest
Carlos Lopez a09598
Carlos Lopez a09598
    if (!quartzEnableRootless)
Carlos Lopez a09598
	RootlessHideAllWindows ();
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* This function from randr.c */
Carlos Lopez a09598
extern char	*ConnectionInfo;
Carlos Lopez a09598
static int padlength[4] = {0, 3, 2, 1};
Carlos Lopez a09598
static void
Carlos Lopez a09598
RREditConnectionInfo (ScreenPtr pScreen)
Carlos Lopez a09598
{
Carlos Lopez a09598
    xConnSetup	    *connSetup;
Carlos Lopez a09598
    char	    *vendor;
Carlos Lopez a09598
    xPixmapFormat   *formats;
Carlos Lopez a09598
    xWindowRoot	    *root;
Carlos Lopez a09598
    xDepth	    *depth;
Carlos Lopez a09598
    xVisualType	    *visual;
Carlos Lopez a09598
    int		    screen = 0;
Carlos Lopez a09598
    int		    d;
Carlos Lopez a09598
Carlos Lopez a09598
    connSetup = (xConnSetup *) ConnectionInfo;
Carlos Lopez a09598
    vendor = (char *) connSetup + sizeof (xConnSetup);
Carlos Lopez a09598
    formats = (xPixmapFormat *) ((char *) vendor +
Carlos Lopez a09598
				 connSetup->nbytesVendor +
Carlos Lopez a09598
				 padlength[connSetup->nbytesVendor & 3]);
Carlos Lopez a09598
    root = (xWindowRoot *) ((char *) formats +
Carlos Lopez a09598
			    sizeof (xPixmapFormat) * screenInfo.numPixmapFormats);
Carlos Lopez a09598
    while (screen != pScreen->myNum)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	depth = (xDepth *) ((char *) root + 
Carlos Lopez a09598
			    sizeof (xWindowRoot));
Carlos Lopez a09598
	for (d = 0; d < root->nDepths; d++)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    visual = (xVisualType *) ((char *) depth +
Carlos Lopez a09598
				      sizeof (xDepth));
Carlos Lopez a09598
	    depth = (xDepth *) ((char *) visual +
Carlos Lopez a09598
				depth->nVisuals * sizeof (xVisualType));
Carlos Lopez a09598
	}
Carlos Lopez a09598
	root = (xWindowRoot *) ((char *) depth);
Carlos Lopez a09598
	screen++;
Carlos Lopez a09598
    }
Carlos Lopez a09598
    root->pixWidth = pScreen->width;
Carlos Lopez a09598
    root->pixHeight = pScreen->height;
Carlos Lopez a09598
    root->mmWidth = pScreen->mmWidth;
Carlos Lopez a09598
    root->mmHeight = pScreen->mmHeight;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
QuartzUpdateScreens (void)
Carlos Lopez a09598
{
Carlos Lopez a09598
    ScreenPtr pScreen;
Carlos Lopez a09598
    WindowPtr pRoot;
Carlos Lopez a09598
    int x, y, width, height, sx, sy;
Carlos Lopez a09598
    xEvent e;
Carlos Lopez a09598
Carlos Lopez a09598
    if (noPseudoramiXExtension || screenInfo.numScreens != 1)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	/* FIXME: if not using Xinerama, we have multiple screens, and
Carlos Lopez a09598
	   to do this properly may need to add or remove screens. Which
Carlos Lopez a09598
	   isn't possible. So don't do anything. Another reason why
Carlos Lopez a09598
	   we default to running with Xinerama. */
Carlos Lopez a09598
Carlos Lopez a09598
	return;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    pScreen = screenInfo.screens[0];
Carlos Lopez a09598
Carlos Lopez a09598
    PseudoramiXResetScreens ();
Carlos Lopez a09598
    addPseudoramiXScreens (&x, &y, &width, &height);
Carlos Lopez a09598
Carlos Lopez a09598
    dixScreenOrigins[pScreen->myNum].x = x;
Carlos Lopez a09598
    dixScreenOrigins[pScreen->myNum].y = y;
Carlos Lopez a09598
    pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width);
Carlos Lopez a09598
    pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height);
Carlos Lopez a09598
    pScreen->width = width;
Carlos Lopez a09598
    pScreen->height = height;
Carlos Lopez a09598
Carlos Lopez a09598
    /* FIXME: should probably do something with RandR here. */
Carlos Lopez a09598
Carlos Lopez a09598
    DarwinAdjustScreenOrigins (&screenInfo);
Carlos Lopez a09598
    RootlessRepositionWindows (screenInfo.screens[0]);
Carlos Lopez a09598
    RootlessUpdateScreenPixmap (screenInfo.screens[0]);
Carlos Lopez a09598
Carlos Lopez a09598
    sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
Carlos Lopez a09598
    sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
Carlos Lopez a09598
Carlos Lopez a09598
    /* Adjust the root window. */
Carlos Lopez a09598
Carlos Lopez a09598
    pRoot = WindowTable[pScreen->myNum];
Carlos Lopez a09598
    pScreen->ResizeWindow (pRoot, x - sx, y - sy, width, height, NULL);
Carlos Lopez a09598
    pScreen->PaintWindowBackground (pRoot, &pRoot->borderClip,  PW_BACKGROUND);
Carlos Lopez a09598
    QuartzIgnoreNextWarpCursor ();
Carlos Lopez a09598
    DefineInitialRootWindow (pRoot);
Carlos Lopez a09598
Carlos Lopez a09598
    /* Send an event for the root reconfigure */
Carlos Lopez a09598
Carlos Lopez a09598
    e.u.u.type = ConfigureNotify;
Carlos Lopez a09598
    e.u.configureNotify.window = pRoot->drawable.id;
Carlos Lopez a09598
    e.u.configureNotify.aboveSibling = None;
Carlos Lopez a09598
    e.u.configureNotify.x = x - sx;
Carlos Lopez a09598
    e.u.configureNotify.y = y - sy;
Carlos Lopez a09598
    e.u.configureNotify.width = width;
Carlos Lopez a09598
    e.u.configureNotify.height = height;
Carlos Lopez a09598
    e.u.configureNotify.borderWidth = wBorderWidth (pRoot);
Carlos Lopez a09598
    e.u.configureNotify.override = pRoot->overrideRedirect;
Carlos Lopez a09598
    DeliverEvents (pRoot, &e, 1, NullWindow);
Carlos Lopez a09598
Carlos Lopez a09598
    /* FIXME: what does this do? */
Carlos Lopez a09598
    RREditConnectionInfo (pScreen);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
do_exec (void (*callback) (void *data), void *data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    /* Do the fork-twice trick to avoid needing to reap zombies */
Carlos Lopez a09598
Carlos Lopez a09598
    int child1, child2 = 0;
Carlos Lopez a09598
    int status;
Carlos Lopez a09598
Carlos Lopez a09598
    /* we should really try to report errors here.. */
Carlos Lopez a09598
Carlos Lopez a09598
    child1 = fork ();
Carlos Lopez a09598
Carlos Lopez a09598
    switch (child1)
Carlos Lopez a09598
    {
Carlos Lopez a09598
    case -1:				/* error */
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case 0:				/* child1 */
Carlos Lopez a09598
	child2 = fork ();
Carlos Lopez a09598
Carlos Lopez a09598
	switch (child2)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	    int max_files, i;
Carlos Lopez a09598
	    char buf[1024], *tem;
Carlos Lopez a09598
Carlos Lopez a09598
	case -1:			/* error */
Carlos Lopez a09598
	    _exit (1);
Carlos Lopez a09598
Carlos Lopez a09598
	case 0:				/* child2 */
Carlos Lopez a09598
	    /* close all open files except for standard streams */
Carlos Lopez a09598
	    max_files = sysconf (_SC_OPEN_MAX);
Carlos Lopez a09598
	    for (i = 3; i < max_files; i++)
Carlos Lopez a09598
		close (i);
Carlos Lopez a09598
Carlos Lopez a09598
	    /* ensure stdin is on /dev/null */
Carlos Lopez a09598
	    close (0);
Carlos Lopez a09598
	    open ("/dev/null", O_RDONLY);
Carlos Lopez a09598
Carlos Lopez a09598
	    /* cd $HOME */
Carlos Lopez a09598
	    tem = getenv ("HOME");
Carlos Lopez a09598
	    if (tem != NULL)
Carlos Lopez a09598
		chdir (tem);
Carlos Lopez a09598
Carlos Lopez a09598
	    /* Setup environment */
Carlos Lopez a09598
	    snprintf (buf, sizeof (buf), ":%s", display);
Carlos Lopez a09598
	    setenv ("DISPLAY", buf, TRUE);
Carlos Lopez a09598
	    tem = getenv ("PATH");
Carlos Lopez a09598
	    if (tem != NULL && tem[0] != NULL)
Carlos Lopez a09598
		snprintf (buf, sizeof (buf), "%s:/usr/X11R6/bin", tem);
Carlos Lopez a09598
	    else
Carlos Lopez a09598
		snprintf (buf, sizeof (buf), "/bin:/usr/bin:/usr/X11R6/bin");
Carlos Lopez a09598
	    setenv ("PATH", buf, TRUE);
Carlos Lopez a09598
Carlos Lopez a09598
	    (*callback) (data);
Carlos Lopez a09598
Carlos Lopez a09598
	    _exit (2);
Carlos Lopez a09598
Carlos Lopez a09598
	default:			/* parent (child1) */
Carlos Lopez a09598
	    _exit (0);
Carlos Lopez a09598
	}
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    default:				/* parent */
Carlos Lopez a09598
	waitpid (child1, &status, 0);
Carlos Lopez a09598
    }
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
run_client_callback (void *data)
Carlos Lopez a09598
{
Carlos Lopez a09598
    char **argv = data;
Carlos Lopez a09598
    execvp (argv[0], argv);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* Note that this function is called from both X server and appkit threads */
Carlos Lopez a09598
void
Carlos Lopez a09598
QuartzRunClient (const char *command)
Carlos Lopez a09598
{
Carlos Lopez a09598
    const char *shell;
Carlos Lopez a09598
    const char *argv[5];
Carlos Lopez a09598
Carlos Lopez a09598
    shell = getenv ("SHELL");
Carlos Lopez a09598
    if (shell == NULL)
Carlos Lopez a09598
	shell = "/bin/bash";
Carlos Lopez a09598
Carlos Lopez a09598
    /* At least [ba]sh, [t]csh and zsh all work with this syntax. We
Carlos Lopez a09598
       need to use an interactive shell to force it to load the user's
Carlos Lopez a09598
       environment. Otherwise things like fink don't work at all well.. */
Carlos Lopez a09598
Carlos Lopez a09598
    argv[0] = shell;
Carlos Lopez a09598
    argv[1] = "-i";
Carlos Lopez a09598
    argv[2] = "-c";
Carlos Lopez a09598
    argv[3] = command;
Carlos Lopez a09598
    argv[4] = NULL;
Carlos Lopez a09598
Carlos Lopez a09598
    do_exec (run_client_callback, argv);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
QuartzSetFullscreen (Bool state)
Carlos Lopez a09598
{
Carlos Lopez a09598
    if (quartzHasRoot == state)
Carlos Lopez a09598
	return;
Carlos Lopez a09598
Carlos Lopez a09598
    quartzHasRoot = state;
Carlos Lopez a09598
Carlos Lopez a09598
    xp_disable_update ();
Carlos Lopez a09598
Carlos Lopez a09598
    if (!quartzHasRoot && !quartzEnableRootless)
Carlos Lopez a09598
	RootlessHideAllWindows ();
Carlos Lopez a09598
Carlos Lopez a09598
    RootlessUpdateRooted (quartzHasRoot);
Carlos Lopez a09598
Carlos Lopez a09598
    if (quartzHasRoot && !quartzEnableRootless)
Carlos Lopez a09598
	RootlessShowAllWindows ();
Carlos Lopez a09598
Carlos Lopez a09598
    /* Only update screen info when something is visible. Avoids the wm
Carlos Lopez a09598
       moving the windows out from under the menubar when it shouldn't */
Carlos Lopez a09598
Carlos Lopez a09598
    if (quartzHasRoot || quartzEnableRootless)
Carlos Lopez a09598
	QuartzUpdateScreens ();
Carlos Lopez a09598
Carlos Lopez a09598
    /* Somehow the menubar manages to interfere with our event stream
Carlos Lopez a09598
       in fullscreen mode, even though it's not visible. */
Carlos Lopez a09598
Carlos Lopez a09598
    X11ApplicationShowHideMenubar (!quartzHasRoot);
Carlos Lopez a09598
Carlos Lopez a09598
    xp_reenable_update ();
Carlos Lopez a09598
Carlos Lopez a09598
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
Carlos Lopez a09598
    if (quartzFullscreenDisableHotkeys)
Carlos Lopez a09598
	xp_disable_hot_keys (quartzHasRoot);
Carlos Lopez a09598
#endif
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
static void
Carlos Lopez a09598
QuartzSetRootless (Bool state)
Carlos Lopez a09598
{
Carlos Lopez a09598
    if (quartzEnableRootless == state)
Carlos Lopez a09598
	return;
Carlos Lopez a09598
Carlos Lopez a09598
    quartzEnableRootless = state;
Carlos Lopez a09598
Carlos Lopez a09598
    if (!quartzEnableRootless && !quartzHasRoot)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	xp_disable_update ();
Carlos Lopez a09598
	RootlessHideAllWindows ();
Carlos Lopez a09598
	xp_reenable_update ();
Carlos Lopez a09598
    }
Carlos Lopez a09598
    else if (quartzEnableRootless && !quartzHasRoot)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	xp_disable_update ();
Carlos Lopez a09598
	RootlessShowAllWindows ();
Carlos Lopez a09598
	QuartzUpdateScreens ();
Carlos Lopez a09598
	xp_reenable_update ();
Carlos Lopez a09598
    }
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* Show the X server on screen. Does nothing if already shown.  Restore the
Carlos Lopez a09598
   X clip regions the X server cursor state. */
Carlos Lopez a09598
static void
Carlos Lopez a09598
QuartzShow (void)
Carlos Lopez a09598
{
Carlos Lopez a09598
    int i;
Carlos Lopez a09598
Carlos Lopez a09598
    if (quartzServerVisible)
Carlos Lopez a09598
	return;
Carlos Lopez a09598
Carlos Lopez a09598
    quartzServerVisible = TRUE;
Carlos Lopez a09598
Carlos Lopez a09598
    for (i = 0; i < screenInfo.numScreens; i++)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	if (screenInfo.screens[i])
Carlos Lopez a09598
	    QuartzResumeXCursor(screenInfo.screens[i]);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    /* FIXME: not sure about this, it may need to have a preference like
Carlos Lopez a09598
       in XDarwin..? */
Carlos Lopez a09598
Carlos Lopez a09598
    if (!quartzEnableRootless)
Carlos Lopez a09598
	QuartzSetFullscreen (TRUE);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* Remove the X server display from the screen. Does nothing if already
Carlos Lopez a09598
   hidden. Set X clip regions to prevent drawing, and restore the Aqua
Carlos Lopez a09598
   cursor. */
Carlos Lopez a09598
static void
Carlos Lopez a09598
QuartzHide (void)
Carlos Lopez a09598
{
Carlos Lopez a09598
    int i;
Carlos Lopez a09598
Carlos Lopez a09598
    if (!quartzServerVisible)
Carlos Lopez a09598
	return;
Carlos Lopez a09598
Carlos Lopez a09598
    for (i = 0; i < screenInfo.numScreens; i++)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	if (screenInfo.screens[i])
Carlos Lopez a09598
	    QuartzSuspendXCursor(screenInfo.screens[i]);
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    QuartzSetFullscreen (FALSE);
Carlos Lopez a09598
Carlos Lopez a09598
    quartzServerVisible = FALSE;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
/* Cleanup before X server shutdown. Release the screen and restore the
Carlos Lopez a09598
   Aqua cursor. */
Carlos Lopez a09598
void
Carlos Lopez a09598
QuartzGiveUp (void)
Carlos Lopez a09598
{
Carlos Lopez a09598
    int i;
Carlos Lopez a09598
Carlos Lopez a09598
    for (i = 0; i < screenInfo.numScreens; i++) {
Carlos Lopez a09598
        if (screenInfo.screens[i]) {
Carlos Lopez a09598
            QuartzSuspendXCursor(screenInfo.screens[i]);
Carlos Lopez a09598
        }
Carlos Lopez a09598
    }
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
int
Carlos Lopez a09598
QuartzProcessArgument( int argc, char *argv[], int i )
Carlos Lopez a09598
{
Carlos Lopez a09598
    /* This arg is passed when launched from the Aqua GUI. */
Carlos Lopez a09598
    if (strncmp (argv[i], "-psn_", 5) == 0)
Carlos Lopez a09598
    {
Carlos Lopez a09598
        return 1;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    if (strcmp (argv[i], "-depth") == 0)
Carlos Lopez a09598
    {
Carlos Lopez a09598
	int arg;
Carlos Lopez a09598
Carlos Lopez a09598
	if (i == argc - 1)
Carlos Lopez a09598
	    FatalError ("-depth requires an argument\n");
Carlos Lopez a09598
Carlos Lopez a09598
	arg = atoi (argv[i + 1]);
Carlos Lopez a09598
	if (arg == 8 || arg == 15 || arg == 24)
Carlos Lopez a09598
	    quartzDesiredDepth = arg;
Carlos Lopez a09598
	else
Carlos Lopez a09598
	    FatalError ("Only 8, 15 and 24 bit color depths are supported.\n");
Carlos Lopez a09598
Carlos Lopez a09598
	return 2;
Carlos Lopez a09598
    }
Carlos Lopez a09598
Carlos Lopez a09598
    return 0;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
QuartzClientMessage (const xEvent *xe)
Carlos Lopez a09598
{
Carlos Lopez a09598
    switch (xe->u.clientMessage.u.l.type)
Carlos Lopez a09598
    {
Carlos Lopez a09598
    case kXquartzControllerNotify:
Carlos Lopez a09598
	AppleWMSendEvent (AppleWMControllerNotify,
Carlos Lopez a09598
			  AppleWMControllerNotifyMask,
Carlos Lopez a09598
			  xe->u.clientMessage.u.l.longs0,
Carlos Lopez a09598
			  xe->u.clientMessage.u.l.longs1);
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case kXquartzPasteboardNotify:
Carlos Lopez a09598
	AppleWMSendEvent (AppleWMPasteboardNotify,
Carlos Lopez a09598
			  AppleWMPasteboardNotifyMask,
Carlos Lopez a09598
			  xe->u.clientMessage.u.l.longs0,
Carlos Lopez a09598
			  xe->u.clientMessage.u.l.longs1);
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case kXquartzActivate:
Carlos Lopez a09598
	QuartzShow ();
Carlos Lopez a09598
	AppleWMSendEvent (AppleWMActivationNotify,
Carlos Lopez a09598
			  AppleWMActivationNotifyMask,
Carlos Lopez a09598
			  AppleWMIsActive, 0);
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case kXquartzDeactivate:
Carlos Lopez a09598
	AppleWMSendEvent (AppleWMActivationNotify,
Carlos Lopez a09598
			  AppleWMActivationNotifyMask,
Carlos Lopez a09598
			  AppleWMIsInactive, 0);
Carlos Lopez a09598
	QuartzHide ();
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case kXquartzDisplayChanged:
Carlos Lopez a09598
	QuartzUpdateScreens ();
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case kXquartzWindowState:
Carlos Lopez a09598
	RootlessNativeWindowStateChanged (xe->u.clientMessage.u.l.longs0,
Carlos Lopez a09598
					  xe->u.clientMessage.u.l.longs1);
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case kXquartzWindowMoved:
Carlos Lopez a09598
	RootlessNativeWindowMoved (xe->u.clientMessage.u.l.longs0);
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case kXquartzToggleFullscreen:
Carlos Lopez a09598
	if (quartzEnableRootless)
Carlos Lopez a09598
	    QuartzSetFullscreen (!quartzHasRoot);
Carlos Lopez a09598
	else if (quartzHasRoot)
Carlos Lopez a09598
	    QuartzHide ();
Carlos Lopez a09598
	else
Carlos Lopez a09598
	    QuartzShow ();
Carlos Lopez a09598
	break;
Carlos Lopez a09598
Carlos Lopez a09598
    case kXquartzSetRootless:
Carlos Lopez a09598
	QuartzSetRootless (xe->u.clientMessage.u.l.longs0);
Carlos Lopez a09598
	if (!quartzEnableRootless && !quartzHasRoot)
Carlos Lopez a09598
	    QuartzHide ();
Carlos Lopez a09598
    }
Carlos Lopez a09598
}