aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xquartz
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-06-11 14:16:16 +0000
committermarha <marha@users.sourceforge.net>2010-06-11 14:16:16 +0000
commitd1e4f4b8546c7955c66dd023bfd6ef437db9d21d (patch)
tree529985e77bfc95aa95fe5b540e8f42b0ef041206 /xorg-server/hw/xquartz
parent13919cf85a6ca41d97238de13344aba59e0f7680 (diff)
parent4c61bf84b11e26e6f22648668c95ea760a379163 (diff)
downloadvcxsrv-d1e4f4b8546c7955c66dd023bfd6ef437db9d21d.tar.gz
vcxsrv-d1e4f4b8546c7955c66dd023bfd6ef437db9d21d.tar.bz2
vcxsrv-d1e4f4b8546c7955c66dd023bfd6ef437db9d21d.zip
svn merge ^/branches/released .
Diffstat (limited to 'xorg-server/hw/xquartz')
-rw-r--r--xorg-server/hw/xquartz/applewm.c6
-rw-r--r--xorg-server/hw/xquartz/darwin.c52
-rw-r--r--xorg-server/hw/xquartz/darwin.h3
-rw-r--r--xorg-server/hw/xquartz/darwinEvents.c1152
-rw-r--r--xorg-server/hw/xquartz/darwinXinput.c8
-rw-r--r--xorg-server/hw/xquartz/mach-startup/bundle-main.c1384
-rw-r--r--xorg-server/hw/xquartz/pseudoramiX.c4
-rw-r--r--xorg-server/hw/xquartz/quartz.c20
-rw-r--r--xorg-server/hw/xquartz/quartzCommon.h171
-rw-r--r--xorg-server/hw/xquartz/quartzKeyboard.c1708
-rw-r--r--xorg-server/hw/xquartz/xpr/dri.c31
-rw-r--r--xorg-server/hw/xquartz/xpr/driWrap.c20
-rw-r--r--xorg-server/hw/xquartz/xpr/xprCursor.c12
-rw-r--r--xorg-server/hw/xquartz/xpr/xprFrame.c1280
-rw-r--r--xorg-server/hw/xquartz/xpr/xprScreen.c4
15 files changed, 2936 insertions, 2919 deletions
diff --git a/xorg-server/hw/xquartz/applewm.c b/xorg-server/hw/xquartz/applewm.c
index 64851e791..054fff776 100644
--- a/xorg-server/hw/xquartz/applewm.c
+++ b/xorg-server/hw/xquartz/applewm.c
@@ -140,10 +140,8 @@ AppleWMSetScreenOrigin(
{
int32_t data[2];
- data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x
- + darwinMainScreenX);
- data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
- + darwinMainScreenY);
+ data[0] = pWin->drawable.pScreen->x + darwinMainScreenX;
+ data[1] = pWin->drawable.pScreen->y + darwinMainScreenY;
dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(),
XA_INTEGER, 32, PropModeReplace, 2, data, TRUE);
diff --git a/xorg-server/hw/xquartz/darwin.c b/xorg-server/hw/xquartz/darwin.c
index ed9543eb2..7814967b8 100644
--- a/xorg-server/hw/xquartz/darwin.c
+++ b/xorg-server/hw/xquartz/darwin.c
@@ -84,8 +84,7 @@ FILE *debug_log_fp = NULL;
* X server shared global variables
*/
int darwinScreensFound = 0;
-static int darwinScreenKeyIndex;
-DevPrivateKey darwinScreenKey = &darwinScreenKeyIndex;
+DevPrivateKeyRec darwinScreenKeyRec;
io_connect_t darwinParamConnect = 0;
int darwinEventReadFD = -1;
int darwinEventWriteFD = -1;
@@ -185,6 +184,9 @@ static Bool DarwinScreenInit(int index, ScreenPtr pScreen, int argc, char **argv
Bool ret;
DarwinFramebufferPtr dfb;
+ if (!dixRegisterPrivateKey(&darwinScreenKeyRec, PRIVATE_SCREEN, 0))
+ return FALSE;
+
// reset index of found screens for each server generation
if (index == 0) {
foundIndex = 0;
@@ -262,8 +264,8 @@ static Bool DarwinScreenInit(int index, ScreenPtr pScreen, int argc, char **argv
return FALSE;
}
- dixScreenOrigins[index].x = dfb->x;
- dixScreenOrigins[index].y = dfb->y;
+ pScreen->x = dfb->x;
+ pScreen->y = dfb->y;
/* ErrorF("Screen %d added: %dx%d @ (%d,%d)\n",
index, dfb->width, dfb->height, dfb->x, dfb->y); */
@@ -526,16 +528,16 @@ DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo)
{
int i, left, top;
- left = dixScreenOrigins[0].x;
- top = dixScreenOrigins[0].y;
+ left = pScreenInfo->screens[0]->x;
+ top = pScreenInfo->screens[0]->y;
/* Find leftmost screen. If there's a tie, take the topmost of the two. */
for (i = 1; i < pScreenInfo->numScreens; i++) {
- if (dixScreenOrigins[i].x < left ||
- (dixScreenOrigins[i].x == left && dixScreenOrigins[i].y < top))
+ if (pScreenInfo->screens[i]->x < left ||
+ (pScreenInfo->screens[i]->x == left && pScreenInfo->screens[i]->y < top))
{
- left = dixScreenOrigins[i].x;
- top = dixScreenOrigins[i].y;
+ left = pScreenInfo->screens[i]->x;
+ top = pScreenInfo->screens[i]->y;
}
}
@@ -551,10 +553,10 @@ DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo)
if (darwinMainScreenX != 0 || darwinMainScreenY != 0) {
for (i = 0; i < pScreenInfo->numScreens; i++) {
- dixScreenOrigins[i].x -= darwinMainScreenX;
- dixScreenOrigins[i].y -= darwinMainScreenY;
+ pScreenInfo->screens[i]->x -= darwinMainScreenX;
+ pScreenInfo->screens[i]->y -= darwinMainScreenY;
DEBUG_LOG("Screen %d placed at X11 coordinate (%d,%d).\n",
- i, dixScreenOrigins[i].x, dixScreenOrigins[i].y);
+ i, pScreenInfo->screens[i]->x, pScreenInfo->screens[i]->y);
}
}
}
@@ -793,7 +795,7 @@ void AbortDDX( void )
void
xf86SetRootClip (ScreenPtr pScreen, int enable)
{
- WindowPtr pWin = WindowTable[pScreen->myNum];
+ WindowPtr pWin = pScreen->root;
WindowPtr pChild;
Bool WasViewable = (Bool)(pWin->viewable);
Bool anyMarked = TRUE;
@@ -817,8 +819,8 @@ xf86SetRootClip (ScreenPtr pScreen, int enable)
{
RegionPtr borderVisible;
- borderVisible = REGION_CREATE(pScreen, NullBox, 1);
- REGION_SUBTRACT(pScreen, borderVisible,
+ borderVisible = RegionCreate(NullBox, 1);
+ RegionSubtract(borderVisible,
&pWin->borderClip, &pWin->winSize);
pWin->valdata->before.borderVisible = borderVisible;
}
@@ -837,13 +839,13 @@ xf86SetRootClip (ScreenPtr pScreen, int enable)
box.y1 = 0;
box.x2 = pScreen->width;
box.y2 = pScreen->height;
- REGION_RESET(pScreen, &pWin->borderClip, &box);
- REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ RegionReset(&pWin->borderClip, &box);
+ RegionBreak(&pWin->clipList);
}
else
{
- REGION_EMPTY(pScreen, &pWin->borderClip);
- REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ RegionEmpty(&pWin->borderClip);
+ RegionBreak(&pWin->clipList);
}
ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
@@ -852,8 +854,8 @@ xf86SetRootClip (ScreenPtr pScreen, int enable)
{
if (pWin->backStorage)
{
- pOldClip = REGION_CREATE(pScreen, NullBox, 1);
- REGION_COPY(pScreen, pOldClip, &pWin->clipList);
+ pOldClip = RegionCreate(NullBox, 1);
+ RegionCopy(pOldClip, &pWin->clipList);
}
if (pWin->firstChild)
@@ -882,7 +884,7 @@ xf86SetRootClip (ScreenPtr pScreen, int enable)
(pWin, 0, 0, pOldClip,
pWin->drawable.x, pWin->drawable.y);
if (WasViewable)
- REGION_DESTROY(pScreen, pOldClip);
+ RegionDestroy(pOldClip);
if (bsExposed)
{
RegionPtr valExposed = NullRegion;
@@ -891,8 +893,8 @@ xf86SetRootClip (ScreenPtr pScreen, int enable)
valExposed = &pWin->valdata->after.exposed;
(*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
if (valExposed)
- REGION_EMPTY(pScreen, valExposed);
- REGION_DESTROY(pScreen, bsExposed);
+ RegionEmpty(valExposed);
+ RegionDestroy(bsExposed);
}
}
if (WasViewable)
diff --git a/xorg-server/hw/xquartz/darwin.h b/xorg-server/hw/xquartz/darwin.h
index 6209b5ef1..7cd4336cd 100644
--- a/xorg-server/hw/xquartz/darwin.h
+++ b/xorg-server/hw/xquartz/darwin.h
@@ -50,7 +50,8 @@ void xf86SetRootClip (ScreenPtr pScreen, int enable);
/*
* Global variables from darwin.c
*/
-extern DevPrivateKey darwinScreenKey; // index into pScreen.devPrivates
+extern DevPrivateKeyRec darwinScreenKeyRec;
+#define darwinScreenKey (&darwinScreenKeyRec)
extern int darwinScreensFound;
extern io_connect_t darwinParamConnect;
extern int darwinEventReadFD;
diff --git a/xorg-server/hw/xquartz/darwinEvents.c b/xorg-server/hw/xquartz/darwinEvents.c
index 421efcedf..db3f5b24e 100644
--- a/xorg-server/hw/xquartz/darwinEvents.c
+++ b/xorg-server/hw/xquartz/darwinEvents.c
@@ -1,576 +1,576 @@
-/*
-Darwin event queue and event handling
-
-Copyright 2007-2008 Apple Inc.
-Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
-Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
-
-This file is based on mieq.c by Keith Packard,
-which contains the following copyright:
-Copyright 1990, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-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
-OPEN GROUP 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 of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- */
-
-#include "sanitizedCarbon.h"
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#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 "os.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 <pthread.h>
-#include <errno.h>
-
-#include <IOKit/hidsystem/IOLLEvent.h>
-
-/* Fake button press/release for scroll wheel move. */
-#define SCROLLWHEELUPFAKE 4
-#define SCROLLWHEELDOWNFAKE 5
-#define SCROLLWHEELLEFTFAKE 6
-#define SCROLLWHEELRIGHTFAKE 7
-
-#include <X11/extensions/applewmconst.h>
-#include "applewmExt.h"
-
-/* FIXME: Abstract this better */
-extern Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev);
-
-int darwin_all_modifier_flags = 0; // last known modifier state
-int darwin_all_modifier_mask = 0;
-int darwin_x11_modifier_mask = 0;
-
-#define FD_ADD_MAX 128
-static int fd_add[FD_ADD_MAX];
-int fd_add_count = 0;
-static pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER;
-static pthread_t fd_add_tid = NULL;
-
-static EventListPtr darwinEvents = NULL;
-
-static pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER;
-
-/*** Pthread Magics ***/
-static 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;
-}
-
-void darwinEvents_lock(void);
-void darwinEvents_lock(void) {
- int err;
- if((err = pthread_mutex_lock(&mieq_lock))) {
- ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
- __FILE__, __FUNCTION__, __LINE__, err);
- spewCallStack();
- }
- if(darwinEvents == NULL) {
- pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
- }
-}
-
-void darwinEvents_unlock(void);
-void darwinEvents_unlock(void) {
- int err;
- if((err = pthread_mutex_unlock(&mieq_lock))) {
- ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
- __FILE__, __FUNCTION__, __LINE__, err);
- spewCallStack();
- }
-}
-
-/*
- * DarwinPressModifierKey
- * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants)
- */
-static void DarwinPressModifierKey(int pressed, int key) {
- int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
-
- if (keycode == 0) {
- ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key);
- return;
- }
-
- DarwinSendKeyboardEvents(pressed, keycode);
-}
-
-/*
- * DarwinUpdateModifiers
- * Send events to update the modifier state.
- */
-
-static int darwin_x11_modifier_mask_list[] = {
-#ifdef NX_DEVICELCMDKEYMASK
- NX_DEVICELCTLKEYMASK, NX_DEVICERCTLKEYMASK,
- NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK,
- NX_DEVICELCMDKEYMASK, NX_DEVICERCMDKEYMASK,
- NX_DEVICELALTKEYMASK, NX_DEVICERALTKEYMASK,
-#else
- NX_CONTROLMASK, NX_SHIFTMASK, NX_COMMANDMASK, NX_ALTERNATEMASK,
-#endif
- NX_ALPHASHIFTMASK,
- 0
-};
-
-static int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, };
-
-static void DarwinUpdateModifiers(
- int pressed, // KeyPress or KeyRelease
- int flags ) // modifier flags that have changed
-{
- int *f;
- int key;
-
- /* Capslock is special. This mask is the state of capslock (on/off),
- * not the state of the button. Hopefully we can find a better solution.
- */
- if(NX_ALPHASHIFTMASK & flags) {
- DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK);
- DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK);
- }
-
- for(f=darwin_x11_modifier_mask_list; *f; f++)
- if(*f & flags && *f != NX_ALPHASHIFTMASK) {
- key = DarwinModifierNXMaskToNXKey(*f);
- if(key == -1)
- ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n", *f);
- else
- DarwinPressModifierKey(pressed, key);
- }
-}
-
-/* Generic handler for Xquartz-specifc events. When possible, these should
- be moved into their own individual functions and set as handlers using
- mieqSetHandler. */
-
-static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) {
- XQuartzEvent *e = &(ie->xquartz_event);
-
- TA_SERVER();
-
- switch(e->subtype) {
- case kXquartzControllerNotify:
- DEBUG_LOG("kXquartzControllerNotify\n");
- AppleWMSendEvent(AppleWMControllerNotify,
- AppleWMControllerNotifyMask,
- e->data[0],
- e->data[1]);
- break;
-
- case kXquartzPasteboardNotify:
- DEBUG_LOG("kXquartzPasteboardNotify\n");
- AppleWMSendEvent(AppleWMPasteboardNotify,
- AppleWMPasteboardNotifyMask,
- e->data[0],
- e->data[1]);
- break;
-
- case kXquartzActivate:
- DEBUG_LOG("kXquartzActivate\n");
- QuartzShow();
- AppleWMSendEvent(AppleWMActivationNotify,
- AppleWMActivationNotifyMask,
- AppleWMIsActive, 0);
- break;
-
- case kXquartzDeactivate:
- DEBUG_LOG("kXquartzDeactivate\n");
- AppleWMSendEvent(AppleWMActivationNotify,
- AppleWMActivationNotifyMask,
- AppleWMIsInactive, 0);
- QuartzHide();
- break;
-
- case kXquartzReloadPreferences:
- DEBUG_LOG("kXquartzReloadPreferences\n");
- AppleWMSendEvent(AppleWMActivationNotify,
- AppleWMActivationNotifyMask,
- AppleWMReloadPreferences, 0);
- break;
-
- case kXquartzToggleFullscreen:
- DEBUG_LOG("kXquartzToggleFullscreen\n");
- if (quartzEnableRootless)
- QuartzSetFullscreen(!quartzHasRoot);
- else if (quartzHasRoot)
- QuartzHide();
- else
- QuartzShow();
- break;
-
- case kXquartzSetRootless:
- DEBUG_LOG("kXquartzSetRootless\n");
- QuartzSetRootless(e->data[0]);
- if (!quartzEnableRootless && !quartzHasRoot)
- QuartzHide();
- break;
-
- case kXquartzSetRootClip:
- QuartzSetRootClip((Bool)e->data[0]);
- break;
-
- case kXquartzQuit:
- GiveUp(0);
- break;
-
- case kXquartzSpaceChanged:
- DEBUG_LOG("kXquartzSpaceChanged\n");
- QuartzSpaceChanged(e->data[0]);
- break;
-
- case kXquartzListenOnOpenFD:
- ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]);
- ListenOnOpenFD((int)e->data[0], 1);
- break;
-
- case kXquartzReloadKeymap:
- DarwinKeyboardReloadHandler();
- break;
-
- case kXquartzDisplayChanged:
- QuartzUpdateScreens();
- break;
-
- default:
- if(!QuartzModeEventHandler(screenNum, e, dev))
- ErrorF("Unknown application defined event type %d.\n", e->subtype);
- }
-}
-
-void DarwinListenOnOpenFD(int fd) {
- ErrorF("DarwinListenOnOpenFD: %d\n", fd);
-
- pthread_mutex_lock(&fd_add_lock);
- if(fd_add_count < FD_ADD_MAX)
- fd_add[fd_add_count++] = fd;
- else
- ErrorF("FD Addition buffer at max. Dropping fd addition request.\n");
-
- pthread_cond_broadcast(&fd_add_ready_cond);
- pthread_mutex_unlock(&fd_add_lock);
-}
-
-static void DarwinProcessFDAdditionQueue_thread(void *args) {
- pthread_mutex_lock(&fd_add_lock);
- while(true) {
- while(fd_add_count) {
- DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1, fd_add[--fd_add_count]);
- }
- pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
- }
-}
-
-Bool DarwinEQInit(void) {
- int *p;
-
- for(p=darwin_x11_modifier_mask_list, darwin_all_modifier_mask=0; *p; p++) {
- darwin_x11_modifier_mask |= *p;
- }
-
- for(p=darwin_all_modifier_mask_additions, darwin_all_modifier_mask= darwin_x11_modifier_mask; *p; p++) {
- darwin_all_modifier_mask |= *p;
- }
-
- mieqInit();
- mieqSetHandler(ET_XQuartz, DarwinEventHandler);
-
- /* Note that this *could* cause a potential async issue, since we're checking
- * darwinEvents without holding the lock, but darwinEvents is only ever set
- * here, so I don't bother.
- */
- if (!darwinEvents) {
- darwinEvents = InitEventList(GetMaximumEventsNum());;
-
- if (!darwinEvents)
- FatalError("Couldn't allocate event buffer\n");
-
- darwinEvents_lock();
- pthread_cond_broadcast(&mieq_ready_cond);
- darwinEvents_unlock();
- }
-
- if(!fd_add_tid)
- fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
-
- return TRUE;
-}
-
-/*
- * ProcessInputEvents
- * Read and process events from the event queue until it is empty.
- */
-void ProcessInputEvents(void) {
- char nullbyte;
- int x = sizeof(nullbyte);
-
- TA_SERVER();
-
- mieqProcessInputEvents();
-
- // Empty the signaling pipe
- while (x == sizeof(nullbyte)) {
- x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
- }
-}
-
-/* Sends a null byte down darwinEventWriteFD, which will cause the
- Dispatch() event loop to check out event queue */
-static void DarwinPokeEQ(void) {
- char nullbyte=0;
- // <daniels> oh, i ... er ... christ.
- write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
-}
-
-/* Convert from Appkit pointer input values to X input values:
- * Note: pointer_x and pointer_y are relative to the upper-left of primary
- * display.
- */
-static void DarwinPrepareValuators(DeviceIntPtr pDev, int *valuators, ScreenPtr screen,
- float pointer_x, float pointer_y,
- float pressure, float tilt_x, float tilt_y) {
- /* Fix offset between darwin and X screens */
- pointer_x -= darwinMainScreenX + dixScreenOrigins[screen->myNum].x;
- pointer_y -= darwinMainScreenY + dixScreenOrigins[screen->myNum].y;
-
- if(pointer_x < 0.0)
- pointer_x = 0.0;
-
- if(pointer_y < 0.0)
- pointer_y = 0.0;
-
- if(pDev == darwinPointer) {
- valuators[0] = pointer_x;
- valuators[1] = pointer_y;
- valuators[2] = 0;
- valuators[3] = 0;
- valuators[4] = 0;
- } else {
- /* Setup our array of values */
- valuators[0] = XQUARTZ_VALUATOR_LIMIT * (pointer_x / (float)screenInfo.screens[0]->width);
- valuators[1] = XQUARTZ_VALUATOR_LIMIT * (pointer_y / (float)screenInfo.screens[0]->height);
- valuators[2] = XQUARTZ_VALUATOR_LIMIT * pressure;
- valuators[3] = XQUARTZ_VALUATOR_LIMIT * tilt_x;
- valuators[4] = XQUARTZ_VALUATOR_LIMIT * tilt_y;
- }
- //DEBUG_LOG("Pointer (%f, %f), Valuators: {%d,%d,%d,%d,%d}\n", pointer_x, pointer_y,
- // valuators[0], valuators[1], valuators[2], valuators[3], valuators[4]);
-}
-
-void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y,
- float pressure, float tilt_x, float tilt_y) {
- static int darwinFakeMouseButtonDown = 0;
- int i, num_events;
- ScreenPtr screen;
- int valuators[5];
-
- //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y);
-
- if(!darwinEvents) {
- DEBUG_LOG("DarwinSendPointerEvents called before darwinEvents was initialized\n");
- return;
- }
-
- screen = miPointerGetScreen(pDev);
- if(!screen) {
- DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
- return;
- }
-
- /* Handle fake click */
- if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
- if(darwinFakeMouseButtonDown != 0) {
- /* We're currently "down" with another button, so release it first */
- DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
- darwinFakeMouseButtonDown=0;
- }
- if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
- ev_button = 2;
- darwinFakeMouseButtonDown = 2;
- DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
- } else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
- ev_button = 3;
- darwinFakeMouseButtonDown = 3;
- DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
- }
- }
-
- if (ev_type == ButtonRelease && ev_button == 1) {
- if(darwinFakeMouseButtonDown) {
- ev_button = darwinFakeMouseButtonDown;
- }
-
- if(darwinFakeMouseButtonDown == 2) {
- DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
- } else if(darwinFakeMouseButtonDown == 3) {
- DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
- }
-
- darwinFakeMouseButtonDown = 0;
- }
-
- DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
- darwinEvents_lock(); {
- num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button,
- POINTER_ABSOLUTE, 0, pDev==darwinTabletCurrent?5:2, valuators);
- for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
- if(num_events > 0) DarwinPokeEQ();
- } darwinEvents_unlock();
-}
-
-void DarwinSendKeyboardEvents(int ev_type, int keycode) {
- int i, num_events;
-
- if(!darwinEvents) {
- DEBUG_LOG("DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
- return;
- }
-
- darwinEvents_lock(); {
- num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
- for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard, (InternalEvent*)darwinEvents[i].event);
- if(num_events > 0) DarwinPokeEQ();
- } darwinEvents_unlock();
-}
-
-void DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
- int i, num_events;
- ScreenPtr screen;
- DeviceIntPtr pDev = darwinTabletCurrent;
- int valuators[5];
-
- DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y);
-
- if(!darwinEvents) {
- DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n");
- return;
- }
-
- screen = miPointerGetScreen(pDev);
- if(!screen) {
- DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
- return;
- }
-
- DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f);
- darwinEvents_lock(); {
- num_events = GetProximityEvents(darwinEvents, pDev, ev_type,
- 0, 5, valuators);
- for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
- if(num_events > 0) DarwinPokeEQ();
- } darwinEvents_unlock();
-}
-
-
-/* Send the appropriate number of button clicks to emulate scroll wheel */
-void DarwinSendScrollEvents(float count_x, float count_y,
- float pointer_x, float pointer_y,
- float pressure, float tilt_x, float tilt_y) {
- int sign_x, sign_y;
- if(!darwinEvents) {
- DEBUG_LOG("DarwinSendScrollEvents called before darwinEvents was initialized\n");
- return;
- }
-
- sign_x = count_x > 0.0f ? SCROLLWHEELLEFTFAKE : SCROLLWHEELRIGHTFAKE;
- sign_y = count_y > 0.0f ? SCROLLWHEELUPFAKE : SCROLLWHEELDOWNFAKE;
- count_x = fabs(count_x);
- count_y = fabs(count_y);
-
- while ((count_x > 0.0f) || (count_y > 0.0f)) {
- if (count_x > 0.0f) {
- DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
- DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
- count_x = count_x - 1.0f;
- }
- if (count_y > 0.0f) {
- DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
- DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
- count_y = count_y - 1.0f;
- }
- }
-}
-
-/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
- reflect changing modifier flags (alt, control, meta, etc) */
-void DarwinUpdateModKeys(int flags) {
- DarwinUpdateModifiers(KeyRelease, darwin_all_modifier_flags & ~flags & darwin_x11_modifier_mask);
- DarwinUpdateModifiers(KeyPress, ~darwin_all_modifier_flags & flags & darwin_x11_modifier_mask);
- darwin_all_modifier_flags = flags;
-}
-
-/*
- * DarwinSendDDXEvent
- * Send the X server thread a message by placing it on the event queue.
- */
-void DarwinSendDDXEvent(int type, int argc, ...) {
- XQuartzEvent e;
- int i;
- va_list args;
-
- memset(&e, 0, sizeof(e));
- e.header = ET_Internal;
- e.type = ET_XQuartz;
- e.length = sizeof(e);
- e.time = GetTimeInMillis();
- e.subtype = type;
-
- if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
- va_start (args, argc);
- for (i = 0; i < argc; i++)
- e.data[i] = (uint32_t) va_arg (args, uint32_t);
- va_end (args);
- }
-
- darwinEvents_lock(); {
- mieqEnqueue(NULL, (InternalEvent*)&e);
- DarwinPokeEQ();
- } darwinEvents_unlock();
-}
+/*
+Darwin event queue and event handling
+
+Copyright 2007-2008 Apple Inc.
+Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
+Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
+
+This file is based on mieq.c by Keith Packard,
+which contains the following copyright:
+Copyright 1990, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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 of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ */
+
+#include "sanitizedCarbon.h"
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#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 "os.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 <pthread.h>
+#include <errno.h>
+
+#include <IOKit/hidsystem/IOLLEvent.h>
+
+/* Fake button press/release for scroll wheel move. */
+#define SCROLLWHEELUPFAKE 4
+#define SCROLLWHEELDOWNFAKE 5
+#define SCROLLWHEELLEFTFAKE 6
+#define SCROLLWHEELRIGHTFAKE 7
+
+#include <X11/extensions/applewmconst.h>
+#include "applewmExt.h"
+
+/* FIXME: Abstract this better */
+extern Bool QuartzModeEventHandler(int screenNum, XQuartzEvent *e, DeviceIntPtr dev);
+
+int darwin_all_modifier_flags = 0; // last known modifier state
+int darwin_all_modifier_mask = 0;
+int darwin_x11_modifier_mask = 0;
+
+#define FD_ADD_MAX 128
+static int fd_add[FD_ADD_MAX];
+int fd_add_count = 0;
+static pthread_mutex_t fd_add_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t fd_add_ready_cond = PTHREAD_COND_INITIALIZER;
+static pthread_t fd_add_tid = NULL;
+
+static EventListPtr darwinEvents = NULL;
+
+static pthread_mutex_t mieq_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t mieq_ready_cond = PTHREAD_COND_INITIALIZER;
+
+/*** Pthread Magics ***/
+static 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;
+}
+
+void darwinEvents_lock(void);
+void darwinEvents_lock(void) {
+ int err;
+ if((err = pthread_mutex_lock(&mieq_lock))) {
+ ErrorF("%s:%s:%d: Failed to lock mieq_lock: %d\n",
+ __FILE__, __FUNCTION__, __LINE__, err);
+ spewCallStack();
+ }
+ if(darwinEvents == NULL) {
+ pthread_cond_wait(&mieq_ready_cond, &mieq_lock);
+ }
+}
+
+void darwinEvents_unlock(void);
+void darwinEvents_unlock(void) {
+ int err;
+ if((err = pthread_mutex_unlock(&mieq_lock))) {
+ ErrorF("%s:%s:%d: Failed to unlock mieq_lock: %d\n",
+ __FILE__, __FUNCTION__, __LINE__, err);
+ spewCallStack();
+ }
+}
+
+/*
+ * DarwinPressModifierKey
+ * Press or release the given modifier key (one of NX_MODIFIERKEY_* constants)
+ */
+static void DarwinPressModifierKey(int pressed, int key) {
+ int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
+
+ if (keycode == 0) {
+ ErrorF("DarwinPressModifierKey bad keycode: key=%d\n", key);
+ return;
+ }
+
+ DarwinSendKeyboardEvents(pressed, keycode);
+}
+
+/*
+ * DarwinUpdateModifiers
+ * Send events to update the modifier state.
+ */
+
+static int darwin_x11_modifier_mask_list[] = {
+#ifdef NX_DEVICELCMDKEYMASK
+ NX_DEVICELCTLKEYMASK, NX_DEVICERCTLKEYMASK,
+ NX_DEVICELSHIFTKEYMASK, NX_DEVICERSHIFTKEYMASK,
+ NX_DEVICELCMDKEYMASK, NX_DEVICERCMDKEYMASK,
+ NX_DEVICELALTKEYMASK, NX_DEVICERALTKEYMASK,
+#else
+ NX_CONTROLMASK, NX_SHIFTMASK, NX_COMMANDMASK, NX_ALTERNATEMASK,
+#endif
+ NX_ALPHASHIFTMASK,
+ 0
+};
+
+static int darwin_all_modifier_mask_additions[] = { NX_SECONDARYFNMASK, };
+
+static void DarwinUpdateModifiers(
+ int pressed, // KeyPress or KeyRelease
+ int flags ) // modifier flags that have changed
+{
+ int *f;
+ int key;
+
+ /* Capslock is special. This mask is the state of capslock (on/off),
+ * not the state of the button. Hopefully we can find a better solution.
+ */
+ if(NX_ALPHASHIFTMASK & flags) {
+ DarwinPressModifierKey(KeyPress, NX_MODIFIERKEY_ALPHALOCK);
+ DarwinPressModifierKey(KeyRelease, NX_MODIFIERKEY_ALPHALOCK);
+ }
+
+ for(f=darwin_x11_modifier_mask_list; *f; f++)
+ if(*f & flags && *f != NX_ALPHASHIFTMASK) {
+ key = DarwinModifierNXMaskToNXKey(*f);
+ if(key == -1)
+ ErrorF("DarwinUpdateModifiers: Unsupported NXMask: 0x%x\n", *f);
+ else
+ DarwinPressModifierKey(pressed, key);
+ }
+}
+
+/* Generic handler for Xquartz-specifc events. When possible, these should
+ be moved into their own individual functions and set as handlers using
+ mieqSetHandler. */
+
+static void DarwinEventHandler(int screenNum, InternalEvent *ie, DeviceIntPtr dev) {
+ XQuartzEvent *e = &(ie->xquartz_event);
+
+ TA_SERVER();
+
+ switch(e->subtype) {
+ case kXquartzControllerNotify:
+ DEBUG_LOG("kXquartzControllerNotify\n");
+ AppleWMSendEvent(AppleWMControllerNotify,
+ AppleWMControllerNotifyMask,
+ e->data[0],
+ e->data[1]);
+ break;
+
+ case kXquartzPasteboardNotify:
+ DEBUG_LOG("kXquartzPasteboardNotify\n");
+ AppleWMSendEvent(AppleWMPasteboardNotify,
+ AppleWMPasteboardNotifyMask,
+ e->data[0],
+ e->data[1]);
+ break;
+
+ case kXquartzActivate:
+ DEBUG_LOG("kXquartzActivate\n");
+ QuartzShow();
+ AppleWMSendEvent(AppleWMActivationNotify,
+ AppleWMActivationNotifyMask,
+ AppleWMIsActive, 0);
+ break;
+
+ case kXquartzDeactivate:
+ DEBUG_LOG("kXquartzDeactivate\n");
+ AppleWMSendEvent(AppleWMActivationNotify,
+ AppleWMActivationNotifyMask,
+ AppleWMIsInactive, 0);
+ QuartzHide();
+ break;
+
+ case kXquartzReloadPreferences:
+ DEBUG_LOG("kXquartzReloadPreferences\n");
+ AppleWMSendEvent(AppleWMActivationNotify,
+ AppleWMActivationNotifyMask,
+ AppleWMReloadPreferences, 0);
+ break;
+
+ case kXquartzToggleFullscreen:
+ DEBUG_LOG("kXquartzToggleFullscreen\n");
+ if (quartzEnableRootless)
+ QuartzSetFullscreen(!quartzHasRoot);
+ else if (quartzHasRoot)
+ QuartzHide();
+ else
+ QuartzShow();
+ break;
+
+ case kXquartzSetRootless:
+ DEBUG_LOG("kXquartzSetRootless\n");
+ QuartzSetRootless(e->data[0]);
+ if (!quartzEnableRootless && !quartzHasRoot)
+ QuartzHide();
+ break;
+
+ case kXquartzSetRootClip:
+ QuartzSetRootClip((Bool)e->data[0]);
+ break;
+
+ case kXquartzQuit:
+ GiveUp(0);
+ break;
+
+ case kXquartzSpaceChanged:
+ DEBUG_LOG("kXquartzSpaceChanged\n");
+ QuartzSpaceChanged(e->data[0]);
+ break;
+
+ case kXquartzListenOnOpenFD:
+ ErrorF("Calling ListenOnOpenFD() for new fd: %d\n", (int)e->data[0]);
+ ListenOnOpenFD((int)e->data[0], 1);
+ break;
+
+ case kXquartzReloadKeymap:
+ DarwinKeyboardReloadHandler();
+ break;
+
+ case kXquartzDisplayChanged:
+ QuartzUpdateScreens();
+ break;
+
+ default:
+ if(!QuartzModeEventHandler(screenNum, e, dev))
+ ErrorF("Unknown application defined event type %d.\n", e->subtype);
+ }
+}
+
+void DarwinListenOnOpenFD(int fd) {
+ ErrorF("DarwinListenOnOpenFD: %d\n", fd);
+
+ pthread_mutex_lock(&fd_add_lock);
+ if(fd_add_count < FD_ADD_MAX)
+ fd_add[fd_add_count++] = fd;
+ else
+ ErrorF("FD Addition buffer at max. Dropping fd addition request.\n");
+
+ pthread_cond_broadcast(&fd_add_ready_cond);
+ pthread_mutex_unlock(&fd_add_lock);
+}
+
+static void DarwinProcessFDAdditionQueue_thread(void *args) {
+ pthread_mutex_lock(&fd_add_lock);
+ while(true) {
+ while(fd_add_count) {
+ DarwinSendDDXEvent(kXquartzListenOnOpenFD, 1, fd_add[--fd_add_count]);
+ }
+ pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
+ }
+}
+
+Bool DarwinEQInit(void) {
+ int *p;
+
+ for(p=darwin_x11_modifier_mask_list, darwin_all_modifier_mask=0; *p; p++) {
+ darwin_x11_modifier_mask |= *p;
+ }
+
+ for(p=darwin_all_modifier_mask_additions, darwin_all_modifier_mask= darwin_x11_modifier_mask; *p; p++) {
+ darwin_all_modifier_mask |= *p;
+ }
+
+ mieqInit();
+ mieqSetHandler(ET_XQuartz, DarwinEventHandler);
+
+ /* Note that this *could* cause a potential async issue, since we're checking
+ * darwinEvents without holding the lock, but darwinEvents is only ever set
+ * here, so I don't bother.
+ */
+ if (!darwinEvents) {
+ darwinEvents = InitEventList(GetMaximumEventsNum());;
+
+ if (!darwinEvents)
+ FatalError("Couldn't allocate event buffer\n");
+
+ darwinEvents_lock();
+ pthread_cond_broadcast(&mieq_ready_cond);
+ darwinEvents_unlock();
+ }
+
+ if(!fd_add_tid)
+ fd_add_tid = create_thread(DarwinProcessFDAdditionQueue_thread, NULL);
+
+ return TRUE;
+}
+
+/*
+ * ProcessInputEvents
+ * Read and process events from the event queue until it is empty.
+ */
+void ProcessInputEvents(void) {
+ char nullbyte;
+ int x = sizeof(nullbyte);
+
+ TA_SERVER();
+
+ mieqProcessInputEvents();
+
+ // Empty the signaling pipe
+ while (x == sizeof(nullbyte)) {
+ x = read(darwinEventReadFD, &nullbyte, sizeof(nullbyte));
+ }
+}
+
+/* Sends a null byte down darwinEventWriteFD, which will cause the
+ Dispatch() event loop to check out event queue */
+static void DarwinPokeEQ(void) {
+ char nullbyte=0;
+ // <daniels> oh, i ... er ... christ.
+ write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte));
+}
+
+/* Convert from Appkit pointer input values to X input values:
+ * Note: pointer_x and pointer_y are relative to the upper-left of primary
+ * display.
+ */
+static void DarwinPrepareValuators(DeviceIntPtr pDev, int *valuators, ScreenPtr screen,
+ float pointer_x, float pointer_y,
+ float pressure, float tilt_x, float tilt_y) {
+ /* Fix offset between darwin and X screens */
+ pointer_x -= darwinMainScreenX + screen->x;
+ pointer_y -= darwinMainScreenY + screen->y;
+
+ if(pointer_x < 0.0)
+ pointer_x = 0.0;
+
+ if(pointer_y < 0.0)
+ pointer_y = 0.0;
+
+ if(pDev == darwinPointer) {
+ valuators[0] = pointer_x;
+ valuators[1] = pointer_y;
+ valuators[2] = 0;
+ valuators[3] = 0;
+ valuators[4] = 0;
+ } else {
+ /* Setup our array of values */
+ valuators[0] = XQUARTZ_VALUATOR_LIMIT * (pointer_x / (float)screenInfo.screens[0]->width);
+ valuators[1] = XQUARTZ_VALUATOR_LIMIT * (pointer_y / (float)screenInfo.screens[0]->height);
+ valuators[2] = XQUARTZ_VALUATOR_LIMIT * pressure;
+ valuators[3] = XQUARTZ_VALUATOR_LIMIT * tilt_x;
+ valuators[4] = XQUARTZ_VALUATOR_LIMIT * tilt_y;
+ }
+ //DEBUG_LOG("Pointer (%f, %f), Valuators: {%d,%d,%d,%d,%d}\n", pointer_x, pointer_y,
+ // valuators[0], valuators[1], valuators[2], valuators[3], valuators[4]);
+}
+
+void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y,
+ float pressure, float tilt_x, float tilt_y) {
+ static int darwinFakeMouseButtonDown = 0;
+ int i, num_events;
+ ScreenPtr screen;
+ int valuators[5];
+
+ //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y);
+
+ if(!darwinEvents) {
+ DEBUG_LOG("DarwinSendPointerEvents called before darwinEvents was initialized\n");
+ return;
+ }
+
+ screen = miPointerGetScreen(pDev);
+ if(!screen) {
+ DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
+ return;
+ }
+
+ /* Handle fake click */
+ if (ev_type == ButtonPress && darwinFakeButtons && ev_button == 1) {
+ if(darwinFakeMouseButtonDown != 0) {
+ /* We're currently "down" with another button, so release it first */
+ DarwinSendPointerEvents(pDev, ButtonRelease, darwinFakeMouseButtonDown, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
+ darwinFakeMouseButtonDown=0;
+ }
+ if (darwin_all_modifier_flags & darwinFakeMouse2Mask) {
+ ev_button = 2;
+ darwinFakeMouseButtonDown = 2;
+ DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
+ } else if (darwin_all_modifier_flags & darwinFakeMouse3Mask) {
+ ev_button = 3;
+ darwinFakeMouseButtonDown = 3;
+ DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
+ }
+ }
+
+ if (ev_type == ButtonRelease && ev_button == 1) {
+ if(darwinFakeMouseButtonDown) {
+ ev_button = darwinFakeMouseButtonDown;
+ }
+
+ if(darwinFakeMouseButtonDown == 2) {
+ DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse2Mask);
+ } else if(darwinFakeMouseButtonDown == 3) {
+ DarwinUpdateModKeys(darwin_all_modifier_flags & ~darwinFakeMouse3Mask);
+ }
+
+ darwinFakeMouseButtonDown = 0;
+ }
+
+ DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
+ darwinEvents_lock(); {
+ num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button,
+ POINTER_ABSOLUTE, 0, pDev==darwinTabletCurrent?5:2, valuators);
+ for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
+ if(num_events > 0) DarwinPokeEQ();
+ } darwinEvents_unlock();
+}
+
+void DarwinSendKeyboardEvents(int ev_type, int keycode) {
+ int i, num_events;
+
+ if(!darwinEvents) {
+ DEBUG_LOG("DarwinSendKeyboardEvents called before darwinEvents was initialized\n");
+ return;
+ }
+
+ darwinEvents_lock(); {
+ num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
+ for(i=0; i<num_events; i++) mieqEnqueue(darwinKeyboard, (InternalEvent*)darwinEvents[i].event);
+ if(num_events > 0) DarwinPokeEQ();
+ } darwinEvents_unlock();
+}
+
+void DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
+ int i, num_events;
+ ScreenPtr screen;
+ DeviceIntPtr pDev = darwinTabletCurrent;
+ int valuators[5];
+
+ DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y);
+
+ if(!darwinEvents) {
+ DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n");
+ return;
+ }
+
+ screen = miPointerGetScreen(pDev);
+ if(!screen) {
+ DEBUG_LOG("DarwinSendPointerEvents called before screen was initialized\n");
+ return;
+ }
+
+ DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f);
+ darwinEvents_lock(); {
+ num_events = GetProximityEvents(darwinEvents, pDev, ev_type,
+ 0, 5, valuators);
+ for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
+ if(num_events > 0) DarwinPokeEQ();
+ } darwinEvents_unlock();
+}
+
+
+/* Send the appropriate number of button clicks to emulate scroll wheel */
+void DarwinSendScrollEvents(float count_x, float count_y,
+ float pointer_x, float pointer_y,
+ float pressure, float tilt_x, float tilt_y) {
+ int sign_x, sign_y;
+ if(!darwinEvents) {
+ DEBUG_LOG("DarwinSendScrollEvents called before darwinEvents was initialized\n");
+ return;
+ }
+
+ sign_x = count_x > 0.0f ? SCROLLWHEELLEFTFAKE : SCROLLWHEELRIGHTFAKE;
+ sign_y = count_y > 0.0f ? SCROLLWHEELUPFAKE : SCROLLWHEELDOWNFAKE;
+ count_x = fabs(count_x);
+ count_y = fabs(count_y);
+
+ while ((count_x > 0.0f) || (count_y > 0.0f)) {
+ if (count_x > 0.0f) {
+ DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
+ DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_x, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
+ count_x = count_x - 1.0f;
+ }
+ if (count_y > 0.0f) {
+ DarwinSendPointerEvents(darwinPointer, ButtonPress, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
+ DarwinSendPointerEvents(darwinPointer, ButtonRelease, sign_y, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
+ count_y = count_y - 1.0f;
+ }
+ }
+}
+
+/* Send the appropriate KeyPress/KeyRelease events to GetKeyboardEvents to
+ reflect changing modifier flags (alt, control, meta, etc) */
+void DarwinUpdateModKeys(int flags) {
+ DarwinUpdateModifiers(KeyRelease, darwin_all_modifier_flags & ~flags & darwin_x11_modifier_mask);
+ DarwinUpdateModifiers(KeyPress, ~darwin_all_modifier_flags & flags & darwin_x11_modifier_mask);
+ darwin_all_modifier_flags = flags;
+}
+
+/*
+ * DarwinSendDDXEvent
+ * Send the X server thread a message by placing it on the event queue.
+ */
+void DarwinSendDDXEvent(int type, int argc, ...) {
+ XQuartzEvent e;
+ int i;
+ va_list args;
+
+ memset(&e, 0, sizeof(e));
+ e.header = ET_Internal;
+ e.type = ET_XQuartz;
+ e.length = sizeof(e);
+ e.time = GetTimeInMillis();
+ e.subtype = type;
+
+ if (argc > 0 && argc < XQUARTZ_EVENT_MAXARGS) {
+ va_start (args, argc);
+ for (i = 0; i < argc; i++)
+ e.data[i] = (uint32_t) va_arg (args, uint32_t);
+ va_end (args);
+ }
+
+ darwinEvents_lock(); {
+ mieqEnqueue(NULL, (InternalEvent*)&e);
+ DarwinPokeEQ();
+ } darwinEvents_unlock();
+}
diff --git a/xorg-server/hw/xquartz/darwinXinput.c b/xorg-server/hw/xquartz/darwinXinput.c
index 54ba2032a..958c7cdd4 100644
--- a/xorg-server/hw/xquartz/darwinXinput.c
+++ b/xorg-server/hw/xquartz/darwinXinput.c
@@ -210,14 +210,14 @@ ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev,
DEBUG_LOG("ChangeDeviceControl(%p, %p, %p)\n", client, dev, control);
switch (control->control) {
case DEVICE_RESOLUTION:
- return (BadMatch);
+ return BadMatch;
case DEVICE_ABS_CALIB:
case DEVICE_ABS_AREA:
- return (BadMatch);
+ return BadMatch;
case DEVICE_CORE:
- return (BadMatch);
+ return BadMatch;
default:
- return (BadMatch);
+ return BadMatch;
}
}
diff --git a/xorg-server/hw/xquartz/mach-startup/bundle-main.c b/xorg-server/hw/xquartz/mach-startup/bundle-main.c
index 63a185fc8..6dc7f9094 100644
--- a/xorg-server/hw/xquartz/mach-startup/bundle-main.c
+++ b/xorg-server/hw/xquartz/mach-startup/bundle-main.c
@@ -1,692 +1,692 @@
-/* main.c -- X application launcher
-
- Copyright (c) 2007 Jeremy Huddleston
- Copyright (c) 2007 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 <CoreFoundation/CoreFoundation.h>
-#include <AvailabilityMacros.h>
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/Xlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <stdbool.h>
-#include <signal.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <sys/time.h>
-#include <fcntl.h>
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <servers/bootstrap.h>
-#include "mach_startup.h"
-#include "mach_startupServer.h"
-
-#include "launchd_fd.h"
-/* From darwinEvents.c ... but don't want to pull in all the server cruft */
-void DarwinListenOnOpenFD(int fd);
-
-extern int noPanoramiXExtension;
-
-#define DEFAULT_CLIENT X11BINDIR "/xterm"
-#define DEFAULT_STARTX X11BINDIR "/startx"
-#define DEFAULT_SHELL "/bin/sh"
-
-#ifndef BUILD_DATE
-#define BUILD_DATE ""
-#endif
-#ifndef XSERVER_VERSION
-#define XSERVER_VERSION "?"
-#endif
-
-static char __crashreporter_info_buff__[4096] = {0};
-static const char *__crashreporter_info__ = &__crashreporter_info_buff__[0];
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
-// This is actually a toolchain requirement, but I'm not sure the correct check,
-// but it should be fine to just only include it for Leopard and later. This line
-// just tells the linker to never strip this symbol (such as for space optimization)
-asm (".desc ___crashreporter_info__, 0x10");
-#endif
-
-static const char *__crashreporter_info__base = "X.Org X Server " XSERVER_VERSION " Build Date: " BUILD_DATE;
-
-static char *launchd_id_prefix = NULL;
-static char *server_bootstrap_name = NULL;
-
-#define DEBUG 1
-
-/* This is in quartzStartup.c */
-int server_main(int argc, char **argv, char **envp);
-
-static int execute(const char *command);
-static char *command_from_prefs(const char *key, const char *default_value);
-
-/*** Pthread Magics ***/
-static 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;
-}
-
-/*** Mach-O IPC Stuffs ***/
-
-union MaxMsgSize {
- union __RequestUnion__mach_startup_subsystem req;
- union __ReplyUnion__mach_startup_subsystem rep;
-};
-
-static mach_port_t checkin_or_register(char *bname) {
- kern_return_t kr;
- mach_port_t mp;
-
- /* If we're started by launchd or the old mach_init */
- kr = bootstrap_check_in(bootstrap_port, bname, &mp);
- if (kr == KERN_SUCCESS)
- return mp;
-
- /* We probably were not started by launchd or the old mach_init */
- kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp);
- if (kr != KERN_SUCCESS) {
- fprintf(stderr, "mach_port_allocate(): %s\n", mach_error_string(kr));
- exit(EXIT_FAILURE);
- }
-
- kr = mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND);
- if (kr != KERN_SUCCESS) {
- fprintf(stderr, "mach_port_insert_right(): %s\n", mach_error_string(kr));
- exit(EXIT_FAILURE);
- }
-
- kr = bootstrap_register(bootstrap_port, bname, mp);
- if (kr != KERN_SUCCESS) {
- fprintf(stderr, "bootstrap_register(): %s\n", mach_error_string(kr));
- exit(EXIT_FAILURE);
- }
-
- return mp;
-}
-
-/*** $DISPLAY handoff ***/
-static int accept_fd_handoff(int connected_fd) {
- int launchd_fd;
-
- char databuf[] = "display";
- struct iovec iov[1];
-
- union {
- struct cmsghdr hdr;
- char bytes[CMSG_SPACE(sizeof(int))];
- } buf;
-
- struct msghdr msg;
- struct cmsghdr *cmsg;
-
- iov[0].iov_base = databuf;
- iov[0].iov_len = sizeof(databuf);
-
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_control = buf.bytes;
- msg.msg_controllen = sizeof(buf);
- msg.msg_name = 0;
- msg.msg_namelen = 0;
- msg.msg_flags = 0;
-
- cmsg = CMSG_FIRSTHDR (&msg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
-
- msg.msg_controllen = cmsg->cmsg_len;
-
- *((int*)CMSG_DATA(cmsg)) = -1;
-
- if(recvmsg(connected_fd, &msg, 0) < 0) {
- fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor. recvmsg() error: %s\n", strerror(errno));
- return -1;
- }
-
- launchd_fd = *((int*)CMSG_DATA(cmsg));
-
- return launchd_fd;
-}
-
-typedef struct {
- int fd;
- string_t filename;
-} socket_handoff_t;
-
-/* This thread accepts an incoming connection and hands off the file
- * descriptor for the new connection to accept_fd_handoff()
- */
-static void socket_handoff_thread(void *arg) {
- socket_handoff_t *handoff_data = (socket_handoff_t *)arg;
- int launchd_fd = -1;
- int connected_fd;
- unsigned remain;
-
- /* Now actually get the passed file descriptor from this connection
- * If we encounter an error, keep listening.
- */
- while(launchd_fd == -1) {
- connected_fd = accept(handoff_data->fd, NULL, NULL);
- if(connected_fd == -1) {
- fprintf(stderr, "X11.app: Failed to accept incoming connection on socket (fd=%d): %s\n", handoff_data->fd, strerror(errno));
- sleep(2);
- continue;
- }
-
- launchd_fd = accept_fd_handoff(connected_fd);
- if(launchd_fd == -1)
- fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor, no descriptor received? Waiting for another connection.\n");
-
- close(connected_fd);
- }
-
- close(handoff_data->fd);
- unlink(handoff_data->filename);
- free(handoff_data);
-
- /* TODO: Clean up this race better... giving xinitrc time to run... need to wait for 1.5 branch:
- *
- * From ajax:
- * There's already an internal callback chain for setting selection [in 1.5]
- * ownership. See the CallSelectionCallback at the bottom of
- * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook
- * into it.
- */
-
- remain = 3000000;
- fprintf(stderr, "X11.app: Received new $DISPLAY fd: %d ... sleeping to allow xinitrc to catchup.\n", launchd_fd);
- while((remain = usleep(remain)) > 0);
-
- fprintf(stderr, "X11.app Handing off fd to server thread via DarwinListenOnOpenFD(%d)\n", launchd_fd);
- DarwinListenOnOpenFD(launchd_fd);
-}
-
-static int create_socket(char *filename_out) {
- struct sockaddr_un servaddr_un;
- struct sockaddr *servaddr;
- socklen_t servaddr_len;
- int ret_fd;
- size_t try, try_max;
-
- for(try=0, try_max=5; try < try_max; try++) {
- tmpnam(filename_out);
-
- /* Setup servaddr_un */
- memset (&servaddr_un, 0, sizeof (struct sockaddr_un));
- servaddr_un.sun_family = AF_UNIX;
- strlcpy(servaddr_un.sun_path, filename_out, sizeof(servaddr_un.sun_path));
-
- servaddr = (struct sockaddr *) &servaddr_un;
- servaddr_len = sizeof(struct sockaddr_un) - sizeof(servaddr_un.sun_path) + strlen(filename_out);
-
- ret_fd = socket(PF_UNIX, SOCK_STREAM, 0);
- if(ret_fd == -1) {
- fprintf(stderr, "X11.app: Failed to create socket (try %d / %d): %s - %s\n", (int)try+1, (int)try_max, filename_out, strerror(errno));
- continue;
- }
-
- if(bind(ret_fd, servaddr, servaddr_len) != 0) {
- fprintf(stderr, "X11.app: Failed to bind socket: %d - %s\n", errno, strerror(errno));
- close(ret_fd);
- return 0;
- }
-
- if(listen(ret_fd, 10) != 0) {
- fprintf(stderr, "X11.app: Failed to listen to socket: %s - %d - %s\n", filename_out, errno, strerror(errno));
- close(ret_fd);
- return 0;
- }
-
-#ifdef DEBUG
- fprintf(stderr, "X11.app: Listening on socket for fd handoff: (%d) %s\n", ret_fd, filename_out);
-#endif
-
- return ret_fd;
- }
-
- return 0;
-}
-
-static int launchd_socket_handed_off = 0;
-
-kern_return_t do_request_fd_handoff_socket(mach_port_t port, string_t filename) {
- socket_handoff_t *handoff_data;
-
- launchd_socket_handed_off = 1;
-
- handoff_data = (socket_handoff_t *)calloc(1,sizeof(socket_handoff_t));
- if(!handoff_data) {
- fprintf(stderr, "X11.app: Error allocating memory for handoff_data\n");
- return KERN_FAILURE;
- }
-
- handoff_data->fd = create_socket(handoff_data->filename);
- if(!handoff_data->fd) {
- free(handoff_data);
- return KERN_FAILURE;
- }
-
- strlcpy(filename, handoff_data->filename, STRING_T_SIZE);
-
- create_thread(socket_handoff_thread, handoff_data);
-
-#ifdef DEBUG
- fprintf(stderr, "X11.app: Thread created for handoff. Returning success to tell caller to connect and push the fd.\n");
-#endif
-
- return KERN_SUCCESS;
-}
-
-kern_return_t do_request_pid(mach_port_t port, int *my_pid) {
- *my_pid = getpid();
- return KERN_SUCCESS;
-}
-
-/*** Server Startup ***/
-kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv,
- mach_msg_type_number_t argvCnt,
- string_array_t envp,
- mach_msg_type_number_t envpCnt) {
- /* And now back to char ** */
- char **_argv = alloca((argvCnt + 1) * sizeof(char *));
- char **_envp = alloca((envpCnt + 1) * sizeof(char *));
- size_t i;
-
- /* If we didn't get handed a launchd DISPLAY socket, we should
- * unset DISPLAY or we can run into problems with pbproxy
- */
- if(!launchd_socket_handed_off) {
- fprintf(stderr, "X11.app: No launchd socket handed off, unsetting DISPLAY\n");
- unsetenv("DISPLAY");
- }
-
- if(!_argv || !_envp) {
- return KERN_FAILURE;
- }
-
- fprintf(stderr, "X11.app: do_start_x11_server(): argc=%d\n", argvCnt);
- for(i=0; i < argvCnt; i++) {
- _argv[i] = argv[i];
- fprintf(stderr, "\targv[%u] = %s\n", (unsigned)i, argv[i]);
- }
- _argv[argvCnt] = NULL;
-
- for(i=0; i < envpCnt; i++) {
- _envp[i] = envp[i];
- }
- _envp[envpCnt] = NULL;
-
- if(server_main(argvCnt, _argv, _envp) == 0)
- return KERN_SUCCESS;
- else
- return KERN_FAILURE;
-}
-
-static int startup_trigger(int argc, char **argv, char **envp) {
- Display *display;
- const char *s;
-
- /* Take care of the case where we're called like a normal DDX */
- if(argc > 1 && argv[1][0] == ':') {
- size_t i;
- kern_return_t kr;
- mach_port_t mp;
- string_array_t newenvp;
- string_array_t newargv;
-
- /* We need to count envp */
- int envpc;
- for(envpc=0; envp[envpc]; envpc++);
-
- /* We have fixed-size string lengths due to limitations in IPC,
- * so we need to copy our argv and envp.
- */
- newargv = (string_array_t)alloca(argc * sizeof(string_t));
- newenvp = (string_array_t)alloca(envpc * sizeof(string_t));
-
- if(!newargv || !newenvp) {
- fprintf(stderr, "Memory allocation failure\n");
- exit(EXIT_FAILURE);
- }
-
- for(i=0; i < argc; i++) {
- strlcpy(newargv[i], argv[i], STRING_T_SIZE);
- }
- for(i=0; i < envpc; i++) {
- strlcpy(newenvp[i], envp[i], STRING_T_SIZE);
- }
-
- kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp);
- if (kr != KERN_SUCCESS) {
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- fprintf(stderr, "bootstrap_look_up(%s): %s\n", server_bootstrap_name, bootstrap_strerror(kr));
-#else
- fprintf(stderr, "bootstrap_look_up(%s): %ul\n", server_bootstrap_name, (unsigned long)kr);
-#endif
- exit(EXIT_FAILURE);
- }
-
- kr = start_x11_server(mp, newargv, argc, newenvp, envpc);
- if (kr != KERN_SUCCESS) {
- fprintf(stderr, "start_x11_server: %s\n", mach_error_string(kr));
- exit(EXIT_FAILURE);
- }
- exit(EXIT_SUCCESS);
- }
-
- /* If we have a process serial number and it's our only arg, act as if
- * the user double clicked the app bundle: launch app_to_run if possible
- */
- if(argc == 1 || (argc == 2 && !strncmp(argv[1], "-psn_", 5))) {
- /* Now, try to open a display, if so, run the launcher */
- display = XOpenDisplay(NULL);
- if(display) {
- /* Could open the display, start the launcher */
- XCloseDisplay(display);
-
- return execute(command_from_prefs("app_to_run", DEFAULT_CLIENT));
- }
- }
-
- /* Start the server */
- if((s = getenv("DISPLAY"))) {
- fprintf(stderr, "X11.app: Could not connect to server (DISPLAY=\"%s\", unsetting). Starting X server.\n", s);
- unsetenv("DISPLAY");
- } else {
- fprintf(stderr, "X11.app: Could not connect to server (DISPLAY is not set). Starting X server.\n");
- }
- return execute(command_from_prefs("startx_script", DEFAULT_STARTX));
-}
-
-/** Setup the environment we want our child processes to inherit */
-static void ensure_path(const char *dir) {
- char buf[1024], *temp;
-
- /* Make sure /usr/X11/bin is in the $PATH */
- temp = getenv("PATH");
- if(temp == NULL || temp[0] == 0) {
- snprintf(buf, sizeof(buf), "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:%s", dir);
- setenv("PATH", buf, TRUE);
- } else if(strnstr(temp, X11BINDIR, sizeof(temp)) == NULL) {
- snprintf(buf, sizeof(buf), "%s:%s", temp, dir);
- setenv("PATH", buf, TRUE);
- }
-}
-
-static void setup_env(void) {
- char *temp;
- const char *pds = NULL;
- const char *disp = getenv("DISPLAY");
- size_t len;
-
- /* Pass on our prefs domain to startx and its inheritors (mainly for
- * quartz-wm and the Xquartz stub's MachIPC)
- */
- CFBundleRef bundle = CFBundleGetMainBundle();
- if(bundle) {
- CFStringRef pd = CFBundleGetIdentifier(bundle);
- if(pd) {
- pds = CFStringGetCStringPtr(pd, 0);
- }
- }
-
- /* fallback to hardcoded value if we can't discover it */
- if(!pds) {
- pds = LAUNCHD_ID_PREFIX".X11";
- }
-
- server_bootstrap_name = malloc(sizeof(char) * (strlen(pds) + 1));
- if(!server_bootstrap_name) {
- fprintf(stderr, "X11.app: Memory allocation error.\n");
- exit(1);
- }
- strcpy(server_bootstrap_name, pds);
- setenv("X11_PREFS_DOMAIN", server_bootstrap_name, 1);
-
- len = strlen(server_bootstrap_name);
- launchd_id_prefix = malloc(sizeof(char) * (len - 3));
- if(!launchd_id_prefix) {
- fprintf(stderr, "X11.app: Memory allocation error.\n");
- exit(1);
- }
- strlcpy(launchd_id_prefix, server_bootstrap_name, len - 3);
-
- /* We need to unset DISPLAY if it is not our socket */
- if(disp) {
- /* s = basename(disp) */
- const char *d, *s;
- for(s = NULL, d = disp; *d; d++) {
- if(*d == '/')
- s = d + 1;
- }
-
- if(s && *s) {
- if(strcmp(launchd_id_prefix, "org.x") == 0 && strcmp(s, ":0") == 0) {
- fprintf(stderr, "X11.app: Detected old style launchd DISPLAY, please update xinit.\n");
- } else {
- temp = (char *)malloc(sizeof(char) * len);
- if(!temp) {
- fprintf(stderr, "X11.app: Memory allocation error creating space for socket name test.\n");
- exit(1);
- }
- strlcpy(temp, launchd_id_prefix, len);
- strlcat(temp, ":0", len);
-
- if(strcmp(temp, s) != 0) {
- /* If we don't have a match, unset it. */
- fprintf(stderr, "X11.app: DISPLAY (\"%s\") does not match our id (\"%s\"), unsetting.\n", disp, launchd_id_prefix);
- unsetenv("DISPLAY");
- }
- free(temp);
- }
- } else {
- /* The DISPLAY environment variable is not formatted like a launchd socket, so reset. */
- fprintf(stderr, "X11.app: DISPLAY does not look like a launchd set variable, unsetting.\n");
- unsetenv("DISPLAY");
- }
- }
-
- /* Make sure PATH is right */
- ensure_path(X11BINDIR);
-
- /* cd $HOME */
- temp = getenv("HOME");
- if(temp != NULL && temp[0] != '\0')
- chdir(temp);
-}
-
-/*** Main ***/
-int main(int argc, char **argv, char **envp) {
- Bool listenOnly = FALSE;
- int i;
- mach_msg_size_t mxmsgsz = sizeof(union MaxMsgSize) + MAX_TRAILER_SIZE;
- mach_port_t mp;
- kern_return_t kr;
-
- /* Setup our environment for our children */
- setup_env();
-
- /* The server must not run the PanoramiX operations. */
- noPanoramiXExtension = TRUE;
-
- /* Setup the initial crasherporter info */
- strlcpy(__crashreporter_info_buff__, __crashreporter_info__base, sizeof(__crashreporter_info_buff__));
-
- fprintf(stderr, "X11.app: main(): argc=%d\n", argc);
- for(i=0; i < argc; i++) {
- fprintf(stderr, "\targv[%u] = %s\n", (unsigned)i, argv[i]);
- if(!strcmp(argv[i], "--listenonly")) {
- listenOnly = TRUE;
- }
- }
-
- mp = checkin_or_register(server_bootstrap_name);
- if(mp == MACH_PORT_NULL) {
- fprintf(stderr, "NULL mach service: %s", server_bootstrap_name);
- return EXIT_FAILURE;
- }
-
- /* Check if we need to do something other than listen, and make another
- * thread handle it.
- */
- if(!listenOnly) {
- pid_t child1, child2;
- int status;
-
- /* Do the fork-twice trick to avoid having to reap zombies */
- child1 = fork();
- switch (child1) {
- case -1: /* error */
- break;
-
- case 0: /* child1 */
- child2 = fork();
-
- switch (child2) {
- int max_files, i;
-
- case -1: /* error */
- break;
-
- case 0: /* child2 */
- /* close all open files except for standard streams */
- max_files = sysconf(_SC_OPEN_MAX);
- for(i = 3; i < max_files; i++)
- close(i);
-
- /* ensure stdin is on /dev/null */
- close(0);
- open("/dev/null", O_RDONLY);
-
- return startup_trigger(argc, argv, envp);
-
- default: /* parent (child1) */
- _exit(0);
- }
- break;
-
- default: /* parent */
- waitpid(child1, &status, 0);
- }
- }
-
- /* Main event loop */
- fprintf(stderr, "Waiting for startup parameters via Mach IPC.\n");
- kr = mach_msg_server(mach_startup_server, mxmsgsz, mp, 0);
- if (kr != KERN_SUCCESS) {
- fprintf(stderr, "%s.X11(mp): %s\n", LAUNCHD_ID_PREFIX, mach_error_string(kr));
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-static int execute(const char *command) {
- const char *newargv[4];
- const char **p;
-
- newargv[0] = command_from_prefs("login_shell", DEFAULT_SHELL);
- newargv[1] = "-c";
- newargv[2] = command;
- newargv[3] = NULL;
-
- fprintf(stderr, "X11.app: Launching %s:\n", command);
- for(p=newargv; *p; p++) {
- fprintf(stderr, "\targv[%ld] = %s\n", (long int)(p - newargv), *p);
- }
-
- execvp (newargv[0], (char * const *) newargv);
- perror ("X11.app: Couldn't exec.");
- return(1);
-}
-
-static char *command_from_prefs(const char *key, const char *default_value) {
- char *command = NULL;
-
- CFStringRef cfKey;
- CFPropertyListRef PlistRef;
-
- if(!key)
- return NULL;
-
- cfKey = CFStringCreateWithCString(NULL, key, kCFStringEncodingASCII);
-
- if(!cfKey)
- return NULL;
-
- PlistRef = CFPreferencesCopyAppValue(cfKey, kCFPreferencesCurrentApplication);
-
- if ((PlistRef == NULL) || (CFGetTypeID(PlistRef) != CFStringGetTypeID())) {
- CFStringRef cfDefaultValue = CFStringCreateWithCString(NULL, default_value, kCFStringEncodingASCII);
- int len = strlen(default_value) + 1;
-
- if(!cfDefaultValue)
- goto command_from_prefs_out;
-
- CFPreferencesSetAppValue(cfKey, cfDefaultValue, kCFPreferencesCurrentApplication);
- CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
- CFRelease(cfDefaultValue);
-
- command = (char *)malloc(len * sizeof(char));
- if(!command)
- goto command_from_prefs_out;
- strcpy(command, default_value);
- } else {
- int len = CFStringGetLength((CFStringRef)PlistRef) + 1;
- command = (char *)malloc(len * sizeof(char));
- if(!command)
- goto command_from_prefs_out;
- CFStringGetCString((CFStringRef)PlistRef, command, len, kCFStringEncodingASCII);
- }
-
-command_from_prefs_out:
- if (PlistRef)
- CFRelease(PlistRef);
- if(cfKey)
- CFRelease(cfKey);
- return command;
-}
+/* main.c -- X application launcher
+
+ Copyright (c) 2007 Jeremy Huddleston
+ Copyright (c) 2007 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 <CoreFoundation/CoreFoundation.h>
+#include <AvailabilityMacros.h>
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <signal.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <sys/time.h>
+#include <fcntl.h>
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <servers/bootstrap.h>
+#include "mach_startup.h"
+#include "mach_startupServer.h"
+
+#include "launchd_fd.h"
+/* From darwinEvents.c ... but don't want to pull in all the server cruft */
+void DarwinListenOnOpenFD(int fd);
+
+extern int noPanoramiXExtension;
+
+#define DEFAULT_CLIENT X11BINDIR "/xterm"
+#define DEFAULT_STARTX X11BINDIR "/startx"
+#define DEFAULT_SHELL "/bin/sh"
+
+#ifndef BUILD_DATE
+#define BUILD_DATE ""
+#endif
+#ifndef XSERVER_VERSION
+#define XSERVER_VERSION "?"
+#endif
+
+static char __crashreporter_info_buff__[4096] = {0};
+static const char *__crashreporter_info__ = &__crashreporter_info_buff__[0];
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+// This is actually a toolchain requirement, but I'm not sure the correct check,
+// but it should be fine to just only include it for Leopard and later. This line
+// just tells the linker to never strip this symbol (such as for space optimization)
+asm (".desc ___crashreporter_info__, 0x10");
+#endif
+
+static const char *__crashreporter_info__base = "X.Org X Server " XSERVER_VERSION " Build Date: " BUILD_DATE;
+
+static char *launchd_id_prefix = NULL;
+static char *server_bootstrap_name = NULL;
+
+#define DEBUG 1
+
+/* This is in quartzStartup.c */
+int server_main(int argc, char **argv, char **envp);
+
+static int execute(const char *command);
+static char *command_from_prefs(const char *key, const char *default_value);
+
+/*** Pthread Magics ***/
+static 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;
+}
+
+/*** Mach-O IPC Stuffs ***/
+
+union MaxMsgSize {
+ union __RequestUnion__mach_startup_subsystem req;
+ union __ReplyUnion__mach_startup_subsystem rep;
+};
+
+static mach_port_t checkin_or_register(char *bname) {
+ kern_return_t kr;
+ mach_port_t mp;
+
+ /* If we're started by launchd or the old mach_init */
+ kr = bootstrap_check_in(bootstrap_port, bname, &mp);
+ if (kr == KERN_SUCCESS)
+ return mp;
+
+ /* We probably were not started by launchd or the old mach_init */
+ kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "mach_port_allocate(): %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ kr = mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "mach_port_insert_right(): %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ kr = bootstrap_register(bootstrap_port, bname, mp);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "bootstrap_register(): %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+
+ return mp;
+}
+
+/*** $DISPLAY handoff ***/
+static int accept_fd_handoff(int connected_fd) {
+ int launchd_fd;
+
+ char databuf[] = "display";
+ struct iovec iov[1];
+
+ union {
+ struct cmsghdr hdr;
+ char bytes[CMSG_SPACE(sizeof(int))];
+ } buf;
+
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+
+ iov[0].iov_base = databuf;
+ iov[0].iov_len = sizeof(databuf);
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = buf.bytes;
+ msg.msg_controllen = sizeof(buf);
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_flags = 0;
+
+ cmsg = CMSG_FIRSTHDR (&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ *((int*)CMSG_DATA(cmsg)) = -1;
+
+ if(recvmsg(connected_fd, &msg, 0) < 0) {
+ fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor. recvmsg() error: %s\n", strerror(errno));
+ return -1;
+ }
+
+ launchd_fd = *((int*)CMSG_DATA(cmsg));
+
+ return launchd_fd;
+}
+
+typedef struct {
+ int fd;
+ string_t filename;
+} socket_handoff_t;
+
+/* This thread accepts an incoming connection and hands off the file
+ * descriptor for the new connection to accept_fd_handoff()
+ */
+static void socket_handoff_thread(void *arg) {
+ socket_handoff_t *handoff_data = (socket_handoff_t *)arg;
+ int launchd_fd = -1;
+ int connected_fd;
+ unsigned remain;
+
+ /* Now actually get the passed file descriptor from this connection
+ * If we encounter an error, keep listening.
+ */
+ while(launchd_fd == -1) {
+ connected_fd = accept(handoff_data->fd, NULL, NULL);
+ if(connected_fd == -1) {
+ fprintf(stderr, "X11.app: Failed to accept incoming connection on socket (fd=%d): %s\n", handoff_data->fd, strerror(errno));
+ sleep(2);
+ continue;
+ }
+
+ launchd_fd = accept_fd_handoff(connected_fd);
+ if(launchd_fd == -1)
+ fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor, no descriptor received? Waiting for another connection.\n");
+
+ close(connected_fd);
+ }
+
+ close(handoff_data->fd);
+ unlink(handoff_data->filename);
+ free(handoff_data);
+
+ /* TODO: Clean up this race better... giving xinitrc time to run... need to wait for 1.5 branch:
+ *
+ * From ajax:
+ * There's already an internal callback chain for setting selection [in 1.5]
+ * ownership. See the CallSelectionCallback at the bottom of
+ * ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook
+ * into it.
+ */
+
+ remain = 3000000;
+ fprintf(stderr, "X11.app: Received new $DISPLAY fd: %d ... sleeping to allow xinitrc to catchup.\n", launchd_fd);
+ while((remain = usleep(remain)) > 0);
+
+ fprintf(stderr, "X11.app Handing off fd to server thread via DarwinListenOnOpenFD(%d)\n", launchd_fd);
+ DarwinListenOnOpenFD(launchd_fd);
+}
+
+static int create_socket(char *filename_out) {
+ struct sockaddr_un servaddr_un;
+ struct sockaddr *servaddr;
+ socklen_t servaddr_len;
+ int ret_fd;
+ size_t try, try_max;
+
+ for(try=0, try_max=5; try < try_max; try++) {
+ tmpnam(filename_out);
+
+ /* Setup servaddr_un */
+ memset (&servaddr_un, 0, sizeof (struct sockaddr_un));
+ servaddr_un.sun_family = AF_UNIX;
+ strlcpy(servaddr_un.sun_path, filename_out, sizeof(servaddr_un.sun_path));
+
+ servaddr = (struct sockaddr *) &servaddr_un;
+ servaddr_len = sizeof(struct sockaddr_un) - sizeof(servaddr_un.sun_path) + strlen(filename_out);
+
+ ret_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if(ret_fd == -1) {
+ fprintf(stderr, "X11.app: Failed to create socket (try %d / %d): %s - %s\n", (int)try+1, (int)try_max, filename_out, strerror(errno));
+ continue;
+ }
+
+ if(bind(ret_fd, servaddr, servaddr_len) != 0) {
+ fprintf(stderr, "X11.app: Failed to bind socket: %d - %s\n", errno, strerror(errno));
+ close(ret_fd);
+ return 0;
+ }
+
+ if(listen(ret_fd, 10) != 0) {
+ fprintf(stderr, "X11.app: Failed to listen to socket: %s - %d - %s\n", filename_out, errno, strerror(errno));
+ close(ret_fd);
+ return 0;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "X11.app: Listening on socket for fd handoff: (%d) %s\n", ret_fd, filename_out);
+#endif
+
+ return ret_fd;
+ }
+
+ return 0;
+}
+
+static int launchd_socket_handed_off = 0;
+
+kern_return_t do_request_fd_handoff_socket(mach_port_t port, string_t filename) {
+ socket_handoff_t *handoff_data;
+
+ launchd_socket_handed_off = 1;
+
+ handoff_data = (socket_handoff_t *)calloc(1,sizeof(socket_handoff_t));
+ if(!handoff_data) {
+ fprintf(stderr, "X11.app: Error allocating memory for handoff_data\n");
+ return KERN_FAILURE;
+ }
+
+ handoff_data->fd = create_socket(handoff_data->filename);
+ if(!handoff_data->fd) {
+ free(handoff_data);
+ return KERN_FAILURE;
+ }
+
+ strlcpy(filename, handoff_data->filename, STRING_T_SIZE);
+
+ create_thread(socket_handoff_thread, handoff_data);
+
+#ifdef DEBUG
+ fprintf(stderr, "X11.app: Thread created for handoff. Returning success to tell caller to connect and push the fd.\n");
+#endif
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t do_request_pid(mach_port_t port, int *my_pid) {
+ *my_pid = getpid();
+ return KERN_SUCCESS;
+}
+
+/*** Server Startup ***/
+kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv,
+ mach_msg_type_number_t argvCnt,
+ string_array_t envp,
+ mach_msg_type_number_t envpCnt) {
+ /* And now back to char ** */
+ char **_argv = alloca((argvCnt + 1) * sizeof(char *));
+ char **_envp = alloca((envpCnt + 1) * sizeof(char *));
+ size_t i;
+
+ /* If we didn't get handed a launchd DISPLAY socket, we should
+ * unset DISPLAY or we can run into problems with pbproxy
+ */
+ if(!launchd_socket_handed_off) {
+ fprintf(stderr, "X11.app: No launchd socket handed off, unsetting DISPLAY\n");
+ unsetenv("DISPLAY");
+ }
+
+ if(!_argv || !_envp) {
+ return KERN_FAILURE;
+ }
+
+ fprintf(stderr, "X11.app: do_start_x11_server(): argc=%d\n", argvCnt);
+ for(i=0; i < argvCnt; i++) {
+ _argv[i] = argv[i];
+ fprintf(stderr, "\targv[%u] = %s\n", (unsigned)i, argv[i]);
+ }
+ _argv[argvCnt] = NULL;
+
+ for(i=0; i < envpCnt; i++) {
+ _envp[i] = envp[i];
+ }
+ _envp[envpCnt] = NULL;
+
+ if(server_main(argvCnt, _argv, _envp) == 0)
+ return KERN_SUCCESS;
+ else
+ return KERN_FAILURE;
+}
+
+static int startup_trigger(int argc, char **argv, char **envp) {
+ Display *display;
+ const char *s;
+
+ /* Take care of the case where we're called like a normal DDX */
+ if(argc > 1 && argv[1][0] == ':') {
+ size_t i;
+ kern_return_t kr;
+ mach_port_t mp;
+ string_array_t newenvp;
+ string_array_t newargv;
+
+ /* We need to count envp */
+ int envpc;
+ for(envpc=0; envp[envpc]; envpc++);
+
+ /* We have fixed-size string lengths due to limitations in IPC,
+ * so we need to copy our argv and envp.
+ */
+ newargv = (string_array_t)alloca(argc * sizeof(string_t));
+ newenvp = (string_array_t)alloca(envpc * sizeof(string_t));
+
+ if(!newargv || !newenvp) {
+ fprintf(stderr, "Memory allocation failure\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for(i=0; i < argc; i++) {
+ strlcpy(newargv[i], argv[i], STRING_T_SIZE);
+ }
+ for(i=0; i < envpc; i++) {
+ strlcpy(newenvp[i], envp[i], STRING_T_SIZE);
+ }
+
+ kr = bootstrap_look_up(bootstrap_port, server_bootstrap_name, &mp);
+ if (kr != KERN_SUCCESS) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ fprintf(stderr, "bootstrap_look_up(%s): %s\n", server_bootstrap_name, bootstrap_strerror(kr));
+#else
+ fprintf(stderr, "bootstrap_look_up(%s): %ul\n", server_bootstrap_name, (unsigned long)kr);
+#endif
+ exit(EXIT_FAILURE);
+ }
+
+ kr = start_x11_server(mp, newargv, argc, newenvp, envpc);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "start_x11_server: %s\n", mach_error_string(kr));
+ exit(EXIT_FAILURE);
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ /* If we have a process serial number and it's our only arg, act as if
+ * the user double clicked the app bundle: launch app_to_run if possible
+ */
+ if(argc == 1 || (argc == 2 && !strncmp(argv[1], "-psn_", 5))) {
+ /* Now, try to open a display, if so, run the launcher */
+ display = XOpenDisplay(NULL);
+ if(display) {
+ /* Could open the display, start the launcher */
+ XCloseDisplay(display);
+
+ return execute(command_from_prefs("app_to_run", DEFAULT_CLIENT));
+ }
+ }
+
+ /* Start the server */
+ if((s = getenv("DISPLAY"))) {
+ fprintf(stderr, "X11.app: Could not connect to server (DISPLAY=\"%s\", unsetting). Starting X server.\n", s);
+ unsetenv("DISPLAY");
+ } else {
+ fprintf(stderr, "X11.app: Could not connect to server (DISPLAY is not set). Starting X server.\n");
+ }
+ return execute(command_from_prefs("startx_script", DEFAULT_STARTX));
+}
+
+/** Setup the environment we want our child processes to inherit */
+static void ensure_path(const char *dir) {
+ char buf[1024], *temp;
+
+ /* Make sure /usr/X11/bin is in the $PATH */
+ temp = getenv("PATH");
+ if(temp == NULL || temp[0] == 0) {
+ snprintf(buf, sizeof(buf), "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:%s", dir);
+ setenv("PATH", buf, TRUE);
+ } else if(strnstr(temp, X11BINDIR, sizeof(temp)) == NULL) {
+ snprintf(buf, sizeof(buf), "%s:%s", temp, dir);
+ setenv("PATH", buf, TRUE);
+ }
+}
+
+static void setup_env(void) {
+ char *temp;
+ const char *pds = NULL;
+ const char *disp = getenv("DISPLAY");
+ size_t len;
+
+ /* Pass on our prefs domain to startx and its inheritors (mainly for
+ * quartz-wm and the Xquartz stub's MachIPC)
+ */
+ CFBundleRef bundle = CFBundleGetMainBundle();
+ if(bundle) {
+ CFStringRef pd = CFBundleGetIdentifier(bundle);
+ if(pd) {
+ pds = CFStringGetCStringPtr(pd, 0);
+ }
+ }
+
+ /* fallback to hardcoded value if we can't discover it */
+ if(!pds) {
+ pds = LAUNCHD_ID_PREFIX".X11";
+ }
+
+ server_bootstrap_name = malloc(sizeof(char) * (strlen(pds) + 1));
+ if(!server_bootstrap_name) {
+ fprintf(stderr, "X11.app: Memory allocation error.\n");
+ exit(1);
+ }
+ strcpy(server_bootstrap_name, pds);
+ setenv("X11_PREFS_DOMAIN", server_bootstrap_name, 1);
+
+ len = strlen(server_bootstrap_name);
+ launchd_id_prefix = malloc(sizeof(char) * (len - 3));
+ if(!launchd_id_prefix) {
+ fprintf(stderr, "X11.app: Memory allocation error.\n");
+ exit(1);
+ }
+ strlcpy(launchd_id_prefix, server_bootstrap_name, len - 3);
+
+ /* We need to unset DISPLAY if it is not our socket */
+ if(disp) {
+ /* s = basename(disp) */
+ const char *d, *s;
+ for(s = NULL, d = disp; *d; d++) {
+ if(*d == '/')
+ s = d + 1;
+ }
+
+ if(s && *s) {
+ if(strcmp(launchd_id_prefix, "org.x") == 0 && strcmp(s, ":0") == 0) {
+ fprintf(stderr, "X11.app: Detected old style launchd DISPLAY, please update xinit.\n");
+ } else {
+ temp = (char *)malloc(sizeof(char) * len);
+ if(!temp) {
+ fprintf(stderr, "X11.app: Memory allocation error creating space for socket name test.\n");
+ exit(1);
+ }
+ strlcpy(temp, launchd_id_prefix, len);
+ strlcat(temp, ":0", len);
+
+ if(strcmp(temp, s) != 0) {
+ /* If we don't have a match, unset it. */
+ fprintf(stderr, "X11.app: DISPLAY (\"%s\") does not match our id (\"%s\"), unsetting.\n", disp, launchd_id_prefix);
+ unsetenv("DISPLAY");
+ }
+ free(temp);
+ }
+ } else {
+ /* The DISPLAY environment variable is not formatted like a launchd socket, so reset. */
+ fprintf(stderr, "X11.app: DISPLAY does not look like a launchd set variable, unsetting.\n");
+ unsetenv("DISPLAY");
+ }
+ }
+
+ /* Make sure PATH is right */
+ ensure_path(X11BINDIR);
+
+ /* cd $HOME */
+ temp = getenv("HOME");
+ if(temp != NULL && temp[0] != '\0')
+ chdir(temp);
+}
+
+/*** Main ***/
+int main(int argc, char **argv, char **envp) {
+ Bool listenOnly = FALSE;
+ int i;
+ mach_msg_size_t mxmsgsz = sizeof(union MaxMsgSize) + MAX_TRAILER_SIZE;
+ mach_port_t mp;
+ kern_return_t kr;
+
+ /* Setup our environment for our children */
+ setup_env();
+
+ /* The server must not run the PanoramiX operations. */
+ noPanoramiXExtension = TRUE;
+
+ /* Setup the initial crasherporter info */
+ strlcpy(__crashreporter_info_buff__, __crashreporter_info__base, sizeof(__crashreporter_info_buff__));
+
+ fprintf(stderr, "X11.app: main(): argc=%d\n", argc);
+ for(i=0; i < argc; i++) {
+ fprintf(stderr, "\targv[%u] = %s\n", (unsigned)i, argv[i]);
+ if(!strcmp(argv[i], "--listenonly")) {
+ listenOnly = TRUE;
+ }
+ }
+
+ mp = checkin_or_register(server_bootstrap_name);
+ if(mp == MACH_PORT_NULL) {
+ fprintf(stderr, "NULL mach service: %s", server_bootstrap_name);
+ return EXIT_FAILURE;
+ }
+
+ /* Check if we need to do something other than listen, and make another
+ * thread handle it.
+ */
+ if(!listenOnly) {
+ pid_t child1, child2;
+ int status;
+
+ /* Do the fork-twice trick to avoid having to reap zombies */
+ child1 = fork();
+ switch (child1) {
+ case -1: /* error */
+ break;
+
+ case 0: /* child1 */
+ child2 = fork();
+
+ switch (child2) {
+ int max_files, i;
+
+ case -1: /* error */
+ break;
+
+ case 0: /* child2 */
+ /* close all open files except for standard streams */
+ max_files = sysconf(_SC_OPEN_MAX);
+ for(i = 3; i < max_files; i++)
+ close(i);
+
+ /* ensure stdin is on /dev/null */
+ close(0);
+ open("/dev/null", O_RDONLY);
+
+ return startup_trigger(argc, argv, envp);
+
+ default: /* parent (child1) */
+ _exit(0);
+ }
+ break;
+
+ default: /* parent */
+ waitpid(child1, &status, 0);
+ }
+ }
+
+ /* Main event loop */
+ fprintf(stderr, "Waiting for startup parameters via Mach IPC.\n");
+ kr = mach_msg_server(mach_startup_server, mxmsgsz, mp, 0);
+ if (kr != KERN_SUCCESS) {
+ fprintf(stderr, "%s.X11(mp): %s\n", LAUNCHD_ID_PREFIX, mach_error_string(kr));
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int execute(const char *command) {
+ const char *newargv[4];
+ const char **p;
+
+ newargv[0] = command_from_prefs("login_shell", DEFAULT_SHELL);
+ newargv[1] = "-c";
+ newargv[2] = command;
+ newargv[3] = NULL;
+
+ fprintf(stderr, "X11.app: Launching %s:\n", command);
+ for(p=newargv; *p; p++) {
+ fprintf(stderr, "\targv[%ld] = %s\n", (long int)(p - newargv), *p);
+ }
+
+ execvp (newargv[0], (char * const *) newargv);
+ perror ("X11.app: Couldn't exec.");
+ return 1;
+}
+
+static char *command_from_prefs(const char *key, const char *default_value) {
+ char *command = NULL;
+
+ CFStringRef cfKey;
+ CFPropertyListRef PlistRef;
+
+ if(!key)
+ return NULL;
+
+ cfKey = CFStringCreateWithCString(NULL, key, kCFStringEncodingASCII);
+
+ if(!cfKey)
+ return NULL;
+
+ PlistRef = CFPreferencesCopyAppValue(cfKey, kCFPreferencesCurrentApplication);
+
+ if ((PlistRef == NULL) || (CFGetTypeID(PlistRef) != CFStringGetTypeID())) {
+ CFStringRef cfDefaultValue = CFStringCreateWithCString(NULL, default_value, kCFStringEncodingASCII);
+ int len = strlen(default_value) + 1;
+
+ if(!cfDefaultValue)
+ goto command_from_prefs_out;
+
+ CFPreferencesSetAppValue(cfKey, cfDefaultValue, kCFPreferencesCurrentApplication);
+ CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
+ CFRelease(cfDefaultValue);
+
+ command = (char *)malloc(len * sizeof(char));
+ if(!command)
+ goto command_from_prefs_out;
+ strcpy(command, default_value);
+ } else {
+ int len = CFStringGetLength((CFStringRef)PlistRef) + 1;
+ command = (char *)malloc(len * sizeof(char));
+ if(!command)
+ goto command_from_prefs_out;
+ CFStringGetCString((CFStringRef)PlistRef, command, len, kCFStringEncodingASCII);
+ }
+
+command_from_prefs_out:
+ if (PlistRef)
+ CFRelease(PlistRef);
+ if(cfKey)
+ CFRelease(cfKey);
+ return command;
+}
diff --git a/xorg-server/hw/xquartz/pseudoramiX.c b/xorg-server/hw/xquartz/pseudoramiX.c
index 1a357528c..ded242d07 100644
--- a/xorg-server/hw/xquartz/pseudoramiX.c
+++ b/xorg-server/hw/xquartz/pseudoramiX.c
@@ -255,9 +255,9 @@ static int ProcPseudoramiXGetScreenSize(ClientPtr client)
rep.sequenceNumber = client->sequence;
/* screen dimensions */
rep.width = pseudoramiXScreens[stuff->screen].w;
- // was panoramiXdataPtr[stuff->screen].width;
+ // was screenInfo.screens[stuff->screen]->width;
rep.height = pseudoramiXScreens[stuff->screen].h;
- // was panoramiXdataPtr[stuff->screen].height;
+ // was screenInfo.screens[stuff->screen]->height;
if (client->swapped) {
swaps (&rep.sequenceNumber, n);
swapl (&rep.length, n);
diff --git a/xorg-server/hw/xquartz/quartz.c b/xorg-server/hw/xquartz/quartz.c
index e073b0586..c7a4d018a 100644
--- a/xorg-server/hw/xquartz/quartz.c
+++ b/xorg-server/hw/xquartz/quartz.c
@@ -73,8 +73,7 @@ int quartzUseAGL = 1;
int quartzEnableKeyEquivalents = 1;
int quartzServerVisible = FALSE;
int quartzServerQuitting = FALSE;
-static int quartzScreenKeyIndex;
-DevPrivateKey quartzScreenKey = &quartzScreenKeyIndex;
+DevPrivateKeyRec quartzScreenKeyRec;
int aquaMenuBarHeight = 0;
QuartzModeProcsPtr quartzProcs = NULL;
const char *quartzOpenGLBundle = NULL;
@@ -167,6 +166,9 @@ void QuartzInitOutput(
FatalError("Could not register block and wakeup handlers.");
}
+ if (!dixRegisterPrivateKey(&quartzScreenKeyRec, PRIVATE_SCREEN, 0))
+ FatalError("Failed to alloc quartz screen private.\n");
+
#if defined(RANDR) && !defined(FAKE_RANDR)
if(!QuartzRandRInit(pScreen))
FatalError("Failed to init RandR extension.\n");
@@ -259,8 +261,8 @@ void QuartzUpdateScreens(void) {
PseudoramiXResetScreens();
quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height);
- dixScreenOrigins[pScreen->myNum].x = x;
- dixScreenOrigins[pScreen->myNum].y = y;
+ pScreen->x = x;
+ pScreen->y = y;
pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width);
pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height);
pScreen->width = width;
@@ -269,14 +271,14 @@ void QuartzUpdateScreens(void) {
DarwinAdjustScreenOrigins(&screenInfo);
quartzProcs->UpdateScreen(pScreen);
- /* DarwinAdjustScreenOrigins or UpdateScreen may change dixScreenOrigins,
+ /* DarwinAdjustScreenOrigins or UpdateScreen may change pScreen->x/y,
* so use it rather than x/y
*/
- sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+ sx = pScreen->x + darwinMainScreenX;
+ sy = pScreen->y + darwinMainScreenY;
/* Adjust the root window. */
- pRoot = WindowTable[pScreen->myNum];
+ pRoot = pScreen->root;
AppleWMSetScreenOrigin(pRoot);
pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL);
miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
@@ -292,7 +294,7 @@ void QuartzUpdateScreens(void) {
inputInfo.pointer->spriteInfo->sprite->physLimits = bounds;
inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds;
- DEBUG_LOG("Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n", width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY, x, y, dixScreenOrigins[pScreen->myNum].x, dixScreenOrigins[pScreen->myNum].y);
+ DEBUG_LOG("Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n", width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY, x, y, pScreen->x, pScreen->y);
/* Send an event for the root reconfigure */
e.u.u.type = ConfigureNotify;
diff --git a/xorg-server/hw/xquartz/quartzCommon.h b/xorg-server/hw/xquartz/quartzCommon.h
index 8ab70f22a..12ed4057e 100644
--- a/xorg-server/hw/xquartz/quartzCommon.h
+++ b/xorg-server/hw/xquartz/quartzCommon.h
@@ -1,85 +1,86 @@
-/*
- * quartzCommon.h
- *
- * Common definitions used internally by all Quartz modes
- *
- * This file should be included before any X11 or IOKit headers
- * so that it can avoid symbol conflicts.
- *
- * Copyright (c) 2001-2004 Torrey T. Lyons and Greg Parker.
- * 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.
- */
-
-#ifndef _QUARTZCOMMON_H
-#define _QUARTZCOMMON_H
-
-#include <X11/Xdefs.h>
-#include "privates.h"
-
-// Quartz specific per screen storage structure
-typedef struct {
- // List of CoreGraphics displays that this X11 screen covers.
- // This is more than one CG display for video mirroring and
- // rootless PseudoramiX mode.
- // No CG display will be covered by more than one X11 screen.
- int displayCount;
- CGDirectDisplayID *displayIDs;
-} QuartzScreenRec, *QuartzScreenPtr;
-
-#define QUARTZ_PRIV(pScreen) \
- ((QuartzScreenPtr)dixLookupPrivate(&pScreen->devPrivates, quartzScreenKey))
-
-// Data stored at startup for Cocoa front end
-extern int quartzEventWriteFD;
-
-// User preferences used by Quartz modes
-extern int quartzUseSysBeep;
-extern int focusOnNewWindow;
-extern int quartzUseAGL;
-extern int quartzEnableKeyEquivalents;
-extern int quartzFullscreenDisableHotkeys;
-extern int quartzOptionSendsAlt;
-
-// Other shared data
-extern int quartzServerVisible;
-extern int quartzServerQuitting;
-extern DevPrivateKey quartzScreenKey;
-extern int aquaMenuBarHeight;
-
-// Name of GLX bundle for native OpenGL
-extern const char *quartzOpenGLBundle;
-
-void QuartzReadPreferences(void);
-void QuartzMessageMainThread(unsigned msg, void *data, unsigned length);
-void QuartzMessageServerThread(int type, int argc, ...);
-void QuartzSetWindowMenu(int nitems, const char **items,
- const char *shortcuts);
-void QuartzFSCapture(void);
-void QuartzFSRelease(void);
-int QuartzFSUseQDCursor(int depth);
-void QuartzBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask);
-void QuartzWakeupHandler(pointer blockData, int result, pointer pReadmask);
-
-#endif /* _QUARTZCOMMON_H */
+/*
+ * quartzCommon.h
+ *
+ * Common definitions used internally by all Quartz modes
+ *
+ * This file should be included before any X11 or IOKit headers
+ * so that it can avoid symbol conflicts.
+ *
+ * Copyright (c) 2001-2004 Torrey T. Lyons and Greg Parker.
+ * 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.
+ */
+
+#ifndef _QUARTZCOMMON_H
+#define _QUARTZCOMMON_H
+
+#include <X11/Xdefs.h>
+#include "privates.h"
+
+// Quartz specific per screen storage structure
+typedef struct {
+ // List of CoreGraphics displays that this X11 screen covers.
+ // This is more than one CG display for video mirroring and
+ // rootless PseudoramiX mode.
+ // No CG display will be covered by more than one X11 screen.
+ int displayCount;
+ CGDirectDisplayID *displayIDs;
+} QuartzScreenRec, *QuartzScreenPtr;
+
+#define QUARTZ_PRIV(pScreen) \
+ ((QuartzScreenPtr)dixLookupPrivate(&pScreen->devPrivates, quartzScreenKey))
+
+// Data stored at startup for Cocoa front end
+extern int quartzEventWriteFD;
+
+// User preferences used by Quartz modes
+extern int quartzUseSysBeep;
+extern int focusOnNewWindow;
+extern int quartzUseAGL;
+extern int quartzEnableKeyEquivalents;
+extern int quartzFullscreenDisableHotkeys;
+extern int quartzOptionSendsAlt;
+
+// Other shared data
+extern int quartzServerVisible;
+extern int quartzServerQuitting;
+extern DevPrivateKeyRec quartzScreenKeyRec;
+#define quartzScreenKey (&quartzScreenKeyRec)
+extern int aquaMenuBarHeight;
+
+// Name of GLX bundle for native OpenGL
+extern const char *quartzOpenGLBundle;
+
+void QuartzReadPreferences(void);
+void QuartzMessageMainThread(unsigned msg, void *data, unsigned length);
+void QuartzMessageServerThread(int type, int argc, ...);
+void QuartzSetWindowMenu(int nitems, const char **items,
+ const char *shortcuts);
+void QuartzFSCapture(void);
+void QuartzFSRelease(void);
+int QuartzFSUseQDCursor(int depth);
+void QuartzBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask);
+void QuartzWakeupHandler(pointer blockData, int result, pointer pReadmask);
+
+#endif /* _QUARTZCOMMON_H */
diff --git a/xorg-server/hw/xquartz/quartzKeyboard.c b/xorg-server/hw/xquartz/quartzKeyboard.c
index 745333f03..8ea198cd5 100644
--- a/xorg-server/hw/xquartz/quartzKeyboard.c
+++ b/xorg-server/hw/xquartz/quartzKeyboard.c
@@ -1,850 +1,858 @@
-/*
- quartzKeyboard.c: Keyboard support for Xquartz
-
- Copyright (c) 2003-2008 Apple Inc.
- Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved.
- Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
-
- Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "sanitizedCarbon.h"
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#define HACK_MISSING 1
-#define HACK_KEYPAD 1
-#define HACK_BLACKLIST 1
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <AvailabilityMacros.h>
-
-#include "quartzCommon.h"
-#include "darwin.h"
-#include "darwinEvents.h"
-
-#include "quartzKeyboard.h"
-#include "quartzAudio.h"
-
-#include "X11Application.h"
-
-#include "threadSafety.h"
-
-#ifdef NDEBUG
-#undef NDEBUG
-#include <assert.h>
-#define NDEBUG 1
-#else
-#include <assert.h>
-#endif
-#include <pthread.h>
-
-#include "xkbsrv.h"
-#include "exevents.h"
-#include "X11/keysym.h"
-#include "keysym2ucs.h"
-
-extern void
-CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
-
-enum {
- MOD_COMMAND = 256,
- MOD_SHIFT = 512,
- MOD_OPTION = 2048,
- MOD_CONTROL = 4096,
-};
-
-#define UKEYSYM(u) ((u) | 0x01000000)
-
-#if HACK_MISSING
-/* Table of keycode->keysym mappings we use to fallback on for important
- keys that are often not in the Unicode mapping. */
-
-const static struct {
- unsigned short keycode;
- KeySym keysym;
-} known_keys[] = {
- {55, XK_Meta_L},
- {56, XK_Shift_L},
- {57, XK_Caps_Lock},
- {58, XK_Alt_L},
- {59, XK_Control_L},
-
- {60, XK_Shift_R},
- {61, XK_Alt_R},
- {62, XK_Control_R},
- {63, XK_Meta_R},
-
- {122, XK_F1},
- {120, XK_F2},
- {99, XK_F3},
- {118, XK_F4},
- {96, XK_F5},
- {97, XK_F6},
- {98, XK_F7},
- {100, XK_F8},
- {101, XK_F9},
- {109, XK_F10},
- {103, XK_F11},
- {111, XK_F12},
- {105, XK_F13},
- {107, XK_F14},
- {113, XK_F15},
-};
-#endif
-
-#if HACK_KEYPAD
-/* Table of keycode->old,new-keysym mappings we use to fixup the numeric
- keypad entries. */
-
-const static struct {
- unsigned short keycode;
- KeySym normal, keypad;
-} known_numeric_keys[] = {
- {65, XK_period, XK_KP_Decimal},
- {67, XK_asterisk, XK_KP_Multiply},
- {69, XK_plus, XK_KP_Add},
- {75, XK_slash, XK_KP_Divide},
- {76, 0x01000003, XK_KP_Enter},
- {78, XK_minus, XK_KP_Subtract},
- {81, XK_equal, XK_KP_Equal},
- {82, XK_0, XK_KP_0},
- {83, XK_1, XK_KP_1},
- {84, XK_2, XK_KP_2},
- {85, XK_3, XK_KP_3},
- {86, XK_4, XK_KP_4},
- {87, XK_5, XK_KP_5},
- {88, XK_6, XK_KP_6},
- {89, XK_7, XK_KP_7},
- {91, XK_8, XK_KP_8},
- {92, XK_9, XK_KP_9},
-};
-#endif
-
-#if HACK_BLACKLIST
-/* <rdar://problem/7824370> wine notepad produces wrong characters on shift+arrow
- * http://xquartz.macosforge.org/trac/ticket/295
- * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html
- *
- * legacy Mac keycodes for arrow keys that shift-modify to math symbols
- */
-const static unsigned short keycode_blacklist[] = {66, 70, 72, 77};
-#endif
-
-/* Table mapping normal keysyms to their dead equivalents.
- FIXME: all the unicode keysyms (apart from circumflex) were guessed. */
-
-const static struct {
- KeySym normal, dead;
-} dead_keys[] = {
- {XK_grave, XK_dead_grave},
- {XK_apostrophe, XK_dead_acute}, /* US:"=" on a Czech keyboard */
- {XK_acute, XK_dead_acute},
- {UKEYSYM (0x384), XK_dead_acute}, /* US:";" on a Greek keyboard */
-// {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */
- {XK_asciicircum, XK_dead_circumflex},
- {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
- {XK_asciitilde, XK_dead_tilde},
- {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */
- {XK_macron, XK_dead_macron},
- {XK_breve, XK_dead_breve},
- {XK_abovedot, XK_dead_abovedot},
- {XK_diaeresis, XK_dead_diaeresis},
- {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */
- {XK_doubleacute, XK_dead_doubleacute},
- {XK_caron, XK_dead_caron},
- {XK_cedilla, XK_dead_cedilla},
- {XK_ogonek, XK_dead_ogonek},
- {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */
- {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */
-/* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */
- {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */
- {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */
- {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */
-};
-
-typedef struct darwinKeyboardInfo_struct {
- CARD8 modMap[MAP_LENGTH];
- KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY];
- unsigned char modifierKeycodes[32][2];
-} darwinKeyboardInfo;
-
-darwinKeyboardInfo keyInfo;
-pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-static void DarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl) {
- // FIXME: to be implemented
- // keyclick, bell volume / pitch, autorepead, LED's
-}
-
-//-----------------------------------------------------------------------------
-// Utility functions to help parse Darwin keymap
-//-----------------------------------------------------------------------------
-
-/*
- * DarwinBuildModifierMaps
- * Use the keyMap field of keyboard info structure to populate
- * the modMap and modifierKeycodes fields.
- */
-static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
- int i;
- KeySym *k;
-
- memset(info->modMap, NoSymbol, sizeof(info->modMap));
- memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes));
-
- for (i = 0; i < NUM_KEYCODES; i++) {
- k = info->keyMap + i * GLYPHS_PER_KEY;
-
- switch (*k) {
- case XK_Shift_L:
- info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
- info->modMap[MIN_KEYCODE + i] = ShiftMask;
- break;
-
- case XK_Shift_R:
-#ifdef NX_MODIFIERKEY_RSHIFT
- info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i;
-#else
- info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
-#endif
- info->modMap[MIN_KEYCODE + i] = ShiftMask;
- break;
-
- case XK_Control_L:
- info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
- info->modMap[MIN_KEYCODE + i] = ControlMask;
- break;
-
- case XK_Control_R:
-#ifdef NX_MODIFIERKEY_RCONTROL
- info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i;
-#else
- info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
-#endif
- info->modMap[MIN_KEYCODE + i] = ControlMask;
- break;
-
- case XK_Caps_Lock:
- info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
- info->modMap[MIN_KEYCODE + i] = LockMask;
- break;
-
- case XK_Alt_L:
- info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
- info->modMap[MIN_KEYCODE + i] = Mod1Mask;
- if(!quartzOptionSendsAlt)
- *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
- break;
-
- case XK_Alt_R:
-#ifdef NX_MODIFIERKEY_RALTERNATE
- info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
-#else
- info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
-#endif
- if(!quartzOptionSendsAlt)
- *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
- info->modMap[MIN_KEYCODE + i] = Mod1Mask;
- break;
-
- case XK_Mode_switch:
- ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n");
- info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
-#ifdef NX_MODIFIERKEY_RALTERNATE
- info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
-#endif
- info->modMap[MIN_KEYCODE + i] = Mod1Mask;
- break;
-
- case XK_Meta_L:
- info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
- info->modMap[MIN_KEYCODE + i] = Mod2Mask;
- break;
-
- case XK_Meta_R:
-#ifdef NX_MODIFIERKEY_RCOMMAND
- info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i;
-#else
- info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
-#endif
- info->modMap[MIN_KEYCODE + i] = Mod2Mask;
- break;
-
- case XK_Num_Lock:
- info->modMap[MIN_KEYCODE + i] = Mod3Mask;
- break;
- }
- }
-}
-
-/*
- * DarwinKeyboardInit
- * Get the Darwin keyboard map and compute an equivalent
- * X keyboard map and modifier map. Set the new keyboard
- * device structure.
- */
-void DarwinKeyboardInit(DeviceIntPtr pDev) {
- // Open a shared connection to the HID System.
- // Note that the Event Status Driver is really just a wrapper
- // for a kIOHIDParamConnectType connection.
- assert(darwinParamConnect = NXOpenEventStatus());
-
- InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl);
-
- DarwinKeyboardReloadHandler();
-
- CopyKeyClass(pDev, inputInfo.keyboard);
-}
-
-/* Set the repeat rates based on global preferences and keycodes for modifiers.
- * Precondition: Has the keyInfo_mutex lock.
- */
-static void DarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue, int keyRepeatValue) {
- if(initialKeyRepeatValue == 300000) { // off
- /* Turn off repeats globally */
- XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff);
- } else {
- int i;
- XkbControlsPtr ctrl;
- XkbControlsRec old;
-
- /* Turn on repeats globally */
- XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn);
-
- /* Setup the bit mask for individual key repeats */
- ctrl = pDev->key->xkbInfo->desc->ctrls;
- old= *ctrl;
-
- ctrl->repeat_delay = initialKeyRepeatValue * 15;
- ctrl->repeat_interval = keyRepeatValue * 15;
-
- /* Turn off key-repeat for modifier keys, on for others */
- /* First set them all on */
- for(i=0; i < XkbPerKeyBitArraySize; i++)
- ctrl->per_key_repeat[i] = -1;
-
- /* Now turn off the modifiers */
- for(i=0; i < 32; i++) {
- unsigned char keycode;
-
- keycode = keyInfo.modifierKeycodes[i][0];
- if(keycode)
- ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE);
-
- keycode = keyInfo.modifierKeycodes[i][1];
- if(keycode)
- ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE);
- }
-
- /* Hurray for data duplication */
- if (pDev->kbdfeed)
- memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat, XkbPerKeyBitArraySize);
-
- //fprintf(stderr, "per_key_repeat =\n");
- //for(i=0; i < XkbPerKeyBitArraySize; i++)
- // fprintf(stderr, "%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n");
-
- /* And now we notify the puppies about the changes */
- XkbDDXChangeControls(pDev, &old, ctrl);
- }
-}
-
-void DarwinKeyboardReloadHandler(void) {
- KeySymsRec keySyms;
- CFIndex initialKeyRepeatValue, keyRepeatValue;
- BOOL ok;
- DeviceIntPtr pDev;
- const char *xmodmap = PROJECTROOT "/bin/xmodmap";
- const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap";
- const char *homedir = getenv("HOME");
- char usermodmap[PATH_MAX], cmd[PATH_MAX];
-
- DEBUG_LOG("DarwinKeyboardReloadHandler\n");
-
- /* Get our key repeat settings from GlobalPreferences */
- (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences"));
-
- initialKeyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"), CFSTR(".GlobalPreferences"), &ok);
- if(!ok)
- initialKeyRepeatValue = 35;
-
- keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("KeyRepeat"), CFSTR(".GlobalPreferences"), &ok);
- if(!ok)
- keyRepeatValue = 6;
-
- pthread_mutex_lock(&keyInfo_mutex); {
- /* Initialize our keySyms */
- keySyms.map = keyInfo.keyMap;
- keySyms.mapWidth = GLYPHS_PER_KEY;
- keySyms.minKeyCode = MIN_KEYCODE;
- keySyms.maxKeyCode = MAX_KEYCODE;
-
- // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap
- /* Apply the mappings to darwinKeyboard */
- XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode,
- keySyms.maxKeyCode - keySyms.minKeyCode + 1,
- keyInfo.modMap, serverClient);
- DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue, keyRepeatValue);
-
- /* Apply the mappings to the core keyboard */
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
- if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
- XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode,
- keySyms.maxKeyCode - keySyms.minKeyCode + 1,
- keyInfo.modMap, serverClient);
- DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue, keyRepeatValue);
- }
- }
- } pthread_mutex_unlock(&keyInfo_mutex);
-
- /* Check for system .Xmodmap */
- if (access(xmodmap, F_OK) == 0) {
- if (access(sysmodmap, F_OK) == 0) {
- snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, sysmodmap);
- X11ApplicationLaunchClient(cmd);
- }
- }
-
- /* Check for user's local .Xmodmap */
- if (homedir != NULL) {
- snprintf (usermodmap, sizeof(usermodmap), "%s/.Xmodmap", homedir);
- if (access(usermodmap, F_OK) == 0) {
- snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, usermodmap);
- X11ApplicationLaunchClient(cmd);
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Modifier translation functions
-//
-// There are three different ways to specify a Mac modifier key:
-// keycode - specifies hardware key, read from keymapping
-// key - NX_MODIFIERKEY_*, really an index
-// mask - NX_*MASK, mask for modifier flags in event record
-// Left and right side have different keycodes but the same key and mask.
-//-----------------------------------------------------------------------------
-
-/*
- * DarwinModifierNXKeyToNXKeycode
- * Return the keycode for an NX_MODIFIERKEY_* modifier.
- * side = 0 for left or 1 for right.
- * Returns 0 if key+side is not a known modifier.
- */
-int DarwinModifierNXKeyToNXKeycode(int key, int side) {
- int retval;
- pthread_mutex_lock(&keyInfo_mutex);
- retval = keyInfo.modifierKeycodes[key][side];
- pthread_mutex_unlock(&keyInfo_mutex);
-
- return retval;
-}
-
-/*
- * DarwinModifierNXKeycodeToNXKey
- * Returns -1 if keycode+side is not a modifier key
- * outSide may be NULL, else it gets 0 for left and 1 for right.
- */
-int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) {
- int key, side;
-
- keycode += MIN_KEYCODE;
-
- // search modifierKeycodes for this keycode+side
- pthread_mutex_lock(&keyInfo_mutex);
- for (key = 0; key < NX_NUMMODIFIERS; key++) {
- for (side = 0; side <= 1; side++) {
- if (keyInfo.modifierKeycodes[key][side] == keycode) break;
- }
- }
- pthread_mutex_unlock(&keyInfo_mutex);
-
- if (key == NX_NUMMODIFIERS) {
- return -1;
- }
- if (outSide) *outSide = side;
-
- return key;
-}
-
-/*
- * DarwinModifierNXMaskToNXKey
- * Returns -1 if mask is not a known modifier mask.
- */
-int DarwinModifierNXMaskToNXKey(int mask) {
- switch (mask) {
- case NX_ALPHASHIFTMASK: return NX_MODIFIERKEY_ALPHALOCK;
- case NX_SHIFTMASK: return NX_MODIFIERKEY_SHIFT;
-#ifdef NX_DEVICELSHIFTKEYMASK
- case NX_DEVICELSHIFTKEYMASK: return NX_MODIFIERKEY_SHIFT;
- case NX_DEVICERSHIFTKEYMASK: return NX_MODIFIERKEY_RSHIFT;
-#endif
- case NX_CONTROLMASK: return NX_MODIFIERKEY_CONTROL;
-#ifdef NX_DEVICELCTLKEYMASK
- case NX_DEVICELCTLKEYMASK: return NX_MODIFIERKEY_CONTROL;
- case NX_DEVICERCTLKEYMASK: return NX_MODIFIERKEY_RCONTROL;
-#endif
- case NX_ALTERNATEMASK: return NX_MODIFIERKEY_ALTERNATE;
-#ifdef NX_DEVICELALTKEYMASK
- case NX_DEVICELALTKEYMASK: return NX_MODIFIERKEY_ALTERNATE;
- case NX_DEVICERALTKEYMASK: return NX_MODIFIERKEY_RALTERNATE;
-#endif
- case NX_COMMANDMASK: return NX_MODIFIERKEY_COMMAND;
-#ifdef NX_DEVICELCMDKEYMASK
- case NX_DEVICELCMDKEYMASK: return NX_MODIFIERKEY_COMMAND;
- case NX_DEVICERCMDKEYMASK: return NX_MODIFIERKEY_RCOMMAND;
-#endif
- case NX_NUMERICPADMASK: return NX_MODIFIERKEY_NUMERICPAD;
- case NX_HELPMASK: return NX_MODIFIERKEY_HELP;
- case NX_SECONDARYFNMASK: return NX_MODIFIERKEY_SECONDARYFN;
- }
- return -1;
-}
-
-/*
- * DarwinModifierNXKeyToNXMask
- * Returns 0 if key is not a known modifier key.
- */
-int DarwinModifierNXKeyToNXMask(int key) {
- switch (key) {
- case NX_MODIFIERKEY_ALPHALOCK: return NX_ALPHASHIFTMASK;
-#ifdef NX_DEVICELSHIFTKEYMASK
- case NX_MODIFIERKEY_SHIFT: return NX_DEVICELSHIFTKEYMASK;
- case NX_MODIFIERKEY_RSHIFT: return NX_DEVICERSHIFTKEYMASK;
- case NX_MODIFIERKEY_CONTROL: return NX_DEVICELCTLKEYMASK;
- case NX_MODIFIERKEY_RCONTROL: return NX_DEVICERCTLKEYMASK;
- case NX_MODIFIERKEY_ALTERNATE: return NX_DEVICELALTKEYMASK;
- case NX_MODIFIERKEY_RALTERNATE: return NX_DEVICERALTKEYMASK;
- case NX_MODIFIERKEY_COMMAND: return NX_DEVICELCMDKEYMASK;
- case NX_MODIFIERKEY_RCOMMAND: return NX_DEVICERCMDKEYMASK;
-#else
- case NX_MODIFIERKEY_SHIFT: return NX_SHIFTMASK;
- case NX_MODIFIERKEY_CONTROL: return NX_CONTROLMASK;
- case NX_MODIFIERKEY_ALTERNATE: return NX_ALTERNATEMASK;
- case NX_MODIFIERKEY_COMMAND: return NX_COMMANDMASK;
-#endif
- case NX_MODIFIERKEY_NUMERICPAD: return NX_NUMERICPADMASK;
- case NX_MODIFIERKEY_HELP: return NX_HELPMASK;
- case NX_MODIFIERKEY_SECONDARYFN: return NX_SECONDARYFNMASK;
- }
- return 0;
-}
-
-/*
- * DarwinModifierStringToNXMask
- * Returns 0 if string is not a known modifier.
- */
-int DarwinModifierStringToNXMask(const char *str, int separatelr) {
-#ifdef NX_DEVICELSHIFTKEYMASK
- if(separatelr) {
- if (!strcasecmp(str, "shift")) return NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK;
- if (!strcasecmp(str, "control")) return NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK;
- if (!strcasecmp(str, "option")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK;
- if (!strcasecmp(str, "alt")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK;
- if (!strcasecmp(str, "command")) return NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK;
- if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK;
- if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK;
- if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK;
- if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK;
- if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK;
- if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK;
- if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK;
- if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK;
- if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK;
- if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK;
- } else {
-#endif
- if (!strcasecmp(str, "shift")) return NX_SHIFTMASK;
- if (!strcasecmp(str, "control")) return NX_CONTROLMASK;
- if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK;
- if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK;
- if (!strcasecmp(str, "command")) return NX_COMMANDMASK;
- if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK;
- if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK;
- if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK;
- if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK;
- if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK;
- if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK;
- if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK;
- if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK;
- if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK;
- if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK;
-#ifdef NX_DEVICELSHIFTKEYMASK
- }
-#endif
- if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK;
- if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK;
- if (!strcasecmp(str, "help")) return NX_HELPMASK;
- if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK;
- return 0;
-}
-
-/*
- * LegalModifier
- * This allows the ddx layer to prevent some keys from being remapped
- * as modifier keys.
- */
-Bool LegalModifier(unsigned int key, DeviceIntPtr pDev)
-{
- return 1;
-}
-
-static inline UniChar macroman2ucs(unsigned char c) {
- /* Precalculated table mapping MacRoman-128 to Unicode. Generated
- by creating single element CFStringRefs then extracting the
- first character. */
-
- static const unsigned short table[128] = {
- 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
- 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
- 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
- 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
- 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
- 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
- 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
- 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
- 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
- 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
- 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
- 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
- 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
- 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
- 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
- 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
- };
-
- if (c < 128) return c;
- else return table[c - 128];
-}
-
-static KeySym make_dead_key(KeySym in) {
- int i;
-
- for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++)
- if (dead_keys[i].normal == in) return dead_keys[i].dead;
-
- return in;
-}
-
-static Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) {
-#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
- KeyboardLayoutRef key_layout;
- int is_uchr = 1;
-#endif
- const void *chr_data = NULL;
- int num_keycodes = NUM_KEYCODES;
- UInt32 keyboard_type = LMGetKbdType();
- int i, j;
- OSStatus err;
- KeySym *k;
- CFDataRef currentKeyLayoutDataRef = NULL;
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource();
-
- if (currentKeyLayoutRef) {
- currentKeyLayoutDataRef = (CFDataRef )TISGetInputSourceProperty(currentKeyLayoutRef, kTISPropertyUnicodeKeyLayoutData);
- if (currentKeyLayoutDataRef)
- chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef);
- }
-#endif
-
-#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
- if (chr_data == NULL) {
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- ErrorF("X11.app: Error detected in determining keyboard layout. If you are using an Apple-provided keyboard layout, please report this error at http://xquartz.macosforge.org and http://bugreport.apple.com\n");
- ErrorF("X11.app: Debug Info: keyboard_type=%u, currentKeyLayoutRef=%p, currentKeyLayoutDataRef=%p, chr_data=%p\n",
- (unsigned)keyboard_type, currentKeyLayoutRef, currentKeyLayoutDataRef, chr_data);
-#endif
-
- KLGetCurrentKeyboardLayout (&key_layout);
- KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data);
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- if(chr_data != NULL) {
- ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n");
- }
-#endif
- }
-
- if (chr_data == NULL) {
- ErrorF("X11.app: Debug Info: kKLuchrData failed, trying kKLKCHRData.\n");
- ErrorF("If you are using a 3rd party keyboard layout, please see http://xquartz.macosforge.org/trac/ticket/154\n");
- KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data);
- is_uchr = 0;
- num_keycodes = 128;
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- if(chr_data != NULL) {
- ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n");
- }
-#endif
- }
-#endif
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- if(currentKeyLayoutRef)
- CFRelease(currentKeyLayoutRef);
-#endif
-
- if (chr_data == NULL) {
- ErrorF ( "Couldn't get uchr or kchr resource\n");
- return FALSE;
- }
-
- /* Scan the keycode range for the Unicode character that each
- key produces in the four shift states. Then convert that to
- an X11 keysym (which may just the bit that says "this is
- Unicode" if it can't find the real symbol.) */
-
- /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate
- must be used instead. */
-
- for (i = 0; i < num_keycodes; i++) {
- static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION,
- MOD_OPTION | MOD_SHIFT};
-
- k = info->keyMap + i * GLYPHS_PER_KEY;
-
- for (j = 0; j < 4; j++) {
-#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
- if (is_uchr) {
-#endif
- UniChar s[8];
- UniCharCount len;
- UInt32 dead_key_state = 0, extra_dead = 0;
-
- err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
- mods[j] >> 8, keyboard_type, 0,
- &dead_key_state, 8, &len, s);
- if (err != noErr) continue;
-
- if (len == 0 && dead_key_state != 0) {
- /* Found a dead key. Work out which one it is, but
- remembering that it's dead. */
- err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
- mods[j] >> 8, keyboard_type,
- kUCKeyTranslateNoDeadKeysMask,
- &extra_dead, 8, &len, s);
- if (err != noErr) continue;
- }
-
- /* Not sure why 0x0010 is there.
- * 0x0000 - <rdar://problem/7793566> 'Unicode Hex Input' ...
- */
- if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) {
- k[j] = ucs2keysym (s[0]);
- if (dead_key_state != 0) k[j] = make_dead_key (k[j]);
- }
-#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
- } else { // kchr
- UInt32 c, state = 0, state2 = 0;
- UInt16 code;
-
- code = i | mods[j];
- c = KeyTranslate (chr_data, code, &state);
-
- /* Dead keys are only processed on key-down, so ask
- to translate those events. When we find a dead key,
- translating the matching key up event will give
- us the actual dead character. */
-
- if (state != 0)
- c = KeyTranslate (chr_data, code | 128, &state2);
-
- /* Characters seem to be in MacRoman encoding. */
-
- if (c != 0 && c != 0x0010) {
- k[j] = ucs2keysym (macroman2ucs (c & 255));
-
- if (state != 0) k[j] = make_dead_key (k[j]);
- }
- }
-#endif
- }
-
- if (k[3] == k[2]) k[3] = NoSymbol;
- if (k[1] == k[0]) k[1] = NoSymbol;
- if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
- if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol;
- }
-
-#if HACK_MISSING
- /* Fix up some things that are normally missing.. */
-
- for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++) {
- k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY;
-
- if ( k[0] == NoSymbol && k[1] == NoSymbol
- && k[2] == NoSymbol && k[3] == NoSymbol)
- k[0] = known_keys[i].keysym;
- }
-#endif
-
-#if HACK_KEYPAD
- /* And some more things. We find the right symbols for the numeric
- keypad, but not the KP_ keysyms. So try to convert known keycodes. */
- for (i = 0; i < sizeof (known_numeric_keys) / sizeof (known_numeric_keys[0]); i++) {
- k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY;
-
- if (k[0] == known_numeric_keys[i].normal)
- k[0] = known_numeric_keys[i].keypad;
- }
-#endif
-
-#if HACK_BLACKLIST
- for (i = 0; i < sizeof (keycode_blacklist) / sizeof (keycode_blacklist[0]); i++) {
- k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY;
- k[0] = k[1] = k[2] = k[3] = NoSymbol;
- }
-#endif
-
- DarwinBuildModifierMaps(info);
-
- return TRUE;
-}
-
-Bool QuartsResyncKeymap(Bool sendDDXEvent) {
- Bool retval;
- /* Update keyInfo */
- pthread_mutex_lock(&keyInfo_mutex);
- memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap));
- retval = QuartzReadSystemKeymap(&keyInfo);
- pthread_mutex_unlock(&keyInfo_mutex);
-
- /* Tell server thread to deal with new keyInfo */
- if(sendDDXEvent)
- DarwinSendDDXEvent(kXquartzReloadKeymap, 0);
-
- return retval;
-}
+/*
+ quartzKeyboard.c: Keyboard support for Xquartz
+
+ Copyright (c) 2003-2008 Apple Inc.
+ Copyright (c) 2001-2004 Torrey T. Lyons. All Rights Reserved.
+ Copyright 2004 Kaleb S. KEITHLEY. All Rights Reserved.
+
+ Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "sanitizedCarbon.h"
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#define HACK_MISSING 1
+#define HACK_KEYPAD 1
+#define HACK_BLACKLIST 1
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <AvailabilityMacros.h>
+
+#include "quartzCommon.h"
+#include "darwin.h"
+#include "darwinEvents.h"
+
+#include "quartzKeyboard.h"
+#include "quartzAudio.h"
+
+#include "X11Application.h"
+
+#include "threadSafety.h"
+
+#ifdef NDEBUG
+#undef NDEBUG
+#include <assert.h>
+#define NDEBUG 1
+#else
+#include <assert.h>
+#endif
+#include <pthread.h>
+
+#include "xkbsrv.h"
+#include "exevents.h"
+#include "X11/keysym.h"
+#include "keysym2ucs.h"
+
+extern void
+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
+
+enum {
+ MOD_COMMAND = 256,
+ MOD_SHIFT = 512,
+ MOD_OPTION = 2048,
+ MOD_CONTROL = 4096,
+};
+
+#define UKEYSYM(u) ((u) | 0x01000000)
+
+#if HACK_MISSING
+/* Table of keycode->keysym mappings we use to fallback on for important
+ keys that are often not in the Unicode mapping. */
+
+const static struct {
+ unsigned short keycode;
+ KeySym keysym;
+} known_keys[] = {
+ {55, XK_Meta_L},
+ {56, XK_Shift_L},
+ {57, XK_Caps_Lock},
+ {58, XK_Alt_L},
+ {59, XK_Control_L},
+
+ {60, XK_Shift_R},
+ {61, XK_Alt_R},
+ {62, XK_Control_R},
+ {63, XK_Meta_R},
+
+ {122, XK_F1},
+ {120, XK_F2},
+ {99, XK_F3},
+ {118, XK_F4},
+ {96, XK_F5},
+ {97, XK_F6},
+ {98, XK_F7},
+ {100, XK_F8},
+ {101, XK_F9},
+ {109, XK_F10},
+ {103, XK_F11},
+ {111, XK_F12},
+ {105, XK_F13},
+ {107, XK_F14},
+ {113, XK_F15},
+};
+#endif
+
+#if HACK_KEYPAD
+/* Table of keycode->old,new-keysym mappings we use to fixup the numeric
+ keypad entries. */
+
+const static struct {
+ unsigned short keycode;
+ KeySym normal, keypad;
+} known_numeric_keys[] = {
+ {65, XK_period, XK_KP_Decimal},
+ {67, XK_asterisk, XK_KP_Multiply},
+ {69, XK_plus, XK_KP_Add},
+ {75, XK_slash, XK_KP_Divide},
+ {76, 0x01000003, XK_KP_Enter},
+ {78, XK_minus, XK_KP_Subtract},
+ {81, XK_equal, XK_KP_Equal},
+ {82, XK_0, XK_KP_0},
+ {83, XK_1, XK_KP_1},
+ {84, XK_2, XK_KP_2},
+ {85, XK_3, XK_KP_3},
+ {86, XK_4, XK_KP_4},
+ {87, XK_5, XK_KP_5},
+ {88, XK_6, XK_KP_6},
+ {89, XK_7, XK_KP_7},
+ {91, XK_8, XK_KP_8},
+ {92, XK_9, XK_KP_9},
+};
+#endif
+
+#if HACK_BLACKLIST
+/* <rdar://problem/7824370> wine notepad produces wrong characters on shift+arrow
+ * http://xquartz.macosforge.org/trac/ticket/295
+ * http://developer.apple.com/legacy/mac/library/documentation/mac/Text/Text-579.html
+ *
+ * legacy Mac keycodes for arrow keys that shift-modify to math symbols
+ */
+const static unsigned short keycode_blacklist[] = {66, 70, 72, 77};
+#endif
+
+/* Table mapping normal keysyms to their dead equivalents.
+ FIXME: all the unicode keysyms (apart from circumflex) were guessed. */
+
+const static struct {
+ KeySym normal, dead;
+} dead_keys[] = {
+ {XK_grave, XK_dead_grave},
+ {XK_apostrophe, XK_dead_acute}, /* US:"=" on a Czech keyboard */
+ {XK_acute, XK_dead_acute},
+ {UKEYSYM (0x384), XK_dead_acute}, /* US:";" on a Greek keyboard */
+// {XK_Greek_accentdieresis, XK_dead_diaeresis}, /* US:"opt+;" on a Greek keyboard ... replace with dead_accentdieresis if there is one */
+ {XK_asciicircum, XK_dead_circumflex},
+ {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
+ {XK_asciitilde, XK_dead_tilde},
+ {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */
+ {XK_macron, XK_dead_macron},
+ {XK_breve, XK_dead_breve},
+ {XK_abovedot, XK_dead_abovedot},
+ {XK_diaeresis, XK_dead_diaeresis},
+ {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */
+ {XK_doubleacute, XK_dead_doubleacute},
+ {XK_caron, XK_dead_caron},
+ {XK_cedilla, XK_dead_cedilla},
+ {XK_ogonek, XK_dead_ogonek},
+ {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */
+ {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */
+/* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */
+ {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */
+ {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */
+ {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */
+};
+
+typedef struct darwinKeyboardInfo_struct {
+ CARD8 modMap[MAP_LENGTH];
+ KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY];
+ unsigned char modifierKeycodes[32][2];
+} darwinKeyboardInfo;
+
+darwinKeyboardInfo keyInfo;
+pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void DarwinChangeKeyboardControl(DeviceIntPtr device, KeybdCtrl *ctrl) {
+ // FIXME: to be implemented
+ // keyclick, bell volume / pitch, autorepead, LED's
+}
+
+//-----------------------------------------------------------------------------
+// Utility functions to help parse Darwin keymap
+//-----------------------------------------------------------------------------
+
+/*
+ * DarwinBuildModifierMaps
+ * Use the keyMap field of keyboard info structure to populate
+ * the modMap and modifierKeycodes fields.
+ */
+static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
+ int i;
+ KeySym *k;
+
+ memset(info->modMap, NoSymbol, sizeof(info->modMap));
+ memset(info->modifierKeycodes, 0, sizeof(info->modifierKeycodes));
+
+ for (i = 0; i < NUM_KEYCODES; i++) {
+ k = info->keyMap + i * GLYPHS_PER_KEY;
+
+ switch (*k) {
+ case XK_Shift_L:
+ info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
+ info->modMap[MIN_KEYCODE + i] = ShiftMask;
+ break;
+
+ case XK_Shift_R:
+#ifdef NX_MODIFIERKEY_RSHIFT
+ info->modifierKeycodes[NX_MODIFIERKEY_RSHIFT][0] = i;
+#else
+ info->modifierKeycodes[NX_MODIFIERKEY_SHIFT][0] = i;
+#endif
+ info->modMap[MIN_KEYCODE + i] = ShiftMask;
+ break;
+
+ case XK_Control_L:
+ info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
+ info->modMap[MIN_KEYCODE + i] = ControlMask;
+ break;
+
+ case XK_Control_R:
+#ifdef NX_MODIFIERKEY_RCONTROL
+ info->modifierKeycodes[NX_MODIFIERKEY_RCONTROL][0] = i;
+#else
+ info->modifierKeycodes[NX_MODIFIERKEY_CONTROL][0] = i;
+#endif
+ info->modMap[MIN_KEYCODE + i] = ControlMask;
+ break;
+
+ case XK_Caps_Lock:
+ info->modifierKeycodes[NX_MODIFIERKEY_ALPHALOCK][0] = i;
+ info->modMap[MIN_KEYCODE + i] = LockMask;
+ break;
+
+ case XK_Alt_L:
+ info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
+ info->modMap[MIN_KEYCODE + i] = Mod1Mask;
+ if(!quartzOptionSendsAlt)
+ *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
+ break;
+
+ case XK_Alt_R:
+#ifdef NX_MODIFIERKEY_RALTERNATE
+ info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
+#else
+ info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
+#endif
+ if(!quartzOptionSendsAlt)
+ *k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
+ info->modMap[MIN_KEYCODE + i] = Mod1Mask;
+ break;
+
+ case XK_Mode_switch:
+ ErrorF("DarwinBuildModifierMaps: XK_Mode_switch encountered, unable to determine side.\n");
+ info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
+#ifdef NX_MODIFIERKEY_RALTERNATE
+ info->modifierKeycodes[NX_MODIFIERKEY_RALTERNATE][0] = i;
+#endif
+ info->modMap[MIN_KEYCODE + i] = Mod1Mask;
+ break;
+
+ case XK_Meta_L:
+ info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
+ info->modMap[MIN_KEYCODE + i] = Mod2Mask;
+ break;
+
+ case XK_Meta_R:
+#ifdef NX_MODIFIERKEY_RCOMMAND
+ info->modifierKeycodes[NX_MODIFIERKEY_RCOMMAND][0] = i;
+#else
+ info->modifierKeycodes[NX_MODIFIERKEY_COMMAND][0] = i;
+#endif
+ info->modMap[MIN_KEYCODE + i] = Mod2Mask;
+ break;
+
+ case XK_Num_Lock:
+ info->modMap[MIN_KEYCODE + i] = Mod3Mask;
+ break;
+ }
+ }
+}
+
+/*
+ * DarwinKeyboardInit
+ * Get the Darwin keyboard map and compute an equivalent
+ * X keyboard map and modifier map. Set the new keyboard
+ * device structure.
+ */
+void DarwinKeyboardInit(DeviceIntPtr pDev) {
+ // Open a shared connection to the HID System.
+ // Note that the Event Status Driver is really just a wrapper
+ // for a kIOHIDParamConnectType connection.
+ assert(darwinParamConnect = NXOpenEventStatus());
+
+ InitKeyboardDeviceStruct(pDev, NULL, NULL, DarwinChangeKeyboardControl);
+
+ DarwinKeyboardReloadHandler();
+
+ CopyKeyClass(pDev, inputInfo.keyboard);
+}
+
+/* Set the repeat rates based on global preferences and keycodes for modifiers.
+ * Precondition: Has the keyInfo_mutex lock.
+ */
+static void DarwinKeyboardSetRepeat(DeviceIntPtr pDev, int initialKeyRepeatValue, int keyRepeatValue) {
+ if(initialKeyRepeatValue == 300000) { // off
+ /* Turn off repeats globally */
+ XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOff);
+ } else {
+ int i;
+ XkbControlsPtr ctrl;
+ XkbControlsRec old;
+
+ /* Turn on repeats globally */
+ XkbSetRepeatKeys(pDev, -1, AutoRepeatModeOn);
+
+ /* Setup the bit mask for individual key repeats */
+ ctrl = pDev->key->xkbInfo->desc->ctrls;
+ old= *ctrl;
+
+ ctrl->repeat_delay = initialKeyRepeatValue * 15;
+ ctrl->repeat_interval = keyRepeatValue * 15;
+
+ /* Turn off key-repeat for modifier keys, on for others */
+ /* First set them all on */
+ for(i=0; i < XkbPerKeyBitArraySize; i++)
+ ctrl->per_key_repeat[i] = -1;
+
+ /* Now turn off the modifiers */
+ for(i=0; i < 32; i++) {
+ unsigned char keycode;
+
+ keycode = keyInfo.modifierKeycodes[i][0];
+ if(keycode)
+ ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE);
+
+ keycode = keyInfo.modifierKeycodes[i][1];
+ if(keycode)
+ ClearBit(ctrl->per_key_repeat, keycode + MIN_KEYCODE);
+ }
+
+ /* Hurray for data duplication */
+ if (pDev->kbdfeed)
+ memcpy(pDev->kbdfeed->ctrl.autoRepeats, ctrl->per_key_repeat, XkbPerKeyBitArraySize);
+
+ //fprintf(stderr, "per_key_repeat =\n");
+ //for(i=0; i < XkbPerKeyBitArraySize; i++)
+ // fprintf(stderr, "%02x%s", ctrl->per_key_repeat[i], (i + 1) & 7 ? "" : "\n");
+
+ /* And now we notify the puppies about the changes */
+ XkbDDXChangeControls(pDev, &old, ctrl);
+ }
+}
+
+void DarwinKeyboardReloadHandler(void) {
+ KeySymsRec keySyms;
+ CFIndex initialKeyRepeatValue, keyRepeatValue;
+ BOOL ok;
+ DeviceIntPtr pDev;
+ const char *xmodmap = PROJECTROOT "/bin/xmodmap";
+ const char *sysmodmap = PROJECTROOT "/lib/X11/xinit/.Xmodmap";
+ const char *homedir = getenv("HOME");
+ char usermodmap[PATH_MAX], cmd[PATH_MAX];
+
+ DEBUG_LOG("DarwinKeyboardReloadHandler\n");
+
+ /* Get our key repeat settings from GlobalPreferences */
+ (void)CFPreferencesAppSynchronize(CFSTR(".GlobalPreferences"));
+
+ initialKeyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("InitialKeyRepeat"), CFSTR(".GlobalPreferences"), &ok);
+ if(!ok)
+ initialKeyRepeatValue = 35;
+
+ keyRepeatValue = CFPreferencesGetAppIntegerValue(CFSTR("KeyRepeat"), CFSTR(".GlobalPreferences"), &ok);
+ if(!ok)
+ keyRepeatValue = 6;
+
+ pthread_mutex_lock(&keyInfo_mutex); {
+ /* Initialize our keySyms */
+ keySyms.map = keyInfo.keyMap;
+ keySyms.mapWidth = GLYPHS_PER_KEY;
+ keySyms.minKeyCode = MIN_KEYCODE;
+ keySyms.maxKeyCode = MAX_KEYCODE;
+
+ // TODO: We should build the entire XkbDescRec and use XkbCopyKeymap
+ /* Apply the mappings to darwinKeyboard */
+ XkbApplyMappingChange(darwinKeyboard, &keySyms, keySyms.minKeyCode,
+ keySyms.maxKeyCode - keySyms.minKeyCode + 1,
+ keyInfo.modMap, serverClient);
+ DarwinKeyboardSetRepeat(darwinKeyboard, initialKeyRepeatValue, keyRepeatValue);
+
+ /* Apply the mappings to the core keyboard */
+ for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
+ if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
+ XkbApplyMappingChange(pDev, &keySyms, keySyms.minKeyCode,
+ keySyms.maxKeyCode - keySyms.minKeyCode + 1,
+ keyInfo.modMap, serverClient);
+ DarwinKeyboardSetRepeat(pDev, initialKeyRepeatValue, keyRepeatValue);
+ }
+ }
+ } pthread_mutex_unlock(&keyInfo_mutex);
+
+ /* Modify with xmodmap */
+ if (access(xmodmap, F_OK) == 0) {
+ /* Check for system .Xmodmap */
+ if (access(sysmodmap, F_OK) == 0) {
+ if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, sysmodmap) < sizeof(cmd)) {
+ X11ApplicationLaunchClient(cmd);
+ } else {
+ ErrorF("X11.app: Unable to create / execute xmodmap command line");
+ }
+ }
+
+ /* Check for user's local .Xmodmap */
+ if ((homedir != NULL) && (snprintf (usermodmap, sizeof(usermodmap), "%s/.Xmodmap", homedir) < sizeof(usermodmap))) {
+ if (access(usermodmap, F_OK) == 0) {
+ if(snprintf (cmd, sizeof(cmd), "%s %s", xmodmap, usermodmap) < sizeof(cmd)) {
+ X11ApplicationLaunchClient(cmd);
+ } else {
+ ErrorF("X11.app: Unable to create / execute xmodmap command line");
+ }
+ }
+ } else {
+ ErrorF("X11.app: Unable to determine path to user's .Xmodmap");
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Modifier translation functions
+//
+// There are three different ways to specify a Mac modifier key:
+// keycode - specifies hardware key, read from keymapping
+// key - NX_MODIFIERKEY_*, really an index
+// mask - NX_*MASK, mask for modifier flags in event record
+// Left and right side have different keycodes but the same key and mask.
+//-----------------------------------------------------------------------------
+
+/*
+ * DarwinModifierNXKeyToNXKeycode
+ * Return the keycode for an NX_MODIFIERKEY_* modifier.
+ * side = 0 for left or 1 for right.
+ * Returns 0 if key+side is not a known modifier.
+ */
+int DarwinModifierNXKeyToNXKeycode(int key, int side) {
+ int retval;
+ pthread_mutex_lock(&keyInfo_mutex);
+ retval = keyInfo.modifierKeycodes[key][side];
+ pthread_mutex_unlock(&keyInfo_mutex);
+
+ return retval;
+}
+
+/*
+ * DarwinModifierNXKeycodeToNXKey
+ * Returns -1 if keycode+side is not a modifier key
+ * outSide may be NULL, else it gets 0 for left and 1 for right.
+ */
+int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide) {
+ int key, side;
+
+ keycode += MIN_KEYCODE;
+
+ // search modifierKeycodes for this keycode+side
+ pthread_mutex_lock(&keyInfo_mutex);
+ for (key = 0; key < NX_NUMMODIFIERS; key++) {
+ for (side = 0; side <= 1; side++) {
+ if (keyInfo.modifierKeycodes[key][side] == keycode) break;
+ }
+ }
+ pthread_mutex_unlock(&keyInfo_mutex);
+
+ if (key == NX_NUMMODIFIERS) {
+ return -1;
+ }
+ if (outSide) *outSide = side;
+
+ return key;
+}
+
+/*
+ * DarwinModifierNXMaskToNXKey
+ * Returns -1 if mask is not a known modifier mask.
+ */
+int DarwinModifierNXMaskToNXKey(int mask) {
+ switch (mask) {
+ case NX_ALPHASHIFTMASK: return NX_MODIFIERKEY_ALPHALOCK;
+ case NX_SHIFTMASK: return NX_MODIFIERKEY_SHIFT;
+#ifdef NX_DEVICELSHIFTKEYMASK
+ case NX_DEVICELSHIFTKEYMASK: return NX_MODIFIERKEY_SHIFT;
+ case NX_DEVICERSHIFTKEYMASK: return NX_MODIFIERKEY_RSHIFT;
+#endif
+ case NX_CONTROLMASK: return NX_MODIFIERKEY_CONTROL;
+#ifdef NX_DEVICELCTLKEYMASK
+ case NX_DEVICELCTLKEYMASK: return NX_MODIFIERKEY_CONTROL;
+ case NX_DEVICERCTLKEYMASK: return NX_MODIFIERKEY_RCONTROL;
+#endif
+ case NX_ALTERNATEMASK: return NX_MODIFIERKEY_ALTERNATE;
+#ifdef NX_DEVICELALTKEYMASK
+ case NX_DEVICELALTKEYMASK: return NX_MODIFIERKEY_ALTERNATE;
+ case NX_DEVICERALTKEYMASK: return NX_MODIFIERKEY_RALTERNATE;
+#endif
+ case NX_COMMANDMASK: return NX_MODIFIERKEY_COMMAND;
+#ifdef NX_DEVICELCMDKEYMASK
+ case NX_DEVICELCMDKEYMASK: return NX_MODIFIERKEY_COMMAND;
+ case NX_DEVICERCMDKEYMASK: return NX_MODIFIERKEY_RCOMMAND;
+#endif
+ case NX_NUMERICPADMASK: return NX_MODIFIERKEY_NUMERICPAD;
+ case NX_HELPMASK: return NX_MODIFIERKEY_HELP;
+ case NX_SECONDARYFNMASK: return NX_MODIFIERKEY_SECONDARYFN;
+ }
+ return -1;
+}
+
+/*
+ * DarwinModifierNXKeyToNXMask
+ * Returns 0 if key is not a known modifier key.
+ */
+int DarwinModifierNXKeyToNXMask(int key) {
+ switch (key) {
+ case NX_MODIFIERKEY_ALPHALOCK: return NX_ALPHASHIFTMASK;
+#ifdef NX_DEVICELSHIFTKEYMASK
+ case NX_MODIFIERKEY_SHIFT: return NX_DEVICELSHIFTKEYMASK;
+ case NX_MODIFIERKEY_RSHIFT: return NX_DEVICERSHIFTKEYMASK;
+ case NX_MODIFIERKEY_CONTROL: return NX_DEVICELCTLKEYMASK;
+ case NX_MODIFIERKEY_RCONTROL: return NX_DEVICERCTLKEYMASK;
+ case NX_MODIFIERKEY_ALTERNATE: return NX_DEVICELALTKEYMASK;
+ case NX_MODIFIERKEY_RALTERNATE: return NX_DEVICERALTKEYMASK;
+ case NX_MODIFIERKEY_COMMAND: return NX_DEVICELCMDKEYMASK;
+ case NX_MODIFIERKEY_RCOMMAND: return NX_DEVICERCMDKEYMASK;
+#else
+ case NX_MODIFIERKEY_SHIFT: return NX_SHIFTMASK;
+ case NX_MODIFIERKEY_CONTROL: return NX_CONTROLMASK;
+ case NX_MODIFIERKEY_ALTERNATE: return NX_ALTERNATEMASK;
+ case NX_MODIFIERKEY_COMMAND: return NX_COMMANDMASK;
+#endif
+ case NX_MODIFIERKEY_NUMERICPAD: return NX_NUMERICPADMASK;
+ case NX_MODIFIERKEY_HELP: return NX_HELPMASK;
+ case NX_MODIFIERKEY_SECONDARYFN: return NX_SECONDARYFNMASK;
+ }
+ return 0;
+}
+
+/*
+ * DarwinModifierStringToNXMask
+ * Returns 0 if string is not a known modifier.
+ */
+int DarwinModifierStringToNXMask(const char *str, int separatelr) {
+#ifdef NX_DEVICELSHIFTKEYMASK
+ if(separatelr) {
+ if (!strcasecmp(str, "shift")) return NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK;
+ if (!strcasecmp(str, "control")) return NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK;
+ if (!strcasecmp(str, "option")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK;
+ if (!strcasecmp(str, "alt")) return NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK;
+ if (!strcasecmp(str, "command")) return NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK;
+ if (!strcasecmp(str, "lshift")) return NX_DEVICELSHIFTKEYMASK;
+ if (!strcasecmp(str, "rshift")) return NX_DEVICERSHIFTKEYMASK;
+ if (!strcasecmp(str, "lcontrol")) return NX_DEVICELCTLKEYMASK;
+ if (!strcasecmp(str, "rcontrol")) return NX_DEVICERCTLKEYMASK;
+ if (!strcasecmp(str, "loption")) return NX_DEVICELALTKEYMASK;
+ if (!strcasecmp(str, "roption")) return NX_DEVICERALTKEYMASK;
+ if (!strcasecmp(str, "lalt")) return NX_DEVICELALTKEYMASK;
+ if (!strcasecmp(str, "ralt")) return NX_DEVICERALTKEYMASK;
+ if (!strcasecmp(str, "lcommand")) return NX_DEVICELCMDKEYMASK;
+ if (!strcasecmp(str, "rcommand")) return NX_DEVICERCMDKEYMASK;
+ } else {
+#endif
+ if (!strcasecmp(str, "shift")) return NX_SHIFTMASK;
+ if (!strcasecmp(str, "control")) return NX_CONTROLMASK;
+ if (!strcasecmp(str, "option")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "alt")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "command")) return NX_COMMANDMASK;
+ if (!strcasecmp(str, "lshift")) return NX_SHIFTMASK;
+ if (!strcasecmp(str, "rshift")) return NX_SHIFTMASK;
+ if (!strcasecmp(str, "lcontrol")) return NX_CONTROLMASK;
+ if (!strcasecmp(str, "rcontrol")) return NX_CONTROLMASK;
+ if (!strcasecmp(str, "loption")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "roption")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "lalt")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "ralt")) return NX_ALTERNATEMASK;
+ if (!strcasecmp(str, "lcommand")) return NX_COMMANDMASK;
+ if (!strcasecmp(str, "rcommand")) return NX_COMMANDMASK;
+#ifdef NX_DEVICELSHIFTKEYMASK
+ }
+#endif
+ if (!strcasecmp(str, "lock")) return NX_ALPHASHIFTMASK;
+ if (!strcasecmp(str, "fn")) return NX_SECONDARYFNMASK;
+ if (!strcasecmp(str, "help")) return NX_HELPMASK;
+ if (!strcasecmp(str, "numlock")) return NX_NUMERICPADMASK;
+ return 0;
+}
+
+/*
+ * LegalModifier
+ * This allows the ddx layer to prevent some keys from being remapped
+ * as modifier keys.
+ */
+Bool LegalModifier(unsigned int key, DeviceIntPtr pDev)
+{
+ return 1;
+}
+
+static inline UniChar macroman2ucs(unsigned char c) {
+ /* Precalculated table mapping MacRoman-128 to Unicode. Generated
+ by creating single element CFStringRefs then extracting the
+ first character. */
+
+ static const unsigned short table[128] = {
+ 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
+ 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
+ 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
+ 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
+ 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
+ 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
+ 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
+ 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
+ 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
+ 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
+ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
+ 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
+ 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
+ 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
+ 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
+ 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
+ };
+
+ if (c < 128) return c;
+ else return table[c - 128];
+}
+
+static KeySym make_dead_key(KeySym in) {
+ int i;
+
+ for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++)
+ if (dead_keys[i].normal == in) return dead_keys[i].dead;
+
+ return in;
+}
+
+static Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) {
+#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ KeyboardLayoutRef key_layout;
+ int is_uchr = 1;
+#endif
+ const void *chr_data = NULL;
+ int num_keycodes = NUM_KEYCODES;
+ UInt32 keyboard_type = LMGetKbdType();
+ int i, j;
+ OSStatus err;
+ KeySym *k;
+ CFDataRef currentKeyLayoutDataRef = NULL;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ TISInputSourceRef currentKeyLayoutRef = TISCopyCurrentKeyboardLayoutInputSource();
+
+ if (currentKeyLayoutRef) {
+ currentKeyLayoutDataRef = (CFDataRef )TISGetInputSourceProperty(currentKeyLayoutRef, kTISPropertyUnicodeKeyLayoutData);
+ if (currentKeyLayoutDataRef)
+ chr_data = CFDataGetBytePtr(currentKeyLayoutDataRef);
+ }
+#endif
+
+#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ if (chr_data == NULL) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ ErrorF("X11.app: Error detected in determining keyboard layout. If you are using an Apple-provided keyboard layout, please report this error at http://xquartz.macosforge.org and http://bugreport.apple.com\n");
+ ErrorF("X11.app: Debug Info: keyboard_type=%u, currentKeyLayoutRef=%p, currentKeyLayoutDataRef=%p, chr_data=%p\n",
+ (unsigned)keyboard_type, currentKeyLayoutRef, currentKeyLayoutDataRef, chr_data);
+#endif
+
+ KLGetCurrentKeyboardLayout (&key_layout);
+ KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ if(chr_data != NULL) {
+ ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n");
+ }
+#endif
+ }
+
+ if (chr_data == NULL) {
+ ErrorF("X11.app: Debug Info: kKLuchrData failed, trying kKLKCHRData.\n");
+ ErrorF("If you are using a 3rd party keyboard layout, please see http://xquartz.macosforge.org/trac/ticket/154\n");
+ KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data);
+ is_uchr = 0;
+ num_keycodes = 128;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ if(chr_data != NULL) {
+ ErrorF("X11.app: Fallback succeeded, but this is still a bug. Please report the above information.\n");
+ }
+#endif
+ }
+#endif
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+ if(currentKeyLayoutRef)
+ CFRelease(currentKeyLayoutRef);
+#endif
+
+ if (chr_data == NULL) {
+ ErrorF ( "Couldn't get uchr or kchr resource\n");
+ return FALSE;
+ }
+
+ /* Scan the keycode range for the Unicode character that each
+ key produces in the four shift states. Then convert that to
+ an X11 keysym (which may just the bit that says "this is
+ Unicode" if it can't find the real symbol.) */
+
+ /* KeyTranslate is not available on 64-bit platforms; UCKeyTranslate
+ must be used instead. */
+
+ for (i = 0; i < num_keycodes; i++) {
+ static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION,
+ MOD_OPTION | MOD_SHIFT};
+
+ k = info->keyMap + i * GLYPHS_PER_KEY;
+
+ for (j = 0; j < 4; j++) {
+#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ if (is_uchr) {
+#endif
+ UniChar s[8];
+ UniCharCount len;
+ UInt32 dead_key_state = 0, extra_dead = 0;
+
+ err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
+ mods[j] >> 8, keyboard_type, 0,
+ &dead_key_state, 8, &len, s);
+ if (err != noErr) continue;
+
+ if (len == 0 && dead_key_state != 0) {
+ /* Found a dead key. Work out which one it is, but
+ remembering that it's dead. */
+ err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
+ mods[j] >> 8, keyboard_type,
+ kUCKeyTranslateNoDeadKeysMask,
+ &extra_dead, 8, &len, s);
+ if (err != noErr) continue;
+ }
+
+ /* Not sure why 0x0010 is there.
+ * 0x0000 - <rdar://problem/7793566> 'Unicode Hex Input' ...
+ */
+ if (len > 0 && s[0] != 0x0010 && s[0] != 0x0000) {
+ k[j] = ucs2keysym (s[0]);
+ if (dead_key_state != 0) k[j] = make_dead_key (k[j]);
+ }
+#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ } else { // kchr
+ UInt32 c, state = 0, state2 = 0;
+ UInt16 code;
+
+ code = i | mods[j];
+ c = KeyTranslate (chr_data, code, &state);
+
+ /* Dead keys are only processed on key-down, so ask
+ to translate those events. When we find a dead key,
+ translating the matching key up event will give
+ us the actual dead character. */
+
+ if (state != 0)
+ c = KeyTranslate (chr_data, code | 128, &state2);
+
+ /* Characters seem to be in MacRoman encoding. */
+
+ if (c != 0 && c != 0x0010) {
+ k[j] = ucs2keysym (macroman2ucs (c & 255));
+
+ if (state != 0) k[j] = make_dead_key (k[j]);
+ }
+ }
+#endif
+ }
+
+ if (k[3] == k[2]) k[3] = NoSymbol;
+ if (k[1] == k[0]) k[1] = NoSymbol;
+ if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
+ if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] = NoSymbol;
+ }
+
+#if HACK_MISSING
+ /* Fix up some things that are normally missing.. */
+
+ for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++) {
+ k = info->keyMap + known_keys[i].keycode * GLYPHS_PER_KEY;
+
+ if ( k[0] == NoSymbol && k[1] == NoSymbol
+ && k[2] == NoSymbol && k[3] == NoSymbol)
+ k[0] = known_keys[i].keysym;
+ }
+#endif
+
+#if HACK_KEYPAD
+ /* And some more things. We find the right symbols for the numeric
+ keypad, but not the KP_ keysyms. So try to convert known keycodes. */
+ for (i = 0; i < sizeof (known_numeric_keys) / sizeof (known_numeric_keys[0]); i++) {
+ k = info->keyMap + known_numeric_keys[i].keycode * GLYPHS_PER_KEY;
+
+ if (k[0] == known_numeric_keys[i].normal)
+ k[0] = known_numeric_keys[i].keypad;
+ }
+#endif
+
+#if HACK_BLACKLIST
+ for (i = 0; i < sizeof (keycode_blacklist) / sizeof (keycode_blacklist[0]); i++) {
+ k = info->keyMap + keycode_blacklist[i] * GLYPHS_PER_KEY;
+ k[0] = k[1] = k[2] = k[3] = NoSymbol;
+ }
+#endif
+
+ DarwinBuildModifierMaps(info);
+
+ return TRUE;
+}
+
+Bool QuartsResyncKeymap(Bool sendDDXEvent) {
+ Bool retval;
+ /* Update keyInfo */
+ pthread_mutex_lock(&keyInfo_mutex);
+ memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap));
+ retval = QuartzReadSystemKeymap(&keyInfo);
+ pthread_mutex_unlock(&keyInfo_mutex);
+
+ /* Tell server thread to deal with new keyInfo */
+ if(sendDDXEvent)
+ DarwinSendDDXEvent(kXquartzReloadKeymap, 0);
+
+ return retval;
+}
diff --git a/xorg-server/hw/xquartz/xpr/dri.c b/xorg-server/hw/xquartz/xpr/dri.c
index 363809d0d..252c2bb4c 100644
--- a/xorg-server/hw/xquartz/xpr/dri.c
+++ b/xorg-server/hw/xquartz/xpr/dri.c
@@ -74,14 +74,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <AvailabilityMacros.h>
-static int DRIScreenPrivKeyIndex;
-static DevPrivateKey DRIScreenPrivKey = &DRIScreenPrivKeyIndex;
-static int DRIWindowPrivKeyIndex;
-static DevPrivateKey DRIWindowPrivKey = &DRIWindowPrivKeyIndex;
-static int DRIPixmapPrivKeyIndex;
-static DevPrivateKey DRIPixmapPrivKey = &DRIPixmapPrivKeyIndex;
-static int DRIPixmapBufferPrivKeyIndex;
-static DevPrivateKey DRIPixmapBufferPrivKey = &DRIPixmapBufferPrivKeyIndex;
+static DevPrivateKeyRec DRIScreenPrivKeyRec;
+#define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
+static DevPrivateKeyRec DRIWindowPrivKeyRec;
+#define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
+static DevPrivateKeyRec DRIPixmapPrivKeyRec;
+#define DRIPixmapPrivKey (&DRIPixmapPrivKeyRec)
+static DevPrivateKeyRec DRIPixmapBufferPrivKeyRec;
+#define DRIPixmapBufferPrivKey (&DRIPixmapBufferPrivKeyRec)
static RESTYPE DRIDrawablePrivResType;
@@ -205,6 +205,15 @@ DRIScreenInit(ScreenPtr pScreen)
DRIScreenPrivPtr pDRIPriv;
int i;
+ if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0))
+ return FALSE;
+ if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0))
+ return FALSE;
+ if (!dixRegisterPrivateKey(&DRIPixmapPrivKeyRec, PRIVATE_PIXMAP, 0))
+ return FALSE;
+ if (!dixRegisterPrivateKey(&DRIPixmapBufferPrivKeyRec, PRIVATE_PIXMAP, 0))
+ return FALSE;
+
pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec));
if (!pDRIPriv) {
dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
@@ -280,7 +289,7 @@ DRIExtensionInit(void)
DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete,
"DRIDrawable");
- return (DRIDrawablePrivResType != 0);
+ return DRIDrawablePrivResType != 0;
}
void
@@ -347,8 +356,8 @@ DRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw)
wc.height = pWin->drawable.height + 2 * pWin->borderWidth;
wc.bit_gravity = XP_GRAVITY_NONE;
- wc.shape_nrects = REGION_NUM_RECTS(&pWin->clipList);
- wc.shape_rects = REGION_RECTS(&pWin->clipList);
+ wc.shape_nrects = RegionNumRects(&pWin->clipList);
+ wc.shape_rects = RegionRects(&pWin->clipList);
wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth);
wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth);
diff --git a/xorg-server/hw/xquartz/xpr/driWrap.c b/xorg-server/hw/xquartz/xpr/driWrap.c
index 2e23cbbf5..37cb8cf5a 100644
--- a/xorg-server/hw/xquartz/xpr/driWrap.c
+++ b/xorg-server/hw/xquartz/xpr/driWrap.c
@@ -55,11 +55,11 @@ typedef struct {
DevUnion devPrivate;
} DRISavedDrawableState;
-static int driGCKeyIndex;
-static DevPrivateKey driGCKey = &driGCKeyIndex;
+static DevPrivateKeyRec driGCKeyRec;
+#define driGCKey (&driGCKeyRec)
-static int driWrapScreenKeyIndex;
-static DevPrivateKey driWrapScreenKey = &driWrapScreenKeyIndex;
+static DevPrivateKeyRec driWrapScreenKeyRec;
+#define driWrapScreenKey (&driWrapScreenKeyRec)
static GCOps driGCOps;
@@ -527,21 +527,15 @@ Bool
DRIWrapInit(ScreenPtr pScreen) {
DRIWrapScreenRec *pScreenPriv;
- if(!dixRequestPrivate(driGCKey, sizeof(DRIGCRec)))
+ if(!dixRegisterPrivateKey(&driGCKeyRec, PRIVATE_GC, sizeof(DRIGCRec)))
return FALSE;
- if(!dixRequestPrivate(driWrapScreenKey, sizeof(DRIWrapScreenRec)))
- return FALSE;
-
- pScreenPriv = malloc(sizeof(*pScreenPriv));
-
- if(NULL == pScreenPriv)
+ if(!dixRegisterPrivateKey(&driWrapScreenKeyRec, PRIVATE_SCREEN, sizeof(DRIWrapScreenRec)))
return FALSE;
+ pScreenPriv = dixGetPrivateAddr(&pScreen->devPrivates, &driWrapScreenKeyRec);
pScreenPriv->CreateGC = pScreen->CreateGC;
pScreen->CreateGC = DRICreateGC;
- dixSetPrivate(&pScreen->devPrivates, driWrapScreenKey, pScreenPriv);
-
return TRUE;
}
diff --git a/xorg-server/hw/xquartz/xpr/xprCursor.c b/xorg-server/hw/xquartz/xpr/xprCursor.c
index df9eef95e..9c7890647 100644
--- a/xorg-server/hw/xquartz/xpr/xprCursor.c
+++ b/xorg-server/hw/xquartz/xpr/xprCursor.c
@@ -57,13 +57,12 @@ typedef struct {
miPointerSpriteFuncPtr spriteFuncs;
} QuartzCursorScreenRec, *QuartzCursorScreenPtr;
-static int darwinCursorScreenKeyIndex;
-static DevPrivateKey darwinCursorScreenKey = &darwinCursorScreenKeyIndex;
+static DevPrivateKeyRec darwinCursorScreenKeyRec;
+#define darwinCursorScreenKey (&darwinCursorScreenKeyRec)
#define CURSOR_PRIV(pScreen) ((QuartzCursorScreenPtr) \
dixLookupPrivate(&pScreen->devPrivates, darwinCursorScreenKey))
-
static Bool
load_cursor(CursorPtr src, int screen)
{
@@ -296,8 +295,8 @@ QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
{
int sx, sy;
- sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+ sx = pScreen->x + darwinMainScreenX;
+ sy = pScreen->y + darwinMainScreenY;
CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y));
}
@@ -360,6 +359,9 @@ QuartzInitCursor(ScreenPtr pScreen)
if (!miDCInitialize(pScreen, &quartzScreenFuncsRec))
return FALSE;
+ if (!dixRegisterPrivateKey(&darwinCursorScreenKeyRec, PRIVATE_SCREEN, 0))
+ return FALSE;
+
ScreenPriv = calloc(1, sizeof(QuartzCursorScreenRec));
if (ScreenPriv == NULL)
return FALSE;
diff --git a/xorg-server/hw/xquartz/xpr/xprFrame.c b/xorg-server/hw/xquartz/xpr/xprFrame.c
index 53dde7acc..52925339f 100644
--- a/xorg-server/hw/xquartz/xpr/xprFrame.c
+++ b/xorg-server/hw/xquartz/xpr/xprFrame.c
@@ -1,640 +1,640 @@
-/*
- * Xplugin rootless implementation frame functions
- *
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- * Copyright (c) 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
-
-#include "xpr.h"
-#include "rootlessCommon.h"
-#include <Xplugin.h>
-#include "x-hash.h"
-#include "x-list.h"
-#include "applewmExt.h"
-
-#include "propertyst.h"
-#include "dix.h"
-#include <X11/Xatom.h>
-#include "windowstr.h"
-#include "quartz.h"
-
-#include "threadSafety.h"
-
-#include <pthread.h>
-
-#define DEFINE_ATOM_HELPER(func,atom_name) \
-static Atom func (void) { \
- static int generation; \
- static Atom atom; \
- if (generation != serverGeneration) { \
- generation = serverGeneration; \
- atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
- } \
- return atom; \
-}
-
-DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
-
-/* Maps xp_window_id -> RootlessWindowRec */
-static x_hash_table *window_hash;
-static pthread_mutex_t window_hash_mutex;
-
-/* Prototypes for static functions */
-static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape);
-static void xprDestroyFrame(RootlessFrameID wid);
-static void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
-static void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity);
-static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
-static void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
-static void xprUnmapFrame(RootlessFrameID wid);
-static void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
-static void xprStopDrawing(RootlessFrameID wid, Bool flush);
-static void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
-static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y);
-static void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
-static Bool xprDoReorderWindow(RootlessWindowPtr pFrame);
-static void xprHideWindow(RootlessFrameID wid);
-static void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
-static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy);
-
-
-static inline xp_error
-xprConfigureWindow(xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- TA_SERVER();
-
- return xp_configure_window(id, mask, values);
-}
-
-
-static void
-xprSetNativeProperty(RootlessWindowPtr pFrame)
-{
- xp_error err;
- unsigned int native_id;
- long data;
-
- TA_SERVER();
-
- err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
- if (err == Success)
- {
- /* FIXME: move this to AppleWM extension */
-
- data = native_id;
- dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(),
- XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
- }
-}
-
-static xp_error
-xprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors)
-{
- return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch);
-}
-
-/*
- * Create and display a new frame.
- */
-static Bool
-xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape)
-{
- WindowPtr pWin = pFrame->win;
- xp_window_changes wc;
- unsigned int mask = 0;
- xp_error err;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- wc.width = pFrame->width;
- wc.height = pFrame->height;
- wc.bit_gravity = XP_GRAVITY_NONE;
- mask |= XP_BOUNDS;
-
- if (pWin->drawable.depth == 8)
- {
- wc.depth = XP_DEPTH_INDEX8;
- wc.colormap = xprColormapCallback;
- wc.colormap_data = pScreen;
- mask |= XP_COLORMAP;
- }
- else if (pWin->drawable.depth == 15)
- wc.depth = XP_DEPTH_RGB555;
- else if (pWin->drawable.depth == 24)
- wc.depth = XP_DEPTH_ARGB8888;
- else
- wc.depth = XP_DEPTH_NIL;
- mask |= XP_DEPTH;
-
- if (pShape != NULL)
- {
- wc.shape_nrects = REGION_NUM_RECTS(pShape);
- wc.shape_rects = REGION_RECTS(pShape);
- wc.shape_tx = wc.shape_ty = 0;
- mask |= XP_SHAPE;
- }
-
- pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
-
- if(quartzEnableRootless)
- wc.window_level = normal_window_levels[pFrame->level];
- else
- wc.window_level = rooted_window_levels[pFrame->level];
- mask |= XP_WINDOW_LEVEL;
-
- err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid);
-
- if (err != Success)
- {
- return FALSE;
- }
-
- if (window_hash == NULL)
- {
- window_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
- pthread_mutex_init(&window_hash_mutex, NULL);
- }
-
- pthread_mutex_lock(&window_hash_mutex);
- x_hash_table_insert(window_hash, pFrame->wid, pFrame);
- pthread_mutex_unlock(&window_hash_mutex);
-
- xprSetNativeProperty(pFrame);
-
- return TRUE;
-}
-
-
-/*
- * Destroy a frame.
- */
-static void
-xprDestroyFrame(RootlessFrameID wid)
-{
- 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));
-}
-
-
-/*
- * Move a frame on screen.
- */
-static void
-xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- // ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
-}
-
-
-/*
- * Resize and move a frame.
- */
-static void
-xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.x = newX;
- wc.y = newY;
- wc.width = newW;
- wc.height = newH;
- wc.bit_gravity = gravity;
-
- /* It's unlikely that being async will save us anything here.
- But it can't hurt. */
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
-}
-
-
-/*
- * Change frame stacking.
- */
-static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
- xp_window_changes wc;
- unsigned int mask = XP_STACKING;
-
- TA_SERVER();
-
- /* Stack frame below nextWid it if it exists, or raise
- frame above everything otherwise. */
-
- if(nextWid == NULL) {
- wc.stack_mode = XP_MAPPED_ABOVE;
- wc.sibling = 0;
- } else {
- wc.stack_mode = XP_MAPPED_BELOW;
- wc.sibling = x_cvt_vptr_to_uint(nextWid);
- }
-
- if(window_hash) {
- RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL);
-
- if(winRec) {
- if(quartzEnableRootless)
- wc.window_level = normal_window_levels[winRec->level];
- else
- wc.window_level = rooted_window_levels[winRec->level];
- mask |= XP_WINDOW_LEVEL;
- }
- }
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
-}
-
-
-/*
- * Change the frame's shape.
- */
-static void
-xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- if (pShape != NULL)
- {
- wc.shape_nrects = REGION_NUM_RECTS(pShape);
- wc.shape_rects = REGION_RECTS(pShape);
- }
- else
- {
- wc.shape_nrects = -1;
- wc.shape_rects = NULL;
- }
-
- wc.shape_tx = wc.shape_ty = 0;
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
-}
-
-
-/*
- * Unmap a frame.
- */
-static void
-xprUnmapFrame(RootlessFrameID wid)
-{
- xp_window_changes wc;
-
- TA_SERVER();
-
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
-}
-
-
-/*
- * Start drawing to a frame.
- * Prepare for direct access to its backing buffer.
- */
-static void
-xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
-{
- void *data[2];
- unsigned int rowbytes[2];
- xp_error err;
-
- TA_SERVER();
-
- err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL);
- if (err != Success)
- FatalError("Could not lock window %i for drawing.", (int)x_cvt_vptr_to_uint(wid));
-
- *pixelData = data[0];
- *bytesPerRow = rowbytes[0];
-}
-
-
-/*
- * Stop drawing to a frame.
- */
-static void
-xprStopDrawing(RootlessFrameID wid, Bool flush)
-{
- TA_SERVER();
-
- xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
-}
-
-
-/*
- * Flush drawing updates to the screen.
- */
-static void
-xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
-{
- TA_SERVER();
-
- xp_flush_window(x_cvt_vptr_to_uint(wid));
-}
-
-
-/*
- * Mark damaged rectangles as requiring redisplay to screen.
- */
-static void
-xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y)
-{
- TA_SERVER();
-
- xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
-}
-
-
-/*
- * Called after the window associated with a frame has been switched
- * to a new top-level parent.
- */
-static void
-xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
-{
- DeleteProperty(serverClient, oldWin, xa_native_window_id());
-
- TA_SERVER();
-
- xprSetNativeProperty(pFrame);
-}
-
-
-/*
- * Called to check if the frame should be reordered when it is restacked.
- */
-static Bool xprDoReorderWindow(RootlessWindowPtr pFrame)
-{
- WindowPtr pWin = pFrame->win;
-
- TA_SERVER();
-
- return AppleWMDoReorderWindow(pWin);
-}
-
-
-/*
- * Copy area in frame to another part of frame.
- * Used to accelerate scrolling.
- */
-static void
-xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy)
-{
- TA_SERVER();
-
- xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
- dstNrects, dstRects, dx, dy);
-}
-
-
-static RootlessFrameProcsRec xprRootlessProcs = {
- xprCreateFrame,
- xprDestroyFrame,
- xprMoveFrame,
- xprResizeFrame,
- xprRestackFrame,
- xprReshapeFrame,
- xprUnmapFrame,
- xprStartDrawing,
- xprStopDrawing,
- xprUpdateRegion,
- xprDamageRects,
- xprSwitchWindow,
- xprDoReorderWindow,
- xprHideWindow,
- xprUpdateColormap,
- xp_copy_bytes,
- xp_fill_bytes,
- xp_composite_pixels,
- xprCopyWindow
-};
-
-
-/*
- * Initialize XPR implementation
- */
-Bool
-xprInit(ScreenPtr pScreen)
-{
- RootlessInit(pScreen, &xprRootlessProcs);
-
- TA_SERVER();
-
- rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
- rootless_FillBytes_threshold = xp_fill_bytes_threshold;
- rootless_CompositePixels_threshold = xp_composite_area_threshold;
- rootless_CopyWindow_threshold = xp_scroll_area_threshold;
-
- return TRUE;
-}
-
-
-/*
- * Given the id of a physical window, try to find the top-level (or root)
- * X window that it represents.
- */
-WindowPtr
-xprGetXWindow(xp_window_id wid)
-{
- RootlessWindowRec *winRec;
-
- if (window_hash == NULL)
- return NULL;
-
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
-
- return winRec != NULL ? winRec->win : NULL;
-}
-
-#ifdef UNUSED_CODE
-/*
- * Given the id of a physical window, try to find the top-level (or root)
- * X window that it represents.
- */
-WindowPtr
-xprGetXWindowFromAppKit(int windowNumber)
-{
- RootlessWindowRec *winRec;
- Bool ret;
- xp_window_id wid;
-
- if (window_hash == NULL)
- return FALSE;
-
- /* need to lock, since this function can be called by any thread */
-
- pthread_mutex_lock(&window_hash_mutex);
-
- if (xp_lookup_native_window(windowNumber, &wid))
- ret = xprGetXWindow(wid) != NULL;
- else
- ret = FALSE;
-
- pthread_mutex_unlock(&window_hash_mutex);
-
- if (!ret) return NULL;
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
-
- return winRec != NULL ? winRec->win : NULL;
-}
-#endif
-
-/*
- * The windowNumber is an AppKit window number. Returns TRUE if xpr is
- * displaying a window with that number.
- */
-Bool
-xprIsX11Window(void *nsWindow, int windowNumber)
-{
- Bool ret;
- xp_window_id wid;
-
- if (window_hash == NULL)
- return FALSE;
-
- /* need to lock, since this function can be called by any thread */
-
- pthread_mutex_lock(&window_hash_mutex);
-
- if (xp_lookup_native_window(windowNumber, &wid))
- ret = xprGetXWindow(wid) != NULL;
- else
- ret = FALSE;
-
- pthread_mutex_unlock(&window_hash_mutex);
-
- return ret;
-}
-
-
-/*
- * xprHideWindows
- * Hide or unhide all top level windows. This is called for application hide/
- * unhide events if the window manager is not Apple-WM aware. Xplugin windows
- * do not hide or unhide themselves.
- */
-void
-xprHideWindows(Bool hide)
-{
- int screen;
- WindowPtr pRoot, pWin;
-
- TA_SERVER();
-
- for (screen = 0; screen < screenInfo.numScreens; screen++) {
- RootlessFrameID prevWid = NULL;
- pRoot = WindowTable[screenInfo.screens[screen]->myNum];
-
- for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
- RootlessWindowRec *winRec = WINREC(pWin);
-
- if (winRec != NULL) {
- if (hide) {
- xprUnmapFrame(winRec->wid);
- } else {
- BoxRec box;
-
- xprRestackFrame(winRec->wid, prevWid);
- prevWid = winRec->wid;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = winRec->width;
- box.y2 = winRec->height;
-
- xprDamageRects(winRec->wid, 1, &box, 0, 0);
- RootlessQueueRedisplay(screenInfo.screens[screen]);
- }
- }
- }
- }
-}
-
-// XXX: identical to x_cvt_vptr_to_uint ?
-#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
-
-Bool no_configure_window;
-
-static inline int
-configure_window (xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- if (!no_configure_window)
- return xp_configure_window (id, mask, values);
- else
- return XP_Success;
-}
-
-
-static
-void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
-{
- /* This is how we tell xp that the colormap may have changed. */
- xp_window_changes wc;
- wc.colormap = xprColormapCallback;
- wc.colormap_data = pScreen;
-
- configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
-}
-
-static
-void xprHideWindow(RootlessFrameID wid)
-{
- xp_window_changes wc;
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
- configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
-}
+/*
+ * Xplugin rootless implementation frame functions
+ *
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 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
+
+#include "xpr.h"
+#include "rootlessCommon.h"
+#include <Xplugin.h>
+#include "x-hash.h"
+#include "x-list.h"
+#include "applewmExt.h"
+
+#include "propertyst.h"
+#include "dix.h"
+#include <X11/Xatom.h>
+#include "windowstr.h"
+#include "quartz.h"
+
+#include "threadSafety.h"
+
+#include <pthread.h>
+
+#define DEFINE_ATOM_HELPER(func,atom_name) \
+static Atom func (void) { \
+ static int generation; \
+ static Atom atom; \
+ if (generation != serverGeneration) { \
+ generation = serverGeneration; \
+ atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
+ } \
+ return atom; \
+}
+
+DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
+
+/* Maps xp_window_id -> RootlessWindowRec */
+static x_hash_table *window_hash;
+static pthread_mutex_t window_hash_mutex;
+
+/* Prototypes for static functions */
+static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
+ int newX, int newY, RegionPtr pShape);
+static void xprDestroyFrame(RootlessFrameID wid);
+static void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
+static void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
+ int newX, int newY, unsigned int newW, unsigned int newH,
+ unsigned int gravity);
+static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
+static void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
+static void xprUnmapFrame(RootlessFrameID wid);
+static void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
+static void xprStopDrawing(RootlessFrameID wid, Bool flush);
+static void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
+static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
+ int shift_x, int shift_y);
+static void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
+static Bool xprDoReorderWindow(RootlessWindowPtr pFrame);
+static void xprHideWindow(RootlessFrameID wid);
+static void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
+static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
+ int dx, int dy);
+
+
+static inline xp_error
+xprConfigureWindow(xp_window_id id, unsigned int mask,
+ const xp_window_changes *values)
+{
+ TA_SERVER();
+
+ return xp_configure_window(id, mask, values);
+}
+
+
+static void
+xprSetNativeProperty(RootlessWindowPtr pFrame)
+{
+ xp_error err;
+ unsigned int native_id;
+ long data;
+
+ TA_SERVER();
+
+ err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
+ if (err == Success)
+ {
+ /* FIXME: move this to AppleWM extension */
+
+ data = native_id;
+ dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(),
+ XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
+ }
+}
+
+static xp_error
+xprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors)
+{
+ return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch);
+}
+
+/*
+ * Create and display a new frame.
+ */
+static Bool
+xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
+ int newX, int newY, RegionPtr pShape)
+{
+ WindowPtr pWin = pFrame->win;
+ xp_window_changes wc;
+ unsigned int mask = 0;
+ xp_error err;
+
+ TA_SERVER();
+
+ wc.x = newX;
+ wc.y = newY;
+ wc.width = pFrame->width;
+ wc.height = pFrame->height;
+ wc.bit_gravity = XP_GRAVITY_NONE;
+ mask |= XP_BOUNDS;
+
+ if (pWin->drawable.depth == 8)
+ {
+ wc.depth = XP_DEPTH_INDEX8;
+ wc.colormap = xprColormapCallback;
+ wc.colormap_data = pScreen;
+ mask |= XP_COLORMAP;
+ }
+ else if (pWin->drawable.depth == 15)
+ wc.depth = XP_DEPTH_RGB555;
+ else if (pWin->drawable.depth == 24)
+ wc.depth = XP_DEPTH_ARGB8888;
+ else
+ wc.depth = XP_DEPTH_NIL;
+ mask |= XP_DEPTH;
+
+ if (pShape != NULL)
+ {
+ wc.shape_nrects = RegionNumRects(pShape);
+ wc.shape_rects = RegionRects(pShape);
+ wc.shape_tx = wc.shape_ty = 0;
+ mask |= XP_SHAPE;
+ }
+
+ pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
+
+ if(quartzEnableRootless)
+ wc.window_level = normal_window_levels[pFrame->level];
+ else
+ wc.window_level = rooted_window_levels[pFrame->level];
+ mask |= XP_WINDOW_LEVEL;
+
+ err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid);
+
+ if (err != Success)
+ {
+ return FALSE;
+ }
+
+ if (window_hash == NULL)
+ {
+ window_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
+ pthread_mutex_init(&window_hash_mutex, NULL);
+ }
+
+ pthread_mutex_lock(&window_hash_mutex);
+ x_hash_table_insert(window_hash, pFrame->wid, pFrame);
+ pthread_mutex_unlock(&window_hash_mutex);
+
+ xprSetNativeProperty(pFrame);
+
+ return TRUE;
+}
+
+
+/*
+ * Destroy a frame.
+ */
+static void
+xprDestroyFrame(RootlessFrameID wid)
+{
+ 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));
+}
+
+
+/*
+ * Move a frame on screen.
+ */
+static void
+xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
+{
+ xp_window_changes wc;
+
+ TA_SERVER();
+
+ wc.x = newX;
+ wc.y = newY;
+ // ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
+}
+
+
+/*
+ * Resize and move a frame.
+ */
+static void
+xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
+ int newX, int newY, unsigned int newW, unsigned int newH,
+ unsigned int gravity)
+{
+ xp_window_changes wc;
+
+ TA_SERVER();
+
+ wc.x = newX;
+ wc.y = newY;
+ wc.width = newW;
+ wc.height = newH;
+ wc.bit_gravity = gravity;
+
+ /* It's unlikely that being async will save us anything here.
+ But it can't hurt. */
+
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
+}
+
+
+/*
+ * Change frame stacking.
+ */
+static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
+ xp_window_changes wc;
+ unsigned int mask = XP_STACKING;
+
+ TA_SERVER();
+
+ /* Stack frame below nextWid it if it exists, or raise
+ frame above everything otherwise. */
+
+ if(nextWid == NULL) {
+ wc.stack_mode = XP_MAPPED_ABOVE;
+ wc.sibling = 0;
+ } else {
+ wc.stack_mode = XP_MAPPED_BELOW;
+ wc.sibling = x_cvt_vptr_to_uint(nextWid);
+ }
+
+ if(window_hash) {
+ RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL);
+
+ if(winRec) {
+ if(quartzEnableRootless)
+ wc.window_level = normal_window_levels[winRec->level];
+ else
+ wc.window_level = rooted_window_levels[winRec->level];
+ mask |= XP_WINDOW_LEVEL;
+ }
+ }
+
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
+}
+
+
+/*
+ * Change the frame's shape.
+ */
+static void
+xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
+{
+ xp_window_changes wc;
+
+ TA_SERVER();
+
+ if (pShape != NULL)
+ {
+ wc.shape_nrects = RegionNumRects(pShape);
+ wc.shape_rects = RegionRects(pShape);
+ }
+ else
+ {
+ wc.shape_nrects = -1;
+ wc.shape_rects = NULL;
+ }
+
+ wc.shape_tx = wc.shape_ty = 0;
+
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
+}
+
+
+/*
+ * Unmap a frame.
+ */
+static void
+xprUnmapFrame(RootlessFrameID wid)
+{
+ xp_window_changes wc;
+
+ TA_SERVER();
+
+ wc.stack_mode = XP_UNMAPPED;
+ wc.sibling = 0;
+
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
+}
+
+
+/*
+ * Start drawing to a frame.
+ * Prepare for direct access to its backing buffer.
+ */
+static void
+xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
+{
+ void *data[2];
+ unsigned int rowbytes[2];
+ xp_error err;
+
+ TA_SERVER();
+
+ err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL);
+ if (err != Success)
+ FatalError("Could not lock window %i for drawing.", (int)x_cvt_vptr_to_uint(wid));
+
+ *pixelData = data[0];
+ *bytesPerRow = rowbytes[0];
+}
+
+
+/*
+ * Stop drawing to a frame.
+ */
+static void
+xprStopDrawing(RootlessFrameID wid, Bool flush)
+{
+ TA_SERVER();
+
+ xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
+}
+
+
+/*
+ * Flush drawing updates to the screen.
+ */
+static void
+xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
+{
+ TA_SERVER();
+
+ xp_flush_window(x_cvt_vptr_to_uint(wid));
+}
+
+
+/*
+ * Mark damaged rectangles as requiring redisplay to screen.
+ */
+static void
+xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
+ int shift_x, int shift_y)
+{
+ TA_SERVER();
+
+ xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
+}
+
+
+/*
+ * Called after the window associated with a frame has been switched
+ * to a new top-level parent.
+ */
+static void
+xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
+{
+ DeleteProperty(serverClient, oldWin, xa_native_window_id());
+
+ TA_SERVER();
+
+ xprSetNativeProperty(pFrame);
+}
+
+
+/*
+ * Called to check if the frame should be reordered when it is restacked.
+ */
+static Bool xprDoReorderWindow(RootlessWindowPtr pFrame)
+{
+ WindowPtr pWin = pFrame->win;
+
+ TA_SERVER();
+
+ return AppleWMDoReorderWindow(pWin);
+}
+
+
+/*
+ * Copy area in frame to another part of frame.
+ * Used to accelerate scrolling.
+ */
+static void
+xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
+ int dx, int dy)
+{
+ TA_SERVER();
+
+ xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
+ dstNrects, dstRects, dx, dy);
+}
+
+
+static RootlessFrameProcsRec xprRootlessProcs = {
+ xprCreateFrame,
+ xprDestroyFrame,
+ xprMoveFrame,
+ xprResizeFrame,
+ xprRestackFrame,
+ xprReshapeFrame,
+ xprUnmapFrame,
+ xprStartDrawing,
+ xprStopDrawing,
+ xprUpdateRegion,
+ xprDamageRects,
+ xprSwitchWindow,
+ xprDoReorderWindow,
+ xprHideWindow,
+ xprUpdateColormap,
+ xp_copy_bytes,
+ xp_fill_bytes,
+ xp_composite_pixels,
+ xprCopyWindow
+};
+
+
+/*
+ * Initialize XPR implementation
+ */
+Bool
+xprInit(ScreenPtr pScreen)
+{
+ RootlessInit(pScreen, &xprRootlessProcs);
+
+ TA_SERVER();
+
+ rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
+ rootless_FillBytes_threshold = xp_fill_bytes_threshold;
+ rootless_CompositePixels_threshold = xp_composite_area_threshold;
+ rootless_CopyWindow_threshold = xp_scroll_area_threshold;
+
+ return TRUE;
+}
+
+
+/*
+ * Given the id of a physical window, try to find the top-level (or root)
+ * X window that it represents.
+ */
+WindowPtr
+xprGetXWindow(xp_window_id wid)
+{
+ RootlessWindowRec *winRec;
+
+ if (window_hash == NULL)
+ return NULL;
+
+ winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
+
+ return winRec != NULL ? winRec->win : NULL;
+}
+
+#ifdef UNUSED_CODE
+/*
+ * Given the id of a physical window, try to find the top-level (or root)
+ * X window that it represents.
+ */
+WindowPtr
+xprGetXWindowFromAppKit(int windowNumber)
+{
+ RootlessWindowRec *winRec;
+ Bool ret;
+ xp_window_id wid;
+
+ if (window_hash == NULL)
+ return FALSE;
+
+ /* need to lock, since this function can be called by any thread */
+
+ pthread_mutex_lock(&window_hash_mutex);
+
+ if (xp_lookup_native_window(windowNumber, &wid))
+ ret = xprGetXWindow(wid) != NULL;
+ else
+ ret = FALSE;
+
+ pthread_mutex_unlock(&window_hash_mutex);
+
+ if (!ret) return NULL;
+ winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
+
+ return winRec != NULL ? winRec->win : NULL;
+}
+#endif
+
+/*
+ * The windowNumber is an AppKit window number. Returns TRUE if xpr is
+ * displaying a window with that number.
+ */
+Bool
+xprIsX11Window(void *nsWindow, int windowNumber)
+{
+ Bool ret;
+ xp_window_id wid;
+
+ if (window_hash == NULL)
+ return FALSE;
+
+ /* need to lock, since this function can be called by any thread */
+
+ pthread_mutex_lock(&window_hash_mutex);
+
+ if (xp_lookup_native_window(windowNumber, &wid))
+ ret = xprGetXWindow(wid) != NULL;
+ else
+ ret = FALSE;
+
+ pthread_mutex_unlock(&window_hash_mutex);
+
+ return ret;
+}
+
+
+/*
+ * xprHideWindows
+ * Hide or unhide all top level windows. This is called for application hide/
+ * unhide events if the window manager is not Apple-WM aware. Xplugin windows
+ * do not hide or unhide themselves.
+ */
+void
+xprHideWindows(Bool hide)
+{
+ int screen;
+ WindowPtr pRoot, pWin;
+
+ TA_SERVER();
+
+ for (screen = 0; screen < screenInfo.numScreens; screen++) {
+ RootlessFrameID prevWid = NULL;
+ pRoot = screenInfo.screens[screen]->root;
+
+ for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ if (winRec != NULL) {
+ if (hide) {
+ xprUnmapFrame(winRec->wid);
+ } else {
+ BoxRec box;
+
+ xprRestackFrame(winRec->wid, prevWid);
+ prevWid = winRec->wid;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = winRec->width;
+ box.y2 = winRec->height;
+
+ xprDamageRects(winRec->wid, 1, &box, 0, 0);
+ RootlessQueueRedisplay(screenInfo.screens[screen]);
+ }
+ }
+ }
+ }
+}
+
+// XXX: identical to x_cvt_vptr_to_uint ?
+#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
+
+Bool no_configure_window;
+
+static inline int
+configure_window (xp_window_id id, unsigned int mask,
+ const xp_window_changes *values)
+{
+ if (!no_configure_window)
+ return xp_configure_window (id, mask, values);
+ else
+ return XP_Success;
+}
+
+
+static
+void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
+{
+ /* This is how we tell xp that the colormap may have changed. */
+ xp_window_changes wc;
+ wc.colormap = xprColormapCallback;
+ wc.colormap_data = pScreen;
+
+ configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
+}
+
+static
+void xprHideWindow(RootlessFrameID wid)
+{
+ xp_window_changes wc;
+ wc.stack_mode = XP_UNMAPPED;
+ wc.sibling = 0;
+ configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
+}
diff --git a/xorg-server/hw/xquartz/xpr/xprScreen.c b/xorg-server/hw/xquartz/xpr/xprScreen.c
index bc68f7923..d4fef8e0a 100644
--- a/xorg-server/hw/xquartz/xpr/xprScreen.c
+++ b/xorg-server/hw/xquartz/xpr/xprScreen.c
@@ -397,7 +397,7 @@ xprUpdateScreen(ScreenPtr pScreen)
rootlessGlobalOffsetX = darwinMainScreenX;
rootlessGlobalOffsetY = darwinMainScreenY;
- AppleWMSetScreenOrigin(WindowTable[pScreen->myNum]);
+ AppleWMSetScreenOrigin(pScreen->root);
RootlessRepositionWindows(pScreen);
RootlessUpdateScreenPixmap(pScreen);
@@ -416,7 +416,7 @@ xprInitInput(int argc, char **argv)
rootlessGlobalOffsetY = darwinMainScreenY;
for (i = 0; i < screenInfo.numScreens; i++)
- AppleWMSetScreenOrigin(WindowTable[i]);
+ AppleWMSetScreenOrigin(screenInfo.screens[i]->root);
}
/*