aboutsummaryrefslogtreecommitdiff
path: root/xorg-server
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server')
-rw-r--r--xorg-server/Xext/xtest.c2
-rw-r--r--xorg-server/Xi/exevents.c11
-rw-r--r--xorg-server/Xi/extinit.c2
-rw-r--r--xorg-server/Xi/xichangehierarchy.c2
-rw-r--r--xorg-server/Xi/xipassivegrab.c622
-rw-r--r--xorg-server/composite/compalloc.c1396
-rw-r--r--xorg-server/configure.ac16
-rw-r--r--xorg-server/dix/devices.c49
-rw-r--r--xorg-server/dix/getevents.c21
-rw-r--r--xorg-server/dix/ptrveloc.c2484
-rw-r--r--xorg-server/dix/resource.c1926
-rw-r--r--xorg-server/glx/Makefile.am199
-rw-r--r--xorg-server/glx/glxcmds.c4665
-rw-r--r--xorg-server/glx/glxdri2.c1583
-rw-r--r--xorg-server/glx/glxext.c1108
-rw-r--r--xorg-server/hw/dmx/input/dmxevents.c1600
-rw-r--r--xorg-server/hw/kdrive/src/kinput.c4
-rw-r--r--xorg-server/hw/xfree86/common/xf86Configure.c1517
-rw-r--r--xorg-server/hw/xfree86/common/xf86Events.c2
-rw-r--r--xorg-server/hw/xfree86/common/xf86Xinput.c15
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/lnx_init.c675
-rw-r--r--xorg-server/hw/xnest/Events.c466
-rw-r--r--xorg-server/hw/xquartz/X11Application.m78
-rw-r--r--xorg-server/hw/xquartz/darwin.c3
-rw-r--r--xorg-server/hw/xquartz/darwin.h1
-rw-r--r--xorg-server/hw/xquartz/darwinEvents.c50
-rw-r--r--xorg-server/hw/xquartz/darwinEvents.h3
-rw-r--r--xorg-server/hw/xquartz/mach-startup/bundle-main.c1389
-rw-r--r--xorg-server/hw/xwin/winkeybd.c1062
-rw-r--r--xorg-server/include/dix-config.h.in3
-rw-r--r--xorg-server/include/input.h11
-rw-r--r--xorg-server/include/inputstr.h2
-rw-r--r--xorg-server/include/ptrveloc.h288
-rw-r--r--xorg-server/test/Makefile.am6
-rw-r--r--xorg-server/test/input.c523
-rw-r--r--xorg-server/test/list.c349
-rw-r--r--xorg-server/test/xi2/Makefile.am10
-rw-r--r--xorg-server/test/xi2/protocol-common.c355
-rw-r--r--xorg-server/test/xi2/protocol-common.h11
-rw-r--r--xorg-server/test/xi2/protocol-eventconvert.c172
-rw-r--r--xorg-server/test/xi2/protocol-xigetclientpointer.c31
-rw-r--r--xorg-server/test/xi2/protocol-xigetselectedevents.c28
-rw-r--r--xorg-server/test/xi2/protocol-xipassivegrabdevice.c234
-rw-r--r--xorg-server/test/xi2/protocol-xiquerydevice.c98
-rw-r--r--xorg-server/test/xi2/protocol-xiquerypointer.c38
-rw-r--r--xorg-server/test/xi2/protocol-xiqueryversion.c28
-rw-r--r--xorg-server/test/xi2/protocol-xiselectevents.c24
-rw-r--r--xorg-server/test/xi2/protocol-xisetclientpointer.c32
-rw-r--r--xorg-server/test/xi2/protocol-xiwarppointer.c24
-rw-r--r--xorg-server/test/xkb.c76
-rw-r--r--xorg-server/test/xtest.c231
-rw-r--r--xorg-server/xkeyboard-config/rules/base.extras.xml.in20
-rw-r--r--xorg-server/xkeyboard-config/symbols/apl2
-rw-r--r--xorg-server/xkeyboard-config/symbols/et2
-rw-r--r--xorg-server/xkeyboard-config/symbols/lv2
-rw-r--r--xorg-server/xkeyboard-config/symbols/us4
-rw-r--r--xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh94
57 files changed, 11996 insertions, 11653 deletions
diff --git a/xorg-server/Xext/xtest.c b/xorg-server/Xext/xtest.c
index 6780aa62a..18e1ef7ae 100644
--- a/xorg-server/Xext/xtest.c
+++ b/xorg-server/Xext/xtest.c
@@ -423,7 +423,7 @@ ProcXTestFakeInput(ClientPtr client)
break;
case KeyPress:
case KeyRelease:
- nevents = GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail);
+ nevents = GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail, NULL);
break;
}
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c
index 18803c95e..76d5c3759 100644
--- a/xorg-server/Xi/exevents.c
+++ b/xorg-server/Xi/exevents.c
@@ -535,6 +535,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
if (from->valuator)
{
ValuatorClassPtr v;
+
if (!to->valuator)
{
classes = to->unused_classes;
@@ -543,18 +544,14 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
classes->valuator = NULL;
}
- to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
- from->valuator->numAxes * sizeof(AxisInfo) +
- from->valuator->numAxes * sizeof(double));
- v = to->valuator;
+ v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
+
if (!v)
FatalError("[Xi] no memory for class shift.\n");
- v->numAxes = from->valuator->numAxes;
- v->axes = (AxisInfoPtr)&v[1];
+ to->valuator = v;
memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
- v->axisVal = (double*)(v->axes + from->valuator->numAxes);
v->sourceid = from->id;
} else if (to->valuator && !from->valuator)
{
diff --git a/xorg-server/Xi/extinit.c b/xorg-server/Xi/extinit.c
index 0b7280d95..51e00783c 100644
--- a/xorg-server/Xi/extinit.c
+++ b/xorg-server/Xi/extinit.c
@@ -511,7 +511,7 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
SRepXIQueryDevice(client, len, (xXIQueryDeviceReply*)rep);
else if (rep->RepType == X_XIGrabDevice)
SRepXIGrabDevice(client, len, (xXIGrabDeviceReply *) rep);
- else if (rep->RepType == X_XIGrabDevice)
+ else if (rep->RepType == X_XIPassiveGrabDevice)
SRepXIPassiveGrabDevice(client, len, (xXIPassiveGrabDeviceReply *) rep);
else if (rep->RepType == X_XIListProperties)
SRepXIListProperties(client, len, (xXIListPropertiesReply *) rep);
diff --git a/xorg-server/Xi/xichangehierarchy.c b/xorg-server/Xi/xichangehierarchy.c
index a3dcab57e..0736a5a36 100644
--- a/xorg-server/Xi/xichangehierarchy.c
+++ b/xorg-server/Xi/xichangehierarchy.c
@@ -116,7 +116,9 @@ void XISendDeviceHierarchyEvent(int flags[MAXDEVICES])
ev->length = bytes_to_int32(ev->num_info * sizeof(xXIHierarchyInfo));
+ memset(&dummyDev, 0, sizeof(dummyDev));
dummyDev.id = XIAllDevices;
+ dummyDev.type = SLAVE;
SendEventToAllWindows(&dummyDev, (XI_HierarchyChangedMask >> 8), (xEvent*)ev, 1);
free(ev);
}
diff --git a/xorg-server/Xi/xipassivegrab.c b/xorg-server/Xi/xipassivegrab.c
index 487c2721b..ae4343344 100644
--- a/xorg-server/Xi/xipassivegrab.c
+++ b/xorg-server/Xi/xipassivegrab.c
@@ -1,307 +1,315 @@
-/*
- * Copyright © 2009 Red Hat, 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- *
- * Author: Peter Hutterer
- */
-
-/***********************************************************************
- *
- * Request to grab or ungrab input device.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include <X11/extensions/XI2.h>
-#include <X11/extensions/XI2proto.h>
-#include "swaprep.h"
-
-#include "exglobals.h" /* BadDevice */
-#include "exevents.h"
-#include "xipassivegrab.h"
-#include "dixgrabs.h"
-
-int
-SProcXIPassiveGrabDevice(ClientPtr client)
-{
- int i;
- char n;
- xXIModifierInfo *mods;
-
- REQUEST(xXIPassiveGrabDeviceReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->grab_window, n);
- swapl(&stuff->cursor, n);
- swapl(&stuff->time, n);
- swapl(&stuff->detail, n);
- swaps(&stuff->mask_len, n);
- swaps(&stuff->num_modifiers, n);
-
- mods = (xXIModifierInfo*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, mods++)
- {
- swapl(&mods->base_mods, n);
- swapl(&mods->latched_mods, n);
- swapl(&mods->locked_mods, n);
- }
-
- return ProcXIPassiveGrabDevice(client);
-}
-
-int
-ProcXIPassiveGrabDevice(ClientPtr client)
-{
- DeviceIntPtr dev, mod_dev;
- xXIPassiveGrabDeviceReply rep;
- int i, ret = Success;
- uint8_t status;
- uint32_t *modifiers;
- xXIGrabModifierInfo *modifiers_failed;
- GrabMask mask;
- GrabParameters param;
- void *tmp;
- int mask_len;
-
- REQUEST(xXIPassiveGrabDeviceReq);
- REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
-
- if (stuff->deviceid == XIAllDevices)
- dev = inputInfo.all_devices;
- else if (stuff->deviceid == XIAllMasterDevices)
- dev = inputInfo.all_master_devices;
- else
- {
- ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
- if (ret != Success)
- return ret;
- }
-
- if (stuff->grab_type != XIGrabtypeButton &&
- stuff->grab_type != XIGrabtypeKeycode &&
- stuff->grab_type != XIGrabtypeEnter &&
- stuff->grab_type != XIGrabtypeFocusIn)
- {
- client->errorValue = stuff->grab_type;
- return BadValue;
- }
-
- if ((stuff->grab_type == XIGrabtypeEnter ||
- stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
- {
- client->errorValue = stuff->detail;
- return BadValue;
- }
-
- if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
- stuff->mask_len * 4) != Success)
- return BadValue;
-
- mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
- memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
- memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
-
- rep.repType = X_Reply;
- rep.RepType = X_XIPassiveGrabDevice;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.num_modifiers = 0;
-
- memset(&param, 0, sizeof(param));
- param.grabtype = GRABTYPE_XI2;
- param.ownerEvents = stuff->owner_events;
- param.this_device_mode = stuff->grab_mode;
- param.other_devices_mode = stuff->paired_device_mode;
- param.grabWindow = stuff->grab_window;
- param.cursor = stuff->cursor;
-
- if (stuff->cursor != None)
- {
- status = dixLookupResourceByType(&tmp, stuff->cursor,
- RT_CURSOR, client, DixUseAccess);
- if (status != Success)
- {
- client->errorValue = stuff->cursor;
- return status;
- }
- }
-
- status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
- if (status != Success)
- return status;
-
- status = CheckGrabValues(client, &param);
-
- modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
- modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
- if (!modifiers_failed)
- return BadAlloc;
-
- mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- {
- param.modifiers = *modifiers;
- switch(stuff->grab_type)
- {
- case XIGrabtypeButton:
- status = GrabButton(client, dev, mod_dev, stuff->detail,
- &param, GRABTYPE_XI2, &mask);
- break;
- case XIGrabtypeKeycode:
- status = GrabKey(client, dev, mod_dev, stuff->detail,
- &param, GRABTYPE_XI2, &mask);
- break;
- case XIGrabtypeEnter:
- case XIGrabtypeFocusIn:
- status = GrabWindow(client, dev, stuff->grab_type,
- &param, &mask);
- break;
- }
-
- if (status != GrabSuccess)
- {
- xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
-
- info->status = status;
- info->modifiers = *modifiers;
- rep.num_modifiers++;
- rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo));
- }
- }
-
- WriteReplyToClient(client, sizeof(rep), &rep);
- if (rep.num_modifiers)
- {
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, rep.length * 4, (char*)modifiers_failed);
- }
- free(modifiers_failed);
- return ret;
-}
-
-void
-SRepXIPassiveGrabDevice(ClientPtr client, int size,
- xXIPassiveGrabDeviceReply * rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swaps(&rep->num_modifiers, n);
-
- WriteToClient(client, size, (char *)rep);
-}
-
-int
-SProcXIPassiveUngrabDevice(ClientPtr client)
-{
- char n;
- int i;
- uint32_t *modifiers;
-
- REQUEST(xXIPassiveUngrabDeviceReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->grab_window, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->detail, n);
- swaps(&stuff->num_modifiers, n);
-
- modifiers = (uint32_t*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- swapl(modifiers, n);
-
- return ProcXIPassiveUngrabDevice(client);
-}
-
-int
-ProcXIPassiveUngrabDevice(ClientPtr client)
-{
- DeviceIntPtr dev, mod_dev;
- WindowPtr win;
- GrabRec tempGrab;
- uint32_t* modifiers;
- int i, rc;
-
- REQUEST(xXIPassiveUngrabDeviceReq);
- REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
-
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
- if (rc != Success)
- return rc;
-
- if (stuff->grab_type != XIGrabtypeButton &&
- stuff->grab_type != XIGrabtypeKeycode &&
- stuff->grab_type != XIGrabtypeEnter &&
- stuff->grab_type != XIGrabtypeFocusIn)
- {
- client->errorValue = stuff->grab_type;
- return BadValue;
- }
-
- if ((stuff->grab_type == XIGrabtypeEnter ||
- stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
- {
- client->errorValue = stuff->detail;
- return BadValue;
- }
-
- rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
-
- mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
-
- tempGrab.resource = client->clientAsMask;
- tempGrab.device = dev;
- tempGrab.window = win;
- switch(stuff->grab_type)
- {
- case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break;
- case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break;
- case XIGrabtypeEnter: tempGrab.type = XI_Enter; break;
- case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break;
- }
- tempGrab.grabtype = GRABTYPE_XI2;
- tempGrab.modifierDevice = mod_dev;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.detail.exact = stuff->detail;
- tempGrab.detail.pMask = NULL;
-
- modifiers = (uint32_t*)&stuff[1];
-
- for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
- {
- tempGrab.modifiersDetail.exact = *modifiers;
- DeletePassiveGrabFromList(&tempGrab);
- }
-
- return Success;
-}
+/*
+ * Copyright © 2009 Red Hat, 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer
+ */
+
+/***********************************************************************
+ *
+ * Request to grab or ungrab input device.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include <X11/extensions/XI2.h>
+#include <X11/extensions/XI2proto.h>
+#include "swaprep.h"
+
+#include "exglobals.h" /* BadDevice */
+#include "exevents.h"
+#include "xipassivegrab.h"
+#include "dixgrabs.h"
+#include "misc.h"
+
+int
+SProcXIPassiveGrabDevice(ClientPtr client)
+{
+ int i;
+ char n;
+ xXIModifierInfo *mods;
+
+ REQUEST(xXIPassiveGrabDeviceReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->grab_window, n);
+ swapl(&stuff->cursor, n);
+ swapl(&stuff->time, n);
+ swapl(&stuff->detail, n);
+ swaps(&stuff->mask_len, n);
+ swaps(&stuff->num_modifiers, n);
+
+ mods = (xXIModifierInfo*)&stuff[1];
+
+ for (i = 0; i < stuff->num_modifiers; i++, mods++)
+ {
+ swapl(&mods->base_mods, n);
+ swapl(&mods->latched_mods, n);
+ swapl(&mods->locked_mods, n);
+ }
+
+ return ProcXIPassiveGrabDevice(client);
+}
+
+int
+ProcXIPassiveGrabDevice(ClientPtr client)
+{
+ DeviceIntPtr dev, mod_dev;
+ xXIPassiveGrabDeviceReply rep;
+ int i, ret = Success;
+ uint8_t status;
+ uint32_t *modifiers;
+ xXIGrabModifierInfo *modifiers_failed;
+ GrabMask mask;
+ GrabParameters param;
+ void *tmp;
+ int mask_len;
+ int n;
+
+ REQUEST(xXIPassiveGrabDeviceReq);
+ REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
+
+ if (stuff->deviceid == XIAllDevices)
+ dev = inputInfo.all_devices;
+ else if (stuff->deviceid == XIAllMasterDevices)
+ dev = inputInfo.all_master_devices;
+ else
+ {
+ ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
+ if (ret != Success)
+ {
+ client->errorValue = stuff->deviceid;
+ return ret;
+ }
+ }
+
+ if (stuff->grab_type != XIGrabtypeButton &&
+ stuff->grab_type != XIGrabtypeKeycode &&
+ stuff->grab_type != XIGrabtypeEnter &&
+ stuff->grab_type != XIGrabtypeFocusIn)
+ {
+ client->errorValue = stuff->grab_type;
+ return BadValue;
+ }
+
+ if ((stuff->grab_type == XIGrabtypeEnter ||
+ stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
+ {
+ client->errorValue = stuff->detail;
+ return BadValue;
+ }
+
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
+ stuff->mask_len * 4) != Success)
+ return BadValue;
+
+ mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
+ memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
+ memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_XIPassiveGrabDevice;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.num_modifiers = 0;
+
+ memset(&param, 0, sizeof(param));
+ param.grabtype = GRABTYPE_XI2;
+ param.ownerEvents = stuff->owner_events;
+ param.this_device_mode = stuff->grab_mode;
+ param.other_devices_mode = stuff->paired_device_mode;
+ param.grabWindow = stuff->grab_window;
+ param.cursor = stuff->cursor;
+
+ if (stuff->cursor != None)
+ {
+ status = dixLookupResourceByType(&tmp, stuff->cursor,
+ RT_CURSOR, client, DixUseAccess);
+ if (status != Success)
+ {
+ client->errorValue = stuff->cursor;
+ return status;
+ }
+ }
+
+ status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
+ if (status != Success)
+ return status;
+
+ status = CheckGrabValues(client, &param);
+ if (status != Success)
+ return status;
+
+ modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
+ modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
+ if (!modifiers_failed)
+ return BadAlloc;
+
+ mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
+
+ for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
+ {
+ param.modifiers = *modifiers;
+ switch(stuff->grab_type)
+ {
+ case XIGrabtypeButton:
+ status = GrabButton(client, dev, mod_dev, stuff->detail,
+ &param, GRABTYPE_XI2, &mask);
+ break;
+ case XIGrabtypeKeycode:
+ status = GrabKey(client, dev, mod_dev, stuff->detail,
+ &param, GRABTYPE_XI2, &mask);
+ break;
+ case XIGrabtypeEnter:
+ case XIGrabtypeFocusIn:
+ status = GrabWindow(client, dev, stuff->grab_type,
+ &param, &mask);
+ break;
+ }
+
+ if (status != GrabSuccess)
+ {
+ xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
+
+ info->status = status;
+ info->modifiers = *modifiers;
+ if (client->swapped)
+ swapl(&info->modifiers, n);
+
+ rep.num_modifiers++;
+ rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo));
+ }
+ }
+
+ WriteReplyToClient(client, sizeof(rep), &rep);
+ if (rep.num_modifiers)
+ WriteToClient(client, rep.length * 4, (char*)modifiers_failed);
+
+ free(modifiers_failed);
+ return ret;
+}
+
+void
+SRepXIPassiveGrabDevice(ClientPtr client, int size,
+ xXIPassiveGrabDeviceReply * rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->num_modifiers, n);
+
+ WriteToClient(client, size, (char *)rep);
+}
+
+int
+SProcXIPassiveUngrabDevice(ClientPtr client)
+{
+ char n;
+ int i;
+ uint32_t *modifiers;
+
+ REQUEST(xXIPassiveUngrabDeviceReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->grab_window, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->detail, n);
+ swaps(&stuff->num_modifiers, n);
+
+ modifiers = (uint32_t*)&stuff[1];
+
+ for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
+ swapl(modifiers, n);
+
+ return ProcXIPassiveUngrabDevice(client);
+}
+
+int
+ProcXIPassiveUngrabDevice(ClientPtr client)
+{
+ DeviceIntPtr dev, mod_dev;
+ WindowPtr win;
+ GrabRec tempGrab;
+ uint32_t* modifiers;
+ int i, rc;
+
+ REQUEST(xXIPassiveUngrabDeviceReq);
+ REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
+
+ rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->grab_type != XIGrabtypeButton &&
+ stuff->grab_type != XIGrabtypeKeycode &&
+ stuff->grab_type != XIGrabtypeEnter &&
+ stuff->grab_type != XIGrabtypeFocusIn)
+ {
+ client->errorValue = stuff->grab_type;
+ return BadValue;
+ }
+
+ if ((stuff->grab_type == XIGrabtypeEnter ||
+ stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
+ {
+ client->errorValue = stuff->detail;
+ return BadValue;
+ }
+
+ rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
+
+ tempGrab.resource = client->clientAsMask;
+ tempGrab.device = dev;
+ tempGrab.window = win;
+ switch(stuff->grab_type)
+ {
+ case XIGrabtypeButton: tempGrab.type = XI_ButtonPress; break;
+ case XIGrabtypeKeycode: tempGrab.type = XI_KeyPress; break;
+ case XIGrabtypeEnter: tempGrab.type = XI_Enter; break;
+ case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn; break;
+ }
+ tempGrab.grabtype = GRABTYPE_XI2;
+ tempGrab.modifierDevice = mod_dev;
+ tempGrab.modifiersDetail.pMask = NULL;
+ tempGrab.detail.exact = stuff->detail;
+ tempGrab.detail.pMask = NULL;
+
+ modifiers = (uint32_t*)&stuff[1];
+
+ for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
+ {
+ tempGrab.modifiersDetail.exact = *modifiers;
+ DeletePassiveGrabFromList(&tempGrab);
+ }
+
+ return Success;
+}
diff --git a/xorg-server/composite/compalloc.c b/xorg-server/composite/compalloc.c
index 745166621..7164c0d3c 100644
--- a/xorg-server/composite/compalloc.c
+++ b/xorg-server/composite/compalloc.c
@@ -1,711 +1,685 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- *
- * Copyright © 2003 Keith Packard
- *
- * 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, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "compint.h"
-
-static void
-compScreenUpdate (ScreenPtr pScreen)
-{
- compCheckTree (pScreen);
- compPaintChildrenToWindow (pScreen->root);
-}
-
-static void
-compBlockHandler (int i,
- pointer blockData,
- pointer pTimeout,
- pointer pReadmask)
-{
- ScreenPtr pScreen = screenInfo.screens[i];
- CompScreenPtr cs = GetCompScreen (pScreen);
-
- pScreen->BlockHandler = cs->BlockHandler;
- compScreenUpdate (pScreen);
- (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
-
- /* Next damage will restore the block handler */
- cs->BlockHandler = NULL;
-}
-
-static void
-compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
-{
- WindowPtr pWin = (WindowPtr) closure;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- CompScreenPtr cs = GetCompScreen (pScreen);
- CompWindowPtr cw = GetCompWindow (pWin);
-
- if (!cs->BlockHandler) {
- cs->BlockHandler = pScreen->BlockHandler;
- pScreen->BlockHandler = compBlockHandler;
- }
- cw->damaged = TRUE;
-
- /* Mark the ancestors */
- pWin = pWin->parent;
- while (pWin) {
- if (pWin->damagedDescendants)
- break;
- pWin->damagedDescendants = TRUE;
- pWin = pWin->parent;
- }
-}
-
-static void
-compDestroyDamage (DamagePtr pDamage, void *closure)
-{
- WindowPtr pWin = (WindowPtr) closure;
- CompWindowPtr cw = GetCompWindow (pWin);
-
- cw->damage = 0;
-}
-
-/*
- * Redirect one window for one client
- */
-int
-compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
-{
- CompWindowPtr cw = GetCompWindow (pWin);
- CompClientWindowPtr ccw;
- Bool wasMapped = pWin->mapped;
- CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
-
- if (pWin == cs->pOverlayWin) {
- return Success;
- }
-
- if (!pWin->parent)
- return BadMatch;
-
- /*
- * Only one Manual update is allowed
- */
- if (cw && update == CompositeRedirectManual)
- for (ccw = cw->clients; ccw; ccw = ccw->next)
- if (ccw->update == CompositeRedirectManual)
- return BadAccess;
-
- /*
- * Allocate per-client per-window structure
- * The client *could* allocate multiple, but while supported,
- * it is not expected to be common
- */
- ccw = malloc(sizeof (CompClientWindowRec));
- if (!ccw)
- return BadAlloc;
- ccw->id = FakeClientID (pClient->index);
- ccw->update = update;
- /*
- * Now make sure there's a per-window structure to hang this from
- */
- if (!cw)
- {
- cw = malloc(sizeof (CompWindowRec));
- if (!cw)
- {
- free(ccw);
- return BadAlloc;
- }
- cw->damage = DamageCreate (compReportDamage,
- compDestroyDamage,
- DamageReportNonEmpty,
- FALSE,
- pWin->drawable.pScreen,
- pWin);
- if (!cw->damage)
- {
- free(ccw);
- free(cw);
- return BadAlloc;
- }
- if (wasMapped)
- {
- DisableMapUnmapEvents (pWin);
- UnmapWindow (pWin, FALSE);
- EnableMapUnmapEvents (pWin);
- }
-
- RegionNull(&cw->borderClip);
- cw->borderClipX = 0;
- cw->borderClipY = 0;
- cw->update = CompositeRedirectAutomatic;
- cw->clients = 0;
- cw->oldx = COMP_ORIGIN_INVALID;
- cw->oldy = COMP_ORIGIN_INVALID;
- cw->damageRegistered = FALSE;
- cw->damaged = FALSE;
- cw->pOldPixmap = NullPixmap;
- dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
- }
- ccw->next = cw->clients;
- cw->clients = ccw;
- if (!AddResource (ccw->id, CompositeClientWindowType, pWin))
- return BadAlloc;
- if (ccw->update == CompositeRedirectManual)
- {
- /* If the window was CompositeRedirectAutomatic, then
- * unmap the window so that the parent clip list will
- * be correctly recomputed.
- */
- if (pWin->mapped)
- {
- DisableMapUnmapEvents (pWin);
- UnmapWindow (pWin, FALSE);
- EnableMapUnmapEvents (pWin);
- }
- if (cw->damageRegistered)
- {
- DamageUnregister (&pWin->drawable, cw->damage);
- cw->damageRegistered = FALSE;
- }
- cw->update = CompositeRedirectManual;
- }
-
- if (!compCheckRedirect (pWin))
- {
- FreeResource (ccw->id, RT_NONE);
- return BadAlloc;
- }
- if (wasMapped && !pWin->mapped)
- {
- Bool overrideRedirect = pWin->overrideRedirect;
- pWin->overrideRedirect = TRUE;
- DisableMapUnmapEvents (pWin);
- MapWindow (pWin, pClient);
- EnableMapUnmapEvents (pWin);
- pWin->overrideRedirect = overrideRedirect;
- }
-
- return Success;
-}
-
-/*
- * Free one of the per-client per-window resources, clearing
- * redirect and the per-window pointer as appropriate
- */
-void
-compFreeClientWindow (WindowPtr pWin, XID id)
-{
- CompWindowPtr cw = GetCompWindow (pWin);
- CompClientWindowPtr ccw, *prev;
- Bool wasMapped = pWin->mapped;
-
- if (!cw)
- return;
- for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next)
- {
- if (ccw->id == id)
- {
- *prev = ccw->next;
- if (ccw->update == CompositeRedirectManual)
- cw->update = CompositeRedirectAutomatic;
- free(ccw);
- break;
- }
- }
- if (!cw->clients)
- {
- if (wasMapped)
- {
- DisableMapUnmapEvents (pWin);
- UnmapWindow (pWin, FALSE);
- EnableMapUnmapEvents (pWin);
- }
-
- if (pWin->redirectDraw != RedirectDrawNone)
- compFreePixmap (pWin);
-
- if (cw->damage)
- DamageDestroy (cw->damage);
-
- RegionUninit(&cw->borderClip);
-
- dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
- free(cw);
- }
- else if (cw->update == CompositeRedirectAutomatic &&
- !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone)
- {
- DamageRegister (&pWin->drawable, cw->damage);
- cw->damageRegistered = TRUE;
- pWin->redirectDraw = RedirectDrawAutomatic;
- DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
- }
- if (wasMapped && !pWin->mapped)
- {
- Bool overrideRedirect = pWin->overrideRedirect;
- pWin->overrideRedirect = TRUE;
- DisableMapUnmapEvents (pWin);
- MapWindow (pWin, clients[CLIENT_ID(id)]);
- EnableMapUnmapEvents (pWin);
- pWin->overrideRedirect = overrideRedirect;
- }
-}
-
-/*
- * This is easy, just free the appropriate resource.
- */
-
-int
-compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
-{
- CompWindowPtr cw = GetCompWindow (pWin);
- CompClientWindowPtr ccw;
-
- if (!cw)
- return BadValue;
-
- for (ccw = cw->clients; ccw; ccw = ccw->next)
- if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
- {
- FreeResource (ccw->id, RT_NONE);
- return Success;
- }
- return BadValue;
-}
-
-/*
- * Redirect all subwindows for one client
- */
-
-int
-compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
-{
- CompSubwindowsPtr csw = GetCompSubwindows (pWin);
- CompClientWindowPtr ccw;
- WindowPtr pChild;
-
- /*
- * Only one Manual update is allowed
- */
- if (csw && update == CompositeRedirectManual)
- for (ccw = csw->clients; ccw; ccw = ccw->next)
- if (ccw->update == CompositeRedirectManual)
- return BadAccess;
- /*
- * Allocate per-client per-window structure
- * The client *could* allocate multiple, but while supported,
- * it is not expected to be common
- */
- ccw = malloc(sizeof (CompClientWindowRec));
- if (!ccw)
- return BadAlloc;
- ccw->id = FakeClientID (pClient->index);
- ccw->update = update;
- /*
- * Now make sure there's a per-window structure to hang this from
- */
- if (!csw)
- {
- csw = malloc(sizeof (CompSubwindowsRec));
- if (!csw)
- {
- free(ccw);
- return BadAlloc;
- }
- csw->update = CompositeRedirectAutomatic;
- csw->clients = 0;
- dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
- }
- /*
- * Redirect all existing windows
- */
- for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
- {
- int ret = compRedirectWindow (pClient, pChild, update);
- if (ret != Success)
- {
- for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
- (void) compUnredirectWindow (pClient, pChild, update);
- if (!csw->clients)
- {
- free(csw);
- dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
- }
- free(ccw);
- return ret;
- }
- }
- /*
- * Hook into subwindows list
- */
- ccw->next = csw->clients;
- csw->clients = ccw;
- if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin))
- return BadAlloc;
- if (ccw->update == CompositeRedirectManual)
- {
- csw->update = CompositeRedirectManual;
- /*
- * tell damage extension that damage events for this client are
- * critical output
- */
- DamageExtSetCritical (pClient, TRUE);
- }
- return Success;
-}
-
-/*
- * Free one of the per-client per-subwindows resources,
- * which frees one redirect per subwindow
- */
-void
-compFreeClientSubwindows (WindowPtr pWin, XID id)
-{
- CompSubwindowsPtr csw = GetCompSubwindows (pWin);
- CompClientWindowPtr ccw, *prev;
- WindowPtr pChild;
-
- if (!csw)
- return;
- for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next)
- {
- if (ccw->id == id)
- {
- ClientPtr pClient = clients[CLIENT_ID(id)];
-
- *prev = ccw->next;
- if (ccw->update == CompositeRedirectManual)
- {
- /*
- * tell damage extension that damage events for this client are
- * critical output
- */
- DamageExtSetCritical (pClient, FALSE);
- csw->update = CompositeRedirectAutomatic;
- if (pWin->mapped)
- (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE);
- }
-
- /*
- * Unredirect all existing subwindows
- */
- for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
- (void) compUnredirectWindow (pClient, pChild, ccw->update);
-
- free(ccw);
- break;
- }
- }
-
- /*
- * Check if all of the per-client records are gone
- */
- if (!csw->clients)
- {
- dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
- free(csw);
- }
-}
-
-/*
- * This is easy, just free the appropriate resource.
- */
-
-int
-compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
-{
- CompSubwindowsPtr csw = GetCompSubwindows (pWin);
- CompClientWindowPtr ccw;
-
- if (!csw)
- return BadValue;
- for (ccw = csw->clients; ccw; ccw = ccw->next)
- if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
- {
- FreeResource (ccw->id, RT_NONE);
- return Success;
- }
- return BadValue;
-}
-
-/*
- * Add redirection information for one subwindow (during reparent)
- */
-
-int
-compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
-{
- CompSubwindowsPtr csw = GetCompSubwindows (pParent);
- CompClientWindowPtr ccw;
-
- if (!csw)
- return Success;
- for (ccw = csw->clients; ccw; ccw = ccw->next)
- {
- int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)],
- pWin, ccw->update);
- if (ret != Success)
- return ret;
- }
- return Success;
-}
-
-/*
- * Remove redirection information for one subwindow (during reparent)
- */
-
-int
-compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
-{
- CompSubwindowsPtr csw = GetCompSubwindows (pParent);
- CompClientWindowPtr ccw;
-
- if (!csw)
- return Success;
- for (ccw = csw->clients; ccw; ccw = ccw->next)
- {
- int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)],
- pWin, ccw->update);
- if (ret != Success)
- return ret;
- }
- return Success;
-}
-
-static int
-bgNoneVisitWindow(WindowPtr pWin, void *null)
-{
- if (pWin->backgroundState != BackgroundPixmap)
- return WT_WALKCHILDREN;
- if (pWin->background.pixmap != None)
- return WT_WALKCHILDREN;
-
- return WT_STOPWALKING;
-}
-
-static PixmapPtr
-compNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- WindowPtr pParent = pWin->parent;
- PixmapPtr pPixmap;
-
- pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
- CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
-
- if (!pPixmap)
- return 0;
-
- pPixmap->screen_x = x;
- pPixmap->screen_y = y;
-
- /* resize allocations will update later in compCopyWindow, not here */
- if (!map)
- return pPixmap;
-
- /*
- * If there's no bg=None in the tree, we're done.
- *
- * We could optimize this more by collection the regions of all the
- * bg=None subwindows and feeding that in as the clip for the
- * CopyArea below, but since window trees are shallow these days it
- * might not be worth the effort.
- */
- if (TraverseTree(pWin, bgNoneVisitWindow, NULL) == WT_NOMATCH)
- return pPixmap;
-
- /*
- * Copy bits from the parent into the new pixmap so that it will
- * have "reasonable" contents in case for background None areas.
- */
- if (pParent->drawable.depth == pWin->drawable.depth)
- {
- GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen);
-
- if (pGC)
- {
- ChangeGCVal val;
- val.val = IncludeInferiors;
-
- ValidateGC(&pPixmap->drawable, pGC);
- ChangeGC (serverClient, pGC, GCSubwindowMode, &val);
- (*pGC->ops->CopyArea) (&pParent->drawable,
- &pPixmap->drawable,
- pGC,
- x - pParent->drawable.x,
- y - pParent->drawable.y,
- w, h, 0, 0);
- FreeScratchGC (pGC);
- }
- }
- else
- {
- PictFormatPtr pSrcFormat = compWindowFormat (pParent);
- PictFormatPtr pDstFormat = compWindowFormat (pWin);
- XID inferiors = IncludeInferiors;
- int error;
-
- PicturePtr pSrcPicture = CreatePicture (None,
- &pParent->drawable,
- pSrcFormat,
- CPSubwindowMode,
- &inferiors,
- serverClient, &error);
-
- PicturePtr pDstPicture = CreatePicture (None,
- &pPixmap->drawable,
- pDstFormat,
- 0, 0,
- serverClient, &error);
-
- if (pSrcPicture && pDstPicture)
- {
- CompositePicture (PictOpSrc,
- pSrcPicture,
- NULL,
- pDstPicture,
- x - pParent->drawable.x,
- y - pParent->drawable.y,
- 0, 0, 0, 0, w, h);
- }
- if (pSrcPicture)
- FreePicture (pSrcPicture, 0);
- if (pDstPicture)
- FreePicture (pDstPicture, 0);
- }
- return pPixmap;
-}
-
-Bool
-compAllocPixmap (WindowPtr pWin)
-{
- int bw = (int) pWin->borderWidth;
- int x = pWin->drawable.x - bw;
- int y = pWin->drawable.y - bw;
- int w = pWin->drawable.width + (bw << 1);
- int h = pWin->drawable.height + (bw << 1);
- PixmapPtr pPixmap = compNewPixmap (pWin, x, y, w, h, TRUE);
- CompWindowPtr cw = GetCompWindow (pWin);
-
- if (!pPixmap)
- return FALSE;
- if (cw->update == CompositeRedirectAutomatic)
- pWin->redirectDraw = RedirectDrawAutomatic;
- else
- pWin->redirectDraw = RedirectDrawManual;
-
- compSetPixmap (pWin, pPixmap);
- cw->oldx = COMP_ORIGIN_INVALID;
- cw->oldy = COMP_ORIGIN_INVALID;
- cw->damageRegistered = FALSE;
- if (cw->update == CompositeRedirectAutomatic)
- {
- DamageRegister (&pWin->drawable, cw->damage);
- cw->damageRegistered = TRUE;
- }
- return TRUE;
-}
-
-void
-compFreePixmap (WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- PixmapPtr pRedirectPixmap, pParentPixmap;
- CompWindowPtr cw = GetCompWindow (pWin);
-
- if (cw->damageRegistered)
- {
- DamageUnregister (&pWin->drawable, cw->damage);
- cw->damageRegistered = FALSE;
- DamageEmpty (cw->damage);
- }
- /*
- * Move the parent-constrained border clip region back into
- * the window so that ValidateTree will handle the unmap
- * case correctly. Unmap adds the window borderClip to the
- * parent exposed area; regions beyond the parent cause crashes
- */
- RegionCopy(&pWin->borderClip, &cw->borderClip);
- pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
- pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
- pWin->redirectDraw = RedirectDrawNone;
- compSetPixmap (pWin, pParentPixmap);
- (*pScreen->DestroyPixmap) (pRedirectPixmap);
-}
-
-/*
- * Make sure the pixmap is the right size and offset. Allocate a new
- * pixmap to change size, adjust origin to change offset, leaving the
- * old pixmap in cw->pOldPixmap so bits can be recovered
- */
-Bool
-compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y,
- unsigned int w, unsigned int h, int bw)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
- PixmapPtr pNew;
- CompWindowPtr cw = GetCompWindow (pWin);
- int pix_x, pix_y;
- int pix_w, pix_h;
-
- assert (cw && pWin->redirectDraw != RedirectDrawNone);
- cw->oldx = pOld->screen_x;
- cw->oldy = pOld->screen_y;
- pix_x = draw_x - bw;
- pix_y = draw_y - bw;
- pix_w = w + (bw << 1);
- pix_h = h + (bw << 1);
- if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height)
- {
- pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h, FALSE);
- if (!pNew)
- return FALSE;
- cw->pOldPixmap = pOld;
- compSetPixmap (pWin, pNew);
- }
- else
- {
- pNew = pOld;
- cw->pOldPixmap = 0;
- }
- pNew->screen_x = pix_x;
- pNew->screen_y = pix_y;
- return TRUE;
-}
+/*
+ * Copyright (c) 2006, Oracle and/or its affiliates. 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Copyright © 2003 Keith Packard
+ *
+ * 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, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "compint.h"
+
+static void
+compScreenUpdate (ScreenPtr pScreen)
+{
+ compCheckTree (pScreen);
+ compPaintChildrenToWindow (pScreen->root);
+}
+
+static void
+compBlockHandler (int i,
+ pointer blockData,
+ pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ pScreen->BlockHandler = cs->BlockHandler;
+ compScreenUpdate (pScreen);
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ /* Next damage will restore the block handler */
+ cs->BlockHandler = NULL;
+}
+
+static void
+compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+ WindowPtr pWin = (WindowPtr) closure;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ if (!cs->BlockHandler) {
+ cs->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = compBlockHandler;
+ }
+ cw->damaged = TRUE;
+
+ /* Mark the ancestors */
+ pWin = pWin->parent;
+ while (pWin) {
+ if (pWin->damagedDescendants)
+ break;
+ pWin->damagedDescendants = TRUE;
+ pWin = pWin->parent;
+ }
+}
+
+static void
+compDestroyDamage (DamagePtr pDamage, void *closure)
+{
+ WindowPtr pWin = (WindowPtr) closure;
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ cw->damage = 0;
+}
+
+/*
+ * Redirect one window for one client
+ */
+int
+compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ CompClientWindowPtr ccw;
+ Bool wasMapped = pWin->mapped;
+ CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
+
+ if (pWin == cs->pOverlayWin) {
+ return Success;
+ }
+
+ if (!pWin->parent)
+ return BadMatch;
+
+ /*
+ * Only one Manual update is allowed
+ */
+ if (cw && update == CompositeRedirectManual)
+ for (ccw = cw->clients; ccw; ccw = ccw->next)
+ if (ccw->update == CompositeRedirectManual)
+ return BadAccess;
+
+ /*
+ * Allocate per-client per-window structure
+ * The client *could* allocate multiple, but while supported,
+ * it is not expected to be common
+ */
+ ccw = malloc(sizeof (CompClientWindowRec));
+ if (!ccw)
+ return BadAlloc;
+ ccw->id = FakeClientID (pClient->index);
+ ccw->update = update;
+ /*
+ * Now make sure there's a per-window structure to hang this from
+ */
+ if (!cw)
+ {
+ cw = malloc(sizeof (CompWindowRec));
+ if (!cw)
+ {
+ free(ccw);
+ return BadAlloc;
+ }
+ cw->damage = DamageCreate (compReportDamage,
+ compDestroyDamage,
+ DamageReportNonEmpty,
+ FALSE,
+ pWin->drawable.pScreen,
+ pWin);
+ if (!cw->damage)
+ {
+ free(ccw);
+ free(cw);
+ return BadAlloc;
+ }
+ if (wasMapped)
+ {
+ DisableMapUnmapEvents (pWin);
+ UnmapWindow (pWin, FALSE);
+ EnableMapUnmapEvents (pWin);
+ }
+
+ RegionNull(&cw->borderClip);
+ cw->borderClipX = 0;
+ cw->borderClipY = 0;
+ cw->update = CompositeRedirectAutomatic;
+ cw->clients = 0;
+ cw->oldx = COMP_ORIGIN_INVALID;
+ cw->oldy = COMP_ORIGIN_INVALID;
+ cw->damageRegistered = FALSE;
+ cw->damaged = FALSE;
+ cw->pOldPixmap = NullPixmap;
+ dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
+ }
+ ccw->next = cw->clients;
+ cw->clients = ccw;
+ if (!AddResource (ccw->id, CompositeClientWindowType, pWin))
+ return BadAlloc;
+ if (ccw->update == CompositeRedirectManual)
+ {
+ /* If the window was CompositeRedirectAutomatic, then
+ * unmap the window so that the parent clip list will
+ * be correctly recomputed.
+ */
+ if (pWin->mapped)
+ {
+ DisableMapUnmapEvents (pWin);
+ UnmapWindow (pWin, FALSE);
+ EnableMapUnmapEvents (pWin);
+ }
+ if (cw->damageRegistered)
+ {
+ DamageUnregister (&pWin->drawable, cw->damage);
+ cw->damageRegistered = FALSE;
+ }
+ cw->update = CompositeRedirectManual;
+ }
+
+ if (!compCheckRedirect (pWin))
+ {
+ FreeResource (ccw->id, RT_NONE);
+ return BadAlloc;
+ }
+ if (wasMapped && !pWin->mapped)
+ {
+ Bool overrideRedirect = pWin->overrideRedirect;
+ pWin->overrideRedirect = TRUE;
+ DisableMapUnmapEvents (pWin);
+ MapWindow (pWin, pClient);
+ EnableMapUnmapEvents (pWin);
+ pWin->overrideRedirect = overrideRedirect;
+ }
+
+ return Success;
+}
+
+/*
+ * Free one of the per-client per-window resources, clearing
+ * redirect and the per-window pointer as appropriate
+ */
+void
+compFreeClientWindow (WindowPtr pWin, XID id)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ CompClientWindowPtr ccw, *prev;
+ Bool wasMapped = pWin->mapped;
+
+ if (!cw)
+ return;
+ for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next)
+ {
+ if (ccw->id == id)
+ {
+ *prev = ccw->next;
+ if (ccw->update == CompositeRedirectManual)
+ cw->update = CompositeRedirectAutomatic;
+ free(ccw);
+ break;
+ }
+ }
+ if (!cw->clients)
+ {
+ if (wasMapped)
+ {
+ DisableMapUnmapEvents (pWin);
+ UnmapWindow (pWin, FALSE);
+ EnableMapUnmapEvents (pWin);
+ }
+
+ if (pWin->redirectDraw != RedirectDrawNone)
+ compFreePixmap (pWin);
+
+ if (cw->damage)
+ DamageDestroy (cw->damage);
+
+ RegionUninit(&cw->borderClip);
+
+ dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
+ free(cw);
+ }
+ else if (cw->update == CompositeRedirectAutomatic &&
+ !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone)
+ {
+ DamageRegister (&pWin->drawable, cw->damage);
+ cw->damageRegistered = TRUE;
+ pWin->redirectDraw = RedirectDrawAutomatic;
+ DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
+ }
+ if (wasMapped && !pWin->mapped)
+ {
+ Bool overrideRedirect = pWin->overrideRedirect;
+ pWin->overrideRedirect = TRUE;
+ DisableMapUnmapEvents (pWin);
+ MapWindow (pWin, clients[CLIENT_ID(id)]);
+ EnableMapUnmapEvents (pWin);
+ pWin->overrideRedirect = overrideRedirect;
+ }
+}
+
+/*
+ * This is easy, just free the appropriate resource.
+ */
+
+int
+compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ CompClientWindowPtr ccw;
+
+ if (!cw)
+ return BadValue;
+
+ for (ccw = cw->clients; ccw; ccw = ccw->next)
+ if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
+ {
+ FreeResource (ccw->id, RT_NONE);
+ return Success;
+ }
+ return BadValue;
+}
+
+/*
+ * Redirect all subwindows for one client
+ */
+
+int
+compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pWin);
+ CompClientWindowPtr ccw;
+ WindowPtr pChild;
+
+ /*
+ * Only one Manual update is allowed
+ */
+ if (csw && update == CompositeRedirectManual)
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ if (ccw->update == CompositeRedirectManual)
+ return BadAccess;
+ /*
+ * Allocate per-client per-window structure
+ * The client *could* allocate multiple, but while supported,
+ * it is not expected to be common
+ */
+ ccw = malloc(sizeof (CompClientWindowRec));
+ if (!ccw)
+ return BadAlloc;
+ ccw->id = FakeClientID (pClient->index);
+ ccw->update = update;
+ /*
+ * Now make sure there's a per-window structure to hang this from
+ */
+ if (!csw)
+ {
+ csw = malloc(sizeof (CompSubwindowsRec));
+ if (!csw)
+ {
+ free(ccw);
+ return BadAlloc;
+ }
+ csw->update = CompositeRedirectAutomatic;
+ csw->clients = 0;
+ dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
+ }
+ /*
+ * Redirect all existing windows
+ */
+ for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+ {
+ int ret = compRedirectWindow (pClient, pChild, update);
+ if (ret != Success)
+ {
+ for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
+ (void) compUnredirectWindow (pClient, pChild, update);
+ if (!csw->clients)
+ {
+ free(csw);
+ dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
+ }
+ free(ccw);
+ return ret;
+ }
+ }
+ /*
+ * Hook into subwindows list
+ */
+ ccw->next = csw->clients;
+ csw->clients = ccw;
+ if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin))
+ return BadAlloc;
+ if (ccw->update == CompositeRedirectManual)
+ {
+ csw->update = CompositeRedirectManual;
+ /*
+ * tell damage extension that damage events for this client are
+ * critical output
+ */
+ DamageExtSetCritical (pClient, TRUE);
+ }
+ return Success;
+}
+
+/*
+ * Free one of the per-client per-subwindows resources,
+ * which frees one redirect per subwindow
+ */
+void
+compFreeClientSubwindows (WindowPtr pWin, XID id)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pWin);
+ CompClientWindowPtr ccw, *prev;
+ WindowPtr pChild;
+
+ if (!csw)
+ return;
+ for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next)
+ {
+ if (ccw->id == id)
+ {
+ ClientPtr pClient = clients[CLIENT_ID(id)];
+
+ *prev = ccw->next;
+ if (ccw->update == CompositeRedirectManual)
+ {
+ /*
+ * tell damage extension that damage events for this client are
+ * critical output
+ */
+ DamageExtSetCritical (pClient, FALSE);
+ csw->update = CompositeRedirectAutomatic;
+ if (pWin->mapped)
+ (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE);
+ }
+
+ /*
+ * Unredirect all existing subwindows
+ */
+ for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+ (void) compUnredirectWindow (pClient, pChild, ccw->update);
+
+ free(ccw);
+ break;
+ }
+ }
+
+ /*
+ * Check if all of the per-client records are gone
+ */
+ if (!csw->clients)
+ {
+ dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
+ free(csw);
+ }
+}
+
+/*
+ * This is easy, just free the appropriate resource.
+ */
+
+int
+compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pWin);
+ CompClientWindowPtr ccw;
+
+ if (!csw)
+ return BadValue;
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
+ {
+ FreeResource (ccw->id, RT_NONE);
+ return Success;
+ }
+ return BadValue;
+}
+
+/*
+ * Add redirection information for one subwindow (during reparent)
+ */
+
+int
+compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pParent);
+ CompClientWindowPtr ccw;
+
+ if (!csw)
+ return Success;
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ {
+ int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)],
+ pWin, ccw->update);
+ if (ret != Success)
+ return ret;
+ }
+ return Success;
+}
+
+/*
+ * Remove redirection information for one subwindow (during reparent)
+ */
+
+int
+compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pParent);
+ CompClientWindowPtr ccw;
+
+ if (!csw)
+ return Success;
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ {
+ int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)],
+ pWin, ccw->update);
+ if (ret != Success)
+ return ret;
+ }
+ return Success;
+}
+
+static PixmapPtr
+compNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ WindowPtr pParent = pWin->parent;
+ PixmapPtr pPixmap;
+
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
+ CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
+
+ if (!pPixmap)
+ return 0;
+
+ pPixmap->screen_x = x;
+ pPixmap->screen_y = y;
+
+ /* resize allocations will update later in compCopyWindow, not here */
+ if (!map)
+ return pPixmap;
+
+ if (pParent->drawable.depth == pWin->drawable.depth)
+ {
+ GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen);
+
+ if (pGC)
+ {
+ ChangeGCVal val;
+ val.val = IncludeInferiors;
+
+ ValidateGC(&pPixmap->drawable, pGC);
+ ChangeGC (serverClient, pGC, GCSubwindowMode, &val);
+ (*pGC->ops->CopyArea) (&pParent->drawable,
+ &pPixmap->drawable,
+ pGC,
+ x - pParent->drawable.x,
+ y - pParent->drawable.y,
+ w, h, 0, 0);
+ FreeScratchGC (pGC);
+ }
+ }
+ else
+ {
+ PictFormatPtr pSrcFormat = compWindowFormat (pParent);
+ PictFormatPtr pDstFormat = compWindowFormat (pWin);
+ XID inferiors = IncludeInferiors;
+ int error;
+
+ PicturePtr pSrcPicture = CreatePicture (None,
+ &pParent->drawable,
+ pSrcFormat,
+ CPSubwindowMode,
+ &inferiors,
+ serverClient, &error);
+
+ PicturePtr pDstPicture = CreatePicture (None,
+ &pPixmap->drawable,
+ pDstFormat,
+ 0, 0,
+ serverClient, &error);
+
+ if (pSrcPicture && pDstPicture)
+ {
+ CompositePicture (PictOpSrc,
+ pSrcPicture,
+ NULL,
+ pDstPicture,
+ x - pParent->drawable.x,
+ y - pParent->drawable.y,
+ 0, 0, 0, 0, w, h);
+ }
+ if (pSrcPicture)
+ FreePicture (pSrcPicture, 0);
+ if (pDstPicture)
+ FreePicture (pDstPicture, 0);
+ }
+ return pPixmap;
+}
+
+Bool
+compAllocPixmap (WindowPtr pWin)
+{
+ int bw = (int) pWin->borderWidth;
+ int x = pWin->drawable.x - bw;
+ int y = pWin->drawable.y - bw;
+ int w = pWin->drawable.width + (bw << 1);
+ int h = pWin->drawable.height + (bw << 1);
+ PixmapPtr pPixmap = compNewPixmap (pWin, x, y, w, h, TRUE);
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ if (!pPixmap)
+ return FALSE;
+ if (cw->update == CompositeRedirectAutomatic)
+ pWin->redirectDraw = RedirectDrawAutomatic;
+ else
+ pWin->redirectDraw = RedirectDrawManual;
+
+ compSetPixmap (pWin, pPixmap);
+ cw->oldx = COMP_ORIGIN_INVALID;
+ cw->oldy = COMP_ORIGIN_INVALID;
+ cw->damageRegistered = FALSE;
+ if (cw->update == CompositeRedirectAutomatic)
+ {
+ DamageRegister (&pWin->drawable, cw->damage);
+ cw->damageRegistered = TRUE;
+ }
+ return TRUE;
+}
+
+void
+compFreePixmap (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ PixmapPtr pRedirectPixmap, pParentPixmap;
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ if (cw->damageRegistered)
+ {
+ DamageUnregister (&pWin->drawable, cw->damage);
+ cw->damageRegistered = FALSE;
+ DamageEmpty (cw->damage);
+ }
+ /*
+ * Move the parent-constrained border clip region back into
+ * the window so that ValidateTree will handle the unmap
+ * case correctly. Unmap adds the window borderClip to the
+ * parent exposed area; regions beyond the parent cause crashes
+ */
+ RegionCopy(&pWin->borderClip, &cw->borderClip);
+ pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
+ pWin->redirectDraw = RedirectDrawNone;
+ compSetPixmap (pWin, pParentPixmap);
+ (*pScreen->DestroyPixmap) (pRedirectPixmap);
+}
+
+/*
+ * Make sure the pixmap is the right size and offset. Allocate a new
+ * pixmap to change size, adjust origin to change offset, leaving the
+ * old pixmap in cw->pOldPixmap so bits can be recovered
+ */
+Bool
+compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y,
+ unsigned int w, unsigned int h, int bw)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
+ PixmapPtr pNew;
+ CompWindowPtr cw = GetCompWindow (pWin);
+ int pix_x, pix_y;
+ int pix_w, pix_h;
+
+ assert (cw && pWin->redirectDraw != RedirectDrawNone);
+ cw->oldx = pOld->screen_x;
+ cw->oldy = pOld->screen_y;
+ pix_x = draw_x - bw;
+ pix_y = draw_y - bw;
+ pix_w = w + (bw << 1);
+ pix_h = h + (bw << 1);
+ if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height)
+ {
+ pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h, FALSE);
+ if (!pNew)
+ return FALSE;
+ cw->pOldPixmap = pOld;
+ compSetPixmap (pWin, pNew);
+ }
+ else
+ {
+ pNew = pOld;
+ cw->pOldPixmap = 0;
+ }
+ pNew->screen_x = pix_x;
+ pNew->screen_y = pix_y;
+ return TRUE;
+}
diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac
index 9e04ff015..56e51a407 100644
--- a/xorg-server/configure.ac
+++ b/xorg-server/configure.ac
@@ -35,7 +35,7 @@ AM_MAINTAINER_MODE
# Require xorg-macros minimum of 1.13 for XORG_ENABLE_UNIT_TESTS
m4_ifndef([XORG_MACROS_VERSION],
[m4_fatal([must install xorg-macros 1.13 or later before running autoconf/autogen])])
-XORG_MACROS_VERSION(1.10)
+XORG_MACROS_VERSION(1.13)
XORG_DEFAULT_OPTIONS
XORG_WITH_DOXYGEN(1.6.1)
XORG_CHECK_SGML_DOCTOOLS(1.5)
@@ -44,7 +44,6 @@ XORG_ENABLE_DEVEL_DOCS
XORG_WITH_XMLTO(0.0.20)
XORG_WITH_FOP
XORG_ENABLE_UNIT_TESTS
-XORG_WITH_GLIB
XORG_LD_WRAP
m4_ifndef([XORG_FONT_MACROS_VERSION], [m4_fatal([must install fontutil 1.1 or later before running autoconf/autogen])])
@@ -726,9 +725,9 @@ case $host_os in
save_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS -framework Carbon"
AC_LINK_IFELSE([char FSFindFolder(); int main() { FSFindFolder(); return 0;}],
- [xorg_cv_Carbon_framework=yes],
- [xorg_cv_Carbon_framework=no])
- LDFLAGS=$save_LDFLAGS])
+ [xorg_cv_Carbon_framework=yes],
+ [xorg_cv_Carbon_framework=no])
+ LDFLAGS=$save_LDFLAGS])
if test "X$xorg_cv_Carbon_framework" = Xyes; then
XQUARTZ=yes
@@ -737,6 +736,10 @@ case $host_os in
fi
fi
+ AC_CHECK_FUNC(dispatch_async,
+ AC_DEFINE([HAVE_LIBDISPATCH], 1, [Define to 1 if you have the libdispatch (GCD) available]),
+ [])
+
if test "x$XQUARTZ" = xyes ; then
XQUARTZ=yes
XVFB=no
@@ -791,7 +794,6 @@ LIBXFONT="xfont >= 1.4.2"
LIBXI="xi >= 1.2.99.1"
LIBXTST="xtst >= 1.0.99.2"
LIBPCIACCESS="pciaccess >= 0.8.0"
-LIBGLIB="glib-2.0 >= 2.16"
LIBUDEV="libudev >= 143"
LIBSELINUX="libselinux >= 2.0.86"
LIBDBUS="dbus-1 >= 1.0"
@@ -1006,7 +1008,7 @@ else
fi
AM_CONDITIONAL(GLX, test "x$GLX" = xyes)
-if test "x$AIGLX" = xyes -a "x$GLX" = xyes -a "x$DRI" = xyes; then
+if test "x$AIGLX" = xyes -a "x$GLX" = xyes -a \( "x$DRI" = xyes -o "x$DRI2" = xyes \); then
AC_DEFINE(AIGLX, 1, [Build AIGLX loader])
else
AIGLX=no
diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c
index 534931c3e..3f46ad6fb 100644
--- a/xorg-server/dix/devices.c
+++ b/xorg-server/dix/devices.c
@@ -1221,13 +1221,46 @@ InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels,
return TRUE;
}
+/**
+ * Allocate a valuator class and set up the pointers for the axis values
+ * appropriately.
+ *
+ * @param src If non-NULL, the memory is reallocated from src. If NULL, the
+ * memory is calloc'd.
+ * @parma numAxes Number of axes to allocate.
+ * @return The allocated valuator struct.
+ */
+ValuatorClassPtr
+AllocValuatorClass(ValuatorClassPtr src, int numAxes)
+{
+ ValuatorClassPtr v;
+ /* force alignment with double */
+ union align_u { ValuatorClassRec valc; double d; } *align;
+ int size;
+
+ size = sizeof(union align_u) + numAxes * (sizeof(double) + sizeof(AxisInfo));
+ align = (union align_u *) realloc(src, size);
+
+ if (!align)
+ return NULL;
+
+ if (!src)
+ memset(align, 0, size);
+
+ v = &align->valc;
+ v->numAxes = numAxes;
+ v->axisVal = (double*)(align + 1);
+ v->axes = (AxisInfoPtr)(v->axisVal + numAxes);
+
+ return v;
+}
+
Bool
InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
int numMotionEvents, int mode)
{
int i;
ValuatorClassPtr valc;
- union align_u { ValuatorClassRec valc; double d; } *align;
if (!dev)
return FALSE;
@@ -1240,13 +1273,10 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
numAxes = MAX_VALUATORS;
}
- align = (union align_u *) calloc(1, sizeof(union align_u) +
- numAxes * sizeof(double) +
- numAxes * sizeof(AxisInfo));
- if (!align)
- return FALSE;
+ valc = AllocValuatorClass(NULL, numAxes);
+ if (!valc)
+ return FALSE;
- valc = &align->valc;
valc->sourceid = dev->id;
valc->motion = NULL;
valc->first_motion = 0;
@@ -1254,9 +1284,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
valc->numMotionEvents = numMotionEvents;
valc->motionHintWindow = NullWindow;
- valc->numAxes = numAxes;
- valc->axisVal = (double *)(align + 1);
- valc->axes = (AxisInfoPtr)(valc->axisVal + numAxes);
if (mode & OutOfProximity)
InitProximityClassDeviceStruct(dev);
@@ -2365,7 +2392,7 @@ ReleaseButtonsAndKeys(DeviceIntPtr dev)
{
if (BitIsOn(k->down, i))
{
- nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i);
+ nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i, NULL);
for (j = 0; j < nevents; j++)
mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
}
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index 644b3887e..0fa8046df 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -616,8 +616,8 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
/**
- * Returns the maximum number of events GetKeyboardEvents,
- * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
+ * Returns the maximum number of events GetKeyboardEvents
+ * and GetPointerEvents will ever return.
*
* This MUST be absolutely constant, from init until exit.
*/
@@ -926,19 +926,6 @@ updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
}
/**
- * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
- * valuators.
- */
-int
-GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
- ValuatorMask mask;
-
- valuator_mask_zero(&mask);
- return GetKeyboardValuatorEvents(events, pDev, type, key_code, &mask);
-}
-
-
-/**
* Returns a set of InternalEvents for KeyPress/KeyRelease, optionally
* also with valuator events.
*
@@ -947,8 +934,8 @@ GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code)
* place via GetMaximumEventsNum(), and for freeing it.
*/
int
-GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
- int key_code, const ValuatorMask *mask_in) {
+GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type,
+ int key_code, const ValuatorMask *mask_in) {
int num_events = 0;
CARD32 ms = 0;
DeviceEvent *event;
diff --git a/xorg-server/dix/ptrveloc.c b/xorg-server/dix/ptrveloc.c
index e95d804c2..dfccf1581 100644
--- a/xorg-server/dix/ptrveloc.c
+++ b/xorg-server/dix/ptrveloc.c
@@ -1,1216 +1,1268 @@
-/*
- *
- * Copyright © 2006-2009 Simon Thum simon dot thum at gmx dot de
- *
- * 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <math.h>
-#include <ptrveloc.h>
-#include <exevents.h>
-#include <X11/Xatom.h>
-#include <os.h>
-
-#include <xserver-properties.h>
-
-/*****************************************************************************
- * Predictable pointer acceleration
- *
- * 2006-2009 by Simon Thum (simon [dot] thum [at] gmx de)
- *
- * Serves 3 complementary functions:
- * 1) provide a sophisticated ballistic velocity estimate to improve
- * the relation between velocity (of the device) and acceleration
- * 2) make arbitrary acceleration profiles possible
- * 3) decelerate by two means (constant and adaptive) if enabled
- *
- * Important concepts are the
- *
- * - Scheme
- * which selects the basic algorithm
- * (see devices.c/InitPointerAccelerationScheme)
- * - Profile
- * which returns an acceleration
- * for a given velocity
- *
- * The profile can be selected by the user at runtime.
- * The classic profile is intended to cleanly perform old-style
- * function selection (threshold =/!= 0)
- *
- ****************************************************************************/
-
-/* fwds */
-int
-SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
-static float
-SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, float velocity,
- float threshold, float acc);
-static PointerAccelerationProfileFunc
-GetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
-static BOOL
-InitializePredictableAccelerationProperties(DeviceIntPtr,
- DeviceVelocityPtr,
- PredictableAccelSchemePtr);
-static BOOL
-DeletePredictableAccelerationProperties(DeviceIntPtr,
- PredictableAccelSchemePtr);
-
-/*#define PTRACCEL_DEBUGGING*/
-
-#ifdef PTRACCEL_DEBUGGING
-#define DebugAccelF ErrorF
-#else
-#define DebugAccelF(...) /* */
-#endif
-
-/********************************
- * Init/Uninit
- *******************************/
-
-/* some int which is not a profile number */
-#define PROFILE_UNINITIALIZE (-100)
-
-/**
- * Init DeviceVelocity struct so it should match the average case
- */
-void
-InitVelocityData(DeviceVelocityPtr vel)
-{
- memset(vel, 0, sizeof(DeviceVelocityRec));
-
- vel->corr_mul = 10.0; /* dots per 10 milisecond should be usable */
- vel->const_acceleration = 1.0; /* no acceleration/deceleration */
- vel->reset_time = 300;
- vel->use_softening = 1;
- vel->min_acceleration = 1.0; /* don't decelerate */
- vel->max_rel_diff = 0.2;
- vel->max_diff = 1.0;
- vel->initial_range = 2;
- vel->average_accel = TRUE;
- SetAccelerationProfile(vel, AccelProfileClassic);
- InitTrackers(vel, 16);
-}
-
-
-/**
- * Clean up DeviceVelocityRec
- */
-void
-FreeVelocityData(DeviceVelocityPtr vel){
- free(vel->tracker);
- SetAccelerationProfile(vel, PROFILE_UNINITIALIZE);
-}
-
-
-/**
- * Init predictable scheme
- */
-Bool
-InitPredictableAccelerationScheme(DeviceIntPtr dev,
- ValuatorAccelerationPtr protoScheme) {
- DeviceVelocityPtr vel;
- ValuatorAccelerationRec scheme;
- PredictableAccelSchemePtr schemeData;
- scheme = *protoScheme;
- vel = calloc(1, sizeof(DeviceVelocityRec));
- schemeData = calloc(1, sizeof(PredictableAccelSchemeRec));
- if (!vel || !schemeData)
- return FALSE;
- InitVelocityData(vel);
- schemeData->vel = vel;
- scheme.accelData = schemeData;
- if (!InitializePredictableAccelerationProperties(dev, vel, schemeData))
- return FALSE;
- /* all fine, assign scheme to device */
- dev->valuator->accelScheme = scheme;
- return TRUE;
-}
-
-
-/**
- * Uninit scheme
- */
-void
-AccelerationDefaultCleanup(DeviceIntPtr dev)
-{
- DeviceVelocityPtr vel = GetDevicePredictableAccelData(dev);
- if (vel) {
- /* the proper guarantee would be that we're not inside of
- * AccelSchemeProc(), but that seems impossible. Schemes don't get
- * switched often anyway.
- */
- OsBlockSignals();
- dev->valuator->accelScheme.AccelSchemeProc = NULL;
- FreeVelocityData(vel);
- free(vel);
- DeletePredictableAccelerationProperties(dev,
- (PredictableAccelSchemePtr) dev->valuator->accelScheme.accelData);
- free(dev->valuator->accelScheme.accelData);
- dev->valuator->accelScheme.accelData = NULL;
- OsReleaseSignals();
- }
-}
-
-
-/*************************
- * Input property support
- ************************/
-
-/**
- * choose profile
- */
-static int
-AccelSetProfileProperty(DeviceIntPtr dev, Atom atom,
- XIPropertyValuePtr val, BOOL checkOnly)
-{
- DeviceVelocityPtr vel;
- int profile, *ptr = &profile;
- int rc;
- int nelem = 1;
-
- if (atom != XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER))
- return Success;
-
- vel = GetDevicePredictableAccelData(dev);
- if (!vel)
- return BadValue;
- rc = XIPropToInt(val, &nelem, &ptr);
-
- if(checkOnly)
- {
- if (rc)
- return rc;
-
- if (GetAccelerationProfile(vel, profile) == NULL)
- return BadValue;
- } else
- SetAccelerationProfile(vel, profile);
-
- return Success;
-}
-
-static long
-AccelInitProfileProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
-{
- int profile = vel->statistics.profile_number;
- Atom prop_profile_number = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
-
- XIChangeDeviceProperty(dev, prop_profile_number, XA_INTEGER, 32,
- PropModeReplace, 1, &profile, FALSE);
- XISetDevicePropertyDeletable(dev, prop_profile_number, FALSE);
- return XIRegisterPropertyHandler(dev, AccelSetProfileProperty, NULL, NULL);
-}
-
-/**
- * constant deceleration
- */
-static int
-AccelSetDecelProperty(DeviceIntPtr dev, Atom atom,
- XIPropertyValuePtr val, BOOL checkOnly)
-{
- DeviceVelocityPtr vel;
- float v, *ptr = &v;
- int rc;
- int nelem = 1;
-
- if (atom != XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION))
- return Success;
-
- vel = GetDevicePredictableAccelData(dev);
- if (!vel)
- return BadValue;
- rc = XIPropToFloat(val, &nelem, &ptr);
-
- if(checkOnly)
- {
- if (rc)
- return rc;
- return (v >= 1.0f) ? Success : BadValue;
- }
-
- if(v >= 1.0f)
- vel->const_acceleration = 1/v;
-
- return Success;
-}
-
-static long
-AccelInitDecelProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
-{
- float fval = 1.0/vel->const_acceleration;
- Atom prop_const_decel = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
- XIChangeDeviceProperty(dev, prop_const_decel,
- XIGetKnownProperty(XATOM_FLOAT), 32,
- PropModeReplace, 1, &fval, FALSE);
- XISetDevicePropertyDeletable(dev, prop_const_decel, FALSE);
- return XIRegisterPropertyHandler(dev, AccelSetDecelProperty, NULL, NULL);
-}
-
-
-/**
- * adaptive deceleration
- */
-static int
-AccelSetAdaptDecelProperty(DeviceIntPtr dev, Atom atom,
- XIPropertyValuePtr val, BOOL checkOnly)
-{
- DeviceVelocityPtr veloc;
- float v, *ptr = &v;
- int rc;
- int nelem = 1;
-
- if (atom != XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION))
- return Success;
-
- veloc = GetDevicePredictableAccelData(dev);
- if (!veloc)
- return BadValue;
- rc = XIPropToFloat(val, &nelem, &ptr);
-
- if(checkOnly)
- {
- if (rc)
- return rc;
- return (v >= 1.0f) ? Success : BadValue;
- }
-
- if(v >= 1.0f)
- veloc->min_acceleration = 1/v;
-
- return Success;
-}
-
-static long
-AccelInitAdaptDecelProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
-{
- float fval = 1.0/vel->min_acceleration;
- Atom prop_adapt_decel = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION);
-
- XIChangeDeviceProperty(dev, prop_adapt_decel, XIGetKnownProperty(XATOM_FLOAT), 32,
- PropModeReplace, 1, &fval, FALSE);
- XISetDevicePropertyDeletable(dev, prop_adapt_decel, FALSE);
- return XIRegisterPropertyHandler(dev, AccelSetAdaptDecelProperty, NULL, NULL);
-}
-
-
-/**
- * velocity scaling
- */
-static int
-AccelSetScaleProperty(DeviceIntPtr dev, Atom atom,
- XIPropertyValuePtr val, BOOL checkOnly)
-{
- DeviceVelocityPtr vel;
- float v, *ptr = &v;
- int rc;
- int nelem = 1;
-
- if (atom != XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING))
- return Success;
-
- vel = GetDevicePredictableAccelData(dev);
- if (!vel)
- return BadValue;
- rc = XIPropToFloat(val, &nelem, &ptr);
-
- if (checkOnly)
- {
- if (rc)
- return rc;
-
- return (v > 0) ? Success : BadValue;
- }
-
- if(v > 0)
- vel->corr_mul = v;
-
- return Success;
-}
-
-static long
-AccelInitScaleProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
-{
- float fval = vel->corr_mul;
- Atom prop_velo_scale = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING);
-
- XIChangeDeviceProperty(dev, prop_velo_scale, XIGetKnownProperty(XATOM_FLOAT), 32,
- PropModeReplace, 1, &fval, FALSE);
- XISetDevicePropertyDeletable(dev, prop_velo_scale, FALSE);
- return XIRegisterPropertyHandler(dev, AccelSetScaleProperty, NULL, NULL);
-}
-
-static BOOL
-InitializePredictableAccelerationProperties(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- PredictableAccelSchemePtr schemeData)
-{
- int num_handlers = 4;
- if(!vel)
- return FALSE;
-
- schemeData->prop_handlers = calloc(num_handlers, sizeof(long));
- if (!schemeData->prop_handlers)
- return FALSE;
- schemeData->num_prop_handlers = num_handlers;
- schemeData->prop_handlers[0] = AccelInitProfileProperty(dev, vel);
- schemeData->prop_handlers[1] = AccelInitDecelProperty(dev, vel);
- schemeData->prop_handlers[2] = AccelInitAdaptDecelProperty(dev, vel);
- schemeData->prop_handlers[3] = AccelInitScaleProperty(dev, vel);
-
- return TRUE;
-}
-
-BOOL
-DeletePredictableAccelerationProperties(
- DeviceIntPtr dev,
- PredictableAccelSchemePtr scheme)
-{
- DeviceVelocityPtr vel;
- Atom prop;
- int i;
-
- prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING);
- XIDeleteDeviceProperty(dev, prop, FALSE);
- prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION);
- XIDeleteDeviceProperty(dev, prop, FALSE);
- prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
- XIDeleteDeviceProperty(dev, prop, FALSE);
- prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
- XIDeleteDeviceProperty(dev, prop, FALSE);
-
- vel = GetDevicePredictableAccelData(dev);
- if (vel) {
- for (i = 0; i < scheme->num_prop_handlers; i++)
- if (scheme->prop_handlers[i])
- XIUnregisterPropertyHandler(dev, scheme->prop_handlers[i]);
- }
-
- free(scheme->prop_handlers);
- scheme->prop_handlers = NULL;
- scheme->num_prop_handlers = 0;
- return TRUE;
-}
-
-/*********************
- * Tracking logic
- ********************/
-
-void
-InitTrackers(DeviceVelocityPtr vel, int ntracker)
-{
- if(ntracker < 1){
- ErrorF("(dix ptracc) invalid number of trackers\n");
- return;
- }
- free(vel->tracker);
- vel->tracker = (MotionTrackerPtr)calloc(ntracker, sizeof(MotionTracker));
- vel->num_tracker = ntracker;
-}
-
-/**
- * return a bit field of possible directions.
- * 0 = N, 2 = E, 4 = S, 6 = W, in-between is as you guess.
- * There's no reason against widening to more precise directions (<45 degrees),
- * should it not perform well. All this is needed for is sort out non-linear
- * motion, so precision isn't paramount. However, one should not flag direction
- * too narrow, since it would then cut the linear segment to zero size way too
- * often.
- */
-static int
-DoGetDirection(int dx, int dy){
- float r;
- int i1, i2;
- /* on insignificant mickeys, flag 135 degrees */
- if(abs(dx) < 2 && abs(dy < 2)){
- /* first check diagonal cases */
- if(dx > 0 && dy > 0)
- return 4+8+16;
- if(dx > 0 && dy < 0)
- return 1+2+4;
- if(dx < 0 && dy < 0)
- return 1+128+64;
- if(dx < 0 && dy > 0)
- return 16+32+64;
- /* check axis-aligned directions */
- if(dx > 0)
- return 2+4+8; /*E*/
- if(dx < 0)
- return 128+64+32; /*W*/
- if(dy > 0)
- return 32+16+8; /*S*/
- if(dy < 0)
- return 128+1+2; /*N*/
- return 255; /* shouldn't happen */
- }
- /* else, compute angle and set appropriate flags */
-#ifdef _ISOC99_SOURCE
- r = atan2f(dy, dx);
-#else
- r = atan2(dy, dx);
-#endif
- /* find direction. We avoid r to become negative,
- * since C has no well-defined modulo for such cases. */
- r = (r+(M_PI*2.5))/(M_PI/4);
- /* this intends to flag 2 directions (90 degrees),
- * except on very well-aligned mickeys. */
- i1 = (int)(r+0.1) % 8;
- i2 = (int)(r+0.9) % 8;
- if(i1 < 0 || i1 > 7 || i2 < 0 || i2 > 7)
- return 255; /* shouldn't happen */
- return 1 << i1 | 1 << i2;
-}
-
-#define DIRECTION_CACHE_RANGE 5
-#define DIRECTION_CACHE_SIZE (DIRECTION_CACHE_RANGE*2+1)
-
-/* cache DoGetDirection(). */
-static int
-GetDirection(int dx, int dy){
- static int cache[DIRECTION_CACHE_SIZE][DIRECTION_CACHE_SIZE];
- int i;
- if (abs(dx) <= DIRECTION_CACHE_RANGE &&
- abs(dy) <= DIRECTION_CACHE_RANGE) {
- /* cacheable */
- i = cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy];
- if(i != 0){
- return i;
- }else{
- i = DoGetDirection(dx, dy);
- cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy] = i;
- return i;
- }
- }else{
- /* non-cacheable */
- return DoGetDirection(dx, dy);
- }
-}
-
-#undef DIRECTION_CACHE_RANGE
-#undef DIRECTION_CACHE_SIZE
-
-
-/* convert offset (age) to array index */
-#define TRACKER_INDEX(s, d) (((s)->num_tracker + (s)->cur_tracker - (d)) % (s)->num_tracker)
-
-static inline void
-FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t)
-{
- int n;
- for(n = 0; n < vel->num_tracker; n++){
- vel->tracker[n].dx += dx;
- vel->tracker[n].dy += dy;
- }
- n = (vel->cur_tracker + 1) % vel->num_tracker;
- vel->tracker[n].dx = 0;
- vel->tracker[n].dy = 0;
- vel->tracker[n].time = cur_t;
- vel->tracker[n].dir = GetDirection(dx, dy);
- DebugAccelF("(dix prtacc) motion [dx: %i dy: %i dir:%i diff: %i]\n",
- dx, dy, vel->tracker[n].dir,
- cur_t - vel->tracker[vel->cur_tracker].time);
- vel->cur_tracker = n;
-}
-
-/**
- * calc velocity for given tracker, with
- * velocity scaling.
- * This assumes linear motion.
- */
-static float
-CalcTracker(DeviceVelocityPtr vel, int offset, int cur_t){
- int index = TRACKER_INDEX(vel, offset);
- float dist = sqrt( vel->tracker[index].dx * vel->tracker[index].dx
- + vel->tracker[index].dy * vel->tracker[index].dy);
- int dtime = cur_t - vel->tracker[index].time;
- if(dtime > 0)
- return dist / dtime;
- else
- return 0;/* synonymous for NaN, since we're not C99 */
-}
-
-/* find the most plausible velocity. That is, the most distant
- * (in time) tracker which isn't too old, beyond a linear partition,
- * or simply too much off initial velocity.
- *
- * May return 0.
- */
-static float
-QueryTrackers(DeviceVelocityPtr vel, int cur_t){
- int n, offset, dir = 255, i = -1, age_ms;
- /* initial velocity: a low-offset, valid velocity */
- float iveloc = 0, res = 0, tmp, vdiff;
- float vfac = vel->corr_mul * vel->const_acceleration; /* premultiply */
- /* loop from current to older data */
- for(offset = 1; offset < vel->num_tracker; offset++){
- n = TRACKER_INDEX(vel, offset);
-
- age_ms = cur_t - vel->tracker[n].time;
-
- /* bail out if data is too old and protect from overrun */
- if (age_ms >= vel->reset_time || age_ms < 0) {
- DebugAccelF("(dix prtacc) query: tracker too old\n");
- break;
- }
-
- /*
- * this heuristic avoids using the linear-motion velocity formula
- * in CalcTracker() on motion that isn't exactly linear. So to get
- * even more precision we could subdivide as a final step, so possible
- * non-linearities are accounted for.
- */
- dir &= vel->tracker[n].dir;
- if(dir == 0){
- DebugAccelF("(dix prtacc) query: no longer linear\n");
- /* instead of breaking it we might also inspect the partition after,
- * but actual improvement with this is probably rare. */
- break;
- }
-
- tmp = CalcTracker(vel, offset, cur_t) * vfac;
-
- if ((iveloc == 0 || offset <= vel->initial_range) && tmp != 0) {
- /* set initial velocity and result */
- res = iveloc = tmp;
- i = offset;
- } else if (iveloc != 0 && tmp != 0) {
- vdiff = fabs(iveloc - tmp);
- if (vdiff <= vel->max_diff ||
- vdiff/(iveloc + tmp) < vel->max_rel_diff) {
- /* we're in range with the initial velocity,
- * so this result is likely better
- * (it contains more information). */
- res = tmp;
- i = offset;
- }else{
- /* we're not in range, quit - it won't get better. */
- DebugAccelF("(dix prtacc) query: tracker too different:"
- " old %2.2f initial %2.2f diff: %2.2f\n",
- tmp, iveloc, vdiff);
- break;
- }
- }
- }
- if(offset == vel->num_tracker){
- DebugAccelF("(dix prtacc) query: last tracker in effect\n");
- i = vel->num_tracker-1;
- }
- if(i>=0){
- n = TRACKER_INDEX(vel, i);
- DebugAccelF("(dix prtacc) result: offset %i [dx: %i dy: %i diff: %i]\n",
- i,
- vel->tracker[n].dx,
- vel->tracker[n].dy,
- cur_t - vel->tracker[n].time);
- }
- return res;
-}
-
-#undef TRACKER_INDEX
-
-/**
- * Perform velocity approximation based on 2D 'mickeys' (mouse motion delta).
- * return true if non-visible state reset is suggested
- */
-short
-ProcessVelocityData2D(
- DeviceVelocityPtr vel,
- int dx,
- int dy,
- int time)
-{
- float velocity;
-
- vel->last_velocity = vel->velocity;
-
- FeedTrackers(vel, dx, dy, time);
-
- velocity = QueryTrackers(vel, time);
-
- vel->velocity = velocity;
- return velocity == 0;
-}
-
-/**
- * this flattens significant ( > 1) mickeys a little bit for more steady
- * constant-velocity response
- */
-static inline float
-ApplySimpleSoftening(int od, int d)
-{
- float res = d;
- if (d <= 1 && d >= -1)
- return res;
- if (d > od)
- res -= 0.5;
- else if (d < od)
- res += 0.5;
- return res;
-}
-
-
-static void
-ApplySofteningAndConstantDeceleration(
- DeviceVelocityPtr vel,
- int dx,
- int dy,
- float* fdx,
- float* fdy,
- short do_soften)
-{
- if (do_soften && vel->use_softening) {
- *fdx = ApplySimpleSoftening(vel->last_dx, dx);
- *fdy = ApplySimpleSoftening(vel->last_dy, dy);
- } else {
- *fdx = dx;
- *fdy = dy;
- }
-
- *fdx *= vel->const_acceleration;
- *fdy *= vel->const_acceleration;
-}
-
-/*
- * compute the acceleration for given velocity and enforce min_acceleartion
- */
-float
-BasicComputeAcceleration(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc){
-
- float result;
- result = vel->Profile(dev, vel, velocity, threshold, acc);
-
- /* enforce min_acceleration */
- if (result < vel->min_acceleration)
- result = vel->min_acceleration;
- return result;
-}
-
-/**
- * Compute acceleration. Takes into account averaging, nv-reset, etc.
- */
-static float
-ComputeAcceleration(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float threshold,
- float acc){
- float res;
-
- if(vel->velocity <= 0){
- DebugAccelF("(dix ptracc) profile skipped\n");
- /*
- * If we have no idea about device velocity, don't pretend it.
- */
- return 1;
- }
-
- if(vel->average_accel && vel->velocity != vel->last_velocity){
- /* use simpson's rule to average acceleration between
- * current and previous velocity.
- * Though being the more natural choice, it causes a minor delay
- * in comparison, so it can be disabled. */
- res = BasicComputeAcceleration(
- dev, vel, vel->velocity, threshold, acc);
- res += BasicComputeAcceleration(
- dev, vel, vel->last_velocity, threshold, acc);
- res += 4.0f * BasicComputeAcceleration(dev, vel,
- (vel->last_velocity + vel->velocity) / 2,
- threshold, acc);
- res /= 6.0f;
- DebugAccelF("(dix ptracc) profile average [%.2f ... %.2f] is %.3f\n",
- vel->velocity, vel->last_velocity, res);
- return res;
- }else{
- res = BasicComputeAcceleration(dev, vel,
- vel->velocity, threshold, acc);
- DebugAccelF("(dix ptracc) profile sample [%.2f] is %.3f\n",
- vel->velocity, res);
- return res;
- }
-}
-
-
-/*****************************************
- * Acceleration functions and profiles
- ****************************************/
-
-/**
- * Polynomial function similar previous one, but with f(1) = 1
- */
-static float
-PolynomialAccelerationProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float ignored,
- float acc)
-{
- return pow(velocity, (acc - 1.0) * 0.5);
-}
-
-
-/**
- * returns acceleration for velocity.
- * This profile selects the two functions like the old scheme did
- */
-static float
-ClassicProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- if (threshold > 0) {
- return SimpleSmoothProfile (dev,
- vel,
- velocity,
- threshold,
- acc);
- } else {
- return PolynomialAccelerationProfile (dev,
- vel,
- velocity,
- 0,
- acc);
- }
-}
-
-
-/**
- * Power profile
- * This has a completely smooth transition curve, i.e. no jumps in the
- * derivatives.
- *
- * This has the expense of overall response dependency on min-acceleration.
- * In effect, min_acceleration mimics const_acceleration in this profile.
- */
-static float
-PowerProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- float vel_dist;
-
- acc = (acc-1.0) * 0.1f + 1.0; /* without this, acc of 2 is unuseable */
-
- if (velocity <= threshold)
- return vel->min_acceleration;
- vel_dist = velocity - threshold;
- return (pow(acc, vel_dist)) * vel->min_acceleration;
-}
-
-
-/**
- * just a smooth function in [0..1] -> [0..1]
- * - point symmetry at 0.5
- * - f'(0) = f'(1) = 0
- * - starts faster than a sinoid
- * - smoothness C1 (Cinf if you dare to ignore endpoints)
- */
-static inline float
-CalcPenumbralGradient(float x){
- x *= 2.0f;
- x -= 1.0f;
- return 0.5f + (x * sqrt(1.0f - x*x) + asin(x))/M_PI;
-}
-
-
-/**
- * acceleration function similar to classic accelerated/unaccelerated,
- * but with smooth transition in between (and towards zero for adaptive dec.).
- */
-static float
-SimpleSmoothProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- if(velocity < 1.0f)
- return CalcPenumbralGradient(0.5 + velocity*0.5) * 2.0f - 1.0f;
- if(threshold < 1.0f)
- threshold = 1.0f;
- if (velocity <= threshold)
- return 1;
- velocity /= threshold;
- if (velocity >= acc)
- return acc;
- else
- return 1.0f + (CalcPenumbralGradient(velocity/acc) * (acc - 1.0f));
-}
-
-
-/**
- * This profile uses the first half of the penumbral gradient as a start
- * and then scales linearly.
- */
-static float
-SmoothLinearProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- float res, nv;
-
- if(acc > 1.0f)
- acc -= 1.0f; /*this is so acc = 1 is no acceleration */
- else
- return 1.0f;
-
- nv = (velocity - threshold) * acc * 0.5f;
-
- if(nv < 0){
- res = 0;
- }else if(nv < 2){
- res = CalcPenumbralGradient(nv*0.25f)*2.0f;
- }else{
- nv -= 2.0f;
- res = nv * 2.0f / M_PI /* steepness of gradient at 0.5 */
- + 1.0f; /* gradient crosses 2|1 */
- }
- res += vel->min_acceleration;
- return res;
-}
-
-
-/**
- * From 0 to threshold, the response graduates smoothly from min_accel to
- * acceleration. Beyond threshold it is exactly the specified acceleration.
- */
-static float
-SmoothLimitedProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- float res;
-
- if(velocity >= threshold || threshold == 0.0f)
- return acc;
-
- velocity /= threshold; /* should be [0..1[ now */
-
- res = CalcPenumbralGradient(velocity) * (acc - vel->min_acceleration);
-
- return vel->min_acceleration + res;
-}
-
-
-static float
-LinearProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- return acc * velocity;
-}
-
-static float
-NoProfile(
- DeviceIntPtr dev,
- DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
-{
- return 1.0f;
-}
-
-static PointerAccelerationProfileFunc
-GetAccelerationProfile(
- DeviceVelocityPtr vel,
- int profile_num)
-{
- switch(profile_num){
- case AccelProfileClassic:
- return ClassicProfile;
- case AccelProfileDeviceSpecific:
- return vel->deviceSpecificProfile;
- case AccelProfilePolynomial:
- return PolynomialAccelerationProfile;
- case AccelProfileSmoothLinear:
- return SmoothLinearProfile;
- case AccelProfileSimple:
- return SimpleSmoothProfile;
- case AccelProfilePower:
- return PowerProfile;
- case AccelProfileLinear:
- return LinearProfile;
- case AccelProfileSmoothLimited:
- return SmoothLimitedProfile;
- case AccelProfileNone:
- return NoProfile;
- default:
- return NULL;
- }
-}
-
-/**
- * Set the profile by number.
- * Intended to make profiles exchangeable at runtime.
- * If you created a profile, give it a number here and in the header to
- * make it selectable. In case some profile-specific init is needed, here
- * would be a good place, since FreeVelocityData() also calls this with
- * PROFILE_UNINITIALIZE.
- *
- * returns FALSE if profile number is unavailable, TRUE otherwise.
- */
-int
-SetAccelerationProfile(
- DeviceVelocityPtr vel,
- int profile_num)
-{
- PointerAccelerationProfileFunc profile;
- profile = GetAccelerationProfile(vel, profile_num);
-
- if(profile == NULL && profile_num != PROFILE_UNINITIALIZE)
- return FALSE;
-
- /* Here one could free old profile-private data */
- free(vel->profile_private);
- vel->profile_private = NULL;
- /* Here one could init profile-private data */
- vel->Profile = profile;
- vel->statistics.profile_number = profile_num;
- return TRUE;
-}
-
-/**********************************************
- * driver interaction
- **********************************************/
-
-
-/**
- * device-specific profile
- *
- * The device-specific profile is intended as a hook for a driver
- * which may want to provide an own acceleration profile.
- * It should not rely on profile-private data, instead
- * it should do init/uninit in the driver (ie. with DEVICE_INIT and friends).
- * Users may override or choose it.
- */
-void
-SetDeviceSpecificAccelerationProfile(
- DeviceVelocityPtr vel,
- PointerAccelerationProfileFunc profile)
-{
- if(vel)
- vel->deviceSpecificProfile = profile;
-}
-
-/**
- * Use this function to obtain a DeviceVelocityPtr for a device. Will return NULL if
- * the predictable acceleration scheme is not in effect.
- */
-DeviceVelocityPtr
-GetDevicePredictableAccelData(
- DeviceIntPtr dev)
-{
- /*sanity check*/
- if(!dev){
- ErrorF("[dix] accel: DeviceIntPtr was NULL");
- return NULL;
- }
- if( dev->valuator &&
- dev->valuator->accelScheme.AccelSchemeProc ==
- acceleratePointerPredictable &&
- dev->valuator->accelScheme.accelData != NULL){
-
- return ((PredictableAccelSchemePtr)
- dev->valuator->accelScheme.accelData)->vel;
- }
- return NULL;
-}
-
-/********************************
- * acceleration schemes
- *******************************/
-
-/**
- * Modifies valuators in-place.
- * This version employs a velocity approximation algorithm to
- * enable fine-grained predictable acceleration profiles.
- */
-void
-acceleratePointerPredictable(
- DeviceIntPtr dev,
- ValuatorMask* val,
- CARD32 evtime)
-{
- float fdx, fdy, tmp, mult; /* no need to init */
- int dx = 0, dy = 0, tmpi;
- DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev);
- Bool soften = TRUE;
-
- if (!velocitydata)
- return;
-
- if (velocitydata->statistics.profile_number == AccelProfileNone &&
- velocitydata->const_acceleration == 1.0f) {
- return; /*we're inactive anyway, so skip the whole thing.*/
- }
-
- if (valuator_mask_isset(val, 0)) {
- dx = valuator_mask_get(val, 0);
- }
-
- if (valuator_mask_isset(val, 1)) {
- dy = valuator_mask_get(val, 1);
- }
-
- if (dx || dy){
- /* reset non-visible state? */
- if (ProcessVelocityData2D(velocitydata, dx , dy, evtime)) {
- soften = FALSE;
- }
-
- if (dev->ptrfeed && dev->ptrfeed->ctrl.num) {
- /* invoke acceleration profile to determine acceleration */
- mult = ComputeAcceleration (dev, velocitydata,
- dev->ptrfeed->ctrl.threshold,
- (float)dev->ptrfeed->ctrl.num /
- (float)dev->ptrfeed->ctrl.den);
-
- if(mult != 1.0f || velocitydata->const_acceleration != 1.0f) {
- ApplySofteningAndConstantDeceleration(velocitydata,
- dx, dy,
- &fdx, &fdy,
- (mult > 1.0f) && soften);
-
- if (dx) {
- tmp = mult * fdx + dev->last.remainder[0];
- /* Since it may not be apparent: lrintf() does not offer
- * strong statements about rounding; however because we
- * process each axis conditionally, there's no danger
- * of a toggling remainder. Its lack of guarantees likely
- * makes it faster on the average target. */
- tmpi = lrintf(tmp);
- valuator_mask_set(val, 0, tmpi);
- dev->last.remainder[0] = tmp - (float)tmpi;
- }
- if (dy) {
- tmp = mult * fdy + dev->last.remainder[1];
- tmpi = lrintf(tmp);
- valuator_mask_set(val, 1, tmpi);
- dev->last.remainder[1] = tmp - (float)tmpi;
- }
- DebugAccelF("pos (%i | %i) remainders x: %.3f y: %.3f delta x:%.3f y:%.3f\n",
- *px, *py, dev->last.remainder[0], dev->last.remainder[1], fdx, fdy);
- }
- }
- }
- /* remember last motion delta (for softening/slow movement treatment) */
- velocitydata->last_dx = dx;
- velocitydata->last_dy = dy;
-}
-
-
-
-/**
- * Originally a part of xf86PostMotionEvent; modifies valuators
- * in-place. Retained mostly for embedded scenarios.
- */
-void
-acceleratePointerLightweight(
- DeviceIntPtr dev,
- ValuatorMask* val,
- CARD32 ignored)
-{
- float mult = 0.0, tmpf;
- int dx = 0, dy = 0, tmpi;
-
- if (valuator_mask_isset(val, 0)) {
- dx = valuator_mask_get(val, 0);
- }
-
- if (valuator_mask_isset(val, 1)) {
- dy = valuator_mask_get(val, 1);
- }
-
- if (!dx && !dy)
- return;
-
- if (dev->ptrfeed && dev->ptrfeed->ctrl.num) {
- /* modeled from xf86Events.c */
- if (dev->ptrfeed->ctrl.threshold) {
- if ((abs(dx) + abs(dy)) >= dev->ptrfeed->ctrl.threshold) {
- tmpf = ((float)dx *
- (float)(dev->ptrfeed->ctrl.num)) /
- (float)(dev->ptrfeed->ctrl.den) +
- dev->last.remainder[0];
- if (dx) {
- tmpi = (int) tmpf;
- valuator_mask_set(val, 0, tmpi);
- dev->last.remainder[0] = tmpf - (float)tmpi;
- }
-
- tmpf = ((float)dy *
- (float)(dev->ptrfeed->ctrl.num)) /
- (float)(dev->ptrfeed->ctrl.den) +
- dev->last.remainder[1];
- if (dy) {
- tmpi = (int) tmpf;
- valuator_mask_set(val, 1, tmpi);
- dev->last.remainder[1] = tmpf - (float)tmpi;
- }
- }
- }
- else {
- mult = pow((float)dx * (float)dx + (float)dy * (float)dy,
- ((float)(dev->ptrfeed->ctrl.num) /
- (float)(dev->ptrfeed->ctrl.den) - 1.0) /
- 2.0) / 2.0;
- if (dx) {
- tmpf = mult * (float)dx +
- dev->last.remainder[0];
- tmpi = (int) tmpf;
- valuator_mask_set(val, 0, tmpi);
- dev->last.remainder[0] = tmpf - (float)tmpi;
- }
- if (dy) {
- tmpf = mult * (float)dy +
- dev->last.remainder[1];
- tmpi = (int)tmpf;
- valuator_mask_set(val, 1, tmpi);
- dev->last.remainder[1] = tmpf - (float)tmpi;
- }
- }
- }
-}
+/*
+ *
+ * Copyright © 2006-2009 Simon Thum simon dot thum at gmx dot de
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <math.h>
+#include <ptrveloc.h>
+#include <exevents.h>
+#include <X11/Xatom.h>
+#include <os.h>
+
+#include <xserver-properties.h>
+
+/*****************************************************************************
+ * Predictable pointer acceleration
+ *
+ * 2006-2009 by Simon Thum (simon [dot] thum [at] gmx de)
+ *
+ * Serves 3 complementary functions:
+ * 1) provide a sophisticated ballistic velocity estimate to improve
+ * the relation between velocity (of the device) and acceleration
+ * 2) make arbitrary acceleration profiles possible
+ * 3) decelerate by two means (constant and adaptive) if enabled
+ *
+ * Important concepts are the
+ *
+ * - Scheme
+ * which selects the basic algorithm
+ * (see devices.c/InitPointerAccelerationScheme)
+ * - Profile
+ * which returns an acceleration
+ * for a given velocity
+ *
+ * The profile can be selected by the user at runtime.
+ * The classic profile is intended to cleanly perform old-style
+ * function selection (threshold =/!= 0)
+ *
+ ****************************************************************************/
+
+/* fwds */
+int
+SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
+static float
+SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, float velocity,
+ float threshold, float acc);
+static PointerAccelerationProfileFunc
+GetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
+static BOOL
+InitializePredictableAccelerationProperties(DeviceIntPtr,
+ DeviceVelocityPtr,
+ PredictableAccelSchemePtr);
+static BOOL
+DeletePredictableAccelerationProperties(DeviceIntPtr,
+ PredictableAccelSchemePtr);
+
+/*#define PTRACCEL_DEBUGGING*/
+
+#ifdef PTRACCEL_DEBUGGING
+#define DebugAccelF ErrorF
+#else
+#define DebugAccelF(...) /* */
+#endif
+
+/********************************
+ * Init/Uninit
+ *******************************/
+
+/* some int which is not a profile number */
+#define PROFILE_UNINITIALIZE (-100)
+
+/**
+ * Init DeviceVelocity struct so it should match the average case
+ */
+void
+InitVelocityData(DeviceVelocityPtr vel)
+{
+ memset(vel, 0, sizeof(DeviceVelocityRec));
+
+ vel->corr_mul = 10.0; /* dots per 10 milisecond should be usable */
+ vel->const_acceleration = 1.0; /* no acceleration/deceleration */
+ vel->reset_time = 300;
+ vel->use_softening = 1;
+ vel->min_acceleration = 1.0; /* don't decelerate */
+ vel->max_rel_diff = 0.2;
+ vel->max_diff = 1.0;
+ vel->initial_range = 2;
+ vel->average_accel = TRUE;
+ SetAccelerationProfile(vel, AccelProfileClassic);
+ InitTrackers(vel, 16);
+}
+
+
+/**
+ * Clean up DeviceVelocityRec
+ */
+void
+FreeVelocityData(DeviceVelocityPtr vel){
+ free(vel->tracker);
+ SetAccelerationProfile(vel, PROFILE_UNINITIALIZE);
+}
+
+
+/**
+ * Init predictable scheme
+ */
+Bool
+InitPredictableAccelerationScheme(DeviceIntPtr dev,
+ ValuatorAccelerationPtr protoScheme) {
+ DeviceVelocityPtr vel;
+ ValuatorAccelerationRec scheme;
+ PredictableAccelSchemePtr schemeData;
+ scheme = *protoScheme;
+ vel = calloc(1, sizeof(DeviceVelocityRec));
+ schemeData = calloc(1, sizeof(PredictableAccelSchemeRec));
+ if (!vel || !schemeData)
+ return FALSE;
+ InitVelocityData(vel);
+ schemeData->vel = vel;
+ scheme.accelData = schemeData;
+ if (!InitializePredictableAccelerationProperties(dev, vel, schemeData))
+ return FALSE;
+ /* all fine, assign scheme to device */
+ dev->valuator->accelScheme = scheme;
+ return TRUE;
+}
+
+
+/**
+ * Uninit scheme
+ */
+void
+AccelerationDefaultCleanup(DeviceIntPtr dev)
+{
+ DeviceVelocityPtr vel = GetDevicePredictableAccelData(dev);
+ if (vel) {
+ /* the proper guarantee would be that we're not inside of
+ * AccelSchemeProc(), but that seems impossible. Schemes don't get
+ * switched often anyway.
+ */
+ OsBlockSignals();
+ dev->valuator->accelScheme.AccelSchemeProc = NULL;
+ FreeVelocityData(vel);
+ free(vel);
+ DeletePredictableAccelerationProperties(dev,
+ (PredictableAccelSchemePtr) dev->valuator->accelScheme.accelData);
+ free(dev->valuator->accelScheme.accelData);
+ dev->valuator->accelScheme.accelData = NULL;
+ OsReleaseSignals();
+ }
+}
+
+
+/*************************
+ * Input property support
+ ************************/
+
+/**
+ * choose profile
+ */
+static int
+AccelSetProfileProperty(DeviceIntPtr dev, Atom atom,
+ XIPropertyValuePtr val, BOOL checkOnly)
+{
+ DeviceVelocityPtr vel;
+ int profile, *ptr = &profile;
+ int rc;
+ int nelem = 1;
+
+ if (atom != XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER))
+ return Success;
+
+ vel = GetDevicePredictableAccelData(dev);
+ if (!vel)
+ return BadValue;
+ rc = XIPropToInt(val, &nelem, &ptr);
+
+ if(checkOnly)
+ {
+ if (rc)
+ return rc;
+
+ if (GetAccelerationProfile(vel, profile) == NULL)
+ return BadValue;
+ } else
+ SetAccelerationProfile(vel, profile);
+
+ return Success;
+}
+
+static long
+AccelInitProfileProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
+{
+ int profile = vel->statistics.profile_number;
+ Atom prop_profile_number = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
+
+ XIChangeDeviceProperty(dev, prop_profile_number, XA_INTEGER, 32,
+ PropModeReplace, 1, &profile, FALSE);
+ XISetDevicePropertyDeletable(dev, prop_profile_number, FALSE);
+ return XIRegisterPropertyHandler(dev, AccelSetProfileProperty, NULL, NULL);
+}
+
+/**
+ * constant deceleration
+ */
+static int
+AccelSetDecelProperty(DeviceIntPtr dev, Atom atom,
+ XIPropertyValuePtr val, BOOL checkOnly)
+{
+ DeviceVelocityPtr vel;
+ float v, *ptr = &v;
+ int rc;
+ int nelem = 1;
+
+ if (atom != XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION))
+ return Success;
+
+ vel = GetDevicePredictableAccelData(dev);
+ if (!vel)
+ return BadValue;
+ rc = XIPropToFloat(val, &nelem, &ptr);
+
+ if(checkOnly)
+ {
+ if (rc)
+ return rc;
+ return (v >= 1.0f) ? Success : BadValue;
+ }
+
+ if(v >= 1.0f)
+ vel->const_acceleration = 1/v;
+
+ return Success;
+}
+
+static long
+AccelInitDecelProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
+{
+ float fval = 1.0/vel->const_acceleration;
+ Atom prop_const_decel = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
+ XIChangeDeviceProperty(dev, prop_const_decel,
+ XIGetKnownProperty(XATOM_FLOAT), 32,
+ PropModeReplace, 1, &fval, FALSE);
+ XISetDevicePropertyDeletable(dev, prop_const_decel, FALSE);
+ return XIRegisterPropertyHandler(dev, AccelSetDecelProperty, NULL, NULL);
+}
+
+
+/**
+ * adaptive deceleration
+ */
+static int
+AccelSetAdaptDecelProperty(DeviceIntPtr dev, Atom atom,
+ XIPropertyValuePtr val, BOOL checkOnly)
+{
+ DeviceVelocityPtr veloc;
+ float v, *ptr = &v;
+ int rc;
+ int nelem = 1;
+
+ if (atom != XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION))
+ return Success;
+
+ veloc = GetDevicePredictableAccelData(dev);
+ if (!veloc)
+ return BadValue;
+ rc = XIPropToFloat(val, &nelem, &ptr);
+
+ if(checkOnly)
+ {
+ if (rc)
+ return rc;
+ return (v >= 1.0f) ? Success : BadValue;
+ }
+
+ if(v >= 1.0f)
+ veloc->min_acceleration = 1/v;
+
+ return Success;
+}
+
+static long
+AccelInitAdaptDecelProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
+{
+ float fval = 1.0/vel->min_acceleration;
+ Atom prop_adapt_decel = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION);
+
+ XIChangeDeviceProperty(dev, prop_adapt_decel, XIGetKnownProperty(XATOM_FLOAT), 32,
+ PropModeReplace, 1, &fval, FALSE);
+ XISetDevicePropertyDeletable(dev, prop_adapt_decel, FALSE);
+ return XIRegisterPropertyHandler(dev, AccelSetAdaptDecelProperty, NULL, NULL);
+}
+
+
+/**
+ * velocity scaling
+ */
+static int
+AccelSetScaleProperty(DeviceIntPtr dev, Atom atom,
+ XIPropertyValuePtr val, BOOL checkOnly)
+{
+ DeviceVelocityPtr vel;
+ float v, *ptr = &v;
+ int rc;
+ int nelem = 1;
+
+ if (atom != XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING))
+ return Success;
+
+ vel = GetDevicePredictableAccelData(dev);
+ if (!vel)
+ return BadValue;
+ rc = XIPropToFloat(val, &nelem, &ptr);
+
+ if (checkOnly)
+ {
+ if (rc)
+ return rc;
+
+ return (v > 0) ? Success : BadValue;
+ }
+
+ if(v > 0)
+ vel->corr_mul = v;
+
+ return Success;
+}
+
+static long
+AccelInitScaleProperty(DeviceIntPtr dev, DeviceVelocityPtr vel)
+{
+ float fval = vel->corr_mul;
+ Atom prop_velo_scale = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING);
+
+ XIChangeDeviceProperty(dev, prop_velo_scale, XIGetKnownProperty(XATOM_FLOAT), 32,
+ PropModeReplace, 1, &fval, FALSE);
+ XISetDevicePropertyDeletable(dev, prop_velo_scale, FALSE);
+ return XIRegisterPropertyHandler(dev, AccelSetScaleProperty, NULL, NULL);
+}
+
+static BOOL
+InitializePredictableAccelerationProperties(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ PredictableAccelSchemePtr schemeData)
+{
+ int num_handlers = 4;
+ if(!vel)
+ return FALSE;
+
+ schemeData->prop_handlers = calloc(num_handlers, sizeof(long));
+ if (!schemeData->prop_handlers)
+ return FALSE;
+ schemeData->num_prop_handlers = num_handlers;
+ schemeData->prop_handlers[0] = AccelInitProfileProperty(dev, vel);
+ schemeData->prop_handlers[1] = AccelInitDecelProperty(dev, vel);
+ schemeData->prop_handlers[2] = AccelInitAdaptDecelProperty(dev, vel);
+ schemeData->prop_handlers[3] = AccelInitScaleProperty(dev, vel);
+
+ return TRUE;
+}
+
+BOOL
+DeletePredictableAccelerationProperties(
+ DeviceIntPtr dev,
+ PredictableAccelSchemePtr scheme)
+{
+ DeviceVelocityPtr vel;
+ Atom prop;
+ int i;
+
+ prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING);
+ XIDeleteDeviceProperty(dev, prop, FALSE);
+ prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION);
+ XIDeleteDeviceProperty(dev, prop, FALSE);
+ prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
+ XIDeleteDeviceProperty(dev, prop, FALSE);
+ prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
+ XIDeleteDeviceProperty(dev, prop, FALSE);
+
+ vel = GetDevicePredictableAccelData(dev);
+ if (vel) {
+ for (i = 0; i < scheme->num_prop_handlers; i++)
+ if (scheme->prop_handlers[i])
+ XIUnregisterPropertyHandler(dev, scheme->prop_handlers[i]);
+ }
+
+ free(scheme->prop_handlers);
+ scheme->prop_handlers = NULL;
+ scheme->num_prop_handlers = 0;
+ return TRUE;
+}
+
+/*********************
+ * Tracking logic
+ ********************/
+
+void
+InitTrackers(DeviceVelocityPtr vel, int ntracker)
+{
+ if(ntracker < 1){
+ ErrorF("(dix ptracc) invalid number of trackers\n");
+ return;
+ }
+ free(vel->tracker);
+ vel->tracker = (MotionTrackerPtr)calloc(ntracker, sizeof(MotionTracker));
+ vel->num_tracker = ntracker;
+}
+
+enum directions {
+ N = (1 << 0),
+ NE = (1 << 1),
+ E = (1 << 2),
+ SE = (1 << 3),
+ S = (1 << 4),
+ SW = (1 << 5),
+ W = (1 << 6),
+ NW = (1 << 7),
+ UNDEFINED = 0xFF
+};
+/**
+ * return a bit field of possible directions.
+ * There's no reason against widening to more precise directions (<45 degrees),
+ * should it not perform well. All this is needed for is sort out non-linear
+ * motion, so precision isn't paramount. However, one should not flag direction
+ * too narrow, since it would then cut the linear segment to zero size way too
+ * often.
+ *
+ * @return A bitmask for N, NE, S, SE, etc. indicating the directions for
+ * this movement.
+ */
+static int
+DoGetDirection(int dx, int dy){
+ int dir = 0;
+
+ /* on insignificant mickeys, flag 135 degrees */
+ if(abs(dx) < 2 && abs(dy) < 2){
+ /* first check diagonal cases */
+ if(dx > 0 && dy > 0)
+ dir = E | SE | S;
+ else if(dx > 0 && dy < 0)
+ dir = N | NE | E;
+ else if(dx < 0 && dy < 0)
+ dir = W | NW | N;
+ else if(dx < 0 && dy > 0)
+ dir = W | SW | S;
+ /* check axis-aligned directions */
+ else if(dx > 0)
+ dir = NE | E | SE;
+ else if(dx < 0)
+ dir = NW | W | SW;
+ else if(dy > 0)
+ dir = SE | S | SW;
+ else if(dy < 0)
+ dir = NE | N | NW;
+ else
+ dir = UNDEFINED; /* shouldn't happen */
+ } else { /* compute angle and set appropriate flags */
+ float r;
+ int i1, i2;
+
+#ifdef _ISOC99_SOURCE
+ r = atan2f(dy, dx);
+#else
+ r = atan2(dy, dx);
+#endif
+ /* find direction.
+ *
+ * Add 360° to avoid r become negative since C has no well-defined
+ * modulo for such cases. Then divide by 45° to get the octant
+ * number, e.g.
+ * 0 <= r <= 1 is [0-45]°
+ * 1 <= r <= 2 is [45-90]°
+ * etc.
+ * But we add extra 90° to match up with our N, S, etc. defines up
+ * there, rest stays the same.
+ */
+ r = (r+(M_PI*2.5))/(M_PI/4);
+ /* this intends to flag 2 directions (45 degrees),
+ * except on very well-aligned mickeys. */
+ i1 = (int)(r+0.1) % 8;
+ i2 = (int)(r+0.9) % 8;
+ if(i1 < 0 || i1 > 7 || i2 < 0 || i2 > 7)
+ dir = UNDEFINED; /* shouldn't happen */
+ else
+ dir = (1 << i1 | 1 << i2);
+ }
+ return dir;
+}
+
+#define DIRECTION_CACHE_RANGE 5
+#define DIRECTION_CACHE_SIZE (DIRECTION_CACHE_RANGE*2+1)
+
+/* cache DoGetDirection().
+ * To avoid excessive use of direction calculation, cache the values for
+ * [-5..5] for both x/y. Anything outside of that is calcualted on the fly.
+ *
+ * @return A bitmask for N, NE, S, SE, etc. indicating the directions for
+ * this movement.
+ */
+static int
+GetDirection(int dx, int dy){
+ static int cache[DIRECTION_CACHE_SIZE][DIRECTION_CACHE_SIZE];
+ int dir;
+ if (abs(dx) <= DIRECTION_CACHE_RANGE &&
+ abs(dy) <= DIRECTION_CACHE_RANGE) {
+ /* cacheable */
+ dir = cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy];
+ if(dir == 0) {
+ dir = DoGetDirection(dx, dy);
+ cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy] = dir;
+ }
+ }else{
+ /* non-cacheable */
+ dir = DoGetDirection(dx, dy);
+ }
+
+ return dir;
+}
+
+#undef DIRECTION_CACHE_RANGE
+#undef DIRECTION_CACHE_SIZE
+
+
+/* convert offset (age) to array index */
+#define TRACKER_INDEX(s, d) (((s)->num_tracker + (s)->cur_tracker - (d)) % (s)->num_tracker)
+#define TRACKER(s, d) &(s)->tracker[TRACKER_INDEX(s,d)]
+
+/**
+ * Add the delta motion to each tracker, then reset the latest tracker to
+ * 0/0 and set it as the current one.
+ */
+static inline void
+FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t)
+{
+ int n;
+ for(n = 0; n < vel->num_tracker; n++){
+ vel->tracker[n].dx += dx;
+ vel->tracker[n].dy += dy;
+ }
+ n = (vel->cur_tracker + 1) % vel->num_tracker;
+ vel->tracker[n].dx = 0;
+ vel->tracker[n].dy = 0;
+ vel->tracker[n].time = cur_t;
+ vel->tracker[n].dir = GetDirection(dx, dy);
+ DebugAccelF("(dix prtacc) motion [dx: %i dy: %i dir:%i diff: %i]\n",
+ dx, dy, vel->tracker[n].dir,
+ cur_t - vel->tracker[vel->cur_tracker].time);
+ vel->cur_tracker = n;
+}
+
+/**
+ * calc velocity for given tracker, with
+ * velocity scaling.
+ * This assumes linear motion.
+ */
+static float
+CalcTracker(const MotionTracker *tracker, int cur_t){
+ float dist = sqrt(tracker->dx * tracker->dx + tracker->dy * tracker->dy);
+ int dtime = cur_t - tracker->time;
+ if(dtime > 0)
+ return dist / dtime;
+ else
+ return 0;/* synonymous for NaN, since we're not C99 */
+}
+
+/* find the most plausible velocity. That is, the most distant
+ * (in time) tracker which isn't too old, the movement vector was
+ * in the same octant, and where the velocity is within an
+ * acceptable range to the inital velocity.
+ *
+ * @return The tracker's velocity or 0 if the above conditions are unmet
+ */
+static float
+QueryTrackers(DeviceVelocityPtr vel, int cur_t){
+ int offset, dir = UNDEFINED, used_offset = -1, age_ms;
+ /* initial velocity: a low-offset, valid velocity */
+ float initial_velocity = 0, result = 0, velocity_diff;
+ float velocity_factor = vel->corr_mul * vel->const_acceleration; /* premultiply */
+ /* loop from current to older data */
+ for(offset = 1; offset < vel->num_tracker; offset++){
+ MotionTracker *tracker = TRACKER(vel, offset);
+ float tracker_velocity;
+
+ age_ms = cur_t - tracker->time;
+
+ /* bail out if data is too old and protect from overrun */
+ if (age_ms >= vel->reset_time || age_ms < 0) {
+ DebugAccelF("(dix prtacc) query: tracker too old\n");
+ break;
+ }
+
+ /*
+ * this heuristic avoids using the linear-motion velocity formula
+ * in CalcTracker() on motion that isn't exactly linear. So to get
+ * even more precision we could subdivide as a final step, so possible
+ * non-linearities are accounted for.
+ */
+ dir &= tracker->dir;
+ if(dir == 0){ /* we've changed octant of movement (e.g. NE → NW) */
+ DebugAccelF("(dix prtacc) query: no longer linear\n");
+ /* instead of breaking it we might also inspect the partition after,
+ * but actual improvement with this is probably rare. */
+ break;
+ }
+
+ tracker_velocity = CalcTracker(tracker, cur_t) * velocity_factor;
+
+ if ((initial_velocity == 0 || offset <= vel->initial_range) && tracker_velocity != 0) {
+ /* set initial velocity and result */
+ result = initial_velocity = tracker_velocity;
+ used_offset = offset;
+ } else if (initial_velocity != 0 && tracker_velocity != 0) {
+ velocity_diff = fabs(initial_velocity - tracker_velocity);
+
+ if (velocity_diff > vel->max_diff &&
+ velocity_diff/(initial_velocity + tracker_velocity) >= vel->max_rel_diff) {
+ /* we're not in range, quit - it won't get better. */
+ DebugAccelF("(dix prtacc) query: tracker too different:"
+ " old %2.2f initial %2.2f diff: %2.2f\n",
+ tracker_velocity, initial_velocity, velocity_diff);
+ break;
+ }
+ /* we're in range with the initial velocity,
+ * so this result is likely better
+ * (it contains more information). */
+ result = tracker_velocity;
+ used_offset = offset;
+ }
+ }
+ if(offset == vel->num_tracker){
+ DebugAccelF("(dix prtacc) query: last tracker in effect\n");
+ used_offset = vel->num_tracker-1;
+ }
+#ifdef PTRACCEL_DEBUGGING
+ if(used_offset >= 0){
+ MotionTracker *tracker = TRACKER(vel, used_offset);
+ DebugAccelF("(dix prtacc) result: offset %i [dx: %i dy: %i diff: %i]\n",
+ used_offset, tracker->dx, tracker->dy, cur_t - tracker->time);
+ }
+#endif
+ return result;
+}
+
+#undef TRACKER_INDEX
+#undef TRACKER
+
+/**
+ * Perform velocity approximation based on 2D 'mickeys' (mouse motion delta).
+ * return true if non-visible state reset is suggested
+ */
+BOOL
+ProcessVelocityData2D(
+ DeviceVelocityPtr vel,
+ int dx,
+ int dy,
+ int time)
+{
+ float velocity;
+
+ vel->last_velocity = vel->velocity;
+
+ FeedTrackers(vel, dx, dy, time);
+
+ velocity = QueryTrackers(vel, time);
+
+ vel->velocity = velocity;
+ return velocity == 0;
+}
+
+/**
+ * this flattens significant ( > 1) mickeys a little bit for more steady
+ * constant-velocity response
+ */
+static inline float
+ApplySimpleSoftening(int prev_delta, int delta)
+{
+ float result = delta;
+
+ if (delta < -1 || delta > 1) {
+ if (delta > prev_delta)
+ result -= 0.5;
+ else if (delta < prev_delta)
+ result += 0.5;
+ }
+ return result;
+}
+
+
+/**
+ * Soften the delta based on previous deltas stored in vel.
+ *
+ * @param[in,out] fdx Delta X, modified in-place.
+ * @param[in,out] fdx Delta Y, modified in-place.
+ */
+static void
+ApplySoftening(
+ DeviceVelocityPtr vel,
+ float* fdx,
+ float* fdy)
+{
+ if (vel->use_softening) {
+ *fdx = ApplySimpleSoftening(vel->last_dx, *fdx);
+ *fdy = ApplySimpleSoftening(vel->last_dy, *fdy);
+ }
+}
+
+static void
+ApplyConstantDeceleration(DeviceVelocityPtr vel, float *fdx, float *fdy)
+{
+ *fdx *= vel->const_acceleration;
+ *fdy *= vel->const_acceleration;
+}
+
+/*
+ * compute the acceleration for given velocity and enforce min_acceleartion
+ */
+float
+BasicComputeAcceleration(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float threshold,
+ float acc){
+
+ float result;
+ result = vel->Profile(dev, vel, velocity, threshold, acc);
+
+ /* enforce min_acceleration */
+ if (result < vel->min_acceleration)
+ result = vel->min_acceleration;
+ return result;
+}
+
+/**
+ * Compute acceleration. Takes into account averaging, nv-reset, etc.
+ * If the velocity has changed, an average is taken of 6 velocity factors:
+ * current velocity, last velocity and 4 times the average between the two.
+ */
+static float
+ComputeAcceleration(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float threshold,
+ float acc){
+ float result;
+
+ if(vel->velocity <= 0){
+ DebugAccelF("(dix ptracc) profile skipped\n");
+ /*
+ * If we have no idea about device velocity, don't pretend it.
+ */
+ return 1;
+ }
+
+ if(vel->average_accel && vel->velocity != vel->last_velocity){
+ /* use simpson's rule to average acceleration between
+ * current and previous velocity.
+ * Though being the more natural choice, it causes a minor delay
+ * in comparison, so it can be disabled. */
+ result = BasicComputeAcceleration(
+ dev, vel, vel->velocity, threshold, acc);
+ result += BasicComputeAcceleration(
+ dev, vel, vel->last_velocity, threshold, acc);
+ result += 4.0f * BasicComputeAcceleration(dev, vel,
+ (vel->last_velocity + vel->velocity) / 2,
+ threshold, acc);
+ result /= 6.0f;
+ DebugAccelF("(dix ptracc) profile average [%.2f ... %.2f] is %.3f\n",
+ vel->velocity, vel->last_velocity, result);
+ }else{
+ result = BasicComputeAcceleration(dev, vel,
+ vel->velocity, threshold, acc);
+ DebugAccelF("(dix ptracc) profile sample [%.2f] is %.3f\n",
+ vel->velocity, res);
+ }
+
+ return result;
+}
+
+
+/*****************************************
+ * Acceleration functions and profiles
+ ****************************************/
+
+/**
+ * Polynomial function similar previous one, but with f(1) = 1
+ */
+static float
+PolynomialAccelerationProfile(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float ignored,
+ float acc)
+{
+ return pow(velocity, (acc - 1.0) * 0.5);
+}
+
+
+/**
+ * returns acceleration for velocity.
+ * This profile selects the two functions like the old scheme did
+ */
+static float
+ClassicProfile(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float threshold,
+ float acc)
+{
+ if (threshold > 0) {
+ return SimpleSmoothProfile (dev,
+ vel,
+ velocity,
+ threshold,
+ acc);
+ } else {
+ return PolynomialAccelerationProfile (dev,
+ vel,
+ velocity,
+ 0,
+ acc);
+ }
+}
+
+
+/**
+ * Power profile
+ * This has a completely smooth transition curve, i.e. no jumps in the
+ * derivatives.
+ *
+ * This has the expense of overall response dependency on min-acceleration.
+ * In effect, min_acceleration mimics const_acceleration in this profile.
+ */
+static float
+PowerProfile(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float threshold,
+ float acc)
+{
+ float vel_dist;
+
+ acc = (acc-1.0) * 0.1f + 1.0; /* without this, acc of 2 is unuseable */
+
+ if (velocity <= threshold)
+ return vel->min_acceleration;
+ vel_dist = velocity - threshold;
+ return (pow(acc, vel_dist)) * vel->min_acceleration;
+}
+
+
+/**
+ * just a smooth function in [0..1] -> [0..1]
+ * - point symmetry at 0.5
+ * - f'(0) = f'(1) = 0
+ * - starts faster than a sinoid
+ * - smoothness C1 (Cinf if you dare to ignore endpoints)
+ */
+static inline float
+CalcPenumbralGradient(float x){
+ x *= 2.0f;
+ x -= 1.0f;
+ return 0.5f + (x * sqrt(1.0f - x*x) + asin(x))/M_PI;
+}
+
+
+/**
+ * acceleration function similar to classic accelerated/unaccelerated,
+ * but with smooth transition in between (and towards zero for adaptive dec.).
+ */
+static float
+SimpleSmoothProfile(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float threshold,
+ float acc)
+{
+ if(velocity < 1.0f)
+ return CalcPenumbralGradient(0.5 + velocity*0.5) * 2.0f - 1.0f;
+ if(threshold < 1.0f)
+ threshold = 1.0f;
+ if (velocity <= threshold)
+ return 1;
+ velocity /= threshold;
+ if (velocity >= acc)
+ return acc;
+ else
+ return 1.0f + (CalcPenumbralGradient(velocity/acc) * (acc - 1.0f));
+}
+
+
+/**
+ * This profile uses the first half of the penumbral gradient as a start
+ * and then scales linearly.
+ */
+static float
+SmoothLinearProfile(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float threshold,
+ float acc)
+{
+ float res, nv;
+
+ if(acc > 1.0f)
+ acc -= 1.0f; /*this is so acc = 1 is no acceleration */
+ else
+ return 1.0f;
+
+ nv = (velocity - threshold) * acc * 0.5f;
+
+ if(nv < 0){
+ res = 0;
+ }else if(nv < 2){
+ res = CalcPenumbralGradient(nv*0.25f)*2.0f;
+ }else{
+ nv -= 2.0f;
+ res = nv * 2.0f / M_PI /* steepness of gradient at 0.5 */
+ + 1.0f; /* gradient crosses 2|1 */
+ }
+ res += vel->min_acceleration;
+ return res;
+}
+
+
+/**
+ * From 0 to threshold, the response graduates smoothly from min_accel to
+ * acceleration. Beyond threshold it is exactly the specified acceleration.
+ */
+static float
+SmoothLimitedProfile(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float threshold,
+ float acc)
+{
+ float res;
+
+ if(velocity >= threshold || threshold == 0.0f)
+ return acc;
+
+ velocity /= threshold; /* should be [0..1[ now */
+
+ res = CalcPenumbralGradient(velocity) * (acc - vel->min_acceleration);
+
+ return vel->min_acceleration + res;
+}
+
+
+static float
+LinearProfile(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float threshold,
+ float acc)
+{
+ return acc * velocity;
+}
+
+static float
+NoProfile(
+ DeviceIntPtr dev,
+ DeviceVelocityPtr vel,
+ float velocity,
+ float threshold,
+ float acc)
+{
+ return 1.0f;
+}
+
+static PointerAccelerationProfileFunc
+GetAccelerationProfile(
+ DeviceVelocityPtr vel,
+ int profile_num)
+{
+ switch(profile_num){
+ case AccelProfileClassic:
+ return ClassicProfile;
+ case AccelProfileDeviceSpecific:
+ return vel->deviceSpecificProfile;
+ case AccelProfilePolynomial:
+ return PolynomialAccelerationProfile;
+ case AccelProfileSmoothLinear:
+ return SmoothLinearProfile;
+ case AccelProfileSimple:
+ return SimpleSmoothProfile;
+ case AccelProfilePower:
+ return PowerProfile;
+ case AccelProfileLinear:
+ return LinearProfile;
+ case AccelProfileSmoothLimited:
+ return SmoothLimitedProfile;
+ case AccelProfileNone:
+ return NoProfile;
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Set the profile by number.
+ * Intended to make profiles exchangeable at runtime.
+ * If you created a profile, give it a number here and in the header to
+ * make it selectable. In case some profile-specific init is needed, here
+ * would be a good place, since FreeVelocityData() also calls this with
+ * PROFILE_UNINITIALIZE.
+ *
+ * returns FALSE if profile number is unavailable, TRUE otherwise.
+ */
+int
+SetAccelerationProfile(
+ DeviceVelocityPtr vel,
+ int profile_num)
+{
+ PointerAccelerationProfileFunc profile;
+ profile = GetAccelerationProfile(vel, profile_num);
+
+ if(profile == NULL && profile_num != PROFILE_UNINITIALIZE)
+ return FALSE;
+
+ /* Here one could free old profile-private data */
+ free(vel->profile_private);
+ vel->profile_private = NULL;
+ /* Here one could init profile-private data */
+ vel->Profile = profile;
+ vel->statistics.profile_number = profile_num;
+ return TRUE;
+}
+
+/**********************************************
+ * driver interaction
+ **********************************************/
+
+
+/**
+ * device-specific profile
+ *
+ * The device-specific profile is intended as a hook for a driver
+ * which may want to provide an own acceleration profile.
+ * It should not rely on profile-private data, instead
+ * it should do init/uninit in the driver (ie. with DEVICE_INIT and friends).
+ * Users may override or choose it.
+ */
+void
+SetDeviceSpecificAccelerationProfile(
+ DeviceVelocityPtr vel,
+ PointerAccelerationProfileFunc profile)
+{
+ if(vel)
+ vel->deviceSpecificProfile = profile;
+}
+
+/**
+ * Use this function to obtain a DeviceVelocityPtr for a device. Will return NULL if
+ * the predictable acceleration scheme is not in effect.
+ */
+DeviceVelocityPtr
+GetDevicePredictableAccelData(
+ DeviceIntPtr dev)
+{
+ /*sanity check*/
+ if(!dev){
+ ErrorF("[dix] accel: DeviceIntPtr was NULL");
+ return NULL;
+ }
+ if( dev->valuator &&
+ dev->valuator->accelScheme.AccelSchemeProc ==
+ acceleratePointerPredictable &&
+ dev->valuator->accelScheme.accelData != NULL){
+
+ return ((PredictableAccelSchemePtr)
+ dev->valuator->accelScheme.accelData)->vel;
+ }
+ return NULL;
+}
+
+/********************************
+ * acceleration schemes
+ *******************************/
+
+/**
+ * Modifies valuators in-place.
+ * This version employs a velocity approximation algorithm to
+ * enable fine-grained predictable acceleration profiles.
+ */
+void
+acceleratePointerPredictable(
+ DeviceIntPtr dev,
+ ValuatorMask* val,
+ CARD32 evtime)
+{
+ int dx = 0, dy = 0, tmpi;
+ DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev);
+ Bool soften = TRUE;
+
+ if (!velocitydata)
+ return;
+
+ if (velocitydata->statistics.profile_number == AccelProfileNone &&
+ velocitydata->const_acceleration == 1.0f) {
+ return; /*we're inactive anyway, so skip the whole thing.*/
+ }
+
+ if (valuator_mask_isset(val, 0)) {
+ dx = valuator_mask_get(val, 0);
+ }
+
+ if (valuator_mask_isset(val, 1)) {
+ dy = valuator_mask_get(val, 1);
+ }
+
+ if (dx || dy){
+ /* reset non-visible state? */
+ if (ProcessVelocityData2D(velocitydata, dx , dy, evtime)) {
+ soften = FALSE;
+ }
+
+ if (dev->ptrfeed && dev->ptrfeed->ctrl.num) {
+ float mult;
+
+ /* invoke acceleration profile to determine acceleration */
+ mult = ComputeAcceleration (dev, velocitydata,
+ dev->ptrfeed->ctrl.threshold,
+ (float)dev->ptrfeed->ctrl.num /
+ (float)dev->ptrfeed->ctrl.den);
+
+ if(mult != 1.0f || velocitydata->const_acceleration != 1.0f) {
+ float fdx = dx,
+ fdy = dy;
+
+ if (mult > 1.0f && soften)
+ ApplySoftening(velocitydata, &fdx, &fdy);
+ ApplyConstantDeceleration(velocitydata, &fdx, &fdy);
+
+ /* Calculate the new delta (with accel) and drop it back
+ * into the valuator masks */
+ if (dx) {
+ float tmp;
+ tmp = mult * fdx + dev->last.remainder[0];
+ /* Since it may not be apparent: lrintf() does not offer
+ * strong statements about rounding; however because we
+ * process each axis conditionally, there's no danger
+ * of a toggling remainder. Its lack of guarantees likely
+ * makes it faster on the average target. */
+ tmpi = lrintf(tmp);
+ valuator_mask_set(val, 0, tmpi);
+ dev->last.remainder[0] = tmp - (float)tmpi;
+ }
+ if (dy) {
+ float tmp;
+ tmp = mult * fdy + dev->last.remainder[1];
+ tmpi = lrintf(tmp);
+ valuator_mask_set(val, 1, tmpi);
+ dev->last.remainder[1] = tmp - (float)tmpi;
+ }
+ DebugAccelF("pos (%i | %i) remainders x: %.3f y: %.3f delta x:%.3f y:%.3f\n",
+ *px, *py, dev->last.remainder[0], dev->last.remainder[1], fdx, fdy);
+ }
+ }
+ }
+ /* remember last motion delta (for softening/slow movement treatment) */
+ velocitydata->last_dx = dx;
+ velocitydata->last_dy = dy;
+}
+
+
+
+/**
+ * Originally a part of xf86PostMotionEvent; modifies valuators
+ * in-place. Retained mostly for embedded scenarios.
+ */
+void
+acceleratePointerLightweight(
+ DeviceIntPtr dev,
+ ValuatorMask* val,
+ CARD32 ignored)
+{
+ float mult = 0.0, tmpf;
+ int dx = 0, dy = 0, tmpi;
+
+ if (valuator_mask_isset(val, 0)) {
+ dx = valuator_mask_get(val, 0);
+ }
+
+ if (valuator_mask_isset(val, 1)) {
+ dy = valuator_mask_get(val, 1);
+ }
+
+ if (!dx && !dy)
+ return;
+
+ if (dev->ptrfeed && dev->ptrfeed->ctrl.num) {
+ /* modeled from xf86Events.c */
+ if (dev->ptrfeed->ctrl.threshold) {
+ if ((abs(dx) + abs(dy)) >= dev->ptrfeed->ctrl.threshold) {
+ tmpf = ((float)dx *
+ (float)(dev->ptrfeed->ctrl.num)) /
+ (float)(dev->ptrfeed->ctrl.den) +
+ dev->last.remainder[0];
+ if (dx) {
+ tmpi = (int) tmpf;
+ valuator_mask_set(val, 0, tmpi);
+ dev->last.remainder[0] = tmpf - (float)tmpi;
+ }
+
+ tmpf = ((float)dy *
+ (float)(dev->ptrfeed->ctrl.num)) /
+ (float)(dev->ptrfeed->ctrl.den) +
+ dev->last.remainder[1];
+ if (dy) {
+ tmpi = (int) tmpf;
+ valuator_mask_set(val, 1, tmpi);
+ dev->last.remainder[1] = tmpf - (float)tmpi;
+ }
+ }
+ }
+ else {
+ mult = pow((float)dx * (float)dx + (float)dy * (float)dy,
+ ((float)(dev->ptrfeed->ctrl.num) /
+ (float)(dev->ptrfeed->ctrl.den) - 1.0) /
+ 2.0) / 2.0;
+ if (dx) {
+ tmpf = mult * (float)dx +
+ dev->last.remainder[0];
+ tmpi = (int) tmpf;
+ valuator_mask_set(val, 0, tmpi);
+ dev->last.remainder[0] = tmpf - (float)tmpi;
+ }
+ if (dy) {
+ tmpf = mult * (float)dy +
+ dev->last.remainder[1];
+ tmpi = (int)tmpf;
+ valuator_mask_set(val, 1, tmpi);
+ dev->last.remainder[1] = tmpf - (float)tmpi;
+ }
+ }
+ }
+}
diff --git a/xorg-server/dix/resource.c b/xorg-server/dix/resource.c
index 339ab403b..eb9f0492a 100644
--- a/xorg-server/dix/resource.c
+++ b/xorg-server/dix/resource.c
@@ -1,963 +1,963 @@
-/************************************************************
-
-Copyright 1987, 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.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-********************************************************/
-/* The panoramix components contained the following notice */
-/*****************************************************************
-
-Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-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.
-
-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
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-******************************************************************/
-/* XSERVER_DTRACE additions:
- * Copyright (c) 2005-2006, Oracle and/or its affiliates. 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-/* Routines to manage various kinds of resources:
- *
- * CreateNewResourceType, CreateNewResourceClass, InitClientResources,
- * FakeClientID, AddResource, FreeResource, FreeClientResources,
- * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange
- */
-
-/*
- * A resource ID is a 32 bit quantity, the upper 2 bits of which are
- * off-limits for client-visible resources. The next 8 bits are
- * used as client ID, and the low 22 bits come from the client.
- * A resource ID is "hashed" by extracting and xoring subfields
- * (varying with the size of the hash table).
- *
- * It is sometimes necessary for the server to create an ID that looks
- * like it belongs to a client. This ID, however, must not be one
- * the client actually can create, or we have the potential for conflict.
- * The 31st bit of the ID is reserved for the server's use for this
- * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to
- * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a
- * resource "owned" by the client.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include "misc.h"
-#include "os.h"
-#include "resource.h"
-#include "dixstruct.h"
-#include "opaque.h"
-#include "windowstr.h"
-#include "dixfont.h"
-#include "colormap.h"
-#include "inputstr.h"
-#include "dixevents.h"
-#include "dixgrabs.h"
-#include "cursor.h"
-#ifdef PANORAMIX
-#include "panoramiX.h"
-#include "panoramiXsrv.h"
-#endif
-#include "xace.h"
-#include <assert.h>
-#include "registry.h"
-
-#ifdef XSERVER_DTRACE
-#include <sys/types.h>
-typedef const char *string;
-#include "Xserver-dtrace.h"
-
-#define TypeNameString(t) LookupResourceName(t)
-#endif
-
-static void RebuildTable(
- int /*client*/
-);
-
-#define SERVER_MINID 32
-
-#define INITBUCKETS 64
-#define INITHASHSIZE 6
-#define MAXHASHSIZE 11
-
-typedef struct _Resource {
- struct _Resource *next;
- XID id;
- RESTYPE type;
- pointer value;
-} ResourceRec, *ResourcePtr;
-
-typedef struct _ClientResource {
- ResourcePtr *resources;
- int elements;
- int buckets;
- int hashsize; /* log(2)(buckets) */
- XID fakeID;
- XID endFakeID;
-} ClientResourceRec;
-
-RESTYPE lastResourceType;
-static RESTYPE lastResourceClass;
-RESTYPE TypeMask;
-
-struct ResourceType {
- DeleteType deleteFunc;
- int errorValue;
-};
-
-static struct ResourceType *resourceTypes;
-static const struct ResourceType predefTypes[] = {
- [RT_NONE & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = (DeleteType)NoopDDA,
- .errorValue = BadValue,
- },
- [RT_WINDOW & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = DeleteWindow,
- .errorValue = BadWindow,
- },
- [RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = dixDestroyPixmap,
- .errorValue = BadPixmap,
- },
- [RT_GC & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = FreeGC,
- .errorValue = BadGC,
- },
- [RT_FONT & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = CloseFont,
- .errorValue = BadFont,
- },
- [RT_CURSOR & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = FreeCursor,
- .errorValue = BadCursor,
- },
- [RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = FreeColormap,
- .errorValue = BadColor,
- },
- [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = FreeClientPixels,
- .errorValue = BadColor,
- },
- [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = OtherClientGone,
- .errorValue = BadValue,
- },
- [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = DeletePassiveGrab,
- .errorValue = BadValue,
- },
-};
-
-CallbackListPtr ResourceStateCallback;
-
-static _X_INLINE void
-CallResourceStateCallback(ResourceState state, ResourceRec *res)
-{
- if (ResourceStateCallback) {
- ResourceStateInfoRec rsi = { state, res->id, res->type, res->value };
- CallCallbacks(&ResourceStateCallback, &rsi);
- }
-}
-
-RESTYPE
-CreateNewResourceType(DeleteType deleteFunc, char *name)
-{
- RESTYPE next = lastResourceType + 1;
- struct ResourceType *types;
-
- if (next & lastResourceClass)
- return 0;
- types = realloc(resourceTypes, (next + 1) * sizeof(*resourceTypes));
- if (!types)
- return 0;
-
- lastResourceType = next;
- resourceTypes = types;
- resourceTypes[next].deleteFunc = deleteFunc;
- resourceTypes[next].errorValue = BadValue;
-
- /* Called even if name is NULL, to remove any previous entry */
- RegisterResourceName(next, name);
-
- return next;
-}
-
-void
-SetResourceTypeErrorValue(RESTYPE type, int errorValue)
-{
- resourceTypes[type & TypeMask].errorValue = errorValue;
-}
-
-RESTYPE
-CreateNewResourceClass(void)
-{
- RESTYPE next = lastResourceClass >> 1;
-
- if (next & lastResourceType)
- return 0;
- lastResourceClass = next;
- TypeMask = next - 1;
- return next;
-}
-
-static ClientResourceRec clientTable[MAXCLIENTS];
-
-/*****************
- * InitClientResources
- * When a new client is created, call this to allocate space
- * in resource table
- *****************/
-
-Bool
-InitClientResources(ClientPtr client)
-{
- int i, j;
-
- if (client == serverClient)
- {
- lastResourceType = RT_LASTPREDEF;
- lastResourceClass = RC_LASTPREDEF;
- TypeMask = RC_LASTPREDEF - 1;
- free(resourceTypes);
- resourceTypes = malloc(sizeof(predefTypes));
- if (!resourceTypes)
- return FALSE;
- memcpy(resourceTypes, predefTypes, sizeof(predefTypes));
- }
- clientTable[i = client->index].resources =
- malloc(INITBUCKETS*sizeof(ResourcePtr));
- if (!clientTable[i].resources)
- return FALSE;
- clientTable[i].buckets = INITBUCKETS;
- clientTable[i].elements = 0;
- clientTable[i].hashsize = INITHASHSIZE;
- /* Many IDs allocated from the server client are visible to clients,
- * so we don't use the SERVER_BIT for them, but we have to start
- * past the magic value constants used in the protocol. For normal
- * clients, we can start from zero, with SERVER_BIT set.
- */
- clientTable[i].fakeID = client->clientAsMask |
- (client->index ? SERVER_BIT : SERVER_MINID);
- clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1;
- for (j=0; j<INITBUCKETS; j++)
- {
- clientTable[i].resources[j] = NULL;
- }
- return TRUE;
-}
-
-
-static int
-Hash(int client, XID id)
-{
- id &= RESOURCE_ID_MASK;
- switch (clientTable[client].hashsize)
- {
- case 6:
- return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));
- case 7:
- return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));
- case 8:
- return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));
- case 9:
- return ((int)(0x1FF & (id ^ (id>>9))));
- case 10:
- return ((int)(0x3FF & (id ^ (id>>10))));
- case 11:
- return ((int)(0x7FF & (id ^ (id>>11))));
- }
- return -1;
-}
-
-static XID
-AvailableID(
- int client,
- XID id,
- XID maxid,
- XID goodid)
-{
- ResourcePtr res;
-
- if ((goodid >= id) && (goodid <= maxid))
- return goodid;
- for (; id <= maxid; id++)
- {
- res = clientTable[client].resources[Hash(client, id)];
- while (res && (res->id != id))
- res = res->next;
- if (!res)
- return id;
- }
- return 0;
-}
-
-void
-GetXIDRange(int client, Bool server, XID *minp, XID *maxp)
-{
- XID id, maxid;
- ResourcePtr *resp;
- ResourcePtr res;
- int i;
- XID goodid;
-
- id = (Mask)client << CLIENTOFFSET;
- if (server)
- id |= client ? SERVER_BIT : SERVER_MINID;
- maxid = id | RESOURCE_ID_MASK;
- goodid = 0;
- for (resp = clientTable[client].resources, i = clientTable[client].buckets;
- --i >= 0;)
- {
- for (res = *resp++; res; res = res->next)
- {
- if ((res->id < id) || (res->id > maxid))
- continue;
- if (((res->id - id) >= (maxid - res->id)) ?
- (goodid = AvailableID(client, id, res->id - 1, goodid)) :
- !(goodid = AvailableID(client, res->id + 1, maxid, goodid)))
- maxid = res->id - 1;
- else
- id = res->id + 1;
- }
- }
- if (id > maxid)
- id = maxid = 0;
- *minp = id;
- *maxp = maxid;
-}
-
-/**
- * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function.
- * This function tries to find count unused XIDs for the given client. It
- * puts the IDs in the array pids and returns the number found, which should
- * almost always be the number requested.
- *
- * The circumstances that lead to a call to this function are very rare.
- * Xlib must run out of IDs while trying to generate a request that wants
- * multiple ID's, like the Multi-buffering CreateImageBuffers request.
- *
- * No rocket science in the implementation; just iterate over all
- * possible IDs for the given client and pick the first count IDs
- * that aren't in use. A more efficient algorithm could probably be
- * invented, but this will be used so rarely that this should suffice.
- */
-
-unsigned int
-GetXIDList(ClientPtr pClient, unsigned count, XID *pids)
-{
- unsigned int found = 0;
- XID rc, id = pClient->clientAsMask;
- XID maxid;
- pointer val;
-
- maxid = id | RESOURCE_ID_MASK;
- while ( (found < count) && (id <= maxid) )
- {
- rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
- DixGetAttrAccess);
- if (rc == BadValue)
- {
- pids[found++] = id;
- }
- id++;
- }
- return found;
-}
-
-/*
- * Return the next usable fake client ID.
- *
- * Normally this is just the next one in line, but if we've used the last
- * in the range, we need to find a new range of safe IDs to avoid
- * over-running another client.
- */
-
-XID
-FakeClientID(int client)
-{
- XID id, maxid;
-
- id = clientTable[client].fakeID++;
- if (id != clientTable[client].endFakeID)
- return id;
- GetXIDRange(client, TRUE, &id, &maxid);
- if (!id) {
- if (!client)
- FatalError("FakeClientID: server internal ids exhausted\n");
- MarkClientException(clients[client]);
- id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3);
- maxid = id | RESOURCE_ID_MASK;
- }
- clientTable[client].fakeID = id + 1;
- clientTable[client].endFakeID = maxid + 1;
- return id;
-}
-
-Bool
-AddResource(XID id, RESTYPE type, pointer value)
-{
- int client;
- ClientResourceRec *rrec;
- ResourcePtr res, *head;
-
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_ALLOC(id, type, value, TypeNameString(type));
-#endif
- client = CLIENT_ID(id);
- rrec = &clientTable[client];
- if (!rrec->buckets)
- {
- ErrorF("[dix] AddResource(%lx, %lx, %lx), client=%d \n",
- (unsigned long)id, type, (unsigned long)value, client);
- FatalError("client not in use\n");
- }
- if ((rrec->elements >= 4*rrec->buckets) &&
- (rrec->hashsize < MAXHASHSIZE))
- RebuildTable(client);
- head = &rrec->resources[Hash(client, id)];
- res = malloc(sizeof(ResourceRec));
- if (!res)
- {
- (*resourceTypes[type & TypeMask].deleteFunc)(value, id);
- return FALSE;
- }
- res->next = *head;
- res->id = id;
- res->type = type;
- res->value = value;
- *head = res;
- rrec->elements++;
- CallResourceStateCallback(ResourceStateAdding, res);
- return TRUE;
-}
-
-static void
-RebuildTable(int client)
-{
- int j;
- ResourcePtr res, next;
- ResourcePtr **tails, *resources;
- ResourcePtr **tptr, *rptr;
-
- /*
- * For now, preserve insertion order, since some ddx layers depend
- * on resources being free in the opposite order they are added.
- */
-
- j = 2 * clientTable[client].buckets;
- tails = malloc(j * sizeof(ResourcePtr *));
- if (!tails)
- return;
- resources = malloc(j * sizeof(ResourcePtr));
- if (!resources)
- {
- free(tails);
- return;
- }
- for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++)
- {
- *rptr = NULL;
- *tptr = rptr;
- }
- clientTable[client].hashsize++;
- for (j = clientTable[client].buckets,
- rptr = clientTable[client].resources;
- --j >= 0;
- rptr++)
- {
- for (res = *rptr; res; res = next)
- {
- next = res->next;
- res->next = NULL;
- tptr = &tails[Hash(client, res->id)];
- **tptr = res;
- *tptr = &res->next;
- }
- }
- free(tails);
- clientTable[client].buckets *= 2;
- free(clientTable[client].resources);
- clientTable[client].resources = resources;
-}
-
-static void
-doFreeResource(ResourcePtr res, Bool skip)
-{
- CallResourceStateCallback(ResourceStateFreeing, res);
-
- if (!skip)
- resourceTypes[res->type & TypeMask].deleteFunc(res->value, res->id);
-
- free(res);
-}
-
-void
-FreeResource(XID id, RESTYPE skipDeleteFuncType)
-{
- int cid;
- ResourcePtr res;
- ResourcePtr *prev, *head;
- int *eltptr;
- int elements;
-
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
- {
- head = &clientTable[cid].resources[Hash(cid, id)];
- eltptr = &clientTable[cid].elements;
-
- prev = head;
- while ( (res = *prev) )
- {
- if (res->id == id)
- {
- RESTYPE rtype = res->type;
-
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_FREE(res->id, res->type,
- res->value, TypeNameString(res->type));
-#endif
- *prev = res->next;
- elements = --*eltptr;
-
- doFreeResource(res, rtype == skipDeleteFuncType);
-
- if (*eltptr != elements)
- prev = head; /* prev may no longer be valid */
- }
- else
- prev = &res->next;
- }
- }
-}
-
-void
-FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
-{
- int cid;
- ResourcePtr res;
- ResourcePtr *prev, *head;
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
- {
- head = &clientTable[cid].resources[Hash(cid, id)];
-
- prev = head;
- while ( (res = *prev) )
- {
- if (res->id == id && res->type == type)
- {
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_FREE(res->id, res->type,
- res->value, TypeNameString(res->type));
-#endif
- *prev = res->next;
- clientTable[cid].elements--;
-
- doFreeResource(res, skipFree);
-
- break;
- }
- else
- prev = &res->next;
- }
- }
-}
-
-/*
- * Change the value associated with a resource id. Caller
- * is responsible for "doing the right thing" with the old
- * data
- */
-
-Bool
-ChangeResourceValue (XID id, RESTYPE rtype, pointer value)
-{
- int cid;
- ResourcePtr res;
-
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
- {
- res = clientTable[cid].resources[Hash(cid, id)];
-
- for (; res; res = res->next)
- if ((res->id == id) && (res->type == rtype))
- {
- res->value = value;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/* Note: if func adds or deletes resources, then func can get called
- * more than once for some resources. If func adds new resources,
- * func might or might not get called for them. func cannot both
- * add and delete an equal number of resources!
- */
-
-void
-FindClientResourcesByType(
- ClientPtr client,
- RESTYPE type,
- FindResType func,
- pointer cdata
-){
- ResourcePtr *resources;
- ResourcePtr this, next;
- int i, elements;
- int *eltptr;
-
- if (!client)
- client = serverClient;
-
- resources = clientTable[client->index].resources;
- eltptr = &clientTable[client->index].elements;
- for (i = 0; i < clientTable[client->index].buckets; i++)
- {
- for (this = resources[i]; this; this = next)
- {
- next = this->next;
- if (!type || this->type == type) {
- elements = *eltptr;
- (*func)(this->value, this->id, cdata);
- if (*eltptr != elements)
- next = resources[i]; /* start over */
- }
- }
- }
-}
-
-void
-FindAllClientResources(
- ClientPtr client,
- FindAllRes func,
- pointer cdata
-){
- ResourcePtr *resources;
- ResourcePtr this, next;
- int i, elements;
- int *eltptr;
-
- if (!client)
- client = serverClient;
-
- resources = clientTable[client->index].resources;
- eltptr = &clientTable[client->index].elements;
- for (i = 0; i < clientTable[client->index].buckets; i++)
- {
- for (this = resources[i]; this; this = next)
- {
- next = this->next;
- elements = *eltptr;
- (*func)(this->value, this->id, this->type, cdata);
- if (*eltptr != elements)
- next = resources[i]; /* start over */
- }
- }
-}
-
-
-pointer
-LookupClientResourceComplex(
- ClientPtr client,
- RESTYPE type,
- FindComplexResType func,
- pointer cdata
-){
- ResourcePtr *resources;
- ResourcePtr this, next;
- pointer value;
- int i;
-
- if (!client)
- client = serverClient;
-
- resources = clientTable[client->index].resources;
- for (i = 0; i < clientTable[client->index].buckets; i++) {
- for (this = resources[i]; this; this = next) {
- next = this->next;
- if (!type || this->type == type) {
- /* workaround func freeing the type as DRI1 does */
- value = this->value;
- if((*func)(value, this->id, cdata))
- return value;
- }
- }
- }
- return NULL;
-}
-
-
-void
-FreeClientNeverRetainResources(ClientPtr client)
-{
- ResourcePtr *resources;
- ResourcePtr this;
- ResourcePtr *prev;
- int j, elements;
- int *eltptr;
-
- if (!client)
- return;
-
- resources = clientTable[client->index].resources;
- eltptr = &clientTable[client->index].elements;
- for (j=0; j < clientTable[client->index].buckets; j++)
- {
- prev = &resources[j];
- while ( (this = *prev) )
- {
- RESTYPE rtype = this->type;
- if (rtype & RC_NEVERRETAIN)
- {
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_FREE(this->id, this->type,
- this->value, TypeNameString(this->type));
-#endif
- *prev = this->next;
- clientTable[client->index].elements--;
- elements = *eltptr;
-
- doFreeResource(this, FALSE);
-
- if (*eltptr != elements)
- prev = &resources[j]; /* prev may no longer be valid */
- }
- else
- prev = &this->next;
- }
- }
-}
-
-void
-FreeClientResources(ClientPtr client)
-{
- ResourcePtr *resources;
- ResourcePtr this;
- int j;
-
- /* This routine shouldn't be called with a null client, but just in
- case ... */
-
- if (!client)
- return;
-
- HandleSaveSet(client);
-
- resources = clientTable[client->index].resources;
- for (j=0; j < clientTable[client->index].buckets; j++)
- {
- /* It may seem silly to update the head of this resource list as
- we delete the members, since the entire list will be deleted any way,
- but there are some resource deletion functions "FreeClientPixels" for
- one which do a LookupID on another resource id (a Colormap id in this
- case), so the resource list must be kept valid up to the point that
- it is deleted, so every time we delete a resource, we must update the
- head, just like in FreeResource. I hope that this doesn't slow down
- mass deletion appreciably. PRH */
-
- ResourcePtr *head;
-
- head = &resources[j];
-
- for (this = *head; this; this = *head)
- {
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_FREE(this->id, this->type,
- this->value, TypeNameString(this->type));
-#endif
- *head = this->next;
- clientTable[client->index].elements--;
-
- doFreeResource(this, FALSE);
- }
- }
- free(clientTable[client->index].resources);
- clientTable[client->index].resources = NULL;
- clientTable[client->index].buckets = 0;
-}
-
-void
-FreeAllResources(void)
-{
- int i;
-
- for (i = currentMaxClients; --i >= 0; )
- {
- if (clientTable[i].buckets)
- FreeClientResources(clients[i]);
- }
-}
-
-Bool
-LegalNewID(XID id, ClientPtr client)
-{
- pointer val;
- int rc;
-
-#ifdef PANORAMIX
- XID minid, maxid;
-
- if (!noPanoramiXExtension) {
- minid = client->clientAsMask | (client->index ?
- SERVER_BIT : SERVER_MINID);
- maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1;
- if ((id >= minid) && (id <= maxid))
- return TRUE;
- }
-#endif /* PANORAMIX */
- if (client->clientAsMask == (id & ~RESOURCE_ID_MASK))
- {
- rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
- DixGetAttrAccess);
- return rc == BadValue;
- }
- return FALSE;
-}
-
-int
-dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype,
- ClientPtr client, Mask mode)
-{
- int cid = CLIENT_ID(id);
- ResourcePtr res = NULL;
-
- *result = NULL;
- if ((rtype & TypeMask) > lastResourceType)
- return BadImplementation;
-
- if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
-
- for (; res; res = res->next)
- if (res->id == id && res->type == rtype)
- break;
- }
- if (!res)
- return resourceTypes[rtype & TypeMask].errorValue;
-
- if (client) {
- client->errorValue = id;
- cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
- res->value, RT_NONE, NULL, mode);
- if (cid == BadValue)
- return resourceTypes[rtype & TypeMask].errorValue;
- if (cid != Success)
- return cid;
- }
-
- *result = res->value;
- return Success;
-}
-
-int
-dixLookupResourceByClass(pointer *result, XID id, RESTYPE rclass,
- ClientPtr client, Mask mode)
-{
- int cid = CLIENT_ID(id);
- ResourcePtr res = NULL;
-
- *result = NULL;
-
- if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
-
- for (; res; res = res->next)
- if (res->id == id && (res->type & rclass))
- break;
- }
- if (!res)
- return BadValue;
-
- if (client) {
- client->errorValue = id;
- cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
- res->value, RT_NONE, NULL, mode);
- if (cid != Success)
- return cid;
- }
-
- *result = res->value;
- return Success;
-}
+/************************************************************
+
+Copyright 1987, 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.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+/* The panoramix components contained the following notice */
+/*****************************************************************
+
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+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.
+
+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
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+/* XSERVER_DTRACE additions:
+ * Copyright (c) 2005-2006, Oracle and/or its affiliates. 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+/* Routines to manage various kinds of resources:
+ *
+ * CreateNewResourceType, CreateNewResourceClass, InitClientResources,
+ * FakeClientID, AddResource, FreeResource, FreeClientResources,
+ * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange
+ */
+
+/*
+ * A resource ID is a 32 bit quantity, the upper 2 bits of which are
+ * off-limits for client-visible resources. The next 8 bits are
+ * used as client ID, and the low 22 bits come from the client.
+ * A resource ID is "hashed" by extracting and xoring subfields
+ * (varying with the size of the hash table).
+ *
+ * It is sometimes necessary for the server to create an ID that looks
+ * like it belongs to a client. This ID, however, must not be one
+ * the client actually can create, or we have the potential for conflict.
+ * The 31st bit of the ID is reserved for the server's use for this
+ * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to
+ * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a
+ * resource "owned" by the client.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "misc.h"
+#include "os.h"
+#include "resource.h"
+#include "dixstruct.h"
+#include "opaque.h"
+#include "windowstr.h"
+#include "dixfont.h"
+#include "colormap.h"
+#include "inputstr.h"
+#include "dixevents.h"
+#include "dixgrabs.h"
+#include "cursor.h"
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+#include "xace.h"
+#include <assert.h>
+#include "registry.h"
+
+#ifdef XSERVER_DTRACE
+#include <sys/types.h>
+typedef const char *string;
+#include "Xserver-dtrace.h"
+
+#define TypeNameString(t) LookupResourceName(t)
+#endif
+
+static void RebuildTable(
+ int /*client*/
+);
+
+#define SERVER_MINID 32
+
+#define INITBUCKETS 64
+#define INITHASHSIZE 6
+#define MAXHASHSIZE 11
+
+typedef struct _Resource {
+ struct _Resource *next;
+ XID id;
+ RESTYPE type;
+ pointer value;
+} ResourceRec, *ResourcePtr;
+
+typedef struct _ClientResource {
+ ResourcePtr *resources;
+ int elements;
+ int buckets;
+ int hashsize; /* log(2)(buckets) */
+ XID fakeID;
+ XID endFakeID;
+} ClientResourceRec;
+
+RESTYPE lastResourceType;
+static RESTYPE lastResourceClass;
+RESTYPE TypeMask;
+
+struct ResourceType {
+ DeleteType deleteFunc;
+ int errorValue;
+};
+
+static struct ResourceType *resourceTypes;
+static const struct ResourceType predefTypes[] = {
+ [RT_NONE & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = (DeleteType)NoopDDA,
+ .errorValue = BadValue,
+ },
+ [RT_WINDOW & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = DeleteWindow,
+ .errorValue = BadWindow,
+ },
+ [RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = dixDestroyPixmap,
+ .errorValue = BadPixmap,
+ },
+ [RT_GC & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = FreeGC,
+ .errorValue = BadGC,
+ },
+ [RT_FONT & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = CloseFont,
+ .errorValue = BadFont,
+ },
+ [RT_CURSOR & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = FreeCursor,
+ .errorValue = BadCursor,
+ },
+ [RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = FreeColormap,
+ .errorValue = BadColor,
+ },
+ [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = FreeClientPixels,
+ .errorValue = BadColor,
+ },
+ [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = OtherClientGone,
+ .errorValue = BadValue,
+ },
+ [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = DeletePassiveGrab,
+ .errorValue = BadValue,
+ },
+};
+
+CallbackListPtr ResourceStateCallback;
+
+static _X_INLINE void
+CallResourceStateCallback(ResourceState state, ResourceRec *res)
+{
+ if (ResourceStateCallback) {
+ ResourceStateInfoRec rsi = { state, res->id, res->type, res->value };
+ CallCallbacks(&ResourceStateCallback, &rsi);
+ }
+}
+
+RESTYPE
+CreateNewResourceType(DeleteType deleteFunc, char *name)
+{
+ RESTYPE next = lastResourceType + 1;
+ struct ResourceType *types;
+
+ if (next & lastResourceClass)
+ return 0;
+ types = realloc(resourceTypes, (next + 1) * sizeof(*resourceTypes));
+ if (!types)
+ return 0;
+
+ lastResourceType = next;
+ resourceTypes = types;
+ resourceTypes[next].deleteFunc = deleteFunc;
+ resourceTypes[next].errorValue = BadValue;
+
+ /* Called even if name is NULL, to remove any previous entry */
+ RegisterResourceName(next, name);
+
+ return next;
+}
+
+void
+SetResourceTypeErrorValue(RESTYPE type, int errorValue)
+{
+ resourceTypes[type & TypeMask].errorValue = errorValue;
+}
+
+RESTYPE
+CreateNewResourceClass(void)
+{
+ RESTYPE next = lastResourceClass >> 1;
+
+ if (next & lastResourceType)
+ return 0;
+ lastResourceClass = next;
+ TypeMask = next - 1;
+ return next;
+}
+
+static ClientResourceRec clientTable[MAXCLIENTS];
+
+/*****************
+ * InitClientResources
+ * When a new client is created, call this to allocate space
+ * in resource table
+ *****************/
+
+Bool
+InitClientResources(ClientPtr client)
+{
+ int i, j;
+
+ if (client == serverClient)
+ {
+ lastResourceType = RT_LASTPREDEF;
+ lastResourceClass = RC_LASTPREDEF;
+ TypeMask = RC_LASTPREDEF - 1;
+ free(resourceTypes);
+ resourceTypes = malloc(sizeof(predefTypes));
+ if (!resourceTypes)
+ return FALSE;
+ memcpy(resourceTypes, predefTypes, sizeof(predefTypes));
+ }
+ clientTable[i = client->index].resources =
+ malloc(INITBUCKETS*sizeof(ResourcePtr));
+ if (!clientTable[i].resources)
+ return FALSE;
+ clientTable[i].buckets = INITBUCKETS;
+ clientTable[i].elements = 0;
+ clientTable[i].hashsize = INITHASHSIZE;
+ /* Many IDs allocated from the server client are visible to clients,
+ * so we don't use the SERVER_BIT for them, but we have to start
+ * past the magic value constants used in the protocol. For normal
+ * clients, we can start from zero, with SERVER_BIT set.
+ */
+ clientTable[i].fakeID = client->clientAsMask |
+ (client->index ? SERVER_BIT : SERVER_MINID);
+ clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1;
+ for (j=0; j<INITBUCKETS; j++)
+ {
+ clientTable[i].resources[j] = NULL;
+ }
+ return TRUE;
+}
+
+
+static int
+Hash(int client, XID id)
+{
+ id &= RESOURCE_ID_MASK;
+ switch (clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));
+ case 7:
+ return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));
+ case 8:
+ return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));
+ case 9:
+ return ((int)(0x1FF & (id ^ (id>>9))));
+ case 10:
+ return ((int)(0x3FF & (id ^ (id>>10))));
+ case 11:
+ return ((int)(0x7FF & (id ^ (id>>11))));
+ }
+ return -1;
+}
+
+static XID
+AvailableID(
+ int client,
+ XID id,
+ XID maxid,
+ XID goodid)
+{
+ ResourcePtr res;
+
+ if ((goodid >= id) && (goodid <= maxid))
+ return goodid;
+ for (; id <= maxid; id++)
+ {
+ res = clientTable[client].resources[Hash(client, id)];
+ while (res && (res->id != id))
+ res = res->next;
+ if (!res)
+ return id;
+ }
+ return 0;
+}
+
+void
+GetXIDRange(int client, Bool server, XID *minp, XID *maxp)
+{
+ XID id, maxid;
+ ResourcePtr *resp;
+ ResourcePtr res;
+ int i;
+ XID goodid;
+
+ id = (Mask)client << CLIENTOFFSET;
+ if (server)
+ id |= client ? SERVER_BIT : SERVER_MINID;
+ maxid = id | RESOURCE_ID_MASK;
+ goodid = 0;
+ for (resp = clientTable[client].resources, i = clientTable[client].buckets;
+ --i >= 0;)
+ {
+ for (res = *resp++; res; res = res->next)
+ {
+ if ((res->id < id) || (res->id > maxid))
+ continue;
+ if (((res->id - id) >= (maxid - res->id)) ?
+ (goodid = AvailableID(client, id, res->id - 1, goodid)) :
+ !(goodid = AvailableID(client, res->id + 1, maxid, goodid)))
+ maxid = res->id - 1;
+ else
+ id = res->id + 1;
+ }
+ }
+ if (id > maxid)
+ id = maxid = 0;
+ *minp = id;
+ *maxp = maxid;
+}
+
+/**
+ * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function.
+ * This function tries to find count unused XIDs for the given client. It
+ * puts the IDs in the array pids and returns the number found, which should
+ * almost always be the number requested.
+ *
+ * The circumstances that lead to a call to this function are very rare.
+ * Xlib must run out of IDs while trying to generate a request that wants
+ * multiple ID's, like the Multi-buffering CreateImageBuffers request.
+ *
+ * No rocket science in the implementation; just iterate over all
+ * possible IDs for the given client and pick the first count IDs
+ * that aren't in use. A more efficient algorithm could probably be
+ * invented, but this will be used so rarely that this should suffice.
+ */
+
+unsigned int
+GetXIDList(ClientPtr pClient, unsigned count, XID *pids)
+{
+ unsigned int found = 0;
+ XID rc, id = pClient->clientAsMask;
+ XID maxid;
+ pointer val;
+
+ maxid = id | RESOURCE_ID_MASK;
+ while ( (found < count) && (id <= maxid) )
+ {
+ rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
+ DixGetAttrAccess);
+ if (rc == BadValue)
+ {
+ pids[found++] = id;
+ }
+ id++;
+ }
+ return found;
+}
+
+/*
+ * Return the next usable fake client ID.
+ *
+ * Normally this is just the next one in line, but if we've used the last
+ * in the range, we need to find a new range of safe IDs to avoid
+ * over-running another client.
+ */
+
+XID
+FakeClientID(int client)
+{
+ XID id, maxid;
+
+ id = clientTable[client].fakeID++;
+ if (id != clientTable[client].endFakeID)
+ return id;
+ GetXIDRange(client, TRUE, &id, &maxid);
+ if (!id) {
+ if (!client)
+ FatalError("FakeClientID: server internal ids exhausted\n");
+ MarkClientException(clients[client]);
+ id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3);
+ maxid = id | RESOURCE_ID_MASK;
+ }
+ clientTable[client].fakeID = id + 1;
+ clientTable[client].endFakeID = maxid + 1;
+ return id;
+}
+
+Bool
+AddResource(XID id, RESTYPE type, pointer value)
+{
+ int client;
+ ClientResourceRec *rrec;
+ ResourcePtr res, *head;
+
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_ALLOC(id, type, value, TypeNameString(type));
+#endif
+ client = CLIENT_ID(id);
+ rrec = &clientTable[client];
+ if (!rrec->buckets)
+ {
+ ErrorF("[dix] AddResource(%lx, %x, %lx), client=%d \n",
+ (unsigned long)id, type, (unsigned long)value, client);
+ FatalError("client not in use\n");
+ }
+ if ((rrec->elements >= 4*rrec->buckets) &&
+ (rrec->hashsize < MAXHASHSIZE))
+ RebuildTable(client);
+ head = &rrec->resources[Hash(client, id)];
+ res = malloc(sizeof(ResourceRec));
+ if (!res)
+ {
+ (*resourceTypes[type & TypeMask].deleteFunc)(value, id);
+ return FALSE;
+ }
+ res->next = *head;
+ res->id = id;
+ res->type = type;
+ res->value = value;
+ *head = res;
+ rrec->elements++;
+ CallResourceStateCallback(ResourceStateAdding, res);
+ return TRUE;
+}
+
+static void
+RebuildTable(int client)
+{
+ int j;
+ ResourcePtr res, next;
+ ResourcePtr **tails, *resources;
+ ResourcePtr **tptr, *rptr;
+
+ /*
+ * For now, preserve insertion order, since some ddx layers depend
+ * on resources being free in the opposite order they are added.
+ */
+
+ j = 2 * clientTable[client].buckets;
+ tails = malloc(j * sizeof(ResourcePtr *));
+ if (!tails)
+ return;
+ resources = malloc(j * sizeof(ResourcePtr));
+ if (!resources)
+ {
+ free(tails);
+ return;
+ }
+ for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++)
+ {
+ *rptr = NULL;
+ *tptr = rptr;
+ }
+ clientTable[client].hashsize++;
+ for (j = clientTable[client].buckets,
+ rptr = clientTable[client].resources;
+ --j >= 0;
+ rptr++)
+ {
+ for (res = *rptr; res; res = next)
+ {
+ next = res->next;
+ res->next = NULL;
+ tptr = &tails[Hash(client, res->id)];
+ **tptr = res;
+ *tptr = &res->next;
+ }
+ }
+ free(tails);
+ clientTable[client].buckets *= 2;
+ free(clientTable[client].resources);
+ clientTable[client].resources = resources;
+}
+
+static void
+doFreeResource(ResourcePtr res, Bool skip)
+{
+ CallResourceStateCallback(ResourceStateFreeing, res);
+
+ if (!skip)
+ resourceTypes[res->type & TypeMask].deleteFunc(res->value, res->id);
+
+ free(res);
+}
+
+void
+FreeResource(XID id, RESTYPE skipDeleteFuncType)
+{
+ int cid;
+ ResourcePtr res;
+ ResourcePtr *prev, *head;
+ int *eltptr;
+ int elements;
+
+ if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
+ {
+ head = &clientTable[cid].resources[Hash(cid, id)];
+ eltptr = &clientTable[cid].elements;
+
+ prev = head;
+ while ( (res = *prev) )
+ {
+ if (res->id == id)
+ {
+ RESTYPE rtype = res->type;
+
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_FREE(res->id, res->type,
+ res->value, TypeNameString(res->type));
+#endif
+ *prev = res->next;
+ elements = --*eltptr;
+
+ doFreeResource(res, rtype == skipDeleteFuncType);
+
+ if (*eltptr != elements)
+ prev = head; /* prev may no longer be valid */
+ }
+ else
+ prev = &res->next;
+ }
+ }
+}
+
+void
+FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
+{
+ int cid;
+ ResourcePtr res;
+ ResourcePtr *prev, *head;
+ if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
+ {
+ head = &clientTable[cid].resources[Hash(cid, id)];
+
+ prev = head;
+ while ( (res = *prev) )
+ {
+ if (res->id == id && res->type == type)
+ {
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_FREE(res->id, res->type,
+ res->value, TypeNameString(res->type));
+#endif
+ *prev = res->next;
+ clientTable[cid].elements--;
+
+ doFreeResource(res, skipFree);
+
+ break;
+ }
+ else
+ prev = &res->next;
+ }
+ }
+}
+
+/*
+ * Change the value associated with a resource id. Caller
+ * is responsible for "doing the right thing" with the old
+ * data
+ */
+
+Bool
+ChangeResourceValue (XID id, RESTYPE rtype, pointer value)
+{
+ int cid;
+ ResourcePtr res;
+
+ if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
+ {
+ res = clientTable[cid].resources[Hash(cid, id)];
+
+ for (; res; res = res->next)
+ if ((res->id == id) && (res->type == rtype))
+ {
+ res->value = value;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* Note: if func adds or deletes resources, then func can get called
+ * more than once for some resources. If func adds new resources,
+ * func might or might not get called for them. func cannot both
+ * add and delete an equal number of resources!
+ */
+
+void
+FindClientResourcesByType(
+ ClientPtr client,
+ RESTYPE type,
+ FindResType func,
+ pointer cdata
+){
+ ResourcePtr *resources;
+ ResourcePtr this, next;
+ int i, elements;
+ int *eltptr;
+
+ if (!client)
+ client = serverClient;
+
+ resources = clientTable[client->index].resources;
+ eltptr = &clientTable[client->index].elements;
+ for (i = 0; i < clientTable[client->index].buckets; i++)
+ {
+ for (this = resources[i]; this; this = next)
+ {
+ next = this->next;
+ if (!type || this->type == type) {
+ elements = *eltptr;
+ (*func)(this->value, this->id, cdata);
+ if (*eltptr != elements)
+ next = resources[i]; /* start over */
+ }
+ }
+ }
+}
+
+void
+FindAllClientResources(
+ ClientPtr client,
+ FindAllRes func,
+ pointer cdata
+){
+ ResourcePtr *resources;
+ ResourcePtr this, next;
+ int i, elements;
+ int *eltptr;
+
+ if (!client)
+ client = serverClient;
+
+ resources = clientTable[client->index].resources;
+ eltptr = &clientTable[client->index].elements;
+ for (i = 0; i < clientTable[client->index].buckets; i++)
+ {
+ for (this = resources[i]; this; this = next)
+ {
+ next = this->next;
+ elements = *eltptr;
+ (*func)(this->value, this->id, this->type, cdata);
+ if (*eltptr != elements)
+ next = resources[i]; /* start over */
+ }
+ }
+}
+
+
+pointer
+LookupClientResourceComplex(
+ ClientPtr client,
+ RESTYPE type,
+ FindComplexResType func,
+ pointer cdata
+){
+ ResourcePtr *resources;
+ ResourcePtr this, next;
+ pointer value;
+ int i;
+
+ if (!client)
+ client = serverClient;
+
+ resources = clientTable[client->index].resources;
+ for (i = 0; i < clientTable[client->index].buckets; i++) {
+ for (this = resources[i]; this; this = next) {
+ next = this->next;
+ if (!type || this->type == type) {
+ /* workaround func freeing the type as DRI1 does */
+ value = this->value;
+ if((*func)(value, this->id, cdata))
+ return value;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+void
+FreeClientNeverRetainResources(ClientPtr client)
+{
+ ResourcePtr *resources;
+ ResourcePtr this;
+ ResourcePtr *prev;
+ int j, elements;
+ int *eltptr;
+
+ if (!client)
+ return;
+
+ resources = clientTable[client->index].resources;
+ eltptr = &clientTable[client->index].elements;
+ for (j=0; j < clientTable[client->index].buckets; j++)
+ {
+ prev = &resources[j];
+ while ( (this = *prev) )
+ {
+ RESTYPE rtype = this->type;
+ if (rtype & RC_NEVERRETAIN)
+ {
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_FREE(this->id, this->type,
+ this->value, TypeNameString(this->type));
+#endif
+ *prev = this->next;
+ clientTable[client->index].elements--;
+ elements = *eltptr;
+
+ doFreeResource(this, FALSE);
+
+ if (*eltptr != elements)
+ prev = &resources[j]; /* prev may no longer be valid */
+ }
+ else
+ prev = &this->next;
+ }
+ }
+}
+
+void
+FreeClientResources(ClientPtr client)
+{
+ ResourcePtr *resources;
+ ResourcePtr this;
+ int j;
+
+ /* This routine shouldn't be called with a null client, but just in
+ case ... */
+
+ if (!client)
+ return;
+
+ HandleSaveSet(client);
+
+ resources = clientTable[client->index].resources;
+ for (j=0; j < clientTable[client->index].buckets; j++)
+ {
+ /* It may seem silly to update the head of this resource list as
+ we delete the members, since the entire list will be deleted any way,
+ but there are some resource deletion functions "FreeClientPixels" for
+ one which do a LookupID on another resource id (a Colormap id in this
+ case), so the resource list must be kept valid up to the point that
+ it is deleted, so every time we delete a resource, we must update the
+ head, just like in FreeResource. I hope that this doesn't slow down
+ mass deletion appreciably. PRH */
+
+ ResourcePtr *head;
+
+ head = &resources[j];
+
+ for (this = *head; this; this = *head)
+ {
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_FREE(this->id, this->type,
+ this->value, TypeNameString(this->type));
+#endif
+ *head = this->next;
+ clientTable[client->index].elements--;
+
+ doFreeResource(this, FALSE);
+ }
+ }
+ free(clientTable[client->index].resources);
+ clientTable[client->index].resources = NULL;
+ clientTable[client->index].buckets = 0;
+}
+
+void
+FreeAllResources(void)
+{
+ int i;
+
+ for (i = currentMaxClients; --i >= 0; )
+ {
+ if (clientTable[i].buckets)
+ FreeClientResources(clients[i]);
+ }
+}
+
+Bool
+LegalNewID(XID id, ClientPtr client)
+{
+ pointer val;
+ int rc;
+
+#ifdef PANORAMIX
+ XID minid, maxid;
+
+ if (!noPanoramiXExtension) {
+ minid = client->clientAsMask | (client->index ?
+ SERVER_BIT : SERVER_MINID);
+ maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1;
+ if ((id >= minid) && (id <= maxid))
+ return TRUE;
+ }
+#endif /* PANORAMIX */
+ if (client->clientAsMask == (id & ~RESOURCE_ID_MASK))
+ {
+ rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
+ DixGetAttrAccess);
+ return rc == BadValue;
+ }
+ return FALSE;
+}
+
+int
+dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype,
+ ClientPtr client, Mask mode)
+{
+ int cid = CLIENT_ID(id);
+ ResourcePtr res = NULL;
+
+ *result = NULL;
+ if ((rtype & TypeMask) > lastResourceType)
+ return BadImplementation;
+
+ if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
+ res = clientTable[cid].resources[Hash(cid, id)];
+
+ for (; res; res = res->next)
+ if (res->id == id && res->type == rtype)
+ break;
+ }
+ if (!res)
+ return resourceTypes[rtype & TypeMask].errorValue;
+
+ if (client) {
+ client->errorValue = id;
+ cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
+ res->value, RT_NONE, NULL, mode);
+ if (cid == BadValue)
+ return resourceTypes[rtype & TypeMask].errorValue;
+ if (cid != Success)
+ return cid;
+ }
+
+ *result = res->value;
+ return Success;
+}
+
+int
+dixLookupResourceByClass(pointer *result, XID id, RESTYPE rclass,
+ ClientPtr client, Mask mode)
+{
+ int cid = CLIENT_ID(id);
+ ResourcePtr res = NULL;
+
+ *result = NULL;
+
+ if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
+ res = clientTable[cid].resources[Hash(cid, id)];
+
+ for (; res; res = res->next)
+ if (res->id == id && (res->type & rclass))
+ break;
+ }
+ if (!res)
+ return BadValue;
+
+ if (client) {
+ client->errorValue = id;
+ cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
+ res->value, RT_NONE, NULL, mode);
+ if (cid != Success)
+ return cid;
+ }
+
+ *result = res->value;
+ return Success;
+}
diff --git a/xorg-server/glx/Makefile.am b/xorg-server/glx/Makefile.am
index 41fdf5fc2..ef8677a7c 100644
--- a/xorg-server/glx/Makefile.am
+++ b/xorg-server/glx/Makefile.am
@@ -1,98 +1,101 @@
-if AIGLX
-GLXDRI_LIBRARY = libglxdri.la
-endif
-
-noinst_LTLIBRARIES = libglx.la $(GLXDRI_LIBRARY)
-
-AM_CFLAGS = \
- @DIX_CFLAGS@ \
- @GL_CFLAGS@ \
- @DRI_CFLAGS@ \
- @XLIB_CFLAGS@ \
- @LIBDRM_CFLAGS@ \
- @DRIPROTO_CFLAGS@ \
- @GLX_DEFINES@ \
- @GLX_ARCH_DEFINES@
-
-# none yet
-#sdk_HEADERS =
-
-INCLUDES = \
- -I$(top_srcdir)/hw/xfree86/os-support \
- -I$(top_srcdir)/hw/xfree86/os-support/bus \
- -I$(top_srcdir)/hw/xfree86/common \
- -I$(top_srcdir)/hw/xfree86/dri \
- -I$(top_srcdir)/mi
-
-if DRI2_AIGLX
-INCLUDES += -I$(top_srcdir)/hw/xfree86/dri2
-endif
-
-glapi_sources = \
- indirect_dispatch.c \
- indirect_dispatch.h \
- indirect_dispatch_swap.c \
- indirect_reqsize.c \
- indirect_reqsize.h \
- indirect_size.h \
- indirect_size_get.c \
- indirect_size_get.h \
- indirect_table.c \
- dispatch.h \
- glapitable.h \
- glapi.c \
- glapi.h \
- glapioffsets.h \
- glprocs.h \
- glthread.c \
- glthread.h
-
-libglxdri_la_SOURCES = \
- glxdri.c \
- extension_string.c \
- extension_string.h
-
-if DRI2_AIGLX
-libglxdri_la_SOURCES += glxdri2.c
-endif
-
-libglxdri_la_LIBADD = $(DLOPEN_LIBS)
-
-libglx_la_SOURCES = \
- $(indirect_sources) \
- $(glapi_sources) \
- indirect_util.c \
- indirect_util.h \
- indirect_program.c \
- indirect_table.h \
- indirect_texture_compression.c \
- glxbyteorder.h \
- glxcmds.c \
- glxcmdsswap.c \
- glxcontext.h \
- glxdrawable.h \
- glxext.c \
- glxext.h \
- glxdriswrast.c \
- glxdricommon.c \
- glxdricommon.h \
- glxscreens.c \
- glxscreens.h \
- glxserver.h \
- glxutil.h \
- render2.c \
- render2swap.c \
- renderpix.c \
- renderpixswap.c \
- rensize.c \
- single2.c \
- single2swap.c \
- singlepix.c \
- singlepixswap.c \
- singlesize.c \
- singlesize.h \
- swap_interval.c \
- unpack.h \
- xfont.c
-
-libglx_la_LIBADD = $(DLOPEN_LIBS)
+if AIGLX
+GLXDRI_LIBRARY = libglxdri.la
+endif
+
+noinst_LTLIBRARIES = libglx.la $(GLXDRI_LIBRARY)
+
+AM_CFLAGS = \
+ @DIX_CFLAGS@ \
+ @GL_CFLAGS@ \
+ @DRI_CFLAGS@ \
+ @XLIB_CFLAGS@ \
+ @LIBDRM_CFLAGS@ \
+ @DRIPROTO_CFLAGS@ \
+ @GLX_DEFINES@ \
+ @GLX_ARCH_DEFINES@
+
+# none yet
+#sdk_HEADERS =
+
+INCLUDES = \
+ -I$(top_srcdir)/hw/xfree86/os-support \
+ -I$(top_srcdir)/hw/xfree86/os-support/bus \
+ -I$(top_srcdir)/hw/xfree86/common \
+ -I$(top_srcdir)/hw/xfree86/dri \
+ -I$(top_srcdir)/mi
+
+if DRI2_AIGLX
+INCLUDES += -I$(top_srcdir)/hw/xfree86/dri2
+endif
+
+glapi_sources = \
+ indirect_dispatch.c \
+ indirect_dispatch.h \
+ indirect_dispatch_swap.c \
+ indirect_reqsize.c \
+ indirect_reqsize.h \
+ indirect_size.h \
+ indirect_size_get.c \
+ indirect_size_get.h \
+ indirect_table.c \
+ dispatch.h \
+ glapitable.h \
+ glapi.c \
+ glapi.h \
+ glapioffsets.h \
+ glprocs.h \
+ glthread.c \
+ glthread.h
+
+libglxdri_la_SOURCES = \
+ extension_string.c \
+ extension_string.h
+
+if DRI
+libglxdri_la_SOURCES += glxdri.c
+endif
+
+if DRI2_AIGLX
+libglxdri_la_SOURCES += glxdri2.c
+endif
+
+libglxdri_la_LIBADD = $(DLOPEN_LIBS)
+
+libglx_la_SOURCES = \
+ $(indirect_sources) \
+ $(glapi_sources) \
+ indirect_util.c \
+ indirect_util.h \
+ indirect_program.c \
+ indirect_table.h \
+ indirect_texture_compression.c \
+ glxbyteorder.h \
+ glxcmds.c \
+ glxcmdsswap.c \
+ glxcontext.h \
+ glxdrawable.h \
+ glxext.c \
+ glxext.h \
+ glxdriswrast.c \
+ glxdricommon.c \
+ glxdricommon.h \
+ glxscreens.c \
+ glxscreens.h \
+ glxserver.h \
+ glxutil.h \
+ render2.c \
+ render2swap.c \
+ renderpix.c \
+ renderpixswap.c \
+ rensize.c \
+ single2.c \
+ single2swap.c \
+ singlepix.c \
+ singlepixswap.c \
+ singlesize.c \
+ singlesize.h \
+ swap_interval.c \
+ unpack.h \
+ xfont.c
+
+libglx_la_LIBADD = $(DLOPEN_LIBS)
diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c
index b524597a8..d5b764fd0 100644
--- a/xorg-server/glx/glxcmds.c
+++ b/xorg-server/glx/glxcmds.c
@@ -1,2331 +1,2334 @@
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. 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 including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * 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
- * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-#include <assert.h>
-
-#include "glxserver.h"
-#include <GL/glxtokens.h>
-#include <unpack.h>
-#include <pixmapstr.h>
-#include <windowstr.h>
-#include "glxutil.h"
-#include "glxext.h"
-#include "glapitable.h"
-#include "glapi.h"
-#include "glthread.h"
-#include "dispatch.h"
-#include "indirect_dispatch.h"
-#include "indirect_table.h"
-#include "indirect_util.h"
-
-static int
-validGlxScreen(ClientPtr client, int screen, __GLXscreen **pGlxScreen, int *err)
-{
- /*
- ** Check if screen exists.
- */
- if (screen < 0 || screen >= screenInfo.numScreens) {
- client->errorValue = screen;
- *err = BadValue;
- return FALSE;
- }
- *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
-
- return TRUE;
-}
-
-static int
-validGlxFBConfig(ClientPtr client, __GLXscreen *pGlxScreen, XID id,
- __GLXconfig **config, int *err)
-{
- __GLXconfig *m;
-
- for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next)
- if (m->fbconfigID == id) {
- *config = m;
- return TRUE;
- }
-
- client->errorValue = id;
- *err = __glXError(GLXBadFBConfig);
-
- return FALSE;
-}
-
-static int
-validGlxVisual(ClientPtr client, __GLXscreen *pGlxScreen, XID id,
- __GLXconfig **config, int *err)
-{
- int i;
-
- for (i = 0; i < pGlxScreen->numVisuals; i++)
- if (pGlxScreen->visuals[i]->visualID == id) {
- *config = pGlxScreen->visuals[i];
- return TRUE;
- }
-
- client->errorValue = id;
- *err = BadValue;
-
- return FALSE;
-}
-
-static int
-validGlxFBConfigForWindow(ClientPtr client, __GLXconfig *config,
- DrawablePtr pDraw, int *err)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- VisualPtr pVisual = NULL;
- XID vid;
- int i;
-
- vid = wVisual((WindowPtr)pDraw);
- for (i = 0; i < pScreen->numVisuals; i++) {
- if (pScreen->visuals[i].vid == vid) {
- pVisual = &pScreen->visuals[i];
- break;
- }
- }
-
- /* FIXME: What exactly should we check here... */
- if (pVisual->class != glxConvertToXVisualType(config->visualType) ||
- !(config->drawableType & GLX_WINDOW_BIT)) {
- client->errorValue = pDraw->id;
- *err = BadMatch;
- return FALSE;
- }
-
- return TRUE;
-}
-
-static int
-validGlxContext(ClientPtr client, XID id, int access_mode,
- __GLXcontext **context, int *err)
-{
- *err = dixLookupResourceByType((pointer *) context, id,
- __glXContextRes, client, access_mode);
- if (*err != Success || (*context)->idExists == GL_FALSE) {
- client->errorValue = id;
- if (*err == BadValue || *err == Success)
- *err = __glXError(GLXBadContext);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static int
-validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
- __GLXdrawable **drawable, int *err)
-{
- int rc;
-
- rc = dixLookupResourceByType((pointer *) drawable, id,
- __glXDrawableRes, client, access_mode);
- if (rc != Success && rc != BadValue) {
- *err = rc;
- client->errorValue = id;
- return FALSE;
- }
-
- /* If the ID of the glx drawable we looked up doesn't match the id
- * we looked for, it's because we looked it up under the X
- * drawable ID (see DoCreateGLXDrawable). */
- if (rc == BadValue ||
- (*drawable)->drawId != id ||
- (type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) {
- client->errorValue = id;
- switch (type) {
- case GLX_DRAWABLE_WINDOW:
- *err = __glXError(GLXBadWindow);
- return FALSE;
- case GLX_DRAWABLE_PIXMAP:
- *err = __glXError(GLXBadPixmap);
- return FALSE;
- case GLX_DRAWABLE_PBUFFER:
- *err = __glXError(GLXBadPbuffer);
- return FALSE;
- case GLX_DRAWABLE_ANY:
- *err = __glXError(GLXBadDrawable);
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-void
-__glXContextDestroy(__GLXcontext *context)
-{
- __glXFlushContextCache();
-}
-
-static void __glXdirectContextDestroy(__GLXcontext *context)
-{
- __glXContextDestroy(context);
- free(context);
-}
-
-static __GLXcontext *__glXdirectContextCreate(__GLXscreen *screen,
- __GLXconfig *modes,
- __GLXcontext *shareContext)
-{
- __GLXcontext *context;
-
- context = calloc(1, sizeof (__GLXcontext));
- if (context == NULL)
- return NULL;
-
- context->destroy = __glXdirectContextDestroy;
-
- return context;
-}
-
-/**
- * Create a GL context with the given properties. This routine is used
- * to implement \c glXCreateContext, \c glXCreateNewContext, and
- * \c glXCreateContextWithConfigSGIX. This works becuase of the hack way
- * that GLXFBConfigs are implemented. Basically, the FBConfigID is the
- * same as the VisualID.
- */
-
-static int
-DoCreateContext(__GLXclientState *cl, GLXContextID gcId,
- GLXContextID shareList, __GLXconfig *config,
- __GLXscreen *pGlxScreen, GLboolean isDirect)
-{
- ClientPtr client = cl->client;
- __GLXcontext *glxc, *shareglxc;
- int err;
-
- LEGAL_NEW_RESOURCE(gcId, client);
-
- /*
- ** Find the display list space that we want to share.
- **
- ** NOTE: In a multithreaded X server, we would need to keep a reference
- ** count for each display list so that if one client detroyed a list that
- ** another client was using, the list would not really be freed until it
- ** was no longer in use. Since this sample implementation has no support
- ** for multithreaded servers, we don't do this.
- */
- if (shareList == None) {
- shareglxc = 0;
- } else {
- if (!validGlxContext(client, shareList, DixReadAccess,
- &shareglxc, &err))
- return err;
-
- if (shareglxc->isDirect) {
- /*
- ** NOTE: no support for sharing display lists between direct
- ** contexts, even if they are in the same address space.
- */
-#if 0
- /* Disabling this code seems to allow shared display lists
- * and texture objects to work. We'll leave it disabled for now.
- */
- client->errorValue = shareList;
- return BadMatch;
-#endif
- } else {
- /*
- ** Create an indirect context regardless of what the client asked
- ** for; this way we can share display list space with shareList.
- */
- isDirect = GL_FALSE;
- }
- }
-
- /*
- ** Allocate memory for the new context
- */
- if (!isDirect)
- glxc = pGlxScreen->createContext(pGlxScreen, config, shareglxc);
- else
- glxc = __glXdirectContextCreate(pGlxScreen, config, shareglxc);
- if (!glxc) {
- return BadAlloc;
- }
-
- /*
- ** Initially, setup the part of the context that could be used by
- ** a GL core that needs windowing information (e.g., Mesa).
- */
- glxc->pGlxScreen = pGlxScreen;
- glxc->config = config;
-
- /*
- ** Register this context as a resource.
- */
- if (!AddResource(gcId, __glXContextRes, (pointer)glxc)) {
- (*glxc->destroy)(glxc);
- client->errorValue = gcId;
- return BadAlloc;
- }
-
- /*
- ** Finally, now that everything is working, setup the rest of the
- ** context.
- */
- glxc->id = gcId;
- glxc->share_id = shareList;
- glxc->idExists = GL_TRUE;
- glxc->isCurrent = GL_FALSE;
- glxc->isDirect = isDirect;
- glxc->renderMode = GL_RENDER;
-
- __glXAddToContextList(glxc);
-
- return Success;
-}
-
-int __glXDisp_CreateContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateContextReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
- return err;
-
- return DoCreateContext(cl, req->context, req->shareList,
- config, pGlxScreen, req->isDirect);
-}
-
-int __glXDisp_CreateNewContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateNewContextReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- return DoCreateContext(cl, req->context, req->shareList,
- config, pGlxScreen, req->isDirect);
-}
-
-int __glXDisp_CreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateContextWithConfigSGIXReq *req =
- (xGLXCreateContextWithConfigSGIXReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateContextWithConfigSGIXReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- return DoCreateContext(cl, req->context, req->shareList,
- config, pGlxScreen, req->isDirect);
-}
-
-int __glXDisp_DestroyContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc;
- __GLXcontext *glxc;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXDestroyContextReq);
-
- if (!validGlxContext(cl->client, req->context, DixDestroyAccess,
- &glxc, &err))
- return err;
-
- glxc->idExists = GL_FALSE;
- if (!glxc->isCurrent)
- FreeResourceByType(req->context, __glXContextRes, FALSE);
-
- return Success;
-}
-
-/*
- * This will return "deleted" contexts, ie, where idExists is GL_FALSE.
- * Contrast validGlxContext, which will not. We're cheating here and
- * using the XID as the context tag, which is fine as long as we defer
- * actually destroying the context until it's no longer referenced, and
- * block clients from trying to MakeCurrent on contexts that are on the
- * way to destruction. Notice that DoMakeCurrent calls validGlxContext
- * for new contexts but __glXLookupContextByTag for previous contexts.
- */
-__GLXcontext *__glXLookupContextByTag(__GLXclientState *cl, GLXContextTag tag)
-{
- __GLXcontext *ret;
-
- if (dixLookupResourceByType((void **)&ret, tag, __glXContextRes,
- cl->client, DixUseAccess) == Success)
- return ret;
-
- return NULL;
-}
-
-/*****************************************************************************/
-
-static void StopUsingContext(__GLXcontext *glxc)
-{
- if (glxc) {
- if (glxc == __glXLastContext) {
- /* Tell server GL library */
- __glXLastContext = 0;
- }
- glxc->isCurrent = GL_FALSE;
- if (!glxc->idExists) {
- FreeResourceByType(glxc->id, __glXContextRes, FALSE);
- }
- }
-}
-
-static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc)
-{
- glxc->isCurrent = GL_TRUE;
- __glXLastContext = glxc;
-}
-
-/**
- * This is a helper function to handle the legacy (pre GLX 1.3) cases
- * where passing an X window to glXMakeCurrent is valid. Given a
- * resource ID, look up the GLX drawable if available, otherwise, make
- * sure it's an X window and create a GLX drawable one the fly.
- */
-static __GLXdrawable *
-__glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client,
- int *error)
-{
- DrawablePtr pDraw;
- __GLXdrawable *pGlxDraw;
- int rc;
-
- if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
- DixWriteAccess, &pGlxDraw, &rc)) {
- if (glxc != NULL && pGlxDraw->config != glxc->config) {
- client->errorValue = drawId;
- *error = BadMatch;
- return NULL;
- }
-
- return pGlxDraw;
- }
-
- /* No active context and an unknown drawable, bail. */
- if (glxc == NULL) {
- client->errorValue = drawId;
- *error = BadMatch;
- return NULL;
- }
-
- /* The drawId wasn't a GLX drawable. Make sure it's a window and
- * create a GLXWindow for it. Check that the drawable screen
- * matches the context screen and that the context fbconfig is
- * compatible with the window visual. */
-
- rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess);
- if (rc != Success || pDraw->type != DRAWABLE_WINDOW) {
- client->errorValue = drawId;
- *error = __glXError(GLXBadDrawable);
- return NULL;
- }
-
- if (pDraw->pScreen != glxc->pGlxScreen->pScreen) {
- client->errorValue = pDraw->pScreen->myNum;
- *error = BadMatch;
- return NULL;
- }
-
- if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
- return NULL;
-
- pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
- pDraw, drawId,
- GLX_DRAWABLE_WINDOW,
- drawId, glxc->config);
-
- /* since we are creating the drawablePrivate, drawId should be new */
- if (!AddResource(drawId, __glXDrawableRes, pGlxDraw)) {
- pGlxDraw->destroy (pGlxDraw);
- *error = BadAlloc;
- return NULL;
- }
-
- return pGlxDraw;
-}
-
-/*****************************************************************************/
-/*
-** Make an OpenGL context and drawable current.
-*/
-
-static int
-DoMakeCurrent(__GLXclientState *cl,
- GLXDrawable drawId, GLXDrawable readId,
- GLXContextID contextId, GLXContextTag tag)
-{
- ClientPtr client = cl->client;
- xGLXMakeCurrentReply reply;
- __GLXcontext *glxc, *prevglxc;
- __GLXdrawable *drawPriv = NULL;
- __GLXdrawable *readPriv = NULL;
- int error;
- GLuint mask;
-
- /*
- ** If one is None and the other isn't, it's a bad match.
- */
-
- mask = (drawId == None) ? (1 << 0) : 0;
- mask |= (readId == None) ? (1 << 1) : 0;
- mask |= (contextId == None) ? (1 << 2) : 0;
-
- if ( (mask != 0x00) && (mask != 0x07) ) {
- return BadMatch;
- }
-
- /*
- ** Lookup old context. If we have one, it must be in a usable state.
- */
- if (tag != 0) {
- prevglxc = __glXLookupContextByTag(cl, tag);
- if (!prevglxc) {
- /*
- ** Tag for previous context is invalid.
- */
- return __glXError(GLXBadContextTag);
- }
- if (prevglxc->renderMode != GL_RENDER) {
- /* Oops. Not in render mode render. */
- client->errorValue = prevglxc->id;
- return __glXError(GLXBadContextState);
- }
- } else {
- prevglxc = 0;
- }
-
- /*
- ** Lookup new context. It must not be current for someone else.
- */
- if (contextId != None) {
- int status;
-
- if (!validGlxContext(client, contextId, DixUseAccess, &glxc, &error))
- return error;
- if ((glxc != prevglxc) && glxc->isCurrent) {
- /* Context is current to somebody else */
- return BadAccess;
- }
-
- assert( drawId != None );
- assert( readId != None );
-
- drawPriv = __glXGetDrawable(glxc, drawId, client, &status);
- if (drawPriv == NULL)
- return status;
-
- readPriv = __glXGetDrawable(glxc, readId, client, &status);
- if (readPriv == NULL)
- return status;
-
- } else {
- /* Switching to no context. Ignore new drawable. */
- glxc = 0;
- drawPriv = 0;
- readPriv = 0;
- }
-
-
- if (prevglxc) {
- /*
- ** Flush the previous context if needed.
- */
- if (prevglxc->hasUnflushedCommands) {
- if (__glXForceCurrent(cl, tag, (int *)&error)) {
- CALL_Flush( GET_DISPATCH(), () );
- prevglxc->hasUnflushedCommands = GL_FALSE;
- } else {
- return error;
- }
- }
-
- /*
- ** Make the previous context not current.
- */
- if (!(*prevglxc->loseCurrent)(prevglxc)) {
- return __glXError(GLXBadContext);
- }
- __glXFlushContextCache();
- if (!prevglxc->isDirect) {
- prevglxc->drawPriv = NULL;
- prevglxc->readPriv = NULL;
- }
- }
-
-
- if ((glxc != 0) && !glxc->isDirect) {
-
- glxc->drawPriv = drawPriv;
- glxc->readPriv = readPriv;
-
- /* make the context current */
- if (!(*glxc->makeCurrent)(glxc)) {
- glxc->drawPriv = NULL;
- glxc->readPriv = NULL;
- return __glXError(GLXBadContext);
- }
-
- glxc->isCurrent = GL_TRUE;
- }
-
- StopUsingContext(prevglxc);
-
- if (glxc) {
- StartUsingContext(cl, glxc);
- reply.contextTag = glxc->id;
- } else {
- reply.contextTag = 0;
- }
-
- reply.length = 0;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __glXSwapMakeCurrentReply(client, &reply);
- } else {
- WriteToClient(client, sz_xGLXMakeCurrentReply, (char *)&reply);
- }
- return Success;
-}
-
-int __glXDisp_MakeCurrent(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXMakeCurrentReq);
-
- return DoMakeCurrent( cl, req->drawable, req->drawable,
- req->context, req->oldContextTag );
-}
-
-int __glXDisp_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXMakeContextCurrentReq);
-
- return DoMakeCurrent( cl, req->drawable, req->readdrawable,
- req->context, req->oldContextTag );
-}
-
-int __glXDisp_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXMakeCurrentReadSGIReq);
-
- return DoMakeCurrent( cl, req->drawable, req->readable,
- req->context, req->oldContextTag );
-}
-
-int __glXDisp_IsDirect(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc;
- xGLXIsDirectReply reply;
- __GLXcontext *glxc;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXIsDirectReq);
-
- if (!validGlxContext(cl->client, req->context, DixReadAccess, &glxc, &err))
- return err;
-
- reply.isDirect = glxc->isDirect;
- reply.length = 0;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __glXSwapIsDirectReply(client, &reply);
- } else {
- WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply);
- }
-
- return Success;
-}
-
-int __glXDisp_QueryVersion(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc;
- xGLXQueryVersionReply reply;
- GLuint major, minor;
-
- REQUEST_SIZE_MATCH(xGLXQueryVersionReq);
-
- major = req->majorVersion;
- minor = req->minorVersion;
- (void)major;
- (void)minor;
-
- /*
- ** Server should take into consideration the version numbers sent by the
- ** client if it wants to work with older clients; however, in this
- ** implementation the server just returns its version number.
- */
- reply.majorVersion = glxMajorVersion;
- reply.minorVersion = glxMinorVersion;
- reply.length = 0;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __glXSwapQueryVersionReply(client, &reply);
- } else {
- WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply);
- }
- return Success;
-}
-
-int __glXDisp_WaitGL(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXWaitGLReq *req = (xGLXWaitGLReq *)pc;
- GLXContextTag tag;
- __GLXcontext *glxc = NULL;
- int error;
-
- REQUEST_SIZE_MATCH(xGLXWaitGLReq);
-
- tag = req->contextTag;
- if (tag) {
- glxc = __glXLookupContextByTag(cl, tag);
- if (!glxc)
- return __glXError(GLXBadContextTag);
-
- if (!__glXForceCurrent(cl, req->contextTag, &error))
- return error;
-
- CALL_Finish( GET_DISPATCH(), () );
- }
-
- if (glxc && glxc->drawPriv->waitGL)
- (*glxc->drawPriv->waitGL)(glxc->drawPriv);
-
- return Success;
-}
-
-int __glXDisp_WaitX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXWaitXReq *req = (xGLXWaitXReq *)pc;
- GLXContextTag tag;
- __GLXcontext *glxc = NULL;
- int error;
-
- REQUEST_SIZE_MATCH(xGLXWaitXReq);
-
- tag = req->contextTag;
- if (tag) {
- glxc = __glXLookupContextByTag(cl, tag);
- if (!glxc)
- return __glXError(GLXBadContextTag);
-
- if (!__glXForceCurrent(cl, req->contextTag, &error))
- return error;
- }
-
- if (glxc && glxc->drawPriv->waitX)
- (*glxc->drawPriv->waitX)(glxc->drawPriv);
-
- return Success;
-}
-
-int __glXDisp_CopyContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc;
- GLXContextID source;
- GLXContextID dest;
- GLXContextTag tag;
- unsigned long mask;
- __GLXcontext *src, *dst;
- int error;
-
- REQUEST_SIZE_MATCH(xGLXCopyContextReq);
-
- source = req->source;
- dest = req->dest;
- tag = req->contextTag;
- mask = req->mask;
- if (!validGlxContext(cl->client, source, DixReadAccess, &src, &error))
- return error;
- if (!validGlxContext(cl->client, dest, DixWriteAccess, &dst, &error))
- return error;
-
- /*
- ** They must be in the same address space, and same screen.
- ** NOTE: no support for direct rendering contexts here.
- */
- if (src->isDirect || dst->isDirect ||
- (src->pGlxScreen != dst->pGlxScreen)) {
- client->errorValue = source;
- return BadMatch;
- }
-
- /*
- ** The destination context must not be current for any client.
- */
- if (dst->isCurrent) {
- client->errorValue = dest;
- return BadAccess;
- }
-
- if (tag) {
- __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag);
-
- if (!tagcx) {
- return __glXError(GLXBadContextTag);
- }
- if (tagcx != src) {
- /*
- ** This would be caused by a faulty implementation of the client
- ** library.
- */
- return BadMatch;
- }
- /*
- ** In this case, glXCopyContext is in both GL and X streams, in terms
- ** of sequentiality.
- */
- if (__glXForceCurrent(cl, tag, &error)) {
- /*
- ** Do whatever is needed to make sure that all preceding requests
- ** in both streams are completed before the copy is executed.
- */
- CALL_Finish( GET_DISPATCH(), () );
- tagcx->hasUnflushedCommands = GL_FALSE;
- } else {
- return error;
- }
- }
- /*
- ** Issue copy. The only reason for failure is a bad mask.
- */
- if (!(*dst->copy)(dst, src, mask)) {
- client->errorValue = mask;
- return BadValue;
- }
- return Success;
-}
-
-enum {
- GLX_VIS_CONFIG_UNPAIRED = 18,
- GLX_VIS_CONFIG_PAIRED = 20
-};
-
-enum {
- GLX_VIS_CONFIG_TOTAL = GLX_VIS_CONFIG_UNPAIRED + GLX_VIS_CONFIG_PAIRED
-};
-
-int __glXDisp_GetVisualConfigs(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc;
- ClientPtr client = cl->client;
- xGLXGetVisualConfigsReply reply;
- __GLXscreen *pGlxScreen;
- __GLXconfig *modes;
- CARD32 buf[GLX_VIS_CONFIG_TOTAL];
- int p, i, err;
- __GLX_DECLARE_SWAP_VARIABLES;
- __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
-
- REQUEST_SIZE_MATCH(xGLXGetVisualConfigsReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
-
- reply.numVisuals = pGlxScreen->numVisuals;
- reply.numProps = GLX_VIS_CONFIG_TOTAL;
- reply.length = (reply.numVisuals * __GLX_SIZE_CARD32 * GLX_VIS_CONFIG_TOTAL) >> 2;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __GLX_SWAP_SHORT(&reply.sequenceNumber);
- __GLX_SWAP_INT(&reply.length);
- __GLX_SWAP_INT(&reply.numVisuals);
- __GLX_SWAP_INT(&reply.numProps);
- }
-
- WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char *)&reply);
-
- for (i = 0; i < pGlxScreen->numVisuals; i++) {
- modes = pGlxScreen->visuals[i];
-
- p = 0;
- buf[p++] = modes->visualID;
- buf[p++] = glxConvertToXVisualType( modes->visualType );
- buf[p++] = (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE;
-
- buf[p++] = modes->redBits;
- buf[p++] = modes->greenBits;
- buf[p++] = modes->blueBits;
- buf[p++] = modes->alphaBits;
- buf[p++] = modes->accumRedBits;
- buf[p++] = modes->accumGreenBits;
- buf[p++] = modes->accumBlueBits;
- buf[p++] = modes->accumAlphaBits;
-
- buf[p++] = modes->doubleBufferMode;
- buf[p++] = modes->stereoMode;
-
- buf[p++] = modes->rgbBits;
- buf[p++] = modes->depthBits;
- buf[p++] = modes->stencilBits;
- buf[p++] = modes->numAuxBuffers;
- buf[p++] = modes->level;
-
- assert(p == GLX_VIS_CONFIG_UNPAIRED);
- /*
- ** Add token/value pairs for extensions.
- */
- buf[p++] = GLX_VISUAL_CAVEAT_EXT;
- buf[p++] = modes->visualRating;
- buf[p++] = GLX_TRANSPARENT_TYPE;
- buf[p++] = modes->transparentPixel;
- buf[p++] = GLX_TRANSPARENT_RED_VALUE;
- buf[p++] = modes->transparentRed;
- buf[p++] = GLX_TRANSPARENT_GREEN_VALUE;
- buf[p++] = modes->transparentGreen;
- buf[p++] = GLX_TRANSPARENT_BLUE_VALUE;
- buf[p++] = modes->transparentBlue;
- buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE;
- buf[p++] = modes->transparentAlpha;
- buf[p++] = GLX_TRANSPARENT_INDEX_VALUE;
- buf[p++] = modes->transparentIndex;
- buf[p++] = GLX_SAMPLES_SGIS;
- buf[p++] = modes->samples;
- buf[p++] = GLX_SAMPLE_BUFFERS_SGIS;
- buf[p++] = modes->sampleBuffers;
- buf[p++] = 0; /* copy over visualSelectGroup (GLX_VISUAL_SELECT_GROUP_SGIX)? */
- buf[p++] = 0;
-
- assert(p == GLX_VIS_CONFIG_TOTAL);
- if (client->swapped) {
- __GLX_SWAP_INT_ARRAY(buf, p);
- }
- WriteToClient(client, __GLX_SIZE_CARD32 * p, (char *)buf);
- }
- return Success;
-}
-
-#define __GLX_TOTAL_FBCONFIG_ATTRIBS (36)
-#define __GLX_FBCONFIG_ATTRIBS_LENGTH (__GLX_TOTAL_FBCONFIG_ATTRIBS * 2)
-/**
- * Send the set of GLXFBConfigs to the client. There is not currently
- * and interface into the driver on the server-side to get GLXFBConfigs,
- * so we "invent" some based on the \c __GLXvisualConfig structures that
- * the driver does supply.
- *
- * The reply format for both \c glXGetFBConfigs and \c glXGetFBConfigsSGIX
- * is the same, so this routine pulls double duty.
- */
-
-static int
-DoGetFBConfigs(__GLXclientState *cl, unsigned screen)
-{
- ClientPtr client = cl->client;
- xGLXGetFBConfigsReply reply;
- __GLXscreen *pGlxScreen;
- CARD32 buf[__GLX_FBCONFIG_ATTRIBS_LENGTH];
- int p, err;
- __GLXconfig *modes;
- __GLX_DECLARE_SWAP_VARIABLES;
- __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
-
- if (!validGlxScreen(cl->client, screen, &pGlxScreen, &err))
- return err;
-
- reply.numFBConfigs = pGlxScreen->numFBConfigs;
- reply.numAttribs = __GLX_TOTAL_FBCONFIG_ATTRIBS;
- reply.length = (__GLX_FBCONFIG_ATTRIBS_LENGTH * reply.numFBConfigs);
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __GLX_SWAP_SHORT(&reply.sequenceNumber);
- __GLX_SWAP_INT(&reply.length);
- __GLX_SWAP_INT(&reply.numFBConfigs);
- __GLX_SWAP_INT(&reply.numAttribs);
- }
-
- WriteToClient(client, sz_xGLXGetFBConfigsReply, (char *)&reply);
-
- for (modes = pGlxScreen->fbconfigs; modes != NULL; modes = modes->next) {
- p = 0;
-
-#define WRITE_PAIR(tag,value) \
- do { buf[p++] = tag ; buf[p++] = value ; } while( 0 )
-
- WRITE_PAIR( GLX_VISUAL_ID, modes->visualID );
- WRITE_PAIR( GLX_FBCONFIG_ID, modes->fbconfigID );
- WRITE_PAIR( GLX_X_RENDERABLE, GL_TRUE );
-
- WRITE_PAIR( GLX_RGBA,
- (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE );
- WRITE_PAIR( GLX_RENDER_TYPE, modes->renderType );
- WRITE_PAIR( GLX_DOUBLEBUFFER, modes->doubleBufferMode );
- WRITE_PAIR( GLX_STEREO, modes->stereoMode );
-
- WRITE_PAIR( GLX_BUFFER_SIZE, modes->rgbBits );
- WRITE_PAIR( GLX_LEVEL, modes->level );
- WRITE_PAIR( GLX_AUX_BUFFERS, modes->numAuxBuffers );
- WRITE_PAIR( GLX_RED_SIZE, modes->redBits );
- WRITE_PAIR( GLX_GREEN_SIZE, modes->greenBits );
- WRITE_PAIR( GLX_BLUE_SIZE, modes->blueBits );
- WRITE_PAIR( GLX_ALPHA_SIZE, modes->alphaBits );
- WRITE_PAIR( GLX_ACCUM_RED_SIZE, modes->accumRedBits );
- WRITE_PAIR( GLX_ACCUM_GREEN_SIZE, modes->accumGreenBits );
- WRITE_PAIR( GLX_ACCUM_BLUE_SIZE, modes->accumBlueBits );
- WRITE_PAIR( GLX_ACCUM_ALPHA_SIZE, modes->accumAlphaBits );
- WRITE_PAIR( GLX_DEPTH_SIZE, modes->depthBits );
- WRITE_PAIR( GLX_STENCIL_SIZE, modes->stencilBits );
- WRITE_PAIR( GLX_X_VISUAL_TYPE, modes->visualType );
- WRITE_PAIR( GLX_CONFIG_CAVEAT, modes->visualRating );
- WRITE_PAIR( GLX_TRANSPARENT_TYPE, modes->transparentPixel );
- WRITE_PAIR( GLX_TRANSPARENT_RED_VALUE, modes->transparentRed );
- WRITE_PAIR( GLX_TRANSPARENT_GREEN_VALUE, modes->transparentGreen );
- WRITE_PAIR( GLX_TRANSPARENT_BLUE_VALUE, modes->transparentBlue );
- WRITE_PAIR( GLX_TRANSPARENT_ALPHA_VALUE, modes->transparentAlpha );
- WRITE_PAIR( GLX_TRANSPARENT_INDEX_VALUE, modes->transparentIndex );
- WRITE_PAIR( GLX_SWAP_METHOD_OML, modes->swapMethod );
- WRITE_PAIR( GLX_SAMPLES_SGIS, modes->samples );
- WRITE_PAIR( GLX_SAMPLE_BUFFERS_SGIS, modes->sampleBuffers );
- /* GLX_VISUAL_SELECT_GROUP_SGIX ? */
- WRITE_PAIR( GLX_DRAWABLE_TYPE, modes->drawableType );
- WRITE_PAIR( GLX_BIND_TO_TEXTURE_RGB_EXT, modes->bindToTextureRgb );
- WRITE_PAIR( GLX_BIND_TO_TEXTURE_RGBA_EXT, modes->bindToTextureRgba );
- WRITE_PAIR( GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture );
- WRITE_PAIR( GLX_BIND_TO_TEXTURE_TARGETS_EXT, modes->bindToTextureTargets );
-
- if (client->swapped) {
- __GLX_SWAP_INT_ARRAY(buf, __GLX_FBCONFIG_ATTRIBS_LENGTH);
- }
- WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_FBCONFIG_ATTRIBS_LENGTH,
- (char *)buf);
- }
- return Success;
-}
-
-
-int __glXDisp_GetFBConfigs(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc;
- REQUEST_SIZE_MATCH(xGLXGetFBConfigsReq);
- return DoGetFBConfigs(cl, req->screen);
-}
-
-int __glXDisp_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc;
- /* work around mesa bug, don't use REQUEST_SIZE_MATCH */
- REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
- return DoGetFBConfigs(cl, req->screen);
-}
-
-GLboolean
-__glXDrawableInit(__GLXdrawable *drawable,
- __GLXscreen *screen, DrawablePtr pDraw, int type,
- XID drawId, __GLXconfig *config)
-{
- drawable->pDraw = pDraw;
- drawable->type = type;
- drawable->drawId = drawId;
- drawable->config = config;
- drawable->eventMask = 0;
-
- return GL_TRUE;
-}
-
-void
-__glXDrawableRelease(__GLXdrawable *drawable)
-{
-}
-
-static int
-DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
- __GLXconfig *config, DrawablePtr pDraw, XID drawableId,
- XID glxDrawableId, int type)
-{
- __GLXdrawable *pGlxDraw;
-
- if (pGlxScreen->pScreen != pDraw->pScreen)
- return BadMatch;
-
- pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
- drawableId, type,
- glxDrawableId, config);
- if (pGlxDraw == NULL)
- return BadAlloc;
-
- if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) {
- pGlxDraw->destroy (pGlxDraw);
- return BadAlloc;
- }
-
- /* Add the glx drawable under the XID of the underlying X drawable
- * too. That way we'll get a callback in DrawableGone and can
- * clean up properly when the drawable is destroyed. */
- if (drawableId != glxDrawableId &&
- !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
- pGlxDraw->destroy (pGlxDraw);
- return BadAlloc;
- }
-
- return Success;
-}
-
-static int
-DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config,
- XID drawableId, XID glxDrawableId)
-{
- DrawablePtr pDraw;
- int err;
-
- LEGAL_NEW_RESOURCE(glxDrawableId, client);
-
- err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess);
- if (err != Success) {
- client->errorValue = drawableId;
- return err;
- }
- if (pDraw->type != DRAWABLE_PIXMAP) {
- client->errorValue = drawableId;
- return BadPixmap;
- }
-
- err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
- glxDrawableId, GLX_DRAWABLE_PIXMAP);
-
- return err;
-}
-
-static void
-determineTextureTarget(ClientPtr client, XID glxDrawableID,
- CARD32 *attribs, CARD32 numAttribs)
-{
- GLenum target = 0;
- GLenum format = 0;
- int i, err;
- __GLXdrawable *pGlxDraw;
-
- if (!validGlxDrawable(client, glxDrawableID, GLX_DRAWABLE_PIXMAP,
- DixWriteAccess, &pGlxDraw, &err))
- /* We just added it in CreatePixmap, so we should never get here. */
- return;
-
- for (i = 0; i < numAttribs; i++) {
- if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
- switch (attribs[2 * i + 1]) {
- case GLX_TEXTURE_2D_EXT:
- target = GL_TEXTURE_2D;
- break;
- case GLX_TEXTURE_RECTANGLE_EXT:
- target = GL_TEXTURE_RECTANGLE_ARB;
- break;
- }
- }
-
- if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
- format = attribs[2 * i + 1];
- }
-
- if (!target) {
- int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height;
-
- if (h & (h - 1) || w & (w - 1))
- target = GL_TEXTURE_RECTANGLE_ARB;
- else
- target = GL_TEXTURE_2D;
- }
-
- pGlxDraw->target = target;
- pGlxDraw->format = format;
-}
-
-int __glXDisp_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
- return err;
-
- return DoCreateGLXPixmap(cl->client, pGlxScreen, config,
- req->pixmap, req->glxpixmap);
-}
-
-int __glXDisp_CreatePixmap(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_AT_LEAST_SIZE(xGLXCreatePixmapReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- err = DoCreateGLXPixmap(cl->client, pGlxScreen, config,
- req->pixmap, req->glxpixmap);
- if (err != Success)
- return err;
-
- determineTextureTarget(cl->client, req->glxpixmap,
- (CARD32*) (req + 1), req->numAttribs);
-
- return Success;
-}
-
-int __glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateGLXPixmapWithConfigSGIXReq *req =
- (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- return DoCreateGLXPixmap(cl->client, pGlxScreen,
- config, req->pixmap, req->glxpixmap);
-}
-
-
-static int DoDestroyDrawable(__GLXclientState *cl, XID glxdrawable, int type)
-{
- __GLXdrawable *pGlxDraw;
- int err;
-
- if (!validGlxDrawable(cl->client, glxdrawable, type,
- DixDestroyAccess, &pGlxDraw, &err))
- return err;
-
- FreeResource(glxdrawable, FALSE);
-
- return Success;
-}
-
-int __glXDisp_DestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq);
-
- return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
-}
-
-int __glXDisp_DestroyPixmap(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc;
-
- /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set
- * length to 3 instead of 2 */
- REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq);
-
- return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
-}
-
-static int
-DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
- int width, int height, XID glxDrawableId)
-{
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- PixmapPtr pPixmap;
- int err;
-
- LEGAL_NEW_RESOURCE(glxDrawableId, client);
-
- if (!validGlxScreen(client, screenNum, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err))
- return err;
-
- __glXenterServer(GL_FALSE);
- pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen,
- width, height, config->rgbBits, 0);
- __glXleaveServer(GL_FALSE);
-
- /* Assign the pixmap the same id as the pbuffer and add it as a
- * resource so it and the DRI2 drawable will be reclaimed when the
- * pbuffer is destroyed. */
- pPixmap->drawable.id = glxDrawableId;
- if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap))
- return BadAlloc;
-
- return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
- glxDrawableId, glxDrawableId,
- GLX_DRAWABLE_PBUFFER);
-}
-
-int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc;
- CARD32 *attrs;
- int width, height, i;
-
- REQUEST_AT_LEAST_SIZE(xGLXCreatePbufferReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3);
-
- attrs = (CARD32 *) (req + 1);
- width = 0;
- height = 0;
-
- for (i = 0; i < req->numAttribs; i++) {
- switch (attrs[i * 2]) {
- case GLX_PBUFFER_WIDTH:
- width = attrs[i * 2 + 1];
- break;
- case GLX_PBUFFER_HEIGHT:
- height = attrs[i * 2 + 1];
- break;
- case GLX_LARGEST_PBUFFER:
- case GLX_PRESERVED_CONTENTS:
- /* FIXME: huh... */
- break;
- }
- }
-
- return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
- width, height, req->pbuffer);
-}
-
-int __glXDisp_CreateGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc;
-
- REQUEST_AT_LEAST_SIZE(xGLXCreateGLXPbufferSGIXReq);
-
- return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
- req->width, req->height, req->pbuffer);
-}
-
-int __glXDisp_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq);
-
- return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
-}
-
-int __glXDisp_DestroyGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq);
-
- return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
-}
-
-static int
-DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable,
- int numAttribs, CARD32 *attribs)
-{
- __GLXdrawable *pGlxDraw;
- int i, err;
-
- if (!validGlxDrawable(client, glxdrawable, GLX_DRAWABLE_ANY,
- DixSetAttrAccess, &pGlxDraw, &err))
- return err;
-
- for (i = 0; i < numAttribs; i++) {
- switch(attribs[i * 2]) {
- case GLX_EVENT_MASK:
- /* All we do is to record the event mask so we can send it
- * back when queried. We never actually clobber the
- * pbuffers, so we never need to send out the event. */
- pGlxDraw->eventMask = attribs[i * 2 + 1];
- break;
- }
- }
-
- return Success;
-}
-
-int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXChangeDrawableAttributesReq *req =
- (xGLXChangeDrawableAttributesReq *) pc;
-
- REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
-#if 0
- /* mesa sends an additional 8 bytes */
- REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
-#else
- if (((sizeof(xGLXChangeDrawableAttributesReq) + (req->numAttribs << 3)) >> 2) < client->req_len)
- return BadLength;
-#endif
-
- return DoChangeDrawableAttributes(cl->client, req->drawable,
- req->numAttribs, (CARD32 *) (req + 1));
-}
-
-int __glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXChangeDrawableAttributesSGIXReq *req =
- (xGLXChangeDrawableAttributesSGIXReq *)pc;
-
- REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesSGIXReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq, req->numAttribs << 3);
-
- return DoChangeDrawableAttributes(cl->client, req->drawable,
- req->numAttribs, (CARD32 *) (req + 1));
-}
-
-int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- ClientPtr client = cl->client;
- DrawablePtr pDraw;
- int err;
-
- REQUEST_AT_LEAST_SIZE(xGLXCreateWindowReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3);
-
- LEGAL_NEW_RESOURCE(req->glxwindow, client);
-
- if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- err = dixLookupDrawable(&pDraw, req->window, client, 0, DixAddAccess);
- if (err != Success || pDraw->type != DRAWABLE_WINDOW) {
- client->errorValue = req->window;
- return BadWindow;
- }
-
- if (!validGlxFBConfigForWindow(client, config, pDraw, &err))
- return err;
-
- return DoCreateGLXDrawable(client, pGlxScreen, config,
- pDraw, req->window,
- req->glxwindow, GLX_DRAWABLE_WINDOW);
-}
-
-int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc;
-
- /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */
- REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
-
- return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW);
-}
-
-
-/*****************************************************************************/
-
-/*
-** NOTE: There is no portable implementation for swap buffers as of
-** this time that is of value. Consequently, this code must be
-** implemented by somebody other than SGI.
-*/
-int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc;
- GLXContextTag tag;
- XID drawId;
- __GLXcontext *glxc = NULL;
- __GLXdrawable *pGlxDraw;
- int error;
-
- REQUEST_SIZE_MATCH(xGLXSwapBuffersReq);
-
- tag = req->contextTag;
- drawId = req->drawable;
- if (tag) {
- glxc = __glXLookupContextByTag(cl, tag);
- if (!glxc) {
- return __glXError(GLXBadContextTag);
- }
- /*
- ** The calling thread is swapping its current drawable. In this case,
- ** glxSwapBuffers is in both GL and X streams, in terms of
- ** sequentiality.
- */
- if (__glXForceCurrent(cl, tag, &error)) {
- /*
- ** Do whatever is needed to make sure that all preceding requests
- ** in both streams are completed before the swap is executed.
- */
- CALL_Finish( GET_DISPATCH(), () );
- glxc->hasUnflushedCommands = GL_FALSE;
- } else {
- return error;
- }
- }
-
- pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
- if (pGlxDraw == NULL)
- return error;
-
- if (pGlxDraw->type == DRAWABLE_WINDOW &&
- (*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE)
- return __glXError(GLXBadDrawable);
-
- return Success;
-}
-
-
-static int
-DoQueryContext(__GLXclientState *cl, GLXContextID gcId)
-{
- ClientPtr client = cl->client;
- __GLXcontext *ctx;
- xGLXQueryContextInfoEXTReply reply;
- int nProps;
- int *sendBuf, *pSendBuf;
- int nReplyBytes;
- int err;
-
- if (!validGlxContext(cl->client, gcId, DixReadAccess, &ctx, &err))
- return err;
-
- nProps = 3;
- reply.length = nProps << 1;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.n = nProps;
-
- nReplyBytes = reply.length << 2;
- sendBuf = (int *)malloc((size_t)nReplyBytes);
- if (sendBuf == NULL) {
- return __glXError(GLXBadContext); /* XXX: Is this correct? */
- }
- pSendBuf = sendBuf;
- *pSendBuf++ = GLX_SHARE_CONTEXT_EXT;
- *pSendBuf++ = (int)(ctx->share_id);
- *pSendBuf++ = GLX_VISUAL_ID_EXT;
- *pSendBuf++ = (int)(ctx->config->visualID);
- *pSendBuf++ = GLX_SCREEN_EXT;
- *pSendBuf++ = (int)(ctx->pGlxScreen->pScreen->myNum);
-
- if (client->swapped) {
- __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf);
- } else {
- WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, (char *)&reply);
- WriteToClient(client, nReplyBytes, (char *)sendBuf);
- }
- free((char *)sendBuf);
-
- return Success;
-}
-
-int __glXDisp_QueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq);
-
- return DoQueryContext(cl, req->context);
-}
-
-int __glXDisp_QueryContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXQueryContextReq);
-
- return DoQueryContext(cl, req->context);
-}
-
-int __glXDisp_BindTexImageEXT(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- ClientPtr client = cl->client;
- __GLXcontext *context;
- __GLXdrawable *pGlxDraw;
- GLXDrawable drawId;
- int buffer;
- int error;
- CARD32 num_attribs;
-
- if ((sizeof(xGLXVendorPrivateReq) + 12) >> 2 > client->req_len)
- return BadLength;
-
- pc += __GLX_VENDPRIV_HDR_SIZE;
-
- drawId = *((CARD32 *) (pc));
- buffer = *((INT32 *) (pc + 4));
- num_attribs = *((CARD32 *) (pc + 8));
- if (num_attribs > (UINT32_MAX >> 3)) {
- client->errorValue = num_attribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 12 + (num_attribs << 3));
-
- if (buffer != GLX_FRONT_LEFT_EXT)
- return __glXError(GLXBadPixmap);
-
- context = __glXForceCurrent (cl, req->contextTag, &error);
- if (!context)
- return error;
-
- if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
- DixReadAccess, &pGlxDraw, &error))
- return error;
-
- if (!context->textureFromPixmap)
- return __glXError(GLXUnsupportedPrivateRequest);
-
- return context->textureFromPixmap->bindTexImage(context,
- buffer,
- pGlxDraw);
-}
-
-int __glXDisp_ReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- ClientPtr client = cl->client;
- __GLXdrawable *pGlxDraw;
- __GLXcontext *context;
- GLXDrawable drawId;
- int buffer;
- int error;
-
- REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8);
-
- pc += __GLX_VENDPRIV_HDR_SIZE;
-
- drawId = *((CARD32 *) (pc));
- buffer = *((INT32 *) (pc + 4));
-
- context = __glXForceCurrent (cl, req->contextTag, &error);
- if (!context)
- return error;
-
- if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
- DixReadAccess, &pGlxDraw, &error))
- return error;
-
- if (!context->textureFromPixmap)
- return __glXError(GLXUnsupportedPrivateRequest);
-
- return context->textureFromPixmap->releaseTexImage(context,
- buffer,
- pGlxDraw);
-}
-
-int __glXDisp_CopySubBufferMESA(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- GLXContextTag tag = req->contextTag;
- __GLXcontext *glxc = NULL;
- __GLXdrawable *pGlxDraw;
- ClientPtr client = cl->client;
- GLXDrawable drawId;
- int error;
- int x, y, width, height;
-
- (void) client;
- (void) req;
-
- REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20);
-
- pc += __GLX_VENDPRIV_HDR_SIZE;
-
- drawId = *((CARD32 *) (pc));
- x = *((INT32 *) (pc + 4));
- y = *((INT32 *) (pc + 8));
- width = *((INT32 *) (pc + 12));
- height = *((INT32 *) (pc + 16));
-
- if (tag) {
- glxc = __glXLookupContextByTag(cl, tag);
- if (!glxc) {
- return __glXError(GLXBadContextTag);
- }
- /*
- ** The calling thread is swapping its current drawable. In this case,
- ** glxSwapBuffers is in both GL and X streams, in terms of
- ** sequentiality.
- */
- if (__glXForceCurrent(cl, tag, &error)) {
- /*
- ** Do whatever is needed to make sure that all preceding requests
- ** in both streams are completed before the swap is executed.
- */
- CALL_Finish( GET_DISPATCH(), () );
- glxc->hasUnflushedCommands = GL_FALSE;
- } else {
- return error;
- }
- }
-
- pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
- if (!pGlxDraw)
- return error;
-
- if (pGlxDraw == NULL ||
- pGlxDraw->type != GLX_DRAWABLE_WINDOW ||
- pGlxDraw->copySubBuffer == NULL)
- return __glXError(GLXBadDrawable);
-
- (*pGlxDraw->copySubBuffer)(pGlxDraw, x, y, width, height);
-
- return Success;
-}
-
-/*
-** Get drawable attributes
-*/
-static int
-DoGetDrawableAttributes(__GLXclientState *cl, XID drawId)
-{
- ClientPtr client = cl->client;
- xGLXGetDrawableAttributesReply reply;
- __GLXdrawable *pGlxDraw;
- CARD32 attributes[6];
- int numAttribs, error;
-
- if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
- DixGetAttrAccess, &pGlxDraw, &error))
- return error;
-
- numAttribs = 3;
- reply.length = numAttribs << 1;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.numAttribs = numAttribs;
-
- attributes[0] = GLX_TEXTURE_TARGET_EXT;
- attributes[1] = pGlxDraw->target == GL_TEXTURE_2D ? GLX_TEXTURE_2D_EXT :
- GLX_TEXTURE_RECTANGLE_EXT;
- attributes[2] = GLX_Y_INVERTED_EXT;
- attributes[3] = GL_FALSE;
- attributes[4] = GLX_EVENT_MASK;
- attributes[5] = pGlxDraw->eventMask;
-
- if (client->swapped) {
- __glXSwapGetDrawableAttributesReply(client, &reply, attributes);
- } else {
- WriteToClient(client, sz_xGLXGetDrawableAttributesReply,
- (char *)&reply);
- WriteToClient(client, reply.length * sizeof (CARD32),
- (char *)attributes);
- }
-
- return Success;
-}
-
-int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc;
-
- /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */
- REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
-
- return DoGetDrawableAttributes(cl, req->drawable);
-}
-
-int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXGetDrawableAttributesSGIXReq *req =
- (xGLXGetDrawableAttributesSGIXReq *)pc;
-
- REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq);
-
- return DoGetDrawableAttributes(cl, req->drawable);
-}
-
-/************************************************************************/
-
-/*
-** Render and Renderlarge are not in the GLX API. They are used by the GLX
-** client library to send batches of GL rendering commands.
-*/
-
-/*
-** Execute all the drawing commands in a request.
-*/
-int __glXDisp_Render(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXRenderReq *req;
- ClientPtr client= cl->client;
- int left, cmdlen, error;
- int commandsDone;
- CARD16 opcode;
- __GLXrenderHeader *hdr;
- __GLXcontext *glxc;
- __GLX_DECLARE_SWAP_VARIABLES;
-
- REQUEST_AT_LEAST_SIZE(xGLXRenderReq);
-
- req = (xGLXRenderReq *) pc;
- if (client->swapped) {
- __GLX_SWAP_SHORT(&req->length);
- __GLX_SWAP_INT(&req->contextTag);
- }
-
- glxc = __glXForceCurrent(cl, req->contextTag, &error);
- if (!glxc) {
- return error;
- }
-
- commandsDone = 0;
- pc += sz_xGLXRenderReq;
- left = (req->length << 2) - sz_xGLXRenderReq;
- while (left > 0) {
- __GLXrenderSizeData entry;
- int extra;
- __GLXdispatchRenderProcPtr proc;
- int err;
-
- if (left < sizeof(__GLXrenderHeader))
- return BadLength;
-
- /*
- ** Verify that the header length and the overall length agree.
- ** Also, each command must be word aligned.
- */
- hdr = (__GLXrenderHeader *) pc;
- if (client->swapped) {
- __GLX_SWAP_SHORT(&hdr->length);
- __GLX_SWAP_SHORT(&hdr->opcode);
- }
- cmdlen = hdr->length;
- opcode = hdr->opcode;
-
- /*
- ** Check for core opcodes and grab entry data.
- */
- err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry);
- proc = (__GLXdispatchRenderProcPtr)
- __glXGetProtocolDecodeFunction(& Render_dispatch_info,
- opcode, client->swapped);
-
- if ((err < 0) || (proc == NULL)) {
- client->errorValue = commandsDone;
- return __glXError(GLXBadRenderRequest);
- }
-
- if (entry.varsize) {
- /* variable size command */
- extra = (*entry.varsize)(pc + __GLX_RENDER_HDR_SIZE,
- client->swapped);
- if (extra < 0) {
- extra = 0;
- }
- if (cmdlen != __GLX_PAD(entry.bytes + extra)) {
- return BadLength;
- }
- } else {
- /* constant size command */
- if (cmdlen != __GLX_PAD(entry.bytes)) {
- return BadLength;
- }
- }
- if (left < cmdlen) {
- return BadLength;
- }
-
- /*
- ** Skip over the header and execute the command. We allow the
- ** caller to trash the command memory. This is useful especially
- ** for things that require double alignment - they can just shift
- ** the data towards lower memory (trashing the header) by 4 bytes
- ** and achieve the required alignment.
- */
- (*proc)(pc + __GLX_RENDER_HDR_SIZE);
- pc += cmdlen;
- left -= cmdlen;
- commandsDone++;
- }
- glxc->hasUnflushedCommands = GL_TRUE;
- return Success;
-}
-
-
-/*
-** Execute a large rendering request (one that spans multiple X requests).
-*/
-int __glXDisp_RenderLarge(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXRenderLargeReq *req;
- ClientPtr client= cl->client;
- size_t dataBytes;
- __GLXrenderLargeHeader *hdr;
- __GLXcontext *glxc;
- int error;
- CARD16 opcode;
- __GLX_DECLARE_SWAP_VARIABLES;
-
- req = (xGLXRenderLargeReq *) pc;
- if (client->swapped) {
- __GLX_SWAP_SHORT(&req->length);
- __GLX_SWAP_INT(&req->contextTag);
- __GLX_SWAP_INT(&req->dataBytes);
- __GLX_SWAP_SHORT(&req->requestNumber);
- __GLX_SWAP_SHORT(&req->requestTotal);
- }
-
- glxc = __glXForceCurrent(cl, req->contextTag, &error);
- if (!glxc) {
- /* Reset in case this isn't 1st request. */
- __glXResetLargeCommandStatus(cl);
- return error;
- }
- dataBytes = req->dataBytes;
-
- /*
- ** Check the request length.
- */
- if ((req->length << 2) != __GLX_PAD(dataBytes) + sz_xGLXRenderLargeReq) {
- client->errorValue = req->length;
- /* Reset in case this isn't 1st request. */
- __glXResetLargeCommandStatus(cl);
- return BadLength;
- }
- pc += sz_xGLXRenderLargeReq;
-
- if (cl->largeCmdRequestsSoFar == 0) {
- __GLXrenderSizeData entry;
- int extra;
- size_t cmdlen;
- int err;
-
- /*
- ** This is the first request of a multi request command.
- ** Make enough space in the buffer, then copy the entire request.
- */
- if (req->requestNumber != 1) {
- client->errorValue = req->requestNumber;
- return __glXError(GLXBadLargeRequest);
- }
-
- hdr = (__GLXrenderLargeHeader *) pc;
- if (client->swapped) {
- __GLX_SWAP_INT(&hdr->length);
- __GLX_SWAP_INT(&hdr->opcode);
- }
- cmdlen = hdr->length;
- opcode = hdr->opcode;
-
- /*
- ** Check for core opcodes and grab entry data.
- */
- err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry);
- if (err < 0) {
- client->errorValue = opcode;
- return __glXError(GLXBadLargeRequest);
- }
-
- if (entry.varsize) {
- /*
- ** If it's a variable-size command (a command whose length must
- ** be computed from its parameters), all the parameters needed
- ** will be in the 1st request, so it's okay to do this.
- */
- extra = (*entry.varsize)(pc + __GLX_RENDER_LARGE_HDR_SIZE,
- client->swapped);
- if (extra < 0) {
- extra = 0;
- }
- /* large command's header is 4 bytes longer, so add 4 */
- if (cmdlen != __GLX_PAD(entry.bytes + 4 + extra)) {
- return BadLength;
- }
- } else {
- /* constant size command */
- if (cmdlen != __GLX_PAD(entry.bytes + 4)) {
- return BadLength;
- }
- }
- /*
- ** Make enough space in the buffer, then copy the entire request.
- */
- if (cl->largeCmdBufSize < cmdlen) {
- if (!cl->largeCmdBuf) {
- cl->largeCmdBuf = (GLbyte *) malloc(cmdlen);
- } else {
- cl->largeCmdBuf = (GLbyte *) realloc(cl->largeCmdBuf, cmdlen);
- }
- if (!cl->largeCmdBuf) {
- return BadAlloc;
- }
- cl->largeCmdBufSize = cmdlen;
- }
- memcpy(cl->largeCmdBuf, pc, dataBytes);
-
- cl->largeCmdBytesSoFar = dataBytes;
- cl->largeCmdBytesTotal = cmdlen;
- cl->largeCmdRequestsSoFar = 1;
- cl->largeCmdRequestsTotal = req->requestTotal;
- return Success;
-
- } else {
- /*
- ** We are receiving subsequent (i.e. not the first) requests of a
- ** multi request command.
- */
-
- /*
- ** Check the request number and the total request count.
- */
- if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) {
- client->errorValue = req->requestNumber;
- __glXResetLargeCommandStatus(cl);
- return __glXError(GLXBadLargeRequest);
- }
- if (req->requestTotal != cl->largeCmdRequestsTotal) {
- client->errorValue = req->requestTotal;
- __glXResetLargeCommandStatus(cl);
- return __glXError(GLXBadLargeRequest);
- }
-
- /*
- ** Check that we didn't get too much data.
- */
- if ((cl->largeCmdBytesSoFar + dataBytes) > cl->largeCmdBytesTotal) {
- client->errorValue = dataBytes;
- __glXResetLargeCommandStatus(cl);
- return __glXError(GLXBadLargeRequest);
- }
- memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes);
- cl->largeCmdBytesSoFar += dataBytes;
- cl->largeCmdRequestsSoFar++;
-
- if (req->requestNumber == cl->largeCmdRequestsTotal) {
- __GLXdispatchRenderProcPtr proc;
-
- /*
- ** This is the last request; it must have enough bytes to complete
- ** the command.
- */
- /* NOTE: the two pad macros have been added below; they are needed
- ** because the client library pads the total byte count, but not
- ** the per-request byte counts. The Protocol Encoding says the
- ** total byte count should not be padded, so a proposal will be
- ** made to the ARB to relax the padding constraint on the total
- ** byte count, thus preserving backward compatibility. Meanwhile,
- ** the padding done below fixes a bug that did not allow
- ** large commands of odd sizes to be accepted by the server.
- */
- if (__GLX_PAD(cl->largeCmdBytesSoFar) !=
- __GLX_PAD(cl->largeCmdBytesTotal)) {
- client->errorValue = dataBytes;
- __glXResetLargeCommandStatus(cl);
- return __glXError(GLXBadLargeRequest);
- }
- hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf;
- /*
- ** The opcode and length field in the header had already been
- ** swapped when the first request was received.
- **
- ** Use the opcode to index into the procedure table.
- */
- opcode = hdr->opcode;
-
- proc = (__GLXdispatchRenderProcPtr)
- __glXGetProtocolDecodeFunction(& Render_dispatch_info, opcode,
- client->swapped);
- if (proc == NULL) {
- client->errorValue = opcode;
- return __glXError(GLXBadLargeRequest);
- }
-
- /*
- ** Skip over the header and execute the command.
- */
- (*proc)(cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE);
- glxc->hasUnflushedCommands = GL_TRUE;
-
- /*
- ** Reset for the next RenderLarge series.
- */
- __glXResetLargeCommandStatus(cl);
- } else {
- /*
- ** This is neither the first nor the last request.
- */
- }
- return Success;
- }
-}
-
-/************************************************************************/
-
-/*
-** No support is provided for the vendor-private requests other than
-** allocating the entry points in the dispatch table.
-*/
-
-int __glXDisp_VendorPrivate(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- GLint vendorcode = req->vendorCode;
- __GLXdispatchVendorPrivProcPtr proc;
-
- REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
-
- proc = (__GLXdispatchVendorPrivProcPtr)
- __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info,
- vendorcode, 0);
- if (proc != NULL) {
- (*proc)(cl, (GLbyte*)req);
- return Success;
- }
-
- cl->client->errorValue = req->vendorCode;
- return __glXError(GLXUnsupportedPrivateRequest);
-}
-
-int __glXDisp_VendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- GLint vendorcode = req->vendorCode;
- __GLXdispatchVendorPrivProcPtr proc;
-
- REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
-
- proc = (__GLXdispatchVendorPrivProcPtr)
- __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info,
- vendorcode, 0);
- if (proc != NULL) {
- return (*proc)(cl, (GLbyte*)req);
- }
-
- cl->client->errorValue = vendorcode;
- return __glXError(GLXUnsupportedPrivateRequest);
-}
-
-int __glXDisp_QueryExtensionsString(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc;
- xGLXQueryExtensionsStringReply reply;
- __GLXscreen *pGlxScreen;
- size_t n, length;
- char *buf;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXQueryExtensionsStringReq);
-
- if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
- return err;
-
- n = strlen(pGlxScreen->GLXextensions) + 1;
- length = __GLX_PAD(n) >> 2;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.length = length;
- reply.n = n;
-
- /* Allocate buffer to make sure it's a multiple of 4 bytes big.*/
- buf = (char *) malloc(length << 2);
- if (buf == NULL)
- return BadAlloc;
- memcpy(buf, pGlxScreen->GLXextensions, n);
-
- if (client->swapped) {
- glxSwapQueryExtensionsStringReply(client, &reply, buf);
- } else {
- WriteToClient(client, sz_xGLXQueryExtensionsStringReply,(char *)&reply);
- WriteToClient(client, (int)(length << 2), (char *)buf);
- }
-
- free(buf);
- return Success;
-}
-
-int __glXDisp_QueryServerString(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc;
- xGLXQueryServerStringReply reply;
- size_t n, length;
- const char *ptr;
- char *buf;
- __GLXscreen *pGlxScreen;
- int err;
- char ver_str[16];
-
- REQUEST_SIZE_MATCH(xGLXQueryServerStringReq);
-
- if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
- return err;
-
- switch(req->name) {
- case GLX_VENDOR:
- ptr = pGlxScreen->GLXvendor;
- break;
- case GLX_VERSION:
- /* Return to the server version rather than the screen version
- * to prevent confusion when they do not match.
- */
- snprintf(ver_str, 16, "%d.%d", glxMajorVersion, glxMinorVersion);
- ptr = ver_str;
- break;
- case GLX_EXTENSIONS:
- ptr = pGlxScreen->GLXextensions;
- break;
- default:
- return BadValue;
- }
-
- n = strlen(ptr) + 1;
- length = __GLX_PAD(n) >> 2;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.length = length;
- reply.n = n;
-
- buf = (char *) malloc(length << 2);
- if (buf == NULL) {
- return BadAlloc;
- }
- memcpy(buf, ptr, n);
-
- if (client->swapped) {
- glxSwapQueryServerStringReply(client, &reply, buf);
- } else {
- WriteToClient(client, sz_xGLXQueryServerStringReply, (char *)&reply);
- WriteToClient(client, (int)(length << 2), buf);
- }
-
- free(buf);
- return Success;
-}
-
-int __glXDisp_ClientInfo(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc;
- const char *buf;
-
- REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq);
-
- buf = (const char *)(req+1);
- if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq)))
- return BadLength;
-
- cl->GLClientmajorVersion = req->major;
- cl->GLClientminorVersion = req->minor;
- free(cl->GLClientextensions);
- cl->GLClientextensions = strdup(buf);
-
- return Success;
-}
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include "glxserver.h"
+#include <GL/glxtokens.h>
+#include <unpack.h>
+#include <pixmapstr.h>
+#include <windowstr.h>
+#include "glxutil.h"
+#include "glxext.h"
+#include "glapitable.h"
+#include "glapi.h"
+#include "glthread.h"
+#include "dispatch.h"
+#include "indirect_dispatch.h"
+#include "indirect_table.h"
+#include "indirect_util.h"
+
+static int
+validGlxScreen(ClientPtr client, int screen, __GLXscreen **pGlxScreen, int *err)
+{
+ /*
+ ** Check if screen exists.
+ */
+ if (screen < 0 || screen >= screenInfo.numScreens) {
+ client->errorValue = screen;
+ *err = BadValue;
+ return FALSE;
+ }
+ *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
+
+ return TRUE;
+}
+
+static int
+validGlxFBConfig(ClientPtr client, __GLXscreen *pGlxScreen, XID id,
+ __GLXconfig **config, int *err)
+{
+ __GLXconfig *m;
+
+ for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next)
+ if (m->fbconfigID == id) {
+ *config = m;
+ return TRUE;
+ }
+
+ client->errorValue = id;
+ *err = __glXError(GLXBadFBConfig);
+
+ return FALSE;
+}
+
+static int
+validGlxVisual(ClientPtr client, __GLXscreen *pGlxScreen, XID id,
+ __GLXconfig **config, int *err)
+{
+ int i;
+
+ for (i = 0; i < pGlxScreen->numVisuals; i++)
+ if (pGlxScreen->visuals[i]->visualID == id) {
+ *config = pGlxScreen->visuals[i];
+ return TRUE;
+ }
+
+ client->errorValue = id;
+ *err = BadValue;
+
+ return FALSE;
+}
+
+static int
+validGlxFBConfigForWindow(ClientPtr client, __GLXconfig *config,
+ DrawablePtr pDraw, int *err)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ VisualPtr pVisual = NULL;
+ XID vid;
+ int i;
+
+ vid = wVisual((WindowPtr)pDraw);
+ for (i = 0; i < pScreen->numVisuals; i++) {
+ if (pScreen->visuals[i].vid == vid) {
+ pVisual = &pScreen->visuals[i];
+ break;
+ }
+ }
+
+ /* FIXME: What exactly should we check here... */
+ if (pVisual->class != glxConvertToXVisualType(config->visualType) ||
+ !(config->drawableType & GLX_WINDOW_BIT)) {
+ client->errorValue = pDraw->id;
+ *err = BadMatch;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int
+validGlxContext(ClientPtr client, XID id, int access_mode,
+ __GLXcontext **context, int *err)
+{
+ *err = dixLookupResourceByType((pointer *) context, id,
+ __glXContextRes, client, access_mode);
+ if (*err != Success || (*context)->idExists == GL_FALSE) {
+ client->errorValue = id;
+ if (*err == BadValue || *err == Success)
+ *err = __glXError(GLXBadContext);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int
+validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
+ __GLXdrawable **drawable, int *err)
+{
+ int rc;
+
+ rc = dixLookupResourceByType((pointer *) drawable, id,
+ __glXDrawableRes, client, access_mode);
+ if (rc != Success && rc != BadValue) {
+ *err = rc;
+ client->errorValue = id;
+ return FALSE;
+ }
+
+ /* If the ID of the glx drawable we looked up doesn't match the id
+ * we looked for, it's because we looked it up under the X
+ * drawable ID (see DoCreateGLXDrawable). */
+ if (rc == BadValue ||
+ (*drawable)->drawId != id ||
+ (type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) {
+ client->errorValue = id;
+ switch (type) {
+ case GLX_DRAWABLE_WINDOW:
+ *err = __glXError(GLXBadWindow);
+ return FALSE;
+ case GLX_DRAWABLE_PIXMAP:
+ *err = __glXError(GLXBadPixmap);
+ return FALSE;
+ case GLX_DRAWABLE_PBUFFER:
+ *err = __glXError(GLXBadPbuffer);
+ return FALSE;
+ case GLX_DRAWABLE_ANY:
+ *err = __glXError(GLXBadDrawable);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+void
+__glXContextDestroy(__GLXcontext *context)
+{
+ __glXFlushContextCache();
+}
+
+static void __glXdirectContextDestroy(__GLXcontext *context)
+{
+ __glXContextDestroy(context);
+ free(context);
+}
+
+static __GLXcontext *__glXdirectContextCreate(__GLXscreen *screen,
+ __GLXconfig *modes,
+ __GLXcontext *shareContext)
+{
+ __GLXcontext *context;
+
+ context = calloc(1, sizeof (__GLXcontext));
+ if (context == NULL)
+ return NULL;
+
+ context->destroy = __glXdirectContextDestroy;
+
+ return context;
+}
+
+/**
+ * Create a GL context with the given properties. This routine is used
+ * to implement \c glXCreateContext, \c glXCreateNewContext, and
+ * \c glXCreateContextWithConfigSGIX. This works becuase of the hack way
+ * that GLXFBConfigs are implemented. Basically, the FBConfigID is the
+ * same as the VisualID.
+ */
+
+static int
+DoCreateContext(__GLXclientState *cl, GLXContextID gcId,
+ GLXContextID shareList, __GLXconfig *config,
+ __GLXscreen *pGlxScreen, GLboolean isDirect)
+{
+ ClientPtr client = cl->client;
+ __GLXcontext *glxc, *shareglxc;
+ int err;
+
+ LEGAL_NEW_RESOURCE(gcId, client);
+
+ /*
+ ** Find the display list space that we want to share.
+ **
+ ** NOTE: In a multithreaded X server, we would need to keep a reference
+ ** count for each display list so that if one client detroyed a list that
+ ** another client was using, the list would not really be freed until it
+ ** was no longer in use. Since this sample implementation has no support
+ ** for multithreaded servers, we don't do this.
+ */
+ if (shareList == None) {
+ shareglxc = 0;
+ } else {
+ if (!validGlxContext(client, shareList, DixReadAccess,
+ &shareglxc, &err))
+ return err;
+
+ if (shareglxc->isDirect) {
+ /*
+ ** NOTE: no support for sharing display lists between direct
+ ** contexts, even if they are in the same address space.
+ */
+#if 0
+ /* Disabling this code seems to allow shared display lists
+ * and texture objects to work. We'll leave it disabled for now.
+ */
+ client->errorValue = shareList;
+ return BadMatch;
+#endif
+ } else {
+ /*
+ ** Create an indirect context regardless of what the client asked
+ ** for; this way we can share display list space with shareList.
+ */
+ isDirect = GL_FALSE;
+ }
+ }
+
+ /*
+ ** Allocate memory for the new context
+ */
+ if (!isDirect)
+ glxc = pGlxScreen->createContext(pGlxScreen, config, shareglxc);
+ else
+ glxc = __glXdirectContextCreate(pGlxScreen, config, shareglxc);
+ if (!glxc) {
+ return BadAlloc;
+ }
+
+ /*
+ ** Initially, setup the part of the context that could be used by
+ ** a GL core that needs windowing information (e.g., Mesa).
+ */
+ glxc->pGlxScreen = pGlxScreen;
+ glxc->config = config;
+
+ /*
+ ** Register this context as a resource.
+ */
+ if (!AddResource(gcId, __glXContextRes, (pointer)glxc)) {
+ (*glxc->destroy)(glxc);
+ client->errorValue = gcId;
+ return BadAlloc;
+ }
+
+ /*
+ ** Finally, now that everything is working, setup the rest of the
+ ** context.
+ */
+ glxc->id = gcId;
+ glxc->share_id = shareList;
+ glxc->idExists = GL_TRUE;
+ glxc->isCurrent = GL_FALSE;
+ glxc->isDirect = isDirect;
+ glxc->renderMode = GL_RENDER;
+
+ __glXAddToContextList(glxc);
+
+ return Success;
+}
+
+int __glXDisp_CreateContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateContextReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
+ return err;
+
+ return DoCreateContext(cl, req->context, req->shareList,
+ config, pGlxScreen, req->isDirect);
+}
+
+int __glXDisp_CreateNewContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateNewContextReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ return DoCreateContext(cl, req->context, req->shareList,
+ config, pGlxScreen, req->isDirect);
+}
+
+int __glXDisp_CreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateContextWithConfigSGIXReq *req =
+ (xGLXCreateContextWithConfigSGIXReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateContextWithConfigSGIXReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ return DoCreateContext(cl, req->context, req->shareList,
+ config, pGlxScreen, req->isDirect);
+}
+
+int __glXDisp_DestroyContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc;
+ __GLXcontext *glxc;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXDestroyContextReq);
+
+ if (!validGlxContext(cl->client, req->context, DixDestroyAccess,
+ &glxc, &err))
+ return err;
+
+ glxc->idExists = GL_FALSE;
+ if (!glxc->isCurrent)
+ FreeResourceByType(req->context, __glXContextRes, FALSE);
+
+ return Success;
+}
+
+/*
+ * This will return "deleted" contexts, ie, where idExists is GL_FALSE.
+ * Contrast validGlxContext, which will not. We're cheating here and
+ * using the XID as the context tag, which is fine as long as we defer
+ * actually destroying the context until it's no longer referenced, and
+ * block clients from trying to MakeCurrent on contexts that are on the
+ * way to destruction. Notice that DoMakeCurrent calls validGlxContext
+ * for new contexts but __glXLookupContextByTag for previous contexts.
+ */
+__GLXcontext *__glXLookupContextByTag(__GLXclientState *cl, GLXContextTag tag)
+{
+ __GLXcontext *ret;
+
+ if (dixLookupResourceByType((void **)&ret, tag, __glXContextRes,
+ cl->client, DixUseAccess) == Success)
+ return ret;
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static void StopUsingContext(__GLXcontext *glxc)
+{
+ if (glxc) {
+ if (glxc == __glXLastContext) {
+ /* Tell server GL library */
+ __glXLastContext = 0;
+ }
+ glxc->isCurrent = GL_FALSE;
+ if (!glxc->idExists) {
+ FreeResourceByType(glxc->id, __glXContextRes, FALSE);
+ }
+ }
+}
+
+static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc)
+{
+ glxc->isCurrent = GL_TRUE;
+ __glXLastContext = glxc;
+}
+
+/**
+ * This is a helper function to handle the legacy (pre GLX 1.3) cases
+ * where passing an X window to glXMakeCurrent is valid. Given a
+ * resource ID, look up the GLX drawable if available, otherwise, make
+ * sure it's an X window and create a GLX drawable one the fly.
+ */
+static __GLXdrawable *
+__glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client,
+ int *error)
+{
+ DrawablePtr pDraw;
+ __GLXdrawable *pGlxDraw;
+ int rc;
+
+ if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
+ DixWriteAccess, &pGlxDraw, &rc)) {
+ if (glxc != NULL && pGlxDraw->config != glxc->config) {
+ client->errorValue = drawId;
+ *error = BadMatch;
+ return NULL;
+ }
+
+ return pGlxDraw;
+ }
+
+ /* No active context and an unknown drawable, bail. */
+ if (glxc == NULL) {
+ client->errorValue = drawId;
+ *error = BadMatch;
+ return NULL;
+ }
+
+ /* The drawId wasn't a GLX drawable. Make sure it's a window and
+ * create a GLXWindow for it. Check that the drawable screen
+ * matches the context screen and that the context fbconfig is
+ * compatible with the window visual. */
+
+ rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess);
+ if (rc != Success || pDraw->type != DRAWABLE_WINDOW) {
+ client->errorValue = drawId;
+ *error = __glXError(GLXBadDrawable);
+ return NULL;
+ }
+
+ if (pDraw->pScreen != glxc->pGlxScreen->pScreen) {
+ client->errorValue = pDraw->pScreen->myNum;
+ *error = BadMatch;
+ return NULL;
+ }
+
+ if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
+ return NULL;
+
+ pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
+ pDraw, drawId,
+ GLX_DRAWABLE_WINDOW,
+ drawId, glxc->config);
+
+ /* since we are creating the drawablePrivate, drawId should be new */
+ if (!AddResource(drawId, __glXDrawableRes, pGlxDraw)) {
+ pGlxDraw->destroy (pGlxDraw);
+ *error = BadAlloc;
+ return NULL;
+ }
+
+ return pGlxDraw;
+}
+
+/*****************************************************************************/
+/*
+** Make an OpenGL context and drawable current.
+*/
+
+static int
+DoMakeCurrent(__GLXclientState *cl,
+ GLXDrawable drawId, GLXDrawable readId,
+ GLXContextID contextId, GLXContextTag tag)
+{
+ ClientPtr client = cl->client;
+ xGLXMakeCurrentReply reply;
+ __GLXcontext *glxc, *prevglxc;
+ __GLXdrawable *drawPriv = NULL;
+ __GLXdrawable *readPriv = NULL;
+ int error;
+ GLuint mask;
+
+ /*
+ ** If one is None and the other isn't, it's a bad match.
+ */
+
+ mask = (drawId == None) ? (1 << 0) : 0;
+ mask |= (readId == None) ? (1 << 1) : 0;
+ mask |= (contextId == None) ? (1 << 2) : 0;
+
+ if ( (mask != 0x00) && (mask != 0x07) ) {
+ return BadMatch;
+ }
+
+ /*
+ ** Lookup old context. If we have one, it must be in a usable state.
+ */
+ if (tag != 0) {
+ prevglxc = __glXLookupContextByTag(cl, tag);
+ if (!prevglxc) {
+ /*
+ ** Tag for previous context is invalid.
+ */
+ return __glXError(GLXBadContextTag);
+ }
+ if (prevglxc->renderMode != GL_RENDER) {
+ /* Oops. Not in render mode render. */
+ client->errorValue = prevglxc->id;
+ return __glXError(GLXBadContextState);
+ }
+ } else {
+ prevglxc = 0;
+ }
+
+ /*
+ ** Lookup new context. It must not be current for someone else.
+ */
+ if (contextId != None) {
+ int status;
+
+ if (!validGlxContext(client, contextId, DixUseAccess, &glxc, &error))
+ return error;
+ if ((glxc != prevglxc) && glxc->isCurrent) {
+ /* Context is current to somebody else */
+ return BadAccess;
+ }
+
+ assert( drawId != None );
+ assert( readId != None );
+
+ drawPriv = __glXGetDrawable(glxc, drawId, client, &status);
+ if (drawPriv == NULL)
+ return status;
+
+ readPriv = __glXGetDrawable(glxc, readId, client, &status);
+ if (readPriv == NULL)
+ return status;
+
+ } else {
+ /* Switching to no context. Ignore new drawable. */
+ glxc = 0;
+ drawPriv = 0;
+ readPriv = 0;
+ }
+
+
+ if (prevglxc) {
+ /*
+ ** Flush the previous context if needed.
+ */
+ if (prevglxc->hasUnflushedCommands) {
+ if (__glXForceCurrent(cl, tag, (int *)&error)) {
+ CALL_Flush( GET_DISPATCH(), () );
+ prevglxc->hasUnflushedCommands = GL_FALSE;
+ } else {
+ return error;
+ }
+ }
+
+ /*
+ ** Make the previous context not current.
+ */
+ if (!(*prevglxc->loseCurrent)(prevglxc)) {
+ return __glXError(GLXBadContext);
+ }
+ __glXFlushContextCache();
+ if (!prevglxc->isDirect) {
+ prevglxc->drawPriv = NULL;
+ prevglxc->readPriv = NULL;
+ }
+ }
+
+
+ if ((glxc != 0) && !glxc->isDirect) {
+
+ glxc->drawPriv = drawPriv;
+ glxc->readPriv = readPriv;
+
+ /* make the context current */
+ if (!(*glxc->makeCurrent)(glxc)) {
+ glxc->drawPriv = NULL;
+ glxc->readPriv = NULL;
+ return __glXError(GLXBadContext);
+ }
+
+ glxc->isCurrent = GL_TRUE;
+ }
+
+ StopUsingContext(prevglxc);
+
+ if (glxc) {
+ StartUsingContext(cl, glxc);
+ reply.contextTag = glxc->id;
+ } else {
+ reply.contextTag = 0;
+ }
+
+ reply.length = 0;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __glXSwapMakeCurrentReply(client, &reply);
+ } else {
+ WriteToClient(client, sz_xGLXMakeCurrentReply, (char *)&reply);
+ }
+ return Success;
+}
+
+int __glXDisp_MakeCurrent(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXMakeCurrentReq);
+
+ return DoMakeCurrent( cl, req->drawable, req->drawable,
+ req->context, req->oldContextTag );
+}
+
+int __glXDisp_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXMakeContextCurrentReq);
+
+ return DoMakeCurrent( cl, req->drawable, req->readdrawable,
+ req->context, req->oldContextTag );
+}
+
+int __glXDisp_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXMakeCurrentReadSGIReq);
+
+ return DoMakeCurrent( cl, req->drawable, req->readable,
+ req->context, req->oldContextTag );
+}
+
+int __glXDisp_IsDirect(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc;
+ xGLXIsDirectReply reply;
+ __GLXcontext *glxc;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXIsDirectReq);
+
+ if (!validGlxContext(cl->client, req->context, DixReadAccess, &glxc, &err))
+ return err;
+
+ reply.isDirect = glxc->isDirect;
+ reply.length = 0;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __glXSwapIsDirectReply(client, &reply);
+ } else {
+ WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply);
+ }
+
+ return Success;
+}
+
+int __glXDisp_QueryVersion(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc;
+ xGLXQueryVersionReply reply;
+ GLuint major, minor;
+
+ REQUEST_SIZE_MATCH(xGLXQueryVersionReq);
+
+ major = req->majorVersion;
+ minor = req->minorVersion;
+ (void)major;
+ (void)minor;
+
+ /*
+ ** Server should take into consideration the version numbers sent by the
+ ** client if it wants to work with older clients; however, in this
+ ** implementation the server just returns its version number.
+ */
+ reply.majorVersion = glxMajorVersion;
+ reply.minorVersion = glxMinorVersion;
+ reply.length = 0;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __glXSwapQueryVersionReply(client, &reply);
+ } else {
+ WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply);
+ }
+ return Success;
+}
+
+int __glXDisp_WaitGL(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXWaitGLReq *req = (xGLXWaitGLReq *)pc;
+ GLXContextTag tag;
+ __GLXcontext *glxc = NULL;
+ int error;
+
+ REQUEST_SIZE_MATCH(xGLXWaitGLReq);
+
+ tag = req->contextTag;
+ if (tag) {
+ glxc = __glXLookupContextByTag(cl, tag);
+ if (!glxc)
+ return __glXError(GLXBadContextTag);
+
+ if (!__glXForceCurrent(cl, req->contextTag, &error))
+ return error;
+
+ CALL_Finish( GET_DISPATCH(), () );
+ }
+
+ if (glxc && glxc->drawPriv->waitGL)
+ (*glxc->drawPriv->waitGL)(glxc->drawPriv);
+
+ return Success;
+}
+
+int __glXDisp_WaitX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXWaitXReq *req = (xGLXWaitXReq *)pc;
+ GLXContextTag tag;
+ __GLXcontext *glxc = NULL;
+ int error;
+
+ REQUEST_SIZE_MATCH(xGLXWaitXReq);
+
+ tag = req->contextTag;
+ if (tag) {
+ glxc = __glXLookupContextByTag(cl, tag);
+ if (!glxc)
+ return __glXError(GLXBadContextTag);
+
+ if (!__glXForceCurrent(cl, req->contextTag, &error))
+ return error;
+ }
+
+ if (glxc && glxc->drawPriv->waitX)
+ (*glxc->drawPriv->waitX)(glxc->drawPriv);
+
+ return Success;
+}
+
+int __glXDisp_CopyContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc;
+ GLXContextID source;
+ GLXContextID dest;
+ GLXContextTag tag;
+ unsigned long mask;
+ __GLXcontext *src, *dst;
+ int error;
+
+ REQUEST_SIZE_MATCH(xGLXCopyContextReq);
+
+ source = req->source;
+ dest = req->dest;
+ tag = req->contextTag;
+ mask = req->mask;
+ if (!validGlxContext(cl->client, source, DixReadAccess, &src, &error))
+ return error;
+ if (!validGlxContext(cl->client, dest, DixWriteAccess, &dst, &error))
+ return error;
+
+ /*
+ ** They must be in the same address space, and same screen.
+ ** NOTE: no support for direct rendering contexts here.
+ */
+ if (src->isDirect || dst->isDirect ||
+ (src->pGlxScreen != dst->pGlxScreen)) {
+ client->errorValue = source;
+ return BadMatch;
+ }
+
+ /*
+ ** The destination context must not be current for any client.
+ */
+ if (dst->isCurrent) {
+ client->errorValue = dest;
+ return BadAccess;
+ }
+
+ if (tag) {
+ __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag);
+
+ if (!tagcx) {
+ return __glXError(GLXBadContextTag);
+ }
+ if (tagcx != src) {
+ /*
+ ** This would be caused by a faulty implementation of the client
+ ** library.
+ */
+ return BadMatch;
+ }
+ /*
+ ** In this case, glXCopyContext is in both GL and X streams, in terms
+ ** of sequentiality.
+ */
+ if (__glXForceCurrent(cl, tag, &error)) {
+ /*
+ ** Do whatever is needed to make sure that all preceding requests
+ ** in both streams are completed before the copy is executed.
+ */
+ CALL_Finish( GET_DISPATCH(), () );
+ tagcx->hasUnflushedCommands = GL_FALSE;
+ } else {
+ return error;
+ }
+ }
+ /*
+ ** Issue copy. The only reason for failure is a bad mask.
+ */
+ if (!(*dst->copy)(dst, src, mask)) {
+ client->errorValue = mask;
+ return BadValue;
+ }
+ return Success;
+}
+
+enum {
+ GLX_VIS_CONFIG_UNPAIRED = 18,
+ GLX_VIS_CONFIG_PAIRED = 20
+};
+
+enum {
+ GLX_VIS_CONFIG_TOTAL = GLX_VIS_CONFIG_UNPAIRED + GLX_VIS_CONFIG_PAIRED
+};
+
+int __glXDisp_GetVisualConfigs(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc;
+ ClientPtr client = cl->client;
+ xGLXGetVisualConfigsReply reply;
+ __GLXscreen *pGlxScreen;
+ __GLXconfig *modes;
+ CARD32 buf[GLX_VIS_CONFIG_TOTAL];
+ int p, i, err;
+ __GLX_DECLARE_SWAP_VARIABLES;
+ __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
+
+ REQUEST_SIZE_MATCH(xGLXGetVisualConfigsReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+
+ reply.numVisuals = pGlxScreen->numVisuals;
+ reply.numProps = GLX_VIS_CONFIG_TOTAL;
+ reply.length = (reply.numVisuals * __GLX_SIZE_CARD32 * GLX_VIS_CONFIG_TOTAL) >> 2;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&reply.sequenceNumber);
+ __GLX_SWAP_INT(&reply.length);
+ __GLX_SWAP_INT(&reply.numVisuals);
+ __GLX_SWAP_INT(&reply.numProps);
+ }
+
+ WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char *)&reply);
+
+ for (i = 0; i < pGlxScreen->numVisuals; i++) {
+ modes = pGlxScreen->visuals[i];
+
+ p = 0;
+ buf[p++] = modes->visualID;
+ buf[p++] = glxConvertToXVisualType( modes->visualType );
+ buf[p++] = (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE;
+
+ buf[p++] = modes->redBits;
+ buf[p++] = modes->greenBits;
+ buf[p++] = modes->blueBits;
+ buf[p++] = modes->alphaBits;
+ buf[p++] = modes->accumRedBits;
+ buf[p++] = modes->accumGreenBits;
+ buf[p++] = modes->accumBlueBits;
+ buf[p++] = modes->accumAlphaBits;
+
+ buf[p++] = modes->doubleBufferMode;
+ buf[p++] = modes->stereoMode;
+
+ buf[p++] = modes->rgbBits;
+ buf[p++] = modes->depthBits;
+ buf[p++] = modes->stencilBits;
+ buf[p++] = modes->numAuxBuffers;
+ buf[p++] = modes->level;
+
+ assert(p == GLX_VIS_CONFIG_UNPAIRED);
+ /*
+ ** Add token/value pairs for extensions.
+ */
+ buf[p++] = GLX_VISUAL_CAVEAT_EXT;
+ buf[p++] = modes->visualRating;
+ buf[p++] = GLX_TRANSPARENT_TYPE;
+ buf[p++] = modes->transparentPixel;
+ buf[p++] = GLX_TRANSPARENT_RED_VALUE;
+ buf[p++] = modes->transparentRed;
+ buf[p++] = GLX_TRANSPARENT_GREEN_VALUE;
+ buf[p++] = modes->transparentGreen;
+ buf[p++] = GLX_TRANSPARENT_BLUE_VALUE;
+ buf[p++] = modes->transparentBlue;
+ buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE;
+ buf[p++] = modes->transparentAlpha;
+ buf[p++] = GLX_TRANSPARENT_INDEX_VALUE;
+ buf[p++] = modes->transparentIndex;
+ buf[p++] = GLX_SAMPLES_SGIS;
+ buf[p++] = modes->samples;
+ buf[p++] = GLX_SAMPLE_BUFFERS_SGIS;
+ buf[p++] = modes->sampleBuffers;
+ buf[p++] = 0; /* copy over visualSelectGroup (GLX_VISUAL_SELECT_GROUP_SGIX)? */
+ buf[p++] = 0;
+
+ assert(p == GLX_VIS_CONFIG_TOTAL);
+ if (client->swapped) {
+ __GLX_SWAP_INT_ARRAY(buf, p);
+ }
+ WriteToClient(client, __GLX_SIZE_CARD32 * p, (char *)buf);
+ }
+ return Success;
+}
+
+#define __GLX_TOTAL_FBCONFIG_ATTRIBS (36)
+#define __GLX_FBCONFIG_ATTRIBS_LENGTH (__GLX_TOTAL_FBCONFIG_ATTRIBS * 2)
+/**
+ * Send the set of GLXFBConfigs to the client. There is not currently
+ * and interface into the driver on the server-side to get GLXFBConfigs,
+ * so we "invent" some based on the \c __GLXvisualConfig structures that
+ * the driver does supply.
+ *
+ * The reply format for both \c glXGetFBConfigs and \c glXGetFBConfigsSGIX
+ * is the same, so this routine pulls double duty.
+ */
+
+static int
+DoGetFBConfigs(__GLXclientState *cl, unsigned screen)
+{
+ ClientPtr client = cl->client;
+ xGLXGetFBConfigsReply reply;
+ __GLXscreen *pGlxScreen;
+ CARD32 buf[__GLX_FBCONFIG_ATTRIBS_LENGTH];
+ int p, err;
+ __GLXconfig *modes;
+ __GLX_DECLARE_SWAP_VARIABLES;
+ __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
+
+ if (!validGlxScreen(cl->client, screen, &pGlxScreen, &err))
+ return err;
+
+ reply.numFBConfigs = pGlxScreen->numFBConfigs;
+ reply.numAttribs = __GLX_TOTAL_FBCONFIG_ATTRIBS;
+ reply.length = (__GLX_FBCONFIG_ATTRIBS_LENGTH * reply.numFBConfigs);
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&reply.sequenceNumber);
+ __GLX_SWAP_INT(&reply.length);
+ __GLX_SWAP_INT(&reply.numFBConfigs);
+ __GLX_SWAP_INT(&reply.numAttribs);
+ }
+
+ WriteToClient(client, sz_xGLXGetFBConfigsReply, (char *)&reply);
+
+ for (modes = pGlxScreen->fbconfigs; modes != NULL; modes = modes->next) {
+ p = 0;
+
+#define WRITE_PAIR(tag,value) \
+ do { buf[p++] = tag ; buf[p++] = value ; } while( 0 )
+
+ WRITE_PAIR( GLX_VISUAL_ID, modes->visualID );
+ WRITE_PAIR( GLX_FBCONFIG_ID, modes->fbconfigID );
+ WRITE_PAIR( GLX_X_RENDERABLE, GL_TRUE );
+
+ WRITE_PAIR( GLX_RGBA,
+ (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE );
+ WRITE_PAIR( GLX_RENDER_TYPE, modes->renderType );
+ WRITE_PAIR( GLX_DOUBLEBUFFER, modes->doubleBufferMode );
+ WRITE_PAIR( GLX_STEREO, modes->stereoMode );
+
+ WRITE_PAIR( GLX_BUFFER_SIZE, modes->rgbBits );
+ WRITE_PAIR( GLX_LEVEL, modes->level );
+ WRITE_PAIR( GLX_AUX_BUFFERS, modes->numAuxBuffers );
+ WRITE_PAIR( GLX_RED_SIZE, modes->redBits );
+ WRITE_PAIR( GLX_GREEN_SIZE, modes->greenBits );
+ WRITE_PAIR( GLX_BLUE_SIZE, modes->blueBits );
+ WRITE_PAIR( GLX_ALPHA_SIZE, modes->alphaBits );
+ WRITE_PAIR( GLX_ACCUM_RED_SIZE, modes->accumRedBits );
+ WRITE_PAIR( GLX_ACCUM_GREEN_SIZE, modes->accumGreenBits );
+ WRITE_PAIR( GLX_ACCUM_BLUE_SIZE, modes->accumBlueBits );
+ WRITE_PAIR( GLX_ACCUM_ALPHA_SIZE, modes->accumAlphaBits );
+ WRITE_PAIR( GLX_DEPTH_SIZE, modes->depthBits );
+ WRITE_PAIR( GLX_STENCIL_SIZE, modes->stencilBits );
+ WRITE_PAIR( GLX_X_VISUAL_TYPE, modes->visualType );
+ WRITE_PAIR( GLX_CONFIG_CAVEAT, modes->visualRating );
+ WRITE_PAIR( GLX_TRANSPARENT_TYPE, modes->transparentPixel );
+ WRITE_PAIR( GLX_TRANSPARENT_RED_VALUE, modes->transparentRed );
+ WRITE_PAIR( GLX_TRANSPARENT_GREEN_VALUE, modes->transparentGreen );
+ WRITE_PAIR( GLX_TRANSPARENT_BLUE_VALUE, modes->transparentBlue );
+ WRITE_PAIR( GLX_TRANSPARENT_ALPHA_VALUE, modes->transparentAlpha );
+ WRITE_PAIR( GLX_TRANSPARENT_INDEX_VALUE, modes->transparentIndex );
+ WRITE_PAIR( GLX_SWAP_METHOD_OML, modes->swapMethod );
+ WRITE_PAIR( GLX_SAMPLES_SGIS, modes->samples );
+ WRITE_PAIR( GLX_SAMPLE_BUFFERS_SGIS, modes->sampleBuffers );
+ /* GLX_VISUAL_SELECT_GROUP_SGIX ? */
+ WRITE_PAIR( GLX_DRAWABLE_TYPE, modes->drawableType );
+ WRITE_PAIR( GLX_BIND_TO_TEXTURE_RGB_EXT, modes->bindToTextureRgb );
+ WRITE_PAIR( GLX_BIND_TO_TEXTURE_RGBA_EXT, modes->bindToTextureRgba );
+ WRITE_PAIR( GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture );
+ WRITE_PAIR( GLX_BIND_TO_TEXTURE_TARGETS_EXT, modes->bindToTextureTargets );
+
+ if (client->swapped) {
+ __GLX_SWAP_INT_ARRAY(buf, __GLX_FBCONFIG_ATTRIBS_LENGTH);
+ }
+ WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_FBCONFIG_ATTRIBS_LENGTH,
+ (char *)buf);
+ }
+ return Success;
+}
+
+
+int __glXDisp_GetFBConfigs(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc;
+ REQUEST_SIZE_MATCH(xGLXGetFBConfigsReq);
+ return DoGetFBConfigs(cl, req->screen);
+}
+
+int __glXDisp_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc;
+ /* work around mesa bug, don't use REQUEST_SIZE_MATCH */
+ REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
+ return DoGetFBConfigs(cl, req->screen);
+}
+
+GLboolean
+__glXDrawableInit(__GLXdrawable *drawable,
+ __GLXscreen *screen, DrawablePtr pDraw, int type,
+ XID drawId, __GLXconfig *config)
+{
+ drawable->pDraw = pDraw;
+ drawable->type = type;
+ drawable->drawId = drawId;
+ drawable->config = config;
+ drawable->eventMask = 0;
+
+ return GL_TRUE;
+}
+
+void
+__glXDrawableRelease(__GLXdrawable *drawable)
+{
+}
+
+static int
+DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
+ __GLXconfig *config, DrawablePtr pDraw, XID drawableId,
+ XID glxDrawableId, int type)
+{
+ __GLXdrawable *pGlxDraw;
+
+ if (pGlxScreen->pScreen != pDraw->pScreen)
+ return BadMatch;
+
+ pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
+ drawableId, type,
+ glxDrawableId, config);
+ if (pGlxDraw == NULL)
+ return BadAlloc;
+
+ if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) {
+ pGlxDraw->destroy (pGlxDraw);
+ return BadAlloc;
+ }
+
+ /*
+ * Windows aren't refcounted, so track both the X and the GLX window
+ * so we get called regardless of destruction order.
+ */
+ if (drawableId != glxDrawableId && type == GLX_DRAWABLE_WINDOW &&
+ !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
+ pGlxDraw->destroy (pGlxDraw);
+ return BadAlloc;
+ }
+
+ return Success;
+}
+
+static int
+DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config,
+ XID drawableId, XID glxDrawableId)
+{
+ DrawablePtr pDraw;
+ int err;
+
+ LEGAL_NEW_RESOURCE(glxDrawableId, client);
+
+ err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess);
+ if (err != Success) {
+ client->errorValue = drawableId;
+ return err;
+ }
+ if (pDraw->type != DRAWABLE_PIXMAP) {
+ client->errorValue = drawableId;
+ return BadPixmap;
+ }
+
+ err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
+ glxDrawableId, GLX_DRAWABLE_PIXMAP);
+
+ ((PixmapPtr)pDraw)->refcnt++;
+
+ return err;
+}
+
+static void
+determineTextureTarget(ClientPtr client, XID glxDrawableID,
+ CARD32 *attribs, CARD32 numAttribs)
+{
+ GLenum target = 0;
+ GLenum format = 0;
+ int i, err;
+ __GLXdrawable *pGlxDraw;
+
+ if (!validGlxDrawable(client, glxDrawableID, GLX_DRAWABLE_PIXMAP,
+ DixWriteAccess, &pGlxDraw, &err))
+ /* We just added it in CreatePixmap, so we should never get here. */
+ return;
+
+ for (i = 0; i < numAttribs; i++) {
+ if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
+ switch (attribs[2 * i + 1]) {
+ case GLX_TEXTURE_2D_EXT:
+ target = GL_TEXTURE_2D;
+ break;
+ case GLX_TEXTURE_RECTANGLE_EXT:
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ break;
+ }
+ }
+
+ if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
+ format = attribs[2 * i + 1];
+ }
+
+ if (!target) {
+ int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height;
+
+ if (h & (h - 1) || w & (w - 1))
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ else
+ target = GL_TEXTURE_2D;
+ }
+
+ pGlxDraw->target = target;
+ pGlxDraw->format = format;
+}
+
+int __glXDisp_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
+ return err;
+
+ return DoCreateGLXPixmap(cl->client, pGlxScreen, config,
+ req->pixmap, req->glxpixmap);
+}
+
+int __glXDisp_CreatePixmap(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_AT_LEAST_SIZE(xGLXCreatePixmapReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ err = DoCreateGLXPixmap(cl->client, pGlxScreen, config,
+ req->pixmap, req->glxpixmap);
+ if (err != Success)
+ return err;
+
+ determineTextureTarget(cl->client, req->glxpixmap,
+ (CARD32*) (req + 1), req->numAttribs);
+
+ return Success;
+}
+
+int __glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateGLXPixmapWithConfigSGIXReq *req =
+ (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ return DoCreateGLXPixmap(cl->client, pGlxScreen,
+ config, req->pixmap, req->glxpixmap);
+}
+
+
+static int DoDestroyDrawable(__GLXclientState *cl, XID glxdrawable, int type)
+{
+ __GLXdrawable *pGlxDraw;
+ int err;
+
+ if (!validGlxDrawable(cl->client, glxdrawable, type,
+ DixDestroyAccess, &pGlxDraw, &err))
+ return err;
+
+ FreeResource(glxdrawable, FALSE);
+
+ return Success;
+}
+
+int __glXDisp_DestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq);
+
+ return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
+}
+
+int __glXDisp_DestroyPixmap(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc;
+
+ /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set
+ * length to 3 instead of 2 */
+ REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq);
+
+ return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
+}
+
+static int
+DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
+ int width, int height, XID glxDrawableId)
+{
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ PixmapPtr pPixmap;
+ int err;
+
+ LEGAL_NEW_RESOURCE(glxDrawableId, client);
+
+ if (!validGlxScreen(client, screenNum, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err))
+ return err;
+
+ __glXenterServer(GL_FALSE);
+ pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen,
+ width, height, config->rgbBits, 0);
+ __glXleaveServer(GL_FALSE);
+
+ /* Assign the pixmap the same id as the pbuffer and add it as a
+ * resource so it and the DRI2 drawable will be reclaimed when the
+ * pbuffer is destroyed. */
+ pPixmap->drawable.id = glxDrawableId;
+ if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap))
+ return BadAlloc;
+
+ return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
+ glxDrawableId, glxDrawableId,
+ GLX_DRAWABLE_PBUFFER);
+}
+
+int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc;
+ CARD32 *attrs;
+ int width, height, i;
+
+ REQUEST_AT_LEAST_SIZE(xGLXCreatePbufferReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3);
+
+ attrs = (CARD32 *) (req + 1);
+ width = 0;
+ height = 0;
+
+ for (i = 0; i < req->numAttribs; i++) {
+ switch (attrs[i * 2]) {
+ case GLX_PBUFFER_WIDTH:
+ width = attrs[i * 2 + 1];
+ break;
+ case GLX_PBUFFER_HEIGHT:
+ height = attrs[i * 2 + 1];
+ break;
+ case GLX_LARGEST_PBUFFER:
+ case GLX_PRESERVED_CONTENTS:
+ /* FIXME: huh... */
+ break;
+ }
+ }
+
+ return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
+ width, height, req->pbuffer);
+}
+
+int __glXDisp_CreateGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXCreateGLXPbufferSGIXReq);
+
+ return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
+ req->width, req->height, req->pbuffer);
+}
+
+int __glXDisp_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq);
+
+ return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
+}
+
+int __glXDisp_DestroyGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq);
+
+ return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
+}
+
+static int
+DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable,
+ int numAttribs, CARD32 *attribs)
+{
+ __GLXdrawable *pGlxDraw;
+ int i, err;
+
+ if (!validGlxDrawable(client, glxdrawable, GLX_DRAWABLE_ANY,
+ DixSetAttrAccess, &pGlxDraw, &err))
+ return err;
+
+ for (i = 0; i < numAttribs; i++) {
+ switch(attribs[i * 2]) {
+ case GLX_EVENT_MASK:
+ /* All we do is to record the event mask so we can send it
+ * back when queried. We never actually clobber the
+ * pbuffers, so we never need to send out the event. */
+ pGlxDraw->eventMask = attribs[i * 2 + 1];
+ break;
+ }
+ }
+
+ return Success;
+}
+
+int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXChangeDrawableAttributesReq *req =
+ (xGLXChangeDrawableAttributesReq *) pc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+#if 0
+ /* mesa sends an additional 8 bytes */
+ REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
+#else
+ if (((sizeof(xGLXChangeDrawableAttributesReq) + (req->numAttribs << 3)) >> 2) < client->req_len)
+ return BadLength;
+#endif
+
+ return DoChangeDrawableAttributes(cl->client, req->drawable,
+ req->numAttribs, (CARD32 *) (req + 1));
+}
+
+int __glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXChangeDrawableAttributesSGIXReq *req =
+ (xGLXChangeDrawableAttributesSGIXReq *)pc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesSGIXReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq, req->numAttribs << 3);
+
+ return DoChangeDrawableAttributes(cl->client, req->drawable,
+ req->numAttribs, (CARD32 *) (req + 1));
+}
+
+int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ ClientPtr client = cl->client;
+ DrawablePtr pDraw;
+ int err;
+
+ REQUEST_AT_LEAST_SIZE(xGLXCreateWindowReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3);
+
+ LEGAL_NEW_RESOURCE(req->glxwindow, client);
+
+ if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ err = dixLookupDrawable(&pDraw, req->window, client, 0, DixAddAccess);
+ if (err != Success || pDraw->type != DRAWABLE_WINDOW) {
+ client->errorValue = req->window;
+ return BadWindow;
+ }
+
+ if (!validGlxFBConfigForWindow(client, config, pDraw, &err))
+ return err;
+
+ return DoCreateGLXDrawable(client, pGlxScreen, config,
+ pDraw, req->window,
+ req->glxwindow, GLX_DRAWABLE_WINDOW);
+}
+
+int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc;
+
+ /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */
+ REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
+
+ return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW);
+}
+
+
+/*****************************************************************************/
+
+/*
+** NOTE: There is no portable implementation for swap buffers as of
+** this time that is of value. Consequently, this code must be
+** implemented by somebody other than SGI.
+*/
+int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc;
+ GLXContextTag tag;
+ XID drawId;
+ __GLXcontext *glxc = NULL;
+ __GLXdrawable *pGlxDraw;
+ int error;
+
+ REQUEST_SIZE_MATCH(xGLXSwapBuffersReq);
+
+ tag = req->contextTag;
+ drawId = req->drawable;
+ if (tag) {
+ glxc = __glXLookupContextByTag(cl, tag);
+ if (!glxc) {
+ return __glXError(GLXBadContextTag);
+ }
+ /*
+ ** The calling thread is swapping its current drawable. In this case,
+ ** glxSwapBuffers is in both GL and X streams, in terms of
+ ** sequentiality.
+ */
+ if (__glXForceCurrent(cl, tag, &error)) {
+ /*
+ ** Do whatever is needed to make sure that all preceding requests
+ ** in both streams are completed before the swap is executed.
+ */
+ CALL_Finish( GET_DISPATCH(), () );
+ glxc->hasUnflushedCommands = GL_FALSE;
+ } else {
+ return error;
+ }
+ }
+
+ pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
+ if (pGlxDraw == NULL)
+ return error;
+
+ if (pGlxDraw->type == DRAWABLE_WINDOW &&
+ (*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE)
+ return __glXError(GLXBadDrawable);
+
+ return Success;
+}
+
+
+static int
+DoQueryContext(__GLXclientState *cl, GLXContextID gcId)
+{
+ ClientPtr client = cl->client;
+ __GLXcontext *ctx;
+ xGLXQueryContextInfoEXTReply reply;
+ int nProps;
+ int *sendBuf, *pSendBuf;
+ int nReplyBytes;
+ int err;
+
+ if (!validGlxContext(cl->client, gcId, DixReadAccess, &ctx, &err))
+ return err;
+
+ nProps = 3;
+ reply.length = nProps << 1;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.n = nProps;
+
+ nReplyBytes = reply.length << 2;
+ sendBuf = (int *)malloc((size_t)nReplyBytes);
+ if (sendBuf == NULL) {
+ return __glXError(GLXBadContext); /* XXX: Is this correct? */
+ }
+ pSendBuf = sendBuf;
+ *pSendBuf++ = GLX_SHARE_CONTEXT_EXT;
+ *pSendBuf++ = (int)(ctx->share_id);
+ *pSendBuf++ = GLX_VISUAL_ID_EXT;
+ *pSendBuf++ = (int)(ctx->config->visualID);
+ *pSendBuf++ = GLX_SCREEN_EXT;
+ *pSendBuf++ = (int)(ctx->pGlxScreen->pScreen->myNum);
+
+ if (client->swapped) {
+ __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf);
+ } else {
+ WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, (char *)&reply);
+ WriteToClient(client, nReplyBytes, (char *)sendBuf);
+ }
+ free((char *)sendBuf);
+
+ return Success;
+}
+
+int __glXDisp_QueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq);
+
+ return DoQueryContext(cl, req->context);
+}
+
+int __glXDisp_QueryContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXQueryContextReq);
+
+ return DoQueryContext(cl, req->context);
+}
+
+int __glXDisp_BindTexImageEXT(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ ClientPtr client = cl->client;
+ __GLXcontext *context;
+ __GLXdrawable *pGlxDraw;
+ GLXDrawable drawId;
+ int buffer;
+ int error;
+ CARD32 num_attribs;
+
+ if ((sizeof(xGLXVendorPrivateReq) + 12) >> 2 > client->req_len)
+ return BadLength;
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+
+ drawId = *((CARD32 *) (pc));
+ buffer = *((INT32 *) (pc + 4));
+ num_attribs = *((CARD32 *) (pc + 8));
+ if (num_attribs > (UINT32_MAX >> 3)) {
+ client->errorValue = num_attribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 12 + (num_attribs << 3));
+
+ if (buffer != GLX_FRONT_LEFT_EXT)
+ return __glXError(GLXBadPixmap);
+
+ context = __glXForceCurrent (cl, req->contextTag, &error);
+ if (!context)
+ return error;
+
+ if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
+ DixReadAccess, &pGlxDraw, &error))
+ return error;
+
+ if (!context->textureFromPixmap)
+ return __glXError(GLXUnsupportedPrivateRequest);
+
+ return context->textureFromPixmap->bindTexImage(context,
+ buffer,
+ pGlxDraw);
+}
+
+int __glXDisp_ReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ ClientPtr client = cl->client;
+ __GLXdrawable *pGlxDraw;
+ __GLXcontext *context;
+ GLXDrawable drawId;
+ int buffer;
+ int error;
+
+ REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+
+ drawId = *((CARD32 *) (pc));
+ buffer = *((INT32 *) (pc + 4));
+
+ context = __glXForceCurrent (cl, req->contextTag, &error);
+ if (!context)
+ return error;
+
+ if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
+ DixReadAccess, &pGlxDraw, &error))
+ return error;
+
+ if (!context->textureFromPixmap)
+ return __glXError(GLXUnsupportedPrivateRequest);
+
+ return context->textureFromPixmap->releaseTexImage(context,
+ buffer,
+ pGlxDraw);
+}
+
+int __glXDisp_CopySubBufferMESA(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ GLXContextTag tag = req->contextTag;
+ __GLXcontext *glxc = NULL;
+ __GLXdrawable *pGlxDraw;
+ ClientPtr client = cl->client;
+ GLXDrawable drawId;
+ int error;
+ int x, y, width, height;
+
+ (void) client;
+ (void) req;
+
+ REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+
+ drawId = *((CARD32 *) (pc));
+ x = *((INT32 *) (pc + 4));
+ y = *((INT32 *) (pc + 8));
+ width = *((INT32 *) (pc + 12));
+ height = *((INT32 *) (pc + 16));
+
+ if (tag) {
+ glxc = __glXLookupContextByTag(cl, tag);
+ if (!glxc) {
+ return __glXError(GLXBadContextTag);
+ }
+ /*
+ ** The calling thread is swapping its current drawable. In this case,
+ ** glxSwapBuffers is in both GL and X streams, in terms of
+ ** sequentiality.
+ */
+ if (__glXForceCurrent(cl, tag, &error)) {
+ /*
+ ** Do whatever is needed to make sure that all preceding requests
+ ** in both streams are completed before the swap is executed.
+ */
+ CALL_Finish( GET_DISPATCH(), () );
+ glxc->hasUnflushedCommands = GL_FALSE;
+ } else {
+ return error;
+ }
+ }
+
+ pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
+ if (!pGlxDraw)
+ return error;
+
+ if (pGlxDraw == NULL ||
+ pGlxDraw->type != GLX_DRAWABLE_WINDOW ||
+ pGlxDraw->copySubBuffer == NULL)
+ return __glXError(GLXBadDrawable);
+
+ (*pGlxDraw->copySubBuffer)(pGlxDraw, x, y, width, height);
+
+ return Success;
+}
+
+/*
+** Get drawable attributes
+*/
+static int
+DoGetDrawableAttributes(__GLXclientState *cl, XID drawId)
+{
+ ClientPtr client = cl->client;
+ xGLXGetDrawableAttributesReply reply;
+ __GLXdrawable *pGlxDraw;
+ CARD32 attributes[6];
+ int numAttribs, error;
+
+ if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
+ DixGetAttrAccess, &pGlxDraw, &error))
+ return error;
+
+ numAttribs = 3;
+ reply.length = numAttribs << 1;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.numAttribs = numAttribs;
+
+ attributes[0] = GLX_TEXTURE_TARGET_EXT;
+ attributes[1] = pGlxDraw->target == GL_TEXTURE_2D ? GLX_TEXTURE_2D_EXT :
+ GLX_TEXTURE_RECTANGLE_EXT;
+ attributes[2] = GLX_Y_INVERTED_EXT;
+ attributes[3] = GL_FALSE;
+ attributes[4] = GLX_EVENT_MASK;
+ attributes[5] = pGlxDraw->eventMask;
+
+ if (client->swapped) {
+ __glXSwapGetDrawableAttributesReply(client, &reply, attributes);
+ } else {
+ WriteToClient(client, sz_xGLXGetDrawableAttributesReply,
+ (char *)&reply);
+ WriteToClient(client, reply.length * sizeof (CARD32),
+ (char *)attributes);
+ }
+
+ return Success;
+}
+
+int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc;
+
+ /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */
+ REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
+
+ return DoGetDrawableAttributes(cl, req->drawable);
+}
+
+int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXGetDrawableAttributesSGIXReq *req =
+ (xGLXGetDrawableAttributesSGIXReq *)pc;
+
+ REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq);
+
+ return DoGetDrawableAttributes(cl, req->drawable);
+}
+
+/************************************************************************/
+
+/*
+** Render and Renderlarge are not in the GLX API. They are used by the GLX
+** client library to send batches of GL rendering commands.
+*/
+
+/*
+** Execute all the drawing commands in a request.
+*/
+int __glXDisp_Render(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXRenderReq *req;
+ ClientPtr client= cl->client;
+ int left, cmdlen, error;
+ int commandsDone;
+ CARD16 opcode;
+ __GLXrenderHeader *hdr;
+ __GLXcontext *glxc;
+ __GLX_DECLARE_SWAP_VARIABLES;
+
+ REQUEST_AT_LEAST_SIZE(xGLXRenderReq);
+
+ req = (xGLXRenderReq *) pc;
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&req->length);
+ __GLX_SWAP_INT(&req->contextTag);
+ }
+
+ glxc = __glXForceCurrent(cl, req->contextTag, &error);
+ if (!glxc) {
+ return error;
+ }
+
+ commandsDone = 0;
+ pc += sz_xGLXRenderReq;
+ left = (req->length << 2) - sz_xGLXRenderReq;
+ while (left > 0) {
+ __GLXrenderSizeData entry;
+ int extra;
+ __GLXdispatchRenderProcPtr proc;
+ int err;
+
+ if (left < sizeof(__GLXrenderHeader))
+ return BadLength;
+
+ /*
+ ** Verify that the header length and the overall length agree.
+ ** Also, each command must be word aligned.
+ */
+ hdr = (__GLXrenderHeader *) pc;
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&hdr->length);
+ __GLX_SWAP_SHORT(&hdr->opcode);
+ }
+ cmdlen = hdr->length;
+ opcode = hdr->opcode;
+
+ /*
+ ** Check for core opcodes and grab entry data.
+ */
+ err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry);
+ proc = (__GLXdispatchRenderProcPtr)
+ __glXGetProtocolDecodeFunction(& Render_dispatch_info,
+ opcode, client->swapped);
+
+ if ((err < 0) || (proc == NULL)) {
+ client->errorValue = commandsDone;
+ return __glXError(GLXBadRenderRequest);
+ }
+
+ if (entry.varsize) {
+ /* variable size command */
+ extra = (*entry.varsize)(pc + __GLX_RENDER_HDR_SIZE,
+ client->swapped);
+ if (extra < 0) {
+ extra = 0;
+ }
+ if (cmdlen != __GLX_PAD(entry.bytes + extra)) {
+ return BadLength;
+ }
+ } else {
+ /* constant size command */
+ if (cmdlen != __GLX_PAD(entry.bytes)) {
+ return BadLength;
+ }
+ }
+ if (left < cmdlen) {
+ return BadLength;
+ }
+
+ /*
+ ** Skip over the header and execute the command. We allow the
+ ** caller to trash the command memory. This is useful especially
+ ** for things that require double alignment - they can just shift
+ ** the data towards lower memory (trashing the header) by 4 bytes
+ ** and achieve the required alignment.
+ */
+ (*proc)(pc + __GLX_RENDER_HDR_SIZE);
+ pc += cmdlen;
+ left -= cmdlen;
+ commandsDone++;
+ }
+ glxc->hasUnflushedCommands = GL_TRUE;
+ return Success;
+}
+
+
+/*
+** Execute a large rendering request (one that spans multiple X requests).
+*/
+int __glXDisp_RenderLarge(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXRenderLargeReq *req;
+ ClientPtr client= cl->client;
+ size_t dataBytes;
+ __GLXrenderLargeHeader *hdr;
+ __GLXcontext *glxc;
+ int error;
+ CARD16 opcode;
+ __GLX_DECLARE_SWAP_VARIABLES;
+
+ req = (xGLXRenderLargeReq *) pc;
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&req->length);
+ __GLX_SWAP_INT(&req->contextTag);
+ __GLX_SWAP_INT(&req->dataBytes);
+ __GLX_SWAP_SHORT(&req->requestNumber);
+ __GLX_SWAP_SHORT(&req->requestTotal);
+ }
+
+ glxc = __glXForceCurrent(cl, req->contextTag, &error);
+ if (!glxc) {
+ /* Reset in case this isn't 1st request. */
+ __glXResetLargeCommandStatus(cl);
+ return error;
+ }
+ dataBytes = req->dataBytes;
+
+ /*
+ ** Check the request length.
+ */
+ if ((req->length << 2) != __GLX_PAD(dataBytes) + sz_xGLXRenderLargeReq) {
+ client->errorValue = req->length;
+ /* Reset in case this isn't 1st request. */
+ __glXResetLargeCommandStatus(cl);
+ return BadLength;
+ }
+ pc += sz_xGLXRenderLargeReq;
+
+ if (cl->largeCmdRequestsSoFar == 0) {
+ __GLXrenderSizeData entry;
+ int extra;
+ size_t cmdlen;
+ int err;
+
+ /*
+ ** This is the first request of a multi request command.
+ ** Make enough space in the buffer, then copy the entire request.
+ */
+ if (req->requestNumber != 1) {
+ client->errorValue = req->requestNumber;
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ hdr = (__GLXrenderLargeHeader *) pc;
+ if (client->swapped) {
+ __GLX_SWAP_INT(&hdr->length);
+ __GLX_SWAP_INT(&hdr->opcode);
+ }
+ cmdlen = hdr->length;
+ opcode = hdr->opcode;
+
+ /*
+ ** Check for core opcodes and grab entry data.
+ */
+ err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry);
+ if (err < 0) {
+ client->errorValue = opcode;
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ if (entry.varsize) {
+ /*
+ ** If it's a variable-size command (a command whose length must
+ ** be computed from its parameters), all the parameters needed
+ ** will be in the 1st request, so it's okay to do this.
+ */
+ extra = (*entry.varsize)(pc + __GLX_RENDER_LARGE_HDR_SIZE,
+ client->swapped);
+ if (extra < 0) {
+ extra = 0;
+ }
+ /* large command's header is 4 bytes longer, so add 4 */
+ if (cmdlen != __GLX_PAD(entry.bytes + 4 + extra)) {
+ return BadLength;
+ }
+ } else {
+ /* constant size command */
+ if (cmdlen != __GLX_PAD(entry.bytes + 4)) {
+ return BadLength;
+ }
+ }
+ /*
+ ** Make enough space in the buffer, then copy the entire request.
+ */
+ if (cl->largeCmdBufSize < cmdlen) {
+ if (!cl->largeCmdBuf) {
+ cl->largeCmdBuf = (GLbyte *) malloc(cmdlen);
+ } else {
+ cl->largeCmdBuf = (GLbyte *) realloc(cl->largeCmdBuf, cmdlen);
+ }
+ if (!cl->largeCmdBuf) {
+ return BadAlloc;
+ }
+ cl->largeCmdBufSize = cmdlen;
+ }
+ memcpy(cl->largeCmdBuf, pc, dataBytes);
+
+ cl->largeCmdBytesSoFar = dataBytes;
+ cl->largeCmdBytesTotal = cmdlen;
+ cl->largeCmdRequestsSoFar = 1;
+ cl->largeCmdRequestsTotal = req->requestTotal;
+ return Success;
+
+ } else {
+ /*
+ ** We are receiving subsequent (i.e. not the first) requests of a
+ ** multi request command.
+ */
+
+ /*
+ ** Check the request number and the total request count.
+ */
+ if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) {
+ client->errorValue = req->requestNumber;
+ __glXResetLargeCommandStatus(cl);
+ return __glXError(GLXBadLargeRequest);
+ }
+ if (req->requestTotal != cl->largeCmdRequestsTotal) {
+ client->errorValue = req->requestTotal;
+ __glXResetLargeCommandStatus(cl);
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ /*
+ ** Check that we didn't get too much data.
+ */
+ if ((cl->largeCmdBytesSoFar + dataBytes) > cl->largeCmdBytesTotal) {
+ client->errorValue = dataBytes;
+ __glXResetLargeCommandStatus(cl);
+ return __glXError(GLXBadLargeRequest);
+ }
+ memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes);
+ cl->largeCmdBytesSoFar += dataBytes;
+ cl->largeCmdRequestsSoFar++;
+
+ if (req->requestNumber == cl->largeCmdRequestsTotal) {
+ __GLXdispatchRenderProcPtr proc;
+
+ /*
+ ** This is the last request; it must have enough bytes to complete
+ ** the command.
+ */
+ /* NOTE: the two pad macros have been added below; they are needed
+ ** because the client library pads the total byte count, but not
+ ** the per-request byte counts. The Protocol Encoding says the
+ ** total byte count should not be padded, so a proposal will be
+ ** made to the ARB to relax the padding constraint on the total
+ ** byte count, thus preserving backward compatibility. Meanwhile,
+ ** the padding done below fixes a bug that did not allow
+ ** large commands of odd sizes to be accepted by the server.
+ */
+ if (__GLX_PAD(cl->largeCmdBytesSoFar) !=
+ __GLX_PAD(cl->largeCmdBytesTotal)) {
+ client->errorValue = dataBytes;
+ __glXResetLargeCommandStatus(cl);
+ return __glXError(GLXBadLargeRequest);
+ }
+ hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf;
+ /*
+ ** The opcode and length field in the header had already been
+ ** swapped when the first request was received.
+ **
+ ** Use the opcode to index into the procedure table.
+ */
+ opcode = hdr->opcode;
+
+ proc = (__GLXdispatchRenderProcPtr)
+ __glXGetProtocolDecodeFunction(& Render_dispatch_info, opcode,
+ client->swapped);
+ if (proc == NULL) {
+ client->errorValue = opcode;
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ /*
+ ** Skip over the header and execute the command.
+ */
+ (*proc)(cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE);
+ glxc->hasUnflushedCommands = GL_TRUE;
+
+ /*
+ ** Reset for the next RenderLarge series.
+ */
+ __glXResetLargeCommandStatus(cl);
+ } else {
+ /*
+ ** This is neither the first nor the last request.
+ */
+ }
+ return Success;
+ }
+}
+
+/************************************************************************/
+
+/*
+** No support is provided for the vendor-private requests other than
+** allocating the entry points in the dispatch table.
+*/
+
+int __glXDisp_VendorPrivate(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ GLint vendorcode = req->vendorCode;
+ __GLXdispatchVendorPrivProcPtr proc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
+
+ proc = (__GLXdispatchVendorPrivProcPtr)
+ __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info,
+ vendorcode, 0);
+ if (proc != NULL) {
+ (*proc)(cl, (GLbyte*)req);
+ return Success;
+ }
+
+ cl->client->errorValue = req->vendorCode;
+ return __glXError(GLXUnsupportedPrivateRequest);
+}
+
+int __glXDisp_VendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ GLint vendorcode = req->vendorCode;
+ __GLXdispatchVendorPrivProcPtr proc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
+
+ proc = (__GLXdispatchVendorPrivProcPtr)
+ __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info,
+ vendorcode, 0);
+ if (proc != NULL) {
+ return (*proc)(cl, (GLbyte*)req);
+ }
+
+ cl->client->errorValue = vendorcode;
+ return __glXError(GLXUnsupportedPrivateRequest);
+}
+
+int __glXDisp_QueryExtensionsString(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc;
+ xGLXQueryExtensionsStringReply reply;
+ __GLXscreen *pGlxScreen;
+ size_t n, length;
+ char *buf;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXQueryExtensionsStringReq);
+
+ if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
+ return err;
+
+ n = strlen(pGlxScreen->GLXextensions) + 1;
+ length = __GLX_PAD(n) >> 2;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = length;
+ reply.n = n;
+
+ /* Allocate buffer to make sure it's a multiple of 4 bytes big.*/
+ buf = (char *) malloc(length << 2);
+ if (buf == NULL)
+ return BadAlloc;
+ memcpy(buf, pGlxScreen->GLXextensions, n);
+
+ if (client->swapped) {
+ glxSwapQueryExtensionsStringReply(client, &reply, buf);
+ } else {
+ WriteToClient(client, sz_xGLXQueryExtensionsStringReply,(char *)&reply);
+ WriteToClient(client, (int)(length << 2), (char *)buf);
+ }
+
+ free(buf);
+ return Success;
+}
+
+int __glXDisp_QueryServerString(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc;
+ xGLXQueryServerStringReply reply;
+ size_t n, length;
+ const char *ptr;
+ char *buf;
+ __GLXscreen *pGlxScreen;
+ int err;
+ char ver_str[16];
+
+ REQUEST_SIZE_MATCH(xGLXQueryServerStringReq);
+
+ if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
+ return err;
+
+ switch(req->name) {
+ case GLX_VENDOR:
+ ptr = pGlxScreen->GLXvendor;
+ break;
+ case GLX_VERSION:
+ /* Return to the server version rather than the screen version
+ * to prevent confusion when they do not match.
+ */
+ snprintf(ver_str, 16, "%d.%d", glxMajorVersion, glxMinorVersion);
+ ptr = ver_str;
+ break;
+ case GLX_EXTENSIONS:
+ ptr = pGlxScreen->GLXextensions;
+ break;
+ default:
+ return BadValue;
+ }
+
+ n = strlen(ptr) + 1;
+ length = __GLX_PAD(n) >> 2;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = length;
+ reply.n = n;
+
+ buf = (char *) malloc(length << 2);
+ if (buf == NULL) {
+ return BadAlloc;
+ }
+ memcpy(buf, ptr, n);
+
+ if (client->swapped) {
+ glxSwapQueryServerStringReply(client, &reply, buf);
+ } else {
+ WriteToClient(client, sz_xGLXQueryServerStringReply, (char *)&reply);
+ WriteToClient(client, (int)(length << 2), buf);
+ }
+
+ free(buf);
+ return Success;
+}
+
+int __glXDisp_ClientInfo(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc;
+ const char *buf;
+
+ REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq);
+
+ buf = (const char *)(req+1);
+ if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq)))
+ return BadLength;
+
+ cl->GLClientmajorVersion = req->major;
+ cl->GLClientminorVersion = req->minor;
+ free(cl->GLClientextensions);
+ cl->GLClientextensions = strdup(buf);
+
+ return Success;
+}
diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c
index db0d3d999..d97971739 100644
--- a/xorg-server/glx/glxdri2.c
+++ b/xorg-server/glx/glxdri2.c
@@ -1,791 +1,792 @@
-/*
- * Copyright © 2007 Red Hat, Inc
- *
- * 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, and that the name of Red Hat,
- * Inc not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission. Red Hat, Inc makes no representations about the
- * suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
- * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <dlfcn.h>
-
-#include <drm.h>
-#include <GL/gl.h>
-#include <GL/internal/dri_interface.h>
-#include <GL/glxtokens.h>
-
-#include <windowstr.h>
-#include <os.h>
-
-#define _XF86DRI_SERVER_
-#include <xf86drm.h>
-#include <xf86.h>
-#include <dri2.h>
-
-#include "glxserver.h"
-#include "glxutil.h"
-#include "glxdricommon.h"
-
-#include "glapitable.h"
-#include "glapi.h"
-#include "glthread.h"
-#include "dispatch.h"
-#include "extension_string.h"
-
-typedef struct __GLXDRIscreen __GLXDRIscreen;
-typedef struct __GLXDRIcontext __GLXDRIcontext;
-typedef struct __GLXDRIdrawable __GLXDRIdrawable;
-
-struct __GLXDRIscreen {
- __GLXscreen base;
- __DRIscreen *driScreen;
- void *driver;
- int fd;
-
- xf86EnterVTProc *enterVT;
- xf86LeaveVTProc *leaveVT;
-
- const __DRIcoreExtension *core;
- const __DRIdri2Extension *dri2;
- const __DRI2flushExtension *flush;
- const __DRIcopySubBufferExtension *copySubBuffer;
- const __DRIswapControlExtension *swapControl;
- const __DRItexBufferExtension *texBuffer;
-
- unsigned char glx_enable_bits[__GLX_EXT_BYTES];
-};
-
-struct __GLXDRIcontext {
- __GLXcontext base;
- __DRIcontext *driContext;
-};
-
-#define MAX_DRAWABLE_BUFFERS 5
-
-struct __GLXDRIdrawable {
- __GLXdrawable base;
- __DRIdrawable *driDrawable;
- __GLXDRIscreen *screen;
-
- /* Dimensions as last reported by DRI2GetBuffers. */
- int width;
- int height;
- __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
- int count;
-};
-
-static void
-__glXDRIdrawableDestroy(__GLXdrawable *drawable)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- const __DRIcoreExtension *core = private->screen->core;
-
- (*core->destroyDrawable)(private->driDrawable);
-
- __glXDrawableRelease(drawable);
-
- free(private);
-}
-
-static void
-__glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
- int x, int y, int w, int h)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- BoxRec box;
- RegionRec region;
-
- box.x1 = x;
- box.y1 = private->height - y - h;
- box.x2 = x + w;
- box.y2 = private->height - y;
- RegionInit(&region, &box, 0);
-
- DRI2CopyRegion(drawable->pDraw, &region,
- DRI2BufferFrontLeft, DRI2BufferBackLeft);
-}
-
-static void
-__glXDRIdrawableWaitX(__GLXdrawable *drawable)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = private->width;
- box.y2 = private->height;
- RegionInit(&region, &box, 0);
-
- DRI2CopyRegion(drawable->pDraw, &region,
- DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
-}
-
-static void
-__glXDRIdrawableWaitGL(__GLXdrawable *drawable)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = private->width;
- box.y2 = private->height;
- RegionInit(&region, &box, 0);
-
- DRI2CopyRegion(drawable->pDraw, &region,
- DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
-}
-
-static void
-__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
- CARD64 msc, CARD64 sbc)
-{
- __GLXdrawable *drawable = data;
- xGLXBufferSwapComplete wire;
-
- if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
- return;
-
- wire.type = __glXEventBase + GLX_BufferSwapComplete;
- switch (type) {
- case DRI2_EXCHANGE_COMPLETE:
- wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
- break;
- case DRI2_BLIT_COMPLETE:
- wire.event_type = GLX_BLIT_COMPLETE_INTEL;
- break;
- case DRI2_FLIP_COMPLETE:
- wire.event_type = GLX_FLIP_COMPLETE_INTEL;
- break;
- default:
- /* unknown swap completion type */
- break;
- }
- wire.drawable = drawable->drawId;
- wire.ust_hi = ust >> 32;
- wire.ust_lo = ust & 0xffffffff;
- wire.msc_hi = msc >> 32;
- wire.msc_lo = msc & 0xffffffff;
- wire.sbc_hi = sbc >> 32;
- wire.sbc_lo = sbc & 0xffffffff;
-
- WriteEventsToClient(client, 1, (xEvent *) &wire);
-}
-
-/*
- * Copy or flip back to front, honoring the swap interval if possible.
- *
- * If the kernel supports it, we request an event for the frame when the
- * swap should happen, then perform the copy when we receive it.
- */
-static GLboolean
-__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
-{
- __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
- __GLXDRIscreen *screen = priv->screen;
- CARD64 unused;
-
-#if __DRI2_FLUSH_VERSION >= 3
- if (screen->flush) {
- (*screen->flush->flush)(priv->driDrawable);
- (*screen->flush->invalidate)(priv->driDrawable);
- }
-#else
- if (screen->flush)
- (*screen->flush->flushInvalidate)(priv->driDrawable);
-#endif
-
- if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
- __glXdriSwapEvent, drawable->pDraw) != Success)
- return FALSE;
-
- return TRUE;
-}
-
-static int
-__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
-{
- if (interval <= 0) /* || interval > BIGNUM? */
- return GLX_BAD_VALUE;
-
- DRI2SwapInterval(drawable->pDraw, interval);
-
- return 0;
-}
-
-static void
-__glXDRIcontextDestroy(__GLXcontext *baseContext)
-{
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
-
- (*screen->core->destroyContext)(context->driContext);
- __glXContextDestroy(&context->base);
- free(context);
-}
-
-static int
-__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
-{
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
- __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
-
- return (*screen->core->bindContext)(context->driContext,
- draw->driDrawable,
- read->driDrawable);
-}
-
-static int
-__glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
-{
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
-
- return (*screen->core->unbindContext)(context->driContext);
-}
-
-static int
-__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
- unsigned long mask)
-{
- __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
- __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
-
- return (*screen->core->copyContext)(dst->driContext,
- src->driContext, mask);
-}
-
-static Bool
-__glXDRIcontextWait(__GLXcontext *baseContext,
- __GLXclientState *cl, int *error)
-{
- if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
- *error = cl->client->noClientException;
- return TRUE;
- }
-
- return FALSE;
-}
-
-#ifdef __DRI_TEX_BUFFER
-
-static int
-__glXDRIbindTexImage(__GLXcontext *baseContext,
- int buffer,
- __GLXdrawable *glxPixmap)
-{
- __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
- const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
-
- if (texBuffer == NULL)
- return Success;
-
-#if __DRI_TEX_BUFFER_VERSION >= 2
- if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
- (*texBuffer->setTexBuffer2)(context->driContext,
- glxPixmap->target,
- glxPixmap->format,
- drawable->driDrawable);
- } else
-#endif
- {
- texBuffer->setTexBuffer(context->driContext,
- glxPixmap->target,
- drawable->driDrawable);
- }
-
- return Success;
-}
-
-static int
-__glXDRIreleaseTexImage(__GLXcontext *baseContext,
- int buffer,
- __GLXdrawable *pixmap)
-{
- /* FIXME: Just unbind the texture? */
- return Success;
-}
-
-#else
-
-static int
-__glXDRIbindTexImage(__GLXcontext *baseContext,
- int buffer,
- __GLXdrawable *glxPixmap)
-{
- return Success;
-}
-
-static int
-__glXDRIreleaseTexImage(__GLXcontext *baseContext,
- int buffer,
- __GLXdrawable *pixmap)
-{
- return Success;
-}
-
-#endif
-
-static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
- __glXDRIbindTexImage,
- __glXDRIreleaseTexImage
-};
-
-static void
-__glXDRIscreenDestroy(__GLXscreen *baseScreen)
-{
- __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
-
- (*screen->core->destroyScreen)(screen->driScreen);
-
- dlclose(screen->driver);
-
- __glXScreenDestroy(baseScreen);
-
- free(screen);
-}
-
-static __GLXcontext *
-__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
- __GLXconfig *glxConfig,
- __GLXcontext *baseShareContext)
-{
- __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
- __GLXDRIcontext *context, *shareContext;
- __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
- __DRIcontext *driShare;
-
- shareContext = (__GLXDRIcontext *) baseShareContext;
- if (shareContext)
- driShare = shareContext->driContext;
- else
- driShare = NULL;
-
- context = calloc(1, sizeof *context);
- if (context == NULL)
- return NULL;
-
- context->base.destroy = __glXDRIcontextDestroy;
- context->base.makeCurrent = __glXDRIcontextMakeCurrent;
- context->base.loseCurrent = __glXDRIcontextLoseCurrent;
- context->base.copy = __glXDRIcontextCopy;
- context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
- context->base.wait = __glXDRIcontextWait;
-
- context->driContext =
- (*screen->dri2->createNewContext)(screen->driScreen,
- config->driConfig,
- driShare, context);
- if (context->driContext == NULL) {
- free(context);
- return NULL;
- }
-
- return &context->base;
-}
-
-static void
-__glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv)
-{
-#if __DRI2_FLUSH_VERSION >= 3
- __GLXDRIdrawable *private = priv;
- __GLXDRIscreen *screen = private->screen;
-
- if (screen->flush)
- (*screen->flush->invalidate)(private->driDrawable);
-#endif
-}
-
-static __GLXdrawable *
-__glXDRIscreenCreateDrawable(ClientPtr client,
- __GLXscreen *screen,
- DrawablePtr pDraw,
- XID drawId,
- int type,
- XID glxDrawId,
- __GLXconfig *glxConfig)
-{
- __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
- __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
- __GLXDRIdrawable *private;
-
- private = calloc(1, sizeof *private);
- if (private == NULL)
- return NULL;
-
- private->screen = driScreen;
- if (!__glXDrawableInit(&private->base, screen,
- pDraw, type, glxDrawId, glxConfig)) {
- free(private);
- return NULL;
- }
-
- private->base.destroy = __glXDRIdrawableDestroy;
- private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
- private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
- private->base.waitGL = __glXDRIdrawableWaitGL;
- private->base.waitX = __glXDRIdrawableWaitX;
-
- if (DRI2CreateDrawable(client, pDraw, drawId,
- __glXDRIinvalidateBuffers, private)) {
- free(private);
- return NULL;
- }
-
- private->driDrawable =
- (*driScreen->dri2->createNewDrawable)(driScreen->driScreen,
- config->driConfig, private);
-
- return &private->base;
-}
-
-static __DRIbuffer *
-dri2GetBuffers(__DRIdrawable *driDrawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *out_count, void *loaderPrivate)
-{
- __GLXDRIdrawable *private = loaderPrivate;
- DRI2BufferPtr *buffers;
- int i;
- int j;
-
- buffers = DRI2GetBuffers(private->base.pDraw,
- width, height, attachments, count, out_count);
- if (*out_count > MAX_DRAWABLE_BUFFERS) {
- *out_count = 0;
- return NULL;
- }
-
- private->width = *width;
- private->height = *height;
-
- /* This assumes the DRI2 buffer attachment tokens matches the
- * __DRIbuffer tokens. */
- j = 0;
- for (i = 0; i < *out_count; i++) {
- /* Do not send the real front buffer of a window to the client.
- */
- if ((private->base.pDraw->type == DRAWABLE_WINDOW)
- && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
- continue;
- }
-
- private->buffers[j].attachment = buffers[i]->attachment;
- private->buffers[j].name = buffers[i]->name;
- private->buffers[j].pitch = buffers[i]->pitch;
- private->buffers[j].cpp = buffers[i]->cpp;
- private->buffers[j].flags = buffers[i]->flags;
- j++;
- }
-
- *out_count = j;
- return private->buffers;
-}
-
-static __DRIbuffer *
-dri2GetBuffersWithFormat(__DRIdrawable *driDrawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *out_count, void *loaderPrivate)
-{
- __GLXDRIdrawable *private = loaderPrivate;
- DRI2BufferPtr *buffers;
- int i;
- int j = 0;
-
- buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
- width, height, attachments, count,
- out_count);
- if (*out_count > MAX_DRAWABLE_BUFFERS) {
- *out_count = 0;
- return NULL;
- }
-
- private->width = *width;
- private->height = *height;
-
- /* This assumes the DRI2 buffer attachment tokens matches the
- * __DRIbuffer tokens. */
- for (i = 0; i < *out_count; i++) {
- /* Do not send the real front buffer of a window to the client.
- */
- if ((private->base.pDraw->type == DRAWABLE_WINDOW)
- && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
- continue;
- }
-
- private->buffers[j].attachment = buffers[i]->attachment;
- private->buffers[j].name = buffers[i]->name;
- private->buffers[j].pitch = buffers[i]->pitch;
- private->buffers[j].cpp = buffers[i]->cpp;
- private->buffers[j].flags = buffers[i]->flags;
- j++;
- }
-
- *out_count = j;
- return private->buffers;
-}
-
-static void
-dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
-{
- (void) driDrawable;
- __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
-}
-
-static const __DRIdri2LoaderExtension loaderExtension = {
- { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
- dri2GetBuffers,
- dri2FlushFrontBuffer,
- dri2GetBuffersWithFormat,
-};
-
-#ifdef __DRI_USE_INVALIDATE
-static const __DRIuseInvalidateExtension dri2UseInvalidate = {
- { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION }
-};
-#endif
-
-static const __DRIextension *loader_extensions[] = {
- &systemTimeExtension.base,
- &loaderExtension.base,
-#ifdef __DRI_USE_INVALIDATE
- &dri2UseInvalidate.base,
-#endif
- NULL
-};
-
-static Bool
-glxDRIEnterVT (int index, int flags)
-{
- ScrnInfoPtr scrn = xf86Screens[index];
- Bool ret;
- __GLXDRIscreen *screen = (__GLXDRIscreen *)
- glxGetScreen(screenInfo.screens[index]);
-
- LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
-
- scrn->EnterVT = screen->enterVT;
-
- ret = scrn->EnterVT (index, flags);
-
- screen->enterVT = scrn->EnterVT;
- scrn->EnterVT = glxDRIEnterVT;
-
- if (!ret)
- return FALSE;
-
- glxResumeClients();
-
- return TRUE;
-}
-
-static void
-glxDRILeaveVT (int index, int flags)
-{
- ScrnInfoPtr scrn = xf86Screens[index];
- __GLXDRIscreen *screen = (__GLXDRIscreen *)
- glxGetScreen(screenInfo.screens[index]);
-
- LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
-
- glxSuspendClients();
-
- scrn->LeaveVT = screen->leaveVT;
- (*screen->leaveVT) (index, flags);
- screen->leaveVT = scrn->LeaveVT;
- scrn->LeaveVT = glxDRILeaveVT;
-}
-
-static void
-initializeExtensions(__GLXDRIscreen *screen)
-{
- ScreenPtr pScreen = screen->base.pScreen;
- const __DRIextension **extensions;
- int i;
-
- extensions = screen->core->getExtensions(screen->driScreen);
-
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_MESA_copy_sub_buffer");
- LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
-
- __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
- LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
-
- if (DRI2HasSwapControl(pScreen)) {
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_SGI_swap_control");
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_MESA_swap_control");
- LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
- }
-
- for (i = 0; extensions[i]; i++) {
-#ifdef __DRI_READ_DRAWABLE
- if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_SGI_make_current_read");
-
- LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
- }
-#endif
-
-#ifdef __DRI_TEX_BUFFER
- if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
- screen->texBuffer =
- (const __DRItexBufferExtension *) extensions[i];
- /* GLX_EXT_texture_from_pixmap is always enabled. */
- LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
- }
-#endif
-
-#ifdef __DRI2_FLUSH
- if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
- extensions[i]->version >= 3) {
- screen->flush = (__DRI2flushExtension *) extensions[i];
- }
-#endif
-
- /* Ignore unknown extensions */
- }
-}
-
-static __GLXscreen *
-__glXDRIscreenProbe(ScreenPtr pScreen)
-{
- const char *driverName, *deviceName;
- __GLXDRIscreen *screen;
- size_t buffer_size;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- const __DRIconfig **driConfigs;
-
- screen = calloc(1, sizeof *screen);
- if (screen == NULL)
- return NULL;
-
- if (!xf86LoaderCheckSymbol("DRI2Connect") ||
- !DRI2Connect(pScreen, DRI2DriverDRI,
- &screen->fd, &driverName, &deviceName)) {
- LogMessage(X_INFO,
- "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
- return NULL;
- }
-
- screen->base.destroy = __glXDRIscreenDestroy;
- screen->base.createContext = __glXDRIscreenCreateContext;
- screen->base.createDrawable = __glXDRIscreenCreateDrawable;
- screen->base.swapInterval = __glXDRIdrawableSwapInterval;
- screen->base.pScreen = pScreen;
-
- __glXInitExtensionEnableBits(screen->glx_enable_bits);
-
- screen->driver = glxProbeDriver(driverName, (void **)&screen->core, __DRI_CORE, 1,
- (void **)&screen->dri2, __DRI_DRI2, 1);
- if (screen->driver == NULL) {
- goto handle_error;
- }
-
- screen->driScreen =
- (*screen->dri2->createNewScreen)(pScreen->myNum,
- screen->fd,
- loader_extensions,
- &driConfigs,
- screen);
-
- if (screen->driScreen == NULL) {
- LogMessage(X_ERROR,
- "AIGLX error: Calling driver entry point failed\n");
- goto handle_error;
- }
-
- initializeExtensions(screen);
-
- screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs,
- GLX_WINDOW_BIT |
- GLX_PIXMAP_BIT |
- GLX_PBUFFER_BIT);
-
- __glXScreenInit(&screen->base, pScreen);
-
- /* The first call simply determines the length of the extension string.
- * This allows us to allocate some memory to hold the extension string,
- * but it requires that we call __glXGetExtensionString a second time.
- */
- buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
- if (buffer_size > 0) {
- free(screen->base.GLXextensions);
-
- screen->base.GLXextensions = xnfalloc(buffer_size);
- (void) __glXGetExtensionString(screen->glx_enable_bits,
- screen->base.GLXextensions);
- }
-
- /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled
- * drivers support the required extensions for GLX 1.4. The extensions
- * we're assuming are:
- *
- * - GLX_SGI_make_current_read (1.3)
- * - GLX_SGIX_fbconfig (1.3)
- * - GLX_SGIX_pbuffer (1.3)
- * - GLX_ARB_multisample (1.4)
- */
- screen->base.GLXmajor = 1;
- screen->base.GLXminor = 4;
-
- screen->enterVT = pScrn->EnterVT;
- pScrn->EnterVT = glxDRIEnterVT;
- screen->leaveVT = pScrn->LeaveVT;
- pScrn->LeaveVT = glxDRILeaveVT;
-
- LogMessage(X_INFO,
- "AIGLX: Loaded and initialized %s\n", driverName);
-
- return &screen->base;
-
- handle_error:
- if (screen->driver)
- dlclose(screen->driver);
-
- free(screen);
-
- LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
-
- return NULL;
-}
-
-_X_EXPORT __GLXprovider __glXDRI2Provider = {
- __glXDRIscreenProbe,
- "DRI2",
- NULL
-};
+/*
+ * Copyright © 2007 Red Hat, Inc
+ *
+ * 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, and that the name of Red Hat,
+ * Inc not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+
+#include <drm.h>
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+#include <GL/glxtokens.h>
+
+#include <windowstr.h>
+#include <os.h>
+
+#define _XF86DRI_SERVER_
+#include <xf86drm.h>
+#include <xf86.h>
+#include <dri2.h>
+
+#include "glxserver.h"
+#include "glxutil.h"
+#include "glxdricommon.h"
+
+#include "glapitable.h"
+#include "glapi.h"
+#include "glthread.h"
+#include "dispatch.h"
+#include "extension_string.h"
+
+typedef struct __GLXDRIscreen __GLXDRIscreen;
+typedef struct __GLXDRIcontext __GLXDRIcontext;
+typedef struct __GLXDRIdrawable __GLXDRIdrawable;
+
+struct __GLXDRIscreen {
+ __GLXscreen base;
+ __DRIscreen *driScreen;
+ void *driver;
+ int fd;
+
+ xf86EnterVTProc *enterVT;
+ xf86LeaveVTProc *leaveVT;
+
+ const __DRIcoreExtension *core;
+ const __DRIdri2Extension *dri2;
+ const __DRI2flushExtension *flush;
+ const __DRIcopySubBufferExtension *copySubBuffer;
+ const __DRIswapControlExtension *swapControl;
+ const __DRItexBufferExtension *texBuffer;
+
+ unsigned char glx_enable_bits[__GLX_EXT_BYTES];
+};
+
+struct __GLXDRIcontext {
+ __GLXcontext base;
+ __DRIcontext *driContext;
+};
+
+#define MAX_DRAWABLE_BUFFERS 5
+
+struct __GLXDRIdrawable {
+ __GLXdrawable base;
+ __DRIdrawable *driDrawable;
+ __GLXDRIscreen *screen;
+
+ /* Dimensions as last reported by DRI2GetBuffers. */
+ int width;
+ int height;
+ __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
+ int count;
+};
+
+static void
+__glXDRIdrawableDestroy(__GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+ const __DRIcoreExtension *core = private->screen->core;
+
+ (*core->destroyDrawable)(private->driDrawable);
+
+ __glXDrawableRelease(drawable);
+
+ free(private);
+}
+
+static void
+__glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
+ int x, int y, int w, int h)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = x;
+ box.y1 = private->height - y - h;
+ box.x2 = x + w;
+ box.y2 = private->height - y;
+ RegionInit(&region, &box, 0);
+
+ DRI2CopyRegion(drawable->pDraw, &region,
+ DRI2BufferFrontLeft, DRI2BufferBackLeft);
+}
+
+static void
+__glXDRIdrawableWaitX(__GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = private->width;
+ box.y2 = private->height;
+ RegionInit(&region, &box, 0);
+
+ DRI2CopyRegion(drawable->pDraw, &region,
+ DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+}
+
+static void
+__glXDRIdrawableWaitGL(__GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = private->width;
+ box.y2 = private->height;
+ RegionInit(&region, &box, 0);
+
+ DRI2CopyRegion(drawable->pDraw, &region,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+}
+
+static void
+__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
+ CARD64 msc, CARD64 sbc)
+{
+ __GLXdrawable *drawable = data;
+ xGLXBufferSwapComplete wire;
+
+ if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
+ return;
+
+ wire.type = __glXEventBase + GLX_BufferSwapComplete;
+ switch (type) {
+ case DRI2_EXCHANGE_COMPLETE:
+ wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+ break;
+ case DRI2_BLIT_COMPLETE:
+ wire.event_type = GLX_BLIT_COMPLETE_INTEL;
+ break;
+ case DRI2_FLIP_COMPLETE:
+ wire.event_type = GLX_FLIP_COMPLETE_INTEL;
+ break;
+ default:
+ /* unknown swap completion type */
+ wire.event_type = 0;
+ break;
+ }
+ wire.drawable = drawable->drawId;
+ wire.ust_hi = ust >> 32;
+ wire.ust_lo = ust & 0xffffffff;
+ wire.msc_hi = msc >> 32;
+ wire.msc_lo = msc & 0xffffffff;
+ wire.sbc_hi = sbc >> 32;
+ wire.sbc_lo = sbc & 0xffffffff;
+
+ WriteEventsToClient(client, 1, (xEvent *) &wire);
+}
+
+/*
+ * Copy or flip back to front, honoring the swap interval if possible.
+ *
+ * If the kernel supports it, we request an event for the frame when the
+ * swap should happen, then perform the copy when we receive it.
+ */
+static GLboolean
+__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
+ __GLXDRIscreen *screen = priv->screen;
+ CARD64 unused;
+
+#if __DRI2_FLUSH_VERSION >= 3
+ if (screen->flush) {
+ (*screen->flush->flush)(priv->driDrawable);
+ (*screen->flush->invalidate)(priv->driDrawable);
+ }
+#else
+ if (screen->flush)
+ (*screen->flush->flushInvalidate)(priv->driDrawable);
+#endif
+
+ if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
+ __glXdriSwapEvent, drawable->pDraw) != Success)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int
+__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
+{
+ if (interval <= 0) /* || interval > BIGNUM? */
+ return GLX_BAD_VALUE;
+
+ DRI2SwapInterval(drawable->pDraw, interval);
+
+ return 0;
+}
+
+static void
+__glXDRIcontextDestroy(__GLXcontext *baseContext)
+{
+ __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
+
+ (*screen->core->destroyContext)(context->driContext);
+ __glXContextDestroy(&context->base);
+ free(context);
+}
+
+static int
+__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
+{
+ __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
+ __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
+ __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
+
+ return (*screen->core->bindContext)(context->driContext,
+ draw->driDrawable,
+ read->driDrawable);
+}
+
+static int
+__glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
+{
+ __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
+
+ return (*screen->core->unbindContext)(context->driContext);
+}
+
+static int
+__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
+ unsigned long mask)
+{
+ __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
+ __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
+
+ return (*screen->core->copyContext)(dst->driContext,
+ src->driContext, mask);
+}
+
+static Bool
+__glXDRIcontextWait(__GLXcontext *baseContext,
+ __GLXclientState *cl, int *error)
+{
+ if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
+ *error = cl->client->noClientException;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#ifdef __DRI_TEX_BUFFER
+
+static int
+__glXDRIbindTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *glxPixmap)
+{
+ __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
+ const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
+ __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
+
+ if (texBuffer == NULL)
+ return Success;
+
+#if __DRI_TEX_BUFFER_VERSION >= 2
+ if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
+ (*texBuffer->setTexBuffer2)(context->driContext,
+ glxPixmap->target,
+ glxPixmap->format,
+ drawable->driDrawable);
+ } else
+#endif
+ {
+ texBuffer->setTexBuffer(context->driContext,
+ glxPixmap->target,
+ drawable->driDrawable);
+ }
+
+ return Success;
+}
+
+static int
+__glXDRIreleaseTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *pixmap)
+{
+ /* FIXME: Just unbind the texture? */
+ return Success;
+}
+
+#else
+
+static int
+__glXDRIbindTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *glxPixmap)
+{
+ return Success;
+}
+
+static int
+__glXDRIreleaseTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *pixmap)
+{
+ return Success;
+}
+
+#endif
+
+static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
+ __glXDRIbindTexImage,
+ __glXDRIreleaseTexImage
+};
+
+static void
+__glXDRIscreenDestroy(__GLXscreen *baseScreen)
+{
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
+
+ (*screen->core->destroyScreen)(screen->driScreen);
+
+ dlclose(screen->driver);
+
+ __glXScreenDestroy(baseScreen);
+
+ free(screen);
+}
+
+static __GLXcontext *
+__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
+ __GLXconfig *glxConfig,
+ __GLXcontext *baseShareContext)
+{
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
+ __GLXDRIcontext *context, *shareContext;
+ __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
+ __DRIcontext *driShare;
+
+ shareContext = (__GLXDRIcontext *) baseShareContext;
+ if (shareContext)
+ driShare = shareContext->driContext;
+ else
+ driShare = NULL;
+
+ context = calloc(1, sizeof *context);
+ if (context == NULL)
+ return NULL;
+
+ context->base.destroy = __glXDRIcontextDestroy;
+ context->base.makeCurrent = __glXDRIcontextMakeCurrent;
+ context->base.loseCurrent = __glXDRIcontextLoseCurrent;
+ context->base.copy = __glXDRIcontextCopy;
+ context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
+ context->base.wait = __glXDRIcontextWait;
+
+ context->driContext =
+ (*screen->dri2->createNewContext)(screen->driScreen,
+ config->driConfig,
+ driShare, context);
+ if (context->driContext == NULL) {
+ free(context);
+ return NULL;
+ }
+
+ return &context->base;
+}
+
+static void
+__glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv)
+{
+#if __DRI2_FLUSH_VERSION >= 3
+ __GLXDRIdrawable *private = priv;
+ __GLXDRIscreen *screen = private->screen;
+
+ if (screen->flush)
+ (*screen->flush->invalidate)(private->driDrawable);
+#endif
+}
+
+static __GLXdrawable *
+__glXDRIscreenCreateDrawable(ClientPtr client,
+ __GLXscreen *screen,
+ DrawablePtr pDraw,
+ XID drawId,
+ int type,
+ XID glxDrawId,
+ __GLXconfig *glxConfig)
+{
+ __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
+ __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
+ __GLXDRIdrawable *private;
+
+ private = calloc(1, sizeof *private);
+ if (private == NULL)
+ return NULL;
+
+ private->screen = driScreen;
+ if (!__glXDrawableInit(&private->base, screen,
+ pDraw, type, glxDrawId, glxConfig)) {
+ free(private);
+ return NULL;
+ }
+
+ private->base.destroy = __glXDRIdrawableDestroy;
+ private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
+ private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
+ private->base.waitGL = __glXDRIdrawableWaitGL;
+ private->base.waitX = __glXDRIdrawableWaitX;
+
+ if (DRI2CreateDrawable(client, pDraw, drawId,
+ __glXDRIinvalidateBuffers, private)) {
+ free(private);
+ return NULL;
+ }
+
+ private->driDrawable =
+ (*driScreen->dri2->createNewDrawable)(driScreen->driScreen,
+ config->driConfig, private);
+
+ return &private->base;
+}
+
+static __DRIbuffer *
+dri2GetBuffers(__DRIdrawable *driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
+{
+ __GLXDRIdrawable *private = loaderPrivate;
+ DRI2BufferPtr *buffers;
+ int i;
+ int j;
+
+ buffers = DRI2GetBuffers(private->base.pDraw,
+ width, height, attachments, count, out_count);
+ if (*out_count > MAX_DRAWABLE_BUFFERS) {
+ *out_count = 0;
+ return NULL;
+ }
+
+ private->width = *width;
+ private->height = *height;
+
+ /* This assumes the DRI2 buffer attachment tokens matches the
+ * __DRIbuffer tokens. */
+ j = 0;
+ for (i = 0; i < *out_count; i++) {
+ /* Do not send the real front buffer of a window to the client.
+ */
+ if ((private->base.pDraw->type == DRAWABLE_WINDOW)
+ && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
+ continue;
+ }
+
+ private->buffers[j].attachment = buffers[i]->attachment;
+ private->buffers[j].name = buffers[i]->name;
+ private->buffers[j].pitch = buffers[i]->pitch;
+ private->buffers[j].cpp = buffers[i]->cpp;
+ private->buffers[j].flags = buffers[i]->flags;
+ j++;
+ }
+
+ *out_count = j;
+ return private->buffers;
+}
+
+static __DRIbuffer *
+dri2GetBuffersWithFormat(__DRIdrawable *driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
+{
+ __GLXDRIdrawable *private = loaderPrivate;
+ DRI2BufferPtr *buffers;
+ int i;
+ int j = 0;
+
+ buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
+ width, height, attachments, count,
+ out_count);
+ if (*out_count > MAX_DRAWABLE_BUFFERS) {
+ *out_count = 0;
+ return NULL;
+ }
+
+ private->width = *width;
+ private->height = *height;
+
+ /* This assumes the DRI2 buffer attachment tokens matches the
+ * __DRIbuffer tokens. */
+ for (i = 0; i < *out_count; i++) {
+ /* Do not send the real front buffer of a window to the client.
+ */
+ if ((private->base.pDraw->type == DRAWABLE_WINDOW)
+ && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
+ continue;
+ }
+
+ private->buffers[j].attachment = buffers[i]->attachment;
+ private->buffers[j].name = buffers[i]->name;
+ private->buffers[j].pitch = buffers[i]->pitch;
+ private->buffers[j].cpp = buffers[i]->cpp;
+ private->buffers[j].flags = buffers[i]->flags;
+ j++;
+ }
+
+ *out_count = j;
+ return private->buffers;
+}
+
+static void
+dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
+{
+ (void) driDrawable;
+ __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
+}
+
+static const __DRIdri2LoaderExtension loaderExtension = {
+ { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
+ dri2GetBuffers,
+ dri2FlushFrontBuffer,
+ dri2GetBuffersWithFormat,
+};
+
+#ifdef __DRI_USE_INVALIDATE
+static const __DRIuseInvalidateExtension dri2UseInvalidate = {
+ { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION }
+};
+#endif
+
+static const __DRIextension *loader_extensions[] = {
+ &systemTimeExtension.base,
+ &loaderExtension.base,
+#ifdef __DRI_USE_INVALIDATE
+ &dri2UseInvalidate.base,
+#endif
+ NULL
+};
+
+static Bool
+glxDRIEnterVT (int index, int flags)
+{
+ ScrnInfoPtr scrn = xf86Screens[index];
+ Bool ret;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *)
+ glxGetScreen(screenInfo.screens[index]);
+
+ LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
+
+ scrn->EnterVT = screen->enterVT;
+
+ ret = scrn->EnterVT (index, flags);
+
+ screen->enterVT = scrn->EnterVT;
+ scrn->EnterVT = glxDRIEnterVT;
+
+ if (!ret)
+ return FALSE;
+
+ glxResumeClients();
+
+ return TRUE;
+}
+
+static void
+glxDRILeaveVT (int index, int flags)
+{
+ ScrnInfoPtr scrn = xf86Screens[index];
+ __GLXDRIscreen *screen = (__GLXDRIscreen *)
+ glxGetScreen(screenInfo.screens[index]);
+
+ LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
+
+ glxSuspendClients();
+
+ scrn->LeaveVT = screen->leaveVT;
+ (*screen->leaveVT) (index, flags);
+ screen->leaveVT = scrn->LeaveVT;
+ scrn->LeaveVT = glxDRILeaveVT;
+}
+
+static void
+initializeExtensions(__GLXDRIscreen *screen)
+{
+ ScreenPtr pScreen = screen->base.pScreen;
+ const __DRIextension **extensions;
+ int i;
+
+ extensions = screen->core->getExtensions(screen->driScreen);
+
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_MESA_copy_sub_buffer");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
+
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
+
+ if (DRI2HasSwapControl(pScreen)) {
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_SGI_swap_control");
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_MESA_swap_control");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
+ }
+
+ for (i = 0; extensions[i]; i++) {
+#ifdef __DRI_READ_DRAWABLE
+ if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_SGI_make_current_read");
+
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
+ }
+#endif
+
+#ifdef __DRI_TEX_BUFFER
+ if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
+ screen->texBuffer =
+ (const __DRItexBufferExtension *) extensions[i];
+ /* GLX_EXT_texture_from_pixmap is always enabled. */
+ LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
+ }
+#endif
+
+#ifdef __DRI2_FLUSH
+ if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
+ extensions[i]->version >= 3) {
+ screen->flush = (__DRI2flushExtension *) extensions[i];
+ }
+#endif
+
+ /* Ignore unknown extensions */
+ }
+}
+
+static __GLXscreen *
+__glXDRIscreenProbe(ScreenPtr pScreen)
+{
+ const char *driverName, *deviceName;
+ __GLXDRIscreen *screen;
+ size_t buffer_size;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ const __DRIconfig **driConfigs;
+
+ screen = calloc(1, sizeof *screen);
+ if (screen == NULL)
+ return NULL;
+
+ if (!xf86LoaderCheckSymbol("DRI2Connect") ||
+ !DRI2Connect(pScreen, DRI2DriverDRI,
+ &screen->fd, &driverName, &deviceName)) {
+ LogMessage(X_INFO,
+ "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
+ return NULL;
+ }
+
+ screen->base.destroy = __glXDRIscreenDestroy;
+ screen->base.createContext = __glXDRIscreenCreateContext;
+ screen->base.createDrawable = __glXDRIscreenCreateDrawable;
+ screen->base.swapInterval = __glXDRIdrawableSwapInterval;
+ screen->base.pScreen = pScreen;
+
+ __glXInitExtensionEnableBits(screen->glx_enable_bits);
+
+ screen->driver = glxProbeDriver(driverName, (void **)&screen->core, __DRI_CORE, 1,
+ (void **)&screen->dri2, __DRI_DRI2, 1);
+ if (screen->driver == NULL) {
+ goto handle_error;
+ }
+
+ screen->driScreen =
+ (*screen->dri2->createNewScreen)(pScreen->myNum,
+ screen->fd,
+ loader_extensions,
+ &driConfigs,
+ screen);
+
+ if (screen->driScreen == NULL) {
+ LogMessage(X_ERROR,
+ "AIGLX error: Calling driver entry point failed\n");
+ goto handle_error;
+ }
+
+ initializeExtensions(screen);
+
+ screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs,
+ GLX_WINDOW_BIT |
+ GLX_PIXMAP_BIT |
+ GLX_PBUFFER_BIT);
+
+ __glXScreenInit(&screen->base, pScreen);
+
+ /* The first call simply determines the length of the extension string.
+ * This allows us to allocate some memory to hold the extension string,
+ * but it requires that we call __glXGetExtensionString a second time.
+ */
+ buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
+ if (buffer_size > 0) {
+ free(screen->base.GLXextensions);
+
+ screen->base.GLXextensions = xnfalloc(buffer_size);
+ (void) __glXGetExtensionString(screen->glx_enable_bits,
+ screen->base.GLXextensions);
+ }
+
+ /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled
+ * drivers support the required extensions for GLX 1.4. The extensions
+ * we're assuming are:
+ *
+ * - GLX_SGI_make_current_read (1.3)
+ * - GLX_SGIX_fbconfig (1.3)
+ * - GLX_SGIX_pbuffer (1.3)
+ * - GLX_ARB_multisample (1.4)
+ */
+ screen->base.GLXmajor = 1;
+ screen->base.GLXminor = 4;
+
+ screen->enterVT = pScrn->EnterVT;
+ pScrn->EnterVT = glxDRIEnterVT;
+ screen->leaveVT = pScrn->LeaveVT;
+ pScrn->LeaveVT = glxDRILeaveVT;
+
+ LogMessage(X_INFO,
+ "AIGLX: Loaded and initialized %s\n", driverName);
+
+ return &screen->base;
+
+ handle_error:
+ if (screen->driver)
+ dlclose(screen->driver);
+
+ free(screen);
+
+ LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
+
+ return NULL;
+}
+
+_X_EXPORT __GLXprovider __glXDRI2Provider = {
+ __glXDRIscreenProbe,
+ "DRI2",
+ NULL
+};
diff --git a/xorg-server/glx/glxext.c b/xorg-server/glx/glxext.c
index 054ece76d..9cfc096c3 100644
--- a/xorg-server/glx/glxext.c
+++ b/xorg-server/glx/glxext.c
@@ -1,552 +1,556 @@
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. 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 including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * 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
- * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-#include "glxserver.h"
-#include <windowstr.h>
-#include <propertyst.h>
-#include <registry.h>
-#include "privates.h"
-#include <os.h>
-#include "unpack.h"
-#include "glxutil.h"
-#include "glxext.h"
-#include "indirect_table.h"
-#include "indirect_util.h"
-
-/*
-** The last context used by the server. It is the context that is current
-** from the server's perspective.
-*/
-__GLXcontext *__glXLastContext;
-
-/*
-** X resources.
-*/
-RESTYPE __glXContextRes;
-RESTYPE __glXDrawableRes;
-
-/*
-** Reply for most singles.
-*/
-xGLXSingleReply __glXReply;
-
-static DevPrivateKeyRec glxClientPrivateKeyRec;
-#define glxClientPrivateKey (&glxClientPrivateKeyRec)
-
-/*
-** Forward declarations.
-*/
-static int __glXDispatch(ClientPtr);
-
-/*
-** Called when the extension is reset.
-*/
-static void ResetExtension(ExtensionEntry* extEntry)
-{
- __glXFlushContextCache();
-}
-
-/*
-** Reset state used to keep track of large (multi-request) commands.
-*/
-void __glXResetLargeCommandStatus(__GLXclientState *cl)
-{
- cl->largeCmdBytesSoFar = 0;
- cl->largeCmdBytesTotal = 0;
- cl->largeCmdRequestsSoFar = 0;
- cl->largeCmdRequestsTotal = 0;
-}
-
-/*
-** This procedure is called when the client who created the context goes
-** away OR when glXDestroyContext is called. In either case, all we do is
-** flag that the ID is no longer valid, and (maybe) free the context.
-** use.
-*/
-static int ContextGone(__GLXcontext* cx, XID id)
-{
- cx->idExists = GL_FALSE;
- if (!cx->isCurrent) {
- __glXFreeContext(cx);
- }
-
- return True;
-}
-
-static __GLXcontext *glxPendingDestroyContexts;
-static __GLXcontext *glxAllContexts;
-static int glxServerLeaveCount;
-static int glxBlockClients;
-
-/*
-** Destroy routine that gets called when a drawable is freed. A drawable
-** contains the ancillary buffers needed for rendering.
-*/
-static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
-{
- __GLXcontext *c, *next;
-
- /* If this drawable was created using glx 1.3 drawable
- * constructors, we added it as a glx drawable resource under both
- * its glx drawable ID and it X drawable ID. Remove the other
- * resource now so we don't a callback for freed memory. */
- if (glxPriv->drawId != glxPriv->pDraw->id) {
- if (xid == glxPriv->drawId)
- FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE);
- else
- FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE);
- }
-
- for (c = glxAllContexts; c; c = next) {
- next = c->next;
- if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
- (*c->loseCurrent)(c);
- c->isCurrent = GL_FALSE;
- if (c == __glXLastContext)
- __glXFlushContextCache();
- }
- if (c->drawPriv == glxPriv)
- c->drawPriv = NULL;
- if (c->readPriv == glxPriv)
- c->readPriv = NULL;
- }
-
- glxPriv->destroy(glxPriv);
-
- return True;
-}
-
-void __glXAddToContextList(__GLXcontext *cx)
-{
- cx->next = glxAllContexts;
- glxAllContexts = cx;
-}
-
-static void __glXRemoveFromContextList(__GLXcontext *cx)
-{
- __GLXcontext *c, *prev;
-
- if (cx == glxAllContexts)
- glxAllContexts = cx->next;
- else {
- prev = glxAllContexts;
- for (c = glxAllContexts; c; c = c->next) {
- if (c == cx)
- prev->next = c->next;
- prev = c;
- }
- }
-}
-
-/*
-** Free a context.
-*/
-GLboolean __glXFreeContext(__GLXcontext *cx)
-{
- if (cx->idExists || cx->isCurrent) return GL_FALSE;
-
- free(cx->feedbackBuf);
- free(cx->selectBuf);
- if (cx == __glXLastContext) {
- __glXFlushContextCache();
- }
-
- __glXRemoveFromContextList(cx);
-
- /* We can get here through both regular dispatching from
- * __glXDispatch() or as a callback from the resource manager. In
- * the latter case we need to lift the DRI lock manually. */
-
- if (!glxBlockClients) {
- __glXleaveServer(GL_FALSE);
- cx->destroy(cx);
- __glXenterServer(GL_FALSE);
- } else {
- cx->next = glxPendingDestroyContexts;
- glxPendingDestroyContexts = cx;
- }
-
- return GL_TRUE;
-}
-
-/************************************************************************/
-
-/*
-** These routines can be used to check whether a particular GL command
-** has caused an error. Specifically, we use them to check whether a
-** given query has caused an error, in which case a zero-length data
-** reply is sent to the client.
-*/
-
-static GLboolean errorOccured = GL_FALSE;
-
-/*
-** The GL was will call this routine if an error occurs.
-*/
-void __glXErrorCallBack(GLenum code)
-{
- errorOccured = GL_TRUE;
-}
-
-/*
-** Clear the error flag before calling the GL command.
-*/
-void __glXClearErrorOccured(void)
-{
- errorOccured = GL_FALSE;
-}
-
-/*
-** Check if the GL command caused an error.
-*/
-GLboolean __glXErrorOccured(void)
-{
- return errorOccured;
-}
-
-static int __glXErrorBase;
-int __glXEventBase;
-
-int __glXError(int error)
-{
- return __glXErrorBase + error;
-}
-
-__GLXclientState *
-glxGetClient(ClientPtr pClient)
-{
- return dixLookupPrivate(&pClient->devPrivates, glxClientPrivateKey);
-}
-
-static void
-glxClientCallback (CallbackListPtr *list,
- pointer closure,
- pointer data)
-{
- NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
- ClientPtr pClient = clientinfo->client;
- __GLXclientState *cl = glxGetClient(pClient);
-
- switch (pClient->clientState) {
- case ClientStateRunning:
- /*
- ** By default, assume that the client supports
- ** GLX major version 1 minor version 0 protocol.
- */
- cl->GLClientmajorVersion = 1;
- cl->GLClientminorVersion = 0;
- cl->client = pClient;
- break;
-
- case ClientStateGone:
- free(cl->returnBuf);
- free(cl->largeCmdBuf);
- free(cl->GLClientextensions);
- break;
-
- default:
- break;
- }
-}
-
-/************************************************************************/
-
-static __GLXprovider *__glXProviderStack;
-
-void GlxPushProvider(__GLXprovider *provider)
-{
- provider->next = __glXProviderStack;
- __glXProviderStack = provider;
-}
-
-/*
-** Initialize the GLX extension.
-*/
-void GlxExtensionInit(void)
-{
- ExtensionEntry *extEntry;
- ScreenPtr pScreen;
- int i;
- __GLXprovider *p;
- Bool glx_provided = False;
-
- __glXContextRes = CreateNewResourceType((DeleteType)ContextGone,
- "GLXContext");
- __glXDrawableRes = CreateNewResourceType((DeleteType)DrawableGone,
- "GLXDrawable");
- if (!__glXContextRes || !__glXDrawableRes)
- return;
-
- if (!dixRegisterPrivateKey(&glxClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (__GLXclientState)))
- return;
- if (!AddCallback (&ClientStateCallback, glxClientCallback, 0))
- return;
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- pScreen = screenInfo.screens[i];
-
- for (p = __glXProviderStack; p != NULL; p = p->next) {
- __GLXscreen *glxScreen;
-
- glxScreen = p->screenProbe(pScreen);
- if (glxScreen != NULL) {
- if (glxScreen->GLXminor < glxMinorVersion)
- glxMinorVersion = glxScreen->GLXminor;
- LogMessage(X_INFO,
- "GLX: Initialized %s GL provider for screen %d\n",
- p->name, i);
- break;
- }
-
- }
-
- if (!p)
- LogMessage(X_INFO,
- "GLX: no usable GL providers found for screen %d\n", i);
- else
- glx_provided = True;
- }
-
- /* don't register extension if GL is not provided on any screen */
- if (!glx_provided)
- return;
-
- /*
- ** Add extension to server extensions.
- */
- extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS,
- __GLX_NUMBER_ERRORS, __glXDispatch,
- __glXDispatch, ResetExtension,
- StandardMinorOpcode);
- if (!extEntry) {
- FatalError("__glXExtensionInit: AddExtensions failed\n");
- return;
- }
- if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) {
- ErrorF("__glXExtensionInit: AddExtensionAlias failed\n");
- return;
- }
-
- __glXErrorBase = extEntry->errorBase;
- __glXEventBase = extEntry->eventBase;
-}
-
-/************************************************************************/
-
-void __glXFlushContextCache(void)
-{
- __glXLastContext = 0;
-}
-
-/*
-** Make a context the current one for the GL (in this implementation, there
-** is only one instance of the GL, and we use it to serve all GL clients by
-** switching it between different contexts). While we are at it, look up
-** a context by its tag and return its (__GLXcontext *).
-*/
-__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
- int *error)
-{
- __GLXcontext *cx;
-
- /*
- ** See if the context tag is legal; it is managed by the extension,
- ** so if it's invalid, we have an implementation error.
- */
- cx = __glXLookupContextByTag(cl, tag);
- if (!cx) {
- cl->client->errorValue = tag;
- *error = __glXError(GLXBadContextTag);
- return 0;
- }
-
- if (!cx->isDirect) {
- if (cx->drawPriv == NULL) {
- /*
- ** The drawable has vanished. It must be a window, because only
- ** windows can be destroyed from under us; GLX pixmaps are
- ** refcounted and don't go away until no one is using them.
- */
- *error = __glXError(GLXBadCurrentWindow);
- return 0;
- }
- }
-
- if (cx->wait && (*cx->wait)(cx, cl, error))
- return NULL;
-
- if (cx == __glXLastContext) {
- /* No need to re-bind */
- return cx;
- }
-
- /* Make this context the current one for the GL. */
- if (!cx->isDirect) {
- if (!(*cx->makeCurrent)(cx)) {
- /* Bind failed, and set the error code. Bummer */
- cl->client->errorValue = cx->id;
- *error = __glXError(GLXBadContextState);
- return 0;
- }
- }
- __glXLastContext = cx;
- return cx;
-}
-
-/************************************************************************/
-
-void glxSuspendClients(void)
-{
- int i;
-
- for (i = 1; i < currentMaxClients; i++) {
- if (clients[i] && glxGetClient(clients[i])->inUse)
- IgnoreClient(clients[i]);
- }
-
- glxBlockClients = TRUE;
-}
-
-void glxResumeClients(void)
-{
- __GLXcontext *cx, *next;
- int i;
-
- glxBlockClients = FALSE;
-
- for (i = 1; i < currentMaxClients; i++) {
- if (clients[i] && glxGetClient(clients[i])->inUse)
- AttendClient(clients[i]);
- }
-
- __glXleaveServer(GL_FALSE);
- for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
- next = cx->next;
-
- cx->destroy(cx);
- }
- glxPendingDestroyContexts = NULL;
- __glXenterServer(GL_FALSE);
-}
-
-static void
-__glXnopEnterServer(GLboolean rendering)
-{
-}
-
-static void
-__glXnopLeaveServer(GLboolean rendering)
-{
-}
-
-static void (*__glXenterServerFunc)(GLboolean) = __glXnopEnterServer;
-static void (*__glXleaveServerFunc)(GLboolean) = __glXnopLeaveServer;
-
-void __glXsetEnterLeaveServerFuncs(void (*enter)(GLboolean),
- void (*leave)(GLboolean))
-{
- __glXenterServerFunc = enter;
- __glXleaveServerFunc = leave;
-}
-
-
-void __glXenterServer(GLboolean rendering)
-{
- glxServerLeaveCount--;
-
- if (glxServerLeaveCount == 0)
- (*__glXenterServerFunc)(rendering);
-}
-
-void __glXleaveServer(GLboolean rendering)
-{
- if (glxServerLeaveCount == 0)
- (*__glXleaveServerFunc)(rendering);
-
- glxServerLeaveCount++;
-}
-
-/*
-** Top level dispatcher; all commands are executed from here down.
-*/
-static int __glXDispatch(ClientPtr client)
-{
- REQUEST(xGLXSingleReq);
- CARD8 opcode;
- __GLXdispatchSingleProcPtr proc;
- __GLXclientState *cl;
- int retval;
-
- opcode = stuff->glxCode;
- cl = glxGetClient(client);
- /* Mark it in use so we suspend it on VT switch. */
- cl->inUse = TRUE;
-
- /*
- ** If we're expecting a glXRenderLarge request, this better be one.
- */
- if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) {
- client->errorValue = stuff->glxCode;
- return __glXError(GLXBadLargeRequest);
- }
-
- /* If we're currently blocking GLX clients, just put this guy to
- * sleep, reset the request and return. */
- if (glxBlockClients) {
- ResetCurrentRequest(client);
- client->sequence--;
- IgnoreClient(client);
- return Success;
- }
-
- /*
- ** Use the opcode to index into the procedure table.
- */
- proc = __glXGetProtocolDecodeFunction(& Single_dispatch_info, opcode,
- client->swapped);
- if (proc != NULL) {
- GLboolean rendering = opcode <= X_GLXRenderLarge;
- __glXleaveServer(rendering);
-
- retval = (*proc)(cl, (GLbyte *) stuff);
-
- __glXenterServer(rendering);
- }
- else {
- retval = BadRequest;
- }
-
- return retval;
-}
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+#include "glxserver.h"
+#include <windowstr.h>
+#include <propertyst.h>
+#include <registry.h>
+#include "privates.h"
+#include <os.h>
+#include "unpack.h"
+#include "glxutil.h"
+#include "glxext.h"
+#include "indirect_table.h"
+#include "indirect_util.h"
+
+/*
+** The last context used by the server. It is the context that is current
+** from the server's perspective.
+*/
+__GLXcontext *__glXLastContext;
+
+/*
+** X resources.
+*/
+RESTYPE __glXContextRes;
+RESTYPE __glXDrawableRes;
+
+/*
+** Reply for most singles.
+*/
+xGLXSingleReply __glXReply;
+
+static DevPrivateKeyRec glxClientPrivateKeyRec;
+#define glxClientPrivateKey (&glxClientPrivateKeyRec)
+
+/*
+** Forward declarations.
+*/
+static int __glXDispatch(ClientPtr);
+
+/*
+** Called when the extension is reset.
+*/
+static void ResetExtension(ExtensionEntry* extEntry)
+{
+ __glXFlushContextCache();
+}
+
+/*
+** Reset state used to keep track of large (multi-request) commands.
+*/
+void __glXResetLargeCommandStatus(__GLXclientState *cl)
+{
+ cl->largeCmdBytesSoFar = 0;
+ cl->largeCmdBytesTotal = 0;
+ cl->largeCmdRequestsSoFar = 0;
+ cl->largeCmdRequestsTotal = 0;
+}
+
+/*
+** This procedure is called when the client who created the context goes
+** away OR when glXDestroyContext is called. In either case, all we do is
+** flag that the ID is no longer valid, and (maybe) free the context.
+** use.
+*/
+static int ContextGone(__GLXcontext* cx, XID id)
+{
+ cx->idExists = GL_FALSE;
+ if (!cx->isCurrent) {
+ __glXFreeContext(cx);
+ }
+
+ return True;
+}
+
+static __GLXcontext *glxPendingDestroyContexts;
+static __GLXcontext *glxAllContexts;
+static int glxServerLeaveCount;
+static int glxBlockClients;
+
+/*
+** Destroy routine that gets called when a drawable is freed. A drawable
+** contains the ancillary buffers needed for rendering.
+*/
+static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
+{
+ __GLXcontext *c, *next;
+
+ if (glxPriv->type == GLX_DRAWABLE_WINDOW) {
+ /* If this was created by glXCreateWindow, free the matching resource */
+ if (glxPriv->drawId != glxPriv->pDraw->id) {
+ if (xid == glxPriv->drawId)
+ FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE);
+ else
+ FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE);
+ }
+ /* otherwise this window was implicitly created by MakeCurrent */
+ }
+
+ for (c = glxAllContexts; c; c = next) {
+ next = c->next;
+ if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
+ (*c->loseCurrent)(c);
+ c->isCurrent = GL_FALSE;
+ if (c == __glXLastContext)
+ __glXFlushContextCache();
+ }
+ if (c->drawPriv == glxPriv)
+ c->drawPriv = NULL;
+ if (c->readPriv == glxPriv)
+ c->readPriv = NULL;
+ }
+
+ /* drop our reference to any backing pixmap */
+ if (glxPriv->type == GLX_DRAWABLE_PIXMAP)
+ glxPriv->pDraw->pScreen->DestroyPixmap((PixmapPtr)glxPriv->pDraw);
+
+ glxPriv->destroy(glxPriv);
+
+ return True;
+}
+
+void __glXAddToContextList(__GLXcontext *cx)
+{
+ cx->next = glxAllContexts;
+ glxAllContexts = cx;
+}
+
+static void __glXRemoveFromContextList(__GLXcontext *cx)
+{
+ __GLXcontext *c, *prev;
+
+ if (cx == glxAllContexts)
+ glxAllContexts = cx->next;
+ else {
+ prev = glxAllContexts;
+ for (c = glxAllContexts; c; c = c->next) {
+ if (c == cx)
+ prev->next = c->next;
+ prev = c;
+ }
+ }
+}
+
+/*
+** Free a context.
+*/
+GLboolean __glXFreeContext(__GLXcontext *cx)
+{
+ if (cx->idExists || cx->isCurrent) return GL_FALSE;
+
+ free(cx->feedbackBuf);
+ free(cx->selectBuf);
+ if (cx == __glXLastContext) {
+ __glXFlushContextCache();
+ }
+
+ __glXRemoveFromContextList(cx);
+
+ /* We can get here through both regular dispatching from
+ * __glXDispatch() or as a callback from the resource manager. In
+ * the latter case we need to lift the DRI lock manually. */
+
+ if (!glxBlockClients) {
+ __glXleaveServer(GL_FALSE);
+ cx->destroy(cx);
+ __glXenterServer(GL_FALSE);
+ } else {
+ cx->next = glxPendingDestroyContexts;
+ glxPendingDestroyContexts = cx;
+ }
+
+ return GL_TRUE;
+}
+
+/************************************************************************/
+
+/*
+** These routines can be used to check whether a particular GL command
+** has caused an error. Specifically, we use them to check whether a
+** given query has caused an error, in which case a zero-length data
+** reply is sent to the client.
+*/
+
+static GLboolean errorOccured = GL_FALSE;
+
+/*
+** The GL was will call this routine if an error occurs.
+*/
+void __glXErrorCallBack(GLenum code)
+{
+ errorOccured = GL_TRUE;
+}
+
+/*
+** Clear the error flag before calling the GL command.
+*/
+void __glXClearErrorOccured(void)
+{
+ errorOccured = GL_FALSE;
+}
+
+/*
+** Check if the GL command caused an error.
+*/
+GLboolean __glXErrorOccured(void)
+{
+ return errorOccured;
+}
+
+static int __glXErrorBase;
+int __glXEventBase;
+
+int __glXError(int error)
+{
+ return __glXErrorBase + error;
+}
+
+__GLXclientState *
+glxGetClient(ClientPtr pClient)
+{
+ return dixLookupPrivate(&pClient->devPrivates, glxClientPrivateKey);
+}
+
+static void
+glxClientCallback (CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ __GLXclientState *cl = glxGetClient(pClient);
+
+ switch (pClient->clientState) {
+ case ClientStateRunning:
+ /*
+ ** By default, assume that the client supports
+ ** GLX major version 1 minor version 0 protocol.
+ */
+ cl->GLClientmajorVersion = 1;
+ cl->GLClientminorVersion = 0;
+ cl->client = pClient;
+ break;
+
+ case ClientStateGone:
+ free(cl->returnBuf);
+ free(cl->largeCmdBuf);
+ free(cl->GLClientextensions);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/************************************************************************/
+
+static __GLXprovider *__glXProviderStack;
+
+void GlxPushProvider(__GLXprovider *provider)
+{
+ provider->next = __glXProviderStack;
+ __glXProviderStack = provider;
+}
+
+/*
+** Initialize the GLX extension.
+*/
+void GlxExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ ScreenPtr pScreen;
+ int i;
+ __GLXprovider *p;
+ Bool glx_provided = False;
+
+ __glXContextRes = CreateNewResourceType((DeleteType)ContextGone,
+ "GLXContext");
+ __glXDrawableRes = CreateNewResourceType((DeleteType)DrawableGone,
+ "GLXDrawable");
+ if (!__glXContextRes || !__glXDrawableRes)
+ return;
+
+ if (!dixRegisterPrivateKey(&glxClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (__GLXclientState)))
+ return;
+ if (!AddCallback (&ClientStateCallback, glxClientCallback, 0))
+ return;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+
+ for (p = __glXProviderStack; p != NULL; p = p->next) {
+ __GLXscreen *glxScreen;
+
+ glxScreen = p->screenProbe(pScreen);
+ if (glxScreen != NULL) {
+ if (glxScreen->GLXminor < glxMinorVersion)
+ glxMinorVersion = glxScreen->GLXminor;
+ LogMessage(X_INFO,
+ "GLX: Initialized %s GL provider for screen %d\n",
+ p->name, i);
+ break;
+ }
+
+ }
+
+ if (!p)
+ LogMessage(X_INFO,
+ "GLX: no usable GL providers found for screen %d\n", i);
+ else
+ glx_provided = True;
+ }
+
+ /* don't register extension if GL is not provided on any screen */
+ if (!glx_provided)
+ return;
+
+ /*
+ ** Add extension to server extensions.
+ */
+ extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS,
+ __GLX_NUMBER_ERRORS, __glXDispatch,
+ __glXDispatch, ResetExtension,
+ StandardMinorOpcode);
+ if (!extEntry) {
+ FatalError("__glXExtensionInit: AddExtensions failed\n");
+ return;
+ }
+ if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) {
+ ErrorF("__glXExtensionInit: AddExtensionAlias failed\n");
+ return;
+ }
+
+ __glXErrorBase = extEntry->errorBase;
+ __glXEventBase = extEntry->eventBase;
+}
+
+/************************************************************************/
+
+void __glXFlushContextCache(void)
+{
+ __glXLastContext = 0;
+}
+
+/*
+** Make a context the current one for the GL (in this implementation, there
+** is only one instance of the GL, and we use it to serve all GL clients by
+** switching it between different contexts). While we are at it, look up
+** a context by its tag and return its (__GLXcontext *).
+*/
+__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
+ int *error)
+{
+ __GLXcontext *cx;
+
+ /*
+ ** See if the context tag is legal; it is managed by the extension,
+ ** so if it's invalid, we have an implementation error.
+ */
+ cx = __glXLookupContextByTag(cl, tag);
+ if (!cx) {
+ cl->client->errorValue = tag;
+ *error = __glXError(GLXBadContextTag);
+ return 0;
+ }
+
+ if (!cx->isDirect) {
+ if (cx->drawPriv == NULL) {
+ /*
+ ** The drawable has vanished. It must be a window, because only
+ ** windows can be destroyed from under us; GLX pixmaps are
+ ** refcounted and don't go away until no one is using them.
+ */
+ *error = __glXError(GLXBadCurrentWindow);
+ return 0;
+ }
+ }
+
+ if (cx->wait && (*cx->wait)(cx, cl, error))
+ return NULL;
+
+ if (cx == __glXLastContext) {
+ /* No need to re-bind */
+ return cx;
+ }
+
+ /* Make this context the current one for the GL. */
+ if (!cx->isDirect) {
+ if (!(*cx->makeCurrent)(cx)) {
+ /* Bind failed, and set the error code. Bummer */
+ cl->client->errorValue = cx->id;
+ *error = __glXError(GLXBadContextState);
+ return 0;
+ }
+ }
+ __glXLastContext = cx;
+ return cx;
+}
+
+/************************************************************************/
+
+void glxSuspendClients(void)
+{
+ int i;
+
+ for (i = 1; i < currentMaxClients; i++) {
+ if (clients[i] && glxGetClient(clients[i])->inUse)
+ IgnoreClient(clients[i]);
+ }
+
+ glxBlockClients = TRUE;
+}
+
+void glxResumeClients(void)
+{
+ __GLXcontext *cx, *next;
+ int i;
+
+ glxBlockClients = FALSE;
+
+ for (i = 1; i < currentMaxClients; i++) {
+ if (clients[i] && glxGetClient(clients[i])->inUse)
+ AttendClient(clients[i]);
+ }
+
+ __glXleaveServer(GL_FALSE);
+ for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
+ next = cx->next;
+
+ cx->destroy(cx);
+ }
+ glxPendingDestroyContexts = NULL;
+ __glXenterServer(GL_FALSE);
+}
+
+static void
+__glXnopEnterServer(GLboolean rendering)
+{
+}
+
+static void
+__glXnopLeaveServer(GLboolean rendering)
+{
+}
+
+static void (*__glXenterServerFunc)(GLboolean) = __glXnopEnterServer;
+static void (*__glXleaveServerFunc)(GLboolean) = __glXnopLeaveServer;
+
+void __glXsetEnterLeaveServerFuncs(void (*enter)(GLboolean),
+ void (*leave)(GLboolean))
+{
+ __glXenterServerFunc = enter;
+ __glXleaveServerFunc = leave;
+}
+
+
+void __glXenterServer(GLboolean rendering)
+{
+ glxServerLeaveCount--;
+
+ if (glxServerLeaveCount == 0)
+ (*__glXenterServerFunc)(rendering);
+}
+
+void __glXleaveServer(GLboolean rendering)
+{
+ if (glxServerLeaveCount == 0)
+ (*__glXleaveServerFunc)(rendering);
+
+ glxServerLeaveCount++;
+}
+
+/*
+** Top level dispatcher; all commands are executed from here down.
+*/
+static int __glXDispatch(ClientPtr client)
+{
+ REQUEST(xGLXSingleReq);
+ CARD8 opcode;
+ __GLXdispatchSingleProcPtr proc;
+ __GLXclientState *cl;
+ int retval;
+
+ opcode = stuff->glxCode;
+ cl = glxGetClient(client);
+ /* Mark it in use so we suspend it on VT switch. */
+ cl->inUse = TRUE;
+
+ /*
+ ** If we're expecting a glXRenderLarge request, this better be one.
+ */
+ if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) {
+ client->errorValue = stuff->glxCode;
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ /* If we're currently blocking GLX clients, just put this guy to
+ * sleep, reset the request and return. */
+ if (glxBlockClients) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ IgnoreClient(client);
+ return Success;
+ }
+
+ /*
+ ** Use the opcode to index into the procedure table.
+ */
+ proc = __glXGetProtocolDecodeFunction(& Single_dispatch_info, opcode,
+ client->swapped);
+ if (proc != NULL) {
+ GLboolean rendering = opcode <= X_GLXRenderLarge;
+ __glXleaveServer(rendering);
+
+ retval = (*proc)(cl, (GLbyte *) stuff);
+
+ __glXenterServer(rendering);
+ }
+ else {
+ retval = BadRequest;
+ }
+
+ return retval;
+}
diff --git a/xorg-server/hw/dmx/input/dmxevents.c b/xorg-server/hw/dmx/input/dmxevents.c
index efcd07da3..15d80f5bb 100644
--- a/xorg-server/hw/dmx/input/dmxevents.c
+++ b/xorg-server/hw/dmx/input/dmxevents.c
@@ -1,800 +1,800 @@
-/*
- * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
- *
- * 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 on 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 (including the
- * next paragraph) 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- * Provide support and helper functions for enqueing events received by
- * the low-level input drivers. */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#define DMX_EVENTS_DEBUG 0
-
-#include "dmxinputinit.h"
-#include "dmxevents.h"
-#include "dmxcb.h"
-#include "dmxcommon.h"
-#include "dmxcursor.h"
-#include "dmxmotion.h"
-#include "dmxsigio.h"
-#include "dmxmap.h"
-
-#include <X11/keysym.h>
-#include "opaque.h"
-#include "inputstr.h"
-#include "inpututils.h"
-#include "mipointer.h"
-#include "mi.h"
-#include "exglobals.h"
-
-#include "xkbsrv.h"
-#include "XIstubs.h"
-
-static int dmxGlobalX, dmxGlobalY; /* Global cursor position */
-static int dmxGlobalInvalid; /* Flag indicating dmxCoreMotion
- * should move the mouse anyway. */
-
-#if DMX_EVENTS_DEBUG
-#define DMXDBG0(f) dmxLog(dmxDebug,f)
-#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
-#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
-#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
-#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
-#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
-#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
-#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
-#else
-#define DMXDBG0(f)
-#define DMXDBG1(f,a)
-#define DMXDBG2(f,a,b)
-#define DMXDBG3(f,a,b,c)
-#define DMXDBG4(f,a,b,c,d)
-#define DMXDBG5(f,a,b,c,d,e)
-#define DMXDBG6(f,a,b,c,d,e,g)
-#define DMXDBG7(f,a,b,c,d,e,g,h)
-#endif
-
-static int dmxApplyFunctions(DMXInputInfo *dmxInput, DMXFunctionType f)
-{
- int i;
- int rc = 0;
-
- for (i = 0; i < dmxInput->numDevs; i+= dmxInput->devs[i]->binding)
- if (dmxInput->devs[i]->functions)
- rc += dmxInput->devs[i]->functions(dmxInput->devs[i]->private, f);
- return rc;
-}
-
-static int dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal,
- int type,
- KeySym keySym)
-{
- DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
-
-#if 1 /* hack to detect ctrl-alt-q, etc */
- static int ctrl = 0, alt = 0;
- /* keep track of ctrl/alt key status */
- if (type == KeyPress && keySym == 0xffe3) {
- ctrl = 1;
- }
- else if (type == KeyRelease && keySym == 0xffe3) {
- ctrl = 0;
- }
- else if (type == KeyPress && keySym == 0xffe9) {
- alt = 1;
- }
- else if (type == KeyRelease && keySym == 0xffe9) {
- alt = 0;
- }
- if (!ctrl || !alt)
- return 0;
-#else
- unsigned short state = 0;
-
- if (dmxLocal->sendsCore)
- state = dmxLocalCoreKeyboard->pDevice->key->state;
- else if (dmxLocal->pDevice->key)
- state = dmxLocal->pDevice->key->state;
-
- DMXDBG3("dmxCheckFunctionKeys: keySym=0x%04x %s state=0x%04x\n",
- keySym, type == KeyPress ? "press" : "release", state);
-
- if ((state & (ControlMask|Mod1Mask)) != (ControlMask|Mod1Mask))
- return 0;
-#endif
-
- switch (keySym) {
- case XK_g:
- if (type == KeyPress)
- dmxApplyFunctions(dmxInput, DMX_FUNCTION_GRAB);
- return 1;
- case XK_f:
- if (type == KeyPress)
- dmxApplyFunctions(dmxInput, DMX_FUNCTION_FINE);
- return 1;
- case XK_q:
- if (type == KeyPress && dmxLocal->sendsCore)
- if (dmxApplyFunctions(dmxInput, DMX_FUNCTION_TERMINATE)) {
- dmxLog(dmxInfo, "User request for termination\n");
- dispatchException |= DE_TERMINATE;
- }
- return 1;
- }
-
- return 0;
-}
-
-
-DMXScreenInfo *dmxFindFirstScreen(int x, int y)
-{
- int i;
-
- for (i = 0; i < dmxNumScreens; i++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[i];
- if (dmxOnScreen(x, y, dmxScreen))
- return dmxScreen;
- }
- return NULL;
-}
-
-
-/**
- * Enqueue a motion event.
- */
-static void enqueueMotion(DevicePtr pDev, int x, int y)
-{
- GETDMXLOCALFROMPDEV;
- DeviceIntPtr p = dmxLocal->pDevice;
- int i, nevents, valuators[3];
- EventListPtr events;
- int detail = 0; /* XXX should this be mask of pressed buttons? */
- ValuatorMask mask;
- valuators[0] = x;
- valuators[1] = y;
-
- valuator_mask_set_range(&mask, 0, 2, valuators);
- GetEventList(&events);
- nevents = GetPointerEvents(events, p, MotionNotify, detail,
- POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(p, (InternalEvent*)(events + i)->event);
- return;
-}
-
-
-void
-dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block)
-{
- DMXScreenInfo *dmxScreen;
- DMXInputInfo *dmxInput;
- ScreenPtr pScreen;
- int localX;
- int localY;
- int i;
-
- if (!dmxGlobalInvalid && dmxGlobalX == x && dmxGlobalY == y)
- return;
-
- DMXDBG5("dmxCoreMotion(%d,%d,%d) dmxGlobalX=%d dmxGlobalY=%d\n",
- x, y, delta, dmxGlobalX, dmxGlobalY);
-
- dmxGlobalInvalid = 0;
- dmxGlobalX = x;
- dmxGlobalY = y;
-
- if (dmxGlobalX < 0)
- dmxGlobalX = 0;
- if (dmxGlobalY < 0)
- dmxGlobalY = 0;
- if (dmxGlobalX >= dmxGlobalWidth)
- dmxGlobalX = dmxGlobalWidth + delta -1;
- if (dmxGlobalY >= dmxGlobalHeight)
- dmxGlobalY = dmxGlobalHeight + delta -1;
-
- if ((dmxScreen = dmxFindFirstScreen(dmxGlobalX, dmxGlobalY))) {
- localX = dmxGlobalX - dmxScreen->rootXOrigin;
- localY = dmxGlobalY - dmxScreen->rootYOrigin;
- if ((pScreen = miPointerGetScreen(inputInfo.pointer))
- && pScreen->myNum == dmxScreen->index) {
- /* Screen is old screen */
- if (block)
- dmxSigioBlock();
- if (pDev)
- enqueueMotion(pDev, localX, localY);
- if (block)
- dmxSigioUnblock();
- } else {
- /* Screen is new */
- DMXDBG4(" New screen: old=%d new=%d localX=%d localY=%d\n",
- pScreen->myNum, dmxScreen->index, localX, localY);
- if (block)
- dmxSigioBlock();
- mieqProcessInputEvents();
- miPointerSetScreen(inputInfo.pointer, dmxScreen->index,
- localX, localY);
- if (pDev)
- enqueueMotion(pDev, localX, localY);
- if (block)
- dmxSigioUnblock();
- }
-#if 00
- miPointerGetPosition(inputInfo.pointer, &localX, &localY);
-
- if ((pScreen = miPointerGetScreen(inputInfo.pointer))) {
- dmxGlobalX = localX + dmxScreens[pScreen->myNum].rootXOrigin;
- dmxGlobalY = localY + dmxScreens[pScreen->myNum].rootYOrigin;
- ErrorF("Global is now %d, %d %d, %d\n", dmxGlobalX, dmxGlobalY,
- localX, localY);
- DMXDBG6(" Moved to dmxGlobalX=%d dmxGlobalY=%d"
- " on screen index=%d/%d localX=%d localY=%d\n",
- dmxGlobalX, dmxGlobalY,
- dmxScreen ? dmxScreen->index : -1, pScreen->myNum,
- localX, localY);
- }
-#endif
- }
- /* Send updates down to all core input
- * drivers */
- for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) {
- int j;
- for (j = 0; j < dmxInput->numDevs; j += dmxInput->devs[j]->binding)
- if (!dmxInput->detached
- && dmxInput->devs[j]->sendsCore
- && dmxInput->devs[j]->update_position)
- dmxInput->devs[j]->update_position(dmxInput->devs[j]->private,
- dmxGlobalX, dmxGlobalY);
- }
- if (!dmxScreen) ProcessInputEvents();
-}
-
-
-
-#define DMX_MAX_AXES 32 /* Max axes reported by this routine */
-static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
- int *v, int firstAxis, int axesCount,
- DMXMotionType type, DMXBlockType block)
-{
- DeviceIntPtr pDevice = dmxLocal->pDevice;
- xEvent xE[2 * DMX_MAX_AXES/6];
- deviceKeyButtonPointer *xev = (deviceKeyButtonPointer *)xE;
- deviceValuator *xv = (deviceValuator *)xev+1;
- int thisX = 0;
- int thisY = 0;
- int i;
- int count;
- EventListPtr events;
- int nevents;
- ValuatorMask mask;
-
- memset(xE, 0, sizeof(xE));
-
- if (axesCount > DMX_MAX_AXES) axesCount = DMX_MAX_AXES;
-
- if ((valuator_get_mode(pDevice,0) == Relative) && axesCount == 2) {
- /* The dmx console is a relative mode
- * device that sometimes reports
- * absolute motion. It only has two
- * axes. */
- if (type == DMX_RELATIVE) {
- thisX = -v[0];
- thisY = -v[1];
- dmxLocal->lastX += thisX;
- dmxLocal->lastY += thisY;
- if (dmxLocal->update_position)
- dmxLocal->update_position(dmxLocal->private,
- dmxLocal->lastX, dmxLocal->lastY);
- } else { /* Convert to relative */
- if (dmxLocal->lastX || dmxLocal->lastY) {
- thisX = v[0] - dmxLocal->lastX;
- thisY = v[1] - dmxLocal->lastY;
- }
- dmxLocal->lastX = v[0];
- dmxLocal->lastY = v[1];
- }
- v[0] = thisX;
- v[1] = thisY;
- }
-
- if (axesCount <= 6) {
- /* Optimize for the common case when
- * only 1 or 2 axes change. */
- xev->time = GetTimeInMillis();
- xev->type = DeviceMotionNotify;
- xev->detail = 0;
- xev->deviceid = pDevice->id | MORE_EVENTS;
-
- xv->type = DeviceValuator;
- xv->deviceid = pDevice->id;
- xv->num_valuators = axesCount;
- xv->first_valuator = firstAxis;
- switch (xv->num_valuators) {
- case 6: xv->valuator5 = v[5];
- case 5: xv->valuator4 = v[4];
- case 4: xv->valuator3 = v[3];
- case 3: xv->valuator2 = v[2];
- case 2: xv->valuator1 = v[1];
- case 1: xv->valuator0 = v[0];
- }
- count = 2;
- } else {
- for (i = 0, count = 0; i < axesCount; i += 6) {
- xev->time = GetTimeInMillis();
- xev->type = DeviceMotionNotify;
- xev->detail = 0;
- xev->deviceid = pDevice->id | MORE_EVENTS;
- xev += 2;
-
- xv->type = DeviceValuator;
- xv->deviceid = pDevice->id;
- xv->num_valuators = (i+6 >= axesCount ? axesCount - i : 6);
- xv->first_valuator = firstAxis + i;
- switch (xv->num_valuators) {
- case 6: xv->valuator5 = v[i+5];
- case 5: xv->valuator4 = v[i+4];
- case 4: xv->valuator3 = v[i+3];
- case 3: xv->valuator2 = v[i+2];
- case 2: xv->valuator1 = v[i+1];
- case 1: xv->valuator0 = v[i+0];
- }
- xv += 2;
- count += 2;
- }
- }
-
- if (block)
- dmxSigioBlock();
- valuator_mask_set_range(&mask, firstAxis, axesCount, v);
- GetEventList(&events);
- nevents = GetPointerEvents(events, pDevice, MotionNotify, 0,
- POINTER_ABSOLUTE, &mask);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
-
- if (block)
- dmxSigioUnblock();
-}
-
-static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
- XEvent *e, DMXBlockType block)
-{
- int type;
- int event = -1;
- XDeviceKeyEvent *ke = (XDeviceKeyEvent *)e;
- XDeviceMotionEvent *me = (XDeviceMotionEvent *)e;
- DeviceIntPtr pDevice = dmxLocal->pDevice;
- int valuators[MAX_VALUATORS];
- EventListPtr events;
- int nevents, i;
- ValuatorMask mask;
-
- if (!e)
- return -1; /* No extended event passed, cannot handle */
-
- if ((XID)dmxLocal->deviceId != ke->deviceid) {
- /* Search for the correct dmxLocal,
- * since backend and console events are
- * picked up for the first device on
- * that X server. */
- int i;
- DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
- for (i = 0; i < dmxInput->numDevs; i++) {
- dmxLocal = dmxInput->devs[i];
- if ((XID)dmxLocal->deviceId == ke->deviceid)
- break;
- }
- }
-
- if ((XID)dmxLocal->deviceId != ke->deviceid
- || (type = dmxMapLookup(dmxLocal, e->type)) < 0)
- return -1; /* No mapping, so this event is unhandled */
-
- switch (type) {
- case XI_DeviceValuator: event = DeviceValuator; break;
- case XI_DeviceKeyPress: event = KeyPress; break;
- case XI_DeviceKeyRelease: event = KeyRelease; break;
- case XI_DeviceButtonPress: event = ButtonPress; break;
- case XI_DeviceButtonRelease: event = ButtonRelease; break;
- case XI_DeviceMotionNotify: event = MotionNotify; break;
- case XI_DeviceFocusIn: event = DeviceFocusIn; break;
- case XI_DeviceFocusOut: event = DeviceFocusOut; break;
- case XI_ProximityIn: event = ProximityIn; break;
- case XI_ProximityOut: event = ProximityOut; break;
- case XI_DeviceStateNotify: event = DeviceStateNotify; break;
- case XI_DeviceMappingNotify: event = DeviceMappingNotify; break;
- case XI_ChangeDeviceNotify: event = ChangeDeviceNotify; break;
- case XI_DeviceKeystateNotify: event = DeviceStateNotify; break;
- case XI_DeviceButtonstateNotify: event = DeviceStateNotify; break;
- }
-
-#define EXTRACT_VALUATORS(ke, valuators) \
- valuators[0] = ke->axis_data[0]; \
- valuators[1] = ke->axis_data[1]; \
- valuators[2] = ke->axis_data[2]; \
- valuators[3] = ke->axis_data[3]; \
- valuators[4] = ke->axis_data[4]; \
- valuators[5] = ke->axis_data[5]; \
-
- switch (type) {
- case XI_DeviceKeyPress:
- case XI_DeviceKeyRelease:
- EXTRACT_VALUATORS(ke, valuators);
- valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
- if (block)
- dmxSigioBlock();
- GetEventList(&events);
- nevents = GetKeyboardValuatorEvents(events, pDevice, event,
- ke->keycode, &mask);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
-
- if (block)
- dmxSigioUnblock();
- break;
- case XI_DeviceButtonPress:
- case XI_DeviceButtonRelease:
- EXTRACT_VALUATORS(ke, valuators);
- valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
- if (block)
- dmxSigioBlock();
- GetEventList(&events);
- nevents = GetPointerEvents(events, pDevice, event, ke->keycode,
- POINTER_ABSOLUTE, &mask);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
-
- if (block)
- dmxSigioUnblock();
- break;
- case XI_ProximityIn:
- case XI_ProximityOut:
- EXTRACT_VALUATORS(ke, valuators);
- valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
- if (block)
- dmxSigioBlock();
- GetEventList(&events);
- nevents = GetProximityEvents(events, pDevice, event, &mask);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
-
- if (block)
- dmxSigioUnblock();
- break;
-
- break;
-
- case XI_DeviceMotionNotify:
- dmxExtMotion(dmxLocal, me->axis_data, me->first_axis, me->axes_count,
- DMX_ABSOLUTE, block);
- break;
- case XI_DeviceFocusIn:
- case XI_DeviceFocusOut:
- case XI_DeviceStateNotify:
- case XI_DeviceMappingNotify:
- case XI_ChangeDeviceNotify:
- case XI_DeviceKeystateNotify:
- case XI_DeviceButtonstateNotify:
- /* These are ignored, since DMX will
- * generate its own events of these
- * types, as necessary.
-
- * Perhaps ChangeDeviceNotify should
- * generate an error, because it is
- * unexpected? */
- break;
- case XI_DeviceValuator:
- default:
- dmxLog(dmxWarning,
- "XInput extension event (remote=%d -> zero-based=%d)"
- " not supported yet\n", e->type, type);
- return -1;
- }
- return 0;
-}
-
-static int dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal, int button)
-{
- ButtonClassPtr b = dmxLocal->pDevice->button;
-
- if (button > b->numButtons) { /* This shouldn't happen. */
- dmxLog(dmxWarning, "Button %d pressed, but only %d buttons?!?\n",
- button, b->numButtons);
- return button;
- }
- return b->map[button];
-}
-
-/** Return DMX's notion of the pointer position in the global coordinate
- * space. */
-void dmxGetGlobalPosition(int *x, int *y)
-{
- *x = dmxGlobalX;
- *y = dmxGlobalY;
-}
-
-/** Invalidate the global position for #dmxCoreMotion. */
-void dmxInvalidateGlobalPosition(void)
-{
- dmxGlobalInvalid = 1;
-}
-
-/** Enqueue a motion event for \a pDev. The \a v vector has length \a
- * axesCount, and contains values for each of the axes, starting at \a
- * firstAxes.
- *
- * The \a type of the motion may be \a DMX_RELATIVE, \a DMX_ABSOLUTE, or
- * \a DMX_ABSOLUTE_CONFINED (in the latter case, the pointer will not be
- * allowed to move outside the global boundaires).
- *
- * If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be
- * blocked around calls to \a enqueueMotion(). */
-void dmxMotion(DevicePtr pDev, int *v, int firstAxes, int axesCount,
- DMXMotionType type, DMXBlockType block)
-{
- GETDMXLOCALFROMPDEV;
-
- if (!dmxLocal->sendsCore) {
- dmxExtMotion(dmxLocal, v, firstAxes, axesCount, type, block);
- return;
- }
- if (axesCount == 2) {
- switch (type) {
- case DMX_RELATIVE:
- dmxCoreMotion(pDev, dmxGlobalX - v[0], dmxGlobalY - v[1], 0, block);
- break;
- case DMX_ABSOLUTE:
- dmxCoreMotion(pDev, v[0], v[1], 0, block);
- break;
- case DMX_ABSOLUTE_CONFINED:
- dmxCoreMotion(pDev, v[0], v[1], -1, block);
- break;
- }
- }
-}
-
-static KeySym dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal,
- KeyCode keyCode)
-{
- KeySym keysym = NoSymbol;
- int effectiveGroup;
- XkbSrvInfoPtr xkbi;
-
- if (!dmxLocal || !dmxLocal->pDevice || !dmxLocal->pDevice->key)
- goto out;
-
- xkbi = dmxLocal->pDevice->key->xkbInfo;
- effectiveGroup = XkbGetEffectiveGroup(xkbi, &xkbi->state, keyCode);
-
- if (effectiveGroup == -1)
- goto out;
-
- keysym = XkbKeySym(xkbi->desc, keyCode, effectiveGroup);
- DMXDBG2("dmxKeyCodeToKeySym: Translated keyCode=%d to keySym=0x%04x\n",
- keyCode, keysym);
-
-out:
- return keysym;
-}
-
-static KeyCode dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal, KeySym keySym,
- int tryFirst)
-{
- /* FIXME: this is quite ineffective, converting to a core map first and
- * then extracting the info from there. It'd be better to run the actual
- * xkb map */
- XkbSrvInfoPtr xkbi = dmxLocal->pDevice->key->xkbInfo;
- KeySymsPtr pKeySyms = XkbGetCoreMap(dmxLocal->pDevice);
- int i;
-
- /* Optimize for similar maps */
- if (XkbKeycodeInRange(xkbi->desc, tryFirst)
- && pKeySyms->map[(tryFirst - xkbi->desc->min_key_code)
- * pKeySyms->mapWidth] == keySym)
- return tryFirst;
-
- for (i = pKeySyms->minKeyCode; i <= pKeySyms->maxKeyCode; i++) {
- if (pKeySyms->map[(i - pKeySyms->minKeyCode)
- * pKeySyms->mapWidth] == keySym) {
- DMXDBG3("dmxKeySymToKeyCode: Translated keySym=0x%04x to"
- " keyCode=%d (reverses to core keySym=0x%04x)\n",
- keySym, i, dmxKeyCodeToKeySym(dmxLocalCoreKeyboard,i));
- return i;
- }
- }
- return 0;
-}
-
-static int dmxFixup(DevicePtr pDev, int detail, KeySym keySym)
-{
- GETDMXLOCALFROMPDEV;
- int keyCode;
-
- if (!dmxLocal->pDevice->key) {
- dmxLog(dmxWarning, "dmxFixup: not a keyboard device (%s)\n",
- dmxLocal->pDevice->name);
- return NoSymbol;
- }
- if (!keySym)
- keySym = dmxKeyCodeToKeySym(dmxLocal, detail);
- if (keySym == NoSymbol)
- return detail;
- keyCode = dmxKeySymToKeyCode(dmxLocalCoreKeyboard, keySym, detail);
-
- return keyCode ? keyCode : detail;
-}
-
-/** Enqueue an event from the \a pDev device with the
- * specified \a type and \a detail. If the event is a KeyPress or
- * KeyRelease event, then the \a keySym is also specified.
- *
- * FIXME: make the code do what the comment says, or remove this comment.
- * If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be
- * blocked around calls to dmxeqEnqueue(). */
-
-void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
- XEvent *e, DMXBlockType block)
-{
- GETDMXINPUTFROMPDEV;
- xEvent xE;
- DeviceIntPtr p = dmxLocal->pDevice;
- int i, nevents, valuators[3];
- EventListPtr events;
- ValuatorMask mask;
-
- DMXDBG2("dmxEnqueue: Enqueuing type=%d detail=0x%0x\n", type, detail);
-
- switch (type) {
- case KeyPress:
- case KeyRelease:
- if (!keySym)
- keySym = dmxKeyCodeToKeySym(dmxLocal, detail);
- if (dmxCheckFunctionKeys(dmxLocal, type, keySym))
- return;
- if (dmxLocal->sendsCore && dmxLocal != dmxLocalCoreKeyboard)
- xE.u.u.detail = dmxFixup(pDev, detail, keySym);
-
- GetEventList(&events);
- /*ErrorF("KEY %d sym %d\n", detail, (int) keySym);*/
- nevents = GetKeyboardEvents(events, p, type, detail);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(p, (InternalEvent*)(events + i)->event);
- return;
-
- case ButtonPress:
- case ButtonRelease:
- detail = dmxGetButtonMapping(dmxLocal, detail);
- valuator_mask_zero(&mask);
- GetEventList(&events);
- nevents = GetPointerEvents(events, p, type, detail,
- POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(p, (InternalEvent*)(events + i)->event);
- return;
-
- case MotionNotify:
- GetEventList(&events);
- valuators[0] = e->xmotion.x;
- valuators[1] = e->xmotion.y;
- valuators[2] = e->xmotion.state; /* FIXME: WTF?? */
- valuator_mask_set_range(&mask, 0, 3, valuators);
- nevents = GetPointerEvents(events, p, type, detail,
- POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
- for (i = 0; i < nevents; i++)
- mieqEnqueue(p, (InternalEvent*)(events + i)->event);
- return;
-
- case EnterNotify:
- case LeaveNotify:
- case KeymapNotify:
- case MappingNotify: /* This is sent because we change the
- * modifier map on the backend/console
- * input device so that we have complete
- * control of the input device LEDs. */
- return;
- default:
- if (type == ProximityIn || type == ProximityOut) {
- if (dmxLocal->sendsCore)
- return; /* Not a core event */
- break;
- }
- if (type >= LASTEvent) {
- if (dmxTranslateAndEnqueueExtEvent(dmxLocal, e, block))
- dmxLogInput(dmxInput, "Unhandled extension event: %d\n", type);
- } else {
- dmxLogInput(dmxInput, "Unhandled event: %d (%s)\n",
- type, dmxEventName(type));
- }
- return;
- }
-
-}
-
-/** A pointer to this routine is passed to low-level input drivers so
- * that all special keychecking is unified to this file. This function
- * returns 0 if no special keys have been pressed. If the user has
- * requested termination of the DMX server, -1 is returned. If the user
- * has requested a switch to a VT, then the (1-based) number of that VT
- * is returned. */
-int dmxCheckSpecialKeys(DevicePtr pDev, KeySym keySym)
-{
- GETDMXINPUTFROMPDEV;
- int vt = 0;
- unsigned short state = 0;
-
- if (dmxLocal->sendsCore)
- state = XkbStateFieldFromRec(&dmxLocalCoreKeyboard->pDevice->key->xkbInfo->state);
- else if (dmxLocal->pDevice->key)
- state = XkbStateFieldFromRec(&dmxLocal->pDevice->key->xkbInfo->state);
-
- if (!dmxLocal->sendsCore) return 0; /* Only for core devices */
-
- DMXDBG2("dmxCheckSpecialKeys: keySym=0x%04x state=0x%04x\n", keySym,state);
-
- if ((state & (ControlMask|Mod1Mask)) != (ControlMask|Mod1Mask)) return 0;
-
- switch (keySym) {
- case XK_F1:
- case XK_F2:
- case XK_F3:
- case XK_F4:
- case XK_F5:
- case XK_F6:
- case XK_F7:
- case XK_F8:
- case XK_F9:
- case XK_F10:
- vt = keySym - XK_F1 + 1;
- break;
-
- case XK_F11:
- case XK_F12:
- vt = keySym - XK_F11 + 11;
- break;
-
- case XK_q: /* To avoid confusion */
- case XK_BackSpace:
- case XK_Delete:
- case XK_KP_Delete:
- dmxLog(dmxInfo, "User request for termination\n");
- dispatchException |= DE_TERMINATE;
- return -1; /* Terminate */
- }
-
- if (vt) {
- dmxLog(dmxInfo, "Request to switch to VT %d\n", vt);
- dmxInput->vt_switch_pending = vt;
- return vt;
- }
-
- return 0; /* Do nothing */
-}
+/*
+ * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * Provide support and helper functions for enqueing events received by
+ * the low-level input drivers. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#define DMX_EVENTS_DEBUG 0
+
+#include "dmxinputinit.h"
+#include "dmxevents.h"
+#include "dmxcb.h"
+#include "dmxcommon.h"
+#include "dmxcursor.h"
+#include "dmxmotion.h"
+#include "dmxsigio.h"
+#include "dmxmap.h"
+
+#include <X11/keysym.h>
+#include "opaque.h"
+#include "inputstr.h"
+#include "inpututils.h"
+#include "mipointer.h"
+#include "mi.h"
+#include "exglobals.h"
+
+#include "xkbsrv.h"
+#include "XIstubs.h"
+
+static int dmxGlobalX, dmxGlobalY; /* Global cursor position */
+static int dmxGlobalInvalid; /* Flag indicating dmxCoreMotion
+ * should move the mouse anyway. */
+
+#if DMX_EVENTS_DEBUG
+#define DMXDBG0(f) dmxLog(dmxDebug,f)
+#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
+#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
+#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
+#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
+#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
+#else
+#define DMXDBG0(f)
+#define DMXDBG1(f,a)
+#define DMXDBG2(f,a,b)
+#define DMXDBG3(f,a,b,c)
+#define DMXDBG4(f,a,b,c,d)
+#define DMXDBG5(f,a,b,c,d,e)
+#define DMXDBG6(f,a,b,c,d,e,g)
+#define DMXDBG7(f,a,b,c,d,e,g,h)
+#endif
+
+static int dmxApplyFunctions(DMXInputInfo *dmxInput, DMXFunctionType f)
+{
+ int i;
+ int rc = 0;
+
+ for (i = 0; i < dmxInput->numDevs; i+= dmxInput->devs[i]->binding)
+ if (dmxInput->devs[i]->functions)
+ rc += dmxInput->devs[i]->functions(dmxInput->devs[i]->private, f);
+ return rc;
+}
+
+static int dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal,
+ int type,
+ KeySym keySym)
+{
+ DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
+
+#if 1 /* hack to detect ctrl-alt-q, etc */
+ static int ctrl = 0, alt = 0;
+ /* keep track of ctrl/alt key status */
+ if (type == KeyPress && keySym == 0xffe3) {
+ ctrl = 1;
+ }
+ else if (type == KeyRelease && keySym == 0xffe3) {
+ ctrl = 0;
+ }
+ else if (type == KeyPress && keySym == 0xffe9) {
+ alt = 1;
+ }
+ else if (type == KeyRelease && keySym == 0xffe9) {
+ alt = 0;
+ }
+ if (!ctrl || !alt)
+ return 0;
+#else
+ unsigned short state = 0;
+
+ if (dmxLocal->sendsCore)
+ state = dmxLocalCoreKeyboard->pDevice->key->state;
+ else if (dmxLocal->pDevice->key)
+ state = dmxLocal->pDevice->key->state;
+
+ DMXDBG3("dmxCheckFunctionKeys: keySym=0x%04x %s state=0x%04x\n",
+ keySym, type == KeyPress ? "press" : "release", state);
+
+ if ((state & (ControlMask|Mod1Mask)) != (ControlMask|Mod1Mask))
+ return 0;
+#endif
+
+ switch (keySym) {
+ case XK_g:
+ if (type == KeyPress)
+ dmxApplyFunctions(dmxInput, DMX_FUNCTION_GRAB);
+ return 1;
+ case XK_f:
+ if (type == KeyPress)
+ dmxApplyFunctions(dmxInput, DMX_FUNCTION_FINE);
+ return 1;
+ case XK_q:
+ if (type == KeyPress && dmxLocal->sendsCore)
+ if (dmxApplyFunctions(dmxInput, DMX_FUNCTION_TERMINATE)) {
+ dmxLog(dmxInfo, "User request for termination\n");
+ dispatchException |= DE_TERMINATE;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+
+DMXScreenInfo *dmxFindFirstScreen(int x, int y)
+{
+ int i;
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ if (dmxOnScreen(x, y, dmxScreen))
+ return dmxScreen;
+ }
+ return NULL;
+}
+
+
+/**
+ * Enqueue a motion event.
+ */
+static void enqueueMotion(DevicePtr pDev, int x, int y)
+{
+ GETDMXLOCALFROMPDEV;
+ DeviceIntPtr p = dmxLocal->pDevice;
+ int i, nevents, valuators[3];
+ EventListPtr events;
+ int detail = 0; /* XXX should this be mask of pressed buttons? */
+ ValuatorMask mask;
+ valuators[0] = x;
+ valuators[1] = y;
+
+ valuator_mask_set_range(&mask, 0, 2, valuators);
+ GetEventList(&events);
+ nevents = GetPointerEvents(events, p, MotionNotify, detail,
+ POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(p, (InternalEvent*)(events + i)->event);
+ return;
+}
+
+
+void
+dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block)
+{
+ DMXScreenInfo *dmxScreen;
+ DMXInputInfo *dmxInput;
+ ScreenPtr pScreen;
+ int localX;
+ int localY;
+ int i;
+
+ if (!dmxGlobalInvalid && dmxGlobalX == x && dmxGlobalY == y)
+ return;
+
+ DMXDBG5("dmxCoreMotion(%d,%d,%d) dmxGlobalX=%d dmxGlobalY=%d\n",
+ x, y, delta, dmxGlobalX, dmxGlobalY);
+
+ dmxGlobalInvalid = 0;
+ dmxGlobalX = x;
+ dmxGlobalY = y;
+
+ if (dmxGlobalX < 0)
+ dmxGlobalX = 0;
+ if (dmxGlobalY < 0)
+ dmxGlobalY = 0;
+ if (dmxGlobalX >= dmxGlobalWidth)
+ dmxGlobalX = dmxGlobalWidth + delta -1;
+ if (dmxGlobalY >= dmxGlobalHeight)
+ dmxGlobalY = dmxGlobalHeight + delta -1;
+
+ if ((dmxScreen = dmxFindFirstScreen(dmxGlobalX, dmxGlobalY))) {
+ localX = dmxGlobalX - dmxScreen->rootXOrigin;
+ localY = dmxGlobalY - dmxScreen->rootYOrigin;
+ if ((pScreen = miPointerGetScreen(inputInfo.pointer))
+ && pScreen->myNum == dmxScreen->index) {
+ /* Screen is old screen */
+ if (block)
+ dmxSigioBlock();
+ if (pDev)
+ enqueueMotion(pDev, localX, localY);
+ if (block)
+ dmxSigioUnblock();
+ } else {
+ /* Screen is new */
+ DMXDBG4(" New screen: old=%d new=%d localX=%d localY=%d\n",
+ pScreen->myNum, dmxScreen->index, localX, localY);
+ if (block)
+ dmxSigioBlock();
+ mieqProcessInputEvents();
+ miPointerSetScreen(inputInfo.pointer, dmxScreen->index,
+ localX, localY);
+ if (pDev)
+ enqueueMotion(pDev, localX, localY);
+ if (block)
+ dmxSigioUnblock();
+ }
+#if 00
+ miPointerGetPosition(inputInfo.pointer, &localX, &localY);
+
+ if ((pScreen = miPointerGetScreen(inputInfo.pointer))) {
+ dmxGlobalX = localX + dmxScreens[pScreen->myNum].rootXOrigin;
+ dmxGlobalY = localY + dmxScreens[pScreen->myNum].rootYOrigin;
+ ErrorF("Global is now %d, %d %d, %d\n", dmxGlobalX, dmxGlobalY,
+ localX, localY);
+ DMXDBG6(" Moved to dmxGlobalX=%d dmxGlobalY=%d"
+ " on screen index=%d/%d localX=%d localY=%d\n",
+ dmxGlobalX, dmxGlobalY,
+ dmxScreen ? dmxScreen->index : -1, pScreen->myNum,
+ localX, localY);
+ }
+#endif
+ }
+ /* Send updates down to all core input
+ * drivers */
+ for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) {
+ int j;
+ for (j = 0; j < dmxInput->numDevs; j += dmxInput->devs[j]->binding)
+ if (!dmxInput->detached
+ && dmxInput->devs[j]->sendsCore
+ && dmxInput->devs[j]->update_position)
+ dmxInput->devs[j]->update_position(dmxInput->devs[j]->private,
+ dmxGlobalX, dmxGlobalY);
+ }
+ if (!dmxScreen) ProcessInputEvents();
+}
+
+
+
+#define DMX_MAX_AXES 32 /* Max axes reported by this routine */
+static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
+ int *v, int firstAxis, int axesCount,
+ DMXMotionType type, DMXBlockType block)
+{
+ DeviceIntPtr pDevice = dmxLocal->pDevice;
+ xEvent xE[2 * DMX_MAX_AXES/6];
+ deviceKeyButtonPointer *xev = (deviceKeyButtonPointer *)xE;
+ deviceValuator *xv = (deviceValuator *)xev+1;
+ int thisX = 0;
+ int thisY = 0;
+ int i;
+ int count;
+ EventListPtr events;
+ int nevents;
+ ValuatorMask mask;
+
+ memset(xE, 0, sizeof(xE));
+
+ if (axesCount > DMX_MAX_AXES) axesCount = DMX_MAX_AXES;
+
+ if ((valuator_get_mode(pDevice,0) == Relative) && axesCount == 2) {
+ /* The dmx console is a relative mode
+ * device that sometimes reports
+ * absolute motion. It only has two
+ * axes. */
+ if (type == DMX_RELATIVE) {
+ thisX = -v[0];
+ thisY = -v[1];
+ dmxLocal->lastX += thisX;
+ dmxLocal->lastY += thisY;
+ if (dmxLocal->update_position)
+ dmxLocal->update_position(dmxLocal->private,
+ dmxLocal->lastX, dmxLocal->lastY);
+ } else { /* Convert to relative */
+ if (dmxLocal->lastX || dmxLocal->lastY) {
+ thisX = v[0] - dmxLocal->lastX;
+ thisY = v[1] - dmxLocal->lastY;
+ }
+ dmxLocal->lastX = v[0];
+ dmxLocal->lastY = v[1];
+ }
+ v[0] = thisX;
+ v[1] = thisY;
+ }
+
+ if (axesCount <= 6) {
+ /* Optimize for the common case when
+ * only 1 or 2 axes change. */
+ xev->time = GetTimeInMillis();
+ xev->type = DeviceMotionNotify;
+ xev->detail = 0;
+ xev->deviceid = pDevice->id | MORE_EVENTS;
+
+ xv->type = DeviceValuator;
+ xv->deviceid = pDevice->id;
+ xv->num_valuators = axesCount;
+ xv->first_valuator = firstAxis;
+ switch (xv->num_valuators) {
+ case 6: xv->valuator5 = v[5];
+ case 5: xv->valuator4 = v[4];
+ case 4: xv->valuator3 = v[3];
+ case 3: xv->valuator2 = v[2];
+ case 2: xv->valuator1 = v[1];
+ case 1: xv->valuator0 = v[0];
+ }
+ count = 2;
+ } else {
+ for (i = 0, count = 0; i < axesCount; i += 6) {
+ xev->time = GetTimeInMillis();
+ xev->type = DeviceMotionNotify;
+ xev->detail = 0;
+ xev->deviceid = pDevice->id | MORE_EVENTS;
+ xev += 2;
+
+ xv->type = DeviceValuator;
+ xv->deviceid = pDevice->id;
+ xv->num_valuators = (i+6 >= axesCount ? axesCount - i : 6);
+ xv->first_valuator = firstAxis + i;
+ switch (xv->num_valuators) {
+ case 6: xv->valuator5 = v[i+5];
+ case 5: xv->valuator4 = v[i+4];
+ case 4: xv->valuator3 = v[i+3];
+ case 3: xv->valuator2 = v[i+2];
+ case 2: xv->valuator1 = v[i+1];
+ case 1: xv->valuator0 = v[i+0];
+ }
+ xv += 2;
+ count += 2;
+ }
+ }
+
+ if (block)
+ dmxSigioBlock();
+ valuator_mask_set_range(&mask, firstAxis, axesCount, v);
+ GetEventList(&events);
+ nevents = GetPointerEvents(events, pDevice, MotionNotify, 0,
+ POINTER_ABSOLUTE, &mask);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
+
+ if (block)
+ dmxSigioUnblock();
+}
+
+static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
+ XEvent *e, DMXBlockType block)
+{
+ int type;
+ int event = -1;
+ XDeviceKeyEvent *ke = (XDeviceKeyEvent *)e;
+ XDeviceMotionEvent *me = (XDeviceMotionEvent *)e;
+ DeviceIntPtr pDevice = dmxLocal->pDevice;
+ int valuators[MAX_VALUATORS];
+ EventListPtr events;
+ int nevents, i;
+ ValuatorMask mask;
+
+ if (!e)
+ return -1; /* No extended event passed, cannot handle */
+
+ if ((XID)dmxLocal->deviceId != ke->deviceid) {
+ /* Search for the correct dmxLocal,
+ * since backend and console events are
+ * picked up for the first device on
+ * that X server. */
+ int i;
+ DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ dmxLocal = dmxInput->devs[i];
+ if ((XID)dmxLocal->deviceId == ke->deviceid)
+ break;
+ }
+ }
+
+ if ((XID)dmxLocal->deviceId != ke->deviceid
+ || (type = dmxMapLookup(dmxLocal, e->type)) < 0)
+ return -1; /* No mapping, so this event is unhandled */
+
+ switch (type) {
+ case XI_DeviceValuator: event = DeviceValuator; break;
+ case XI_DeviceKeyPress: event = KeyPress; break;
+ case XI_DeviceKeyRelease: event = KeyRelease; break;
+ case XI_DeviceButtonPress: event = ButtonPress; break;
+ case XI_DeviceButtonRelease: event = ButtonRelease; break;
+ case XI_DeviceMotionNotify: event = MotionNotify; break;
+ case XI_DeviceFocusIn: event = DeviceFocusIn; break;
+ case XI_DeviceFocusOut: event = DeviceFocusOut; break;
+ case XI_ProximityIn: event = ProximityIn; break;
+ case XI_ProximityOut: event = ProximityOut; break;
+ case XI_DeviceStateNotify: event = DeviceStateNotify; break;
+ case XI_DeviceMappingNotify: event = DeviceMappingNotify; break;
+ case XI_ChangeDeviceNotify: event = ChangeDeviceNotify; break;
+ case XI_DeviceKeystateNotify: event = DeviceStateNotify; break;
+ case XI_DeviceButtonstateNotify: event = DeviceStateNotify; break;
+ }
+
+#define EXTRACT_VALUATORS(ke, valuators) \
+ valuators[0] = ke->axis_data[0]; \
+ valuators[1] = ke->axis_data[1]; \
+ valuators[2] = ke->axis_data[2]; \
+ valuators[3] = ke->axis_data[3]; \
+ valuators[4] = ke->axis_data[4]; \
+ valuators[5] = ke->axis_data[5]; \
+
+ switch (type) {
+ case XI_DeviceKeyPress:
+ case XI_DeviceKeyRelease:
+ EXTRACT_VALUATORS(ke, valuators);
+ valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
+ if (block)
+ dmxSigioBlock();
+ GetEventList(&events);
+ nevents = GetKeyboardEvents(events, pDevice, event,
+ ke->keycode, &mask);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
+
+ if (block)
+ dmxSigioUnblock();
+ break;
+ case XI_DeviceButtonPress:
+ case XI_DeviceButtonRelease:
+ EXTRACT_VALUATORS(ke, valuators);
+ valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
+ if (block)
+ dmxSigioBlock();
+ GetEventList(&events);
+ nevents = GetPointerEvents(events, pDevice, event, ke->keycode,
+ POINTER_ABSOLUTE, &mask);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
+
+ if (block)
+ dmxSigioUnblock();
+ break;
+ case XI_ProximityIn:
+ case XI_ProximityOut:
+ EXTRACT_VALUATORS(ke, valuators);
+ valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
+ if (block)
+ dmxSigioBlock();
+ GetEventList(&events);
+ nevents = GetProximityEvents(events, pDevice, event, &mask);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
+
+ if (block)
+ dmxSigioUnblock();
+ break;
+
+ break;
+
+ case XI_DeviceMotionNotify:
+ dmxExtMotion(dmxLocal, me->axis_data, me->first_axis, me->axes_count,
+ DMX_ABSOLUTE, block);
+ break;
+ case XI_DeviceFocusIn:
+ case XI_DeviceFocusOut:
+ case XI_DeviceStateNotify:
+ case XI_DeviceMappingNotify:
+ case XI_ChangeDeviceNotify:
+ case XI_DeviceKeystateNotify:
+ case XI_DeviceButtonstateNotify:
+ /* These are ignored, since DMX will
+ * generate its own events of these
+ * types, as necessary.
+
+ * Perhaps ChangeDeviceNotify should
+ * generate an error, because it is
+ * unexpected? */
+ break;
+ case XI_DeviceValuator:
+ default:
+ dmxLog(dmxWarning,
+ "XInput extension event (remote=%d -> zero-based=%d)"
+ " not supported yet\n", e->type, type);
+ return -1;
+ }
+ return 0;
+}
+
+static int dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal, int button)
+{
+ ButtonClassPtr b = dmxLocal->pDevice->button;
+
+ if (button > b->numButtons) { /* This shouldn't happen. */
+ dmxLog(dmxWarning, "Button %d pressed, but only %d buttons?!?\n",
+ button, b->numButtons);
+ return button;
+ }
+ return b->map[button];
+}
+
+/** Return DMX's notion of the pointer position in the global coordinate
+ * space. */
+void dmxGetGlobalPosition(int *x, int *y)
+{
+ *x = dmxGlobalX;
+ *y = dmxGlobalY;
+}
+
+/** Invalidate the global position for #dmxCoreMotion. */
+void dmxInvalidateGlobalPosition(void)
+{
+ dmxGlobalInvalid = 1;
+}
+
+/** Enqueue a motion event for \a pDev. The \a v vector has length \a
+ * axesCount, and contains values for each of the axes, starting at \a
+ * firstAxes.
+ *
+ * The \a type of the motion may be \a DMX_RELATIVE, \a DMX_ABSOLUTE, or
+ * \a DMX_ABSOLUTE_CONFINED (in the latter case, the pointer will not be
+ * allowed to move outside the global boundaires).
+ *
+ * If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be
+ * blocked around calls to \a enqueueMotion(). */
+void dmxMotion(DevicePtr pDev, int *v, int firstAxes, int axesCount,
+ DMXMotionType type, DMXBlockType block)
+{
+ GETDMXLOCALFROMPDEV;
+
+ if (!dmxLocal->sendsCore) {
+ dmxExtMotion(dmxLocal, v, firstAxes, axesCount, type, block);
+ return;
+ }
+ if (axesCount == 2) {
+ switch (type) {
+ case DMX_RELATIVE:
+ dmxCoreMotion(pDev, dmxGlobalX - v[0], dmxGlobalY - v[1], 0, block);
+ break;
+ case DMX_ABSOLUTE:
+ dmxCoreMotion(pDev, v[0], v[1], 0, block);
+ break;
+ case DMX_ABSOLUTE_CONFINED:
+ dmxCoreMotion(pDev, v[0], v[1], -1, block);
+ break;
+ }
+ }
+}
+
+static KeySym dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal,
+ KeyCode keyCode)
+{
+ KeySym keysym = NoSymbol;
+ int effectiveGroup;
+ XkbSrvInfoPtr xkbi;
+
+ if (!dmxLocal || !dmxLocal->pDevice || !dmxLocal->pDevice->key)
+ goto out;
+
+ xkbi = dmxLocal->pDevice->key->xkbInfo;
+ effectiveGroup = XkbGetEffectiveGroup(xkbi, &xkbi->state, keyCode);
+
+ if (effectiveGroup == -1)
+ goto out;
+
+ keysym = XkbKeySym(xkbi->desc, keyCode, effectiveGroup);
+ DMXDBG2("dmxKeyCodeToKeySym: Translated keyCode=%d to keySym=0x%04x\n",
+ keyCode, keysym);
+
+out:
+ return keysym;
+}
+
+static KeyCode dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal, KeySym keySym,
+ int tryFirst)
+{
+ /* FIXME: this is quite ineffective, converting to a core map first and
+ * then extracting the info from there. It'd be better to run the actual
+ * xkb map */
+ XkbSrvInfoPtr xkbi = dmxLocal->pDevice->key->xkbInfo;
+ KeySymsPtr pKeySyms = XkbGetCoreMap(dmxLocal->pDevice);
+ int i;
+
+ /* Optimize for similar maps */
+ if (XkbKeycodeInRange(xkbi->desc, tryFirst)
+ && pKeySyms->map[(tryFirst - xkbi->desc->min_key_code)
+ * pKeySyms->mapWidth] == keySym)
+ return tryFirst;
+
+ for (i = pKeySyms->minKeyCode; i <= pKeySyms->maxKeyCode; i++) {
+ if (pKeySyms->map[(i - pKeySyms->minKeyCode)
+ * pKeySyms->mapWidth] == keySym) {
+ DMXDBG3("dmxKeySymToKeyCode: Translated keySym=0x%04x to"
+ " keyCode=%d (reverses to core keySym=0x%04x)\n",
+ keySym, i, dmxKeyCodeToKeySym(dmxLocalCoreKeyboard,i));
+ return i;
+ }
+ }
+ return 0;
+}
+
+static int dmxFixup(DevicePtr pDev, int detail, KeySym keySym)
+{
+ GETDMXLOCALFROMPDEV;
+ int keyCode;
+
+ if (!dmxLocal->pDevice->key) {
+ dmxLog(dmxWarning, "dmxFixup: not a keyboard device (%s)\n",
+ dmxLocal->pDevice->name);
+ return NoSymbol;
+ }
+ if (!keySym)
+ keySym = dmxKeyCodeToKeySym(dmxLocal, detail);
+ if (keySym == NoSymbol)
+ return detail;
+ keyCode = dmxKeySymToKeyCode(dmxLocalCoreKeyboard, keySym, detail);
+
+ return keyCode ? keyCode : detail;
+}
+
+/** Enqueue an event from the \a pDev device with the
+ * specified \a type and \a detail. If the event is a KeyPress or
+ * KeyRelease event, then the \a keySym is also specified.
+ *
+ * FIXME: make the code do what the comment says, or remove this comment.
+ * If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be
+ * blocked around calls to dmxeqEnqueue(). */
+
+void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
+ XEvent *e, DMXBlockType block)
+{
+ GETDMXINPUTFROMPDEV;
+ xEvent xE;
+ DeviceIntPtr p = dmxLocal->pDevice;
+ int i, nevents, valuators[3];
+ EventListPtr events;
+ ValuatorMask mask;
+
+ DMXDBG2("dmxEnqueue: Enqueuing type=%d detail=0x%0x\n", type, detail);
+
+ switch (type) {
+ case KeyPress:
+ case KeyRelease:
+ if (!keySym)
+ keySym = dmxKeyCodeToKeySym(dmxLocal, detail);
+ if (dmxCheckFunctionKeys(dmxLocal, type, keySym))
+ return;
+ if (dmxLocal->sendsCore && dmxLocal != dmxLocalCoreKeyboard)
+ xE.u.u.detail = dmxFixup(pDev, detail, keySym);
+
+ GetEventList(&events);
+ /*ErrorF("KEY %d sym %d\n", detail, (int) keySym);*/
+ nevents = GetKeyboardEvents(events, p, type, detail, NULL);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(p, (InternalEvent*)(events + i)->event);
+ return;
+
+ case ButtonPress:
+ case ButtonRelease:
+ detail = dmxGetButtonMapping(dmxLocal, detail);
+ valuator_mask_zero(&mask);
+ GetEventList(&events);
+ nevents = GetPointerEvents(events, p, type, detail,
+ POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(p, (InternalEvent*)(events + i)->event);
+ return;
+
+ case MotionNotify:
+ GetEventList(&events);
+ valuators[0] = e->xmotion.x;
+ valuators[1] = e->xmotion.y;
+ valuators[2] = e->xmotion.state; /* FIXME: WTF?? */
+ valuator_mask_set_range(&mask, 0, 3, valuators);
+ nevents = GetPointerEvents(events, p, type, detail,
+ POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(p, (InternalEvent*)(events + i)->event);
+ return;
+
+ case EnterNotify:
+ case LeaveNotify:
+ case KeymapNotify:
+ case MappingNotify: /* This is sent because we change the
+ * modifier map on the backend/console
+ * input device so that we have complete
+ * control of the input device LEDs. */
+ return;
+ default:
+ if (type == ProximityIn || type == ProximityOut) {
+ if (dmxLocal->sendsCore)
+ return; /* Not a core event */
+ break;
+ }
+ if (type >= LASTEvent) {
+ if (dmxTranslateAndEnqueueExtEvent(dmxLocal, e, block))
+ dmxLogInput(dmxInput, "Unhandled extension event: %d\n", type);
+ } else {
+ dmxLogInput(dmxInput, "Unhandled event: %d (%s)\n",
+ type, dmxEventName(type));
+ }
+ return;
+ }
+
+}
+
+/** A pointer to this routine is passed to low-level input drivers so
+ * that all special keychecking is unified to this file. This function
+ * returns 0 if no special keys have been pressed. If the user has
+ * requested termination of the DMX server, -1 is returned. If the user
+ * has requested a switch to a VT, then the (1-based) number of that VT
+ * is returned. */
+int dmxCheckSpecialKeys(DevicePtr pDev, KeySym keySym)
+{
+ GETDMXINPUTFROMPDEV;
+ int vt = 0;
+ unsigned short state = 0;
+
+ if (dmxLocal->sendsCore)
+ state = XkbStateFieldFromRec(&dmxLocalCoreKeyboard->pDevice->key->xkbInfo->state);
+ else if (dmxLocal->pDevice->key)
+ state = XkbStateFieldFromRec(&dmxLocal->pDevice->key->xkbInfo->state);
+
+ if (!dmxLocal->sendsCore) return 0; /* Only for core devices */
+
+ DMXDBG2("dmxCheckSpecialKeys: keySym=0x%04x state=0x%04x\n", keySym,state);
+
+ if ((state & (ControlMask|Mod1Mask)) != (ControlMask|Mod1Mask)) return 0;
+
+ switch (keySym) {
+ case XK_F1:
+ case XK_F2:
+ case XK_F3:
+ case XK_F4:
+ case XK_F5:
+ case XK_F6:
+ case XK_F7:
+ case XK_F8:
+ case XK_F9:
+ case XK_F10:
+ vt = keySym - XK_F1 + 1;
+ break;
+
+ case XK_F11:
+ case XK_F12:
+ vt = keySym - XK_F11 + 11;
+ break;
+
+ case XK_q: /* To avoid confusion */
+ case XK_BackSpace:
+ case XK_Delete:
+ case XK_KP_Delete:
+ dmxLog(dmxInfo, "User request for termination\n");
+ dispatchException |= DE_TERMINATE;
+ return -1; /* Terminate */
+ }
+
+ if (vt) {
+ dmxLog(dmxInfo, "Request to switch to VT %d\n", vt);
+ dmxInput->vt_switch_pending = vt;
+ return vt;
+ }
+
+ return 0; /* Do nothing */
+}
diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c
index e3bc4c523..f21475fb6 100644
--- a/xorg-server/hw/kdrive/src/kinput.c
+++ b/xorg-server/hw/kdrive/src/kinput.c
@@ -1804,7 +1804,7 @@ KdReleaseAllKeys (void)
if (key_is_down(ki->dixdev, key, KEY_POSTED | KEY_PROCESSED)) {
KdHandleKeyboardEvent(ki, KeyRelease, key);
GetEventList(&kdEvents);
- nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key);
+ nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key, NULL);
for (i = 0; i < nEvents; i++)
KdQueueEvent (ki->dixdev, (kdEvents + i)->event);
}
@@ -1864,7 +1864,7 @@ KdEnqueueKeyboardEvent(KdKeyboardInfo *ki,
GetEventList(&kdEvents);
- nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code);
+ nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code, NULL);
for (i = 0; i < nEvents; i++)
KdQueueEvent(ki->dixdev, (InternalEvent *)((kdEvents + i)->event));
}
diff --git a/xorg-server/hw/xfree86/common/xf86Configure.c b/xorg-server/hw/xfree86/common/xf86Configure.c
index bccdd403c..975266943 100644
--- a/xorg-server/hw/xfree86/common/xf86Configure.c
+++ b/xorg-server/hw/xfree86/common/xf86Configure.c
@@ -1,762 +1,755 @@
-/*
- * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
- *
- * 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, and that the name of Alan Hourihane not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Alan Hourihane makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
- *
- * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: Alan Hourihane, alanh@fairlite.demon.co.uk
- *
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "xf86.h"
-#include "xf86Config.h"
-#include "xf86_OSlib.h"
-#include "xf86Priv.h"
-#define IN_XSERVER
-#include "Configint.h"
-#include "xf86DDC.h"
-#include "xf86pciBus.h"
-#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
-#include "xf86Bus.h"
-#include "xf86Sbus.h"
-#endif
-#include "misc.h"
-
-typedef struct _DevToConfig {
- GDevRec GDev;
- struct pci_device * pVideo;
-#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
- sbusDevicePtr sVideo;
-#endif
- int iDriver;
-} DevToConfigRec, *DevToConfigPtr;
-
-static DevToConfigPtr DevToConfig = NULL;
-static int nDevToConfig = 0, CurrentDriver;
-
-xf86MonPtr ConfiguredMonitor;
-Bool xf86DoConfigurePass1 = TRUE;
-static Bool foundMouse = FALSE;
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-static char *DFLT_MOUSE_DEV = "/dev/sysmouse";
-static char *DFLT_MOUSE_PROTO = "auto";
-#elif defined(linux)
-static char DFLT_MOUSE_DEV[] = "/dev/input/mice";
-static char DFLT_MOUSE_PROTO[] = "auto";
-#else
-static char *DFLT_MOUSE_DEV = "/dev/mouse";
-static char *DFLT_MOUSE_PROTO = "auto";
-#endif
-
-/*
- * This is called by the driver, either through xf86Match???Instances() or
- * directly. We allocate a GDevRec and fill it in as much as we can, letting
- * the caller fill in the rest and/or change it as it sees fit.
- */
-GDevPtr
-xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, int chipset)
-{
- int ret, i, j;
-
- if (!xf86DoConfigure || !xf86DoConfigurePass1)
- return NULL;
-
- /* Check for duplicates */
- for (i = 0; i < nDevToConfig; i++) {
- switch (bus) {
- case BUS_PCI:
- ret = xf86PciConfigure(busData, DevToConfig[i].pVideo);
- break;
-#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
- case BUS_SBUS:
- ret = xf86SbusConfigure(busData, DevToConfig[i].sVideo);
- break;
-#endif
- default:
- return NULL;
- }
- if (ret == 0)
- goto out;
- }
-
- /* Allocate new structure occurrence */
- i = nDevToConfig++;
- DevToConfig =
- xnfrealloc(DevToConfig, nDevToConfig * sizeof(DevToConfigRec));
- memset(DevToConfig + i, 0, sizeof(DevToConfigRec));
-
- DevToConfig[i].GDev.chipID =
- DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1;
-
- DevToConfig[i].iDriver = CurrentDriver;
-
- /* Fill in what we know, converting the driver name to lower case */
- DevToConfig[i].GDev.driver = xnfalloc(strlen(driver) + 1);
- for (j = 0; (DevToConfig[i].GDev.driver[j] = tolower(driver[j])); j++);
-
- switch (bus) {
- case BUS_PCI:
- xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo,
- &DevToConfig[i].GDev, &chipset);
- break;
-#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
- case BUS_SBUS:
- xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo,
- &DevToConfig[i].GDev);
- break;
-#endif
- default:
- break;
- }
-
- /* Get driver's available options */
- if (xf86DriverList[CurrentDriver]->AvailableOptions)
- DevToConfig[i].GDev.options = (OptionInfoPtr)
- (*xf86DriverList[CurrentDriver]->AvailableOptions)(chipset,
- bus);
-
- return &DevToConfig[i].GDev;
-
-out:
- return NULL;
-}
-
-static XF86ConfInputPtr
-configureInputSection (void)
-{
- XF86ConfInputPtr mouse = NULL;
- parsePrologue (XF86ConfInputPtr, XF86ConfInputRec)
-
- ptr->inp_identifier = "Keyboard0";
- ptr->inp_driver = "kbd";
- ptr->list.next = NULL;
-
- /* Crude mechanism to auto-detect mouse (os dependent) */
- {
- int fd;
-#ifdef WSCONS_SUPPORT
- fd = open("/dev/wsmouse", 0);
- if (fd >= 0) {
- DFLT_MOUSE_DEV = "/dev/wsmouse";
- DFLT_MOUSE_PROTO = "wsmouse";
- close(fd);
- } else {
- ErrorF("cannot open /dev/wsmouse\n");
- }
-#endif
-
- fd = open(DFLT_MOUSE_DEV, 0);
- if (fd != -1) {
- foundMouse = TRUE;
- close(fd);
- }
- }
-
- mouse = calloc(1, sizeof(XF86ConfInputRec));
- mouse->inp_identifier = "Mouse0";
- mouse->inp_driver = "mouse";
- mouse->inp_option_lst =
- xf86addNewOption(mouse->inp_option_lst, strdup("Protocol"),
- strdup(DFLT_MOUSE_PROTO));
- mouse->inp_option_lst =
- xf86addNewOption(mouse->inp_option_lst, strdup("Device"),
- strdup(DFLT_MOUSE_DEV));
- mouse->inp_option_lst =
- xf86addNewOption(mouse->inp_option_lst, strdup("ZAxisMapping"),
- strdup("4 5 6 7"));
- ptr = (XF86ConfInputPtr)xf86addListItem((glp)ptr, (glp)mouse);
- return ptr;
-}
-
-static XF86ConfScreenPtr
-configureScreenSection (int screennum)
-{
- int i;
- int depths[] = { 1, 4, 8, 15, 16, 24/*, 32*/ };
- parsePrologue (XF86ConfScreenPtr, XF86ConfScreenRec)
-
- XNFasprintf(&ptr->scrn_identifier, "Screen%d", screennum);
- XNFasprintf(&ptr->scrn_monitor_str, "Monitor%d", screennum);
- XNFasprintf(&ptr->scrn_device_str, "Card%d", screennum);
-
- for (i=0; i<sizeof(depths)/sizeof(depths[0]); i++)
- {
- XF86ConfDisplayPtr display;
-
- display = calloc(1, sizeof(XF86ConfDisplayRec));
- display->disp_depth = depths[i];
- display->disp_black.red = display->disp_white.red = -1;
- display->disp_black.green = display->disp_white.green = -1;
- display->disp_black.blue = display->disp_white.blue = -1;
- ptr->scrn_display_lst = (XF86ConfDisplayPtr)xf86addListItem(
- (glp)ptr->scrn_display_lst, (glp)display);
- }
-
- return ptr;
-}
-
-static const char*
-optionTypeToString(OptionValueType type)
-{
- switch (type) {
- case OPTV_NONE:
- return "";
- case OPTV_INTEGER:
- return "<i>";
- case OPTV_STRING:
- return "<str>";
- case OPTV_ANYSTR:
- return "[<str>]";
- case OPTV_REAL:
- return "<f>";
- case OPTV_BOOLEAN:
- return "[<bool>]";
- case OPTV_FREQ:
- return "<freq>";
- case OPTV_PERCENT:
- return "<percent>";
- default:
- return "";
- }
-}
-
-static XF86ConfDevicePtr
-configureDeviceSection (int screennum)
-{
- OptionInfoPtr p;
- int i = 0;
- parsePrologue (XF86ConfDevicePtr, XF86ConfDeviceRec)
-
- /* Move device info to parser structure */
- if (asprintf(&ptr->dev_identifier, "Card%d", screennum) == -1)
- ptr->dev_identifier = NULL;
- ptr->dev_chipset = DevToConfig[screennum].GDev.chipset;
- ptr->dev_busid = DevToConfig[screennum].GDev.busID;
- ptr->dev_driver = DevToConfig[screennum].GDev.driver;
- ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac;
- for (i = 0; (i < MAXDACSPEEDS) && (i < CONF_MAXDACSPEEDS); i++)
- ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i];
- ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam;
- ptr->dev_textclockfreq = DevToConfig[screennum].GDev.textClockFreq;
- ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase;
- ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase;
- ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase;
- ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip;
- for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks); i++)
- ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i];
- ptr->dev_clocks = i;
- ptr->dev_chipid = DevToConfig[screennum].GDev.chipID;
- ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev;
- ptr->dev_irq = DevToConfig[screennum].GDev.irq;
-
- /* Make sure older drivers don't segv */
- if (DevToConfig[screennum].GDev.options) {
- /* Fill in the available driver options for people to use */
- const char *descrip =
- " ### Available Driver options are:-\n"
- " ### Values: <i>: integer, <f>: float, "
- "<bool>: \"True\"/\"False\",\n"
- " ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n"
- " ### <percent>: \"<f>%\"\n"
- " ### [arg]: arg optional\n";
- ptr->dev_comment = strdup(descrip);
- if (ptr->dev_comment) {
- for (p = DevToConfig[screennum].GDev.options;
- p->name != NULL; p++) {
- char *p_e;
- const char *prefix = " #Option ";
- const char *middle = " \t# ";
- const char *suffix = "\n";
- const char *opttype = optionTypeToString(p->type);
- char *optname;
- int len = strlen(ptr->dev_comment) + strlen(prefix) +
- strlen(middle) + strlen(suffix) + 1;
-
- if (asprintf(&optname, "\"%s\"", p->name) == -1)
- break;
-
- len += max(20, strlen(optname));
- len += strlen(opttype);
-
- ptr->dev_comment = realloc(ptr->dev_comment, len);
- if (!ptr->dev_comment)
- break;
- p_e = ptr->dev_comment + strlen(ptr->dev_comment);
- sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle,
- opttype, suffix);
- free(optname);
- }
- }
- }
-
- return ptr;
-}
-
-static XF86ConfLayoutPtr
-configureLayoutSection (void)
-{
- int scrnum = 0;
- parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec)
-
- ptr->lay_identifier = "X.org Configured";
-
- {
- XF86ConfInputrefPtr iptr;
-
- iptr = malloc (sizeof (XF86ConfInputrefRec));
- iptr->list.next = NULL;
- iptr->iref_option_lst = NULL;
- iptr->iref_inputdev_str = "Mouse0";
- iptr->iref_option_lst =
- xf86addNewOption (iptr->iref_option_lst, strdup("CorePointer"), NULL);
- ptr->lay_input_lst = (XF86ConfInputrefPtr)
- xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
- }
-
- {
- XF86ConfInputrefPtr iptr;
-
- iptr = malloc (sizeof (XF86ConfInputrefRec));
- iptr->list.next = NULL;
- iptr->iref_option_lst = NULL;
- iptr->iref_inputdev_str = "Keyboard0";
- iptr->iref_option_lst =
- xf86addNewOption (iptr->iref_option_lst, strdup("CoreKeyboard"), NULL);
- ptr->lay_input_lst = (XF86ConfInputrefPtr)
- xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
- }
-
- for (scrnum = 0; scrnum < nDevToConfig; scrnum++) {
- XF86ConfAdjacencyPtr aptr;
-
- aptr = malloc (sizeof (XF86ConfAdjacencyRec));
- aptr->list.next = NULL;
- aptr->adj_x = 0;
- aptr->adj_y = 0;
- aptr->adj_scrnum = scrnum;
- XNFasprintf(&aptr->adj_screen_str, "Screen%d", scrnum);
- if (scrnum == 0) {
- aptr->adj_where = CONF_ADJ_ABSOLUTE;
- aptr->adj_refscreen = NULL;
- }
- else {
- aptr->adj_where = CONF_ADJ_RIGHTOF;
- XNFasprintf(&aptr->adj_refscreen, "Screen%d", scrnum - 1);
- }
- ptr->lay_adjacency_lst =
- (XF86ConfAdjacencyPtr)xf86addListItem((glp)ptr->lay_adjacency_lst,
- (glp)aptr);
- }
-
- return ptr;
-}
-
-static XF86ConfFlagsPtr
-configureFlagsSection (void)
-{
- parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec)
-
- return ptr;
-}
-
-static XF86ConfModulePtr
-configureModuleSection (void)
-{
- char **elist, **el;
- /* Find the list of extension & font modules. */
- const char *esubdirs[] = {
- "extensions",
- "fonts",
- NULL
- };
- parsePrologue (XF86ConfModulePtr, XF86ConfModuleRec)
-
- elist = LoaderListDirs(esubdirs, NULL);
- if (elist) {
- for (el = elist; *el; el++) {
- XF86LoadPtr module;
-
- module = calloc(1, sizeof(XF86LoadRec));
- module->load_name = *el;
- ptr->mod_load_lst = (XF86LoadPtr)xf86addListItem(
- (glp)ptr->mod_load_lst, (glp)module);
- }
- free(elist);
- }
-
- return ptr;
-}
-
-static XF86ConfFilesPtr
-configureFilesSection (void)
-{
- parsePrologue (XF86ConfFilesPtr, XF86ConfFilesRec)
-
- if (xf86ModulePath)
- ptr->file_modulepath = strdup(xf86ModulePath);
- if (defaultFontPath)
- ptr->file_fontpath = strdup(defaultFontPath);
-
- return ptr;
-}
-
-static XF86ConfMonitorPtr
-configureMonitorSection (int screennum)
-{
- parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
-
- XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum);
- ptr->mon_vendor = strdup("Monitor Vendor");
- ptr->mon_modelname = strdup("Monitor Model");
-
- return ptr;
-}
-
-/* Initialize Configure Monitor from Detailed Timing Block */
-static void handle_detailed_input(struct detailed_monitor_section *det_mon,
- void *data)
-{
- XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data;
-
- switch (det_mon->type) {
- case DS_NAME:
- ptr->mon_modelname = realloc(ptr->mon_modelname,
- strlen((char*)(det_mon->section.name)) +
- 1);
- strcpy(ptr->mon_modelname,
- (char*)(det_mon->section.name));
- break;
- case DS_RANGES:
- ptr->mon_hsync[ptr->mon_n_hsync].lo =
- det_mon->section.ranges.min_h;
- ptr->mon_hsync[ptr->mon_n_hsync].hi =
- det_mon->section.ranges.max_h;
- ptr->mon_n_vrefresh = 1;
- ptr->mon_vrefresh[ptr->mon_n_hsync].lo =
- det_mon->section.ranges.min_v;
- ptr->mon_vrefresh[ptr->mon_n_hsync].hi =
- det_mon->section.ranges.max_v;
- ptr->mon_n_hsync++;
- default:
- break;
- }
-}
-
-static XF86ConfMonitorPtr
-configureDDCMonitorSection (int screennum)
-{
- int len, mon_width, mon_height;
-#define displaySizeMaxLen 80
- char displaySize_string[displaySizeMaxLen];
- int displaySizeLen;
-
- parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
-
- XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum);
- ptr->mon_vendor = strdup(ConfiguredMonitor->vendor.name);
- XNFasprintf(&ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id);
-
- /* features in centimetres, we want millimetres */
- mon_width = 10 * ConfiguredMonitor->features.hsize ;
- mon_height = 10 * ConfiguredMonitor->features.vsize ;
-
-#ifdef CONFIGURE_DISPLAYSIZE
- ptr->mon_width = mon_width;
- ptr->mon_height = mon_height;
-#else
- if (mon_width && mon_height) {
- /* when values available add DisplaySize option AS A COMMENT */
-
- displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen,
- "\t#DisplaySize\t%5d %5d\t# mm\n",
- mon_width, mon_height);
-
- if (displaySizeLen>0 && displaySizeLen<displaySizeMaxLen) {
- if (ptr->mon_comment) {
- len = strlen(ptr->mon_comment);
- } else {
- len = 0;
- }
- if ((ptr->mon_comment =
- realloc(ptr->mon_comment, len + strlen(displaySize_string) + 1))) {
- strcpy(ptr->mon_comment + len, displaySize_string);
- }
- }
- }
-#endif /* def CONFIGURE_DISPLAYSIZE */
-
- xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input,
- ptr);
-
- if (ConfiguredMonitor->features.dpms) {
- ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, strdup("DPMS"), NULL);
- }
-
- return ptr;
-}
-
-void
-DoConfigure(void)
-{
- int i,j, screennum = -1;
- char *home = NULL;
- char filename[PATH_MAX];
- char *addslash = "";
- XF86ConfigPtr xf86config = NULL;
- char **vlist, **vl;
- int *dev2screen;
-
- vlist = xf86DriverlistFromCompile();
-
- if (!vlist) {
- ErrorF("Missing output drivers. Configuration failed.\n");
- goto bail;
- }
-
- ErrorF("List of video drivers:\n");
- for (vl = vlist; *vl; vl++)
- ErrorF("\t%s\n", *vl);
-
- /* Load all the drivers that were found. */
- xf86LoadModules(vlist, NULL);
-
- free(vlist);
-
- for (i = 0; i < xf86NumDrivers; i++) {
- xorgHWFlags flags;
- if (!xf86DriverList[i]->driverFunc
- || !xf86DriverList[i]->driverFunc(NULL,
- GET_REQUIRED_HW_INTERFACES,
- &flags)
- || NEED_IO_ENABLED(flags)) {
- xorgHWAccess = TRUE;
- break;
- }
- }
- /* Enable full I/O access */
- if (xorgHWAccess) {
- if(!xf86EnableIO())
- /* oops, we have failed */
- xorgHWAccess = FALSE;
- }
-
- /* Create XF86Config file structure */
- xf86config = calloc(1, sizeof(XF86ConfigRec));
-
- /* Call all of the probe functions, reporting the results. */
- for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) {
- xorgHWFlags flags;
- Bool found_screen;
- DriverRec * const drv = xf86DriverList[CurrentDriver];
-
- if (!xorgHWAccess) {
- if (!drv->driverFunc
- || !drv->driverFunc( NULL, GET_REQUIRED_HW_INTERFACES, &flags )
- || NEED_IO_ENABLED(flags))
- continue;
- }
-
- found_screen = xf86CallDriverProbe( drv, TRUE );
- if ( found_screen && drv->Identify ) {
- (*drv->Identify)(0);
- }
- }
-
- if (nDevToConfig <= 0) {
- ErrorF("No devices to configure. Configuration failed.\n");
- goto bail;
- }
-
- /* Add device, monitor and screen sections for detected devices */
- for (screennum = 0; screennum < nDevToConfig; screennum++) {
- XF86ConfDevicePtr DevicePtr;
- XF86ConfMonitorPtr MonitorPtr;
- XF86ConfScreenPtr ScreenPtr;
-
- DevicePtr = configureDeviceSection(screennum);
- xf86config->conf_device_lst = (XF86ConfDevicePtr)xf86addListItem(
- (glp)xf86config->conf_device_lst, (glp)DevicePtr);
- MonitorPtr = configureMonitorSection(screennum);
- xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem(
- (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr);
- ScreenPtr = configureScreenSection(screennum);
- xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem(
- (glp)xf86config->conf_screen_lst, (glp)ScreenPtr);
- }
-
- xf86config->conf_files = configureFilesSection();
- xf86config->conf_modules = configureModuleSection();
- xf86config->conf_flags = configureFlagsSection();
- xf86config->conf_videoadaptor_lst = NULL;
- xf86config->conf_modes_lst = NULL;
- xf86config->conf_vendor_lst = NULL;
- xf86config->conf_dri = NULL;
- xf86config->conf_input_lst = configureInputSection();
- xf86config->conf_layout_lst = configureLayoutSection();
-
- home = getenv("HOME");
- if ((home == NULL) || (home[0] == '\0')) {
- home = "/";
- } else {
- /* Determine if trailing slash is present or needed */
- int l = strlen(home);
-
- if (home[l-1] != '/') {
- addslash = "/";
- }
- }
-
- snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new",
- home, addslash);
-
- if (xf86writeConfigFile(filename, xf86config) == 0) {
- xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
- filename, strerror(errno));
- goto bail;
- }
-
- xf86DoConfigurePass1 = FALSE;
- /* Try to get DDC information filled in */
- xf86ConfigFile = filename;
- if (xf86HandleConfigFile(FALSE) != CONFIG_OK) {
- goto bail;
- }
-
- xf86DoConfigurePass1 = FALSE;
-
- dev2screen = xnfcalloc(1,xf86NumDrivers*sizeof(int));
-
- {
- Bool *driverProbed = xnfcalloc(1,xf86NumDrivers*sizeof(Bool));
- for (screennum = 0; screennum < nDevToConfig; screennum++) {
- int k,l,n,oldNumScreens;
-
- i = DevToConfig[screennum].iDriver;
-
- if (driverProbed[i]) continue;
- driverProbed[i] = TRUE;
-
- oldNumScreens = xf86NumScreens;
-
- xf86CallDriverProbe( xf86DriverList[i], FALSE );
-
- /* reorder */
- k = screennum > 0 ? screennum : 1;
- for (l = oldNumScreens; l < xf86NumScreens; l++) {
- /* is screen primary? */
- Bool primary = FALSE;
- for (n = 0; n<xf86Screens[l]->numEntities; n++) {
- if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) {
- dev2screen[0] = l;
- primary = TRUE;
- break;
- }
- }
- if (primary) continue;
- /* not primary: assign it to next device of same driver */
- /*
- * NOTE: we assume that devices in DevToConfig
- * and xf86Screens[] have the same order except
- * for the primary device which always comes first.
- */
- for (; k < nDevToConfig; k++) {
- if (DevToConfig[k].iDriver == i) {
- dev2screen[k++] = l;
- break;
- }
- }
- }
- }
- free(driverProbed);
- }
-
-
- if (nDevToConfig != xf86NumScreens) {
- ErrorF("Number of created screens does not match number of detected"
- " devices.\n Configuration failed.\n");
- goto bail;
- }
-
- xf86PostProbe();
-
- for (j = 0; j < xf86NumScreens; j++) {
- xf86Screens[j]->scrnIndex = j;
- }
-
- xf86freeMonitorList(xf86config->conf_monitor_lst);
- xf86config->conf_monitor_lst = NULL;
- xf86freeScreenList(xf86config->conf_screen_lst);
- xf86config->conf_screen_lst = NULL;
- for (j = 0; j < xf86NumScreens; j++) {
- XF86ConfMonitorPtr MonitorPtr;
- XF86ConfScreenPtr ScreenPtr;
-
- ConfiguredMonitor = NULL;
-
- if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]],
- PROBE_DETECT) &&
- ConfiguredMonitor) {
- MonitorPtr = configureDDCMonitorSection(j);
- } else {
- MonitorPtr = configureMonitorSection(j);
- }
- ScreenPtr = configureScreenSection(j);
- xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem(
- (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr);
- xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem(
- (glp)xf86config->conf_screen_lst, (glp)ScreenPtr);
- }
-
- if (xf86writeConfigFile(filename, xf86config) == 0) {
- xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
- filename, strerror(errno));
- goto bail;
- }
-
- ErrorF("\n");
-
- if (!foundMouse) {
- ErrorF("\n"__XSERVERNAME__" is not able to detect your mouse.\n"
- "Edit the file and correct the Device.\n");
- } else {
- ErrorF("\n"__XSERVERNAME__" detected your mouse at device %s.\n"
- "Please check your config if the mouse is still not\n"
- "operational, as by default "__XSERVERNAME__
- " tries to autodetect\n"
- "the protocol.\n",DFLT_MOUSE_DEV);
- }
-
- if (xf86NumScreens > 1) {
- ErrorF("\n"__XSERVERNAME__
- " has configured a multihead system, please check your config.\n");
- }
-
- ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE ,filename);
- ErrorF("To test the server, run 'X -config %s'\n\n", filename);
-
-bail:
- OsCleanup(TRUE);
- AbortDDX();
- fflush(stderr);
- exit(0);
-}
+/*
+ * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales.
+ *
+ * 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, and that the name of Alan Hourihane not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Alan Hourihane makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Alan Hourihane, alanh@fairlite.demon.co.uk
+ *
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "xf86.h"
+#include "xf86Config.h"
+#include "xf86_OSlib.h"
+#include "xf86Priv.h"
+#define IN_XSERVER
+#include "Configint.h"
+#include "xf86DDC.h"
+#include "xf86pciBus.h"
+#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
+#include "xf86Bus.h"
+#include "xf86Sbus.h"
+#endif
+#include "misc.h"
+
+typedef struct _DevToConfig {
+ GDevRec GDev;
+ struct pci_device * pVideo;
+#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
+ sbusDevicePtr sVideo;
+#endif
+ int iDriver;
+} DevToConfigRec, *DevToConfigPtr;
+
+static DevToConfigPtr DevToConfig = NULL;
+static int nDevToConfig = 0, CurrentDriver;
+
+xf86MonPtr ConfiguredMonitor;
+Bool xf86DoConfigurePass1 = TRUE;
+static Bool foundMouse = FALSE;
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+static char *DFLT_MOUSE_DEV = "/dev/sysmouse";
+static char *DFLT_MOUSE_PROTO = "auto";
+#elif defined(linux)
+static char DFLT_MOUSE_DEV[] = "/dev/input/mice";
+static char DFLT_MOUSE_PROTO[] = "auto";
+#elif defined(WSCONS_SUPPORT)
+static char *DFLT_MOUSE_DEV = "/dev/wsmouse";
+static char *DFLT_MOUSE_PROTO = "wsmouse";
+#else
+static char *DFLT_MOUSE_DEV = "/dev/mouse";
+static char *DFLT_MOUSE_PROTO = "auto";
+#endif
+
+/*
+ * This is called by the driver, either through xf86Match???Instances() or
+ * directly. We allocate a GDevRec and fill it in as much as we can, letting
+ * the caller fill in the rest and/or change it as it sees fit.
+ */
+GDevPtr
+xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, int chipset)
+{
+ int ret, i, j;
+
+ if (!xf86DoConfigure || !xf86DoConfigurePass1)
+ return NULL;
+
+ /* Check for duplicates */
+ for (i = 0; i < nDevToConfig; i++) {
+ switch (bus) {
+ case BUS_PCI:
+ ret = xf86PciConfigure(busData, DevToConfig[i].pVideo);
+ break;
+#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
+ case BUS_SBUS:
+ ret = xf86SbusConfigure(busData, DevToConfig[i].sVideo);
+ break;
+#endif
+ default:
+ return NULL;
+ }
+ if (ret == 0)
+ goto out;
+ }
+
+ /* Allocate new structure occurrence */
+ i = nDevToConfig++;
+ DevToConfig =
+ xnfrealloc(DevToConfig, nDevToConfig * sizeof(DevToConfigRec));
+ memset(DevToConfig + i, 0, sizeof(DevToConfigRec));
+
+ DevToConfig[i].GDev.chipID =
+ DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1;
+
+ DevToConfig[i].iDriver = CurrentDriver;
+
+ /* Fill in what we know, converting the driver name to lower case */
+ DevToConfig[i].GDev.driver = xnfalloc(strlen(driver) + 1);
+ for (j = 0; (DevToConfig[i].GDev.driver[j] = tolower(driver[j])); j++);
+
+ switch (bus) {
+ case BUS_PCI:
+ xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo,
+ &DevToConfig[i].GDev, &chipset);
+ break;
+#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
+ case BUS_SBUS:
+ xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo,
+ &DevToConfig[i].GDev);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ /* Get driver's available options */
+ if (xf86DriverList[CurrentDriver]->AvailableOptions)
+ DevToConfig[i].GDev.options = (OptionInfoPtr)
+ (*xf86DriverList[CurrentDriver]->AvailableOptions)(chipset,
+ bus);
+
+ return &DevToConfig[i].GDev;
+
+out:
+ return NULL;
+}
+
+static XF86ConfInputPtr
+configureInputSection (void)
+{
+ XF86ConfInputPtr mouse = NULL;
+ parsePrologue (XF86ConfInputPtr, XF86ConfInputRec)
+
+ ptr->inp_identifier = "Keyboard0";
+ ptr->inp_driver = "kbd";
+ ptr->list.next = NULL;
+
+ /* Crude mechanism to auto-detect mouse (os dependent) */
+ {
+ int fd;
+
+ fd = open(DFLT_MOUSE_DEV, 0);
+ if (fd != -1) {
+ foundMouse = TRUE;
+ close(fd);
+ }
+ }
+
+ mouse = calloc(1, sizeof(XF86ConfInputRec));
+ mouse->inp_identifier = "Mouse0";
+ mouse->inp_driver = "mouse";
+ mouse->inp_option_lst =
+ xf86addNewOption(mouse->inp_option_lst, strdup("Protocol"),
+ strdup(DFLT_MOUSE_PROTO));
+ mouse->inp_option_lst =
+ xf86addNewOption(mouse->inp_option_lst, strdup("Device"),
+ strdup(DFLT_MOUSE_DEV));
+ mouse->inp_option_lst =
+ xf86addNewOption(mouse->inp_option_lst, strdup("ZAxisMapping"),
+ strdup("4 5 6 7"));
+ ptr = (XF86ConfInputPtr)xf86addListItem((glp)ptr, (glp)mouse);
+ return ptr;
+}
+
+static XF86ConfScreenPtr
+configureScreenSection (int screennum)
+{
+ int i;
+ int depths[] = { 1, 4, 8, 15, 16, 24/*, 32*/ };
+ parsePrologue (XF86ConfScreenPtr, XF86ConfScreenRec)
+
+ XNFasprintf(&ptr->scrn_identifier, "Screen%d", screennum);
+ XNFasprintf(&ptr->scrn_monitor_str, "Monitor%d", screennum);
+ XNFasprintf(&ptr->scrn_device_str, "Card%d", screennum);
+
+ for (i=0; i<sizeof(depths)/sizeof(depths[0]); i++)
+ {
+ XF86ConfDisplayPtr display;
+
+ display = calloc(1, sizeof(XF86ConfDisplayRec));
+ display->disp_depth = depths[i];
+ display->disp_black.red = display->disp_white.red = -1;
+ display->disp_black.green = display->disp_white.green = -1;
+ display->disp_black.blue = display->disp_white.blue = -1;
+ ptr->scrn_display_lst = (XF86ConfDisplayPtr)xf86addListItem(
+ (glp)ptr->scrn_display_lst, (glp)display);
+ }
+
+ return ptr;
+}
+
+static const char*
+optionTypeToString(OptionValueType type)
+{
+ switch (type) {
+ case OPTV_NONE:
+ return "";
+ case OPTV_INTEGER:
+ return "<i>";
+ case OPTV_STRING:
+ return "<str>";
+ case OPTV_ANYSTR:
+ return "[<str>]";
+ case OPTV_REAL:
+ return "<f>";
+ case OPTV_BOOLEAN:
+ return "[<bool>]";
+ case OPTV_FREQ:
+ return "<freq>";
+ case OPTV_PERCENT:
+ return "<percent>";
+ default:
+ return "";
+ }
+}
+
+static XF86ConfDevicePtr
+configureDeviceSection (int screennum)
+{
+ OptionInfoPtr p;
+ int i = 0;
+ parsePrologue (XF86ConfDevicePtr, XF86ConfDeviceRec)
+
+ /* Move device info to parser structure */
+ if (asprintf(&ptr->dev_identifier, "Card%d", screennum) == -1)
+ ptr->dev_identifier = NULL;
+ ptr->dev_chipset = DevToConfig[screennum].GDev.chipset;
+ ptr->dev_busid = DevToConfig[screennum].GDev.busID;
+ ptr->dev_driver = DevToConfig[screennum].GDev.driver;
+ ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac;
+ for (i = 0; (i < MAXDACSPEEDS) && (i < CONF_MAXDACSPEEDS); i++)
+ ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i];
+ ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam;
+ ptr->dev_textclockfreq = DevToConfig[screennum].GDev.textClockFreq;
+ ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase;
+ ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase;
+ ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase;
+ ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip;
+ for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks); i++)
+ ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i];
+ ptr->dev_clocks = i;
+ ptr->dev_chipid = DevToConfig[screennum].GDev.chipID;
+ ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev;
+ ptr->dev_irq = DevToConfig[screennum].GDev.irq;
+
+ /* Make sure older drivers don't segv */
+ if (DevToConfig[screennum].GDev.options) {
+ /* Fill in the available driver options for people to use */
+ const char *descrip =
+ " ### Available Driver options are:-\n"
+ " ### Values: <i>: integer, <f>: float, "
+ "<bool>: \"True\"/\"False\",\n"
+ " ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n"
+ " ### <percent>: \"<f>%\"\n"
+ " ### [arg]: arg optional\n";
+ ptr->dev_comment = strdup(descrip);
+ if (ptr->dev_comment) {
+ for (p = DevToConfig[screennum].GDev.options;
+ p->name != NULL; p++) {
+ char *p_e;
+ const char *prefix = " #Option ";
+ const char *middle = " \t# ";
+ const char *suffix = "\n";
+ const char *opttype = optionTypeToString(p->type);
+ char *optname;
+ int len = strlen(ptr->dev_comment) + strlen(prefix) +
+ strlen(middle) + strlen(suffix) + 1;
+
+ if (asprintf(&optname, "\"%s\"", p->name) == -1)
+ break;
+
+ len += max(20, strlen(optname));
+ len += strlen(opttype);
+
+ ptr->dev_comment = realloc(ptr->dev_comment, len);
+ if (!ptr->dev_comment)
+ break;
+ p_e = ptr->dev_comment + strlen(ptr->dev_comment);
+ sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle,
+ opttype, suffix);
+ free(optname);
+ }
+ }
+ }
+
+ return ptr;
+}
+
+static XF86ConfLayoutPtr
+configureLayoutSection (void)
+{
+ int scrnum = 0;
+ parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec)
+
+ ptr->lay_identifier = "X.org Configured";
+
+ {
+ XF86ConfInputrefPtr iptr;
+
+ iptr = malloc (sizeof (XF86ConfInputrefRec));
+ iptr->list.next = NULL;
+ iptr->iref_option_lst = NULL;
+ iptr->iref_inputdev_str = "Mouse0";
+ iptr->iref_option_lst =
+ xf86addNewOption (iptr->iref_option_lst, strdup("CorePointer"), NULL);
+ ptr->lay_input_lst = (XF86ConfInputrefPtr)
+ xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
+ }
+
+ {
+ XF86ConfInputrefPtr iptr;
+
+ iptr = malloc (sizeof (XF86ConfInputrefRec));
+ iptr->list.next = NULL;
+ iptr->iref_option_lst = NULL;
+ iptr->iref_inputdev_str = "Keyboard0";
+ iptr->iref_option_lst =
+ xf86addNewOption (iptr->iref_option_lst, strdup("CoreKeyboard"), NULL);
+ ptr->lay_input_lst = (XF86ConfInputrefPtr)
+ xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr);
+ }
+
+ for (scrnum = 0; scrnum < nDevToConfig; scrnum++) {
+ XF86ConfAdjacencyPtr aptr;
+
+ aptr = malloc (sizeof (XF86ConfAdjacencyRec));
+ aptr->list.next = NULL;
+ aptr->adj_x = 0;
+ aptr->adj_y = 0;
+ aptr->adj_scrnum = scrnum;
+ XNFasprintf(&aptr->adj_screen_str, "Screen%d", scrnum);
+ if (scrnum == 0) {
+ aptr->adj_where = CONF_ADJ_ABSOLUTE;
+ aptr->adj_refscreen = NULL;
+ }
+ else {
+ aptr->adj_where = CONF_ADJ_RIGHTOF;
+ XNFasprintf(&aptr->adj_refscreen, "Screen%d", scrnum - 1);
+ }
+ ptr->lay_adjacency_lst =
+ (XF86ConfAdjacencyPtr)xf86addListItem((glp)ptr->lay_adjacency_lst,
+ (glp)aptr);
+ }
+
+ return ptr;
+}
+
+static XF86ConfFlagsPtr
+configureFlagsSection (void)
+{
+ parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec)
+
+ return ptr;
+}
+
+static XF86ConfModulePtr
+configureModuleSection (void)
+{
+ char **elist, **el;
+ /* Find the list of extension & font modules. */
+ const char *esubdirs[] = {
+ "extensions",
+ "fonts",
+ NULL
+ };
+ parsePrologue (XF86ConfModulePtr, XF86ConfModuleRec)
+
+ elist = LoaderListDirs(esubdirs, NULL);
+ if (elist) {
+ for (el = elist; *el; el++) {
+ XF86LoadPtr module;
+
+ module = calloc(1, sizeof(XF86LoadRec));
+ module->load_name = *el;
+ ptr->mod_load_lst = (XF86LoadPtr)xf86addListItem(
+ (glp)ptr->mod_load_lst, (glp)module);
+ }
+ free(elist);
+ }
+
+ return ptr;
+}
+
+static XF86ConfFilesPtr
+configureFilesSection (void)
+{
+ parsePrologue (XF86ConfFilesPtr, XF86ConfFilesRec)
+
+ if (xf86ModulePath)
+ ptr->file_modulepath = strdup(xf86ModulePath);
+ if (defaultFontPath)
+ ptr->file_fontpath = strdup(defaultFontPath);
+
+ return ptr;
+}
+
+static XF86ConfMonitorPtr
+configureMonitorSection (int screennum)
+{
+ parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
+
+ XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum);
+ ptr->mon_vendor = strdup("Monitor Vendor");
+ ptr->mon_modelname = strdup("Monitor Model");
+
+ return ptr;
+}
+
+/* Initialize Configure Monitor from Detailed Timing Block */
+static void handle_detailed_input(struct detailed_monitor_section *det_mon,
+ void *data)
+{
+ XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data;
+
+ switch (det_mon->type) {
+ case DS_NAME:
+ ptr->mon_modelname = realloc(ptr->mon_modelname,
+ strlen((char*)(det_mon->section.name)) +
+ 1);
+ strcpy(ptr->mon_modelname,
+ (char*)(det_mon->section.name));
+ break;
+ case DS_RANGES:
+ ptr->mon_hsync[ptr->mon_n_hsync].lo =
+ det_mon->section.ranges.min_h;
+ ptr->mon_hsync[ptr->mon_n_hsync].hi =
+ det_mon->section.ranges.max_h;
+ ptr->mon_n_vrefresh = 1;
+ ptr->mon_vrefresh[ptr->mon_n_hsync].lo =
+ det_mon->section.ranges.min_v;
+ ptr->mon_vrefresh[ptr->mon_n_hsync].hi =
+ det_mon->section.ranges.max_v;
+ ptr->mon_n_hsync++;
+ default:
+ break;
+ }
+}
+
+static XF86ConfMonitorPtr
+configureDDCMonitorSection (int screennum)
+{
+ int len, mon_width, mon_height;
+#define displaySizeMaxLen 80
+ char displaySize_string[displaySizeMaxLen];
+ int displaySizeLen;
+
+ parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec)
+
+ XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum);
+ ptr->mon_vendor = strdup(ConfiguredMonitor->vendor.name);
+ XNFasprintf(&ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id);
+
+ /* features in centimetres, we want millimetres */
+ mon_width = 10 * ConfiguredMonitor->features.hsize ;
+ mon_height = 10 * ConfiguredMonitor->features.vsize ;
+
+#ifdef CONFIGURE_DISPLAYSIZE
+ ptr->mon_width = mon_width;
+ ptr->mon_height = mon_height;
+#else
+ if (mon_width && mon_height) {
+ /* when values available add DisplaySize option AS A COMMENT */
+
+ displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen,
+ "\t#DisplaySize\t%5d %5d\t# mm\n",
+ mon_width, mon_height);
+
+ if (displaySizeLen>0 && displaySizeLen<displaySizeMaxLen) {
+ if (ptr->mon_comment) {
+ len = strlen(ptr->mon_comment);
+ } else {
+ len = 0;
+ }
+ if ((ptr->mon_comment =
+ realloc(ptr->mon_comment, len + strlen(displaySize_string) + 1))) {
+ strcpy(ptr->mon_comment + len, displaySize_string);
+ }
+ }
+ }
+#endif /* def CONFIGURE_DISPLAYSIZE */
+
+ xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input,
+ ptr);
+
+ if (ConfiguredMonitor->features.dpms) {
+ ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, strdup("DPMS"), NULL);
+ }
+
+ return ptr;
+}
+
+void
+DoConfigure(void)
+{
+ int i,j, screennum = -1;
+ char *home = NULL;
+ char filename[PATH_MAX];
+ char *addslash = "";
+ XF86ConfigPtr xf86config = NULL;
+ char **vlist, **vl;
+ int *dev2screen;
+
+ vlist = xf86DriverlistFromCompile();
+
+ if (!vlist) {
+ ErrorF("Missing output drivers. Configuration failed.\n");
+ goto bail;
+ }
+
+ ErrorF("List of video drivers:\n");
+ for (vl = vlist; *vl; vl++)
+ ErrorF("\t%s\n", *vl);
+
+ /* Load all the drivers that were found. */
+ xf86LoadModules(vlist, NULL);
+
+ free(vlist);
+
+ for (i = 0; i < xf86NumDrivers; i++) {
+ xorgHWFlags flags;
+ if (!xf86DriverList[i]->driverFunc
+ || !xf86DriverList[i]->driverFunc(NULL,
+ GET_REQUIRED_HW_INTERFACES,
+ &flags)
+ || NEED_IO_ENABLED(flags)) {
+ xorgHWAccess = TRUE;
+ break;
+ }
+ }
+ /* Enable full I/O access */
+ if (xorgHWAccess) {
+ if(!xf86EnableIO())
+ /* oops, we have failed */
+ xorgHWAccess = FALSE;
+ }
+
+ /* Create XF86Config file structure */
+ xf86config = calloc(1, sizeof(XF86ConfigRec));
+
+ /* Call all of the probe functions, reporting the results. */
+ for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) {
+ xorgHWFlags flags;
+ Bool found_screen;
+ DriverRec * const drv = xf86DriverList[CurrentDriver];
+
+ if (!xorgHWAccess) {
+ if (!drv->driverFunc
+ || !drv->driverFunc( NULL, GET_REQUIRED_HW_INTERFACES, &flags )
+ || NEED_IO_ENABLED(flags))
+ continue;
+ }
+
+ found_screen = xf86CallDriverProbe( drv, TRUE );
+ if ( found_screen && drv->Identify ) {
+ (*drv->Identify)(0);
+ }
+ }
+
+ if (nDevToConfig <= 0) {
+ ErrorF("No devices to configure. Configuration failed.\n");
+ goto bail;
+ }
+
+ /* Add device, monitor and screen sections for detected devices */
+ for (screennum = 0; screennum < nDevToConfig; screennum++) {
+ XF86ConfDevicePtr DevicePtr;
+ XF86ConfMonitorPtr MonitorPtr;
+ XF86ConfScreenPtr ScreenPtr;
+
+ DevicePtr = configureDeviceSection(screennum);
+ xf86config->conf_device_lst = (XF86ConfDevicePtr)xf86addListItem(
+ (glp)xf86config->conf_device_lst, (glp)DevicePtr);
+ MonitorPtr = configureMonitorSection(screennum);
+ xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem(
+ (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr);
+ ScreenPtr = configureScreenSection(screennum);
+ xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem(
+ (glp)xf86config->conf_screen_lst, (glp)ScreenPtr);
+ }
+
+ xf86config->conf_files = configureFilesSection();
+ xf86config->conf_modules = configureModuleSection();
+ xf86config->conf_flags = configureFlagsSection();
+ xf86config->conf_videoadaptor_lst = NULL;
+ xf86config->conf_modes_lst = NULL;
+ xf86config->conf_vendor_lst = NULL;
+ xf86config->conf_dri = NULL;
+ xf86config->conf_input_lst = configureInputSection();
+ xf86config->conf_layout_lst = configureLayoutSection();
+
+ home = getenv("HOME");
+ if ((home == NULL) || (home[0] == '\0')) {
+ home = "/";
+ } else {
+ /* Determine if trailing slash is present or needed */
+ int l = strlen(home);
+
+ if (home[l-1] != '/') {
+ addslash = "/";
+ }
+ }
+
+ snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new",
+ home, addslash);
+
+ if (xf86writeConfigFile(filename, xf86config) == 0) {
+ xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
+ filename, strerror(errno));
+ goto bail;
+ }
+
+ xf86DoConfigurePass1 = FALSE;
+ /* Try to get DDC information filled in */
+ xf86ConfigFile = filename;
+ if (xf86HandleConfigFile(FALSE) != CONFIG_OK) {
+ goto bail;
+ }
+
+ xf86DoConfigurePass1 = FALSE;
+
+ dev2screen = xnfcalloc(1,xf86NumDrivers*sizeof(int));
+
+ {
+ Bool *driverProbed = xnfcalloc(1,xf86NumDrivers*sizeof(Bool));
+ for (screennum = 0; screennum < nDevToConfig; screennum++) {
+ int k,l,n,oldNumScreens;
+
+ i = DevToConfig[screennum].iDriver;
+
+ if (driverProbed[i]) continue;
+ driverProbed[i] = TRUE;
+
+ oldNumScreens = xf86NumScreens;
+
+ xf86CallDriverProbe( xf86DriverList[i], FALSE );
+
+ /* reorder */
+ k = screennum > 0 ? screennum : 1;
+ for (l = oldNumScreens; l < xf86NumScreens; l++) {
+ /* is screen primary? */
+ Bool primary = FALSE;
+ for (n = 0; n<xf86Screens[l]->numEntities; n++) {
+ if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) {
+ dev2screen[0] = l;
+ primary = TRUE;
+ break;
+ }
+ }
+ if (primary) continue;
+ /* not primary: assign it to next device of same driver */
+ /*
+ * NOTE: we assume that devices in DevToConfig
+ * and xf86Screens[] have the same order except
+ * for the primary device which always comes first.
+ */
+ for (; k < nDevToConfig; k++) {
+ if (DevToConfig[k].iDriver == i) {
+ dev2screen[k++] = l;
+ break;
+ }
+ }
+ }
+ }
+ free(driverProbed);
+ }
+
+
+ if (nDevToConfig != xf86NumScreens) {
+ ErrorF("Number of created screens does not match number of detected"
+ " devices.\n Configuration failed.\n");
+ goto bail;
+ }
+
+ xf86PostProbe();
+
+ for (j = 0; j < xf86NumScreens; j++) {
+ xf86Screens[j]->scrnIndex = j;
+ }
+
+ xf86freeMonitorList(xf86config->conf_monitor_lst);
+ xf86config->conf_monitor_lst = NULL;
+ xf86freeScreenList(xf86config->conf_screen_lst);
+ xf86config->conf_screen_lst = NULL;
+ for (j = 0; j < xf86NumScreens; j++) {
+ XF86ConfMonitorPtr MonitorPtr;
+ XF86ConfScreenPtr ScreenPtr;
+
+ ConfiguredMonitor = NULL;
+
+ if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]],
+ PROBE_DETECT) &&
+ ConfiguredMonitor) {
+ MonitorPtr = configureDDCMonitorSection(j);
+ } else {
+ MonitorPtr = configureMonitorSection(j);
+ }
+ ScreenPtr = configureScreenSection(j);
+ xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem(
+ (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr);
+ xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem(
+ (glp)xf86config->conf_screen_lst, (glp)ScreenPtr);
+ }
+
+ if (xf86writeConfigFile(filename, xf86config) == 0) {
+ xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n",
+ filename, strerror(errno));
+ goto bail;
+ }
+
+ ErrorF("\n");
+
+ if (!foundMouse) {
+ ErrorF("\n"__XSERVERNAME__" is not able to detect your mouse.\n"
+ "Edit the file and correct the Device.\n");
+ } else {
+ ErrorF("\n"__XSERVERNAME__" detected your mouse at device %s.\n"
+ "Please check your config if the mouse is still not\n"
+ "operational, as by default "__XSERVERNAME__
+ " tries to autodetect\n"
+ "the protocol.\n",DFLT_MOUSE_DEV);
+ }
+
+ if (xf86NumScreens > 1) {
+ ErrorF("\n"__XSERVERNAME__
+ " has configured a multihead system, please check your config.\n");
+ }
+
+ ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE ,filename);
+ ErrorF("To test the server, run 'X -config %s'\n\n", filename);
+
+bail:
+ OsCleanup(TRUE);
+ AbortDDX();
+ fflush(stderr);
+ exit(0);
+}
diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c
index 84c0d182a..3006ad183 100644
--- a/xorg-server/hw/xfree86/common/xf86Events.c
+++ b/xorg-server/hw/xfree86/common/xf86Events.c
@@ -399,7 +399,7 @@ xf86ReleaseKeys(DeviceIntPtr pDev)
i++) {
if (key_is_down(pDev, i, KEY_POSTED)) {
sigstate = xf86BlockSIGIO ();
- nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i);
+ nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i, NULL);
for (j = 0; j < nevents; j++)
mieqEnqueue(pDev, (InternalEvent*)(xf86Events + j)->event);
xf86UnblockSIGIO(sigstate);
diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c
index ae22ef268..ef4542c5f 100644
--- a/xorg-server/hw/xfree86/common/xf86Xinput.c
+++ b/xorg-server/hw/xfree86/common/xf86Xinput.c
@@ -1013,7 +1013,6 @@ xf86PostMotionEventM(DeviceIntPtr device,
const ValuatorMask *mask)
{
int i = 0, nevents = 0;
- DeviceEvent *event;
int flags = 0;
if (valuator_mask_num_valuators(mask) > 0)
@@ -1054,7 +1053,6 @@ xf86PostMotionEventM(DeviceIntPtr device,
nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask);
for (i = 0; i < nevents; i++) {
- event = (DeviceEvent*)((xf86Events + i)->event);
mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event));
}
}
@@ -1252,16 +1250,9 @@ xf86PostKeyEventM(DeviceIntPtr device,
}
#endif
- if (is_absolute) {
- nevents = GetKeyboardValuatorEvents(xf86Events, device,
- is_down ? KeyPress : KeyRelease,
- key_code, mask);
- }
- else {
- nevents = GetKeyboardEvents(xf86Events, device,
- is_down ? KeyPress : KeyRelease,
- key_code);
- }
+ nevents = GetKeyboardEvents(xf86Events, device,
+ is_down ? KeyPress : KeyRelease,
+ key_code, mask);
for (i = 0; i < nevents; i++)
mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event));
diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
index d1f29d909..77dfb2f16 100644
--- a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
+++ b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
@@ -1,330 +1,345 @@
-/*
- * Copyright 1992 by Orest Zborowski <obz@Kodak.com>
- * Copyright 1993 by David Wexelblat <dwex@goblin.org>
- *
- * 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, and that the names of Orest Zborowski and David Wexelblat
- * not be used in advertising or publicity pertaining to distribution of
- * the software without specific, written prior permission. Orest Zborowski
- * and David Wexelblat make no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD
- * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE
- * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xmd.h>
-
-#include "compiler.h"
-
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-
-#include <sys/stat.h>
-
-static Bool KeepTty = FALSE;
-static Bool VTSwitch = TRUE;
-static Bool ShareVTs = FALSE;
-static int activeVT = -1;
-
-static char vtname[11];
-static struct termios tty_attr; /* tty state to restore */
-static int tty_mode; /* kbd mode to restore */
-
-static void *console_handler;
-
-static void
-drain_console(int fd, void *closure)
-{
- errno = 0;
- if (tcflush(fd, TCIOFLUSH) == -1 && errno == EIO) {
- xf86RemoveGeneralHandler(console_handler);
- console_handler = NULL;
- }
-}
-
-static void
-switch_to(int vt, const char *from)
-{
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vt) < 0)
- FatalError("%s: VT_ACTIVATE failed: %s\n", from, strerror(errno));
-
- if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, vt) < 0)
- FatalError("%s: VT_WAITACTIVE failed: %s\n", from, strerror(errno));
-}
-
-void
-xf86OpenConsole(void)
-{
- int i, fd = -1;
- struct vt_mode VT;
- struct vt_stat vts;
- MessageType from = X_PROBED;
- char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
- char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
-
- if (serverGeneration == 1) {
-
- /* when KeepTty check if we're run with euid==0 */
- if (KeepTty && geteuid() != 0)
- FatalError("xf86OpenConsole:"
- " Server must be suid root for option \"KeepTTY\"\n");
-
- /*
- * setup the virtual terminal manager
- */
- if (xf86Info.vtno != -1) {
- from = X_CMDLINE;
- } else {
-
- i=0;
- while (tty0[i] != NULL) {
- if ((fd = open(tty0[i],O_WRONLY,0)) >= 0)
- break;
- i++;
- }
-
- if (fd < 0)
- FatalError(
- "xf86OpenConsole: Cannot open /dev/tty0 (%s)\n",
- strerror(errno));
-
- if (ShareVTs)
- {
- if (ioctl(fd, VT_GETSTATE, &vts) == 0)
- xf86Info.vtno = vts.v_active;
- else
- FatalError("xf86OpenConsole: Cannot find the current"
- " VT (%s)\n", strerror(errno));
- } else {
- if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
- (xf86Info.vtno == -1))
- FatalError("xf86OpenConsole: Cannot find a free VT: %s\n",
- strerror(errno));
- }
- close(fd);
- }
-
- xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
-
- if (!KeepTty) {
- pid_t ppid = getppid();
- pid_t ppgid;
- ppgid = getpgid(ppid);
-
- /*
- * change to parent process group that pgid != pid so
- * that setsid() doesn't fail and we become process
- * group leader
- */
- if (setpgid(0,ppgid) < 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: setpgid failed: %s\n",
- strerror(errno));
-
- /* become process group leader */
- if ((setsid() < 0))
- xf86Msg(X_WARNING, "xf86OpenConsole: setsid failed: %s\n",
- strerror(errno));
- }
-
- i=0;
- while (vcs[i] != NULL) {
- sprintf(vtname, vcs[i], xf86Info.vtno); /* /dev/tty1-64 */
- if ((xf86Info.consoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) >= 0)
- break;
- i++;
- }
-
- if (xf86Info.consoleFd < 0)
- FatalError("xf86OpenConsole: Cannot open virtual console"
- " %d (%s)\n", xf86Info.vtno, strerror(errno));
-
- /*
- * Linux doesn't switch to an active vt after the last close of a vt,
- * so we do this ourselves by remembering which is active now.
- */
- if (ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts) < 0)
- xf86Msg(X_WARNING,"xf86OpenConsole: VT_GETSTATE failed: %s\n",
- strerror(errno));
- else
- activeVT = vts.v_active;
-
-#if 0
- if (!KeepTty) {
- /*
- * Detach from the controlling tty to avoid char loss
- */
- if ((i = open("/dev/tty",O_RDWR)) >= 0) {
- ioctl(i, TIOCNOTTY, 0);
- close(i);
- }
- }
-#endif
-
- if (!ShareVTs)
- {
- struct termios nTty;
-
- /*
- * now get the VT. This _must_ succeed, or else fail completely.
- */
- switch_to(xf86Info.vtno, "xf86OpenConsole");
-
- if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
- FatalError("xf86OpenConsole: VT_GETMODE failed %s\n",
- strerror(errno));
-
- signal(SIGUSR1, xf86VTRequest);
-
- VT.mode = VT_PROCESS;
- VT.relsig = SIGUSR1;
- VT.acqsig = SIGUSR1;
-
- if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
- FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed: %s\n",
- strerror(errno));
-
- if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0)
- FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed %s\n",
- strerror(errno));
-
- tcgetattr(xf86Info.consoleFd, &tty_attr);
- ioctl(xf86Info.consoleFd, KDGKBMODE, &tty_mode);
-
- if (ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW) < 0)
- FatalError("xf86OpenConsole: KDSKBMODE K_RAW failed %s\n",
- strerror(errno));
-
- nTty = tty_attr;
- nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
- nTty.c_oflag = 0;
- nTty.c_cflag = CREAD | CS8;
- nTty.c_lflag = 0;
- nTty.c_cc[VTIME]=0;
- nTty.c_cc[VMIN]=1;
- cfsetispeed(&nTty, 9600);
- cfsetospeed(&nTty, 9600);
- tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty);
-
- /* need to keep the buffer clean, else the kernel gets angry */
- xf86SetConsoleHandler(drain_console, NULL);
-
- /* we really should have a InitOSInputDevices() function instead
- * of Init?$#*&Device(). So I just place it here */
- }
- } else { /* serverGeneration != 1 */
- if (!ShareVTs && VTSwitch)
- {
- /* now get the VT */
- switch_to(xf86Info.vtno, "xf86OpenConsole");
- }
- }
-}
-
-void
-xf86CloseConsole(void)
-{
- struct vt_mode VT;
-
- if (ShareVTs) {
- close(xf86Info.consoleFd);
- return;
- }
-
- if (console_handler) {
- xf86RemoveGeneralHandler(console_handler);
- console_handler = NULL;
- };
-
- /* Back to text mode ... */
- if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT) < 0)
- xf86Msg(X_WARNING, "xf86CloseConsole: KDSETMODE failed: %s\n",
- strerror(errno));
-
- ioctl(xf86Info.consoleFd, KDSKBMODE, tty_mode);
- tcsetattr(xf86Info.consoleFd, TCSANOW, &tty_attr);
-
- if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
- xf86Msg(X_WARNING, "xf86CloseConsole: VT_GETMODE failed: %s\n",
- strerror(errno));
- else {
- /* set dflt vt handling */
- VT.mode = VT_AUTO;
- if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
- xf86Msg(X_WARNING, "xf86CloseConsole: VT_SETMODE failed: %s\n",
- strerror(errno));
- }
-
- if (VTSwitch)
- {
- /*
- * Perform a switch back to the active VT when we were started
- */
- if (activeVT >= 0) {
- switch_to(activeVT, "xf86CloseConsole");
- activeVT = -1;
- }
- }
- close(xf86Info.consoleFd); /* make the vt-manager happy */
-}
-
-int
-xf86ProcessArgument(int argc, char *argv[], int i)
-{
- /*
- * Keep server from detaching from controlling tty. This is useful
- * when debugging (so the server can receive keyboard signals.
- */
- if (!strcmp(argv[i], "-keeptty"))
- {
- KeepTty = TRUE;
- return 1;
- }
- if (!strcmp(argv[i], "-novtswitch"))
- {
- VTSwitch = FALSE;
- return 1;
- }
- if (!strcmp(argv[i], "-sharevts"))
- {
- ShareVTs = TRUE;
- return 1;
- }
- if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
- {
- if (sscanf(argv[i], "vt%2d", &xf86Info.vtno) == 0)
- {
- UseMsg();
- xf86Info.vtno = -1;
- return 0;
- }
- return 1;
- }
- return 0;
-}
-
-void
-xf86UseMsg(void)
-{
- ErrorF("vtXX use the specified VT number\n");
- ErrorF("-keeptty ");
- ErrorF("don't detach controlling tty (for debugging only)\n");
- ErrorF("-novtswitch don't immediately switch to new VT\n");
- ErrorF("-sharevts share VTs with another X server\n");
-}
+/*
+ * Copyright 1992 by Orest Zborowski <obz@Kodak.com>
+ * Copyright 1993 by David Wexelblat <dwex@goblin.org>
+ *
+ * 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, and that the names of Orest Zborowski and David Wexelblat
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission. Orest Zborowski
+ * and David Wexelblat make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE
+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+
+#include "compiler.h"
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+
+#include <sys/stat.h>
+
+static Bool KeepTty = FALSE;
+static Bool VTSwitch = TRUE;
+static Bool ShareVTs = FALSE;
+static int activeVT = -1;
+
+static char vtname[11];
+static struct termios tty_attr; /* tty state to restore */
+static int tty_mode; /* kbd mode to restore */
+
+static void *console_handler;
+
+static void
+drain_console(int fd, void *closure)
+{
+ errno = 0;
+ if (tcflush(fd, TCIOFLUSH) == -1 && errno == EIO) {
+ xf86RemoveGeneralHandler(console_handler);
+ console_handler = NULL;
+ }
+}
+
+static void
+switch_to(int vt, const char *from)
+{
+ int ret;
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_ACTIVATE, vt));
+ if (ret < 0)
+ FatalError("%s: VT_ACTIVATE failed: %s\n", from, strerror(errno));
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_WAITACTIVE, vt));
+ if (ret < 0)
+ FatalError("%s: VT_WAITACTIVE failed: %s\n", from, strerror(errno));
+}
+
+void
+xf86OpenConsole(void)
+{
+ int i, fd = -1, ret;
+ struct vt_mode VT;
+ struct vt_stat vts;
+ MessageType from = X_PROBED;
+ char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
+ char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
+
+ if (serverGeneration == 1) {
+
+ /* when KeepTty check if we're run with euid==0 */
+ if (KeepTty && geteuid() != 0)
+ FatalError("xf86OpenConsole:"
+ " Server must be suid root for option \"KeepTTY\"\n");
+
+ /*
+ * setup the virtual terminal manager
+ */
+ if (xf86Info.vtno != -1) {
+ from = X_CMDLINE;
+ } else {
+
+ i=0;
+ while (tty0[i] != NULL) {
+ if ((fd = open(tty0[i],O_WRONLY,0)) >= 0)
+ break;
+ i++;
+ }
+
+ if (fd < 0)
+ FatalError(
+ "xf86OpenConsole: Cannot open /dev/tty0 (%s)\n",
+ strerror(errno));
+
+ if (ShareVTs)
+ {
+ SYSCALL(ret = ioctl(fd, VT_GETSTATE, &vts));
+ if (ret < 0)
+ FatalError("xf86OpenConsole: Cannot find the current"
+ " VT (%s)\n", strerror(errno));
+ xf86Info.vtno = vts.v_active;
+ } else {
+ SYSCALL(ret = ioctl(fd, VT_OPENQRY, &xf86Info.vtno));
+ if (ret < 0)
+ FatalError("xf86OpenConsole: Cannot find a free VT: "
+ "%s\n", strerror(errno));
+ if (xf86Info.vtno == -1)
+ FatalError("xf86OpenConsole: Cannot find a free VT\n");
+ }
+ close(fd);
+ }
+
+ xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
+
+ if (!KeepTty) {
+ pid_t ppid = getppid();
+ pid_t ppgid;
+ ppgid = getpgid(ppid);
+
+ /*
+ * change to parent process group that pgid != pid so
+ * that setsid() doesn't fail and we become process
+ * group leader
+ */
+ if (setpgid(0,ppgid) < 0)
+ xf86Msg(X_WARNING, "xf86OpenConsole: setpgid failed: %s\n",
+ strerror(errno));
+
+ /* become process group leader */
+ if ((setsid() < 0))
+ xf86Msg(X_WARNING, "xf86OpenConsole: setsid failed: %s\n",
+ strerror(errno));
+ }
+
+ i=0;
+ while (vcs[i] != NULL) {
+ sprintf(vtname, vcs[i], xf86Info.vtno); /* /dev/tty1-64 */
+ if ((xf86Info.consoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) >= 0)
+ break;
+ i++;
+ }
+
+ if (xf86Info.consoleFd < 0)
+ FatalError("xf86OpenConsole: Cannot open virtual console"
+ " %d (%s)\n", xf86Info.vtno, strerror(errno));
+
+ /*
+ * Linux doesn't switch to an active vt after the last close of a vt,
+ * so we do this ourselves by remembering which is active now.
+ */
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts));
+ if (ret < 0)
+ xf86Msg(X_WARNING,"xf86OpenConsole: VT_GETSTATE failed: %s\n",
+ strerror(errno));
+ else
+ activeVT = vts.v_active;
+
+#if 0
+ if (!KeepTty) {
+ /*
+ * Detach from the controlling tty to avoid char loss
+ */
+ if ((i = open("/dev/tty",O_RDWR)) >= 0) {
+ SYSCALL(ioctl(i, TIOCNOTTY, 0));
+ close(i);
+ }
+ }
+#endif
+
+ if (!ShareVTs)
+ {
+ struct termios nTty;
+
+ /*
+ * now get the VT. This _must_ succeed, or else fail completely.
+ */
+ switch_to(xf86Info.vtno, "xf86OpenConsole");
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
+ if (ret < 0)
+ FatalError("xf86OpenConsole: VT_GETMODE failed %s\n",
+ strerror(errno));
+
+ signal(SIGUSR1, xf86VTRequest);
+
+ VT.mode = VT_PROCESS;
+ VT.relsig = SIGUSR1;
+ VT.acqsig = SIGUSR1;
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_SETMODE, &VT));
+ if (ret < 0)
+ FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed: %s\n",
+ strerror(errno));
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS));
+ if (ret < 0)
+ FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed %s\n",
+ strerror(errno));
+
+ tcgetattr(xf86Info.consoleFd, &tty_attr);
+ SYSCALL(ioctl(xf86Info.consoleFd, KDGKBMODE, &tty_mode));
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW));
+ if (ret < 0)
+ FatalError("xf86OpenConsole: KDSKBMODE K_RAW failed %s\n",
+ strerror(errno));
+
+ nTty = tty_attr;
+ nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
+ nTty.c_oflag = 0;
+ nTty.c_cflag = CREAD | CS8;
+ nTty.c_lflag = 0;
+ nTty.c_cc[VTIME]=0;
+ nTty.c_cc[VMIN]=1;
+ cfsetispeed(&nTty, 9600);
+ cfsetospeed(&nTty, 9600);
+ tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty);
+
+ /* need to keep the buffer clean, else the kernel gets angry */
+ xf86SetConsoleHandler(drain_console, NULL);
+
+ /* we really should have a InitOSInputDevices() function instead
+ * of Init?$#*&Device(). So I just place it here */
+ }
+ } else { /* serverGeneration != 1 */
+ if (!ShareVTs && VTSwitch)
+ {
+ /* now get the VT */
+ switch_to(xf86Info.vtno, "xf86OpenConsole");
+ }
+ }
+}
+
+void
+xf86CloseConsole(void)
+{
+ struct vt_mode VT;
+ int ret;
+
+ if (ShareVTs) {
+ close(xf86Info.consoleFd);
+ return;
+ }
+
+ if (console_handler) {
+ xf86RemoveGeneralHandler(console_handler);
+ console_handler = NULL;
+ };
+
+ /* Back to text mode ... */
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT));
+ if (ret < 0)
+ xf86Msg(X_WARNING, "xf86CloseConsole: KDSETMODE failed: %s\n",
+ strerror(errno));
+
+ SYSCALL(ioctl(xf86Info.consoleFd, KDSKBMODE, tty_mode));
+ tcsetattr(xf86Info.consoleFd, TCSANOW, &tty_attr);
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
+ if (ret < 0)
+ xf86Msg(X_WARNING, "xf86CloseConsole: VT_GETMODE failed: %s\n",
+ strerror(errno));
+ else {
+ /* set dflt vt handling */
+ VT.mode = VT_AUTO;
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_SETMODE, &VT));
+ if (ret < 0)
+ xf86Msg(X_WARNING, "xf86CloseConsole: VT_SETMODE failed: %s\n",
+ strerror(errno));
+ }
+
+ if (VTSwitch)
+ {
+ /*
+ * Perform a switch back to the active VT when we were started
+ */
+ if (activeVT >= 0) {
+ switch_to(activeVT, "xf86CloseConsole");
+ activeVT = -1;
+ }
+ }
+ close(xf86Info.consoleFd); /* make the vt-manager happy */
+}
+
+int
+xf86ProcessArgument(int argc, char *argv[], int i)
+{
+ /*
+ * Keep server from detaching from controlling tty. This is useful
+ * when debugging (so the server can receive keyboard signals.
+ */
+ if (!strcmp(argv[i], "-keeptty"))
+ {
+ KeepTty = TRUE;
+ return 1;
+ }
+ if (!strcmp(argv[i], "-novtswitch"))
+ {
+ VTSwitch = FALSE;
+ return 1;
+ }
+ if (!strcmp(argv[i], "-sharevts"))
+ {
+ ShareVTs = TRUE;
+ return 1;
+ }
+ if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
+ {
+ if (sscanf(argv[i], "vt%2d", &xf86Info.vtno) == 0)
+ {
+ UseMsg();
+ xf86Info.vtno = -1;
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+void
+xf86UseMsg(void)
+{
+ ErrorF("vtXX use the specified VT number\n");
+ ErrorF("-keeptty ");
+ ErrorF("don't detach controlling tty (for debugging only)\n");
+ ErrorF("-novtswitch don't immediately switch to new VT\n");
+ ErrorF("-sharevts share VTs with another X server\n");
+}
diff --git a/xorg-server/hw/xnest/Events.c b/xorg-server/hw/xnest/Events.c
index 6b8edf143..5c800860a 100644
--- a/xorg-server/hw/xnest/Events.c
+++ b/xorg-server/hw/xnest/Events.c
@@ -1,233 +1,233 @@
-/*
-
-Copyright 1993 by Davor Matic
-
-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. Davor Matic makes no representations about
-the suitability of this software for any purpose. It is provided "as
-is" without express or implied warranty.
-
-*/
-
-#ifdef HAVE_XNEST_CONFIG_H
-#include <xnest-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "screenint.h"
-#include "input.h"
-#include "misc.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "servermd.h"
-#include "inputstr.h"
-#include "inpututils.h"
-
-#include "mi.h"
-
-#include "Xnest.h"
-
-#include "Args.h"
-#include "Color.h"
-#include "Display.h"
-#include "Screen.h"
-#include "XNWindow.h"
-#include "Events.h"
-#include "Keyboard.h"
-#include "Pointer.h"
-#include "mipointer.h"
-
-CARD32 lastEventTime = 0;
-
-extern EventList *xnestEvents;
-
-void
-ProcessInputEvents(void)
-{
- mieqProcessInputEvents();
-}
-
-int
-TimeSinceLastInputEvent(void)
-{
- if (lastEventTime == 0)
- lastEventTime = GetTimeInMillis();
- return GetTimeInMillis() - lastEventTime;
-}
-
-void
-SetTimeSinceLastInputEvent(void)
-{
- lastEventTime = GetTimeInMillis();
-}
-
-static Bool
-xnestExposurePredicate(Display *display, XEvent *event, char *args)
-{
- return event->type == Expose || event->type == ProcessedExpose;
-}
-
-static Bool
-xnestNotExposurePredicate(Display *display, XEvent *event, char *args)
-{
- return !xnestExposurePredicate(display, event, args);
-}
-
-void
-xnestCollectExposures(void)
-{
- XEvent X;
- WindowPtr pWin;
- RegionRec Rgn;
- BoxRec Box;
-
- while (XCheckIfEvent(xnestDisplay, &X, xnestExposurePredicate, NULL)) {
- pWin = xnestWindowPtr(X.xexpose.window);
-
- if (pWin && X.xexpose.width && X.xexpose.height) {
- Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + X.xexpose.x;
- Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + X.xexpose.y;
- Box.x2 = Box.x1 + X.xexpose.width;
- Box.y2 = Box.y1 + X.xexpose.height;
-
- RegionInit(&Rgn, &Box, 1);
-
- miSendExposures(pWin, &Rgn, Box.x2, Box.y2);
- }
- }
-}
-
-void
-xnestQueueKeyEvent(int type, unsigned int keycode)
-{
- int i, n;
-
- GetEventList(&xnestEvents);
- lastEventTime = GetTimeInMillis();
- n = GetKeyboardEvents(xnestEvents, xnestKeyboardDevice, type, keycode);
- for (i = 0; i < n; i++)
- mieqEnqueue(xnestKeyboardDevice, (InternalEvent*)(xnestEvents + i)->event);
-}
-
-void
-xnestCollectEvents(void)
-{
- XEvent X;
- int i, n, valuators[2];
- ValuatorMask mask;
- ScreenPtr pScreen;
- GetEventList(&xnestEvents);
-
- while (XCheckIfEvent(xnestDisplay, &X, xnestNotExposurePredicate, NULL)) {
- switch (X.type) {
- case KeyPress:
- xnestUpdateModifierState(X.xkey.state);
- xnestQueueKeyEvent(KeyPress, X.xkey.keycode);
- break;
-
- case KeyRelease:
- xnestUpdateModifierState(X.xkey.state);
- xnestQueueKeyEvent(KeyRelease, X.xkey.keycode);
- break;
-
- case ButtonPress:
- valuator_mask_set_range(&mask, 0, 0, NULL);
- xnestUpdateModifierState(X.xkey.state);
- lastEventTime = GetTimeInMillis();
- n = GetPointerEvents(xnestEvents, xnestPointerDevice, ButtonPress,
- X.xbutton.button, POINTER_RELATIVE, &mask);
- for (i = 0; i < n; i++)
- mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
- break;
-
- case ButtonRelease:
- valuator_mask_set_range(&mask, 0, 0, NULL);
- xnestUpdateModifierState(X.xkey.state);
- lastEventTime = GetTimeInMillis();
- n = GetPointerEvents(xnestEvents, xnestPointerDevice, ButtonRelease,
- X.xbutton.button, POINTER_RELATIVE, &mask);
- for (i = 0; i < n; i++)
- mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
- break;
-
- case MotionNotify:
- valuators[0] = X.xmotion.x;
- valuators[1] = X.xmotion.y;
- valuator_mask_set_range(&mask, 0, 2, valuators);
- lastEventTime = GetTimeInMillis();
- n = GetPointerEvents(xnestEvents, xnestPointerDevice, MotionNotify,
- 0, POINTER_ABSOLUTE, &mask);
- for (i = 0; i < n; i++)
- mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
- break;
-
- case FocusIn:
- if (X.xfocus.detail != NotifyInferior) {
- pScreen = xnestScreen(X.xfocus.window);
- if (pScreen)
- xnestDirectInstallColormaps(pScreen);
- }
- break;
-
- case FocusOut:
- if (X.xfocus.detail != NotifyInferior) {
- pScreen = xnestScreen(X.xfocus.window);
- if (pScreen)
- xnestDirectUninstallColormaps(pScreen);
- }
- break;
-
- case KeymapNotify:
- break;
-
- case EnterNotify:
- if (X.xcrossing.detail != NotifyInferior) {
- pScreen = xnestScreen(X.xcrossing.window);
- if (pScreen) {
- NewCurrentScreen(inputInfo.pointer, pScreen, X.xcrossing.x, X.xcrossing.y);
- valuators[0] = X.xcrossing.x;
- valuators[1] = X.xcrossing.y;
- valuator_mask_set_range(&mask, 0, 2, valuators);
- lastEventTime = GetTimeInMillis();
- n = GetPointerEvents(xnestEvents, xnestPointerDevice, MotionNotify,
- 0, POINTER_ABSOLUTE, &mask);
- for (i = 0; i < n; i++)
- mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
- xnestDirectInstallColormaps(pScreen);
- }
- }
- break;
-
- case LeaveNotify:
- if (X.xcrossing.detail != NotifyInferior) {
- pScreen = xnestScreen(X.xcrossing.window);
- if (pScreen) {
- xnestDirectUninstallColormaps(pScreen);
- }
- }
- break;
-
- case DestroyNotify:
- if (xnestParentWindow != (Window) 0 &&
- X.xdestroywindow.window == xnestParentWindow)
- exit (0);
- break;
-
- case CirculateNotify:
- case ConfigureNotify:
- case GravityNotify:
- case MapNotify:
- case ReparentNotify:
- case UnmapNotify:
- break;
-
- default:
- ErrorF("xnest warning: unhandled event\n");
- break;
- }
- }
-}
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifdef HAVE_XNEST_CONFIG_H
+#include <xnest-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "screenint.h"
+#include "input.h"
+#include "misc.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "servermd.h"
+#include "inputstr.h"
+#include "inpututils.h"
+
+#include "mi.h"
+
+#include "Xnest.h"
+
+#include "Args.h"
+#include "Color.h"
+#include "Display.h"
+#include "Screen.h"
+#include "XNWindow.h"
+#include "Events.h"
+#include "Keyboard.h"
+#include "Pointer.h"
+#include "mipointer.h"
+
+CARD32 lastEventTime = 0;
+
+extern EventList *xnestEvents;
+
+void
+ProcessInputEvents(void)
+{
+ mieqProcessInputEvents();
+}
+
+int
+TimeSinceLastInputEvent(void)
+{
+ if (lastEventTime == 0)
+ lastEventTime = GetTimeInMillis();
+ return GetTimeInMillis() - lastEventTime;
+}
+
+void
+SetTimeSinceLastInputEvent(void)
+{
+ lastEventTime = GetTimeInMillis();
+}
+
+static Bool
+xnestExposurePredicate(Display *display, XEvent *event, char *args)
+{
+ return event->type == Expose || event->type == ProcessedExpose;
+}
+
+static Bool
+xnestNotExposurePredicate(Display *display, XEvent *event, char *args)
+{
+ return !xnestExposurePredicate(display, event, args);
+}
+
+void
+xnestCollectExposures(void)
+{
+ XEvent X;
+ WindowPtr pWin;
+ RegionRec Rgn;
+ BoxRec Box;
+
+ while (XCheckIfEvent(xnestDisplay, &X, xnestExposurePredicate, NULL)) {
+ pWin = xnestWindowPtr(X.xexpose.window);
+
+ if (pWin && X.xexpose.width && X.xexpose.height) {
+ Box.x1 = pWin->drawable.x + wBorderWidth(pWin) + X.xexpose.x;
+ Box.y1 = pWin->drawable.y + wBorderWidth(pWin) + X.xexpose.y;
+ Box.x2 = Box.x1 + X.xexpose.width;
+ Box.y2 = Box.y1 + X.xexpose.height;
+
+ RegionInit(&Rgn, &Box, 1);
+
+ miSendExposures(pWin, &Rgn, Box.x2, Box.y2);
+ }
+ }
+}
+
+void
+xnestQueueKeyEvent(int type, unsigned int keycode)
+{
+ int i, n;
+
+ GetEventList(&xnestEvents);
+ lastEventTime = GetTimeInMillis();
+ n = GetKeyboardEvents(xnestEvents, xnestKeyboardDevice, type, keycode, NULL);
+ for (i = 0; i < n; i++)
+ mieqEnqueue(xnestKeyboardDevice, (InternalEvent*)(xnestEvents + i)->event);
+}
+
+void
+xnestCollectEvents(void)
+{
+ XEvent X;
+ int i, n, valuators[2];
+ ValuatorMask mask;
+ ScreenPtr pScreen;
+ GetEventList(&xnestEvents);
+
+ while (XCheckIfEvent(xnestDisplay, &X, xnestNotExposurePredicate, NULL)) {
+ switch (X.type) {
+ case KeyPress:
+ xnestUpdateModifierState(X.xkey.state);
+ xnestQueueKeyEvent(KeyPress, X.xkey.keycode);
+ break;
+
+ case KeyRelease:
+ xnestUpdateModifierState(X.xkey.state);
+ xnestQueueKeyEvent(KeyRelease, X.xkey.keycode);
+ break;
+
+ case ButtonPress:
+ valuator_mask_set_range(&mask, 0, 0, NULL);
+ xnestUpdateModifierState(X.xkey.state);
+ lastEventTime = GetTimeInMillis();
+ n = GetPointerEvents(xnestEvents, xnestPointerDevice, ButtonPress,
+ X.xbutton.button, POINTER_RELATIVE, &mask);
+ for (i = 0; i < n; i++)
+ mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
+ break;
+
+ case ButtonRelease:
+ valuator_mask_set_range(&mask, 0, 0, NULL);
+ xnestUpdateModifierState(X.xkey.state);
+ lastEventTime = GetTimeInMillis();
+ n = GetPointerEvents(xnestEvents, xnestPointerDevice, ButtonRelease,
+ X.xbutton.button, POINTER_RELATIVE, &mask);
+ for (i = 0; i < n; i++)
+ mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
+ break;
+
+ case MotionNotify:
+ valuators[0] = X.xmotion.x;
+ valuators[1] = X.xmotion.y;
+ valuator_mask_set_range(&mask, 0, 2, valuators);
+ lastEventTime = GetTimeInMillis();
+ n = GetPointerEvents(xnestEvents, xnestPointerDevice, MotionNotify,
+ 0, POINTER_ABSOLUTE, &mask);
+ for (i = 0; i < n; i++)
+ mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
+ break;
+
+ case FocusIn:
+ if (X.xfocus.detail != NotifyInferior) {
+ pScreen = xnestScreen(X.xfocus.window);
+ if (pScreen)
+ xnestDirectInstallColormaps(pScreen);
+ }
+ break;
+
+ case FocusOut:
+ if (X.xfocus.detail != NotifyInferior) {
+ pScreen = xnestScreen(X.xfocus.window);
+ if (pScreen)
+ xnestDirectUninstallColormaps(pScreen);
+ }
+ break;
+
+ case KeymapNotify:
+ break;
+
+ case EnterNotify:
+ if (X.xcrossing.detail != NotifyInferior) {
+ pScreen = xnestScreen(X.xcrossing.window);
+ if (pScreen) {
+ NewCurrentScreen(inputInfo.pointer, pScreen, X.xcrossing.x, X.xcrossing.y);
+ valuators[0] = X.xcrossing.x;
+ valuators[1] = X.xcrossing.y;
+ valuator_mask_set_range(&mask, 0, 2, valuators);
+ lastEventTime = GetTimeInMillis();
+ n = GetPointerEvents(xnestEvents, xnestPointerDevice, MotionNotify,
+ 0, POINTER_ABSOLUTE, &mask);
+ for (i = 0; i < n; i++)
+ mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
+ xnestDirectInstallColormaps(pScreen);
+ }
+ }
+ break;
+
+ case LeaveNotify:
+ if (X.xcrossing.detail != NotifyInferior) {
+ pScreen = xnestScreen(X.xcrossing.window);
+ if (pScreen) {
+ xnestDirectUninstallColormaps(pScreen);
+ }
+ }
+ break;
+
+ case DestroyNotify:
+ if (xnestParentWindow != (Window) 0 &&
+ X.xdestroywindow.window == xnestParentWindow)
+ exit (0);
+ break;
+
+ case CirculateNotify:
+ case ConfigureNotify:
+ case GravityNotify:
+ case MapNotify:
+ case ReparentNotify:
+ case UnmapNotify:
+ break;
+
+ default:
+ ErrorF("xnest warning: unhandled event\n");
+ break;
+ }
+ }
+}
diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m
index 3521517a2..e56bf0cf3 100644
--- a/xorg-server/hw/xquartz/X11Application.m
+++ b/xorg-server/hw/xquartz/X11Application.m
@@ -61,6 +61,12 @@ extern int xpbproxy_run (void);
#define XSERVER_VERSION "?"
#endif
+#ifdef HAVE_LIBDISPATCH
+#include <dispatch/dispatch.h>
+
+static dispatch_queue_t eventTranslationQueue;
+#endif
+
/* Stuck modifier / button state... force release when we context switch */
static NSEventType keyState[NUM_KEYCODES];
@@ -385,7 +391,15 @@ static void message_kit_thread (SEL selector, NSObject *arg) {
if (for_appkit) [super sendEvent:e];
- if (for_x) [self sendX11NSEvent:e];
+ if (for_x) {
+#ifdef HAVE_LIBDISPATCH
+ dispatch_async(eventTranslationQueue, ^{
+#endif
+ [self sendX11NSEvent:e];
+#ifdef HAVE_LIBDISPATCH
+ });
+#endif
+ }
}
- (void) set_window_menu:(NSArray *)list {
@@ -950,7 +964,7 @@ environment the next time you start X11?", @"Startup xinitrc dialog");
[X11App prefs_synchronize];
}
-static inline pthread_t create_thread(void *func, void *arg) {
+static inline pthread_t create_thread(void *(*func)(void *), void *arg) {
pthread_attr_t attr;
pthread_t tid;
@@ -999,6 +1013,11 @@ void X11ApplicationMain (int argc, char **argv, char **envp) {
aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) -
NSMaxY([[NSScreen mainScreen] visibleFrame]);
+#ifdef HAVE_LIBDISPATCH
+ eventTranslationQueue = dispatch_queue_create(LAUNCHD_ID_PREFIX".X11.NSEventsToX11EventsQueue", NULL);
+ assert(eventTranslationQueue != NULL);
+#endif
+
/* Set the key layout seed before we start the server */
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
last_key_layout = TISCopyCurrentKeyboardLayoutInputSource();
@@ -1079,13 +1098,29 @@ static const char *untrusted_str(NSEvent *e) {
#endif
- (void) sendX11NSEvent:(NSEvent *)e {
- NSPoint location = NSZeroPoint, tilt = NSZeroPoint;
+ NSPoint location = NSZeroPoint;
int ev_button, ev_type;
- float pressure = 0.0;
+ static float pressure = 0.0; // static so ProximityOut will have the value from the previous tablet event
+ static NSPoint tilt; // static so ProximityOut will have the value from the previous tablet event
+ static DeviceIntPtr darwinTabletCurrent = NULL;
+ static BOOL needsProximityIn = NO; // Do we do need to handle a pending ProximityIn once we have pressure/tilt?
DeviceIntPtr pDev;
int modifierFlags;
BOOL isMouseOrTabletEvent, isTabletEvent;
+#ifdef HAVE_LIBDISPATCH
+ static dispatch_once_t once_pred;
+ dispatch_once(&once_pred, ^{
+ tilt = NSZeroPoint;
+ darwinTabletCurrent = darwinTabletStylus;
+ });
+#else
+ if(!darwinTabletCurrent) {
+ tilt = NSZeroPoint;
+ darwinTabletCurrent = darwinTabletStylus;
+ }
+#endif
+
isMouseOrTabletEvent = [e type] == NSLeftMouseDown || [e type] == NSOtherMouseDown || [e type] == NSRightMouseDown ||
[e type] == NSLeftMouseUp || [e type] == NSOtherMouseUp || [e type] == NSRightMouseUp ||
[e type] == NSLeftMouseDragged || [e type] == NSOtherMouseDragged || [e type] == NSRightMouseDragged ||
@@ -1207,19 +1242,14 @@ static const char *untrusted_str(NSEvent *e) {
darwinTabletCurrent=darwinTabletCursor;
break;
}
-
- /* NSTabletProximityEventSubtype doesn't encode pressure ant tilt
- * So we just pretend the motion was caused by the mouse. Hopefully
- * we'll have a better solution for this in the future (like maybe
- * NSTabletProximityEventSubtype will come from NSTabletPoint
- * rather than NSMouseMoved.
- pressure = [e pressure];
- tilt = [e tilt];
- pDev = darwinTabletCurrent;
- */
- DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut,
- location.x, location.y);
+ if([e isEnteringProximity])
+ needsProximityIn = YES;
+ else
+ DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut,
+ location.x, location.y, pressure,
+ tilt.x, tilt.y);
+ return;
}
if ([e type] == NSTabletPoint || [e subtype] == NSTabletPointEventSubtype) {
@@ -1227,6 +1257,14 @@ static const char *untrusted_str(NSEvent *e) {
tilt = [e tilt];
pDev = darwinTabletCurrent;
+
+ if(needsProximityIn) {
+ DarwinSendProximityEvents(darwinTabletCurrent, ProximityIn,
+ location.x, location.y, pressure,
+ tilt.x, tilt.y);
+
+ needsProximityIn = NO;
+ }
}
if(!XQuartzServerVisible && noTestExtensions) {
@@ -1280,8 +1318,12 @@ static const char *untrusted_str(NSEvent *e) {
break;
}
- DarwinSendProximityEvents([e isEnteringProximity] ? ProximityIn : ProximityOut,
- location.x, location.y);
+ if([e isEnteringProximity])
+ needsProximityIn = YES;
+ else
+ DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut,
+ location.x, location.y, pressure,
+ tilt.x, tilt.y);
break;
case NSScrollWheel:
diff --git a/xorg-server/hw/xquartz/darwin.c b/xorg-server/hw/xquartz/darwin.c
index 3b6f0a29e..00be74ba0 100644
--- a/xorg-server/hw/xquartz/darwin.c
+++ b/xorg-server/hw/xquartz/darwin.c
@@ -117,7 +117,6 @@ unsigned int windowItemModMask = NX_COMMANDMASK;
// devices
DeviceIntPtr darwinKeyboard = NULL;
DeviceIntPtr darwinPointer = NULL;
-DeviceIntPtr darwinTabletCurrent = NULL;
DeviceIntPtr darwinTabletStylus = NULL;
DeviceIntPtr darwinTabletCursor = NULL;
DeviceIntPtr darwinTabletEraser = NULL;
@@ -492,8 +491,6 @@ void InitInput( int argc, char **argv )
darwinTabletEraser = AddInputDevice(serverClient, DarwinTabletProc, TRUE);
darwinTabletEraser->name = strdup("eraser");
- darwinTabletCurrent = darwinTabletStylus;
-
DarwinEQInit();
QuartzInitInput(argc, argv);
diff --git a/xorg-server/hw/xquartz/darwin.h b/xorg-server/hw/xquartz/darwin.h
index e874af24c..360225742 100644
--- a/xorg-server/hw/xquartz/darwin.h
+++ b/xorg-server/hw/xquartz/darwin.h
@@ -56,7 +56,6 @@ extern io_connect_t darwinParamConnect;
extern int darwinEventReadFD;
extern int darwinEventWriteFD;
extern DeviceIntPtr darwinPointer;
-extern DeviceIntPtr darwinTabletCurrent;
extern DeviceIntPtr darwinTabletCursor;
extern DeviceIntPtr darwinTabletStylus;
extern DeviceIntPtr darwinTabletEraser;
diff --git a/xorg-server/hw/xquartz/darwinEvents.c b/xorg-server/hw/xquartz/darwinEvents.c
index 16fec4a01..40d8a4e9e 100644
--- a/xorg-server/hw/xquartz/darwinEvents.c
+++ b/xorg-server/hw/xquartz/darwinEvents.c
@@ -61,6 +61,7 @@ in this Software without prior written authorization from The Open Group.
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
+#include <time.h>
#include <IOKit/hidsystem/IOLLEvent.h>
@@ -93,7 +94,7 @@ 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) {
+static pthread_t create_thread(void *(*func)(void *), void *arg) {
pthread_attr_t attr;
pthread_t tid;
@@ -304,7 +305,28 @@ void DarwinListenOnOpenFD(int fd) {
pthread_mutex_unlock(&fd_add_lock);
}
-static void DarwinProcessFDAdditionQueue_thread(void *args) {
+static void *DarwinProcessFDAdditionQueue_thread(void *args) {
+ /* TODO: Possibly adjust this to no longer be a race... maybe trigger this
+ * once a client connects and claims to be the WM.
+ *
+ * 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.
+ */
+
+ struct timespec sleep_for;
+ struct timespec sleep_remaining;
+
+ sleep_for.tv_sec = 3;
+ sleep_for.tv_nsec = 0;
+
+ ErrorF("X11.app: DarwinProcessFDAdditionQueue_thread: Sleeping to allow xinitrc to catchup.\n");
+ while(nanosleep(&sleep_for, &sleep_remaining) != 0) {
+ sleep_for = sleep_remaining;
+ }
+
pthread_mutex_lock(&fd_add_lock);
while(true) {
while(fd_add_count) {
@@ -312,6 +334,8 @@ static void DarwinProcessFDAdditionQueue_thread(void *args) {
}
pthread_cond_wait(&fd_add_ready_cond, &fd_add_lock);
}
+
+ return NULL;
}
Bool DarwinEQInit(void) {
@@ -465,7 +489,7 @@ void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, floa
DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
darwinEvents_lock(); {
ValuatorMask mask;
- valuator_mask_set_range(&mask, 0, (pDev == darwinTabletCurrent) ? 5 : 2, valuators);
+ valuator_mask_set_range(&mask, 0, (pDev == darwinPointer) ? 2 : 5, valuators);
num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button,
POINTER_ABSOLUTE, &mask);
for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
@@ -482,24 +506,24 @@ void DarwinSendKeyboardEvents(int ev_type, int keycode) {
}
darwinEvents_lock(); {
- num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE);
+ num_events = GetKeyboardEvents(darwinEvents, darwinKeyboard, ev_type, keycode + MIN_KEYCODE, NULL);
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;
+void DarwinSendProximityEvents(DeviceIntPtr pDev, int ev_type, float pointer_x, float pointer_y,
+ float pressure, float tilt_x, float tilt_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);
+ DEBUG_LOG("DarwinSendProximityEvents: %d l:%f,%f p:%f t:%f,%f\n", ev_type, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
- if(!darwinEvents) {
- DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n");
- return;
- }
+ if(!darwinEvents) {
+ DEBUG_LOG("DarwinSendProximityEvents called before darwinEvents was initialized\n");
+ return;
+ }
screen = miPointerGetScreen(pDev);
if(!screen) {
@@ -507,7 +531,7 @@ void DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
return;
}
- DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f);
+ DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
darwinEvents_lock(); {
ValuatorMask mask;
valuator_mask_set_range(&mask, 0, 5, valuators);
diff --git a/xorg-server/hw/xquartz/darwinEvents.h b/xorg-server/hw/xquartz/darwinEvents.h
index 590305f3e..6769c8bd8 100644
--- a/xorg-server/hw/xquartz/darwinEvents.h
+++ b/xorg-server/hw/xquartz/darwinEvents.h
@@ -37,7 +37,8 @@ void DarwinEQPointerPost(DeviceIntPtr pDev, xEventPtr e);
void DarwinEQSwitchScreen(ScreenPtr pScreen, Bool fromDIX);
void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, float pointer_x, float pointer_y,
float pressure, float tilt_x, float tilt_y);
-void DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y);
+void DarwinSendProximityEvents(DeviceIntPtr pDev, int ev_type, float pointer_x, float pointer_y,
+ float pressure, float tilt_x, float tilt_y);
void DarwinSendKeyboardEvents(int ev_type, int keycode);
void DarwinSendScrollEvents(float count_x, float count_y, float pointer_x, float pointer_y,
float pressure, float tilt_x, float tilt_y);
diff --git a/xorg-server/hw/xquartz/mach-startup/bundle-main.c b/xorg-server/hw/xquartz/mach-startup/bundle-main.c
index aaff1c625..6a6c01c3b 100644
--- a/xorg-server/hw/xquartz/mach-startup/bundle-main.c
+++ b/xorg-server/hw/xquartz/mach-startup/bundle-main.c
@@ -1,691 +1,698 @@
-/* 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__ __attribute__((__used__)) = &__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 = strdup(pds);
- if(!server_bootstrap_name) {
- fprintf(stderr, "X11.app: Memory allocation error.\n");
- exit(1);
- }
- 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 <stdbool.h>
+#include <signal.h>
+
+#ifdef HAVE_LIBDISPATCH
+#include <dispatch/dispatch.h>
+#else
+#include <pthread.h>
+#endif
+
+#include <sys/socket.h>
+#include <sys/un.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__ __attribute__((__used__)) = &__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);
+
+#ifndef HAVE_LIBDISPATCH
+/*** Pthread Magics ***/
+static pthread_t create_thread(void *(*func)(void *), 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;
+}
+#endif
+
+/*** 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()
+ */
+#ifdef HAVE_LIBDISPATCH
+static void socket_handoff(socket_handoff_t *handoff_data) {
+#else
+static void *socket_handoff_thread(void *arg) {
+ socket_handoff_t *handoff_data = (socket_handoff_t *)arg;
+#endif
+
+ int launchd_fd = -1;
+ int connected_fd;
+
+ /* 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);
+
+ fprintf(stderr, "X11.app Handing off fd to server thread via DarwinListenOnOpenFD(%d)\n", launchd_fd);
+ DarwinListenOnOpenFD(launchd_fd);
+
+#ifndef HAVE_LIBDISPATCH
+ return NULL;
+#endif
+}
+
+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);
+
+#ifdef HAVE_LIBDISPATCH
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
+ socket_handoff(handoff_data);
+ });
+#else
+ create_thread(socket_handoff_thread, handoff_data);
+#endif
+
+#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 = strdup(pds);
+ if(!server_bootstrap_name) {
+ fprintf(stderr, "X11.app: Memory allocation error.\n");
+ exit(1);
+ }
+ 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/xwin/winkeybd.c b/xorg-server/hw/xwin/winkeybd.c
index 94318969f..912e2de1c 100644
--- a/xorg-server/hw/xwin/winkeybd.c
+++ b/xorg-server/hw/xwin/winkeybd.c
@@ -1,531 +1,531 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 XFREE86 PROJECT 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 XFree86 Project
- *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 XFree86 Project.
- *
- * Authors: Dakshinamurthy Karra
- * Suhaib M Siddiqi
- * Peter Busch
- * Harold L Hunt II
- */
-
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include "winkeybd.h"
-#include "winconfig.h"
-#include "winmsg.h"
-
-#include "xkbsrv.h"
-
-static Bool g_winKeyState[NUM_KEYCODES];
-
-/*
- * Local prototypes
- */
-
-static void
-winKeybdBell (int iPercent, DeviceIntPtr pDeviceInt,
- pointer pCtrl, int iClass);
-
-static void
-winKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl);
-
-
-/*
- * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
- * into an ASCII scan code.
- *
- * We do this ourselves, rather than letting Windows handle it,
- * because Windows tends to munge the handling of special keys,
- * like AltGr on European keyboards.
- */
-
-void
-winTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode)
-{
- int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
- int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
- int iParam = HIWORD (lParam);
- int iParamScanCode = LOBYTE (iParam);
-
- winDebug("winTranslateKey: wParam %08x lParam %08x\n", wParam, lParam);
-
-/* WM_ key messages faked by Vista speech recognition (WSR) don't have a
- * scan code.
- *
- * Vocola 3 (Rick Mohr's supplement to WSR) uses
- * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a
- * scan code of 1
- */
- if (iParamScanCode <= 1)
- {
- if (VK_PRIOR <= wParam && wParam <= VK_DOWN)
- /* Trigger special case table to translate to extended
- * keycode, otherwise if num_lock is on, we can get keypad
- * numbers instead of navigation keys. */
- iParam |= KF_EXTENDED;
- else
- iParamScanCode = MapVirtualKeyEx(wParam,
- /*MAPVK_VK_TO_VSC*/0,
- GetKeyboardLayout(0));
- }
-
- /* Branch on special extended, special non-extended, or normal key */
- if ((iParam & KF_EXTENDED) && iKeyFixupEx)
- *piScanCode = iKeyFixupEx;
- else if (iKeyFixup)
- *piScanCode = iKeyFixup;
- else if (wParam == 0 && iParamScanCode == 0x70)
- *piScanCode = KEY_HKTG;
- else
- switch (iParamScanCode)
- {
- case 0x70:
- *piScanCode = KEY_HKTG;
- break;
- case 0x73:
- *piScanCode = KEY_BSlash2;
- break;
- default:
- *piScanCode = iParamScanCode;
- break;
- }
-}
-
-
-/* Ring the keyboard bell (system speaker on PCs) */
-static void
-winKeybdBell (int iPercent, DeviceIntPtr pDeviceInt,
- pointer pCtrl, int iClass)
-{
- /*
- * We can't use Beep () here because it uses the PC speaker
- * on NT/2000. MessageBeep (MB_OK) will play the default system
- * sound on systems with a sound card or it will beep the PC speaker
- * on systems that do not have a sound card.
- */
- MessageBeep (MB_OK);
-}
-
-
-/* Change some keyboard configuration parameters */
-static void
-winKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl)
-{
-}
-
-
-/*
- * See Porting Layer Definition - p. 18
- * winKeybdProc is known as a DeviceProc.
- */
-
-int
-winKeybdProc (DeviceIntPtr pDeviceInt, int iState)
-{
- DevicePtr pDevice = (DevicePtr) pDeviceInt;
- XkbSrvInfoPtr xkbi;
- XkbControlsPtr ctrl;
-
- switch (iState)
- {
- case DEVICE_INIT:
- winConfigKeyboard (pDeviceInt);
-
- /* FIXME: Maybe we should use winGetKbdLeds () here? */
- defaultKeyboardControl.leds = g_winInfo.keyboard.leds;
-
- winErrorFVerb(2, "Rules = \"%s\" Model = \"%s\" Layout = \"%s\""
- " Variant = \"%s\" Options = \"%s\"\n",
- g_winInfo.xkb.rules ? g_winInfo.xkb.rules : "none",
- g_winInfo.xkb.model ? g_winInfo.xkb.model : "none",
- g_winInfo.xkb.layout ? g_winInfo.xkb.layout : "none",
- g_winInfo.xkb.variant ? g_winInfo.xkb.variant : "none",
- g_winInfo.xkb.options ? g_winInfo.xkb.options : "none");
-
- InitKeyboardDeviceStruct (pDeviceInt,
- &g_winInfo.xkb,
- winKeybdBell,
- winKeybdCtrl);
-
- xkbi = pDeviceInt->key->xkbInfo;
- if ((xkbi != NULL) && (xkbi->desc != NULL))
- {
- ctrl = xkbi->desc->ctrls;
- ctrl->repeat_delay = g_winInfo.keyboard.delay;
- ctrl->repeat_interval = 1000/g_winInfo.keyboard.rate;
- }
- else
- {
- winErrorFVerb (1, "winKeybdProc - Error initializing keyboard AutoRepeat\n");
- }
-
- break;
-
- case DEVICE_ON:
- pDevice->on = TRUE;
-
- // immediately copy the state of this keyboard device to the VCK
- // (which otherwise happens lazily after the first keypress)
- CopyKeyClass(pDeviceInt, inputInfo.keyboard);
- break;
-
- case DEVICE_CLOSE:
- case DEVICE_OFF:
- pDevice->on = FALSE;
- break;
- }
-
- return Success;
-}
-
-
-/*
- * Detect current mode key states upon server startup.
- *
- * Simulate a press and release of any key that is currently
- * toggled.
- */
-
-void
-winInitializeModeKeyStates (void)
-{
- /* Restore NumLock */
- if (GetKeyState (VK_NUMLOCK) & 0x0001)
- {
- winSendKeyEvent (KEY_NumLock, TRUE);
- winSendKeyEvent (KEY_NumLock, FALSE);
- }
-
- /* Restore CapsLock */
- if (GetKeyState (VK_CAPITAL) & 0x0001)
- {
- winSendKeyEvent (KEY_CapsLock, TRUE);
- winSendKeyEvent (KEY_CapsLock, FALSE);
- }
-
- /* Restore ScrollLock */
- if (GetKeyState (VK_SCROLL) & 0x0001)
- {
- winSendKeyEvent (KEY_ScrollLock, TRUE);
- winSendKeyEvent (KEY_ScrollLock, FALSE);
- }
-
- /* Restore KanaLock */
- if (GetKeyState (VK_KANA) & 0x0001)
- {
- winSendKeyEvent (KEY_HKTG, TRUE);
- winSendKeyEvent (KEY_HKTG, FALSE);
- }
-}
-
-
-/*
- * Upon regaining the keyboard focus we must
- * resynchronize our internal mode key states
- * with the actual state of the keys.
- */
-
-void
-winRestoreModeKeyStates (void)
-{
- DWORD dwKeyState;
- BOOL processEvents = TRUE;
- unsigned short internalKeyStates;
-
- /* X server is being initialized */
- if (!inputInfo.keyboard)
- return;
-
- /* Only process events if the rootwindow is mapped. The keyboard events
- * will cause segfaults otherwise */
- if (screenInfo.screens[0]->root && screenInfo.screens[0]->root->mapped == FALSE)
- processEvents = FALSE;
-
- /* Force to process all pending events in the mi event queue */
- if (processEvents)
- mieqProcessInputEvents ();
-
- /* Read the mode key states of our X server */
- /* (stored in the virtual core keyboard) */
- internalKeyStates = XkbStateFieldFromRec(&inputInfo.keyboard->key->xkbInfo->state);
- winDebug("winRestoreModeKeyStates: state %d\n", internalKeyStates);
-
- /*
- * NOTE: The C XOR operator, ^, will not work here because it is
- * a bitwise operator, not a logical operator. C does not
- * have a logical XOR operator, so we use a macro instead.
- */
-
- /* Has the key state changed? */
- dwKeyState = GetKeyState (VK_NUMLOCK) & 0x0001;
- if (WIN_XOR (internalKeyStates & NumLockMask, dwKeyState))
- {
- winSendKeyEvent (KEY_NumLock, TRUE);
- winSendKeyEvent (KEY_NumLock, FALSE);
- }
-
- /* Has the key state changed? */
- dwKeyState = GetKeyState (VK_CAPITAL) & 0x0001;
- if (WIN_XOR (internalKeyStates & LockMask, dwKeyState))
- {
- winSendKeyEvent (KEY_CapsLock, TRUE);
- winSendKeyEvent (KEY_CapsLock, FALSE);
- }
-
- /* Has the key state changed? */
- dwKeyState = GetKeyState (VK_SCROLL) & 0x0001;
- if (WIN_XOR (internalKeyStates & ScrollLockMask, dwKeyState))
- {
- winSendKeyEvent (KEY_ScrollLock, TRUE);
- winSendKeyEvent (KEY_ScrollLock, FALSE);
- }
-
- /* Has the key state changed? */
- dwKeyState = GetKeyState (VK_KANA) & 0x0001;
- if (WIN_XOR (internalKeyStates & KanaMask, dwKeyState))
- {
- winSendKeyEvent (KEY_HKTG, TRUE);
- winSendKeyEvent (KEY_HKTG, FALSE);
- }
-}
-
-
-/*
- * Look for the lovely fake Control_L press/release generated by Windows
- * when AltGr is pressed/released on a non-U.S. keyboard.
- */
-
-Bool
-winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
-{
- MSG msgNext;
- LONG lTime;
- Bool fReturn;
-
- /*
- * Fake Ctrl_L presses will be followed by an Alt_R keypress
- * with the same timestamp as the Ctrl_L press.
- */
- if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
- && wParam == VK_CONTROL
- && (HIWORD (lParam) & KF_EXTENDED) == 0)
- {
- /* Got a Ctrl_L press */
-
- /* Get time of current message */
- lTime = GetMessageTime ();
-
- /* Look for fake Ctrl_L preceeding an Alt_R press. */
- fReturn = PeekMessage (&msgNext, NULL,
- WM_KEYDOWN, WM_SYSKEYDOWN,
- PM_NOREMOVE);
-
- /*
- * Try again if the first call fails.
- * NOTE: This usually happens when TweakUI is enabled.
- */
- if (!fReturn)
- {
- /* Voodoo to make sure that the Alt_R message has posted */
- Sleep (0);
-
- /* Look for fake Ctrl_L preceeding an Alt_R press. */
- fReturn = PeekMessage (&msgNext, NULL,
- WM_KEYDOWN, WM_SYSKEYDOWN,
- PM_NOREMOVE);
- }
- if (msgNext.message != WM_KEYDOWN && msgNext.message != WM_SYSKEYDOWN)
- fReturn = 0;
-
- /* Is next press an Alt_R with the same timestamp? */
- if (fReturn && msgNext.wParam == VK_MENU
- && msgNext.time == lTime
- && (HIWORD (msgNext.lParam) & KF_EXTENDED))
- {
- /*
- * Next key press is Alt_R with same timestamp as current
- * Ctrl_L message. Therefore, this Ctrl_L press is a fake
- * event, so discard it.
- */
- return TRUE;
- }
- }
-
- /*
- * Fake Ctrl_L releases will be followed by an Alt_R release
- * with the same timestamp as the Ctrl_L release.
- */
- if ((message == WM_KEYUP || message == WM_SYSKEYUP)
- && wParam == VK_CONTROL
- && (HIWORD (lParam) & KF_EXTENDED) == 0)
- {
- /* Got a Ctrl_L release */
-
- /* Get time of current message */
- lTime = GetMessageTime ();
-
- /* Look for fake Ctrl_L release preceeding an Alt_R release. */
- fReturn = PeekMessage (&msgNext, NULL,
- WM_KEYUP, WM_SYSKEYUP,
- PM_NOREMOVE);
-
- /*
- * Try again if the first call fails.
- * NOTE: This usually happens when TweakUI is enabled.
- */
- if (!fReturn)
- {
- /* Voodoo to make sure that the Alt_R message has posted */
- Sleep (0);
-
- /* Look for fake Ctrl_L release preceeding an Alt_R release. */
- fReturn = PeekMessage (&msgNext, NULL,
- WM_KEYUP, WM_SYSKEYUP,
- PM_NOREMOVE);
- }
-
- if (msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP)
- fReturn = 0;
-
- /* Is next press an Alt_R with the same timestamp? */
- if (fReturn
- && (msgNext.message == WM_KEYUP
- || msgNext.message == WM_SYSKEYUP)
- && msgNext.wParam == VK_MENU
- && msgNext.time == lTime
- && (HIWORD (msgNext.lParam) & KF_EXTENDED))
- {
- /*
- * Next key release is Alt_R with same timestamp as current
- * Ctrl_L message. Therefore, this Ctrl_L release is a fake
- * event, so discard it.
- */
- return TRUE;
- }
- }
-
- /* Not a fake control left press/release */
- return FALSE;
-}
-
-
-/*
- * Lift any modifier keys that are pressed
- */
-
-void
-winKeybdReleaseKeys (void)
-{
- int i;
-
-#ifdef HAS_DEVWINDOWS
- /* Verify that the mi input system has been initialized */
- if (g_fdMessageQueue == WIN_FD_INVALID)
- return;
-#endif
-
- /* Loop through all keys */
- for (i = 0; i < NUM_KEYCODES; ++i)
- {
- /* Pop key if pressed */
- if (g_winKeyState[i])
- winSendKeyEvent (i, FALSE);
-
- /* Reset pressed flag for keys */
- g_winKeyState[i] = FALSE;
- }
-}
-
-
-/*
- * Take a raw X key code and send an up or down event for it.
- *
- * Thanks to VNC for inspiration, though it is a simple function.
- */
-
-void
-winSendKeyEvent (DWORD dwKey, Bool fDown)
-{
- EventListPtr events;
- int i, nevents;
-
- /*
- * When alt-tabing between screens we can get phantom key up messages
- * Here we only pass them through it we think we should!
- */
- if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) return;
-
- /* Update the keyState map */
- g_winKeyState[dwKey] = fDown;
-
- GetEventList(&events);
- nevents = GetKeyboardEvents(events, g_pwinKeyboard, fDown ? KeyPress : KeyRelease, dwKey + MIN_KEYCODE);
-
- for (i = 0; i < nevents; i++)
- mieqEnqueue(g_pwinKeyboard, (InternalEvent*)events[i].event);
-
- winDebug("winSendKeyEvent: dwKey: %d, fDown: %d, nEvents %d\n",
- dwKey, fDown, nevents);
-}
-
-BOOL winCheckKeyPressed(WPARAM wParam, LPARAM lParam)
-{
- switch (wParam)
- {
- case VK_CONTROL:
- if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl])
- return TRUE;
- if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl])
- return TRUE;
- break;
- case VK_SHIFT:
- if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR])
- return TRUE;
- if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL])
- return TRUE;
- break;
- default:
- return TRUE;
- }
- return FALSE;
-}
-
-/* Only on shift release message is sent even if both are pressed.
- * Fix this here
- */
-void winFixShiftKeys (int iScanCode)
-{
- if (GetKeyState (VK_SHIFT) & 0x8000)
- return;
-
- if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR])
- winSendKeyEvent (KEY_ShiftR, FALSE);
- if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL])
- winSendKeyEvent (KEY_ShiftL, FALSE);
-}
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 XFREE86 PROJECT 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 XFree86 Project
+ *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 XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include "winkeybd.h"
+#include "winconfig.h"
+#include "winmsg.h"
+
+#include "xkbsrv.h"
+
+static Bool g_winKeyState[NUM_KEYCODES];
+
+/*
+ * Local prototypes
+ */
+
+static void
+winKeybdBell (int iPercent, DeviceIntPtr pDeviceInt,
+ pointer pCtrl, int iClass);
+
+static void
+winKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl);
+
+
+/*
+ * Translate a Windows WM_[SYS]KEY(UP/DOWN) message
+ * into an ASCII scan code.
+ *
+ * We do this ourselves, rather than letting Windows handle it,
+ * because Windows tends to munge the handling of special keys,
+ * like AltGr on European keyboards.
+ */
+
+void
+winTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode)
+{
+ int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1];
+ int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2];
+ int iParam = HIWORD (lParam);
+ int iParamScanCode = LOBYTE (iParam);
+
+ winDebug("winTranslateKey: wParam %08x lParam %08x\n", wParam, lParam);
+
+/* WM_ key messages faked by Vista speech recognition (WSR) don't have a
+ * scan code.
+ *
+ * Vocola 3 (Rick Mohr's supplement to WSR) uses
+ * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a
+ * scan code of 1
+ */
+ if (iParamScanCode <= 1)
+ {
+ if (VK_PRIOR <= wParam && wParam <= VK_DOWN)
+ /* Trigger special case table to translate to extended
+ * keycode, otherwise if num_lock is on, we can get keypad
+ * numbers instead of navigation keys. */
+ iParam |= KF_EXTENDED;
+ else
+ iParamScanCode = MapVirtualKeyEx(wParam,
+ /*MAPVK_VK_TO_VSC*/0,
+ GetKeyboardLayout(0));
+ }
+
+ /* Branch on special extended, special non-extended, or normal key */
+ if ((iParam & KF_EXTENDED) && iKeyFixupEx)
+ *piScanCode = iKeyFixupEx;
+ else if (iKeyFixup)
+ *piScanCode = iKeyFixup;
+ else if (wParam == 0 && iParamScanCode == 0x70)
+ *piScanCode = KEY_HKTG;
+ else
+ switch (iParamScanCode)
+ {
+ case 0x70:
+ *piScanCode = KEY_HKTG;
+ break;
+ case 0x73:
+ *piScanCode = KEY_BSlash2;
+ break;
+ default:
+ *piScanCode = iParamScanCode;
+ break;
+ }
+}
+
+
+/* Ring the keyboard bell (system speaker on PCs) */
+static void
+winKeybdBell (int iPercent, DeviceIntPtr pDeviceInt,
+ pointer pCtrl, int iClass)
+{
+ /*
+ * We can't use Beep () here because it uses the PC speaker
+ * on NT/2000. MessageBeep (MB_OK) will play the default system
+ * sound on systems with a sound card or it will beep the PC speaker
+ * on systems that do not have a sound card.
+ */
+ MessageBeep (MB_OK);
+}
+
+
+/* Change some keyboard configuration parameters */
+static void
+winKeybdCtrl (DeviceIntPtr pDevice, KeybdCtrl *pCtrl)
+{
+}
+
+
+/*
+ * See Porting Layer Definition - p. 18
+ * winKeybdProc is known as a DeviceProc.
+ */
+
+int
+winKeybdProc (DeviceIntPtr pDeviceInt, int iState)
+{
+ DevicePtr pDevice = (DevicePtr) pDeviceInt;
+ XkbSrvInfoPtr xkbi;
+ XkbControlsPtr ctrl;
+
+ switch (iState)
+ {
+ case DEVICE_INIT:
+ winConfigKeyboard (pDeviceInt);
+
+ /* FIXME: Maybe we should use winGetKbdLeds () here? */
+ defaultKeyboardControl.leds = g_winInfo.keyboard.leds;
+
+ winErrorFVerb(2, "Rules = \"%s\" Model = \"%s\" Layout = \"%s\""
+ " Variant = \"%s\" Options = \"%s\"\n",
+ g_winInfo.xkb.rules ? g_winInfo.xkb.rules : "none",
+ g_winInfo.xkb.model ? g_winInfo.xkb.model : "none",
+ g_winInfo.xkb.layout ? g_winInfo.xkb.layout : "none",
+ g_winInfo.xkb.variant ? g_winInfo.xkb.variant : "none",
+ g_winInfo.xkb.options ? g_winInfo.xkb.options : "none");
+
+ InitKeyboardDeviceStruct (pDeviceInt,
+ &g_winInfo.xkb,
+ winKeybdBell,
+ winKeybdCtrl);
+
+ xkbi = pDeviceInt->key->xkbInfo;
+ if ((xkbi != NULL) && (xkbi->desc != NULL))
+ {
+ ctrl = xkbi->desc->ctrls;
+ ctrl->repeat_delay = g_winInfo.keyboard.delay;
+ ctrl->repeat_interval = 1000/g_winInfo.keyboard.rate;
+ }
+ else
+ {
+ winErrorFVerb (1, "winKeybdProc - Error initializing keyboard AutoRepeat\n");
+ }
+
+ break;
+
+ case DEVICE_ON:
+ pDevice->on = TRUE;
+
+ // immediately copy the state of this keyboard device to the VCK
+ // (which otherwise happens lazily after the first keypress)
+ CopyKeyClass(pDeviceInt, inputInfo.keyboard);
+ break;
+
+ case DEVICE_CLOSE:
+ case DEVICE_OFF:
+ pDevice->on = FALSE;
+ break;
+ }
+
+ return Success;
+}
+
+
+/*
+ * Detect current mode key states upon server startup.
+ *
+ * Simulate a press and release of any key that is currently
+ * toggled.
+ */
+
+void
+winInitializeModeKeyStates (void)
+{
+ /* Restore NumLock */
+ if (GetKeyState (VK_NUMLOCK) & 0x0001)
+ {
+ winSendKeyEvent (KEY_NumLock, TRUE);
+ winSendKeyEvent (KEY_NumLock, FALSE);
+ }
+
+ /* Restore CapsLock */
+ if (GetKeyState (VK_CAPITAL) & 0x0001)
+ {
+ winSendKeyEvent (KEY_CapsLock, TRUE);
+ winSendKeyEvent (KEY_CapsLock, FALSE);
+ }
+
+ /* Restore ScrollLock */
+ if (GetKeyState (VK_SCROLL) & 0x0001)
+ {
+ winSendKeyEvent (KEY_ScrollLock, TRUE);
+ winSendKeyEvent (KEY_ScrollLock, FALSE);
+ }
+
+ /* Restore KanaLock */
+ if (GetKeyState (VK_KANA) & 0x0001)
+ {
+ winSendKeyEvent (KEY_HKTG, TRUE);
+ winSendKeyEvent (KEY_HKTG, FALSE);
+ }
+}
+
+
+/*
+ * Upon regaining the keyboard focus we must
+ * resynchronize our internal mode key states
+ * with the actual state of the keys.
+ */
+
+void
+winRestoreModeKeyStates (void)
+{
+ DWORD dwKeyState;
+ BOOL processEvents = TRUE;
+ unsigned short internalKeyStates;
+
+ /* X server is being initialized */
+ if (!inputInfo.keyboard)
+ return;
+
+ /* Only process events if the rootwindow is mapped. The keyboard events
+ * will cause segfaults otherwise */
+ if (screenInfo.screens[0]->root && screenInfo.screens[0]->root->mapped == FALSE)
+ processEvents = FALSE;
+
+ /* Force to process all pending events in the mi event queue */
+ if (processEvents)
+ mieqProcessInputEvents ();
+
+ /* Read the mode key states of our X server */
+ /* (stored in the virtual core keyboard) */
+ internalKeyStates = XkbStateFieldFromRec(&inputInfo.keyboard->key->xkbInfo->state);
+ winDebug("winRestoreModeKeyStates: state %d\n", internalKeyStates);
+
+ /*
+ * NOTE: The C XOR operator, ^, will not work here because it is
+ * a bitwise operator, not a logical operator. C does not
+ * have a logical XOR operator, so we use a macro instead.
+ */
+
+ /* Has the key state changed? */
+ dwKeyState = GetKeyState (VK_NUMLOCK) & 0x0001;
+ if (WIN_XOR (internalKeyStates & NumLockMask, dwKeyState))
+ {
+ winSendKeyEvent (KEY_NumLock, TRUE);
+ winSendKeyEvent (KEY_NumLock, FALSE);
+ }
+
+ /* Has the key state changed? */
+ dwKeyState = GetKeyState (VK_CAPITAL) & 0x0001;
+ if (WIN_XOR (internalKeyStates & LockMask, dwKeyState))
+ {
+ winSendKeyEvent (KEY_CapsLock, TRUE);
+ winSendKeyEvent (KEY_CapsLock, FALSE);
+ }
+
+ /* Has the key state changed? */
+ dwKeyState = GetKeyState (VK_SCROLL) & 0x0001;
+ if (WIN_XOR (internalKeyStates & ScrollLockMask, dwKeyState))
+ {
+ winSendKeyEvent (KEY_ScrollLock, TRUE);
+ winSendKeyEvent (KEY_ScrollLock, FALSE);
+ }
+
+ /* Has the key state changed? */
+ dwKeyState = GetKeyState (VK_KANA) & 0x0001;
+ if (WIN_XOR (internalKeyStates & KanaMask, dwKeyState))
+ {
+ winSendKeyEvent (KEY_HKTG, TRUE);
+ winSendKeyEvent (KEY_HKTG, FALSE);
+ }
+}
+
+
+/*
+ * Look for the lovely fake Control_L press/release generated by Windows
+ * when AltGr is pressed/released on a non-U.S. keyboard.
+ */
+
+Bool
+winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
+{
+ MSG msgNext;
+ LONG lTime;
+ Bool fReturn;
+
+ /*
+ * Fake Ctrl_L presses will be followed by an Alt_R keypress
+ * with the same timestamp as the Ctrl_L press.
+ */
+ if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+ && wParam == VK_CONTROL
+ && (HIWORD (lParam) & KF_EXTENDED) == 0)
+ {
+ /* Got a Ctrl_L press */
+
+ /* Get time of current message */
+ lTime = GetMessageTime ();
+
+ /* Look for fake Ctrl_L preceeding an Alt_R press. */
+ fReturn = PeekMessage (&msgNext, NULL,
+ WM_KEYDOWN, WM_SYSKEYDOWN,
+ PM_NOREMOVE);
+
+ /*
+ * Try again if the first call fails.
+ * NOTE: This usually happens when TweakUI is enabled.
+ */
+ if (!fReturn)
+ {
+ /* Voodoo to make sure that the Alt_R message has posted */
+ Sleep (0);
+
+ /* Look for fake Ctrl_L preceeding an Alt_R press. */
+ fReturn = PeekMessage (&msgNext, NULL,
+ WM_KEYDOWN, WM_SYSKEYDOWN,
+ PM_NOREMOVE);
+ }
+ if (msgNext.message != WM_KEYDOWN && msgNext.message != WM_SYSKEYDOWN)
+ fReturn = 0;
+
+ /* Is next press an Alt_R with the same timestamp? */
+ if (fReturn && msgNext.wParam == VK_MENU
+ && msgNext.time == lTime
+ && (HIWORD (msgNext.lParam) & KF_EXTENDED))
+ {
+ /*
+ * Next key press is Alt_R with same timestamp as current
+ * Ctrl_L message. Therefore, this Ctrl_L press is a fake
+ * event, so discard it.
+ */
+ return TRUE;
+ }
+ }
+
+ /*
+ * Fake Ctrl_L releases will be followed by an Alt_R release
+ * with the same timestamp as the Ctrl_L release.
+ */
+ if ((message == WM_KEYUP || message == WM_SYSKEYUP)
+ && wParam == VK_CONTROL
+ && (HIWORD (lParam) & KF_EXTENDED) == 0)
+ {
+ /* Got a Ctrl_L release */
+
+ /* Get time of current message */
+ lTime = GetMessageTime ();
+
+ /* Look for fake Ctrl_L release preceeding an Alt_R release. */
+ fReturn = PeekMessage (&msgNext, NULL,
+ WM_KEYUP, WM_SYSKEYUP,
+ PM_NOREMOVE);
+
+ /*
+ * Try again if the first call fails.
+ * NOTE: This usually happens when TweakUI is enabled.
+ */
+ if (!fReturn)
+ {
+ /* Voodoo to make sure that the Alt_R message has posted */
+ Sleep (0);
+
+ /* Look for fake Ctrl_L release preceeding an Alt_R release. */
+ fReturn = PeekMessage (&msgNext, NULL,
+ WM_KEYUP, WM_SYSKEYUP,
+ PM_NOREMOVE);
+ }
+
+ if (msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP)
+ fReturn = 0;
+
+ /* Is next press an Alt_R with the same timestamp? */
+ if (fReturn
+ && (msgNext.message == WM_KEYUP
+ || msgNext.message == WM_SYSKEYUP)
+ && msgNext.wParam == VK_MENU
+ && msgNext.time == lTime
+ && (HIWORD (msgNext.lParam) & KF_EXTENDED))
+ {
+ /*
+ * Next key release is Alt_R with same timestamp as current
+ * Ctrl_L message. Therefore, this Ctrl_L release is a fake
+ * event, so discard it.
+ */
+ return TRUE;
+ }
+ }
+
+ /* Not a fake control left press/release */
+ return FALSE;
+}
+
+
+/*
+ * Lift any modifier keys that are pressed
+ */
+
+void
+winKeybdReleaseKeys (void)
+{
+ int i;
+
+#ifdef HAS_DEVWINDOWS
+ /* Verify that the mi input system has been initialized */
+ if (g_fdMessageQueue == WIN_FD_INVALID)
+ return;
+#endif
+
+ /* Loop through all keys */
+ for (i = 0; i < NUM_KEYCODES; ++i)
+ {
+ /* Pop key if pressed */
+ if (g_winKeyState[i])
+ winSendKeyEvent (i, FALSE);
+
+ /* Reset pressed flag for keys */
+ g_winKeyState[i] = FALSE;
+ }
+}
+
+
+/*
+ * Take a raw X key code and send an up or down event for it.
+ *
+ * Thanks to VNC for inspiration, though it is a simple function.
+ */
+
+void
+winSendKeyEvent (DWORD dwKey, Bool fDown)
+{
+ EventListPtr events;
+ int i, nevents;
+
+ /*
+ * When alt-tabing between screens we can get phantom key up messages
+ * Here we only pass them through it we think we should!
+ */
+ if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) return;
+
+ /* Update the keyState map */
+ g_winKeyState[dwKey] = fDown;
+
+ GetEventList(&events);
+ nevents = GetKeyboardEvents(events, g_pwinKeyboard, fDown ? KeyPress : KeyRelease, dwKey + MIN_KEYCODE, NULL);
+
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(g_pwinKeyboard, (InternalEvent*)events[i].event);
+
+ winDebug("winSendKeyEvent: dwKey: %d, fDown: %d, nEvents %d\n",
+ dwKey, fDown, nevents);
+}
+
+BOOL winCheckKeyPressed(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam)
+ {
+ case VK_CONTROL:
+ if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl])
+ return TRUE;
+ if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl])
+ return TRUE;
+ break;
+ case VK_SHIFT:
+ if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR])
+ return TRUE;
+ if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL])
+ return TRUE;
+ break;
+ default:
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Only on shift release message is sent even if both are pressed.
+ * Fix this here
+ */
+void winFixShiftKeys (int iScanCode)
+{
+ if (GetKeyState (VK_SHIFT) & 0x8000)
+ return;
+
+ if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR])
+ winSendKeyEvent (KEY_ShiftR, FALSE);
+ if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL])
+ winSendKeyEvent (KEY_ShiftL, FALSE);
+}
diff --git a/xorg-server/include/dix-config.h.in b/xorg-server/include/dix-config.h.in
index fd9ecced2..14229b435 100644
--- a/xorg-server/include/dix-config.h.in
+++ b/xorg-server/include/dix-config.h.in
@@ -136,6 +136,9 @@
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
+/* Define to 1 if you have the libdispatch (GCD) available */
+#undef HAVE_LIBDISPATCH
+
/* Define to 1 if you have the `link' function. */
#undef HAVE_LINK
diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h
index 2bb85ffaa..86078daee 100644
--- a/xorg-server/include/input.h
+++ b/xorg-server/include/input.h
@@ -102,6 +102,7 @@ typedef unsigned long Leds;
typedef struct _OtherClients *OtherClientsPtr;
typedef struct _InputClients *InputClientsPtr;
typedef struct _DeviceIntRec *DeviceIntPtr;
+typedef struct _ValuatorClassRec *ValuatorClassPtr;
typedef struct _ClassesRec *ClassesPtr;
typedef struct _SpriteRec *SpritePtr;
typedef union _GrabMask GrabMask;
@@ -300,6 +301,10 @@ extern _X_EXPORT Bool InitButtonClassDeviceStruct(
Atom* /* labels */,
CARD8* /*map*/);
+extern _X_INTERNAL ValuatorClassPtr AllocValuatorClass(
+ ValuatorClassPtr src,
+ int numAxes);
+
extern _X_EXPORT Bool InitValuatorClassDeviceStruct(
DeviceIntPtr /*device*/,
int /*numAxes*/,
@@ -460,12 +465,6 @@ extern _X_EXPORT int GetKeyboardEvents(
EventListPtr events,
DeviceIntPtr pDev,
int type,
- int key_code);
-
-extern int GetKeyboardValuatorEvents(
- EventListPtr events,
- DeviceIntPtr pDev,
- int type,
int key_code,
const ValuatorMask *mask);
diff --git a/xorg-server/include/inputstr.h b/xorg-server/include/inputstr.h
index f63df8087..bd7c78dec 100644
--- a/xorg-server/include/inputstr.h
+++ b/xorg-server/include/inputstr.h
@@ -283,7 +283,7 @@ typedef struct _ValuatorClassRec {
unsigned short numAxes;
double *axisVal; /* always absolute, but device-coord system */
ValuatorAccelerationRec accelScheme;
-} ValuatorClassRec, *ValuatorClassPtr;
+} ValuatorClassRec;
typedef struct _ButtonClassRec {
int sourceid;
diff --git a/xorg-server/include/ptrveloc.h b/xorg-server/include/ptrveloc.h
index 1198146f1..6ca309c8c 100644
--- a/xorg-server/include/ptrveloc.h
+++ b/xorg-server/include/ptrveloc.h
@@ -1,144 +1,144 @@
-/*
- *
- * Copyright © 2006-2011 Simon Thum simon dot thum at gmx dot de
- *
- * 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#ifndef POINTERVELOCITY_H
-#define POINTERVELOCITY_H
-
-#include <input.h>
-
-/* constants for acceleration profiles */
-
-#define AccelProfileNone -1
-#define AccelProfileClassic 0
-#define AccelProfileDeviceSpecific 1
-#define AccelProfilePolynomial 2
-#define AccelProfileSmoothLinear 3
-#define AccelProfileSimple 4
-#define AccelProfilePower 5
-#define AccelProfileLinear 6
-#define AccelProfileSmoothLimited 7
-#define AccelProfileLAST AccelProfileSmoothLimited
-
-/* fwd */
-struct _DeviceVelocityRec;
-
-/**
- * profile
- * returns actual acceleration depending on velocity, acceleration control,...
- */
-typedef float (*PointerAccelerationProfileFunc)
- (DeviceIntPtr dev, struct _DeviceVelocityRec* vel,
- float velocity, float threshold, float accelCoeff);
-
-/**
- * a motion history, with just enough information to
- * calc mean velocity and decide which motion was along
- * a more or less straight line
- */
-typedef struct _MotionTracker {
- int dx, dy; /* accumulated delta for each axis */
- int time; /* time of creation */
- int dir; /* initial direction bitfield */
-} MotionTracker, *MotionTrackerPtr;
-
-/**
- * Contains all data needed to implement mouse ballistics
- */
-typedef struct _DeviceVelocityRec {
- MotionTrackerPtr tracker;
- int num_tracker;
- int cur_tracker; /* current index */
- float velocity; /* velocity as guessed by algorithm */
- float last_velocity; /* previous velocity estimate */
- int last_dx; /* last time-difference */
- int last_dy ; /* phase of last/current estimate */
- float corr_mul; /* config: multiply this into velocity */
- float const_acceleration; /* config: (recipr.) const deceleration */
- float min_acceleration; /* config: minimum acceleration */
- short reset_time; /* config: reset non-visible state after # ms */
- short use_softening; /* config: use softening of mouse values */
- float max_rel_diff; /* config: max. relative difference */
- float max_diff; /* config: max. difference */
- int initial_range; /* config: max. offset used as initial velocity */
- Bool average_accel; /* config: average acceleration over velocity */
- PointerAccelerationProfileFunc Profile;
- PointerAccelerationProfileFunc deviceSpecificProfile;
- void* profile_private;/* extended data, see SetAccelerationProfile() */
- struct { /* to be able to query this information */
- int profile_number;
- } statistics;
-} DeviceVelocityRec, *DeviceVelocityPtr;
-
-/**
- * contains the run-time data for the predictable scheme, that is, a
- * DeviceVelocityPtr and the property handlers.
- */
-typedef struct _PredictableAccelSchemeRec {
- DeviceVelocityPtr vel;
- long* prop_handlers;
- int num_prop_handlers;
-} PredictableAccelSchemeRec, *PredictableAccelSchemePtr;
-
-extern _X_EXPORT void
-InitVelocityData(DeviceVelocityPtr vel);
-
-extern _X_EXPORT void
-InitTrackers(DeviceVelocityPtr vel, int ntracker);
-
-extern _X_EXPORT short
-ProcessVelocityData2D(DeviceVelocityPtr vel, int dx, int dy, int time);
-
-extern _X_EXPORT float
-BasicComputeAcceleration(DeviceIntPtr dev, DeviceVelocityPtr vel,
- float velocity, float threshold, float acc);
-
-extern _X_EXPORT void
-FreeVelocityData(DeviceVelocityPtr vel);
-
-extern _X_EXPORT int
-SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
-
-extern _X_EXPORT DeviceVelocityPtr
-GetDevicePredictableAccelData(DeviceIntPtr dev);
-
-extern _X_EXPORT void
-SetDeviceSpecificAccelerationProfile(DeviceVelocityPtr vel,
- PointerAccelerationProfileFunc profile);
-
-extern _X_INTERNAL void
-AccelerationDefaultCleanup(DeviceIntPtr dev);
-
-extern _X_INTERNAL Bool
-InitPredictableAccelerationScheme(DeviceIntPtr dev,
- struct _ValuatorAccelerationRec* protoScheme);
-
-extern _X_INTERNAL void
-acceleratePointerPredictable(DeviceIntPtr dev, ValuatorMask* val,
- CARD32 evtime);
-
-extern _X_INTERNAL void
-acceleratePointerLightweight(DeviceIntPtr dev, ValuatorMask* val,
- CARD32 evtime);
-
-#endif /* POINTERVELOCITY_H */
+/*
+ *
+ * Copyright © 2006-2011 Simon Thum simon dot thum at gmx dot de
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef POINTERVELOCITY_H
+#define POINTERVELOCITY_H
+
+#include <input.h>
+
+/* constants for acceleration profiles */
+
+#define AccelProfileNone -1
+#define AccelProfileClassic 0
+#define AccelProfileDeviceSpecific 1
+#define AccelProfilePolynomial 2
+#define AccelProfileSmoothLinear 3
+#define AccelProfileSimple 4
+#define AccelProfilePower 5
+#define AccelProfileLinear 6
+#define AccelProfileSmoothLimited 7
+#define AccelProfileLAST AccelProfileSmoothLimited
+
+/* fwd */
+struct _DeviceVelocityRec;
+
+/**
+ * profile
+ * returns actual acceleration depending on velocity, acceleration control,...
+ */
+typedef float (*PointerAccelerationProfileFunc)
+ (DeviceIntPtr dev, struct _DeviceVelocityRec* vel,
+ float velocity, float threshold, float accelCoeff);
+
+/**
+ * a motion history, with just enough information to
+ * calc mean velocity and decide which motion was along
+ * a more or less straight line
+ */
+typedef struct _MotionTracker {
+ int dx, dy; /* accumulated delta for each axis */
+ int time; /* time of creation */
+ int dir; /* initial direction bitfield */
+} MotionTracker, *MotionTrackerPtr;
+
+/**
+ * Contains all data needed to implement mouse ballistics
+ */
+typedef struct _DeviceVelocityRec {
+ MotionTrackerPtr tracker;
+ int num_tracker;
+ int cur_tracker; /* current index */
+ float velocity; /* velocity as guessed by algorithm */
+ float last_velocity; /* previous velocity estimate */
+ int last_dx; /* last time-difference */
+ int last_dy ; /* phase of last/current estimate */
+ float corr_mul; /* config: multiply this into velocity */
+ float const_acceleration; /* config: (recipr.) const deceleration */
+ float min_acceleration; /* config: minimum acceleration */
+ short reset_time; /* config: reset non-visible state after # ms */
+ short use_softening; /* config: use softening of mouse values */
+ float max_rel_diff; /* config: max. relative difference */
+ float max_diff; /* config: max. difference */
+ int initial_range; /* config: max. offset used as initial velocity */
+ Bool average_accel; /* config: average acceleration over velocity */
+ PointerAccelerationProfileFunc Profile;
+ PointerAccelerationProfileFunc deviceSpecificProfile;
+ void* profile_private;/* extended data, see SetAccelerationProfile() */
+ struct { /* to be able to query this information */
+ int profile_number;
+ } statistics;
+} DeviceVelocityRec, *DeviceVelocityPtr;
+
+/**
+ * contains the run-time data for the predictable scheme, that is, a
+ * DeviceVelocityPtr and the property handlers.
+ */
+typedef struct _PredictableAccelSchemeRec {
+ DeviceVelocityPtr vel;
+ long* prop_handlers;
+ int num_prop_handlers;
+} PredictableAccelSchemeRec, *PredictableAccelSchemePtr;
+
+extern _X_EXPORT void
+InitVelocityData(DeviceVelocityPtr vel);
+
+extern _X_EXPORT void
+InitTrackers(DeviceVelocityPtr vel, int ntracker);
+
+extern _X_EXPORT BOOL
+ProcessVelocityData2D(DeviceVelocityPtr vel, int dx, int dy, int time);
+
+extern _X_EXPORT float
+BasicComputeAcceleration(DeviceIntPtr dev, DeviceVelocityPtr vel,
+ float velocity, float threshold, float acc);
+
+extern _X_EXPORT void
+FreeVelocityData(DeviceVelocityPtr vel);
+
+extern _X_EXPORT int
+SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
+
+extern _X_EXPORT DeviceVelocityPtr
+GetDevicePredictableAccelData(DeviceIntPtr dev);
+
+extern _X_EXPORT void
+SetDeviceSpecificAccelerationProfile(DeviceVelocityPtr vel,
+ PointerAccelerationProfileFunc profile);
+
+extern _X_INTERNAL void
+AccelerationDefaultCleanup(DeviceIntPtr dev);
+
+extern _X_INTERNAL Bool
+InitPredictableAccelerationScheme(DeviceIntPtr dev,
+ struct _ValuatorAccelerationRec* protoScheme);
+
+extern _X_INTERNAL void
+acceleratePointerPredictable(DeviceIntPtr dev, ValuatorMask* val,
+ CARD32 evtime);
+
+extern _X_INTERNAL void
+acceleratePointerLightweight(DeviceIntPtr dev, ValuatorMask* val,
+ CARD32 evtime);
+
+#endif /* POINTERVELOCITY_H */
diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am
index f3265b788..fe9bc1f2e 100644
--- a/xorg-server/test/Makefile.am
+++ b/xorg-server/test/Makefile.am
@@ -1,5 +1,4 @@
if ENABLE_UNIT_TESTS
-if HAVE_GLIB
if HAVE_LD_WRAP
SUBDIRS= . xi2
noinst_PROGRAMS = xkb input xtest list
@@ -7,9 +6,9 @@ check_LTLIBRARIES = libxservertest.la
TESTS=$(noinst_PROGRAMS)
-AM_CFLAGS = $(DIX_CFLAGS) $(GLIB_CFLAGS) @XORG_CFLAGS@
+AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
INCLUDES = @XORG_INCS@
-TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLIB_LIBS)
+TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS)
if SPECIAL_DTRACE_OBJECTS
TEST_LDADD += $(OS_LIB) $(DIX_LIB)
@@ -38,7 +37,6 @@ libxservertest_la_LIBADD = \
@XORG_LIBS@
endif
endif
-endif
CLEANFILES=libxservertest.c
diff --git a/xorg-server/test/input.c b/xorg-server/test/input.c
index c13b4f213..ac37d67a1 100644
--- a/xorg-server/test/input.c
+++ b/xorg-server/test/input.c
@@ -40,7 +40,7 @@
#include "dixgrabs.h"
#include "eventstr.h"
#include "inpututils.h"
-#include <glib.h>
+#include "assert.h"
/**
* Init a device with axes.
@@ -60,24 +60,24 @@ static void dix_init_valuators(void)
memset(&dev, 0, sizeof(DeviceIntRec));
dev.type = MASTER_POINTER; /* claim it's a master to stop ptracccel */
- g_assert(InitValuatorClassDeviceStruct(NULL, 0, atoms, 0, 0) == FALSE);
- g_assert(InitValuatorClassDeviceStruct(&dev, num_axes, atoms, 0, Absolute));
+ assert(InitValuatorClassDeviceStruct(NULL, 0, atoms, 0, 0) == FALSE);
+ assert(InitValuatorClassDeviceStruct(&dev, num_axes, atoms, 0, Absolute));
val = dev.valuator;
- g_assert(val);
- g_assert(val->numAxes == num_axes);
- g_assert(val->numMotionEvents == 0);
- g_assert(val->axisVal);
+ assert(val);
+ assert(val->numAxes == num_axes);
+ assert(val->numMotionEvents == 0);
+ assert(val->axisVal);
for (i = 0; i < num_axes; i++)
{
- g_assert(val->axisVal[i] == 0);
- g_assert(val->axes->min_value == NO_AXIS_LIMITS);
- g_assert(val->axes->max_value == NO_AXIS_LIMITS);
- g_assert(val->axes->mode == Absolute);
+ assert(val->axisVal[i] == 0);
+ assert(val->axes->min_value == NO_AXIS_LIMITS);
+ assert(val->axes->max_value == NO_AXIS_LIMITS);
+ assert(val->axes->mode == Absolute);
}
- g_assert(dev.last.numValuators == num_axes);
+ assert(dev.last.numValuators == num_axes);
}
/* just check the known success cases, and that error cases set the client's
@@ -97,48 +97,48 @@ static void dix_check_grab_values(void)
param.ownerEvents = FALSE;
rc = CheckGrabValues(&client, &param);
- g_assert(rc == Success);
+ assert(rc == Success);
param.this_device_mode = GrabModeAsync;
rc = CheckGrabValues(&client, &param);
- g_assert(rc == Success);
+ assert(rc == Success);
param.this_device_mode = GrabModeAsync + 1;
rc = CheckGrabValues(&client, &param);
- g_assert(rc == BadValue);
- g_assert(client.errorValue == param.this_device_mode);
- g_assert(client.errorValue == GrabModeAsync + 1);
+ assert(rc == BadValue);
+ assert(client.errorValue == param.this_device_mode);
+ assert(client.errorValue == GrabModeAsync + 1);
param.this_device_mode = GrabModeSync;
param.other_devices_mode = GrabModeAsync;
rc = CheckGrabValues(&client, &param);
- g_assert(rc == Success);
+ assert(rc == Success);
param.other_devices_mode = GrabModeAsync + 1;
rc = CheckGrabValues(&client, &param);
- g_assert(rc == BadValue);
- g_assert(client.errorValue == param.other_devices_mode);
- g_assert(client.errorValue == GrabModeAsync + 1);
+ assert(rc == BadValue);
+ assert(client.errorValue == param.other_devices_mode);
+ assert(client.errorValue == GrabModeAsync + 1);
param.other_devices_mode = GrabModeSync;
param.modifiers = 1 << 13;
rc = CheckGrabValues(&client, &param);
- g_assert(rc == BadValue);
- g_assert(client.errorValue == param.modifiers);
- g_assert(client.errorValue == (1 << 13));
+ assert(rc == BadValue);
+ assert(client.errorValue == param.modifiers);
+ assert(client.errorValue == (1 << 13));
param.modifiers = AnyModifier;
param.ownerEvents = TRUE;
rc = CheckGrabValues(&client, &param);
- g_assert(rc == Success);
+ assert(rc == Success);
param.ownerEvents = 3;
rc = CheckGrabValues(&client, &param);
- g_assert(rc == BadValue);
- g_assert(client.errorValue == param.ownerEvents);
- g_assert(client.errorValue == 3);
+ assert(rc == BadValue);
+ assert(client.errorValue == param.ownerEvents);
+ assert(client.errorValue == 3);
}
@@ -160,21 +160,21 @@ static void dix_event_to_core(int type)
/* EventToCore memsets the event to 0 */
#define test_event() \
- g_assert(rc == Success); \
- g_assert(core); \
- g_assert(count == 1); \
- g_assert(core->u.u.type == type); \
- g_assert(core->u.u.detail == detail); \
- g_assert(core->u.keyButtonPointer.time == time); \
- g_assert(core->u.keyButtonPointer.rootX == x); \
- g_assert(core->u.keyButtonPointer.rootY == y); \
- g_assert(core->u.keyButtonPointer.state == state); \
- g_assert(core->u.keyButtonPointer.eventX == 0); \
- g_assert(core->u.keyButtonPointer.eventY == 0); \
- g_assert(core->u.keyButtonPointer.root == ROOT_WINDOW_ID); \
- g_assert(core->u.keyButtonPointer.event == 0); \
- g_assert(core->u.keyButtonPointer.child == 0); \
- g_assert(core->u.keyButtonPointer.sameScreen == FALSE);
+ assert(rc == Success); \
+ assert(core); \
+ assert(count == 1); \
+ assert(core->u.u.type == type); \
+ assert(core->u.u.detail == detail); \
+ assert(core->u.keyButtonPointer.time == time); \
+ assert(core->u.keyButtonPointer.rootX == x); \
+ assert(core->u.keyButtonPointer.rootY == y); \
+ assert(core->u.keyButtonPointer.state == state); \
+ assert(core->u.keyButtonPointer.eventX == 0); \
+ assert(core->u.keyButtonPointer.eventY == 0); \
+ assert(core->u.keyButtonPointer.root == ROOT_WINDOW_ID); \
+ assert(core->u.keyButtonPointer.event == 0); \
+ assert(core->u.keyButtonPointer.child == 0); \
+ assert(core->u.keyButtonPointer.sameScreen == FALSE);
x = 0;
y = 0;
@@ -217,11 +217,11 @@ static void dix_event_to_core(int type)
ev.root_x = x;
ev.root_y = y;
rc = EventToCore((InternalEvent*)&ev, &core, &count);
- g_assert(rc == Success);
- g_assert(core);
- g_assert(count == 1);
- g_assert(core->u.keyButtonPointer.rootX != x);
- g_assert(core->u.keyButtonPointer.rootY != y);
+ assert(rc == Success);
+ assert(core);
+ assert(count == 1);
+ assert(core->u.keyButtonPointer.rootX != x);
+ assert(core->u.keyButtonPointer.rootY != y);
x = 0x7FFF;
y = 0x7FFF;
@@ -245,7 +245,7 @@ static void dix_event_to_core(int type)
detail = 0xFFF; /* too big */
ev.detail.key = detail;
rc = EventToCore((InternalEvent*)&ev, &core, &count);
- g_assert(rc == BadMatch);
+ assert(rc == BadMatch);
detail = 0xFF; /* too big */
ev.detail.key = detail;
@@ -257,11 +257,11 @@ static void dix_event_to_core(int type)
state = 0x10000; /* too big */
ev.corestate = state;
rc = EventToCore((InternalEvent*)&ev, &core, &count);
- g_assert(rc == Success);
- g_assert(core);
- g_assert(count == 1);
- g_assert(core->u.keyButtonPointer.state != state);
- g_assert(core->u.keyButtonPointer.state == (state & 0xFFFF));
+ assert(rc == Success);
+ assert(core);
+ assert(count == 1);
+ assert(core->u.keyButtonPointer.state != state);
+ assert(core->u.keyButtonPointer.state == (state & 0xFFFF));
#undef test_event
}
@@ -278,7 +278,7 @@ static void dix_event_to_core_fail(int evtype, int expected_rc)
ev.type = evtype;
rc = EventToCore((InternalEvent*)&ev, &core, &count);
- g_assert(rc == expected_rc);
+ assert(rc == expected_rc);
}
static void dix_event_to_core_conversion(void)
@@ -304,28 +304,28 @@ _dix_test_xi_convert(DeviceEvent *ev, int expected_rc, int expected_count)
int rc;
rc = EventToXI((InternalEvent*)ev, &xi, &count);
- g_assert(rc == expected_rc);
- g_assert(count >= expected_count);
+ assert(rc == expected_rc);
+ assert(count >= expected_count);
if (count > 0){
deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*)xi;
- g_assert(kbp->type == IEventBase + ev->type);
- g_assert(kbp->detail == ev->detail.key);
- g_assert(kbp->time == ev->time);
- g_assert((kbp->deviceid & ~MORE_EVENTS) == ev->deviceid);
- g_assert(kbp->root_x == ev->root_x);
- g_assert(kbp->root_y == ev->root_y);
- g_assert(kbp->state == ev->corestate);
- g_assert(kbp->event_x == 0);
- g_assert(kbp->event_y == 0);
- g_assert(kbp->root == ev->root);
- g_assert(kbp->event == 0);
- g_assert(kbp->child == 0);
- g_assert(kbp->same_screen == FALSE);
+ assert(kbp->type == IEventBase + ev->type);
+ assert(kbp->detail == ev->detail.key);
+ assert(kbp->time == ev->time);
+ assert((kbp->deviceid & ~MORE_EVENTS) == ev->deviceid);
+ assert(kbp->root_x == ev->root_x);
+ assert(kbp->root_y == ev->root_y);
+ assert(kbp->state == ev->corestate);
+ assert(kbp->event_x == 0);
+ assert(kbp->event_y == 0);
+ assert(kbp->root == ev->root);
+ assert(kbp->event == 0);
+ assert(kbp->child == 0);
+ assert(kbp->same_screen == FALSE);
while (--count > 0) {
deviceValuator *v = (deviceValuator*)&xi[count];
- g_assert(v->type == DeviceValuator);
- g_assert(v->num_valuators <= 6);
+ assert(v->type == DeviceValuator);
+ assert(v->num_valuators <= 6);
}
@@ -436,7 +436,7 @@ static void dix_event_to_xi1_conversion(void)
static void xi2_struct_sizes(void)
{
#define compare(req) \
- g_assert(sizeof(req) == sz_##req);
+ assert(sizeof(req) == sz_##req);
compare(xXIQueryVersionReq);
compare(xXIWarpPointerReq);
@@ -476,23 +476,23 @@ static void dix_grab_matching(void)
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_XI2;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_XI2;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_CORE;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* XI2 grabs for different devices must fail, regardless of ignoreDevice
* XI2 grabs for master devices must fail against a slave */
@@ -516,28 +516,28 @@ static void dix_grab_matching(void)
b.device = &dev2;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.device = &dev2;
b.device = &dev1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.device = inputInfo.all_master_devices;
b.device = &dev1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.device = &dev1;
b.device = inputInfo.all_master_devices;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* ignoreDevice FALSE must fail for different devices for CORE and XI */
a.grabtype = GRABTYPE_XI;
@@ -547,7 +547,7 @@ static void dix_grab_matching(void)
a.modifierDevice = &dev1;
b.modifierDevice = &dev1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
@@ -556,7 +556,7 @@ static void dix_grab_matching(void)
a.modifierDevice = &dev1;
b.modifierDevice = &dev1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* ignoreDevice FALSE must fail for different modifier devices for CORE
* and XI */
@@ -567,7 +567,7 @@ static void dix_grab_matching(void)
a.modifierDevice = &dev1;
b.modifierDevice = &dev2;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
@@ -576,7 +576,7 @@ static void dix_grab_matching(void)
a.modifierDevice = &dev1;
b.modifierDevice = &dev2;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* different event type must fail */
a.grabtype = GRABTYPE_XI2;
@@ -588,9 +588,9 @@ static void dix_grab_matching(void)
a.type = XI_KeyPress;
b.type = XI_KeyRelease;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
@@ -601,9 +601,9 @@ static void dix_grab_matching(void)
a.type = XI_KeyPress;
b.type = XI_KeyRelease;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_XI;
@@ -614,9 +614,9 @@ static void dix_grab_matching(void)
a.type = XI_KeyPress;
b.type = XI_KeyRelease;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* different modifiers must fail */
a.grabtype = GRABTYPE_XI2;
@@ -630,23 +630,23 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = 1;
b.modifiersDetail.exact = 2;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_XI;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* AnyModifier must fail for XI2 */
a.grabtype = GRABTYPE_XI2;
@@ -654,9 +654,9 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = AnyModifier;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* XIAnyModifier must fail for CORE and XI */
a.grabtype = GRABTYPE_XI;
@@ -664,18 +664,18 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = XIAnyModifier;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
a.modifiersDetail.exact = XIAnyModifier;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* different detail must fail */
a.grabtype = GRABTYPE_XI2;
@@ -685,23 +685,23 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = 1;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_XI;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* detail of AnyModifier must fail */
a.grabtype = GRABTYPE_XI2;
@@ -711,23 +711,23 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = 1;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_XI;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* detail of XIAnyModifier must fail */
a.grabtype = GRABTYPE_XI2;
@@ -737,23 +737,23 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = 1;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_XI;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
+ assert(rc == FALSE);
/* XIAnyModifier or AnyModifer must succeed */
a.grabtype = GRABTYPE_XI2;
@@ -763,9 +763,9 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = XIAnyModifier;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
@@ -774,9 +774,9 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = AnyModifier;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_XI;
@@ -785,9 +785,9 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = AnyModifier;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
/* AnyKey or XIAnyKeycode must succeed */
a.grabtype = GRABTYPE_XI2;
@@ -797,9 +797,9 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = 1;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
a.grabtype = GRABTYPE_CORE;
b.grabtype = GRABTYPE_CORE;
@@ -808,9 +808,9 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = 1;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
a.grabtype = GRABTYPE_XI;
b.grabtype = GRABTYPE_XI;
@@ -819,9 +819,9 @@ static void dix_grab_matching(void)
a.modifiersDetail.exact = 1;
b.modifiersDetail.exact = 1;
rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
+ assert(rc == TRUE);
}
static void test_bits_to_byte(int i)
@@ -829,9 +829,9 @@ static void test_bits_to_byte(int i)
int expected_bytes;
expected_bytes = (i + 7)/8;
- g_assert(bits_to_bytes(i) >= i/8);
- g_assert((bits_to_bytes(i) * 8) - i <= 7);
- g_assert(expected_bytes == bits_to_bytes(i));
+ assert(bits_to_bytes(i) >= i/8);
+ assert((bits_to_bytes(i) * 8) - i <= 7);
+ assert(expected_bytes == bits_to_bytes(i));
}
static void test_bytes_to_int32(int i)
@@ -839,9 +839,9 @@ static void test_bytes_to_int32(int i)
int expected_4byte;
expected_4byte = (i + 3)/4;
- g_assert(bytes_to_int32(i) <= i);
- g_assert((bytes_to_int32(i) * 4) - i <= 3);
- g_assert(expected_4byte == bytes_to_int32(i));
+ assert(bytes_to_int32(i) <= i);
+ assert((bytes_to_int32(i) * 4) - i <= 3);
+ assert(expected_4byte == bytes_to_int32(i));
}
static void test_pad_to_int32(int i)
@@ -849,13 +849,13 @@ static void test_pad_to_int32(int i)
int expected_bytes;
expected_bytes = ((i + 3)/4) * 4;
- g_assert(pad_to_int32(i) >= i);
- g_assert(pad_to_int32(i) - i <= 3);
- g_assert(expected_bytes == pad_to_int32(i));
+ assert(pad_to_int32(i) >= i);
+ assert(pad_to_int32(i) - i <= 3);
+ assert(expected_bytes == pad_to_int32(i));
}
static void include_byte_padding_macros(void)
{
- g_test_message("Testing bits_to_bytes()");
+ printf("Testing bits_to_bytes()\n");
/* the macros don't provide overflow protection */
test_bits_to_byte(0);
@@ -868,7 +868,7 @@ static void include_byte_padding_macros(void)
test_bits_to_byte(INT_MAX - 9);
test_bits_to_byte(INT_MAX - 8);
- g_test_message("Testing bytes_to_int32()");
+ printf("Testing bytes_to_int32()\n");
test_bytes_to_int32(0);
test_bytes_to_int32(1);
@@ -884,7 +884,7 @@ static void include_byte_padding_macros(void)
test_bytes_to_int32(INT_MAX - 4);
test_bytes_to_int32(INT_MAX - 3);
- g_test_message("Testing pad_to_int32");
+ printf("Testing pad_to_int32\n");
test_pad_to_int32(0);
test_pad_to_int32(0);
@@ -910,47 +910,47 @@ static void xi_unregister_handlers(void)
memset(&dev, 0, sizeof(dev));
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 1);
+ assert(handler == 1);
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 2);
+ assert(handler == 2);
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 3);
+ assert(handler == 3);
- g_test_message("Unlinking from front.");
+ printf("Unlinking from front.\n");
XIUnregisterPropertyHandler(&dev, 4); /* NOOP */
- g_assert(dev.properties.handlers->id == 3);
+ assert(dev.properties.handlers->id == 3);
XIUnregisterPropertyHandler(&dev, 3);
- g_assert(dev.properties.handlers->id == 2);
+ assert(dev.properties.handlers->id == 2);
XIUnregisterPropertyHandler(&dev, 2);
- g_assert(dev.properties.handlers->id == 1);
+ assert(dev.properties.handlers->id == 1);
XIUnregisterPropertyHandler(&dev, 1);
- g_assert(dev.properties.handlers == NULL);
+ assert(dev.properties.handlers == NULL);
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 4);
+ assert(handler == 4);
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 5);
+ assert(handler == 5);
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 6);
+ assert(handler == 6);
XIUnregisterPropertyHandler(&dev, 3); /* NOOP */
- g_assert(dev.properties.handlers->next->next->next == NULL);
+ assert(dev.properties.handlers->next->next->next == NULL);
XIUnregisterPropertyHandler(&dev, 4);
- g_assert(dev.properties.handlers->next->next == NULL);
+ assert(dev.properties.handlers->next->next == NULL);
XIUnregisterPropertyHandler(&dev, 5);
- g_assert(dev.properties.handlers->next == NULL);
+ assert(dev.properties.handlers->next == NULL);
XIUnregisterPropertyHandler(&dev, 6);
- g_assert(dev.properties.handlers == NULL);
+ assert(dev.properties.handlers == NULL);
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 7);
+ assert(handler == 7);
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 8);
+ assert(handler == 8);
handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 9);
+ assert(handler == 9);
XIDeleteAllDeviceProperties(&dev);
- g_assert(dev.properties.handlers == NULL);
+ assert(dev.properties.handlers == NULL);
XIUnregisterPropertyHandler(&dev, 7); /* NOOP */
}
@@ -960,44 +960,44 @@ static void cmp_attr_fields(InputAttributes *attr1,
{
char **tags1, **tags2;
- g_assert(attr1 && attr2);
- g_assert(attr1 != attr2);
- g_assert(attr1->flags == attr2->flags);
+ assert(attr1 && attr2);
+ assert(attr1 != attr2);
+ assert(attr1->flags == attr2->flags);
if (attr1->product != NULL)
{
- g_assert(attr1->product != attr2->product);
- g_assert(strcmp(attr1->product, attr2->product) == 0);
+ assert(attr1->product != attr2->product);
+ assert(strcmp(attr1->product, attr2->product) == 0);
} else
- g_assert(attr2->product == NULL);
+ assert(attr2->product == NULL);
if (attr1->vendor != NULL)
{
- g_assert(attr1->vendor != attr2->vendor);
- g_assert(strcmp(attr1->vendor, attr2->vendor) == 0);
+ assert(attr1->vendor != attr2->vendor);
+ assert(strcmp(attr1->vendor, attr2->vendor) == 0);
} else
- g_assert(attr2->vendor == NULL);
+ assert(attr2->vendor == NULL);
if (attr1->device != NULL)
{
- g_assert(attr1->device != attr2->device);
- g_assert(strcmp(attr1->device, attr2->device) == 0);
+ assert(attr1->device != attr2->device);
+ assert(strcmp(attr1->device, attr2->device) == 0);
} else
- g_assert(attr2->device == NULL);
+ assert(attr2->device == NULL);
if (attr1->pnp_id != NULL)
{
- g_assert(attr1->pnp_id != attr2->pnp_id);
- g_assert(strcmp(attr1->pnp_id, attr2->pnp_id) == 0);
+ assert(attr1->pnp_id != attr2->pnp_id);
+ assert(strcmp(attr1->pnp_id, attr2->pnp_id) == 0);
} else
- g_assert(attr2->pnp_id == NULL);
+ assert(attr2->pnp_id == NULL);
if (attr1->usb_id != NULL)
{
- g_assert(attr1->usb_id != attr2->usb_id);
- g_assert(strcmp(attr1->usb_id, attr2->usb_id) == 0);
+ assert(attr1->usb_id != attr2->usb_id);
+ assert(strcmp(attr1->usb_id, attr2->usb_id) == 0);
} else
- g_assert(attr2->usb_id == NULL);
+ assert(attr2->usb_id == NULL);
tags1 = attr1->tags;
tags2 = attr2->tags;
@@ -1005,25 +1005,25 @@ static void cmp_attr_fields(InputAttributes *attr1,
/* if we don't have any tags, skip the tag checking bits */
if (!tags1)
{
- g_assert(!tags2);
+ assert(!tags2);
return;
}
/* Don't lug around empty arrays */
- g_assert(*tags1);
- g_assert(*tags2);
+ assert(*tags1);
+ assert(*tags2);
/* check for identical content, but duplicated */
while (*tags1)
{
- g_assert(*tags1 != *tags2);
- g_assert(strcmp(*tags1, *tags2) == 0);
+ assert(*tags1 != *tags2);
+ assert(strcmp(*tags1, *tags2) == 0);
tags1++;
tags2++;
}
/* ensure tags1 and tags2 have the same no of elements */
- g_assert(!*tags2);
+ assert(!*tags2);
/* check for not sharing memory */
tags1 = attr1->tags;
@@ -1031,7 +1031,7 @@ static void cmp_attr_fields(InputAttributes *attr1,
{
tags2 = attr2->tags;
while (*tags2)
- g_assert(*tags1 != *tags2++);
+ assert(*tags1 != *tags2++);
tags1++;
}
@@ -1044,10 +1044,10 @@ static void dix_input_attributes(void)
char *tags[4] = {"tag1", "tag2", "tag2", NULL};
new = DuplicateInputAttributes(NULL);
- g_assert(!new);
+ assert(!new);
new = DuplicateInputAttributes(&orig);
- g_assert(memcmp(&orig, new, sizeof(InputAttributes)) == 0);
+ assert(memcmp(&orig, new, sizeof(InputAttributes)) == 0);
orig.product = "product name";
new = DuplicateInputAttributes(&orig);
@@ -1097,69 +1097,69 @@ static void dix_input_valuator_masks(void)
valuators[i] = i;
mask = valuator_mask_new(nvaluators);
- g_assert(mask != NULL);
- g_assert(valuator_mask_size(mask) == 0);
- g_assert(valuator_mask_num_valuators(mask) == 0);
+ assert(mask != NULL);
+ assert(valuator_mask_size(mask) == 0);
+ assert(valuator_mask_num_valuators(mask) == 0);
for (i = 0; i < nvaluators; i++)
{
- g_assert(!valuator_mask_isset(mask, i));
+ assert(!valuator_mask_isset(mask, i));
valuator_mask_set(mask, i, valuators[i]);
- g_assert(valuator_mask_isset(mask, i));
- g_assert(valuator_mask_get(mask, i) == valuators[i]);
- g_assert(valuator_mask_size(mask) == i + 1);
- g_assert(valuator_mask_num_valuators(mask) == i + 1);
+ assert(valuator_mask_isset(mask, i));
+ assert(valuator_mask_get(mask, i) == valuators[i]);
+ assert(valuator_mask_size(mask) == i + 1);
+ assert(valuator_mask_num_valuators(mask) == i + 1);
}
for (i = 0; i < nvaluators; i++)
{
- g_assert(valuator_mask_isset(mask, i));
+ assert(valuator_mask_isset(mask, i));
valuator_mask_unset(mask, i);
/* we're removing valuators from the front, so size should stay the
* same until the last bit is removed */
if (i < nvaluators - 1)
- g_assert(valuator_mask_size(mask) == nvaluators);
- g_assert(!valuator_mask_isset(mask, i));
+ assert(valuator_mask_size(mask) == nvaluators);
+ assert(!valuator_mask_isset(mask, i));
}
- g_assert(valuator_mask_size(mask) == 0);
+ assert(valuator_mask_size(mask) == 0);
valuator_mask_zero(mask);
- g_assert(valuator_mask_size(mask) == 0);
- g_assert(valuator_mask_num_valuators(mask) == 0);
+ assert(valuator_mask_size(mask) == 0);
+ assert(valuator_mask_num_valuators(mask) == 0);
for (i = 0; i < nvaluators; i++)
- g_assert(!valuator_mask_isset(mask, i));
+ assert(!valuator_mask_isset(mask, i));
first_val = 5;
num_vals = 6;
valuator_mask_set_range(mask, first_val, num_vals, valuators);
- g_assert(valuator_mask_size(mask) == first_val + num_vals);
- g_assert(valuator_mask_num_valuators(mask) == num_vals);
+ assert(valuator_mask_size(mask) == first_val + num_vals);
+ assert(valuator_mask_num_valuators(mask) == num_vals);
for (i = 0; i < nvaluators; i++)
{
if (i < first_val || i >= first_val + num_vals)
- g_assert(!valuator_mask_isset(mask, i));
+ assert(!valuator_mask_isset(mask, i));
else
{
- g_assert(valuator_mask_isset(mask, i));
- g_assert(valuator_mask_get(mask, i) == valuators[i - first_val]);
+ assert(valuator_mask_isset(mask, i));
+ assert(valuator_mask_get(mask, i) == valuators[i - first_val]);
}
}
copy = valuator_mask_new(nvaluators);
valuator_mask_copy(copy, mask);
- g_assert(mask != copy);
- g_assert(valuator_mask_size(mask) == valuator_mask_size(copy));
- g_assert(valuator_mask_num_valuators(mask) == valuator_mask_num_valuators(copy));
+ assert(mask != copy);
+ assert(valuator_mask_size(mask) == valuator_mask_size(copy));
+ assert(valuator_mask_num_valuators(mask) == valuator_mask_num_valuators(copy));
for (i = 0; i < nvaluators; i++)
{
- g_assert(valuator_mask_isset(mask, i) == valuator_mask_isset(copy, i));
- g_assert(valuator_mask_get(mask, i) == valuator_mask_get(copy, i));
+ assert(valuator_mask_isset(mask, i) == valuator_mask_isset(copy, i));
+ assert(valuator_mask_get(mask, i) == valuator_mask_get(copy, i));
}
valuator_mask_free(&mask);
- g_assert(mask == NULL);
+ assert(mask == NULL);
}
static void dix_valuator_mode(void)
@@ -1172,24 +1172,24 @@ static void dix_valuator_mode(void)
memset(&dev, 0, sizeof(DeviceIntRec));
dev.type = MASTER_POINTER; /* claim it's a master to stop ptracccel */
- g_assert(InitValuatorClassDeviceStruct(NULL, 0, atoms, 0, 0) == FALSE);
- g_assert(InitValuatorClassDeviceStruct(&dev, num_axes, atoms, 0, Absolute));
+ assert(InitValuatorClassDeviceStruct(NULL, 0, atoms, 0, 0) == FALSE);
+ assert(InitValuatorClassDeviceStruct(&dev, num_axes, atoms, 0, Absolute));
for (i = 0; i < num_axes; i++)
{
- g_assert(valuator_get_mode(&dev, i) == Absolute);
+ assert(valuator_get_mode(&dev, i) == Absolute);
valuator_set_mode(&dev, i, Relative);
- g_assert(dev.valuator->axes[i].mode == Relative);
- g_assert(valuator_get_mode(&dev, i) == Relative);
+ assert(dev.valuator->axes[i].mode == Relative);
+ assert(valuator_get_mode(&dev, i) == Relative);
}
valuator_set_mode(&dev, VALUATOR_MODE_ALL_AXES, Absolute);
for (i = 0; i < num_axes; i++)
- g_assert(valuator_get_mode(&dev, i) == Absolute);
+ assert(valuator_get_mode(&dev, i) == Absolute);
valuator_set_mode(&dev, VALUATOR_MODE_ALL_AXES, Relative);
for (i = 0; i < num_axes; i++)
- g_assert(valuator_get_mode(&dev, i) == Relative);
+ assert(valuator_get_mode(&dev, i) == Relative);
}
static void include_bit_test_macros(void)
@@ -1199,34 +1199,53 @@ static void include_bit_test_macros(void)
for (i = 0; i < sizeof(mask)/sizeof(mask[0]); i++)
{
- g_assert(BitIsOn(mask, i) == 0);
+ assert(BitIsOn(mask, i) == 0);
SetBit(mask, i);
- g_assert(BitIsOn(mask, i) == 1);
- g_assert(!!(mask[i/8] & (1 << (i % 8))));
- g_assert(CountBits(mask, sizeof(mask)) == 1);
+ assert(BitIsOn(mask, i) == 1);
+ assert(!!(mask[i/8] & (1 << (i % 8))));
+ assert(CountBits(mask, sizeof(mask)) == 1);
ClearBit(mask, i);
- g_assert(BitIsOn(mask, i) == 0);
+ assert(BitIsOn(mask, i) == 0);
}
}
+/**
+ * Ensure that val->axisVal and val->axes are aligned on doubles.
+ */
+static void dix_valuator_alloc(void)
+{
+ ValuatorClassPtr v = NULL;
+ int num_axes = 0;
+
+ while (num_axes < 5)
+ {
+ v = AllocValuatorClass(v, num_axes);
+
+ assert(v);
+ assert(v->numAxes == num_axes);
+ assert(((void*)v->axisVal - (void*)v) % sizeof(double) == 0);
+ assert(((void*)v->axes - (void*)v) % sizeof(double) == 0);
+ num_axes ++;
+ }
+
+ free(v);
+}
+
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
- g_test_add_func("/dix/input/valuator-masks", dix_input_valuator_masks);
- g_test_add_func("/dix/input/attributes", dix_input_attributes);
- g_test_add_func("/dix/input/init-valuators", dix_init_valuators);
- g_test_add_func("/dix/input/event-core-conversion", dix_event_to_core_conversion);
- g_test_add_func("/dix/input/event-xi1-conversion", dix_event_to_xi1_conversion);
- g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values);
- g_test_add_func("/dix/input/xi2-struct-sizes", xi2_struct_sizes);
- g_test_add_func("/dix/input/grab_matching", dix_grab_matching);
- g_test_add_func("/dix/input/valuator_mode", dix_valuator_mode);
- g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
- g_test_add_func("/include/bit_test_macros", include_bit_test_macros);
- g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
-
-
- return g_test_run();
+ dix_input_valuator_masks();
+ dix_input_attributes();
+ dix_init_valuators();
+ dix_event_to_core_conversion();
+ dix_event_to_xi1_conversion();
+ dix_check_grab_values();
+ xi2_struct_sizes();
+ dix_grab_matching();
+ dix_valuator_mode();
+ include_byte_padding_macros();
+ include_bit_test_macros();
+ xi_unregister_handlers();
+ dix_valuator_alloc();
+
+ return 0;
}
diff --git a/xorg-server/test/list.c b/xorg-server/test/list.c
index 7e035fe58..b101c7619 100644
--- a/xorg-server/test/list.c
+++ b/xorg-server/test/list.c
@@ -1,176 +1,173 @@
-/**
- * Copyright © 2011 Red Hat, 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/Xlib.h>
-#include <list.h>
-#include <string.h>
-#include <glib.h>
-
-struct parent {
- int a;
- struct list children;
- int b;
-};
-
-struct child {
- int foo;
- int bar;
- struct list node;
-};
-
-static void
-test_list_init(void)
-{
- struct parent parent, tmp;
-
- memset(&parent, 0, sizeof(parent));
- parent.a = 0xa5a5a5;
- parent.b = ~0xa5a5a5;
-
- tmp = parent;
-
- list_init(&parent.children);
-
- /* test we haven't touched anything else. */
- g_assert(parent.a == tmp.a);
- g_assert(parent.b == tmp.b);
-
- g_assert(list_is_empty(&parent.children));
-}
-
-static void
-test_list_add(void)
-{
- struct parent parent = {0};
- struct child child[3];
- struct child *c;
-
- list_init(&parent.children);
-
- list_add(&child[0].node, &parent.children);
- g_assert(!list_is_empty(&parent.children));
-
- c = list_first_entry(&parent.children, struct child, node);
- g_assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
-
- /* note: list_add prepends */
- list_add(&child[1].node, &parent.children);
- c = list_first_entry(&parent.children, struct child, node);
- g_assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
-
- list_add(&child[2].node, &parent.children);
- c = list_first_entry(&parent.children, struct child, node);
- g_assert(memcmp(c, &child[2], sizeof(struct child)) == 0);
-};
-
-static void
-test_list_del(void)
-{
- struct parent parent = {0};
- struct child child[3];
- struct child *c;
-
- list_init(&parent.children);
-
- list_add(&child[0].node, &parent.children);
- g_assert(!list_is_empty(&parent.children));
-
- list_del(&parent.children);
- g_assert(list_is_empty(&parent.children));
-
- list_add(&child[0].node, &parent.children);
- list_del(&child[0].node);
- g_assert(list_is_empty(&parent.children));
-
- list_add(&child[0].node, &parent.children);
- list_add(&child[1].node, &parent.children);
-
- c = list_first_entry(&parent.children, struct child, node);
- g_assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
-
- /* delete first node */
- list_del(&child[1].node);
- g_assert(!list_is_empty(&parent.children));
- g_assert(list_is_empty(&child[1].node));
- c = list_first_entry(&parent.children, struct child, node);
- g_assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
-
- /* delete last node */
- list_add(&child[1].node, &parent.children);
- list_del(&child[0].node);
- c = list_first_entry(&parent.children, struct child, node);
- g_assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
-
- /* delete list head */
- list_add(&child[0].node, &parent.children);
- list_del(&parent.children);
- g_assert(list_is_empty(&parent.children));
- g_assert(!list_is_empty(&child[1].node));
- g_assert(!list_is_empty(&child[2].node));
-}
-
-static void
-test_list_for_each(void)
-{
- struct parent parent = {0};
- struct child child[3];
- struct child *c;
- int i = 0;
-
- list_init(&parent.children);
-
- list_add(&child[2].node, &parent.children);
- list_add(&child[1].node, &parent.children);
- list_add(&child[0].node, &parent.children);
-
- list_for_each_entry(c, &parent.children, node) {
- g_assert(memcmp(c, &child[i], sizeof(struct child)) == 0);
- i++;
- }
-
- /* foreach on empty list */
- list_del(&parent.children);
- g_assert(list_is_empty(&parent.children));
-
- list_for_each_entry(c, &parent.children, node) {
- g_assert(0); /* we must not get here */
- }
-}
-
-
-int main(int argc, char** argv)
-{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
- g_test_add_func("/list/init", test_list_init);
- g_test_add_func("/list/add", test_list_add);
- g_test_add_func("/list/del", test_list_del);
- g_test_add_func("/list/for_each", test_list_for_each);
-
- return g_test_run();
-}
+/**
+ * Copyright © 2011 Red Hat, 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <list.h>
+#include <string.h>
+#include <assert.h>
+
+struct parent {
+ int a;
+ struct list children;
+ int b;
+};
+
+struct child {
+ int foo;
+ int bar;
+ struct list node;
+};
+
+static void
+test_list_init(void)
+{
+ struct parent parent, tmp;
+
+ memset(&parent, 0, sizeof(parent));
+ parent.a = 0xa5a5a5;
+ parent.b = ~0xa5a5a5;
+
+ tmp = parent;
+
+ list_init(&parent.children);
+
+ /* test we haven't touched anything else. */
+ assert(parent.a == tmp.a);
+ assert(parent.b == tmp.b);
+
+ assert(list_is_empty(&parent.children));
+}
+
+static void
+test_list_add(void)
+{
+ struct parent parent = {0};
+ struct child child[3];
+ struct child *c;
+
+ list_init(&parent.children);
+
+ list_add(&child[0].node, &parent.children);
+ assert(!list_is_empty(&parent.children));
+
+ c = list_first_entry(&parent.children, struct child, node);
+ assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
+
+ /* note: list_add prepends */
+ list_add(&child[1].node, &parent.children);
+ c = list_first_entry(&parent.children, struct child, node);
+ assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
+
+ list_add(&child[2].node, &parent.children);
+ c = list_first_entry(&parent.children, struct child, node);
+ assert(memcmp(c, &child[2], sizeof(struct child)) == 0);
+};
+
+static void
+test_list_del(void)
+{
+ struct parent parent = {0};
+ struct child child[3];
+ struct child *c;
+
+ list_init(&parent.children);
+
+ list_add(&child[0].node, &parent.children);
+ assert(!list_is_empty(&parent.children));
+
+ list_del(&parent.children);
+ assert(list_is_empty(&parent.children));
+
+ list_add(&child[0].node, &parent.children);
+ list_del(&child[0].node);
+ assert(list_is_empty(&parent.children));
+
+ list_add(&child[0].node, &parent.children);
+ list_add(&child[1].node, &parent.children);
+
+ c = list_first_entry(&parent.children, struct child, node);
+ assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
+
+ /* delete first node */
+ list_del(&child[1].node);
+ assert(!list_is_empty(&parent.children));
+ assert(list_is_empty(&child[1].node));
+ c = list_first_entry(&parent.children, struct child, node);
+ assert(memcmp(c, &child[0], sizeof(struct child)) == 0);
+
+ /* delete last node */
+ list_add(&child[1].node, &parent.children);
+ list_del(&child[0].node);
+ c = list_first_entry(&parent.children, struct child, node);
+ assert(memcmp(c, &child[1], sizeof(struct child)) == 0);
+
+ /* delete list head */
+ list_add(&child[0].node, &parent.children);
+ list_del(&parent.children);
+ assert(list_is_empty(&parent.children));
+ assert(!list_is_empty(&child[1].node));
+ assert(!list_is_empty(&child[2].node));
+}
+
+static void
+test_list_for_each(void)
+{
+ struct parent parent = {0};
+ struct child child[3];
+ struct child *c;
+ int i = 0;
+
+ list_init(&parent.children);
+
+ list_add(&child[2].node, &parent.children);
+ list_add(&child[1].node, &parent.children);
+ list_add(&child[0].node, &parent.children);
+
+ list_for_each_entry(c, &parent.children, node) {
+ assert(memcmp(c, &child[i], sizeof(struct child)) == 0);
+ i++;
+ }
+
+ /* foreach on empty list */
+ list_del(&parent.children);
+ assert(list_is_empty(&parent.children));
+
+ list_for_each_entry(c, &parent.children, node) {
+ assert(0); /* we must not get here */
+ }
+}
+
+
+int main(int argc, char** argv)
+{
+ test_list_init();
+ test_list_add();
+ test_list_del();
+ test_list_for_each();
+
+ return 0;
+}
diff --git a/xorg-server/test/xi2/Makefile.am b/xorg-server/test/xi2/Makefile.am
index 1b9bfe08e..b15d8ba02 100644
--- a/xorg-server/test/xi2/Makefile.am
+++ b/xorg-server/test/xi2/Makefile.am
@@ -1,5 +1,4 @@
if ENABLE_UNIT_TESTS
-if HAVE_GLIB
if HAVE_LD_WRAP
noinst_PROGRAMS = \
protocol-xiqueryversion \
@@ -8,15 +7,16 @@ noinst_PROGRAMS = \
protocol-xigetselectedevents \
protocol-xisetclientpointer \
protocol-xigetclientpointer \
+ protocol-xipassivegrabdevice \
protocol-xiquerypointer \
protocol-xiwarppointer \
protocol-eventconvert
TESTS=$(noinst_PROGRAMS)
-AM_CFLAGS = $(DIX_CFLAGS) $(GLIB_CFLAGS) @XORG_CFLAGS@
+AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
INCLUDES = @XORG_INCS@
-TEST_LDADD=../libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLIB_LIBS)
+TEST_LDADD=../libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS)
COMMON_SOURCES=protocol-common.h protocol-common.c
if SPECIAL_DTRACE_OBJECTS
@@ -30,6 +30,7 @@ protocol_xigetselectedevents_LDADD=$(TEST_LDADD)
protocol_xisetclientpointer_LDADD=$(TEST_LDADD)
protocol_xigetclientpointer_LDADD=$(TEST_LDADD)
protocol_xiquerypointer_LDADD=$(TEST_LDADD)
+protocol_xipassivegrabdevice_LDADD=$(TEST_LDADD)
protocol_xiwarppointer_LDADD=$(TEST_LDADD)
protocol_eventconvert_LDADD=$(TEST_LDADD)
@@ -39,6 +40,7 @@ protocol_xiselectevents_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,dixLookupWindow -Wl,-wra
protocol_xigetselectedevents_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow -Wl,-wrap,AddResource
protocol_xisetclientpointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,dixLookupClient
protocol_xigetclientpointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupClient
+protocol_xipassivegrabdevice_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,GrabButton -Wl,-wrap,dixLookupWindow -Wl,-wrap,WriteToClient
protocol_xiquerypointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow
protocol_xiwarppointer_LDFLAGS=$(AM_LDFLAGS) -Wl,-wrap,WriteToClient -Wl,-wrap,dixLookupWindow
@@ -49,7 +51,7 @@ protocol_xigetselectedevents_SOURCES=$(COMMON_SOURCES) protocol-xigetselectedeve
protocol_xisetclientpointer_SOURCES=$(COMMON_SOURCES) protocol-xisetclientpointer.c
protocol_xigetclientpointer_SOURCES=$(COMMON_SOURCES) protocol-xigetclientpointer.c
protocol_xiquerypointer_SOURCES=$(COMMON_SOURCES) protocol-xiquerypointer.c
+protocol_xipassivegrabdevice_SOURCES=$(COMMON_SOURCES) protocol-xipassivegrabdevice.c
protocol_xiwarppointer_SOURCES=$(COMMON_SOURCES) protocol-xiwarppointer.c
endif
endif
-endif
diff --git a/xorg-server/test/xi2/protocol-common.c b/xorg-server/test/xi2/protocol-common.c
index 86a7201b8..6ffc69721 100644
--- a/xorg-server/test/xi2/protocol-common.c
+++ b/xorg-server/test/xi2/protocol-common.c
@@ -1,178 +1,177 @@
-/**
- * Copyright © 2009 Red Hat, 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdint.h>
-#include "extinit.h" /* for XInputExtensionInit */
-#include "exglobals.h"
-#include "xkbsrv.h" /* for XkbInitPrivates */
-#include <glib.h>
-
-#include "protocol-common.h"
-
-struct devices devices;
-ScreenRec screen;
-WindowRec root;
-WindowRec window;
-
-void *userdata;
-
-extern int CorePointerProc(DeviceIntPtr pDev, int what);
-extern int CoreKeyboardProc(DeviceIntPtr pDev, int what);
-
-static void fake_init_sprite(DeviceIntPtr dev)
-{
- SpritePtr sprite;
- sprite = dev->spriteInfo->sprite;
-
- sprite->spriteTraceSize = 10;
- sprite->spriteTrace = calloc(sprite->spriteTraceSize, sizeof(WindowPtr));
- sprite->spriteTraceGood = 1;
- sprite->spriteTrace[0] = &root;
- sprite->hot.x = SPRITE_X;
- sprite->hot.y = SPRITE_Y;
- sprite->hotPhys.x = sprite->hot.x;
- sprite->hotPhys.y = sprite->hot.y;
- sprite->win = &window;
- sprite->hotPhys.pScreen = &screen;
- sprite->physLimits.x1 = 0;
- sprite->physLimits.y1 = 0;
- sprite->physLimits.x2 = screen.width;
- sprite->physLimits.y2 = screen.height;
-}
-
-/**
- * Create and init 2 master devices (VCP + VCK) and two slave devices, one
- * default mouse, one default keyboard.
- */
-struct devices init_devices(void)
-{
- ClientRec client;
- struct devices devices;
-
- client = init_client(0, NULL);
-
- AllocDevicePair(&client, "Virtual core", &devices.vcp, &devices.vck,
- CorePointerProc, CoreKeyboardProc, TRUE);
- inputInfo.pointer = devices.vcp;
- inputInfo.keyboard = devices.vck;
- ActivateDevice(devices.vcp, FALSE);
- ActivateDevice(devices.vck, FALSE);
- EnableDevice(devices.vcp, FALSE);
- EnableDevice(devices.vck, FALSE);
-
- AllocDevicePair(&client, "", &devices.mouse, &devices.kbd,
- CorePointerProc, CoreKeyboardProc, FALSE);
- ActivateDevice(devices.mouse, FALSE);
- ActivateDevice(devices.kbd, FALSE);
- EnableDevice(devices.mouse, FALSE);
- EnableDevice(devices.kbd, FALSE);
-
- devices.num_devices = 4;
- devices.num_master_devices = 2;
-
- fake_init_sprite(devices.mouse);
- fake_init_sprite(devices.vcp);
-
- return devices;
-}
-
-
-/* Create minimal client, with the given buffer and len as request buffer */
-ClientRec init_client(int len, void *data)
-{
- ClientRec client = { 0 };
-
- /* we store the privates now and reassign it after the memset. this way
- * we can share them across multiple test runs and don't have to worry
- * about freeing them after each test run. */
-
- client.index = CLIENT_INDEX;
- client.clientAsMask = CLIENT_MASK;
- client.sequence = CLIENT_SEQUENCE;
- client.req_len = len;
-
- client.requestBuffer = data;
- dixAllocatePrivates(&client.devPrivates, PRIVATE_CLIENT);
- return client;
-}
-
-void init_window(WindowPtr window, WindowPtr parent, int id)
-{
- memset(window, 0, sizeof(window));
-
- window->drawable.id = id;
- if (parent)
- {
- window->drawable.x = 30;
- window->drawable.y = 50;
- window->drawable.width = 100;
- window->drawable.height = 200;
- }
- window->parent = parent;
- window->optional = calloc(1, sizeof(WindowOptRec));
- g_assert(window->optional);
-}
-
-extern DevPrivateKeyRec miPointerScreenKeyRec;
-extern DevPrivateKeyRec miPointerPrivKeyRec;
-
-/* Needed for the screen setup, otherwise we crash during sprite initialization */
-static Bool device_cursor_init(DeviceIntPtr dev, ScreenPtr screen) { return TRUE; }
-static Bool set_cursor_pos(DeviceIntPtr dev, ScreenPtr screen, int x, int y, Bool event) { return TRUE; }
-void init_simple(void)
-{
- screenInfo.numScreens = 1;
- screenInfo.screens[0] = &screen;
-
- screen.myNum = 0;
- screen.id = 100;
- screen.width = 640;
- screen.height = 480;
- screen.DeviceCursorInitialize = device_cursor_init;
- screen.SetCursorPosition = set_cursor_pos;
-
- dixResetPrivates();
- InitAtoms();
- XkbInitPrivates();
- dixRegisterPrivateKey(&XIClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(XIClientRec));
- dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0);
- dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0);
- XInputExtensionInit();
-
- init_window(&root, NULL, ROOT_WINDOW_ID);
- init_window(&window, &root, CLIENT_WINDOW_ID);
-
- devices = init_devices();
-}
-
-void __wrap_WriteToClient(ClientPtr client, int len, void *data)
-{
- g_assert(reply_handler != NULL);
-
- (*reply_handler)(client, len, data, userdata);
-}
-
+/**
+ * Copyright © 2009 Red Hat, 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdint.h>
+#include "extinit.h" /* for XInputExtensionInit */
+#include "exglobals.h"
+#include "xkbsrv.h" /* for XkbInitPrivates */
+
+#include "protocol-common.h"
+
+struct devices devices;
+ScreenRec screen;
+WindowRec root;
+WindowRec window;
+
+void *userdata;
+
+extern int CorePointerProc(DeviceIntPtr pDev, int what);
+extern int CoreKeyboardProc(DeviceIntPtr pDev, int what);
+
+static void fake_init_sprite(DeviceIntPtr dev)
+{
+ SpritePtr sprite;
+ sprite = dev->spriteInfo->sprite;
+
+ sprite->spriteTraceSize = 10;
+ sprite->spriteTrace = calloc(sprite->spriteTraceSize, sizeof(WindowPtr));
+ sprite->spriteTraceGood = 1;
+ sprite->spriteTrace[0] = &root;
+ sprite->hot.x = SPRITE_X;
+ sprite->hot.y = SPRITE_Y;
+ sprite->hotPhys.x = sprite->hot.x;
+ sprite->hotPhys.y = sprite->hot.y;
+ sprite->win = &window;
+ sprite->hotPhys.pScreen = &screen;
+ sprite->physLimits.x1 = 0;
+ sprite->physLimits.y1 = 0;
+ sprite->physLimits.x2 = screen.width;
+ sprite->physLimits.y2 = screen.height;
+}
+
+/**
+ * Create and init 2 master devices (VCP + VCK) and two slave devices, one
+ * default mouse, one default keyboard.
+ */
+struct devices init_devices(void)
+{
+ ClientRec client;
+ struct devices devices;
+
+ client = init_client(0, NULL);
+
+ AllocDevicePair(&client, "Virtual core", &devices.vcp, &devices.vck,
+ CorePointerProc, CoreKeyboardProc, TRUE);
+ inputInfo.pointer = devices.vcp;
+ inputInfo.keyboard = devices.vck;
+ ActivateDevice(devices.vcp, FALSE);
+ ActivateDevice(devices.vck, FALSE);
+ EnableDevice(devices.vcp, FALSE);
+ EnableDevice(devices.vck, FALSE);
+
+ AllocDevicePair(&client, "", &devices.mouse, &devices.kbd,
+ CorePointerProc, CoreKeyboardProc, FALSE);
+ ActivateDevice(devices.mouse, FALSE);
+ ActivateDevice(devices.kbd, FALSE);
+ EnableDevice(devices.mouse, FALSE);
+ EnableDevice(devices.kbd, FALSE);
+
+ devices.num_devices = 4;
+ devices.num_master_devices = 2;
+
+ fake_init_sprite(devices.mouse);
+ fake_init_sprite(devices.vcp);
+
+ return devices;
+}
+
+
+/* Create minimal client, with the given buffer and len as request buffer */
+ClientRec init_client(int len, void *data)
+{
+ ClientRec client = { 0 };
+
+ /* we store the privates now and reassign it after the memset. this way
+ * we can share them across multiple test runs and don't have to worry
+ * about freeing them after each test run. */
+
+ client.index = CLIENT_INDEX;
+ client.clientAsMask = CLIENT_MASK;
+ client.sequence = CLIENT_SEQUENCE;
+ client.req_len = len;
+
+ client.requestBuffer = data;
+ dixAllocatePrivates(&client.devPrivates, PRIVATE_CLIENT);
+ return client;
+}
+
+void init_window(WindowPtr window, WindowPtr parent, int id)
+{
+ memset(window, 0, sizeof(window));
+
+ window->drawable.id = id;
+ if (parent)
+ {
+ window->drawable.x = 30;
+ window->drawable.y = 50;
+ window->drawable.width = 100;
+ window->drawable.height = 200;
+ }
+ window->parent = parent;
+ window->optional = calloc(1, sizeof(WindowOptRec));
+ assert(window->optional);
+}
+
+extern DevPrivateKeyRec miPointerScreenKeyRec;
+extern DevPrivateKeyRec miPointerPrivKeyRec;
+
+/* Needed for the screen setup, otherwise we crash during sprite initialization */
+static Bool device_cursor_init(DeviceIntPtr dev, ScreenPtr screen) { return TRUE; }
+static Bool set_cursor_pos(DeviceIntPtr dev, ScreenPtr screen, int x, int y, Bool event) { return TRUE; }
+void init_simple(void)
+{
+ screenInfo.numScreens = 1;
+ screenInfo.screens[0] = &screen;
+
+ screen.myNum = 0;
+ screen.id = 100;
+ screen.width = 640;
+ screen.height = 480;
+ screen.DeviceCursorInitialize = device_cursor_init;
+ screen.SetCursorPosition = set_cursor_pos;
+
+ dixResetPrivates();
+ InitAtoms();
+ XkbInitPrivates();
+ dixRegisterPrivateKey(&XIClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(XIClientRec));
+ dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0);
+ dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0);
+ XInputExtensionInit();
+
+ init_window(&root, NULL, ROOT_WINDOW_ID);
+ init_window(&window, &root, CLIENT_WINDOW_ID);
+
+ devices = init_devices();
+}
+
+void __wrap_WriteToClient(ClientPtr client, int len, void *data)
+{
+ assert(reply_handler != NULL);
+
+ (*reply_handler)(client, len, data, userdata);
+}
+
diff --git a/xorg-server/test/xi2/protocol-common.h b/xorg-server/test/xi2/protocol-common.h
index afa08780c..18c61e62a 100644
--- a/xorg-server/test/xi2/protocol-common.h
+++ b/xorg-server/test/xi2/protocol-common.h
@@ -29,6 +29,7 @@
#include "windowstr.h"
#include "scrnintstr.h"
#include "exevents.h"
+#include <assert.h>
#ifndef PROTOCOL_COMMON_H
#define PROTOCOL_COMMON_H
@@ -38,11 +39,11 @@ extern int BadDevice;
/* Check default values in a reply */
#define reply_check_defaults(rep, len, type) \
{ \
- g_assert((len) >= sz_x##type##Reply); \
- g_assert((rep)->repType == X_Reply); \
- g_assert((rep)->RepType == X_##type); \
- g_assert((rep)->sequenceNumber == CLIENT_SEQUENCE); \
- g_assert((rep)->length >= (sz_x##type##Reply - 32)/4); \
+ assert((len) >= sz_x##type##Reply); \
+ assert((rep)->repType == X_Reply); \
+ assert((rep)->RepType == X_##type); \
+ assert((rep)->sequenceNumber == CLIENT_SEQUENCE); \
+ assert((rep)->length >= (sz_x##type##Reply - 32)/4); \
}
/* initialise default values for request */
diff --git a/xorg-server/test/xi2/protocol-eventconvert.c b/xorg-server/test/xi2/protocol-eventconvert.c
index 0478c33fe..edba974bf 100644
--- a/xorg-server/test/xi2/protocol-eventconvert.c
+++ b/xorg-server/test/xi2/protocol-eventconvert.c
@@ -25,7 +25,6 @@
#endif
#include <stdint.h>
-#include <glib.h>
#include "inputstr.h"
#include "eventstr.h"
@@ -33,7 +32,6 @@
#include "exevents.h"
#include <X11/extensions/XI2proto.h>
-
static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
BOOL swap)
{
@@ -58,21 +56,21 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
}
- g_assert(out->type == GenericEvent);
- g_assert(out->extension == 0); /* IReqCode defaults to 0 */
- g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
- g_assert(out->time == in->time);
- g_assert(out->detail == in->detail.button);
- g_assert(out->deviceid == in->deviceid);
- g_assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(sizeof(in->valuators.mask))));
- g_assert(out->flags == 0); /* FIXME: we don't set the flags yet */
+ assert(out->type == GenericEvent);
+ assert(out->extension == 0); /* IReqCode defaults to 0 */
+ assert(out->evtype == GetXI2Type((InternalEvent*)in));
+ assert(out->time == in->time);
+ assert(out->detail == in->detail.button);
+ assert(out->deviceid == in->deviceid);
+ assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(sizeof(in->valuators.mask))));
+ assert(out->flags == 0); /* FIXME: we don't set the flags yet */
ptr = (unsigned char*)&out[1];
bits_set = 0;
for (i = 0; out->valuators_len && i < sizeof(in->valuators.mask) * 8; i++)
{
- g_assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
+ assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
if (XIMaskIsSet(in->valuators.mask, i))
bits_set++;
}
@@ -81,13 +79,13 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
* set. Each bit set represents 2 8-byte values, hence the
* 'bits_set * 4' */
len = out->valuators_len + bits_set * 4;
- g_assert(out->length == len);
+ assert(out->length == len);
nvals = 0;
for (i = 0; out->valuators_len && i < MAX_VALUATORS; i++)
{
- g_assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
+ assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
if (XIMaskIsSet(in->valuators.mask, i))
{
FP3232 vi, vo;
@@ -106,8 +104,8 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
swapl(&vo.frac, n);
}
- g_assert(vi.integral == vo.integral);
- g_assert(vi.frac == vo.frac);
+ assert(vi.integral == vo.integral);
+ assert(vi.frac == vo.frac);
raw_value = value + bits_set;
@@ -123,8 +121,8 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
swapl(&vo.frac, n);
}
- g_assert(vi.integral == vo.integral);
- g_assert(vi.frac == vo.frac);
+ assert(vi.integral == vo.integral);
+ assert(vi.frac == vo.frac);
nvals++;
}
@@ -137,7 +135,7 @@ static void test_XIRawEvent(RawDeviceEvent *in)
int rc;
rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
- g_assert(rc == Success);
+ assert(rc == Success);
test_values_XIRawEvent(in, out, FALSE);
@@ -158,24 +156,24 @@ static void test_convert_XIFocusEvent(void)
in.header = ET_Internal;
in.type = ET_Enter;
rc = EventToXI2((InternalEvent*)&in, &out);
- g_assert(rc == Success);
- g_assert(out == NULL);
+ assert(rc == Success);
+ assert(out == NULL);
in.header = ET_Internal;
in.type = ET_FocusIn;
rc = EventToXI2((InternalEvent*)&in, &out);
- g_assert(rc == Success);
- g_assert(out == NULL);
+ assert(rc == Success);
+ assert(out == NULL);
in.header = ET_Internal;
in.type = ET_FocusOut;
rc = EventToXI2((InternalEvent*)&in, &out);
- g_assert(rc == BadImplementation);
+ assert(rc == BadImplementation);
in.header = ET_Internal;
in.type = ET_Leave;
rc = EventToXI2((InternalEvent*)&in, &out);
- g_assert(rc == BadImplementation);
+ assert(rc == BadImplementation);
}
@@ -186,7 +184,7 @@ static void test_convert_XIRawEvent(void)
memset(&in, 0, sizeof(in));
- g_test_message("Testing all event types");
+ printf("Testing all event types\n");
in.header = ET_Internal;
in.type = ET_RawMotion;
test_XIRawEvent(&in);
@@ -207,7 +205,7 @@ static void test_convert_XIRawEvent(void)
in.type = ET_RawButtonRelease;
test_XIRawEvent(&in);
- g_test_message("Testing details and other fields");
+ printf("Testing details and other fields\n");
in.detail.button = 1L;
test_XIRawEvent(&in);
in.detail.button = 1L << 8;
@@ -239,7 +237,7 @@ static void test_convert_XIRawEvent(void)
in.deviceid = ~0 & 0xFF;
test_XIRawEvent(&in);
- g_test_message("Testing valuator masks");
+ printf("Testing valuator masks\n");
for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
{
XISetMask(in.valuators.mask, i);
@@ -301,14 +299,14 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
swapl(&out->flags, n);
}
- g_assert(out->extension == 0); /* IReqCode defaults to 0 */
- g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
- g_assert(out->time == in->time);
- g_assert(out->detail == in->detail.button);
- g_assert(out->length >= 12);
+ assert(out->extension == 0); /* IReqCode defaults to 0 */
+ assert(out->evtype == GetXI2Type((InternalEvent*)in));
+ assert(out->time == in->time);
+ assert(out->detail == in->detail.button);
+ assert(out->length >= 12);
- g_assert(out->deviceid == in->deviceid);
- g_assert(out->sourceid == in->sourceid);
+ assert(out->deviceid == in->deviceid);
+ assert(out->sourceid == in->sourceid);
switch (in->type) {
case ET_KeyPress:
@@ -318,41 +316,41 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
flagmask = 0;
break;
}
- g_assert((out->flags & ~flagmask) == 0);
+ assert((out->flags & ~flagmask) == 0);
- g_assert(out->root == in->root);
- g_assert(out->event == None); /* set in FixUpEventFromWindow */
- g_assert(out->child == None); /* set in FixUpEventFromWindow */
+ assert(out->root == in->root);
+ assert(out->event == None); /* set in FixUpEventFromWindow */
+ assert(out->child == None); /* set in FixUpEventFromWindow */
- g_assert(out->mods.base_mods == in->mods.base);
- g_assert(out->mods.latched_mods == in->mods.latched);
- g_assert(out->mods.locked_mods == in->mods.locked);
- g_assert(out->mods.effective_mods == in->mods.effective);
+ assert(out->mods.base_mods == in->mods.base);
+ assert(out->mods.latched_mods == in->mods.latched);
+ assert(out->mods.locked_mods == in->mods.locked);
+ assert(out->mods.effective_mods == in->mods.effective);
- g_assert(out->group.base_group == in->group.base);
- g_assert(out->group.latched_group == in->group.latched);
- g_assert(out->group.locked_group == in->group.locked);
- g_assert(out->group.effective_group == in->group.effective);
+ assert(out->group.base_group == in->group.base);
+ assert(out->group.latched_group == in->group.latched);
+ assert(out->group.locked_group == in->group.locked);
+ assert(out->group.effective_group == in->group.effective);
- g_assert(out->event_x == 0); /* set in FixUpEventFromWindow */
- g_assert(out->event_y == 0); /* set in FixUpEventFromWindow */
+ assert(out->event_x == 0); /* set in FixUpEventFromWindow */
+ assert(out->event_y == 0); /* set in FixUpEventFromWindow */
- g_assert(out->root_x == FP1616(in->root_x, in->root_x_frac));
- g_assert(out->root_y == FP1616(in->root_y, in->root_y_frac));
+ assert(out->root_x == FP1616(in->root_x, in->root_x_frac));
+ assert(out->root_y == FP1616(in->root_y, in->root_y_frac));
buttons = 0;
for (i = 0; i < bits_to_bytes(sizeof(in->buttons)); i++)
{
if (XIMaskIsSet(in->buttons, i))
{
- g_assert(out->buttons_len >= bytes_to_int32(bits_to_bytes(i)));
+ assert(out->buttons_len >= bytes_to_int32(bits_to_bytes(i)));
buttons++;
}
}
ptr = (unsigned char*)&out[1];
for (i = 0; i < sizeof(in->buttons) * 8; i++)
- g_assert(XIMaskIsSet(in->buttons, i) == XIMaskIsSet(ptr, i));
+ assert(XIMaskIsSet(in->buttons, i) == XIMaskIsSet(ptr, i));
valuators = 0;
@@ -360,7 +358,7 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
if (XIMaskIsSet(in->valuators.mask, i))
valuators++;
- g_assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(valuators)));
+ assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(valuators)));
ptr += out->buttons_len * 4;
values = (FP3232*)(ptr + out->valuators_len * 4);
@@ -368,11 +366,11 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
i < (out->valuators_len * 4) * 8; i++)
{
if (i > sizeof(in->valuators.mask) * 8)
- g_assert(!XIMaskIsSet(ptr, i));
+ assert(!XIMaskIsSet(ptr, i));
else if (i > out->valuators_len * 4 * 8)
- g_assert(!XIMaskIsSet(in->valuators.mask, i));
+ assert(!XIMaskIsSet(in->valuators.mask, i));
else {
- g_assert(XIMaskIsSet(in->valuators.mask, i) ==
+ assert(XIMaskIsSet(in->valuators.mask, i) ==
XIMaskIsSet(ptr, i));
if (XIMaskIsSet(ptr, i))
@@ -392,8 +390,8 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
}
- g_assert(vi.integral == vo.integral);
- g_assert(vi.frac == vo.frac);
+ assert(vi.integral == vo.integral);
+ assert(vi.frac == vo.frac);
values++;
}
}
@@ -406,7 +404,7 @@ static void test_XIDeviceEvent(DeviceEvent *in)
int rc;
rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
- g_assert(rc == Success);
+ assert(rc == Success);
test_values_XIDeviceEvent(in, out, FALSE);
@@ -425,7 +423,7 @@ static void test_convert_XIDeviceEvent(void)
memset(&in, 0, sizeof(in));
- g_test_message("Testing simple field values");
+ printf("Testing simple field values\n");
in.header = ET_Internal;
in.type = ET_Motion;
in.length = sizeof(DeviceEvent);
@@ -449,7 +447,7 @@ static void test_convert_XIDeviceEvent(void)
test_XIDeviceEvent(&in);
- g_test_message("Testing field ranges");
+ printf("Testing field ranges\n");
/* 32 bit */
in.detail.button = 1L;
test_XIDeviceEvent(&in);
@@ -597,7 +595,7 @@ static void test_convert_XIDeviceEvent(void)
in.mods.effective = ~0 & 0xFF;
test_XIDeviceEvent(&in);
- g_test_message("Testing button masks");
+ printf("Testing button masks\n");
for (i = 0; i < sizeof(in.buttons) * 8; i++)
{
XISetMask(in.buttons, i);
@@ -611,7 +609,7 @@ static void test_convert_XIDeviceEvent(void)
test_XIDeviceEvent(&in);
}
- g_test_message("Testing valuator masks");
+ printf("Testing valuator masks\n");
for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
{
XISetMask(in.valuators.mask, i);
@@ -656,12 +654,12 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
swaps(&out->num_classes, n);
}
- g_assert(out->type == GenericEvent);
- g_assert(out->extension == 0); /* IReqCode defaults to 0 */
- g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
- g_assert(out->time == in->time);
- g_assert(out->deviceid == in->deviceid);
- g_assert(out->sourceid == in->sourceid);
+ assert(out->type == GenericEvent);
+ assert(out->extension == 0); /* IReqCode defaults to 0 */
+ assert(out->evtype == GetXI2Type((InternalEvent*)in));
+ assert(out->time == in->time);
+ assert(out->deviceid == in->deviceid);
+ assert(out->sourceid == in->sourceid);
ptr = (unsigned char*)&out[1];
for (i = 0; i < out->num_classes; i++)
@@ -689,11 +687,11 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
swaps(&b->num_buttons, n);
}
- g_assert(b->length ==
+ assert(b->length ==
bytes_to_int32(sizeof(xXIButtonInfo)) +
bytes_to_int32(bits_to_bytes(b->num_buttons)) +
b->num_buttons);
- g_assert(b->num_buttons == in->buttons.num_buttons);
+ assert(b->num_buttons == in->buttons.num_buttons);
names = (Atom*)((char*)&b[1] +
pad_to_int32(bits_to_bytes(b->num_buttons)));
@@ -704,7 +702,7 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
char n;
swapl(&names[j], n);
}
- g_assert(names[j] == in->buttons.names[j]);
+ assert(names[j] == in->buttons.names[j]);
}
}
break;
@@ -719,10 +717,10 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
swaps(&k->num_keycodes, n);
}
- g_assert(k->length ==
+ assert(k->length ==
bytes_to_int32(sizeof(xXIKeyInfo)) +
k->num_keycodes);
- g_assert(k->num_keycodes == in->keys.max_keycode -
+ assert(k->num_keycodes == in->keys.max_keycode -
in->keys.min_keycode + 1);
kc = (uint32_t*)&k[1];
@@ -733,21 +731,22 @@ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
char n;
swapl(&kc[j], n);
}
- g_assert(kc[j] >= in->keys.min_keycode);
- g_assert(kc[j] <= in->keys.max_keycode);
+ assert(kc[j] >= in->keys.min_keycode);
+ assert(kc[j] <= in->keys.max_keycode);
}
}
break;
case XIValuatorClass:
{
xXIValuatorInfo *v = (xXIValuatorInfo*)any;
- g_assert(v->length ==
+ assert(v->length ==
bytes_to_int32(sizeof(xXIValuatorInfo)));
}
break;
default:
- g_error("Invalid class type.\n");
+ printf("Invalid class type.\n\n");
+ assert(1);
break;
}
@@ -762,7 +761,7 @@ static void test_XIDeviceChangedEvent(DeviceChangedEvent *in)
int rc;
rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
- g_assert(rc == Success);
+ assert(rc == Success);
test_values_XIDeviceChangedEvent(in, out, FALSE);
@@ -779,7 +778,7 @@ static void test_convert_XIDeviceChangedEvent(void)
DeviceChangedEvent in;
int i;
- g_test_message("Testing simple field values");
+ printf("Testing simple field values\n");
memset(&in, 0, sizeof(in));
in.header = ET_Internal;
in.type = ET_DeviceChanged;
@@ -905,13 +904,10 @@ static void test_convert_XIDeviceChangedEvent(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
- g_test_add_func("/xi2/eventconvert/XIRawEvent", test_convert_XIRawEvent);
- g_test_add_func("/xi2/eventconvert/XIFocusEvent", test_convert_XIFocusEvent);
- g_test_add_func("/xi2/eventconvert/XIDeviceEvent", test_convert_XIDeviceEvent);
- g_test_add_func("/xi2/eventconvert/XIDeviceChangedEvent", test_convert_XIDeviceChangedEvent);
+ test_convert_XIRawEvent();
+ test_convert_XIFocusEvent();
+ test_convert_XIDeviceEvent();
+ test_convert_XIDeviceChangedEvent();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xi2/protocol-xigetclientpointer.c b/xorg-server/test/xi2/protocol-xigetclientpointer.c
index 6b4d04957..5e45e7b32 100644
--- a/xorg-server/test/xi2/protocol-xigetclientpointer.c
+++ b/xorg-server/test/xi2/protocol-xigetclientpointer.c
@@ -39,7 +39,6 @@
#include "exevents.h"
#include "protocol-common.h"
-#include <glib.h>
struct {
int cp_is_set;
@@ -79,9 +78,9 @@ static void reply_XIGetClientPointer(ClientPtr client, int len, char *data, void
reply_check_defaults(rep, len, XIGetClientPointer);
- g_assert(rep->set == test_data.cp_is_set);
+ assert(rep->set == test_data.cp_is_set);
if (rep->set)
- g_assert(rep->deviceid == test_data.dev->id);
+ assert(rep->deviceid == test_data.dev->id);
}
static void request_XIGetClientPointer(ClientPtr client, xXIGetClientPointerReq* req, int error)
@@ -92,19 +91,19 @@ static void request_XIGetClientPointer(ClientPtr client, xXIGetClientPointerReq*
test_data.win = req->win;
rc = ProcXIGetClientPointer(&client_request);
- g_assert(rc == error);
+ assert(rc == error);
if (rc == BadWindow)
- g_assert(client_request.errorValue == req->win);
+ assert(client_request.errorValue == req->win);
client_request.swapped = TRUE;
swapl(&req->win, n);
swaps(&req->length, n);
rc = SProcXIGetClientPointer(&client_request);
- g_assert(rc == error);
+ assert(rc == error);
if (rc == BadWindow)
- g_assert(client_request.errorValue == req->win);
+ assert(client_request.errorValue == req->win);
}
@@ -121,21 +120,21 @@ static void test_XIGetClientPointer(void)
client_request = init_client(request.length, &request);
- g_test_message("Testing invalid window");
+ printf("Testing invalid window\n");
request.win = INVALID_WINDOW_ID;
request_XIGetClientPointer(&client_request, &request, BadWindow);
test_data.cp_is_set = FALSE;
- g_test_message("Testing window None, unset ClientPointer.");
+ printf("Testing window None, unset ClientPointer.\n");
request.win = None;
request_XIGetClientPointer(&client_request, &request, Success);
- g_test_message("Testing valid window, unset ClientPointer.");
+ printf("Testing valid window, unset ClientPointer.\n");
request.win = CLIENT_WINDOW_ID;
request_XIGetClientPointer(&client_request, &request, Success);
- g_test_message("Testing valid window, set ClientPointer.");
+ printf("Testing valid window, set ClientPointer.\n");
client_window.clientPtr = devices.vcp;
test_data.dev = devices.vcp;
test_data.cp_is_set = TRUE;
@@ -144,7 +143,7 @@ static void test_XIGetClientPointer(void)
client_window.clientPtr = NULL;
- g_test_message("Testing window None, set ClientPointer.");
+ printf("Testing window None, set ClientPointer.\n");
client_request.clientPtr = devices.vcp;
test_data.dev = devices.vcp;
test_data.cp_is_set = TRUE;
@@ -154,14 +153,10 @@ static void test_XIGetClientPointer(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
init_simple();
client_window = init_client(0, NULL);
+ test_XIGetClientPointer();
- g_test_add_func("/xi2/protocol/XIGetClientPointer", test_XIGetClientPointer);
-
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xi2/protocol-xigetselectedevents.c b/xorg-server/test/xi2/protocol-xigetselectedevents.c
index 97aae159f..55de77356 100644
--- a/xorg-server/test/xi2/protocol-xigetselectedevents.c
+++ b/xorg-server/test/xi2/protocol-xigetselectedevents.c
@@ -48,7 +48,6 @@
#include "exevents.h"
#include "protocol-common.h"
-#include <glib.h>
static void reply_XIGetSelectedEvents(ClientPtr client, int len, char *data, void *userdata);
static void reply_XIGetSelectedEvents_data(ClientPtr client, int len, char *data, void *userdata);
@@ -100,7 +99,7 @@ static void reply_XIGetSelectedEvents(ClientPtr client, int len, char *data, voi
reply_check_defaults(rep, len, XIGetSelectedEvents);
- g_assert(rep->num_masks == test_data.num_masks_expected);
+ assert(rep->num_masks == test_data.num_masks_expected);
reply_handler = reply_XIGetSelectedEvents_data;
}
@@ -121,11 +120,11 @@ static void reply_XIGetSelectedEvents_data(ClientPtr client, int len, char *data
swaps(&mask->mask_len, n);
}
- g_assert(mask->deviceid < 6);
- g_assert(mask->mask_len <= (((XI2LASTEVENT + 8)/8) + 3)/4) ;
+ assert(mask->deviceid < 6);
+ assert(mask->mask_len <= (((XI2LASTEVENT + 8)/8) + 3)/4) ;
bitmask = (unsigned char*)&mask[1];
- g_assert(memcmp(bitmask,
+ assert(memcmp(bitmask,
test_data.mask[mask->deviceid],
mask->mask_len * 4) == 0);
@@ -145,14 +144,14 @@ static void request_XIGetSelectedEvents(xXIGetSelectedEventsReq* req, int error)
reply_handler = reply_XIGetSelectedEvents;
rc = ProcXIGetSelectedEvents(&client);
- g_assert(rc == error);
+ assert(rc == error);
reply_handler = reply_XIGetSelectedEvents;
client.swapped = TRUE;
swapl(&req->win, n);
swaps(&req->length, n);
rc = SProcXIGetSelectedEvents(&client);
- g_assert(rc == error);
+ assert(rc == error);
}
static void test_XIGetSelectedEvents(void)
@@ -165,11 +164,11 @@ static void test_XIGetSelectedEvents(void)
request_init(&request, XIGetSelectedEvents);
- g_test_message("Testing for BadWindow on invalid window.");
+ printf("Testing for BadWindow on invalid window.\n");
request.win = None;
request_XIGetSelectedEvents(&request, BadWindow);
- g_test_message("Testing for zero-length (unset) masks.");
+ printf("Testing for zero-length (unset) masks.\n");
/* No masks set yet */
test_data.num_masks_expected = 0;
request.win = ROOT_WINDOW_ID;
@@ -181,7 +180,7 @@ static void test_XIGetSelectedEvents(void)
memset(test_data.mask, 0,
sizeof(test_data.mask));
- g_test_message("Testing for valid masks");
+ printf("Testing for valid masks\n");
memset(&dev, 0, sizeof(dev)); /* dev->id is enough for XISetEventMask */
request.win = ROOT_WINDOW_ID;
@@ -210,7 +209,7 @@ static void test_XIGetSelectedEvents(void)
}
}
- g_test_message("Testing removing all masks");
+ printf("Testing removing all masks\n");
/* Unset all masks one-by-one */
for (j = MAXDEVICES - 1; j >= 0; j--)
{
@@ -229,13 +228,10 @@ static void test_XIGetSelectedEvents(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
init_simple();
- g_test_add_func("/xi2/protocol/XIGetSelectedEvents", test_XIGetSelectedEvents);
+ test_XIGetSelectedEvents();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xi2/protocol-xipassivegrabdevice.c b/xorg-server/test/xi2/protocol-xipassivegrabdevice.c
new file mode 100644
index 000000000..a61c1549c
--- /dev/null
+++ b/xorg-server/test/xi2/protocol-xipassivegrabdevice.c
@@ -0,0 +1,234 @@
+/**
+ * Copyright © 2011 Red Hat, 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+/*
+ * Protocol testing for XIPassiveGrab request.
+ */
+#include <stdint.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/XI2proto.h>
+#include "inputstr.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "xipassivegrab.h"
+#include "exevents.h"
+
+#include "protocol-common.h"
+
+static ClientRec client_request;
+#define N_MODS 7
+static uint32_t modifiers[N_MODS] = {1, 2, 3, 4, 5, 6, 7};
+
+struct test_data {
+ int num_modifiers;
+} testdata;
+
+int __wrap_GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
+ int button, GrabParameters *param, GrabType grabtype,
+ GrabMask *mask);
+static void reply_XIPassiveGrabDevice_data(ClientPtr client, int len, char *data, void *userdata);
+
+int __wrap_dixLookupWindow(WindowPtr *win, XID id, ClientPtr client, Mask access)
+{
+ if (id == root.drawable.id)
+ {
+ *win = &root;
+ return Success;
+ } else if (id == window.drawable.id)
+ {
+ *win = &window;
+ return Success;
+ }
+
+ return __real_dixLookupWindow(win, id, client, access);
+}
+
+int __wrap_GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
+ int button, GrabParameters *param, GrabType grabtype,
+ GrabMask *mask)
+{
+ /* Fail every odd modifier */
+ if (param->modifiers % 2)
+ return BadAccess;
+
+ return Success;
+}
+
+static void reply_XIPassiveGrabDevice(ClientPtr client, int len, char *data, void *userdata)
+{
+ xXIPassiveGrabDeviceReply *rep = (xXIPassiveGrabDeviceReply*)data;
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->num_modifiers, n);
+
+ testdata.num_modifiers = rep->num_modifiers;
+ }
+
+ reply_check_defaults(rep, len, XIPassiveGrabDevice);
+
+ /* ProcXIPassiveGrabDevice sends the data in two batches, let the second
+ * handler handle the modifier data */
+ if (rep->num_modifiers > 0)
+ reply_handler = reply_XIPassiveGrabDevice_data;
+}
+
+static void reply_XIPassiveGrabDevice_data(ClientPtr client, int len, char *data, void *userdata)
+{
+ int i;
+ int n;
+
+ xXIGrabModifierInfo *mods = (xXIGrabModifierInfo*)data;
+
+ for (i = 0; i < testdata.num_modifiers; i++, mods++)
+ {
+ if (client->swapped)
+ swapl(&mods->modifiers, n);
+
+ /* 1 - 7 is the range we use for the global modifiers array
+ * above */
+ assert(mods->modifiers > 0);
+ assert(mods->modifiers <= 7);
+ assert(mods->modifiers % 2 == 1); /* because we fail odd ones */
+ assert(mods->status != Success);
+ assert(mods->pad0 == 0);
+ assert(mods->pad1 == 0);
+ }
+
+ reply_handler = reply_XIPassiveGrabDevice;
+}
+
+static void request_XIPassiveGrabDevice(ClientPtr client, xXIPassiveGrabDeviceReq* req, int error, int errval)
+{
+ char n;
+ int rc;
+ int modifiers;
+
+ rc = ProcXIPassiveGrabDevice(&client_request);
+ assert(rc == error);
+
+ if (rc != Success)
+ assert(client_request.errorValue == errval);
+
+ client_request.swapped = TRUE;
+ swaps(&req->length, n);
+ swapl(&req->time, n);
+ swapl(&req->grab_window, n);
+ swapl(&req->cursor, n);
+ swapl(&req->detail, n);
+ swaps(&req->deviceid, n);
+ modifiers = req->num_modifiers;
+ swaps(&req->num_modifiers, n);
+ swaps(&req->mask_len, n);
+
+ while(modifiers--)
+ {
+ CARD32 *mod = ((CARD32*)(req + 1)) + modifiers;
+ swapl(mod, n);
+ }
+
+ rc = SProcXIPassiveGrabDevice(&client_request);
+ assert(rc == error);
+
+ if (rc != Success)
+ assert(client_request.errorValue == errval);
+}
+
+static unsigned char *data[4096]; /* the request buffer */
+static void test_XIPassiveGrabDevice(void)
+{
+ int i;
+ xXIPassiveGrabDeviceReq *request = (xXIPassiveGrabDeviceReq*)data;
+ unsigned char *mask;
+
+ request_init(request, XIPassiveGrabDevice);
+
+ request->grab_window = CLIENT_WINDOW_ID;
+
+ reply_handler = reply_XIPassiveGrabDevice;
+ client_request = init_client(request->length, request);
+
+ printf("Testing invalid device\n");
+ request->deviceid = 12;
+ request_XIPassiveGrabDevice(&client_request, request, BadDevice, request->deviceid);
+
+ request->deviceid = XIAllMasterDevices;
+
+ printf("Testing invalid grab types\n");
+ for (i = XIGrabtypeFocusIn + 1; i < 0xFF; i++)
+ {
+ request->grab_type = i;
+ request_XIPassiveGrabDevice(&client_request, request, BadValue, request->grab_type);
+ }
+
+ printf("Testing invalid grab type + detail combinations\n");
+ request->grab_type = XIGrabtypeEnter;
+ request->detail = 1;
+ request_XIPassiveGrabDevice(&client_request, request, BadValue, request->detail);
+
+ request->grab_type = XIGrabtypeFocusIn;
+ request_XIPassiveGrabDevice(&client_request, request, BadValue, request->detail);
+
+ request->detail = 0;
+
+ printf("Testing invalid masks\n");
+ mask = (unsigned char*)&request[1];
+
+ request->mask_len = bytes_to_int32(XI2LASTEVENT + 1);
+ request->length += request->mask_len;
+ SetBit(mask, XI2LASTEVENT + 1);
+ request_XIPassiveGrabDevice(&client_request, request, BadValue, XI2LASTEVENT + 1);
+
+ ClearBit(mask, XI2LASTEVENT + 1);
+
+ /* tested all special cases now, test a few valid cases */
+
+ /* no modifiers */
+ request->deviceid = XIAllDevices;
+ request->grab_type = XIGrabtypeButton;
+ request->detail = XIAnyButton;
+ request_XIPassiveGrabDevice(&client_request, request, Success, 0);
+
+ /* some modifiers */
+ request->num_modifiers = N_MODS;
+ request->length += N_MODS;
+ memcpy((uint32_t*)(request + 1) + request->mask_len, modifiers, sizeof(modifiers));
+ request_XIPassiveGrabDevice(&client_request, request, Success, 0);
+}
+
+int main(int argc, char** argv)
+{
+ init_simple();
+
+ test_XIPassiveGrabDevice();
+
+ return 0;
+}
diff --git a/xorg-server/test/xi2/protocol-xiquerydevice.c b/xorg-server/test/xi2/protocol-xiquerydevice.c
index 508fc4dfb..cb1cc8130 100644
--- a/xorg-server/test/xi2/protocol-xiquerydevice.c
+++ b/xorg-server/test/xi2/protocol-xiquerydevice.c
@@ -38,7 +38,6 @@
#include "xiquerydevice.h"
#include "protocol-common.h"
-#include <glib.h>
/*
* Protocol testing for XIQueryDevice request and reply.
*
@@ -74,11 +73,11 @@ static void reply_XIQueryDevice(ClientPtr client, int len, char* data, void *use
reply_check_defaults(rep, len, XIQueryDevice);
if (querydata->which_device == XIAllDevices)
- g_assert(rep->num_devices == devices.num_devices);
+ assert(rep->num_devices == devices.num_devices);
else if (querydata->which_device == XIAllMasterDevices)
- g_assert(rep->num_devices == devices.num_master_devices);
+ assert(rep->num_devices == devices.num_master_devices);
else
- g_assert(rep->num_devices == 1);
+ assert(rep->num_devices == 1);
querydata->num_devices_in_reply = rep->num_devices;
reply_handler = reply_XIQueryDevice_data;
@@ -107,46 +106,46 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void
}
if (querydata->which_device > XIAllMasterDevices)
- g_assert(info->deviceid == querydata->which_device);
+ assert(info->deviceid == querydata->which_device);
- g_assert(info->deviceid >= 2); /* 0 and 1 is reserved */
+ assert(info->deviceid >= 2); /* 0 and 1 is reserved */
switch(info->deviceid)
{
case 2: /* VCP */
dev = devices.vcp;
- g_assert(info->use == XIMasterPointer);
- g_assert(info->attachment == devices.vck->id);
- g_assert(info->num_classes == 3); /* 2 axes + button */
+ assert(info->use == XIMasterPointer);
+ assert(info->attachment == devices.vck->id);
+ assert(info->num_classes == 3); /* 2 axes + button */
break;
case 3: /* VCK */
dev = devices.vck;
- g_assert(info->use == XIMasterKeyboard);
- g_assert(info->attachment == devices.vcp->id);
- g_assert(info->num_classes == 1);
+ assert(info->use == XIMasterKeyboard);
+ assert(info->attachment == devices.vcp->id);
+ assert(info->num_classes == 1);
break;
case 4: /* mouse */
dev = devices.mouse;
- g_assert(info->use == XISlavePointer);
- g_assert(info->attachment == devices.vcp->id);
- g_assert(info->num_classes == 3); /* 2 axes + button */
+ assert(info->use == XISlavePointer);
+ assert(info->attachment == devices.vcp->id);
+ assert(info->num_classes == 3); /* 2 axes + button */
break;
case 5: /* keyboard */
dev = devices.kbd;
- g_assert(info->use == XISlaveKeyboard);
- g_assert(info->attachment == devices.vck->id);
- g_assert(info->num_classes == 1);
+ assert(info->use == XISlaveKeyboard);
+ assert(info->attachment == devices.vck->id);
+ assert(info->num_classes == 1);
break;
default:
/* We shouldn't get here */
- g_assert(0);
+ assert(0);
break;
}
- g_assert(info->enabled == dev->enabled);
- g_assert(info->name_len == strlen(dev->name));
- g_assert(strncmp((char*)&info[1], dev->name, info->name_len) == 0);
+ assert(info->enabled == dev->enabled);
+ assert(info->name_len == strlen(dev->name));
+ assert(strncmp((char*)&info[1], dev->name, info->name_len) == 0);
any = (xXIAnyInfo*)((char*)&info[1] + ((info->name_len + 3)/4) * 4);
for (j = 0; j < info->num_classes; j++)
@@ -171,9 +170,9 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void
if (client->swapped)
swaps(&ki->num_keycodes, n);
- g_assert(any->type == XIKeyClass);
- g_assert(ki->num_keycodes == (xkb->max_key_code - xkb->min_key_code + 1));
- g_assert(any->length == (2 + ki->num_keycodes));
+ assert(any->type == XIKeyClass);
+ assert(ki->num_keycodes == (xkb->max_key_code - xkb->min_key_code + 1));
+ assert(any->length == (2 + ki->num_keycodes));
kc = (uint32_t*)&ki[1];
for (k = 0; k < ki->num_keycodes; k++, kc++)
@@ -181,15 +180,15 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void
if (client->swapped)
swapl(kc, n);
- g_assert(*kc >= xkb->min_key_code);
- g_assert(*kc <= xkb->max_key_code);
+ assert(*kc >= xkb->min_key_code);
+ assert(*kc <= xkb->max_key_code);
}
break;
}
case 2: /* VCP and mouse have the same properties */
case 4:
{
- g_assert(any->type == XIButtonClass ||
+ assert(any->type == XIButtonClass ||
any->type == XIValuatorClass);
if (any->type == XIButtonClass)
@@ -200,10 +199,10 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void
if (client->swapped)
swaps(&bi->num_buttons, n);
- g_assert(bi->num_buttons == devices.vcp->button->numButtons);
+ assert(bi->num_buttons == devices.vcp->button->numButtons);
len = 2 + bi->num_buttons + bytes_to_int32(bits_to_bytes(bi->num_buttons));
- g_assert(bi->length == len);
+ assert(bi->length == len);
} else if (any->type == XIValuatorClass)
{
xXIValuatorInfo *vi = (xXIValuatorInfo*)any;
@@ -219,17 +218,17 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void
swapl(&vi->resolution, n);
}
- g_assert(vi->length == 11);
- g_assert(vi->number == 0 ||
+ assert(vi->length == 11);
+ assert(vi->number == 0 ||
vi->number == 1);
- g_assert(vi->mode == XIModeRelative);
+ assert(vi->mode == XIModeRelative);
/* device was set up as relative, so standard
* values here. */
- g_assert(vi->min.integral == -1);
- g_assert(vi->min.frac == 0);
- g_assert(vi->max.integral == -1);
- g_assert(vi->max.frac == 0);
- g_assert(vi->resolution == 0);
+ assert(vi->min.integral == -1);
+ assert(vi->min.frac == 0);
+ assert(vi->max.integral == -1);
+ assert(vi->max.frac == 0);
+ assert(vi->resolution == 0);
}
}
break;
@@ -257,10 +256,10 @@ static void request_XIQueryDevice(struct test_data *querydata,
request.deviceid = deviceid;
rc = ProcXIQueryDevice(&client);
- g_assert(rc == error);
+ assert(rc == error);
if (rc != Success)
- g_assert(client.errorValue == deviceid);
+ assert(client.errorValue == deviceid);
reply_handler = reply_XIQueryDevice;
@@ -268,10 +267,10 @@ static void request_XIQueryDevice(struct test_data *querydata,
swaps(&request.length, n);
swaps(&request.deviceid, n);
rc = SProcXIQueryDevice(&client);
- g_assert(rc == error);
+ assert(rc == error);
if (rc != Success)
- g_assert(client.errorValue == deviceid);
+ assert(client.errorValue == deviceid);
}
static void test_XIQueryDevice(void)
@@ -284,16 +283,16 @@ static void test_XIQueryDevice(void)
userdata = &data;
request_init(&request, XIQueryDevice);
- g_test_message("Testing XIAllDevices.");
+ printf("Testing XIAllDevices.\n");
request_XIQueryDevice(&data, XIAllDevices, Success);
- g_test_message("Testing XIAllMasterDevices.");
+ printf("Testing XIAllMasterDevices.\n");
request_XIQueryDevice(&data, XIAllMasterDevices, Success);
- g_test_message("Testing existing device ids.");
+ printf("Testing existing device ids.\n");
for (i = 2; i < 6; i++)
request_XIQueryDevice(&data, i, Success);
- g_test_message("Testing non-existing device ids.");
+ printf("Testing non-existing device ids.\n");
for (i = 6; i <= 0xFFFF; i++)
request_XIQueryDevice(&data, i, BadDevice);
@@ -304,13 +303,10 @@ static void test_XIQueryDevice(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
init_simple();
- g_test_add_func("/dix/xi2protocol/XIQueryDevice", test_XIQueryDevice);
+ test_XIQueryDevice();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xi2/protocol-xiquerypointer.c b/xorg-server/test/xi2/protocol-xiquerypointer.c
index a42d59515..0985ec70d 100644
--- a/xorg-server/test/xi2/protocol-xiquerypointer.c
+++ b/xorg-server/test/xi2/protocol-xiquerypointer.c
@@ -39,7 +39,6 @@
#include "exevents.h"
#include "protocol-common.h"
-#include <glib.h>
static ClientRec client_request;
static void reply_XIQueryPointer_data(ClientPtr client, int len,
@@ -96,18 +95,18 @@ static void reply_XIQueryPointer(ClientPtr client, int len, char *data,
reply_check_defaults(rep, len, XIQueryPointer);
- g_assert(rep->root == root.drawable.id);
- g_assert(rep->same_screen == xTrue);
+ assert(rep->root == root.drawable.id);
+ assert(rep->same_screen == xTrue);
sprite = test_data.dev->spriteInfo->sprite;
- g_assert((rep->root_x >> 16) == sprite->hot.x);
- g_assert((rep->root_y >> 16) == sprite->hot.y);
+ assert((rep->root_x >> 16) == sprite->hot.x);
+ assert((rep->root_y >> 16) == sprite->hot.y);
if (test_data.win == &root)
{
- g_assert(rep->root_x == rep->win_x);
- g_assert(rep->root_y == rep->win_y);
- g_assert(rep->child == window.drawable.id);
+ assert(rep->root_x == rep->win_x);
+ assert(rep->root_y == rep->win_y);
+ assert(rep->child == window.drawable.id);
} else
{
int x, y;
@@ -115,13 +114,13 @@ static void reply_XIQueryPointer(ClientPtr client, int len, char *data,
x = sprite->hot.x - window.drawable.x;
y = sprite->hot.y - window.drawable.y;
- g_assert((rep->win_x >> 16) == x);
- g_assert((rep->win_y >> 16) == y);
- g_assert(rep->child == None);
+ assert((rep->win_x >> 16) == x);
+ assert((rep->win_y >> 16) == y);
+ assert(rep->child == None);
}
- g_assert(rep->same_screen == xTrue);
+ assert(rep->same_screen == xTrue);
reply_handler = reply_XIQueryPointer_data;
}
@@ -137,19 +136,19 @@ static void request_XIQueryPointer(ClientPtr client, xXIQueryPointerReq* req, in
int rc;
rc = ProcXIQueryPointer(&client_request);
- g_assert(rc == error);
+ assert(rc == error);
if (rc == BadDevice)
- g_assert(client_request.errorValue == req->deviceid);
+ assert(client_request.errorValue == req->deviceid);
client_request.swapped = TRUE;
swaps(&req->deviceid, n);
swaps(&req->length, n);
rc = SProcXIQueryPointer(&client_request);
- g_assert(rc == error);
+ assert(rc == error);
if (rc == BadDevice)
- g_assert(client_request.errorValue == req->deviceid);
+ assert(client_request.errorValue == req->deviceid);
}
static void test_XIQueryPointer(void)
@@ -209,12 +208,9 @@ static void test_XIQueryPointer(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
init_simple();
- g_test_add_func("/xi2/protocol/XIQueryPointer", test_XIQueryPointer);
+ test_XIQueryPointer();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xi2/protocol-xiqueryversion.c b/xorg-server/test/xi2/protocol-xiqueryversion.c
index 46e62acbd..3bb356e7f 100644
--- a/xorg-server/test/xi2/protocol-xiqueryversion.c
+++ b/xorg-server/test/xi2/protocol-xiqueryversion.c
@@ -46,7 +46,6 @@
#include "xiqueryversion.h"
#include "protocol-common.h"
-#include <glib.h>
extern XExtensionVersion XIVersion;
@@ -74,14 +73,14 @@ static void reply_XIQueryVersion(ClientPtr client, int len, char* data, void *us
reply_check_defaults(rep, len, XIQueryVersion);
- g_assert(rep->length == 0);
+ assert(rep->length == 0);
sver = versions->major_server * 1000 + versions->minor_server;
cver = versions->major_client * 1000 + versions->minor_client;
ver = rep->major_version * 1000 + rep->minor_version;
- g_assert(ver >= 2000);
- g_assert((sver > cver) ? ver == cver : ver == sver);
+ assert(ver >= 2000);
+ assert((sver > cver) ? ver == cver : ver == sver);
}
/**
@@ -115,7 +114,7 @@ static void request_XIQueryVersion(int smaj, int smin, int cmaj, int cmin, int e
request.major_version = versions.major_client;
request.minor_version = versions.minor_client;
rc = ProcXIQueryVersion(&client);
- g_assert(rc == error);
+ assert(rc == error);
client.swapped = TRUE;
@@ -124,7 +123,7 @@ static void request_XIQueryVersion(int smaj, int smin, int cmaj, int cmin, int e
swaps(&request.minor_version, n);
rc = SProcXIQueryVersion(&client);
- g_assert(rc == error);
+ assert(rc == error);
}
/* Client version less than 2.0 must return BadValue, all other combinations
@@ -133,23 +132,23 @@ static void test_XIQueryVersion(void)
{
reply_handler = reply_XIQueryVersion;
- g_test_message("Server version 2.0 - client versions [1..3].0");
+ printf("Server version 2.0 - client versions [1..3].0\n");
/* some simple tests to catch common errors quickly */
request_XIQueryVersion(2, 0, 1, 0, BadValue);
request_XIQueryVersion(2, 0, 2, 0, Success);
request_XIQueryVersion(2, 0, 3, 0, Success);
- g_test_message("Server version 3.0 - client versions [1..3].0");
+ printf("Server version 3.0 - client versions [1..3].0\n");
request_XIQueryVersion(3, 0, 1, 0, BadValue);
request_XIQueryVersion(3, 0, 2, 0, Success);
request_XIQueryVersion(3, 0, 3, 0, Success);
- g_test_message("Server version 2.0 - client versions [1..3].[1..3]");
+ printf("Server version 2.0 - client versions [1..3].[1..3]\n");
request_XIQueryVersion(2, 0, 1, 1, BadValue);
request_XIQueryVersion(2, 0, 2, 2, Success);
request_XIQueryVersion(2, 0, 3, 3, Success);
- g_test_message("Server version 2.2 - client versions [1..3].0");
+ printf("Server version 2.2 - client versions [1..3].0\n");
request_XIQueryVersion(2, 2, 1, 0, BadValue);
request_XIQueryVersion(2, 2, 2, 0, Success);
request_XIQueryVersion(2, 2, 3, 0, Success);
@@ -158,7 +157,7 @@ static void test_XIQueryVersion(void)
/* this one takes a while */
unsigned int cmin, cmaj, smin, smaj;
- g_test_message("Testing all combinations.");
+ printf("Testing all combinations.\n");
for (smaj = 2; smaj <= 0xFFFF; smaj++)
for (smin = 0; smin <= 0xFFFF; smin++)
for (cmin = 0; cmin <= 0xFFFF; cmin++)
@@ -175,12 +174,9 @@ static void test_XIQueryVersion(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
init_simple();
- g_test_add_func("/xi2/protocol/XIQueryVersion", test_XIQueryVersion);
+ test_XIQueryVersion();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xi2/protocol-xiselectevents.c b/xorg-server/test/xi2/protocol-xiselectevents.c
index f951a14fe..fa422e2cb 100644
--- a/xorg-server/test/xi2/protocol-xiselectevents.c
+++ b/xorg-server/test/xi2/protocol-xiselectevents.c
@@ -58,7 +58,6 @@
#include "xiselectev.h"
#include "protocol-common.h"
-#include <glib.h>
static unsigned char *data[4096 * 20]; /* the request data buffer */
@@ -107,7 +106,7 @@ static void request_XISelectEvent(xXISelectEventsReq *req, int error)
client = init_client(req->length, req);
rc = ProcXISelectEvents(&client);
- g_assert(rc == error);
+ assert(rc == error);
client.swapped = TRUE;
@@ -124,7 +123,7 @@ static void request_XISelectEvent(xXISelectEventsReq *req, int error)
swaps(&req->length, n);
swaps(&req->num_masks, n);
rc = SProcXISelectEvents(&client);
- g_assert(rc == error);
+ assert(rc == error);
}
static void request_XISelectEvents_masks(xXISelectEventsReq *req)
@@ -250,7 +249,7 @@ static void test_XISelectEvents(void)
request_init(req, XISelectEvents);
- g_test_message("Testing for BadValue on zero-length masks");
+ printf("Testing for BadValue on zero-length masks\n");
/* zero masks are BadValue, regardless of the window */
req->num_masks = 0;
@@ -263,7 +262,7 @@ static void test_XISelectEvents(void)
req->win = CLIENT_WINDOW_ID;
request_XISelectEvent(req, BadValue);
- g_test_message("Testing for BadWindow.");
+ printf("Testing for BadWindow.\n");
/* None window is BadWindow, regardless of the masks.
* We don't actually need to set the masks here, BadWindow must occur
* before checking the masks.
@@ -283,7 +282,7 @@ static void test_XISelectEvents(void)
req->num_masks = 0xFFFC;
request_XISelectEvent(req, BadWindow);
- g_test_message("Triggering num_masks/length overflow");
+ printf("Triggering num_masks/length overflow\n");
req->win = ROOT_WINDOW_ID;
/* Integer overflow - req->length can't hold that much */
req->num_masks = 0xFFFF;
@@ -292,14 +291,14 @@ static void test_XISelectEvents(void)
req->win = ROOT_WINDOW_ID;
req->num_masks = 1;
- g_test_message("Triggering bogus mask length error");
+ printf("Triggering bogus mask length error\n");
mask = (xXIEventMask*)&req[1];
mask->deviceid = 0;
mask->mask_len = 0xFFFF;
request_XISelectEvent(req, BadLength);
/* testing various device ids */
- g_test_message("Testing existing device ids.");
+ printf("Testing existing device ids.\n");
for (i = 0; i < 6; i++)
{
mask = (xXIEventMask*)&req[1];
@@ -310,7 +309,7 @@ static void test_XISelectEvents(void)
request_XISelectEvent(req, Success);
}
- g_test_message("Testing non-existing device ids.");
+ printf("Testing non-existing device ids.\n");
for (i = 6; i <= 0xFFFF; i++)
{
req->win = ROOT_WINDOW_ID;
@@ -326,13 +325,10 @@ static void test_XISelectEvents(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
init_simple();
- g_test_add_func("/xi2/protocol/XISelectEvents", test_XISelectEvents);
+ test_XISelectEvents();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xi2/protocol-xisetclientpointer.c b/xorg-server/test/xi2/protocol-xisetclientpointer.c
index 2e638eea7..c266b6560 100644
--- a/xorg-server/test/xi2/protocol-xisetclientpointer.c
+++ b/xorg-server/test/xi2/protocol-xisetclientpointer.c
@@ -46,7 +46,6 @@
#include "exevents.h"
#include "protocol-common.h"
-#include <glib.h>
static ClientRec client_window;
static ClientRec client_request;
@@ -72,20 +71,20 @@ static void request_XISetClientPointer(xXISetClientPointerReq* req, int error)
client_request = init_client(req->length, req);
rc = ProcXISetClientPointer(&client_request);
- g_assert(rc == error);
+ assert(rc == error);
if (rc == BadDevice)
- g_assert(client_request.errorValue == req->deviceid);
+ assert(client_request.errorValue == req->deviceid);
client_request.swapped = TRUE;
swapl(&req->win, n);
swaps(&req->length, n);
swaps(&req->deviceid, n);
rc = SProcXISetClientPointer(&client_request);
- g_assert(rc == error);
+ assert(rc == error);
if (rc == BadDevice)
- g_assert(client_request.errorValue == req->deviceid);
+ assert(client_request.errorValue == req->deviceid);
}
@@ -98,36 +97,36 @@ static void test_XISetClientPointer(void)
request.win = CLIENT_WINDOW_ID;
- g_test_message("Testing BadDevice error for XIAllDevices and XIMasterDevices.");
+ printf("Testing BadDevice error for XIAllDevices and XIMasterDevices.\n");
request.deviceid = XIAllDevices;
request_XISetClientPointer(&request, BadDevice);
request.deviceid = XIAllMasterDevices;
request_XISetClientPointer(&request, BadDevice);
- g_test_message("Testing Success for VCP and VCK.");
+ printf("Testing Success for VCP and VCK.\n");
request.deviceid = devices.vcp->id; /* 2 */
request_XISetClientPointer(&request, Success);
- g_assert(client_window.clientPtr->id == 2);
+ assert(client_window.clientPtr->id == 2);
request.deviceid = devices.vck->id; /* 3 */
request_XISetClientPointer(&request, Success);
- g_assert(client_window.clientPtr->id == 2);
+ assert(client_window.clientPtr->id == 2);
- g_test_message("Testing BadDevice error for all other devices.");
+ printf("Testing BadDevice error for all other devices.\n");
for (i = 4; i <= 0xFFFF; i++)
{
request.deviceid = i;
request_XISetClientPointer(&request, BadDevice);
}
- g_test_message("Testing window None");
+ printf("Testing window None\n");
request.win = None;
request.deviceid = devices.vcp->id; /* 2 */
request_XISetClientPointer(&request, Success);
- g_assert(client_request.clientPtr->id == 2);
+ assert(client_request.clientPtr->id == 2);
- g_test_message("Testing invalid window");
+ printf("Testing invalid window\n");
request.win = INVALID_WINDOW_ID;
request.deviceid = devices.vcp->id;
request_XISetClientPointer(&request, BadWindow);
@@ -137,13 +136,10 @@ static void test_XISetClientPointer(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
init_simple();
client_window = init_client(0, NULL);
- g_test_add_func("/xi2/protocol/XISetClientPointer", test_XISetClientPointer);
+ test_XISetClientPointer();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xi2/protocol-xiwarppointer.c b/xorg-server/test/xi2/protocol-xiwarppointer.c
index 75b7617a0..0c8db453d 100644
--- a/xorg-server/test/xi2/protocol-xiwarppointer.c
+++ b/xorg-server/test/xi2/protocol-xiwarppointer.c
@@ -39,7 +39,6 @@
#include "exevents.h"
#include "protocol-common.h"
-#include <glib.h>
static int expected_x = SPRITE_X;
static int expected_y = SPRITE_Y;
@@ -70,8 +69,8 @@ int __wrap_dixLookupWindow(WindowPtr *win, XID id, ClientPtr client, Mask access
static Bool ScreenSetCursorPosition(DeviceIntPtr dev, ScreenPtr screen,
int x, int y, Bool generateEvent)
{
- g_assert(x == expected_x);
- g_assert(y == expected_y);
+ assert(x == expected_x);
+ assert(y == expected_y);
return TRUE;
}
@@ -83,12 +82,12 @@ static void request_XIWarpPointer(ClientPtr client, xXIWarpPointerReq* req,
int rc;
rc = ProcXIWarpPointer(client);
- g_assert(rc == error);
+ assert(rc == error);
if (rc == BadDevice)
- g_assert(client->errorValue == req->deviceid);
+ assert(client->errorValue == req->deviceid);
else if (rc == BadWindow)
- g_assert(client->errorValue == req->dst_win ||
+ assert(client->errorValue == req->dst_win ||
client->errorValue == req->src_win);
@@ -105,12 +104,12 @@ static void request_XIWarpPointer(ClientPtr client, xXIWarpPointerReq* req,
swaps(&req->deviceid, n);
rc = SProcXIWarpPointer(client);
- g_assert(rc == error);
+ assert(rc == error);
if (rc == BadDevice)
- g_assert(client->errorValue == req->deviceid);
+ assert(client->errorValue == req->deviceid);
else if (rc == BadWindow)
- g_assert(client->errorValue == req->dst_win ||
+ assert(client->errorValue == req->dst_win ||
client->errorValue == req->src_win);
client->swapped = FALSE;
@@ -204,13 +203,10 @@ static void test_XIWarpPointer(void)
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
init_simple();
screen.SetCursorPosition = ScreenSetCursorPosition;
- g_test_add_func("/xi2/protocol/XIWarpPointer", test_XIWarpPointer);
+ test_XIWarpPointer();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xkb.c b/xorg-server/test/xkb.c
index 6fbb26a01..421153cd1 100644
--- a/xorg-server/test/xkb.c
+++ b/xorg-server/test/xkb.c
@@ -46,8 +46,7 @@
#include <X11/extensions/XKMformat.h>
#include "xkbfile.h"
#include "../xkb/xkb.h"
-
-#include <glib.h>
+#include <assert.h>
/**
* Initialize an empty XkbRMLVOSet.
@@ -62,16 +61,16 @@ static void xkb_get_rules_test(void)
XkbGetRulesDflts(&rmlvo);
- g_assert(rmlvo.rules);
- g_assert(rmlvo.model);
- g_assert(rmlvo.layout);
- g_assert(rmlvo.variant);
- g_assert(rmlvo.options);
- g_assert(strcmp(rmlvo.rules, XKB_DFLT_RULES) == 0);
- g_assert(strcmp(rmlvo.model, XKB_DFLT_MODEL) == 0);
- g_assert(strcmp(rmlvo.layout, XKB_DFLT_LAYOUT) == 0);
- g_assert(strcmp(rmlvo.variant, XKB_DFLT_VARIANT) == 0);
- g_assert(strcmp(rmlvo.options, XKB_DFLT_OPTIONS) == 0);
+ assert(rmlvo.rules);
+ assert(rmlvo.model);
+ assert(rmlvo.layout);
+ assert(rmlvo.variant);
+ assert(rmlvo.options);
+ assert(strcmp(rmlvo.rules, XKB_DFLT_RULES) == 0);
+ assert(strcmp(rmlvo.model, XKB_DFLT_MODEL) == 0);
+ assert(strcmp(rmlvo.layout, XKB_DFLT_LAYOUT) == 0);
+ assert(strcmp(rmlvo.variant, XKB_DFLT_VARIANT) == 0);
+ assert(strcmp(rmlvo.options, XKB_DFLT_OPTIONS) == 0);
}
/**
@@ -95,17 +94,17 @@ static void xkb_set_rules_test(void)
XkbGetRulesDflts(&rmlvo_new);
/* XkbGetRulesDflts strdups the values */
- g_assert(rmlvo.rules != rmlvo_new.rules);
- g_assert(rmlvo.model != rmlvo_new.model);
- g_assert(rmlvo.layout != rmlvo_new.layout);
- g_assert(rmlvo.variant != rmlvo_new.variant);
- g_assert(rmlvo.options != rmlvo_new.options);
-
- g_assert(strcmp(rmlvo.rules, rmlvo_new.rules) == 0);
- g_assert(strcmp(rmlvo.model, rmlvo_new.model) == 0);
- g_assert(strcmp(rmlvo.layout, rmlvo_new.layout) == 0);
- g_assert(strcmp(rmlvo.variant, rmlvo_new.variant) == 0);
- g_assert(strcmp(rmlvo.options, rmlvo_new.options) == 0);
+ assert(rmlvo.rules != rmlvo_new.rules);
+ assert(rmlvo.model != rmlvo_new.model);
+ assert(rmlvo.layout != rmlvo_new.layout);
+ assert(rmlvo.variant != rmlvo_new.variant);
+ assert(rmlvo.options != rmlvo_new.options);
+
+ assert(strcmp(rmlvo.rules, rmlvo_new.rules) == 0);
+ assert(strcmp(rmlvo.model, rmlvo_new.model) == 0);
+ assert(strcmp(rmlvo.layout, rmlvo_new.layout) == 0);
+ assert(strcmp(rmlvo.variant, rmlvo_new.variant) == 0);
+ assert(strcmp(rmlvo.options, rmlvo_new.options) == 0);
}
@@ -145,29 +144,26 @@ static void xkb_set_get_rules_test(void)
/* This test is iffy, because strictly we may be comparing against already
* freed memory */
- g_assert(strcmp(rmlvo.rules, rmlvo_backup.rules) == 0);
- g_assert(strcmp(rmlvo.model, rmlvo_backup.model) == 0);
- g_assert(strcmp(rmlvo.layout, rmlvo_backup.layout) == 0);
- g_assert(strcmp(rmlvo.variant, rmlvo_backup.variant) == 0);
- g_assert(strcmp(rmlvo.options, rmlvo_backup.options) == 0);
+ assert(strcmp(rmlvo.rules, rmlvo_backup.rules) == 0);
+ assert(strcmp(rmlvo.model, rmlvo_backup.model) == 0);
+ assert(strcmp(rmlvo.layout, rmlvo_backup.layout) == 0);
+ assert(strcmp(rmlvo.variant, rmlvo_backup.variant) == 0);
+ assert(strcmp(rmlvo.options, rmlvo_backup.options) == 0);
XkbGetRulesDflts(&rmlvo);
- g_assert(strcmp(rmlvo.rules, rmlvo_backup.rules) == 0);
- g_assert(strcmp(rmlvo.model, rmlvo_backup.model) == 0);
- g_assert(strcmp(rmlvo.layout, rmlvo_backup.layout) == 0);
- g_assert(strcmp(rmlvo.variant, rmlvo_backup.variant) == 0);
- g_assert(strcmp(rmlvo.options, rmlvo_backup.options) == 0);
+ assert(strcmp(rmlvo.rules, rmlvo_backup.rules) == 0);
+ assert(strcmp(rmlvo.model, rmlvo_backup.model) == 0);
+ assert(strcmp(rmlvo.layout, rmlvo_backup.layout) == 0);
+ assert(strcmp(rmlvo.variant, rmlvo_backup.variant) == 0);
+ assert(strcmp(rmlvo.options, rmlvo_backup.options) == 0);
}
int main(int argc, char** argv)
{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
- g_test_add_func("/xkb/set-get-rules", xkb_set_get_rules_test);
- g_test_add_func("/xkb/get-rules", xkb_get_rules_test);
- g_test_add_func("/xkb/set-rules", xkb_set_rules_test);
+ xkb_set_get_rules_test();
+ xkb_get_rules_test();
+ xkb_set_rules_test();
- return g_test_run();
+ return 0;
}
diff --git a/xorg-server/test/xtest.c b/xorg-server/test/xtest.c
index cd8f23bff..2ab46505f 100644
--- a/xorg-server/test/xtest.c
+++ b/xorg-server/test/xtest.c
@@ -1,118 +1,113 @@
-/**
- * Copyright © 2009 Red Hat, 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-#include <stdint.h>
-#include <X11/Xatom.h>
-#include "input.h"
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "exevents.h"
-#include "xkbsrv.h"
-#include "xserver-properties.h"
-
-#include <glib.h>
-
-/**
- */
-
-/* from Xext/xtest.c */
-extern DeviceIntPtr xtestpointer, xtestkeyboard;
-
-/* Needed for the screen setup, otherwise we crash during sprite initialization */
-static Bool device_cursor_init(DeviceIntPtr dev, ScreenPtr screen) { return TRUE; }
-
-static void xtest_init_devices(void)
-{
- ScreenRec screen;
-
- /* random stuff that needs initialization */
- memset(&screen, 0, sizeof(screen));
- screenInfo.numScreens = 1;
- screenInfo.screens[0] = &screen;
- screen.myNum = 0;
- screen.id = 100;
- screen.width = 640;
- screen.height = 480;
- screen.DeviceCursorInitialize = device_cursor_init;
- dixResetPrivates();
- InitAtoms();
-
- XkbInitPrivates();
-
- /* this also inits the xtest devices */
- InitCoreDevices();
-
- g_assert(xtestpointer);
- g_assert(xtestkeyboard);
- g_assert(IsXTestDevice(xtestpointer, NULL));
- g_assert(IsXTestDevice(xtestkeyboard, NULL));
- g_assert(IsXTestDevice(xtestpointer, inputInfo.pointer));
- g_assert(IsXTestDevice(xtestkeyboard, inputInfo.keyboard));
- g_assert(GetXTestDevice(inputInfo.pointer) == xtestpointer);
- g_assert(GetXTestDevice(inputInfo.keyboard) == xtestkeyboard);
-}
-
-/**
- * Each xtest devices has a property attached marking it. This property
- * cannot be changed.
- */
-static void xtest_properties(void)
-{
- int rc;
- char value = 1;
- XIPropertyValuePtr prop;
- Atom xtest_prop = XIGetKnownProperty(XI_PROP_XTEST_DEVICE);
-
- rc = XIGetDeviceProperty(xtestpointer, xtest_prop, &prop);
- g_assert(rc == Success);
- g_assert(prop);
-
- rc = XIGetDeviceProperty(xtestkeyboard, xtest_prop, &prop);
- g_assert(rc == Success);
- g_assert(prop != NULL);
-
- rc = XIChangeDeviceProperty(xtestpointer, xtest_prop,
- XA_INTEGER, 8, PropModeReplace, 1, &value, FALSE);
- g_assert(rc == BadAccess);
- rc = XIChangeDeviceProperty(xtestkeyboard, xtest_prop,
- XA_INTEGER, 8, PropModeReplace, 1, &value, FALSE);
- g_assert(rc == BadAccess);
-}
-
-
-
-int main(int argc, char** argv)
-{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
- g_test_add_func("/dix/xtest/init", xtest_init_devices);
- g_test_add_func("/dix/xtest/properties", xtest_properties);
-
- return g_test_run();
-}
-
-
+/**
+ * Copyright © 2009 Red Hat, 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include <stdint.h>
+#include <X11/Xatom.h>
+#include "input.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "exevents.h"
+#include "xkbsrv.h"
+#include "xserver-properties.h"
+
+/**
+ */
+
+/* from Xext/xtest.c */
+extern DeviceIntPtr xtestpointer, xtestkeyboard;
+
+/* Needed for the screen setup, otherwise we crash during sprite initialization */
+static Bool device_cursor_init(DeviceIntPtr dev, ScreenPtr screen) { return TRUE; }
+
+static void xtest_init_devices(void)
+{
+ ScreenRec screen;
+
+ /* random stuff that needs initialization */
+ memset(&screen, 0, sizeof(screen));
+ screenInfo.numScreens = 1;
+ screenInfo.screens[0] = &screen;
+ screen.myNum = 0;
+ screen.id = 100;
+ screen.width = 640;
+ screen.height = 480;
+ screen.DeviceCursorInitialize = device_cursor_init;
+ dixResetPrivates();
+ InitAtoms();
+
+ XkbInitPrivates();
+
+ /* this also inits the xtest devices */
+ InitCoreDevices();
+
+ assert(xtestpointer);
+ assert(xtestkeyboard);
+ assert(IsXTestDevice(xtestpointer, NULL));
+ assert(IsXTestDevice(xtestkeyboard, NULL));
+ assert(IsXTestDevice(xtestpointer, inputInfo.pointer));
+ assert(IsXTestDevice(xtestkeyboard, inputInfo.keyboard));
+ assert(GetXTestDevice(inputInfo.pointer) == xtestpointer);
+ assert(GetXTestDevice(inputInfo.keyboard) == xtestkeyboard);
+}
+
+/**
+ * Each xtest devices has a property attached marking it. This property
+ * cannot be changed.
+ */
+static void xtest_properties(void)
+{
+ int rc;
+ char value = 1;
+ XIPropertyValuePtr prop;
+ Atom xtest_prop = XIGetKnownProperty(XI_PROP_XTEST_DEVICE);
+
+ rc = XIGetDeviceProperty(xtestpointer, xtest_prop, &prop);
+ assert(rc == Success);
+ assert(prop);
+
+ rc = XIGetDeviceProperty(xtestkeyboard, xtest_prop, &prop);
+ assert(rc == Success);
+ assert(prop != NULL);
+
+ rc = XIChangeDeviceProperty(xtestpointer, xtest_prop,
+ XA_INTEGER, 8, PropModeReplace, 1, &value, FALSE);
+ assert(rc == BadAccess);
+ rc = XIChangeDeviceProperty(xtestkeyboard, xtest_prop,
+ XA_INTEGER, 8, PropModeReplace, 1, &value, FALSE);
+ assert(rc == BadAccess);
+}
+
+
+
+int main(int argc, char** argv)
+{
+ xtest_init_devices();
+ xtest_properties();
+
+ return 0;
+}
+
+
diff --git a/xorg-server/xkeyboard-config/rules/base.extras.xml.in b/xorg-server/xkeyboard-config/rules/base.extras.xml.in
index 19f8fade7..4faff93c3 100644
--- a/xorg-server/xkeyboard-config/rules/base.extras.xml.in
+++ b/xorg-server/xkeyboard-config/rules/base.extras.xml.in
@@ -7,7 +7,7 @@
<configItem>
<name>apl</name>
<_shortDescription>APL</_shortDescription>
- <_description>APL</_description>
+ <_description>APL Keyboard Symbols</_description>
<languageList><iso639Id>eng</iso639Id></languageList>
</configItem>
<variantList/>
@@ -40,7 +40,7 @@
<configItem>
<name>ir</name>
<_shortDescription>Iran</_shortDescription>
- <_description>Iran</_description>
+ <_description>Persian</_description>
<languageList><iso639Id>per</iso639Id></languageList>
</configItem>
<variantList>
@@ -88,13 +88,13 @@
<variant>
<configItem>
<name>ykeydvorak</name>
- <_description>Latvian (US Dvorak, Y-letter variant)</_description>
+ <_description>Latvian (US Dvorak, Y variant)</_description>
</configItem>
</variant>
<variant>
<configItem>
<name>minuskeydvorak</name>
- <_description>Latvian (US Dvorak, minus-letter variant)</_description>
+ <_description>Latvian (US Dvorak, minus variant)</_description>
</configItem>
</variant>
<variant>
@@ -106,13 +106,13 @@
<variant>
<configItem>
<name>ykeydvorakprogr</name>
- <_description>Latvian (programmer US Dvorak, Y-letter variant)</_description>
+ <_description>Latvian (programmer US Dvorak, Y variant)</_description>
</configItem>
</variant>
<variant>
<configItem>
<name>minuskeydvorakprogr</name>
- <_description>Latvian (programmer US Dvorak - minus-letter variant)</_description>
+ <_description>Latvian (programmer US Dvorak, minus variant)</_description>
</configItem>
</variant>
<variant>
@@ -132,15 +132,15 @@
<layout>
<configItem>
<name>us</name>
- <_shortDescription>USA</_shortDescription>
- <_description>USA</_description>
+ <_shortDescription>en</_shortDescription>
+ <_description>English (US)</_description>
<languageList><iso639Id>eng</iso639Id></languageList>
</configItem>
<variantList>
<variant>
<configItem>
<name>intl-unicode</name>
- <_description>English (US, international (AltGr Unicode combining)</_description>
+ <_description>English (US, international AltGr Unicode combining)</_description>
</configItem>
</variant>
<variant>
@@ -185,7 +185,7 @@
<configItem>
<name>rs</name>
<_shortDescription>Srb</_shortDescription>
- <_description>Serbia</_description>
+ <_description>Serbian</_description>
<languageList><iso639Id>srp</iso639Id></languageList>
</configItem>
<variantList>
diff --git a/xorg-server/xkeyboard-config/symbols/apl b/xorg-server/xkeyboard-config/symbols/apl
index 4421cc398..0ebc26843 100644
--- a/xorg-server/xkeyboard-config/symbols/apl
+++ b/xorg-server/xkeyboard-config/symbols/apl
@@ -122,7 +122,7 @@ xkb_symbols "unified" {
default
partial alphanumeric_keys modifier_keys
xkb_symbols "sax" {
- name[Group1]= "APL Keyboard Symbols: Sharp APL for Unix";
+ name[Group1]= "APL Keyboard Symbols";
include "apl(unified)"
diff --git a/xorg-server/xkeyboard-config/symbols/et b/xorg-server/xkeyboard-config/symbols/et
index dccf9ca06..22ba892aa 100644
--- a/xorg-server/xkeyboard-config/symbols/et
+++ b/xorg-server/xkeyboard-config/symbols/et
@@ -14,7 +14,7 @@ xkb_symbols "basic" {
partial alphanumeric_keys
xkb_symbols "olpc" {
- name[Group1]="Ethiopia";
+ name[Group1]="Amharic";
key <AE01> { [ 0x01001369, 0x01001372 ] }; // 1
key <AE02> { [ 0x0100136a, 0x01001373 ] }; // 2
diff --git a/xorg-server/xkeyboard-config/symbols/lv b/xorg-server/xkeyboard-config/symbols/lv
index 97e4220fc..77a9458b0 100644
--- a/xorg-server/xkeyboard-config/symbols/lv
+++ b/xorg-server/xkeyboard-config/symbols/lv
@@ -452,7 +452,7 @@ xkb_symbols "ykeydvorakprogr" {
include "lv(dvorakprogr)"
- name[Group1]= "Latvian (programmer US-Dvorak, Y variant)";
+ name[Group1]= "Latvian (programmer US Dvorak, Y variant)";
key <AD05> {[ISO_Level3_Latch, ISO_Level3_Latch, y, Y]};
key <SPCE> {[space, space, y, Y]};
diff --git a/xorg-server/xkeyboard-config/symbols/us b/xorg-server/xkeyboard-config/symbols/us
index 19ddae869..1d8bdd0dd 100644
--- a/xorg-server/xkeyboard-config/symbols/us
+++ b/xorg-server/xkeyboard-config/symbols/us
@@ -992,7 +992,7 @@ partial alphanumeric_keys
xkb_symbols "olpc" {
include "us(basic)"
- name[Group1]= "USA";
+ name[Group1]= "English (US)";
// OLPC international US English keyboard layout.
// It's a little different from the usual international layout.
@@ -1146,7 +1146,7 @@ xkb_symbols "hbs" {
partial alphanumeric_keys
xkb_symbols "htcdream" {
include "inet(htcdream)"
- name[Group1]= "English (USA)";
+ name[Group1]= "English (US)";
//second row
key <AD01> { [ q, Q, Tab, Tab ] };
diff --git a/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh b/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh
index ccaaba7e0..90981a939 100644
--- a/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh
+++ b/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh
@@ -1,43 +1,51 @@
-#!/bin/sh
-
-#
-# This script compares the group names which "have to be", according to the descriptions in base.xml -
-# and actually existing in the symbol files. Some differences are ok (like extra double quotes or
-# extra escaping character) - but all the rest should be in sync.
-#
-
-ROOT="`dirname $0`/.."
-F1=reg2ll.lst
-F2=gn2ll.lst
-
-xsltproc $ROOT/xslt/reg2ll.xsl $ROOT/rules/base.xml | sort | uniq > $F1
-
-for i in $ROOT/symbols/*; do
- if [ -f $i ]; then
- id="`basename $i`"
- export id
- gawk 'BEGIN{
- FS = "\"";
- id = ENVIRON["id"];
- isDefault = 0;
-}
-/.*default.*/{
- isDefault = 1;
-}
-/xkb_symbols/{
- variant = $2;
-}/^[[:space:]]*name\[Group1\][[:space:]]*=/{
- if (isDefault == 1)
- {
- printf "%s:\"%s\"\n",id,$2;
- isDefault=0;
- } else
- {
- name=$2;
- printf "%s(%s):\"%s\"\n", id, variant, name;
- }
-}' $i
- fi
-done | sort | uniq > $F2
-
-diff $F1 $F2
+#!/bin/sh
+
+#
+# This script compares the group names which "have to be", according to the descriptions in base.xml -
+# and actually existing in the symbol files. Some differences are ok (like extra double quotes or
+# extra escaping character) - but all the rest should be in sync.
+#
+
+ROOT="`dirname $0`/.."
+F1=reg2ll.lst
+F2=gn2ll.lst
+F1b=${F1}base
+F1e=${F1}extras
+
+xsltproc $ROOT/xslt/reg2ll.xsl $ROOT/rules/base.xml > $F1b
+xsltproc $ROOT/xslt/reg2ll.xsl $ROOT/rules/base.extras.xml > $F1e
+cat $F1b $F1e | sort | uniq > $F1
+rm -f $F1e $F1e
+
+for i in $ROOT/symbols/*; do
+ if [ -f $i ]; then
+ id="`basename $i`"
+ export id
+ gawk 'BEGIN{
+ FS = "\"";
+ id = ENVIRON["id"];
+ isDefault = 0;
+}
+/.*default.*/{
+ isDefault = 1;
+}
+/xkb_symbols/{
+ variant = $2;
+}/^[[:space:]]*name\[Group1\][[:space:]]*=/{
+ if (isDefault == 1)
+ {
+ printf "%s:\"%s\"\n",id,$2;
+ isDefault=0;
+ } else
+ {
+ name=$2;
+ if (variant == "olpc" || variant == "htcdream")
+ printf "%s:\"%s\"\n", id, name;
+ else
+ printf "%s(%s):\"%s\"\n", id, variant, name;
+ }
+}' $i
+ fi
+done | sort | uniq > $F2
+
+diff $F1 $F2