From 5e633abcca598289d0423d89bb400b41e6417259 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 15 Mar 2011 21:35:41 +0000 Subject: xserver libX11 libxcb mesa git update 15 Mar 2011 --- xorg-server/Xi/xipassivegrab.c | 614 +-- xorg-server/Xi/xiproperty.c | 4 +- xorg-server/config/hal.c | 6 +- xorg-server/config/udev.c | 6 +- xorg-server/configure.ac | 4542 ++++++++--------- xorg-server/dix/devices.c | 5258 +++++++++---------- xorg-server/dix/eventconvert.c | 1537 +++--- xorg-server/dix/getevents.c | 2638 +++++----- xorg-server/dix/ptrveloc.c | 2413 ++++----- xorg-server/fb/fbpict.c | 746 +-- xorg-server/glx/glxdri.c | 44 +- xorg-server/glx/glxdri2.c | 39 +- xorg-server/glx/glxdricommon.c | 57 + xorg-server/glx/glxdricommon.h | 87 +- xorg-server/glx/glxdriswrast.c | 50 +- xorg-server/hw/dmx/dmx.h | 2 - xorg-server/hw/dmx/dmxpict.c | 87 - xorg-server/hw/dmx/dmxpict.h | 10 - xorg-server/hw/dmx/doc/Makefile.am | 557 +- xorg-server/hw/xfree86/Makefile.am | 238 +- xorg-server/hw/xfree86/common/xf86Configure.c | 1527 +++--- xorg-server/hw/xfree86/common/xf86Xinput.c | 2815 +++++----- xorg-server/hw/xfree86/doc/Makefile.am | 8 +- xorg-server/hw/xfree86/doc/man/Makefile.am | 3 - xorg-server/hw/xfree86/doc/man/Xorg.man | 689 --- xorg-server/hw/xfree86/doc/man/xorg.conf.d.man | 1 - xorg-server/hw/xfree86/doc/man/xorg.conf.man | 2478 --------- xorg-server/hw/xfree86/man/Makefile.am | 3 + xorg-server/hw/xfree86/man/Xorg.man | 689 +++ xorg-server/hw/xfree86/man/xorg.conf.d.man | 1 + xorg-server/hw/xfree86/man/xorg.conf.man | 2478 +++++++++ xorg-server/hw/xfree86/modes/xf86Crtc.c | 6479 ++++++++++++------------ xorg-server/hw/xfree86/os-support/xf86_OSlib.h | 833 ++- xorg-server/hw/xfree86/parser/scan.c | 11 +- xorg-server/include/input.h | 1188 +++-- xorg-server/include/misc.h | 592 +-- xorg-server/include/propertyst.h | 136 +- xorg-server/include/ptrveloc.h | 282 +- xorg-server/include/resource.h | 510 +- xorg-server/mi/mipointer.c | 1386 ++--- xorg-server/mi/mipointer.h | 1 + xorg-server/mi/misprite.c | 2087 ++++---- xorg-server/miext/cw/cw.h | 2 - xorg-server/miext/cw/cw_render.c | 64 - xorg-server/os/access.c | 19 - xorg-server/os/osinit.c | 623 ++- xorg-server/os/utils.c | 11 - xorg-server/os/xdmcp.c | 2 +- xorg-server/randr/randr.c | 1006 ++-- xorg-server/randr/randrstr.h | 1944 +++---- xorg-server/randr/rrcrtc.c | 2857 ++++++----- xorg-server/record/record.c | 5873 +++++++++++---------- xorg-server/render/mipict.c | 1254 +++-- xorg-server/render/mipict.h | 353 +- xorg-server/render/mitri.c | 200 +- xorg-server/render/picture.c | 45 +- xorg-server/render/picturestr.h | 2 - xorg-server/test/Makefile.am | 3 +- xorg-server/test/list.c | 176 + xorg-server/xkb/xkbActions.c | 2875 ++++++----- 60 files changed, 30234 insertions(+), 30207 deletions(-) delete mode 100644 xorg-server/hw/xfree86/doc/man/Makefile.am delete mode 100644 xorg-server/hw/xfree86/doc/man/Xorg.man delete mode 100644 xorg-server/hw/xfree86/doc/man/xorg.conf.d.man delete mode 100644 xorg-server/hw/xfree86/doc/man/xorg.conf.man create mode 100644 xorg-server/hw/xfree86/man/Makefile.am create mode 100644 xorg-server/hw/xfree86/man/Xorg.man create mode 100644 xorg-server/hw/xfree86/man/xorg.conf.d.man create mode 100644 xorg-server/hw/xfree86/man/xorg.conf.man create mode 100644 xorg-server/test/list.c (limited to 'xorg-server') diff --git a/xorg-server/Xi/xipassivegrab.c b/xorg-server/Xi/xipassivegrab.c index 8663d12a1..487c2721b 100644 --- a/xorg-server/Xi/xipassivegrab.c +++ b/xorg-server/Xi/xipassivegrab.c @@ -1,307 +1,307 @@ -/* - * 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 -#endif - -#include "inputstr.h" /* DeviceIntPtr */ -#include "windowstr.h" /* window structure */ -#include -#include -#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(¶m, 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, ¶m); - - 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, - ¶m, GRABTYPE_XI2, &mask); - break; - case XIGrabtypeKeycode: - status = GrabKey(client, dev, mod_dev, stuff->detail, - ¶m, GRABTYPE_XI2, &mask); - break; - case XIGrabtypeEnter: - case XIGrabtypeFocusIn: - status = GrabWindow(client, dev, stuff->grab_type, - ¶m, &mask); - break; - } - - if (status != GrabSuccess) - { - xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers; - - info->status = status; - info->modifiers = *modifiers; - rep.num_modifiers++; - rep.length++; - } - } - - WriteReplyToClient(client, sizeof(rep), &rep); - if (rep.num_modifiers) - { - client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; - WriteSwappedDataToClient(client, rep.num_modifiers * 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 +#endif + +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include +#include +#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(¶m, 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, ¶m); + + 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, + ¶m, GRABTYPE_XI2, &mask); + break; + case XIGrabtypeKeycode: + status = GrabKey(client, dev, mod_dev, stuff->detail, + ¶m, GRABTYPE_XI2, &mask); + break; + case XIGrabtypeEnter: + case XIGrabtypeFocusIn: + status = GrabWindow(client, dev, stuff->grab_type, + ¶m, &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; +} diff --git a/xorg-server/Xi/xiproperty.c b/xorg-server/Xi/xiproperty.c index c1a25bbf7..b10891d1c 100644 --- a/xorg-server/Xi/xiproperty.c +++ b/xorg-server/Xi/xiproperty.c @@ -1051,11 +1051,11 @@ SProcXChangeDeviceProperty (ClientPtr client) char n; REQUEST(xChangeDevicePropertyReq); + REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq); swaps(&stuff->length, n); swapl(&stuff->property, n); swapl(&stuff->type, n); swapl(&stuff->nUnits, n); - REQUEST_SIZE_MATCH(xChangeDevicePropertyReq); return (ProcXChangeDeviceProperty(client)); } @@ -1295,12 +1295,12 @@ SProcXIChangeProperty(ClientPtr client) char n; REQUEST(xXIChangePropertyReq); + REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq); swaps(&stuff->length, n); swaps(&stuff->deviceid, n); swapl(&stuff->property, n); swapl(&stuff->type, n); swapl(&stuff->num_items, n); - REQUEST_SIZE_MATCH(xXIChangePropertyReq); return (ProcXIChangeProperty(client)); } diff --git a/xorg-server/config/hal.c b/xorg-server/config/hal.c index 2aff6f9fd..929643653 100644 --- a/xorg-server/config/hal.c +++ b/xorg-server/config/hal.c @@ -392,10 +392,10 @@ unwind: free(driver); free(name); free(config_info); - while (!dev && (tmpo = options)) { + while ((tmpo = options)) { options = tmpo->next; - free(tmpo->key); - free(tmpo->value); + free(tmpo->key); /* NULL if dev != NULL */ + free(tmpo->value); /* NULL if dev != NULL */ free(tmpo); } diff --git a/xorg-server/config/udev.c b/xorg-server/config/udev.c index eeacff162..44319e4db 100644 --- a/xorg-server/config/udev.c +++ b/xorg-server/config/udev.c @@ -197,10 +197,10 @@ device_added(struct udev_device *udev_device) unwind: free(config_info); - while (!dev && (tmpo = options)) { + while ((tmpo = options)) { options = tmpo->next; - free(tmpo->key); - free(tmpo->value); + free(tmpo->key); /* NULL if dev != NULL */ + free(tmpo->value); /* NULL if dev != NULL */ free(tmpo); } diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index 681f9d9c5..83ec3f9d0 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -1,2271 +1,2271 @@ -dnl Copyright © 2003-2007 Keith Packard, Daniel Stone -dnl -dnl Permission is hereby granted, free of charge, to any person obtaining a -dnl copy of this software and associated documentation files (the "Software"), -dnl to deal in the Software without restriction, including without limitation -dnl the rights to use, copy, modify, merge, publish, distribute, sublicense, -dnl and/or sell copies of the Software, and to permit persons to whom the -dnl Software is furnished to do so, subject to the following conditions: -dnl -dnl The above copyright notice and this permission notice (including the next -dnl paragraph) shall be included in all copies or substantial portions of the -dnl Software. -dnl -dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -dnl IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -dnl DEALINGS IN THE SOFTWARE. -dnl -dnl Authors: Keith Packard -dnl Daniel Stone -dnl an unwitting cast of miscellaneous others -dnl -dnl Process this file with autoconf to create configure. - -AC_PREREQ(2.57) -AC_INIT([xorg-server], 1.10.99.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) -RELEASE_DATE="unreleased" -AC_CONFIG_SRCDIR([Makefile.am]) -AM_INIT_AUTOMAKE([foreign dist-bzip2]) -AM_MAINTAINER_MODE - -# Require xorg-macros minimum of 1.10 for XORG_CHECK_SGML_DOCTOOLS -m4_ifndef([XORG_MACROS_VERSION], - [m4_fatal([must install xorg-macros 1.10 or later before running autoconf/autogen])]) -XORG_MACROS_VERSION(1.10) -XORG_DEFAULT_OPTIONS -XORG_WITH_DOXYGEN(1.6.1) -XORG_CHECK_SGML_DOCTOOLS(1.5) - -m4_ifndef([XORG_FONT_MACROS_VERSION], [m4_fatal([must install fontutil 1.1 or later before running autoconf/autogen])]) -XORG_FONT_MACROS_VERSION(1.1) - -dnl this gets generated by autoheader, and thus contains all the defines. we -dnl don't ever actually use it, internally. -AC_CONFIG_HEADERS(include/do-not-use-config.h) -dnl xorg-server.h is an external header, designed to be included by loadable -dnl drivers. -AC_CONFIG_HEADERS(include/xorg-server.h) -dnl dix-config.h covers most of the DIX (i.e. everything but the DDX, not just -dnl dix/). -AC_CONFIG_HEADERS(include/dix-config.h) -dnl xorg-config.h covers the Xorg DDX. -AC_CONFIG_HEADERS(include/xorg-config.h) -dnl xkb-config.h covers XKB for the Xorg and Xnest DDXs. -AC_CONFIG_HEADERS(include/xkb-config.h) -dnl xwin-config.h covers the XWin DDX. -AC_CONFIG_HEADERS(include/xwin-config.h) -dnl kdrive-config.h covers the kdrive DDX -AC_CONFIG_HEADERS(include/kdrive-config.h) -dnl version-config.h covers the version numbers so they can be bumped without -dnl forcing an entire recompile.x -AC_CONFIG_HEADERS(include/version-config.h) - -AM_PROG_AS -AC_PROG_LN_S -AC_LIBTOOL_WIN32_DLL -AC_DISABLE_STATIC -AC_PROG_LIBTOOL -AC_PROG_MAKE_SET -PKG_PROG_PKG_CONFIG -AC_PROG_LEX -AC_PROG_YACC -AC_SYS_LARGEFILE -XORG_PROG_RAWCPP - -# Quoted so that make will expand $(CWARNFLAGS) in makefiles to allow -# easier overrides at build time. -XSERVER_CFLAGS='$(CWARNFLAGS)' - -dnl Check for dtrace program (needed to build Xserver dtrace probes) -dnl Also checks for , since some Linux distros have an -dnl ISDN trace program named dtrace -AC_ARG_WITH(dtrace, AS_HELP_STRING([--with-dtrace=PATH], - [Enable dtrace probes (default: enabled if dtrace found)]), - [WDTRACE=$withval], [WDTRACE=auto]) -if test "x$WDTRACE" = "xyes" -o "x$WDTRACE" = "xauto" ; then - AC_PATH_PROG(DTRACE, [dtrace], [not_found], [$PATH:/usr/sbin]) - if test "x$DTRACE" = "xnot_found" ; then - if test "x$WDTRACE" = "xyes" ; then - AC_MSG_FAILURE([dtrace requested but not found]) - fi - WDTRACE="no" - else - AC_CHECK_HEADER(sys/sdt.h, [HAS_SDT_H="yes"], [HAS_SDT_H="no"]) - if test "x$WDTRACE" = "xauto" -a "x$HAS_SDT_H" = "xno" ; then - WDTRACE="no" - fi - fi -fi -if test "x$WDTRACE" != "xno" ; then - AC_DEFINE(XSERVER_DTRACE, 1, - [Define to 1 if the DTrace Xserver provider probes should be built in.]) - -# Solaris/OpenSolaris require dtrace -G to build dtrace probe information into -# object files, and require linking with those as relocatable objects, not .a -# archives. MacOS X handles all this in the normal compiler toolchain, and on -# some releases (like Tiger), will error out on dtrace -G. For now, other -# platforms with Dtrace ports are assumed to support -G (the FreeBSD and Linux -# ports appear to, based on my web searches, but have not yet been tested). - case $host_os in - darwin*) SPECIAL_DTRACE_OBJECTS=no ;; - *) SPECIAL_DTRACE_OBJECTS=yes ;; - esac -fi -AM_CONDITIONAL(XSERVER_DTRACE, [test "x$WDTRACE" != "xno"]) -AM_CONDITIONAL(SPECIAL_DTRACE_OBJECTS, [test "x$SPECIAL_DTRACE_OBJECTS" = "xyes"]) - -AC_HEADER_DIRENT -AC_HEADER_STDC -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h sys/utsname.h]) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_C_BIGENDIAN([ENDIAN="X_BIG_ENDIAN"], [ENDIAN="X_LITTLE_ENDIAN"]) - -AC_CHECK_SIZEOF([unsigned long]) -if test "$ac_cv_sizeof_unsigned_long" = 8; then - AC_DEFINE(_XSERVER64, 1, [Define to 1 if unsigned long is 64 bits.]) -fi - -AC_TYPE_PID_T - -# Checks for headers/macros for byte swapping -# Known variants: -# bswap_16, bswap_32, bswap_64 (glibc) -# __swap16, __swap32, __swap64 (OpenBSD) -# bswap16, bswap32, bswap64 (other BSD's) -# and a fallback to local macros if none of the above are found - -# if is found, assume it's the correct version -AC_CHECK_HEADERS([byteswap.h]) - -# if is found, have to check which version -AC_CHECK_HEADER([sys/endian.h], [HAVE_SYS_ENDIAN_H="yes"], [HAVE_SYS_ENDIAN_H="no"]) - -if test "x$HAVE_SYS_ENDIAN_H" = "xyes" ; then - AC_MSG_CHECKING([for __swap16 variant of byteswapping macros]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([ -#include -#include - ], [ -int a = 1, b; -b = __swap16(a); - ]) -], [SYS_ENDIAN__SWAP='yes'], [SYS_ENDIAN__SWAP='no']) - AC_MSG_RESULT([$SYS_ENDIAN__SWAP]) - - AC_MSG_CHECKING([for bswap16 variant of byteswapping macros]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([ -#include -#include - ], [ -int a = 1, b; -b = bswap16(a); - ]) -], [SYS_ENDIAN_BSWAP='yes'], [SYS_ENDIAN_BSWAP='no']) - AC_MSG_RESULT([$SYS_ENDIAN_BSWAP]) - - if test "$SYS_ENDIAN_BSWAP" = "yes" ; then - USE_SYS_ENDIAN_H=yes - BSWAP=bswap - else - if test "$SYS_ENDIAN__SWAP" = "yes" ; then - USE_SYS_ENDIAN_H=yes - BSWAP=__swap - else - USE_SYS_ENDIAN_H=no - fi - fi - - if test "$USE_SYS_ENDIAN_H" = "yes" ; then - AC_DEFINE([USE_SYS_ENDIAN_H], 1, - [Define to use byteswap macros from ]) - AC_DEFINE_UNQUOTED([bswap_16], ${BSWAP}16, - [Define to 16-bit byteswap macro]) - AC_DEFINE_UNQUOTED([bswap_32], ${BSWAP}32, - [Define to 32-bit byteswap macro]) - AC_DEFINE_UNQUOTED([bswap_64], ${BSWAP}64, - [Define to 64-bit byteswap macro]) - fi -fi - -dnl Check to see if dlopen is in default libraries (like Solaris, which -dnl has it in libc), or if libdl is needed to get it. -AC_CHECK_FUNC([dlopen], [], - AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl")) -AC_SUBST(DLOPEN_LIBS) - -dnl Checks for library functions. -AC_FUNC_VPRINTF -AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr \ - strtol getopt getopt_long vsnprintf walkcontext backtrace \ - getisax getzoneid shmctl64 strcasestr ffs vasprintf]) -AC_FUNC_ALLOCA -dnl Old HAS_* names used in os/*.c. -AC_CHECK_FUNC([getdtablesize], - AC_DEFINE(HAS_GETDTABLESIZE, 1, [Have the 'getdtablesize' function.])) -AC_CHECK_FUNC([getifaddrs], - AC_DEFINE(HAS_GETIFADDRS, 1, [Have the 'getifaddrs' function.])) -AC_CHECK_FUNC([getpeereid], - AC_DEFINE(HAS_GETPEEREID, 1, [Have the 'getpeereid' function.])) -AC_CHECK_FUNC([getpeerucred], - AC_DEFINE(HAS_GETPEERUCRED, 1, [Have the 'getpeerucred' function.])) -AC_CHECK_FUNC([strlcat], HAVE_STRLCAT=yes, HAVE_STRLCAT=no) -AM_CONDITIONAL(NEED_STRLCAT, [test x$HAVE_STRLCAT = xno]) -AC_CHECK_FUNC([strlcpy], AC_DEFINE(HAS_STRLCPY, 1, [Have the 'strlcpy' function])) - -AM_CONDITIONAL(NEED_VSNPRINTF, [test x$HAVE_VSNPRINTF = xno]) - -dnl Check for mmap support for Xvfb -AC_CHECK_FUNC([mmap], AC_DEFINE(HAS_MMAP, 1, [Have the 'mmap' function.])) - -dnl Find the math libary -AC_CHECK_LIB(m, sqrt) -AC_CHECK_LIB(m, cbrt, AC_DEFINE(HAVE_CBRT, 1, [Have the 'cbrt' function])) - -AC_CHECK_HEADERS([ndbm.h dbm.h rpcsvc/dbm.h]) - -dnl AGPGART headers -AC_CHECK_HEADERS([linux/agpgart.h sys/agpio.h sys/agpgart.h], AGP=yes) -AM_CONDITIONAL(AGP, [test "x$AGP" = xyes]) - -dnl APM header -AC_CHECK_HEADERS([linux/apm_bios.h], LNXAPM=yes) -AM_CONDITIONAL(LNXAPM, [test "x$LNXAPM" = xyes]) - -dnl fbdev header -AC_CHECK_HEADERS([linux/fb.h], FBDEV=yes) -AM_CONDITIONAL(FBDEVHW, [test "x$FBDEV" = xyes]) - -dnl MTRR header -AC_CHECK_HEADERS([asm/mtrr.h], ac_cv_asm_mtrr_h=yes) -if test "x$ac_cv_asm_mtrr_h" = xyes; then - HAVE_MTRR=yes -fi - -dnl BSD MTRR header -AC_CHECK_HEADERS([sys/memrange.h], ac_cv_memrange_h=yes) -if test "x$ac_cv_memrange_h" = xyes; then - HAVE_MTRR=yes -fi - -if test "x$HAVE_MTRR" = xyes; then - AC_DEFINE(HAS_MTRR_SUPPORT, 1, [MTRR support available]) -fi - -dnl A NetBSD MTRR header -AC_CHECK_HEADERS([machine/mtrr.h], ac_cv_machine_mtrr_h=yes) -if test "x$ac_cv_machine_mtrr_h" = xyes; then - AC_DEFINE(HAS_MTRR_BUILTIN, 1, [Define to 1 if NetBSD built-in MTRR - support is available]) -fi - -dnl FreeBSD kldload support (sys/linker.h) -AC_CHECK_HEADERS([sys/linker.h], - [ac_cv_sys_linker_h=yes], - [ac_cv_sys_linker_h=no], - [#include ]) -AM_CONDITIONAL(FREEBSD_KLDLOAD, [test "x$ac_cv_sys_linker_h" = xyes]) - -AC_CACHE_CHECK([for SYSV IPC], - ac_cv_sysv_ipc, - [AC_TRY_LINK([ -#include -#include -#include -],[ -{ - int id; - id = shmget(IPC_PRIVATE, 512, SHM_W | SHM_R); - if (id < 0) return -1; - return shmctl(id, IPC_RMID, 0); -}], - [ac_cv_sysv_ipc=yes], - [ac_cv_sysv_ipc=no])]) -if test "x$ac_cv_sysv_ipc" = xyes; then - AC_DEFINE(HAVE_SYSV_IPC, 1, [Define to 1 if SYSV IPC is available]) -fi - -dnl OpenBSD /dev/xf86 aperture driver -if test -c /dev/xf86 ; then - AC_DEFINE(HAS_APERTURE_DRV, 1, [System has /dev/xf86 aperture driver]) -fi - -dnl BSD APM support -AC_CHECK_HEADER([machine/apmvar.h],[ - AC_CHECK_HEADER([sys/event.h], - ac_cv_BSD_KQUEUE_APM=yes, - ac_cv_BSD_APM=yes)]) - -AM_CONDITIONAL(BSD_APM, [test "x$ac_cv_BSD_APM" = xyes]) -AM_CONDITIONAL(BSD_KQUEUE_APM, [test "x$ac_cv_BSD_KQUEUE_APM" = xyes]) - -dnl glibc backtrace support check (hw/xfree86/common/xf86Events.c) -AC_CHECK_HEADER([execinfo.h],[ - AC_CHECK_LIB(c, backtrace, [ - AC_DEFINE(HAVE_BACKTRACE, 1, [Has backtrace support]) - AC_DEFINE(HAVE_EXECINFO_H, 1, [Have execinfo.h]) - ])] -) - -dnl --------------------------------------------------------------------------- -dnl Bus options and CPU capabilities. Replaces logic in -dnl hw/xfree86/os-support/bus/Makefile.am, among others. -dnl --------------------------------------------------------------------------- -DEFAULT_INT10="x86emu" - -dnl Override defaults as needed for specific platforms: - -case $host_cpu in - alpha*) - ALPHA_VIDEO=yes - case $host_os in - *freebsd*) SYS_LIBS=-lio ;; - *netbsd*) AC_DEFINE(USE_ALPHA_PIO, 1, [NetBSD PIO alpha IO]) ;; - esac - GLX_ARCH_DEFINES="-D__GLX_ALIGN64 -mieee" - ;; - arm*) - ARM_VIDEO=yes - ;; - i*86) - I386_VIDEO=yes - case $host_os in - *freebsd*) AC_DEFINE(USE_DEV_IO) ;; - *dragonfly*) AC_DEFINE(USE_DEV_IO) ;; - *netbsd*) AC_DEFINE(USE_I386_IOPL) - SYS_LIBS=-li386 - ;; - *openbsd*) AC_DEFINE(USE_I386_IOPL) - SYS_LIBS=-li386 - ;; - esac - ;; - powerpc*) - PPC_VIDEO=yes - case $host_os in - *freebsd*) DEFAULT_INT10=stub ;; - esac - ;; - sparc*) - SPARC64_VIDEO=yes - BSD_ARCH_SOURCES="sparc64_video.c ioperm_noop.c" - GLX_ARCH_DEFINES="-D__GLX_ALIGN64" - ;; - x86_64*|amd64*) - I386_VIDEO=yes - case $host_os in - *freebsd*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; - *dragonfly*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; - *netbsd*) AC_DEFINE(USE_I386_IOPL, 1, [BSD i386 iopl]) - SYS_LIBS=-lx86_64 - ;; - *openbsd*) AC_DEFINE(USE_AMD64_IOPL, 1, [BSD AMD64 iopl]) - SYS_LIBS=-lamd64 - ;; - esac - GLX_ARCH_DEFINES="-D__GLX_ALIGN64" - ;; - ia64*) - GLX_ARCH_DEFINES="-D__GLX_ALIGN64" - ;; - s390*) - GLX_ARCH_DEFINES="-D__GLX_ALIGN64" - ;; -esac -AC_SUBST(GLX_ARCH_DEFINES) - -dnl BSD *_video.c selection -AM_CONDITIONAL(ALPHA_VIDEO, [test "x$ALPHA_VIDEO" = xyes]) -AM_CONDITIONAL(ARM_VIDEO, [test "x$ARM_VIDEO" = xyes]) -AM_CONDITIONAL(I386_VIDEO, [test "x$I386_VIDEO" = xyes]) -AM_CONDITIONAL(PPC_VIDEO, [test "x$PPC_VIDEO" = xyes]) -AM_CONDITIONAL(SPARC64_VIDEO, [test "x$SPARC64_VIDEO" = xyes]) - -DRI=no -USE_SIGIO_BY_DEFAULT="yes" -dnl it would be nice to autodetect these *CONS_SUPPORTs -case $host_os in - *freebsd* | *dragonfly*) - case $host_os in - kfreebsd*-gnu) ;; - *) AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) ;; - esac - AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) - AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) - AC_DEFINE(SYSCONS_SUPPORT, 1, [System has syscons console]) - DRI=yes - ;; - *netbsd*) - AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) - AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) - AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) - AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) - DRI=yes - ;; - *openbsd*) - AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) - AC_DEFINE(PCVT_SUPPORT, 1, [System has PC console]) - AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) - ;; - *linux*) - DRI=yes - ;; - *solaris*) - PKG_CHECK_EXISTS(libdrm, DRI=yes, DRI=no) - # Disable use of SIGIO by default until some system bugs are - # fixed - see Sun/OpenSolaris bug id 6879897 - USE_SIGIO_BY_DEFAULT="no" - ;; - darwin*) - AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) - ;; - cygwin*) - CFLAGS="$CFLAGS -DFD_SETSIZE=256" - ;; -esac - -dnl augment XORG_RELEASE_VERSION for our snapshot number and to expose the -dnl major number -PVMAJOR=`echo $PACKAGE_VERSION | cut -d . -f 1` -PVS=`echo $PACKAGE_VERSION | cut -d . -f 4 | cut -d - -f 1` -if test "x$PVS" = "x"; then - PVS="0" -fi - -VENDOR_RELEASE="((($PVMAJOR) * 10000000) + (($PVM) * 100000) + (($PVP) * 1000) + $PVS)" -VENDOR_MAN_VERSION="Version ${PACKAGE_VERSION}" - -VENDOR_NAME="The X.Org Foundation" -VENDOR_NAME_SHORT="X.Org" -VENDOR_WEB="http://wiki.x.org" - -m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))]) - -dnl Build options. -AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], - [Obsolete - use --enable-strict-compilation instead]), - AC_MSG_ERROR([--enable-werror has been replaced by --enable-strict-compilation])) - -AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], - [Enable debugging (default: disabled)]), - [DEBUGGING=$enableval], [DEBUGGING=no]) -AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--enable-unit-tests], - [Enable unit-tests (default: auto)]), - [UNITTESTS=$enableval], [UNITTESTS=auto]) -AC_ARG_ENABLE(use-sigio-by-default, AS_HELP_STRING([--enable-use-sigio-by-default] - [Enable SIGIO input handlers by default (default: $USE_SIGIO_BY_DEFAULT)]), - [USE_SIGIO_BY_DEFAULT=$enableval], []) -AC_ARG_WITH(int10, AS_HELP_STRING([--with-int10=BACKEND], [int10 backend: vm86, x86emu or stub]), - [INT10="$withval"], - [INT10="$DEFAULT_INT10"]) -AC_ARG_WITH(vendor-name, AS_HELP_STRING([--with-vendor-name=VENDOR], - [Vendor string reported by the server]), - [ VENDOR_NAME="$withval" ], []) -AC_ARG_WITH(vendor-name-short, AS_HELP_STRING([--with-vendor-name-short=VENDOR], - [Short version of vendor string reported by the server]), - [ VENDOR_NAME_SHORT="$withval" ], []) -AC_ARG_WITH(vendor-web, AS_HELP_STRING([--with-vendor-web=URL], - [Vendor web address reported by the server]), - [ VENDOR_WEB="$withval" ], []) -AC_ARG_WITH(module-dir, AS_HELP_STRING([--with-module-dir=DIR], - [Directory where modules are installed (default: $libdir/xorg/modules)]), - [ moduledir="$withval" ], - [ moduledir="${libdir}/xorg/modules" ]) -AC_ARG_WITH(log-dir, AS_HELP_STRING([--with-log-dir=DIR], - [Directory where log files are kept (default: $localstatedir/log)]), - [ logdir="$withval" ], - [ logdir="$localstatedir/log" ]) -AC_ARG_WITH(builder-addr, AS_HELP_STRING([--with-builder-addr=ADDRESS], - [Builder address (default: xorg@lists.freedesktop.org)]), - [ BUILDERADDR="$withval" ], - [ BUILDERADDR="xorg@lists.freedesktop.org" ]) -AC_ARG_WITH(os-name, AS_HELP_STRING([--with-os-name=OSNAME], [Name of OS (default: output of "uname -srm")]), - [ OSNAME="$withval" ], - [ OSNAME=`uname -srm` ]) -AC_ARG_WITH(os-vendor, AS_HELP_STRING([--with-os-vendor=OSVENDOR], [Name of OS vendor]), - [ OSVENDOR="$withval" ], - [ OSVENDOR="" ]) -AC_ARG_WITH(builderstring, AS_HELP_STRING([--with-builderstring=BUILDERSTRING], [Additional builder string]), - [ BUILDERSTRING="$withval" ] - [ ]) - -dnl Determine font path -XORG_FONTROOTDIR -XORG_FONTSUBDIR(FONTMISCDIR, fontmiscdir, misc) -XORG_FONTSUBDIR(FONTOTFDIR, fontotfdir, OTF) -XORG_FONTSUBDIR(FONTTTFDIR, fontttfdir, TTF) -XORG_FONTSUBDIR(FONTTYPE1DIR, fonttype1dir, Type1) -XORG_FONTSUBDIR(FONT75DPIDIR, font75dpidir, 75dpi) -XORG_FONTSUBDIR(FONT100DPIDIR, font100dpidir, 100dpi) - -dnl Uses --default-font-path if set, otherwise checks for /etc/X11/fontpath.d, -dnl otherwise uses standard subdirectories of FONTROOTDIR. When cross -dnl compiling, assume default font path uses standard FONTROOTDIR directories. -DEFAULT_FONT_PATH="${FONTMISCDIR}/,${FONTTTFDIR}/,${FONTOTFDIR}/,${FONTTYPE1DIR}/,${FONT100DPIDIR}/,${FONT75DPIDIR}/" -if test "$cross_compiling" != yes; then - AC_CHECK_FILE([${sysconfdir}/X11/fontpath.d], - [DEFAULT_FONT_PATH='catalogue:${sysconfdir}/X11/fontpath.d'], - [case $host_os in - darwin*) DEFAULT_FONT_PATH="${DEFAULT_FONT_PATH},/Library/Fonts,/System/Library/Fonts" ;; - esac]) -fi -AC_ARG_WITH(default-font-path, AS_HELP_STRING([--with-default-font-path=PATH], [Comma separated list of font dirs]), - [ FONTPATH="$withval" ], - [ FONTPATH="${DEFAULT_FONT_PATH}" ]) - -AC_MSG_CHECKING([for default font path]) -AC_MSG_RESULT([$FONTPATH]) - -AC_ARG_WITH(xkb-path, AS_HELP_STRING([--with-xkb-path=PATH], [Path to XKB base dir (default: ${datadir}/X11/xkb)]), - [ XKBPATH="$withval" ], - [ XKBPATH="${datadir}/X11/xkb" ]) -AC_ARG_WITH(xkb-output, AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${datadir}/X11/xkb/compiled)]), - [ XKBOUTPUT="$withval" ], - [ XKBOUTPUT="compiled" ]) -AC_ARG_WITH(default-xkb-rules, AS_HELP_STRING([--with-default-xkb-rules=RULES], - [Keyboard ruleset (default: base/evdev)]), - [ XKB_DFLT_RULES="$withval" ], - [ XKB_DFLT_RULES="" ]) -AC_ARG_WITH(default-xkb-model, AS_HELP_STRING([--with-default-xkb-model=MODEL], - [Keyboard model (default: pc105)]), - [ XKB_DFLT_MODEL="$withval" ], - [ XKB_DFLT_MODEL="pc105" ]) -AC_ARG_WITH(default-xkb-layout, AS_HELP_STRING([--with-default-xkb-layout=LAYOUT], - [Keyboard layout (default: us)]), - [ XKB_DFLT_LAYOUT="$withval" ], - [ XKB_DFLT_LAYOUT="us" ]) -AC_ARG_WITH(default-xkb-variant, AS_HELP_STRING([--with-default-xkb-variant=VARIANT], - [Keyboard variant (default: (none))]), - [ XKB_DFLT_VARIANT="$withval" ], - [ XKB_DFLT_VARIANT="" ]) -AC_ARG_WITH(default-xkb-options, AS_HELP_STRING([--with-default-xkb-options=OPTIONS], - [Keyboard layout options (default: (none))]), - [ XKB_DFLT_OPTIONS="$withval" ], - [ XKB_DFLT_OPTIONS="" ]) -AC_ARG_WITH(serverconfig-path, AS_HELP_STRING([--with-serverconfig-path=PATH], - [Directory where ancillary server config files are installed (default: ${libdir}/xorg)]), - [ SERVERCONFIG="$withval" ], - [ SERVERCONFIG="${libdir}/xorg" ]) -AC_ARG_WITH(apple-applications-dir,AS_HELP_STRING([--with-apple-applications-dir=PATH], [Path to the Applications directory (default: /Applications/Utilities)]), - [ APPLE_APPLICATIONS_DIR="${withval}" ], - [ APPLE_APPLICATIONS_DIR="/Applications/Utilities" ]) -AC_SUBST([APPLE_APPLICATIONS_DIR]) -AC_ARG_WITH(apple-application-name,AS_HELP_STRING([--with-apple-application-name=NAME], [Name for the .app (default: X11)]), - [ APPLE_APPLICATION_NAME="${withval}" ], - [ APPLE_APPLICATION_NAME="X11" ]) -AC_SUBST([APPLE_APPLICATION_NAME]) -AC_ARG_WITH(launchd-id-prefix, AS_HELP_STRING([--with-launchd-id-prefix=PATH], [Prefix to use for launchd identifiers (default: org.x)]), - [ LAUNCHD_ID_PREFIX="${withval}" ], - [ LAUNCHD_ID_PREFIX="org.x" ]) -AC_SUBST([LAUNCHD_ID_PREFIX]) -AC_DEFINE_UNQUOTED(LAUNCHD_ID_PREFIX, "$LAUNCHD_ID_PREFIX", [Prefix to use for launchd identifiers]) -AC_ARG_ENABLE(sparkle,AS_HELP_STRING([--enable-sparkle], [Enable updating of X11.app using the Sparkle Framework (default: disabled)]), - [ XQUARTZ_SPARKLE="${enableval}" ], - [ XQUARTZ_SPARKLE="no" ]) -AC_SUBST([XQUARTZ_SPARKLE]) -AC_ARG_ENABLE(install-libxf86config, - AS_HELP_STRING([--enable-install-libxf86config], - [Install libxf86config (default: disabled)]), - [INSTALL_LIBXF86CONFIG=$enableval], - [INSTALL_LIBXF86CONFIG=no]) -AC_ARG_ENABLE(visibility, AC_HELP_STRING([--enable-visibility], [Enable symbol visibility (default: auto)]), - [SYMBOL_VISIBILITY=$enableval], - [SYMBOL_VISIBILITY=auto]) -AC_ARG_ENABLE(pc98, AC_HELP_STRING([--enable-pc98], [Enable PC98 support in Xorg (default: auto)]), - [SUPPORT_PC98=$enableval], - [SUPPORT_PC98=auto]) - -dnl GLX build options -AC_ARG_ENABLE(aiglx, AS_HELP_STRING([--enable-aiglx], [Build accelerated indirect GLX (default: enabled)]), - [AIGLX=$enableval], - [AIGLX=yes]) -AX_TLS -AC_ARG_ENABLE(glx-tls, AS_HELP_STRING([--enable-glx-tls], [Build GLX with TLS support (default: auto)]), - [GLX_USE_TLS=$enableval], - [GLX_USE_TLS=no - if test "${ac_cv_tls}" != "none" ; then - GLX_USE_TLS=yes - fi]) -AC_SUBST(GLX_TLS, ${GLX_USE_TLS}) - -dnl Extensions. -AC_ARG_ENABLE(registry, AS_HELP_STRING([--disable-registry], [Build string registry module (default: enabled)]), [XREGISTRY=$enableval], [XREGISTRY=yes]) -AC_ARG_ENABLE(composite, AS_HELP_STRING([--disable-composite], [Build Composite extension (default: enabled)]), [COMPOSITE=$enableval], [COMPOSITE=yes]) -AC_ARG_ENABLE(mitshm, AS_HELP_STRING([--disable-shm], [Build SHM extension (default: enabled)]), [MITSHM=$enableval], [MITSHM=yes]) -AC_ARG_ENABLE(xres, AS_HELP_STRING([--disable-xres], [Build XRes extension (default: enabled)]), [RES=$enableval], [RES=yes]) -AC_ARG_ENABLE(record, AS_HELP_STRING([--disable-record], [Build Record extension (default: enabled)]), [RECORD=$enableval], [RECORD=yes]) -AC_ARG_ENABLE(xv, AS_HELP_STRING([--disable-xv], [Build Xv extension (default: enabled)]), [XV=$enableval], [XV=yes]) -AC_ARG_ENABLE(xvmc, AS_HELP_STRING([--disable-xvmc], [Build XvMC extension (default: enabled)]), [XVMC=$enableval], [XVMC=yes]) -AC_ARG_ENABLE(dga, AS_HELP_STRING([--disable-dga], [Build DGA extension (default: auto)]), [DGA=$enableval], [DGA=auto]) -AC_ARG_ENABLE(screensaver, AS_HELP_STRING([--disable-screensaver], [Build ScreenSaver extension (default: enabled)]), [SCREENSAVER=$enableval], [SCREENSAVER=yes]) -AC_ARG_ENABLE(xdmcp, AS_HELP_STRING([--disable-xdmcp], [Build XDMCP extension (default: auto)]), [XDMCP=$enableval], [XDMCP=auto]) -AC_ARG_ENABLE(xdm-auth-1, AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-Auth-1 extension (default: auto)]), [XDMAUTH=$enableval], [XDMAUTH=auto]) -AC_ARG_ENABLE(glx, AS_HELP_STRING([--disable-glx], [Build GLX extension (default: enabled)]), [GLX=$enableval], [GLX=yes]) -AC_ARG_ENABLE(dri, AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval]) -AC_ARG_ENABLE(dri2, AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto]) -AC_ARG_ENABLE(xinerama, AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes]) -AC_ARG_ENABLE(xf86vidmode, AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto]) -AC_ARG_ENABLE(xace, AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes]) -AC_ARG_ENABLE(xselinux, AS_HELP_STRING([--enable-xselinux], [Build SELinux extension (default: disabled)]), [XSELINUX=$enableval], [XSELINUX=no]) -AC_ARG_ENABLE(xcsecurity, AS_HELP_STRING([--enable-xcsecurity], [Build Security extension (default: disabled)]), [XCSECURITY=$enableval], [XCSECURITY=no]) -AC_ARG_ENABLE(tslib, AS_HELP_STRING([--enable-tslib], [Build kdrive tslib touchscreen support (default: disabled)]), [TSLIB=$enableval], [TSLIB=no]) -AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes]) -AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--enable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no]) -AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes]) -AC_ARG_ENABLE(config-udev, AS_HELP_STRING([--enable-config-udev], [Build udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto]) -AC_ARG_ENABLE(config-dbus, AS_HELP_STRING([--enable-config-dbus], [Build D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=no]) -AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto]) -AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes]) -AC_ARG_ENABLE(xaa, AS_HELP_STRING([--enable-xaa], [Build XAA (default: enabled)]), [XAA=$enableval], [XAA=yes]) -AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with vga access (default: enabled)]), [VGAHW=$enableval], [VGAHW=yes]) -AC_ARG_ENABLE(vbe, AS_HELP_STRING([--enable-vbe], [Build Xorg with VBE module (default: enabled)]), [VBE=$enableval], [VBE=yes]) -AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) -AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no]) -AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes]) -AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes]) - -dnl DDXes. -AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) -AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (default: auto)]), [DMX=$enableval], [DMX=auto]) -AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes]) -AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto]) -AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) -AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) -AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) -dnl kdrive and its subsystems -AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: no)]), [KDRIVE=$enableval], [KDRIVE=no]) -AC_ARG_ENABLE(xephyr, AS_HELP_STRING([--enable-xephyr], [Build the kdrive Xephyr server (default: auto)]), [XEPHYR=$enableval], [XEPHYR=auto]) -AC_ARG_ENABLE(xfake, AS_HELP_STRING([--enable-xfake], [Build the kdrive 'fake' server (default: auto)]), [XFAKE=$enableval], [XFAKE=auto]) -AC_ARG_ENABLE(xfbdev, AS_HELP_STRING([--enable-xfbdev], [Build the kdrive framebuffer device server (default: auto)]), [XFBDEV=$enableval], [XFBDEV=auto]) -dnl kdrive options -AC_ARG_ENABLE(kdrive-kbd, AS_HELP_STRING([--enable-kdrive-kbd], [Build kbd driver for kdrive (default: auto)]), [KDRIVE_KBD=$enableval], [KDRIVE_KBD=auto]) -AC_ARG_ENABLE(kdrive-mouse, AC_HELP_STRING([--enable-kdrive-mouse], [Build mouse driver for kdrive (default: auto)]), [KDRIVE_MOUSE=$enableval], [KDRIVE_MOUSE=auto]) -AC_ARG_ENABLE(kdrive-evdev, AC_HELP_STRING([--enable-kdrive-evdev], [Build evdev driver for kdrive (default: auto)]), [KDRIVE_EVDEV=$enableval], [KDRIVE_EVDEV=auto]) - - -dnl chown/chmod to be setuid root as part of build -dnl Replaces InstallXserverSetUID in imake -AC_ARG_ENABLE(install-setuid, - AS_HELP_STRING([--enable-install-setuid], - [Install Xorg server as owned by root with setuid bit (default: auto)]), - [SETUID=$enableval], [SETUID=auto]) -AC_MSG_CHECKING([to see if we can install the Xorg server as root]) -if test "x$SETUID" = "xauto" ; then - case $host_os in - cygwin*) SETUID="no" ;; - darwin*) SETUID="no" ;; - *) - case $host_cpu in - sparc) SETUID="no" ;; - *) SETUID="yes" ;; - esac - esac - if test "x$SETUID" = xyes; then - touch testfile - chown root testfile > /dev/null 2>&1 || SETUID="no" - rm -f testfile - fi -fi -AC_MSG_RESULT([$SETUID]) -AM_CONDITIONAL(INSTALL_SETUID, [test "x$SETUID" = "xyes"]) - -dnl Issue an error if xtrans.m4 was not found and XTRANS_CONNECTION_FLAGS macro -dnl was not expanded, since xorg-server with no transport types is rather useless. -dnl -dnl If you're seeing an error here, be sure you installed the lib/xtrans module -dnl first and if it's not in the default location, that you set the ACLOCAL -dnl environment variable to find it, such as: -dnl ACLOCAL="aclocal -I ${PREFIX}/share/aclocal" -m4_pattern_forbid([^XTRANS_CONNECTION_FLAGS$]) - -# Transport selection macro from xtrans.m4 -XTRANS_CONNECTION_FLAGS - -# Secure RPC detection macro from xtrans.m4 -XTRANS_SECURE_RPC_FLAGS -AM_CONDITIONAL(SECURE_RPC, [test "x$SECURE_RPC" = xyes]) - -AM_CONDITIONAL(INT10_VM86, [test "x$INT10" = xvm86]) -AM_CONDITIONAL(INT10_X86EMU, [test "x$INT10" = xx86emu]) -AM_CONDITIONAL(INT10_STUB, [test "x$INT10" = xstub]) -if test "x$INT10" = xyes; then - dnl VM86 headers - AC_CHECK_HEADERS([sys/vm86.h sys/io.h]) -fi - -XORG_ENABLE_DOCS -XORG_ENABLE_DEVEL_DOCS -XORG_WITH_XMLTO(0.0.20) -XORG_WITH_FOP - -dnl Handle installing libxf86config -AM_CONDITIONAL(INSTALL_LIBXF86CONFIG, [test "x$INSTALL_LIBXF86CONFIG" = xyes]) - -dnl DDX Detection... Yes, it's ugly to have it here... but we need to -dnl handle this early on so that we don't require unsupported extensions -case $host_os in - cygwin*) - DGA=no - DRI2=no - XF86VIDMODE=no - XSELINUX=no - XV=no - ;; - darwin*) - DRI2=no - - if test x$XQUARTZ = xauto; then - AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[ - 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]) - - if test "X$xorg_cv_Carbon_framework" = Xyes; then - XQUARTZ=yes - else - XQUARTZ=no - fi - fi - - if test "x$XQUARTZ" = xyes ; then - XQUARTZ=yes - XVFB=no - XNEST=no - - COMPOSITE=no - DGA=no - DPMSExtension=no - XF86VIDMODE=no - fi - ;; - *) XQUARTZ=no ;; -esac - -dnl --------------------------------------------------------------------------- -dnl Extension section -dnl --------------------------------------------------------------------------- -XEXT_INC='-I$(top_srcdir)/Xext' -XEXT_LIB='$(top_builddir)/Xext/libXext.la' -XEXTXORG_LIB='$(top_builddir)/Xext/libXextbuiltin.la' - -dnl Optional modules -VIDEOPROTO="videoproto" -COMPOSITEPROTO="compositeproto >= 0.4" -RECORDPROTO="recordproto >= 1.13.99.1" -SCRNSAVERPROTO="scrnsaverproto >= 1.1" -RESOURCEPROTO="resourceproto" -DRIPROTO="xf86driproto >= 2.1.0" -DRI2PROTO="dri2proto >= 2.3" -XINERAMAPROTO="xineramaproto" -BIGFONTPROTO="xf86bigfontproto >= 1.2.0" -DGAPROTO="xf86dgaproto >= 2.0.99.1" -GLPROTO="glproto >= 1.4.10" -DMXPROTO="dmxproto >= 2.2.99.1" -VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1" -WINDOWSWMPROTO="windowswmproto" -APPLEWMPROTO="applewmproto >= 1.4" - -dnl Core modules for most extensions, et al. -SDK_REQUIRED_MODULES="[xproto >= 7.0.17] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 1.9.99.902] [kbproto >= 1.0.3] fontsproto" -# Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc -AC_SUBST(SDK_REQUIRED_MODULES) - -dnl List of libraries that require a specific version -LIBAPPLEWM="applewm >= 1.4" -LIBDMX="dmx >= 1.0.99.1" -LIBDRI="dri >= 7.8.0" -LIBDRM="libdrm >= 2.3.0" -LIBGL="gl >= 7.1.0" -LIBXEXT="xext >= 1.0.99.4" -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" -LIBPIXMAN="pixman-1 >= 0.21.6" - -dnl Pixman is always required, but we separate it out so we can link -dnl specific modules against it -PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) -REQUIRED_LIBS="$REQUIRED_LIBS $LIBPIXMAN $LIBXFONT xau" - -REQUIRED_MODULES="[fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] $SDK_REQUIRED_MODULES" - -if test "x$CONFIG_UDEV" = xyes && - { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then - AC_MSG_ERROR([Hotplugging through both libudev and dbus/hal not allowed]) -fi - -PKG_CHECK_MODULES(UDEV, $LIBUDEV, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no]) -if test "x$CONFIG_UDEV" = xauto; then - CONFIG_UDEV="$HAVE_LIBUDEV" -fi -AM_CONDITIONAL(CONFIG_UDEV, [test "x$CONFIG_UDEV" = xyes]) -if test "x$CONFIG_UDEV" = xyes; then - CONFIG_DBUS_API=no - CONFIG_HAL=no - if ! test "x$HAVE_LIBUDEV" = xyes; then - AC_MSG_ERROR([udev configuration API requested, but libudev is not installed]) - fi - AC_DEFINE(CONFIG_UDEV, 1, [Use libudev for input hotplug]) -fi - -dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas -dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config -dnl API. -PKG_CHECK_MODULES(DBUS, $LIBDBUS, [HAVE_DBUS=yes], [HAVE_DBUS=no]) -if test "x$HAVE_DBUS" = xyes; then - AC_DEFINE(HAVE_DBUS, 1, [Have D-Bus support]) -fi -AM_CONDITIONAL(HAVE_DBUS, [test "x$HAVE_DBUS" = xyes]) - -if test "x$CONFIG_DBUS_API" = xauto; then - CONFIG_DBUS_API="$HAVE_DBUS" -fi -if test "x$CONFIG_DBUS_API" = xyes; then - if ! test "x$HAVE_DBUS" = xyes; then - AC_MSG_ERROR([D-Bus configuration API requested, but D-Bus is not installed.]) - fi - - AC_DEFINE(CONFIG_DBUS_API, 1, [Use the D-Bus input configuration API]) - CONFIG_NEED_DBUS="yes" -fi -AM_CONDITIONAL(CONFIG_DBUS_API, [test "x$CONFIG_DBUS_API" = xyes]) - -PKG_CHECK_MODULES(HAL, hal, [HAVE_HAL=yes], [HAVE_HAL=no]) -if test "x$CONFIG_HAL" = xauto; then - CONFIG_HAL="$HAVE_HAL" -fi -if test "x$CONFIG_HAL" = xyes; then - if ! test "x$HAVE_HAL" = xyes; then - AC_MSG_ERROR([HAL hotplug API requested, but HAL is not installed.]) - fi - - AC_DEFINE(CONFIG_HAL, 1, [Use the HAL hotplug API]) - CONFIG_NEED_DBUS="yes" -fi -AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes]) - -if test "x$CONFIG_NEED_DBUS" = xyes; then - AC_DEFINE(CONFIG_NEED_DBUS, 1, [Use D-Bus for input hotplug]) -fi -AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes]) - -if test "x$USE_SIGIO_BY_DEFAULT" = xyes; then - USE_SIGIO_BY_DEFAULT_VALUE=TRUE -else - USE_SIGIO_BY_DEFAULT_VALUE=FALSE -fi -AC_DEFINE_UNQUOTED([USE_SIGIO_BY_DEFAULT], [$USE_SIGIO_BY_DEFAULT_VALUE], - [Use SIGIO handlers for input device events by default]) - -AC_MSG_CHECKING([for glibc...]) -AC_PREPROC_IFELSE([ -#include -#ifndef __GLIBC__ -#error -#endif -], glibc=yes, glibc=no) -AC_MSG_RESULT([$glibc]) - -AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], - [AC_CHECK_LIB([rt], [clock_gettime], [have_clock_gettime=-lrt], - [have_clock_gettime=no])]) - -AC_MSG_CHECKING([for a useful monotonic clock ...]) - -if ! test "x$have_clock_gettime" = xno; then - if ! test "x$have_clock_gettime" = xyes; then - CLOCK_LIBS="$have_clock_gettime" - else - CLOCK_LIBS="" - fi - - LIBS_SAVE="$LIBS" - LIBS="$CLOCK_LIBS" - CPPFLAGS_SAVE="$CPPFLAGS" - - if test x"$glibc" = xyes; then - CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE=200112L" - fi - - AC_RUN_IFELSE([ -#include - -int main(int argc, char *argv[[]]) { - struct timespec tp; - - if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) - return 0; - else - return 1; -} - ], [MONOTONIC_CLOCK=yes], [MONOTONIC_CLOCK=no], - [MONOTONIC_CLOCK="cross compiling"]) - - LIBS="$LIBS_SAVE" - CPPFLAGS="$CPPFLAGS_SAVE" -else - MONOTONIC_CLOCK=no -fi - -AC_MSG_RESULT([$MONOTONIC_CLOCK]) - -if test "x$MONOTONIC_CLOCK" = xyes; then - AC_DEFINE(MONOTONIC_CLOCK, 1, [Have monotonic clock from clock_gettime()]) - LIBS="$LIBS $CLOCK_LIBS" -fi - -AM_CONDITIONAL(XV, [test "x$XV" = xyes]) -if test "x$XV" = xyes; then - AC_DEFINE(XV, 1, [Support Xv extension]) - AC_DEFINE(XvExtension, 1, [Build Xv extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $VIDEOPROTO" - SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $VIDEOPROTO" -else - XVMC=no -fi - -AM_CONDITIONAL(XVMC, [test "x$XVMC" = xyes]) -if test "x$XVMC" = xyes; then - AC_DEFINE(XvMCExtension, 1, [Build XvMC extension]) -fi - -AM_CONDITIONAL(XREGISTRY, [test "x$XREGISTRY" = xyes]) -if test "x$XREGISTRY" = xyes; then - AC_DEFINE(XREGISTRY, 1, [Build registry module]) -fi - -AM_CONDITIONAL(COMPOSITE, [test "x$COMPOSITE" = xyes]) -if test "x$COMPOSITE" = xyes; then - AC_DEFINE(COMPOSITE, 1, [Support Composite Extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $COMPOSITEPROTO" - COMPOSITE_LIB='$(top_builddir)/composite/libcomposite.la' - COMPOSITE_INC='-I$(top_srcdir)/composite' -fi - -AM_CONDITIONAL(MITSHM, [test "x$MITSHM" = xyes]) -if test "x$MITSHM" = xyes; then - AC_DEFINE(MITSHM, 1, [Support MIT-SHM extension]) - AC_DEFINE(HAS_SHM, 1, [Support SHM]) -fi - -AM_CONDITIONAL(RECORD, [test "x$RECORD" = xyes]) -if test "x$RECORD" = xyes; then - AC_DEFINE(XRECORD, 1, [Support Record extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $RECORDPROTO" - RECORD_LIB='$(top_builddir)/record/librecord.la' -fi - -AM_CONDITIONAL(SCREENSAVER, [test "x$SCREENSAVER" = xyes]) -if test "x$SCREENSAVER" = xyes; then - AC_DEFINE(SCREENSAVER, 1, [Support MIT-SCREEN-SAVER extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $SCRNSAVERPROTO" -fi - -AM_CONDITIONAL(RES, [test "x$RES" = xyes]) -if test "x$RES" = xyes; then - AC_DEFINE(RES, 1, [Support X resource extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $RESOURCEPROTO" -fi - -# The XRes extension may support client ID tracking only if it has -# been specifically enabled. Client ID tracking is implicitly not -# supported if XRes extension is disabled. -AC_MSG_CHECKING([whether to track client ids]) -if test "x$RES" = xyes && test "x$CLIENTIDS" = xyes; then - AC_DEFINE(CLIENTIDS, 1, [Support client ID tracking]) -else - CLIENTIDS=no -fi -AC_MSG_RESULT([$CLIENTIDS]) -AM_CONDITIONAL(CLIENTIDS, [test "x$CLIENTIDS" = xyes]) - -if test "x$GLX" = xyes; then - PKG_CHECK_MODULES([XLIB], [x11]) - PKG_CHECK_MODULES([GL], $GLPROTO $LIBGL) - AC_SUBST(XLIB_CFLAGS) - AC_DEFINE(GLXEXT, 1, [Build GLX extension]) - GLX_LIBS='$(top_builddir)/glx/libglx.la' - GLX_SYS_LIBS="$GLX_SYS_LIBS" -else - GLX=no -fi -AM_CONDITIONAL(GLX, test "x$GLX" = xyes) - -if test "x$AIGLX" = xyes -a "x$GLX" = xyes -a "x$DRI" = xyes; then - AC_DEFINE(AIGLX, 1, [Build AIGLX loader]) -else - AIGLX=no -fi -AM_CONDITIONAL(AIGLX, test "x$AIGLX" = xyes) - -if test "x$GLX_USE_TLS" = xyes ; then - GLX_DEFINES="-DGLX_USE_TLS -DPTHREADS" - GLX_SYS_LIBS="$GLX_SYS_LIBS -lpthread" -fi -AC_SUBST([GLX_DEFINES]) - -AM_CONDITIONAL(DRI, test "x$DRI" = xyes) -if test "x$DRI" = xyes; then - AC_DEFINE(XF86DRI, 1, [Build DRI extension]) - PKG_CHECK_MODULES([DRIPROTO], [$DRIPROTO]) - PKG_CHECK_MODULES([DRI], $GLPROTO $LIBDRI) - AC_SUBST(DRIPROTO_CFLAGS) -fi - -PKG_CHECK_MODULES([DRI2PROTO], $DRI2PROTO, - [HAVE_DRI2PROTO=yes], [HAVE_DRI2PROTO=no]) -case "$DRI2,$HAVE_DRI2PROTO" in - yes,no) - AC_MSG_ERROR([DRI2 requested, but dri2proto not found.]) - ;; - yes,yes | auto,yes) - AC_DEFINE(DRI2, 1, [Build DRI2 extension]) - DRI2=yes - SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI2PROTO" - ;; -esac -AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes) - -if test "x$DRI" = xyes || test "x$DRI2" = xyes; then - if test "x$DRM" = xyes; then - AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support]) - PKG_CHECK_MODULES([LIBDRM], $LIBDRM) - fi -fi - -if test "x$DRI2" = xyes; then - save_CFLAGS=$CFLAGS - CFLAGS="$GL_CFLAGS $LIBDRM_CFLAGS" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include -#include -#ifndef __DRI_DRI2 -#error DRI2 extension not available. -#endif]])], - [HAVE_DRI2EXTENSION=yes], - [HAVE_DRI2EXTENSION=no]) - CFLAGS=$save_CFLAGS - if test "x$HAVE_DRI2EXTENSION" = xyes; then - AC_DEFINE(DRI2_AIGLX, 1, [Build DRI2 AIGLX loader]) - DRI2_AIGLX=yes - else - AC_MSG_NOTICE([DRI2 AIGLX disabled, __DRI_DRI2 not defined in dri_interface.h.]) - DRI2_AIGLX=no - fi -fi -AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes) - - -AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes]) -if test "x$XINERAMA" = xyes; then - AC_DEFINE(XINERAMA, 1, [Support Xinerama extension]) - AC_DEFINE(PANORAMIX, 1, [Internal define for Xinerama]) - REQUIRED_MODULES="$REQUIRED_MODULES $XINERAMAPROTO" - SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $XINERAMAPROTO" -fi - -AM_CONDITIONAL(XACE, [test "x$XACE" = xyes]) -if test "x$XACE" = xyes; then - AC_DEFINE(XACE, 1, [Build X-ACE extension]) -fi - -AM_CONDITIONAL(XSELINUX, [test "x$XSELINUX" = xyes]) -if test "x$XSELINUX" = xyes; then - if test "x$XACE" != xyes; then - AC_MSG_ERROR([cannot build SELinux extension without X-ACE]) - fi - AC_CHECK_HEADERS([libaudit.h], [], AC_MSG_ERROR([SELinux extension requires audit system headers])) - AC_CHECK_LIB(audit, audit_open, [], AC_MSG_ERROR([SELinux extension requires audit system library])) - PKG_CHECK_MODULES([SELINUX], $LIBSELINUX) - SELINUX_LIBS="$SELINUX_LIBS -laudit" - AC_DEFINE(XSELINUX, 1, [Build SELinux extension]) -fi - -AM_CONDITIONAL(XCSECURITY, [test "x$XCSECURITY" = xyes]) -if test "x$XCSECURITY" = xyes; then - if test "x$XACE" != xyes; then - AC_MSG_ERROR([cannot build Security extension without X-ACE]) - fi - AC_DEFINE(XCSECURITY, 1, [Build Security extension]) -fi - -AM_CONDITIONAL(DBE, [test "x$DBE" = xyes]) -if test "x$DBE" = xyes; then - AC_DEFINE(DBE, 1, [Support DBE extension]) - DBE_LIB='$(top_builddir)/dbe/libdbe.la' -fi - -AM_CONDITIONAL(XF86BIGFONT, [test "x$XF86BIGFONT" = xyes]) -if test "x$XF86BIGFONT" = xyes; then - AC_DEFINE(XF86BIGFONT, 1, [Support XF86 Big font extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $BIGFONTPROTO" -fi - -AM_CONDITIONAL(DPMSExtension, [test "x$DPMSExtension" = xyes]) -if test "x$DPMSExtension" = xyes; then - AC_DEFINE(DPMSExtension, 1, [Support DPMS extension]) -fi - -AC_DEFINE(RENDER, 1, [Support RENDER extension]) -RENDER_LIB='$(top_builddir)/render/librender.la' -RENDER_INC='-I$(top_srcdir)/render' - -AC_DEFINE(RANDR, 1, [Support RANDR extension]) -RANDR_LIB='$(top_builddir)/randr/librandr.la' -RANDR_INC='-I$(top_srcdir)/randr' - -AC_DEFINE(XFIXES,1,[Support XFixes extension]) -FIXES_LIB='$(top_builddir)/xfixes/libxfixes.la' -FIXES_INC='-I$(top_srcdir)/xfixes' - -AC_DEFINE(DAMAGE,1,[Support Damage extension]) -DAMAGE_LIB='$(top_builddir)/damageext/libdamageext.la' -DAMAGE_INC='-I$(top_srcdir)/damageext' -MIEXT_DAMAGE_LIB='$(top_builddir)/miext/damage/libdamage.la' -MIEXT_DAMAGE_INC='-I$(top_srcdir)/miext/damage' - -# XINPUT extension is integral part of the server -AC_DEFINE(XINPUT, 1, [Support X Input extension]) -XI_LIB='$(top_builddir)/Xi/libXi.la' -XI_INC='-I$(top_srcdir)/Xi' - -AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes) -AM_CONDITIONAL(XAA, test "x$XAA" = xyes) -AM_CONDITIONAL(VGAHW, test "x$VGAHW" = xyes) -AM_CONDITIONAL(VBE, test "x$VBE" = xyes) -AM_CONDITIONAL(INT10MODULE, test "x$INT10MODULE" = xyes) - -AC_DEFINE(SHAPE, 1, [Support SHAPE extension]) - -AC_DEFINE_DIR(XKB_BASE_DIRECTORY, XKBPATH, [Path to XKB data]) -AC_ARG_WITH(xkb-bin-directory, - AS_HELP_STRING([--with-xkb-bin-directory=DIR], [Directory containing xkbcomp program]), - [XKB_BIN_DIRECTORY="$withval"], - [XKB_BIN_DIRECTORY="$bindir"]) - -AC_DEFINE_DIR(XKB_BIN_DIRECTORY, XKB_BIN_DIRECTORY, [Path to XKB bin dir]) - -dnl Make sure XKM_OUTPUT_DIR is an absolute path -XKBOUTPUT_FIRSTCHAR=`echo $XKBOUTPUT | cut -b 1` -if [[ x$XKBOUTPUT_FIRSTCHAR != x/ -a x$XKBOUTPUT_FIRSTCHAR != 'x$' ]] ; then - XKBOUTPUT="$XKB_BASE_DIRECTORY/$XKBOUTPUT" -fi - -dnl XKM_OUTPUT_DIR (used in code) must end in / or file names get hosed -dnl XKB_COMPILED_DIR (used in Makefiles) must not or install-sh gets confused - -XKBOUTPUT=`echo $XKBOUTPUT/ | $SED 's|/*$|/|'` -XKB_COMPILED_DIR=`echo $XKBOUTPUT | $SED 's|/*$||'` -AC_DEFINE_DIR(XKM_OUTPUT_DIR, XKBOUTPUT, [Path to XKB output dir]) -AC_SUBST(XKB_COMPILED_DIR) - -if test "x$XKB_DFLT_RULES" = x; then - case $host_os in - linux*) - dnl doesn't take AutoAddDevices into account, but whatever. - if test "x$CONFIG_HAL" = xyes; then - XKB_DFLT_RULES="evdev" - else - XKB_DFLT_RULES="base" - fi - ;; - *) - XKB_DFLT_RULES="base" - ;; - esac -fi -AC_DEFINE_UNQUOTED(XKB_DFLT_RULES, ["$XKB_DFLT_RULES"], [Default XKB ruleset]) -AC_DEFINE_UNQUOTED(XKB_DFLT_MODEL, ["$XKB_DFLT_MODEL"], [Default XKB model]) -AC_DEFINE_UNQUOTED(XKB_DFLT_LAYOUT, ["$XKB_DFLT_LAYOUT"], [Default XKB layout]) -AC_DEFINE_UNQUOTED(XKB_DFLT_VARIANT, ["$XKB_DFLT_VARIANT"], [Default XKB variant]) -AC_DEFINE_UNQUOTED(XKB_DFLT_OPTIONS, ["$XKB_DFLT_OPTIONS"], [Default XKB options]) - -XKB_LIB='$(top_builddir)/xkb/libxkb.la' -XKB_STUB_LIB='$(top_builddir)/xkb/libxkbstubs.la' -REQUIRED_MODULES="$REQUIRED_MODULES xkbfile" - -AC_CHECK_FUNC(strcasecmp, [], AC_DEFINE([NEED_STRCASECMP], 1, - [Do not have 'strcasecmp'.])) -AC_CHECK_FUNC(strncasecmp, [], AC_DEFINE([NEED_STRNCASECMP], 1, - [Do not have 'strncasecmp'.])) -AC_CHECK_FUNC(strcasestr, [], AC_DEFINE([NEED_STRCASESTR], 1, - [Do not have 'strcasestr'.])) - -PKG_CHECK_MODULES([XDMCP], [xdmcp], [have_libxdmcp="yes"], [have_libxdmcp="no"]) -if test "x$have_libxdmcp" = xyes; then - AC_CHECK_LIB(Xdmcp, XdmcpWrap, [have_xdmcpwrap="yes"], [have_xdmcpwrap="no"], [$XDMCP_LIBS]) -fi -if test "x$XDMCP" = xauto; then - if test "x$have_libxdmcp" = xyes; then - XDMCP=yes - else - XDMCP=no - fi -fi -if test "x$XDMAUTH" = xauto; then - if test "x$have_libxdmcp" = xyes && test "x$have_xdmcpwrap" = xyes; then - XDMAUTH=yes - else - XDMAUTH=no - fi -fi - -AM_CONDITIONAL(XDMCP, [test "x$XDMCP" = xyes]) -if test "x$XDMCP" = xyes; then - AC_DEFINE(XDMCP, 1, [Support XDM Control Protocol]) - REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" - XDMCP_MODULES="xdmcp" -fi - -AM_CONDITIONAL(XDMAUTH, [test "x$XDMAUTH" = xyes]) -if test "x$XDMAUTH" = xyes; then - AC_DEFINE(HASXDMAUTH,1,[Support XDM-AUTH*-1]) - if ! test "x$XDMCP" = xyes; then - REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" - XDMCP_MODULES="xdmcp" - fi -fi - -AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path]) -AC_DEFINE_DIR(PCI_TXT_IDS_PATH, PCI_TXT_IDS_DIR, [Default PCI text file ID path]) -AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path]) -AC_DEFINE_DIR(BASE_FONT_PATH, FONTROOTDIR, [Default base font path]) -dridriverdir=`$PKG_CONFIG --variable=dridriverdir dri` -AC_DEFINE_DIR(DRI_DRIVER_PATH, dridriverdir, [Default DRI driver path]) -AC_DEFINE_UNQUOTED(XVENDORNAME, ["$VENDOR_NAME"], [Vendor name]) -AC_DEFINE_UNQUOTED(XVENDORNAMESHORT, ["$VENDOR_NAME_SHORT"], [Short vendor name]) -AC_DEFINE_UNQUOTED(XORG_DATE, ["$RELEASE_DATE"], [Vendor release]) -AC_DEFINE_UNQUOTED(XORG_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) -AC_DEFINE_UNQUOTED(BUILDERADDR, ["$BUILDERADDR"], [Builder address]) - -if test -z "$OSNAME"; then - OSNAME="UNKNOWN" -fi - -AC_DEFINE_UNQUOTED(OSNAME, ["$OSNAME"], [Operating System Name]) -AC_DEFINE_UNQUOTED(OSVENDOR, ["$OSVENDOR"], [Operating System Vendor]) -AC_DEFINE_UNQUOTED(BUILDERSTRING, ["$BUILDERSTRING"], [Builder string]) - -AC_SUBST([VENDOR_NAME_SHORT]) -AC_DEFINE_UNQUOTED(VENDOR_NAME, ["$VENDOR_NAME"], [Vendor name]) -AC_DEFINE_UNQUOTED(VENDOR_NAME_SHORT, ["$VENDOR_NAME_SHORT"], [Vendor name]) -AC_DEFINE_UNQUOTED(VENDOR_RELEASE, [$VENDOR_RELEASE], [Vendor release]) -AC_DEFINE_UNQUOTED(VENDOR_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) - -AC_DEFINE(NO_LIBCWRAPPER, 1, [Define to 1 if modules should avoid the libcwrapper]) - -if test "x$DEBUGGING" = xyes; then - AC_DEFINE(DEBUG, 1, [Enable debugging code]) -fi -AM_CONDITIONAL(DEBUG, [test "x$DEBUGGING" = xyes]) - -# If unittests aren't explicitly disabled, check for required support -if test "x$UNITTESTS" != xno ; then - PKG_CHECK_MODULES([GLIB], $LIBGLIB, - [HAVE_GLIB=yes], [HAVE_GLIB=no]) - - # Check if linker supports -wrap, passed via compiler flags - # When cross-compiling, reports no, since unit tests run from - # "make check", so would be running on build machine, not target - AC_MSG_CHECKING([whether the linker supports -wrap]) - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -Wl,-wrap,exit" - AC_RUN_IFELSE([AC_LANG_PROGRAM([[ - void __wrap_exit (int s) - { - __real_exit (0); - }]], - [[exit (1);]])], - [linker_can_wrap="yes"], - [linker_can_wrap="no"], - [linker_can_wrap="no"]) - AC_MSG_RESULT([$linker_can_wrap]) - LDFLAGS="$save_LDFLAGS" -fi - -if test "x$UNITTESTS" = xauto; then - if test "x$HAVE_GLIB" = xyes && test "x$linker_can_wrap" = xyes; then - UNITTESTS=yes - else - UNITTESTS=no - fi -fi -if test "x$UNITTESTS" = xyes; then - if test "x$HAVE_GLIB" = xno; then - AC_MSG_ERROR([glib required to build unit tests]) - fi - if test "x$linker_can_wrap" = xno; then - AC_MSG_ERROR([ld -wrap support required to build unit tests]) - fi - AC_DEFINE(UNITTESTS, 1, [Enable unit tests]) - AC_SUBST([GLIB_LIBS]) - AC_SUBST([GLIB_CFLAGS]) -fi -AM_CONDITIONAL(UNITTESTS, [test "x$UNITTESTS" = xyes]) - -AC_DEFINE(XTEST, 1, [Support XTest extension]) -AC_DEFINE(XSYNC, 1, [Support XSync extension]) -AC_DEFINE(XCMISC, 1, [Support XCMisc extension]) -AC_DEFINE(BIGREQS, 1, [Support BigRequests extension]) - -if test "x$SPECIAL_DTRACE_OBJECTS" = "xyes" ; then - DIX_LIB='$(top_builddir)/dix/dix.O' - OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS) $(DLOPEN_LIBS)' -else - DIX_LIB='$(top_builddir)/dix/libdix.la' - OS_LIB='$(top_builddir)/os/libos.la' -fi -AC_SUBST([DIX_LIB]) -AC_SUBST([OS_LIB]) - -MAIN_LIB='$(top_builddir)/dix/libmain.la' -AC_SUBST([MAIN_LIB]) - -MI_LIB='$(top_builddir)/mi/libmi.la' -MI_EXT_LIB='$(top_builddir)/mi/libmiext.la' -MI_INC='-I$(top_srcdir)/mi' -FB_LIB='$(top_builddir)/fb/libfb.la' -FB_INC='-I$(top_srcdir)/fb' -MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow' -MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' -MIEXT_SYNC_INC='-I$(top_srcdir)/miext/sync' -MIEXT_SYNC_LIB='$(top_builddir)/miext/sync/libsync.la' -CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include' - -# SHA1 hashing -AC_ARG_WITH([sha1], - [AS_HELP_STRING([--with-sha1=libc|libmd|libgcrypt|libcrypto|libsha1|CommonCrypto], - [choose SHA1 implementation])]) -AC_CHECK_FUNC([SHA1Init], [HAVE_SHA1_IN_LIBC=yes]) -if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_LIBC" = xyes; then - with_sha1=libc -fi -if test "x$with_sha1" = xlibc && test "x$HAVE_SHA1_IN_LIBC" != xyes; then - AC_MSG_ERROR([libc requested but not found]) -fi -if test "x$with_sha1" = xlibc; then - AC_DEFINE([HAVE_SHA1_IN_LIBC], [1], - [Use libc SHA1 functions]) - SHA1_LIBS="" -fi -AC_CHECK_FUNC([CC_SHA1_Init], [HAVE_SHA1_IN_COMMONCRYPTO=yes]) -if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_COMMONCRYPTO" = xyes; then - with_sha1=CommonCrypto -fi -if test "x$with_sha1" = xCommonCrypto && test "x$HAVE_SHA1_IN_COMMONCRYPTO" != xyes; then - AC_MSG_ERROR([CommonCrypto requested but not found]) -fi -if test "x$with_sha1" = xCommonCrypto; then - AC_DEFINE([HAVE_SHA1_IN_COMMONCRYPTO], [1], - [Use CommonCrypto SHA1 functions]) - SHA1_LIBS="" -fi -AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes]) -if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then - with_sha1=libmd -fi -if test "x$with_sha1" = xlibmd && test "x$HAVE_LIBMD" != xyes; then - AC_MSG_ERROR([libmd requested but not found]) -fi -if test "x$with_sha1" = xlibmd; then - AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1], - [Use libmd SHA1 functions]) - SHA1_LIBS=-lmd -fi -PKG_CHECK_MODULES([LIBSHA1], [libsha1], [HAVE_LIBSHA1=yes], [HAVE_LIBSHA1=no]) -if test "x$with_sha1" = x && test "x$HAVE_LIBSHA1" = xyes; then - with_sha1=libsha1 -fi -if test "x$with_sha1" = xlibsha1 && test "x$HAVE_LIBSHA1" != xyes; then - AC_MSG_ERROR([libsha1 requested but not found]) -fi -if test "x$with_sha1" = xlibsha1; then - AC_DEFINE([HAVE_SHA1_IN_LIBSHA1], [1], - [Use libsha1 for SHA1]) - SHA1_LIBS=-lsha1 -fi -AC_CHECK_LIB([gcrypt], [gcry_md_open], [HAVE_LIBGCRYPT=yes]) -if test "x$with_sha1" = x && test "x$HAVE_LIBGCRYPT" = xyes; then - with_sha1=libgcrypt -fi -if test "x$with_sha1" = xlibgcrypt && test "x$HAVE_LIBGCRYPT" != xyes; then - AC_MSG_ERROR([libgcrypt requested but not found]) -fi -if test "x$with_sha1" = xlibgcrypt; then - AC_DEFINE([HAVE_SHA1_IN_LIBGCRYPT], [1], - [Use libgcrypt SHA1 functions]) - SHA1_LIBS=-lgcrypt -fi -# We don't need all of the OpenSSL libraries, just libcrypto -AC_CHECK_LIB([crypto], [SHA1_Init], [HAVE_LIBCRYPTO=yes]) -PKG_CHECK_MODULES([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes], - [HAVE_OPENSSL_PKC=no]) -if test "x$HAVE_LIBCRYPTO" = xyes || test "x$HAVE_OPENSSL_PKC" = xyes; then - if test "x$with_sha1" = x; then - with_sha1=libcrypto - fi -else - if test "x$with_sha1" = xlibcrypto; then - AC_MSG_ERROR([OpenSSL libcrypto requested but not found]) - fi -fi -if test "x$with_sha1" = xlibcrypto; then - if test "x$HAVE_LIBCRYPTO" = xyes; then - SHA1_LIBS=-lcrypto - else - SHA1_LIBS="$OPENSSL_LIBS" - SHA1_CFLAGS="$OPENSSL_CFLAGS" - fi -fi -AC_MSG_CHECKING([for SHA1 implementation]) -if test "x$with_sha1" = x; then - AC_MSG_ERROR([No suitable SHA1 implementation found]) -fi -AC_MSG_RESULT([$with_sha1]) -AC_SUBST(SHA1_LIBS) -AC_SUBST(SHA1_CFLAGS) - -PKG_CHECK_MODULES([XSERVERCFLAGS], [$REQUIRED_MODULES $REQUIRED_LIBS]) -PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS]) - -# Autotools has some unfortunate issues with library handling. In order to -# get a server to rebuild when a dependency in the tree is changed, it must -# be listed in SERVERNAME_DEPENDENCIES. However, no system libraries may be -# listed there, or some versions of autotools will break (especially if a -L -# is required to find the library). So, we keep two sets of libraries -# detected: NAMESPACE_LIBS for in-tree libraries to be linked against, which -# will go into the _DEPENDENCIES and _LDADD of the server, and -# NAMESPACE_SYS_LIBS which will go into only the _LDADD. The -# NAMESPACEMODULES_LIBS detected from pkgconfig should always go in -# NAMESPACE_SYS_LIBS. -# -# XSERVER_LIBS is the set of in-tree libraries which all servers require. -# XSERVER_SYS_LIBS is the set of out-of-tree libraries which all servers -# require. -# -XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS}" -XSERVER_LIBS="$DIX_LIB $MI_LIB $OS_LIB" -XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS}" -AC_SUBST([XSERVER_LIBS]) -AC_SUBST([XSERVER_SYS_LIBS]) - -UTILS_SYS_LIBS="${SYS_LIBS}" -AC_SUBST([UTILS_SYS_LIBS]) - -# The Xorg binary needs to export symbols so that they can be used from modules -# Some platforms require extra flags to do this. libtool should set the -# necessary flags for each platform when -export-dynamic is passed to it. -LD_EXPORT_SYMBOLS_FLAG="-export-dynamic" -AC_SUBST([LD_EXPORT_SYMBOLS_FLAG]) - -dnl Imake defines SVR4 on SVR4 systems, and many files check for it, so -dnl we need to replicate that here until those can all be fixed -AC_MSG_CHECKING([if SVR4 needs to be defined]) -AC_EGREP_CPP([I_AM_SVR4],[ -#if defined(SVR4) || defined(__svr4__) || defined(__SVR4) - I_AM_SVR4 -#endif -],[ -AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4]) -AC_MSG_RESULT([yes])], AC_MSG_RESULT([no])) - -XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC" - -dnl --------------------------------------------------------------------------- -dnl DDX section. -dnl --------------------------------------------------------------------------- - -dnl Xvfb DDX - -AC_MSG_CHECKING([whether to build Xvfb DDX]) -AC_MSG_RESULT([$XVFB]) -AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes]) - -if test "x$XVFB" = xyes; then - XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB" - XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS" - AC_SUBST([XVFB_LIBS]) - AC_SUBST([XVFB_SYS_LIBS]) -fi - - -dnl Xnest DDX - -PKG_CHECK_MODULES(XNESTMODULES, [$LIBXEXT x11 xau $XDMCP_MODULES], [have_xnest=yes], [have_xnest=no]) -AC_MSG_CHECKING([whether to build Xnest DDX]) -if test "x$XNEST" = xauto; then - XNEST="$have_xnest" -fi -AC_MSG_RESULT([$XNEST]) -AM_CONDITIONAL(XNEST, [test "x$XNEST" = xyes]) - -if test "x$XNEST" = xyes; then - if test "x$have_xnest" = xno; then - AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.]) - fi - XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB" - XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" - AC_SUBST([XNEST_LIBS]) - AC_SUBST([XNEST_SYS_LIBS]) -fi - - -dnl Xorg DDX - -AC_MSG_CHECKING([whether to build Xorg DDX]) -if test "x$XORG" = xauto; then - XORG="yes" - case $host_os in - cygwin*) XORG="no" ;; - darwin*) XORG="no" ;; - esac -fi -AC_MSG_RESULT([$XORG]) - -xorg_bus_linuxpci=no -xorg_bus_bsdpci=no -xorg_bus_sparc=no - -if test "x$XORG" = xyes; then - XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common' - XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os' - XORG_INCS="$XORG_DDXINCS $XORG_OSINCS" - XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H" - XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB" - - dnl ================================================================== - dnl symbol visibility - symbol_visibility= - have_visibility=disabled - if test x$SYMBOL_VISIBILITY != xno; then - AC_MSG_CHECKING(for symbol visibility support) - if test x$GCC = xyes; then - VISIBILITY_CFLAGS="-fvisibility=hidden" - else - AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) - if test x$SUNCC = xyes; then - VISIBILITY_CFLAGS="-xldscope=hidden" - else - have_visibility=no - fi - fi - if test x$have_visibility != xno; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $VISIBILITY_CFLAGS" - AC_TRY_COMPILE( - [#include - extern _X_HIDDEN int hidden_int; - extern _X_EXPORT int public_int; - extern _X_HIDDEN int hidden_int_func(void); - extern _X_EXPORT int public_int_func(void);], - [], - have_visibility=yes, - have_visibility=no) - CFLAGS=$save_CFLAGS - fi - AC_MSG_RESULT([$have_visibility]) - if test x$have_visibility != xno; then - symbol_visibility=$VISIBILITY_CFLAGS - XORG_CFLAGS="$XORG_CFLAGS $VISIBILITY_CFLAGS" - XSERVER_CFLAGS="$XSERVER_CFLAGS $VISIBILITY_CFLAGS" - fi - fi - dnl added to xorg-server.pc - AC_SUBST([symbol_visibility]) - dnl =================================================================== - - PKG_CHECK_MODULES([PCIACCESS], $LIBPCIACCESS) - SAVE_LIBS=$LIBS - SAVE_CFLAGS=$CFLAGS - CFLAGS=$PCIACCESS_CFLAGS - LIBS=$PCIACCESS_LIBS - AC_CHECK_FUNCS([pci_system_init_dev_mem]) - AC_CHECK_FUNCS([pci_device_enable]) - AC_CHECK_FUNCS([pci_device_is_boot_vga]) - AC_CHECK_FUNCS([pci_device_vgaarb_init]) - LIBS=$SAVE_LIBS - CFLAGS=$SAVE_CFLAGS - XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS" - XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS" - - case $host_os in - linux*) - if test "x$LNXAPM" = xyes; then - XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" - fi - XORG_OS="linux" - XORG_OS_SUBDIR="linux" - xorg_bus_linuxpci="yes" - linux_acpi="no" - case $host_cpu in - ia64*) - linux_ia64=yes - linux_acpi="yes" - ;; - alpha*) - linux_alpha=yes - ;; - i*86|amd64*|x86_64*) - linux_acpi="yes" - ;; - *) - ;; - esac - ;; - freebsd* | kfreebsd*-gnu | dragonfly*) - XORG_OS="freebsd" - XORG_OS_SUBDIR="bsd" - xorg_bus_bsdpci="yes" - ;; - netbsd*) - XORG_OS="netbsd" - XORG_OS_SUBDIR="bsd" - xorg_bus_bsdpci="yes" - ;; - openbsd*) - if test "x$ac_cv_BSD_APM" = xyes \ - -o "x$ac_cv_BSD_KQUEUE_APM" = xyes; then - XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" - fi - XORG_OS="openbsd" - XORG_OS_SUBDIR="bsd" - xorg_bus_bsdpci="yes" - ;; - solaris*) - XORG_OS="solaris" - XORG_OS_SUBDIR="solaris" - XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" - # Use the same stubs as BSD for old functions, since we now - # use libpciaccess for PCI - xorg_bus_bsdpci="yes" - AC_CHECK_HEADERS([sys/kd.h]) - AC_CHECK_HEADERS([sys/vt.h], [solaris_vt=yes], [solaris_vt=no]) - # Check for minimum supported release - AC_MSG_CHECKING([Solaris version]) - OS_MINOR=`echo ${host_os}|$SED -e 's/^.*solaris2\.//' -e s'/\..*$//'` - if test "${OS_MINOR}" -ge 7 ; then - AC_MSG_RESULT(Solaris ${OS_MINOR}) - else - AC_MSG_RESULT(Solaris `echo ${host_os}|$SED -e 's/^.*solaris//`) - fi - if test "${OS_MINOR}" -lt 8 ; then - AC_MSG_ERROR([This release no longer supports Solaris versions older than Solaris 8.]) - fi - AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) - if test "x$SUNCC" = "xyes"; then - solaris_asm_inline="yes" - fi - AC_CHECK_DECL([_LP64], [SOLARIS_64="yes"], [SOLARIS_64="no"]) - - case $host_cpu in - sparc*) - SOLARIS_INOUT_ARCH="sparcv8plus" - ;; - i*86) - if test x$SOLARIS_64 = xyes ; then - SOLARIS_INOUT_ARCH="amd64" - else - SOLARIS_INOUT_ARCH="ia32" - fi - ;; - *) - AC_MSG_ERROR([Unsupported Solaris platform. Only SPARC & x86 \ - are supported on Solaris in this release. If you are \ - interested in porting Xorg to your platform, please email \ - xorg@lists.freedesktop.org.]) ;; - esac - AC_SUBST([SOLARIS_INOUT_ARCH]) - if test x$solaris_asm_inline = xyes ; then - SOLARIS_ASM_CFLAGS='$(top_srcdir)/hw/xfree86/os-support/solaris/solaris-$(SOLARIS_INOUT_ARCH).il' - XORG_CFLAGS="${XORG_CFLAGS} "'$(SOLARIS_ASM_CFLAGS)' - fi - AC_SUBST([SOLARIS_ASM_CFLAGS]) - if test "x$SUPPORT_PC98" = xauto; then - SUPPORT_PC98="no" - fi - ;; - gnu*) - XORG_OS="gnu" - XORG_OS_SUBDIR="hurd" - # Use the same stubs as BSD for old functions, since we now - # use libpciaccess for PCI - xorg_bus_bsdpci="yes" - ;; - *) - XORG_OS="unknown" - XORG_OS_SUBDIR="unknown" - AC_MSG_ERROR([m4_text_wrap(m4_join([ ], - [Your OS is unknown. Xorg currently only supports Linux,], - [Free/Open/Net/DragonFlyBSD, Solaris/OpenSolaris, & GNU Hurd.], - [If you are interested in porting Xorg to your platform,], - [please email xorg@lists.freedesktop.org.]))]) - ;; - esac - - case $host_cpu in - sparc*) - xorg_bus_sparc="yes" - ;; - i*86) - if test "x$SUPPORT_PC98" = xauto; then - SUPPORT_PC98="yes" - fi - ;; - esac - - if test "x$SUPPORT_PC98" = xauto; then - SUPPORT_PC98="no" - fi - if test "x$SUPPORT_PC98" = xyes; then - AC_DEFINE(SUPPORT_PC98, 1, [Support PC98]) - fi - if test "x$XORG_OS_PCI" = x ; then - XORG_OS_PCI=$XORG_OS - fi - if test "x$DGA" = xauto; then - PKG_CHECK_MODULES(DGA, $DGAPROTO, [DGA=yes], [DGA=no]) - fi - if test "x$DGA" = xyes; then - XORG_MODULES="$XORG_MODULES $DGAPROTO" - PKG_CHECK_MODULES(DGA, $DGAPROTO) - AC_DEFINE(DGA, 1, [Support DGA extension]) - AC_DEFINE(XFreeXDGA, 1, [Build XDGA support]) - fi - - if test "x$XF86VIDMODE" = xauto; then - PKG_CHECK_MODULES(XF86VIDMODE, $VIDMODEPROTO, [XF86VIDMODE=yes], [XF86VIDMODE=no]) - fi - if test "x$XF86VIDMODE" = xyes; then - XORG_MODULES="$XORG_MODULES $VIDMODEPROTO" - PKG_CHECK_MODULES(XF86VIDMODE, $VIDMODEPROTO) - AC_DEFINE(XF86VIDMODE, 1, [Support XFree86 Video Mode extension]) - fi - - if test -n "$XORG_MODULES"; then - PKG_CHECK_MODULES(XORG_MODULES, [$XORG_MODULES]) - XORG_CFLAGS="$XORG_CFLAGS $XORG_MODULES_CFLAGS" - XORG_SYS_LIBS="$XORG_SYS_LIBS $XORG_MODULES_LIBS" - fi - - AC_SUBST([XORG_LIBS]) - AC_SUBST([XORG_SYS_LIBS]) - AC_SUBST([XORG_INCS]) - AC_SUBST([XORG_OS]) - AC_SUBST([XORG_OS_SUBDIR]) - - AC_PATH_PROG(PERL, perl, no) - dnl unlikely as this may be ... - if test "x$PERL" = xno; then - AC_MSG_ERROR([Perl is required to build the XFree86/Xorg DDX.]) - fi - AC_SUBST(PERL) - - AC_SUBST([XORG_CFLAGS]) - - dnl these only go in xorg-config.h - XF86CONFIGFILE="xorg.conf" - XF86CONFIGDIR="xorg.conf.d" - AC_SUBST(XF86CONFIGDIR) - CONFIGFILE="$sysconfdir/$XF86CONFIGFILE" - LOGPREFIX="$logdir/Xorg." - AC_DEFINE(XORG_SERVER, 1, [Building Xorg server]) - AC_DEFINE(XORGSERVER, 1, [Building Xorg server]) - AC_DEFINE(XFree86Server, 1, [Building XFree86 server]) - AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server]) - AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) - AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs]) - AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions]) - AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server]) - AC_DEFINE_DIR(__XCONFIGFILE__, XF86CONFIGFILE, [Name of configuration file]) - AC_DEFINE_DIR(XF86CONFIGFILE, XF86CONFIGFILE, [Name of configuration file]) - AC_DEFINE_DIR(__XCONFIGDIR__, XF86CONFIGDIR, [Name of configuration directory]) - AC_DEFINE_DIR(DEFAULT_MODULE_PATH, moduledir, [Default module search path]) - AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path]) - AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default log location]) - AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) - AC_DEFINE(XSERVER_LIBPCIACCESS, 1, [Use libpciaccess for all pci manipulation]) - if test "x$VGAHW" = xyes; then - AC_DEFINE(WITH_VGAHW, 1, [Building vgahw module]) - fi - - driverdir="$moduledir/drivers" - AC_SUBST([moduledir]) - AC_SUBST([driverdir]) - sdkdir="$includedir/xorg" - extdir="$includedir/X11/extensions" - sysconfigdir="$datadir/X11/$XF86CONFIGDIR" - AC_SUBST([sdkdir]) - AC_SUBST([extdir]) - AC_SUBST([sysconfigdir]) - AC_SUBST([logdir]) - - # stuff the ABI versions into the pc file too - extract_abi() { - grep ^.define.*${1}_VERSION ${srcdir}/hw/xfree86/common/xf86Module.h | tr '(),' ' .' | awk '{ print $4$5 }' - } - abi_ansic=`extract_abi ANSIC` - abi_videodrv=`extract_abi VIDEODRV` - abi_xinput=`extract_abi XINPUT` - abi_extension=`extract_abi EXTENSION` - AC_SUBST([abi_ansic]) - AC_SUBST([abi_videodrv]) - AC_SUBST([abi_xinput]) - AC_SUBST([abi_extension]) -fi -AM_CONDITIONAL([XORG], [test "x$XORG" = xyes]) -AM_CONDITIONAL([XORG_BUS_LINUXPCI], [test "x$xorg_bus_linuxpci" = xyes]) -AM_CONDITIONAL([XORG_BUS_BSDPCI], [test "x$xorg_bus_bsdpci" = xyes]) -AM_CONDITIONAL([XORG_BUS_SPARC], [test "x$xorg_bus_sparc" = xyes]) -AM_CONDITIONAL([LINUX_IA64], [test "x$linux_ia64" = xyes]) -AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes]) -AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = xyes]) -AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test "x$solaris_asm_inline" = xyes]) -AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes]) -AM_CONDITIONAL([DGA], [test "x$DGA" = xyes]) -AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) - -dnl XWin DDX - -AC_MSG_CHECKING([whether to build XWin DDX]) -if test "x$XWIN" = xauto; then - case $host_os in - cygwin*) XWIN="yes" ;; - mingw*) XWIN="yes" ;; - *) XWIN="no" ;; - esac -fi -AC_MSG_RESULT([$XWIN]) - -if test "x$XWIN" = xyes; then - AC_DEFINE_DIR(SYSCONFDIR, sysconfdir, [Location of system.XWinrc]) - AC_DEFINE_DIR(DEFAULT_LOGDIR, logdir, [Default log location]) - AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) - AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) - AC_CHECK_TOOL(WINDRES, windres) - - PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau]) - - if test "x$WINDOWSWM" = xauto; then - PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no]) - fi - if test "x$WINDOWSWM" = xyes ; then - PKG_CHECK_MODULES(WINDOWSWM, $WINDOWSWMPROTO) - XWINMODULES_CFLAGS="$XWINMODULES_CFLAGS $WINDOWSWM_CFLAGS" - AC_DEFINE(ROOTLESS,1,[Build Rootless code]) - fi - - case $host_os in - cygwin*) - XWIN_SERVER_NAME=XWin - AC_DEFINE(HAS_DEVWINDOWS,1,[Cygwin has /dev/windows for signaling new win32 messages]) - ;; - mingw*) - XWIN_SERVER_NAME=Xming - AC_DEFINE(RELOCATE_PROJECTROOT,1,[Make PROJECT_ROOT relative to the xserver location]) - AC_DEFINE(HAS_WINSOCK,1,[Use Windows sockets]) - XWIN_SYS_LIBS=-lwinsock2 - ;; - esac - XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB" - XWIN_SYS_LIBS="$XWIN_SYS_LIBS $XWINMODULES_LIBS" - AC_SUBST(XWIN_LIBS) - AC_SUBST(XWIN_SERVER_NAME) - AC_SUBST(XWIN_SYS_LIBS) - - if test "x$DEBUGGING" = xyes; then - AC_DEFINE(CYGDEBUG, 1, [Simple debug messages]) - AC_DEFINE(CYGWINDOWING_DEBUG, 1, [Debug messages for window handling]) - AC_DEFINE(CYGMULTIWINDOW_DEBUG, 1, [Debug window manager]) - fi - - AC_DEFINE(DDXOSVERRORF, 1, [Use OsVendorVErrorF]) - AC_DEFINE(DDXBEFORERESET, 1, [Use ddxBeforeReset ]) -fi -AM_CONDITIONAL(XWIN, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_MULTIWINDOW, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_MULTIWINDOWEXTWM, [test "x$XWIN" = xyes && test "x$WINDOWSWM" = xyes]) -AM_CONDITIONAL(XWIN_CLIPBOARD, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_GLX_WINDOWS, [test "x$XWIN" = xyes && false]) -AM_CONDITIONAL(XWIN_NATIVEGDI, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_PRIMARYFB, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_RANDR, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_XV, [test "x$XWIN" = xyes && test "x$XV" = xyes]) - -dnl Darwin / OS X DDX -if test "x$XQUARTZ" = xyes; then - AC_DEFINE(XQUARTZ,1,[Have Quartz]) - AC_DEFINE(ROOTLESS,1,[Build Rootless code]) - - DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_LIB $MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB" - AC_SUBST([DARWIN_LIBS]) - - AC_CHECK_LIB([Xplugin],[xp_init],[:]) - - CFLAGS="${CFLAGS} -DROOTLESS_WORKAROUND -DROOTLESS_SAFEALPHA -DNO_ALLOCA" - - PKG_CHECK_MODULES(XPBPROXY, $APPLEWMPROTO $LIBAPPLEWM xfixes x11) - - if test "x$XQUARTZ_SPARKLE" = xyes ; then - AC_DEFINE(XQUARTZ_SPARKLE,1,[Support application updating through sparkle.]) - fi - - if test "x$STANDALONE_XPBPROXY" = xyes ; then - AC_DEFINE(STANDALONE_XPBPROXY,1,[Build a standalone xpbproxy]) - fi -fi - -# Support for objc in autotools is minimal and not documented. -OBJC='$(CC)' -OBJCLD='$(CCLD)' -OBJCLINK='$(LINK)' -OBJCFLAGS='$(CFLAGS)' -AC_SUBST([OBJC]) -AC_SUBST([OBJCCLD]) -AC_SUBST([OBJCLINK]) -AC_SUBST([OBJCFLAGS]) -# internal, undocumented automake func follows :( -_AM_DEPENDENCIES([OBJC]) -AM_CONDITIONAL(XQUARTZ, [test "x$XQUARTZ" = xyes]) -AM_CONDITIONAL(XQUARTZ_SPARKLE, [test "x$XQUARTZ_SPARKLE" != "xno"]) -AM_CONDITIONAL(STANDALONE_XPBPROXY, [test "x$STANDALONE_XPBPROXY" = xyes]) - -dnl DMX DDX -PKG_CHECK_MODULES( - [DMXMODULES], - [xmuu $LIBXEXT x11 xrender xfixes $LIBXI $DMXPROTO xau $XDMCP_MODULES], - [PKG_CHECK_MODULES( - [XDMXCONFIG_DEP], - [xaw7 xmu xt xpm x11], - [have_dmx=yes], - [have_dmx=no])], - [have_dmx=no]) -AC_MSG_CHECKING([whether to build Xdmx DDX]) -if test "x$DMX" = xauto; then - DMX="$have_dmx" - case $host_os in - cygwin*) DMX="no" ;; - darwin*) DMX="no" ;; - esac -fi -AC_MSG_RESULT([$DMX]) -AM_CONDITIONAL(DMX, [test "x$DMX" = xyes]) - -if test "x$DMX" = xyes; then - if test "x$have_dmx" = xno; then - AC_MSG_ERROR([Xdmx build explicitly requested, but required - modules not found.]) - fi - DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC" - XDMX_CFLAGS="$DMXMODULES_CFLAGS" - XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB" - XDMX_SYS_LIBS="$DMXMODULES_LIBS" - AC_SUBST([XDMX_CFLAGS]) - AC_SUBST([XDMX_LIBS]) - AC_SUBST([XDMX_SYS_LIBS]) - -dnl USB sources in DMX require - AC_CHECK_HEADER([linux/input.h], DMX_BUILD_USB="yes", - DMX_BUILD_USB="no") -dnl Linux sources in DMX require - AC_CHECK_HEADER([linux/keyboard.h], DMX_BUILD_LNX="yes", - DMX_BUILD_LNX="no") - AC_SUBST(XDMXCONFIG_DEP_CFLAGS) - AC_SUBST(XDMXCONFIG_DEP_LIBS) - PKG_CHECK_MODULES([DMXEXAMPLES_DEP], [$LIBDMX $LIBXEXT x11]) - AC_SUBST(DMXEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([DMXXMUEXAMPLES_DEP], [$LIBDMX xmu $LIBXEXT x11]) - AC_SUBST(DMXXMUEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([DMXXIEXAMPLES_DEP], [$LIBDMX $LIBXI $LIBXEXT x11]) - AC_SUBST(DMXXIEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([XTSTEXAMPLES_DEP], [$LIBXTST $LIBXEXT x11]) - AC_SUBST(XTSTEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([XRESEXAMPLES_DEP], [xres $LIBXEXT x11]) - AC_SUBST(XRESEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([X11EXAMPLES_DEP], [$LIBXEXT x11]) - AC_SUBST(X11EXAMPLES_DEP_LIBS) - -fi -AM_CONDITIONAL([DMX_BUILD_LNX], [test "x$DMX_BUILD_LNX" = xyes]) -AM_CONDITIONAL([DMX_BUILD_USB], [test "x$DMX_BUILD_USB" = xyes]) - -dnl kdrive DDX - -XEPHYR_LIBS= -XEPHYR_INCS= - -AM_CONDITIONAL(KDRIVE, [test x$KDRIVE = xyes]) - -if test "$KDRIVE" = yes; then - AC_DEFINE(KDRIVESERVER,1,[Build Kdrive X server]) - AC_DEFINE(KDRIVEDDXACTIONS,,[Build kdrive ddx]) - - AC_CHECK_HEADERS([linux/fb.h]) - if test "$ac_cv_header_linux_fb_h" = yes && test "x$XFBDEV" = xauto; then - XFBDEV=yes - fi - - if test "x$XFBDEV" = xyes; then - KDRIVEFBDEVLIB=yes - AC_DEFINE(KDRIVEFBDEV, 1, [Build fbdev-based kdrive server]) - fi - - - PKG_CHECK_MODULES([TSLIB], [tslib-0.0], [HAVE_TSLIB="yes"], [HAVE_TSLIB="no"]) - if test "x$HAVE_TSLIB" = xno; then - AC_CHECK_LIB(ts, ts_open, [ - HAVE_TSLIB="yes" - TSLIB_LIBS="-lts" - ]) - fi - - if test "xTSLIB" = xauto; then - TSLIB="$HAVE_TSLIB" - fi - - if test "x$TSLIB" = xyes; then - if ! test "x$HAVE_TSLIB" = xyes; then - AC_MSG_ERROR([tslib must be installed to build the tslib driver. See http://tslib.berlios.de/]) - else - AC_DEFINE(TSLIB, 1, [Have tslib support]) - fi - fi - - if test "x$KDRIVE_KBD" = xyes; then - AC_DEFINE(KDRIVE_KBD, 1, [Enable KDrive kbd driver]) - fi - if test "x$KDRIVE_EVDEV" = xyes; then - AC_DEFINE(KDRIVE_EVDEV, 1, [Enable KDrive evdev driver]) - fi - if test "x$KDRIVE_MOUSE" = xyes; then - AC_DEFINE(KDRIVE_MOUSE, 1, [Enable KDrive mouse driver]) - fi - - XEPHYR_REQUIRED_LIBS="x11 $LIBXEXT xau xdmcp" - if test "x$XV" = xyes; then - XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS xv" - fi - if test "x$DRI" = xyes && test "x$GLX" = xyes; then - XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS $LIBGL libdrm" - fi - - PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [xephyr="yes"], [xephyr="no"]) - if test "x$XEPHYR" = xauto; then - XEPHYR=$xephyr - fi - if test "x$XEPHYR" = xyes && test "x$xephyr" = xno; then - AC_MSG_ERROR([Xephyr dependencies missing]) - fi - - # Xephyr needs nanosleep() which is in librt on Solaris - AC_CHECK_FUNC([nanosleep], [], - AC_CHECK_LIB([rt], [nanosleep], XEPHYR_LIBS="$XEPHYR_LIBS -lrt")) - - # damage shadow extension glx (NOTYET) fb mi - KDRIVE_INC='-I$(top_srcdir)/hw/kdrive/src' - KDRIVE_PURE_INCS="$KDRIVE_INC $MIEXT_SYNC_INC $MIEXT_DAMAGE_INC $MIEXT_SHADOW_INC $XEXT_INC $FB_INC $MI_INC" - KDRIVE_OS_INC='-I$(top_srcdir)/hw/kdrive/linux' - KDRIVE_INCS="$KDRIVE_PURE_INCS $KDRIVE_OS_INC" - - KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS" - - KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB" - KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la' - case $host_os in - *linux*) - KDRIVE_OS_LIB='$(top_builddir)/hw/kdrive/linux/liblinux.la' - KDRIVELINUX=yes - if test "x$KDRIVE_EVDEV" = xauto; then - KDRIVE_EVDEV=yes - fi - if test "x$KDRIVE_KBD" = xauto; then - KDRIVE_KBD=yes - fi - if test "x$KDRIVE_MOUSE" = xauto; then - KDRIVE_MOUSE=yes - fi - ;; - *) - if test "x$KDRIVE_EVDEV" = xauto; then - KDRIVE_EVDEV=no - fi - if test "x$KDRIVE_KBD" = xauto; then - KDRIVE_KBD=no - fi - if test "x$KDRIVE_MOUSE" = xauto; then - KDRIVE_MOUSE=no - fi - ;; - esac - KDRIVE_STUB_LIB='$(top_builddir)/hw/kdrive/src/libkdrivestubs.la' - KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB" - KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS" - KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB" - KDRIVE_LIBS="$KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS $DLOPEN_LIBS $TSLIB_LIBS" - - AC_SUBST([XEPHYR_LIBS]) - AC_SUBST([XEPHYR_INCS]) -fi -AC_SUBST([KDRIVE_INCS]) -AC_SUBST([KDRIVE_PURE_INCS]) -AC_SUBST([KDRIVE_CFLAGS]) -AC_SUBST([KDRIVE_PURE_LIBS]) -AC_SUBST([KDRIVE_LOCAL_LIBS]) -AC_SUBST([KDRIVE_LIBS]) -AM_CONDITIONAL(KDRIVELINUX, [test "x$KDRIVELINUX" = xyes]) -AM_CONDITIONAL(KDRIVE_EVDEV, [test "x$KDRIVE_EVDEV" = xyes]) -AM_CONDITIONAL(KDRIVE_KBD, [test "x$KDRIVE_KBD" = xyes]) -AM_CONDITIONAL(KDRIVE_MOUSE, [test "x$KDRIVE_MOUSE" = xyes]) -AM_CONDITIONAL(TSLIB, [test "x$HAVE_TSLIB" = xyes]) -AM_CONDITIONAL(KDRIVEFBDEV, [test "x$XFBDEV" = xyes]) -AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes]) -AM_CONDITIONAL(BUILD_KDRIVEFBDEVLIB, [test "x$KDRIVE" = xyes && test "x$KDRIVEFBDEVLIB" = xyes]) -AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes]) - -dnl and the rest of these are generic, so they're in config.h -dnl -dnl though, thanks to the passing of some significant amount of time, the -dnl above is probably a complete fallacy, and you should not rely on it. -dnl but this is still actually better than imake, honest. -daniels - -AC_TRY_COMPILE([ -#include -#ifndef __GLIBC__ -#error not glibc -#endif -], [], [AC_DEFINE(_GNU_SOURCE, 1, - [ Enable GNU and other extensions to the C environment for glibc])]) - -AC_DEFINE_DIR(PROJECTROOT, prefix, [Overall prefix]) - -AC_SUBST([RELEASE_DATE]) -BUILD_DATE="`date +'%Y%m%d'`" -AC_SUBST([BUILD_DATE]) -BUILD_TIME="`date +'1%H%M%S'`" -AC_SUBST([BUILD_TIME]) - -DIX_CFLAGS="-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS" - -AC_SUBST([DIX_CFLAGS]) - -AC_SUBST([libdir]) -AC_SUBST([exec_prefix]) -AC_SUBST([prefix]) - -AC_CONFIG_COMMANDS([sdksyms], [touch hw/xfree86/loader/sdksyms.dep]) - -AC_OUTPUT([ -Makefile -glx/Makefile -include/Makefile -composite/Makefile -damageext/Makefile -dbe/Makefile -dix/Makefile -doc/Makefile -doc/man/Makefile -doc/xml/Makefile -doc/xml/dtrace/Makefile -doc/xml/xserver.ent -fb/Makefile -record/Makefile -config/Makefile -mi/Makefile -miext/Makefile -miext/sync/Makefile -miext/damage/Makefile -miext/shadow/Makefile -miext/cw/Makefile -miext/rootless/Makefile -os/Makefile -randr/Makefile -render/Makefile -xkb/Makefile -Xext/Makefile -Xi/Makefile -xfixes/Makefile -exa/Makefile -hw/Makefile -hw/xfree86/Makefile -hw/xfree86/common/Makefile -hw/xfree86/common/xf86Build.h -hw/xfree86/ddc/Makefile -hw/xfree86/dixmods/Makefile -hw/xfree86/dixmods/extmod/Makefile -hw/xfree86/doc/Makefile -hw/xfree86/doc/devel/Makefile -hw/xfree86/doc/man/Makefile -hw/xfree86/doc/sgml/Makefile -hw/xfree86/dri/Makefile -hw/xfree86/dri2/Makefile -hw/xfree86/exa/Makefile -hw/xfree86/exa/man/Makefile -hw/xfree86/fbdevhw/Makefile -hw/xfree86/fbdevhw/man/Makefile -hw/xfree86/i2c/Makefile -hw/xfree86/int10/Makefile -hw/xfree86/loader/Makefile -hw/xfree86/modes/Makefile -hw/xfree86/os-support/Makefile -hw/xfree86/os-support/bsd/Makefile -hw/xfree86/os-support/bus/Makefile -hw/xfree86/os-support/hurd/Makefile -hw/xfree86/os-support/misc/Makefile -hw/xfree86/os-support/linux/Makefile -hw/xfree86/os-support/solaris/Makefile -hw/xfree86/parser/Makefile -hw/xfree86/ramdac/Makefile -hw/xfree86/shadowfb/Makefile -hw/xfree86/vbe/Makefile -hw/xfree86/vgahw/Makefile -hw/xfree86/x86emu/Makefile -hw/xfree86/xaa/Makefile -hw/xfree86/utils/Makefile -hw/xfree86/utils/man/Makefile -hw/xfree86/utils/cvt/Makefile -hw/xfree86/utils/gtf/Makefile -hw/dmx/config/Makefile -hw/dmx/config/man/Makefile -hw/dmx/doc/Makefile -hw/dmx/doc/doxygen.conf -hw/dmx/examples/Makefile -hw/dmx/input/Makefile -hw/dmx/glxProxy/Makefile -hw/dmx/Makefile -hw/dmx/man/Makefile -hw/vfb/Makefile -hw/vfb/man/Makefile -hw/xnest/Makefile -hw/xnest/man/Makefile -hw/xwin/Makefile -hw/xwin/glx/Makefile -hw/xwin/man/Makefile -hw/xquartz/Makefile -hw/xquartz/GL/Makefile -hw/xquartz/bundle/Makefile -hw/xquartz/man/Makefile -hw/xquartz/mach-startup/Makefile -hw/xquartz/pbproxy/Makefile -hw/xquartz/xpr/Makefile -hw/kdrive/Makefile -hw/kdrive/ephyr/Makefile -hw/kdrive/ephyr/man/Makefile -hw/kdrive/fake/Makefile -hw/kdrive/fbdev/Makefile -hw/kdrive/linux/Makefile -hw/kdrive/src/Makefile -test/Makefile -test/xi2/Makefile -xorg-server.pc -]) +dnl Copyright © 2003-2007 Keith Packard, Daniel Stone +dnl +dnl Permission is hereby granted, free of charge, to any person obtaining a +dnl copy of this software and associated documentation files (the "Software"), +dnl to deal in the Software without restriction, including without limitation +dnl the rights to use, copy, modify, merge, publish, distribute, sublicense, +dnl and/or sell copies of the Software, and to permit persons to whom the +dnl Software is furnished to do so, subject to the following conditions: +dnl +dnl The above copyright notice and this permission notice (including the next +dnl paragraph) shall be included in all copies or substantial portions of the +dnl Software. +dnl +dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +dnl IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +dnl DEALINGS IN THE SOFTWARE. +dnl +dnl Authors: Keith Packard +dnl Daniel Stone +dnl an unwitting cast of miscellaneous others +dnl +dnl Process this file with autoconf to create configure. + +AC_PREREQ(2.57) +AC_INIT([xorg-server], 1.10.99.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) +RELEASE_DATE="unreleased" +AC_CONFIG_SRCDIR([Makefile.am]) +AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AM_MAINTAINER_MODE + +# Require xorg-macros minimum of 1.10 for XORG_CHECK_SGML_DOCTOOLS +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.10 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.10) +XORG_DEFAULT_OPTIONS +XORG_WITH_DOXYGEN(1.6.1) +XORG_CHECK_SGML_DOCTOOLS(1.5) + +m4_ifndef([XORG_FONT_MACROS_VERSION], [m4_fatal([must install fontutil 1.1 or later before running autoconf/autogen])]) +XORG_FONT_MACROS_VERSION(1.1) + +dnl this gets generated by autoheader, and thus contains all the defines. we +dnl don't ever actually use it, internally. +AC_CONFIG_HEADERS(include/do-not-use-config.h) +dnl xorg-server.h is an external header, designed to be included by loadable +dnl drivers. +AC_CONFIG_HEADERS(include/xorg-server.h) +dnl dix-config.h covers most of the DIX (i.e. everything but the DDX, not just +dnl dix/). +AC_CONFIG_HEADERS(include/dix-config.h) +dnl xorg-config.h covers the Xorg DDX. +AC_CONFIG_HEADERS(include/xorg-config.h) +dnl xkb-config.h covers XKB for the Xorg and Xnest DDXs. +AC_CONFIG_HEADERS(include/xkb-config.h) +dnl xwin-config.h covers the XWin DDX. +AC_CONFIG_HEADERS(include/xwin-config.h) +dnl kdrive-config.h covers the kdrive DDX +AC_CONFIG_HEADERS(include/kdrive-config.h) +dnl version-config.h covers the version numbers so they can be bumped without +dnl forcing an entire recompile.x +AC_CONFIG_HEADERS(include/version-config.h) + +AM_PROG_AS +AC_PROG_LN_S +AC_LIBTOOL_WIN32_DLL +AC_DISABLE_STATIC +AC_PROG_LIBTOOL +AC_PROG_MAKE_SET +PKG_PROG_PKG_CONFIG +AC_PROG_LEX +AC_PROG_YACC +AC_SYS_LARGEFILE +XORG_PROG_RAWCPP + +# Quoted so that make will expand $(CWARNFLAGS) in makefiles to allow +# easier overrides at build time. +XSERVER_CFLAGS='$(CWARNFLAGS)' + +dnl Check for dtrace program (needed to build Xserver dtrace probes) +dnl Also checks for , since some Linux distros have an +dnl ISDN trace program named dtrace +AC_ARG_WITH(dtrace, AS_HELP_STRING([--with-dtrace=PATH], + [Enable dtrace probes (default: enabled if dtrace found)]), + [WDTRACE=$withval], [WDTRACE=auto]) +if test "x$WDTRACE" = "xyes" -o "x$WDTRACE" = "xauto" ; then + AC_PATH_PROG(DTRACE, [dtrace], [not_found], [$PATH:/usr/sbin]) + if test "x$DTRACE" = "xnot_found" ; then + if test "x$WDTRACE" = "xyes" ; then + AC_MSG_FAILURE([dtrace requested but not found]) + fi + WDTRACE="no" + else + AC_CHECK_HEADER(sys/sdt.h, [HAS_SDT_H="yes"], [HAS_SDT_H="no"]) + if test "x$WDTRACE" = "xauto" -a "x$HAS_SDT_H" = "xno" ; then + WDTRACE="no" + fi + fi +fi +if test "x$WDTRACE" != "xno" ; then + AC_DEFINE(XSERVER_DTRACE, 1, + [Define to 1 if the DTrace Xserver provider probes should be built in.]) + +# Solaris/OpenSolaris require dtrace -G to build dtrace probe information into +# object files, and require linking with those as relocatable objects, not .a +# archives. MacOS X handles all this in the normal compiler toolchain, and on +# some releases (like Tiger), will error out on dtrace -G. For now, other +# platforms with Dtrace ports are assumed to support -G (the FreeBSD and Linux +# ports appear to, based on my web searches, but have not yet been tested). + case $host_os in + darwin*) SPECIAL_DTRACE_OBJECTS=no ;; + *) SPECIAL_DTRACE_OBJECTS=yes ;; + esac +fi +AM_CONDITIONAL(XSERVER_DTRACE, [test "x$WDTRACE" != "xno"]) +AM_CONDITIONAL(SPECIAL_DTRACE_OBJECTS, [test "x$SPECIAL_DTRACE_OBJECTS" = "xyes"]) + +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h sys/utsname.h]) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_BIGENDIAN([ENDIAN="X_BIG_ENDIAN"], [ENDIAN="X_LITTLE_ENDIAN"]) + +AC_CHECK_SIZEOF([unsigned long]) +if test "$ac_cv_sizeof_unsigned_long" = 8; then + AC_DEFINE(_XSERVER64, 1, [Define to 1 if unsigned long is 64 bits.]) +fi + +AC_TYPE_PID_T + +# Checks for headers/macros for byte swapping +# Known variants: +# bswap_16, bswap_32, bswap_64 (glibc) +# __swap16, __swap32, __swap64 (OpenBSD) +# bswap16, bswap32, bswap64 (other BSD's) +# and a fallback to local macros if none of the above are found + +# if is found, assume it's the correct version +AC_CHECK_HEADERS([byteswap.h]) + +# if is found, have to check which version +AC_CHECK_HEADER([sys/endian.h], [HAVE_SYS_ENDIAN_H="yes"], [HAVE_SYS_ENDIAN_H="no"]) + +if test "x$HAVE_SYS_ENDIAN_H" = "xyes" ; then + AC_MSG_CHECKING([for __swap16 variant of byteswapping macros]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include +#include + ], [ +int a = 1, b; +b = __swap16(a); + ]) +], [SYS_ENDIAN__SWAP='yes'], [SYS_ENDIAN__SWAP='no']) + AC_MSG_RESULT([$SYS_ENDIAN__SWAP]) + + AC_MSG_CHECKING([for bswap16 variant of byteswapping macros]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include +#include + ], [ +int a = 1, b; +b = bswap16(a); + ]) +], [SYS_ENDIAN_BSWAP='yes'], [SYS_ENDIAN_BSWAP='no']) + AC_MSG_RESULT([$SYS_ENDIAN_BSWAP]) + + if test "$SYS_ENDIAN_BSWAP" = "yes" ; then + USE_SYS_ENDIAN_H=yes + BSWAP=bswap + else + if test "$SYS_ENDIAN__SWAP" = "yes" ; then + USE_SYS_ENDIAN_H=yes + BSWAP=__swap + else + USE_SYS_ENDIAN_H=no + fi + fi + + if test "$USE_SYS_ENDIAN_H" = "yes" ; then + AC_DEFINE([USE_SYS_ENDIAN_H], 1, + [Define to use byteswap macros from ]) + AC_DEFINE_UNQUOTED([bswap_16], ${BSWAP}16, + [Define to 16-bit byteswap macro]) + AC_DEFINE_UNQUOTED([bswap_32], ${BSWAP}32, + [Define to 32-bit byteswap macro]) + AC_DEFINE_UNQUOTED([bswap_64], ${BSWAP}64, + [Define to 64-bit byteswap macro]) + fi +fi + +dnl Check to see if dlopen is in default libraries (like Solaris, which +dnl has it in libc), or if libdl is needed to get it. +AC_CHECK_FUNC([dlopen], [], + AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl")) +AC_SUBST(DLOPEN_LIBS) + +dnl Checks for library functions. +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr \ + strtol getopt getopt_long vsnprintf walkcontext backtrace \ + getisax getzoneid shmctl64 strcasestr ffs vasprintf]) +AC_FUNC_ALLOCA +dnl Old HAS_* names used in os/*.c. +AC_CHECK_FUNC([getdtablesize], + AC_DEFINE(HAS_GETDTABLESIZE, 1, [Have the 'getdtablesize' function.])) +AC_CHECK_FUNC([getifaddrs], + AC_DEFINE(HAS_GETIFADDRS, 1, [Have the 'getifaddrs' function.])) +AC_CHECK_FUNC([getpeereid], + AC_DEFINE(HAS_GETPEEREID, 1, [Have the 'getpeereid' function.])) +AC_CHECK_FUNC([getpeerucred], + AC_DEFINE(HAS_GETPEERUCRED, 1, [Have the 'getpeerucred' function.])) +AC_CHECK_FUNC([strlcat], HAVE_STRLCAT=yes, HAVE_STRLCAT=no) +AM_CONDITIONAL(NEED_STRLCAT, [test x$HAVE_STRLCAT = xno]) +AC_CHECK_FUNC([strlcpy], AC_DEFINE(HAS_STRLCPY, 1, [Have the 'strlcpy' function])) + +AM_CONDITIONAL(NEED_VSNPRINTF, [test x$HAVE_VSNPRINTF = xno]) + +dnl Check for mmap support for Xvfb +AC_CHECK_FUNC([mmap], AC_DEFINE(HAS_MMAP, 1, [Have the 'mmap' function.])) + +dnl Find the math libary +AC_CHECK_LIB(m, sqrt) +AC_CHECK_LIB(m, cbrt, AC_DEFINE(HAVE_CBRT, 1, [Have the 'cbrt' function])) + +AC_CHECK_HEADERS([ndbm.h dbm.h rpcsvc/dbm.h]) + +dnl AGPGART headers +AC_CHECK_HEADERS([linux/agpgart.h sys/agpio.h sys/agpgart.h], AGP=yes) +AM_CONDITIONAL(AGP, [test "x$AGP" = xyes]) + +dnl APM header +AC_CHECK_HEADERS([linux/apm_bios.h], LNXAPM=yes) +AM_CONDITIONAL(LNXAPM, [test "x$LNXAPM" = xyes]) + +dnl fbdev header +AC_CHECK_HEADERS([linux/fb.h], FBDEV=yes) +AM_CONDITIONAL(FBDEVHW, [test "x$FBDEV" = xyes]) + +dnl MTRR header +AC_CHECK_HEADERS([asm/mtrr.h], ac_cv_asm_mtrr_h=yes) +if test "x$ac_cv_asm_mtrr_h" = xyes; then + HAVE_MTRR=yes +fi + +dnl BSD MTRR header +AC_CHECK_HEADERS([sys/memrange.h], ac_cv_memrange_h=yes) +if test "x$ac_cv_memrange_h" = xyes; then + HAVE_MTRR=yes +fi + +if test "x$HAVE_MTRR" = xyes; then + AC_DEFINE(HAS_MTRR_SUPPORT, 1, [MTRR support available]) +fi + +dnl A NetBSD MTRR header +AC_CHECK_HEADERS([machine/mtrr.h], ac_cv_machine_mtrr_h=yes) +if test "x$ac_cv_machine_mtrr_h" = xyes; then + AC_DEFINE(HAS_MTRR_BUILTIN, 1, [Define to 1 if NetBSD built-in MTRR + support is available]) +fi + +dnl FreeBSD kldload support (sys/linker.h) +AC_CHECK_HEADERS([sys/linker.h], + [ac_cv_sys_linker_h=yes], + [ac_cv_sys_linker_h=no], + [#include ]) +AM_CONDITIONAL(FREEBSD_KLDLOAD, [test "x$ac_cv_sys_linker_h" = xyes]) + +AC_CACHE_CHECK([for SYSV IPC], + ac_cv_sysv_ipc, + [AC_TRY_LINK([ +#include +#include +#include +],[ +{ + int id; + id = shmget(IPC_PRIVATE, 512, SHM_W | SHM_R); + if (id < 0) return -1; + return shmctl(id, IPC_RMID, 0); +}], + [ac_cv_sysv_ipc=yes], + [ac_cv_sysv_ipc=no])]) +if test "x$ac_cv_sysv_ipc" = xyes; then + AC_DEFINE(HAVE_SYSV_IPC, 1, [Define to 1 if SYSV IPC is available]) +fi + +dnl OpenBSD /dev/xf86 aperture driver +if test -c /dev/xf86 ; then + AC_DEFINE(HAS_APERTURE_DRV, 1, [System has /dev/xf86 aperture driver]) +fi + +dnl BSD APM support +AC_CHECK_HEADER([machine/apmvar.h],[ + AC_CHECK_HEADER([sys/event.h], + ac_cv_BSD_KQUEUE_APM=yes, + ac_cv_BSD_APM=yes)]) + +AM_CONDITIONAL(BSD_APM, [test "x$ac_cv_BSD_APM" = xyes]) +AM_CONDITIONAL(BSD_KQUEUE_APM, [test "x$ac_cv_BSD_KQUEUE_APM" = xyes]) + +dnl glibc backtrace support check (hw/xfree86/common/xf86Events.c) +AC_CHECK_HEADER([execinfo.h],[ + AC_CHECK_LIB(c, backtrace, [ + AC_DEFINE(HAVE_BACKTRACE, 1, [Has backtrace support]) + AC_DEFINE(HAVE_EXECINFO_H, 1, [Have execinfo.h]) + ])] +) + +dnl --------------------------------------------------------------------------- +dnl Bus options and CPU capabilities. Replaces logic in +dnl hw/xfree86/os-support/bus/Makefile.am, among others. +dnl --------------------------------------------------------------------------- +DEFAULT_INT10="x86emu" + +dnl Override defaults as needed for specific platforms: + +case $host_cpu in + alpha*) + ALPHA_VIDEO=yes + case $host_os in + *freebsd*) SYS_LIBS=-lio ;; + *netbsd*) AC_DEFINE(USE_ALPHA_PIO, 1, [NetBSD PIO alpha IO]) ;; + esac + GLX_ARCH_DEFINES="-D__GLX_ALIGN64 -mieee" + ;; + arm*) + ARM_VIDEO=yes + ;; + i*86) + I386_VIDEO=yes + case $host_os in + *freebsd*) AC_DEFINE(USE_DEV_IO) ;; + *dragonfly*) AC_DEFINE(USE_DEV_IO) ;; + *netbsd*) AC_DEFINE(USE_I386_IOPL) + SYS_LIBS=-li386 + ;; + *openbsd*) AC_DEFINE(USE_I386_IOPL) + SYS_LIBS=-li386 + ;; + esac + ;; + powerpc*) + PPC_VIDEO=yes + case $host_os in + *freebsd*) DEFAULT_INT10=stub ;; + esac + ;; + sparc*) + SPARC64_VIDEO=yes + BSD_ARCH_SOURCES="sparc64_video.c ioperm_noop.c" + GLX_ARCH_DEFINES="-D__GLX_ALIGN64" + ;; + x86_64*|amd64*) + I386_VIDEO=yes + case $host_os in + *freebsd*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; + *dragonfly*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; + *netbsd*) AC_DEFINE(USE_I386_IOPL, 1, [BSD i386 iopl]) + SYS_LIBS=-lx86_64 + ;; + *openbsd*) AC_DEFINE(USE_AMD64_IOPL, 1, [BSD AMD64 iopl]) + SYS_LIBS=-lamd64 + ;; + esac + GLX_ARCH_DEFINES="-D__GLX_ALIGN64" + ;; + ia64*) + GLX_ARCH_DEFINES="-D__GLX_ALIGN64" + ;; + s390*) + GLX_ARCH_DEFINES="-D__GLX_ALIGN64" + ;; +esac +AC_SUBST(GLX_ARCH_DEFINES) + +dnl BSD *_video.c selection +AM_CONDITIONAL(ALPHA_VIDEO, [test "x$ALPHA_VIDEO" = xyes]) +AM_CONDITIONAL(ARM_VIDEO, [test "x$ARM_VIDEO" = xyes]) +AM_CONDITIONAL(I386_VIDEO, [test "x$I386_VIDEO" = xyes]) +AM_CONDITIONAL(PPC_VIDEO, [test "x$PPC_VIDEO" = xyes]) +AM_CONDITIONAL(SPARC64_VIDEO, [test "x$SPARC64_VIDEO" = xyes]) + +DRI=no +USE_SIGIO_BY_DEFAULT="yes" +dnl it would be nice to autodetect these *CONS_SUPPORTs +case $host_os in + *freebsd* | *dragonfly*) + case $host_os in + kfreebsd*-gnu) ;; + *) AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) ;; + esac + AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) + AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) + AC_DEFINE(SYSCONS_SUPPORT, 1, [System has syscons console]) + DRI=yes + ;; + *netbsd*) + AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) + AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) + AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) + AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) + DRI=yes + ;; + *openbsd*) + AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) + AC_DEFINE(PCVT_SUPPORT, 1, [System has PC console]) + AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) + ;; + *linux*) + DRI=yes + ;; + *solaris*) + PKG_CHECK_EXISTS(libdrm, DRI=yes, DRI=no) + # Disable use of SIGIO by default until some system bugs are + # fixed - see Sun/OpenSolaris bug id 6879897 + USE_SIGIO_BY_DEFAULT="no" + ;; + darwin*) + AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) + ;; + cygwin*) + CFLAGS="$CFLAGS -DFD_SETSIZE=256" + ;; +esac + +dnl augment XORG_RELEASE_VERSION for our snapshot number and to expose the +dnl major number +PVMAJOR=`echo $PACKAGE_VERSION | cut -d . -f 1` +PVS=`echo $PACKAGE_VERSION | cut -d . -f 4 | cut -d - -f 1` +if test "x$PVS" = "x"; then + PVS="0" +fi + +VENDOR_RELEASE="((($PVMAJOR) * 10000000) + (($PVM) * 100000) + (($PVP) * 1000) + $PVS)" +VENDOR_MAN_VERSION="Version ${PACKAGE_VERSION}" + +VENDOR_NAME="The X.Org Foundation" +VENDOR_NAME_SHORT="X.Org" +VENDOR_WEB="http://wiki.x.org" + +m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))]) + +dnl Build options. +AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], + [Obsolete - use --enable-strict-compilation instead]), + AC_MSG_ERROR([--enable-werror has been replaced by --enable-strict-compilation])) + +AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], + [Enable debugging (default: disabled)]), + [DEBUGGING=$enableval], [DEBUGGING=no]) +AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--enable-unit-tests], + [Enable unit-tests (default: auto)]), + [UNITTESTS=$enableval], [UNITTESTS=auto]) +AC_ARG_ENABLE(use-sigio-by-default, AS_HELP_STRING([--enable-use-sigio-by-default] + [Enable SIGIO input handlers by default (default: $USE_SIGIO_BY_DEFAULT)]), + [USE_SIGIO_BY_DEFAULT=$enableval], []) +AC_ARG_WITH(int10, AS_HELP_STRING([--with-int10=BACKEND], [int10 backend: vm86, x86emu or stub]), + [INT10="$withval"], + [INT10="$DEFAULT_INT10"]) +AC_ARG_WITH(vendor-name, AS_HELP_STRING([--with-vendor-name=VENDOR], + [Vendor string reported by the server]), + [ VENDOR_NAME="$withval" ], []) +AC_ARG_WITH(vendor-name-short, AS_HELP_STRING([--with-vendor-name-short=VENDOR], + [Short version of vendor string reported by the server]), + [ VENDOR_NAME_SHORT="$withval" ], []) +AC_ARG_WITH(vendor-web, AS_HELP_STRING([--with-vendor-web=URL], + [Vendor web address reported by the server]), + [ VENDOR_WEB="$withval" ], []) +AC_ARG_WITH(module-dir, AS_HELP_STRING([--with-module-dir=DIR], + [Directory where modules are installed (default: $libdir/xorg/modules)]), + [ moduledir="$withval" ], + [ moduledir="${libdir}/xorg/modules" ]) +AC_ARG_WITH(log-dir, AS_HELP_STRING([--with-log-dir=DIR], + [Directory where log files are kept (default: $localstatedir/log)]), + [ logdir="$withval" ], + [ logdir="$localstatedir/log" ]) +AC_ARG_WITH(builder-addr, AS_HELP_STRING([--with-builder-addr=ADDRESS], + [Builder address (default: xorg@lists.freedesktop.org)]), + [ BUILDERADDR="$withval" ], + [ BUILDERADDR="xorg@lists.freedesktop.org" ]) +AC_ARG_WITH(os-name, AS_HELP_STRING([--with-os-name=OSNAME], [Name of OS (default: output of "uname -srm")]), + [ OSNAME="$withval" ], + [ OSNAME=`uname -srm` ]) +AC_ARG_WITH(os-vendor, AS_HELP_STRING([--with-os-vendor=OSVENDOR], [Name of OS vendor]), + [ OSVENDOR="$withval" ], + [ OSVENDOR="" ]) +AC_ARG_WITH(builderstring, AS_HELP_STRING([--with-builderstring=BUILDERSTRING], [Additional builder string]), + [ BUILDERSTRING="$withval" ] + [ ]) + +dnl Determine font path +XORG_FONTROOTDIR +XORG_FONTSUBDIR(FONTMISCDIR, fontmiscdir, misc) +XORG_FONTSUBDIR(FONTOTFDIR, fontotfdir, OTF) +XORG_FONTSUBDIR(FONTTTFDIR, fontttfdir, TTF) +XORG_FONTSUBDIR(FONTTYPE1DIR, fonttype1dir, Type1) +XORG_FONTSUBDIR(FONT75DPIDIR, font75dpidir, 75dpi) +XORG_FONTSUBDIR(FONT100DPIDIR, font100dpidir, 100dpi) + +dnl Uses --default-font-path if set, otherwise checks for /etc/X11/fontpath.d, +dnl otherwise uses standard subdirectories of FONTROOTDIR. When cross +dnl compiling, assume default font path uses standard FONTROOTDIR directories. +DEFAULT_FONT_PATH="${FONTMISCDIR}/,${FONTTTFDIR}/,${FONTOTFDIR}/,${FONTTYPE1DIR}/,${FONT100DPIDIR}/,${FONT75DPIDIR}/" +if test "$cross_compiling" != yes; then + AC_CHECK_FILE([${sysconfdir}/X11/fontpath.d], + [DEFAULT_FONT_PATH='catalogue:${sysconfdir}/X11/fontpath.d'], + [case $host_os in + darwin*) DEFAULT_FONT_PATH="${DEFAULT_FONT_PATH},/Library/Fonts,/System/Library/Fonts" ;; + esac]) +fi +AC_ARG_WITH(default-font-path, AS_HELP_STRING([--with-default-font-path=PATH], [Comma separated list of font dirs]), + [ FONTPATH="$withval" ], + [ FONTPATH="${DEFAULT_FONT_PATH}" ]) + +AC_MSG_CHECKING([for default font path]) +AC_MSG_RESULT([$FONTPATH]) + +AC_ARG_WITH(xkb-path, AS_HELP_STRING([--with-xkb-path=PATH], [Path to XKB base dir (default: ${datadir}/X11/xkb)]), + [ XKBPATH="$withval" ], + [ XKBPATH="${datadir}/X11/xkb" ]) +AC_ARG_WITH(xkb-output, AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${datadir}/X11/xkb/compiled)]), + [ XKBOUTPUT="$withval" ], + [ XKBOUTPUT="compiled" ]) +AC_ARG_WITH(default-xkb-rules, AS_HELP_STRING([--with-default-xkb-rules=RULES], + [Keyboard ruleset (default: base/evdev)]), + [ XKB_DFLT_RULES="$withval" ], + [ XKB_DFLT_RULES="" ]) +AC_ARG_WITH(default-xkb-model, AS_HELP_STRING([--with-default-xkb-model=MODEL], + [Keyboard model (default: pc105)]), + [ XKB_DFLT_MODEL="$withval" ], + [ XKB_DFLT_MODEL="pc105" ]) +AC_ARG_WITH(default-xkb-layout, AS_HELP_STRING([--with-default-xkb-layout=LAYOUT], + [Keyboard layout (default: us)]), + [ XKB_DFLT_LAYOUT="$withval" ], + [ XKB_DFLT_LAYOUT="us" ]) +AC_ARG_WITH(default-xkb-variant, AS_HELP_STRING([--with-default-xkb-variant=VARIANT], + [Keyboard variant (default: (none))]), + [ XKB_DFLT_VARIANT="$withval" ], + [ XKB_DFLT_VARIANT="" ]) +AC_ARG_WITH(default-xkb-options, AS_HELP_STRING([--with-default-xkb-options=OPTIONS], + [Keyboard layout options (default: (none))]), + [ XKB_DFLT_OPTIONS="$withval" ], + [ XKB_DFLT_OPTIONS="" ]) +AC_ARG_WITH(serverconfig-path, AS_HELP_STRING([--with-serverconfig-path=PATH], + [Directory where ancillary server config files are installed (default: ${libdir}/xorg)]), + [ SERVERCONFIG="$withval" ], + [ SERVERCONFIG="${libdir}/xorg" ]) +AC_ARG_WITH(apple-applications-dir,AS_HELP_STRING([--with-apple-applications-dir=PATH], [Path to the Applications directory (default: /Applications/Utilities)]), + [ APPLE_APPLICATIONS_DIR="${withval}" ], + [ APPLE_APPLICATIONS_DIR="/Applications/Utilities" ]) +AC_SUBST([APPLE_APPLICATIONS_DIR]) +AC_ARG_WITH(apple-application-name,AS_HELP_STRING([--with-apple-application-name=NAME], [Name for the .app (default: X11)]), + [ APPLE_APPLICATION_NAME="${withval}" ], + [ APPLE_APPLICATION_NAME="X11" ]) +AC_SUBST([APPLE_APPLICATION_NAME]) +AC_ARG_WITH(launchd-id-prefix, AS_HELP_STRING([--with-launchd-id-prefix=PATH], [Prefix to use for launchd identifiers (default: org.x)]), + [ LAUNCHD_ID_PREFIX="${withval}" ], + [ LAUNCHD_ID_PREFIX="org.x" ]) +AC_SUBST([LAUNCHD_ID_PREFIX]) +AC_DEFINE_UNQUOTED(LAUNCHD_ID_PREFIX, "$LAUNCHD_ID_PREFIX", [Prefix to use for launchd identifiers]) +AC_ARG_ENABLE(sparkle,AS_HELP_STRING([--enable-sparkle], [Enable updating of X11.app using the Sparkle Framework (default: disabled)]), + [ XQUARTZ_SPARKLE="${enableval}" ], + [ XQUARTZ_SPARKLE="no" ]) +AC_SUBST([XQUARTZ_SPARKLE]) +AC_ARG_ENABLE(install-libxf86config, + AS_HELP_STRING([--enable-install-libxf86config], + [Install libxf86config (default: disabled)]), + [INSTALL_LIBXF86CONFIG=$enableval], + [INSTALL_LIBXF86CONFIG=no]) +AC_ARG_ENABLE(visibility, AC_HELP_STRING([--enable-visibility], [Enable symbol visibility (default: auto)]), + [SYMBOL_VISIBILITY=$enableval], + [SYMBOL_VISIBILITY=auto]) +AC_ARG_ENABLE(pc98, AC_HELP_STRING([--enable-pc98], [Enable PC98 support in Xorg (default: auto)]), + [SUPPORT_PC98=$enableval], + [SUPPORT_PC98=auto]) + +dnl GLX build options +AC_ARG_ENABLE(aiglx, AS_HELP_STRING([--enable-aiglx], [Build accelerated indirect GLX (default: enabled)]), + [AIGLX=$enableval], + [AIGLX=yes]) +AX_TLS +AC_ARG_ENABLE(glx-tls, AS_HELP_STRING([--enable-glx-tls], [Build GLX with TLS support (default: auto)]), + [GLX_USE_TLS=$enableval], + [GLX_USE_TLS=no + if test "${ac_cv_tls}" != "none" ; then + GLX_USE_TLS=yes + fi]) +AC_SUBST(GLX_TLS, ${GLX_USE_TLS}) + +dnl Extensions. +AC_ARG_ENABLE(registry, AS_HELP_STRING([--disable-registry], [Build string registry module (default: enabled)]), [XREGISTRY=$enableval], [XREGISTRY=yes]) +AC_ARG_ENABLE(composite, AS_HELP_STRING([--disable-composite], [Build Composite extension (default: enabled)]), [COMPOSITE=$enableval], [COMPOSITE=yes]) +AC_ARG_ENABLE(mitshm, AS_HELP_STRING([--disable-shm], [Build SHM extension (default: enabled)]), [MITSHM=$enableval], [MITSHM=yes]) +AC_ARG_ENABLE(xres, AS_HELP_STRING([--disable-xres], [Build XRes extension (default: enabled)]), [RES=$enableval], [RES=yes]) +AC_ARG_ENABLE(record, AS_HELP_STRING([--disable-record], [Build Record extension (default: enabled)]), [RECORD=$enableval], [RECORD=yes]) +AC_ARG_ENABLE(xv, AS_HELP_STRING([--disable-xv], [Build Xv extension (default: enabled)]), [XV=$enableval], [XV=yes]) +AC_ARG_ENABLE(xvmc, AS_HELP_STRING([--disable-xvmc], [Build XvMC extension (default: enabled)]), [XVMC=$enableval], [XVMC=yes]) +AC_ARG_ENABLE(dga, AS_HELP_STRING([--disable-dga], [Build DGA extension (default: auto)]), [DGA=$enableval], [DGA=auto]) +AC_ARG_ENABLE(screensaver, AS_HELP_STRING([--disable-screensaver], [Build ScreenSaver extension (default: enabled)]), [SCREENSAVER=$enableval], [SCREENSAVER=yes]) +AC_ARG_ENABLE(xdmcp, AS_HELP_STRING([--disable-xdmcp], [Build XDMCP extension (default: auto)]), [XDMCP=$enableval], [XDMCP=auto]) +AC_ARG_ENABLE(xdm-auth-1, AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-Auth-1 extension (default: auto)]), [XDMAUTH=$enableval], [XDMAUTH=auto]) +AC_ARG_ENABLE(glx, AS_HELP_STRING([--disable-glx], [Build GLX extension (default: enabled)]), [GLX=$enableval], [GLX=yes]) +AC_ARG_ENABLE(dri, AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval]) +AC_ARG_ENABLE(dri2, AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto]) +AC_ARG_ENABLE(xinerama, AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes]) +AC_ARG_ENABLE(xf86vidmode, AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto]) +AC_ARG_ENABLE(xace, AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes]) +AC_ARG_ENABLE(xselinux, AS_HELP_STRING([--enable-xselinux], [Build SELinux extension (default: disabled)]), [XSELINUX=$enableval], [XSELINUX=no]) +AC_ARG_ENABLE(xcsecurity, AS_HELP_STRING([--enable-xcsecurity], [Build Security extension (default: disabled)]), [XCSECURITY=$enableval], [XCSECURITY=no]) +AC_ARG_ENABLE(tslib, AS_HELP_STRING([--enable-tslib], [Build kdrive tslib touchscreen support (default: disabled)]), [TSLIB=$enableval], [TSLIB=no]) +AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes]) +AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--enable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no]) +AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes]) +AC_ARG_ENABLE(config-udev, AS_HELP_STRING([--enable-config-udev], [Build udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto]) +AC_ARG_ENABLE(config-dbus, AS_HELP_STRING([--enable-config-dbus], [Build D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=no]) +AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto]) +AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes]) +AC_ARG_ENABLE(xaa, AS_HELP_STRING([--enable-xaa], [Build XAA (default: enabled)]), [XAA=$enableval], [XAA=yes]) +AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with vga access (default: enabled)]), [VGAHW=$enableval], [VGAHW=yes]) +AC_ARG_ENABLE(vbe, AS_HELP_STRING([--enable-vbe], [Build Xorg with VBE module (default: enabled)]), [VBE=$enableval], [VBE=yes]) +AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) +AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no]) +AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes]) +AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes]) + +dnl DDXes. +AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) +AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (default: auto)]), [DMX=$enableval], [DMX=auto]) +AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes]) +AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto]) +AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) +AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) +AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) +dnl kdrive and its subsystems +AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: no)]), [KDRIVE=$enableval], [KDRIVE=no]) +AC_ARG_ENABLE(xephyr, AS_HELP_STRING([--enable-xephyr], [Build the kdrive Xephyr server (default: auto)]), [XEPHYR=$enableval], [XEPHYR=auto]) +AC_ARG_ENABLE(xfake, AS_HELP_STRING([--enable-xfake], [Build the kdrive 'fake' server (default: auto)]), [XFAKE=$enableval], [XFAKE=auto]) +AC_ARG_ENABLE(xfbdev, AS_HELP_STRING([--enable-xfbdev], [Build the kdrive framebuffer device server (default: auto)]), [XFBDEV=$enableval], [XFBDEV=auto]) +dnl kdrive options +AC_ARG_ENABLE(kdrive-kbd, AS_HELP_STRING([--enable-kdrive-kbd], [Build kbd driver for kdrive (default: auto)]), [KDRIVE_KBD=$enableval], [KDRIVE_KBD=auto]) +AC_ARG_ENABLE(kdrive-mouse, AC_HELP_STRING([--enable-kdrive-mouse], [Build mouse driver for kdrive (default: auto)]), [KDRIVE_MOUSE=$enableval], [KDRIVE_MOUSE=auto]) +AC_ARG_ENABLE(kdrive-evdev, AC_HELP_STRING([--enable-kdrive-evdev], [Build evdev driver for kdrive (default: auto)]), [KDRIVE_EVDEV=$enableval], [KDRIVE_EVDEV=auto]) + + +dnl chown/chmod to be setuid root as part of build +dnl Replaces InstallXserverSetUID in imake +AC_ARG_ENABLE(install-setuid, + AS_HELP_STRING([--enable-install-setuid], + [Install Xorg server as owned by root with setuid bit (default: auto)]), + [SETUID=$enableval], [SETUID=auto]) +AC_MSG_CHECKING([to see if we can install the Xorg server as root]) +if test "x$SETUID" = "xauto" ; then + case $host_os in + cygwin*) SETUID="no" ;; + darwin*) SETUID="no" ;; + *) + case $host_cpu in + sparc) SETUID="no" ;; + *) SETUID="yes" ;; + esac + esac + if test "x$SETUID" = xyes; then + touch testfile + chown root testfile > /dev/null 2>&1 || SETUID="no" + rm -f testfile + fi +fi +AC_MSG_RESULT([$SETUID]) +AM_CONDITIONAL(INSTALL_SETUID, [test "x$SETUID" = "xyes"]) + +dnl Issue an error if xtrans.m4 was not found and XTRANS_CONNECTION_FLAGS macro +dnl was not expanded, since xorg-server with no transport types is rather useless. +dnl +dnl If you're seeing an error here, be sure you installed the lib/xtrans module +dnl first and if it's not in the default location, that you set the ACLOCAL +dnl environment variable to find it, such as: +dnl ACLOCAL="aclocal -I ${PREFIX}/share/aclocal" +m4_pattern_forbid([^XTRANS_CONNECTION_FLAGS$]) + +# Transport selection macro from xtrans.m4 +XTRANS_CONNECTION_FLAGS + +# Secure RPC detection macro from xtrans.m4 +XTRANS_SECURE_RPC_FLAGS +AM_CONDITIONAL(SECURE_RPC, [test "x$SECURE_RPC" = xyes]) + +AM_CONDITIONAL(INT10_VM86, [test "x$INT10" = xvm86]) +AM_CONDITIONAL(INT10_X86EMU, [test "x$INT10" = xx86emu]) +AM_CONDITIONAL(INT10_STUB, [test "x$INT10" = xstub]) +if test "x$INT10" = xyes; then + dnl VM86 headers + AC_CHECK_HEADERS([sys/vm86.h sys/io.h]) +fi + +XORG_ENABLE_DOCS +XORG_ENABLE_DEVEL_DOCS +XORG_WITH_XMLTO(0.0.20) +XORG_WITH_FOP + +dnl Handle installing libxf86config +AM_CONDITIONAL(INSTALL_LIBXF86CONFIG, [test "x$INSTALL_LIBXF86CONFIG" = xyes]) + +dnl DDX Detection... Yes, it's ugly to have it here... but we need to +dnl handle this early on so that we don't require unsupported extensions +case $host_os in + cygwin*) + DGA=no + DRI2=no + XF86VIDMODE=no + XSELINUX=no + XV=no + ;; + darwin*) + DRI2=no + + if test x$XQUARTZ = xauto; then + AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[ + 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]) + + if test "X$xorg_cv_Carbon_framework" = Xyes; then + XQUARTZ=yes + else + XQUARTZ=no + fi + fi + + if test "x$XQUARTZ" = xyes ; then + XQUARTZ=yes + XVFB=no + XNEST=no + + COMPOSITE=no + DGA=no + DPMSExtension=no + XF86VIDMODE=no + fi + ;; + *) XQUARTZ=no ;; +esac + +dnl --------------------------------------------------------------------------- +dnl Extension section +dnl --------------------------------------------------------------------------- +XEXT_INC='-I$(top_srcdir)/Xext' +XEXT_LIB='$(top_builddir)/Xext/libXext.la' +XEXTXORG_LIB='$(top_builddir)/Xext/libXextbuiltin.la' + +dnl Optional modules +VIDEOPROTO="videoproto" +COMPOSITEPROTO="compositeproto >= 0.4" +RECORDPROTO="recordproto >= 1.13.99.1" +SCRNSAVERPROTO="scrnsaverproto >= 1.1" +RESOURCEPROTO="resourceproto" +DRIPROTO="xf86driproto >= 2.1.0" +DRI2PROTO="dri2proto >= 2.3" +XINERAMAPROTO="xineramaproto" +BIGFONTPROTO="xf86bigfontproto >= 1.2.0" +DGAPROTO="xf86dgaproto >= 2.0.99.1" +GLPROTO="glproto >= 1.4.10" +DMXPROTO="dmxproto >= 2.2.99.1" +VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1" +WINDOWSWMPROTO="windowswmproto" +APPLEWMPROTO="applewmproto >= 1.4" + +dnl Core modules for most extensions, et al. +SDK_REQUIRED_MODULES="[xproto >= 7.0.17] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 1.9.99.902] [kbproto >= 1.0.3] fontsproto" +# Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc +AC_SUBST(SDK_REQUIRED_MODULES) + +dnl List of libraries that require a specific version +LIBAPPLEWM="applewm >= 1.4" +LIBDMX="dmx >= 1.0.99.1" +LIBDRI="dri >= 7.8.0" +LIBDRM="libdrm >= 2.3.0" +LIBGL="gl >= 7.1.0" +LIBXEXT="xext >= 1.0.99.4" +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" +LIBPIXMAN="pixman-1 >= 0.21.6" + +dnl Pixman is always required, but we separate it out so we can link +dnl specific modules against it +PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) +REQUIRED_LIBS="$REQUIRED_LIBS $LIBPIXMAN $LIBXFONT xau" + +REQUIRED_MODULES="[fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] $SDK_REQUIRED_MODULES" + +if test "x$CONFIG_UDEV" = xyes && + { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then + AC_MSG_ERROR([Hotplugging through both libudev and dbus/hal not allowed]) +fi + +PKG_CHECK_MODULES(UDEV, $LIBUDEV, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no]) +if test "x$CONFIG_UDEV" = xauto; then + CONFIG_UDEV="$HAVE_LIBUDEV" +fi +AM_CONDITIONAL(CONFIG_UDEV, [test "x$CONFIG_UDEV" = xyes]) +if test "x$CONFIG_UDEV" = xyes; then + CONFIG_DBUS_API=no + CONFIG_HAL=no + if ! test "x$HAVE_LIBUDEV" = xyes; then + AC_MSG_ERROR([udev configuration API requested, but libudev is not installed]) + fi + AC_DEFINE(CONFIG_UDEV, 1, [Use libudev for input hotplug]) +fi + +dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas +dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config +dnl API. +PKG_CHECK_MODULES(DBUS, $LIBDBUS, [HAVE_DBUS=yes], [HAVE_DBUS=no]) +if test "x$HAVE_DBUS" = xyes; then + AC_DEFINE(HAVE_DBUS, 1, [Have D-Bus support]) +fi +AM_CONDITIONAL(HAVE_DBUS, [test "x$HAVE_DBUS" = xyes]) + +if test "x$CONFIG_DBUS_API" = xauto; then + CONFIG_DBUS_API="$HAVE_DBUS" +fi +if test "x$CONFIG_DBUS_API" = xyes; then + if ! test "x$HAVE_DBUS" = xyes; then + AC_MSG_ERROR([D-Bus configuration API requested, but D-Bus is not installed.]) + fi + + AC_DEFINE(CONFIG_DBUS_API, 1, [Use the D-Bus input configuration API]) + CONFIG_NEED_DBUS="yes" +fi +AM_CONDITIONAL(CONFIG_DBUS_API, [test "x$CONFIG_DBUS_API" = xyes]) + +PKG_CHECK_MODULES(HAL, hal, [HAVE_HAL=yes], [HAVE_HAL=no]) +if test "x$CONFIG_HAL" = xauto; then + CONFIG_HAL="$HAVE_HAL" +fi +if test "x$CONFIG_HAL" = xyes; then + if ! test "x$HAVE_HAL" = xyes; then + AC_MSG_ERROR([HAL hotplug API requested, but HAL is not installed.]) + fi + + AC_DEFINE(CONFIG_HAL, 1, [Use the HAL hotplug API]) + CONFIG_NEED_DBUS="yes" +fi +AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes]) + +if test "x$CONFIG_NEED_DBUS" = xyes; then + AC_DEFINE(CONFIG_NEED_DBUS, 1, [Use D-Bus for input hotplug]) +fi +AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes]) + +if test "x$USE_SIGIO_BY_DEFAULT" = xyes; then + USE_SIGIO_BY_DEFAULT_VALUE=TRUE +else + USE_SIGIO_BY_DEFAULT_VALUE=FALSE +fi +AC_DEFINE_UNQUOTED([USE_SIGIO_BY_DEFAULT], [$USE_SIGIO_BY_DEFAULT_VALUE], + [Use SIGIO handlers for input device events by default]) + +AC_MSG_CHECKING([for glibc...]) +AC_PREPROC_IFELSE([ +#include +#ifndef __GLIBC__ +#error +#endif +], glibc=yes, glibc=no) +AC_MSG_RESULT([$glibc]) + +AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], + [AC_CHECK_LIB([rt], [clock_gettime], [have_clock_gettime=-lrt], + [have_clock_gettime=no])]) + +AC_MSG_CHECKING([for a useful monotonic clock ...]) + +if ! test "x$have_clock_gettime" = xno; then + if ! test "x$have_clock_gettime" = xyes; then + CLOCK_LIBS="$have_clock_gettime" + else + CLOCK_LIBS="" + fi + + LIBS_SAVE="$LIBS" + LIBS="$CLOCK_LIBS" + CPPFLAGS_SAVE="$CPPFLAGS" + + if test x"$glibc" = xyes; then + CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE=200112L" + fi + + AC_RUN_IFELSE([ +#include + +int main(int argc, char *argv[[]]) { + struct timespec tp; + + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + return 0; + else + return 1; +} + ], [MONOTONIC_CLOCK=yes], [MONOTONIC_CLOCK=no], + [MONOTONIC_CLOCK="cross compiling"]) + + LIBS="$LIBS_SAVE" + CPPFLAGS="$CPPFLAGS_SAVE" +else + MONOTONIC_CLOCK=no +fi + +AC_MSG_RESULT([$MONOTONIC_CLOCK]) + +if test "x$MONOTONIC_CLOCK" = xyes; then + AC_DEFINE(MONOTONIC_CLOCK, 1, [Have monotonic clock from clock_gettime()]) + LIBS="$LIBS $CLOCK_LIBS" +fi + +AM_CONDITIONAL(XV, [test "x$XV" = xyes]) +if test "x$XV" = xyes; then + AC_DEFINE(XV, 1, [Support Xv extension]) + AC_DEFINE(XvExtension, 1, [Build Xv extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $VIDEOPROTO" + SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $VIDEOPROTO" +else + XVMC=no +fi + +AM_CONDITIONAL(XVMC, [test "x$XVMC" = xyes]) +if test "x$XVMC" = xyes; then + AC_DEFINE(XvMCExtension, 1, [Build XvMC extension]) +fi + +AM_CONDITIONAL(XREGISTRY, [test "x$XREGISTRY" = xyes]) +if test "x$XREGISTRY" = xyes; then + AC_DEFINE(XREGISTRY, 1, [Build registry module]) +fi + +AM_CONDITIONAL(COMPOSITE, [test "x$COMPOSITE" = xyes]) +if test "x$COMPOSITE" = xyes; then + AC_DEFINE(COMPOSITE, 1, [Support Composite Extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $COMPOSITEPROTO" + COMPOSITE_LIB='$(top_builddir)/composite/libcomposite.la' + COMPOSITE_INC='-I$(top_srcdir)/composite' +fi + +AM_CONDITIONAL(MITSHM, [test "x$MITSHM" = xyes]) +if test "x$MITSHM" = xyes; then + AC_DEFINE(MITSHM, 1, [Support MIT-SHM extension]) + AC_DEFINE(HAS_SHM, 1, [Support SHM]) +fi + +AM_CONDITIONAL(RECORD, [test "x$RECORD" = xyes]) +if test "x$RECORD" = xyes; then + AC_DEFINE(XRECORD, 1, [Support Record extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $RECORDPROTO" + RECORD_LIB='$(top_builddir)/record/librecord.la' +fi + +AM_CONDITIONAL(SCREENSAVER, [test "x$SCREENSAVER" = xyes]) +if test "x$SCREENSAVER" = xyes; then + AC_DEFINE(SCREENSAVER, 1, [Support MIT-SCREEN-SAVER extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $SCRNSAVERPROTO" +fi + +AM_CONDITIONAL(RES, [test "x$RES" = xyes]) +if test "x$RES" = xyes; then + AC_DEFINE(RES, 1, [Support X resource extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $RESOURCEPROTO" +fi + +# The XRes extension may support client ID tracking only if it has +# been specifically enabled. Client ID tracking is implicitly not +# supported if XRes extension is disabled. +AC_MSG_CHECKING([whether to track client ids]) +if test "x$RES" = xyes && test "x$CLIENTIDS" = xyes; then + AC_DEFINE(CLIENTIDS, 1, [Support client ID tracking]) +else + CLIENTIDS=no +fi +AC_MSG_RESULT([$CLIENTIDS]) +AM_CONDITIONAL(CLIENTIDS, [test "x$CLIENTIDS" = xyes]) + +if test "x$GLX" = xyes; then + PKG_CHECK_MODULES([XLIB], [x11]) + PKG_CHECK_MODULES([GL], $GLPROTO $LIBGL) + AC_SUBST(XLIB_CFLAGS) + AC_DEFINE(GLXEXT, 1, [Build GLX extension]) + GLX_LIBS='$(top_builddir)/glx/libglx.la' + GLX_SYS_LIBS="$GLX_SYS_LIBS" +else + GLX=no +fi +AM_CONDITIONAL(GLX, test "x$GLX" = xyes) + +if test "x$AIGLX" = xyes -a "x$GLX" = xyes -a "x$DRI" = xyes; then + AC_DEFINE(AIGLX, 1, [Build AIGLX loader]) +else + AIGLX=no +fi +AM_CONDITIONAL(AIGLX, test "x$AIGLX" = xyes) + +if test "x$GLX_USE_TLS" = xyes ; then + GLX_DEFINES="-DGLX_USE_TLS -DPTHREADS" + GLX_SYS_LIBS="$GLX_SYS_LIBS -lpthread" +fi +AC_SUBST([GLX_DEFINES]) + +AM_CONDITIONAL(DRI, test "x$DRI" = xyes) +if test "x$DRI" = xyes; then + AC_DEFINE(XF86DRI, 1, [Build DRI extension]) + PKG_CHECK_MODULES([DRIPROTO], [$DRIPROTO]) + PKG_CHECK_MODULES([DRI], $GLPROTO $LIBDRI) + AC_SUBST(DRIPROTO_CFLAGS) +fi + +PKG_CHECK_MODULES([DRI2PROTO], $DRI2PROTO, + [HAVE_DRI2PROTO=yes], [HAVE_DRI2PROTO=no]) +case "$DRI2,$HAVE_DRI2PROTO" in + yes,no) + AC_MSG_ERROR([DRI2 requested, but dri2proto not found.]) + ;; + yes,yes | auto,yes) + AC_DEFINE(DRI2, 1, [Build DRI2 extension]) + DRI2=yes + SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI2PROTO" + ;; +esac +AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes) + +if test "x$DRI" = xyes || test "x$DRI2" = xyes; then + if test "x$DRM" = xyes; then + AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support]) + PKG_CHECK_MODULES([LIBDRM], $LIBDRM) + fi +fi + +if test "x$DRI2" = xyes; then + save_CFLAGS=$CFLAGS + CFLAGS="$GL_CFLAGS $LIBDRM_CFLAGS" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include +#include +#ifndef __DRI_DRI2 +#error DRI2 extension not available. +#endif]])], + [HAVE_DRI2EXTENSION=yes], + [HAVE_DRI2EXTENSION=no]) + CFLAGS=$save_CFLAGS + if test "x$HAVE_DRI2EXTENSION" = xyes; then + AC_DEFINE(DRI2_AIGLX, 1, [Build DRI2 AIGLX loader]) + DRI2_AIGLX=yes + else + AC_MSG_NOTICE([DRI2 AIGLX disabled, __DRI_DRI2 not defined in dri_interface.h.]) + DRI2_AIGLX=no + fi +fi +AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes) + + +AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes]) +if test "x$XINERAMA" = xyes; then + AC_DEFINE(XINERAMA, 1, [Support Xinerama extension]) + AC_DEFINE(PANORAMIX, 1, [Internal define for Xinerama]) + REQUIRED_MODULES="$REQUIRED_MODULES $XINERAMAPROTO" + SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $XINERAMAPROTO" +fi + +AM_CONDITIONAL(XACE, [test "x$XACE" = xyes]) +if test "x$XACE" = xyes; then + AC_DEFINE(XACE, 1, [Build X-ACE extension]) +fi + +AM_CONDITIONAL(XSELINUX, [test "x$XSELINUX" = xyes]) +if test "x$XSELINUX" = xyes; then + if test "x$XACE" != xyes; then + AC_MSG_ERROR([cannot build SELinux extension without X-ACE]) + fi + AC_CHECK_HEADERS([libaudit.h], [], AC_MSG_ERROR([SELinux extension requires audit system headers])) + AC_CHECK_LIB(audit, audit_open, [], AC_MSG_ERROR([SELinux extension requires audit system library])) + PKG_CHECK_MODULES([SELINUX], $LIBSELINUX) + SELINUX_LIBS="$SELINUX_LIBS -laudit" + AC_DEFINE(XSELINUX, 1, [Build SELinux extension]) +fi + +AM_CONDITIONAL(XCSECURITY, [test "x$XCSECURITY" = xyes]) +if test "x$XCSECURITY" = xyes; then + if test "x$XACE" != xyes; then + AC_MSG_ERROR([cannot build Security extension without X-ACE]) + fi + AC_DEFINE(XCSECURITY, 1, [Build Security extension]) +fi + +AM_CONDITIONAL(DBE, [test "x$DBE" = xyes]) +if test "x$DBE" = xyes; then + AC_DEFINE(DBE, 1, [Support DBE extension]) + DBE_LIB='$(top_builddir)/dbe/libdbe.la' +fi + +AM_CONDITIONAL(XF86BIGFONT, [test "x$XF86BIGFONT" = xyes]) +if test "x$XF86BIGFONT" = xyes; then + AC_DEFINE(XF86BIGFONT, 1, [Support XF86 Big font extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $BIGFONTPROTO" +fi + +AM_CONDITIONAL(DPMSExtension, [test "x$DPMSExtension" = xyes]) +if test "x$DPMSExtension" = xyes; then + AC_DEFINE(DPMSExtension, 1, [Support DPMS extension]) +fi + +AC_DEFINE(RENDER, 1, [Support RENDER extension]) +RENDER_LIB='$(top_builddir)/render/librender.la' +RENDER_INC='-I$(top_srcdir)/render' + +AC_DEFINE(RANDR, 1, [Support RANDR extension]) +RANDR_LIB='$(top_builddir)/randr/librandr.la' +RANDR_INC='-I$(top_srcdir)/randr' + +AC_DEFINE(XFIXES,1,[Support XFixes extension]) +FIXES_LIB='$(top_builddir)/xfixes/libxfixes.la' +FIXES_INC='-I$(top_srcdir)/xfixes' + +AC_DEFINE(DAMAGE,1,[Support Damage extension]) +DAMAGE_LIB='$(top_builddir)/damageext/libdamageext.la' +DAMAGE_INC='-I$(top_srcdir)/damageext' +MIEXT_DAMAGE_LIB='$(top_builddir)/miext/damage/libdamage.la' +MIEXT_DAMAGE_INC='-I$(top_srcdir)/miext/damage' + +# XINPUT extension is integral part of the server +AC_DEFINE(XINPUT, 1, [Support X Input extension]) +XI_LIB='$(top_builddir)/Xi/libXi.la' +XI_INC='-I$(top_srcdir)/Xi' + +AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes) +AM_CONDITIONAL(XAA, test "x$XAA" = xyes) +AM_CONDITIONAL(VGAHW, test "x$VGAHW" = xyes) +AM_CONDITIONAL(VBE, test "x$VBE" = xyes) +AM_CONDITIONAL(INT10MODULE, test "x$INT10MODULE" = xyes) + +AC_DEFINE(SHAPE, 1, [Support SHAPE extension]) + +AC_DEFINE_DIR(XKB_BASE_DIRECTORY, XKBPATH, [Path to XKB data]) +AC_ARG_WITH(xkb-bin-directory, + AS_HELP_STRING([--with-xkb-bin-directory=DIR], [Directory containing xkbcomp program]), + [XKB_BIN_DIRECTORY="$withval"], + [XKB_BIN_DIRECTORY="$bindir"]) + +AC_DEFINE_DIR(XKB_BIN_DIRECTORY, XKB_BIN_DIRECTORY, [Path to XKB bin dir]) + +dnl Make sure XKM_OUTPUT_DIR is an absolute path +XKBOUTPUT_FIRSTCHAR=`echo $XKBOUTPUT | cut -b 1` +if [[ x$XKBOUTPUT_FIRSTCHAR != x/ -a x$XKBOUTPUT_FIRSTCHAR != 'x$' ]] ; then + XKBOUTPUT="$XKB_BASE_DIRECTORY/$XKBOUTPUT" +fi + +dnl XKM_OUTPUT_DIR (used in code) must end in / or file names get hosed +dnl XKB_COMPILED_DIR (used in Makefiles) must not or install-sh gets confused + +XKBOUTPUT=`echo $XKBOUTPUT/ | $SED 's|/*$|/|'` +XKB_COMPILED_DIR=`echo $XKBOUTPUT | $SED 's|/*$||'` +AC_DEFINE_DIR(XKM_OUTPUT_DIR, XKBOUTPUT, [Path to XKB output dir]) +AC_SUBST(XKB_COMPILED_DIR) + +if test "x$XKB_DFLT_RULES" = x; then + case $host_os in + linux*) + dnl doesn't take AutoAddDevices into account, but whatever. + if test "x$CONFIG_HAL" = xyes; then + XKB_DFLT_RULES="evdev" + else + XKB_DFLT_RULES="base" + fi + ;; + *) + XKB_DFLT_RULES="base" + ;; + esac +fi +AC_DEFINE_UNQUOTED(XKB_DFLT_RULES, ["$XKB_DFLT_RULES"], [Default XKB ruleset]) +AC_DEFINE_UNQUOTED(XKB_DFLT_MODEL, ["$XKB_DFLT_MODEL"], [Default XKB model]) +AC_DEFINE_UNQUOTED(XKB_DFLT_LAYOUT, ["$XKB_DFLT_LAYOUT"], [Default XKB layout]) +AC_DEFINE_UNQUOTED(XKB_DFLT_VARIANT, ["$XKB_DFLT_VARIANT"], [Default XKB variant]) +AC_DEFINE_UNQUOTED(XKB_DFLT_OPTIONS, ["$XKB_DFLT_OPTIONS"], [Default XKB options]) + +XKB_LIB='$(top_builddir)/xkb/libxkb.la' +XKB_STUB_LIB='$(top_builddir)/xkb/libxkbstubs.la' +REQUIRED_MODULES="$REQUIRED_MODULES xkbfile" + +AC_CHECK_FUNC(strcasecmp, [], AC_DEFINE([NEED_STRCASECMP], 1, + [Do not have 'strcasecmp'.])) +AC_CHECK_FUNC(strncasecmp, [], AC_DEFINE([NEED_STRNCASECMP], 1, + [Do not have 'strncasecmp'.])) +AC_CHECK_FUNC(strcasestr, [], AC_DEFINE([NEED_STRCASESTR], 1, + [Do not have 'strcasestr'.])) + +PKG_CHECK_MODULES([XDMCP], [xdmcp], [have_libxdmcp="yes"], [have_libxdmcp="no"]) +if test "x$have_libxdmcp" = xyes; then + AC_CHECK_LIB(Xdmcp, XdmcpWrap, [have_xdmcpwrap="yes"], [have_xdmcpwrap="no"], [$XDMCP_LIBS]) +fi +if test "x$XDMCP" = xauto; then + if test "x$have_libxdmcp" = xyes; then + XDMCP=yes + else + XDMCP=no + fi +fi +if test "x$XDMAUTH" = xauto; then + if test "x$have_libxdmcp" = xyes && test "x$have_xdmcpwrap" = xyes; then + XDMAUTH=yes + else + XDMAUTH=no + fi +fi + +AM_CONDITIONAL(XDMCP, [test "x$XDMCP" = xyes]) +if test "x$XDMCP" = xyes; then + AC_DEFINE(XDMCP, 1, [Support XDM Control Protocol]) + REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" + XDMCP_MODULES="xdmcp" +fi + +AM_CONDITIONAL(XDMAUTH, [test "x$XDMAUTH" = xyes]) +if test "x$XDMAUTH" = xyes; then + AC_DEFINE(HASXDMAUTH,1,[Support XDM-AUTH*-1]) + if ! test "x$XDMCP" = xyes; then + REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" + XDMCP_MODULES="xdmcp" + fi +fi + +AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path]) +AC_DEFINE_DIR(PCI_TXT_IDS_PATH, PCI_TXT_IDS_DIR, [Default PCI text file ID path]) +AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path]) +AC_DEFINE_DIR(BASE_FONT_PATH, FONTROOTDIR, [Default base font path]) +dridriverdir=`$PKG_CONFIG --variable=dridriverdir dri` +AC_DEFINE_DIR(DRI_DRIVER_PATH, dridriverdir, [Default DRI driver path]) +AC_DEFINE_UNQUOTED(XVENDORNAME, ["$VENDOR_NAME"], [Vendor name]) +AC_DEFINE_UNQUOTED(XVENDORNAMESHORT, ["$VENDOR_NAME_SHORT"], [Short vendor name]) +AC_DEFINE_UNQUOTED(XORG_DATE, ["$RELEASE_DATE"], [Vendor release]) +AC_DEFINE_UNQUOTED(XORG_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) +AC_DEFINE_UNQUOTED(BUILDERADDR, ["$BUILDERADDR"], [Builder address]) + +if test -z "$OSNAME"; then + OSNAME="UNKNOWN" +fi + +AC_DEFINE_UNQUOTED(OSNAME, ["$OSNAME"], [Operating System Name]) +AC_DEFINE_UNQUOTED(OSVENDOR, ["$OSVENDOR"], [Operating System Vendor]) +AC_DEFINE_UNQUOTED(BUILDERSTRING, ["$BUILDERSTRING"], [Builder string]) + +AC_SUBST([VENDOR_NAME_SHORT]) +AC_DEFINE_UNQUOTED(VENDOR_NAME, ["$VENDOR_NAME"], [Vendor name]) +AC_DEFINE_UNQUOTED(VENDOR_NAME_SHORT, ["$VENDOR_NAME_SHORT"], [Vendor name]) +AC_DEFINE_UNQUOTED(VENDOR_RELEASE, [$VENDOR_RELEASE], [Vendor release]) +AC_DEFINE_UNQUOTED(VENDOR_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) + +AC_DEFINE(NO_LIBCWRAPPER, 1, [Define to 1 if modules should avoid the libcwrapper]) + +if test "x$DEBUGGING" = xyes; then + AC_DEFINE(DEBUG, 1, [Enable debugging code]) +fi +AM_CONDITIONAL(DEBUG, [test "x$DEBUGGING" = xyes]) + +# If unittests aren't explicitly disabled, check for required support +if test "x$UNITTESTS" != xno ; then + PKG_CHECK_MODULES([GLIB], $LIBGLIB, + [HAVE_GLIB=yes], [HAVE_GLIB=no]) + + # Check if linker supports -wrap, passed via compiler flags + # When cross-compiling, reports no, since unit tests run from + # "make check", so would be running on build machine, not target + AC_MSG_CHECKING([whether the linker supports -wrap]) + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,-wrap,exit" + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ + void __wrap_exit (int s) + { + __real_exit (0); + }]], + [[exit (1);]])], + [linker_can_wrap="yes"], + [linker_can_wrap="no"], + [linker_can_wrap="no"]) + AC_MSG_RESULT([$linker_can_wrap]) + LDFLAGS="$save_LDFLAGS" +fi + +if test "x$UNITTESTS" = xauto; then + if test "x$HAVE_GLIB" = xyes && test "x$linker_can_wrap" = xyes; then + UNITTESTS=yes + else + UNITTESTS=no + fi +fi +if test "x$UNITTESTS" = xyes; then + if test "x$HAVE_GLIB" = xno; then + AC_MSG_ERROR([glib required to build unit tests]) + fi + if test "x$linker_can_wrap" = xno; then + AC_MSG_ERROR([ld -wrap support required to build unit tests]) + fi + AC_DEFINE(UNITTESTS, 1, [Enable unit tests]) + AC_SUBST([GLIB_LIBS]) + AC_SUBST([GLIB_CFLAGS]) +fi +AM_CONDITIONAL(UNITTESTS, [test "x$UNITTESTS" = xyes]) + +AC_DEFINE(XTEST, 1, [Support XTest extension]) +AC_DEFINE(XSYNC, 1, [Support XSync extension]) +AC_DEFINE(XCMISC, 1, [Support XCMisc extension]) +AC_DEFINE(BIGREQS, 1, [Support BigRequests extension]) + +if test "x$SPECIAL_DTRACE_OBJECTS" = "xyes" ; then + DIX_LIB='$(top_builddir)/dix/dix.O' + OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS) $(DLOPEN_LIBS)' +else + DIX_LIB='$(top_builddir)/dix/libdix.la' + OS_LIB='$(top_builddir)/os/libos.la' +fi +AC_SUBST([DIX_LIB]) +AC_SUBST([OS_LIB]) + +MAIN_LIB='$(top_builddir)/dix/libmain.la' +AC_SUBST([MAIN_LIB]) + +MI_LIB='$(top_builddir)/mi/libmi.la' +MI_EXT_LIB='$(top_builddir)/mi/libmiext.la' +MI_INC='-I$(top_srcdir)/mi' +FB_LIB='$(top_builddir)/fb/libfb.la' +FB_INC='-I$(top_srcdir)/fb' +MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow' +MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' +MIEXT_SYNC_INC='-I$(top_srcdir)/miext/sync' +MIEXT_SYNC_LIB='$(top_builddir)/miext/sync/libsync.la' +CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include' + +# SHA1 hashing +AC_ARG_WITH([sha1], + [AS_HELP_STRING([--with-sha1=libc|libmd|libgcrypt|libcrypto|libsha1|CommonCrypto], + [choose SHA1 implementation])]) +AC_CHECK_FUNC([SHA1Init], [HAVE_SHA1_IN_LIBC=yes]) +if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_LIBC" = xyes; then + with_sha1=libc +fi +if test "x$with_sha1" = xlibc && test "x$HAVE_SHA1_IN_LIBC" != xyes; then + AC_MSG_ERROR([libc requested but not found]) +fi +if test "x$with_sha1" = xlibc; then + AC_DEFINE([HAVE_SHA1_IN_LIBC], [1], + [Use libc SHA1 functions]) + SHA1_LIBS="" +fi +AC_CHECK_FUNC([CC_SHA1_Init], [HAVE_SHA1_IN_COMMONCRYPTO=yes]) +if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_COMMONCRYPTO" = xyes; then + with_sha1=CommonCrypto +fi +if test "x$with_sha1" = xCommonCrypto && test "x$HAVE_SHA1_IN_COMMONCRYPTO" != xyes; then + AC_MSG_ERROR([CommonCrypto requested but not found]) +fi +if test "x$with_sha1" = xCommonCrypto; then + AC_DEFINE([HAVE_SHA1_IN_COMMONCRYPTO], [1], + [Use CommonCrypto SHA1 functions]) + SHA1_LIBS="" +fi +AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes]) +if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then + with_sha1=libmd +fi +if test "x$with_sha1" = xlibmd && test "x$HAVE_LIBMD" != xyes; then + AC_MSG_ERROR([libmd requested but not found]) +fi +if test "x$with_sha1" = xlibmd; then + AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1], + [Use libmd SHA1 functions]) + SHA1_LIBS=-lmd +fi +PKG_CHECK_MODULES([LIBSHA1], [libsha1], [HAVE_LIBSHA1=yes], [HAVE_LIBSHA1=no]) +if test "x$with_sha1" = x && test "x$HAVE_LIBSHA1" = xyes; then + with_sha1=libsha1 +fi +if test "x$with_sha1" = xlibsha1 && test "x$HAVE_LIBSHA1" != xyes; then + AC_MSG_ERROR([libsha1 requested but not found]) +fi +if test "x$with_sha1" = xlibsha1; then + AC_DEFINE([HAVE_SHA1_IN_LIBSHA1], [1], + [Use libsha1 for SHA1]) + SHA1_LIBS=-lsha1 +fi +AC_CHECK_LIB([gcrypt], [gcry_md_open], [HAVE_LIBGCRYPT=yes]) +if test "x$with_sha1" = x && test "x$HAVE_LIBGCRYPT" = xyes; then + with_sha1=libgcrypt +fi +if test "x$with_sha1" = xlibgcrypt && test "x$HAVE_LIBGCRYPT" != xyes; then + AC_MSG_ERROR([libgcrypt requested but not found]) +fi +if test "x$with_sha1" = xlibgcrypt; then + AC_DEFINE([HAVE_SHA1_IN_LIBGCRYPT], [1], + [Use libgcrypt SHA1 functions]) + SHA1_LIBS=-lgcrypt +fi +# We don't need all of the OpenSSL libraries, just libcrypto +AC_CHECK_LIB([crypto], [SHA1_Init], [HAVE_LIBCRYPTO=yes]) +PKG_CHECK_MODULES([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes], + [HAVE_OPENSSL_PKC=no]) +if test "x$HAVE_LIBCRYPTO" = xyes || test "x$HAVE_OPENSSL_PKC" = xyes; then + if test "x$with_sha1" = x; then + with_sha1=libcrypto + fi +else + if test "x$with_sha1" = xlibcrypto; then + AC_MSG_ERROR([OpenSSL libcrypto requested but not found]) + fi +fi +if test "x$with_sha1" = xlibcrypto; then + if test "x$HAVE_LIBCRYPTO" = xyes; then + SHA1_LIBS=-lcrypto + else + SHA1_LIBS="$OPENSSL_LIBS" + SHA1_CFLAGS="$OPENSSL_CFLAGS" + fi +fi +AC_MSG_CHECKING([for SHA1 implementation]) +if test "x$with_sha1" = x; then + AC_MSG_ERROR([No suitable SHA1 implementation found]) +fi +AC_MSG_RESULT([$with_sha1]) +AC_SUBST(SHA1_LIBS) +AC_SUBST(SHA1_CFLAGS) + +PKG_CHECK_MODULES([XSERVERCFLAGS], [$REQUIRED_MODULES $REQUIRED_LIBS]) +PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS]) + +# Autotools has some unfortunate issues with library handling. In order to +# get a server to rebuild when a dependency in the tree is changed, it must +# be listed in SERVERNAME_DEPENDENCIES. However, no system libraries may be +# listed there, or some versions of autotools will break (especially if a -L +# is required to find the library). So, we keep two sets of libraries +# detected: NAMESPACE_LIBS for in-tree libraries to be linked against, which +# will go into the _DEPENDENCIES and _LDADD of the server, and +# NAMESPACE_SYS_LIBS which will go into only the _LDADD. The +# NAMESPACEMODULES_LIBS detected from pkgconfig should always go in +# NAMESPACE_SYS_LIBS. +# +# XSERVER_LIBS is the set of in-tree libraries which all servers require. +# XSERVER_SYS_LIBS is the set of out-of-tree libraries which all servers +# require. +# +XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS}" +XSERVER_LIBS="$DIX_LIB $MI_LIB $OS_LIB" +XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS}" +AC_SUBST([XSERVER_LIBS]) +AC_SUBST([XSERVER_SYS_LIBS]) + +UTILS_SYS_LIBS="${SYS_LIBS}" +AC_SUBST([UTILS_SYS_LIBS]) + +# The Xorg binary needs to export symbols so that they can be used from modules +# Some platforms require extra flags to do this. libtool should set the +# necessary flags for each platform when -export-dynamic is passed to it. +LD_EXPORT_SYMBOLS_FLAG="-export-dynamic" +AC_SUBST([LD_EXPORT_SYMBOLS_FLAG]) + +dnl Imake defines SVR4 on SVR4 systems, and many files check for it, so +dnl we need to replicate that here until those can all be fixed +AC_MSG_CHECKING([if SVR4 needs to be defined]) +AC_EGREP_CPP([I_AM_SVR4],[ +#if defined(SVR4) || defined(__svr4__) || defined(__SVR4) + I_AM_SVR4 +#endif +],[ +AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4]) +AC_MSG_RESULT([yes])], AC_MSG_RESULT([no])) + +XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC" + +dnl --------------------------------------------------------------------------- +dnl DDX section. +dnl --------------------------------------------------------------------------- + +dnl Xvfb DDX + +AC_MSG_CHECKING([whether to build Xvfb DDX]) +AC_MSG_RESULT([$XVFB]) +AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes]) + +if test "x$XVFB" = xyes; then + XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB" + XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS" + AC_SUBST([XVFB_LIBS]) + AC_SUBST([XVFB_SYS_LIBS]) +fi + + +dnl Xnest DDX + +PKG_CHECK_MODULES(XNESTMODULES, [$LIBXEXT x11 xau $XDMCP_MODULES], [have_xnest=yes], [have_xnest=no]) +AC_MSG_CHECKING([whether to build Xnest DDX]) +if test "x$XNEST" = xauto; then + XNEST="$have_xnest" +fi +AC_MSG_RESULT([$XNEST]) +AM_CONDITIONAL(XNEST, [test "x$XNEST" = xyes]) + +if test "x$XNEST" = xyes; then + if test "x$have_xnest" = xno; then + AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.]) + fi + XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB" + XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" + AC_SUBST([XNEST_LIBS]) + AC_SUBST([XNEST_SYS_LIBS]) +fi + + +dnl Xorg DDX + +AC_MSG_CHECKING([whether to build Xorg DDX]) +if test "x$XORG" = xauto; then + XORG="yes" + case $host_os in + cygwin*) XORG="no" ;; + darwin*) XORG="no" ;; + esac +fi +AC_MSG_RESULT([$XORG]) + +xorg_bus_linuxpci=no +xorg_bus_bsdpci=no +xorg_bus_sparc=no + +if test "x$XORG" = xyes; then + XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common' + XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os' + XORG_INCS="$XORG_DDXINCS $XORG_OSINCS" + XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H" + XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB" + + dnl ================================================================== + dnl symbol visibility + symbol_visibility= + have_visibility=disabled + if test x$SYMBOL_VISIBILITY != xno; then + AC_MSG_CHECKING(for symbol visibility support) + if test x$GCC = xyes; then + VISIBILITY_CFLAGS="-fvisibility=hidden" + else + AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) + if test x$SUNCC = xyes; then + VISIBILITY_CFLAGS="-xldscope=hidden" + else + have_visibility=no + fi + fi + if test x$have_visibility != xno; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $VISIBILITY_CFLAGS" + AC_TRY_COMPILE( + [#include + extern _X_HIDDEN int hidden_int; + extern _X_EXPORT int public_int; + extern _X_HIDDEN int hidden_int_func(void); + extern _X_EXPORT int public_int_func(void);], + [], + have_visibility=yes, + have_visibility=no) + CFLAGS=$save_CFLAGS + fi + AC_MSG_RESULT([$have_visibility]) + if test x$have_visibility != xno; then + symbol_visibility=$VISIBILITY_CFLAGS + XORG_CFLAGS="$XORG_CFLAGS $VISIBILITY_CFLAGS" + XSERVER_CFLAGS="$XSERVER_CFLAGS $VISIBILITY_CFLAGS" + fi + fi + dnl added to xorg-server.pc + AC_SUBST([symbol_visibility]) + dnl =================================================================== + + PKG_CHECK_MODULES([PCIACCESS], $LIBPCIACCESS) + SAVE_LIBS=$LIBS + SAVE_CFLAGS=$CFLAGS + CFLAGS=$PCIACCESS_CFLAGS + LIBS=$PCIACCESS_LIBS + AC_CHECK_FUNCS([pci_system_init_dev_mem]) + AC_CHECK_FUNCS([pci_device_enable]) + AC_CHECK_FUNCS([pci_device_is_boot_vga]) + AC_CHECK_FUNCS([pci_device_vgaarb_init]) + LIBS=$SAVE_LIBS + CFLAGS=$SAVE_CFLAGS + XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS" + XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS" + + case $host_os in + linux*) + if test "x$LNXAPM" = xyes; then + XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" + fi + XORG_OS="linux" + XORG_OS_SUBDIR="linux" + xorg_bus_linuxpci="yes" + linux_acpi="no" + case $host_cpu in + ia64*) + linux_ia64=yes + linux_acpi="yes" + ;; + alpha*) + linux_alpha=yes + ;; + i*86|amd64*|x86_64*) + linux_acpi="yes" + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + XORG_OS="freebsd" + XORG_OS_SUBDIR="bsd" + xorg_bus_bsdpci="yes" + ;; + netbsd*) + XORG_OS="netbsd" + XORG_OS_SUBDIR="bsd" + xorg_bus_bsdpci="yes" + ;; + openbsd*) + if test "x$ac_cv_BSD_APM" = xyes \ + -o "x$ac_cv_BSD_KQUEUE_APM" = xyes; then + XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" + fi + XORG_OS="openbsd" + XORG_OS_SUBDIR="bsd" + xorg_bus_bsdpci="yes" + ;; + solaris*) + XORG_OS="solaris" + XORG_OS_SUBDIR="solaris" + XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" + # Use the same stubs as BSD for old functions, since we now + # use libpciaccess for PCI + xorg_bus_bsdpci="yes" + AC_CHECK_HEADERS([sys/kd.h]) + AC_CHECK_HEADERS([sys/vt.h], [solaris_vt=yes], [solaris_vt=no]) + # Check for minimum supported release + AC_MSG_CHECKING([Solaris version]) + OS_MINOR=`echo ${host_os}|$SED -e 's/^.*solaris2\.//' -e s'/\..*$//'` + if test "${OS_MINOR}" -ge 7 ; then + AC_MSG_RESULT(Solaris ${OS_MINOR}) + else + AC_MSG_RESULT(Solaris `echo ${host_os}|$SED -e 's/^.*solaris//`) + fi + if test "${OS_MINOR}" -lt 8 ; then + AC_MSG_ERROR([This release no longer supports Solaris versions older than Solaris 8.]) + fi + AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) + if test "x$SUNCC" = "xyes"; then + solaris_asm_inline="yes" + fi + AC_CHECK_DECL([_LP64], [SOLARIS_64="yes"], [SOLARIS_64="no"]) + + case $host_cpu in + sparc*) + SOLARIS_INOUT_ARCH="sparcv8plus" + ;; + i*86) + if test x$SOLARIS_64 = xyes ; then + SOLARIS_INOUT_ARCH="amd64" + else + SOLARIS_INOUT_ARCH="ia32" + fi + ;; + *) + AC_MSG_ERROR([Unsupported Solaris platform. Only SPARC & x86 \ + are supported on Solaris in this release. If you are \ + interested in porting Xorg to your platform, please email \ + xorg@lists.freedesktop.org.]) ;; + esac + AC_SUBST([SOLARIS_INOUT_ARCH]) + if test x$solaris_asm_inline = xyes ; then + SOLARIS_ASM_CFLAGS='$(top_srcdir)/hw/xfree86/os-support/solaris/solaris-$(SOLARIS_INOUT_ARCH).il' + XORG_CFLAGS="${XORG_CFLAGS} "'$(SOLARIS_ASM_CFLAGS)' + fi + AC_SUBST([SOLARIS_ASM_CFLAGS]) + if test "x$SUPPORT_PC98" = xauto; then + SUPPORT_PC98="no" + fi + ;; + gnu*) + XORG_OS="gnu" + XORG_OS_SUBDIR="hurd" + # Use the same stubs as BSD for old functions, since we now + # use libpciaccess for PCI + xorg_bus_bsdpci="yes" + ;; + *) + XORG_OS="unknown" + XORG_OS_SUBDIR="unknown" + AC_MSG_ERROR([m4_text_wrap(m4_join([ ], + [Your OS is unknown. Xorg currently only supports Linux,], + [Free/Open/Net/DragonFlyBSD, Solaris/OpenSolaris, & GNU Hurd.], + [If you are interested in porting Xorg to your platform,], + [please email xorg@lists.freedesktop.org.]))]) + ;; + esac + + case $host_cpu in + sparc*) + xorg_bus_sparc="yes" + ;; + i*86) + if test "x$SUPPORT_PC98" = xauto; then + SUPPORT_PC98="yes" + fi + ;; + esac + + if test "x$SUPPORT_PC98" = xauto; then + SUPPORT_PC98="no" + fi + if test "x$SUPPORT_PC98" = xyes; then + AC_DEFINE(SUPPORT_PC98, 1, [Support PC98]) + fi + if test "x$XORG_OS_PCI" = x ; then + XORG_OS_PCI=$XORG_OS + fi + if test "x$DGA" = xauto; then + PKG_CHECK_MODULES(DGA, $DGAPROTO, [DGA=yes], [DGA=no]) + fi + if test "x$DGA" = xyes; then + XORG_MODULES="$XORG_MODULES $DGAPROTO" + PKG_CHECK_MODULES(DGA, $DGAPROTO) + AC_DEFINE(DGA, 1, [Support DGA extension]) + AC_DEFINE(XFreeXDGA, 1, [Build XDGA support]) + fi + + if test "x$XF86VIDMODE" = xauto; then + PKG_CHECK_MODULES(XF86VIDMODE, $VIDMODEPROTO, [XF86VIDMODE=yes], [XF86VIDMODE=no]) + fi + if test "x$XF86VIDMODE" = xyes; then + XORG_MODULES="$XORG_MODULES $VIDMODEPROTO" + PKG_CHECK_MODULES(XF86VIDMODE, $VIDMODEPROTO) + AC_DEFINE(XF86VIDMODE, 1, [Support XFree86 Video Mode extension]) + fi + + if test -n "$XORG_MODULES"; then + PKG_CHECK_MODULES(XORG_MODULES, [$XORG_MODULES]) + XORG_CFLAGS="$XORG_CFLAGS $XORG_MODULES_CFLAGS" + XORG_SYS_LIBS="$XORG_SYS_LIBS $XORG_MODULES_LIBS" + fi + + AC_SUBST([XORG_LIBS]) + AC_SUBST([XORG_SYS_LIBS]) + AC_SUBST([XORG_INCS]) + AC_SUBST([XORG_OS]) + AC_SUBST([XORG_OS_SUBDIR]) + + AC_PATH_PROG(PERL, perl, no) + dnl unlikely as this may be ... + if test "x$PERL" = xno; then + AC_MSG_ERROR([Perl is required to build the XFree86/Xorg DDX.]) + fi + AC_SUBST(PERL) + + AC_SUBST([XORG_CFLAGS]) + + dnl these only go in xorg-config.h + XF86CONFIGFILE="xorg.conf" + XF86CONFIGDIR="xorg.conf.d" + AC_SUBST(XF86CONFIGDIR) + CONFIGFILE="$sysconfdir/$XF86CONFIGFILE" + LOGPREFIX="$logdir/Xorg." + AC_DEFINE(XORG_SERVER, 1, [Building Xorg server]) + AC_DEFINE(XORGSERVER, 1, [Building Xorg server]) + AC_DEFINE(XFree86Server, 1, [Building XFree86 server]) + AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server]) + AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) + AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs]) + AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions]) + AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server]) + AC_DEFINE_DIR(__XCONFIGFILE__, XF86CONFIGFILE, [Name of configuration file]) + AC_DEFINE_DIR(XF86CONFIGFILE, XF86CONFIGFILE, [Name of configuration file]) + AC_DEFINE_DIR(__XCONFIGDIR__, XF86CONFIGDIR, [Name of configuration directory]) + AC_DEFINE_DIR(DEFAULT_MODULE_PATH, moduledir, [Default module search path]) + AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path]) + AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default log location]) + AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) + AC_DEFINE(XSERVER_LIBPCIACCESS, 1, [Use libpciaccess for all pci manipulation]) + if test "x$VGAHW" = xyes; then + AC_DEFINE(WITH_VGAHW, 1, [Building vgahw module]) + fi + + driverdir="$moduledir/drivers" + AC_SUBST([moduledir]) + AC_SUBST([driverdir]) + sdkdir="$includedir/xorg" + extdir="$includedir/X11/extensions" + sysconfigdir="$datadir/X11/$XF86CONFIGDIR" + AC_SUBST([sdkdir]) + AC_SUBST([extdir]) + AC_SUBST([sysconfigdir]) + AC_SUBST([logdir]) + + # stuff the ABI versions into the pc file too + extract_abi() { + grep ^.define.*${1}_VERSION ${srcdir}/hw/xfree86/common/xf86Module.h | tr '(),' ' .' | awk '{ print $4$5 }' + } + abi_ansic=`extract_abi ANSIC` + abi_videodrv=`extract_abi VIDEODRV` + abi_xinput=`extract_abi XINPUT` + abi_extension=`extract_abi EXTENSION` + AC_SUBST([abi_ansic]) + AC_SUBST([abi_videodrv]) + AC_SUBST([abi_xinput]) + AC_SUBST([abi_extension]) +fi +AM_CONDITIONAL([XORG], [test "x$XORG" = xyes]) +AM_CONDITIONAL([XORG_BUS_LINUXPCI], [test "x$xorg_bus_linuxpci" = xyes]) +AM_CONDITIONAL([XORG_BUS_BSDPCI], [test "x$xorg_bus_bsdpci" = xyes]) +AM_CONDITIONAL([XORG_BUS_SPARC], [test "x$xorg_bus_sparc" = xyes]) +AM_CONDITIONAL([LINUX_IA64], [test "x$linux_ia64" = xyes]) +AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes]) +AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = xyes]) +AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test "x$solaris_asm_inline" = xyes]) +AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes]) +AM_CONDITIONAL([DGA], [test "x$DGA" = xyes]) +AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) + +dnl XWin DDX + +AC_MSG_CHECKING([whether to build XWin DDX]) +if test "x$XWIN" = xauto; then + case $host_os in + cygwin*) XWIN="yes" ;; + mingw*) XWIN="yes" ;; + *) XWIN="no" ;; + esac +fi +AC_MSG_RESULT([$XWIN]) + +if test "x$XWIN" = xyes; then + AC_DEFINE_DIR(SYSCONFDIR, sysconfdir, [Location of system.XWinrc]) + AC_DEFINE_DIR(DEFAULT_LOGDIR, logdir, [Default log location]) + AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) + AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) + AC_CHECK_TOOL(WINDRES, windres) + + PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau]) + + if test "x$WINDOWSWM" = xauto; then + PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no]) + fi + if test "x$WINDOWSWM" = xyes ; then + PKG_CHECK_MODULES(WINDOWSWM, $WINDOWSWMPROTO) + XWINMODULES_CFLAGS="$XWINMODULES_CFLAGS $WINDOWSWM_CFLAGS" + AC_DEFINE(ROOTLESS,1,[Build Rootless code]) + fi + + case $host_os in + cygwin*) + XWIN_SERVER_NAME=XWin + AC_DEFINE(HAS_DEVWINDOWS,1,[Cygwin has /dev/windows for signaling new win32 messages]) + ;; + mingw*) + XWIN_SERVER_NAME=Xming + AC_DEFINE(RELOCATE_PROJECTROOT,1,[Make PROJECT_ROOT relative to the xserver location]) + AC_DEFINE(HAS_WINSOCK,1,[Use Windows sockets]) + XWIN_SYS_LIBS=-lwinsock2 + ;; + esac + XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB" + XWIN_SYS_LIBS="$XWIN_SYS_LIBS $XWINMODULES_LIBS" + AC_SUBST(XWIN_LIBS) + AC_SUBST(XWIN_SERVER_NAME) + AC_SUBST(XWIN_SYS_LIBS) + + if test "x$DEBUGGING" = xyes; then + AC_DEFINE(CYGDEBUG, 1, [Simple debug messages]) + AC_DEFINE(CYGWINDOWING_DEBUG, 1, [Debug messages for window handling]) + AC_DEFINE(CYGMULTIWINDOW_DEBUG, 1, [Debug window manager]) + fi + + AC_DEFINE(DDXOSVERRORF, 1, [Use OsVendorVErrorF]) + AC_DEFINE(DDXBEFORERESET, 1, [Use ddxBeforeReset ]) +fi +AM_CONDITIONAL(XWIN, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_MULTIWINDOW, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_MULTIWINDOWEXTWM, [test "x$XWIN" = xyes && test "x$WINDOWSWM" = xyes]) +AM_CONDITIONAL(XWIN_CLIPBOARD, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_GLX_WINDOWS, [test "x$XWIN" = xyes && false]) +AM_CONDITIONAL(XWIN_NATIVEGDI, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_PRIMARYFB, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_RANDR, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_XV, [test "x$XWIN" = xyes && test "x$XV" = xyes]) + +dnl Darwin / OS X DDX +if test "x$XQUARTZ" = xyes; then + AC_DEFINE(XQUARTZ,1,[Have Quartz]) + AC_DEFINE(ROOTLESS,1,[Build Rootless code]) + + DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_LIB $MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB" + AC_SUBST([DARWIN_LIBS]) + + AC_CHECK_LIB([Xplugin],[xp_init],[:]) + + CFLAGS="${CFLAGS} -DROOTLESS_WORKAROUND -DROOTLESS_SAFEALPHA -DNO_ALLOCA" + + PKG_CHECK_MODULES(XPBPROXY, $APPLEWMPROTO $LIBAPPLEWM xfixes x11) + + if test "x$XQUARTZ_SPARKLE" = xyes ; then + AC_DEFINE(XQUARTZ_SPARKLE,1,[Support application updating through sparkle.]) + fi + + if test "x$STANDALONE_XPBPROXY" = xyes ; then + AC_DEFINE(STANDALONE_XPBPROXY,1,[Build a standalone xpbproxy]) + fi +fi + +# Support for objc in autotools is minimal and not documented. +OBJC='$(CC)' +OBJCLD='$(CCLD)' +OBJCLINK='$(LINK)' +OBJCFLAGS='$(CFLAGS)' +AC_SUBST([OBJC]) +AC_SUBST([OBJCCLD]) +AC_SUBST([OBJCLINK]) +AC_SUBST([OBJCFLAGS]) +# internal, undocumented automake func follows :( +_AM_DEPENDENCIES([OBJC]) +AM_CONDITIONAL(XQUARTZ, [test "x$XQUARTZ" = xyes]) +AM_CONDITIONAL(XQUARTZ_SPARKLE, [test "x$XQUARTZ_SPARKLE" != "xno"]) +AM_CONDITIONAL(STANDALONE_XPBPROXY, [test "x$STANDALONE_XPBPROXY" = xyes]) + +dnl DMX DDX +PKG_CHECK_MODULES( + [DMXMODULES], + [xmuu $LIBXEXT x11 xrender xfixes $LIBXI $DMXPROTO xau $XDMCP_MODULES], + [PKG_CHECK_MODULES( + [XDMXCONFIG_DEP], + [xaw7 xmu xt xpm x11], + [have_dmx=yes], + [have_dmx=no])], + [have_dmx=no]) +AC_MSG_CHECKING([whether to build Xdmx DDX]) +if test "x$DMX" = xauto; then + DMX="$have_dmx" + case $host_os in + cygwin*) DMX="no" ;; + darwin*) DMX="no" ;; + esac +fi +AC_MSG_RESULT([$DMX]) +AM_CONDITIONAL(DMX, [test "x$DMX" = xyes]) + +if test "x$DMX" = xyes; then + if test "x$have_dmx" = xno; then + AC_MSG_ERROR([Xdmx build explicitly requested, but required + modules not found.]) + fi + DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC" + XDMX_CFLAGS="$DMXMODULES_CFLAGS" + XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB" + XDMX_SYS_LIBS="$DMXMODULES_LIBS" + AC_SUBST([XDMX_CFLAGS]) + AC_SUBST([XDMX_LIBS]) + AC_SUBST([XDMX_SYS_LIBS]) + +dnl USB sources in DMX require + AC_CHECK_HEADER([linux/input.h], DMX_BUILD_USB="yes", + DMX_BUILD_USB="no") +dnl Linux sources in DMX require + AC_CHECK_HEADER([linux/keyboard.h], DMX_BUILD_LNX="yes", + DMX_BUILD_LNX="no") + AC_SUBST(XDMXCONFIG_DEP_CFLAGS) + AC_SUBST(XDMXCONFIG_DEP_LIBS) + PKG_CHECK_MODULES([DMXEXAMPLES_DEP], [$LIBDMX $LIBXEXT x11]) + AC_SUBST(DMXEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([DMXXMUEXAMPLES_DEP], [$LIBDMX xmu $LIBXEXT x11]) + AC_SUBST(DMXXMUEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([DMXXIEXAMPLES_DEP], [$LIBDMX $LIBXI $LIBXEXT x11]) + AC_SUBST(DMXXIEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([XTSTEXAMPLES_DEP], [$LIBXTST $LIBXEXT x11]) + AC_SUBST(XTSTEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([XRESEXAMPLES_DEP], [xres $LIBXEXT x11]) + AC_SUBST(XRESEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([X11EXAMPLES_DEP], [$LIBXEXT x11]) + AC_SUBST(X11EXAMPLES_DEP_LIBS) + +fi +AM_CONDITIONAL([DMX_BUILD_LNX], [test "x$DMX_BUILD_LNX" = xyes]) +AM_CONDITIONAL([DMX_BUILD_USB], [test "x$DMX_BUILD_USB" = xyes]) + +dnl kdrive DDX + +XEPHYR_LIBS= +XEPHYR_INCS= + +AM_CONDITIONAL(KDRIVE, [test x$KDRIVE = xyes]) + +if test "$KDRIVE" = yes; then + AC_DEFINE(KDRIVESERVER,1,[Build Kdrive X server]) + AC_DEFINE(KDRIVEDDXACTIONS,,[Build kdrive ddx]) + + AC_CHECK_HEADERS([linux/fb.h]) + if test "$ac_cv_header_linux_fb_h" = yes && test "x$XFBDEV" = xauto; then + XFBDEV=yes + fi + + if test "x$XFBDEV" = xyes; then + KDRIVEFBDEVLIB=yes + AC_DEFINE(KDRIVEFBDEV, 1, [Build fbdev-based kdrive server]) + fi + + + PKG_CHECK_MODULES([TSLIB], [tslib-0.0], [HAVE_TSLIB="yes"], [HAVE_TSLIB="no"]) + if test "x$HAVE_TSLIB" = xno; then + AC_CHECK_LIB(ts, ts_open, [ + HAVE_TSLIB="yes" + TSLIB_LIBS="-lts" + ]) + fi + + if test "xTSLIB" = xauto; then + TSLIB="$HAVE_TSLIB" + fi + + if test "x$TSLIB" = xyes; then + if ! test "x$HAVE_TSLIB" = xyes; then + AC_MSG_ERROR([tslib must be installed to build the tslib driver. See http://tslib.berlios.de/]) + else + AC_DEFINE(TSLIB, 1, [Have tslib support]) + fi + fi + + if test "x$KDRIVE_KBD" = xyes; then + AC_DEFINE(KDRIVE_KBD, 1, [Enable KDrive kbd driver]) + fi + if test "x$KDRIVE_EVDEV" = xyes; then + AC_DEFINE(KDRIVE_EVDEV, 1, [Enable KDrive evdev driver]) + fi + if test "x$KDRIVE_MOUSE" = xyes; then + AC_DEFINE(KDRIVE_MOUSE, 1, [Enable KDrive mouse driver]) + fi + + XEPHYR_REQUIRED_LIBS="x11 $LIBXEXT xau xdmcp" + if test "x$XV" = xyes; then + XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS xv" + fi + if test "x$DRI" = xyes && test "x$GLX" = xyes; then + XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS $LIBGL libdrm" + fi + + PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [xephyr="yes"], [xephyr="no"]) + if test "x$XEPHYR" = xauto; then + XEPHYR=$xephyr + fi + if test "x$XEPHYR" = xyes && test "x$xephyr" = xno; then + AC_MSG_ERROR([Xephyr dependencies missing]) + fi + + # Xephyr needs nanosleep() which is in librt on Solaris + AC_CHECK_FUNC([nanosleep], [], + AC_CHECK_LIB([rt], [nanosleep], XEPHYR_LIBS="$XEPHYR_LIBS -lrt")) + + # damage shadow extension glx (NOTYET) fb mi + KDRIVE_INC='-I$(top_srcdir)/hw/kdrive/src' + KDRIVE_PURE_INCS="$KDRIVE_INC $MIEXT_SYNC_INC $MIEXT_DAMAGE_INC $MIEXT_SHADOW_INC $XEXT_INC $FB_INC $MI_INC" + KDRIVE_OS_INC='-I$(top_srcdir)/hw/kdrive/linux' + KDRIVE_INCS="$KDRIVE_PURE_INCS $KDRIVE_OS_INC" + + KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS" + + KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB" + KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la' + case $host_os in + *linux*) + KDRIVE_OS_LIB='$(top_builddir)/hw/kdrive/linux/liblinux.la' + KDRIVELINUX=yes + if test "x$KDRIVE_EVDEV" = xauto; then + KDRIVE_EVDEV=yes + fi + if test "x$KDRIVE_KBD" = xauto; then + KDRIVE_KBD=yes + fi + if test "x$KDRIVE_MOUSE" = xauto; then + KDRIVE_MOUSE=yes + fi + ;; + *) + if test "x$KDRIVE_EVDEV" = xauto; then + KDRIVE_EVDEV=no + fi + if test "x$KDRIVE_KBD" = xauto; then + KDRIVE_KBD=no + fi + if test "x$KDRIVE_MOUSE" = xauto; then + KDRIVE_MOUSE=no + fi + ;; + esac + KDRIVE_STUB_LIB='$(top_builddir)/hw/kdrive/src/libkdrivestubs.la' + KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB" + KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS" + KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB" + KDRIVE_LIBS="$KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS $DLOPEN_LIBS $TSLIB_LIBS" + + AC_SUBST([XEPHYR_LIBS]) + AC_SUBST([XEPHYR_INCS]) +fi +AC_SUBST([KDRIVE_INCS]) +AC_SUBST([KDRIVE_PURE_INCS]) +AC_SUBST([KDRIVE_CFLAGS]) +AC_SUBST([KDRIVE_PURE_LIBS]) +AC_SUBST([KDRIVE_LOCAL_LIBS]) +AC_SUBST([KDRIVE_LIBS]) +AM_CONDITIONAL(KDRIVELINUX, [test "x$KDRIVELINUX" = xyes]) +AM_CONDITIONAL(KDRIVE_EVDEV, [test "x$KDRIVE_EVDEV" = xyes]) +AM_CONDITIONAL(KDRIVE_KBD, [test "x$KDRIVE_KBD" = xyes]) +AM_CONDITIONAL(KDRIVE_MOUSE, [test "x$KDRIVE_MOUSE" = xyes]) +AM_CONDITIONAL(TSLIB, [test "x$HAVE_TSLIB" = xyes]) +AM_CONDITIONAL(KDRIVEFBDEV, [test "x$XFBDEV" = xyes]) +AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes]) +AM_CONDITIONAL(BUILD_KDRIVEFBDEVLIB, [test "x$KDRIVE" = xyes && test "x$KDRIVEFBDEVLIB" = xyes]) +AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes]) + +dnl and the rest of these are generic, so they're in config.h +dnl +dnl though, thanks to the passing of some significant amount of time, the +dnl above is probably a complete fallacy, and you should not rely on it. +dnl but this is still actually better than imake, honest. -daniels + +AC_TRY_COMPILE([ +#include +#ifndef __GLIBC__ +#error not glibc +#endif +], [], [AC_DEFINE(_GNU_SOURCE, 1, + [ Enable GNU and other extensions to the C environment for glibc])]) + +AC_DEFINE_DIR(PROJECTROOT, prefix, [Overall prefix]) + +AC_SUBST([RELEASE_DATE]) +BUILD_DATE="`date +'%Y%m%d'`" +AC_SUBST([BUILD_DATE]) +BUILD_TIME="`date +'1%H%M%S'`" +AC_SUBST([BUILD_TIME]) + +DIX_CFLAGS="-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS" + +AC_SUBST([DIX_CFLAGS]) + +AC_SUBST([libdir]) +AC_SUBST([exec_prefix]) +AC_SUBST([prefix]) + +AC_CONFIG_COMMANDS([sdksyms], [touch hw/xfree86/loader/sdksyms.dep]) + +AC_OUTPUT([ +Makefile +glx/Makefile +include/Makefile +composite/Makefile +damageext/Makefile +dbe/Makefile +dix/Makefile +doc/Makefile +doc/man/Makefile +doc/xml/Makefile +doc/xml/dtrace/Makefile +doc/xml/xserver.ent +fb/Makefile +record/Makefile +config/Makefile +mi/Makefile +miext/Makefile +miext/sync/Makefile +miext/damage/Makefile +miext/shadow/Makefile +miext/cw/Makefile +miext/rootless/Makefile +os/Makefile +randr/Makefile +render/Makefile +xkb/Makefile +Xext/Makefile +Xi/Makefile +xfixes/Makefile +exa/Makefile +hw/Makefile +hw/xfree86/Makefile +hw/xfree86/common/Makefile +hw/xfree86/common/xf86Build.h +hw/xfree86/ddc/Makefile +hw/xfree86/dixmods/Makefile +hw/xfree86/dixmods/extmod/Makefile +hw/xfree86/doc/Makefile +hw/xfree86/doc/devel/Makefile +hw/xfree86/doc/sgml/Makefile +hw/xfree86/dri/Makefile +hw/xfree86/dri2/Makefile +hw/xfree86/exa/Makefile +hw/xfree86/exa/man/Makefile +hw/xfree86/fbdevhw/Makefile +hw/xfree86/fbdevhw/man/Makefile +hw/xfree86/i2c/Makefile +hw/xfree86/int10/Makefile +hw/xfree86/loader/Makefile +hw/xfree86/man/Makefile +hw/xfree86/modes/Makefile +hw/xfree86/os-support/Makefile +hw/xfree86/os-support/bsd/Makefile +hw/xfree86/os-support/bus/Makefile +hw/xfree86/os-support/hurd/Makefile +hw/xfree86/os-support/misc/Makefile +hw/xfree86/os-support/linux/Makefile +hw/xfree86/os-support/solaris/Makefile +hw/xfree86/parser/Makefile +hw/xfree86/ramdac/Makefile +hw/xfree86/shadowfb/Makefile +hw/xfree86/vbe/Makefile +hw/xfree86/vgahw/Makefile +hw/xfree86/x86emu/Makefile +hw/xfree86/xaa/Makefile +hw/xfree86/utils/Makefile +hw/xfree86/utils/man/Makefile +hw/xfree86/utils/cvt/Makefile +hw/xfree86/utils/gtf/Makefile +hw/dmx/config/Makefile +hw/dmx/config/man/Makefile +hw/dmx/doc/Makefile +hw/dmx/doc/doxygen.conf +hw/dmx/examples/Makefile +hw/dmx/input/Makefile +hw/dmx/glxProxy/Makefile +hw/dmx/Makefile +hw/dmx/man/Makefile +hw/vfb/Makefile +hw/vfb/man/Makefile +hw/xnest/Makefile +hw/xnest/man/Makefile +hw/xwin/Makefile +hw/xwin/glx/Makefile +hw/xwin/man/Makefile +hw/xquartz/Makefile +hw/xquartz/GL/Makefile +hw/xquartz/bundle/Makefile +hw/xquartz/man/Makefile +hw/xquartz/mach-startup/Makefile +hw/xquartz/pbproxy/Makefile +hw/xquartz/xpr/Makefile +hw/kdrive/Makefile +hw/kdrive/ephyr/Makefile +hw/kdrive/ephyr/man/Makefile +hw/kdrive/fake/Makefile +hw/kdrive/fbdev/Makefile +hw/kdrive/linux/Makefile +hw/kdrive/src/Makefile +test/Makefile +test/xi2/Makefile +xorg-server.pc +]) diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c index e57c27b00..7f500d63d 100644 --- a/xorg-server/dix/devices.c +++ b/xorg-server/dix/devices.c @@ -1,2628 +1,2630 @@ -/************************************************************ - -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. - -********************************************************/ - - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include "misc.h" -#include "resource.h" -#include -#include -#include "windowstr.h" -#include "inputstr.h" -#include "scrnintstr.h" -#include "cursorstr.h" -#include "dixstruct.h" -#include "ptrveloc.h" -#include "site.h" -#include "xkbsrv.h" -#include "privates.h" -#include "xace.h" -#include "mi.h" - -#include "dispatch.h" -#include "swaprep.h" -#include "dixevents.h" -#include "mipointer.h" -#include "eventstr.h" - -#include -#include -#include -#include -#include -#include "exglobals.h" -#include "exevents.h" -#include "xiquerydevice.h" /* for SizeDeviceClasses */ -#include "xiproperty.h" -#include "enterleave.h" /* for EnterWindow() */ -#include "xserver-properties.h" -#include "xichangehierarchy.h" /* For XISendDeviceHierarchyEvent */ - -/** @file - * This file handles input device-related stuff. - */ - -static void RecalculateMasterButtons(DeviceIntPtr slave); - -static void -DeviceSetTransform(DeviceIntPtr dev, float *transform) -{ - struct pixman_f_transform scale; - double sx, sy; - int x, y; - - /** - * calculate combined transformation matrix: - * - * M = InvScale * Transform * Scale - * - * So we can later transform points using M * p - * - * Where: - * Scale scales coordinates into 0..1 range - * Transform is the user supplied (affine) transform - * InvScale scales coordinates back up into their native range - */ - sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value; - sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value; - - /* invscale */ - pixman_f_transform_init_scale(&scale, sx, sy); - scale.m[0][2] = dev->valuator->axes[0].min_value; - scale.m[1][2] = dev->valuator->axes[1].min_value; - - /* transform */ - for (y=0; y<3; y++) - for (x=0; x<3; x++) - dev->transform.m[y][x] = *transform++; - - pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform); - - /* scale */ - pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy); - scale.m[0][2] = -dev->valuator->axes[0].min_value / sx; - scale.m[1][2] = -dev->valuator->axes[1].min_value / sy; - - pixman_f_transform_multiply(&dev->transform, &dev->transform, &scale); -} - -/** - * DIX property handler. - */ -static int -DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, - BOOL checkonly) -{ - if (property == XIGetKnownProperty(XI_PROP_ENABLED)) - { - if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1) - return BadValue; - - /* Don't allow disabling of VCP/VCK */ - if ((dev == inputInfo.pointer || dev == inputInfo.keyboard) && - !(*(CARD8*)prop->data)) - return BadAccess; - - if (!checkonly) - { - if ((*((CARD8*)prop->data)) && !dev->enabled) - EnableDevice(dev, TRUE); - else if (!(*((CARD8*)prop->data)) && dev->enabled) - DisableDevice(dev, TRUE); - } - } else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM)) - { - float *f = (float*)prop->data; - int i; - - if (prop->format != 32 || prop->size != 9 || - prop->type != XIGetKnownProperty(XATOM_FLOAT)) - return BadValue; - - for (i=0; i<9; i++) - if (!isfinite(f[i])) - return BadValue; - - if (!checkonly) - DeviceSetTransform(dev, f); - } - - return Success; -} - -/* Pair the keyboard to the pointer device. Keyboard events will follow the - * pointer sprite. Only applicable for master devices. - * If the client is set, the request to pair comes from some client. In this - * case, we need to check for access. If the client is NULL, it's from an - * internal automatic pairing, we must always permit this. - */ -static int -PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd) -{ - if (!ptr) - return BadDevice; - - /* Don't allow pairing for slave devices */ - if (!IsMaster(ptr) || !IsMaster(kbd)) - return BadDevice; - - if (ptr->spriteInfo->paired) - return BadDevice; - - if (kbd->spriteInfo->spriteOwner) - { - free(kbd->spriteInfo->sprite); - kbd->spriteInfo->sprite = NULL; - kbd->spriteInfo->spriteOwner = FALSE; - } - - kbd->spriteInfo->sprite = ptr->spriteInfo->sprite; - kbd->spriteInfo->paired = ptr; - ptr->spriteInfo->paired = kbd; - return Success; -} - - -/** - * Find and return the next unpaired MD pointer device. - */ -static DeviceIntPtr -NextFreePointerDevice(void) -{ - DeviceIntPtr dev; - for (dev = inputInfo.devices; dev; dev = dev->next) - if (IsMaster(dev) && - dev->spriteInfo->spriteOwner && - !dev->spriteInfo->paired) - return dev; - return NULL; -} - -/** - * Create a new input device and init it to sane values. The device is added - * to the server's off_devices list. - * - * @param deviceProc Callback for device control function (switch dev on/off). - * @return The newly created device. - */ -DeviceIntPtr -AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) -{ - DeviceIntPtr dev, *prev; /* not a typo */ - DeviceIntPtr devtmp; - int devid; - char devind[MAXDEVICES]; - BOOL enabled; - float transform[9]; - - /* Find next available id, 0 and 1 are reserved */ - memset(devind, 0, sizeof(char)*MAXDEVICES); - for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next) - devind[devtmp->id]++; - for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next) - devind[devtmp->id]++; - for (devid = 2; devid < MAXDEVICES && devind[devid]; devid++) - ; - - if (devid >= MAXDEVICES) - return (DeviceIntPtr)NULL; - dev = _dixAllocateObjectWithPrivates(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), - sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), - offsetof(DeviceIntRec, devPrivates), PRIVATE_DEVICE); - if (!dev) - return (DeviceIntPtr)NULL; - dev->id = devid; - dev->public.processInputProc = ProcessOtherEvent; - dev->public.realInputProc = ProcessOtherEvent; - dev->public.enqueueInputProc = EnqueueEvent; - dev->deviceProc = deviceProc; - dev->startup = autoStart; - - /* device grab defaults */ - dev->deviceGrab.grabTime = currentTime; - dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; - dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; - - XkbSetExtension(dev, ProcessKeyboardEvent); - - dev->coreEvents = TRUE; - - /* sprite defaults */ - dev->spriteInfo = (SpriteInfoPtr)&dev[1]; - - /* security creation/labeling check - */ - if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) { - free(dev); - return NULL; - } - - inputInfo.numDevices++; - - for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next) - ; - *prev = dev; - dev->next = NULL; - - enabled = FALSE; - XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), - XA_INTEGER, 8, PropModeReplace, 1, &enabled, - FALSE); - XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE); - - /* unity matrix */ - memset(transform, 0, sizeof(transform)); - transform[0] = transform[4] = transform[8] = 1.0f; - - XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), - XIGetKnownProperty(XATOM_FLOAT), 32, - PropModeReplace, 9, transform, FALSE); - XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), - FALSE); - - XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL); - - return dev; -} - -void -SendDevicePresenceEvent(int deviceid, int type) -{ - DeviceIntRec dummyDev; - devicePresenceNotify ev; - - memset(&dummyDev, 0, sizeof(DeviceIntRec)); - ev.type = DevicePresenceNotify; - ev.time = currentTime.milliseconds; - ev.devchange = type; - ev.deviceid = deviceid; - dummyDev.id = XIAllDevices; - SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, - (xEvent*)&ev, 1); -} - -/** - * Enable the device through the driver, add the device to the device list. - * Switch device ON through the driver and push it onto the global device - * list. Initialize the DIX sprite or pair the device. All clients are - * notified about the device being enabled. - * - * A master pointer device needs to be enabled before a master keyboard - * device. - * - * @param The device to be enabled. - * @param sendevent True if an XI2 event should be sent. - * @return TRUE on success or FALSE otherwise. - */ -Bool -EnableDevice(DeviceIntPtr dev, BOOL sendevent) -{ - DeviceIntPtr *prev; - int ret; - DeviceIntPtr other; - BOOL enabled; - int flags[MAXDEVICES] = {0}; - - for (prev = &inputInfo.off_devices; - *prev && (*prev != dev); - prev = &(*prev)->next) - ; - - if (!dev->spriteInfo->sprite) - { - if (IsMaster(dev)) - { - /* Sprites appear on first root window, so we can hardcode it */ - if (dev->spriteInfo->spriteOwner) - { - InitializeSprite(dev, screenInfo.screens[0]->root); - /* mode doesn't matter */ - EnterWindow(dev, screenInfo.screens[0]->root, NotifyAncestor); - } - else if ((other = NextFreePointerDevice()) == NULL) - { - ErrorF("[dix] cannot find pointer to pair with. " - "This is a bug.\n"); - return FALSE; - } else - PairDevices(NULL, other, dev); - } else - { - if (dev->coreEvents) - other = (IsPointerDevice(dev)) ? inputInfo.pointer : - inputInfo.keyboard; - else - other = NULL; /* auto-float non-core devices */ - AttachDevice(NULL, dev, other); - } - } - - if ((*prev != dev) || !dev->inited || - ((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) { - ErrorF("[dix] couldn't enable device %d\n", dev->id); - return FALSE; - } - dev->enabled = TRUE; - *prev = dev->next; - - for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next) - ; - *prev = dev; - dev->next = NULL; - - enabled = TRUE; - XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), - XA_INTEGER, 8, PropModeReplace, 1, &enabled, - TRUE); - - SendDevicePresenceEvent(dev->id, DeviceEnabled); - if (sendevent) - { - flags[dev->id] |= XIDeviceEnabled; - XISendDeviceHierarchyEvent(flags); - } - - RecalculateMasterButtons(dev); - - return TRUE; -} - -/** - * Switch a device off through the driver and push it onto the off_devices - * list. A device will not send events while disabled. All clients are - * notified about the device being disabled. - * - * Master keyboard devices have to be disabled before master pointer devices - * otherwise things turn bad. - * - * @param sendevent True if an XI2 event should be sent. - * @return TRUE on success or FALSE otherwise. - */ -Bool -DisableDevice(DeviceIntPtr dev, BOOL sendevent) -{ - DeviceIntPtr *prev, other; - BOOL enabled; - int flags[MAXDEVICES] = {0}; - - for (prev = &inputInfo.devices; - *prev && (*prev != dev); - prev = &(*prev)->next) - ; - if (*prev != dev) - return FALSE; - - /* float attached devices */ - if (IsMaster(dev)) - { - for (other = inputInfo.devices; other; other = other->next) - { - if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev) - { - AttachDevice(NULL, other, NULL); - flags[other->id] |= XISlaveDetached; - } - } - } - else - { - for (other = inputInfo.devices; other; other = other->next) - { - if (IsMaster(other) && other->lastSlave == dev) - other->lastSlave = NULL; - } - } - - if (IsMaster(dev) && dev->spriteInfo->sprite) - { - for (other = inputInfo.devices; other; other = other->next) - { - if (other->spriteInfo->paired == dev) - { - ErrorF("[dix] cannot disable device, still paired. " - "This is a bug. \n"); - return FALSE; - } - } - } - - (void)(*dev->deviceProc)(dev, DEVICE_OFF); - dev->enabled = FALSE; - - /* now that the device is disabled, we can reset the signal handler's - * last.slave */ - OsBlockSignals(); - for (other = inputInfo.devices; other; other = other->next) - { - if (other->last.slave == dev) - other->last.slave = NULL; - } - OsReleaseSignals(); - - LeaveWindow(dev); - SetFocusOut(dev); - - *prev = dev->next; - dev->next = inputInfo.off_devices; - inputInfo.off_devices = dev; - - enabled = FALSE; - XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), - XA_INTEGER, 8, PropModeReplace, 1, &enabled, - TRUE); - - SendDevicePresenceEvent(dev->id, DeviceDisabled); - if (sendevent) - { - flags[dev->id] = XIDeviceDisabled; - XISendDeviceHierarchyEvent(flags); - } - - RecalculateMasterButtons(dev); - - return TRUE; -} - -/** - * Initialise a new device through the driver and tell all clients about the - * new device. - * - * Must be called before EnableDevice. - * The device will NOT send events until it is enabled! - * - * @param sendevent True if an XI2 event should be sent. - * @return Success or an error code on failure. - */ -int -ActivateDevice(DeviceIntPtr dev, BOOL sendevent) -{ - int ret = Success; - ScreenPtr pScreen = screenInfo.screens[0]; - - if (!dev || !dev->deviceProc) - return BadImplementation; - - ret = (*dev->deviceProc) (dev, DEVICE_INIT); - dev->inited = (ret == Success); - if (!dev->inited) - return ret; - - /* Initialize memory for sprites. */ - if (IsMaster(dev) && dev->spriteInfo->spriteOwner) - if (!pScreen->DeviceCursorInitialize(dev, pScreen)) - ret = BadAlloc; - - SendDevicePresenceEvent(dev->id, DeviceAdded); - if (sendevent) - { - int flags[MAXDEVICES] = {0}; - flags[dev->id] = XISlaveAdded; - XISendDeviceHierarchyEvent(flags); - } - return ret; -} - -/** - * Ring the bell. - * The actual task of ringing the bell is the job of the DDX. - */ -static void -CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something) -{ - KeybdCtrl *ctrl = arg; - - DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration); -} - -static void -CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl) -{ - return; -} - -/** - * Device control function for the Virtual Core Keyboard. - */ -int -CoreKeyboardProc(DeviceIntPtr pDev, int what) -{ - - switch (what) { - case DEVICE_INIT: - if (!InitKeyboardDeviceStruct(pDev, NULL, CoreKeyboardBell, - CoreKeyboardCtl)) - { - ErrorF("Keyboard initialization failed. This could be a missing " - "or incorrect setup of xkeyboard-config.\n"); - return BadValue; - } - return Success; - - case DEVICE_ON: - case DEVICE_OFF: - return Success; - - case DEVICE_CLOSE: - return Success; - } - - return BadMatch; -} - -/** - * Device control function for the Virtual Core Pointer. - */ -int -CorePointerProc(DeviceIntPtr pDev, int what) -{ -#define NBUTTONS 10 -#define NAXES 2 - BYTE map[NBUTTONS + 1]; - int i = 0; - Atom btn_labels[NBUTTONS] = {0}; - Atom axes_labels[NAXES] = {0}; - - switch (what) { - case DEVICE_INIT: - for (i = 1; i <= NBUTTONS; i++) - map[i] = i; - - btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); - btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); - btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); - btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); - btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); - btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); - btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); - /* don't know about the rest */ - - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); - - if (!InitPointerDeviceStruct((DevicePtr)pDev, map, NBUTTONS, btn_labels, - (PtrCtrlProcPtr)NoopDDA, - GetMotionHistorySize(), NAXES, axes_labels)) - { - ErrorF("Could not initialize device '%s'. Out of memory.\n", - pDev->name); - return BadAlloc; /* IPDS only fails on allocs */ - } - pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; - pDev->last.valuators[0] = pDev->valuator->axisVal[0]; - pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; - pDev->last.valuators[1] = pDev->valuator->axisVal[1]; - break; - - case DEVICE_CLOSE: - break; - - default: - break; - } - - return Success; - -#undef NBUTTONS -#undef NAXES -} - -/** - * Initialise the two core devices, VCP and VCK (see events.c). - * Both devices are not tied to physical devices, but guarantee that there is - * always a keyboard and a pointer present and keep the protocol semantics. - * - * Note that the server MUST have two core devices at all times, even if there - * is no physical device connected. - */ -void -InitCoreDevices(void) -{ - if (AllocDevicePair(serverClient, "Virtual core", - &inputInfo.pointer, &inputInfo.keyboard, - CorePointerProc, CoreKeyboardProc, - TRUE) != Success) - FatalError("Failed to allocate core devices"); - - if (ActivateDevice(inputInfo.pointer, TRUE) != Success || - ActivateDevice(inputInfo.keyboard, TRUE) != Success) - FatalError("Failed to activate core devices."); - if (!EnableDevice(inputInfo.pointer, TRUE) || - !EnableDevice(inputInfo.keyboard, TRUE)) - FatalError("Failed to enable core devices."); - - InitXTestDevices(); -} - -/** - * Activate all switched-off devices and then enable all those devices. - * - * Will return an error if no core keyboard or core pointer is present. - * In theory this should never happen if you call InitCoreDevices() first. - * - * InitAndStartDevices needs to be called AFTER the windows are initialized. - * Devices will start sending events after InitAndStartDevices() has - * completed. - * - * @return Success or error code on failure. - */ -int -InitAndStartDevices(void) -{ - DeviceIntPtr dev, next; - - for (dev = inputInfo.off_devices; dev; dev = dev->next) { - DebugF("(dix) initialising device %d\n", dev->id); - if (!dev->inited) - ActivateDevice(dev, TRUE); - } - - /* enable real devices */ - for (dev = inputInfo.off_devices; dev; dev = next) - { - DebugF("(dix) enabling device %d\n", dev->id); - next = dev->next; - if (dev->inited && dev->startup) - EnableDevice(dev, TRUE); - } - - return Success; -} - -/** - * Free the given device class and reset the pointer to NULL. - */ -static void -FreeDeviceClass(int type, pointer *class) -{ - if (!(*class)) - return; - - switch(type) - { - case KeyClass: - { - KeyClassPtr* k = (KeyClassPtr*)class; - if ((*k)->xkbInfo) - { - XkbFreeInfo((*k)->xkbInfo); - (*k)->xkbInfo = NULL; - } - free((*k)); - break; - } - case ButtonClass: - { - ButtonClassPtr *b = (ButtonClassPtr*)class; - free((*b)->xkb_acts); - free((*b)); - break; - } - case ValuatorClass: - { - ValuatorClassPtr *v = (ValuatorClassPtr*)class; - - free((*v)->motion); - free((*v)); - break; - } - case FocusClass: - { - FocusClassPtr *f = (FocusClassPtr*)class; - free((*f)->trace); - free((*f)); - break; - } - case ProximityClass: - { - ProximityClassPtr *p = (ProximityClassPtr*)class; - free((*p)); - break; - } - } - *class = NULL; -} - -static void -FreeFeedbackClass(int type, pointer *class) -{ - if (!(*class)) - return; - - switch(type) - { - case KbdFeedbackClass: - { - KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class; - KbdFeedbackPtr k, knext; - for (k = (*kbdfeed); k; k = knext) { - knext = k->next; - if (k->xkb_sli) - XkbFreeSrvLedInfo(k->xkb_sli); - free(k); - } - break; - } - case PtrFeedbackClass: - { - PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class; - PtrFeedbackPtr p, pnext; - - for (p = (*ptrfeed); p; p = pnext) { - pnext = p->next; - free(p); - } - break; - } - case IntegerFeedbackClass: - { - IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class; - IntegerFeedbackPtr i, inext; - - for (i = (*intfeed); i; i = inext) { - inext = i->next; - free(i); - } - break; - } - case StringFeedbackClass: - { - StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class; - StringFeedbackPtr s, snext; - - for (s = (*stringfeed); s; s = snext) { - snext = s->next; - free(s->ctrl.symbols_supported); - free(s->ctrl.symbols_displayed); - free(s); - } - break; - } - case BellFeedbackClass: - { - BellFeedbackPtr *bell = (BellFeedbackPtr*)class; - BellFeedbackPtr b, bnext; - - for (b = (*bell); b; b = bnext) { - bnext = b->next; - free(b); - } - break; - } - case LedFeedbackClass: - { - LedFeedbackPtr *leds = (LedFeedbackPtr*)class; - LedFeedbackPtr l, lnext; - - for (l = (*leds); l; l = lnext) { - lnext = l->next; - if (l->xkb_sli) - XkbFreeSrvLedInfo(l->xkb_sli); - free(l); - } - break; - } - } - *class = NULL; -} - -static void -FreeAllDeviceClasses(ClassesPtr classes) -{ - if (!classes) - return; - - FreeDeviceClass(KeyClass, (pointer)&classes->key); - FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator); - FreeDeviceClass(ButtonClass, (pointer)&classes->button); - FreeDeviceClass(FocusClass, (pointer)&classes->focus); - FreeDeviceClass(ProximityClass, (pointer)&classes->proximity); - - FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed); - FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed); - FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed); - FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed); - FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell); - FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds); - -} - -/** - * Close down a device and free all resources. - * Once closed down, the driver will probably not expect you that you'll ever - * enable it again and free associated structs. If you want the device to just - * be disabled, DisableDevice(). - * Don't call this function directly, use RemoveDevice() instead. - */ -static void -CloseDevice(DeviceIntPtr dev) -{ - ScreenPtr screen = screenInfo.screens[0]; - ClassesPtr classes; - int j; - - if (!dev) - return; - - XIDeleteAllDeviceProperties(dev); - - if (dev->inited) - (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); - - /* free sprite memory */ - if (IsMaster(dev) && dev->spriteInfo->sprite) - screen->DeviceCursorCleanup(dev, screen); - - /* free acceleration info */ - if(dev->valuator && dev->valuator->accelScheme.AccelCleanupProc) - dev->valuator->accelScheme.AccelCleanupProc(dev); - - while (dev->xkb_interest) - XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); - - free(dev->name); - - classes = (ClassesPtr)&dev->key; - FreeAllDeviceClasses(classes); - - if (IsMaster(dev)) - { - classes = dev->unused_classes; - FreeAllDeviceClasses(classes); - free(classes); - } - - if (DevHasCursor(dev) && dev->spriteInfo->sprite) { - if (dev->spriteInfo->sprite->current) - FreeCursor(dev->spriteInfo->sprite->current, None); - free(dev->spriteInfo->sprite->spriteTrace); - free(dev->spriteInfo->sprite); - } - - /* a client may have the device set as client pointer */ - for (j = 0; j < currentMaxClients; j++) - { - if (clients[j] && clients[j]->clientPtr == dev) - { - clients[j]->clientPtr = NULL; - clients[j]->clientPtr = PickPointer(clients[j]); - } - } - - free(dev->deviceGrab.sync.event); - dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE); -} - -/** - * Shut down all devices of one list and free all resources. - */ -static -void -CloseDeviceList(DeviceIntPtr *listHead) -{ - /* Used to mark devices that we tried to free */ - Bool freedIds[MAXDEVICES]; - DeviceIntPtr dev; - int i; - - if (listHead == NULL) - return; - - for (i = 0; i < MAXDEVICES; i++) - freedIds[i] = FALSE; - - dev = *listHead; - while (dev != NULL) - { - freedIds[dev->id] = TRUE; - DeleteInputDeviceRequest(dev); - - dev = *listHead; - while (dev != NULL && freedIds[dev->id]) - dev = dev->next; - } -} - -/** - * Shut down all devices, free all resources, etc. - * Only useful if you're shutting down the server! - */ -void -CloseDownDevices(void) -{ - DeviceIntPtr dev; - - /* Float all SDs before closing them. Note that at this point resources - * (e.g. cursors) have been freed already, so we can't just call - * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master - * to NULL and pretend nothing happened. - */ - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (!IsMaster(dev) && !IsFloating(dev)) - dev->master = NULL; - } - - CloseDeviceList(&inputInfo.devices); - CloseDeviceList(&inputInfo.off_devices); - - CloseDevice(inputInfo.pointer); - CloseDevice(inputInfo.keyboard); - - inputInfo.devices = NULL; - inputInfo.off_devices = NULL; - inputInfo.keyboard = NULL; - inputInfo.pointer = NULL; - XkbDeleteRulesDflts(); -} - -/** - * Remove the cursor sprite for all devices. This needs to be done before any - * resources are freed or any device is deleted. - */ -void -UndisplayDevices(void) -{ - DeviceIntPtr dev; - ScreenPtr screen = screenInfo.screens[0]; - - for (dev = inputInfo.devices; dev; dev = dev->next) - screen->DisplayCursor(dev, screen, NullCursor); -} - -/** - * Remove a device from the device list, closes it and thus frees all - * resources. - * Removes both enabled and disabled devices and notifies all devices about - * the removal of the device. - * - * No PresenceNotify is sent for device that the client never saw. This can - * happen if a malloc fails during the addition of master devices. If - * dev->init is FALSE it means the client never received a DeviceAdded event, - * so let's not send a DeviceRemoved event either. - * - * @param sendevent True if an XI2 event should be sent. - */ -int -RemoveDevice(DeviceIntPtr dev, BOOL sendevent) -{ - DeviceIntPtr prev,tmp,next; - int ret = BadMatch; - ScreenPtr screen = screenInfo.screens[0]; - int deviceid; - int initialized; - int flags[MAXDEVICES] = {0}; - - DebugF("(dix) removing device %d\n", dev->id); - - if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer) - return BadImplementation; - - initialized = dev->inited; - deviceid = dev->id; - - if (initialized) - { - if (DevHasCursor(dev)) - screen->DisplayCursor(dev, screen, NullCursor); - - DisableDevice(dev, sendevent); - flags[dev->id] = XIDeviceDisabled; - } - - prev = NULL; - for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { - next = tmp->next; - if (tmp == dev) { - - if (prev==NULL) - inputInfo.devices = next; - else - prev->next = next; - - flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved; - CloseDevice(tmp); - ret = Success; - } - } - - prev = NULL; - for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) { - next = tmp->next; - if (tmp == dev) { - flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved; - CloseDevice(tmp); - - if (prev == NULL) - inputInfo.off_devices = next; - else - prev->next = next; - - ret = Success; - } - } - - if (ret == Success && initialized) { - inputInfo.numDevices--; - SendDevicePresenceEvent(deviceid, DeviceRemoved); - if (sendevent) - XISendDeviceHierarchyEvent(flags); - } - - return ret; -} - -int -NumMotionEvents(void) -{ - /* only called to fill data in initial connection reply. - * VCP is ok here, it is the only fixed device we have. */ - return inputInfo.pointer->valuator->numMotionEvents; -} - -int -dixLookupDevice(DeviceIntPtr *pDev, int id, ClientPtr client, Mask access_mode) -{ - DeviceIntPtr dev; - int rc; - *pDev = NULL; - - for (dev=inputInfo.devices; dev; dev=dev->next) { - if (dev->id == id) - goto found; - } - for (dev=inputInfo.off_devices; dev; dev=dev->next) { - if (dev->id == id) - goto found; - } - return BadDevice; - -found: - rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); - if (rc == Success) - *pDev = dev; - return rc; -} - -void -QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode) -{ - if (inputInfo.keyboard) { - *minCode = inputInfo.keyboard->key->xkbInfo->desc->min_key_code; - *maxCode = inputInfo.keyboard->key->xkbInfo->desc->max_key_code; - } -} - -/* Notably, this function does not expand the destination's keycode range, or - * notify clients. */ -Bool -SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) -{ - int i, j; - KeySym *tmp; - int rowDif = src->minKeyCode - dst->minKeyCode; - - /* if keysym map size changes, grow map first */ - if (src->mapWidth < dst->mapWidth) { - for (i = src->minKeyCode; i <= src->maxKeyCode; i++) { -#define SI(r, c) (((r - src->minKeyCode) * src->mapWidth) + (c)) -#define DI(r, c) (((r - dst->minKeyCode) * dst->mapWidth) + (c)) - for (j = 0; j < src->mapWidth; j++) - dst->map[DI(i, j)] = src->map[SI(i, j)]; - for (j = src->mapWidth; j < dst->mapWidth; j++) - dst->map[DI(i, j)] = NoSymbol; -#undef SI -#undef DI - } - return TRUE; - } - else if (src->mapWidth > dst->mapWidth) { - i = sizeof(KeySym) * src->mapWidth * - (dst->maxKeyCode - dst->minKeyCode + 1); - tmp = calloc(sizeof(KeySym), i); - if (!tmp) - return FALSE; - - if (dst->map) { - for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) - memmove(&tmp[i * src->mapWidth], &dst->map[i * dst->mapWidth], - dst->mapWidth * sizeof(KeySym)); - free(dst->map); - } - dst->mapWidth = src->mapWidth; - dst->map = tmp; - } - else if (!dst->map) { - i = sizeof(KeySym) * src->mapWidth * - (dst->maxKeyCode - dst->minKeyCode + 1); - tmp = calloc(sizeof(KeySym), i); - if (!tmp) - return FALSE; - - dst->map = tmp; - dst->mapWidth = src->mapWidth; - } - - memmove(&dst->map[rowDif * dst->mapWidth], src->map, - (src->maxKeyCode - src->minKeyCode + 1) * - dst->mapWidth * sizeof(KeySym)); - - return TRUE; -} - -Bool -InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels, - CARD8 *map) -{ - ButtonClassPtr butc; - int i; - - butc = calloc(1, sizeof(ButtonClassRec)); - if (!butc) - return FALSE; - butc->numButtons = numButtons; - butc->sourceid = dev->id; - for (i = 1; i <= numButtons; i++) - butc->map[i] = map[i]; - for (i = numButtons + 1; i < MAP_LENGTH; i++) - butc->map[i] = i; - memcpy(butc->labels, labels, numButtons * sizeof(Atom)); - dev->button = butc; - return TRUE; -} - -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; - - if (numAxes > MAX_VALUATORS) - { - LogMessage(X_WARNING, - "Device '%s' has %d axes, only using first %d.\n", - dev->name, numAxes, MAX_VALUATORS); - numAxes = MAX_VALUATORS; - } - - align = (union align_u *) calloc(1, sizeof(union align_u) + - numAxes * sizeof(double) + - numAxes * sizeof(AxisInfo)); - if (!align) - return FALSE; - - valc = &align->valc; - valc->sourceid = dev->id; - valc->motion = NULL; - valc->first_motion = 0; - valc->last_motion = 0; - - 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); - - dev->valuator = valc; - - AllocateMotionHistory(dev); - - for (i=0; iaxisVal[i]=0; - } - - dev->last.numValuators = numAxes; - - if (IsMaster(dev) || /* do not accelerate master or xtest devices */ - IsXTestDevice(dev, NULL)) - InitPointerAccelerationScheme(dev, PtrAccelNoOp); - else - InitPointerAccelerationScheme(dev, PtrAccelDefault); - return TRUE; -} - -/* global list of acceleration schemes */ -ValuatorAccelerationRec pointerAccelerationScheme[] = { - {PtrAccelNoOp, NULL, NULL, NULL, NULL}, - {PtrAccelPredictable, acceleratePointerPredictable, NULL, - InitPredictableAccelerationScheme, AccelerationDefaultCleanup}, - {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL, NULL}, - {-1, NULL, NULL, NULL, NULL} /* terminator */ -}; - -/** - * install an acceleration scheme. returns TRUE on success, and should not - * change anything if unsuccessful. - */ -Bool -InitPointerAccelerationScheme(DeviceIntPtr dev, - int scheme) -{ - int x, i = -1; - ValuatorClassPtr val; - - val = dev->valuator; - - if (!val) - return FALSE; - - if (IsMaster(dev) && scheme != PtrAccelNoOp) - return FALSE; - - for (x = 0; pointerAccelerationScheme[x].number >= 0; x++) { - if(pointerAccelerationScheme[x].number == scheme){ - i = x; - break; - } - } - - if (-1 == i) - return FALSE; - - if (val->accelScheme.AccelCleanupProc) - val->accelScheme.AccelCleanupProc(dev); - - if (pointerAccelerationScheme[i].AccelInitProc) { - if (!pointerAccelerationScheme[i].AccelInitProc(dev, - &pointerAccelerationScheme[i])) { - return FALSE; - } - } else { - val->accelScheme = pointerAccelerationScheme[i]; - } - return TRUE; -} - -Bool -InitAbsoluteClassDeviceStruct(DeviceIntPtr dev) -{ - AbsoluteClassPtr abs; - - abs = malloc(sizeof(AbsoluteClassRec)); - if (!abs) - return FALSE; - - /* we don't do anything sensible with these, but should */ - abs->min_x = NO_AXIS_LIMITS; - abs->min_y = NO_AXIS_LIMITS; - abs->max_x = NO_AXIS_LIMITS; - abs->max_y = NO_AXIS_LIMITS; - abs->flip_x = 0; - abs->flip_y = 0; - abs->rotation = 0; - abs->button_threshold = 0; - - abs->offset_x = 0; - abs->offset_y = 0; - abs->width = NO_AXIS_LIMITS; - abs->height = NO_AXIS_LIMITS; - abs->following = 0; - abs->screen = 0; - - abs->sourceid = dev->id; - - dev->absolute = abs; - - return TRUE; -} - -Bool -InitFocusClassDeviceStruct(DeviceIntPtr dev) -{ - FocusClassPtr focc; - - focc = malloc(sizeof(FocusClassRec)); - if (!focc) - return FALSE; - focc->win = PointerRootWin; - focc->revert = None; - focc->time = currentTime; - focc->trace = (WindowPtr *)NULL; - focc->traceSize = 0; - focc->traceGood = 0; - focc->sourceid = dev->id; - dev->focus = focc; - return TRUE; -} - -Bool -InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc) -{ - PtrFeedbackPtr feedc; - - feedc = malloc(sizeof(PtrFeedbackClassRec)); - if (!feedc) - return FALSE; - feedc->CtrlProc = controlProc; - feedc->ctrl = defaultPointerControl; - feedc->ctrl.id = 0; - if ( (feedc->next = dev->ptrfeed) ) - feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1; - dev->ptrfeed = feedc; - (*controlProc)(dev, &feedc->ctrl); - return TRUE; -} - - -static LedCtrl defaultLedControl = { - DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0}; - -static BellCtrl defaultBellControl = { - DEFAULT_BELL, - DEFAULT_BELL_PITCH, - DEFAULT_BELL_DURATION, - 0}; - -static IntegerCtrl defaultIntegerControl = { - DEFAULT_INT_RESOLUTION, - DEFAULT_INT_MIN_VALUE, - DEFAULT_INT_MAX_VALUE, - DEFAULT_INT_DISPLAYED, - 0}; - -Bool -InitStringFeedbackClassDeviceStruct ( - DeviceIntPtr dev, StringCtrlProcPtr controlProc, - int max_symbols, int num_symbols_supported, KeySym *symbols) -{ - int i; - StringFeedbackPtr feedc; - - feedc = malloc(sizeof(StringFeedbackClassRec)); - if (!feedc) - return FALSE; - feedc->CtrlProc = controlProc; - feedc->ctrl.num_symbols_supported = num_symbols_supported; - feedc->ctrl.num_symbols_displayed = 0; - feedc->ctrl.max_symbols = max_symbols; - feedc->ctrl.symbols_supported = malloc(sizeof (KeySym) * num_symbols_supported); - feedc->ctrl.symbols_displayed = malloc(sizeof (KeySym) * max_symbols); - if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) - { - free(feedc->ctrl.symbols_supported); - free(feedc->ctrl.symbols_displayed); - free(feedc); - return FALSE; - } - for (i=0; ictrl.symbols_supported+i) = *symbols++; - for (i=0; ictrl.symbols_displayed+i) = (KeySym) 0; - feedc->ctrl.id = 0; - if ( (feedc->next = dev->stringfeed) ) - feedc->ctrl.id = dev->stringfeed->ctrl.id + 1; - dev->stringfeed = feedc; - (*controlProc)(dev, &feedc->ctrl); - return TRUE; -} - -Bool -InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, - BellCtrlProcPtr controlProc) -{ - BellFeedbackPtr feedc; - - feedc = malloc(sizeof(BellFeedbackClassRec)); - if (!feedc) - return FALSE; - feedc->CtrlProc = controlProc; - feedc->BellProc = bellProc; - feedc->ctrl = defaultBellControl; - feedc->ctrl.id = 0; - if ( (feedc->next = dev->bell) ) - feedc->ctrl.id = dev->bell->ctrl.id + 1; - dev->bell = feedc; - (*controlProc)(dev, &feedc->ctrl); - return TRUE; -} - -Bool -InitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc) -{ - LedFeedbackPtr feedc; - - feedc = malloc(sizeof(LedFeedbackClassRec)); - if (!feedc) - return FALSE; - feedc->CtrlProc = controlProc; - feedc->ctrl = defaultLedControl; - feedc->ctrl.id = 0; - if ( (feedc->next = dev->leds) ) - feedc->ctrl.id = dev->leds->ctrl.id + 1; - feedc->xkb_sli= NULL; - dev->leds = feedc; - (*controlProc)(dev, &feedc->ctrl); - return TRUE; -} - -Bool -InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc) -{ - IntegerFeedbackPtr feedc; - - feedc = malloc(sizeof(IntegerFeedbackClassRec)); - if (!feedc) - return FALSE; - feedc->CtrlProc = controlProc; - feedc->ctrl = defaultIntegerControl; - feedc->ctrl.id = 0; - if ( (feedc->next = dev->intfeed) ) - feedc->ctrl.id = dev->intfeed->ctrl.id + 1; - dev->intfeed = feedc; - (*controlProc)(dev, &feedc->ctrl); - return TRUE; -} - -Bool -InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_labels, - PtrCtrlProcPtr controlProc, int numMotionEvents, - int numAxes, Atom *axes_labels) -{ - DeviceIntPtr dev = (DeviceIntPtr)device; - - return(InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) && - InitValuatorClassDeviceStruct(dev, numAxes, axes_labels, - numMotionEvents, Relative) && - InitPtrFeedbackClassDeviceStruct(dev, controlProc)); -} - -/* - * Check if the given buffer contains elements between low (inclusive) and - * high (inclusive) only. - * - * @return TRUE if the device map is invalid, FALSE otherwise. - */ -Bool -BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval) -{ - int i; - - for (i = 0; i < length; i++) - if (buff[i]) /* only check non-zero elements */ - { - if ((low > buff[i]) || (high < buff[i])) - { - *errval = buff[i]; - return TRUE; - } - } - return FALSE; -} - -int -ProcSetModifierMapping(ClientPtr client) -{ - xSetModifierMappingReply rep; - int rc; - REQUEST(xSetModifierMappingReq); - REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq); - - if (client->req_len != ((stuff->numKeyPerModifier << 1) + - bytes_to_int32(sizeof(xSetModifierMappingReq)))) - return BadLength; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rc = change_modmap(client, PickKeyboard(client), (KeyCode *)&stuff[1], - stuff->numKeyPerModifier); - if (rc == MappingFailed || rc == -1) - return BadValue; - if (rc != Success && rc != MappingSuccess && rc != MappingFailed && - rc != MappingBusy) - return rc; - - rep.success = rc; - - WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); - return Success; -} - -int -ProcGetModifierMapping(ClientPtr client) -{ - xGetModifierMappingReply rep; - int max_keys_per_mod = 0; - KeyCode *modkeymap = NULL; - REQUEST_SIZE_MATCH(xReq); - - generate_modkeymap(client, PickKeyboard(client), &modkeymap, - &max_keys_per_mod); - - memset(&rep, 0, sizeof(xGetModifierMappingReply)); - rep.type = X_Reply; - rep.numKeyPerModifier = max_keys_per_mod; - rep.sequenceNumber = client->sequence; - /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ - rep.length = max_keys_per_mod << 1; - - WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); - (void)WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap); - - free(modkeymap); - - return Success; -} - -int -ProcChangeKeyboardMapping(ClientPtr client) -{ - REQUEST(xChangeKeyboardMappingReq); - unsigned len; - KeySymsRec keysyms; - DeviceIntPtr pDev, tmp; - int rc; - REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); - - len = client->req_len - bytes_to_int32(sizeof(xChangeKeyboardMappingReq)); - if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) - return BadLength; - - pDev = PickKeyboard(client); - - if ((stuff->firstKeyCode < pDev->key->xkbInfo->desc->min_key_code) || - (stuff->firstKeyCode > pDev->key->xkbInfo->desc->max_key_code)) { - client->errorValue = stuff->firstKeyCode; - return BadValue; - - } - if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) > - pDev->key->xkbInfo->desc->max_key_code) || - (stuff->keySymsPerKeyCode == 0)) { - client->errorValue = stuff->keySymsPerKeyCode; - return BadValue; - } - - keysyms.minKeyCode = stuff->firstKeyCode; - keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1; - keysyms.mapWidth = stuff->keySymsPerKeyCode; - keysyms.map = (KeySym *) &stuff[1]; - - rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); - if (rc != Success) - return rc; - - XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode, - stuff->keyCodes, NULL, client); - - for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { - if (IsMaster(tmp) || GetMaster(tmp, MASTER_KEYBOARD) != pDev) - continue; - if (!tmp->key) - continue; - - rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); - if (rc != Success) - continue; - - XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode, - stuff->keyCodes, NULL, client); - } - - return Success; -} - -int -ProcSetPointerMapping(ClientPtr client) -{ - BYTE *map; - int ret; - int i, j; - DeviceIntPtr ptr = PickPointer(client); - xSetPointerMappingReply rep; - REQUEST(xSetPointerMappingReq); - REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); - - if (client->req_len != - bytes_to_int32(sizeof(xSetPointerMappingReq) + stuff->nElts)) - return BadLength; - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.success = MappingSuccess; - map = (BYTE *)&stuff[1]; - - /* So we're bounded here by the number of core buttons. This check - * probably wants disabling through XFixes. */ - /* MPX: With ClientPointer, we can return the right number of buttons. - * Let's just hope nobody changed ClientPointer between GetPointerMapping - * and SetPointerMapping - */ - if (stuff->nElts != ptr->button->numButtons) { - client->errorValue = stuff->nElts; - return BadValue; - } - - /* Core protocol specs don't allow for duplicate mappings; this check - * almost certainly wants disabling through XFixes too. */ - for (i = 0; i < stuff->nElts; i++) { - for (j = i + 1; j < stuff->nElts; j++) { - if (map[i] && map[i] == map[j]) { - client->errorValue = map[i]; - return BadValue; - } - } - } - - ret = ApplyPointerMapping(ptr, map, stuff->nElts, client); - if (ret == MappingBusy) - rep.success = ret; - else if (ret == -1) - return BadValue; - else if (ret != Success) - return ret; - - WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); - return Success; -} - -int -ProcGetKeyboardMapping(ClientPtr client) -{ - xGetKeyboardMappingReply rep; - DeviceIntPtr kbd = PickKeyboard(client); - XkbDescPtr xkb; - KeySymsPtr syms; - int rc; - REQUEST(xGetKeyboardMappingReq); - REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); - - rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); - if (rc != Success) - return rc; - - xkb = kbd->key->xkbInfo->desc; - - if ((stuff->firstKeyCode < xkb->min_key_code) || - (stuff->firstKeyCode > xkb->max_key_code)) { - client->errorValue = stuff->firstKeyCode; - return BadValue; - } - if (stuff->firstKeyCode + stuff->count > xkb->max_key_code + 1) { - client->errorValue = stuff->count; - return BadValue; - } - - syms = XkbGetCoreMap(kbd); - if (!syms) - return BadAlloc; - - memset(&rep, 0, sizeof(xGetKeyboardMappingReply)); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.keySymsPerKeyCode = syms->mapWidth; - /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ - rep.length = syms->mapWidth * stuff->count; - WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep); - client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; - WriteSwappedDataToClient(client, - syms->mapWidth * stuff->count * sizeof(KeySym), - &syms->map[syms->mapWidth * (stuff->firstKeyCode - - syms->minKeyCode)]); - free(syms->map); - free(syms); - - return Success; -} - -int -ProcGetPointerMapping(ClientPtr client) -{ - xGetPointerMappingReply rep; - /* Apps may get different values each time they call GetPointerMapping as - * the ClientPointer could change. */ - DeviceIntPtr ptr = PickPointer(client); - ButtonClassPtr butc = ptr->button; - int rc; - REQUEST_SIZE_MATCH(xReq); - - rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.nElts = (butc) ? butc->numButtons : 0; - rep.length = ((unsigned)rep.nElts + (4-1))/4; - WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); - if (butc) - WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]); - return Success; -} - -void -NoteLedState(DeviceIntPtr keybd, int led, Bool on) -{ - KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl; - if (on) - ctrl->leds |= ((Leds)1 << (led - 1)); - else - ctrl->leds &= ~((Leds)1 << (led - 1)); -} - -int -Ones(unsigned long mask) /* HACKMEM 169 */ -{ - unsigned long y; - - y = (mask >> 1) &033333333333; - y = mask - y - ((y >>1) & 033333333333); - return (((y + (y >> 3)) & 030707070707) % 077); -} - -static int -DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, - BITS32 vmask) -{ -#define DO_ALL (-1) - KeybdCtrl ctrl; - int t; - int led = DO_ALL; - int key = DO_ALL; - BITS32 index2; - int mask = vmask, i; - XkbEventCauseRec cause; - - ctrl = keybd->kbdfeed->ctrl; - while (vmask) { - index2 = (BITS32) lowbit (vmask); - vmask &= ~index2; - switch (index2) { - case KBKeyClickPercent: - t = (INT8)*vlist; - vlist++; - if (t == -1) { - t = defaultKeyboardControl.click; - } - else if (t < 0 || t > 100) { - client->errorValue = t; - return BadValue; - } - ctrl.click = t; - break; - case KBBellPercent: - t = (INT8)*vlist; - vlist++; - if (t == -1) { - t = defaultKeyboardControl.bell; - } - else if (t < 0 || t > 100) { - client->errorValue = t; - return BadValue; - } - ctrl.bell = t; - break; - case KBBellPitch: - t = (INT16)*vlist; - vlist++; - if (t == -1) { - t = defaultKeyboardControl.bell_pitch; - } - else if (t < 0) { - client->errorValue = t; - return BadValue; - } - ctrl.bell_pitch = t; - break; - case KBBellDuration: - t = (INT16)*vlist; - vlist++; - if (t == -1) - t = defaultKeyboardControl.bell_duration; - else if (t < 0) { - client->errorValue = t; - return BadValue; - } - ctrl.bell_duration = t; - break; - case KBLed: - led = (CARD8)*vlist; - vlist++; - if (led < 1 || led > 32) { - client->errorValue = led; - return BadValue; - } - if (!(mask & KBLedMode)) - return BadMatch; - break; - case KBLedMode: - t = (CARD8)*vlist; - vlist++; - if (t == LedModeOff) { - if (led == DO_ALL) - ctrl.leds = 0x0; - else - ctrl.leds &= ~(((Leds)(1)) << (led - 1)); - } - else if (t == LedModeOn) { - if (led == DO_ALL) - ctrl.leds = ~0L; - else - ctrl.leds |= (((Leds)(1)) << (led - 1)); - } - else { - client->errorValue = t; - return BadValue; - } - - XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client); - XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))), - ctrl.leds, &cause); - ctrl.leds = keybd->kbdfeed->ctrl.leds; - - break; - case KBKey: - key = (KeyCode)*vlist; - vlist++; - if ((KeyCode)key < keybd->key->xkbInfo->desc->min_key_code || - (KeyCode)key > keybd->key->xkbInfo->desc->max_key_code) { - client->errorValue = key; - return BadValue; - } - if (!(mask & KBAutoRepeatMode)) - return BadMatch; - break; - case KBAutoRepeatMode: - i = (key >> 3); - mask = (1 << (key & 7)); - t = (CARD8)*vlist; - vlist++; - if (key != DO_ALL) - XkbDisableComputedAutoRepeats(keybd,key); - if (t == AutoRepeatModeOff) { - if (key == DO_ALL) - ctrl.autoRepeat = FALSE; - else - ctrl.autoRepeats[i] &= ~mask; - } - else if (t == AutoRepeatModeOn) { - if (key == DO_ALL) - ctrl.autoRepeat = TRUE; - else - ctrl.autoRepeats[i] |= mask; - } - else if (t == AutoRepeatModeDefault) { - if (key == DO_ALL) - ctrl.autoRepeat = defaultKeyboardControl.autoRepeat; - else - ctrl.autoRepeats[i] = - (ctrl.autoRepeats[i] & ~mask) | - (defaultKeyboardControl.autoRepeats[i] & mask); - } - else { - client->errorValue = t; - return BadValue; - } - break; - default: - client->errorValue = mask; - return BadValue; - } - } - keybd->kbdfeed->ctrl = ctrl; - - /* The XKB RepeatKeys control and core protocol global autorepeat */ - /* value are linked */ - XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat); - - return Success; - -#undef DO_ALL -} - -/** - * Changes kbd control on the ClientPointer and all attached SDs. - */ -int -ProcChangeKeyboardControl (ClientPtr client) -{ - XID *vlist; - BITS32 vmask; - int ret = Success, error = Success; - DeviceIntPtr pDev = NULL, keyboard; - REQUEST(xChangeKeyboardControlReq); - - REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); - - vmask = stuff->mask; - vlist = (XID *)&stuff[1]; - - if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask)) - return BadLength; - - keyboard = PickKeyboard(client); - - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if ((pDev == keyboard || - (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard)) - && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { - ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); - if (ret != Success) - return ret; - } - } - - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if ((pDev == keyboard || - (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard)) - && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { - ret = DoChangeKeyboardControl(client, pDev, vlist, vmask); - if (ret != Success) - error = ret; - } - } - - return error; -} - -int -ProcGetKeyboardControl (ClientPtr client) -{ - int rc, i; - DeviceIntPtr kbd = PickKeyboard(client); - KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl; - xGetKeyboardControlReply rep; - REQUEST_SIZE_MATCH(xReq); - - rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 5; - rep.sequenceNumber = client->sequence; - rep.globalAutoRepeat = ctrl->autoRepeat; - rep.keyClickPercent = ctrl->click; - rep.bellPercent = ctrl->bell; - rep.bellPitch = ctrl->bell_pitch; - rep.bellDuration = ctrl->bell_duration; - rep.ledMask = ctrl->leds; - for (i = 0; i < 32; i++) - rep.map[i] = ctrl->autoRepeats[i]; - WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); - return Success; -} - -int -ProcBell(ClientPtr client) -{ - DeviceIntPtr dev, keybd = PickKeyboard(client); - int base = keybd->kbdfeed->ctrl.bell; - int newpercent; - int rc; - REQUEST(xBellReq); - REQUEST_SIZE_MATCH(xBellReq); - - if (stuff->percent < -100 || stuff->percent > 100) { - client->errorValue = stuff->percent; - return BadValue; - } - - newpercent = (base * stuff->percent) / 100; - if (stuff->percent < 0) - newpercent = base + newpercent; - else - newpercent = base - newpercent + stuff->percent; - - for (dev = inputInfo.devices; dev; dev = dev->next) { - if ((dev == keybd || - (!IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == keybd)) && - dev->kbdfeed && dev->kbdfeed->BellProc) { - - rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixBellAccess); - if (rc != Success) - return rc; - XkbHandleBell(FALSE, FALSE, dev, newpercent, - &dev->kbdfeed->ctrl, 0, None, NULL, client); - } - } - - return Success; -} - -int -ProcChangePointerControl(ClientPtr client) -{ - DeviceIntPtr dev, mouse = PickPointer(client); - PtrCtrl ctrl; /* might get BadValue part way through */ - int rc; - REQUEST(xChangePointerControlReq); - REQUEST_SIZE_MATCH(xChangePointerControlReq); - - ctrl = mouse->ptrfeed->ctrl; - if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) { - client->errorValue = stuff->doAccel; - return BadValue; - } - if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) { - client->errorValue = stuff->doThresh; - return BadValue; - } - if (stuff->doAccel) { - if (stuff->accelNum == -1) { - ctrl.num = defaultPointerControl.num; - } - else if (stuff->accelNum < 0) { - client->errorValue = stuff->accelNum; - return BadValue; - } - else { - ctrl.num = stuff->accelNum; - } - - if (stuff->accelDenum == -1) { - ctrl.den = defaultPointerControl.den; - } - else if (stuff->accelDenum <= 0) { - client->errorValue = stuff->accelDenum; - return BadValue; - } - else { - ctrl.den = stuff->accelDenum; - } - } - if (stuff->doThresh) { - if (stuff->threshold == -1) { - ctrl.threshold = defaultPointerControl.threshold; - } - else if (stuff->threshold < 0) { - client->errorValue = stuff->threshold; - return BadValue; - } - else { - ctrl.threshold = stuff->threshold; - } - } - - for (dev = inputInfo.devices; dev; dev = dev->next) { - if ((dev == mouse || - (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) && - dev->ptrfeed) { - rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); - if (rc != Success) - return rc; - } - } - - for (dev = inputInfo.devices; dev; dev = dev->next) { - if ((dev == mouse || - (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) && - dev->ptrfeed) { - dev->ptrfeed->ctrl = ctrl; - } - } - - return Success; -} - -int -ProcGetPointerControl(ClientPtr client) -{ - DeviceIntPtr ptr = PickPointer(client); - PtrCtrl *ctrl = &ptr->ptrfeed->ctrl; - xGetPointerControlReply rep; - int rc; - REQUEST_SIZE_MATCH(xReq); - - rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.threshold = ctrl->threshold; - rep.accelNumerator = ctrl->num; - rep.accelDenominator = ctrl->den; - WriteReplyToClient(client, sizeof(xGenericReply), &rep); - return Success; -} - -void -MaybeStopHint(DeviceIntPtr dev, ClientPtr client) -{ - GrabPtr grab = dev->deviceGrab.grab; - - if ((grab && SameClient(grab, client) && - ((grab->eventMask & PointerMotionHintMask) || - (grab->ownerEvents && - (EventMaskForClient(dev->valuator->motionHintWindow, client) & - PointerMotionHintMask)))) || - (!grab && - (EventMaskForClient(dev->valuator->motionHintWindow, client) & - PointerMotionHintMask))) - dev->valuator->motionHintWindow = NullWindow; -} - -int -ProcGetMotionEvents(ClientPtr client) -{ - WindowPtr pWin; - xTimecoord * coords = (xTimecoord *) NULL; - xGetMotionEventsReply rep; - int i, count, xmin, xmax, ymin, ymax, rc; - unsigned long nEvents; - DeviceIntPtr mouse = PickPointer(client); - TimeStamp start, stop; - REQUEST(xGetMotionEventsReq); - REQUEST_SIZE_MATCH(xGetMotionEventsReq); - - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); - if (rc != Success) - return rc; - - if (mouse->valuator->motionHintWindow) - MaybeStopHint(mouse, client); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - nEvents = 0; - start = ClientTimeToServerTime(stuff->start); - stop = ClientTimeToServerTime(stuff->stop); - if ((CompareTimeStamps(start, stop) != LATER) && - (CompareTimeStamps(start, currentTime) != LATER) && - mouse->valuator->numMotionEvents) - { - if (CompareTimeStamps(stop, currentTime) == LATER) - stop = currentTime; - count = GetMotionHistory(mouse, &coords, start.milliseconds, - stop.milliseconds, pWin->drawable.pScreen, - TRUE); - xmin = pWin->drawable.x - wBorderWidth (pWin); - xmax = pWin->drawable.x + (int)pWin->drawable.width + - wBorderWidth (pWin); - ymin = pWin->drawable.y - wBorderWidth (pWin); - ymax = pWin->drawable.y + (int)pWin->drawable.height + - wBorderWidth (pWin); - for (i = 0; i < count; i++) - if ((xmin <= coords[i].x) && (coords[i].x < xmax) && - (ymin <= coords[i].y) && (coords[i].y < ymax)) - { - coords[nEvents].time = coords[i].time; - coords[nEvents].x = coords[i].x - pWin->drawable.x; - coords[nEvents].y = coords[i].y - pWin->drawable.y; - nEvents++; - } - } - rep.length = nEvents * bytes_to_int32(sizeof(xTimecoord)); - rep.nEvents = nEvents; - WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep); - if (nEvents) - { - client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite; - WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord), - (char *)coords); - } - free(coords); - return Success; -} - -int -ProcQueryKeymap(ClientPtr client) -{ - xQueryKeymapReply rep; - int rc, i; - DeviceIntPtr keybd = PickKeyboard(client); - CARD8 *down = keybd->key->down; - - REQUEST_SIZE_MATCH(xReq); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 2; - - rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); - if (rc != Success && rc != BadAccess) - return rc; - - for (i = 0; i<32; i++) - rep.map[i] = down[i]; - - if (rc == BadAccess) - memset(rep.map, 0, 32); - - WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); - - return Success; -} - - -/** - * Recalculate the number of buttons for the master device. The number of - * buttons on the master device is equal to the number of buttons on the - * slave device with the highest number of buttons. - */ -static void -RecalculateMasterButtons(DeviceIntPtr slave) -{ - DeviceIntPtr dev, master; - int maxbuttons = 0; - - if (!slave->button || IsMaster(slave)) - return; - - master = GetMaster(slave, MASTER_POINTER); - if (!master) - return; - - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (IsMaster(dev) || - GetMaster(dev, MASTER_ATTACHED) != master || - !dev->button) - continue; - - maxbuttons = max(maxbuttons, dev->button->numButtons); - } - - if (master->button && master->button->numButtons != maxbuttons) - { - int i; - DeviceChangedEvent event; - - memset(&event, 0, sizeof(event)); - - master->button->numButtons = maxbuttons; - - event.header = ET_Internal; - event.type = ET_DeviceChanged; - event.time = GetTimeInMillis(); - event.deviceid = master->id; - event.flags = DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE; - event.buttons.num_buttons = maxbuttons; - memcpy(&event.buttons.names, master->button->labels, maxbuttons * - sizeof(Atom)); - - if (master->valuator) - { - event.num_valuators = master->valuator->numAxes; - for (i = 0; i < event.num_valuators; i++) - { - event.valuators[i].min = master->valuator->axes[i].min_value; - event.valuators[i].max = master->valuator->axes[i].max_value; - event.valuators[i].resolution = master->valuator->axes[i].resolution; - event.valuators[i].mode = master->valuator->axes[i].mode; - event.valuators[i].name = master->valuator->axes[i].label; - } - } - - if (master->key) - { - event.keys.min_keycode = master->key->xkbInfo->desc->min_key_code; - event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code; - } - - XISendDeviceChangedEvent(master, master, &event); - } -} - -/** - * Generate release events for all keys/button currently down on this - * device. - */ -static void -ReleaseButtonsAndKeys(DeviceIntPtr dev) -{ - EventListPtr eventlist = InitEventList(GetMaximumEventsNum()); - ButtonClassPtr b = dev->button; - KeyClassPtr k = dev->key; - int i, j, nevents; - - if (!eventlist) /* no release events for you */ - return; - - /* Release all buttons */ - for (i = 0; b && i < b->numButtons; i++) - { - if (BitIsOn(b->down, i)) - { - nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL); - for (j = 0; j < nevents; j++) - mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); - } - } - - /* Release all keys */ - for (i = 0; k && i < MAP_LENGTH; i++) - { - if (BitIsOn(k->down, i)) - { - nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i); - for (j = 0; j < nevents; j++) - mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); - } - } - - FreeEventList(eventlist, GetMaximumEventsNum()); -} - -/** - * Attach device 'dev' to device 'master'. - * Client is set to the client that issued the request, or NULL if it comes - * from some internal automatic pairing. - * - * Master may be NULL to set the device floating. - * - * We don't allow multi-layer hierarchies right now. You can't attach a slave - * to another slave. - */ -int -AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) -{ - ScreenPtr screen; - DeviceIntPtr oldmaster; - if (!dev || IsMaster(dev)) - return BadDevice; - - if (master && !IsMaster(master)) /* can't attach to slaves */ - return BadDevice; - - /* set from floating to floating? */ - if (IsFloating(dev) && !master && dev->enabled) - return Success; - - /* free the existing sprite. */ - if (IsFloating(dev) && dev->spriteInfo->paired == dev) - { - screen = miPointerGetScreen(dev); - screen->DeviceCursorCleanup(dev, screen); - free(dev->spriteInfo->sprite); - } - - ReleaseButtonsAndKeys(dev); - - oldmaster = GetMaster(dev, MASTER_ATTACHED); - dev->master = master; - - /* If device is set to floating, we need to create a sprite for it, - * otherwise things go bad. However, we don't want to render the cursor, - * so we reset spriteOwner. - * Sprite has to be forced to NULL first, otherwise InitializeSprite won't - * alloc new memory but overwrite the previous one. - */ - if (!master) - { - WindowPtr currentRoot; - - if (dev->spriteInfo->sprite) - currentRoot = GetCurrentRootWindow(dev); - else /* new device auto-set to floating */ - currentRoot = screenInfo.screens[0]->root; - - /* we need to init a fake sprite */ - screen = currentRoot->drawable.pScreen; - screen->DeviceCursorInitialize(dev, screen); - dev->spriteInfo->sprite = NULL; - InitializeSprite(dev, currentRoot); - dev->spriteInfo->spriteOwner = FALSE; - dev->spriteInfo->paired = dev; - } else - { - dev->spriteInfo->sprite = master->spriteInfo->sprite; - dev->spriteInfo->paired = master; - dev->spriteInfo->spriteOwner = FALSE; - - RecalculateMasterButtons(master); - } - - /* XXX: in theory, the MD should change back to its old, original - * classes when the last SD is detached. Thanks to the XTEST devices, - * we'll always have an SD attached until the MD is removed. - * So let's not worry about that. - */ - - return Success; -} - -/** - * Return the device paired with the given device or NULL. - * Returns the device paired with the parent master if the given device is a - * slave device. - */ -DeviceIntPtr -GetPairedDevice(DeviceIntPtr dev) -{ - if (!IsMaster(dev) && !IsFloating(dev)) - dev = GetMaster(dev, MASTER_ATTACHED); - - return dev->spriteInfo->paired; -} - - -/** - * Returns the right master for the type of event needed. If the event is a - * keyboard event. - * This function may be called with a master device as argument. If so, the - * returned master is either the device itself or the paired master device. - * If dev is a floating slave device, NULL is returned. - * - * @type ::MASTER_KEYBOARD or ::MASTER_POINTER or ::MASTER_ATTACHED - * @return The requested master device. In the case of MASTER_ATTACHED, this - * is the directly attached master to this device, regardless of the type. - * Otherwise, it is either the master keyboard or pointer for this device. - */ -DeviceIntPtr -GetMaster(DeviceIntPtr dev, int which) -{ - DeviceIntPtr master; - - if (IsMaster(dev)) - master = dev; - else - master = dev->master; - - if (master && which != MASTER_ATTACHED) - { - if (which == MASTER_KEYBOARD) - { - if (master->type != MASTER_KEYBOARD) - master = GetPairedDevice(master); - } else - { - if (master->type != MASTER_POINTER) - master = GetPairedDevice(master); - } - } - - return master; -} - -/** - * Create a new device pair (== one pointer, one keyboard device). - * Only allocates the devices, you will need to call ActivateDevice() and - * EnableDevice() manually. - * Either a master or a slave device can be created depending on - * the value for master. - */ -int -AllocDevicePair (ClientPtr client, char* name, - DeviceIntPtr* ptr, - DeviceIntPtr* keybd, - DeviceProc ptr_proc, - DeviceProc keybd_proc, - Bool master) -{ - DeviceIntPtr pointer; - DeviceIntPtr keyboard; - *ptr = *keybd = NULL; - - pointer = AddInputDevice(client, ptr_proc, TRUE); - if (!pointer) - return BadAlloc; - - if (asprintf(&pointer->name, "%s pointer", name) == -1) { - pointer->name = NULL; - RemoveDevice(pointer, FALSE); - return BadAlloc; - } - - pointer->public.processInputProc = ProcessOtherEvent; - pointer->public.realInputProc = ProcessOtherEvent; - XkbSetExtension(pointer, ProcessPointerEvent); - pointer->deviceGrab.ActivateGrab = ActivatePointerGrab; - pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab; - pointer->coreEvents = TRUE; - pointer->spriteInfo->spriteOwner = TRUE; - - pointer->lastSlave = NULL; - pointer->last.slave = NULL; - pointer->type = (master) ? MASTER_POINTER : SLAVE; - - keyboard = AddInputDevice(client, keybd_proc, TRUE); - if (!keyboard) - { - RemoveDevice(pointer, FALSE); - return BadAlloc; - } - - if (asprintf(&keyboard->name, "%s keyboard", name) == -1) { - keyboard->name = NULL; - RemoveDevice(keyboard, FALSE); - RemoveDevice(pointer, FALSE); - return BadAlloc; - } - - keyboard->public.processInputProc = ProcessOtherEvent; - keyboard->public.realInputProc = ProcessOtherEvent; - XkbSetExtension(keyboard, ProcessKeyboardEvent); - keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab; - keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; - keyboard->coreEvents = TRUE; - keyboard->spriteInfo->spriteOwner = FALSE; - - keyboard->lastSlave = NULL; - keyboard->last.slave = NULL; - keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE; - - /* The ClassesRec stores the device classes currently not used. */ - pointer->unused_classes = calloc(1, sizeof(ClassesRec)); - keyboard->unused_classes = calloc(1, sizeof(ClassesRec)); - - *ptr = pointer; - *keybd = keyboard; - - return Success; -} - -/** - * Return Relative or Absolute for the device. - */ -int valuator_get_mode(DeviceIntPtr dev, int axis) -{ - return (dev->valuator->axes[axis].mode & DeviceMode); -} - -/** - * Set the given mode for the axis. If axis is VALUATOR_MODE_ALL_AXES, then - * set the mode for all axes. - */ -void valuator_set_mode(DeviceIntPtr dev, int axis, int mode) -{ - if (axis != VALUATOR_MODE_ALL_AXES) - dev->valuator->axes[axis].mode = mode; - else { - int i; - for (i = 0; i < dev->valuator->numAxes; i++) - dev->valuator->axes[i].mode = mode; - } -} +/************************************************************ + +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. + +********************************************************/ + + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "misc.h" +#include "resource.h" +#include +#include +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "ptrveloc.h" +#include "site.h" +#include "xkbsrv.h" +#include "privates.h" +#include "xace.h" +#include "mi.h" + +#include "dispatch.h" +#include "swaprep.h" +#include "dixevents.h" +#include "mipointer.h" +#include "eventstr.h" + +#include +#include +#include +#include +#include +#include "exglobals.h" +#include "exevents.h" +#include "xiquerydevice.h" /* for SizeDeviceClasses */ +#include "xiproperty.h" +#include "enterleave.h" /* for EnterWindow() */ +#include "xserver-properties.h" +#include "xichangehierarchy.h" /* For XISendDeviceHierarchyEvent */ + +/** @file + * This file handles input device-related stuff. + */ + +static void RecalculateMasterButtons(DeviceIntPtr slave); + +static void +DeviceSetTransform(DeviceIntPtr dev, float *transform) +{ + struct pixman_f_transform scale; + double sx, sy; + int x, y; + + /** + * calculate combined transformation matrix: + * + * M = InvScale * Transform * Scale + * + * So we can later transform points using M * p + * + * Where: + * Scale scales coordinates into 0..1 range + * Transform is the user supplied (affine) transform + * InvScale scales coordinates back up into their native range + */ + sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value; + sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value; + + /* invscale */ + pixman_f_transform_init_scale(&scale, sx, sy); + scale.m[0][2] = dev->valuator->axes[0].min_value; + scale.m[1][2] = dev->valuator->axes[1].min_value; + + /* transform */ + for (y=0; y<3; y++) + for (x=0; x<3; x++) + dev->transform.m[y][x] = *transform++; + + pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform); + + /* scale */ + pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy); + scale.m[0][2] = -dev->valuator->axes[0].min_value / sx; + scale.m[1][2] = -dev->valuator->axes[1].min_value / sy; + + pixman_f_transform_multiply(&dev->transform, &dev->transform, &scale); +} + +/** + * DIX property handler. + */ +static int +DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, + BOOL checkonly) +{ + if (property == XIGetKnownProperty(XI_PROP_ENABLED)) + { + if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1) + return BadValue; + + /* Don't allow disabling of VCP/VCK */ + if ((dev == inputInfo.pointer || dev == inputInfo.keyboard) && + !(*(CARD8*)prop->data)) + return BadAccess; + + if (!checkonly) + { + if ((*((CARD8*)prop->data)) && !dev->enabled) + EnableDevice(dev, TRUE); + else if (!(*((CARD8*)prop->data)) && dev->enabled) + DisableDevice(dev, TRUE); + } + } else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM)) + { + float *f = (float*)prop->data; + int i; + + if (prop->format != 32 || prop->size != 9 || + prop->type != XIGetKnownProperty(XATOM_FLOAT)) + return BadValue; + + for (i=0; i<9; i++) + if (!isfinite(f[i])) + return BadValue; + + if (!checkonly) + DeviceSetTransform(dev, f); + } + + return Success; +} + +/* Pair the keyboard to the pointer device. Keyboard events will follow the + * pointer sprite. Only applicable for master devices. + * If the client is set, the request to pair comes from some client. In this + * case, we need to check for access. If the client is NULL, it's from an + * internal automatic pairing, we must always permit this. + */ +static int +PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd) +{ + if (!ptr) + return BadDevice; + + /* Don't allow pairing for slave devices */ + if (!IsMaster(ptr) || !IsMaster(kbd)) + return BadDevice; + + if (ptr->spriteInfo->paired) + return BadDevice; + + if (kbd->spriteInfo->spriteOwner) + { + free(kbd->spriteInfo->sprite); + kbd->spriteInfo->sprite = NULL; + kbd->spriteInfo->spriteOwner = FALSE; + } + + kbd->spriteInfo->sprite = ptr->spriteInfo->sprite; + kbd->spriteInfo->paired = ptr; + ptr->spriteInfo->paired = kbd; + return Success; +} + + +/** + * Find and return the next unpaired MD pointer device. + */ +static DeviceIntPtr +NextFreePointerDevice(void) +{ + DeviceIntPtr dev; + for (dev = inputInfo.devices; dev; dev = dev->next) + if (IsMaster(dev) && + dev->spriteInfo->spriteOwner && + !dev->spriteInfo->paired) + return dev; + return NULL; +} + +/** + * Create a new input device and init it to sane values. The device is added + * to the server's off_devices list. + * + * @param deviceProc Callback for device control function (switch dev on/off). + * @return The newly created device. + */ +DeviceIntPtr +AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) +{ + DeviceIntPtr dev, *prev; /* not a typo */ + DeviceIntPtr devtmp; + int devid; + char devind[MAXDEVICES]; + BOOL enabled; + float transform[9]; + + /* Find next available id, 0 and 1 are reserved */ + memset(devind, 0, sizeof(char)*MAXDEVICES); + for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next) + devind[devtmp->id]++; + for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next) + devind[devtmp->id]++; + for (devid = 2; devid < MAXDEVICES && devind[devid]; devid++) + ; + + if (devid >= MAXDEVICES) + return (DeviceIntPtr)NULL; + dev = _dixAllocateObjectWithPrivates(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), + sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), + offsetof(DeviceIntRec, devPrivates), PRIVATE_DEVICE); + if (!dev) + return (DeviceIntPtr)NULL; + dev->id = devid; + dev->public.processInputProc = ProcessOtherEvent; + dev->public.realInputProc = ProcessOtherEvent; + dev->public.enqueueInputProc = EnqueueEvent; + dev->deviceProc = deviceProc; + dev->startup = autoStart; + + /* device grab defaults */ + dev->deviceGrab.grabTime = currentTime; + dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; + dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; + + XkbSetExtension(dev, ProcessKeyboardEvent); + + dev->coreEvents = TRUE; + + /* sprite defaults */ + dev->spriteInfo = (SpriteInfoPtr)&dev[1]; + + /* security creation/labeling check + */ + if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) { + free(dev); + return NULL; + } + + inputInfo.numDevices++; + + for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next) + ; + *prev = dev; + dev->next = NULL; + + enabled = FALSE; + XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), + XA_INTEGER, 8, PropModeReplace, 1, &enabled, + FALSE); + XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE); + + /* unity matrix */ + memset(transform, 0, sizeof(transform)); + transform[0] = transform[4] = transform[8] = 1.0f; + + XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), + XIGetKnownProperty(XATOM_FLOAT), 32, + PropModeReplace, 9, transform, FALSE); + XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), + FALSE); + + XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL); + + return dev; +} + +void +SendDevicePresenceEvent(int deviceid, int type) +{ + DeviceIntRec dummyDev; + devicePresenceNotify ev; + + memset(&dummyDev, 0, sizeof(DeviceIntRec)); + ev.type = DevicePresenceNotify; + ev.time = currentTime.milliseconds; + ev.devchange = type; + ev.deviceid = deviceid; + dummyDev.id = XIAllDevices; + SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, + (xEvent*)&ev, 1); +} + +/** + * Enable the device through the driver, add the device to the device list. + * Switch device ON through the driver and push it onto the global device + * list. Initialize the DIX sprite or pair the device. All clients are + * notified about the device being enabled. + * + * A master pointer device needs to be enabled before a master keyboard + * device. + * + * @param The device to be enabled. + * @param sendevent True if an XI2 event should be sent. + * @return TRUE on success or FALSE otherwise. + */ +Bool +EnableDevice(DeviceIntPtr dev, BOOL sendevent) +{ + DeviceIntPtr *prev; + int ret; + DeviceIntPtr other; + BOOL enabled; + int flags[MAXDEVICES] = {0}; + + for (prev = &inputInfo.off_devices; + *prev && (*prev != dev); + prev = &(*prev)->next) + ; + + if (!dev->spriteInfo->sprite) + { + if (IsMaster(dev)) + { + /* Sprites appear on first root window, so we can hardcode it */ + if (dev->spriteInfo->spriteOwner) + { + InitializeSprite(dev, screenInfo.screens[0]->root); + /* mode doesn't matter */ + EnterWindow(dev, screenInfo.screens[0]->root, NotifyAncestor); + } + else if ((other = NextFreePointerDevice()) == NULL) + { + ErrorF("[dix] cannot find pointer to pair with. " + "This is a bug.\n"); + return FALSE; + } else + PairDevices(NULL, other, dev); + } else + { + if (dev->coreEvents) + other = (IsPointerDevice(dev)) ? inputInfo.pointer : + inputInfo.keyboard; + else + other = NULL; /* auto-float non-core devices */ + AttachDevice(NULL, dev, other); + } + } + + if ((*prev != dev) || !dev->inited || + ((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) { + ErrorF("[dix] couldn't enable device %d\n", dev->id); + return FALSE; + } + dev->enabled = TRUE; + *prev = dev->next; + + for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next) + ; + *prev = dev; + dev->next = NULL; + + enabled = TRUE; + XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), + XA_INTEGER, 8, PropModeReplace, 1, &enabled, + TRUE); + + SendDevicePresenceEvent(dev->id, DeviceEnabled); + if (sendevent) + { + flags[dev->id] |= XIDeviceEnabled; + XISendDeviceHierarchyEvent(flags); + } + + RecalculateMasterButtons(dev); + + return TRUE; +} + +/** + * Switch a device off through the driver and push it onto the off_devices + * list. A device will not send events while disabled. All clients are + * notified about the device being disabled. + * + * Master keyboard devices have to be disabled before master pointer devices + * otherwise things turn bad. + * + * @param sendevent True if an XI2 event should be sent. + * @return TRUE on success or FALSE otherwise. + */ +Bool +DisableDevice(DeviceIntPtr dev, BOOL sendevent) +{ + DeviceIntPtr *prev, other; + BOOL enabled; + int flags[MAXDEVICES] = {0}; + + for (prev = &inputInfo.devices; + *prev && (*prev != dev); + prev = &(*prev)->next) + ; + if (*prev != dev) + return FALSE; + + /* float attached devices */ + if (IsMaster(dev)) + { + for (other = inputInfo.devices; other; other = other->next) + { + if (!IsMaster(other) && GetMaster(other, MASTER_ATTACHED) == dev) + { + AttachDevice(NULL, other, NULL); + flags[other->id] |= XISlaveDetached; + } + } + } + else + { + for (other = inputInfo.devices; other; other = other->next) + { + if (IsMaster(other) && other->lastSlave == dev) + other->lastSlave = NULL; + } + } + + if (IsMaster(dev) && dev->spriteInfo->sprite) + { + for (other = inputInfo.devices; other; other = other->next) + { + if (other->spriteInfo->paired == dev) + { + ErrorF("[dix] cannot disable device, still paired. " + "This is a bug. \n"); + return FALSE; + } + } + } + + (void)(*dev->deviceProc)(dev, DEVICE_OFF); + dev->enabled = FALSE; + + /* now that the device is disabled, we can reset the signal handler's + * last.slave */ + OsBlockSignals(); + for (other = inputInfo.devices; other; other = other->next) + { + if (other->last.slave == dev) + other->last.slave = NULL; + } + OsReleaseSignals(); + + LeaveWindow(dev); + SetFocusOut(dev); + + *prev = dev->next; + dev->next = inputInfo.off_devices; + inputInfo.off_devices = dev; + + enabled = FALSE; + XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), + XA_INTEGER, 8, PropModeReplace, 1, &enabled, + TRUE); + + SendDevicePresenceEvent(dev->id, DeviceDisabled); + if (sendevent) + { + flags[dev->id] = XIDeviceDisabled; + XISendDeviceHierarchyEvent(flags); + } + + RecalculateMasterButtons(dev); + + return TRUE; +} + +/** + * Initialise a new device through the driver and tell all clients about the + * new device. + * + * Must be called before EnableDevice. + * The device will NOT send events until it is enabled! + * + * @param sendevent True if an XI2 event should be sent. + * @return Success or an error code on failure. + */ +int +ActivateDevice(DeviceIntPtr dev, BOOL sendevent) +{ + int ret = Success; + ScreenPtr pScreen = screenInfo.screens[0]; + + if (!dev || !dev->deviceProc) + return BadImplementation; + + ret = (*dev->deviceProc) (dev, DEVICE_INIT); + dev->inited = (ret == Success); + if (!dev->inited) + return ret; + + /* Initialize memory for sprites. */ + if (IsMaster(dev) && dev->spriteInfo->spriteOwner) + if (!pScreen->DeviceCursorInitialize(dev, pScreen)) + ret = BadAlloc; + + SendDevicePresenceEvent(dev->id, DeviceAdded); + if (sendevent) + { + int flags[MAXDEVICES] = {0}; + flags[dev->id] = XISlaveAdded; + XISendDeviceHierarchyEvent(flags); + } + return ret; +} + +/** + * Ring the bell. + * The actual task of ringing the bell is the job of the DDX. + */ +static void +CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something) +{ + KeybdCtrl *ctrl = arg; + + DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration); +} + +static void +CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl) +{ + return; +} + +/** + * Device control function for the Virtual Core Keyboard. + */ +int +CoreKeyboardProc(DeviceIntPtr pDev, int what) +{ + + switch (what) { + case DEVICE_INIT: + if (!InitKeyboardDeviceStruct(pDev, NULL, CoreKeyboardBell, + CoreKeyboardCtl)) + { + ErrorF("Keyboard initialization failed. This could be a missing " + "or incorrect setup of xkeyboard-config.\n"); + return BadValue; + } + return Success; + + case DEVICE_ON: + case DEVICE_OFF: + return Success; + + case DEVICE_CLOSE: + return Success; + } + + return BadMatch; +} + +/** + * Device control function for the Virtual Core Pointer. + */ +int +CorePointerProc(DeviceIntPtr pDev, int what) +{ +#define NBUTTONS 10 +#define NAXES 2 + BYTE map[NBUTTONS + 1]; + int i = 0; + Atom btn_labels[NBUTTONS] = {0}; + Atom axes_labels[NAXES] = {0}; + + switch (what) { + case DEVICE_INIT: + for (i = 1; i <= NBUTTONS; i++) + map[i] = i; + + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); + btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); + btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); + btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); + btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); + /* don't know about the rest */ + + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); + + if (!InitPointerDeviceStruct((DevicePtr)pDev, map, NBUTTONS, btn_labels, + (PtrCtrlProcPtr)NoopDDA, + GetMotionHistorySize(), NAXES, axes_labels)) + { + ErrorF("Could not initialize device '%s'. Out of memory.\n", + pDev->name); + return BadAlloc; /* IPDS only fails on allocs */ + } + pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + pDev->last.valuators[0] = pDev->valuator->axisVal[0]; + pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; + pDev->last.valuators[1] = pDev->valuator->axisVal[1]; + break; + + case DEVICE_CLOSE: + break; + + default: + break; + } + + return Success; + +#undef NBUTTONS +#undef NAXES +} + +/** + * Initialise the two core devices, VCP and VCK (see events.c). + * Both devices are not tied to physical devices, but guarantee that there is + * always a keyboard and a pointer present and keep the protocol semantics. + * + * Note that the server MUST have two core devices at all times, even if there + * is no physical device connected. + */ +void +InitCoreDevices(void) +{ + if (AllocDevicePair(serverClient, "Virtual core", + &inputInfo.pointer, &inputInfo.keyboard, + CorePointerProc, CoreKeyboardProc, + TRUE) != Success) + FatalError("Failed to allocate core devices"); + + if (ActivateDevice(inputInfo.pointer, TRUE) != Success || + ActivateDevice(inputInfo.keyboard, TRUE) != Success) + FatalError("Failed to activate core devices."); + if (!EnableDevice(inputInfo.pointer, TRUE) || + !EnableDevice(inputInfo.keyboard, TRUE)) + FatalError("Failed to enable core devices."); + + InitXTestDevices(); +} + +/** + * Activate all switched-off devices and then enable all those devices. + * + * Will return an error if no core keyboard or core pointer is present. + * In theory this should never happen if you call InitCoreDevices() first. + * + * InitAndStartDevices needs to be called AFTER the windows are initialized. + * Devices will start sending events after InitAndStartDevices() has + * completed. + * + * @return Success or error code on failure. + */ +int +InitAndStartDevices(void) +{ + DeviceIntPtr dev, next; + + for (dev = inputInfo.off_devices; dev; dev = dev->next) { + DebugF("(dix) initialising device %d\n", dev->id); + if (!dev->inited) + ActivateDevice(dev, TRUE); + } + + /* enable real devices */ + for (dev = inputInfo.off_devices; dev; dev = next) + { + DebugF("(dix) enabling device %d\n", dev->id); + next = dev->next; + if (dev->inited && dev->startup) + EnableDevice(dev, TRUE); + } + + return Success; +} + +/** + * Free the given device class and reset the pointer to NULL. + */ +static void +FreeDeviceClass(int type, pointer *class) +{ + if (!(*class)) + return; + + switch(type) + { + case KeyClass: + { + KeyClassPtr* k = (KeyClassPtr*)class; + if ((*k)->xkbInfo) + { + XkbFreeInfo((*k)->xkbInfo); + (*k)->xkbInfo = NULL; + } + free((*k)); + break; + } + case ButtonClass: + { + ButtonClassPtr *b = (ButtonClassPtr*)class; + free((*b)->xkb_acts); + free((*b)); + break; + } + case ValuatorClass: + { + ValuatorClassPtr *v = (ValuatorClassPtr*)class; + + free((*v)->motion); + free((*v)); + break; + } + case FocusClass: + { + FocusClassPtr *f = (FocusClassPtr*)class; + free((*f)->trace); + free((*f)); + break; + } + case ProximityClass: + { + ProximityClassPtr *p = (ProximityClassPtr*)class; + free((*p)); + break; + } + } + *class = NULL; +} + +static void +FreeFeedbackClass(int type, pointer *class) +{ + if (!(*class)) + return; + + switch(type) + { + case KbdFeedbackClass: + { + KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class; + KbdFeedbackPtr k, knext; + for (k = (*kbdfeed); k; k = knext) { + knext = k->next; + if (k->xkb_sli) + XkbFreeSrvLedInfo(k->xkb_sli); + free(k); + } + break; + } + case PtrFeedbackClass: + { + PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class; + PtrFeedbackPtr p, pnext; + + for (p = (*ptrfeed); p; p = pnext) { + pnext = p->next; + free(p); + } + break; + } + case IntegerFeedbackClass: + { + IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class; + IntegerFeedbackPtr i, inext; + + for (i = (*intfeed); i; i = inext) { + inext = i->next; + free(i); + } + break; + } + case StringFeedbackClass: + { + StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class; + StringFeedbackPtr s, snext; + + for (s = (*stringfeed); s; s = snext) { + snext = s->next; + free(s->ctrl.symbols_supported); + free(s->ctrl.symbols_displayed); + free(s); + } + break; + } + case BellFeedbackClass: + { + BellFeedbackPtr *bell = (BellFeedbackPtr*)class; + BellFeedbackPtr b, bnext; + + for (b = (*bell); b; b = bnext) { + bnext = b->next; + free(b); + } + break; + } + case LedFeedbackClass: + { + LedFeedbackPtr *leds = (LedFeedbackPtr*)class; + LedFeedbackPtr l, lnext; + + for (l = (*leds); l; l = lnext) { + lnext = l->next; + if (l->xkb_sli) + XkbFreeSrvLedInfo(l->xkb_sli); + free(l); + } + break; + } + } + *class = NULL; +} + +static void +FreeAllDeviceClasses(ClassesPtr classes) +{ + if (!classes) + return; + + FreeDeviceClass(KeyClass, (pointer)&classes->key); + FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator); + FreeDeviceClass(ButtonClass, (pointer)&classes->button); + FreeDeviceClass(FocusClass, (pointer)&classes->focus); + FreeDeviceClass(ProximityClass, (pointer)&classes->proximity); + + FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed); + FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed); + FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed); + FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed); + FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell); + FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds); + +} + +/** + * Close down a device and free all resources. + * Once closed down, the driver will probably not expect you that you'll ever + * enable it again and free associated structs. If you want the device to just + * be disabled, DisableDevice(). + * Don't call this function directly, use RemoveDevice() instead. + */ +static void +CloseDevice(DeviceIntPtr dev) +{ + ScreenPtr screen = screenInfo.screens[0]; + ClassesPtr classes; + int j; + + if (!dev) + return; + + XIDeleteAllDeviceProperties(dev); + + if (dev->inited) + (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); + + /* free sprite memory */ + if (IsMaster(dev) && dev->spriteInfo->sprite) + screen->DeviceCursorCleanup(dev, screen); + + /* free acceleration info */ + if(dev->valuator && dev->valuator->accelScheme.AccelCleanupProc) + dev->valuator->accelScheme.AccelCleanupProc(dev); + + while (dev->xkb_interest) + XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); + + free(dev->name); + + classes = (ClassesPtr)&dev->key; + FreeAllDeviceClasses(classes); + + if (IsMaster(dev)) + { + classes = dev->unused_classes; + FreeAllDeviceClasses(classes); + free(classes); + } + + if (DevHasCursor(dev) && dev->spriteInfo->sprite) { + if (dev->spriteInfo->sprite->current) + FreeCursor(dev->spriteInfo->sprite->current, None); + free(dev->spriteInfo->sprite->spriteTrace); + free(dev->spriteInfo->sprite); + } + + /* a client may have the device set as client pointer */ + for (j = 0; j < currentMaxClients; j++) + { + if (clients[j] && clients[j]->clientPtr == dev) + { + clients[j]->clientPtr = NULL; + clients[j]->clientPtr = PickPointer(clients[j]); + } + } + + free(dev->deviceGrab.sync.event); + free(dev->config_info); /* Allocated in xf86ActivateDevice. */ + dev->config_info = NULL; + dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE); +} + +/** + * Shut down all devices of one list and free all resources. + */ +static +void +CloseDeviceList(DeviceIntPtr *listHead) +{ + /* Used to mark devices that we tried to free */ + Bool freedIds[MAXDEVICES]; + DeviceIntPtr dev; + int i; + + if (listHead == NULL) + return; + + for (i = 0; i < MAXDEVICES; i++) + freedIds[i] = FALSE; + + dev = *listHead; + while (dev != NULL) + { + freedIds[dev->id] = TRUE; + DeleteInputDeviceRequest(dev); + + dev = *listHead; + while (dev != NULL && freedIds[dev->id]) + dev = dev->next; + } +} + +/** + * Shut down all devices, free all resources, etc. + * Only useful if you're shutting down the server! + */ +void +CloseDownDevices(void) +{ + DeviceIntPtr dev; + + /* Float all SDs before closing them. Note that at this point resources + * (e.g. cursors) have been freed already, so we can't just call + * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master + * to NULL and pretend nothing happened. + */ + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!IsMaster(dev) && !IsFloating(dev)) + dev->master = NULL; + } + + CloseDeviceList(&inputInfo.devices); + CloseDeviceList(&inputInfo.off_devices); + + CloseDevice(inputInfo.pointer); + CloseDevice(inputInfo.keyboard); + + inputInfo.devices = NULL; + inputInfo.off_devices = NULL; + inputInfo.keyboard = NULL; + inputInfo.pointer = NULL; + XkbDeleteRulesDflts(); +} + +/** + * Remove the cursor sprite for all devices. This needs to be done before any + * resources are freed or any device is deleted. + */ +void +UndisplayDevices(void) +{ + DeviceIntPtr dev; + ScreenPtr screen = screenInfo.screens[0]; + + for (dev = inputInfo.devices; dev; dev = dev->next) + screen->DisplayCursor(dev, screen, NullCursor); +} + +/** + * Remove a device from the device list, closes it and thus frees all + * resources. + * Removes both enabled and disabled devices and notifies all devices about + * the removal of the device. + * + * No PresenceNotify is sent for device that the client never saw. This can + * happen if a malloc fails during the addition of master devices. If + * dev->init is FALSE it means the client never received a DeviceAdded event, + * so let's not send a DeviceRemoved event either. + * + * @param sendevent True if an XI2 event should be sent. + */ +int +RemoveDevice(DeviceIntPtr dev, BOOL sendevent) +{ + DeviceIntPtr prev,tmp,next; + int ret = BadMatch; + ScreenPtr screen = screenInfo.screens[0]; + int deviceid; + int initialized; + int flags[MAXDEVICES] = {0}; + + DebugF("(dix) removing device %d\n", dev->id); + + if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer) + return BadImplementation; + + initialized = dev->inited; + deviceid = dev->id; + + if (initialized) + { + if (DevHasCursor(dev)) + screen->DisplayCursor(dev, screen, NullCursor); + + DisableDevice(dev, sendevent); + flags[dev->id] = XIDeviceDisabled; + } + + prev = NULL; + for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { + next = tmp->next; + if (tmp == dev) { + + if (prev==NULL) + inputInfo.devices = next; + else + prev->next = next; + + flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved; + CloseDevice(tmp); + ret = Success; + } + } + + prev = NULL; + for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) { + next = tmp->next; + if (tmp == dev) { + flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved; + CloseDevice(tmp); + + if (prev == NULL) + inputInfo.off_devices = next; + else + prev->next = next; + + ret = Success; + } + } + + if (ret == Success && initialized) { + inputInfo.numDevices--; + SendDevicePresenceEvent(deviceid, DeviceRemoved); + if (sendevent) + XISendDeviceHierarchyEvent(flags); + } + + return ret; +} + +int +NumMotionEvents(void) +{ + /* only called to fill data in initial connection reply. + * VCP is ok here, it is the only fixed device we have. */ + return inputInfo.pointer->valuator->numMotionEvents; +} + +int +dixLookupDevice(DeviceIntPtr *pDev, int id, ClientPtr client, Mask access_mode) +{ + DeviceIntPtr dev; + int rc; + *pDev = NULL; + + for (dev=inputInfo.devices; dev; dev=dev->next) { + if (dev->id == id) + goto found; + } + for (dev=inputInfo.off_devices; dev; dev=dev->next) { + if (dev->id == id) + goto found; + } + return BadDevice; + +found: + rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); + if (rc == Success) + *pDev = dev; + return rc; +} + +void +QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode) +{ + if (inputInfo.keyboard) { + *minCode = inputInfo.keyboard->key->xkbInfo->desc->min_key_code; + *maxCode = inputInfo.keyboard->key->xkbInfo->desc->max_key_code; + } +} + +/* Notably, this function does not expand the destination's keycode range, or + * notify clients. */ +Bool +SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) +{ + int i, j; + KeySym *tmp; + int rowDif = src->minKeyCode - dst->minKeyCode; + + /* if keysym map size changes, grow map first */ + if (src->mapWidth < dst->mapWidth) { + for (i = src->minKeyCode; i <= src->maxKeyCode; i++) { +#define SI(r, c) (((r - src->minKeyCode) * src->mapWidth) + (c)) +#define DI(r, c) (((r - dst->minKeyCode) * dst->mapWidth) + (c)) + for (j = 0; j < src->mapWidth; j++) + dst->map[DI(i, j)] = src->map[SI(i, j)]; + for (j = src->mapWidth; j < dst->mapWidth; j++) + dst->map[DI(i, j)] = NoSymbol; +#undef SI +#undef DI + } + return TRUE; + } + else if (src->mapWidth > dst->mapWidth) { + i = sizeof(KeySym) * src->mapWidth * + (dst->maxKeyCode - dst->minKeyCode + 1); + tmp = calloc(sizeof(KeySym), i); + if (!tmp) + return FALSE; + + if (dst->map) { + for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) + memmove(&tmp[i * src->mapWidth], &dst->map[i * dst->mapWidth], + dst->mapWidth * sizeof(KeySym)); + free(dst->map); + } + dst->mapWidth = src->mapWidth; + dst->map = tmp; + } + else if (!dst->map) { + i = sizeof(KeySym) * src->mapWidth * + (dst->maxKeyCode - dst->minKeyCode + 1); + tmp = calloc(sizeof(KeySym), i); + if (!tmp) + return FALSE; + + dst->map = tmp; + dst->mapWidth = src->mapWidth; + } + + memmove(&dst->map[rowDif * dst->mapWidth], src->map, + (src->maxKeyCode - src->minKeyCode + 1) * + dst->mapWidth * sizeof(KeySym)); + + return TRUE; +} + +Bool +InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels, + CARD8 *map) +{ + ButtonClassPtr butc; + int i; + + butc = calloc(1, sizeof(ButtonClassRec)); + if (!butc) + return FALSE; + butc->numButtons = numButtons; + butc->sourceid = dev->id; + for (i = 1; i <= numButtons; i++) + butc->map[i] = map[i]; + for (i = numButtons + 1; i < MAP_LENGTH; i++) + butc->map[i] = i; + memcpy(butc->labels, labels, numButtons * sizeof(Atom)); + dev->button = butc; + return TRUE; +} + +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; + + if (numAxes > MAX_VALUATORS) + { + LogMessage(X_WARNING, + "Device '%s' has %d axes, only using first %d.\n", + dev->name, numAxes, MAX_VALUATORS); + numAxes = MAX_VALUATORS; + } + + align = (union align_u *) calloc(1, sizeof(union align_u) + + numAxes * sizeof(double) + + numAxes * sizeof(AxisInfo)); + if (!align) + return FALSE; + + valc = &align->valc; + valc->sourceid = dev->id; + valc->motion = NULL; + valc->first_motion = 0; + valc->last_motion = 0; + + 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); + + dev->valuator = valc; + + AllocateMotionHistory(dev); + + for (i=0; iaxisVal[i]=0; + } + + dev->last.numValuators = numAxes; + + if (IsMaster(dev) || /* do not accelerate master or xtest devices */ + IsXTestDevice(dev, NULL)) + InitPointerAccelerationScheme(dev, PtrAccelNoOp); + else + InitPointerAccelerationScheme(dev, PtrAccelDefault); + return TRUE; +} + +/* global list of acceleration schemes */ +ValuatorAccelerationRec pointerAccelerationScheme[] = { + {PtrAccelNoOp, NULL, NULL, NULL, NULL}, + {PtrAccelPredictable, acceleratePointerPredictable, NULL, + InitPredictableAccelerationScheme, AccelerationDefaultCleanup}, + {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL, NULL}, + {-1, NULL, NULL, NULL, NULL} /* terminator */ +}; + +/** + * install an acceleration scheme. returns TRUE on success, and should not + * change anything if unsuccessful. + */ +Bool +InitPointerAccelerationScheme(DeviceIntPtr dev, + int scheme) +{ + int x, i = -1; + ValuatorClassPtr val; + + val = dev->valuator; + + if (!val) + return FALSE; + + if (IsMaster(dev) && scheme != PtrAccelNoOp) + return FALSE; + + for (x = 0; pointerAccelerationScheme[x].number >= 0; x++) { + if(pointerAccelerationScheme[x].number == scheme){ + i = x; + break; + } + } + + if (-1 == i) + return FALSE; + + if (val->accelScheme.AccelCleanupProc) + val->accelScheme.AccelCleanupProc(dev); + + if (pointerAccelerationScheme[i].AccelInitProc) { + if (!pointerAccelerationScheme[i].AccelInitProc(dev, + &pointerAccelerationScheme[i])) { + return FALSE; + } + } else { + val->accelScheme = pointerAccelerationScheme[i]; + } + return TRUE; +} + +Bool +InitAbsoluteClassDeviceStruct(DeviceIntPtr dev) +{ + AbsoluteClassPtr abs; + + abs = malloc(sizeof(AbsoluteClassRec)); + if (!abs) + return FALSE; + + /* we don't do anything sensible with these, but should */ + abs->min_x = NO_AXIS_LIMITS; + abs->min_y = NO_AXIS_LIMITS; + abs->max_x = NO_AXIS_LIMITS; + abs->max_y = NO_AXIS_LIMITS; + abs->flip_x = 0; + abs->flip_y = 0; + abs->rotation = 0; + abs->button_threshold = 0; + + abs->offset_x = 0; + abs->offset_y = 0; + abs->width = NO_AXIS_LIMITS; + abs->height = NO_AXIS_LIMITS; + abs->following = 0; + abs->screen = 0; + + abs->sourceid = dev->id; + + dev->absolute = abs; + + return TRUE; +} + +Bool +InitFocusClassDeviceStruct(DeviceIntPtr dev) +{ + FocusClassPtr focc; + + focc = malloc(sizeof(FocusClassRec)); + if (!focc) + return FALSE; + focc->win = PointerRootWin; + focc->revert = None; + focc->time = currentTime; + focc->trace = (WindowPtr *)NULL; + focc->traceSize = 0; + focc->traceGood = 0; + focc->sourceid = dev->id; + dev->focus = focc; + return TRUE; +} + +Bool +InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc) +{ + PtrFeedbackPtr feedc; + + feedc = malloc(sizeof(PtrFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultPointerControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->ptrfeed) ) + feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1; + dev->ptrfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + + +static LedCtrl defaultLedControl = { + DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0}; + +static BellCtrl defaultBellControl = { + DEFAULT_BELL, + DEFAULT_BELL_PITCH, + DEFAULT_BELL_DURATION, + 0}; + +static IntegerCtrl defaultIntegerControl = { + DEFAULT_INT_RESOLUTION, + DEFAULT_INT_MIN_VALUE, + DEFAULT_INT_MAX_VALUE, + DEFAULT_INT_DISPLAYED, + 0}; + +Bool +InitStringFeedbackClassDeviceStruct ( + DeviceIntPtr dev, StringCtrlProcPtr controlProc, + int max_symbols, int num_symbols_supported, KeySym *symbols) +{ + int i; + StringFeedbackPtr feedc; + + feedc = malloc(sizeof(StringFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl.num_symbols_supported = num_symbols_supported; + feedc->ctrl.num_symbols_displayed = 0; + feedc->ctrl.max_symbols = max_symbols; + feedc->ctrl.symbols_supported = malloc(sizeof (KeySym) * num_symbols_supported); + feedc->ctrl.symbols_displayed = malloc(sizeof (KeySym) * max_symbols); + if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) + { + free(feedc->ctrl.symbols_supported); + free(feedc->ctrl.symbols_displayed); + free(feedc); + return FALSE; + } + for (i=0; ictrl.symbols_supported+i) = *symbols++; + for (i=0; ictrl.symbols_displayed+i) = (KeySym) 0; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->stringfeed) ) + feedc->ctrl.id = dev->stringfeed->ctrl.id + 1; + dev->stringfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +Bool +InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, + BellCtrlProcPtr controlProc) +{ + BellFeedbackPtr feedc; + + feedc = malloc(sizeof(BellFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->BellProc = bellProc; + feedc->ctrl = defaultBellControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->bell) ) + feedc->ctrl.id = dev->bell->ctrl.id + 1; + dev->bell = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +Bool +InitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc) +{ + LedFeedbackPtr feedc; + + feedc = malloc(sizeof(LedFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultLedControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->leds) ) + feedc->ctrl.id = dev->leds->ctrl.id + 1; + feedc->xkb_sli= NULL; + dev->leds = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +Bool +InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc) +{ + IntegerFeedbackPtr feedc; + + feedc = malloc(sizeof(IntegerFeedbackClassRec)); + if (!feedc) + return FALSE; + feedc->CtrlProc = controlProc; + feedc->ctrl = defaultIntegerControl; + feedc->ctrl.id = 0; + if ( (feedc->next = dev->intfeed) ) + feedc->ctrl.id = dev->intfeed->ctrl.id + 1; + dev->intfeed = feedc; + (*controlProc)(dev, &feedc->ctrl); + return TRUE; +} + +Bool +InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_labels, + PtrCtrlProcPtr controlProc, int numMotionEvents, + int numAxes, Atom *axes_labels) +{ + DeviceIntPtr dev = (DeviceIntPtr)device; + + return(InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) && + InitValuatorClassDeviceStruct(dev, numAxes, axes_labels, + numMotionEvents, Relative) && + InitPtrFeedbackClassDeviceStruct(dev, controlProc)); +} + +/* + * Check if the given buffer contains elements between low (inclusive) and + * high (inclusive) only. + * + * @return TRUE if the device map is invalid, FALSE otherwise. + */ +Bool +BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval) +{ + int i; + + for (i = 0; i < length; i++) + if (buff[i]) /* only check non-zero elements */ + { + if ((low > buff[i]) || (high < buff[i])) + { + *errval = buff[i]; + return TRUE; + } + } + return FALSE; +} + +int +ProcSetModifierMapping(ClientPtr client) +{ + xSetModifierMappingReply rep; + int rc; + REQUEST(xSetModifierMappingReq); + REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq); + + if (client->req_len != ((stuff->numKeyPerModifier << 1) + + bytes_to_int32(sizeof(xSetModifierMappingReq)))) + return BadLength; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = change_modmap(client, PickKeyboard(client), (KeyCode *)&stuff[1], + stuff->numKeyPerModifier); + if (rc == MappingFailed || rc == -1) + return BadValue; + if (rc != Success && rc != MappingSuccess && rc != MappingFailed && + rc != MappingBusy) + return rc; + + rep.success = rc; + + WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); + return Success; +} + +int +ProcGetModifierMapping(ClientPtr client) +{ + xGetModifierMappingReply rep; + int max_keys_per_mod = 0; + KeyCode *modkeymap = NULL; + REQUEST_SIZE_MATCH(xReq); + + generate_modkeymap(client, PickKeyboard(client), &modkeymap, + &max_keys_per_mod); + + memset(&rep, 0, sizeof(xGetModifierMappingReply)); + rep.type = X_Reply; + rep.numKeyPerModifier = max_keys_per_mod; + rep.sequenceNumber = client->sequence; + /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ + rep.length = max_keys_per_mod << 1; + + WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); + (void)WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap); + + free(modkeymap); + + return Success; +} + +int +ProcChangeKeyboardMapping(ClientPtr client) +{ + REQUEST(xChangeKeyboardMappingReq); + unsigned len; + KeySymsRec keysyms; + DeviceIntPtr pDev, tmp; + int rc; + REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); + + len = client->req_len - bytes_to_int32(sizeof(xChangeKeyboardMappingReq)); + if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) + return BadLength; + + pDev = PickKeyboard(client); + + if ((stuff->firstKeyCode < pDev->key->xkbInfo->desc->min_key_code) || + (stuff->firstKeyCode > pDev->key->xkbInfo->desc->max_key_code)) { + client->errorValue = stuff->firstKeyCode; + return BadValue; + + } + if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) > + pDev->key->xkbInfo->desc->max_key_code) || + (stuff->keySymsPerKeyCode == 0)) { + client->errorValue = stuff->keySymsPerKeyCode; + return BadValue; + } + + keysyms.minKeyCode = stuff->firstKeyCode; + keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1; + keysyms.mapWidth = stuff->keySymsPerKeyCode; + keysyms.map = (KeySym *) &stuff[1]; + + rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); + if (rc != Success) + return rc; + + XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode, + stuff->keyCodes, NULL, client); + + for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { + if (IsMaster(tmp) || GetMaster(tmp, MASTER_KEYBOARD) != pDev) + continue; + if (!tmp->key) + continue; + + rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); + if (rc != Success) + continue; + + XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode, + stuff->keyCodes, NULL, client); + } + + return Success; +} + +int +ProcSetPointerMapping(ClientPtr client) +{ + BYTE *map; + int ret; + int i, j; + DeviceIntPtr ptr = PickPointer(client); + xSetPointerMappingReply rep; + REQUEST(xSetPointerMappingReq); + REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); + + if (client->req_len != + bytes_to_int32(sizeof(xSetPointerMappingReq) + stuff->nElts)) + return BadLength; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.success = MappingSuccess; + map = (BYTE *)&stuff[1]; + + /* So we're bounded here by the number of core buttons. This check + * probably wants disabling through XFixes. */ + /* MPX: With ClientPointer, we can return the right number of buttons. + * Let's just hope nobody changed ClientPointer between GetPointerMapping + * and SetPointerMapping + */ + if (stuff->nElts != ptr->button->numButtons) { + client->errorValue = stuff->nElts; + return BadValue; + } + + /* Core protocol specs don't allow for duplicate mappings; this check + * almost certainly wants disabling through XFixes too. */ + for (i = 0; i < stuff->nElts; i++) { + for (j = i + 1; j < stuff->nElts; j++) { + if (map[i] && map[i] == map[j]) { + client->errorValue = map[i]; + return BadValue; + } + } + } + + ret = ApplyPointerMapping(ptr, map, stuff->nElts, client); + if (ret == MappingBusy) + rep.success = ret; + else if (ret == -1) + return BadValue; + else if (ret != Success) + return ret; + + WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); + return Success; +} + +int +ProcGetKeyboardMapping(ClientPtr client) +{ + xGetKeyboardMappingReply rep; + DeviceIntPtr kbd = PickKeyboard(client); + XkbDescPtr xkb; + KeySymsPtr syms; + int rc; + REQUEST(xGetKeyboardMappingReq); + REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); + + rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); + if (rc != Success) + return rc; + + xkb = kbd->key->xkbInfo->desc; + + if ((stuff->firstKeyCode < xkb->min_key_code) || + (stuff->firstKeyCode > xkb->max_key_code)) { + client->errorValue = stuff->firstKeyCode; + return BadValue; + } + if (stuff->firstKeyCode + stuff->count > xkb->max_key_code + 1) { + client->errorValue = stuff->count; + return BadValue; + } + + syms = XkbGetCoreMap(kbd); + if (!syms) + return BadAlloc; + + memset(&rep, 0, sizeof(xGetKeyboardMappingReply)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.keySymsPerKeyCode = syms->mapWidth; + /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ + rep.length = syms->mapWidth * stuff->count; + WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep); + client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; + WriteSwappedDataToClient(client, + syms->mapWidth * stuff->count * sizeof(KeySym), + &syms->map[syms->mapWidth * (stuff->firstKeyCode - + syms->minKeyCode)]); + free(syms->map); + free(syms); + + return Success; +} + +int +ProcGetPointerMapping(ClientPtr client) +{ + xGetPointerMappingReply rep; + /* Apps may get different values each time they call GetPointerMapping as + * the ClientPointer could change. */ + DeviceIntPtr ptr = PickPointer(client); + ButtonClassPtr butc = ptr->button; + int rc; + REQUEST_SIZE_MATCH(xReq); + + rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.nElts = (butc) ? butc->numButtons : 0; + rep.length = ((unsigned)rep.nElts + (4-1))/4; + WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); + if (butc) + WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]); + return Success; +} + +void +NoteLedState(DeviceIntPtr keybd, int led, Bool on) +{ + KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl; + if (on) + ctrl->leds |= ((Leds)1 << (led - 1)); + else + ctrl->leds &= ~((Leds)1 << (led - 1)); +} + +int +Ones(unsigned long mask) /* HACKMEM 169 */ +{ + unsigned long y; + + y = (mask >> 1) &033333333333; + y = mask - y - ((y >>1) & 033333333333); + return (((y + (y >> 3)) & 030707070707) % 077); +} + +static int +DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, + BITS32 vmask) +{ +#define DO_ALL (-1) + KeybdCtrl ctrl; + int t; + int led = DO_ALL; + int key = DO_ALL; + BITS32 index2; + int mask = vmask, i; + XkbEventCauseRec cause; + + ctrl = keybd->kbdfeed->ctrl; + while (vmask) { + index2 = (BITS32) lowbit (vmask); + vmask &= ~index2; + switch (index2) { + case KBKeyClickPercent: + t = (INT8)*vlist; + vlist++; + if (t == -1) { + t = defaultKeyboardControl.click; + } + else if (t < 0 || t > 100) { + client->errorValue = t; + return BadValue; + } + ctrl.click = t; + break; + case KBBellPercent: + t = (INT8)*vlist; + vlist++; + if (t == -1) { + t = defaultKeyboardControl.bell; + } + else if (t < 0 || t > 100) { + client->errorValue = t; + return BadValue; + } + ctrl.bell = t; + break; + case KBBellPitch: + t = (INT16)*vlist; + vlist++; + if (t == -1) { + t = defaultKeyboardControl.bell_pitch; + } + else if (t < 0) { + client->errorValue = t; + return BadValue; + } + ctrl.bell_pitch = t; + break; + case KBBellDuration: + t = (INT16)*vlist; + vlist++; + if (t == -1) + t = defaultKeyboardControl.bell_duration; + else if (t < 0) { + client->errorValue = t; + return BadValue; + } + ctrl.bell_duration = t; + break; + case KBLed: + led = (CARD8)*vlist; + vlist++; + if (led < 1 || led > 32) { + client->errorValue = led; + return BadValue; + } + if (!(mask & KBLedMode)) + return BadMatch; + break; + case KBLedMode: + t = (CARD8)*vlist; + vlist++; + if (t == LedModeOff) { + if (led == DO_ALL) + ctrl.leds = 0x0; + else + ctrl.leds &= ~(((Leds)(1)) << (led - 1)); + } + else if (t == LedModeOn) { + if (led == DO_ALL) + ctrl.leds = ~0L; + else + ctrl.leds |= (((Leds)(1)) << (led - 1)); + } + else { + client->errorValue = t; + return BadValue; + } + + XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client); + XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))), + ctrl.leds, &cause); + ctrl.leds = keybd->kbdfeed->ctrl.leds; + + break; + case KBKey: + key = (KeyCode)*vlist; + vlist++; + if ((KeyCode)key < keybd->key->xkbInfo->desc->min_key_code || + (KeyCode)key > keybd->key->xkbInfo->desc->max_key_code) { + client->errorValue = key; + return BadValue; + } + if (!(mask & KBAutoRepeatMode)) + return BadMatch; + break; + case KBAutoRepeatMode: + i = (key >> 3); + mask = (1 << (key & 7)); + t = (CARD8)*vlist; + vlist++; + if (key != DO_ALL) + XkbDisableComputedAutoRepeats(keybd,key); + if (t == AutoRepeatModeOff) { + if (key == DO_ALL) + ctrl.autoRepeat = FALSE; + else + ctrl.autoRepeats[i] &= ~mask; + } + else if (t == AutoRepeatModeOn) { + if (key == DO_ALL) + ctrl.autoRepeat = TRUE; + else + ctrl.autoRepeats[i] |= mask; + } + else if (t == AutoRepeatModeDefault) { + if (key == DO_ALL) + ctrl.autoRepeat = defaultKeyboardControl.autoRepeat; + else + ctrl.autoRepeats[i] = + (ctrl.autoRepeats[i] & ~mask) | + (defaultKeyboardControl.autoRepeats[i] & mask); + } + else { + client->errorValue = t; + return BadValue; + } + break; + default: + client->errorValue = mask; + return BadValue; + } + } + keybd->kbdfeed->ctrl = ctrl; + + /* The XKB RepeatKeys control and core protocol global autorepeat */ + /* value are linked */ + XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat); + + return Success; + +#undef DO_ALL +} + +/** + * Changes kbd control on the ClientPointer and all attached SDs. + */ +int +ProcChangeKeyboardControl (ClientPtr client) +{ + XID *vlist; + BITS32 vmask; + int ret = Success, error = Success; + DeviceIntPtr pDev = NULL, keyboard; + REQUEST(xChangeKeyboardControlReq); + + REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq); + + vmask = stuff->mask; + vlist = (XID *)&stuff[1]; + + if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask)) + return BadLength; + + keyboard = PickKeyboard(client); + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { + if ((pDev == keyboard || + (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard)) + && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { + ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess); + if (ret != Success) + return ret; + } + } + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { + if ((pDev == keyboard || + (!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard)) + && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { + ret = DoChangeKeyboardControl(client, pDev, vlist, vmask); + if (ret != Success) + error = ret; + } + } + + return error; +} + +int +ProcGetKeyboardControl (ClientPtr client) +{ + int rc, i; + DeviceIntPtr kbd = PickKeyboard(client); + KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl; + xGetKeyboardControlReply rep; + REQUEST_SIZE_MATCH(xReq); + + rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 5; + rep.sequenceNumber = client->sequence; + rep.globalAutoRepeat = ctrl->autoRepeat; + rep.keyClickPercent = ctrl->click; + rep.bellPercent = ctrl->bell; + rep.bellPitch = ctrl->bell_pitch; + rep.bellDuration = ctrl->bell_duration; + rep.ledMask = ctrl->leds; + for (i = 0; i < 32; i++) + rep.map[i] = ctrl->autoRepeats[i]; + WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); + return Success; +} + +int +ProcBell(ClientPtr client) +{ + DeviceIntPtr dev, keybd = PickKeyboard(client); + int base = keybd->kbdfeed->ctrl.bell; + int newpercent; + int rc; + REQUEST(xBellReq); + REQUEST_SIZE_MATCH(xBellReq); + + if (stuff->percent < -100 || stuff->percent > 100) { + client->errorValue = stuff->percent; + return BadValue; + } + + newpercent = (base * stuff->percent) / 100; + if (stuff->percent < 0) + newpercent = base + newpercent; + else + newpercent = base - newpercent + stuff->percent; + + for (dev = inputInfo.devices; dev; dev = dev->next) { + if ((dev == keybd || + (!IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == keybd)) && + dev->kbdfeed && dev->kbdfeed->BellProc) { + + rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixBellAccess); + if (rc != Success) + return rc; + XkbHandleBell(FALSE, FALSE, dev, newpercent, + &dev->kbdfeed->ctrl, 0, None, NULL, client); + } + } + + return Success; +} + +int +ProcChangePointerControl(ClientPtr client) +{ + DeviceIntPtr dev, mouse = PickPointer(client); + PtrCtrl ctrl; /* might get BadValue part way through */ + int rc; + REQUEST(xChangePointerControlReq); + REQUEST_SIZE_MATCH(xChangePointerControlReq); + + ctrl = mouse->ptrfeed->ctrl; + if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) { + client->errorValue = stuff->doAccel; + return BadValue; + } + if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) { + client->errorValue = stuff->doThresh; + return BadValue; + } + if (stuff->doAccel) { + if (stuff->accelNum == -1) { + ctrl.num = defaultPointerControl.num; + } + else if (stuff->accelNum < 0) { + client->errorValue = stuff->accelNum; + return BadValue; + } + else { + ctrl.num = stuff->accelNum; + } + + if (stuff->accelDenum == -1) { + ctrl.den = defaultPointerControl.den; + } + else if (stuff->accelDenum <= 0) { + client->errorValue = stuff->accelDenum; + return BadValue; + } + else { + ctrl.den = stuff->accelDenum; + } + } + if (stuff->doThresh) { + if (stuff->threshold == -1) { + ctrl.threshold = defaultPointerControl.threshold; + } + else if (stuff->threshold < 0) { + client->errorValue = stuff->threshold; + return BadValue; + } + else { + ctrl.threshold = stuff->threshold; + } + } + + for (dev = inputInfo.devices; dev; dev = dev->next) { + if ((dev == mouse || + (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) && + dev->ptrfeed) { + rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); + if (rc != Success) + return rc; + } + } + + for (dev = inputInfo.devices; dev; dev = dev->next) { + if ((dev == mouse || + (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) && + dev->ptrfeed) { + dev->ptrfeed->ctrl = ctrl; + } + } + + return Success; +} + +int +ProcGetPointerControl(ClientPtr client) +{ + DeviceIntPtr ptr = PickPointer(client); + PtrCtrl *ctrl = &ptr->ptrfeed->ctrl; + xGetPointerControlReply rep; + int rc; + REQUEST_SIZE_MATCH(xReq); + + rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.threshold = ctrl->threshold; + rep.accelNumerator = ctrl->num; + rep.accelDenominator = ctrl->den; + WriteReplyToClient(client, sizeof(xGenericReply), &rep); + return Success; +} + +void +MaybeStopHint(DeviceIntPtr dev, ClientPtr client) +{ + GrabPtr grab = dev->deviceGrab.grab; + + if ((grab && SameClient(grab, client) && + ((grab->eventMask & PointerMotionHintMask) || + (grab->ownerEvents && + (EventMaskForClient(dev->valuator->motionHintWindow, client) & + PointerMotionHintMask)))) || + (!grab && + (EventMaskForClient(dev->valuator->motionHintWindow, client) & + PointerMotionHintMask))) + dev->valuator->motionHintWindow = NullWindow; +} + +int +ProcGetMotionEvents(ClientPtr client) +{ + WindowPtr pWin; + xTimecoord * coords = (xTimecoord *) NULL; + xGetMotionEventsReply rep; + int i, count, xmin, xmax, ymin, ymax, rc; + unsigned long nEvents; + DeviceIntPtr mouse = PickPointer(client); + TimeStamp start, stop; + REQUEST(xGetMotionEventsReq); + REQUEST_SIZE_MATCH(xGetMotionEventsReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); + if (rc != Success) + return rc; + + if (mouse->valuator->motionHintWindow) + MaybeStopHint(mouse, client); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + nEvents = 0; + start = ClientTimeToServerTime(stuff->start); + stop = ClientTimeToServerTime(stuff->stop); + if ((CompareTimeStamps(start, stop) != LATER) && + (CompareTimeStamps(start, currentTime) != LATER) && + mouse->valuator->numMotionEvents) + { + if (CompareTimeStamps(stop, currentTime) == LATER) + stop = currentTime; + count = GetMotionHistory(mouse, &coords, start.milliseconds, + stop.milliseconds, pWin->drawable.pScreen, + TRUE); + xmin = pWin->drawable.x - wBorderWidth (pWin); + xmax = pWin->drawable.x + (int)pWin->drawable.width + + wBorderWidth (pWin); + ymin = pWin->drawable.y - wBorderWidth (pWin); + ymax = pWin->drawable.y + (int)pWin->drawable.height + + wBorderWidth (pWin); + for (i = 0; i < count; i++) + if ((xmin <= coords[i].x) && (coords[i].x < xmax) && + (ymin <= coords[i].y) && (coords[i].y < ymax)) + { + coords[nEvents].time = coords[i].time; + coords[nEvents].x = coords[i].x - pWin->drawable.x; + coords[nEvents].y = coords[i].y - pWin->drawable.y; + nEvents++; + } + } + rep.length = nEvents * bytes_to_int32(sizeof(xTimecoord)); + rep.nEvents = nEvents; + WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep); + if (nEvents) + { + client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite; + WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord), + (char *)coords); + } + free(coords); + return Success; +} + +int +ProcQueryKeymap(ClientPtr client) +{ + xQueryKeymapReply rep; + int rc, i; + DeviceIntPtr keybd = PickKeyboard(client); + CARD8 *down = keybd->key->down; + + REQUEST_SIZE_MATCH(xReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 2; + + rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); + if (rc != Success && rc != BadAccess) + return rc; + + for (i = 0; i<32; i++) + rep.map[i] = down[i]; + + if (rc == BadAccess) + memset(rep.map, 0, 32); + + WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); + + return Success; +} + + +/** + * Recalculate the number of buttons for the master device. The number of + * buttons on the master device is equal to the number of buttons on the + * slave device with the highest number of buttons. + */ +static void +RecalculateMasterButtons(DeviceIntPtr slave) +{ + DeviceIntPtr dev, master; + int maxbuttons = 0; + + if (!slave->button || IsMaster(slave)) + return; + + master = GetMaster(slave, MASTER_POINTER); + if (!master) + return; + + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (IsMaster(dev) || + GetMaster(dev, MASTER_ATTACHED) != master || + !dev->button) + continue; + + maxbuttons = max(maxbuttons, dev->button->numButtons); + } + + if (master->button && master->button->numButtons != maxbuttons) + { + int i; + DeviceChangedEvent event; + + memset(&event, 0, sizeof(event)); + + master->button->numButtons = maxbuttons; + + event.header = ET_Internal; + event.type = ET_DeviceChanged; + event.time = GetTimeInMillis(); + event.deviceid = master->id; + event.flags = DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE; + event.buttons.num_buttons = maxbuttons; + memcpy(&event.buttons.names, master->button->labels, maxbuttons * + sizeof(Atom)); + + if (master->valuator) + { + event.num_valuators = master->valuator->numAxes; + for (i = 0; i < event.num_valuators; i++) + { + event.valuators[i].min = master->valuator->axes[i].min_value; + event.valuators[i].max = master->valuator->axes[i].max_value; + event.valuators[i].resolution = master->valuator->axes[i].resolution; + event.valuators[i].mode = master->valuator->axes[i].mode; + event.valuators[i].name = master->valuator->axes[i].label; + } + } + + if (master->key) + { + event.keys.min_keycode = master->key->xkbInfo->desc->min_key_code; + event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code; + } + + XISendDeviceChangedEvent(master, master, &event); + } +} + +/** + * Generate release events for all keys/button currently down on this + * device. + */ +static void +ReleaseButtonsAndKeys(DeviceIntPtr dev) +{ + EventListPtr eventlist = InitEventList(GetMaximumEventsNum()); + ButtonClassPtr b = dev->button; + KeyClassPtr k = dev->key; + int i, j, nevents; + + if (!eventlist) /* no release events for you */ + return; + + /* Release all buttons */ + for (i = 0; b && i < b->numButtons; i++) + { + if (BitIsOn(b->down, i)) + { + nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL); + for (j = 0; j < nevents; j++) + mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); + } + } + + /* Release all keys */ + for (i = 0; k && i < MAP_LENGTH; i++) + { + if (BitIsOn(k->down, i)) + { + nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i); + for (j = 0; j < nevents; j++) + mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL); + } + } + + FreeEventList(eventlist, GetMaximumEventsNum()); +} + +/** + * Attach device 'dev' to device 'master'. + * Client is set to the client that issued the request, or NULL if it comes + * from some internal automatic pairing. + * + * Master may be NULL to set the device floating. + * + * We don't allow multi-layer hierarchies right now. You can't attach a slave + * to another slave. + */ +int +AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) +{ + ScreenPtr screen; + DeviceIntPtr oldmaster; + if (!dev || IsMaster(dev)) + return BadDevice; + + if (master && !IsMaster(master)) /* can't attach to slaves */ + return BadDevice; + + /* set from floating to floating? */ + if (IsFloating(dev) && !master && dev->enabled) + return Success; + + /* free the existing sprite. */ + if (IsFloating(dev) && dev->spriteInfo->paired == dev) + { + screen = miPointerGetScreen(dev); + screen->DeviceCursorCleanup(dev, screen); + free(dev->spriteInfo->sprite); + } + + ReleaseButtonsAndKeys(dev); + + oldmaster = GetMaster(dev, MASTER_ATTACHED); + dev->master = master; + + /* If device is set to floating, we need to create a sprite for it, + * otherwise things go bad. However, we don't want to render the cursor, + * so we reset spriteOwner. + * Sprite has to be forced to NULL first, otherwise InitializeSprite won't + * alloc new memory but overwrite the previous one. + */ + if (!master) + { + WindowPtr currentRoot; + + if (dev->spriteInfo->sprite) + currentRoot = GetCurrentRootWindow(dev); + else /* new device auto-set to floating */ + currentRoot = screenInfo.screens[0]->root; + + /* we need to init a fake sprite */ + screen = currentRoot->drawable.pScreen; + screen->DeviceCursorInitialize(dev, screen); + dev->spriteInfo->sprite = NULL; + InitializeSprite(dev, currentRoot); + dev->spriteInfo->spriteOwner = FALSE; + dev->spriteInfo->paired = dev; + } else + { + dev->spriteInfo->sprite = master->spriteInfo->sprite; + dev->spriteInfo->paired = master; + dev->spriteInfo->spriteOwner = FALSE; + + RecalculateMasterButtons(master); + } + + /* XXX: in theory, the MD should change back to its old, original + * classes when the last SD is detached. Thanks to the XTEST devices, + * we'll always have an SD attached until the MD is removed. + * So let's not worry about that. + */ + + return Success; +} + +/** + * Return the device paired with the given device or NULL. + * Returns the device paired with the parent master if the given device is a + * slave device. + */ +DeviceIntPtr +GetPairedDevice(DeviceIntPtr dev) +{ + if (!IsMaster(dev) && !IsFloating(dev)) + dev = GetMaster(dev, MASTER_ATTACHED); + + return dev->spriteInfo->paired; +} + + +/** + * Returns the right master for the type of event needed. If the event is a + * keyboard event. + * This function may be called with a master device as argument. If so, the + * returned master is either the device itself or the paired master device. + * If dev is a floating slave device, NULL is returned. + * + * @type ::MASTER_KEYBOARD or ::MASTER_POINTER or ::MASTER_ATTACHED + * @return The requested master device. In the case of MASTER_ATTACHED, this + * is the directly attached master to this device, regardless of the type. + * Otherwise, it is either the master keyboard or pointer for this device. + */ +DeviceIntPtr +GetMaster(DeviceIntPtr dev, int which) +{ + DeviceIntPtr master; + + if (IsMaster(dev)) + master = dev; + else + master = dev->master; + + if (master && which != MASTER_ATTACHED) + { + if (which == MASTER_KEYBOARD) + { + if (master->type != MASTER_KEYBOARD) + master = GetPairedDevice(master); + } else + { + if (master->type != MASTER_POINTER) + master = GetPairedDevice(master); + } + } + + return master; +} + +/** + * Create a new device pair (== one pointer, one keyboard device). + * Only allocates the devices, you will need to call ActivateDevice() and + * EnableDevice() manually. + * Either a master or a slave device can be created depending on + * the value for master. + */ +int +AllocDevicePair (ClientPtr client, char* name, + DeviceIntPtr* ptr, + DeviceIntPtr* keybd, + DeviceProc ptr_proc, + DeviceProc keybd_proc, + Bool master) +{ + DeviceIntPtr pointer; + DeviceIntPtr keyboard; + *ptr = *keybd = NULL; + + pointer = AddInputDevice(client, ptr_proc, TRUE); + if (!pointer) + return BadAlloc; + + if (asprintf(&pointer->name, "%s pointer", name) == -1) { + pointer->name = NULL; + RemoveDevice(pointer, FALSE); + return BadAlloc; + } + + pointer->public.processInputProc = ProcessOtherEvent; + pointer->public.realInputProc = ProcessOtherEvent; + XkbSetExtension(pointer, ProcessPointerEvent); + pointer->deviceGrab.ActivateGrab = ActivatePointerGrab; + pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab; + pointer->coreEvents = TRUE; + pointer->spriteInfo->spriteOwner = TRUE; + + pointer->lastSlave = NULL; + pointer->last.slave = NULL; + pointer->type = (master) ? MASTER_POINTER : SLAVE; + + keyboard = AddInputDevice(client, keybd_proc, TRUE); + if (!keyboard) + { + RemoveDevice(pointer, FALSE); + return BadAlloc; + } + + if (asprintf(&keyboard->name, "%s keyboard", name) == -1) { + keyboard->name = NULL; + RemoveDevice(keyboard, FALSE); + RemoveDevice(pointer, FALSE); + return BadAlloc; + } + + keyboard->public.processInputProc = ProcessOtherEvent; + keyboard->public.realInputProc = ProcessOtherEvent; + XkbSetExtension(keyboard, ProcessKeyboardEvent); + keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab; + keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; + keyboard->coreEvents = TRUE; + keyboard->spriteInfo->spriteOwner = FALSE; + + keyboard->lastSlave = NULL; + keyboard->last.slave = NULL; + keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE; + + /* The ClassesRec stores the device classes currently not used. */ + pointer->unused_classes = calloc(1, sizeof(ClassesRec)); + keyboard->unused_classes = calloc(1, sizeof(ClassesRec)); + + *ptr = pointer; + *keybd = keyboard; + + return Success; +} + +/** + * Return Relative or Absolute for the device. + */ +int valuator_get_mode(DeviceIntPtr dev, int axis) +{ + return (dev->valuator->axes[axis].mode & DeviceMode); +} + +/** + * Set the given mode for the axis. If axis is VALUATOR_MODE_ALL_AXES, then + * set the mode for all axes. + */ +void valuator_set_mode(DeviceIntPtr dev, int axis, int mode) +{ + if (axis != VALUATOR_MODE_ALL_AXES) + dev->valuator->axes[axis].mode = mode; + else { + int i; + for (i = 0; i < dev->valuator->numAxes; i++) + dev->valuator->axes[i].mode = mode; + } +} diff --git a/xorg-server/dix/eventconvert.c b/xorg-server/dix/eventconvert.c index 760729beb..d5ac54796 100644 --- a/xorg-server/dix/eventconvert.c +++ b/xorg-server/dix/eventconvert.c @@ -1,767 +1,770 @@ -/* - * 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. - * - */ - -/** - * @file eventconvert.c - * This file contains event conversion routines from InternalEvent to the - * matching protocol events. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "dix.h" -#include "inputstr.h" -#include "misc.h" -#include "eventstr.h" -#include "exglobals.h" -#include "eventconvert.h" -#include "xiquerydevice.h" -#include "xkbsrv.h" - - -static int countValuators(DeviceEvent *ev, int *first); -static int getValuatorEvents(DeviceEvent *ev, deviceValuator *xv); -static int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count); -static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce); -static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi); -static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi); - -/* Do not use, read comments below */ -BOOL EventIsKeyRepeat(xEvent *event); - -/** - * Hack to allow detectable autorepeat for core and XI1 events. - * The sequence number is unused until we send to the client and can be - * misused to store data. More or less, anyway. - * - * Do not use this. It may change any time without warning, eat your babies - * and piss on your cat. - */ -static void -EventSetKeyRepeatFlag(xEvent *event, BOOL on) -{ - event->u.u.sequenceNumber = on; -} - -/** - * Check if the event was marked as a repeat event before. - * NOTE: This is a nasty hack and should NOT be used by anyone else but - * TryClientEvents. - */ -BOOL -EventIsKeyRepeat(xEvent *event) -{ - return !!event->u.u.sequenceNumber; -} - -/** - * Convert the given event to the respective core event. - * - * Return values: - * Success ... core contains the matching core event. - * BadValue .. One or more values in the internal event are invalid. - * BadMatch .. The event has no core equivalent. - * - * @param[in] event The event to convert into a core event. - * @param[in] core The memory location to store the core event at. - * @return Success or the matching error code. - */ -int -EventToCore(InternalEvent *event, xEvent **core_out, int *count_out) -{ - xEvent *core = NULL; - int count = 0; - int ret = BadImplementation; - - switch(event->any.type) - { - case ET_Motion: - { - DeviceEvent *e = &event->device_event; - /* Don't create core motion event if neither x nor y are - * present */ - if (!BitIsOn(e->valuators.mask, 0) && - !BitIsOn(e->valuators.mask, 1)) - { - ret = BadMatch; - goto out; - } - } - /* fallthrough */ - case ET_ButtonPress: - case ET_ButtonRelease: - case ET_KeyPress: - case ET_KeyRelease: - { - DeviceEvent *e = &event->device_event; - - if (e->detail.key > 0xFF) - { - ret = BadMatch; - goto out; - } - - core = calloc(1, sizeof(*core)); - if (!core) - return BadAlloc; - count = 1; - core->u.u.type = e->type - ET_KeyPress + KeyPress; - core->u.u.detail = e->detail.key & 0xFF; - core->u.keyButtonPointer.time = e->time; - core->u.keyButtonPointer.rootX = e->root_x; - core->u.keyButtonPointer.rootY = e->root_y; - core->u.keyButtonPointer.state = e->corestate; - core->u.keyButtonPointer.root = e->root; - EventSetKeyRepeatFlag(core, - (e->type == ET_KeyPress && - e->key_repeat)); - ret = Success; - } - break; - case ET_ProximityIn: - case ET_ProximityOut: - case ET_RawKeyPress: - case ET_RawKeyRelease: - case ET_RawButtonPress: - case ET_RawButtonRelease: - case ET_RawMotion: - ret = BadMatch; - goto out; - default: - /* XXX: */ - ErrorF("[dix] EventToCore: Not implemented yet \n"); - ret = BadImplementation; - } - -out: - *core_out = core; - *count_out = count; - return ret; -} - -/** - * Convert the given event to the respective XI 1.x event and store it in - * xi. xi is allocated on demand and must be freed by the caller. - * count returns the number of events in xi. If count is 1, and the type of - * xi is GenericEvent, then xi may be larger than 32 bytes. - * - * Return values: - * Success ... core contains the matching core event. - * BadValue .. One or more values in the internal event are invalid. - * BadMatch .. The event has no XI equivalent. - * - * @param[in] ev The event to convert into an XI 1 event. - * @param[out] xi Future memory location for the XI event. - * @param[out] count Number of elements in xi. - * - * @return Success or the error code. - */ -int -EventToXI(InternalEvent *ev, xEvent **xi, int *count) -{ - switch (ev->any.type) - { - case ET_Motion: - case ET_ButtonPress: - case ET_ButtonRelease: - case ET_KeyPress: - case ET_KeyRelease: - case ET_ProximityIn: - case ET_ProximityOut: - return eventToKeyButtonPointer(&ev->device_event, xi, count); - case ET_DeviceChanged: - case ET_RawKeyPress: - case ET_RawKeyRelease: - case ET_RawButtonPress: - case ET_RawButtonRelease: - case ET_RawMotion: - *count = 0; - *xi = NULL; - return BadMatch; - default: - break; - } - - ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->any.type); - return BadImplementation; -} - -/** - * Convert the given event to the respective XI 2.x event and store it in xi. - * xi is allocated on demand and must be freed by the caller. - * - * Return values: - * Success ... core contains the matching core event. - * BadValue .. One or more values in the internal event are invalid. - * BadMatch .. The event has no XI2 equivalent. - * - * @param[in] ev The event to convert into an XI2 event - * @param[out] xi Future memory location for the XI2 event. - * - * @return Success or the error code. - */ -int -EventToXI2(InternalEvent *ev, xEvent **xi) -{ - switch (ev->any.type) - { - /* Enter/FocusIn are for grabs. We don't need an actual event, since - * the real events delivered are triggered elsewhere */ - case ET_Enter: - case ET_FocusIn: - *xi = NULL; - return Success; - case ET_Motion: - case ET_ButtonPress: - case ET_ButtonRelease: - case ET_KeyPress: - case ET_KeyRelease: - return eventToDeviceEvent(&ev->device_event, xi); - case ET_ProximityIn: - case ET_ProximityOut: - *xi = NULL; - return BadMatch; - case ET_DeviceChanged: - return eventToDeviceChanged(&ev->changed_event, xi); - case ET_RawKeyPress: - case ET_RawKeyRelease: - case ET_RawButtonPress: - case ET_RawButtonRelease: - case ET_RawMotion: - return eventToRawEvent(&ev->raw_event, xi); - default: - break; - } - - ErrorF("[dix] EventToXI2: Not implemented for %d \n", ev->any.type); - return BadImplementation; -} - -static int -eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count) -{ - int num_events; - int first; /* dummy */ - deviceKeyButtonPointer *kbp; - - /* Sorry, XI 1.x protocol restrictions. */ - if (ev->detail.button > 0xFF || ev->deviceid >= 0x80) - { - *count = 0; - return Success; - } - - num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */ - if (num_events <= 0) - { - switch (ev->type) - { - case ET_KeyPress: - case ET_KeyRelease: - case ET_ButtonPress: - case ET_ButtonRelease: - /* no axes is ok */ - break; - case ET_Motion: - case ET_ProximityIn: - case ET_ProximityOut: - *count = 0; - return BadMatch; - } - } - - num_events++; /* the actual event event */ - - *xi = calloc(num_events, sizeof(xEvent)); - if (!(*xi)) - { - return BadAlloc; - } - - kbp = (deviceKeyButtonPointer*)(*xi); - kbp->detail = ev->detail.button; - kbp->time = ev->time; - kbp->root = ev->root; - kbp->root_x = ev->root_x; - kbp->root_y = ev->root_y; - kbp->deviceid = ev->deviceid; - kbp->state = ev->corestate; - EventSetKeyRepeatFlag((xEvent*)kbp, - (ev->type == ET_KeyPress && ev->key_repeat)); - - if (num_events > 1) - kbp->deviceid |= MORE_EVENTS; - - switch(ev->type) - { - case ET_Motion: kbp->type = DeviceMotionNotify; break; - case ET_ButtonPress: kbp->type = DeviceButtonPress; break; - case ET_ButtonRelease: kbp->type = DeviceButtonRelease; break; - case ET_KeyPress: kbp->type = DeviceKeyPress; break; - case ET_KeyRelease: kbp->type = DeviceKeyRelease; break; - case ET_ProximityIn: kbp->type = ProximityIn; break; - case ET_ProximityOut: kbp->type = ProximityOut; break; - default: - break; - } - - if (num_events > 1) - { - getValuatorEvents(ev, (deviceValuator*)(kbp + 1)); - } - - *count = num_events; - return Success; -} - - -/** - * Set first to the first valuator in the event ev and return the number of - * valuators from first to the last set valuator. - */ -static int -countValuators(DeviceEvent *ev, int *first) -{ - int first_valuator = -1, last_valuator = -1, num_valuators = 0; - int i; - - for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) - { - if (BitIsOn(ev->valuators.mask, i)) - { - if (first_valuator == -1) - first_valuator = i; - last_valuator = i; - } - } - - if (first_valuator != -1) - { - num_valuators = last_valuator - first_valuator + 1; - *first = first_valuator; - } - - return num_valuators; -} - -static int -getValuatorEvents(DeviceEvent *ev, deviceValuator *xv) -{ - int i; - int state = 0; - int first_valuator, num_valuators; - - - num_valuators = countValuators(ev, &first_valuator); - if (num_valuators > 0) - { - DeviceIntPtr dev = NULL; - dixLookupDevice(&dev, ev->deviceid, serverClient, DixUseAccess); - /* State needs to be assembled BEFORE the device is updated. */ - state = (dev && dev->key) ? XkbStateFieldFromRec(&dev->key->xkbInfo->state) : 0; - state |= (dev && dev->button) ? (dev->button->state) : 0; - } - - /* FIXME: non-continuous valuator data in internal events*/ - for (i = 0; i < num_valuators; i += 6, xv++) { - xv->type = DeviceValuator; - xv->first_valuator = first_valuator + i; - xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i); - xv->deviceid = ev->deviceid; - xv->device_state = state; - switch (xv->num_valuators) { - case 6: - xv->valuator5 = ev->valuators.data[xv->first_valuator + 5]; - case 5: - xv->valuator4 = ev->valuators.data[xv->first_valuator + 4]; - case 4: - xv->valuator3 = ev->valuators.data[xv->first_valuator + 3]; - case 3: - xv->valuator2 = ev->valuators.data[xv->first_valuator + 2]; - case 2: - xv->valuator1 = ev->valuators.data[xv->first_valuator + 1]; - case 1: - xv->valuator0 = ev->valuators.data[xv->first_valuator + 0]; - } - - if (i + 6 < num_valuators) - xv->deviceid |= MORE_EVENTS; - } - - return (num_valuators + 5) / 6; -} - - -static int -appendKeyInfo(DeviceChangedEvent *dce, xXIKeyInfo* info) -{ - uint32_t *kc; - int i; - - info->type = XIKeyClass; - info->num_keycodes = dce->keys.max_keycode - dce->keys.min_keycode + 1; - info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes; - info->sourceid = dce->sourceid; - - kc = (uint32_t*)&info[1]; - for (i = 0; i < info->num_keycodes; i++) - *kc++ = i + dce->keys.min_keycode; - - return info->length * 4; -} - -static int -appendButtonInfo(DeviceChangedEvent *dce, xXIButtonInfo *info) -{ - unsigned char *bits; - int mask_len; - - mask_len = bytes_to_int32(bits_to_bytes(dce->buttons.num_buttons)); - - info->type = XIButtonClass; - info->num_buttons = dce->buttons.num_buttons; - info->length = bytes_to_int32(sizeof(xXIButtonInfo)) + - info->num_buttons + mask_len; - info->sourceid = dce->sourceid; - - bits = (unsigned char*)&info[1]; - memset(bits, 0, mask_len * 4); - /* FIXME: is_down? */ - - bits += mask_len * 4; - memcpy(bits, dce->buttons.names, dce->buttons.num_buttons * sizeof(Atom)); - - return info->length * 4; -} - -static int -appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumber) -{ - info->type = XIValuatorClass; - info->length = sizeof(xXIValuatorInfo)/4; - info->label = dce->valuators[axisnumber].name; - info->min.integral = dce->valuators[axisnumber].min; - info->min.frac = 0; - info->max.integral = dce->valuators[axisnumber].max; - info->max.frac = 0; - /* FIXME: value */ - info->value.integral = 0; - info->value.frac = 0; - info->resolution = dce->valuators[axisnumber].resolution; - info->number = axisnumber; - info->mode = dce->valuators[axisnumber].mode; - info->sourceid = dce->sourceid; - - return info->length * 4; -} - -static int -eventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi) -{ - xXIDeviceChangedEvent *dcce; - int len = sizeof(xXIDeviceChangedEvent); - int nkeys; - char *ptr; - - if (dce->buttons.num_buttons) - { - len += sizeof(xXIButtonInfo); - len += dce->buttons.num_buttons * sizeof(Atom); /* button names */ - len += pad_to_int32(bits_to_bytes(dce->buttons.num_buttons)); - } - if (dce->num_valuators) - len += sizeof(xXIValuatorInfo) * dce->num_valuators; - - nkeys = (dce->keys.max_keycode > 0) ? - dce->keys.max_keycode - dce->keys.min_keycode + 1 : 0; - if (nkeys > 0) - { - len += sizeof(xXIKeyInfo); - len += sizeof(CARD32) * nkeys; /* keycodes */ - } - - dcce = calloc(1, len); - if (!dcce) - { - ErrorF("[Xi] BadAlloc in SendDeviceChangedEvent.\n"); - return BadAlloc; - } - - dcce->type = GenericEvent; - dcce->extension = IReqCode; - dcce->evtype = XI_DeviceChanged; - dcce->time = dce->time; - dcce->deviceid = dce->deviceid; - dcce->sourceid = dce->sourceid; - dcce->reason = (dce->flags & DEVCHANGE_DEVICE_CHANGE) ? XIDeviceChange : XISlaveSwitch; - dcce->num_classes = 0; - dcce->length = bytes_to_int32(len - sizeof(xEvent)); - - ptr = (char*)&dcce[1]; - if (dce->buttons.num_buttons) - { - dcce->num_classes++; - ptr += appendButtonInfo(dce, (xXIButtonInfo*)ptr); - } - - if (nkeys) - { - dcce->num_classes++; - ptr += appendKeyInfo(dce, (xXIKeyInfo*)ptr); - } - - if (dce->num_valuators) - { - int i; - - dcce->num_classes += dce->num_valuators; - for (i = 0; i < dce->num_valuators; i++) - ptr += appendValuatorInfo(dce, (xXIValuatorInfo*)ptr, i); - } - - *xi = (xEvent*)dcce; - - return Success; -} - -static int count_bits(unsigned char* ptr, int len) -{ - int bits = 0; - unsigned int i; - unsigned char x; - - for (i = 0; i < len; i++) - { - x = ptr[i]; - while(x > 0) - { - bits += (x & 0x1); - x >>= 1; - } - } - return bits; -} - -static int -eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) -{ - int len = sizeof(xXIDeviceEvent); - xXIDeviceEvent *xde; - int i, btlen, vallen; - char *ptr; - FP3232 *axisval; - - /* FIXME: this should just send the buttons we have, not MAX_BUTTONs. Same - * with MAX_VALUATORS below */ - /* btlen is in 4 byte units */ - btlen = bytes_to_int32(bits_to_bytes(MAX_BUTTONS)); - len += btlen * 4; /* buttonmask len */ - - - vallen = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)/sizeof(ev->valuators.mask[0])); - len += vallen * 2 * sizeof(uint32_t); /* axisvalues */ - vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); - len += vallen * 4; /* valuators mask */ - - *xi = calloc(1, len); - xde = (xXIDeviceEvent*)*xi; - xde->type = GenericEvent; - xde->extension = IReqCode; - xde->evtype = GetXI2Type((InternalEvent*)ev); - xde->time = ev->time; - xde->length = bytes_to_int32(len - sizeof(xEvent)); - xde->detail = ev->detail.button; - xde->root = ev->root; - xde->buttons_len = btlen; - xde->valuators_len = vallen; - xde->deviceid = ev->deviceid; - xde->sourceid = ev->sourceid; - xde->root_x = FP1616(ev->root_x, ev->root_x_frac); - xde->root_y = FP1616(ev->root_y, ev->root_y_frac); - - if (ev->key_repeat) - xde->flags |= XIKeyRepeat; - - xde->mods.base_mods = ev->mods.base; - xde->mods.latched_mods = ev->mods.latched; - xde->mods.locked_mods = ev->mods.locked; - xde->mods.effective_mods = ev->mods.effective; - - xde->group.base_group = ev->group.base; - xde->group.latched_group = ev->group.latched; - xde->group.locked_group = ev->group.locked; - xde->group.effective_group = ev->group.effective; - - ptr = (char*)&xde[1]; - for (i = 0; i < sizeof(ev->buttons) * 8; i++) - { - if (BitIsOn(ev->buttons, i)) - SetBit(ptr, i); - } - - ptr += xde->buttons_len * 4; - axisval = (FP3232*)(ptr + xde->valuators_len * 4); - for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) - { - if (BitIsOn(ev->valuators.mask, i)) - { - SetBit(ptr, i); - axisval->integral = ev->valuators.data[i]; - axisval->frac = ev->valuators.data_frac[i]; - axisval++; - } - } - - return Success; -} - -static int -eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) -{ - xXIRawEvent* raw; - int vallen, nvals; - int i, len = sizeof(xXIRawEvent); - char *ptr; - FP3232 *axisval; - - nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)); - len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once - raw, once processed */ - vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); - len += vallen * 4; /* valuators mask */ - - *xi = calloc(1, len); - raw = (xXIRawEvent*)*xi; - raw->type = GenericEvent; - raw->extension = IReqCode; - raw->evtype = GetXI2Type((InternalEvent*)ev); - raw->time = ev->time; - raw->length = bytes_to_int32(len - sizeof(xEvent)); - raw->detail = ev->detail.button; - raw->deviceid = ev->deviceid; - raw->valuators_len = vallen; - - ptr = (char*)&raw[1]; - axisval = (FP3232*)(ptr + raw->valuators_len * 4); - for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) - { - if (BitIsOn(ev->valuators.mask, i)) - { - SetBit(ptr, i); - axisval->integral = ev->valuators.data[i]; - axisval->frac = ev->valuators.data_frac[i]; - (axisval + nvals)->integral = ev->valuators.data_raw[i]; - (axisval + nvals)->frac = ev->valuators.data_raw_frac[i]; - axisval++; - } - } - - return Success; -} - -/** - * Return the corresponding core type for the given event or 0 if no core - * equivalent exists. - */ -int -GetCoreType(InternalEvent *event) -{ - int coretype = 0; - switch(event->any.type) - { - case ET_Motion: coretype = MotionNotify; break; - case ET_ButtonPress: coretype = ButtonPress; break; - case ET_ButtonRelease: coretype = ButtonRelease; break; - case ET_KeyPress: coretype = KeyPress; break; - case ET_KeyRelease: coretype = KeyRelease; break; - default: - break; - } - return coretype; -} - -/** - * Return the corresponding XI 1.x type for the given event or 0 if no - * equivalent exists. - */ -int -GetXIType(InternalEvent *event) -{ - int xitype = 0; - switch(event->any.type) - { - case ET_Motion: xitype = DeviceMotionNotify; break; - case ET_ButtonPress: xitype = DeviceButtonPress; break; - case ET_ButtonRelease: xitype = DeviceButtonRelease; break; - case ET_KeyPress: xitype = DeviceKeyPress; break; - case ET_KeyRelease: xitype = DeviceKeyRelease; break; - case ET_ProximityIn: xitype = ProximityIn; break; - case ET_ProximityOut: xitype = ProximityOut; break; - default: - break; - } - return xitype; -} - -/** - * Return the corresponding XI 2.x type for the given event or 0 if no - * equivalent exists. - */ -int -GetXI2Type(InternalEvent *event) -{ - int xi2type = 0; - - switch(event->any.type) - { - case ET_Motion: xi2type = XI_Motion; break; - case ET_ButtonPress: xi2type = XI_ButtonPress; break; - case ET_ButtonRelease: xi2type = XI_ButtonRelease; break; - case ET_KeyPress: xi2type = XI_KeyPress; break; - case ET_KeyRelease: xi2type = XI_KeyRelease; break; - case ET_Enter: xi2type = XI_Enter; break; - case ET_Leave: xi2type = XI_Leave; break; - case ET_Hierarchy: xi2type = XI_HierarchyChanged; break; - case ET_DeviceChanged: xi2type = XI_DeviceChanged; break; - case ET_RawKeyPress: xi2type = XI_RawKeyPress; break; - case ET_RawKeyRelease: xi2type = XI_RawKeyRelease; break; - case ET_RawButtonPress: xi2type = XI_RawButtonPress; break; - case ET_RawButtonRelease: xi2type = XI_RawButtonRelease; break; - case ET_RawMotion: xi2type = XI_RawMotion; break; - case ET_FocusIn: xi2type = XI_FocusIn; break; - case ET_FocusOut: xi2type = XI_FocusOut; break; - default: - break; - } - return xi2type; -} +/* + * 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. + * + */ + +/** + * @file eventconvert.c + * This file contains event conversion routines from InternalEvent to the + * matching protocol events. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "dix.h" +#include "inputstr.h" +#include "misc.h" +#include "eventstr.h" +#include "exglobals.h" +#include "eventconvert.h" +#include "xiquerydevice.h" +#include "xkbsrv.h" + + +static int countValuators(DeviceEvent *ev, int *first); +static int getValuatorEvents(DeviceEvent *ev, deviceValuator *xv); +static int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count); +static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce); +static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi); +static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi); + +/* Do not use, read comments below */ +BOOL EventIsKeyRepeat(xEvent *event); + +/** + * Hack to allow detectable autorepeat for core and XI1 events. + * The sequence number is unused until we send to the client and can be + * misused to store data. More or less, anyway. + * + * Do not use this. It may change any time without warning, eat your babies + * and piss on your cat. + */ +static void +EventSetKeyRepeatFlag(xEvent *event, BOOL on) +{ + event->u.u.sequenceNumber = on; +} + +/** + * Check if the event was marked as a repeat event before. + * NOTE: This is a nasty hack and should NOT be used by anyone else but + * TryClientEvents. + */ +BOOL +EventIsKeyRepeat(xEvent *event) +{ + return !!event->u.u.sequenceNumber; +} + +/** + * Convert the given event to the respective core event. + * + * Return values: + * Success ... core contains the matching core event. + * BadValue .. One or more values in the internal event are invalid. + * BadMatch .. The event has no core equivalent. + * + * @param[in] event The event to convert into a core event. + * @param[in] core The memory location to store the core event at. + * @return Success or the matching error code. + */ +int +EventToCore(InternalEvent *event, xEvent **core_out, int *count_out) +{ + xEvent *core = NULL; + int count = 0; + int ret = BadImplementation; + + switch(event->any.type) + { + case ET_Motion: + { + DeviceEvent *e = &event->device_event; + /* Don't create core motion event if neither x nor y are + * present */ + if (!BitIsOn(e->valuators.mask, 0) && + !BitIsOn(e->valuators.mask, 1)) + { + ret = BadMatch; + goto out; + } + } + /* fallthrough */ + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_KeyPress: + case ET_KeyRelease: + { + DeviceEvent *e = &event->device_event; + + if (e->detail.key > 0xFF) + { + ret = BadMatch; + goto out; + } + + core = calloc(1, sizeof(*core)); + if (!core) + return BadAlloc; + count = 1; + core->u.u.type = e->type - ET_KeyPress + KeyPress; + core->u.u.detail = e->detail.key & 0xFF; + core->u.keyButtonPointer.time = e->time; + core->u.keyButtonPointer.rootX = e->root_x; + core->u.keyButtonPointer.rootY = e->root_y; + core->u.keyButtonPointer.state = e->corestate; + core->u.keyButtonPointer.root = e->root; + EventSetKeyRepeatFlag(core, + (e->type == ET_KeyPress && + e->key_repeat)); + ret = Success; + } + break; + case ET_ProximityIn: + case ET_ProximityOut: + case ET_RawKeyPress: + case ET_RawKeyRelease: + case ET_RawButtonPress: + case ET_RawButtonRelease: + case ET_RawMotion: + ret = BadMatch; + goto out; + default: + /* XXX: */ + ErrorF("[dix] EventToCore: Not implemented yet \n"); + ret = BadImplementation; + } + +out: + *core_out = core; + *count_out = count; + return ret; +} + +/** + * Convert the given event to the respective XI 1.x event and store it in + * xi. xi is allocated on demand and must be freed by the caller. + * count returns the number of events in xi. If count is 1, and the type of + * xi is GenericEvent, then xi may be larger than 32 bytes. + * + * Return values: + * Success ... core contains the matching core event. + * BadValue .. One or more values in the internal event are invalid. + * BadMatch .. The event has no XI equivalent. + * + * @param[in] ev The event to convert into an XI 1 event. + * @param[out] xi Future memory location for the XI event. + * @param[out] count Number of elements in xi. + * + * @return Success or the error code. + */ +int +EventToXI(InternalEvent *ev, xEvent **xi, int *count) +{ + switch (ev->any.type) + { + case ET_Motion: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ProximityIn: + case ET_ProximityOut: + return eventToKeyButtonPointer(&ev->device_event, xi, count); + case ET_DeviceChanged: + case ET_RawKeyPress: + case ET_RawKeyRelease: + case ET_RawButtonPress: + case ET_RawButtonRelease: + case ET_RawMotion: + *count = 0; + *xi = NULL; + return BadMatch; + default: + break; + } + + ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->any.type); + return BadImplementation; +} + +/** + * Convert the given event to the respective XI 2.x event and store it in xi. + * xi is allocated on demand and must be freed by the caller. + * + * Return values: + * Success ... core contains the matching core event. + * BadValue .. One or more values in the internal event are invalid. + * BadMatch .. The event has no XI2 equivalent. + * + * @param[in] ev The event to convert into an XI2 event + * @param[out] xi Future memory location for the XI2 event. + * + * @return Success or the error code. + */ +int +EventToXI2(InternalEvent *ev, xEvent **xi) +{ + switch (ev->any.type) + { + /* Enter/FocusIn are for grabs. We don't need an actual event, since + * the real events delivered are triggered elsewhere */ + case ET_Enter: + case ET_FocusIn: + *xi = NULL; + return Success; + case ET_Motion: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_KeyPress: + case ET_KeyRelease: + return eventToDeviceEvent(&ev->device_event, xi); + case ET_ProximityIn: + case ET_ProximityOut: + *xi = NULL; + return BadMatch; + case ET_DeviceChanged: + return eventToDeviceChanged(&ev->changed_event, xi); + case ET_RawKeyPress: + case ET_RawKeyRelease: + case ET_RawButtonPress: + case ET_RawButtonRelease: + case ET_RawMotion: + return eventToRawEvent(&ev->raw_event, xi); + default: + break; + } + + ErrorF("[dix] EventToXI2: Not implemented for %d \n", ev->any.type); + return BadImplementation; +} + +static int +eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count) +{ + int num_events; + int first; /* dummy */ + deviceKeyButtonPointer *kbp; + + /* Sorry, XI 1.x protocol restrictions. */ + if (ev->detail.button > 0xFF || ev->deviceid >= 0x80) + { + *count = 0; + return Success; + } + + num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */ + if (num_events <= 0) + { + switch (ev->type) + { + case ET_KeyPress: + case ET_KeyRelease: + case ET_ButtonPress: + case ET_ButtonRelease: + /* no axes is ok */ + break; + case ET_Motion: + case ET_ProximityIn: + case ET_ProximityOut: + *count = 0; + return BadMatch; + default: + *count = 0; + return BadImplementation; + } + } + + num_events++; /* the actual event event */ + + *xi = calloc(num_events, sizeof(xEvent)); + if (!(*xi)) + { + return BadAlloc; + } + + kbp = (deviceKeyButtonPointer*)(*xi); + kbp->detail = ev->detail.button; + kbp->time = ev->time; + kbp->root = ev->root; + kbp->root_x = ev->root_x; + kbp->root_y = ev->root_y; + kbp->deviceid = ev->deviceid; + kbp->state = ev->corestate; + EventSetKeyRepeatFlag((xEvent*)kbp, + (ev->type == ET_KeyPress && ev->key_repeat)); + + if (num_events > 1) + kbp->deviceid |= MORE_EVENTS; + + switch(ev->type) + { + case ET_Motion: kbp->type = DeviceMotionNotify; break; + case ET_ButtonPress: kbp->type = DeviceButtonPress; break; + case ET_ButtonRelease: kbp->type = DeviceButtonRelease; break; + case ET_KeyPress: kbp->type = DeviceKeyPress; break; + case ET_KeyRelease: kbp->type = DeviceKeyRelease; break; + case ET_ProximityIn: kbp->type = ProximityIn; break; + case ET_ProximityOut: kbp->type = ProximityOut; break; + default: + break; + } + + if (num_events > 1) + { + getValuatorEvents(ev, (deviceValuator*)(kbp + 1)); + } + + *count = num_events; + return Success; +} + + +/** + * Set first to the first valuator in the event ev and return the number of + * valuators from first to the last set valuator. + */ +static int +countValuators(DeviceEvent *ev, int *first) +{ + int first_valuator = -1, last_valuator = -1, num_valuators = 0; + int i; + + for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) + { + if (BitIsOn(ev->valuators.mask, i)) + { + if (first_valuator == -1) + first_valuator = i; + last_valuator = i; + } + } + + if (first_valuator != -1) + { + num_valuators = last_valuator - first_valuator + 1; + *first = first_valuator; + } + + return num_valuators; +} + +static int +getValuatorEvents(DeviceEvent *ev, deviceValuator *xv) +{ + int i; + int state = 0; + int first_valuator, num_valuators; + + + num_valuators = countValuators(ev, &first_valuator); + if (num_valuators > 0) + { + DeviceIntPtr dev = NULL; + dixLookupDevice(&dev, ev->deviceid, serverClient, DixUseAccess); + /* State needs to be assembled BEFORE the device is updated. */ + state = (dev && dev->key) ? XkbStateFieldFromRec(&dev->key->xkbInfo->state) : 0; + state |= (dev && dev->button) ? (dev->button->state) : 0; + } + + /* FIXME: non-continuous valuator data in internal events*/ + for (i = 0; i < num_valuators; i += 6, xv++) { + xv->type = DeviceValuator; + xv->first_valuator = first_valuator + i; + xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i); + xv->deviceid = ev->deviceid; + xv->device_state = state; + switch (xv->num_valuators) { + case 6: + xv->valuator5 = ev->valuators.data[xv->first_valuator + 5]; + case 5: + xv->valuator4 = ev->valuators.data[xv->first_valuator + 4]; + case 4: + xv->valuator3 = ev->valuators.data[xv->first_valuator + 3]; + case 3: + xv->valuator2 = ev->valuators.data[xv->first_valuator + 2]; + case 2: + xv->valuator1 = ev->valuators.data[xv->first_valuator + 1]; + case 1: + xv->valuator0 = ev->valuators.data[xv->first_valuator + 0]; + } + + if (i + 6 < num_valuators) + xv->deviceid |= MORE_EVENTS; + } + + return (num_valuators + 5) / 6; +} + + +static int +appendKeyInfo(DeviceChangedEvent *dce, xXIKeyInfo* info) +{ + uint32_t *kc; + int i; + + info->type = XIKeyClass; + info->num_keycodes = dce->keys.max_keycode - dce->keys.min_keycode + 1; + info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes; + info->sourceid = dce->sourceid; + + kc = (uint32_t*)&info[1]; + for (i = 0; i < info->num_keycodes; i++) + *kc++ = i + dce->keys.min_keycode; + + return info->length * 4; +} + +static int +appendButtonInfo(DeviceChangedEvent *dce, xXIButtonInfo *info) +{ + unsigned char *bits; + int mask_len; + + mask_len = bytes_to_int32(bits_to_bytes(dce->buttons.num_buttons)); + + info->type = XIButtonClass; + info->num_buttons = dce->buttons.num_buttons; + info->length = bytes_to_int32(sizeof(xXIButtonInfo)) + + info->num_buttons + mask_len; + info->sourceid = dce->sourceid; + + bits = (unsigned char*)&info[1]; + memset(bits, 0, mask_len * 4); + /* FIXME: is_down? */ + + bits += mask_len * 4; + memcpy(bits, dce->buttons.names, dce->buttons.num_buttons * sizeof(Atom)); + + return info->length * 4; +} + +static int +appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumber) +{ + info->type = XIValuatorClass; + info->length = sizeof(xXIValuatorInfo)/4; + info->label = dce->valuators[axisnumber].name; + info->min.integral = dce->valuators[axisnumber].min; + info->min.frac = 0; + info->max.integral = dce->valuators[axisnumber].max; + info->max.frac = 0; + /* FIXME: value */ + info->value.integral = 0; + info->value.frac = 0; + info->resolution = dce->valuators[axisnumber].resolution; + info->number = axisnumber; + info->mode = dce->valuators[axisnumber].mode; + info->sourceid = dce->sourceid; + + return info->length * 4; +} + +static int +eventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi) +{ + xXIDeviceChangedEvent *dcce; + int len = sizeof(xXIDeviceChangedEvent); + int nkeys; + char *ptr; + + if (dce->buttons.num_buttons) + { + len += sizeof(xXIButtonInfo); + len += dce->buttons.num_buttons * sizeof(Atom); /* button names */ + len += pad_to_int32(bits_to_bytes(dce->buttons.num_buttons)); + } + if (dce->num_valuators) + len += sizeof(xXIValuatorInfo) * dce->num_valuators; + + nkeys = (dce->keys.max_keycode > 0) ? + dce->keys.max_keycode - dce->keys.min_keycode + 1 : 0; + if (nkeys > 0) + { + len += sizeof(xXIKeyInfo); + len += sizeof(CARD32) * nkeys; /* keycodes */ + } + + dcce = calloc(1, len); + if (!dcce) + { + ErrorF("[Xi] BadAlloc in SendDeviceChangedEvent.\n"); + return BadAlloc; + } + + dcce->type = GenericEvent; + dcce->extension = IReqCode; + dcce->evtype = XI_DeviceChanged; + dcce->time = dce->time; + dcce->deviceid = dce->deviceid; + dcce->sourceid = dce->sourceid; + dcce->reason = (dce->flags & DEVCHANGE_DEVICE_CHANGE) ? XIDeviceChange : XISlaveSwitch; + dcce->num_classes = 0; + dcce->length = bytes_to_int32(len - sizeof(xEvent)); + + ptr = (char*)&dcce[1]; + if (dce->buttons.num_buttons) + { + dcce->num_classes++; + ptr += appendButtonInfo(dce, (xXIButtonInfo*)ptr); + } + + if (nkeys) + { + dcce->num_classes++; + ptr += appendKeyInfo(dce, (xXIKeyInfo*)ptr); + } + + if (dce->num_valuators) + { + int i; + + dcce->num_classes += dce->num_valuators; + for (i = 0; i < dce->num_valuators; i++) + ptr += appendValuatorInfo(dce, (xXIValuatorInfo*)ptr, i); + } + + *xi = (xEvent*)dcce; + + return Success; +} + +static int count_bits(unsigned char* ptr, int len) +{ + int bits = 0; + unsigned int i; + unsigned char x; + + for (i = 0; i < len; i++) + { + x = ptr[i]; + while(x > 0) + { + bits += (x & 0x1); + x >>= 1; + } + } + return bits; +} + +static int +eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) +{ + int len = sizeof(xXIDeviceEvent); + xXIDeviceEvent *xde; + int i, btlen, vallen; + char *ptr; + FP3232 *axisval; + + /* FIXME: this should just send the buttons we have, not MAX_BUTTONs. Same + * with MAX_VALUATORS below */ + /* btlen is in 4 byte units */ + btlen = bytes_to_int32(bits_to_bytes(MAX_BUTTONS)); + len += btlen * 4; /* buttonmask len */ + + + vallen = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)/sizeof(ev->valuators.mask[0])); + len += vallen * 2 * sizeof(uint32_t); /* axisvalues */ + vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); + len += vallen * 4; /* valuators mask */ + + *xi = calloc(1, len); + xde = (xXIDeviceEvent*)*xi; + xde->type = GenericEvent; + xde->extension = IReqCode; + xde->evtype = GetXI2Type((InternalEvent*)ev); + xde->time = ev->time; + xde->length = bytes_to_int32(len - sizeof(xEvent)); + xde->detail = ev->detail.button; + xde->root = ev->root; + xde->buttons_len = btlen; + xde->valuators_len = vallen; + xde->deviceid = ev->deviceid; + xde->sourceid = ev->sourceid; + xde->root_x = FP1616(ev->root_x, ev->root_x_frac); + xde->root_y = FP1616(ev->root_y, ev->root_y_frac); + + if (ev->key_repeat) + xde->flags |= XIKeyRepeat; + + xde->mods.base_mods = ev->mods.base; + xde->mods.latched_mods = ev->mods.latched; + xde->mods.locked_mods = ev->mods.locked; + xde->mods.effective_mods = ev->mods.effective; + + xde->group.base_group = ev->group.base; + xde->group.latched_group = ev->group.latched; + xde->group.locked_group = ev->group.locked; + xde->group.effective_group = ev->group.effective; + + ptr = (char*)&xde[1]; + for (i = 0; i < sizeof(ev->buttons) * 8; i++) + { + if (BitIsOn(ev->buttons, i)) + SetBit(ptr, i); + } + + ptr += xde->buttons_len * 4; + axisval = (FP3232*)(ptr + xde->valuators_len * 4); + for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) + { + if (BitIsOn(ev->valuators.mask, i)) + { + SetBit(ptr, i); + axisval->integral = ev->valuators.data[i]; + axisval->frac = ev->valuators.data_frac[i]; + axisval++; + } + } + + return Success; +} + +static int +eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) +{ + xXIRawEvent* raw; + int vallen, nvals; + int i, len = sizeof(xXIRawEvent); + char *ptr; + FP3232 *axisval; + + nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)); + len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once + raw, once processed */ + vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); + len += vallen * 4; /* valuators mask */ + + *xi = calloc(1, len); + raw = (xXIRawEvent*)*xi; + raw->type = GenericEvent; + raw->extension = IReqCode; + raw->evtype = GetXI2Type((InternalEvent*)ev); + raw->time = ev->time; + raw->length = bytes_to_int32(len - sizeof(xEvent)); + raw->detail = ev->detail.button; + raw->deviceid = ev->deviceid; + raw->valuators_len = vallen; + + ptr = (char*)&raw[1]; + axisval = (FP3232*)(ptr + raw->valuators_len * 4); + for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) + { + if (BitIsOn(ev->valuators.mask, i)) + { + SetBit(ptr, i); + axisval->integral = ev->valuators.data[i]; + axisval->frac = ev->valuators.data_frac[i]; + (axisval + nvals)->integral = ev->valuators.data_raw[i]; + (axisval + nvals)->frac = ev->valuators.data_raw_frac[i]; + axisval++; + } + } + + return Success; +} + +/** + * Return the corresponding core type for the given event or 0 if no core + * equivalent exists. + */ +int +GetCoreType(InternalEvent *event) +{ + int coretype = 0; + switch(event->any.type) + { + case ET_Motion: coretype = MotionNotify; break; + case ET_ButtonPress: coretype = ButtonPress; break; + case ET_ButtonRelease: coretype = ButtonRelease; break; + case ET_KeyPress: coretype = KeyPress; break; + case ET_KeyRelease: coretype = KeyRelease; break; + default: + break; + } + return coretype; +} + +/** + * Return the corresponding XI 1.x type for the given event or 0 if no + * equivalent exists. + */ +int +GetXIType(InternalEvent *event) +{ + int xitype = 0; + switch(event->any.type) + { + case ET_Motion: xitype = DeviceMotionNotify; break; + case ET_ButtonPress: xitype = DeviceButtonPress; break; + case ET_ButtonRelease: xitype = DeviceButtonRelease; break; + case ET_KeyPress: xitype = DeviceKeyPress; break; + case ET_KeyRelease: xitype = DeviceKeyRelease; break; + case ET_ProximityIn: xitype = ProximityIn; break; + case ET_ProximityOut: xitype = ProximityOut; break; + default: + break; + } + return xitype; +} + +/** + * Return the corresponding XI 2.x type for the given event or 0 if no + * equivalent exists. + */ +int +GetXI2Type(InternalEvent *event) +{ + int xi2type = 0; + + switch(event->any.type) + { + case ET_Motion: xi2type = XI_Motion; break; + case ET_ButtonPress: xi2type = XI_ButtonPress; break; + case ET_ButtonRelease: xi2type = XI_ButtonRelease; break; + case ET_KeyPress: xi2type = XI_KeyPress; break; + case ET_KeyRelease: xi2type = XI_KeyRelease; break; + case ET_Enter: xi2type = XI_Enter; break; + case ET_Leave: xi2type = XI_Leave; break; + case ET_Hierarchy: xi2type = XI_HierarchyChanged; break; + case ET_DeviceChanged: xi2type = XI_DeviceChanged; break; + case ET_RawKeyPress: xi2type = XI_RawKeyPress; break; + case ET_RawKeyRelease: xi2type = XI_RawKeyRelease; break; + case ET_RawButtonPress: xi2type = XI_RawButtonPress; break; + case ET_RawButtonRelease: xi2type = XI_RawButtonRelease; break; + case ET_RawMotion: xi2type = XI_RawMotion; break; + case ET_FocusIn: xi2type = XI_FocusIn; break; + case ET_FocusOut: xi2type = XI_FocusOut; break; + default: + break; + } + return xi2type; +} diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c index 5b8e3798d..2361810a0 100644 --- a/xorg-server/dix/getevents.c +++ b/xorg-server/dix/getevents.c @@ -1,1324 +1,1314 @@ -/* - * Copyright © 2006 Nokia Corporation - * Copyright © 2006-2007 Daniel Stone - * Copyright © 2008 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. - * - * Authors: Daniel Stone - * Peter Hutterer - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "misc.h" -#include "resource.h" -#include "inputstr.h" -#include "scrnintstr.h" -#include "cursorstr.h" -#include "dixstruct.h" -#include "globals.h" -#include "dixevents.h" -#include "mipointer.h" -#include "eventstr.h" -#include "eventconvert.h" -#include "inpututils.h" - -#include -#include "xkbsrv.h" - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif - -#include -#include -#include -#include "exglobals.h" -#include "exevents.h" -#include "exglobals.h" -#include "extnsionst.h" -#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */ - -/* Number of motion history events to store. */ -#define MOTION_HISTORY_SIZE 256 - -/* InputEventList is the container list for all input events generated by the - * DDX. The DDX is expected to call GetEventList() and then pass the list into - * Get{Pointer|Keyboard}Events. - */ -EventListPtr InputEventList = NULL; -int InputEventListLen = 0; - -int -GetEventList(EventListPtr* list) -{ - *list = InputEventList; - return InputEventListLen; -} - -/** - * Pick some arbitrary size for Xi motion history. - */ -int -GetMotionHistorySize(void) -{ - return MOTION_HISTORY_SIZE; -} - -void -set_button_down(DeviceIntPtr pDev, int button, int type) -{ - if (type == BUTTON_PROCESSED) - SetBit(pDev->button->down, button); - else - SetBit(pDev->button->postdown, button); -} - -void -set_button_up(DeviceIntPtr pDev, int button, int type) -{ - if (type == BUTTON_PROCESSED) - ClearBit(pDev->button->down, button); - else - ClearBit(pDev->button->postdown, button); -} - -Bool -button_is_down(DeviceIntPtr pDev, int button, int type) -{ - Bool ret = FALSE; - - if (type & BUTTON_PROCESSED) - ret = ret || BitIsOn(pDev->button->down, button); - if (type & BUTTON_POSTED) - ret = ret || BitIsOn(pDev->button->postdown, button); - - return ret; -} - -void -set_key_down(DeviceIntPtr pDev, int key_code, int type) -{ - if (type == KEY_PROCESSED) - SetBit(pDev->key->down, key_code); - else - SetBit(pDev->key->postdown, key_code); -} - -void -set_key_up(DeviceIntPtr pDev, int key_code, int type) -{ - if (type == KEY_PROCESSED) - ClearBit(pDev->key->down, key_code); - else - ClearBit(pDev->key->postdown, key_code); -} - -Bool -key_is_down(DeviceIntPtr pDev, int key_code, int type) -{ - Bool ret = FALSE; - - if (type & KEY_PROCESSED) - ret = ret || BitIsOn(pDev->key->down, key_code); - if (type & KEY_POSTED) - ret = ret || BitIsOn(pDev->key->postdown, key_code); - - return ret; -} - -static Bool -key_autorepeats(DeviceIntPtr pDev, int key_code) -{ - return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] & - (1 << (key_code & 7))); -} - -static void -init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms) -{ - memset(event, 0, sizeof(DeviceEvent)); - event->header = ET_Internal; - event->length = sizeof(DeviceEvent); - event->time = ms; - event->deviceid = dev->id; - event->sourceid = dev->id; -} - -static void -init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail) -{ - memset(event, 0, sizeof(RawDeviceEvent)); - event->header = ET_Internal; - event->length = sizeof(RawDeviceEvent); - event->type = ET_RawKeyPress - ET_KeyPress + type; - event->time = ms; - event->deviceid = dev->id; - event->sourceid = dev->id; - event->detail.button = detail; -} - -static void -set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data) -{ - int i; - - for (i = 0; i < valuator_mask_size(mask); i++) - { - if (valuator_mask_isset(mask, i)) - { - SetBit(event->valuators.mask, i); - data[i] = valuator_mask_get(mask, i); - } - } -} - - -static void -set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask) -{ - int i; - - for (i = 0; i < valuator_mask_size(mask); i++) - { - if (valuator_mask_isset(mask, i)) - { - SetBit(event->valuators.mask, i); - if (valuator_get_mode(dev, i) == Absolute) - SetBit(event->valuators.mode, i); - event->valuators.data[i] = valuator_mask_get(mask, i); - event->valuators.data_frac[i] = - dev->last.remainder[i] * (1 << 16) * (1 << 16); - } - } -} - -void -CreateClassesChangedEvent(EventList* event, - DeviceIntPtr master, - DeviceIntPtr slave, - int type) -{ - int i; - DeviceChangedEvent *dce; - CARD32 ms = GetTimeInMillis(); - - dce = (DeviceChangedEvent*)event->event; - memset(dce, 0, sizeof(DeviceChangedEvent)); - dce->deviceid = slave->id; - dce->masterid = master->id; - dce->header = ET_Internal; - dce->length = sizeof(DeviceChangedEvent); - dce->type = ET_DeviceChanged; - dce->time = ms; - dce->flags = type; - dce->flags |= DEVCHANGE_SLAVE_SWITCH; - dce->sourceid = slave->id; - - if (slave->button) - { - dce->buttons.num_buttons = slave->button->numButtons; - for (i = 0; i < dce->buttons.num_buttons; i++) - dce->buttons.names[i] = slave->button->labels[i]; - } - if (slave->valuator) - { - dce->num_valuators = slave->valuator->numAxes; - for (i = 0; i < dce->num_valuators; i++) - { - dce->valuators[i].min = slave->valuator->axes[i].min_value; - dce->valuators[i].max = slave->valuator->axes[i].max_value; - dce->valuators[i].resolution = slave->valuator->axes[i].resolution; - dce->valuators[i].mode = slave->valuator->axes[i].mode; - dce->valuators[i].name = slave->valuator->axes[i].label; - } - } - if (slave->key) - { - dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code; - dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code; - } -} - -/** - * Rescale the coord between the two axis ranges. - */ -static int -rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to, - int defmax) -{ - int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return; - float value; - - if(from && from->min_value < from->max_value) { - fmin = from->min_value; - fmax = from->max_value; - } - if(to && to->min_value < to->max_value) { - tmin = to->min_value; - tmax = to->max_value; - } - - if(fmin == tmin && fmax == tmax) { - if (remainder_return) - *remainder_return = remainder; - return coord; - } - - if(fmax == fmin) { /* avoid division by 0 */ - if (remainder_return) - *remainder_return = 0.0; - return 0; - } - - value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin; - coord_return = lroundf(value); - if (remainder_return) - *remainder_return = value - coord_return; - return coord_return; -} - -/** - * Update all coordinates when changing to a different SD - * to ensure that relative reporting will work as expected - * without loss of precision. - * - * pDev->last.valuators will be in absolute device coordinates after this - * function. - */ -static void -updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) -{ - ScreenPtr scr = miPointerGetScreen(pDev); - int i; - DeviceIntPtr lastSlave; - - /* master->last.valuators[0]/[1] is in screen coords and the actual - * position of the pointer */ - pDev->last.valuators[0] = master->last.valuators[0]; - pDev->last.valuators[1] = master->last.valuators[1]; - - if (!pDev->valuator) - return; - - /* scale back to device coordinates */ - if(pDev->valuator->numAxes > 0) - pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0], - &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width); - if(pDev->valuator->numAxes > 1) - pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1], - &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height); - - /* calculate the other axis as well based on info from the old - * slave-device. If the old slave had less axes than this one, - * last.valuators is reset to 0. - */ - if ((lastSlave = master->last.slave) && lastSlave->valuator) { - for (i = 2; i < pDev->valuator->numAxes; i++) { - if (i >= lastSlave->valuator->numAxes) - pDev->last.valuators[i] = 0; - else - pDev->last.valuators[i] = - rescaleValuatorAxis(pDev->last.valuators[i], - pDev->last.remainder[i], - &pDev->last.remainder[i], - lastSlave->valuator->axes + i, - pDev->valuator->axes + i, 0); - } - } - -} - -/** - * Allocate the motion history buffer. - */ -void -AllocateMotionHistory(DeviceIntPtr pDev) -{ - int size; - free(pDev->valuator->motion); - - if (pDev->valuator->numMotionEvents < 1) - return; - - /* An MD must have a motion history size large enough to keep all - * potential valuators, plus the respective range of the valuators. - * 3 * INT32 for (min_val, max_val, curr_val)) - */ - if (IsMaster(pDev)) - size = sizeof(INT32) * 3 * MAX_VALUATORS; - else { - ValuatorClassPtr v = pDev->valuator; - int numAxes; - /* XI1 doesn't understand mixed mode devices */ - for (numAxes = 0; numAxes < v->numAxes; numAxes++) - if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0)) - break; - size = sizeof(INT32) * numAxes; - } - - size += sizeof(Time); - - pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size); - pDev->valuator->first_motion = 0; - pDev->valuator->last_motion = 0; - if (!pDev->valuator->motion) - ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n", - pDev->name, size * pDev->valuator->numMotionEvents); -} - -/** - * Dump the motion history between start and stop into the supplied buffer. - * Only records the event for a given screen in theory, but in practice, we - * sort of ignore this. - * - * If core is set, we only generate x/y, in INT16, scaled to screen coords. - */ -int -GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, - unsigned long stop, ScreenPtr pScreen, BOOL core) -{ - char *ibuff = NULL, *obuff; - int i = 0, ret = 0; - int j, coord; - Time current; - /* The size of a single motion event. */ - int size; - int dflt; - AxisInfo from, *to; /* for scaling */ - INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */ - INT16 *corebuf; - AxisInfo core_axis = {0}; - - if (!pDev->valuator || !pDev->valuator->numMotionEvents) - return 0; - - if (core && !pScreen) - return 0; - - if (IsMaster(pDev)) - size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time); - else - size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); - - *buff = malloc(size * pDev->valuator->numMotionEvents); - if (!(*buff)) - return 0; - obuff = (char *)*buff; - - for (i = pDev->valuator->first_motion; - i != pDev->valuator->last_motion; - i = (i + 1) % pDev->valuator->numMotionEvents) { - /* We index the input buffer by which element we're accessing, which - * is not monotonic, and the output buffer by how many events we've - * written so far. */ - ibuff = (char *) pDev->valuator->motion + (i * size); - memcpy(¤t, ibuff, sizeof(Time)); - - if (current > stop) { - return ret; - } - else if (current >= start) { - if (core) - { - memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ - - icbuf = (INT32*)(ibuff + sizeof(Time)); - corebuf = (INT16*)(obuff + sizeof(Time)); - - /* fetch x coordinate + range */ - memcpy(&from.min_value, icbuf++, sizeof(INT32)); - memcpy(&from.max_value, icbuf++, sizeof(INT32)); - memcpy(&coord, icbuf++, sizeof(INT32)); - - /* scale to screen coords */ - to = &core_axis; - to->max_value = pScreen->width; - coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width); - - memcpy(corebuf, &coord, sizeof(INT16)); - corebuf++; - - /* fetch y coordinate + range */ - memcpy(&from.min_value, icbuf++, sizeof(INT32)); - memcpy(&from.max_value, icbuf++, sizeof(INT32)); - memcpy(&coord, icbuf++, sizeof(INT32)); - - to->max_value = pScreen->height; - coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height); - memcpy(corebuf, &coord, sizeof(INT16)); - - } else if (IsMaster(pDev)) - { - memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ - - ocbuf = (INT32*)(obuff + sizeof(Time)); - icbuf = (INT32*)(ibuff + sizeof(Time)); - for (j = 0; j < MAX_VALUATORS; j++) - { - if (j >= pDev->valuator->numAxes) - break; - - /* fetch min/max/coordinate */ - memcpy(&from.min_value, icbuf++, sizeof(INT32)); - memcpy(&from.max_value, icbuf++, sizeof(INT32)); - memcpy(&coord, icbuf++, sizeof(INT32)); - - to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL; - - /* x/y scaled to screen if no range is present */ - if (j == 0 && (from.max_value < from.min_value)) - from.max_value = pScreen->width; - else if (j == 1 && (from.max_value < from.min_value)) - from.max_value = pScreen->height; - - if (j == 0 && (to->max_value < to->min_value)) - dflt = pScreen->width; - else if (j == 1 && (to->max_value < to->min_value)) - dflt = pScreen->height; - else - dflt = 0; - - /* scale from stored range into current range */ - coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0); - memcpy(ocbuf, &coord, sizeof(INT32)); - ocbuf++; - } - } else - memcpy(obuff, ibuff, size); - - /* don't advance by size here. size may be different to the - * actually written size if the MD has less valuators than MAX */ - if (core) - obuff += sizeof(INT32) + sizeof(Time); - else - obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); - ret++; - } - } - - return ret; -} - - -/** - * Update the motion history for a specific device, with the list of - * valuators. - * - * Layout of the history buffer: - * for SDs: [time] [val0] [val1] ... [valn] - * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn] - * - * For events that have some valuators unset: - * min_val == max_val == val == 0. - */ -static void -updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask, - int *valuators) -{ - char *buff = (char *) pDev->valuator->motion; - ValuatorClassPtr v; - int i; - - if (!pDev->valuator->numMotionEvents) - return; - - v = pDev->valuator; - if (IsMaster(pDev)) - { - buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) * - v->last_motion; - - memcpy(buff, &ms, sizeof(Time)); - buff += sizeof(Time); - - memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS); - - for (i = 0; i < v->numAxes; i++) - { - /* XI1 doesn't support mixed mode devices */ - if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0)) - break; - if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) - { - buff += 3 * sizeof(INT32); - continue; - } - memcpy(buff, &v->axes[i].min_value, sizeof(INT32)); - buff += sizeof(INT32); - memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); - buff += sizeof(INT32); - memcpy(buff, &valuators[i], sizeof(INT32)); - buff += sizeof(INT32); - } - } else - { - - buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * - pDev->valuator->last_motion; - - memcpy(buff, &ms, sizeof(Time)); - buff += sizeof(Time); - - memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes); - - for (i = 0; i < MAX_VALUATORS; i++) - { - if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) - { - buff += sizeof(INT32); - continue; - } - memcpy(buff, &valuators[i], sizeof(INT32)); - buff += sizeof(INT32); - } - } - - pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % - pDev->valuator->numMotionEvents; - /* If we're wrapping around, just keep the circular buffer going. */ - if (pDev->valuator->first_motion == pDev->valuator->last_motion) - pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) % - pDev->valuator->numMotionEvents; - - return; -} - - -/** - * Returns the maximum number of events GetKeyboardEvents, - * GetKeyboardValuatorEvents, and GetPointerEvents will ever return. - * - * This MUST be absolutely constant, from init until exit. - */ -int -GetMaximumEventsNum(void) { - /* One raw event - * One device event - * One possible device changed event - */ - return 3; -} - - -/** - * Clip an axis to its bounds, which are declared in the call to - * InitValuatorAxisClassStruct. - */ -static void -clipAxis(DeviceIntPtr pDev, int axisNum, int *val) -{ - AxisInfoPtr axis; - - if (axisNum >= pDev->valuator->numAxes) - return; - - axis = pDev->valuator->axes + axisNum; - - /* If a value range is defined, clip. If not, do nothing */ - if (axis->max_value <= axis->min_value) - return; - - if (*val < axis->min_value) - *val = axis->min_value; - if (*val > axis->max_value) - *val = axis->max_value; -} - -/** - * Clip every axis in the list of valuators to its bounds. - */ -static void -clipValuators(DeviceIntPtr pDev, ValuatorMask *mask) -{ - int i; - - for (i = 0; i < valuator_mask_size(mask); i++) - if (valuator_mask_isset(mask, i)) - { - int val = valuator_mask_get(mask, i); - clipAxis(pDev, i, &val); - valuator_mask_set(mask, i, val); - } -} - -/** - * Create the DCCE event (does not update the master's device state yet, this - * is done in the event processing). - * Pull in the coordinates from the MD if necessary. - * - * @param events Pointer to a pre-allocated event list. - * @param dev The slave device that generated an event. - * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT - * @param num_events The current number of events, returns the number of - * events if a DCCE was generated. - * @return The updated @events pointer. - */ -EventListPtr -UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events) -{ - DeviceIntPtr master; - - master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : MASTER_KEYBOARD); - - if (master && master->last.slave != dev) - { - CreateClassesChangedEvent(events, master, dev, type); - if (IsPointerDevice(master)) - { - updateSlaveDeviceCoords(master, dev); - master->last.numValuators = dev->last.numValuators; - } - master->last.slave = dev; - (*num_events)++; - events++; - } - return events; -} - -/** - * Move the device's pointer to the position given in the valuators. - * - * @param dev The device which's pointer is to be moved. - * @param x Returns the x position of the pointer after the move. - * @param y Returns the y position of the pointer after the move. - * @param mask Bit mask of valid valuators. - * @param valuators Valuator data for each axis between @first and - * @first+@num. - */ -static void -moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) -{ - int i; - - if (valuator_mask_isset(mask, 0)) - *x = valuator_mask_get(mask, 0); - else - *x = dev->last.valuators[0]; - - if (valuator_mask_isset(mask, 1)) - *y = valuator_mask_get(mask, 1); - else - *y = dev->last.valuators[1]; - - clipAxis(dev, 0, x); - clipAxis(dev, 1, y); - - for (i = 2; i < valuator_mask_size(mask); i++) - { - if (valuator_mask_isset(mask, i)) - { - dev->last.valuators[i] = valuator_mask_get(mask, i); - clipAxis(dev, i, &dev->last.valuators[i]); - } - } -} - -/** - * Move the device's pointer by the values given in @valuators. - * - * @param dev The device which's pointer is to be moved. - * @param x Returns the x position of the pointer after the move. - * @param y Returns the y position of the pointer after the move. - * @param mask Bit mask of valid valuators. - * @param valuators Valuator data for each axis between @first and - * @first+@num. - */ -static void -moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) -{ - int i; - - *x = dev->last.valuators[0]; - *y = dev->last.valuators[1]; - - if (valuator_mask_isset(mask, 0)) - *x += valuator_mask_get(mask, 0); - - if (valuator_mask_isset(mask, 1)) - *y += valuator_mask_get(mask, 1); - - /* if attached, clip both x and y to the defined limits (usually - * co-ord space limit). If it is attached, we need x/y to go over the - * limits to be able to change screens. */ - if(dev->valuator && IsMaster(dev) || !IsFloating(dev)) { - if (valuator_get_mode(dev, 0) == Absolute) - clipAxis(dev, 0, x); - if (valuator_get_mode(dev, 1) == Absolute) - clipAxis(dev, 1, y); - } - - /* calc other axes, clip, drop back into valuators */ - for (i = 2; i < valuator_mask_size(mask); i++) - { - if (valuator_mask_isset(mask, i)) - { - dev->last.valuators[i] += valuator_mask_get(mask, i); - if (valuator_get_mode(dev, i) == Absolute) - clipAxis(dev, i, &dev->last.valuators[i]); - valuator_mask_set(mask, i, dev->last.valuators[i]); - } - } -} - -/** - * Accelerate the data in valuators based on the device's acceleration scheme. - * - * @param dev The device which's pointer is to be moved. - * @param first The first valuator in @valuators - * @param num Total number of valuators in @valuators. - * @param valuators Valuator data for each axis between @first and - * @first+@num. - * @param ms Current time. - */ -static void -accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms) -{ - if (dev->valuator->accelScheme.AccelSchemeProc) - dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms); -} - -/** - * If we have HW cursors, this actually moves the visible sprite. If not, we - * just do all the screen crossing, etc. - * - * We scale from device to screen coordinates here, call - * miPointerSetPosition() and then scale back into device coordinates (if - * needed). miPSP will change x/y if the screen was crossed. - * - * @param dev The device to be moved. - * @param x Pointer to current x-axis value, may be modified. - * @param y Pointer to current y-axis value, may be modified. - * @param x_frac Fractional part of current x-axis value, may be modified. - * @param y_frac Fractional part of current y-axis value, may be modified. - * @param scr Screen the device's sprite is currently on. - * @param screenx Screen x coordinate the sprite is on after the update. - * @param screeny Screen y coordinate the sprite is on after the update. - * @param screenx_frac Fractional part of screen x coordinate, as above. - * @param screeny_frac Fractional part of screen y coordinate, as above. - */ -static void -positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac, - ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac) -{ - int old_screenx, old_screeny; - - /* scale x&y to screen */ - if (dev->valuator && dev->valuator->numAxes > 0) { - *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac, - dev->valuator->axes + 0, NULL, scr->width); - } else { - *screenx = dev->last.valuators[0]; - *screenx_frac = dev->last.remainder[0]; - } - - if (dev->valuator && dev->valuator->numAxes > 1) { - *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac, - dev->valuator->axes + 1, NULL, scr->height); - } else { - *screeny = dev->last.valuators[1]; - *screeny_frac = dev->last.remainder[1]; - } - - /* Hit the left screen edge? */ - if (*screenx <= 0 && *screenx_frac < 0.0f) - { - *screenx_frac = 0.0f; - x_frac = 0.0f; - } - if (*screeny <= 0 && *screeny_frac < 0.0f) - { - *screeny_frac = 0.0f; - y_frac = 0.0f; - } - - - old_screenx = *screenx; - old_screeny = *screeny; - /* This takes care of crossing screens for us, as well as clipping - * to the current screen. */ - miPointerSetPosition(dev, screenx, screeny); - - if(!IsMaster(dev) || !IsFloating(dev)) { - DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); - master->last.valuators[0] = *screenx; - master->last.valuators[1] = *screeny; - master->last.remainder[0] = *screenx_frac; - master->last.remainder[1] = *screeny_frac; - } - - if (dev->valuator) - { - /* Crossed screen? Scale back to device coordiantes */ - if(*screenx != old_screenx) - { - scr = miPointerGetScreen(dev); - *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL, - dev->valuator->axes + 0, scr->width); - } - if(*screeny != old_screeny) - { - scr = miPointerGetScreen(dev); - *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL, - dev->valuator->axes + 1, scr->height); - } - } - - /* dropy x/y (device coordinates) back into valuators for next event */ - dev->last.valuators[0] = *x; - dev->last.valuators[1] = *y; - dev->last.remainder[0] = x_frac; - dev->last.remainder[1] = y_frac; -} - -/** - * Update the motion history for the device and (if appropriate) for its - * master device. - * @param dev Slave device to update. - * @param mask Bit mask of valid valuators to append to history. - * @param num Total number of valuators to append to history. - * @param ms Current time - */ -static void -updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms) -{ - if (!dev->valuator) - return; - - updateMotionHistory(dev, ms, mask, dev->last.valuators); - if(!IsMaster(dev) || !IsFloating(dev)) - { - DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); - updateMotionHistory(master, ms, mask, dev->last.valuators); - } -} - -/** - * 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. - * - * events is not NULL-terminated; the return value is the number of events. - * The DDX is responsible for allocating the event structure in the first - * place via GetMaximumEventsNum(), and for freeing it. - */ -int -GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, - int key_code, const ValuatorMask *mask_in) { - int num_events = 0; - CARD32 ms = 0; - DeviceEvent *event; - RawDeviceEvent *raw; - ValuatorMask mask; - - /* refuse events from disabled devices */ - if (!pDev->enabled) - return 0; - - if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed || - (type != KeyPress && type != KeyRelease) || - (key_code < 8 || key_code > 255)) - return 0; - - num_events = 1; - - events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events); - - /* Handle core repeating, via press/release/press/release. */ - if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) { - /* If autorepeating is disabled either globally or just for that key, - * or we have a modifier, don't generate a repeat event. */ - if (!pDev->kbdfeed->ctrl.autoRepeat || - !key_autorepeats(pDev, key_code) || - pDev->key->xkbInfo->desc->map->modmap[key_code]) - return 0; - } - - ms = GetTimeInMillis(); - - raw = (RawDeviceEvent*)events->event; - events++; - num_events++; - - valuator_mask_copy(&mask, mask_in); - - init_raw(pDev, raw, ms, type, key_code); - set_raw_valuators(raw, &mask, raw->valuators.data_raw); - - clipValuators(pDev, &mask); - - set_raw_valuators(raw, &mask, raw->valuators.data); - - event = (DeviceEvent*) events->event; - init_event(pDev, event, ms); - event->detail.key = key_code; - - if (type == KeyPress) { - event->type = ET_KeyPress; - set_key_down(pDev, key_code, KEY_POSTED); - } - else if (type == KeyRelease) { - event->type = ET_KeyRelease; - set_key_up(pDev, key_code, KEY_POSTED); - } - - clipValuators(pDev, &mask); - - set_valuators(pDev, event, &mask); - - return num_events; -} - -/** - * Initialize an event list and fill with 32 byte sized events. - * This event list is to be passed into GetPointerEvents() and - * GetKeyboardEvents(). - * - * @param num_events Number of elements in list. - */ -EventListPtr -InitEventList(int num_events) -{ - EventListPtr events; - int i; - - events = (EventListPtr)calloc(num_events, sizeof(EventList)); - if (!events) - return NULL; - - for (i = 0; i < num_events; i++) - { - events[i].evlen = sizeof(InternalEvent); - events[i].event = calloc(1, sizeof(InternalEvent)); - if (!events[i].event) - { - /* rollback */ - while(i--) - free(events[i].event); - free(events); - events = NULL; - break; - } - } - - return events; -} - -/** - * Free an event list. - * - * @param list The list to be freed. - * @param num_events Number of elements in list. - */ -void -FreeEventList(EventListPtr list, int num_events) -{ - if (!list) - return; - while(num_events--) - free(list[num_events].event); - free(list); -} - -static void -transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) -{ - struct pixman_f_vector p; - - /* p' = M * p in homogeneous coordinates */ - p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) : - dev->last.valuators[0]); - p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) : - dev->last.valuators[1]); - p.v[2] = 1.0; - - pixman_f_transform_point(&dev->transform, &p); - - if (lround(p.v[0]) != dev->last.valuators[0]) - valuator_mask_set(mask, 0, lround(p.v[0])); - if (lround(p.v[1]) != dev->last.valuators[1]) - valuator_mask_set(mask, 1, lround(p.v[1])); -} - -/** - * Generate a series of InternalEvents (filled into the EventList) - * representing pointer motion, or button presses. - * - * events is not NULL-terminated; the return value is the number of events. - * The DDX is responsible for allocating the event structure in the first - * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. - * - * In the generated events rootX/Y will be in absolute screen coords and - * the valuator information in the absolute or relative device coords. - * - * last.valuators[x] of the device is always in absolute device coords. - * last.valuators[x] of the master device is in absolute screen coords. - * - * master->last.valuators[x] for x > 2 is undefined. - */ -int -GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, - int flags, const ValuatorMask *mask_in) { - int num_events = 1; - CARD32 ms; - DeviceEvent *event; - RawDeviceEvent *raw; - int x = 0, y = 0, /* device coords */ - cx, cy; /* only screen coordinates */ - float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac; - ScreenPtr scr = miPointerGetScreen(pDev); - ValuatorMask mask; - - /* refuse events from disabled devices */ - if (!pDev->enabled) - return 0; - - if (!scr) - return 0; - - switch (type) - { - case MotionNotify: - if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) - return 0; - break; - case ButtonPress: - case ButtonRelease: - if (!pDev->button || !buttons) - return 0; - break; - default: - return 0; - } - - ms = GetTimeInMillis(); /* before pointer update to help precision */ - - events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); - - raw = (RawDeviceEvent*)events->event; - events++; - num_events++; - - valuator_mask_copy(&mask, mask_in); - - init_raw(pDev, raw, ms, type, buttons); - set_raw_valuators(raw, &mask, raw->valuators.data_raw); - - if (flags & POINTER_ABSOLUTE) - { - if (flags & POINTER_SCREEN) /* valuators are in screen coords */ - { - int scaled; - - if (valuator_mask_isset(&mask, 0)) - { - scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0), - 0.0, &x_frac, NULL, - pDev->valuator->axes + 0, - scr->width); - valuator_mask_set(&mask, 0, scaled); - } - if (valuator_mask_isset(&mask, 1)) - { - scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1), - 0.0, &y_frac, NULL, - pDev->valuator->axes + 1, - scr->height); - valuator_mask_set(&mask, 1, scaled); - } - } - - transformAbsolute(pDev, &mask); - moveAbsolute(pDev, &x, &y, &mask); - } else { - if (flags & POINTER_ACCELERATE) { - /* FIXME: Pointer acceleration only requires X and Y values. This - * should be converted to masked valuators. */ - int vals[2]; - vals[0] = valuator_mask_isset(&mask, 0) ? - valuator_mask_get(&mask, 0) : 0; - vals[1] = valuator_mask_isset(&mask, 1) ? - valuator_mask_get(&mask, 1) : 0; - accelPointer(pDev, 0, 2, vals, ms); - - if (valuator_mask_isset(&mask, 0)) - valuator_mask_set(&mask, 0, vals[0]); - if (valuator_mask_isset(&mask, 1)) - valuator_mask_set(&mask, 1, vals[1]); - - /* The pointer acceleration code modifies the fractional part - * in-place, so we need to extract this information first */ - x_frac = pDev->last.remainder[0]; - y_frac = pDev->last.remainder[1]; - } - moveRelative(pDev, &x, &y, &mask); - } - - set_raw_valuators(raw, &mask, raw->valuators.data); - - positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac); - updateHistory(pDev, &mask, ms); - - /* Update the valuators with the true value sent to the client*/ - if (valuator_mask_isset(&mask, 0)) - valuator_mask_set(&mask, 0, x); - if (valuator_mask_isset(&mask, 1)) - valuator_mask_set(&mask, 1, y); - - clipValuators(pDev, &mask); - - event = (DeviceEvent*) events->event; - init_event(pDev, event, ms); - - if (type == MotionNotify) { - event->type = ET_Motion; - event->detail.button = 0; - } - else { - if (type == ButtonPress) { - event->type = ET_ButtonPress; - set_button_down(pDev, buttons, BUTTON_POSTED); - } - else if (type == ButtonRelease) { - event->type = ET_ButtonRelease; - set_button_up(pDev, buttons, BUTTON_POSTED); - } - event->detail.button = buttons; - } - - event->root_x = cx; /* root_x/y always in screen coords */ - event->root_y = cy; - event->root_x_frac = cx_frac; - event->root_y_frac = cy_frac; - - set_valuators(pDev, event, &mask); - - return num_events; -} - - -/** - * Generate ProximityIn/ProximityOut InternalEvents, accompanied by - * valuators. - * - * events is not NULL-terminated; the return value is the number of events. - * The DDX is responsible for allocating the event structure in the first - * place via GetMaximumEventsNum(), and for freeing it. - */ -int -GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in) -{ - int num_events = 1, i; - DeviceEvent *event; - ValuatorMask mask; - - /* refuse events from disabled devices */ - if (!pDev->enabled) - return 0; - - /* Sanity checks. */ - if ((type != ProximityIn && type != ProximityOut) || !mask_in) - return 0; - if (!pDev->valuator) - return 0; - - valuator_mask_copy(&mask, mask_in); - - /* ignore relative axes for proximity. */ - for (i = 0; i < valuator_mask_size(&mask); i++) - { - if (valuator_mask_isset(&mask, i) && - valuator_get_mode(pDev, i) == Relative) - valuator_mask_unset(&mask, i); - } - - /* FIXME: posting proximity events with relative valuators only results - * in an empty event, EventToXI() will fail to convert → no event sent - * to client. */ - - events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); - - event = (DeviceEvent *) events->event; - init_event(pDev, event, GetTimeInMillis()); - event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; - - clipValuators(pDev, &mask); - - set_valuators(pDev, event, &mask); - - return num_events; -} - -/** - * Synthesize a single motion event for the core pointer. - * - * Used in cursor functions, e.g. when cursor confinement changes, and we need - * to shift the pointer to get it inside the new bounds. - */ -void -PostSyntheticMotion(DeviceIntPtr pDev, - int x, - int y, - int screen, - unsigned long time) -{ - DeviceEvent ev; - -#ifdef PANORAMIX - /* Translate back to the sprite screen since processInputProc - will translate from sprite screen to screen 0 upon reentry - to the DIX layer. */ - if (!noPanoramiXExtension) { - x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x; - y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y; - } -#endif - - memset(&ev, 0, sizeof(DeviceEvent)); - init_event(pDev, &ev, time); - ev.root_x = x; - ev.root_y = y; - ev.type = ET_Motion; - ev.time = time; - - /* FIXME: MD/SD considerations? */ - (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev); -} +/* + * Copyright © 2006 Nokia Corporation + * Copyright © 2006-2007 Daniel Stone + * Copyright © 2008 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. + * + * Authors: Daniel Stone + * Peter Hutterer + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "misc.h" +#include "resource.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "cursorstr.h" +#include "dixstruct.h" +#include "globals.h" +#include "dixevents.h" +#include "mipointer.h" +#include "eventstr.h" +#include "eventconvert.h" +#include "inpututils.h" + +#include +#include "xkbsrv.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include +#include +#include +#include "exglobals.h" +#include "exevents.h" +#include "exglobals.h" +#include "extnsionst.h" +#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */ + +/* Number of motion history events to store. */ +#define MOTION_HISTORY_SIZE 256 + +/* InputEventList is the container list for all input events generated by the + * DDX. The DDX is expected to call GetEventList() and then pass the list into + * Get{Pointer|Keyboard}Events. + */ +EventListPtr InputEventList = NULL; +int InputEventListLen = 0; + +int +GetEventList(EventListPtr* list) +{ + *list = InputEventList; + return InputEventListLen; +} + +/** + * Pick some arbitrary size for Xi motion history. + */ +int +GetMotionHistorySize(void) +{ + return MOTION_HISTORY_SIZE; +} + +void +set_button_down(DeviceIntPtr pDev, int button, int type) +{ + if (type == BUTTON_PROCESSED) + SetBit(pDev->button->down, button); + else + SetBit(pDev->button->postdown, button); +} + +void +set_button_up(DeviceIntPtr pDev, int button, int type) +{ + if (type == BUTTON_PROCESSED) + ClearBit(pDev->button->down, button); + else + ClearBit(pDev->button->postdown, button); +} + +Bool +button_is_down(DeviceIntPtr pDev, int button, int type) +{ + Bool ret = FALSE; + + if (type & BUTTON_PROCESSED) + ret = ret || BitIsOn(pDev->button->down, button); + if (type & BUTTON_POSTED) + ret = ret || BitIsOn(pDev->button->postdown, button); + + return ret; +} + +void +set_key_down(DeviceIntPtr pDev, int key_code, int type) +{ + if (type == KEY_PROCESSED) + SetBit(pDev->key->down, key_code); + else + SetBit(pDev->key->postdown, key_code); +} + +void +set_key_up(DeviceIntPtr pDev, int key_code, int type) +{ + if (type == KEY_PROCESSED) + ClearBit(pDev->key->down, key_code); + else + ClearBit(pDev->key->postdown, key_code); +} + +Bool +key_is_down(DeviceIntPtr pDev, int key_code, int type) +{ + Bool ret = FALSE; + + if (type & KEY_PROCESSED) + ret = ret || BitIsOn(pDev->key->down, key_code); + if (type & KEY_POSTED) + ret = ret || BitIsOn(pDev->key->postdown, key_code); + + return ret; +} + +static Bool +key_autorepeats(DeviceIntPtr pDev, int key_code) +{ + return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] & + (1 << (key_code & 7))); +} + +static void +init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms) +{ + memset(event, 0, sizeof(DeviceEvent)); + event->header = ET_Internal; + event->length = sizeof(DeviceEvent); + event->time = ms; + event->deviceid = dev->id; + event->sourceid = dev->id; +} + +static void +init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail) +{ + memset(event, 0, sizeof(RawDeviceEvent)); + event->header = ET_Internal; + event->length = sizeof(RawDeviceEvent); + event->type = ET_RawKeyPress - ET_KeyPress + type; + event->time = ms; + event->deviceid = dev->id; + event->sourceid = dev->id; + event->detail.button = detail; +} + +static void +set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data) +{ + int i; + + for (i = 0; i < valuator_mask_size(mask); i++) + { + if (valuator_mask_isset(mask, i)) + { + SetBit(event->valuators.mask, i); + data[i] = valuator_mask_get(mask, i); + } + } +} + + +static void +set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask) +{ + int i; + + for (i = 0; i < valuator_mask_size(mask); i++) + { + if (valuator_mask_isset(mask, i)) + { + SetBit(event->valuators.mask, i); + if (valuator_get_mode(dev, i) == Absolute) + SetBit(event->valuators.mode, i); + event->valuators.data[i] = valuator_mask_get(mask, i); + event->valuators.data_frac[i] = + dev->last.remainder[i] * (1 << 16) * (1 << 16); + } + } +} + +void +CreateClassesChangedEvent(EventList* event, + DeviceIntPtr master, + DeviceIntPtr slave, + int type) +{ + int i; + DeviceChangedEvent *dce; + CARD32 ms = GetTimeInMillis(); + + dce = (DeviceChangedEvent*)event->event; + memset(dce, 0, sizeof(DeviceChangedEvent)); + dce->deviceid = slave->id; + dce->masterid = master->id; + dce->header = ET_Internal; + dce->length = sizeof(DeviceChangedEvent); + dce->type = ET_DeviceChanged; + dce->time = ms; + dce->flags = type; + dce->flags |= DEVCHANGE_SLAVE_SWITCH; + dce->sourceid = slave->id; + + if (slave->button) + { + dce->buttons.num_buttons = slave->button->numButtons; + for (i = 0; i < dce->buttons.num_buttons; i++) + dce->buttons.names[i] = slave->button->labels[i]; + } + if (slave->valuator) + { + dce->num_valuators = slave->valuator->numAxes; + for (i = 0; i < dce->num_valuators; i++) + { + dce->valuators[i].min = slave->valuator->axes[i].min_value; + dce->valuators[i].max = slave->valuator->axes[i].max_value; + dce->valuators[i].resolution = slave->valuator->axes[i].resolution; + dce->valuators[i].mode = slave->valuator->axes[i].mode; + dce->valuators[i].name = slave->valuator->axes[i].label; + } + } + if (slave->key) + { + dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code; + dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code; + } +} + +/** + * Rescale the coord between the two axis ranges. + */ +static int +rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to, + int defmax) +{ + int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return; + float value; + + if(from && from->min_value < from->max_value) { + fmin = from->min_value; + fmax = from->max_value; + } + if(to && to->min_value < to->max_value) { + tmin = to->min_value; + tmax = to->max_value; + } + + if(fmin == tmin && fmax == tmax) { + if (remainder_return) + *remainder_return = remainder; + return coord; + } + + if(fmax == fmin) { /* avoid division by 0 */ + if (remainder_return) + *remainder_return = 0.0; + return 0; + } + + value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin; + coord_return = lroundf(value); + if (remainder_return) + *remainder_return = value - coord_return; + return coord_return; +} + +/** + * Update all coordinates when changing to a different SD + * to ensure that relative reporting will work as expected + * without loss of precision. + * + * pDev->last.valuators will be in absolute device coordinates after this + * function. + */ +static void +updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev) +{ + ScreenPtr scr = miPointerGetScreen(pDev); + int i; + DeviceIntPtr lastSlave; + + /* master->last.valuators[0]/[1] is in screen coords and the actual + * position of the pointer */ + pDev->last.valuators[0] = master->last.valuators[0]; + pDev->last.valuators[1] = master->last.valuators[1]; + + if (!pDev->valuator) + return; + + /* scale back to device coordinates */ + if(pDev->valuator->numAxes > 0) + pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0], + &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width); + if(pDev->valuator->numAxes > 1) + pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1], + &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height); + + /* calculate the other axis as well based on info from the old + * slave-device. If the old slave had less axes than this one, + * last.valuators is reset to 0. + */ + if ((lastSlave = master->last.slave) && lastSlave->valuator) { + for (i = 2; i < pDev->valuator->numAxes; i++) { + if (i >= lastSlave->valuator->numAxes) + pDev->last.valuators[i] = 0; + else + pDev->last.valuators[i] = + rescaleValuatorAxis(pDev->last.valuators[i], + pDev->last.remainder[i], + &pDev->last.remainder[i], + lastSlave->valuator->axes + i, + pDev->valuator->axes + i, 0); + } + } + +} + +/** + * Allocate the motion history buffer. + */ +void +AllocateMotionHistory(DeviceIntPtr pDev) +{ + int size; + free(pDev->valuator->motion); + + if (pDev->valuator->numMotionEvents < 1) + return; + + /* An MD must have a motion history size large enough to keep all + * potential valuators, plus the respective range of the valuators. + * 3 * INT32 for (min_val, max_val, curr_val)) + */ + if (IsMaster(pDev)) + size = sizeof(INT32) * 3 * MAX_VALUATORS; + else { + ValuatorClassPtr v = pDev->valuator; + int numAxes; + /* XI1 doesn't understand mixed mode devices */ + for (numAxes = 0; numAxes < v->numAxes; numAxes++) + if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0)) + break; + size = sizeof(INT32) * numAxes; + } + + size += sizeof(Time); + + pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size); + pDev->valuator->first_motion = 0; + pDev->valuator->last_motion = 0; + if (!pDev->valuator->motion) + ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n", + pDev->name, size * pDev->valuator->numMotionEvents); +} + +/** + * Dump the motion history between start and stop into the supplied buffer. + * Only records the event for a given screen in theory, but in practice, we + * sort of ignore this. + * + * If core is set, we only generate x/y, in INT16, scaled to screen coords. + */ +int +GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start, + unsigned long stop, ScreenPtr pScreen, BOOL core) +{ + char *ibuff = NULL, *obuff; + int i = 0, ret = 0; + int j, coord; + Time current; + /* The size of a single motion event. */ + int size; + int dflt; + AxisInfo from, *to; /* for scaling */ + INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */ + INT16 *corebuf; + AxisInfo core_axis = {0}; + + if (!pDev->valuator || !pDev->valuator->numMotionEvents) + return 0; + + if (core && !pScreen) + return 0; + + if (IsMaster(pDev)) + size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time); + else + size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); + + *buff = malloc(size * pDev->valuator->numMotionEvents); + if (!(*buff)) + return 0; + obuff = (char *)*buff; + + for (i = pDev->valuator->first_motion; + i != pDev->valuator->last_motion; + i = (i + 1) % pDev->valuator->numMotionEvents) { + /* We index the input buffer by which element we're accessing, which + * is not monotonic, and the output buffer by how many events we've + * written so far. */ + ibuff = (char *) pDev->valuator->motion + (i * size); + memcpy(¤t, ibuff, sizeof(Time)); + + if (current > stop) { + return ret; + } + else if (current >= start) { + if (core) + { + memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ + + icbuf = (INT32*)(ibuff + sizeof(Time)); + corebuf = (INT16*)(obuff + sizeof(Time)); + + /* fetch x coordinate + range */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + /* scale to screen coords */ + to = &core_axis; + to->max_value = pScreen->width; + coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width); + + memcpy(corebuf, &coord, sizeof(INT16)); + corebuf++; + + /* fetch y coordinate + range */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + to->max_value = pScreen->height; + coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height); + memcpy(corebuf, &coord, sizeof(INT16)); + + } else if (IsMaster(pDev)) + { + memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */ + + ocbuf = (INT32*)(obuff + sizeof(Time)); + icbuf = (INT32*)(ibuff + sizeof(Time)); + for (j = 0; j < MAX_VALUATORS; j++) + { + if (j >= pDev->valuator->numAxes) + break; + + /* fetch min/max/coordinate */ + memcpy(&from.min_value, icbuf++, sizeof(INT32)); + memcpy(&from.max_value, icbuf++, sizeof(INT32)); + memcpy(&coord, icbuf++, sizeof(INT32)); + + to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL; + + /* x/y scaled to screen if no range is present */ + if (j == 0 && (from.max_value < from.min_value)) + from.max_value = pScreen->width; + else if (j == 1 && (from.max_value < from.min_value)) + from.max_value = pScreen->height; + + if (j == 0 && (to->max_value < to->min_value)) + dflt = pScreen->width; + else if (j == 1 && (to->max_value < to->min_value)) + dflt = pScreen->height; + else + dflt = 0; + + /* scale from stored range into current range */ + coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0); + memcpy(ocbuf, &coord, sizeof(INT32)); + ocbuf++; + } + } else + memcpy(obuff, ibuff, size); + + /* don't advance by size here. size may be different to the + * actually written size if the MD has less valuators than MAX */ + if (core) + obuff += sizeof(INT32) + sizeof(Time); + else + obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time); + ret++; + } + } + + return ret; +} + + +/** + * Update the motion history for a specific device, with the list of + * valuators. + * + * Layout of the history buffer: + * for SDs: [time] [val0] [val1] ... [valn] + * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn] + * + * For events that have some valuators unset: + * min_val == max_val == val == 0. + */ +static void +updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask, + int *valuators) +{ + char *buff = (char *) pDev->valuator->motion; + ValuatorClassPtr v; + int i; + + if (!pDev->valuator->numMotionEvents) + return; + + v = pDev->valuator; + if (IsMaster(pDev)) + { + buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) * + v->last_motion; + + memcpy(buff, &ms, sizeof(Time)); + buff += sizeof(Time); + + memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS); + + for (i = 0; i < v->numAxes; i++) + { + /* XI1 doesn't support mixed mode devices */ + if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0)) + break; + if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) + { + buff += 3 * sizeof(INT32); + continue; + } + memcpy(buff, &v->axes[i].min_value, sizeof(INT32)); + buff += sizeof(INT32); + memcpy(buff, &v->axes[i].max_value, sizeof(INT32)); + buff += sizeof(INT32); + memcpy(buff, &valuators[i], sizeof(INT32)); + buff += sizeof(INT32); + } + } else + { + + buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) * + pDev->valuator->last_motion; + + memcpy(buff, &ms, sizeof(Time)); + buff += sizeof(Time); + + memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes); + + for (i = 0; i < MAX_VALUATORS; i++) + { + if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) + { + buff += sizeof(INT32); + continue; + } + memcpy(buff, &valuators[i], sizeof(INT32)); + buff += sizeof(INT32); + } + } + + pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) % + pDev->valuator->numMotionEvents; + /* If we're wrapping around, just keep the circular buffer going. */ + if (pDev->valuator->first_motion == pDev->valuator->last_motion) + pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) % + pDev->valuator->numMotionEvents; + + return; +} + + +/** + * Returns the maximum number of events GetKeyboardEvents, + * GetKeyboardValuatorEvents, and GetPointerEvents will ever return. + * + * This MUST be absolutely constant, from init until exit. + */ +int +GetMaximumEventsNum(void) { + /* One raw event + * One device event + * One possible device changed event + */ + return 3; +} + + +/** + * Clip an axis to its bounds, which are declared in the call to + * InitValuatorAxisClassStruct. + */ +static void +clipAxis(DeviceIntPtr pDev, int axisNum, int *val) +{ + AxisInfoPtr axis; + + if (axisNum >= pDev->valuator->numAxes) + return; + + axis = pDev->valuator->axes + axisNum; + + /* If a value range is defined, clip. If not, do nothing */ + if (axis->max_value <= axis->min_value) + return; + + if (*val < axis->min_value) + *val = axis->min_value; + if (*val > axis->max_value) + *val = axis->max_value; +} + +/** + * Clip every axis in the list of valuators to its bounds. + */ +static void +clipValuators(DeviceIntPtr pDev, ValuatorMask *mask) +{ + int i; + + for (i = 0; i < valuator_mask_size(mask); i++) + if (valuator_mask_isset(mask, i)) + { + int val = valuator_mask_get(mask, i); + clipAxis(pDev, i, &val); + valuator_mask_set(mask, i, val); + } +} + +/** + * Create the DCCE event (does not update the master's device state yet, this + * is done in the event processing). + * Pull in the coordinates from the MD if necessary. + * + * @param events Pointer to a pre-allocated event list. + * @param dev The slave device that generated an event. + * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT + * @param num_events The current number of events, returns the number of + * events if a DCCE was generated. + * @return The updated @events pointer. + */ +EventListPtr +UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events) +{ + DeviceIntPtr master; + + master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : MASTER_KEYBOARD); + + if (master && master->last.slave != dev) + { + CreateClassesChangedEvent(events, master, dev, type); + if (IsPointerDevice(master)) + { + updateSlaveDeviceCoords(master, dev); + master->last.numValuators = dev->last.numValuators; + } + master->last.slave = dev; + (*num_events)++; + events++; + } + return events; +} + +/** + * Move the device's pointer to the position given in the valuators. + * + * @param dev The device which's pointer is to be moved. + * @param x Returns the x position of the pointer after the move. + * @param y Returns the y position of the pointer after the move. + * @param mask Bit mask of valid valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + */ +static void +moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) +{ + int i; + + if (valuator_mask_isset(mask, 0)) + *x = valuator_mask_get(mask, 0); + else + *x = dev->last.valuators[0]; + + if (valuator_mask_isset(mask, 1)) + *y = valuator_mask_get(mask, 1); + else + *y = dev->last.valuators[1]; + + clipAxis(dev, 0, x); + clipAxis(dev, 1, y); + + for (i = 2; i < valuator_mask_size(mask); i++) + { + if (valuator_mask_isset(mask, i)) + { + dev->last.valuators[i] = valuator_mask_get(mask, i); + clipAxis(dev, i, &dev->last.valuators[i]); + } + } +} + +/** + * Move the device's pointer by the values given in @valuators. + * + * @param dev The device which's pointer is to be moved. + * @param x Returns the x position of the pointer after the move. + * @param y Returns the y position of the pointer after the move. + * @param mask Bit mask of valid valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + */ +static void +moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask) +{ + int i; + + *x = dev->last.valuators[0]; + *y = dev->last.valuators[1]; + + if (valuator_mask_isset(mask, 0)) + *x += valuator_mask_get(mask, 0); + + if (valuator_mask_isset(mask, 1)) + *y += valuator_mask_get(mask, 1); + + /* if attached, clip both x and y to the defined limits (usually + * co-ord space limit). If it is attached, we need x/y to go over the + * limits to be able to change screens. */ + if (dev->valuator && (IsMaster(dev) || !IsFloating(dev))) { + if (valuator_get_mode(dev, 0) == Absolute) + clipAxis(dev, 0, x); + if (valuator_get_mode(dev, 1) == Absolute) + clipAxis(dev, 1, y); + } + + /* calc other axes, clip, drop back into valuators */ + for (i = 2; i < valuator_mask_size(mask); i++) + { + if (valuator_mask_isset(mask, i)) + { + dev->last.valuators[i] += valuator_mask_get(mask, i); + if (valuator_get_mode(dev, i) == Absolute) + clipAxis(dev, i, &dev->last.valuators[i]); + valuator_mask_set(mask, i, dev->last.valuators[i]); + } + } +} + +/** + * Accelerate the data in valuators based on the device's acceleration scheme. + * + * @param dev The device which's pointer is to be moved. + * @param valuators Valuator mask + * @param ms Current time. + */ +static void +accelPointer(DeviceIntPtr dev, ValuatorMask* valuators, CARD32 ms) +{ + if (dev->valuator->accelScheme.AccelSchemeProc) + dev->valuator->accelScheme.AccelSchemeProc(dev, valuators, ms); +} + +/** + * If we have HW cursors, this actually moves the visible sprite. If not, we + * just do all the screen crossing, etc. + * + * We scale from device to screen coordinates here, call + * miPointerSetPosition() and then scale back into device coordinates (if + * needed). miPSP will change x/y if the screen was crossed. + * + * The coordinates provided are always absolute. The parameter mode whether + * it was relative or absolute movement that landed us at those coordinates. + * + * @param dev The device to be moved. + * @param mode Movement mode (Absolute or Relative) + * @param x Pointer to current x-axis value, may be modified. + * @param y Pointer to current y-axis value, may be modified. + * @param x_frac Fractional part of current x-axis value, may be modified. + * @param y_frac Fractional part of current y-axis value, may be modified. + * @param scr Screen the device's sprite is currently on. + * @param screenx Screen x coordinate the sprite is on after the update. + * @param screeny Screen y coordinate the sprite is on after the update. + * @param screenx_frac Fractional part of screen x coordinate, as above. + * @param screeny_frac Fractional part of screen y coordinate, as above. + */ +static void +positionSprite(DeviceIntPtr dev, int mode, + int *x, int *y, float x_frac, float y_frac, + ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac) +{ + int old_screenx, old_screeny; + + /* scale x&y to screen */ + if (dev->valuator && dev->valuator->numAxes > 0) { + *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac, + dev->valuator->axes + 0, NULL, scr->width); + } else { + *screenx = dev->last.valuators[0]; + *screenx_frac = dev->last.remainder[0]; + } + + if (dev->valuator && dev->valuator->numAxes > 1) { + *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac, + dev->valuator->axes + 1, NULL, scr->height); + } else { + *screeny = dev->last.valuators[1]; + *screeny_frac = dev->last.remainder[1]; + } + + /* Hit the left screen edge? */ + if (*screenx <= 0 && *screenx_frac < 0.0f) + { + *screenx_frac = 0.0f; + x_frac = 0.0f; + } + if (*screeny <= 0 && *screeny_frac < 0.0f) + { + *screeny_frac = 0.0f; + y_frac = 0.0f; + } + + + old_screenx = *screenx; + old_screeny = *screeny; + /* This takes care of crossing screens for us, as well as clipping + * to the current screen. */ + miPointerSetPosition(dev, mode, screenx, screeny); + + if(!IsMaster(dev) || !IsFloating(dev)) { + DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); + master->last.valuators[0] = *screenx; + master->last.valuators[1] = *screeny; + master->last.remainder[0] = *screenx_frac; + master->last.remainder[1] = *screeny_frac; + } + + if (dev->valuator) + { + /* Crossed screen? Scale back to device coordiantes */ + if(*screenx != old_screenx) + { + scr = miPointerGetScreen(dev); + *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL, + dev->valuator->axes + 0, scr->width); + } + if(*screeny != old_screeny) + { + scr = miPointerGetScreen(dev); + *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL, + dev->valuator->axes + 1, scr->height); + } + } + + /* dropy x/y (device coordinates) back into valuators for next event */ + dev->last.valuators[0] = *x; + dev->last.valuators[1] = *y; + dev->last.remainder[0] = x_frac; + dev->last.remainder[1] = y_frac; +} + +/** + * Update the motion history for the device and (if appropriate) for its + * master device. + * @param dev Slave device to update. + * @param mask Bit mask of valid valuators to append to history. + * @param num Total number of valuators to append to history. + * @param ms Current time + */ +static void +updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms) +{ + if (!dev->valuator) + return; + + updateMotionHistory(dev, ms, mask, dev->last.valuators); + if(!IsMaster(dev) || !IsFloating(dev)) + { + DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); + updateMotionHistory(master, ms, mask, dev->last.valuators); + } +} + +/** + * 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. + * + * events is not NULL-terminated; the return value is the number of events. + * The DDX is responsible for allocating the event structure in the first + * place via GetMaximumEventsNum(), and for freeing it. + */ +int +GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, + int key_code, const ValuatorMask *mask_in) { + int num_events = 0; + CARD32 ms = 0; + DeviceEvent *event; + RawDeviceEvent *raw; + ValuatorMask mask; + + /* refuse events from disabled devices */ + if (!pDev->enabled) + return 0; + + if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed || + (type != KeyPress && type != KeyRelease) || + (key_code < 8 || key_code > 255)) + return 0; + + num_events = 1; + + events = UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events); + + /* Handle core repeating, via press/release/press/release. */ + if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) { + /* If autorepeating is disabled either globally or just for that key, + * or we have a modifier, don't generate a repeat event. */ + if (!pDev->kbdfeed->ctrl.autoRepeat || + !key_autorepeats(pDev, key_code) || + pDev->key->xkbInfo->desc->map->modmap[key_code]) + return 0; + } + + ms = GetTimeInMillis(); + + raw = (RawDeviceEvent*)events->event; + events++; + num_events++; + + valuator_mask_copy(&mask, mask_in); + + init_raw(pDev, raw, ms, type, key_code); + set_raw_valuators(raw, &mask, raw->valuators.data_raw); + + clipValuators(pDev, &mask); + + set_raw_valuators(raw, &mask, raw->valuators.data); + + event = (DeviceEvent*) events->event; + init_event(pDev, event, ms); + event->detail.key = key_code; + + if (type == KeyPress) { + event->type = ET_KeyPress; + set_key_down(pDev, key_code, KEY_POSTED); + } + else if (type == KeyRelease) { + event->type = ET_KeyRelease; + set_key_up(pDev, key_code, KEY_POSTED); + } + + clipValuators(pDev, &mask); + + set_valuators(pDev, event, &mask); + + return num_events; +} + +/** + * Initialize an event list and fill with 32 byte sized events. + * This event list is to be passed into GetPointerEvents() and + * GetKeyboardEvents(). + * + * @param num_events Number of elements in list. + */ +EventListPtr +InitEventList(int num_events) +{ + EventListPtr events; + int i; + + events = (EventListPtr)calloc(num_events, sizeof(EventList)); + if (!events) + return NULL; + + for (i = 0; i < num_events; i++) + { + events[i].evlen = sizeof(InternalEvent); + events[i].event = calloc(1, sizeof(InternalEvent)); + if (!events[i].event) + { + /* rollback */ + while(i--) + free(events[i].event); + free(events); + events = NULL; + break; + } + } + + return events; +} + +/** + * Free an event list. + * + * @param list The list to be freed. + * @param num_events Number of elements in list. + */ +void +FreeEventList(EventListPtr list, int num_events) +{ + if (!list) + return; + while(num_events--) + free(list[num_events].event); + free(list); +} + +static void +transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask) +{ + struct pixman_f_vector p; + + /* p' = M * p in homogeneous coordinates */ + p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) : + dev->last.valuators[0]); + p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) : + dev->last.valuators[1]); + p.v[2] = 1.0; + + pixman_f_transform_point(&dev->transform, &p); + + if (lround(p.v[0]) != dev->last.valuators[0]) + valuator_mask_set(mask, 0, lround(p.v[0])); + if (lround(p.v[1]) != dev->last.valuators[1]) + valuator_mask_set(mask, 1, lround(p.v[1])); +} + +/** + * Generate a series of InternalEvents (filled into the EventList) + * representing pointer motion, or button presses. + * + * events is not NULL-terminated; the return value is the number of events. + * The DDX is responsible for allocating the event structure in the first + * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. + * + * In the generated events rootX/Y will be in absolute screen coords and + * the valuator information in the absolute or relative device coords. + * + * last.valuators[x] of the device is always in absolute device coords. + * last.valuators[x] of the master device is in absolute screen coords. + * + * master->last.valuators[x] for x > 2 is undefined. + */ +int +GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, + int flags, const ValuatorMask *mask_in) { + int num_events = 1; + CARD32 ms; + DeviceEvent *event; + RawDeviceEvent *raw; + int x = 0, y = 0, /* device coords */ + cx, cy; /* only screen coordinates */ + float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac; + ScreenPtr scr = miPointerGetScreen(pDev); + ValuatorMask mask; + + /* refuse events from disabled devices */ + if (!pDev->enabled) + return 0; + + if (!scr) + return 0; + + switch (type) + { + case MotionNotify: + if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) + return 0; + break; + case ButtonPress: + case ButtonRelease: + if (!pDev->button || !buttons) + return 0; + break; + default: + return 0; + } + + ms = GetTimeInMillis(); /* before pointer update to help precision */ + + events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); + + raw = (RawDeviceEvent*)events->event; + events++; + num_events++; + + valuator_mask_copy(&mask, mask_in); + + init_raw(pDev, raw, ms, type, buttons); + set_raw_valuators(raw, &mask, raw->valuators.data_raw); + + if (flags & POINTER_ABSOLUTE) + { + if (flags & POINTER_SCREEN) /* valuators are in screen coords */ + { + int scaled; + + if (valuator_mask_isset(&mask, 0)) + { + scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0), + 0.0, &x_frac, NULL, + pDev->valuator->axes + 0, + scr->width); + valuator_mask_set(&mask, 0, scaled); + } + if (valuator_mask_isset(&mask, 1)) + { + scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1), + 0.0, &y_frac, NULL, + pDev->valuator->axes + 1, + scr->height); + valuator_mask_set(&mask, 1, scaled); + } + } + + transformAbsolute(pDev, &mask); + moveAbsolute(pDev, &x, &y, &mask); + } else { + if (flags & POINTER_ACCELERATE) { + accelPointer(pDev, &mask, ms); + /* The pointer acceleration code modifies the fractional part + * in-place, so we need to extract this information first */ + x_frac = pDev->last.remainder[0]; + y_frac = pDev->last.remainder[1]; + } + moveRelative(pDev, &x, &y, &mask); + } + + set_raw_valuators(raw, &mask, raw->valuators.data); + + positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, + &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac); + updateHistory(pDev, &mask, ms); + + /* Update the valuators with the true value sent to the client*/ + if (valuator_mask_isset(&mask, 0)) + valuator_mask_set(&mask, 0, x); + if (valuator_mask_isset(&mask, 1)) + valuator_mask_set(&mask, 1, y); + + clipValuators(pDev, &mask); + + event = (DeviceEvent*) events->event; + init_event(pDev, event, ms); + + if (type == MotionNotify) { + event->type = ET_Motion; + event->detail.button = 0; + } + else { + if (type == ButtonPress) { + event->type = ET_ButtonPress; + set_button_down(pDev, buttons, BUTTON_POSTED); + } + else if (type == ButtonRelease) { + event->type = ET_ButtonRelease; + set_button_up(pDev, buttons, BUTTON_POSTED); + } + event->detail.button = buttons; + } + + event->root_x = cx; /* root_x/y always in screen coords */ + event->root_y = cy; + event->root_x_frac = cx_frac; + event->root_y_frac = cy_frac; + + set_valuators(pDev, event, &mask); + + return num_events; +} + + +/** + * Generate ProximityIn/ProximityOut InternalEvents, accompanied by + * valuators. + * + * events is not NULL-terminated; the return value is the number of events. + * The DDX is responsible for allocating the event structure in the first + * place via GetMaximumEventsNum(), and for freeing it. + */ +int +GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in) +{ + int num_events = 1, i; + DeviceEvent *event; + ValuatorMask mask; + + /* refuse events from disabled devices */ + if (!pDev->enabled) + return 0; + + /* Sanity checks. */ + if ((type != ProximityIn && type != ProximityOut) || !mask_in) + return 0; + if (!pDev->valuator) + return 0; + + valuator_mask_copy(&mask, mask_in); + + /* ignore relative axes for proximity. */ + for (i = 0; i < valuator_mask_size(&mask); i++) + { + if (valuator_mask_isset(&mask, i) && + valuator_get_mode(pDev, i) == Relative) + valuator_mask_unset(&mask, i); + } + + /* FIXME: posting proximity events with relative valuators only results + * in an empty event, EventToXI() will fail to convert → no event sent + * to client. */ + + events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); + + event = (DeviceEvent *) events->event; + init_event(pDev, event, GetTimeInMillis()); + event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; + + clipValuators(pDev, &mask); + + set_valuators(pDev, event, &mask); + + return num_events; +} + +/** + * Synthesize a single motion event for the core pointer. + * + * Used in cursor functions, e.g. when cursor confinement changes, and we need + * to shift the pointer to get it inside the new bounds. + */ +void +PostSyntheticMotion(DeviceIntPtr pDev, + int x, + int y, + int screen, + unsigned long time) +{ + DeviceEvent ev; + +#ifdef PANORAMIX + /* Translate back to the sprite screen since processInputProc + will translate from sprite screen to screen 0 upon reentry + to the DIX layer. */ + if (!noPanoramiXExtension) { + x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x; + y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y; + } +#endif + + memset(&ev, 0, sizeof(DeviceEvent)); + init_event(pDev, &ev, time); + ev.root_x = x; + ev.root_y = y; + ev.type = ET_Motion; + ev.time = time; + + /* FIXME: MD/SD considerations? */ + (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev); +} diff --git a/xorg-server/dix/ptrveloc.c b/xorg-server/dix/ptrveloc.c index e6ac2ed14..e95d804c2 100644 --- a/xorg-server/dix/ptrveloc.c +++ b/xorg-server/dix/ptrveloc.c @@ -1,1197 +1,1216 @@ -/* - * - * 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 -#endif - -#include -#include -#include -#include - -#include - -/***************************************************************************** - * 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 dev); -static BOOL -DeletePredictableAccelerationProperties(DeviceIntPtr dev); - -/*#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; - scheme = *protoScheme; - vel = calloc(1, sizeof(DeviceVelocityRec)); - if (!vel) - return FALSE; - InitVelocityData(vel); - scheme.accelData = vel; - dev->valuator->accelScheme = scheme; - InitializePredictableAccelerationProperties(dev); - return TRUE; -} - - -/** - * Uninit scheme - */ -void -AccelerationDefaultCleanup(DeviceIntPtr dev) -{ - /*sanity check*/ - if( dev->valuator->accelScheme.AccelSchemeProc == acceleratePointerPredictable - && dev->valuator->accelScheme.accelData != NULL){ - dev->valuator->accelScheme.AccelSchemeProc = NULL; - FreeVelocityData(dev->valuator->accelScheme.accelData); - free(dev->valuator->accelScheme.accelData); - dev->valuator->accelScheme.accelData = NULL; - DeletePredictableAccelerationProperties(dev); - } -} - - -/************************* - * 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); -} - -BOOL -InitializePredictableAccelerationProperties(DeviceIntPtr dev) -{ - DeviceVelocityPtr vel = GetDevicePredictableAccelData(dev); - - if(!vel) - return FALSE; - - vel->prop_handlers[0] = AccelInitProfileProperty(dev, vel); - vel->prop_handlers[1] = AccelInitDecelProperty(dev, vel); - vel->prop_handlers[2] = AccelInitAdaptDecelProperty(dev, vel); - vel->prop_handlers[3] = AccelInitScaleProperty(dev, vel); - - return TRUE; -} - -BOOL -DeletePredictableAccelerationProperties(DeviceIntPtr dev) -{ - 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); - for (i = 0; vel && i < NPROPS_PREDICTABLE_ACCEL; i++) - if (vel->prop_handlers[i]) - XIUnregisterPropertyHandler(dev, vel->prop_handlers[i]); - - 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)malloc(ntracker * sizeof(MotionTracker)); - memset(vel->tracker, 0, 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 (DeviceVelocityPtr)dev->valuator->accelScheme.accelData; - } - 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, - int first_valuator, - int num_valuators, - int *valuators, - int evtime) -{ - float fdx, fdy, tmp, mult; /* no need to init */ - int dx = 0, dy = 0; - int *px = NULL, *py = NULL; - DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev); - Bool soften = TRUE; - - if (!num_valuators || !valuators || !velocitydata) - return; - - if (velocitydata->statistics.profile_number == AccelProfileNone && - velocitydata->const_acceleration == 1.0f) { - return; /*we're inactive anyway, so skip the whole thing.*/ - } - - if (first_valuator == 0) { - dx = valuators[0]; - px = &valuators[0]; - } - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { - dy = valuators[1 - first_valuator]; - py = &valuators[1 - first_valuator]; - } - - 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. */ - *px = lrintf(tmp); - dev->last.remainder[0] = tmp - (float)*px; - } - if (dy) { - tmp = mult * fdy + dev->last.remainder[1]; - *py = lrintf(tmp); - dev->last.remainder[1] = tmp - (float)*py; - } - 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, - int first_valuator, - int num_valuators, - int *valuators, - int ignored) -{ - float mult = 0.0; - int dx = 0, dy = 0; - int *px = NULL, *py = NULL; - - if (!num_valuators || !valuators) - return; - - if (first_valuator == 0) { - dx = valuators[0]; - px = &valuators[0]; - } - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { - dy = valuators[1 - first_valuator]; - py = &valuators[1 - first_valuator]; - } - - 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) { - dev->last.remainder[0] = ((float)dx * - (float)(dev->ptrfeed->ctrl.num)) / - (float)(dev->ptrfeed->ctrl.den) + - dev->last.remainder[0]; - if (px) { - *px = (int)dev->last.remainder[0]; - dev->last.remainder[0] = dev->last.remainder[0] - - (float)(*px); - } - - dev->last.remainder[1] = ((float)dy * - (float)(dev->ptrfeed->ctrl.num)) / - (float)(dev->ptrfeed->ctrl.den) + - dev->last.remainder[1]; - if (py) { - *py = (int)dev->last.remainder[1]; - dev->last.remainder[1] = dev->last.remainder[1] - - (float)(*py); - } - } - } - 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) { - dev->last.remainder[0] = mult * (float)dx + - dev->last.remainder[0]; - *px = (int)dev->last.remainder[0]; - dev->last.remainder[0] = dev->last.remainder[0] - - (float)(*px); - } - if (dy) { - dev->last.remainder[1] = mult * (float)dy + - dev->last.remainder[1]; - *py = (int)dev->last.remainder[1]; - dev->last.remainder[1] = dev->last.remainder[1] - - (float)(*py); - } - } - } -} +/* + * + * 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 +#endif + +#include +#include +#include +#include +#include + +#include + +/***************************************************************************** + * 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; + } + } + } +} diff --git a/xorg-server/fb/fbpict.c b/xorg-server/fb/fbpict.c index 312f3df21..fb26632bd 100644 --- a/xorg-server/fb/fbpict.c +++ b/xorg-server/fb/fbpict.c @@ -1,373 +1,373 @@ -/* - * - * Copyright © 2000 SuSE, Inc. - * 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 SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * 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: Keith Packard, SuSE, Inc. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include "fb.h" - -#include "picturestr.h" -#include "mipict.h" -#include "fbpict.h" - -void -fbComposite (CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height) -{ - pixman_image_t *src, *mask, *dest; - int src_xoff, src_yoff; - int msk_xoff, msk_yoff; - int dst_xoff, dst_yoff; - - miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height); - if (pMask) - miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height); - - src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff); - mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff); - dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff); - - if (src && dest && !(pMask && !mask)) - { - pixman_image_composite (op, src, mask, dest, - xSrc + src_xoff, ySrc + src_yoff, - xMask + msk_xoff, yMask + msk_yoff, - xDst + dst_xoff, yDst + dst_yoff, - width, height); - } - - free_pixman_pict (pSrc, src); - free_pixman_pict (pMask, mask); - free_pixman_pict (pDst, dest); -} - -static pixman_image_t * -create_solid_fill_image (PicturePtr pict) -{ - PictSolidFill *solid = &pict->pSourcePict->solidFill; - pixman_color_t color; - CARD32 a, r, g, b; - - a = (solid->color & 0xff000000) >> 24; - r = (solid->color & 0x00ff0000) >> 16; - g = (solid->color & 0x0000ff00) >> 8; - b = (solid->color & 0x000000ff) >> 0; - - color.alpha = (a << 8) | a; - color.red = (r << 8) | r; - color.green = (g << 8) | g; - color.blue = (b << 8) | b; - - return pixman_image_create_solid_fill (&color); -} - -static pixman_image_t * -create_linear_gradient_image (PictGradient *gradient) -{ - PictLinearGradient *linear = (PictLinearGradient *)gradient; - pixman_point_fixed_t p1; - pixman_point_fixed_t p2; - - p1.x = linear->p1.x; - p1.y = linear->p1.y; - p2.x = linear->p2.x; - p2.y = linear->p2.y; - - return pixman_image_create_linear_gradient ( - &p1, &p2, (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); -} - -static pixman_image_t * -create_radial_gradient_image (PictGradient *gradient) -{ - PictRadialGradient *radial = (PictRadialGradient *)gradient; - pixman_point_fixed_t c1; - pixman_point_fixed_t c2; - - c1.x = radial->c1.x; - c1.y = radial->c1.y; - c2.x = radial->c2.x; - c2.y = radial->c2.y; - - return pixman_image_create_radial_gradient ( - &c1, &c2, radial->c1.radius, - radial->c2.radius, - (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); -} - -static pixman_image_t * -create_conical_gradient_image (PictGradient *gradient) -{ - PictConicalGradient *conical = (PictConicalGradient *)gradient; - pixman_point_fixed_t center; - - center.x = conical->center.x; - center.y = conical->center.y; - - return pixman_image_create_conical_gradient ( - ¢er, conical->angle, (pixman_gradient_stop_t *)gradient->stops, - gradient->nstops); -} - -static pixman_image_t * -create_bits_picture (PicturePtr pict, - Bool has_clip, - int *xoff, - int *yoff) -{ - PixmapPtr pixmap; - FbBits *bits; - FbStride stride; - int bpp; - pixman_image_t *image; - - fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff); - fbGetPixmapBitsData(pixmap, bits, stride, bpp); - - image = pixman_image_create_bits ( - pict->format, - pixmap->drawable.width, pixmap->drawable.height, - (uint32_t *)bits, stride * sizeof (FbStride)); - - -#ifdef FB_ACCESS_WRAPPER -#if FB_SHIFT==5 - - pixman_image_set_accessors (image, - (pixman_read_memory_func_t)wfbReadMemory, - (pixman_write_memory_func_t)wfbWriteMemory); - -#else - -#error The pixman library only works when FbBits is 32 bits wide - -#endif -#endif - - /* pCompositeClip is undefined for source pictures, so - * only set the clip region for pictures with drawables - */ - if (has_clip) - { - if (pict->clientClipType != CT_NONE) - pixman_image_set_has_client_clip (image, TRUE); - - if (*xoff || *yoff) - pixman_region_translate (pict->pCompositeClip, *xoff, *yoff); - - pixman_image_set_clip_region (image, pict->pCompositeClip); - - if (*xoff || *yoff) - pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff); - } - - /* Indexed table */ - if (pict->pFormat->index.devPrivate) - pixman_image_set_indexed (image, pict->pFormat->index.devPrivate); - - /* Add in drawable origin to position within the image */ - *xoff += pict->pDrawable->x; - *yoff += pict->pDrawable->y; - - return image; -} - -static pixman_image_t * -image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map); - -static void -set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) -{ - pixman_repeat_t repeat; - pixman_filter_t filter; - - if (pict->transform) - { - /* For source images, adjust the transform to account - * for the drawable offset within the pixman image, - * then set the offset to 0 as it will be used - * to compute positions within the transformed image. - */ - if (!has_clip) { - struct pixman_transform adjusted; - - adjusted = *pict->transform; - pixman_transform_translate(&adjusted, - NULL, - pixman_int_to_fixed(*xoff), - pixman_int_to_fixed(*yoff)); - pixman_image_set_transform (image, &adjusted); - *xoff = 0; - *yoff = 0; - } else - pixman_image_set_transform (image, pict->transform); - } - - switch (pict->repeatType) - { - default: - case RepeatNone: - repeat = PIXMAN_REPEAT_NONE; - break; - - case RepeatPad: - repeat = PIXMAN_REPEAT_PAD; - break; - - case RepeatNormal: - repeat = PIXMAN_REPEAT_NORMAL; - break; - - case RepeatReflect: - repeat = PIXMAN_REPEAT_REFLECT; - break; - } - - pixman_image_set_repeat (image, repeat); - - /* Fetch alpha map unless 'pict' is being used - * as the alpha map for this operation - */ - if (pict->alphaMap && !is_alpha_map) - { - int alpha_xoff, alpha_yoff; - pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE); - - pixman_image_set_alpha_map ( - image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y); - - free_pixman_pict (pict->alphaMap, alpha_map); - } - - pixman_image_set_component_alpha (image, pict->componentAlpha); - - switch (pict->filter) - { - default: - case PictFilterNearest: - case PictFilterFast: - filter = PIXMAN_FILTER_NEAREST; - break; - - case PictFilterBilinear: - case PictFilterGood: - filter = PIXMAN_FILTER_BILINEAR; - break; - - case PictFilterConvolution: - filter = PIXMAN_FILTER_CONVOLUTION; - break; - } - - pixman_image_set_filter (image, filter, (pixman_fixed_t *)pict->filter_params, pict->filter_nparams); - pixman_image_set_source_clipping (image, TRUE); -} - -static pixman_image_t * -image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) -{ - pixman_image_t *image = NULL; - - if (!pict) - return NULL; - - if (pict->pDrawable) - { - image = create_bits_picture (pict, has_clip, xoff, yoff); - } - else if (pict->pSourcePict) - { - SourcePict *sp = pict->pSourcePict; - - if (sp->type == SourcePictTypeSolidFill) - { - image = create_solid_fill_image (pict); - } - else - { - PictGradient *gradient = &pict->pSourcePict->gradient; - - if (sp->type == SourcePictTypeLinear) - image = create_linear_gradient_image (gradient); - else if (sp->type == SourcePictTypeRadial) - image = create_radial_gradient_image (gradient); - else if (sp->type == SourcePictTypeConical) - image = create_conical_gradient_image (gradient); - } - *xoff = *yoff = 0; - } - - if (image) - set_image_properties (image, pict, has_clip, xoff, yoff, is_alpha_map); - - return image; -} - -pixman_image_t * -image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff) -{ - return image_from_pict_internal (pict, has_clip, xoff, yoff, FALSE); -} - -void -free_pixman_pict (PicturePtr pict, pixman_image_t *image) -{ - if (image && pixman_image_unref (image) && pict->pDrawable) - fbFinishAccess (pict->pDrawable); -} - -Bool -fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) -{ - - PictureScreenPtr ps; - - if (!miPictureInit (pScreen, formats, nformats)) - return FALSE; - ps = GetPictureScreen(pScreen); - ps->Composite = fbComposite; - ps->Glyphs = miGlyphs; - ps->CompositeRects = miCompositeRects; - ps->RasterizeTrapezoid = fbRasterizeTrapezoid; - ps->Trapezoids = fbTrapezoids; - ps->AddTraps = fbAddTraps; - ps->AddTriangles = fbAddTriangles; - ps->Triangles = fbTriangles; - - return TRUE; -} +/* + * + * Copyright © 2000 SuSE, Inc. + * 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +void +fbComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + pixman_image_t *src, *mask, *dest; + int src_xoff, src_yoff; + int msk_xoff, msk_yoff; + int dst_xoff, dst_yoff; + + miCompositeSourceValidate (pSrc); + if (pMask) + miCompositeSourceValidate (pMask); + + src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff); + mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff); + dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff); + + if (src && dest && !(pMask && !mask)) + { + pixman_image_composite (op, src, mask, dest, + xSrc + src_xoff, ySrc + src_yoff, + xMask + msk_xoff, yMask + msk_yoff, + xDst + dst_xoff, yDst + dst_yoff, + width, height); + } + + free_pixman_pict (pSrc, src); + free_pixman_pict (pMask, mask); + free_pixman_pict (pDst, dest); +} + +static pixman_image_t * +create_solid_fill_image (PicturePtr pict) +{ + PictSolidFill *solid = &pict->pSourcePict->solidFill; + pixman_color_t color; + CARD32 a, r, g, b; + + a = (solid->color & 0xff000000) >> 24; + r = (solid->color & 0x00ff0000) >> 16; + g = (solid->color & 0x0000ff00) >> 8; + b = (solid->color & 0x000000ff) >> 0; + + color.alpha = (a << 8) | a; + color.red = (r << 8) | r; + color.green = (g << 8) | g; + color.blue = (b << 8) | b; + + return pixman_image_create_solid_fill (&color); +} + +static pixman_image_t * +create_linear_gradient_image (PictGradient *gradient) +{ + PictLinearGradient *linear = (PictLinearGradient *)gradient; + pixman_point_fixed_t p1; + pixman_point_fixed_t p2; + + p1.x = linear->p1.x; + p1.y = linear->p1.y; + p2.x = linear->p2.x; + p2.y = linear->p2.y; + + return pixman_image_create_linear_gradient ( + &p1, &p2, (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); +} + +static pixman_image_t * +create_radial_gradient_image (PictGradient *gradient) +{ + PictRadialGradient *radial = (PictRadialGradient *)gradient; + pixman_point_fixed_t c1; + pixman_point_fixed_t c2; + + c1.x = radial->c1.x; + c1.y = radial->c1.y; + c2.x = radial->c2.x; + c2.y = radial->c2.y; + + return pixman_image_create_radial_gradient ( + &c1, &c2, radial->c1.radius, + radial->c2.radius, + (pixman_gradient_stop_t *)gradient->stops, gradient->nstops); +} + +static pixman_image_t * +create_conical_gradient_image (PictGradient *gradient) +{ + PictConicalGradient *conical = (PictConicalGradient *)gradient; + pixman_point_fixed_t center; + + center.x = conical->center.x; + center.y = conical->center.y; + + return pixman_image_create_conical_gradient ( + ¢er, conical->angle, (pixman_gradient_stop_t *)gradient->stops, + gradient->nstops); +} + +static pixman_image_t * +create_bits_picture (PicturePtr pict, + Bool has_clip, + int *xoff, + int *yoff) +{ + PixmapPtr pixmap; + FbBits *bits; + FbStride stride; + int bpp; + pixman_image_t *image; + + fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff); + fbGetPixmapBitsData(pixmap, bits, stride, bpp); + + image = pixman_image_create_bits ( + pict->format, + pixmap->drawable.width, pixmap->drawable.height, + (uint32_t *)bits, stride * sizeof (FbStride)); + + +#ifdef FB_ACCESS_WRAPPER +#if FB_SHIFT==5 + + pixman_image_set_accessors (image, + (pixman_read_memory_func_t)wfbReadMemory, + (pixman_write_memory_func_t)wfbWriteMemory); + +#else + +#error The pixman library only works when FbBits is 32 bits wide + +#endif +#endif + + /* pCompositeClip is undefined for source pictures, so + * only set the clip region for pictures with drawables + */ + if (has_clip) + { + if (pict->clientClipType != CT_NONE) + pixman_image_set_has_client_clip (image, TRUE); + + if (*xoff || *yoff) + pixman_region_translate (pict->pCompositeClip, *xoff, *yoff); + + pixman_image_set_clip_region (image, pict->pCompositeClip); + + if (*xoff || *yoff) + pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff); + } + + /* Indexed table */ + if (pict->pFormat->index.devPrivate) + pixman_image_set_indexed (image, pict->pFormat->index.devPrivate); + + /* Add in drawable origin to position within the image */ + *xoff += pict->pDrawable->x; + *yoff += pict->pDrawable->y; + + return image; +} + +static pixman_image_t * +image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map); + +static void +set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) +{ + pixman_repeat_t repeat; + pixman_filter_t filter; + + if (pict->transform) + { + /* For source images, adjust the transform to account + * for the drawable offset within the pixman image, + * then set the offset to 0 as it will be used + * to compute positions within the transformed image. + */ + if (!has_clip) { + struct pixman_transform adjusted; + + adjusted = *pict->transform; + pixman_transform_translate(&adjusted, + NULL, + pixman_int_to_fixed(*xoff), + pixman_int_to_fixed(*yoff)); + pixman_image_set_transform (image, &adjusted); + *xoff = 0; + *yoff = 0; + } else + pixman_image_set_transform (image, pict->transform); + } + + switch (pict->repeatType) + { + default: + case RepeatNone: + repeat = PIXMAN_REPEAT_NONE; + break; + + case RepeatPad: + repeat = PIXMAN_REPEAT_PAD; + break; + + case RepeatNormal: + repeat = PIXMAN_REPEAT_NORMAL; + break; + + case RepeatReflect: + repeat = PIXMAN_REPEAT_REFLECT; + break; + } + + pixman_image_set_repeat (image, repeat); + + /* Fetch alpha map unless 'pict' is being used + * as the alpha map for this operation + */ + if (pict->alphaMap && !is_alpha_map) + { + int alpha_xoff, alpha_yoff; + pixman_image_t *alpha_map = image_from_pict_internal (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff, TRUE); + + pixman_image_set_alpha_map ( + image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y); + + free_pixman_pict (pict->alphaMap, alpha_map); + } + + pixman_image_set_component_alpha (image, pict->componentAlpha); + + switch (pict->filter) + { + default: + case PictFilterNearest: + case PictFilterFast: + filter = PIXMAN_FILTER_NEAREST; + break; + + case PictFilterBilinear: + case PictFilterGood: + filter = PIXMAN_FILTER_BILINEAR; + break; + + case PictFilterConvolution: + filter = PIXMAN_FILTER_CONVOLUTION; + break; + } + + pixman_image_set_filter (image, filter, (pixman_fixed_t *)pict->filter_params, pict->filter_nparams); + pixman_image_set_source_clipping (image, TRUE); +} + +static pixman_image_t * +image_from_pict_internal (PicturePtr pict, Bool has_clip, int *xoff, int *yoff, Bool is_alpha_map) +{ + pixman_image_t *image = NULL; + + if (!pict) + return NULL; + + if (pict->pDrawable) + { + image = create_bits_picture (pict, has_clip, xoff, yoff); + } + else if (pict->pSourcePict) + { + SourcePict *sp = pict->pSourcePict; + + if (sp->type == SourcePictTypeSolidFill) + { + image = create_solid_fill_image (pict); + } + else + { + PictGradient *gradient = &pict->pSourcePict->gradient; + + if (sp->type == SourcePictTypeLinear) + image = create_linear_gradient_image (gradient); + else if (sp->type == SourcePictTypeRadial) + image = create_radial_gradient_image (gradient); + else if (sp->type == SourcePictTypeConical) + image = create_conical_gradient_image (gradient); + } + *xoff = *yoff = 0; + } + + if (image) + set_image_properties (image, pict, has_clip, xoff, yoff, is_alpha_map); + + return image; +} + +pixman_image_t * +image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff) +{ + return image_from_pict_internal (pict, has_clip, xoff, yoff, FALSE); +} + +void +free_pixman_pict (PicturePtr pict, pixman_image_t *image) +{ + if (image && pixman_image_unref (image) && pict->pDrawable) + fbFinishAccess (pict->pDrawable); +} + +Bool +fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + + PictureScreenPtr ps; + + if (!miPictureInit (pScreen, formats, nformats)) + return FALSE; + ps = GetPictureScreen(pScreen); + ps->Composite = fbComposite; + ps->Glyphs = miGlyphs; + ps->CompositeRects = miCompositeRects; + ps->RasterizeTrapezoid = fbRasterizeTrapezoid; + ps->Trapezoids = fbTrapezoids; + ps->AddTraps = fbAddTraps; + ps->AddTriangles = fbAddTriangles; + ps->Triangles = fbTriangles; + + return TRUE; +} diff --git a/xorg-server/glx/glxdri.c b/xorg-server/glx/glxdri.c index e0713b8a1..b394cdedc 100644 --- a/xorg-server/glx/glxdri.c +++ b/xorg-server/glx/glxdri.c @@ -858,8 +858,6 @@ static const __DRIextension *loader_extensions[] = { -static const char dri_driver_path[] = DRI_DRIVER_PATH; - static Bool glxDRIEnterVT (int index, int flags) { @@ -971,13 +969,10 @@ __glXDRIscreenProbe(ScreenPtr pScreen) drm_handle_t hFB; int junk; __GLXDRIscreen *screen; - char filename[128]; Bool isCapable; size_t buffer_size; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; const __DRIconfig **driConfigs; - const __DRIextension **extensions; - int i; if (!xf86LoaderCheckSymbol("DRIQueryDirectRenderingCapable") || !DRIQueryDirectRenderingCapable(pScreen, &isCapable) || @@ -1052,42 +1047,15 @@ __glXDRIscreenProbe(ScreenPtr pScreen) goto handle_error; } - snprintf(filename, sizeof filename, "%s/%s_dri.so", - dri_driver_path, driverName); - - screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); + screen->driver = glxProbeDriver(driverName, + (void **)&screen->core, + __DRI_CORE, __DRI_CORE_VERSION, + (void **)&screen->legacy, + __DRI_LEGACY, __DRI_LEGACY_VERSION); if (screen->driver == NULL) { - LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", - filename, dlerror()); goto handle_error; } - - extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS); - if (extensions == NULL) { - LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", - driverName, dlerror()); - goto handle_error; - } - for (i = 0; extensions[i]; i++) { - if (strcmp(extensions[i]->name, __DRI_CORE) == 0 && - extensions[i]->version >= __DRI_CORE_VERSION) { - screen->core = (__DRIcoreExtension *) extensions[i]; - } - - if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0 && - extensions[i]->version >= __DRI_LEGACY_VERSION) { - screen->legacy = (__DRIlegacyExtension *) extensions[i]; - } - } - - if (screen->core == NULL || screen->legacy == NULL) { - LogMessage(X_ERROR, - "AIGLX error: %s does not export required DRI extension\n", - driverName); - goto handle_error; - } - /* * Get device-specific info. pDevPriv will point to a struct * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that @@ -1172,7 +1140,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen) pScrn->LeaveVT = glxDRILeaveVT; LogMessage(X_INFO, - "AIGLX: Loaded and initialized %s\n", filename); + "AIGLX: Loaded and initialized %s\n", driverName); return &screen->base; diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c index c9c316be5..9d4aeab23 100644 --- a/xorg-server/glx/glxdri2.c +++ b/xorg-server/glx/glxdri2.c @@ -599,8 +599,6 @@ static const __DRIextension *loader_extensions[] = { NULL }; -static const char dri_driver_path[] = DRI_DRIVER_PATH; - static Bool glxDRIEnterVT (int index, int flags) { @@ -702,12 +700,9 @@ __glXDRIscreenProbe(ScreenPtr pScreen) { const char *driverName, *deviceName; __GLXDRIscreen *screen; - char filename[128]; size_t buffer_size; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - const __DRIextension **extensions; const __DRIconfig **driConfigs; - int i; screen = calloc(1, sizeof *screen); if (screen == NULL) @@ -729,40 +724,12 @@ __glXDRIscreenProbe(ScreenPtr pScreen) __glXInitExtensionEnableBits(screen->glx_enable_bits); - snprintf(filename, sizeof filename, - "%s/%s_dri.so", dri_driver_path, driverName); - - screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); + screen->driver = glxProbeDriver(driverName, (void **)&screen->core, __DRI_CORE, 1, + (void **)&screen->dri2, __DRI_DRI2, 1); if (screen->driver == NULL) { - LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", - filename, dlerror()); goto handle_error; } - - extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS); - if (extensions == NULL) { - LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", - driverName, dlerror()); - goto handle_error; - } - for (i = 0; extensions[i]; i++) { - if (strcmp(extensions[i]->name, __DRI_CORE) == 0 && - extensions[i]->version >= 1) { - screen->core = (const __DRIcoreExtension *) extensions[i]; - } - if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 && - extensions[i]->version >= 1) { - screen->dri2 = (const __DRIdri2Extension *) extensions[i]; - } - } - - if (screen->core == NULL || screen->dri2 == NULL) { - LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n", - driverName); - goto handle_error; - } - screen->driScreen = (*screen->dri2->createNewScreen)(pScreen->myNum, screen->fd, @@ -816,7 +783,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen) pScrn->LeaveVT = glxDRILeaveVT; LogMessage(X_INFO, - "AIGLX: Loaded and initialized %s\n", filename); + "AIGLX: Loaded and initialized %s\n", driverName); return &screen->base; diff --git a/xorg-server/glx/glxdricommon.c b/xorg-server/glx/glxdricommon.c index 44078fb41..2fcda8fb8 100644 --- a/xorg-server/glx/glxdricommon.c +++ b/xorg-server/glx/glxdricommon.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -204,3 +205,59 @@ glxConvertConfigs(const __DRIcoreExtension *core, return head.next; } + +static const char dri_driver_path[] = DRI_DRIVER_PATH; + +void * +glxProbeDriver(const char *driverName, + void **coreExt, const char *coreName, int coreVersion, + void **renderExt, const char *renderName, int renderVersion) +{ + int i; + void *driver; + char filename[PATH_MAX]; + const __DRIextension **extensions; + + snprintf(filename, sizeof filename, "%s/%s_dri.so", + dri_driver_path, driverName); + + driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); + if (driver == NULL) { + LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", + filename, dlerror()); + goto cleanup_failure; + } + + extensions = dlsym(driver, __DRI_DRIVER_EXTENSIONS); + if (extensions == NULL) { + LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", + driverName, dlerror()); + goto cleanup_failure; + } + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, coreName) == 0 && + extensions[i]->version >= coreVersion) { + *coreExt = (void *)extensions[i]; + } + + if (strcmp(extensions[i]->name, renderName) == 0 && + extensions[i]->version >= renderVersion) { + *renderExt = (void *)extensions[i]; + } + } + + if (*coreExt == NULL || *renderExt == NULL) { + LogMessage(X_ERROR, + "AIGLX error: %s does not export required DRI extension\n", + driverName); + goto cleanup_failure; + } + return driver; + +cleanup_failure: + if (driver) + dlclose(driver); + *coreExt = *renderExt = NULL; + return NULL; +} diff --git a/xorg-server/glx/glxdricommon.h b/xorg-server/glx/glxdricommon.h index 41e2d2770..ef7b531f6 100644 --- a/xorg-server/glx/glxdricommon.h +++ b/xorg-server/glx/glxdricommon.h @@ -1,41 +1,46 @@ -/* - * Copyright © 2008 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 the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#ifndef _GLX_dri_common_h -#define _GLX_dri_common_h - -typedef struct __GLXDRIconfig __GLXDRIconfig; -struct __GLXDRIconfig { - __GLXconfig config; - const __DRIconfig *driConfig; -}; - -__GLXconfig * -glxConvertConfigs(const __DRIcoreExtension *core, - const __DRIconfig **configs, unsigned int drawableType); - -extern const __DRIsystemTimeExtension systemTimeExtension; - -#endif +/* + * Copyright © 2008 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 the + * copyright holders not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. + */ + +#ifndef _GLX_dri_common_h +#define _GLX_dri_common_h + +typedef struct __GLXDRIconfig __GLXDRIconfig; +struct __GLXDRIconfig { + __GLXconfig config; + const __DRIconfig *driConfig; +}; + +__GLXconfig * +glxConvertConfigs(const __DRIcoreExtension *core, + const __DRIconfig **configs, unsigned int drawableType); + +extern const __DRIsystemTimeExtension systemTimeExtension; + +void * +glxProbeDriver(const char *name, + void **coreExt, const char *coreName, int coreVersion, + void **renderExt, const char *renderName, int renderVersion); + +#endif diff --git a/xorg-server/glx/glxdriswrast.c b/xorg-server/glx/glxdriswrast.c index 30ce19ed1..fb2316a62 100644 --- a/xorg-server/glx/glxdriswrast.c +++ b/xorg-server/glx/glxdriswrast.c @@ -201,6 +201,14 @@ __glXDRIbindTexImage(__GLXcontext *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); @@ -427,17 +435,12 @@ initializeExtensions(__GLXDRIscreen *screen) } } -static const char dri_driver_path[] = DRI_DRIVER_PATH; - static __GLXscreen * __glXDRIscreenProbe(ScreenPtr pScreen) { const char *driverName = "swrast"; __GLXDRIscreen *screen; - char filename[128]; - const __DRIextension **extensions; const __DRIconfig **driConfigs; - int i; screen = calloc(1, sizeof *screen); if (screen == NULL) @@ -449,40 +452,15 @@ __glXDRIscreenProbe(ScreenPtr pScreen) screen->base.swapInterval = NULL; screen->base.pScreen = pScreen; - snprintf(filename, sizeof filename, - "%s/%s_dri.so", dri_driver_path, driverName); - - screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); + screen->driver = glxProbeDriver(driverName, + (void **)&screen->core, + __DRI_CORE, __DRI_CORE_VERSION, + (void **)&screen->swrast, + __DRI_SWRAST, __DRI_SWRAST_VERSION); if (screen->driver == NULL) { - LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", - filename, dlerror()); goto handle_error; } - extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS); - if (extensions == NULL) { - LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", - driverName, dlerror()); - goto handle_error; - } - - for (i = 0; extensions[i]; i++) { - if (strcmp(extensions[i]->name, __DRI_CORE) == 0 && - extensions[i]->version >= __DRI_CORE_VERSION) { - screen->core = (const __DRIcoreExtension *) extensions[i]; - } - if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0 && - extensions[i]->version >= __DRI_SWRAST_VERSION) { - screen->swrast = (const __DRIswrastExtension *) extensions[i]; - } - } - - if (screen->core == NULL || screen->swrast == NULL) { - LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n", - driverName); - goto handle_error; - } - screen->driScreen = (*screen->swrast->createNewScreen)(pScreen->myNum, loader_extensions, @@ -508,7 +486,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen) screen->base.GLXminor = 4; LogMessage(X_INFO, - "AIGLX: Loaded and initialized %s\n", filename); + "AIGLX: Loaded and initialized %s\n", driverName); return &screen->base; diff --git a/xorg-server/hw/dmx/dmx.h b/xorg-server/hw/dmx/dmx.h index ddc11e368..dc5d25e16 100644 --- a/xorg-server/hw/dmx/dmx.h +++ b/xorg-server/hw/dmx/dmx.h @@ -249,8 +249,6 @@ typedef struct _DMXScreenInfo { TrapezoidsProcPtr Trapezoids; TrianglesProcPtr Triangles; - TriStripProcPtr TriStrip; - TriFanProcPtr TriFan; } DMXScreenInfo; /* Global variables available to all Xserver/hw/dmx routines. */ diff --git a/xorg-server/hw/dmx/dmxpict.c b/xorg-server/hw/dmx/dmxpict.c index 3f5cd4a50..1ea6543e0 100644 --- a/xorg-server/hw/dmx/dmxpict.c +++ b/xorg-server/hw/dmx/dmxpict.c @@ -165,8 +165,6 @@ Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats) DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps); DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps); - DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps); - DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps); return TRUE; } @@ -1237,88 +1235,3 @@ void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps); } - -/** Composite a triangle strip on the appropriate screen. For a - * complete description see the protocol document of the RENDER - * library. */ -void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int npoint, xPointFixed *points) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); - dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); - - DMX_UNWRAP(TriStrip, dmxScreen, ps); -#if 0 - if (ps->TriStrip) - ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); -#endif - - /* Draw trapezoids on back-end server */ - if (pDstPriv->pict) { - XRenderPictFormat *pFormat; - - pFormat = dmxFindFormat(dmxScreen, maskFormat); - if (!pFormat) { - /* FIXME: Error! */ - } - - XRenderCompositeTriStrip(dmxScreen->beDisplay, - op, - pSrcPriv->pict, - pDstPriv->pict, - pFormat, - xSrc, ySrc, - (XPointFixed *)points, - npoint); - dmxSync(dmxScreen, FALSE); - } - - DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps); -} - -/** Composite a triangle fan on the appropriate screen. For a complete - * description see the protocol document of the RENDER library. */ -void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int npoint, xPointFixed *points) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); - dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); - - DMX_UNWRAP(TriFan, dmxScreen, ps); -#if 0 - if (ps->TriFan) - ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); -#endif - - /* Draw trapezoids on back-end server */ - if (pDstPriv->pict) { - XRenderPictFormat *pFormat; - - pFormat = dmxFindFormat(dmxScreen, maskFormat); - if (!pFormat) { - /* FIXME: Error! */ - } - - XRenderCompositeTriFan(dmxScreen->beDisplay, - op, - pSrcPriv->pict, - pDstPriv->pict, - pFormat, - xSrc, ySrc, - (XPointFixed *)points, - npoint); - dmxSync(dmxScreen, FALSE); - } - - DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps); -} diff --git a/xorg-server/hw/dmx/dmxpict.h b/xorg-server/hw/dmx/dmxpict.h index d196f639a..f1d8c1f52 100644 --- a/xorg-server/hw/dmx/dmxpict.h +++ b/xorg-server/hw/dmx/dmxpict.h @@ -100,16 +100,6 @@ extern void dmxTriangles(CARD8 op, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntri, xTriangle *tris); -extern void dmxTriStrip(CARD8 op, - PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int npoint, xPointFixed *points); -extern void dmxTriFan(CARD8 op, - PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int npoint, xPointFixed *points); extern int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet); extern Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet); diff --git a/xorg-server/hw/dmx/doc/Makefile.am b/xorg-server/hw/dmx/doc/Makefile.am index 8e7360288..d3acf23b7 100644 --- a/xorg-server/hw/dmx/doc/Makefile.am +++ b/xorg-server/hw/dmx/doc/Makefile.am @@ -1,280 +1,277 @@ -# Copyright 2005 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 -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. Red -# Hat makes no representations about the suitability of this software -# for any purpose. It is provided "as is" without express or implied -# warranty. -# -# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN -# NO EVENT SHALL RED HAT 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. - -doc_sources = dmx.xml scaled.xml - -# Developer's documentation is not installed -if ENABLE_DEVEL_DOCS -include $(top_srcdir)/doc/xml/xmlrules-noinst.in -endif ENABLE_DEVEL_DOCS - -DOXYGEN_HEAD=\ - html/annotated.html - -DOXYGEN_REST= \ - dmx.txt \ - scaled.txt \ - html/ChkNotMaskEv_8c.html \ - html/ChkNotMaskEv_8h.html \ - html/ChkNotMaskEv_8h_source.html \ - html/classes.html \ - html/dmx_8h.html \ - html/dmx_8h_source.html \ - html/dmxarg_8c.html \ - html/dmxarg_8h.html \ - html/dmxarg_8h_source.html \ - html/dmxbackend_8c.html \ - html/dmxbackend_8h.html \ - html/dmxbackend_8h_source.html \ - html/dmxcb_8c.html \ - html/dmxcb_8h.html \ - html/dmxcb_8h_source.html \ - html/dmxclient_8h.html \ - html/dmxclient_8h_source.html \ - html/dmxcmap_8c.html \ - html/dmxcmap_8h.html \ - html/dmxcmap_8h_source.html \ - html/dmxcommon_8c.html \ - html/dmxcommon_8h.html \ - html/dmxcommon_8h_source.html \ - html/dmxcompat_8c.html \ - html/dmxcompat_8h.html \ - html/dmxcompat_8h_source.html \ - html/dmxconfig_8c.html \ - html/dmxconfig_8h.html \ - html/dmxconfig_8h_source.html \ - html/dmxconsole_8c.html \ - html/dmxconsole_8h.html \ - html/dmxconsole_8h_source.html \ - html/dmxcursor_8c.html \ - html/dmxcursor_8h.html \ - html/dmxcursor_8h_source.html \ - html/dmxdetach_8c.html \ - html/dmxdpms_8c.html \ - html/dmxdpms_8h.html \ - html/dmxdpms_8h_source.html \ - html/dmxdummy_8c.html \ - html/dmxdummy_8h.html \ - html/dmxdummy_8h_source.html \ - html/dmxevents_8c.html \ - html/dmxevents_8h.html \ - html/dmxevents_8h_source.html \ - html/dmxextension_8c.html \ - html/dmxextension_8h.html \ - html/dmxextension_8h_source.html \ - html/dmxfont_8c.html \ - html/dmxfont_8h.html \ - html/dmxfont_8h_source.html \ - html/dmxgc_8c.html \ - html/dmxgc_8h.html \ - html/dmxgc_8h_source.html \ - html/dmxgcops_8c.html \ - html/dmxgcops_8h.html \ - html/dmxgcops_8h_source.html \ - html/dmx__glxvisuals_8h_source.html \ - html/dmxinit_8c.html \ - html/dmxinit_8h.html \ - html/dmxinit_8h_source.html \ - html/dmxinput_8c.html \ - html/dmxinput_8h.html \ - html/dmxinput_8h_source.html \ - html/dmxinputinit_8c.html \ - html/dmxinputinit_8h.html \ - html/dmxinputinit_8h_source.html \ - html/dmxlog_8c.html \ - html/dmxlog_8h.html \ - html/dmxlog_8h_source.html \ - html/dmxmap_8c.html \ - html/dmxmap_8h.html \ - html/dmxmap_8h_source.html \ - html/dmxmotion_8c.html \ - html/dmxmotion_8h.html \ - html/dmxmotion_8h_source.html \ - html/dmxparse_8c.html \ - html/dmxparse_8h.html \ - html/dmxparse_8h_source.html \ - html/dmxpict_8c.html \ - html/dmxpict_8h.html \ - html/dmxpict_8h_source.html \ - html/dmxpixmap_8c.html \ - html/dmxpixmap_8h.html \ - html/dmxpixmap_8h_source.html \ - html/dmxprint_8c.html \ - html/dmxprint_8h.html \ - html/dmxprint_8h_source.html \ - html/dmxprop_8c.html \ - html/dmxprop_8h.html \ - html/dmxprop_8h_source.html \ - html/dmxscrinit_8c.html \ - html/dmxscrinit_8h.html \ - html/dmxscrinit_8h_source.html \ - html/dmxshadow_8c.html \ - html/dmxshadow_8h.html \ - html/dmxshadow_8h_source.html \ - html/dmxsigio_8c.html \ - html/dmxsigio_8h.html \ - html/dmxsigio_8h_source.html \ - html/dmxstat_8c.html \ - html/dmxstat_8h.html \ - html/dmxstat_8h_source.html \ - html/dmxsync_8c.html \ - html/dmxsync_8h.html \ - html/dmxsync_8h_source.html \ - html/dmxvisual_8c.html \ - html/dmxvisual_8h.html \ - html/dmxvisual_8h_source.html \ - html/dmxwindow_8c.html \ - html/dmxwindow_8h.html \ - html/dmxwindow_8h_source.html \ - html/dmxxinput_8c.html \ - html/doxygen.css \ - html/doxygen.png \ - html/files.html \ - html/ftv2blank.png \ - html/ftv2doc.png \ - html/ftv2folderclosed.png \ - html/ftv2folderopen.png \ - html/ftv2lastnode.png \ - html/ftv2link.png \ - html/ftv2mlastnode.png \ - html/ftv2mnode.png \ - html/ftv2node.png \ - html/ftv2plastnode.png \ - html/ftv2pnode.png \ - html/ftv2vertline.png \ - html/functions.html \ - html/functions_vars.html \ - html/globals_defs.html \ - html/globals_enum.html \ - html/globals_eval.html \ - html/globals_func.html \ - html/globals.html \ - html/globals_type.html \ - html/globals_vars.html \ - html/index.html \ - html/lnx-keyboard_8c.html \ - html/lnx-keyboard_8h.html \ - html/lnx-keyboard_8h_source.html \ - html/lnx-ms_8c.html \ - html/lnx-ms_8h.html \ - html/lnx-ms_8h_source.html \ - html/lnx-ps2_8c.html \ - html/lnx-ps2_8h.html \ - html/lnx-ps2_8h_source.html \ - html/main.html \ - html/struct__dmxArg.html \ - html/struct__dmxColormapPriv.html \ - html/structDMXConfigCmdStruct.html \ - html/struct__DMXConfigComment.html \ - html/struct__DMXConfigDisplay.html \ - html/struct__DMXConfigEntry.html \ - html/struct__DMXConfigFullDim.html \ - html/structDMXConfigListStruct.html \ - html/struct__DMXConfigNumber.html \ - html/struct__DMXConfigOption.html \ - html/struct__DMXConfigPair.html \ - html/struct__DMXConfigParam.html \ - html/struct__DMXConfigPartDim.html \ - html/struct__DMXConfigString.html \ - html/struct__DMXConfigSub.html \ - html/struct__DMXConfigToken.html \ - html/struct__DMXConfigVirtual.html \ - html/struct__DMXConfigWall.html \ - html/struct__dmxCursorPriv.html \ - html/structDMXDesktopAttributesRec.html \ - html/struct__DMXEventMap.html \ - html/struct__dmxFontPriv.html \ - html/struct__dmxGCPriv.html \ - html/structdmxGlxVisualPrivate.html \ - html/struct__dmxGlyphPriv.html \ - html/structDMXInputAttributesRec.html \ - html/struct__DMXInputInfo.html \ - html/struct__DMXLocalInitInfo.html \ - html/struct__DMXLocalInputInfo.html \ - html/struct__dmxPictPriv.html \ - html/struct__dmxPixPriv.html \ - html/structDMXScreenAttributesRec.html \ - html/struct__DMXScreenInfo.html \ - html/struct__DMXStatAvg.html \ - html/struct__DMXStatInfo.html \ - html/structDMXWindowAttributesRec.html \ - html/struct__dmxWinPriv.html \ - html/struct__myPrivate.html \ - html/tree.html \ - html/usb-common_8c.html \ - html/usb-common_8h.html \ - html/usb-common_8h_source.html \ - html/usb-keyboard_8c.html \ - html/usb-keyboard_8h.html \ - html/usb-keyboard_8h_source.html \ - html/usb-mouse_8c.html \ - html/usb-mouse_8h.html \ - html/usb-mouse_8h_source.html \ - html/usb-other_8c.html \ - html/usb-other_8h.html \ - html/usb-other_8h_source.html \ - html/usb-private_8h.html \ - html/usb-private_8h_source.html - -DOXYGEN_FILES=$(DOXYGEN_HEAD) $(DOXYGEN_REST) - -EXTRA_DIST = \ - $(XML_FILES) \ - DMXSpec.txt \ - DMXSpec-v1.txt \ - doxygen.conf \ - doxygen.css \ - doxygen.foot \ - doxygen.head \ - $(DOXYGEN_FILES) - -if ENABLE_DEVEL_DOCS -if HAVE_DOXYGEN - -DOXYGEN_SRC=doxygen.head doxygen.foot doxygen.css doxygen.conf - -all-local: $(DOXYGEN_FILES) - -dist-local: $(DOXYGEN_FILES) - -$(DOXYGEN_HEAD): $(DOXYGEN_SRC) - $(DOXYGEN) doxygen.conf - -$(DOXYGEN_REST): $(DOXYGEN_HEAD) - -maintainer-clean-local: - rm -rf html/ scaled.txt dmx.txt - -distclean-local: - rm -rf html/ scaled.txt dmx.txt - -endif HAVE_DOXYGEN -endif ENABLE_DEVEL_DOCS - -$(builddir)/doxygen.head: - $(LN_S) $(srcdir)/doxygen.head $@ - -$(builddir)/doxygen.foot: - $(LN_S) $(srcdir)/doxygen.foot $@ - -$(builddir)doxygen.css: - $(LN_S) $(srcdir)/doxygen.css $@ - +# Copyright 2005 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 +# not be used in advertising or publicity pertaining to distribution +# of the software without specific, written prior permission. Red +# Hat makes no representations about the suitability of this software +# for any purpose. It is provided "as is" without express or implied +# warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +# NO EVENT SHALL RED HAT 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. + +doc_sources = dmx.xml scaled.xml + +# Developer's documentation is not installed +if ENABLE_DEVEL_DOCS +include $(top_srcdir)/doc/xml/xmlrules-noinst.in +endif ENABLE_DEVEL_DOCS + +DOXYGEN_HEAD=\ + html/annotated.html + +DOXYGEN_REST= \ + html/ChkNotMaskEv_8c.html \ + html/ChkNotMaskEv_8h.html \ + html/ChkNotMaskEv_8h_source.html \ + html/classes.html \ + html/dmx_8h.html \ + html/dmx_8h_source.html \ + html/dmxarg_8c.html \ + html/dmxarg_8h.html \ + html/dmxarg_8h_source.html \ + html/dmxbackend_8c.html \ + html/dmxbackend_8h.html \ + html/dmxbackend_8h_source.html \ + html/dmxcb_8c.html \ + html/dmxcb_8h.html \ + html/dmxcb_8h_source.html \ + html/dmxclient_8h.html \ + html/dmxclient_8h_source.html \ + html/dmxcmap_8c.html \ + html/dmxcmap_8h.html \ + html/dmxcmap_8h_source.html \ + html/dmxcommon_8c.html \ + html/dmxcommon_8h.html \ + html/dmxcommon_8h_source.html \ + html/dmxcompat_8c.html \ + html/dmxcompat_8h.html \ + html/dmxcompat_8h_source.html \ + html/dmxconfig_8c.html \ + html/dmxconfig_8h.html \ + html/dmxconfig_8h_source.html \ + html/dmxconsole_8c.html \ + html/dmxconsole_8h.html \ + html/dmxconsole_8h_source.html \ + html/dmxcursor_8c.html \ + html/dmxcursor_8h.html \ + html/dmxcursor_8h_source.html \ + html/dmxdetach_8c.html \ + html/dmxdpms_8c.html \ + html/dmxdpms_8h.html \ + html/dmxdpms_8h_source.html \ + html/dmxdummy_8c.html \ + html/dmxdummy_8h.html \ + html/dmxdummy_8h_source.html \ + html/dmxevents_8c.html \ + html/dmxevents_8h.html \ + html/dmxevents_8h_source.html \ + html/dmxextension_8c.html \ + html/dmxextension_8h.html \ + html/dmxextension_8h_source.html \ + html/dmxfont_8c.html \ + html/dmxfont_8h.html \ + html/dmxfont_8h_source.html \ + html/dmxgc_8c.html \ + html/dmxgc_8h.html \ + html/dmxgc_8h_source.html \ + html/dmxgcops_8c.html \ + html/dmxgcops_8h.html \ + html/dmxgcops_8h_source.html \ + html/dmx__glxvisuals_8h_source.html \ + html/dmxinit_8c.html \ + html/dmxinit_8h.html \ + html/dmxinit_8h_source.html \ + html/dmxinput_8c.html \ + html/dmxinput_8h.html \ + html/dmxinput_8h_source.html \ + html/dmxinputinit_8c.html \ + html/dmxinputinit_8h.html \ + html/dmxinputinit_8h_source.html \ + html/dmxlog_8c.html \ + html/dmxlog_8h.html \ + html/dmxlog_8h_source.html \ + html/dmxmap_8c.html \ + html/dmxmap_8h.html \ + html/dmxmap_8h_source.html \ + html/dmxmotion_8c.html \ + html/dmxmotion_8h.html \ + html/dmxmotion_8h_source.html \ + html/dmxparse_8c.html \ + html/dmxparse_8h.html \ + html/dmxparse_8h_source.html \ + html/dmxpict_8c.html \ + html/dmxpict_8h.html \ + html/dmxpict_8h_source.html \ + html/dmxpixmap_8c.html \ + html/dmxpixmap_8h.html \ + html/dmxpixmap_8h_source.html \ + html/dmxprint_8c.html \ + html/dmxprint_8h.html \ + html/dmxprint_8h_source.html \ + html/dmxprop_8c.html \ + html/dmxprop_8h.html \ + html/dmxprop_8h_source.html \ + html/dmxscrinit_8c.html \ + html/dmxscrinit_8h.html \ + html/dmxscrinit_8h_source.html \ + html/dmxshadow_8c.html \ + html/dmxshadow_8h.html \ + html/dmxshadow_8h_source.html \ + html/dmxsigio_8c.html \ + html/dmxsigio_8h.html \ + html/dmxsigio_8h_source.html \ + html/dmxstat_8c.html \ + html/dmxstat_8h.html \ + html/dmxstat_8h_source.html \ + html/dmxsync_8c.html \ + html/dmxsync_8h.html \ + html/dmxsync_8h_source.html \ + html/dmxvisual_8c.html \ + html/dmxvisual_8h.html \ + html/dmxvisual_8h_source.html \ + html/dmxwindow_8c.html \ + html/dmxwindow_8h.html \ + html/dmxwindow_8h_source.html \ + html/dmxxinput_8c.html \ + html/doxygen.css \ + html/doxygen.png \ + html/files.html \ + html/ftv2blank.png \ + html/ftv2doc.png \ + html/ftv2folderclosed.png \ + html/ftv2folderopen.png \ + html/ftv2lastnode.png \ + html/ftv2link.png \ + html/ftv2mlastnode.png \ + html/ftv2mnode.png \ + html/ftv2node.png \ + html/ftv2plastnode.png \ + html/ftv2pnode.png \ + html/ftv2vertline.png \ + html/functions.html \ + html/functions_vars.html \ + html/globals_defs.html \ + html/globals_enum.html \ + html/globals_eval.html \ + html/globals_func.html \ + html/globals.html \ + html/globals_type.html \ + html/globals_vars.html \ + html/index.html \ + html/lnx-keyboard_8c.html \ + html/lnx-keyboard_8h.html \ + html/lnx-keyboard_8h_source.html \ + html/lnx-ms_8c.html \ + html/lnx-ms_8h.html \ + html/lnx-ms_8h_source.html \ + html/lnx-ps2_8c.html \ + html/lnx-ps2_8h.html \ + html/lnx-ps2_8h_source.html \ + html/main.html \ + html/struct__dmxArg.html \ + html/struct__dmxColormapPriv.html \ + html/structDMXConfigCmdStruct.html \ + html/struct__DMXConfigComment.html \ + html/struct__DMXConfigDisplay.html \ + html/struct__DMXConfigEntry.html \ + html/struct__DMXConfigFullDim.html \ + html/structDMXConfigListStruct.html \ + html/struct__DMXConfigNumber.html \ + html/struct__DMXConfigOption.html \ + html/struct__DMXConfigPair.html \ + html/struct__DMXConfigParam.html \ + html/struct__DMXConfigPartDim.html \ + html/struct__DMXConfigString.html \ + html/struct__DMXConfigSub.html \ + html/struct__DMXConfigToken.html \ + html/struct__DMXConfigVirtual.html \ + html/struct__DMXConfigWall.html \ + html/struct__dmxCursorPriv.html \ + html/structDMXDesktopAttributesRec.html \ + html/struct__DMXEventMap.html \ + html/struct__dmxFontPriv.html \ + html/struct__dmxGCPriv.html \ + html/structdmxGlxVisualPrivate.html \ + html/struct__dmxGlyphPriv.html \ + html/structDMXInputAttributesRec.html \ + html/struct__DMXInputInfo.html \ + html/struct__DMXLocalInitInfo.html \ + html/struct__DMXLocalInputInfo.html \ + html/struct__dmxPictPriv.html \ + html/struct__dmxPixPriv.html \ + html/structDMXScreenAttributesRec.html \ + html/struct__DMXScreenInfo.html \ + html/struct__DMXStatAvg.html \ + html/struct__DMXStatInfo.html \ + html/structDMXWindowAttributesRec.html \ + html/struct__dmxWinPriv.html \ + html/struct__myPrivate.html \ + html/tree.html \ + html/usb-common_8c.html \ + html/usb-common_8h.html \ + html/usb-common_8h_source.html \ + html/usb-keyboard_8c.html \ + html/usb-keyboard_8h.html \ + html/usb-keyboard_8h_source.html \ + html/usb-mouse_8c.html \ + html/usb-mouse_8h.html \ + html/usb-mouse_8h_source.html \ + html/usb-other_8c.html \ + html/usb-other_8h.html \ + html/usb-other_8h_source.html \ + html/usb-private_8h.html \ + html/usb-private_8h_source.html + +DOXYGEN_FILES=$(DOXYGEN_HEAD) $(DOXYGEN_REST) + +EXTRA_DIST = \ + DMXSpec.txt \ + DMXSpec-v1.txt \ + doxygen.conf \ + doxygen.css \ + doxygen.foot \ + doxygen.head \ + $(DOXYGEN_FILES) + +if ENABLE_DEVEL_DOCS +if HAVE_DOXYGEN + +DOXYGEN_SRC=doxygen.head doxygen.foot doxygen.css doxygen.conf + +all-local: $(DOXYGEN_FILES) + +dist-local: $(DOXYGEN_FILES) + +$(DOXYGEN_HEAD): $(DOXYGEN_SRC) + $(DOXYGEN) doxygen.conf + +$(DOXYGEN_REST): $(DOXYGEN_HEAD) + +maintainer-clean-local: + rm -rf html/ + +distclean-local: + rm -rf html/ + +endif HAVE_DOXYGEN +endif ENABLE_DEVEL_DOCS + +$(builddir)/doxygen.head: + $(LN_S) $(srcdir)/doxygen.head $@ + +$(builddir)/doxygen.foot: + $(LN_S) $(srcdir)/doxygen.foot $@ + +$(builddir)doxygen.css: + $(LN_S) $(srcdir)/doxygen.css $@ + diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am index c23b1fd6c..94ef966e2 100644 --- a/xorg-server/hw/xfree86/Makefile.am +++ b/xorg-server/hw/xfree86/Makefile.am @@ -1,120 +1,118 @@ - -if DRI -DRI_SUBDIR = dri -endif - -if DRI2 -DRI2_SUBDIR = dri2 -endif - -if XF86UTILS -XF86UTILS_SUBDIR = utils -endif - -if XAA -XAA_SUBDIR = xaa -endif - -if VGAHW -VGAHW_SUBDIR = vgahw -endif - -if VBE -VBE_SUBDIR = vbe -endif - -if INT10MODULE -INT10_SUBDIR = int10 -endif - -DOC_SUBDIR = doc - -SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw os-support parser \ - ramdac shadowfb $(VBE_SUBDIR) $(VGAHW_SUBDIR) $(XAA_SUBDIR) \ - loader dixmods exa modes \ - $(DRI_SUBDIR) $(DRI2_SUBDIR) $(XF86UTILS_SUBDIR) $(DOC_SUBDIR) - -DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \ - parser ramdac shadowfb vbe vgahw xaa \ - loader dixmods dri dri2 exa modes \ - utils doc - -bin_PROGRAMS = Xorg -Xorg_SOURCES = xorg.c - -AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@ -INCLUDES = @XORG_INCS@ - -noinst_LTLIBRARIES = libxorg.la -libxorg_la_SOURCES = libxorg.c -libxorg_la_LIBADD = \ - $(XSERVER_LIBS) \ - loader/libloader.la \ - os-support/libxorgos.la \ - common/libcommon.la \ - parser/libxf86config_internal.la \ - dixmods/libdixmods.la \ - modes/libxf86modes.la \ - ramdac/libramdac.la \ - ddc/libddc.la \ - i2c/libi2c.la \ - dixmods/libxorgxkb.la \ - $(top_builddir)/mi/libmi.la \ - $(top_builddir)/os/libos.la \ - @XORG_LIBS@ - -libxorg_la_DEPENDENCIES = $(libxorg_la_LIBADD) - -libxorg.c xorg.c: - touch $@ - -DISTCLEANFILES = libxorg.c xorg.c - -Xorg_DEPENDENCIES = libxorg.la -Xorg_LDADD = $(MAIN_LIB) libxorg.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) - -Xorg_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) - -BUILT_SOURCES = xorg.conf.example -DISTCLEANFILES += xorg.conf.example -EXTRA_DIST = xorgconf.cpp - -if SPECIAL_DTRACE_OBJECTS -# Re-add dtrace object code that gets lost when building static libraries -Xorg_LDADD += $(XSERVER_LIBS) -endif - -if SOLARIS_ASM_INLINE -# Needs to be built before any files are compiled when using Sun compilers -# so in*/out* inline definitions are properly processed. - -BUILT_SOURCES += os-support/solaris/solaris-@SOLARIS_INOUT_ARCH@.il - -os-support/solaris/solaris-@SOLARIS_INOUT_ARCH@.il: - cd os-support/solaris ; \ - $(MAKE) $(AM_MAKEFLAGS) solaris-@SOLARIS_INOUT_ARCH@.il -endif - -# do not use $(mkdir_p) if you want automake 1.7 to work -install-data-local: - mkdir -p $(DESTDIR)$(logdir) - - -install-exec-local: install-binPROGRAMS - (cd $(DESTDIR)$(bindir) && rm -f X && ln -s Xorg X) -if INSTALL_SETUID - chown root $(DESTDIR)$(bindir)/Xorg - chmod u+s $(DESTDIR)$(bindir)/Xorg -endif - -# Use variables from XORG_MANPAGE_SECTIONS and X Server configuration -# Do not include manpages.am as values are not appropriate for rc files -CONF_SUBSTS = -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g' \ - -e 's|MODULEPATH|$(DEFAULT_MODULE_PATH)|g' \ - -e 's|DEFAULTFONTPATH|$(COMPILEDDEFAULTFONTPATH)|g' - -xorg.conf.example: xorgconf.cpp - $(AM_V_GEN)$(SED) $(CONF_SUBSTS) < $< > $@ - -relink: - $(AM_V_at)rm -f Xorg && $(MAKE) Xorg + +if DRI +DRI_SUBDIR = dri +endif + +if DRI2 +DRI2_SUBDIR = dri2 +endif + +if XF86UTILS +XF86UTILS_SUBDIR = utils +endif + +if XAA +XAA_SUBDIR = xaa +endif + +if VGAHW +VGAHW_SUBDIR = vgahw +endif + +if VBE +VBE_SUBDIR = vbe +endif + +if INT10MODULE +INT10_SUBDIR = int10 +endif + +SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw os-support parser \ + ramdac shadowfb $(VBE_SUBDIR) $(VGAHW_SUBDIR) $(XAA_SUBDIR) \ + loader dixmods exa modes \ + $(DRI_SUBDIR) $(DRI2_SUBDIR) $(XF86UTILS_SUBDIR) doc man + +DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \ + parser ramdac shadowfb vbe vgahw xaa \ + loader dixmods dri dri2 exa modes \ + utils doc man + +bin_PROGRAMS = Xorg +Xorg_SOURCES = xorg.c + +AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@ +INCLUDES = @XORG_INCS@ + +noinst_LTLIBRARIES = libxorg.la +libxorg_la_SOURCES = libxorg.c +libxorg_la_LIBADD = \ + $(XSERVER_LIBS) \ + loader/libloader.la \ + os-support/libxorgos.la \ + common/libcommon.la \ + parser/libxf86config_internal.la \ + dixmods/libdixmods.la \ + modes/libxf86modes.la \ + ramdac/libramdac.la \ + ddc/libddc.la \ + i2c/libi2c.la \ + dixmods/libxorgxkb.la \ + $(top_builddir)/mi/libmi.la \ + $(top_builddir)/os/libos.la \ + @XORG_LIBS@ + +libxorg_la_DEPENDENCIES = $(libxorg_la_LIBADD) + +libxorg.c xorg.c: + touch $@ + +DISTCLEANFILES = libxorg.c xorg.c + +Xorg_DEPENDENCIES = libxorg.la +Xorg_LDADD = $(MAIN_LIB) libxorg.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) + +Xorg_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) + +BUILT_SOURCES = xorg.conf.example +DISTCLEANFILES += xorg.conf.example +EXTRA_DIST = xorgconf.cpp + +if SPECIAL_DTRACE_OBJECTS +# Re-add dtrace object code that gets lost when building static libraries +Xorg_LDADD += $(XSERVER_LIBS) +endif + +if SOLARIS_ASM_INLINE +# Needs to be built before any files are compiled when using Sun compilers +# so in*/out* inline definitions are properly processed. + +BUILT_SOURCES += os-support/solaris/solaris-@SOLARIS_INOUT_ARCH@.il + +os-support/solaris/solaris-@SOLARIS_INOUT_ARCH@.il: + cd os-support/solaris ; \ + $(MAKE) $(AM_MAKEFLAGS) solaris-@SOLARIS_INOUT_ARCH@.il +endif + +# do not use $(mkdir_p) if you want automake 1.7 to work +install-data-local: + mkdir -p $(DESTDIR)$(logdir) + + +install-exec-local: install-binPROGRAMS + (cd $(DESTDIR)$(bindir) && rm -f X && ln -s Xorg X) +if INSTALL_SETUID + chown root $(DESTDIR)$(bindir)/Xorg + chmod u+s $(DESTDIR)$(bindir)/Xorg +endif + +# Use variables from XORG_MANPAGE_SECTIONS and X Server configuration +# Do not include manpages.am as values are not appropriate for rc files +CONF_SUBSTS = -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g' \ + -e 's|MODULEPATH|$(DEFAULT_MODULE_PATH)|g' \ + -e 's|DEFAULTFONTPATH|$(COMPILEDDEFAULTFONTPATH)|g' + +xorg.conf.example: xorgconf.cpp + $(AM_V_GEN)$(SED) $(CONF_SUBSTS) < $< > $@ + +relink: + $(AM_V_at)rm -f Xorg && $(MAKE) Xorg diff --git a/xorg-server/hw/xfree86/common/xf86Configure.c b/xorg-server/hw/xfree86/common/xf86Configure.c index 883c48cc0..bccdd403c 100644 --- a/xorg-server/hw/xfree86/common/xf86Configure.c +++ b/xorg-server/hw/xfree86/common/xf86Configure.c @@ -1,765 +1,762 @@ -/* - * 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 -#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 - -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; idisp_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 ""; - case OPTV_STRING: - return ""; - case OPTV_ANYSTR: - return "[]"; - case OPTV_REAL: - return ""; - case OPTV_BOOLEAN: - return "[]"; - case OPTV_FREQ: - return ""; - case OPTV_PERCENT: - return ""; - 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: : integer, : float, " - ": \"True\"/\"False\",\n" - " ### : \"String\", : \" Hz/kHz/MHz\",\n" - " ### : \"%\"\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 && displaySizeLenmon_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; -} - -#if !defined(PATH_MAX) -# define PATH_MAX 1024 -#endif - -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; nnumEntities; 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 +#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; idisp_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 ""; + case OPTV_STRING: + return ""; + case OPTV_ANYSTR: + return "[]"; + case OPTV_REAL: + return ""; + case OPTV_BOOLEAN: + return "[]"; + case OPTV_FREQ: + return ""; + case OPTV_PERCENT: + return ""; + 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: : integer, : float, " + ": \"True\"/\"False\",\n" + " ### : \"String\", : \" Hz/kHz/MHz\",\n" + " ### : \"%\"\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 && displaySizeLenmon_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; nnumEntities; 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/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index 74365e10b..4166a1c38 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -1,1406 +1,1409 @@ -/* - * Copyright 1995-1999 by Frederic Lepied, France. - * - * 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 Frederic Lepied not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Frederic Lepied makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL FREDERIC LEPIED 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. - * - */ -/* - * Copyright (c) 2000-2002 by The XFree86 Project, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86Config.h" -#include "xf86Xinput.h" -#include "xf86Optrec.h" -#include "mipointer.h" -#include "extinit.h" -#include "loaderProcs.h" - -#include "exevents.h" /* AddInputDevice */ -#include "exglobals.h" -#include "eventstr.h" -#include "inpututils.h" - -#include /* InputClassMatches */ -#ifdef HAVE_FNMATCH_H -#include -#endif -#ifdef HAVE_SYS_UTSNAME_H -#include -#endif - -#include -#include /* for int64_t */ - -#include "mi.h" - -#include /* dix pointer acceleration */ -#include - -#ifdef XFreeXDGA -#include "dgaproc.h" -#endif - -#include "xkbsrv.h" - -/* Valuator verification macro */ -#define XI_VERIFY_VALUATORS(num_valuators) \ - if (num_valuators > MAX_VALUATORS) { \ - xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ - " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ - return; \ - } - -EventListPtr xf86Events = NULL; - -static int -xf86InputDevicePostInit(DeviceIntPtr dev); - -/** - * Eval config and modify DeviceVelocityRec accordingly - */ -static void -ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, - DeviceVelocityPtr s) -{ - int tempi; - float tempf; - Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); - Atom prop; - - if(!s) - return; - - /* common settings (available via device properties) */ - tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); - if (tempf > 1.0) { - xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", - devname, tempf); - prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); - if (tempf > 1.0) { - xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", - devname, tempf); - prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - /* select profile by number */ - tempi = xf86SetIntOption(list, "AccelerationProfile", - s->statistics.profile_number); - - prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); - if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, - PropModeReplace, 1, &tempi, FALSE) == Success) { - xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, - tempi); - } else { - xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", - devname, tempi); - } - - /* set scaling */ - tempf = xf86SetRealOption(list, "ExpectedRate", 0); - prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); - if (tempf > 0) { - tempf = 1000.0 / tempf; - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } else { - tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); - if (tempi > 1) - InitTrackers(s, tempi); - - s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", - s->initial_range); - - s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); - - tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); - if (tempf >= 0) { - xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", - devname, tempf*100.0); - s->max_rel_diff = tempf; - } - - /* Configure softening. If const deceleration is used, this is expected - * to provide better subpixel information so we enable - * softening by default only if ConstantDeceleration is not used - */ - s->use_softening = xf86SetBoolOption(list, "Softening", - s->const_acceleration == 1.0); - - s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", - s->average_accel); - - s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); -} - -static void -ApplyAccelerationSettings(DeviceIntPtr dev){ - int scheme, i; - DeviceVelocityPtr pVel; - InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; - char* schemeStr; - - if (dev->valuator && dev->ptrfeed) { - schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); - - scheme = dev->valuator->accelScheme.number; - - if (!xf86NameCmp(schemeStr, "predictable")) - scheme = PtrAccelPredictable; - - if (!xf86NameCmp(schemeStr, "lightweight")) - scheme = PtrAccelLightweight; - - if (!xf86NameCmp(schemeStr, "none")) - scheme = PtrAccelNoOp; - - /* reinit scheme if needed */ - if (dev->valuator->accelScheme.number != scheme) { - if (dev->valuator->accelScheme.AccelCleanupProc) { - dev->valuator->accelScheme.AccelCleanupProc(dev); - } - - if (InitPointerAccelerationScheme(dev, scheme)) { - xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", - pInfo->name, schemeStr, scheme); - } else { - xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", - pInfo->name, schemeStr); - scheme = dev->valuator->accelScheme.number; - } - } else { - xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", - pInfo->name, scheme); - } - - free(schemeStr); - - /* process special configuration */ - switch (scheme) { - case PtrAccelPredictable: - pVel = GetDevicePredictableAccelData(dev); - ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, - pVel); - break; - } - - i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", - dev->ptrfeed->ctrl.num); - if (i >= 0) - dev->ptrfeed->ctrl.num = i; - - i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", - dev->ptrfeed->ctrl.den); - if (i > 0) - dev->ptrfeed->ctrl.den = i; - - i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", - dev->ptrfeed->ctrl.threshold); - if (i >= 0) - dev->ptrfeed->ctrl.threshold = i; - - xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", - pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ - ((float)dev->ptrfeed->ctrl.den)); - xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", - pInfo->name, dev->ptrfeed->ctrl.threshold); - } -} - -/*********************************************************************** - * - * xf86ProcessCommonOptions -- - * - * Process global options. - * - *********************************************************************** - */ -void -xf86ProcessCommonOptions(InputInfoPtr pInfo, - pointer list) -{ - if (xf86SetBoolOption(list, "Floating", 0) || - !xf86SetBoolOption(list, "AlwaysCore", 1) || - !xf86SetBoolOption(list, "SendCoreEvents", 1) || - !xf86SetBoolOption(list, "CorePointer", 1) || - !xf86SetBoolOption(list, "CoreKeyboard", 1)) { - xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); - } else { - pInfo->flags |= XI86_ALWAYS_CORE; - xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); - } -} - -/*********************************************************************** - * - * xf86ActivateDevice -- - * - * Initialize an input device. - * - * Returns TRUE on success, or FALSE otherwise. - *********************************************************************** - */ -static DeviceIntPtr -xf86ActivateDevice(InputInfoPtr pInfo) -{ - DeviceIntPtr dev; - Atom atom; - - dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); - - if (dev == NULL) - { - xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", - pInfo->name); - pInfo->dev = NULL; - return NULL; - } - - atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); - AssignTypeAndName(dev, atom, pInfo->name); - dev->public.devicePrivate = pInfo; - pInfo->dev = dev; - - dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; - dev->type = SLAVE; - dev->spriteInfo->spriteOwner = FALSE; - - dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); - - if (serverGeneration == 1) - xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", - pInfo->name, pInfo->type_name); - - return dev; -} - -/**************************************************************************** - * - * Caller: ProcXSetDeviceMode - * - * Change the mode of an extension device. - * This function is used to change the mode of a device from reporting - * relative motion to reporting absolute positional information, and - * vice versa. - * The default implementation below is that no such devices are supported. - * - *********************************************************************** - */ - -int -SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) -{ - InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; - - if (pInfo->switch_mode) { - return (*pInfo->switch_mode)(client, dev, mode); - } - else - return BadMatch; -} - - -/*********************************************************************** - * - * Caller: ProcXSetDeviceValuators - * - * Set the value of valuators on an extension input device. - * This function is used to set the initial value of valuators on - * those input devices that are capable of reporting either relative - * motion or an absolute position, and allow an initial position to be set. - * The default implementation below is that no such devices are supported. - * - *********************************************************************** - */ - -int -SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, - int first_valuator, int num_valuators) -{ - InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; - - if (pInfo->set_device_valuators) - return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, - num_valuators); - - return BadMatch; -} - - -/*********************************************************************** - * - * Caller: ProcXChangeDeviceControl - * - * Change the specified device controls on an extension input device. - * - *********************************************************************** - */ - -int -ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) -{ - InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; - - if (!pInfo->control_proc) { - switch (control->control) { - case DEVICE_CORE: - return BadMatch; - case DEVICE_RESOLUTION: - case DEVICE_ABS_CALIB: - case DEVICE_ABS_AREA: - case DEVICE_ENABLE: - return Success; - default: - return BadMatch; - } - } - else { - return (*pInfo->control_proc)(pInfo, control); - } -} - -/* - * Get the operating system name from uname and store it statically to avoid - * repeating the system call each time MatchOS is checked. - */ -static const char * -HostOS(void) -{ -#ifdef HAVE_SYS_UTSNAME_H - struct utsname name; - static char host_os[sizeof(name.sysname)] = ""; - - if (*host_os == '\0') { - if (uname(&name) >= 0) - strcpy(host_os, name.sysname); - else { - strncpy(host_os, "unknown", sizeof(host_os)); - host_os[sizeof(host_os)-1] = '\0'; - } - } - return host_os; -#else - return ""; -#endif -} - -static int -match_substring(const char *attr, const char *pattern) -{ - return (strstr(attr, pattern)) ? 0 : -1; -} - -#ifdef HAVE_FNMATCH_H -static int -match_pattern(const char *attr, const char *pattern) -{ - return fnmatch(pattern, attr, 0); -} -#else -#define match_pattern match_substring -#endif - -#ifdef HAVE_FNMATCH_H -static int -match_path_pattern(const char *attr, const char *pattern) -{ - return fnmatch(pattern, attr, FNM_PATHNAME); -} -#else -#define match_path_pattern match_substring -#endif - -/* - * Match an attribute against a list of NULL terminated arrays of patterns. - * If a pattern in each list entry is matched, return TRUE. - */ -static Bool -MatchAttrToken(const char *attr, struct list *patterns, - int (*compare)(const char *attr, const char *pattern)) -{ - const xf86MatchGroup *group; - - /* If there are no patterns, accept the match */ - if (list_is_empty(patterns)) - return TRUE; - - /* If there are patterns but no attribute, reject the match */ - if (!attr) - return FALSE; - - /* - * Otherwise, iterate the list of patterns ensuring each entry has a - * match. Each list entry is a separate Match line of the same type. - */ - list_for_each_entry(group, patterns, entry) { - char * const *cur; - Bool match = FALSE; - - for (cur = group->values; *cur; cur++) - if ((*compare)(attr, *cur) == 0) { - match = TRUE; - break; - } - if (!match) - return FALSE; - } - - /* All the entries in the list matched the attribute */ - return TRUE; -} - -/* - * Classes without any Match statements match all devices. Otherwise, all - * statements must match. - */ -static Bool -InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, - const InputAttributes *attrs) -{ - /* MatchProduct substring */ - if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) - return FALSE; - - /* MatchVendor substring */ - if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) - return FALSE; - - /* MatchDevicePath pattern */ - if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) - return FALSE; - - /* MatchOS case-insensitive string */ - if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) - return FALSE; - - /* MatchPnPID pattern */ - if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) - return FALSE; - - /* MatchUSBID pattern */ - if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) - return FALSE; - - /* MatchDriver string */ - if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) - return FALSE; - - /* - * MatchTag string - * See if any of the device's tags match any of the MatchTag tokens. - */ - if (!list_is_empty(&iclass->match_tag)) { - char * const *tag; - Bool match; - - if (!attrs->tags) - return FALSE; - for (tag = attrs->tags, match = FALSE; *tag; tag++) { - if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { - match = TRUE; - break; - } - } - if (!match) - return FALSE; - } - - /* MatchIs* booleans */ - if (iclass->is_keyboard.set && - iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) - return FALSE; - if (iclass->is_pointer.set && - iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) - return FALSE; - if (iclass->is_joystick.set && - iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) - return FALSE; - if (iclass->is_tablet.set && - iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) - return FALSE; - if (iclass->is_touchpad.set && - iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) - return FALSE; - if (iclass->is_touchscreen.set && - iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) - return FALSE; - - return TRUE; -} - -/* - * Merge in any InputClass configurations. Options in each InputClass - * section have more priority than the original device configuration as - * well as any previous InputClass sections. - */ -static int -MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) -{ - XF86ConfInputClassPtr cl; - XF86OptionPtr classopts; - - for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { - if (!InputClassMatches(cl, idev, attrs)) - continue; - - /* Collect class options and driver settings */ - classopts = xf86optionListDup(cl->option_lst); - if (cl->driver) { - free(idev->driver); - idev->driver = xstrdup(cl->driver); - if (!idev->driver) { - xf86Msg(X_ERROR, "Failed to allocate memory while merging " - "InputClass configuration"); - return BadAlloc; - } - classopts = xf86ReplaceStrOption(classopts, "driver", - idev->driver); - } - - /* Apply options to device with InputClass settings preferred. */ - xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", - idev->name, cl->identifier); - idev->options = xf86optionListMerge(idev->options, classopts); - } - - return Success; -} - -/* - * Iterate the list of classes and look for Option "Ignore". Return the - * value of the last matching class and holler when returning TRUE. - */ -static Bool -IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) -{ - XF86ConfInputClassPtr cl; - Bool ignore = FALSE; - const char *ignore_class; - - for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { - if (!InputClassMatches(cl, idev, attrs)) - continue; - if (xf86findOption(cl->option_lst, "Ignore")) { - ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); - ignore_class = cl->identifier; - } - } - - if (ignore) - xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", - idev->name, ignore_class); - return ignore; -} - -InputInfoPtr -xf86AllocateInput(void) -{ - InputInfoPtr pInfo; - - pInfo = calloc(sizeof(*pInfo), 1); - if (!pInfo) - return NULL; - - pInfo->fd = -1; - pInfo->type_name = "UNKNOWN"; - - return pInfo; -} - -/* Append InputInfoRec to the tail of xf86InputDevs. */ -static void -xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) -{ - InputInfoPtr *prev = NULL; - - pInfo->drv = drv; - pInfo->module = DuplicateModule(drv->module, NULL); - - for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) - ; - - *prev = pInfo; - pInfo->next = NULL; - - xf86CollectInputOptions(pInfo, (const char**)drv->default_options); - xf86OptionListReport(pInfo->options); - xf86ProcessCommonOptions(pInfo, pInfo->options); -} - -/* - * Remove an entry from xf86InputDevs and free all the device's information. - */ -void -xf86DeleteInput(InputInfoPtr pInp, int flags) -{ - /* First check if the inputdev is valid. */ - if (pInp == NULL) - return; - - if (pInp->module) - UnloadModule(pInp->module); - - /* This should *really* be handled in drv->UnInit(dev) call instead, but - * if the driver forgets about it make sure we free it or at least crash - * with flying colors */ - free(pInp->private); - - FreeInputAttributes(pInp->attrs); - - /* Remove the entry from the list. */ - if (pInp == xf86InputDevs) - xf86InputDevs = pInp->next; - else { - InputInfoPtr p = xf86InputDevs; - while (p && p->next != pInp) - p = p->next; - if (p) - p->next = pInp->next; - /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ - } - - free(pInp->driver); - free(pInp->name); - xf86optionListFree(pInp->options); - free(pInp); -} - -/* - * Apply backend-specific initialization. Invoked after ActiveteDevice(), - * i.e. after the driver successfully completed DEVICE_INIT and the device - * is advertised. - * @param dev the device - * @return Success or an error code - */ -static int -xf86InputDevicePostInit(DeviceIntPtr dev) { - ApplyAccelerationSettings(dev); - return Success; -} - -/** - * Create a new input device, activate and enable it. - * - * Possible return codes: - * BadName .. a bad driver name was supplied. - * BadImplementation ... The driver does not have a PreInit function. This - * is a driver bug. - * BadMatch .. device initialization failed. - * BadAlloc .. too many input devices - * - * @param idev The device, already set up with identifier, driver, and the - * options. - * @param pdev Pointer to the new device, if Success was reported. - * @param enable Enable the device after activating it. - * - * @return Success or an error code - */ -_X_INTERNAL int -xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) -{ - InputDriverPtr drv = NULL; - DeviceIntPtr dev = NULL; - int rval; - - /* Memory leak for every attached device if we don't - * test if the module is already loaded first */ - drv = xf86LookupInputDriver(pInfo->driver); - if (!drv) - if (xf86LoadOneModule(pInfo->driver, NULL)) - drv = xf86LookupInputDriver(pInfo->driver); - if (!drv) { - xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); - rval = BadName; - goto unwind; - } - - if (!drv->PreInit) { - xf86Msg(X_ERROR, - "Input driver `%s' has no PreInit function (ignoring)\n", - drv->driverName); - rval = BadImplementation; - goto unwind; - } - - xf86AddInput(drv, pInfo); - - rval = drv->PreInit(drv, pInfo, 0); - - if (rval != Success) { - xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); - goto unwind; - } - - if (!(dev = xf86ActivateDevice(pInfo))) - { - rval = BadAlloc; - goto unwind; - } - - rval = ActivateDevice(dev, TRUE); - if (rval != Success) - { - xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); - RemoveDevice(dev, TRUE); - goto unwind; - } - - rval = xf86InputDevicePostInit(dev); - if (rval != Success) - { - xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); - RemoveDevice(dev, TRUE); - goto unwind; - } - - /* Enable it if it's properly initialised and we're currently in the VT */ - if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) - { - EnableDevice(dev, TRUE); - if (!dev->enabled) - { - xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); - rval = BadMatch; - goto unwind; - } - /* send enter/leave event, update sprite window */ - CheckMotion(NULL, dev); - } - - *pdev = dev; - return Success; - -unwind: - if(pInfo) { - if(drv && drv->UnInit) - drv->UnInit(drv, pInfo, 0); - else - xf86DeleteInput(pInfo, 0); - } - return rval; -} - -int -NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, - DeviceIntPtr *pdev) -{ - InputInfoPtr pInfo = NULL; - InputOption *option = NULL; - int rval = Success; - int is_auto = 0; - - pInfo = xf86AllocateInput(); - if (!pInfo) - return BadAlloc; - - for (option = options; option; option = option->next) { - if (strcasecmp(option->key, "driver") == 0) { - if (pInfo->driver) { - rval = BadRequest; - goto unwind; - } - pInfo->driver = xstrdup(option->value); - if (!pInfo->driver) { - rval = BadAlloc; - goto unwind; - } - } - - if (strcasecmp(option->key, "name") == 0 || - strcasecmp(option->key, "identifier") == 0) { - if (pInfo->name) { - rval = BadRequest; - goto unwind; - } - pInfo->name = xstrdup(option->value); - if (!pInfo->name) { - rval = BadAlloc; - goto unwind; - } - } - - if (strcmp(option->key, "_source") == 0 && - (strcmp(option->value, "server/hal") == 0 || - strcmp(option->value, "server/udev") == 0)) { - is_auto = 1; - if (!xf86Info.autoAddDevices) { - rval = BadMatch; - goto unwind; - } - } - } - - for (option = options; option; option = option->next) { - /* Steal option key/value strings from the provided list. - * We need those strings, the InputOption list doesn't. */ - pInfo->options = xf86addNewOption(pInfo->options, - option->key, option->value); - option->key = NULL; - option->value = NULL; - } - - /* Apply InputClass settings */ - if (attrs) { - if (IgnoreInputClass(pInfo, attrs)) { - rval = BadIDChoice; - goto unwind; - } - - rval = MergeInputClasses(pInfo, attrs); - if (rval != Success) - goto unwind; - - pInfo->attrs = DuplicateInputAttributes(attrs); - } - - if (!pInfo->driver || !pInfo->name) { - xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); - rval = BadRequest; - goto unwind; - } - - if (!pInfo->name) { - xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); - rval = BadMatch; - goto unwind; - } - - rval = xf86NewInputDevice(pInfo, pdev, - (!is_auto || (is_auto && xf86Info.autoEnableDevices))); - - return rval; - -unwind: - if (is_auto && !xf86Info.autoAddDevices) - xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); - xf86DeleteInput(pInfo, 0); - return rval; -} - -void -DeleteInputDeviceRequest(DeviceIntPtr pDev) -{ - InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; - InputDriverPtr drv = NULL; - Bool isMaster = IsMaster(pDev); - - if (pInfo) /* need to get these before RemoveDevice */ - drv = pInfo->drv; - - OsBlockSignals(); - RemoveDevice(pDev, TRUE); - - if (!isMaster && pInfo != NULL) - { - if(drv->UnInit) - drv->UnInit(drv, pInfo, 0); - else - xf86DeleteInput(pInfo, 0); - } - OsReleaseSignals(); -} - -/* - * convenient functions to post events - */ - -void -xf86PostMotionEvent(DeviceIntPtr device, - int is_absolute, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i = 0; - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_zero(&mask); - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); - va_end(var); - - xf86PostMotionEventM(device, is_absolute, &mask); -} - -void -xf86PostMotionEventP(DeviceIntPtr device, - int is_absolute, - int first_valuator, - int num_valuators, - const int *valuators) -{ - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); - xf86PostMotionEventM(device, is_absolute, &mask); -} - -void -xf86PostMotionEventM(DeviceIntPtr device, - int is_absolute, - const ValuatorMask *mask) -{ - int i = 0, nevents = 0; - DeviceEvent *event; - int flags = 0; - - if (valuator_mask_num_valuators(mask) > 0) - { - if (is_absolute) - flags = POINTER_ABSOLUTE; - else - flags = POINTER_RELATIVE | POINTER_ACCELERATE; - } - -#if XFreeXDGA - /* The evdev driver may not always send all axes across. */ - if (valuator_mask_isset(mask, 0) || - valuator_mask_isset(mask, 1)) - if (miPointerGetScreen(device)) { - int index = miPointerGetScreen(device)->myNum; - int dx = 0, dy = 0; - - if (valuator_mask_isset(mask, 0)) - { - dx = valuator_mask_get(mask, 0); - if (is_absolute) - dx -= device->last.valuators[0]; - } - - if (valuator_mask_isset(mask, 1)) - { - dy = valuator_mask_get(mask, 1); - if (is_absolute) - dy -= device->last.valuators[1]; - } - - if (DGAStealMotionEvent(device, index, dx, dy)) - return; - } -#endif - - 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)); - } -} - -void -xf86PostProximityEvent(DeviceIntPtr device, - int is_in, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i; - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_zero(&mask); - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); - va_end(var); - - xf86PostProximityEventM(device, is_in, &mask); -} - -void -xf86PostProximityEventP(DeviceIntPtr device, - int is_in, - int first_valuator, - int num_valuators, - const int *valuators) -{ - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); - xf86PostProximityEventM(device, is_in, &mask); -} - -void -xf86PostProximityEventM(DeviceIntPtr device, - int is_in, - const ValuatorMask *mask) -{ - int i, nevents; - - nevents = GetProximityEvents(xf86Events, device, - is_in ? ProximityIn : ProximityOut, mask); - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); - -} - -void -xf86PostButtonEvent(DeviceIntPtr device, - int is_absolute, - int button, - int is_down, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - ValuatorMask mask; - int i = 0; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_zero(&mask); - - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); - va_end(var); - - xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); -} - -void -xf86PostButtonEventP(DeviceIntPtr device, - int is_absolute, - int button, - int is_down, - int first_valuator, - int num_valuators, - const int *valuators) -{ - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); - xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); -} - -void -xf86PostButtonEventM(DeviceIntPtr device, - int is_absolute, - int button, - int is_down, - const ValuatorMask *mask) -{ - int i = 0, nevents = 0; - int flags = 0; - - if (valuator_mask_num_valuators(mask) > 0) - { - if (is_absolute) - flags = POINTER_ABSOLUTE; - else - flags = POINTER_RELATIVE | POINTER_ACCELERATE; - } - -#if XFreeXDGA - if (miPointerGetScreen(device)) { - int index = miPointerGetScreen(device)->myNum; - - if (DGAStealButtonEvent(device, index, button, is_down)) - return; - } -#endif - - nevents = GetPointerEvents(xf86Events, device, - is_down ? ButtonPress : ButtonRelease, button, - flags, mask); - - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); - -} - -void -xf86PostKeyEvent(DeviceIntPtr device, - unsigned int key_code, - int is_down, - int is_absolute, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i = 0; - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_zero(&mask); - - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); - va_end(var); - - xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); -} - -void -xf86PostKeyEventP(DeviceIntPtr device, - unsigned int key_code, - int is_down, - int is_absolute, - int first_valuator, - int num_valuators, - const int *valuators) -{ - ValuatorMask mask; - - XI_VERIFY_VALUATORS(num_valuators); - - valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); - xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); -} - -void -xf86PostKeyEventM(DeviceIntPtr device, - unsigned int key_code, - int is_down, - int is_absolute, - const ValuatorMask *mask) -{ - int i = 0, nevents = 0; - -#if XFreeXDGA - DeviceIntPtr pointer; - - /* Some pointers send key events, paired device is wrong then. */ - pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); - if (miPointerGetScreen(pointer)) { - int index = miPointerGetScreen(pointer)->myNum; - - if (DGAStealKeyEvent(device, index, key_code, is_down)) - return; - } -#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); - } - - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); -} - -void -xf86PostKeyboardEvent(DeviceIntPtr device, - unsigned int key_code, - int is_down) -{ - ValuatorMask mask; - - valuator_mask_zero(&mask); - xf86PostKeyEventM(device, key_code, is_down, 0, &mask); -} - -InputInfoPtr -xf86FirstLocalDevice(void) -{ - return xf86InputDevs; -} - -/* - * Cx - raw data from touch screen - * to_max - scaled highest dimension - * (remember, this is of rows - 1 because of 0 origin) - * to_min - scaled lowest dimension - * from_max - highest raw value from touch screen calibration - * from_min - lowest raw value from touch screen calibration - * - * This function is the same for X or Y coordinates. - * You may have to reverse the high and low values to compensate for - * different orgins on the touch screen vs X. - * - * e.g. to scale from device coordinates into screen coordinates, call - * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); - */ - -int -xf86ScaleAxis(int Cx, - int to_max, - int to_min, - int from_max, - int from_min ) -{ - int X; - int64_t to_width = to_max - to_min; - int64_t from_width = from_max - from_min; - - if (from_width) { - X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); - } - else { - X = 0; - ErrorF ("Divide by Zero in xf86ScaleAxis\n"); - } - - if (X > to_max) - X = to_max; - if (X < to_min) - X = to_min; - - return X; -} - -/* - * This function checks the given screen against the current screen and - * makes changes if appropriate. It should be called from an XInput driver's - * ReadInput function before any events are posted, if the device is screen - * specific like a touch screen. - */ -void -xf86XInputSetScreen(InputInfoPtr pInfo, - int screen_number, - int x, - int y) -{ - if (miPointerGetScreen(pInfo->dev) != - screenInfo.screens[screen_number]) { - miPointerSetScreen(pInfo->dev, screen_number, x, y); - } -} - - -void -xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, - int resolution, int min_res, int max_res, int mode) -{ - if (!dev || !dev->valuator) - return; - - InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, - max_res, mode); -} - -/* - * Set the valuator values to be in synch with dix/event.c - * DefineInitialRootWindow(). - */ -void -xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) -{ - if (axnum == 0) { - dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; - dev->last.valuators[0] = dev->valuator->axisVal[0]; - } - else if (axnum == 1) { - dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; - dev->last.valuators[1] = dev->valuator->axisVal[1]; - } -} - - -/** - * Deactivate a device. Call this function from the driver if you receive a - * read error or something else that spoils your day. - * Device will be moved to the off_devices list, but it will still be there - * until you really clean up after it. - * Notifies the client about an inactive device. - * - * @param panic True if device is unrecoverable and needs to be removed. - */ -void -xf86DisableDevice(DeviceIntPtr dev, Bool panic) -{ - if(!panic) - { - DisableDevice(dev, TRUE); - } else - { - SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); - DeleteInputDeviceRequest(dev); - } -} - -/** - * Reactivate a device. Call this function from the driver if you just found - * out that the read error wasn't quite that bad after all. - * Device will be re-activated, and an event sent to the client. - */ -void -xf86EnableDevice(DeviceIntPtr dev) -{ - EnableDevice(dev, TRUE); -} - -/* end of xf86Xinput.c */ +/* + * Copyright 1995-1999 by Frederic Lepied, France. + * + * 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 Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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. + * + */ +/* + * Copyright (c) 2000-2002 by The XFree86 Project, 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Config.h" +#include "xf86Xinput.h" +#include "xf86Optrec.h" +#include "mipointer.h" +#include "extinit.h" +#include "loaderProcs.h" + +#include "exevents.h" /* AddInputDevice */ +#include "exglobals.h" +#include "eventstr.h" +#include "inpututils.h" + +#include /* InputClassMatches */ +#ifdef HAVE_FNMATCH_H +#include +#endif +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif + +#include +#include /* for int64_t */ + +#include "mi.h" + +#include /* dix pointer acceleration */ +#include + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include "xkbsrv.h" + +/* Valuator verification macro */ +#define XI_VERIFY_VALUATORS(num_valuators) \ + if (num_valuators > MAX_VALUATORS) { \ + xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ + " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ + return; \ + } + +EventListPtr xf86Events = NULL; + +static int +xf86InputDevicePostInit(DeviceIntPtr dev); + +/** + * Eval config and modify DeviceVelocityRec accordingly + */ +static void +ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, + DeviceVelocityPtr s) +{ + int tempi; + float tempf; + Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); + Atom prop; + + if(!s) + return; + + /* common settings (available via device properties) */ + tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + /* select profile by number */ + tempi = xf86SetIntOption(list, "AccelerationProfile", + s->statistics.profile_number); + + prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); + if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, + PropModeReplace, 1, &tempi, FALSE) == Success) { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, + tempi); + } else { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", + devname, tempi); + } + + /* set scaling */ + tempf = xf86SetRealOption(list, "ExpectedRate", 0); + prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); + if (tempf > 0) { + tempf = 1000.0 / tempf; + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } else { + tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); + if (tempi > 1) + InitTrackers(s, tempi); + + s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", + s->initial_range); + + s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); + + tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); + if (tempf >= 0) { + xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", + devname, tempf*100.0); + s->max_rel_diff = tempf; + } + + /* Configure softening. If const deceleration is used, this is expected + * to provide better subpixel information so we enable + * softening by default only if ConstantDeceleration is not used + */ + s->use_softening = xf86SetBoolOption(list, "Softening", + s->const_acceleration == 1.0); + + s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", + s->average_accel); + + s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); +} + +static void +ApplyAccelerationSettings(DeviceIntPtr dev){ + int scheme, i; + DeviceVelocityPtr pVel; + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + char* schemeStr; + + if (dev->valuator && dev->ptrfeed) { + schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); + + scheme = dev->valuator->accelScheme.number; + + if (!xf86NameCmp(schemeStr, "predictable")) + scheme = PtrAccelPredictable; + + if (!xf86NameCmp(schemeStr, "lightweight")) + scheme = PtrAccelLightweight; + + if (!xf86NameCmp(schemeStr, "none")) + scheme = PtrAccelNoOp; + + /* reinit scheme if needed */ + if (dev->valuator->accelScheme.number != scheme) { + if (dev->valuator->accelScheme.AccelCleanupProc) { + dev->valuator->accelScheme.AccelCleanupProc(dev); + } + + if (InitPointerAccelerationScheme(dev, scheme)) { + xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", + pInfo->name, schemeStr, scheme); + } else { + xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", + pInfo->name, schemeStr); + scheme = dev->valuator->accelScheme.number; + } + } else { + xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", + pInfo->name, scheme); + } + + free(schemeStr); + + /* process special configuration */ + switch (scheme) { + case PtrAccelPredictable: + pVel = GetDevicePredictableAccelData(dev); + ProcessVelocityConfiguration (dev, pInfo->name, pInfo->options, + pVel); + break; + } + + i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", + dev->ptrfeed->ctrl.num); + if (i >= 0) + dev->ptrfeed->ctrl.num = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", + dev->ptrfeed->ctrl.den); + if (i > 0) + dev->ptrfeed->ctrl.den = i; + + i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", + dev->ptrfeed->ctrl.threshold); + if (i >= 0) + dev->ptrfeed->ctrl.threshold = i; + + xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", + pInfo->name, ((float)dev->ptrfeed->ctrl.num)/ + ((float)dev->ptrfeed->ctrl.den)); + xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", + pInfo->name, dev->ptrfeed->ctrl.threshold); + } +} + +/*********************************************************************** + * + * xf86ProcessCommonOptions -- + * + * Process global options. + * + *********************************************************************** + */ +void +xf86ProcessCommonOptions(InputInfoPtr pInfo, + pointer list) +{ + if (xf86SetBoolOption(list, "Floating", 0) || + !xf86SetBoolOption(list, "AlwaysCore", 1) || + !xf86SetBoolOption(list, "SendCoreEvents", 1) || + !xf86SetBoolOption(list, "CorePointer", 1) || + !xf86SetBoolOption(list, "CoreKeyboard", 1)) { + xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); + } else { + pInfo->flags |= XI86_ALWAYS_CORE; + xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); + } +} + +/*********************************************************************** + * + * xf86ActivateDevice -- + * + * Initialize an input device. + * + * Returns TRUE on success, or FALSE otherwise. + *********************************************************************** + */ +static DeviceIntPtr +xf86ActivateDevice(InputInfoPtr pInfo) +{ + DeviceIntPtr dev; + Atom atom; + + dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); + + if (dev == NULL) + { + xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", + pInfo->name); + pInfo->dev = NULL; + return NULL; + } + + atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); + AssignTypeAndName(dev, atom, pInfo->name); + dev->public.devicePrivate = pInfo; + pInfo->dev = dev; + + dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; + dev->type = SLAVE; + dev->spriteInfo->spriteOwner = FALSE; + + dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); + + if (serverGeneration == 1) + xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", + pInfo->name, pInfo->type_name); + + return dev; +} + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (pInfo->switch_mode) { + return (*pInfo->switch_mode)(client, dev, mode); + } + else + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, + int first_valuator, int num_valuators) +{ + InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; + + if (pInfo->set_device_valuators) + return (*pInfo->set_device_valuators)(pInfo, valuators, first_valuator, + num_valuators); + + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + *********************************************************************** + */ + +int +ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) +{ + InputInfoPtr pInfo = (InputInfoPtr)dev->public.devicePrivate; + + if (!pInfo->control_proc) { + switch (control->control) { + case DEVICE_CORE: + return BadMatch; + case DEVICE_RESOLUTION: + case DEVICE_ABS_CALIB: + case DEVICE_ABS_AREA: + case DEVICE_ENABLE: + return Success; + default: + return BadMatch; + } + } + else { + return (*pInfo->control_proc)(pInfo, control); + } +} + +/* + * Get the operating system name from uname and store it statically to avoid + * repeating the system call each time MatchOS is checked. + */ +static const char * +HostOS(void) +{ +#ifdef HAVE_SYS_UTSNAME_H + struct utsname name; + static char host_os[sizeof(name.sysname)] = ""; + + if (*host_os == '\0') { + if (uname(&name) >= 0) + strcpy(host_os, name.sysname); + else { + strncpy(host_os, "unknown", sizeof(host_os)); + host_os[sizeof(host_os)-1] = '\0'; + } + } + return host_os; +#else + return ""; +#endif +} + +static int +match_substring(const char *attr, const char *pattern) +{ + return (strstr(attr, pattern)) ? 0 : -1; +} + +#ifdef HAVE_FNMATCH_H +static int +match_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, 0); +} +#else +#define match_pattern match_substring +#endif + +#ifdef HAVE_FNMATCH_H +static int +match_path_pattern(const char *attr, const char *pattern) +{ + return fnmatch(pattern, attr, FNM_PATHNAME); +} +#else +#define match_path_pattern match_substring +#endif + +/* + * Match an attribute against a list of NULL terminated arrays of patterns. + * If a pattern in each list entry is matched, return TRUE. + */ +static Bool +MatchAttrToken(const char *attr, struct list *patterns, + int (*compare)(const char *attr, const char *pattern)) +{ + const xf86MatchGroup *group; + + /* If there are no patterns, accept the match */ + if (list_is_empty(patterns)) + return TRUE; + + /* If there are patterns but no attribute, reject the match */ + if (!attr) + return FALSE; + + /* + * Otherwise, iterate the list of patterns ensuring each entry has a + * match. Each list entry is a separate Match line of the same type. + */ + list_for_each_entry(group, patterns, entry) { + char * const *cur; + Bool match = FALSE; + + for (cur = group->values; *cur; cur++) + if ((*compare)(attr, *cur) == 0) { + match = TRUE; + break; + } + if (!match) + return FALSE; + } + + /* All the entries in the list matched the attribute */ + return TRUE; +} + +/* + * Classes without any Match statements match all devices. Otherwise, all + * statements must match. + */ +static Bool +InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, + const InputAttributes *attrs) +{ + /* MatchProduct substring */ + if (!MatchAttrToken(attrs->product, &iclass->match_product, match_substring)) + return FALSE; + + /* MatchVendor substring */ + if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) + return FALSE; + + /* MatchDevicePath pattern */ + if (!MatchAttrToken(attrs->device, &iclass->match_device, match_path_pattern)) + return FALSE; + + /* MatchOS case-insensitive string */ + if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) + return FALSE; + + /* MatchPnPID pattern */ + if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) + return FALSE; + + /* MatchUSBID pattern */ + if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) + return FALSE; + + /* MatchDriver string */ + if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) + return FALSE; + + /* + * MatchTag string + * See if any of the device's tags match any of the MatchTag tokens. + */ + if (!list_is_empty(&iclass->match_tag)) { + char * const *tag; + Bool match; + + if (!attrs->tags) + return FALSE; + for (tag = attrs->tags, match = FALSE; *tag; tag++) { + if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { + match = TRUE; + break; + } + } + if (!match) + return FALSE; + } + + /* MatchIs* booleans */ + if (iclass->is_keyboard.set && + iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) + return FALSE; + if (iclass->is_pointer.set && + iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) + return FALSE; + if (iclass->is_joystick.set && + iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) + return FALSE; + if (iclass->is_tablet.set && + iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) + return FALSE; + if (iclass->is_touchpad.set && + iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) + return FALSE; + if (iclass->is_touchscreen.set && + iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) + return FALSE; + + return TRUE; +} + +/* + * Merge in any InputClass configurations. Options in each InputClass + * section have more priority than the original device configuration as + * well as any previous InputClass sections. + */ +static int +MergeInputClasses(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + XF86OptionPtr classopts; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + + /* Collect class options and driver settings */ + classopts = xf86optionListDup(cl->option_lst); + if (cl->driver) { + free(idev->driver); + idev->driver = xstrdup(cl->driver); + if (!idev->driver) { + xf86Msg(X_ERROR, "Failed to allocate memory while merging " + "InputClass configuration"); + return BadAlloc; + } + classopts = xf86ReplaceStrOption(classopts, "driver", + idev->driver); + } + + /* Apply options to device with InputClass settings preferred. */ + xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", + idev->name, cl->identifier); + idev->options = xf86optionListMerge(idev->options, classopts); + } + + return Success; +} + +/* + * Iterate the list of classes and look for Option "Ignore". Return the + * value of the last matching class and holler when returning TRUE. + */ +static Bool +IgnoreInputClass(const InputInfoPtr idev, const InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + Bool ignore = FALSE; + const char *ignore_class; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, idev, attrs)) + continue; + if (xf86findOption(cl->option_lst, "Ignore")) { + ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); + ignore_class = cl->identifier; + } + } + + if (ignore) + xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", + idev->name, ignore_class); + return ignore; +} + +InputInfoPtr +xf86AllocateInput(void) +{ + InputInfoPtr pInfo; + + pInfo = calloc(sizeof(*pInfo), 1); + if (!pInfo) + return NULL; + + pInfo->fd = -1; + pInfo->type_name = "UNKNOWN"; + + return pInfo; +} + +/* Append InputInfoRec to the tail of xf86InputDevs. */ +static void +xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) +{ + InputInfoPtr *prev = NULL; + + pInfo->drv = drv; + pInfo->module = DuplicateModule(drv->module, NULL); + + for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) + ; + + *prev = pInfo; + pInfo->next = NULL; + + xf86CollectInputOptions(pInfo, (const char**)drv->default_options); + xf86OptionListReport(pInfo->options); + xf86ProcessCommonOptions(pInfo, pInfo->options); +} + +/* + * Remove an entry from xf86InputDevs and free all the device's information. + */ +void +xf86DeleteInput(InputInfoPtr pInp, int flags) +{ + /* First check if the inputdev is valid. */ + if (pInp == NULL) + return; + + if (pInp->module) + UnloadModule(pInp->module); + + /* This should *really* be handled in drv->UnInit(dev) call instead, but + * if the driver forgets about it make sure we free it or at least crash + * with flying colors */ + free(pInp->private); + + FreeInputAttributes(pInp->attrs); + + /* Remove the entry from the list. */ + if (pInp == xf86InputDevs) + xf86InputDevs = pInp->next; + else { + InputInfoPtr p = xf86InputDevs; + while (p && p->next != pInp) + p = p->next; + if (p) + p->next = pInp->next; + /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ + } + + free(pInp->driver); + free(pInp->name); + xf86optionListFree(pInp->options); + free(pInp); +} + +/* + * Apply backend-specific initialization. Invoked after ActiveteDevice(), + * i.e. after the driver successfully completed DEVICE_INIT and the device + * is advertised. + * @param dev the device + * @return Success or an error code + */ +static int +xf86InputDevicePostInit(DeviceIntPtr dev) { + ApplyAccelerationSettings(dev); + return Success; +} + +/** + * Create a new input device, activate and enable it. + * + * Possible return codes: + * BadName .. a bad driver name was supplied. + * BadImplementation ... The driver does not have a PreInit function. This + * is a driver bug. + * BadMatch .. device initialization failed. + * BadAlloc .. too many input devices + * + * @param idev The device, already set up with identifier, driver, and the + * options. + * @param pdev Pointer to the new device, if Success was reported. + * @param enable Enable the device after activating it. + * + * @return Success or an error code + */ +_X_INTERNAL int +xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) +{ + InputDriverPtr drv = NULL; + DeviceIntPtr dev = NULL; + int rval; + + /* Memory leak for every attached device if we don't + * test if the module is already loaded first */ + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) + if (xf86LoadOneModule(pInfo->driver, NULL)) + drv = xf86LookupInputDriver(pInfo->driver); + if (!drv) { + xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); + rval = BadName; + goto unwind; + } + + if (!drv->PreInit) { + xf86Msg(X_ERROR, + "Input driver `%s' has no PreInit function (ignoring)\n", + drv->driverName); + rval = BadImplementation; + goto unwind; + } + + xf86AddInput(drv, pInfo); + + rval = drv->PreInit(drv, pInfo, 0); + + if (rval != Success) { + xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); + goto unwind; + } + + if (!(dev = xf86ActivateDevice(pInfo))) + { + rval = BadAlloc; + goto unwind; + } + + rval = ActivateDevice(dev, TRUE); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + rval = xf86InputDevicePostInit(dev); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); + RemoveDevice(dev, TRUE); + goto unwind; + } + + /* Enable it if it's properly initialised and we're currently in the VT */ + if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) + { + OsBlockSignals(); + EnableDevice(dev, TRUE); + if (!dev->enabled) + { + OsReleaseSignals(); + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); + rval = BadMatch; + goto unwind; + } + /* send enter/leave event, update sprite window */ + CheckMotion(NULL, dev); + OsReleaseSignals(); + } + + *pdev = dev; + return Success; + +unwind: + if(pInfo) { + if(drv && drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + return rval; +} + +int +NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, + DeviceIntPtr *pdev) +{ + InputInfoPtr pInfo = NULL; + InputOption *option = NULL; + int rval = Success; + int is_auto = 0; + + pInfo = xf86AllocateInput(); + if (!pInfo) + return BadAlloc; + + for (option = options; option; option = option->next) { + if (strcasecmp(option->key, "driver") == 0) { + if (pInfo->driver) { + rval = BadRequest; + goto unwind; + } + pInfo->driver = xstrdup(option->value); + if (!pInfo->driver) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcasecmp(option->key, "name") == 0 || + strcasecmp(option->key, "identifier") == 0) { + if (pInfo->name) { + rval = BadRequest; + goto unwind; + } + pInfo->name = xstrdup(option->value); + if (!pInfo->name) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcmp(option->key, "_source") == 0 && + (strcmp(option->value, "server/hal") == 0 || + strcmp(option->value, "server/udev") == 0)) { + is_auto = 1; + if (!xf86Info.autoAddDevices) { + rval = BadMatch; + goto unwind; + } + } + } + + for (option = options; option; option = option->next) { + /* Steal option key/value strings from the provided list. + * We need those strings, the InputOption list doesn't. */ + pInfo->options = xf86addNewOption(pInfo->options, + option->key, option->value); + option->key = NULL; + option->value = NULL; + } + + /* Apply InputClass settings */ + if (attrs) { + if (IgnoreInputClass(pInfo, attrs)) { + rval = BadIDChoice; + goto unwind; + } + + rval = MergeInputClasses(pInfo, attrs); + if (rval != Success) + goto unwind; + + pInfo->attrs = DuplicateInputAttributes(attrs); + } + + if (!pInfo->driver || !pInfo->name) { + xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); + rval = BadRequest; + goto unwind; + } + + if (!pInfo->name) { + xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); + rval = BadMatch; + goto unwind; + } + + rval = xf86NewInputDevice(pInfo, pdev, + (!is_auto || (is_auto && xf86Info.autoEnableDevices))); + + return rval; + +unwind: + if (is_auto && !xf86Info.autoAddDevices) + xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); + xf86DeleteInput(pInfo, 0); + return rval; +} + +void +DeleteInputDeviceRequest(DeviceIntPtr pDev) +{ + InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; + InputDriverPtr drv = NULL; + Bool isMaster = IsMaster(pDev); + + if (pInfo) /* need to get these before RemoveDevice */ + drv = pInfo->drv; + + OsBlockSignals(); + RemoveDevice(pDev, TRUE); + + if (!isMaster && pInfo != NULL) + { + if(drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + OsReleaseSignals(); +} + +/* + * convenient functions to post events + */ + +void +xf86PostMotionEvent(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventP(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostMotionEventM(device, is_absolute, &mask); +} + +void +xf86PostMotionEventM(DeviceIntPtr device, + int is_absolute, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + DeviceEvent *event; + int flags = 0; + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + /* The evdev driver may not always send all axes across. */ + if (valuator_mask_isset(mask, 0) || + valuator_mask_isset(mask, 1)) + if (miPointerGetScreen(device)) { + int index = miPointerGetScreen(device)->myNum; + int dx = 0, dy = 0; + + if (valuator_mask_isset(mask, 0)) + { + dx = valuator_mask_get(mask, 0); + if (is_absolute) + dx -= device->last.valuators[0]; + } + + if (valuator_mask_isset(mask, 1)) + { + dy = valuator_mask_get(mask, 1); + if (is_absolute) + dy -= device->last.valuators[1]; + } + + if (DGAStealMotionEvent(device, index, dx, dy)) + return; + } +#endif + + 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)); + } +} + +void +xf86PostProximityEvent(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventP(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostProximityEventM(device, is_in, &mask); +} + +void +xf86PostProximityEventM(DeviceIntPtr device, + int is_in, + const ValuatorMask *mask) +{ + int i, nevents; + + nevents = GetProximityEvents(xf86Events, device, + is_in ? ProximityIn : ProximityOut, mask); + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostButtonEvent(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + ValuatorMask mask; + int i = 0; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventP(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); +} + +void +xf86PostButtonEventM(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + int flags = 0; + + if (valuator_mask_num_valuators(mask) > 0) + { + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + } + +#if XFreeXDGA + if (miPointerGetScreen(device)) { + int index = miPointerGetScreen(device)->myNum; + + if (DGAStealButtonEvent(device, index, button, is_down)) + return; + } +#endif + + nevents = GetPointerEvents(xf86Events, device, + is_down ? ButtonPress : ButtonRelease, button, + flags, mask); + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostKeyEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_zero(&mask); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); + va_end(var); + + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventP(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + const int *valuators) +{ + ValuatorMask mask; + + XI_VERIFY_VALUATORS(num_valuators); + + valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); + xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); +} + +void +xf86PostKeyEventM(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + const ValuatorMask *mask) +{ + int i = 0, nevents = 0; + +#if XFreeXDGA + DeviceIntPtr pointer; + + /* Some pointers send key events, paired device is wrong then. */ + pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); + if (miPointerGetScreen(pointer)) { + int index = miPointerGetScreen(pointer)->myNum; + + if (DGAStealKeyEvent(device, index, key_code, is_down)) + return; + } +#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); + } + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); +} + +void +xf86PostKeyboardEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down) +{ + ValuatorMask mask; + + valuator_mask_zero(&mask); + xf86PostKeyEventM(device, key_code, is_down, 0, &mask); +} + +InputInfoPtr +xf86FirstLocalDevice(void) +{ + return xf86InputDevs; +} + +/* + * Cx - raw data from touch screen + * to_max - scaled highest dimension + * (remember, this is of rows - 1 because of 0 origin) + * to_min - scaled lowest dimension + * from_max - highest raw value from touch screen calibration + * from_min - lowest raw value from touch screen calibration + * + * This function is the same for X or Y coordinates. + * You may have to reverse the high and low values to compensate for + * different orgins on the touch screen vs X. + * + * e.g. to scale from device coordinates into screen coordinates, call + * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); + */ + +int +xf86ScaleAxis(int Cx, + int to_max, + int to_min, + int from_max, + int from_min ) +{ + int X; + int64_t to_width = to_max - to_min; + int64_t from_width = from_max - from_min; + + if (from_width) { + X = (int)(((to_width * (Cx - from_min)) / from_width) + to_min); + } + else { + X = 0; + ErrorF ("Divide by Zero in xf86ScaleAxis\n"); + } + + if (X > to_max) + X = to_max; + if (X < to_min) + X = to_min; + + return X; +} + +/* + * This function checks the given screen against the current screen and + * makes changes if appropriate. It should be called from an XInput driver's + * ReadInput function before any events are posted, if the device is screen + * specific like a touch screen. + */ +void +xf86XInputSetScreen(InputInfoPtr pInfo, + int screen_number, + int x, + int y) +{ + if (miPointerGetScreen(pInfo->dev) != + screenInfo.screens[screen_number]) { + miPointerSetScreen(pInfo->dev, screen_number, x, y); + } +} + + +void +xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, + int resolution, int min_res, int max_res, int mode) +{ + if (!dev || !dev->valuator) + return; + + InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, + max_res, mode); +} + +/* + * Set the valuator values to be in synch with dix/event.c + * DefineInitialRootWindow(). + */ +void +xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) +{ + if (axnum == 0) { + dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + dev->last.valuators[0] = dev->valuator->axisVal[0]; + } + else if (axnum == 1) { + dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; + dev->last.valuators[1] = dev->valuator->axisVal[1]; + } +} + + +/** + * Deactivate a device. Call this function from the driver if you receive a + * read error or something else that spoils your day. + * Device will be moved to the off_devices list, but it will still be there + * until you really clean up after it. + * Notifies the client about an inactive device. + * + * @param panic True if device is unrecoverable and needs to be removed. + */ +void +xf86DisableDevice(DeviceIntPtr dev, Bool panic) +{ + if(!panic) + { + DisableDevice(dev, TRUE); + } else + { + SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); + DeleteInputDeviceRequest(dev); + } +} + +/** + * Reactivate a device. Call this function from the driver if you just found + * out that the read error wasn't quite that bad after all. + * Device will be re-activated, and an event sent to the client. + */ +void +xf86EnableDevice(DeviceIntPtr dev) +{ + EnableDevice(dev, TRUE); +} + +/* end of xf86Xinput.c */ diff --git a/xorg-server/hw/xfree86/doc/Makefile.am b/xorg-server/hw/xfree86/doc/Makefile.am index 80217365d..acb8937f0 100644 --- a/xorg-server/hw/xfree86/doc/Makefile.am +++ b/xorg-server/hw/xfree86/doc/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = devel man sgml - -EXTRA_DIST = \ - README.modes +SUBDIRS = devel sgml + +EXTRA_DIST = \ + README.modes diff --git a/xorg-server/hw/xfree86/doc/man/Makefile.am b/xorg-server/hw/xfree86/doc/man/Makefile.am deleted file mode 100644 index 80e22cbab..000000000 --- a/xorg-server/hw/xfree86/doc/man/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -include $(top_srcdir)/manpages.am -appman_PRE = Xorg.man -fileman_PRE = xorg.conf.man xorg.conf.d.man diff --git a/xorg-server/hw/xfree86/doc/man/Xorg.man b/xorg-server/hw/xfree86/doc/man/Xorg.man deleted file mode 100644 index 6fa334cc3..000000000 --- a/xorg-server/hw/xfree86/doc/man/Xorg.man +++ /dev/null @@ -1,689 +0,0 @@ -.\" $XdotOrg: xserver/xorg/hw/xfree86/doc/man/Xorg.man.pre,v 1.3 2005/07/04 18:41:01 ajax Exp $ -.\" shorthand for double quote that works everywhere. -.ds q \N'34' -.TH __xservername__ __appmansuffix__ __vendorversion__ -.SH NAME -__xservername__ - X11R7 X server -.SH SYNOPSIS -.B __xservername__ -.RI [\fB:\fP display ] -.RI [ option -.IR ... ] -.SH DESCRIPTION -.B __xservername__ -is a full featured X server that was originally designed for UNIX and -UNIX-like operating systems running on Intel x86 hardware. It now runs -on a wider range of hardware and OS platforms. -.PP -This work was derived by the X.Org Foundation from the XFree86 Project's -.I "XFree86\ 4.4rc2" -release. -The XFree86 release was originally derived from -.I "X386\ 1.2" -by Thomas Roell which was contributed to X11R5 by Snitily Graphics -Consulting Service. -.SH PLATFORMS -.PP -.B __xservername__ -operates under a wide range of operating systems and hardware platforms. -The Intel x86 (IA32) architecture is the most widely supported hardware -platform. Other hardware platforms include Compaq Alpha, Intel IA64, AMD64, -SPARC and PowerPC. The most widely supported operating systems are the -free/OpenSource UNIX-like systems such as Linux, FreeBSD, NetBSD, -OpenBSD, and Solaris. Commercial UNIX operating systems such as -UnixWare are also supported. Other supported operating systems include -GNU Hurd. Mac OS X is supported with the -Xquartz(__appmansuffix__) X server. Win32/Cygwin is supported with the -XWin(__appmansuffix__) X server. -.PP -.SH "NETWORK CONNECTIONS" -.B __xservername__ -supports connections made using the following reliable -byte-streams: -.TP 4 -.I "Local" -On most platforms, the "Local" connection type is a UNIX-domain socket. -On some System V platforms, the "local" connection types also include -STREAMS pipes, named pipes, and some other mechanisms. -.TP 4 -.I TCP\/IP -.B __xservername__ -listens on port -.RI 6000+ n , -where -.I n -is the display number. This connection type can be disabled with the -.B \-nolisten -option (see the Xserver(1) man page for details). -.SH "ENVIRONMENT VARIABLES" -For operating systems that support local connections other than Unix -Domain sockets (SVR3 and SVR4), there is a compiled-in list specifying -the order in which local connections should be attempted. This list -can be overridden by the -.I XLOCAL -environment variable described below. If the display name indicates a -best-choice connection should be made (e.g. -.BR :0.0 ), -each connection mechanism is tried until a connection succeeds or no -more mechanisms are available. Note: for these OSs, the Unix Domain -socket connection is treated differently from the other local connection -types. To use it the connection must be made to -.BR unix:0.0 . -.PP -The -.I XLOCAL -environment variable should contain a list of one more -more of the following: -.PP -.RS 8 -.nf -NAMED -PTS -SCO -ISC -.fi -.RE -.PP -which represent SVR4 Named Streams pipe, Old-style USL Streams pipe, -SCO XSight Streams pipe, and ISC Streams pipe, respectively. You can -select a single mechanism (e.g. -.IR XLOCAL=NAMED ), -or an ordered list (e.g. \fIXLOCAL="NAMED:PTS:SCO"\fP). -his variable overrides the compiled-in defaults. For SVR4 it is -recommended that -.I NAMED -be the first preference connection. The default setting is -.IR PTS:NAMED:ISC:SCO . -.PP -To globally override the compiled-in defaults, you should define (and -export if using -.B sh -or -.BR ksh ) -.I XLOCAL -globally. If you use startx(1) or xinit(1), the definition should be -at the top of your -.I .xinitrc -file. If you use xdm(1), the definitions should be early on in the -.I __projectroot__/lib/X11/xdm/Xsession -script. -.SH OPTIONS -.B __xservername__ -supports several mechanisms for supplying/obtaining configuration and -run-time parameters: command line options, environment variables, the -__xconfigfile__(__filemansuffix__) configuration files, auto-detection, and -fallback defaults. When the same information is supplied in more than -one way, the highest precedence mechanism is used. The list of mechanisms -is ordered from highest precedence to lowest. Note that not all parameters -can be supplied via all methods. The available command line options -and environment variables (and some defaults) are described here and in -the Xserver(__appmansuffix__) manual page. Most configuration file -parameters, with their defaults, are described in the -__xconfigfile__(__filemansuffix__) manual page. Driver and module specific -configuration parameters are described in the relevant driver or module -manual page. -.PP -In addition to the normal server options described in the -Xserver(__appmansuffix__) manual page, -.B __xservername__ -accepts the following command line switches: -.TP 8 -.BI vt XX -.I XX -specifies the Virtual Terminal device number which -.B __xservername__ -will use. Without this option, -.B __xservername__ -will pick the first available Virtual Terminal that it can locate. This -option applies only to platforms that have virtual terminal support, such -as Linux, BSD, OpenSolaris, SVR3, and SVR4. -.TP -.B \-allowMouseOpenFail -Allow the server to start up even if the mouse device can't be opened -or initialised. This is equivalent to the -.B AllowMouseOpenFail -__xconfigfile__(__filemansuffix__) file option. -.TP 8 -.B \-allowNonLocalXvidtune -Make the VidMode extension available to remote clients. This allows -the xvidtune client to connect from another host. This is equivalent -to the -.B AllowNonLocalXvidtune -__xconfigfile__(__filemansuffix__) file option. By default non-local -connections are not allowed. -.TP 8 -.BI \-bgamma " value" -Set the blue gamma correction. -.I value -must be between 0.1 and 10. -The default is 1.0. Not all drivers support this. See also the -.BR \-gamma , -.BR \-rgamma , -and -.B \-ggamma -options. -.TP 8 -.BI \-bpp " n" -No longer supported. Use -.B \-depth -to set the color depth, and use -.B \-fbbpp -if you really need to force a non-default framebuffer (hardware) pixel -format. -.TP 8 -.BI \-config " file" -Read the server configuration from -.IR file . -This option will work for any file when the server is run as root (i.e, -with real-uid 0), or for files relative to a directory in the config -search path for all other users. -.TP 8 -.BI \-configdir " directory" -Read the server configuration files from -.IR directory . -This option will work for any directory when the server is run as root -(i.e, with real-uid 0), or for directories relative to a directory in the -config directory search path for all other users. -.TP 8 -.B \-configure -When this option is specified, the -.B __xservername__ -server loads all video driver modules, probes for available hardware, -and writes out an initial __xconfigfile__(__filemansuffix__) file based on -what was detected. This option currently has some problems on some -platforms, but in most cases it is a good way to bootstrap the -configuration process. This option is only available when the server -is run as root (i.e, with real-uid 0). -.TP 8 -.BI "\-crt /dev/tty" XX -SCO only. This is the same as the -.B vt -option, and is provided for compatibility with the native SCO X server. -.TP 8 -.BI \-depth " n" -Sets the default color depth. Legal values are 1, 4, 8, 15, 16, and -24. Not all drivers support all values. -.TP 8 -.B \-disableVidMode -Disable the parts of the VidMode extension (used by the xvidtune -client) that can be used to change the video modes. This is equivalent -to the -.B DisableVidModeExtension -__xconfigfile__(__filemansuffix__) file option. -.TP 8 -.B \-fbbpp \fIn\fP -Sets the number of framebuffer bits per pixel. You should only set this -if you're sure it's necessary; normally the server can deduce the correct -value from -.B \-depth -above. Useful if you want to run a depth 24 configuration with a 24 -bpp framebuffer rather than the (possibly default) 32 bpp framebuffer -(or vice versa). Legal values are 1, 8, 16, 24, 32. Not all drivers -support all values. -.TP 8 -.B \-flipPixels -Swap the default values for the black and white pixels. -.TP 8 -.BI \-gamma " value" -Set the gamma correction. -.I value -must be between 0.1 and 10. The default is 1.0. This value is applied -equally to the R, G and B values. Those values can be set independently -with the -.BR \-rgamma , -.BR \-bgamma , -and -.B \-ggamma -options. Not all drivers support this. -.TP 8 -.BI \-ggamma " value" -Set the green gamma correction. -.I value -must be between 0.1 and 10. The default is 1.0. Not all drivers support -this. See also the -.BR \-gamma , -.BR \-rgamma , -and -.B \-bgamma -options. -.TP 8 -.B \-ignoreABI -The -.B __xservername__ -server checks the ABI revision levels of each module that it loads. It -will normally refuse to load modules with ABI revisions that are newer -than the server's. This is because such modules might use interfaces -that the server does not have. When this option is specified, mismatches -like this are downgraded from fatal errors to warnings. This option -should be used with care. -.TP 8 -.B \-isolateDevice \fIbus\-id\fP -Restrict device resets to the device at -.IR bus\-id . -The -.I bus\-id -string has the form -.IB bustype : bus : device : function -(e.g., \(oqPCI:1:0:0\(cq). -At present, only isolation of PCI devices is supported; i.e., this option -is ignored if -.I bustype -is anything other than \(oqPCI\(cq. -.TP 8 -.B \-keeptty -Prevent the server from detaching its initial controlling terminal. -This option is only useful when debugging the server. Not all platforms -support (or can use) this option. -.TP 8 -.BI \-keyboard " keyboard-name" -Use the __xconfigfile__(__filemansuffix__) file -.B InputDevice -section called -.I keyboard-name -as the core keyboard. This option is ignored when the -.B Layout -section specifies a core keyboard. In the absence of both a Layout -section and this option, the first relevant -.B InputDevice -section is used for the core keyboard. -.TP 8 -.BI \-layout " layout-name" -Use the __xconfigfile__(__filemansuffix__) file -.B Layout -section called -.IR layout-name . -By default the first -.B Layout -section is used. -.TP 8 -.BI \-logfile " filename" -Use the file called -.I filename -as the -.B __xservername__ -server log file. The default log file is -.BI __logdir__/__xservername__. n .log -on most platforms, where -.I n -is the display number of the -.B __xservername__ -server. The default may be in a different directory on some platforms. -This option is only available when the server is run as root (i.e, with -real-uid 0). -.TP 8 -.BR \-logverbose " [\fIn\fP]" -Sets the verbosity level for information printed to the -.B __xservername__ -server log file. If the -.I n -value isn't supplied, each occurrence of this option increments the log -file verbosity level. When the -.I n -value is supplied, the log file verbosity level is set to that value. -The default log file verbosity level is 3. -.TP 8 -.BI \-modulepath " searchpath" -Set the module search path to -.IR searchpath . -.I searchpath -is a comma separated list of directories to search for -.B __xservername__ -server modules. This option is only available when the server is run -as root (i.e, with real-uid 0). -.TP 8 -.B \-nosilk -Disable Silken Mouse support. -.TP 8 -.B \-pixmap24 -Set the internal pixmap format for depth 24 pixmaps to 24 bits per pixel. -The default is usually 32 bits per pixel. There is normally little -reason to use this option. Some client applications don't like this -pixmap format, even though it is a perfectly legal format. This is -equivalent to the -.B Pixmap -__xconfigfile__(__filemansuffix__) file option. -.TP 8 -.B \-pixmap32 -Set the internal pixmap format for depth 24 pixmaps to 32 bits per pixel. -This is usually the default. This is equivalent to the -.B Pixmap -__xconfigfile__(__filemansuffix__) file option. -.TP 8 -.BI \-pointer " pointer-name" -Use the __xconfigfile__(__filemansuffix__) file -.B InputDevice -section called -.I pointer-name -as the core pointer. This option is ignored when the -.B Layout -section specifies a core pointer. In the absence of both a Layout -section and this option, the first relevant -.B InputDevice -section is used for the core pointer. -.TP 8 -.B \-quiet -Suppress most informational messages at startup. The verbosity level -is set to zero. -.TP 8 -.BI \-rgamma " value" -Set the red gamma correction. -.I value -must be between 0.1 and 10. The default is 1.0. Not all drivers support -this. See also the -.BR \-gamma , -.BR \-bgamma , -and -.B \-ggamma -options. -.TP 8 -.BI \-screen " screen-name" -Use the __xconfigfile__(__filemansuffix__) file -.B Screen -section called -.IR screen-name . -By default the screens referenced by the default -.B Layout -section are used, or the first -.B Screen -section when there are no -.B Layout -sections. -.TP 8 -.B \-showconfig -This is the same as the -.B \-version -option, and is included for compatibility reasons. It may be removed -in a future release, so the -.B \-version -option should be used instead. -.TP 8 -.B \-showDefaultModulePath -Print out the default module path the server was compiled with. -.TP 8 -.B \-showDefaultLibPath -Print out the path libraries should be installed to. -.TP 8 -.B \-showopts -For each driver module installed, print out the list of options and their -argument types. -.TP 8 -.BI \-weight " nnn" -Set RGB weighting at 16 bpp. The default is 565. This applies only to -those drivers which support 16 bpp. -.TP 8 -.BR \-verbose " [\fIn\fP]" -Sets the verbosity level for information printed on stderr. If the -.I n -value isn't supplied, each occurrence of this option increments the -verbosity level. When the -.I n -value is supplied, the verbosity level is set to that value. The default -verbosity level is 0. -.TP 8 -.B \-version -Print out the server version, patchlevel, release date, the operating -system/platform it was built on, and whether it includes module loader -support. -.SH "KEYBOARD" -.PP -The -.B __xservername__ -server is normally configured to recognize various special combinations -of key presses that instruct the server to perform some action, rather -than just sending the key press event to a client application. These actions -depend on the XKB keymap loaded by a particular keyboard device and may or -may not be available on a given configuration. -.PP -The following key combinations are commonly part of the default XKEYBOARD -keymap. -.TP 8 -.B Ctrl+Alt+Backspace -Immediately kills the server -- no questions asked. It can be disabled by -setting the -.B DontZap -__xconfigfile__(__filemansuffix__) file option to a TRUE value. -.PP -.RS 8 -It should be noted that zapping is triggered by the -.B Terminate_Server -action in the keyboard map. This action is not part of the default keymaps -but can be enabled with the XKB option -.B \*qterminate:ctrl_alt_bksp\*q. -.RE -.TP 8 -.B Ctrl+Alt+Keypad-Plus -Change video mode to next one specified in the configuration file. -This can be disabled with the -.B DontZoom -__xconfigfile__(__filemansuffix__) file option. -.TP 8 -.B Ctrl+Alt+Keypad-Minus -Change video mode to previous one specified in the configuration file. -This can be disabled with the -.B DontZoom -__xconfigfile__(__filemansuffix__) file option. -.TP 8 -.B Ctrl+Alt+F1...F12 -For systems with virtual terminal support, these keystroke -combinations are used to switch to virtual terminals 1 through 12, -respectively. This can be disabled with the -.B DontVTSwitch -__xconfigfile__(__filemansuffix__) file option. -.SH CONFIGURATION -.B __xservername__ -typically uses a configuration file called -.B __xconfigfile__ -and configuration files with the suffix -.I .conf -in a directory called -.B __xconfigdir__ -for its initial setup. -Refer to the __xconfigfile__(__filemansuffix__) manual page for information -about the format of this file. -.PP -.B __xservername__ -has a mechanism for automatically generating a built-in configuration -at run-time when no -.B __xconfigfile__ -file or -.B __xconfigdir__ -files are present. The current version of this automatic configuration -mechanism works in two ways. -.PP -The first is via enhancements that have made many components of the -.B __xconfigfile__ -file optional. This means that information that can be probed or -reasonably deduced doesn't need to be specified explicitly, greatly -reducing the amount of built-in configuration information that needs to -be generated at run-time. -.PP -The second is to have "safe" fallbacks for most configuration information. -This maximises the likelihood that the -.B __xservername__ -server will start up in some usable configuration even when information -about the specific hardware is not available. -.PP -The automatic configuration support for __xservername__ is work in progress. -It is currently aimed at the most popular hardware and software platforms -supported by __xservername__. Enhancements are planned for future releases. -.SH FILES -The -.B __xservername__ -server config files can be found in a range of locations. These are -documented fully in the __xconfigfile__(__filemansuffix__) manual page. The -most commonly used locations are shown here. -.TP 30 -.B /etc/X11/__xconfigfile__ -Server configuration file. -.TP 30 -.B /etc/X11/__xconfigfile__-4 -Server configuration file. -.TP 30 -.B /etc/__xconfigfile__ -Server configuration file. -.TP 30 -.B __projectroot__/etc/__xconfigfile__ -Server configuration file. -.TP 30 -.B __projectroot__/lib/X11/__xconfigfile__ -Server configuration file. -.TP 30 -.B /etc/X11/__xconfigdir__ -Server configuration directory. -.TP 30 -.B /etc/X11/__xconfigdir__-4 -Server configuration directory. -.TP 30 -.B /etc/__xconfigdir__ -Server configuration directory. -.TP 30 -.B __projectroot__/etc/__xconfigdir__ -Server configuration directory. -.TP 30 -.B __projectroot__/lib/X11/__xconfigdir__ -Server configuration directory. -.TP 30 -.BI __logdir__/__xservername__. n .log -Server log file for display -.IR n . -.TP 30 -.B __projectroot__/bin/\(** -Client binaries. -.TP 30 -.B __projectroot__/include/\(** -Header files. -.TP 30 -.B __projectroot__/lib/\(** -Libraries. -.TP 30 -.B __datadir__/fonts/X11/\(** -Fonts. -.TP 30 -.B __projectroot__/share/X11/XErrorDB -Client error message database. -.TP 30 -.B __projectroot__/lib/X11/app-defaults/\(** -Client resource specifications. -.TP 30 -.B __mandir__/man?/\(** -Manual pages. -.TP 30 -.BI /etc/X n .hosts -Initial access control list for display -.IR n . -.SH "SEE ALSO" -X(__miscmansuffix__), Xserver(__appmansuffix__), xdm(__appmansuffix__), xinit(__appmansuffix__), -__xconfigfile__(__filemansuffix__), xvidtune(__appmansuffix__), -apm(__drivermansuffix__), -ati(__drivermansuffix__), -chips(__drivermansuffix__), -cirrus(__drivermansuffix__), -cyrix(__drivermansuffix__), -fbdev(__drivermansuffix__), -glide(__drivermansuffix__), -glint(__drivermansuffix__), -i128(__drivermansuffix__), -i740(__drivermansuffix__), -imstt(__drivermansuffix__), -intel(__drivermansuffix__), -mga(__drivermansuffix__), -neomagic(__drivermansuffix__), -nsc(__drivermansuffix__), -nv(__drivermansuffix__), -openchrome (__drivermansuffix__), -r128(__drivermansuffix__), -rendition(__drivermansuffix__), -s3virge(__drivermansuffix__), -siliconmotion(__drivermansuffix__), -sis(__drivermansuffix__), -sunbw2(__drivermansuffix__), -suncg14(__drivermansuffix__), -suncg3(__drivermansuffix__), -suncg6(__drivermansuffix__), -sunffb(__drivermansuffix__), -sunleo(__drivermansuffix__), -suntcx(__drivermansuffix__), -tdfx(__drivermansuffix__), -tga(__drivermansuffix__), -trident(__drivermansuffix__), -tseng(__drivermansuffix__), -v4l(__drivermansuffix__), -vesa(__drivermansuffix__), -vmware(__drivermansuffix__), -.br -Web site -.IR . - -.SH AUTHORS -__xservername__ has many contributors world wide. The names of most of them -can be found in the documentation, ChangeLog files in the source tree, -and in the actual source code. -.PP -__xservername__ was originally based on XFree86 4.4rc2. -That was originally based on \fIX386 1.2\fP by Thomas Roell, which -was contributed to the then X Consortium's X11R5 distribution by SGCS. -.PP -__xservername__ is released by the X.Org Foundation. -.PP -The project that became XFree86 was originally founded in 1992 by -David Dawes, Glenn Lai, Jim Tsillas and David Wexelblat. -.PP -XFree86 was later integrated in the then X Consortium's X11R6 release -by a group of dedicated XFree86 developers, including the following: -.PP -.RS 4 -.nf -Stuart Anderson \fIanderson@metrolink.com\fP -Doug Anson \fIdanson@lgc.com\fP -Gertjan Akkerman \fIakkerman@dutiba.twi.tudelft.nl\fP -Mike Bernson \fImike@mbsun.mlb.org\fP -Robin Cutshaw \fIrobin@XFree86.org\fP -David Dawes \fIdawes@XFree86.org\fP -Marc Evans \fImarc@XFree86.org\fP -Pascal Haible \fIhaible@izfm.uni-stuttgart.de\fP -Matthieu Herrb \fIMatthieu.Herrb@laas.fr\fP -Dirk Hohndel \fIhohndel@XFree86.org\fP -David Holland \fIdavidh@use.com\fP -Alan Hourihane \fIalanh@fairlite.demon.co.uk\fP -Jeffrey Hsu \fIhsu@soda.berkeley.edu\fP -Glenn Lai \fIglenn@cs.utexas.edu\fP -Ted Lemon \fImellon@ncd.com\fP -Rich Murphey \fIrich@XFree86.org\fP -Hans Nasten \fInasten@everyware.se\fP -Mark Snitily \fImark@sgcs.com\fP -Randy Terbush \fIrandyt@cse.unl.edu\fP -Jon Tombs \fItombs@XFree86.org\fP -Kees Verstoep \fIversto@cs.vu.nl\fP -Paul Vixie \fIpaul@vix.com\fP -Mark Weaver \fIMark_Weaver@brown.edu\fP -David Wexelblat \fIdwex@XFree86.org\fP -Philip Wheatley \fIPhilip.Wheatley@ColumbiaSC.NCR.COM\fP -Thomas Wolfram \fIwolf@prz.tu-berlin.de\fP -Orest Zborowski \fIorestz@eskimo.com\fP -.fi -.RE -.PP -__xservername__ source is available from the FTP server -\fI\fP, and from the X.Org -server \fI\fP. Documentation and other -information can be found from the X.Org web site -\fI\fP. - -.SH LEGAL -.PP -.B __xservername__ -is copyright software, provided under licenses that permit modification -and redistribution in source and binary form without fee. -.B __xservername__ is copyright by numerous authors and -contributors from around the world. Licensing information can be found -at -.IR . -Refer to the source code for specific copyright notices. -.PP -.B XFree86(TM) -is a trademark of The XFree86 Project, Inc. -.PP -.B X11(TM) -and -.B X Window System(TM) -are trademarks of The Open Group. diff --git a/xorg-server/hw/xfree86/doc/man/xorg.conf.d.man b/xorg-server/hw/xfree86/doc/man/xorg.conf.d.man deleted file mode 100644 index 6b3379ece..000000000 --- a/xorg-server/hw/xfree86/doc/man/xorg.conf.d.man +++ /dev/null @@ -1 +0,0 @@ -.so man__filemansuffix__/xorg.conf.__filemansuffix__ diff --git a/xorg-server/hw/xfree86/doc/man/xorg.conf.man b/xorg-server/hw/xfree86/doc/man/xorg.conf.man deleted file mode 100644 index e3fd0eadf..000000000 --- a/xorg-server/hw/xfree86/doc/man/xorg.conf.man +++ /dev/null @@ -1,2478 +0,0 @@ -.\" shorthand for double quote that works everywhere. -.ds q \N'34' -.TH __xconfigfile__ __filemansuffix__ __vendorversion__ -.SH NAME -__xconfigfile__ and __xconfigdir__ \- configuration files for -__xservername__ X server -.SH INTRODUCTION -.B __xservername__ -supports several mechanisms for supplying/obtaining configuration and -run-time parameters: command line options, environment variables, the -__xconfigfile__ and __xconfigdir__ configuration files, auto-detection, -and fallback defaults. When the same information is supplied in more -than one way, the highest precedence mechanism is used. The list of -mechanisms is ordered from highest precedence to lowest. Note that not -all parameters can be supplied via all methods. The available command -line options and environment variables (and some defaults) are -described in the Xserver(__appmansuffix__) and -__xservername__(__appmansuffix__) manual pages. Most configuration file -parameters, with their defaults, are described below. Driver and module -specific configuration parameters are described in the relevant driver -or module manual page. -.SH DESCRIPTION -.B __xservername__ -uses a configuration file called -.I __xconfigfile__ -and files ending in the suffix -.I .conf -from the directory -.I __xconfigdir__ -for its initial setup. -The -.I __xconfigfile__ -configuration file is searched for in the following places when the -server is started as a normal user: -.PP -.RS 4 -.nf -.IR /etc/X11/ -.IR __projectroot__/etc/X11/ -.IB /etc/X11/ $XORGCONFIG -.IB __projectroot__/etc/X11/ $XORGCONFIG -.I /etc/X11/__xconfigfile__ -.I /etc/__xconfigfile__ -.IR __projectroot__/etc/X11/__xconfigfile__. -.I __projectroot__/etc/X11/__xconfigfile__ -.IR __projectroot__/lib/X11/__xconfigfile__. -.I __projectroot__/lib/X11/__xconfigfile__ -.fi -.RE -.PP -where -.I -is a relative path (with no \(lq..\(rq components) specified with the -.B \-config -command line option, -.B $XORGCONFIG -is the relative path (with no \(lq..\(rq components) specified by that -environment variable, and -.I -is the machine's hostname as reported by -.BR gethostname (__libmansuffix__). -.PP -When the __xservername__ server is started by the \(lqroot\(rq user, the config file -search locations are as follows: -.PP -.RS 4 -.nf - -.IR /etc/X11/ -.IR __projectroot__/etc/X11/ -.B $XORGCONFIG -.IB /etc/X11/ $XORGCONFIG -.IB __projectroot__/etc/X11/ $XORGCONFIG -.I /etc/X11/__xconfigfile__ -.I /etc/__xconfigfile__ -.IR __projectroot__/etc/X11/__xconfigfile__. -.I __projectroot__/etc/X11/__xconfigfile__ -.IR __projectroot__/lib/X11/__xconfigfile__. -.I __projectroot__/lib/X11/__xconfigfile__ -.fi -.RE -.PP -where -.I -is the path specified with the -.B \-config -command line option (which may be absolute or relative), -.B $XORGCONFIG -is the path specified by that -environment variable (absolute or relative), -.B $HOME -is the path specified by that environment variable (usually the home -directory), and -.I -is the machine's hostname as reported by -.BR gethostname (__libmansuffix__). -.PP -Additional configuration files are searched for in the following -directories when the server is started as a normal user: -.PP -.RS 4 -.nf -.IR /etc/X11/ -.IR __sysconfdir__/X11/ -.I /etc/X11/__xconfigdir__ -.I __sysconfdir__/X11/__xconfigdir__ -.fi -.RE -.PP -where -.I -is a relative path (with no \(lq..\(rq components) specified with the -.B \-configdir -command line option. -.PP -When the __xservername__ server is started by the \(lqroot\(rq user, the -config directory search locations are as follows: -.PP -.RS 4 -.nf - -.IR /etc/X11/ -.IR __sysconfdir__/X11/ -.I /etc/X11/__xconfigdir__ -.I __sysconfdir__/X11/__xconfigdir__ -.fi -.RE -.PP -where -.I -is the path specified with the -.B \-configdir -command line option (which may be absolute or relative). -.PP -Finally, configuration files will also be searched for in directories -reserved for system use. These are to separate configuration files from -the vendor or 3rd party packages from those of local administration. -These files are found in the following directories: -.PP -.RS 4 -.nf -.I /usr/share/X11/__xconfigdir__ -.I __datadir__/X11/__xconfigdir__ -.fi -.RE -.PP -The -.I __xconfigfile__ -and -.I __xconfigdir__ -files are composed of a number of sections which may be present in any order, -or omitted to use default configuration values. -Each section has the form: -.PP -.RS 4 -.nf -.BI "Section \*q" SectionName \*q -.RI " " SectionEntry - ... -.B EndSection -.fi -.RE -.PP -The section names are: -.PP -.RS 4 -.nf -.BR "Files " "File pathnames" -.BR "ServerFlags " "Server flags" -.BR "Module " "Dynamic module loading" -.BR "Extensions " "Extension enabling" -.BR "InputDevice " "Input device description" -.BR "InputClass " "Input class description" -.BR "Device " "Graphics device description" -.BR "VideoAdaptor " "Xv video adaptor description" -.BR "Monitor " "Monitor description" -.BR "Modes " "Video modes descriptions" -.BR "Screen " "Screen configuration" -.BR "ServerLayout " "Overall layout" -.BR "DRI " "DRI\-specific configuration" -.BR "Vendor " "Vendor\-specific configuration" -.fi -.RE -.PP -The following obsolete section names are still recognised for compatibility -purposes. -In new config files, the -.B InputDevice -section should be used instead. -.PP -.RS 4 -.nf -.BR "Keyboard " "Keyboard configuration" -.BR "Pointer " "Pointer/mouse configuration" -.fi -.RE -.PP -The old -.B XInput -section is no longer recognised. -.PP -The -.B ServerLayout -sections are at the highest level. -They bind together the input and output devices that will be used in a session. -The input devices are described in the -.B InputDevice -sections. -Output devices usually consist of multiple independent components (e.g., -a graphics board and a monitor). -These multiple components are bound together in the -.B Screen -sections, and it is these that are referenced by the -.B ServerLayout -section. -Each -.B Screen -section binds together a graphics board and a monitor. -The graphics boards are described in the -.B Device -sections, and the monitors are described in the -.B Monitor -sections. -.PP -Config file keywords are case\-insensitive, and \(lq_\(rq characters are -ignored. -Most strings (including -.B Option -names) are also case-insensitive, and insensitive to white space and -\(lq_\(rq characters. -.PP -Each config file entry usually takes up a single line in the file. They -consist of a keyword, which is possibly followed by one or more arguments, -with the number and types of the arguments depending on the keyword. -The argument types are: -.PP -.RS 4 -.nf -.BR "Integer " "an integer number in decimal, hex or octal" -.BR "Real " "a floating point number" -.BR "String " "a string enclosed in double quote marks (\*q)" -.fi -.RE -.PP -Note: hex integer values must be prefixed with \(lq0x\(rq, and octal values -with \(lq0\(rq. -.PP -A special keyword called -.B Option -may be used to provide free\-form data to various components of the server. -The -.B Option -keyword takes either one or two string arguments. -The first is the option name, and the optional second argument is the -option value. -Some commonly used option value types include: -.PP -.RS 4 -.nf -.BR "Integer " "an integer number in decimal, hex or octal" -.BR "Real " "a floating point number" -.BR "String " "a sequence of characters" -.BR "Boolean " "a boolean value (see below)" -.BR "Frequency " "a frequency value (see below)" -.fi -.RE -.PP -Note that -.I all -.B Option -values, not just strings, must be enclosed in quotes. -.PP -Boolean options may optionally have a value specified. -When no value is specified, the option's value is -.BR TRUE . -The following boolean option values are recognised as -.BR TRUE : -.PP -.RS 4 -.BR 1 , -.BR on , -.BR true , -.B yes -.RE -.PP -and the following boolean option values are recognised as -.BR FALSE : -.PP -.RS 4 -.BR 0 , -.BR off , -.BR false , -.B no -.RE -.PP -If an option name is prefixed with -.RB \*q No \*q, -then the option value is negated. -.PP -Example: the following option entries are equivalent: -.PP -.RS 4 -.nf -.B "Option \*qAccel\*q \*qOff\*q" -.B "Option \*qNoAccel\*q" -.B "Option \*qNoAccel\*q \*qOn\*q" -.B "Option \*qAccel\*q \*qfalse\*q" -.B "Option \*qAccel\*q \*qno\*q" -.fi -.RE -.PP -Frequency option values consist of a real number that is optionally -followed by one of the following frequency units: -.PP -.RS 4 -.BR Hz , -.BR k , -.BR kHz , -.BR M , -.B MHz -.RE -.PP -When the unit name is omitted, the correct units will be determined from -the value and the expectations of the appropriate range of the value. -It is recommended that the units always be specified when using frequency -option values to avoid any errors in determining the value. -.SH "FILES SECTION" -The -.B Files -section is used to specify some path names required by the server. -Some of these paths can also be set from the command line (see -.BR Xserver (__appmansuffix__) -and -.BR __xservername__ (__appmansuffix__)). -The command line settings override the values specified in the config -file. -The -.B Files -section is optional, as are all of the entries that may appear in it. -.PP -The entries that can appear in this section are: -.TP 7 -.BI "FontPath \*q" path \*q -sets the search path for fonts. -This path is a comma separated list of font path elements which the __xservername__ -server searches for font databases. -Multiple -.B FontPath -entries may be specified, and they will be concatenated to build up the -fontpath used by the server. Font path elements can be absolute -directory paths, catalogue directories or a font server identifier. The -formats of the later two are explained below: -.PP -.RS 7 -Catalogue directories: -.PP -.RS 4 -Catalogue directories can be specified using the prefix \fBcatalogue:\fR -before the directory name. The directory can then be populated with -symlinks pointing to the real font directories, using the following -syntax in the symlink name: -.PP -.RS 4 -.IR : [attribute]: pri= -.RE -.PP -where -.I -is an alphanumeric identifier, -.I [attribute] -is an attribute which will be passed to the underlying FPE and -.I -is a number used to order the fontfile FPEs. Examples: -.PP -.RS 4 -.nf -.I 75dpi:unscaled:pri=20 -> /usr/share/X11/fonts/75dpi -.I gscript:pri=60 -> /usr/share/fonts/default/ghostscript -.I misc:unscaled:pri=10 \-> /usr/share/X11/fonts/misc -.fi -.PP -.RE .RE .RE -.PP -.RS 7 -Font server identifiers: -.PP -.RS 4 -Font server identifiers have the form: -.RS 4 -.PP -.IR / : -.RE -.PP -where -.I -is the transport type to use to connect to the font server (e.g., -.B unix -for UNIX\-domain sockets or -.B tcp -for a TCP/IP connection), -.I -is the hostname of the machine running the font server, and -.I -is the port number that the font server is listening on (usually 7100). -.RE -.PP -When this entry is not specified in the config file, the server falls back -to the compiled\-in default font path, which contains the following -font path elements (which can be set inside a catalogue directory): -.PP -.RS 4 -.nf -.I __datadir__/fonts/X11/misc/ -.I __datadir__/fonts/X11/TTF/ -.I __datadir__/fonts/X11/OTF/ -.I __datadir__/fonts/X11/Type1/ -.I __datadir__/fonts/X11/100dpi/ -.I __datadir__/fonts/X11/75dpi/ -.fi -.RE -.PP -Font path elements that are found to be invalid are removed from the -font path when the server starts up. -.RE -.TP 7 -.BI "ModulePath \*q" path \*q -sets the search path for loadable __xservername__ server modules. -This path is a comma separated list of directories which the __xservername__ server -searches for loadable modules loading in the order specified. -Multiple -.B ModulePath -entries may be specified, and they will be concatenated to build the -module search path used by the server. The default module path is -.PP -.RS 11 -__modulepath__ -.RE -.\" The LogFile keyword is not currently implemented -.ig -.TP 7 -.BI "LogFile \*q" path \*q -sets the name of the __xservername__ server log file. -The default log file name is -.PP -.RS 11 -.RI __logdir__/__xservername__. .log -.RE -.PP -.RS 7 -where -.I -is the display number for the __xservername__ server. -.. -.TP 7 -.BI "XkbDir \*q" path \*q -sets the base directory for keyboard layout files. The -.B \-xkbdir -command line option can be used to override this. The default directory is -.PP -.RS 11 -__xkbdir__ -.RE -.SH "SERVERFLAGS SECTION" -In addition to options specific to this section (described below), the -.B ServerFlags -section is used to specify some global -__xservername__ server options. -All of the entries in this section are -.BR Options , -although for compatibility purposes some of the old style entries are -still recognised. -Those old style entries are not documented here, and using them is -discouraged. -The -.B ServerFlags -section is optional, as are the entries that may be specified in it. -.PP -.B Options -specified in this section (with the exception of the -.B \*qDefaultServerLayout\*q -.BR Option ) -may be overridden by -.B Options -specified in the active -.B ServerLayout -section. -Options with command line equivalents are overridden when their command -line equivalent is used. -The options recognised by this section are: -.TP 7 -.BI "Option \*qDefaultServerLayout\*q \*q" layout\-id \*q -This specifies the default -.B ServerLayout -section to use in the absence of the -.B \-layout -command line option. -.TP 7 -.BI "Option \*qNoTrapSignals\*q \*q" boolean \*q -This prevents the __xservername__ server from trapping a range of unexpected fatal -signals and exiting cleanly. -Instead, the __xservername__ server will die and drop core where the fault occurred. -The default behaviour is for the __xservername__ server to exit cleanly, but still drop a -core file. -In general you never want to use this option unless you are debugging an __xservername__ -server problem and know how to deal with the consequences. -.TP 7 -.BI "Option \*qUseSIGIO\*q \*q" boolean \*q -This controls whether the __xservername__ server requests that events from -input devices be reported via a SIGIO signal handler (also known as SIGPOLL -on some platforms), or only reported via the standard select(3) loop. -The default behaviour is platform specific. In general you do not want to -use this option unless you are debugging the __xservername__ server, or -working around a specific bug until it is fixed, and understand the -consequences. -.TP 7 -.BI "Option \*qDontVTSwitch\*q \*q" boolean \*q -This disallows the use of the -.BI Ctrl+Alt+F n -sequence (where -.RI F n -refers to one of the numbered function keys). -That sequence is normally used to switch to another \*qvirtual terminal\*q -on operating systems that have this feature. -When this option is enabled, that key sequence has no special meaning and -is passed to clients. -Default: off. -.TP 7 -.BI "Option \*qDontZap\*q \*q" boolean \*q -This disallows the use of the -.B Terminate_Server -XKB action (usually on Ctrl+Alt+Backspace, depending on XKB options). -This action is normally used to terminate the __xservername__ server. -When this option is enabled, the action has no effect. -Default: off. -.TP 7 -.BI "Option \*qDontZoom\*q \*q" boolean \*q -This disallows the use of the -.B Ctrl+Alt+Keypad\-Plus -and -.B Ctrl+Alt+Keypad\-Minus -sequences. -These sequences allows you to switch between video modes. -When this option is enabled, those key sequences have no special meaning -and are passed to clients. -Default: off. -.TP 7 -.BI "Option \*qDisableVidModeExtension\*q \*q" boolean \*q -This disables the parts of the VidMode extension used by the xvidtune client -that can be used to change the video modes. -Default: the VidMode extension is enabled. -.TP 7 -.BI "Option \*qAllowNonLocalXvidtune\*q \*q" boolean \*q -This allows the xvidtune client (and other clients that use the VidMode -extension) to connect from another host. -Default: off. -.TP 7 -.BI "Option \*qAllowMouseOpenFail\*q \*q" boolean \*q -This tells the mousedrv(__drivermansuffix__) and vmmouse(__drivermansuffix__) -drivers to not report failure if the mouse device can't be opened/initialised. -It has no effect on the evdev(__drivermansuffix__) or other drivers. -Default: false. -.TP 7 -.BI "Option \*qVTSysReq\*q \*q" boolean \*q -enables the SYSV\-style VT switch sequence for non\-SYSV systems -which support VT switching. -This sequence is -.B Alt\-SysRq -followed by a function key -.RB ( Fn ). -This prevents the __xservername__ server trapping the -keys used for the default VT switch sequence, which means that clients can -access them. -Default: off. -.TP 7 -.BI "Option \*qBlankTime\*q \*q" time \*q -sets the inactivity timeout for the -.B blank -phase of the screensaver. -.I time -is in minutes. -This is equivalent to the __xservername__ server's -.B \-s -flag, and the value can be changed at run\-time with -.BR xset(__appmansuffix__). -Default: 10 minutes. -.TP 7 -.BI "Option \*qStandbyTime\*q \*q" time \*q -sets the inactivity timeout for the -.B standby -phase of DPMS mode. -.I time -is in minutes, and the value can be changed at run\-time with -.BR xset(__appmansuffix__). -Default: 10 minutes. -This is only suitable for VESA DPMS compatible monitors, and may not be -supported by all video drivers. -It is only enabled for screens that have the -.B \*qDPMS\*q -option set (see the MONITOR section below). -.TP 7 -.BI "Option \*qSuspendTime\*q \*q" time \*q -sets the inactivity timeout for the -.B suspend -phase of DPMS mode. -.I time -is in minutes, and the value can be changed at run\-time with -.BR xset(__appmansuffix__). -Default: 10 minutes. -This is only suitable for VESA DPMS compatible monitors, and may not be -supported by all video drivers. -It is only enabled for screens that have the -.B \*qDPMS\*q -option set (see the MONITOR section below). -.TP 7 -.BI "Option \*qOffTime\*q \*q" time \*q -sets the inactivity timeout for the -.B off -phase of DPMS mode. -.I time -is in minutes, and the value can be changed at run\-time with -.BR xset(__appmansuffix__). -Default: 10 minutes. -This is only suitable for VESA DPMS compatible monitors, and may not be -supported by all video drivers. -It is only enabled for screens that have the -.B \*qDPMS\*q -option set (see the MONITOR section below). -.TP 7 -.BI "Option \*qPixmap\*q \*q" bpp \*q -This sets the pixmap format to use for depth 24. -Allowed values for -.I bpp -are 24 and 32. -Default: 32 unless driver constraints don't allow this (which is rare). -Note: some clients don't behave well when this value is set to 24. -.TP 7 -.BI "Option \*qPC98\*q \*q" boolean \*q -Specify that the machine is a Japanese PC\-98 machine. -This should not be enabled for anything other than the Japanese\-specific -PC\-98 architecture. -Default: auto\-detected. -.TP 7 -.BI "Option \*qNoPM\*q \*q" boolean \*q -Disables something to do with power management events. -Default: PM enabled on platforms that support it. -.TP 7 -.BI "Option \*qXinerama\*q \*q" boolean \*q -enable or disable XINERAMA extension. -Default is disabled. -.TP 7 -.BI "Option \*qAIGLX\*q \*q" boolean \*q -enable or disable AIGLX. AIGLX is enabled by default. -.TP 7 -.BI "Option \*qDRI2\*q \*q" boolean \*q -enable or disable DRI2. DRI2 is disabled by default. -.TP 7 -.BI "Option \*qGlxVisuals\*q \*q" string \*q -This option controls how many GLX visuals the GLX modules sets up. -The default value is -.BR "typical" , -which will setup up a typical subset of -the GLXFBConfigs provided by the driver as GLX visuals. Other options are -.BR "minimal" , -which will set up the minimal set allowed by the GLX specification and -.BR "all" -which will setup GLX visuals for all GLXFBConfigs. -.TP 7 -.BI "Option \*qUseDefaultFontPath\*q \*q" boolean \*q -Include the default font path even if other paths are specified in -xorg.conf. If enabled, other font paths are included as well. Enabled by -default. -.TP 7 -.BI "Option \*qIgnoreABI\*q \*q" boolean \*q -Allow modules built for a different, potentially incompatible version of -the X server to load. Disabled by default. -.TP 7 -.BI "Option \*qAutoAddDevices\*q \*q" boolean \*q -If this option is disabled, then no devices will be added from HAL events. -Enabled by default. -.TP 7 -.BI "Option \*qAutoEnableDevices\*q \*q" boolean \*q -If this option is disabled, then the devices will be added (and the -DevicePresenceNotify event sent), but not enabled, thus leaving policy up -to the client. -Enabled by default. -.TP 7 -.BI "Option \*qLog\*q \*q" string \*q -This option controls whether the log is flushed and/or synced to disk after -each message. -Possible values are -.B flush -or -.BR sync . -Unset by default. -.SH "MODULE SECTION" -The -.B Module -section is used to specify which __xservername__ server modules should be loaded. -This section is ignored when the __xservername__ server is built in static form. -The type of modules normally loaded in this section are __xservername__ server -extension modules. -Most other module types are loaded automatically when they are needed via -other mechanisms. -The -.B Module -section is optional, as are all of the entries that may be specified in -it. -.PP -Entries in this section may be in two forms. -The first and most commonly used form is an entry that uses the -.B Load -keyword, as described here: -.TP 7 -.BI "Load \*q" modulename \*q -This instructs the server to load the module called -.IR modulename . -The module name given should be the module's standard name, not the -module file name. -The standard name is case\-sensitive, and does not include the \(lqlib\(rq -prefix, or the \(lq.a\(rq, \(lq.o\(rq, or \(lq.so\(rq suffixes. -.PP -.RS 7 -Example: the DRI extension module can be loaded with the following entry: -.PP -.RS 4 -.B "Load \*qdri\*q" -.RE -.RE -.TP 7 -.BI "Disable \*q" modulename \*q -This instructs the server to not load the module called -.IR modulename . -Some modules are loaded by default in the server, and this overrides that -default. If a -.B Load -instruction is given for the same module, it overrides the -.B Disable -instruction and the module is loaded. The module name given should be the -module's standard name, not the module file name. As with the -.B Load -instruction, the standard name is case-sensitive, and does not include the -"lib" prefix, or the ".a", ".o", or ".so" suffixes. -.PP -The second form of entry is a -.BR SubSection, -with the subsection name being the module name, and the contents of the -.B SubSection -being -.B Options -that are passed to the module when it is loaded. -.PP -Example: the extmod module (which contains a miscellaneous group of -server extensions) can be loaded, with the XFree86\-DGA extension -disabled by using the following entry: -.PP -.RS 4 -.nf -.B "SubSection \*qextmod\*q" -.B " Option \*qomit XFree86\-DGA\*q" -.B EndSubSection -.fi -.RE -.PP -Modules are searched for in each directory specified in the -.B ModulePath -search path, and in the drivers, extensions, input, internal, and -multimedia subdirectories of each of those directories. -In addition to this, operating system specific subdirectories of all -the above are searched first if they exist. -.PP -To see what extension modules are available, check the extensions -subdirectory under: -.PP -.RS 4 -.nf -__modulepath__ -.fi -.RE -.PP -The \(lqextmod\(rq, \(lqdbe\(rq, \(lqdri\(rq, \(lqdri2\(rq, \(lqglx\(rq, -and \(lqrecord\(rq extension modules are loaded automatically, if they -are present, unless disabled with \*qDisable\*q entries. -It is recommended -that at very least the \(lqextmod\(rq extension module be loaded. -If it isn't, some commonly used server extensions (like the SHAPE -extension) will not be available. -.SH "EXTENSIONS SECTION" -The -.B Extensions -section is used to specify which X11 protocol extensions should be enabled -or disabled. -The -.B Extensions -section is optional, as are all of the entries that may be specified in -it. -.PP -Entries in this section are listed as Option statements with the name of -the extension as the first argument, and a boolean value as the second. -The extension name is case\-sensitive, and matches the form shown in the output -of \*qXorg -extension ?\*q. -.PP -.RS 7 -Example: the MIT-SHM extension can be disabled with the following entry: -.PP -.RS 4 -.nf -.B "Section \*qExtensions\*q" -.B " Option \*qMIT-SHM\*q \*qDisable\*q" -.B "EndSection" -.fi -.RE -.RE -.SH "INPUTDEVICE SECTION" -The config file may have multiple -.B InputDevice -sections. -Recent X servers employ input hotplugging to add input devices, with the HAL -backend being the default backend for X servers since 1.4. It is usually not -necessary to provide -.B InputDevice -sections in the xorg.conf if hotplugging is enabled. -.PP -If hotplugging is disabled, there will normally -be at least two: one for the core (primary) keyboard -and one for the core pointer. -If either of these two is missing, a default configuration for the missing -ones will be used. In the absence of an explicitly specified core input -device, the first -.B InputDevice -marked as -.B CorePointer -(or -.BR CoreKeyboard ) -is used. -If there is no match there, the first -.B InputDevice -that uses the \(lqmouse\(rq (or \(lqkbd\(rq) driver is used. -The final fallback is to use built\-in default configurations. -Currently the default configuration may not work as expected on all platforms. -.PP -.B InputDevice -sections have the following format: -.PP -.RS 4 -.nf -.B "Section \*qInputDevice\*q" -.BI " Identifier \*q" name \*q -.BI " Driver \*q" inputdriver \*q -.I " options" -.I " ..." -.B "EndSection" -.fi -.RE -.PP -The -.B Identifier -and -.B Driver -entries are required in all -.B InputDevice -sections. -All other entries are optional. -.PP -The -.B Identifier -entry specifies the unique name for this input device. -The -.B Driver -entry specifies the name of the driver to use for this input device. -When using the loadable server, the input driver module -.RI \*q inputdriver \*q -will be loaded for each active -.B InputDevice -section. -An -.B InputDevice -section is considered active if it is referenced by an active -.B ServerLayout -section, if it is referenced by the -.B \-keyboard -or -.B \-pointer -command line options, or if it is selected implicitly as the core pointer -or keyboard device in the absence of such explicit references. -The most commonly used input drivers are -.BR evdev (__drivermansuffix__) -on Linux systems, and -.BR kbd (__drivermansuffix__) -and -.BR mousedrv (__drivermansuffix__) -on other platforms. -.PP -.PP -.B InputDevice -sections recognise some driver\-independent -.BR Options , -which are described here. -See the individual input driver manual pages for a description of the -device\-specific options. -.TP 7 -.BI "Option \*qAutoServerLayout\*q \*q" boolean \*q -Always add the device to the ServerLayout section used by this instance of -the server. This affects implied layouts as well as explicit layouts -specified in the configuration and/or on the command line. -.TP 7 -.BI "Option \*qCorePointer\*q" -Deprecated, see -.B Floating -.TP 7 -.BI "Option \*qCoreKeyboard\*q" -Deprecated, see -.B Floating -.TP 7 -.BI "Option \*qAlwaysCore\*q \*q" boolean \*q -Deprecated, see -.B Floating -.TP 7 -.BI "Option \*qSendCoreEvents\*q \*q" boolean \*q -Deprecated, see -.B Floating - -.TP 7 -.BI "Option \*qFloating\*q \*q" boolean \*q -When enabled, the input device is set up floating and does not -report events through any master device or control a cursor. The device is -only available to clients using the X Input Extension API. This option is -disabled by default. -The options -.B CorePointer, -.B CoreKeyboard, -.B AlwaysCore, -and -.B SendCoreEvents, -are the inverse of option -.B Floating -(i.e. -.B SendCoreEvents \*qon\*q -is equivalent to -.B Floating \*qoff\*q -). - -This option controls the startup behavior only, a device -may be reattached or set floating at runtime. -.PP -For pointing devices, the following options control how the pointer -is accelerated or decelerated with respect to physical device motion. Most of -these can be adjusted at runtime, see the xinput(1) man page for details. Only -the most important acceleration options are discussed here. -.TP 7 -.BI "Option \*qAccelerationProfile\*q \*q" integer \*q -Select the profile. In layman's terms, the profile constitutes the "feeling" of -the acceleration. More formally, it defines how the transfer function (actual -acceleration as a function of current device velocity and acceleration controls) -is constructed. This is mainly a matter of personal preference. -.PP -.RS 6 -.nf -.B " 0 classic (mostly compatible)" -.B "-1 none (only constant deceleration is applied)" -.B " 1 device-dependent" -.B " 2 polynomial (polynomial function)" -.B " 3 smooth linear (soft knee, then linear)" -.B " 4 simple (normal when slow, otherwise accelerated)" -.B " 5 power (power function)" -.B " 6 linear (more speed, more acceleration)" -.B " 7 limited (like linear, but maxes out at threshold)" -.fi -.RE -.TP 7 -.BI "Option \*qConstantDeceleration\*q \*q" real \*q -Makes the pointer go -.B deceleration -times slower than normal. Most useful for high-resolution devices. -.TP 7 -.BI "Option \*qAdaptiveDeceleration\*q \*q" real \*q -Allows to actually decelerate the pointer when going slow. At most, it will be -.B adaptive deceleration -times slower. Enables precise pointer placement without sacrificing speed. -.TP 7 -.BI "Option \*qAccelerationScheme\*q \*q" string \*q -Selects the scheme, which is the underlying algorithm. -.PP -.RS 7 -.nf -.B "predictable default algorithm (behaving more predictable)" -.B "lightweight old acceleration code (as specified in the X protocol spec)" -.B "none no acceleration or deceleration" -.fi -.RE -.TP 7 -.BI "Option \*qAccelerationNumerator\*q \*q" integer \*q -.TP 7 -.BI "Option \*qAccelerationDenominator\*q \*q" integer \*q -Set numerator and denominator of the acceleration factor. The acceleration -factor is a rational which, together with threshold, can be used to tweak -profiles to suit the users needs. The -.B simple -and -.B limited -profiles use it directly (i.e. they accelerate by the factor), for other -profiles it should hold that a higher acceleration factor leads to a faster -pointer. Typically, 1 is unaccelerated and values up to 5 are sensible. -.TP 7 -.BI "Option \*qAccelerationThreshold\*q \*q" integer \*q -Set the threshold, which is roughly the velocity (usually device units per 10 -ms) required for acceleration to become effective. The precise effect varies -with the profile however. - -.SH "INPUTCLASS SECTION" -The config file may have multiple -.B InputClass -sections. -These sections are optional and are used to provide configuration for a -class of input devices as they are automatically added. An input device can -match more than one -.B InputClass -section. Each class can override settings from a previous class, so it is -best to arrange the sections with the most generic matches first. -.PP -.B InputClass -sections have the following format: -.PP -.RS 4 -.nf -.B "Section \*qInputClass\*q" -.BI " Identifier \*q" name \*q -.I " entries" -.I " ..." -.I " options" -.I " ..." -.B "EndSection" -.fi -.RE -.PP -The -.B Identifier -entry is required in all -.B InputClass -sections. -All other entries are optional. -.PP -The -.B Identifier -entry specifies the unique name for this input class. -The -.B Driver -entry specifies the name of the driver to use for this input device. -After all classes have been examined, the -.RI \*q inputdriver \*q -module from the first -.B Driver -entry will be enabled when using the loadable server. -.PP -When an input device is automatically added, its characteristics are -checked against all -.B InputClass -sections. Each section can contain optional entries to narrow the match -of the class. If none of the optional entries appear, the -.B InputClass -section is generic and will match any input device. If more than one of -these entries appear, they all must match for the configuration to apply. -.PP -There are two types of match entries used in -.B InputClass -sections. The first allows various tokens to be matched against attributes -of the device. An entry can be constructed to match attributes from different -devices by separating arguments with a '|' character. Multiple entries of the -same type may be supplied to add multiple matching conditions on the same -attribute. For example: -.PP -.RS 4 -.nf -.B "Section \*qInputClass\*q" -.B " Identifier \*qMy Class\*q" -.B " # product string must contain example and -.B " # either gizmo or gadget -.B " MatchProduct \*qexample\*q -.B " MatchProduct \*qgizmo|gadget\*q -.I " ..." -.B "EndSection" -.fi -.RE -.TP 7 -.BI "MatchProduct \*q" matchproduct \*q -This entry can be used to check if the substring -.RI \*q matchproduct \*q -occurs in the device's product name. -.TP 7 -.BI "MatchVendor \*q" matchvendor \*q -This entry can be used to check if the substring -.RI \*q matchvendor \*q -occurs in the device's vendor name. -.TP 7 -.BI "MatchDevicePath \*q" matchdevice \*q -This entry can be used to check if the device file matches the -.RI \*q matchdevice \*q -pathname pattern. -.TP 7 -.BI "MatchOS \*q" matchos \*q -This entry can be used to check if the operating system matches the -case-insensitive -.RI \*q matchos \*q -string. This entry is only supported on platforms providing the -.BR uname (2) -system call. -.TP 7 -.BI "MatchPnPID \*q" matchpnp \*q -The device's Plug and Play (PnP) ID can be checked against the -.RI \*q matchpnp \*q -shell wildcard pattern. -.TP 7 -.BI "MatchUSBID \*q" matchusb \*q -The device's USB ID can be checked against the -.RI \*q matchusb \*q -shell wildcard pattern. The ID is constructed as lowercase hexadecimal numbers -separated by a ':'. This is the same format as the -.BR lsusb (8) -program. -.TP 7 -.BI "MatchDriver \*q" matchdriver \*q -Check the case-sensitive string -.RI \*q matchdriver \*q -against the currently configured driver of the device. Ordering of sections -using this entry is important since it will not match unless the driver has -been set by the config backend or a previous -.B InputClass -section. -.TP 7 -.BI "MatchTag \*q" matchtag \*q -This entry can be used to check if tags assigned by the config backend -matches the -.RI \*q matchtag \*q -pattern. A match is found if at least one of the tags given in -.RI \*q matchtag \*q -matches at least one of the tags assigned by the backend. -.PP -The second type of entry is used to match device types. These entries take a -boolean argument similar to -.B Option -entries. -.TP 7 -.BI "MatchIsKeyboard \*q" bool \*q -.TP 7 -.BI "MatchIsPointer \*q" bool \*q -.TP 7 -.BI "MatchIsJoystick \*q" bool \*q -.TP 7 -.BI "MatchIsTablet \*q" bool \*q -.TP 7 -.BI "MatchIsTouchpad \*q" bool \*q -.TP 7 -.BI "MatchIsTouchscreen \*q" bool \*q -.PP -When an input device has been matched to the -.B InputClass -section, any -.B Option -entries are applied to the device. One -.B InputClass -specific -.B Option -is recognized. See the -.B InputDevice -section above for a description of the remaining -.B Option -entries. -.TP 7 -.BI "Option \*qIgnore\*q \*q" boolean \*q -This optional entry specifies that the device should be ignored entirely, -and not added to the server. This can be useful when the device is handled -by another program and no X events should be generated. -.SH "DEVICE SECTION" -The config file may have multiple -.B Device -sections. -There must be at least one, for the video card being used. -.PP -.B Device -sections have the following format: -.PP -.RS 4 -.nf -.B "Section \*qDevice\*q" -.BI " Identifier \*q" name \*q -.BI " Driver \*q" driver \*q -.I " entries" -.I " ..." -.B "EndSection" -.fi -.RE -.PP -The -.B Identifier -and -.B Driver -entries are required in all -.B Device -sections. All other entries are optional. -.PP -The -.B Identifier -entry specifies the unique name for this graphics device. -The -.B Driver -entry specifies the name of the driver to use for this graphics device. -When using the loadable server, the driver module -.RI \*q driver \*q -will be loaded for each active -.B Device -section. -A -.B Device -section is considered active if it is referenced by an active -.B Screen -section. -.PP -.B Device -sections recognise some driver\-independent entries and -.BR Options , -which are described here. -Not all drivers make use of these -driver\-independent entries, and many of those that do don't require them -to be specified because the information is auto\-detected. -See the individual graphics driver manual pages for further information -about this, and for a description of the device\-specific options. -Note that most of the -.B Options -listed here (but not the other entries) may be specified in the -.B Screen -section instead of here in the -.B Device -section. -.TP 7 -.BI "BusID \*q" bus\-id \*q -This specifies the bus location of the graphics card. -For PCI/AGP cards, -the -.I bus\-id -string has the form -.BI PCI: bus : device : function -(e.g., \(lqPCI:1:0:0\(rq might be appropriate for an AGP card). -This field is usually optional in single-head configurations when using -the primary graphics card. -In multi-head configurations, or when using a secondary graphics card in a -single-head configuration, this entry is mandatory. -Its main purpose is to make an unambiguous connection between the device -section and the hardware it is representing. -This information can usually be found by running the pciaccess tool -scanpci. -.TP 7 -.BI "Screen " number -This option is mandatory for cards where a single PCI entity can drive more -than one display (i.e., multiple CRTCs sharing a single graphics accelerator -and video memory). -One -.B Device -section is required for each head, and this -parameter determines which head each of the -.B Device -sections applies to. -The legal values of -.I number -range from 0 to one less than the total number of heads per entity. -Most drivers require that the primary screen (0) be present. -.TP 7 -.BI "Chipset \*q" chipset \*q -This usually optional entry specifies the chipset used on the graphics -board. -In most cases this entry is not required because the drivers will probe the -hardware to determine the chipset type. -Don't specify it unless the driver-specific documentation recommends that you -do. -.TP 7 -.BI "Ramdac \*q" ramdac\-type \*q -This optional entry specifies the type of RAMDAC used on the graphics -board. -This is only used by a few of the drivers, and in most cases it is not -required because the drivers will probe the hardware to determine the -RAMDAC type where possible. -Don't specify it unless the driver-specific documentation recommends that you -do. -.TP 7 -.BI "DacSpeed " speed -.TP 7 -.BI "DacSpeed " "speed\-8 speed\-16 speed\-24 speed\-32" -This optional entry specifies the RAMDAC speed rating (which is usually -printed on the RAMDAC chip). -The speed is in MHz. -When one value is given, it applies to all framebuffer pixel sizes. -When multiple values are given, they apply to the framebuffer pixel sizes -8, 16, 24 and 32 respectively. -This is not used by many drivers, and only needs to be specified when the -speed rating of the RAMDAC is different from the defaults built in to -driver, or when the driver can't auto-detect the correct defaults. -Don't specify it unless the driver-specific documentation recommends that you -do. -.TP 7 -.BI "Clocks " "clock ..." -specifies the pixel that are on your graphics board. -The clocks are in MHz, and may be specified as a floating point number. -The value is stored internally to the nearest kHz. -The ordering of the clocks is important. -It must match the order in which they are selected on the graphics board. -Multiple -.B Clocks -lines may be specified, and each is concatenated to form the list. -Most drivers do not use this entry, and it is only required for some older -boards with non-programmable clocks. -Don't specify this entry unless the driver-specific documentation explicitly -recommends that you do. -.TP -.BI "ClockChip \*q" clockchip\-type \*q -This optional entry is used to specify the clock chip type on graphics -boards which have a programmable clock generator. -Only a few __xservername__ drivers support programmable clock chips. -For details, see the appropriate driver manual page. -.TP 7 -.BI "VideoRam " "mem" -This optional entry specifies the amount of video ram that is installed -on the graphics board. -This is measured in kBytes. -In most cases this is not required because the __xservername__ server probes -the graphics board to determine this quantity. -The driver-specific documentation should indicate when it might be needed. -.TP 7 -.BI "BiosBase " "baseaddress" -This optional entry specifies the base address of the video BIOS for -the VGA board. -This address is normally auto-detected, and should only be specified if the -driver-specific documentation recommends it. -.TP 7 -.BI "MemBase " "baseaddress" -This optional entry specifies the memory base address of a graphics -board's linear frame buffer. -This entry is not used by many drivers, and it should only be specified if -the driver-specific documentation recommends it. -.TP 7 -.BI "IOBase " "baseaddress" -This optional entry specifies the IO base address. -This entry is not used by many drivers, and it should only be specified if -the driver-specific documentation recommends it. -.TP 7 -.BI "ChipID " "id" -This optional entry specifies a numerical ID representing the chip type. -For PCI cards, it is usually the device ID. -This can be used to override the auto-detection, but that should only be done -when the driver-specific documentation recommends it. -.TP 7 -.BI "ChipRev " "rev" -This optional entry specifies the chip revision number. -This can be used to override the auto-detection, but that should only be done -when the driver-specific documentation recommends it. -.TP 7 -.BI "TextClockFreq " "freq" -This optional entry specifies the pixel clock frequency that is used -for the regular text mode. -The frequency is specified in MHz. -This is rarely used. -.TP 7 -.BI "Option \*qModeDebug\*q \*q" boolean \*q -Enable printing of additional debugging information about modesetting to -the server log. -.ig -.TP 7 -This optional entry allows an IRQ number to be specified. -.. -.TP 7 -.B Options -Option flags may be specified in the -.B Device -sections. -These include driver\-specific options and driver\-independent options. -The former are described in the driver\-specific documentation. -Some of the latter are described below in the section about the -.B Screen -section, and they may also be included here. - -.SH "VIDEOADAPTOR SECTION" -Nobody wants to say how this works. -Maybe nobody knows ... - -.SH "MONITOR SECTION" -The config file may have multiple -.B Monitor -sections. -There should normally be at least one, for the monitor being used, -but a default configuration will be created when one isn't specified. -.PP -.B Monitor -sections have the following format: -.PP -.RS 4 -.nf -.B "Section \*qMonitor\*q" -.BI " Identifier \*q" name \*q -.I " entries" -.I " ..." -.B "EndSection" -.fi -.RE -.PP -The only mandatory entry in a -.B Monitor -section is the -.B Identifier -entry. -.PP -The -.B Identifier -entry specifies the unique name for this monitor. -The -.B Monitor -section may be used to provide information about the specifications of the -monitor, monitor-specific -.BR Options , -and information about the video modes to use with the monitor. -.PP -With RandR 1.2-enabled drivers, monitor sections may be tied to specific -outputs of the video card. Using the name of the output defined by the video -driver plus the identifier of a monitor section, one associates a monitor -section with an output by adding an option to the Device section in the -following format: - -.B Option \*qMonitor-outputname\*q \*qmonitorsection\*q - -(for example, -.B Option \*qMonitor-VGA\*q \*qVGA monitor\*q -for a VGA output) -.PP -In the absence of specific association of monitor sections to outputs, if a -monitor section is present the server will associate it with an output to -preserve compatibility for previous single-head configurations. -.PP -Specifying video modes is optional because the server will use the DDC or other -information provided by the monitor to automatically configure the list of -modes available. -When modes are specified explicitly in the -.B Monitor -section (with the -.BR Modes , -.BR ModeLine , -or -.B UseModes -keywords), built-in modes with the same names are not included. -Built-in modes with different names are, however, still implicitly included, -when they meet the requirements of the monitor. -.PP -The entries that may be used in -.B Monitor -sections are described below. -.TP 7 -.BI "VendorName \*q" vendor \*q -This optional entry specifies the monitor's manufacturer. -.TP 7 -.BI "ModelName \*q" model \*q -This optional entry specifies the monitor's model. -.TP 7 -.BI "HorizSync " "horizsync\-range" -gives the range(s) of horizontal sync frequencies supported by the -monitor. -.I horizsync\-range -may be a comma separated list of either discrete values or ranges of -values. -A range of values is two values separated by a dash. -By default the values are in units of kHz. -They may be specified in MHz or Hz -if -.B MHz -or -.B Hz -is added to the end of the line. -The data given here is used by the __xservername__ server to determine if video -modes are within the specifications of the monitor. -This information should be available in the monitor's handbook. -If this entry is omitted, a default range of 28\-33kHz is used. -.TP 7 -.BI "VertRefresh " "vertrefresh\-range" -gives the range(s) of vertical refresh frequencies supported by the -monitor. -.I vertrefresh\-range -may be a comma separated list of either discrete values or ranges of -values. -A range of values is two values separated by a dash. -By default the values are in units of Hz. -They may be specified in MHz or kHz -if -.B MHz -or -.B kHz -is added to the end of the line. -The data given here is used by the __xservername__ server to determine if video -modes are within the specifications of the monitor. -This information should be available in the monitor's handbook. -If this entry is omitted, a default range of 43\-72Hz is used. -.TP 7 -.BI "DisplaySize " "width height" -This optional entry gives the width and height, in millimetres, of the -picture area of the monitor. -If given this is used to calculate the horizontal and vertical pitch (DPI) of -the screen. -.TP 7 -.BI "Gamma " "gamma\-value" -.TP 7 -.BI "Gamma " "red\-gamma green\-gamma blue\-gamma" -This is an optional entry that can be used to specify the gamma correction -for the monitor. -It may be specified as either a single value or as three separate RGB values. -The values should be in the range 0.1 to 10.0, and the default is 1.0. -Not all drivers are capable of using this information. -.TP 7 -.BI "UseModes \*q" modesection\-id \*q -Include the set of modes listed in the -.B Modes -section called -.IR modesection\-id. -This makes all of the modes defined in that section available for use by -this monitor. -.TP 7 -.BI "Mode \*q" name \*q -This is an optional multi-line entry that can be used to provide -definitions for video modes for the monitor. -In most cases this isn't necessary because the built-in set of VESA standard -modes will be sufficient. -The -.B Mode -keyword indicates the start of a multi-line video mode description. -The mode description is terminated with the -.B EndMode -keyword. -The mode description consists of the following entries: -.RS 7 -.TP 4 -.BI "DotClock " clock -is the dot (pixel) clock rate to be used for the mode. -.TP 4 -.BI "HTimings " "hdisp hsyncstart hsyncend htotal" -specifies the horizontal timings for the mode. -.TP 4 -.BI "VTimings " "vdisp vsyncstart vsyncend vtotal" -specifies the vertical timings for the mode. -.TP 4 -.BI "Flags \*q" flag \*q " ..." -specifies an optional set of mode flags, each of which is a separate -string in double quotes. -.B \*qInterlace\*q -indicates that the mode is interlaced. -.B \*qDoubleScan\*q -indicates a mode where each scanline is doubled. -.B \*q+HSync\*q -and -.B \*q\-HSync\*q -can be used to select the polarity of the HSync signal. -.B \*q+VSync\*q -and -.B \*q\-VSync\*q -can be used to select the polarity of the VSync signal. -.B \*qComposite\*q -can be used to specify composite sync on hardware where this is supported. -Additionally, on some hardware, -.B \*q+CSync\*q -and -.B \*q\-CSync\*q -may be used to select the composite sync polarity. -.TP 4 -.BI "HSkew " hskew -specifies the number of pixels (towards the right edge of the screen) by -which the display enable signal is to be skewed. -Not all drivers use this information. -This option might become necessary to override the default value supplied -by the server (if any). -\(lqRoving\(rq horizontal lines indicate this value needs to be increased. -If the last few pixels on a scan line appear on the left of the screen, -this value should be decreased. -.TP 4 -.BI "VScan " vscan -specifies the number of times each scanline is painted on the screen. -Not all drivers use this information. -Values less than 1 are treated as 1, which is the default. -Generally, the -.B \*qDoubleScan\*q -.B Flag -mentioned above doubles this value. -.RE -.TP 7 -.BI "ModeLine \*q" name \*q " mode\-description" -This entry is a more compact version of the -.B Mode -entry, and it also can be used to specify video modes for the monitor. -is a single line format for specifying video modes. -In most cases this isn't necessary because the built\-in set of VESA -standard modes will be sufficient. -.PP -.RS 7 -The -.I mode\-description -is in four sections, the first three of which are mandatory. -The first is the dot (pixel) clock. -This is a single number specifying the pixel clock rate for the mode in -MHz. -The second section is a list of four numbers specifying the horizontal -timings. -These numbers are the -.IR hdisp , -.IR hsyncstart , -.IR hsyncend , -and -.I htotal -values. -The third section is a list of four numbers specifying the vertical -timings. -These numbers are the -.IR vdisp , -.IR vsyncstart , -.IR vsyncend , -and -.I vtotal -values. -The final section is a list of flags specifying other characteristics of -the mode. -.B Interlace -indicates that the mode is interlaced. -.B DoubleScan -indicates a mode where each scanline is doubled. -.B +HSync -and -.B \-HSync -can be used to select the polarity of the HSync signal. -.B +VSync -and -.B \-VSync -can be used to select the polarity of the VSync signal. -.B Composite -can be used to specify composite sync on hardware where this is supported. -Additionally, on some hardware, -.B +CSync -and -.B \-CSync -may be used to select the composite sync polarity. -The -.B HSkew -and -.B VScan -options mentioned above in the -.B Modes -entry description can also be used here. -.RE -.TP 7 -.BI "Option " "\*qDPMS\*q " \*qbool\*q -This option controls whether the server should enable the DPMS extension -for power management for this screen. The default is to enable the -extension. -.TP 7 -.BI "Option " "\*qSyncOnGreen\*q " \*qbool\*q -This option controls whether the video card should drive the sync signal -on the green color pin. Not all cards support this option, and most -monitors do not require it. The default is off. -.TP 7 -.BI "Option " "\*qPrimary\*q " \*qbool\*q -This optional entry specifies that the monitor should be treated as the primary -monitor. (RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qPreferredMode\*q " \*qstring\*q -This optional entry specifies a mode to be marked as the preferred initial mode -of the monitor. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qPosition\*q " "\*qx y\*q" -This optional entry specifies the position of the monitor within the X -screen. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qLeftOf\*q " \*qoutput\*q -This optional entry specifies that the monitor should be positioned to the -left of the output (not monitor) of the given name. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qRightOf\*q " \*qoutput\*q -This optional entry specifies that the monitor should be positioned to the -right of the output (not monitor) of the given name. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qAbove\*q " \*qoutput\*q -This optional entry specifies that the monitor should be positioned above the -output (not monitor) of the given name. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qBelow\*q " \*qoutput\*q -This optional entry specifies that the monitor should be positioned below the -output (not monitor) of the given name. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qEnable\*q " \*qbool\*q -This optional entry specifies whether the monitor should be turned on -at startup. By default, the server will attempt to enable all connected -monitors. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qDefaultModes\*q " \*qbool\*q -This optional entry specifies whether the server should add supported default -modes to the list of modes offered on this monitor. By default, the server -will add default modes; you should only disable this if you can guarantee -that EDID will be available at all times, or if you have added custom modelines -which the server can use. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qMinClock\*q " \*qfrequency\*q -This optional entry specifies the minimum dot clock, in kHz, that is supported -by the monitor. -.TP 7 -.BI "Option " "\*qMaxClock\*q " \*qfrequency\*q -This optional entry specifies the maximum dot clock, in kHz, that is supported -by the monitor. -.TP 7 -.BI "Option " "\*qIgnore\*q " \*qbool\*q -This optional entry specifies that the monitor should be ignored entirely, -and not reported through RandR. This is useful if the hardware reports the -presence of outputs that don't exist. -(RandR 1.2-supporting drivers only) -.TP 7 -.BI "Option " "\*qRotate\*q " \*qrotation\*q -This optional entry specifies the initial rotation of the given monitor. -Valid values for rotation are \*qnormal\*q, \*qleft\*q, \*qright\*q, and -\*qinverted\*q. -(RandR 1.2-supporting drivers only) - -.SH "MODES SECTION" -The config file may have multiple -.B Modes -sections, or none. -These sections provide a way of defining sets of video modes independently -of the -.B Monitor -sections. -.B Monitor -sections may include the definitions provided in these sections by -using the -.B UseModes -keyword. -In most cases the -.B Modes -sections are not necessary because the built\-in set of VESA standard modes -will be sufficient. -.PP -.B Modes -sections have the following format: -.PP -.RS 4 -.nf -.B "Section \*qModes\*q" -.BI " Identifier \*q" name \*q -.I " entries" -.I " ..." -.B "EndSection" -.fi -.RE -.PP -The -.B Identifier -entry specifies the unique name for this set of mode descriptions. -The other entries permitted in -.B Modes -sections are the -.B Mode -and -.B ModeLine -entries that are described above in the -.B Monitor -section. -.SH "SCREEN SECTION" -The config file may have multiple -.B Screen -sections. -There must be at least one, for the \(lqscreen\(rq being used. -A \(lqscreen\(rq represents the binding of a graphics device -.RB ( Device -section) and a monitor -.RB ( Monitor -section). -A -.B Screen -section is considered \(lqactive\(rq if it is referenced by an active -.B ServerLayout -section or by the -.B \-screen -command line option. -If neither of those is present, the first -.B Screen -section found in the config file is considered the active one. -.PP -.B Screen -sections have the following format: -.PP -.RS 4 -.nf -.B "Section \*qScreen\*q" -.BI " Identifier \*q" name \*q -.BI " Device \*q" devid \*q -.BI " Monitor \*q" monid \*q -.I " entries" -.I " ..." -.BI " SubSection \*qDisplay\*q" -.I " entries" -.I " ... -.B " EndSubSection" -.I " ..." -.B "EndSection" -.fi -.RE -.PP -The -.B Identifier -and -.B Device -entries are mandatory. -All others are optional. -.PP -The -.B Identifier -entry specifies the unique name for this screen. -The -.B Screen -section provides information specific to the whole screen, including -screen\-specific -.BR Options . -In multi\-head configurations, there will be multiple active -.B Screen -sections, one for each head. -The entries available -for this section are: -.TP 7 -.BI "Device \*q" device\-id \*q -This mandatory entry specifies the -.B Device -section to be used for this screen. -This is what ties a specific graphics card to a screen. -The -.I device\-id -must match the -.B Identifier -of a -.B Device -section in the config file. -.TP 7 -.BI "Monitor \*q" monitor\-id \*q -specifies which monitor description is to be used for this screen. -If a -.B Monitor -name is not specified, a default configuration is used. -Currently the default configuration may not function as expected on all -platforms. -.TP 7 -.BI "VideoAdaptor \*q" xv\-id \*q -specifies an optional Xv video adaptor description to be used with this -screen. -.TP 7 -.BI "DefaultDepth " depth -specifies which color depth the server should use by default. -The -.B \-depth -command line option can be used to override this. -If neither is specified, the default depth is driver\-specific, but in most -cases is 8. -.TP 7 -.BI "DefaultFbBpp " bpp -specifies which framebuffer layout to use by default. -The -.B \-fbbpp -command line option can be used to override this. -In most cases the driver will chose the best default value for this. -The only case where there is even a choice in this value is for depth 24, -where some hardware supports both a packed 24 bit framebuffer layout and a -sparse 32 bit framebuffer layout. -.TP 7 -.B Options -Various -.B Option -flags may be specified in the -.B Screen -section. -Some are driver\-specific and are described in the driver documentation. -Others are driver\-independent, and will eventually be described here. -.\" XXX These should really be in an xaa man page. -.TP 7 -.BI "Option \*qAccel\*q" -Enables XAA (X Acceleration Architecture), a mechanism that makes video cards' -2D hardware acceleration available to the __xservername__ server. -This option is on by default, but it may be necessary to turn it off if -there are bugs in the driver. -There are many options to disable specific accelerated operations, listed -below. -Note that disabling an operation will have no effect if the operation is -not accelerated (whether due to lack of support in the hardware or in the -driver). -.TP 7 -.BI "Option \*qInitPrimary\*q \*q" boolean \*q -Use the Int10 module to initialize the primary graphics card. -Normally, only secondary cards are soft-booted using the Int10 module, as the -primary card has already been initialized by the BIOS at boot time. -Default: false. -.TP 7 -.BI "Option \*qNoInt10\*q \*q" boolean \*q -Disables the Int10 module, a module that uses the int10 call to the BIOS -of the graphics card to initialize it. -Default: false. -.TP 7 -.BI "Option \*qNoMTRR\*q" -Disables MTRR (Memory Type Range Register) support, a feature of modern -processors which can improve video performance by a factor of up to 2.5. -Some hardware has buggy MTRR support, and some video drivers have been -known to exhibit problems when MTRR's are used. -.TP 7 -.BI "Option \*qXaaNoCPUToScreenColorExpandFill\*q" -Disables accelerated rectangular expansion blits from source patterns -stored in system memory (using a memory\-mapped aperture). -.TP 7 -.BI "Option \*qXaaNoColor8x8PatternFillRect\*q" -Disables accelerated fills of a rectangular region with a full\-color -pattern. -.TP 7 -.BI "Option \*qXaaNoColor8x8PatternFillTrap\*q" -Disables accelerated fills of a trapezoidal region with a full\-color -pattern. -.TP 7 -.BI "Option \*qXaaNoDashedBresenhamLine\*q" -Disables accelerated dashed Bresenham line draws. -.TP 7 -.BI "Option \*qXaaNoDashedTwoPointLine\*q" -Disables accelerated dashed line draws between two arbitrary points. -.TP 7 -.BI "Option \*qXaaNoImageWriteRect\*q" -Disables accelerated transfers of full\-color rectangular patterns from -system memory to video memory (using a memory\-mapped aperture). -.TP 7 -.BI "Option \*qXaaNoMono8x8PatternFillRect\*q" -Disables accelerated fills of a rectangular region with a monochrome -pattern. -.TP 7 -.BI "Option \*qXaaNoMono8x8PatternFillTrap\*q" -Disables accelerated fills of a trapezoidal region with a monochrome -pattern. -.TP 7 -.BI "Option \*qXaaNoOffscreenPixmaps\*q" -Disables accelerated draws into pixmaps stored in offscreen video memory. -.TP 7 -.BI "Option \*qXaaNoPixmapCache\*q" -Disables caching of patterns in offscreen video memory. -.TP 7 -.BI "Option \*qXaaNoScanlineCPUToScreenColorExpandFill\*q" -Disables accelerated rectangular expansion blits from source patterns -stored in system memory (one scan line at a time). -.TP 7 -.BI "Option \*qXaaNoScanlineImageWriteRect\*q" -Disables accelerated transfers of full\-color rectangular patterns from -system memory to video memory (one scan line at a time). -.TP 7 -.BI "Option \*qXaaNoScreenToScreenColorExpandFill\*q" -Disables accelerated rectangular expansion blits from source patterns -stored in offscreen video memory. -.TP 7 -.BI "Option \*qXaaNoScreenToScreenCopy\*q" -Disables accelerated copies of rectangular regions from one part of -video memory to another part of video memory. -.TP 7 -.BI "Option \*qXaaNoSolidBresenhamLine\*q" -Disables accelerated solid Bresenham line draws. -.TP 7 -.BI "Option \*qXaaNoSolidFillRect\*q" -Disables accelerated solid\-color fills of rectangles. -.TP 7 -.BI "Option \*qXaaNoSolidFillTrap\*q" -Disables accelerated solid\-color fills of Bresenham trapezoids. -.TP 7 -.BI "Option \*qXaaNoSolidHorVertLine\*q" -Disables accelerated solid horizontal and vertical line draws. -.TP 7 -.BI "Option \*qXaaNoSolidTwoPointLine\*q" -Disables accelerated solid line draws between two arbitrary points. -.PP -Each -.B Screen -section may optionally contain one or more -.B Display -subsections. -Those subsections provide depth/fbbpp specific configuration information, -and the one chosen depends on the depth and/or fbbpp that is being used for -the screen. -The -.B Display -subsection format is described in the section below. - -.SH "DISPLAY SUBSECTION" -Each -.B Screen -section may have multiple -.B Display -subsections. -The \(lqactive\(rq -.B Display -subsection is the first that matches the depth and/or fbbpp values being -used, or failing that, the first that has neither a depth or fbbpp value -specified. -The -.B Display -subsections are optional. -When there isn't one that matches the depth and/or fbbpp values being used, -all the parameters that can be specified here fall back to their defaults. -.PP -.B Display -subsections have the following format: -.PP -.RS 4 -.nf -.B " SubSection \*qDisplay\*q" -.BI " Depth " depth -.I " entries" -.I " ..." -.B " EndSubSection" -.fi -.RE -.TP 7 -.BI "Depth " depth -This entry specifies what colour depth the -.B Display -subsection is to be used for. -This entry is usually specified, but it may be omitted to create a match\-all -.B Display -subsection or when wishing to match only against the -.B FbBpp -parameter. -The range of -.I depth -values that are allowed depends on the driver. -Most drivers support 8, 15, 16 and 24. -Some also support 1 and/or 4, and some may support other values (like 30). -Note: -.I depth -means the number of bits in a pixel that are actually used to determine -the pixel colour. -32 is not a valid -.I depth -value. -Most hardware that uses 32 bits per pixel only uses 24 of them to hold the -colour information, which means that the colour depth is 24, not 32. -.TP 7 -.BI "FbBpp " bpp -This entry specifies the framebuffer format this -.B Display -subsection is to be used for. -This entry is only needed when providing depth 24 configurations that allow -a choice between a 24 bpp packed framebuffer format and a 32bpp sparse -framebuffer format. -In most cases this entry should not be used. -.TP 7 -.BI "Weight " "red\-weight green\-weight blue\-weight" -This optional entry specifies the relative RGB weighting to be used -for a screen is being used at depth 16 for drivers that allow multiple -formats. -This may also be specified from the command line with the -.B \-weight -option (see -.BR __xservername__(__appmansuffix__)). -.TP 7 -.BI "Virtual " "xdim ydim" -This optional entry specifies the virtual screen resolution to be used. -.I xdim -must be a multiple of either 8 or 16 for most drivers, and a multiple -of 32 when running in monochrome mode. -The given value will be rounded down if this is not the case. -Video modes which are too large for the specified virtual size will be -rejected. -If this entry is not present, the virtual screen resolution will be set to -accommodate all the valid video modes given in the -.B Modes -entry. -Some drivers/hardware combinations do not support virtual screens. -Refer to the appropriate driver\-specific documentation for details. -.TP 7 -.BI "ViewPort " "x0 y0" -This optional entry sets the upper left corner of the initial display. -This is only relevant when the virtual screen resolution is different -from the resolution of the initial video mode. -If this entry is not given, then the initial display will be centered in -the virtual display area. -.TP 7 -.BI "Modes \*q" mode\-name \*q " ..." -This optional entry specifies the list of video modes to use. -Each -.I mode\-name -specified must be in double quotes. -They must correspond to those specified or referenced in the appropriate -.B Monitor -section (including implicitly referenced built\-in VESA standard modes). -The server will delete modes from this list which don't satisfy various -requirements. -The first valid mode in this list will be the default display mode for -startup. -The list of valid modes is converted internally into a circular list. -It is possible to switch to the next mode with -.B Ctrl+Alt+Keypad\-Plus -and to the previous mode with -.BR Ctrl+Alt+Keypad\-Minus . -When this entry is omitted, the valid modes referenced by the appropriate -.B Monitor -section will be used. If the -.B Monitor -section contains no modes, then the selection will be taken from the -built-in VESA standard modes. -.TP 7 -.BI "Visual \*q" visual\-name \*q -This optional entry sets the default root visual type. -This may also be specified from the command line (see the -.BR Xserver(__appmansuffix__) -man page). -The visual types available for depth 8 are (default is -.BR PseudoColor ): -.PP -.RS 11 -.nf -.B StaticGray -.B GrayScale -.B StaticColor -.B PseudoColor -.B TrueColor -.B DirectColor -.fi -.RE -.PP -.RS 7 -The visual type available for the depths 15, 16 and 24 are (default is -.BR TrueColor ): -.PP -.RS 4 -.nf -.B TrueColor -.B DirectColor -.fi -.RE -.PP -Not all drivers support -.B DirectColor -at these depths. -.PP -The visual types available for the depth 4 are (default is -.BR StaticColor ): -.PP -.RS 4 -.nf -.B StaticGray -.B GrayScale -.B StaticColor -.B PseudoColor -.fi -.RE -.PP -The visual type available for the depth 1 (monochrome) is -.BR StaticGray . -.RE -.TP 7 -.BI "Black " "red green blue" -This optional entry allows the \(lqblack\(rq colour to be specified. -This is only supported at depth 1. -The default is black. -.TP 7 -.BI "White " "red green blue" -This optional entry allows the \(lqwhite\(rq colour to be specified. -This is only supported at depth 1. -The default is white. -.TP 7 -.B Options -Option flags may be specified in the -.B Display -subsections. -These may include driver\-specific options and driver\-independent options. -The former are described in the driver\-specific documentation. -Some of the latter are described above in the section about the -.B Screen -section, and they may also be included here. -.SH "SERVERLAYOUT SECTION" -The config file may have multiple -.B ServerLayout -sections. -A \(lqserver layout\(rq represents the binding of one or more screens -.RB ( Screen -sections) and one or more input devices -.RB ( InputDevice -sections) to form a complete configuration. -In multi\-head configurations, it also specifies the relative layout of the -heads. -A -.B ServerLayout -section is considered \(lqactive\(rq if it is referenced by the -.B \-layout -command line option or by an -.B "Option \*qDefaultServerLayout\*q" -entry in the -.B ServerFlags -section (the former takes precedence over the latter). -If those options are not used, the first -.B ServerLayout -section found in the config file is considered the active one. -If no -.B ServerLayout -sections are present, the single active screen and two active (core) -input devices are selected as described in the relevant sections above. -.PP -.B ServerLayout -sections have the following format: -.PP -.RS 4 -.nf -.B "Section \*qServerLayout\*q" -.BI " Identifier \*q" name \*q -.BI " Screen \*q" screen\-id \*q -.I " ..." -.BI " InputDevice \*q" idev\-id \*q -.I " ..." -.I " options" -.I " ..." -.B "EndSection" -.fi -.RE -.PP -Each -.B ServerLayout -section must have an -.B Identifier -entry and at least one -.B Screen -entry. -.PP -The -.B Identifier -entry specifies the unique name for this server layout. -The -.B ServerLayout -section provides information specific to the whole session, including -session\-specific -.BR Options . -The -.B ServerFlags -options (described above) may be specified here, and ones given here -override those given in the -.B ServerFlags -section. -.PP -The entries that may be used in this section are described here. -.TP 7 -.BI "Screen " "screen\-num" " \*qscreen\-id\*q " "position\-information" -One of these entries must be given for each screen being used in -a session. -The -.I screen\-id -field is mandatory, and specifies the -.B Screen -section being referenced. -The -.I screen\-num -field is optional, and may be used to specify the screen number -in multi\-head configurations. -When this field is omitted, the screens will be numbered in the order that -they are listed in. -The numbering starts from 0, and must be consecutive. -The -.I position\-information -field describes the way multiple screens are positioned. -There are a number of different ways that this information can be provided: -.RS 7 -.TP 4 -.I "x y" -.TP 4 -.BI "Absolute " "x y" -These both specify that the upper left corner's coordinates are -.RI ( x , y ). -The -.B Absolute -keyword is optional. -Some older versions of XFree86 (4.2 and earlier) don't recognise the -.B Absolute -keyword, so it's safest to just specify the coordinates without it. -.TP 4 -.BI "RightOf \*q" screen\-id \*q -.TP 4 -.BI "LeftOf \*q" screen\-id \*q -.TP 4 -.BI "Above \*q" screen\-id \*q -.TP 4 -.BI "Below \*q" screen\-id \*q -.TP 4 -.BI "Relative \*q" screen\-id \*q " x y" -These give the screen's location relative to another screen. -The first four position the screen immediately to the right, left, above or -below the other screen. -When positioning to the right or left, the top edges are aligned. -When positioning above or below, the left edges are aligned. -The -.B Relative -form specifies the offset of the screen's origin (upper left corner) -relative to the origin of another screen. -.RE -.TP 7 -.BI "InputDevice \*q" idev\-id "\*q \*q" option \*q " ..." -One of these entries should be given for each input device being used in -a session. -Normally at least two are required, one each for the core pointer and -keyboard devices. -If either of those is missing, suitable -.B InputDevice -entries are searched for using the method described above in the -.B INPUTDEVICE -section. The -.I idev\-id -field is mandatory, and specifies the name of the -.B InputDevice -section being referenced. -Multiple -.I option -fields may be specified, each in double quotes. -The options permitted here are any that may also be given in the -.B InputDevice -sections. -Normally only session\-specific input device options would be used here. -The most commonly used options are: -.PP -.RS 11 -.nf -.B \*qCorePointer\*q -.B \*qCoreKeyboard\*q -.B \*qSendCoreEvents\*q -.fi -.RE -.PP -.RS 7 -and the first two should normally be used to indicate the core pointer -and core keyboard devices respectively. -.RE -.TP 7 -.B Options -In addition to the following, any option permitted in the -.B ServerFlags -section may also be specified here. -When the same option appears in both places, the value given here overrides -the one given in the -.B ServerFlags -section. -.TP 7 -.BI "Option \*qIsolateDevice\*q \*q" bus\-id \*q -Restrict device resets to the specified -.IR bus\-id . -See the -.B BusID -option (described in -.BR "DEVICE SECTION" , -above) for the format of the -.I bus\-id -parameter. -This option overrides -.BR SingleCard , -if specified. -At present, only PCI devices can be isolated in this manner. -.TP 7 -.BI "Option \*qSingleCard\*q \*q" boolean \*q -As -.BR IsolateDevice , -except that the bus ID of the first device in the layout is used. -.PP -Here is an example of a -.B ServerLayout -section for a dual headed configuration with two mice: -.PP -.RS 4 -.nf -.B "Section \*qServerLayout\*q" -.B " Identifier \*qLayout 1\*q" -.B " Screen \*qMGA 1\*q" -.B " Screen \*qMGA 2\*q RightOf \*qMGA 1\*q" -.B " InputDevice \*qKeyboard 1\*q \*qCoreKeyboard\*q" -.B " InputDevice \*qMouse 1\*q \*qCorePointer\*q" -.B " InputDevice \*qMouse 2\*q \*qSendCoreEvents\*q" -.B " Option \*qBlankTime\*q \*q5\*q" -.B "EndSection" -.fi -.RE -.SH "DRI SECTION" -This optional section is used to provide some information for the -Direct Rendering Infrastructure. -Details about the format of this section can be found on-line at -.IR . -.SH "VENDOR SECTION" -The optional -.B Vendor -section may be used to provide vendor\-specific configuration information. -Multiple -.B Vendor -sections may be present, and they may contain an -.B Identifier -entry and multiple -.B Option -flags. -The data therein is not used in this release. -.PP -.SH "SEE ALSO" -General: -.BR X (__miscmansuffix__), -.BR Xserver (__appmansuffix__), -.BR __xservername__ (__appmansuffix__), -.BR cvt (__appmansuffix__), -.BR gtf (__appmansuffix__). -.PP -.B "Not all modules or interfaces are available on all platforms." -.PP -Display drivers: -.BR apm (__drivermansuffix__), -.BR ati (__drivermansuffix__), -.BR chips (__drivermansuffix__), -.BR cirrus (__drivermansuffix__), -.BR cyrix (__drivermansuffix__), -.BR fbdev (__drivermansuffix__), -.BR glide (__drivermansuffix__), -.BR glint (__drivermansuffix__), -.BR i128 (__drivermansuffix__), -.BR i740 (__drivermansuffix__), -.BR imstt (__drivermansuffix__), -.BR intel (__drivermansuffix__), -.BR mga (__drivermansuffix__), -.BR neomagic (__drivermansuffix__), -.BR nv (__drivermansuffix__), -.BR openchrome (__drivermansuffix__), -.BR r128 (__drivermansuffix__), -.BR radeon (__drivermansuffix__), -.BR rendition (__drivermansuffix__), -.BR savage (__drivermansuffix__), -.BR s3virge (__drivermansuffix__), -.BR siliconmotion (__drivermansuffix__), -.BR sis (__drivermansuffix__), -.BR sisusb (__drivermansuffix__), -.BR sunbw2 (__drivermansuffix__), -.BR suncg14 (__drivermansuffix__), -.BR suncg3 (__drivermansuffix__), -.BR suncg6 (__drivermansuffix__), -.BR sunffb (__drivermansuffix__), -.BR sunleo (__drivermansuffix__), -.BR suntcx (__drivermansuffix__), -.BR tdfx (__drivermansuffix__), -.\" .BR tga (__drivermansuffix__), -.BR trident (__drivermansuffix__), -.BR tseng (__drivermansuffix__), -.BR vesa (__drivermansuffix__), -.BR vmware (__drivermansuffix__), -.BR voodoo (__drivermansuffix__), -.BR wsfb (__drivermansuffix__), -.BR xgi (__drivermansuffix__), -.BR xgixp (__drivermansuffix__). -.PP -Input drivers: -.BR acecad (__drivermansuffix__), -.BR citron (__drivermansuffix__), -.BR elographics (__drivermansuffix__), -.BR evdev (__drivermansuffix__), -.BR fpit (__drivermansuffix__), -.BR joystick (__drivermansuffix__), -.BR kbd (__drivermansuffix__), -.BR mousedrv (__drivermansuffix__), -.BR mutouch (__drivermansuffix__), -.BR penmount (__drivermansuffix__), -.BR synaptics (__drivermansuffix__), -.BR vmmouse (__drivermansuffix__), -.BR void (__drivermansuffix__), -.BR wacom (__drivermansuffix__). -.PP -Other modules and interfaces: -.BR exa (__drivermansuffix__), -.BR fbdevhw (__drivermansuffix__), -.\" .BR shadowfb (__drivermansuffix__), -.BR v4l (__drivermansuffix__). -.br -.SH AUTHORS -This manual page was largely rewritten by David Dawes -.IR . diff --git a/xorg-server/hw/xfree86/man/Makefile.am b/xorg-server/hw/xfree86/man/Makefile.am new file mode 100644 index 000000000..80e22cbab --- /dev/null +++ b/xorg-server/hw/xfree86/man/Makefile.am @@ -0,0 +1,3 @@ +include $(top_srcdir)/manpages.am +appman_PRE = Xorg.man +fileman_PRE = xorg.conf.man xorg.conf.d.man diff --git a/xorg-server/hw/xfree86/man/Xorg.man b/xorg-server/hw/xfree86/man/Xorg.man new file mode 100644 index 000000000..6fa334cc3 --- /dev/null +++ b/xorg-server/hw/xfree86/man/Xorg.man @@ -0,0 +1,689 @@ +.\" $XdotOrg: xserver/xorg/hw/xfree86/doc/man/Xorg.man.pre,v 1.3 2005/07/04 18:41:01 ajax Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH __xservername__ __appmansuffix__ __vendorversion__ +.SH NAME +__xservername__ - X11R7 X server +.SH SYNOPSIS +.B __xservername__ +.RI [\fB:\fP display ] +.RI [ option +.IR ... ] +.SH DESCRIPTION +.B __xservername__ +is a full featured X server that was originally designed for UNIX and +UNIX-like operating systems running on Intel x86 hardware. It now runs +on a wider range of hardware and OS platforms. +.PP +This work was derived by the X.Org Foundation from the XFree86 Project's +.I "XFree86\ 4.4rc2" +release. +The XFree86 release was originally derived from +.I "X386\ 1.2" +by Thomas Roell which was contributed to X11R5 by Snitily Graphics +Consulting Service. +.SH PLATFORMS +.PP +.B __xservername__ +operates under a wide range of operating systems and hardware platforms. +The Intel x86 (IA32) architecture is the most widely supported hardware +platform. Other hardware platforms include Compaq Alpha, Intel IA64, AMD64, +SPARC and PowerPC. The most widely supported operating systems are the +free/OpenSource UNIX-like systems such as Linux, FreeBSD, NetBSD, +OpenBSD, and Solaris. Commercial UNIX operating systems such as +UnixWare are also supported. Other supported operating systems include +GNU Hurd. Mac OS X is supported with the +Xquartz(__appmansuffix__) X server. Win32/Cygwin is supported with the +XWin(__appmansuffix__) X server. +.PP +.SH "NETWORK CONNECTIONS" +.B __xservername__ +supports connections made using the following reliable +byte-streams: +.TP 4 +.I "Local" +On most platforms, the "Local" connection type is a UNIX-domain socket. +On some System V platforms, the "local" connection types also include +STREAMS pipes, named pipes, and some other mechanisms. +.TP 4 +.I TCP\/IP +.B __xservername__ +listens on port +.RI 6000+ n , +where +.I n +is the display number. This connection type can be disabled with the +.B \-nolisten +option (see the Xserver(1) man page for details). +.SH "ENVIRONMENT VARIABLES" +For operating systems that support local connections other than Unix +Domain sockets (SVR3 and SVR4), there is a compiled-in list specifying +the order in which local connections should be attempted. This list +can be overridden by the +.I XLOCAL +environment variable described below. If the display name indicates a +best-choice connection should be made (e.g. +.BR :0.0 ), +each connection mechanism is tried until a connection succeeds or no +more mechanisms are available. Note: for these OSs, the Unix Domain +socket connection is treated differently from the other local connection +types. To use it the connection must be made to +.BR unix:0.0 . +.PP +The +.I XLOCAL +environment variable should contain a list of one more +more of the following: +.PP +.RS 8 +.nf +NAMED +PTS +SCO +ISC +.fi +.RE +.PP +which represent SVR4 Named Streams pipe, Old-style USL Streams pipe, +SCO XSight Streams pipe, and ISC Streams pipe, respectively. You can +select a single mechanism (e.g. +.IR XLOCAL=NAMED ), +or an ordered list (e.g. \fIXLOCAL="NAMED:PTS:SCO"\fP). +his variable overrides the compiled-in defaults. For SVR4 it is +recommended that +.I NAMED +be the first preference connection. The default setting is +.IR PTS:NAMED:ISC:SCO . +.PP +To globally override the compiled-in defaults, you should define (and +export if using +.B sh +or +.BR ksh ) +.I XLOCAL +globally. If you use startx(1) or xinit(1), the definition should be +at the top of your +.I .xinitrc +file. If you use xdm(1), the definitions should be early on in the +.I __projectroot__/lib/X11/xdm/Xsession +script. +.SH OPTIONS +.B __xservername__ +supports several mechanisms for supplying/obtaining configuration and +run-time parameters: command line options, environment variables, the +__xconfigfile__(__filemansuffix__) configuration files, auto-detection, and +fallback defaults. When the same information is supplied in more than +one way, the highest precedence mechanism is used. The list of mechanisms +is ordered from highest precedence to lowest. Note that not all parameters +can be supplied via all methods. The available command line options +and environment variables (and some defaults) are described here and in +the Xserver(__appmansuffix__) manual page. Most configuration file +parameters, with their defaults, are described in the +__xconfigfile__(__filemansuffix__) manual page. Driver and module specific +configuration parameters are described in the relevant driver or module +manual page. +.PP +In addition to the normal server options described in the +Xserver(__appmansuffix__) manual page, +.B __xservername__ +accepts the following command line switches: +.TP 8 +.BI vt XX +.I XX +specifies the Virtual Terminal device number which +.B __xservername__ +will use. Without this option, +.B __xservername__ +will pick the first available Virtual Terminal that it can locate. This +option applies only to platforms that have virtual terminal support, such +as Linux, BSD, OpenSolaris, SVR3, and SVR4. +.TP +.B \-allowMouseOpenFail +Allow the server to start up even if the mouse device can't be opened +or initialised. This is equivalent to the +.B AllowMouseOpenFail +__xconfigfile__(__filemansuffix__) file option. +.TP 8 +.B \-allowNonLocalXvidtune +Make the VidMode extension available to remote clients. This allows +the xvidtune client to connect from another host. This is equivalent +to the +.B AllowNonLocalXvidtune +__xconfigfile__(__filemansuffix__) file option. By default non-local +connections are not allowed. +.TP 8 +.BI \-bgamma " value" +Set the blue gamma correction. +.I value +must be between 0.1 and 10. +The default is 1.0. Not all drivers support this. See also the +.BR \-gamma , +.BR \-rgamma , +and +.B \-ggamma +options. +.TP 8 +.BI \-bpp " n" +No longer supported. Use +.B \-depth +to set the color depth, and use +.B \-fbbpp +if you really need to force a non-default framebuffer (hardware) pixel +format. +.TP 8 +.BI \-config " file" +Read the server configuration from +.IR file . +This option will work for any file when the server is run as root (i.e, +with real-uid 0), or for files relative to a directory in the config +search path for all other users. +.TP 8 +.BI \-configdir " directory" +Read the server configuration files from +.IR directory . +This option will work for any directory when the server is run as root +(i.e, with real-uid 0), or for directories relative to a directory in the +config directory search path for all other users. +.TP 8 +.B \-configure +When this option is specified, the +.B __xservername__ +server loads all video driver modules, probes for available hardware, +and writes out an initial __xconfigfile__(__filemansuffix__) file based on +what was detected. This option currently has some problems on some +platforms, but in most cases it is a good way to bootstrap the +configuration process. This option is only available when the server +is run as root (i.e, with real-uid 0). +.TP 8 +.BI "\-crt /dev/tty" XX +SCO only. This is the same as the +.B vt +option, and is provided for compatibility with the native SCO X server. +.TP 8 +.BI \-depth " n" +Sets the default color depth. Legal values are 1, 4, 8, 15, 16, and +24. Not all drivers support all values. +.TP 8 +.B \-disableVidMode +Disable the parts of the VidMode extension (used by the xvidtune +client) that can be used to change the video modes. This is equivalent +to the +.B DisableVidModeExtension +__xconfigfile__(__filemansuffix__) file option. +.TP 8 +.B \-fbbpp \fIn\fP +Sets the number of framebuffer bits per pixel. You should only set this +if you're sure it's necessary; normally the server can deduce the correct +value from +.B \-depth +above. Useful if you want to run a depth 24 configuration with a 24 +bpp framebuffer rather than the (possibly default) 32 bpp framebuffer +(or vice versa). Legal values are 1, 8, 16, 24, 32. Not all drivers +support all values. +.TP 8 +.B \-flipPixels +Swap the default values for the black and white pixels. +.TP 8 +.BI \-gamma " value" +Set the gamma correction. +.I value +must be between 0.1 and 10. The default is 1.0. This value is applied +equally to the R, G and B values. Those values can be set independently +with the +.BR \-rgamma , +.BR \-bgamma , +and +.B \-ggamma +options. Not all drivers support this. +.TP 8 +.BI \-ggamma " value" +Set the green gamma correction. +.I value +must be between 0.1 and 10. The default is 1.0. Not all drivers support +this. See also the +.BR \-gamma , +.BR \-rgamma , +and +.B \-bgamma +options. +.TP 8 +.B \-ignoreABI +The +.B __xservername__ +server checks the ABI revision levels of each module that it loads. It +will normally refuse to load modules with ABI revisions that are newer +than the server's. This is because such modules might use interfaces +that the server does not have. When this option is specified, mismatches +like this are downgraded from fatal errors to warnings. This option +should be used with care. +.TP 8 +.B \-isolateDevice \fIbus\-id\fP +Restrict device resets to the device at +.IR bus\-id . +The +.I bus\-id +string has the form +.IB bustype : bus : device : function +(e.g., \(oqPCI:1:0:0\(cq). +At present, only isolation of PCI devices is supported; i.e., this option +is ignored if +.I bustype +is anything other than \(oqPCI\(cq. +.TP 8 +.B \-keeptty +Prevent the server from detaching its initial controlling terminal. +This option is only useful when debugging the server. Not all platforms +support (or can use) this option. +.TP 8 +.BI \-keyboard " keyboard-name" +Use the __xconfigfile__(__filemansuffix__) file +.B InputDevice +section called +.I keyboard-name +as the core keyboard. This option is ignored when the +.B Layout +section specifies a core keyboard. In the absence of both a Layout +section and this option, the first relevant +.B InputDevice +section is used for the core keyboard. +.TP 8 +.BI \-layout " layout-name" +Use the __xconfigfile__(__filemansuffix__) file +.B Layout +section called +.IR layout-name . +By default the first +.B Layout +section is used. +.TP 8 +.BI \-logfile " filename" +Use the file called +.I filename +as the +.B __xservername__ +server log file. The default log file is +.BI __logdir__/__xservername__. n .log +on most platforms, where +.I n +is the display number of the +.B __xservername__ +server. The default may be in a different directory on some platforms. +This option is only available when the server is run as root (i.e, with +real-uid 0). +.TP 8 +.BR \-logverbose " [\fIn\fP]" +Sets the verbosity level for information printed to the +.B __xservername__ +server log file. If the +.I n +value isn't supplied, each occurrence of this option increments the log +file verbosity level. When the +.I n +value is supplied, the log file verbosity level is set to that value. +The default log file verbosity level is 3. +.TP 8 +.BI \-modulepath " searchpath" +Set the module search path to +.IR searchpath . +.I searchpath +is a comma separated list of directories to search for +.B __xservername__ +server modules. This option is only available when the server is run +as root (i.e, with real-uid 0). +.TP 8 +.B \-nosilk +Disable Silken Mouse support. +.TP 8 +.B \-pixmap24 +Set the internal pixmap format for depth 24 pixmaps to 24 bits per pixel. +The default is usually 32 bits per pixel. There is normally little +reason to use this option. Some client applications don't like this +pixmap format, even though it is a perfectly legal format. This is +equivalent to the +.B Pixmap +__xconfigfile__(__filemansuffix__) file option. +.TP 8 +.B \-pixmap32 +Set the internal pixmap format for depth 24 pixmaps to 32 bits per pixel. +This is usually the default. This is equivalent to the +.B Pixmap +__xconfigfile__(__filemansuffix__) file option. +.TP 8 +.BI \-pointer " pointer-name" +Use the __xconfigfile__(__filemansuffix__) file +.B InputDevice +section called +.I pointer-name +as the core pointer. This option is ignored when the +.B Layout +section specifies a core pointer. In the absence of both a Layout +section and this option, the first relevant +.B InputDevice +section is used for the core pointer. +.TP 8 +.B \-quiet +Suppress most informational messages at startup. The verbosity level +is set to zero. +.TP 8 +.BI \-rgamma " value" +Set the red gamma correction. +.I value +must be between 0.1 and 10. The default is 1.0. Not all drivers support +this. See also the +.BR \-gamma , +.BR \-bgamma , +and +.B \-ggamma +options. +.TP 8 +.BI \-screen " screen-name" +Use the __xconfigfile__(__filemansuffix__) file +.B Screen +section called +.IR screen-name . +By default the screens referenced by the default +.B Layout +section are used, or the first +.B Screen +section when there are no +.B Layout +sections. +.TP 8 +.B \-showconfig +This is the same as the +.B \-version +option, and is included for compatibility reasons. It may be removed +in a future release, so the +.B \-version +option should be used instead. +.TP 8 +.B \-showDefaultModulePath +Print out the default module path the server was compiled with. +.TP 8 +.B \-showDefaultLibPath +Print out the path libraries should be installed to. +.TP 8 +.B \-showopts +For each driver module installed, print out the list of options and their +argument types. +.TP 8 +.BI \-weight " nnn" +Set RGB weighting at 16 bpp. The default is 565. This applies only to +those drivers which support 16 bpp. +.TP 8 +.BR \-verbose " [\fIn\fP]" +Sets the verbosity level for information printed on stderr. If the +.I n +value isn't supplied, each occurrence of this option increments the +verbosity level. When the +.I n +value is supplied, the verbosity level is set to that value. The default +verbosity level is 0. +.TP 8 +.B \-version +Print out the server version, patchlevel, release date, the operating +system/platform it was built on, and whether it includes module loader +support. +.SH "KEYBOARD" +.PP +The +.B __xservername__ +server is normally configured to recognize various special combinations +of key presses that instruct the server to perform some action, rather +than just sending the key press event to a client application. These actions +depend on the XKB keymap loaded by a particular keyboard device and may or +may not be available on a given configuration. +.PP +The following key combinations are commonly part of the default XKEYBOARD +keymap. +.TP 8 +.B Ctrl+Alt+Backspace +Immediately kills the server -- no questions asked. It can be disabled by +setting the +.B DontZap +__xconfigfile__(__filemansuffix__) file option to a TRUE value. +.PP +.RS 8 +It should be noted that zapping is triggered by the +.B Terminate_Server +action in the keyboard map. This action is not part of the default keymaps +but can be enabled with the XKB option +.B \*qterminate:ctrl_alt_bksp\*q. +.RE +.TP 8 +.B Ctrl+Alt+Keypad-Plus +Change video mode to next one specified in the configuration file. +This can be disabled with the +.B DontZoom +__xconfigfile__(__filemansuffix__) file option. +.TP 8 +.B Ctrl+Alt+Keypad-Minus +Change video mode to previous one specified in the configuration file. +This can be disabled with the +.B DontZoom +__xconfigfile__(__filemansuffix__) file option. +.TP 8 +.B Ctrl+Alt+F1...F12 +For systems with virtual terminal support, these keystroke +combinations are used to switch to virtual terminals 1 through 12, +respectively. This can be disabled with the +.B DontVTSwitch +__xconfigfile__(__filemansuffix__) file option. +.SH CONFIGURATION +.B __xservername__ +typically uses a configuration file called +.B __xconfigfile__ +and configuration files with the suffix +.I .conf +in a directory called +.B __xconfigdir__ +for its initial setup. +Refer to the __xconfigfile__(__filemansuffix__) manual page for information +about the format of this file. +.PP +.B __xservername__ +has a mechanism for automatically generating a built-in configuration +at run-time when no +.B __xconfigfile__ +file or +.B __xconfigdir__ +files are present. The current version of this automatic configuration +mechanism works in two ways. +.PP +The first is via enhancements that have made many components of the +.B __xconfigfile__ +file optional. This means that information that can be probed or +reasonably deduced doesn't need to be specified explicitly, greatly +reducing the amount of built-in configuration information that needs to +be generated at run-time. +.PP +The second is to have "safe" fallbacks for most configuration information. +This maximises the likelihood that the +.B __xservername__ +server will start up in some usable configuration even when information +about the specific hardware is not available. +.PP +The automatic configuration support for __xservername__ is work in progress. +It is currently aimed at the most popular hardware and software platforms +supported by __xservername__. Enhancements are planned for future releases. +.SH FILES +The +.B __xservername__ +server config files can be found in a range of locations. These are +documented fully in the __xconfigfile__(__filemansuffix__) manual page. The +most commonly used locations are shown here. +.TP 30 +.B /etc/X11/__xconfigfile__ +Server configuration file. +.TP 30 +.B /etc/X11/__xconfigfile__-4 +Server configuration file. +.TP 30 +.B /etc/__xconfigfile__ +Server configuration file. +.TP 30 +.B __projectroot__/etc/__xconfigfile__ +Server configuration file. +.TP 30 +.B __projectroot__/lib/X11/__xconfigfile__ +Server configuration file. +.TP 30 +.B /etc/X11/__xconfigdir__ +Server configuration directory. +.TP 30 +.B /etc/X11/__xconfigdir__-4 +Server configuration directory. +.TP 30 +.B /etc/__xconfigdir__ +Server configuration directory. +.TP 30 +.B __projectroot__/etc/__xconfigdir__ +Server configuration directory. +.TP 30 +.B __projectroot__/lib/X11/__xconfigdir__ +Server configuration directory. +.TP 30 +.BI __logdir__/__xservername__. n .log +Server log file for display +.IR n . +.TP 30 +.B __projectroot__/bin/\(** +Client binaries. +.TP 30 +.B __projectroot__/include/\(** +Header files. +.TP 30 +.B __projectroot__/lib/\(** +Libraries. +.TP 30 +.B __datadir__/fonts/X11/\(** +Fonts. +.TP 30 +.B __projectroot__/share/X11/XErrorDB +Client error message database. +.TP 30 +.B __projectroot__/lib/X11/app-defaults/\(** +Client resource specifications. +.TP 30 +.B __mandir__/man?/\(** +Manual pages. +.TP 30 +.BI /etc/X n .hosts +Initial access control list for display +.IR n . +.SH "SEE ALSO" +X(__miscmansuffix__), Xserver(__appmansuffix__), xdm(__appmansuffix__), xinit(__appmansuffix__), +__xconfigfile__(__filemansuffix__), xvidtune(__appmansuffix__), +apm(__drivermansuffix__), +ati(__drivermansuffix__), +chips(__drivermansuffix__), +cirrus(__drivermansuffix__), +cyrix(__drivermansuffix__), +fbdev(__drivermansuffix__), +glide(__drivermansuffix__), +glint(__drivermansuffix__), +i128(__drivermansuffix__), +i740(__drivermansuffix__), +imstt(__drivermansuffix__), +intel(__drivermansuffix__), +mga(__drivermansuffix__), +neomagic(__drivermansuffix__), +nsc(__drivermansuffix__), +nv(__drivermansuffix__), +openchrome (__drivermansuffix__), +r128(__drivermansuffix__), +rendition(__drivermansuffix__), +s3virge(__drivermansuffix__), +siliconmotion(__drivermansuffix__), +sis(__drivermansuffix__), +sunbw2(__drivermansuffix__), +suncg14(__drivermansuffix__), +suncg3(__drivermansuffix__), +suncg6(__drivermansuffix__), +sunffb(__drivermansuffix__), +sunleo(__drivermansuffix__), +suntcx(__drivermansuffix__), +tdfx(__drivermansuffix__), +tga(__drivermansuffix__), +trident(__drivermansuffix__), +tseng(__drivermansuffix__), +v4l(__drivermansuffix__), +vesa(__drivermansuffix__), +vmware(__drivermansuffix__), +.br +Web site +.IR . + +.SH AUTHORS +__xservername__ has many contributors world wide. The names of most of them +can be found in the documentation, ChangeLog files in the source tree, +and in the actual source code. +.PP +__xservername__ was originally based on XFree86 4.4rc2. +That was originally based on \fIX386 1.2\fP by Thomas Roell, which +was contributed to the then X Consortium's X11R5 distribution by SGCS. +.PP +__xservername__ is released by the X.Org Foundation. +.PP +The project that became XFree86 was originally founded in 1992 by +David Dawes, Glenn Lai, Jim Tsillas and David Wexelblat. +.PP +XFree86 was later integrated in the then X Consortium's X11R6 release +by a group of dedicated XFree86 developers, including the following: +.PP +.RS 4 +.nf +Stuart Anderson \fIanderson@metrolink.com\fP +Doug Anson \fIdanson@lgc.com\fP +Gertjan Akkerman \fIakkerman@dutiba.twi.tudelft.nl\fP +Mike Bernson \fImike@mbsun.mlb.org\fP +Robin Cutshaw \fIrobin@XFree86.org\fP +David Dawes \fIdawes@XFree86.org\fP +Marc Evans \fImarc@XFree86.org\fP +Pascal Haible \fIhaible@izfm.uni-stuttgart.de\fP +Matthieu Herrb \fIMatthieu.Herrb@laas.fr\fP +Dirk Hohndel \fIhohndel@XFree86.org\fP +David Holland \fIdavidh@use.com\fP +Alan Hourihane \fIalanh@fairlite.demon.co.uk\fP +Jeffrey Hsu \fIhsu@soda.berkeley.edu\fP +Glenn Lai \fIglenn@cs.utexas.edu\fP +Ted Lemon \fImellon@ncd.com\fP +Rich Murphey \fIrich@XFree86.org\fP +Hans Nasten \fInasten@everyware.se\fP +Mark Snitily \fImark@sgcs.com\fP +Randy Terbush \fIrandyt@cse.unl.edu\fP +Jon Tombs \fItombs@XFree86.org\fP +Kees Verstoep \fIversto@cs.vu.nl\fP +Paul Vixie \fIpaul@vix.com\fP +Mark Weaver \fIMark_Weaver@brown.edu\fP +David Wexelblat \fIdwex@XFree86.org\fP +Philip Wheatley \fIPhilip.Wheatley@ColumbiaSC.NCR.COM\fP +Thomas Wolfram \fIwolf@prz.tu-berlin.de\fP +Orest Zborowski \fIorestz@eskimo.com\fP +.fi +.RE +.PP +__xservername__ source is available from the FTP server +\fI\fP, and from the X.Org +server \fI\fP. Documentation and other +information can be found from the X.Org web site +\fI\fP. + +.SH LEGAL +.PP +.B __xservername__ +is copyright software, provided under licenses that permit modification +and redistribution in source and binary form without fee. +.B __xservername__ is copyright by numerous authors and +contributors from around the world. Licensing information can be found +at +.IR . +Refer to the source code for specific copyright notices. +.PP +.B XFree86(TM) +is a trademark of The XFree86 Project, Inc. +.PP +.B X11(TM) +and +.B X Window System(TM) +are trademarks of The Open Group. diff --git a/xorg-server/hw/xfree86/man/xorg.conf.d.man b/xorg-server/hw/xfree86/man/xorg.conf.d.man new file mode 100644 index 000000000..6b3379ece --- /dev/null +++ b/xorg-server/hw/xfree86/man/xorg.conf.d.man @@ -0,0 +1 @@ +.so man__filemansuffix__/xorg.conf.__filemansuffix__ diff --git a/xorg-server/hw/xfree86/man/xorg.conf.man b/xorg-server/hw/xfree86/man/xorg.conf.man new file mode 100644 index 000000000..e3fd0eadf --- /dev/null +++ b/xorg-server/hw/xfree86/man/xorg.conf.man @@ -0,0 +1,2478 @@ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH __xconfigfile__ __filemansuffix__ __vendorversion__ +.SH NAME +__xconfigfile__ and __xconfigdir__ \- configuration files for +__xservername__ X server +.SH INTRODUCTION +.B __xservername__ +supports several mechanisms for supplying/obtaining configuration and +run-time parameters: command line options, environment variables, the +__xconfigfile__ and __xconfigdir__ configuration files, auto-detection, +and fallback defaults. When the same information is supplied in more +than one way, the highest precedence mechanism is used. The list of +mechanisms is ordered from highest precedence to lowest. Note that not +all parameters can be supplied via all methods. The available command +line options and environment variables (and some defaults) are +described in the Xserver(__appmansuffix__) and +__xservername__(__appmansuffix__) manual pages. Most configuration file +parameters, with their defaults, are described below. Driver and module +specific configuration parameters are described in the relevant driver +or module manual page. +.SH DESCRIPTION +.B __xservername__ +uses a configuration file called +.I __xconfigfile__ +and files ending in the suffix +.I .conf +from the directory +.I __xconfigdir__ +for its initial setup. +The +.I __xconfigfile__ +configuration file is searched for in the following places when the +server is started as a normal user: +.PP +.RS 4 +.nf +.IR /etc/X11/ +.IR __projectroot__/etc/X11/ +.IB /etc/X11/ $XORGCONFIG +.IB __projectroot__/etc/X11/ $XORGCONFIG +.I /etc/X11/__xconfigfile__ +.I /etc/__xconfigfile__ +.IR __projectroot__/etc/X11/__xconfigfile__. +.I __projectroot__/etc/X11/__xconfigfile__ +.IR __projectroot__/lib/X11/__xconfigfile__. +.I __projectroot__/lib/X11/__xconfigfile__ +.fi +.RE +.PP +where +.I +is a relative path (with no \(lq..\(rq components) specified with the +.B \-config +command line option, +.B $XORGCONFIG +is the relative path (with no \(lq..\(rq components) specified by that +environment variable, and +.I +is the machine's hostname as reported by +.BR gethostname (__libmansuffix__). +.PP +When the __xservername__ server is started by the \(lqroot\(rq user, the config file +search locations are as follows: +.PP +.RS 4 +.nf + +.IR /etc/X11/ +.IR __projectroot__/etc/X11/ +.B $XORGCONFIG +.IB /etc/X11/ $XORGCONFIG +.IB __projectroot__/etc/X11/ $XORGCONFIG +.I /etc/X11/__xconfigfile__ +.I /etc/__xconfigfile__ +.IR __projectroot__/etc/X11/__xconfigfile__. +.I __projectroot__/etc/X11/__xconfigfile__ +.IR __projectroot__/lib/X11/__xconfigfile__. +.I __projectroot__/lib/X11/__xconfigfile__ +.fi +.RE +.PP +where +.I +is the path specified with the +.B \-config +command line option (which may be absolute or relative), +.B $XORGCONFIG +is the path specified by that +environment variable (absolute or relative), +.B $HOME +is the path specified by that environment variable (usually the home +directory), and +.I +is the machine's hostname as reported by +.BR gethostname (__libmansuffix__). +.PP +Additional configuration files are searched for in the following +directories when the server is started as a normal user: +.PP +.RS 4 +.nf +.IR /etc/X11/ +.IR __sysconfdir__/X11/ +.I /etc/X11/__xconfigdir__ +.I __sysconfdir__/X11/__xconfigdir__ +.fi +.RE +.PP +where +.I +is a relative path (with no \(lq..\(rq components) specified with the +.B \-configdir +command line option. +.PP +When the __xservername__ server is started by the \(lqroot\(rq user, the +config directory search locations are as follows: +.PP +.RS 4 +.nf + +.IR /etc/X11/ +.IR __sysconfdir__/X11/ +.I /etc/X11/__xconfigdir__ +.I __sysconfdir__/X11/__xconfigdir__ +.fi +.RE +.PP +where +.I +is the path specified with the +.B \-configdir +command line option (which may be absolute or relative). +.PP +Finally, configuration files will also be searched for in directories +reserved for system use. These are to separate configuration files from +the vendor or 3rd party packages from those of local administration. +These files are found in the following directories: +.PP +.RS 4 +.nf +.I /usr/share/X11/__xconfigdir__ +.I __datadir__/X11/__xconfigdir__ +.fi +.RE +.PP +The +.I __xconfigfile__ +and +.I __xconfigdir__ +files are composed of a number of sections which may be present in any order, +or omitted to use default configuration values. +Each section has the form: +.PP +.RS 4 +.nf +.BI "Section \*q" SectionName \*q +.RI " " SectionEntry + ... +.B EndSection +.fi +.RE +.PP +The section names are: +.PP +.RS 4 +.nf +.BR "Files " "File pathnames" +.BR "ServerFlags " "Server flags" +.BR "Module " "Dynamic module loading" +.BR "Extensions " "Extension enabling" +.BR "InputDevice " "Input device description" +.BR "InputClass " "Input class description" +.BR "Device " "Graphics device description" +.BR "VideoAdaptor " "Xv video adaptor description" +.BR "Monitor " "Monitor description" +.BR "Modes " "Video modes descriptions" +.BR "Screen " "Screen configuration" +.BR "ServerLayout " "Overall layout" +.BR "DRI " "DRI\-specific configuration" +.BR "Vendor " "Vendor\-specific configuration" +.fi +.RE +.PP +The following obsolete section names are still recognised for compatibility +purposes. +In new config files, the +.B InputDevice +section should be used instead. +.PP +.RS 4 +.nf +.BR "Keyboard " "Keyboard configuration" +.BR "Pointer " "Pointer/mouse configuration" +.fi +.RE +.PP +The old +.B XInput +section is no longer recognised. +.PP +The +.B ServerLayout +sections are at the highest level. +They bind together the input and output devices that will be used in a session. +The input devices are described in the +.B InputDevice +sections. +Output devices usually consist of multiple independent components (e.g., +a graphics board and a monitor). +These multiple components are bound together in the +.B Screen +sections, and it is these that are referenced by the +.B ServerLayout +section. +Each +.B Screen +section binds together a graphics board and a monitor. +The graphics boards are described in the +.B Device +sections, and the monitors are described in the +.B Monitor +sections. +.PP +Config file keywords are case\-insensitive, and \(lq_\(rq characters are +ignored. +Most strings (including +.B Option +names) are also case-insensitive, and insensitive to white space and +\(lq_\(rq characters. +.PP +Each config file entry usually takes up a single line in the file. They +consist of a keyword, which is possibly followed by one or more arguments, +with the number and types of the arguments depending on the keyword. +The argument types are: +.PP +.RS 4 +.nf +.BR "Integer " "an integer number in decimal, hex or octal" +.BR "Real " "a floating point number" +.BR "String " "a string enclosed in double quote marks (\*q)" +.fi +.RE +.PP +Note: hex integer values must be prefixed with \(lq0x\(rq, and octal values +with \(lq0\(rq. +.PP +A special keyword called +.B Option +may be used to provide free\-form data to various components of the server. +The +.B Option +keyword takes either one or two string arguments. +The first is the option name, and the optional second argument is the +option value. +Some commonly used option value types include: +.PP +.RS 4 +.nf +.BR "Integer " "an integer number in decimal, hex or octal" +.BR "Real " "a floating point number" +.BR "String " "a sequence of characters" +.BR "Boolean " "a boolean value (see below)" +.BR "Frequency " "a frequency value (see below)" +.fi +.RE +.PP +Note that +.I all +.B Option +values, not just strings, must be enclosed in quotes. +.PP +Boolean options may optionally have a value specified. +When no value is specified, the option's value is +.BR TRUE . +The following boolean option values are recognised as +.BR TRUE : +.PP +.RS 4 +.BR 1 , +.BR on , +.BR true , +.B yes +.RE +.PP +and the following boolean option values are recognised as +.BR FALSE : +.PP +.RS 4 +.BR 0 , +.BR off , +.BR false , +.B no +.RE +.PP +If an option name is prefixed with +.RB \*q No \*q, +then the option value is negated. +.PP +Example: the following option entries are equivalent: +.PP +.RS 4 +.nf +.B "Option \*qAccel\*q \*qOff\*q" +.B "Option \*qNoAccel\*q" +.B "Option \*qNoAccel\*q \*qOn\*q" +.B "Option \*qAccel\*q \*qfalse\*q" +.B "Option \*qAccel\*q \*qno\*q" +.fi +.RE +.PP +Frequency option values consist of a real number that is optionally +followed by one of the following frequency units: +.PP +.RS 4 +.BR Hz , +.BR k , +.BR kHz , +.BR M , +.B MHz +.RE +.PP +When the unit name is omitted, the correct units will be determined from +the value and the expectations of the appropriate range of the value. +It is recommended that the units always be specified when using frequency +option values to avoid any errors in determining the value. +.SH "FILES SECTION" +The +.B Files +section is used to specify some path names required by the server. +Some of these paths can also be set from the command line (see +.BR Xserver (__appmansuffix__) +and +.BR __xservername__ (__appmansuffix__)). +The command line settings override the values specified in the config +file. +The +.B Files +section is optional, as are all of the entries that may appear in it. +.PP +The entries that can appear in this section are: +.TP 7 +.BI "FontPath \*q" path \*q +sets the search path for fonts. +This path is a comma separated list of font path elements which the __xservername__ +server searches for font databases. +Multiple +.B FontPath +entries may be specified, and they will be concatenated to build up the +fontpath used by the server. Font path elements can be absolute +directory paths, catalogue directories or a font server identifier. The +formats of the later two are explained below: +.PP +.RS 7 +Catalogue directories: +.PP +.RS 4 +Catalogue directories can be specified using the prefix \fBcatalogue:\fR +before the directory name. The directory can then be populated with +symlinks pointing to the real font directories, using the following +syntax in the symlink name: +.PP +.RS 4 +.IR : [attribute]: pri= +.RE +.PP +where +.I +is an alphanumeric identifier, +.I [attribute] +is an attribute which will be passed to the underlying FPE and +.I +is a number used to order the fontfile FPEs. Examples: +.PP +.RS 4 +.nf +.I 75dpi:unscaled:pri=20 -> /usr/share/X11/fonts/75dpi +.I gscript:pri=60 -> /usr/share/fonts/default/ghostscript +.I misc:unscaled:pri=10 \-> /usr/share/X11/fonts/misc +.fi +.PP +.RE .RE .RE +.PP +.RS 7 +Font server identifiers: +.PP +.RS 4 +Font server identifiers have the form: +.RS 4 +.PP +.IR / : +.RE +.PP +where +.I +is the transport type to use to connect to the font server (e.g., +.B unix +for UNIX\-domain sockets or +.B tcp +for a TCP/IP connection), +.I +is the hostname of the machine running the font server, and +.I +is the port number that the font server is listening on (usually 7100). +.RE +.PP +When this entry is not specified in the config file, the server falls back +to the compiled\-in default font path, which contains the following +font path elements (which can be set inside a catalogue directory): +.PP +.RS 4 +.nf +.I __datadir__/fonts/X11/misc/ +.I __datadir__/fonts/X11/TTF/ +.I __datadir__/fonts/X11/OTF/ +.I __datadir__/fonts/X11/Type1/ +.I __datadir__/fonts/X11/100dpi/ +.I __datadir__/fonts/X11/75dpi/ +.fi +.RE +.PP +Font path elements that are found to be invalid are removed from the +font path when the server starts up. +.RE +.TP 7 +.BI "ModulePath \*q" path \*q +sets the search path for loadable __xservername__ server modules. +This path is a comma separated list of directories which the __xservername__ server +searches for loadable modules loading in the order specified. +Multiple +.B ModulePath +entries may be specified, and they will be concatenated to build the +module search path used by the server. The default module path is +.PP +.RS 11 +__modulepath__ +.RE +.\" The LogFile keyword is not currently implemented +.ig +.TP 7 +.BI "LogFile \*q" path \*q +sets the name of the __xservername__ server log file. +The default log file name is +.PP +.RS 11 +.RI __logdir__/__xservername__. .log +.RE +.PP +.RS 7 +where +.I +is the display number for the __xservername__ server. +.. +.TP 7 +.BI "XkbDir \*q" path \*q +sets the base directory for keyboard layout files. The +.B \-xkbdir +command line option can be used to override this. The default directory is +.PP +.RS 11 +__xkbdir__ +.RE +.SH "SERVERFLAGS SECTION" +In addition to options specific to this section (described below), the +.B ServerFlags +section is used to specify some global +__xservername__ server options. +All of the entries in this section are +.BR Options , +although for compatibility purposes some of the old style entries are +still recognised. +Those old style entries are not documented here, and using them is +discouraged. +The +.B ServerFlags +section is optional, as are the entries that may be specified in it. +.PP +.B Options +specified in this section (with the exception of the +.B \*qDefaultServerLayout\*q +.BR Option ) +may be overridden by +.B Options +specified in the active +.B ServerLayout +section. +Options with command line equivalents are overridden when their command +line equivalent is used. +The options recognised by this section are: +.TP 7 +.BI "Option \*qDefaultServerLayout\*q \*q" layout\-id \*q +This specifies the default +.B ServerLayout +section to use in the absence of the +.B \-layout +command line option. +.TP 7 +.BI "Option \*qNoTrapSignals\*q \*q" boolean \*q +This prevents the __xservername__ server from trapping a range of unexpected fatal +signals and exiting cleanly. +Instead, the __xservername__ server will die and drop core where the fault occurred. +The default behaviour is for the __xservername__ server to exit cleanly, but still drop a +core file. +In general you never want to use this option unless you are debugging an __xservername__ +server problem and know how to deal with the consequences. +.TP 7 +.BI "Option \*qUseSIGIO\*q \*q" boolean \*q +This controls whether the __xservername__ server requests that events from +input devices be reported via a SIGIO signal handler (also known as SIGPOLL +on some platforms), or only reported via the standard select(3) loop. +The default behaviour is platform specific. In general you do not want to +use this option unless you are debugging the __xservername__ server, or +working around a specific bug until it is fixed, and understand the +consequences. +.TP 7 +.BI "Option \*qDontVTSwitch\*q \*q" boolean \*q +This disallows the use of the +.BI Ctrl+Alt+F n +sequence (where +.RI F n +refers to one of the numbered function keys). +That sequence is normally used to switch to another \*qvirtual terminal\*q +on operating systems that have this feature. +When this option is enabled, that key sequence has no special meaning and +is passed to clients. +Default: off. +.TP 7 +.BI "Option \*qDontZap\*q \*q" boolean \*q +This disallows the use of the +.B Terminate_Server +XKB action (usually on Ctrl+Alt+Backspace, depending on XKB options). +This action is normally used to terminate the __xservername__ server. +When this option is enabled, the action has no effect. +Default: off. +.TP 7 +.BI "Option \*qDontZoom\*q \*q" boolean \*q +This disallows the use of the +.B Ctrl+Alt+Keypad\-Plus +and +.B Ctrl+Alt+Keypad\-Minus +sequences. +These sequences allows you to switch between video modes. +When this option is enabled, those key sequences have no special meaning +and are passed to clients. +Default: off. +.TP 7 +.BI "Option \*qDisableVidModeExtension\*q \*q" boolean \*q +This disables the parts of the VidMode extension used by the xvidtune client +that can be used to change the video modes. +Default: the VidMode extension is enabled. +.TP 7 +.BI "Option \*qAllowNonLocalXvidtune\*q \*q" boolean \*q +This allows the xvidtune client (and other clients that use the VidMode +extension) to connect from another host. +Default: off. +.TP 7 +.BI "Option \*qAllowMouseOpenFail\*q \*q" boolean \*q +This tells the mousedrv(__drivermansuffix__) and vmmouse(__drivermansuffix__) +drivers to not report failure if the mouse device can't be opened/initialised. +It has no effect on the evdev(__drivermansuffix__) or other drivers. +Default: false. +.TP 7 +.BI "Option \*qVTSysReq\*q \*q" boolean \*q +enables the SYSV\-style VT switch sequence for non\-SYSV systems +which support VT switching. +This sequence is +.B Alt\-SysRq +followed by a function key +.RB ( Fn ). +This prevents the __xservername__ server trapping the +keys used for the default VT switch sequence, which means that clients can +access them. +Default: off. +.TP 7 +.BI "Option \*qBlankTime\*q \*q" time \*q +sets the inactivity timeout for the +.B blank +phase of the screensaver. +.I time +is in minutes. +This is equivalent to the __xservername__ server's +.B \-s +flag, and the value can be changed at run\-time with +.BR xset(__appmansuffix__). +Default: 10 minutes. +.TP 7 +.BI "Option \*qStandbyTime\*q \*q" time \*q +sets the inactivity timeout for the +.B standby +phase of DPMS mode. +.I time +is in minutes, and the value can be changed at run\-time with +.BR xset(__appmansuffix__). +Default: 10 minutes. +This is only suitable for VESA DPMS compatible monitors, and may not be +supported by all video drivers. +It is only enabled for screens that have the +.B \*qDPMS\*q +option set (see the MONITOR section below). +.TP 7 +.BI "Option \*qSuspendTime\*q \*q" time \*q +sets the inactivity timeout for the +.B suspend +phase of DPMS mode. +.I time +is in minutes, and the value can be changed at run\-time with +.BR xset(__appmansuffix__). +Default: 10 minutes. +This is only suitable for VESA DPMS compatible monitors, and may not be +supported by all video drivers. +It is only enabled for screens that have the +.B \*qDPMS\*q +option set (see the MONITOR section below). +.TP 7 +.BI "Option \*qOffTime\*q \*q" time \*q +sets the inactivity timeout for the +.B off +phase of DPMS mode. +.I time +is in minutes, and the value can be changed at run\-time with +.BR xset(__appmansuffix__). +Default: 10 minutes. +This is only suitable for VESA DPMS compatible monitors, and may not be +supported by all video drivers. +It is only enabled for screens that have the +.B \*qDPMS\*q +option set (see the MONITOR section below). +.TP 7 +.BI "Option \*qPixmap\*q \*q" bpp \*q +This sets the pixmap format to use for depth 24. +Allowed values for +.I bpp +are 24 and 32. +Default: 32 unless driver constraints don't allow this (which is rare). +Note: some clients don't behave well when this value is set to 24. +.TP 7 +.BI "Option \*qPC98\*q \*q" boolean \*q +Specify that the machine is a Japanese PC\-98 machine. +This should not be enabled for anything other than the Japanese\-specific +PC\-98 architecture. +Default: auto\-detected. +.TP 7 +.BI "Option \*qNoPM\*q \*q" boolean \*q +Disables something to do with power management events. +Default: PM enabled on platforms that support it. +.TP 7 +.BI "Option \*qXinerama\*q \*q" boolean \*q +enable or disable XINERAMA extension. +Default is disabled. +.TP 7 +.BI "Option \*qAIGLX\*q \*q" boolean \*q +enable or disable AIGLX. AIGLX is enabled by default. +.TP 7 +.BI "Option \*qDRI2\*q \*q" boolean \*q +enable or disable DRI2. DRI2 is disabled by default. +.TP 7 +.BI "Option \*qGlxVisuals\*q \*q" string \*q +This option controls how many GLX visuals the GLX modules sets up. +The default value is +.BR "typical" , +which will setup up a typical subset of +the GLXFBConfigs provided by the driver as GLX visuals. Other options are +.BR "minimal" , +which will set up the minimal set allowed by the GLX specification and +.BR "all" +which will setup GLX visuals for all GLXFBConfigs. +.TP 7 +.BI "Option \*qUseDefaultFontPath\*q \*q" boolean \*q +Include the default font path even if other paths are specified in +xorg.conf. If enabled, other font paths are included as well. Enabled by +default. +.TP 7 +.BI "Option \*qIgnoreABI\*q \*q" boolean \*q +Allow modules built for a different, potentially incompatible version of +the X server to load. Disabled by default. +.TP 7 +.BI "Option \*qAutoAddDevices\*q \*q" boolean \*q +If this option is disabled, then no devices will be added from HAL events. +Enabled by default. +.TP 7 +.BI "Option \*qAutoEnableDevices\*q \*q" boolean \*q +If this option is disabled, then the devices will be added (and the +DevicePresenceNotify event sent), but not enabled, thus leaving policy up +to the client. +Enabled by default. +.TP 7 +.BI "Option \*qLog\*q \*q" string \*q +This option controls whether the log is flushed and/or synced to disk after +each message. +Possible values are +.B flush +or +.BR sync . +Unset by default. +.SH "MODULE SECTION" +The +.B Module +section is used to specify which __xservername__ server modules should be loaded. +This section is ignored when the __xservername__ server is built in static form. +The type of modules normally loaded in this section are __xservername__ server +extension modules. +Most other module types are loaded automatically when they are needed via +other mechanisms. +The +.B Module +section is optional, as are all of the entries that may be specified in +it. +.PP +Entries in this section may be in two forms. +The first and most commonly used form is an entry that uses the +.B Load +keyword, as described here: +.TP 7 +.BI "Load \*q" modulename \*q +This instructs the server to load the module called +.IR modulename . +The module name given should be the module's standard name, not the +module file name. +The standard name is case\-sensitive, and does not include the \(lqlib\(rq +prefix, or the \(lq.a\(rq, \(lq.o\(rq, or \(lq.so\(rq suffixes. +.PP +.RS 7 +Example: the DRI extension module can be loaded with the following entry: +.PP +.RS 4 +.B "Load \*qdri\*q" +.RE +.RE +.TP 7 +.BI "Disable \*q" modulename \*q +This instructs the server to not load the module called +.IR modulename . +Some modules are loaded by default in the server, and this overrides that +default. If a +.B Load +instruction is given for the same module, it overrides the +.B Disable +instruction and the module is loaded. The module name given should be the +module's standard name, not the module file name. As with the +.B Load +instruction, the standard name is case-sensitive, and does not include the +"lib" prefix, or the ".a", ".o", or ".so" suffixes. +.PP +The second form of entry is a +.BR SubSection, +with the subsection name being the module name, and the contents of the +.B SubSection +being +.B Options +that are passed to the module when it is loaded. +.PP +Example: the extmod module (which contains a miscellaneous group of +server extensions) can be loaded, with the XFree86\-DGA extension +disabled by using the following entry: +.PP +.RS 4 +.nf +.B "SubSection \*qextmod\*q" +.B " Option \*qomit XFree86\-DGA\*q" +.B EndSubSection +.fi +.RE +.PP +Modules are searched for in each directory specified in the +.B ModulePath +search path, and in the drivers, extensions, input, internal, and +multimedia subdirectories of each of those directories. +In addition to this, operating system specific subdirectories of all +the above are searched first if they exist. +.PP +To see what extension modules are available, check the extensions +subdirectory under: +.PP +.RS 4 +.nf +__modulepath__ +.fi +.RE +.PP +The \(lqextmod\(rq, \(lqdbe\(rq, \(lqdri\(rq, \(lqdri2\(rq, \(lqglx\(rq, +and \(lqrecord\(rq extension modules are loaded automatically, if they +are present, unless disabled with \*qDisable\*q entries. +It is recommended +that at very least the \(lqextmod\(rq extension module be loaded. +If it isn't, some commonly used server extensions (like the SHAPE +extension) will not be available. +.SH "EXTENSIONS SECTION" +The +.B Extensions +section is used to specify which X11 protocol extensions should be enabled +or disabled. +The +.B Extensions +section is optional, as are all of the entries that may be specified in +it. +.PP +Entries in this section are listed as Option statements with the name of +the extension as the first argument, and a boolean value as the second. +The extension name is case\-sensitive, and matches the form shown in the output +of \*qXorg -extension ?\*q. +.PP +.RS 7 +Example: the MIT-SHM extension can be disabled with the following entry: +.PP +.RS 4 +.nf +.B "Section \*qExtensions\*q" +.B " Option \*qMIT-SHM\*q \*qDisable\*q" +.B "EndSection" +.fi +.RE +.RE +.SH "INPUTDEVICE SECTION" +The config file may have multiple +.B InputDevice +sections. +Recent X servers employ input hotplugging to add input devices, with the HAL +backend being the default backend for X servers since 1.4. It is usually not +necessary to provide +.B InputDevice +sections in the xorg.conf if hotplugging is enabled. +.PP +If hotplugging is disabled, there will normally +be at least two: one for the core (primary) keyboard +and one for the core pointer. +If either of these two is missing, a default configuration for the missing +ones will be used. In the absence of an explicitly specified core input +device, the first +.B InputDevice +marked as +.B CorePointer +(or +.BR CoreKeyboard ) +is used. +If there is no match there, the first +.B InputDevice +that uses the \(lqmouse\(rq (or \(lqkbd\(rq) driver is used. +The final fallback is to use built\-in default configurations. +Currently the default configuration may not work as expected on all platforms. +.PP +.B InputDevice +sections have the following format: +.PP +.RS 4 +.nf +.B "Section \*qInputDevice\*q" +.BI " Identifier \*q" name \*q +.BI " Driver \*q" inputdriver \*q +.I " options" +.I " ..." +.B "EndSection" +.fi +.RE +.PP +The +.B Identifier +and +.B Driver +entries are required in all +.B InputDevice +sections. +All other entries are optional. +.PP +The +.B Identifier +entry specifies the unique name for this input device. +The +.B Driver +entry specifies the name of the driver to use for this input device. +When using the loadable server, the input driver module +.RI \*q inputdriver \*q +will be loaded for each active +.B InputDevice +section. +An +.B InputDevice +section is considered active if it is referenced by an active +.B ServerLayout +section, if it is referenced by the +.B \-keyboard +or +.B \-pointer +command line options, or if it is selected implicitly as the core pointer +or keyboard device in the absence of such explicit references. +The most commonly used input drivers are +.BR evdev (__drivermansuffix__) +on Linux systems, and +.BR kbd (__drivermansuffix__) +and +.BR mousedrv (__drivermansuffix__) +on other platforms. +.PP +.PP +.B InputDevice +sections recognise some driver\-independent +.BR Options , +which are described here. +See the individual input driver manual pages for a description of the +device\-specific options. +.TP 7 +.BI "Option \*qAutoServerLayout\*q \*q" boolean \*q +Always add the device to the ServerLayout section used by this instance of +the server. This affects implied layouts as well as explicit layouts +specified in the configuration and/or on the command line. +.TP 7 +.BI "Option \*qCorePointer\*q" +Deprecated, see +.B Floating +.TP 7 +.BI "Option \*qCoreKeyboard\*q" +Deprecated, see +.B Floating +.TP 7 +.BI "Option \*qAlwaysCore\*q \*q" boolean \*q +Deprecated, see +.B Floating +.TP 7 +.BI "Option \*qSendCoreEvents\*q \*q" boolean \*q +Deprecated, see +.B Floating + +.TP 7 +.BI "Option \*qFloating\*q \*q" boolean \*q +When enabled, the input device is set up floating and does not +report events through any master device or control a cursor. The device is +only available to clients using the X Input Extension API. This option is +disabled by default. +The options +.B CorePointer, +.B CoreKeyboard, +.B AlwaysCore, +and +.B SendCoreEvents, +are the inverse of option +.B Floating +(i.e. +.B SendCoreEvents \*qon\*q +is equivalent to +.B Floating \*qoff\*q +). + +This option controls the startup behavior only, a device +may be reattached or set floating at runtime. +.PP +For pointing devices, the following options control how the pointer +is accelerated or decelerated with respect to physical device motion. Most of +these can be adjusted at runtime, see the xinput(1) man page for details. Only +the most important acceleration options are discussed here. +.TP 7 +.BI "Option \*qAccelerationProfile\*q \*q" integer \*q +Select the profile. In layman's terms, the profile constitutes the "feeling" of +the acceleration. More formally, it defines how the transfer function (actual +acceleration as a function of current device velocity and acceleration controls) +is constructed. This is mainly a matter of personal preference. +.PP +.RS 6 +.nf +.B " 0 classic (mostly compatible)" +.B "-1 none (only constant deceleration is applied)" +.B " 1 device-dependent" +.B " 2 polynomial (polynomial function)" +.B " 3 smooth linear (soft knee, then linear)" +.B " 4 simple (normal when slow, otherwise accelerated)" +.B " 5 power (power function)" +.B " 6 linear (more speed, more acceleration)" +.B " 7 limited (like linear, but maxes out at threshold)" +.fi +.RE +.TP 7 +.BI "Option \*qConstantDeceleration\*q \*q" real \*q +Makes the pointer go +.B deceleration +times slower than normal. Most useful for high-resolution devices. +.TP 7 +.BI "Option \*qAdaptiveDeceleration\*q \*q" real \*q +Allows to actually decelerate the pointer when going slow. At most, it will be +.B adaptive deceleration +times slower. Enables precise pointer placement without sacrificing speed. +.TP 7 +.BI "Option \*qAccelerationScheme\*q \*q" string \*q +Selects the scheme, which is the underlying algorithm. +.PP +.RS 7 +.nf +.B "predictable default algorithm (behaving more predictable)" +.B "lightweight old acceleration code (as specified in the X protocol spec)" +.B "none no acceleration or deceleration" +.fi +.RE +.TP 7 +.BI "Option \*qAccelerationNumerator\*q \*q" integer \*q +.TP 7 +.BI "Option \*qAccelerationDenominator\*q \*q" integer \*q +Set numerator and denominator of the acceleration factor. The acceleration +factor is a rational which, together with threshold, can be used to tweak +profiles to suit the users needs. The +.B simple +and +.B limited +profiles use it directly (i.e. they accelerate by the factor), for other +profiles it should hold that a higher acceleration factor leads to a faster +pointer. Typically, 1 is unaccelerated and values up to 5 are sensible. +.TP 7 +.BI "Option \*qAccelerationThreshold\*q \*q" integer \*q +Set the threshold, which is roughly the velocity (usually device units per 10 +ms) required for acceleration to become effective. The precise effect varies +with the profile however. + +.SH "INPUTCLASS SECTION" +The config file may have multiple +.B InputClass +sections. +These sections are optional and are used to provide configuration for a +class of input devices as they are automatically added. An input device can +match more than one +.B InputClass +section. Each class can override settings from a previous class, so it is +best to arrange the sections with the most generic matches first. +.PP +.B InputClass +sections have the following format: +.PP +.RS 4 +.nf +.B "Section \*qInputClass\*q" +.BI " Identifier \*q" name \*q +.I " entries" +.I " ..." +.I " options" +.I " ..." +.B "EndSection" +.fi +.RE +.PP +The +.B Identifier +entry is required in all +.B InputClass +sections. +All other entries are optional. +.PP +The +.B Identifier +entry specifies the unique name for this input class. +The +.B Driver +entry specifies the name of the driver to use for this input device. +After all classes have been examined, the +.RI \*q inputdriver \*q +module from the first +.B Driver +entry will be enabled when using the loadable server. +.PP +When an input device is automatically added, its characteristics are +checked against all +.B InputClass +sections. Each section can contain optional entries to narrow the match +of the class. If none of the optional entries appear, the +.B InputClass +section is generic and will match any input device. If more than one of +these entries appear, they all must match for the configuration to apply. +.PP +There are two types of match entries used in +.B InputClass +sections. The first allows various tokens to be matched against attributes +of the device. An entry can be constructed to match attributes from different +devices by separating arguments with a '|' character. Multiple entries of the +same type may be supplied to add multiple matching conditions on the same +attribute. For example: +.PP +.RS 4 +.nf +.B "Section \*qInputClass\*q" +.B " Identifier \*qMy Class\*q" +.B " # product string must contain example and +.B " # either gizmo or gadget +.B " MatchProduct \*qexample\*q +.B " MatchProduct \*qgizmo|gadget\*q +.I " ..." +.B "EndSection" +.fi +.RE +.TP 7 +.BI "MatchProduct \*q" matchproduct \*q +This entry can be used to check if the substring +.RI \*q matchproduct \*q +occurs in the device's product name. +.TP 7 +.BI "MatchVendor \*q" matchvendor \*q +This entry can be used to check if the substring +.RI \*q matchvendor \*q +occurs in the device's vendor name. +.TP 7 +.BI "MatchDevicePath \*q" matchdevice \*q +This entry can be used to check if the device file matches the +.RI \*q matchdevice \*q +pathname pattern. +.TP 7 +.BI "MatchOS \*q" matchos \*q +This entry can be used to check if the operating system matches the +case-insensitive +.RI \*q matchos \*q +string. This entry is only supported on platforms providing the +.BR uname (2) +system call. +.TP 7 +.BI "MatchPnPID \*q" matchpnp \*q +The device's Plug and Play (PnP) ID can be checked against the +.RI \*q matchpnp \*q +shell wildcard pattern. +.TP 7 +.BI "MatchUSBID \*q" matchusb \*q +The device's USB ID can be checked against the +.RI \*q matchusb \*q +shell wildcard pattern. The ID is constructed as lowercase hexadecimal numbers +separated by a ':'. This is the same format as the +.BR lsusb (8) +program. +.TP 7 +.BI "MatchDriver \*q" matchdriver \*q +Check the case-sensitive string +.RI \*q matchdriver \*q +against the currently configured driver of the device. Ordering of sections +using this entry is important since it will not match unless the driver has +been set by the config backend or a previous +.B InputClass +section. +.TP 7 +.BI "MatchTag \*q" matchtag \*q +This entry can be used to check if tags assigned by the config backend +matches the +.RI \*q matchtag \*q +pattern. A match is found if at least one of the tags given in +.RI \*q matchtag \*q +matches at least one of the tags assigned by the backend. +.PP +The second type of entry is used to match device types. These entries take a +boolean argument similar to +.B Option +entries. +.TP 7 +.BI "MatchIsKeyboard \*q" bool \*q +.TP 7 +.BI "MatchIsPointer \*q" bool \*q +.TP 7 +.BI "MatchIsJoystick \*q" bool \*q +.TP 7 +.BI "MatchIsTablet \*q" bool \*q +.TP 7 +.BI "MatchIsTouchpad \*q" bool \*q +.TP 7 +.BI "MatchIsTouchscreen \*q" bool \*q +.PP +When an input device has been matched to the +.B InputClass +section, any +.B Option +entries are applied to the device. One +.B InputClass +specific +.B Option +is recognized. See the +.B InputDevice +section above for a description of the remaining +.B Option +entries. +.TP 7 +.BI "Option \*qIgnore\*q \*q" boolean \*q +This optional entry specifies that the device should be ignored entirely, +and not added to the server. This can be useful when the device is handled +by another program and no X events should be generated. +.SH "DEVICE SECTION" +The config file may have multiple +.B Device +sections. +There must be at least one, for the video card being used. +.PP +.B Device +sections have the following format: +.PP +.RS 4 +.nf +.B "Section \*qDevice\*q" +.BI " Identifier \*q" name \*q +.BI " Driver \*q" driver \*q +.I " entries" +.I " ..." +.B "EndSection" +.fi +.RE +.PP +The +.B Identifier +and +.B Driver +entries are required in all +.B Device +sections. All other entries are optional. +.PP +The +.B Identifier +entry specifies the unique name for this graphics device. +The +.B Driver +entry specifies the name of the driver to use for this graphics device. +When using the loadable server, the driver module +.RI \*q driver \*q +will be loaded for each active +.B Device +section. +A +.B Device +section is considered active if it is referenced by an active +.B Screen +section. +.PP +.B Device +sections recognise some driver\-independent entries and +.BR Options , +which are described here. +Not all drivers make use of these +driver\-independent entries, and many of those that do don't require them +to be specified because the information is auto\-detected. +See the individual graphics driver manual pages for further information +about this, and for a description of the device\-specific options. +Note that most of the +.B Options +listed here (but not the other entries) may be specified in the +.B Screen +section instead of here in the +.B Device +section. +.TP 7 +.BI "BusID \*q" bus\-id \*q +This specifies the bus location of the graphics card. +For PCI/AGP cards, +the +.I bus\-id +string has the form +.BI PCI: bus : device : function +(e.g., \(lqPCI:1:0:0\(rq might be appropriate for an AGP card). +This field is usually optional in single-head configurations when using +the primary graphics card. +In multi-head configurations, or when using a secondary graphics card in a +single-head configuration, this entry is mandatory. +Its main purpose is to make an unambiguous connection between the device +section and the hardware it is representing. +This information can usually be found by running the pciaccess tool +scanpci. +.TP 7 +.BI "Screen " number +This option is mandatory for cards where a single PCI entity can drive more +than one display (i.e., multiple CRTCs sharing a single graphics accelerator +and video memory). +One +.B Device +section is required for each head, and this +parameter determines which head each of the +.B Device +sections applies to. +The legal values of +.I number +range from 0 to one less than the total number of heads per entity. +Most drivers require that the primary screen (0) be present. +.TP 7 +.BI "Chipset \*q" chipset \*q +This usually optional entry specifies the chipset used on the graphics +board. +In most cases this entry is not required because the drivers will probe the +hardware to determine the chipset type. +Don't specify it unless the driver-specific documentation recommends that you +do. +.TP 7 +.BI "Ramdac \*q" ramdac\-type \*q +This optional entry specifies the type of RAMDAC used on the graphics +board. +This is only used by a few of the drivers, and in most cases it is not +required because the drivers will probe the hardware to determine the +RAMDAC type where possible. +Don't specify it unless the driver-specific documentation recommends that you +do. +.TP 7 +.BI "DacSpeed " speed +.TP 7 +.BI "DacSpeed " "speed\-8 speed\-16 speed\-24 speed\-32" +This optional entry specifies the RAMDAC speed rating (which is usually +printed on the RAMDAC chip). +The speed is in MHz. +When one value is given, it applies to all framebuffer pixel sizes. +When multiple values are given, they apply to the framebuffer pixel sizes +8, 16, 24 and 32 respectively. +This is not used by many drivers, and only needs to be specified when the +speed rating of the RAMDAC is different from the defaults built in to +driver, or when the driver can't auto-detect the correct defaults. +Don't specify it unless the driver-specific documentation recommends that you +do. +.TP 7 +.BI "Clocks " "clock ..." +specifies the pixel that are on your graphics board. +The clocks are in MHz, and may be specified as a floating point number. +The value is stored internally to the nearest kHz. +The ordering of the clocks is important. +It must match the order in which they are selected on the graphics board. +Multiple +.B Clocks +lines may be specified, and each is concatenated to form the list. +Most drivers do not use this entry, and it is only required for some older +boards with non-programmable clocks. +Don't specify this entry unless the driver-specific documentation explicitly +recommends that you do. +.TP +.BI "ClockChip \*q" clockchip\-type \*q +This optional entry is used to specify the clock chip type on graphics +boards which have a programmable clock generator. +Only a few __xservername__ drivers support programmable clock chips. +For details, see the appropriate driver manual page. +.TP 7 +.BI "VideoRam " "mem" +This optional entry specifies the amount of video ram that is installed +on the graphics board. +This is measured in kBytes. +In most cases this is not required because the __xservername__ server probes +the graphics board to determine this quantity. +The driver-specific documentation should indicate when it might be needed. +.TP 7 +.BI "BiosBase " "baseaddress" +This optional entry specifies the base address of the video BIOS for +the VGA board. +This address is normally auto-detected, and should only be specified if the +driver-specific documentation recommends it. +.TP 7 +.BI "MemBase " "baseaddress" +This optional entry specifies the memory base address of a graphics +board's linear frame buffer. +This entry is not used by many drivers, and it should only be specified if +the driver-specific documentation recommends it. +.TP 7 +.BI "IOBase " "baseaddress" +This optional entry specifies the IO base address. +This entry is not used by many drivers, and it should only be specified if +the driver-specific documentation recommends it. +.TP 7 +.BI "ChipID " "id" +This optional entry specifies a numerical ID representing the chip type. +For PCI cards, it is usually the device ID. +This can be used to override the auto-detection, but that should only be done +when the driver-specific documentation recommends it. +.TP 7 +.BI "ChipRev " "rev" +This optional entry specifies the chip revision number. +This can be used to override the auto-detection, but that should only be done +when the driver-specific documentation recommends it. +.TP 7 +.BI "TextClockFreq " "freq" +This optional entry specifies the pixel clock frequency that is used +for the regular text mode. +The frequency is specified in MHz. +This is rarely used. +.TP 7 +.BI "Option \*qModeDebug\*q \*q" boolean \*q +Enable printing of additional debugging information about modesetting to +the server log. +.ig +.TP 7 +This optional entry allows an IRQ number to be specified. +.. +.TP 7 +.B Options +Option flags may be specified in the +.B Device +sections. +These include driver\-specific options and driver\-independent options. +The former are described in the driver\-specific documentation. +Some of the latter are described below in the section about the +.B Screen +section, and they may also be included here. + +.SH "VIDEOADAPTOR SECTION" +Nobody wants to say how this works. +Maybe nobody knows ... + +.SH "MONITOR SECTION" +The config file may have multiple +.B Monitor +sections. +There should normally be at least one, for the monitor being used, +but a default configuration will be created when one isn't specified. +.PP +.B Monitor +sections have the following format: +.PP +.RS 4 +.nf +.B "Section \*qMonitor\*q" +.BI " Identifier \*q" name \*q +.I " entries" +.I " ..." +.B "EndSection" +.fi +.RE +.PP +The only mandatory entry in a +.B Monitor +section is the +.B Identifier +entry. +.PP +The +.B Identifier +entry specifies the unique name for this monitor. +The +.B Monitor +section may be used to provide information about the specifications of the +monitor, monitor-specific +.BR Options , +and information about the video modes to use with the monitor. +.PP +With RandR 1.2-enabled drivers, monitor sections may be tied to specific +outputs of the video card. Using the name of the output defined by the video +driver plus the identifier of a monitor section, one associates a monitor +section with an output by adding an option to the Device section in the +following format: + +.B Option \*qMonitor-outputname\*q \*qmonitorsection\*q + +(for example, +.B Option \*qMonitor-VGA\*q \*qVGA monitor\*q +for a VGA output) +.PP +In the absence of specific association of monitor sections to outputs, if a +monitor section is present the server will associate it with an output to +preserve compatibility for previous single-head configurations. +.PP +Specifying video modes is optional because the server will use the DDC or other +information provided by the monitor to automatically configure the list of +modes available. +When modes are specified explicitly in the +.B Monitor +section (with the +.BR Modes , +.BR ModeLine , +or +.B UseModes +keywords), built-in modes with the same names are not included. +Built-in modes with different names are, however, still implicitly included, +when they meet the requirements of the monitor. +.PP +The entries that may be used in +.B Monitor +sections are described below. +.TP 7 +.BI "VendorName \*q" vendor \*q +This optional entry specifies the monitor's manufacturer. +.TP 7 +.BI "ModelName \*q" model \*q +This optional entry specifies the monitor's model. +.TP 7 +.BI "HorizSync " "horizsync\-range" +gives the range(s) of horizontal sync frequencies supported by the +monitor. +.I horizsync\-range +may be a comma separated list of either discrete values or ranges of +values. +A range of values is two values separated by a dash. +By default the values are in units of kHz. +They may be specified in MHz or Hz +if +.B MHz +or +.B Hz +is added to the end of the line. +The data given here is used by the __xservername__ server to determine if video +modes are within the specifications of the monitor. +This information should be available in the monitor's handbook. +If this entry is omitted, a default range of 28\-33kHz is used. +.TP 7 +.BI "VertRefresh " "vertrefresh\-range" +gives the range(s) of vertical refresh frequencies supported by the +monitor. +.I vertrefresh\-range +may be a comma separated list of either discrete values or ranges of +values. +A range of values is two values separated by a dash. +By default the values are in units of Hz. +They may be specified in MHz or kHz +if +.B MHz +or +.B kHz +is added to the end of the line. +The data given here is used by the __xservername__ server to determine if video +modes are within the specifications of the monitor. +This information should be available in the monitor's handbook. +If this entry is omitted, a default range of 43\-72Hz is used. +.TP 7 +.BI "DisplaySize " "width height" +This optional entry gives the width and height, in millimetres, of the +picture area of the monitor. +If given this is used to calculate the horizontal and vertical pitch (DPI) of +the screen. +.TP 7 +.BI "Gamma " "gamma\-value" +.TP 7 +.BI "Gamma " "red\-gamma green\-gamma blue\-gamma" +This is an optional entry that can be used to specify the gamma correction +for the monitor. +It may be specified as either a single value or as three separate RGB values. +The values should be in the range 0.1 to 10.0, and the default is 1.0. +Not all drivers are capable of using this information. +.TP 7 +.BI "UseModes \*q" modesection\-id \*q +Include the set of modes listed in the +.B Modes +section called +.IR modesection\-id. +This makes all of the modes defined in that section available for use by +this monitor. +.TP 7 +.BI "Mode \*q" name \*q +This is an optional multi-line entry that can be used to provide +definitions for video modes for the monitor. +In most cases this isn't necessary because the built-in set of VESA standard +modes will be sufficient. +The +.B Mode +keyword indicates the start of a multi-line video mode description. +The mode description is terminated with the +.B EndMode +keyword. +The mode description consists of the following entries: +.RS 7 +.TP 4 +.BI "DotClock " clock +is the dot (pixel) clock rate to be used for the mode. +.TP 4 +.BI "HTimings " "hdisp hsyncstart hsyncend htotal" +specifies the horizontal timings for the mode. +.TP 4 +.BI "VTimings " "vdisp vsyncstart vsyncend vtotal" +specifies the vertical timings for the mode. +.TP 4 +.BI "Flags \*q" flag \*q " ..." +specifies an optional set of mode flags, each of which is a separate +string in double quotes. +.B \*qInterlace\*q +indicates that the mode is interlaced. +.B \*qDoubleScan\*q +indicates a mode where each scanline is doubled. +.B \*q+HSync\*q +and +.B \*q\-HSync\*q +can be used to select the polarity of the HSync signal. +.B \*q+VSync\*q +and +.B \*q\-VSync\*q +can be used to select the polarity of the VSync signal. +.B \*qComposite\*q +can be used to specify composite sync on hardware where this is supported. +Additionally, on some hardware, +.B \*q+CSync\*q +and +.B \*q\-CSync\*q +may be used to select the composite sync polarity. +.TP 4 +.BI "HSkew " hskew +specifies the number of pixels (towards the right edge of the screen) by +which the display enable signal is to be skewed. +Not all drivers use this information. +This option might become necessary to override the default value supplied +by the server (if any). +\(lqRoving\(rq horizontal lines indicate this value needs to be increased. +If the last few pixels on a scan line appear on the left of the screen, +this value should be decreased. +.TP 4 +.BI "VScan " vscan +specifies the number of times each scanline is painted on the screen. +Not all drivers use this information. +Values less than 1 are treated as 1, which is the default. +Generally, the +.B \*qDoubleScan\*q +.B Flag +mentioned above doubles this value. +.RE +.TP 7 +.BI "ModeLine \*q" name \*q " mode\-description" +This entry is a more compact version of the +.B Mode +entry, and it also can be used to specify video modes for the monitor. +is a single line format for specifying video modes. +In most cases this isn't necessary because the built\-in set of VESA +standard modes will be sufficient. +.PP +.RS 7 +The +.I mode\-description +is in four sections, the first three of which are mandatory. +The first is the dot (pixel) clock. +This is a single number specifying the pixel clock rate for the mode in +MHz. +The second section is a list of four numbers specifying the horizontal +timings. +These numbers are the +.IR hdisp , +.IR hsyncstart , +.IR hsyncend , +and +.I htotal +values. +The third section is a list of four numbers specifying the vertical +timings. +These numbers are the +.IR vdisp , +.IR vsyncstart , +.IR vsyncend , +and +.I vtotal +values. +The final section is a list of flags specifying other characteristics of +the mode. +.B Interlace +indicates that the mode is interlaced. +.B DoubleScan +indicates a mode where each scanline is doubled. +.B +HSync +and +.B \-HSync +can be used to select the polarity of the HSync signal. +.B +VSync +and +.B \-VSync +can be used to select the polarity of the VSync signal. +.B Composite +can be used to specify composite sync on hardware where this is supported. +Additionally, on some hardware, +.B +CSync +and +.B \-CSync +may be used to select the composite sync polarity. +The +.B HSkew +and +.B VScan +options mentioned above in the +.B Modes +entry description can also be used here. +.RE +.TP 7 +.BI "Option " "\*qDPMS\*q " \*qbool\*q +This option controls whether the server should enable the DPMS extension +for power management for this screen. The default is to enable the +extension. +.TP 7 +.BI "Option " "\*qSyncOnGreen\*q " \*qbool\*q +This option controls whether the video card should drive the sync signal +on the green color pin. Not all cards support this option, and most +monitors do not require it. The default is off. +.TP 7 +.BI "Option " "\*qPrimary\*q " \*qbool\*q +This optional entry specifies that the monitor should be treated as the primary +monitor. (RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qPreferredMode\*q " \*qstring\*q +This optional entry specifies a mode to be marked as the preferred initial mode +of the monitor. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qPosition\*q " "\*qx y\*q" +This optional entry specifies the position of the monitor within the X +screen. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qLeftOf\*q " \*qoutput\*q +This optional entry specifies that the monitor should be positioned to the +left of the output (not monitor) of the given name. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qRightOf\*q " \*qoutput\*q +This optional entry specifies that the monitor should be positioned to the +right of the output (not monitor) of the given name. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qAbove\*q " \*qoutput\*q +This optional entry specifies that the monitor should be positioned above the +output (not monitor) of the given name. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qBelow\*q " \*qoutput\*q +This optional entry specifies that the monitor should be positioned below the +output (not monitor) of the given name. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qEnable\*q " \*qbool\*q +This optional entry specifies whether the monitor should be turned on +at startup. By default, the server will attempt to enable all connected +monitors. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qDefaultModes\*q " \*qbool\*q +This optional entry specifies whether the server should add supported default +modes to the list of modes offered on this monitor. By default, the server +will add default modes; you should only disable this if you can guarantee +that EDID will be available at all times, or if you have added custom modelines +which the server can use. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qMinClock\*q " \*qfrequency\*q +This optional entry specifies the minimum dot clock, in kHz, that is supported +by the monitor. +.TP 7 +.BI "Option " "\*qMaxClock\*q " \*qfrequency\*q +This optional entry specifies the maximum dot clock, in kHz, that is supported +by the monitor. +.TP 7 +.BI "Option " "\*qIgnore\*q " \*qbool\*q +This optional entry specifies that the monitor should be ignored entirely, +and not reported through RandR. This is useful if the hardware reports the +presence of outputs that don't exist. +(RandR 1.2-supporting drivers only) +.TP 7 +.BI "Option " "\*qRotate\*q " \*qrotation\*q +This optional entry specifies the initial rotation of the given monitor. +Valid values for rotation are \*qnormal\*q, \*qleft\*q, \*qright\*q, and +\*qinverted\*q. +(RandR 1.2-supporting drivers only) + +.SH "MODES SECTION" +The config file may have multiple +.B Modes +sections, or none. +These sections provide a way of defining sets of video modes independently +of the +.B Monitor +sections. +.B Monitor +sections may include the definitions provided in these sections by +using the +.B UseModes +keyword. +In most cases the +.B Modes +sections are not necessary because the built\-in set of VESA standard modes +will be sufficient. +.PP +.B Modes +sections have the following format: +.PP +.RS 4 +.nf +.B "Section \*qModes\*q" +.BI " Identifier \*q" name \*q +.I " entries" +.I " ..." +.B "EndSection" +.fi +.RE +.PP +The +.B Identifier +entry specifies the unique name for this set of mode descriptions. +The other entries permitted in +.B Modes +sections are the +.B Mode +and +.B ModeLine +entries that are described above in the +.B Monitor +section. +.SH "SCREEN SECTION" +The config file may have multiple +.B Screen +sections. +There must be at least one, for the \(lqscreen\(rq being used. +A \(lqscreen\(rq represents the binding of a graphics device +.RB ( Device +section) and a monitor +.RB ( Monitor +section). +A +.B Screen +section is considered \(lqactive\(rq if it is referenced by an active +.B ServerLayout +section or by the +.B \-screen +command line option. +If neither of those is present, the first +.B Screen +section found in the config file is considered the active one. +.PP +.B Screen +sections have the following format: +.PP +.RS 4 +.nf +.B "Section \*qScreen\*q" +.BI " Identifier \*q" name \*q +.BI " Device \*q" devid \*q +.BI " Monitor \*q" monid \*q +.I " entries" +.I " ..." +.BI " SubSection \*qDisplay\*q" +.I " entries" +.I " ... +.B " EndSubSection" +.I " ..." +.B "EndSection" +.fi +.RE +.PP +The +.B Identifier +and +.B Device +entries are mandatory. +All others are optional. +.PP +The +.B Identifier +entry specifies the unique name for this screen. +The +.B Screen +section provides information specific to the whole screen, including +screen\-specific +.BR Options . +In multi\-head configurations, there will be multiple active +.B Screen +sections, one for each head. +The entries available +for this section are: +.TP 7 +.BI "Device \*q" device\-id \*q +This mandatory entry specifies the +.B Device +section to be used for this screen. +This is what ties a specific graphics card to a screen. +The +.I device\-id +must match the +.B Identifier +of a +.B Device +section in the config file. +.TP 7 +.BI "Monitor \*q" monitor\-id \*q +specifies which monitor description is to be used for this screen. +If a +.B Monitor +name is not specified, a default configuration is used. +Currently the default configuration may not function as expected on all +platforms. +.TP 7 +.BI "VideoAdaptor \*q" xv\-id \*q +specifies an optional Xv video adaptor description to be used with this +screen. +.TP 7 +.BI "DefaultDepth " depth +specifies which color depth the server should use by default. +The +.B \-depth +command line option can be used to override this. +If neither is specified, the default depth is driver\-specific, but in most +cases is 8. +.TP 7 +.BI "DefaultFbBpp " bpp +specifies which framebuffer layout to use by default. +The +.B \-fbbpp +command line option can be used to override this. +In most cases the driver will chose the best default value for this. +The only case where there is even a choice in this value is for depth 24, +where some hardware supports both a packed 24 bit framebuffer layout and a +sparse 32 bit framebuffer layout. +.TP 7 +.B Options +Various +.B Option +flags may be specified in the +.B Screen +section. +Some are driver\-specific and are described in the driver documentation. +Others are driver\-independent, and will eventually be described here. +.\" XXX These should really be in an xaa man page. +.TP 7 +.BI "Option \*qAccel\*q" +Enables XAA (X Acceleration Architecture), a mechanism that makes video cards' +2D hardware acceleration available to the __xservername__ server. +This option is on by default, but it may be necessary to turn it off if +there are bugs in the driver. +There are many options to disable specific accelerated operations, listed +below. +Note that disabling an operation will have no effect if the operation is +not accelerated (whether due to lack of support in the hardware or in the +driver). +.TP 7 +.BI "Option \*qInitPrimary\*q \*q" boolean \*q +Use the Int10 module to initialize the primary graphics card. +Normally, only secondary cards are soft-booted using the Int10 module, as the +primary card has already been initialized by the BIOS at boot time. +Default: false. +.TP 7 +.BI "Option \*qNoInt10\*q \*q" boolean \*q +Disables the Int10 module, a module that uses the int10 call to the BIOS +of the graphics card to initialize it. +Default: false. +.TP 7 +.BI "Option \*qNoMTRR\*q" +Disables MTRR (Memory Type Range Register) support, a feature of modern +processors which can improve video performance by a factor of up to 2.5. +Some hardware has buggy MTRR support, and some video drivers have been +known to exhibit problems when MTRR's are used. +.TP 7 +.BI "Option \*qXaaNoCPUToScreenColorExpandFill\*q" +Disables accelerated rectangular expansion blits from source patterns +stored in system memory (using a memory\-mapped aperture). +.TP 7 +.BI "Option \*qXaaNoColor8x8PatternFillRect\*q" +Disables accelerated fills of a rectangular region with a full\-color +pattern. +.TP 7 +.BI "Option \*qXaaNoColor8x8PatternFillTrap\*q" +Disables accelerated fills of a trapezoidal region with a full\-color +pattern. +.TP 7 +.BI "Option \*qXaaNoDashedBresenhamLine\*q" +Disables accelerated dashed Bresenham line draws. +.TP 7 +.BI "Option \*qXaaNoDashedTwoPointLine\*q" +Disables accelerated dashed line draws between two arbitrary points. +.TP 7 +.BI "Option \*qXaaNoImageWriteRect\*q" +Disables accelerated transfers of full\-color rectangular patterns from +system memory to video memory (using a memory\-mapped aperture). +.TP 7 +.BI "Option \*qXaaNoMono8x8PatternFillRect\*q" +Disables accelerated fills of a rectangular region with a monochrome +pattern. +.TP 7 +.BI "Option \*qXaaNoMono8x8PatternFillTrap\*q" +Disables accelerated fills of a trapezoidal region with a monochrome +pattern. +.TP 7 +.BI "Option \*qXaaNoOffscreenPixmaps\*q" +Disables accelerated draws into pixmaps stored in offscreen video memory. +.TP 7 +.BI "Option \*qXaaNoPixmapCache\*q" +Disables caching of patterns in offscreen video memory. +.TP 7 +.BI "Option \*qXaaNoScanlineCPUToScreenColorExpandFill\*q" +Disables accelerated rectangular expansion blits from source patterns +stored in system memory (one scan line at a time). +.TP 7 +.BI "Option \*qXaaNoScanlineImageWriteRect\*q" +Disables accelerated transfers of full\-color rectangular patterns from +system memory to video memory (one scan line at a time). +.TP 7 +.BI "Option \*qXaaNoScreenToScreenColorExpandFill\*q" +Disables accelerated rectangular expansion blits from source patterns +stored in offscreen video memory. +.TP 7 +.BI "Option \*qXaaNoScreenToScreenCopy\*q" +Disables accelerated copies of rectangular regions from one part of +video memory to another part of video memory. +.TP 7 +.BI "Option \*qXaaNoSolidBresenhamLine\*q" +Disables accelerated solid Bresenham line draws. +.TP 7 +.BI "Option \*qXaaNoSolidFillRect\*q" +Disables accelerated solid\-color fills of rectangles. +.TP 7 +.BI "Option \*qXaaNoSolidFillTrap\*q" +Disables accelerated solid\-color fills of Bresenham trapezoids. +.TP 7 +.BI "Option \*qXaaNoSolidHorVertLine\*q" +Disables accelerated solid horizontal and vertical line draws. +.TP 7 +.BI "Option \*qXaaNoSolidTwoPointLine\*q" +Disables accelerated solid line draws between two arbitrary points. +.PP +Each +.B Screen +section may optionally contain one or more +.B Display +subsections. +Those subsections provide depth/fbbpp specific configuration information, +and the one chosen depends on the depth and/or fbbpp that is being used for +the screen. +The +.B Display +subsection format is described in the section below. + +.SH "DISPLAY SUBSECTION" +Each +.B Screen +section may have multiple +.B Display +subsections. +The \(lqactive\(rq +.B Display +subsection is the first that matches the depth and/or fbbpp values being +used, or failing that, the first that has neither a depth or fbbpp value +specified. +The +.B Display +subsections are optional. +When there isn't one that matches the depth and/or fbbpp values being used, +all the parameters that can be specified here fall back to their defaults. +.PP +.B Display +subsections have the following format: +.PP +.RS 4 +.nf +.B " SubSection \*qDisplay\*q" +.BI " Depth " depth +.I " entries" +.I " ..." +.B " EndSubSection" +.fi +.RE +.TP 7 +.BI "Depth " depth +This entry specifies what colour depth the +.B Display +subsection is to be used for. +This entry is usually specified, but it may be omitted to create a match\-all +.B Display +subsection or when wishing to match only against the +.B FbBpp +parameter. +The range of +.I depth +values that are allowed depends on the driver. +Most drivers support 8, 15, 16 and 24. +Some also support 1 and/or 4, and some may support other values (like 30). +Note: +.I depth +means the number of bits in a pixel that are actually used to determine +the pixel colour. +32 is not a valid +.I depth +value. +Most hardware that uses 32 bits per pixel only uses 24 of them to hold the +colour information, which means that the colour depth is 24, not 32. +.TP 7 +.BI "FbBpp " bpp +This entry specifies the framebuffer format this +.B Display +subsection is to be used for. +This entry is only needed when providing depth 24 configurations that allow +a choice between a 24 bpp packed framebuffer format and a 32bpp sparse +framebuffer format. +In most cases this entry should not be used. +.TP 7 +.BI "Weight " "red\-weight green\-weight blue\-weight" +This optional entry specifies the relative RGB weighting to be used +for a screen is being used at depth 16 for drivers that allow multiple +formats. +This may also be specified from the command line with the +.B \-weight +option (see +.BR __xservername__(__appmansuffix__)). +.TP 7 +.BI "Virtual " "xdim ydim" +This optional entry specifies the virtual screen resolution to be used. +.I xdim +must be a multiple of either 8 or 16 for most drivers, and a multiple +of 32 when running in monochrome mode. +The given value will be rounded down if this is not the case. +Video modes which are too large for the specified virtual size will be +rejected. +If this entry is not present, the virtual screen resolution will be set to +accommodate all the valid video modes given in the +.B Modes +entry. +Some drivers/hardware combinations do not support virtual screens. +Refer to the appropriate driver\-specific documentation for details. +.TP 7 +.BI "ViewPort " "x0 y0" +This optional entry sets the upper left corner of the initial display. +This is only relevant when the virtual screen resolution is different +from the resolution of the initial video mode. +If this entry is not given, then the initial display will be centered in +the virtual display area. +.TP 7 +.BI "Modes \*q" mode\-name \*q " ..." +This optional entry specifies the list of video modes to use. +Each +.I mode\-name +specified must be in double quotes. +They must correspond to those specified or referenced in the appropriate +.B Monitor +section (including implicitly referenced built\-in VESA standard modes). +The server will delete modes from this list which don't satisfy various +requirements. +The first valid mode in this list will be the default display mode for +startup. +The list of valid modes is converted internally into a circular list. +It is possible to switch to the next mode with +.B Ctrl+Alt+Keypad\-Plus +and to the previous mode with +.BR Ctrl+Alt+Keypad\-Minus . +When this entry is omitted, the valid modes referenced by the appropriate +.B Monitor +section will be used. If the +.B Monitor +section contains no modes, then the selection will be taken from the +built-in VESA standard modes. +.TP 7 +.BI "Visual \*q" visual\-name \*q +This optional entry sets the default root visual type. +This may also be specified from the command line (see the +.BR Xserver(__appmansuffix__) +man page). +The visual types available for depth 8 are (default is +.BR PseudoColor ): +.PP +.RS 11 +.nf +.B StaticGray +.B GrayScale +.B StaticColor +.B PseudoColor +.B TrueColor +.B DirectColor +.fi +.RE +.PP +.RS 7 +The visual type available for the depths 15, 16 and 24 are (default is +.BR TrueColor ): +.PP +.RS 4 +.nf +.B TrueColor +.B DirectColor +.fi +.RE +.PP +Not all drivers support +.B DirectColor +at these depths. +.PP +The visual types available for the depth 4 are (default is +.BR StaticColor ): +.PP +.RS 4 +.nf +.B StaticGray +.B GrayScale +.B StaticColor +.B PseudoColor +.fi +.RE +.PP +The visual type available for the depth 1 (monochrome) is +.BR StaticGray . +.RE +.TP 7 +.BI "Black " "red green blue" +This optional entry allows the \(lqblack\(rq colour to be specified. +This is only supported at depth 1. +The default is black. +.TP 7 +.BI "White " "red green blue" +This optional entry allows the \(lqwhite\(rq colour to be specified. +This is only supported at depth 1. +The default is white. +.TP 7 +.B Options +Option flags may be specified in the +.B Display +subsections. +These may include driver\-specific options and driver\-independent options. +The former are described in the driver\-specific documentation. +Some of the latter are described above in the section about the +.B Screen +section, and they may also be included here. +.SH "SERVERLAYOUT SECTION" +The config file may have multiple +.B ServerLayout +sections. +A \(lqserver layout\(rq represents the binding of one or more screens +.RB ( Screen +sections) and one or more input devices +.RB ( InputDevice +sections) to form a complete configuration. +In multi\-head configurations, it also specifies the relative layout of the +heads. +A +.B ServerLayout +section is considered \(lqactive\(rq if it is referenced by the +.B \-layout +command line option or by an +.B "Option \*qDefaultServerLayout\*q" +entry in the +.B ServerFlags +section (the former takes precedence over the latter). +If those options are not used, the first +.B ServerLayout +section found in the config file is considered the active one. +If no +.B ServerLayout +sections are present, the single active screen and two active (core) +input devices are selected as described in the relevant sections above. +.PP +.B ServerLayout +sections have the following format: +.PP +.RS 4 +.nf +.B "Section \*qServerLayout\*q" +.BI " Identifier \*q" name \*q +.BI " Screen \*q" screen\-id \*q +.I " ..." +.BI " InputDevice \*q" idev\-id \*q +.I " ..." +.I " options" +.I " ..." +.B "EndSection" +.fi +.RE +.PP +Each +.B ServerLayout +section must have an +.B Identifier +entry and at least one +.B Screen +entry. +.PP +The +.B Identifier +entry specifies the unique name for this server layout. +The +.B ServerLayout +section provides information specific to the whole session, including +session\-specific +.BR Options . +The +.B ServerFlags +options (described above) may be specified here, and ones given here +override those given in the +.B ServerFlags +section. +.PP +The entries that may be used in this section are described here. +.TP 7 +.BI "Screen " "screen\-num" " \*qscreen\-id\*q " "position\-information" +One of these entries must be given for each screen being used in +a session. +The +.I screen\-id +field is mandatory, and specifies the +.B Screen +section being referenced. +The +.I screen\-num +field is optional, and may be used to specify the screen number +in multi\-head configurations. +When this field is omitted, the screens will be numbered in the order that +they are listed in. +The numbering starts from 0, and must be consecutive. +The +.I position\-information +field describes the way multiple screens are positioned. +There are a number of different ways that this information can be provided: +.RS 7 +.TP 4 +.I "x y" +.TP 4 +.BI "Absolute " "x y" +These both specify that the upper left corner's coordinates are +.RI ( x , y ). +The +.B Absolute +keyword is optional. +Some older versions of XFree86 (4.2 and earlier) don't recognise the +.B Absolute +keyword, so it's safest to just specify the coordinates without it. +.TP 4 +.BI "RightOf \*q" screen\-id \*q +.TP 4 +.BI "LeftOf \*q" screen\-id \*q +.TP 4 +.BI "Above \*q" screen\-id \*q +.TP 4 +.BI "Below \*q" screen\-id \*q +.TP 4 +.BI "Relative \*q" screen\-id \*q " x y" +These give the screen's location relative to another screen. +The first four position the screen immediately to the right, left, above or +below the other screen. +When positioning to the right or left, the top edges are aligned. +When positioning above or below, the left edges are aligned. +The +.B Relative +form specifies the offset of the screen's origin (upper left corner) +relative to the origin of another screen. +.RE +.TP 7 +.BI "InputDevice \*q" idev\-id "\*q \*q" option \*q " ..." +One of these entries should be given for each input device being used in +a session. +Normally at least two are required, one each for the core pointer and +keyboard devices. +If either of those is missing, suitable +.B InputDevice +entries are searched for using the method described above in the +.B INPUTDEVICE +section. The +.I idev\-id +field is mandatory, and specifies the name of the +.B InputDevice +section being referenced. +Multiple +.I option +fields may be specified, each in double quotes. +The options permitted here are any that may also be given in the +.B InputDevice +sections. +Normally only session\-specific input device options would be used here. +The most commonly used options are: +.PP +.RS 11 +.nf +.B \*qCorePointer\*q +.B \*qCoreKeyboard\*q +.B \*qSendCoreEvents\*q +.fi +.RE +.PP +.RS 7 +and the first two should normally be used to indicate the core pointer +and core keyboard devices respectively. +.RE +.TP 7 +.B Options +In addition to the following, any option permitted in the +.B ServerFlags +section may also be specified here. +When the same option appears in both places, the value given here overrides +the one given in the +.B ServerFlags +section. +.TP 7 +.BI "Option \*qIsolateDevice\*q \*q" bus\-id \*q +Restrict device resets to the specified +.IR bus\-id . +See the +.B BusID +option (described in +.BR "DEVICE SECTION" , +above) for the format of the +.I bus\-id +parameter. +This option overrides +.BR SingleCard , +if specified. +At present, only PCI devices can be isolated in this manner. +.TP 7 +.BI "Option \*qSingleCard\*q \*q" boolean \*q +As +.BR IsolateDevice , +except that the bus ID of the first device in the layout is used. +.PP +Here is an example of a +.B ServerLayout +section for a dual headed configuration with two mice: +.PP +.RS 4 +.nf +.B "Section \*qServerLayout\*q" +.B " Identifier \*qLayout 1\*q" +.B " Screen \*qMGA 1\*q" +.B " Screen \*qMGA 2\*q RightOf \*qMGA 1\*q" +.B " InputDevice \*qKeyboard 1\*q \*qCoreKeyboard\*q" +.B " InputDevice \*qMouse 1\*q \*qCorePointer\*q" +.B " InputDevice \*qMouse 2\*q \*qSendCoreEvents\*q" +.B " Option \*qBlankTime\*q \*q5\*q" +.B "EndSection" +.fi +.RE +.SH "DRI SECTION" +This optional section is used to provide some information for the +Direct Rendering Infrastructure. +Details about the format of this section can be found on-line at +.IR . +.SH "VENDOR SECTION" +The optional +.B Vendor +section may be used to provide vendor\-specific configuration information. +Multiple +.B Vendor +sections may be present, and they may contain an +.B Identifier +entry and multiple +.B Option +flags. +The data therein is not used in this release. +.PP +.SH "SEE ALSO" +General: +.BR X (__miscmansuffix__), +.BR Xserver (__appmansuffix__), +.BR __xservername__ (__appmansuffix__), +.BR cvt (__appmansuffix__), +.BR gtf (__appmansuffix__). +.PP +.B "Not all modules or interfaces are available on all platforms." +.PP +Display drivers: +.BR apm (__drivermansuffix__), +.BR ati (__drivermansuffix__), +.BR chips (__drivermansuffix__), +.BR cirrus (__drivermansuffix__), +.BR cyrix (__drivermansuffix__), +.BR fbdev (__drivermansuffix__), +.BR glide (__drivermansuffix__), +.BR glint (__drivermansuffix__), +.BR i128 (__drivermansuffix__), +.BR i740 (__drivermansuffix__), +.BR imstt (__drivermansuffix__), +.BR intel (__drivermansuffix__), +.BR mga (__drivermansuffix__), +.BR neomagic (__drivermansuffix__), +.BR nv (__drivermansuffix__), +.BR openchrome (__drivermansuffix__), +.BR r128 (__drivermansuffix__), +.BR radeon (__drivermansuffix__), +.BR rendition (__drivermansuffix__), +.BR savage (__drivermansuffix__), +.BR s3virge (__drivermansuffix__), +.BR siliconmotion (__drivermansuffix__), +.BR sis (__drivermansuffix__), +.BR sisusb (__drivermansuffix__), +.BR sunbw2 (__drivermansuffix__), +.BR suncg14 (__drivermansuffix__), +.BR suncg3 (__drivermansuffix__), +.BR suncg6 (__drivermansuffix__), +.BR sunffb (__drivermansuffix__), +.BR sunleo (__drivermansuffix__), +.BR suntcx (__drivermansuffix__), +.BR tdfx (__drivermansuffix__), +.\" .BR tga (__drivermansuffix__), +.BR trident (__drivermansuffix__), +.BR tseng (__drivermansuffix__), +.BR vesa (__drivermansuffix__), +.BR vmware (__drivermansuffix__), +.BR voodoo (__drivermansuffix__), +.BR wsfb (__drivermansuffix__), +.BR xgi (__drivermansuffix__), +.BR xgixp (__drivermansuffix__). +.PP +Input drivers: +.BR acecad (__drivermansuffix__), +.BR citron (__drivermansuffix__), +.BR elographics (__drivermansuffix__), +.BR evdev (__drivermansuffix__), +.BR fpit (__drivermansuffix__), +.BR joystick (__drivermansuffix__), +.BR kbd (__drivermansuffix__), +.BR mousedrv (__drivermansuffix__), +.BR mutouch (__drivermansuffix__), +.BR penmount (__drivermansuffix__), +.BR synaptics (__drivermansuffix__), +.BR vmmouse (__drivermansuffix__), +.BR void (__drivermansuffix__), +.BR wacom (__drivermansuffix__). +.PP +Other modules and interfaces: +.BR exa (__drivermansuffix__), +.BR fbdevhw (__drivermansuffix__), +.\" .BR shadowfb (__drivermansuffix__), +.BR v4l (__drivermansuffix__). +.br +.SH AUTHORS +This manual page was largely rewritten by David Dawes +.IR . diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index 86f038aa1..1f43ab9a6 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -1,3242 +1,3237 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2008 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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 -#else -#ifdef HAVE_CONFIG_H -#include -#endif -#endif - -#include -#include -#include - -#include "xf86.h" -#include "xf86DDC.h" -#include "xf86Crtc.h" -#include "xf86Modes.h" -#include "xf86Priv.h" -#include "xf86RandR12.h" -#include "X11/extensions/render.h" -#include "X11/extensions/dpmsconst.h" -#include "X11/Xatom.h" -#include "picturestr.h" - -#include "xf86xv.h" - -#define NO_OUTPUT_DEFAULT_WIDTH 1024 -#define NO_OUTPUT_DEFAULT_HEIGHT 768 -/* - * Initialize xf86CrtcConfig structure - */ - -int xf86CrtcConfigPrivateIndex = -1; - -void -xf86CrtcConfigInit (ScrnInfoPtr scrn, - const xf86CrtcConfigFuncsRec *funcs) -{ - xf86CrtcConfigPtr config; - - if (xf86CrtcConfigPrivateIndex == -1) - xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); - - config->funcs = funcs; - - scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; -} - -void -xf86CrtcSetSizeRange (ScrnInfoPtr scrn, - int minWidth, int minHeight, - int maxWidth, int maxHeight) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->minWidth = minWidth; - config->minHeight = minHeight; - config->maxWidth = maxWidth; - config->maxHeight = maxHeight; -} - -/* - * Crtc functions - */ -xf86CrtcPtr -xf86CrtcCreate (ScrnInfoPtr scrn, - const xf86CrtcFuncsRec *funcs) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc, *crtcs; - - crtc = calloc(sizeof (xf86CrtcRec), 1); - if (!crtc) - return NULL; - crtc->version = XF86_CRTC_VERSION; - crtc->scrn = scrn; - crtc->funcs = funcs; -#ifdef RANDR_12_INTERFACE - crtc->randr_crtc = NULL; -#endif - crtc->rotation = RR_Rotate_0; - crtc->desiredRotation = RR_Rotate_0; - pixman_transform_init_identity (&crtc->crtc_to_framebuffer); - pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); - pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); - crtc->filter = NULL; - crtc->params = NULL; - crtc->nparams = 0; - crtc->filter_width = 0; - crtc->filter_height = 0; - crtc->transform_in_use = FALSE; - crtc->transformPresent = FALSE; - crtc->desiredTransformPresent = FALSE; - memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); - - /* Preallocate gamma at a sensible size. */ - crtc->gamma_size = 256; - crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16)); - if (!crtc->gamma_red) { - free(crtc); - return NULL; - } - crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; - crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; - - if (xf86_config->crtc) - crtcs = realloc(xf86_config->crtc, - (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); - else - crtcs = malloc((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); - if (!crtcs) - { - free(crtc); - return NULL; - } - xf86_config->crtc = crtcs; - xf86_config->crtc[xf86_config->num_crtc++] = crtc; - return crtc; -} - -void -xf86CrtcDestroy (xf86CrtcPtr crtc) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); - int c; - - (*crtc->funcs->destroy) (crtc); - for (c = 0; c < xf86_config->num_crtc; c++) - if (xf86_config->crtc[c] == crtc) - { - memmove (&xf86_config->crtc[c], - &xf86_config->crtc[c+1], - ((xf86_config->num_crtc - (c + 1)) * sizeof(void*))); - xf86_config->num_crtc--; - break; - } - free(crtc->params); - free(crtc->gamma_red); - free(crtc); -} - - -/** - * Return whether any outputs are connected to the specified pipe - */ - -Bool -xf86CrtcInUse (xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o; - - for (o = 0; o < xf86_config->num_output; o++) - if (xf86_config->output[o]->crtc == crtc) - return TRUE; - return FALSE; -} - -void -xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen) -{ - int subpixel_order = SubPixelUnknown; - Bool has_none = FALSE; - ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - - if (output->crtc == crtc) - { - switch (output->subpixel_order) { - case SubPixelNone: - has_none = TRUE; - break; - case SubPixelUnknown: - break; - default: - subpixel_order = output->subpixel_order; - break; - } - } - if (subpixel_order != SubPixelUnknown) - break; - } - if (subpixel_order != SubPixelUnknown) - { - static const int circle[4] = { - SubPixelHorizontalRGB, - SubPixelVerticalRGB, - SubPixelHorizontalBGR, - SubPixelVerticalBGR, - }; - int rotate; - int c; - for (rotate = 0; rotate < 4; rotate++) - if (crtc->rotation & (1 << rotate)) - break; - for (c = 0; c < 4; c++) - if (circle[c] == subpixel_order) - break; - c = (c + rotate) & 0x3; - if ((crtc->rotation & RR_Reflect_X) && !(c & 1)) - c ^= 2; - if ((crtc->rotation & RR_Reflect_Y) && (c & 1)) - c ^= 2; - subpixel_order = circle[c]; - break; - } - } - if (subpixel_order == SubPixelUnknown && has_none) - subpixel_order = SubPixelNone; - PictureSetSubpixelOrder (pScreen, subpixel_order); -} - -/** - * Sets the given video mode on the given crtc - */ -Bool -xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, - RRTransformPtr transform, int x, int y) -{ - ScrnInfoPtr scrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - Bool ret = FALSE; - Bool didLock = FALSE; - DisplayModePtr adjusted_mode; - DisplayModeRec saved_mode; - int saved_x, saved_y; - Rotation saved_rotation; - RRTransformRec saved_transform; - Bool saved_transform_present; - - crtc->enabled = xf86CrtcInUse (crtc); - - /* We only hit this if someone explicitly sends a "disabled" modeset. */ - if (!crtc->enabled) - { - /* Check everything for stuff that should be off. */ - xf86DisableUnusedFunctions(scrn); - return TRUE; - } - - adjusted_mode = xf86DuplicateMode(mode); - - - saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; - saved_rotation = crtc->rotation; - if (crtc->transformPresent) { - RRTransformInit (&saved_transform); - RRTransformCopy (&saved_transform, &crtc->transform); - } - saved_transform_present = crtc->transformPresent; - - /* Update crtc values up front so the driver can rely on them for mode - * setting. - */ - crtc->mode = *mode; - crtc->x = x; - crtc->y = y; - crtc->rotation = rotation; - if (transform) { - RRTransformCopy (&crtc->transform, transform); - crtc->transformPresent = TRUE; - } else - crtc->transformPresent = FALSE; - - if (crtc->funcs->set_mode_major) { - ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y); - goto done; - } - - didLock = crtc->funcs->lock (crtc); - /* Pass our mode to the outputs and the CRTC to give them a chance to - * adjust it according to limitations or output properties, and also - * a chance to reject the mode entirely. - */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { - goto done; - } - } - - if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { - goto done; - } - - if (!xf86CrtcRotate (crtc)) - goto done; - - /* Prepare the outputs and CRTCs before setting the mode. */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - /* Disable the output as the first thing we do. */ - output->funcs->prepare(output); - } - - crtc->funcs->prepare(crtc); - - /* Set up the DPLL and any output state that needs to adjust or depend - * on the DPLL. - */ - crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y); - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->mode_set(output, mode, adjusted_mode); - } - - /* Only upload when needed, to avoid unneeded delays. */ - if (!crtc->active && crtc->funcs->gamma_set) - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); - - /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ - crtc->funcs->commit(crtc); - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->commit(output); - } - - ret = TRUE; - -done: - if (ret) { - crtc->active = TRUE; - if (scrn->pScreen) - xf86CrtcSetScreenSubpixelOrder (scrn->pScreen); - if (scrn->ModeSet) - scrn->ModeSet(scrn); - } else { - crtc->x = saved_x; - crtc->y = saved_y; - crtc->rotation = saved_rotation; - crtc->mode = saved_mode; - if (saved_transform_present) - RRTransformCopy (&crtc->transform, &saved_transform); - crtc->transformPresent = saved_transform_present; - } - - free(adjusted_mode->name); - free(adjusted_mode); - - if (didLock) - crtc->funcs->unlock (crtc); - - return ret; -} - -/** - * Sets the given video mode on the given crtc, but without providing - * a transform - */ -Bool -xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, - int x, int y) -{ - return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y); -} - -/** - * Pans the screen, does not change the mode - */ -void -xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y) -{ - ScrnInfoPtr scrn = crtc->scrn; - - crtc->x = x; - crtc->y = y; - if (crtc->funcs->set_origin) { - if (!xf86CrtcRotate (crtc)) - return; - crtc->funcs->set_origin (crtc, x, y); - if (scrn->ModeSet) - scrn->ModeSet(scrn); - } - else - xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y); -} - -/* - * Output functions - */ - -extern XF86ConfigPtr xf86configptr; - -typedef enum { - OPTION_PREFERRED_MODE, - OPTION_POSITION, - OPTION_BELOW, - OPTION_RIGHT_OF, - OPTION_ABOVE, - OPTION_LEFT_OF, - OPTION_ENABLE, - OPTION_DISABLE, - OPTION_MIN_CLOCK, - OPTION_MAX_CLOCK, - OPTION_IGNORE, - OPTION_ROTATE, - OPTION_PANNING, - OPTION_PRIMARY, - OPTION_DEFAULT_MODES, -} OutputOpts; - -static OptionInfoRec xf86OutputOptions[] = { - {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, - {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, - {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, - {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, - {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, - {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, - {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, - {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, - {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, - {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE }, - {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_DEFAULT_MODES, "DefaultModes", OPTV_BOOLEAN, {0}, FALSE }, - {-1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -enum { - OPTION_MODEDEBUG, -}; - -static OptionInfoRec xf86DeviceOptions[] = { - {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE }, - {-1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -static void -xf86OutputSetMonitor (xf86OutputPtr output) -{ - char *option_name; - char *monitor; - - if (!output->name) - return; - - free(output->options); - - output->options = xnfalloc (sizeof (xf86OutputOptions)); - memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); - - XNFasprintf(&option_name, "monitor-%s", output->name); - monitor = xf86findOptionValue (output->scrn->options, option_name); - if (!monitor) - monitor = output->name; - else - xf86MarkOptionUsedByName (output->scrn->options, option_name); - free(option_name); - output->conf_monitor = xf86findMonitor (monitor, - xf86configptr->conf_monitor_lst); - /* - * Find the monitor section of the screen and use that - */ - if (!output->conf_monitor && output->use_screen_monitor) - output->conf_monitor = xf86findMonitor (output->scrn->monitor->id, - xf86configptr->conf_monitor_lst); - if (output->conf_monitor) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s using monitor section %s\n", - output->name, output->conf_monitor->mon_identifier); - xf86ProcessOptions (output->scrn->scrnIndex, - output->conf_monitor->mon_option_lst, - output->options); - } - else - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s has no monitor section\n", - output->name); -} - -static Bool -xf86OutputEnabled (xf86OutputPtr output, Bool strict) -{ - Bool enable, disable; - - /* check to see if this output was enabled in the config file */ - if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s enabled by config file\n", output->name); - return TRUE; - } - /* or if this output was disabled in the config file */ - if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s disabled by config file\n", output->name); - return FALSE; - } - - /* If not, try to only light up the ones we know are connected */ - if (strict) { - enable = output->status == XF86OutputStatusConnected; - } - /* But if that fails, try to light up even outputs we're unsure of */ - else { - enable = output->status != XF86OutputStatusDisconnected; - } - - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s %sconnected\n", output->name, enable ? "" : "dis"); - return enable; -} - -static Bool -xf86OutputIgnored (xf86OutputPtr output) -{ - return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE); -} - -static char *direction[4] = { - "normal", - "left", - "inverted", - "right" -}; - -static Rotation -xf86OutputInitialRotation (xf86OutputPtr output) -{ - char *rotate_name = xf86GetOptValString (output->options, - OPTION_ROTATE); - int i; - - if (!rotate_name) { - if (output->initial_rotation) - return output->initial_rotation; - return RR_Rotate_0; - } - - for (i = 0; i < 4; i++) - if (xf86nameCompare (direction[i], rotate_name) == 0) - return 1 << i; - return RR_Rotate_0; -} - -xf86OutputPtr -xf86OutputCreate (ScrnInfoPtr scrn, - const xf86OutputFuncsRec *funcs, - const char *name) -{ - xf86OutputPtr output, *outputs; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int len; - Bool primary; - - if (name) - len = strlen (name) + 1; - else - len = 0; - - output = calloc(sizeof (xf86OutputRec) + len, 1); - if (!output) - return NULL; - output->scrn = scrn; - output->funcs = funcs; - if (name) - { - output->name = (char *) (output + 1); - strcpy (output->name, name); - } - output->subpixel_order = SubPixelUnknown; - /* - * Use the old per-screen monitor section for the first output - */ - output->use_screen_monitor = (xf86_config->num_output == 0); -#ifdef RANDR_12_INTERFACE - output->randr_output = NULL; -#endif - if (name) - { - xf86OutputSetMonitor (output); - if (xf86OutputIgnored (output)) - { - free(output); - return FALSE; - } - } - - - if (xf86_config->output) - outputs = realloc(xf86_config->output, - (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); - else - outputs = malloc((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); - if (!outputs) - { - free(output); - return NULL; - } - - xf86_config->output = outputs; - - if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary) - { - memmove(xf86_config->output + 1, xf86_config->output, - xf86_config->num_output * sizeof (xf86OutputPtr)); - xf86_config->output[0] = output; - } - else - { - xf86_config->output[xf86_config->num_output] = output; - } - - xf86_config->num_output++; - - return output; -} - -Bool -xf86OutputRename (xf86OutputPtr output, const char *name) -{ - char *newname = strdup(name); - - if (!newname) - return FALSE; /* so sorry... */ - - if (output->name && output->name != (char *) (output + 1)) - free(output->name); - output->name = newname; - xf86OutputSetMonitor (output); - if (xf86OutputIgnored (output)) - return FALSE; - return TRUE; -} - -void -xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor) -{ - if (use_screen_monitor != output->use_screen_monitor) - { - output->use_screen_monitor = use_screen_monitor; - xf86OutputSetMonitor (output); - } -} - -void -xf86OutputDestroy (xf86OutputPtr output) -{ - ScrnInfoPtr scrn = output->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - (*output->funcs->destroy) (output); - while (output->probed_modes) - xf86DeleteMode (&output->probed_modes, output->probed_modes); - for (o = 0; o < xf86_config->num_output; o++) - if (xf86_config->output[o] == output) - { - memmove (&xf86_config->output[o], - &xf86_config->output[o+1], - ((xf86_config->num_output - (o + 1)) * sizeof(void*))); - xf86_config->num_output--; - break; - } - if (output->name && output->name != (char *) (output + 1)) - free(output->name); - free(output); -} - -/* - * Called during CreateScreenResources to hook up RandR - */ -static Bool -xf86CrtcCreateScreenResources (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - screen->CreateScreenResources = config->CreateScreenResources; - - if (!(*screen->CreateScreenResources)(screen)) - return FALSE; - - if (!xf86RandR12CreateScreenResources (screen)) - return FALSE; - - return TRUE; -} - -/* - * Clean up config on server reset - */ -static Bool -xf86CrtcCloseScreen (int index, ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o, c; - - screen->CloseScreen = config->CloseScreen; - - xf86RotateCloseScreen (screen); - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->randr_output = NULL; - } - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->randr_crtc = NULL; - } - xf86RandR12CloseScreen (screen); - - return screen->CloseScreen (index, screen); -} - -/* - * Called at ScreenInit time to set up - */ -#ifdef RANDR_13_INTERFACE -int -#else -Bool -#endif -xf86CrtcScreenInit (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - /* Rotation */ - xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); - xf86DisableRandR(); /* Disable old RandR extension support */ - xf86RandR12Init (screen); - - /* support all rotations if every crtc has the shadow alloc funcs */ - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) - break; - } - if (c == config->num_crtc) - { - xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | - RR_Rotate_180 | RR_Rotate_270 | - RR_Reflect_X | RR_Reflect_Y); - xf86RandR12SetTransformSupport (screen, TRUE); - } - else - { - xf86RandR12SetRotations (screen, RR_Rotate_0); - xf86RandR12SetTransformSupport (screen, FALSE); - } - - /* Wrap CreateScreenResources so we can initialize the RandR code */ - config->CreateScreenResources = screen->CreateScreenResources; - screen->CreateScreenResources = xf86CrtcCreateScreenResources; - - config->CloseScreen = screen->CloseScreen; - screen->CloseScreen = xf86CrtcCloseScreen; - -#ifdef XFreeXDGA - _xf86_di_dga_init_internal(screen); -#endif -#ifdef RANDR_13_INTERFACE - return RANDR_INTERFACE_VERSION; -#else - return TRUE; -#endif -} - -static DisplayModePtr -xf86DefaultMode (xf86OutputPtr output, int width, int height) -{ - DisplayModePtr target_mode = NULL; - DisplayModePtr mode; - int target_diff = 0; - int target_preferred = 0; - int mm_height; - - mm_height = output->mm_height; - if (!mm_height) - mm_height = (768 * 25.4) / DEFAULT_DPI; - /* - * Pick a mode closest to DEFAULT_DPI - */ - for (mode = output->probed_modes; mode; mode = mode->next) - { - int dpi; - int preferred = (((mode->type & M_T_PREFERRED) != 0) + - ((mode->type & M_T_USERPREF) != 0)); - int diff; - - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - /* yes, use VDisplay here, not xf86ModeHeight */ - dpi = (mode->VDisplay * 254) / (mm_height * 10); - diff = dpi - DEFAULT_DPI; - diff = diff < 0 ? -diff : diff; - if (target_mode == NULL || (preferred > target_preferred) || - (preferred == target_preferred && diff < target_diff)) - { - target_mode = mode; - target_diff = diff; - target_preferred = preferred; - } - } - return target_mode; -} - -static DisplayModePtr -xf86ClosestMode (xf86OutputPtr output, - DisplayModePtr match, Rotation match_rotation, - int width, int height) -{ - DisplayModePtr target_mode = NULL; - DisplayModePtr mode; - int target_diff = 0; - - /* - * Pick a mode closest to the specified mode - */ - for (mode = output->probed_modes; mode; mode = mode->next) - { - int dx, dy; - int diff; - - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - /* exact matches are preferred */ - if (output->initial_rotation == match_rotation && - xf86ModesEqual (mode, match)) - return mode; - - dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); - dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); - diff = dx * dx + dy * dy; - if (target_mode == NULL || diff < target_diff) - { - target_mode = mode; - target_diff = diff; - } - } - return target_mode; -} - -static DisplayModePtr -xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) -{ - DisplayModePtr mode; - - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - if (mode->type & M_T_PREFERRED) - return mode; - } - return NULL; -} - -static DisplayModePtr -xf86OutputHasUserPreferredMode (xf86OutputPtr output) -{ - DisplayModePtr mode, first = output->probed_modes; - - for (mode = first; mode && mode->next != first; mode = mode->next) - if (mode->type & M_T_USERPREF) - return mode; - - return NULL; -} - -static int -xf86PickCrtcs (ScrnInfoPtr scrn, - xf86CrtcPtr *best_crtcs, - DisplayModePtr *modes, - int n, - int width, - int height) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - xf86OutputPtr output; - xf86CrtcPtr crtc; - xf86CrtcPtr *crtcs; - xf86CrtcPtr best_crtc; - int best_score; - int score; - int my_score; - - if (n == config->num_output) - return 0; - output = config->output[n]; - - /* - * Compute score with this output disabled - */ - best_crtcs[n] = NULL; - best_crtc = NULL; - best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); - if (modes[n] == NULL) - return best_score; - - crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr)); - if (!crtcs) - return best_score; - - my_score = 1; - /* Score outputs that are known to be connected higher */ - if (output->status == XF86OutputStatusConnected) - my_score++; - /* Score outputs with preferred modes higher */ - if (xf86OutputHasPreferredMode (output, width, height)) - my_score++; - /* - * Select a crtc for this output and - * then attempt to configure the remaining - * outputs - */ - for (c = 0; c < config->num_crtc; c++) - { - if ((output->possible_crtcs & (1 << c)) == 0) - continue; - - crtc = config->crtc[c]; - /* - * Check to see if some other output is - * using this crtc - */ - for (o = 0; o < n; o++) - if (best_crtcs[o] == crtc) - break; - if (o < n) - { - /* - * If the two outputs desire the same mode, - * see if they can be cloned - */ - if (xf86ModesEqual (modes[o], modes[n]) && - config->output[o]->initial_rotation == config->output[n]->initial_rotation && - config->output[o]->initial_x == config->output[n]->initial_x && - config->output[o]->initial_y == config->output[n]->initial_y) - { - if ((output->possible_clones & (1 << o)) == 0) - continue; /* nope, try next CRTC */ - } - else - continue; /* different modes, can't clone */ - } - crtcs[n] = crtc; - memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); - score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); - if (score > best_score) - { - best_crtc = crtc; - best_score = score; - memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); - } - } - free(crtcs); - return best_score; -} - - -/* - * Compute the virtual size necessary to place all of the available - * crtcs in the specified configuration. - * - * canGrow indicates that the driver can make the screen larger than its initial - * configuration. If FALSE, this function will enlarge the screen to include - * the largest available mode. - */ - -static void -xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp, - Bool canGrow) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int width = 0, height = 0; - int o; - int c; - int s; - - for (c = 0; c < config->num_crtc; c++) - { - int crtc_width = 0, crtc_height = 0; - xf86CrtcPtr crtc = config->crtc[c]; - - if (crtc->enabled) - { - crtc_width = crtc->desiredX + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation); - crtc_height = crtc->desiredY + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation); - } - if (!canGrow) { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - for (s = 0; s < config->num_crtc; s++) - if (output->possible_crtcs & (1 << s)) - { - DisplayModePtr mode; - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (mode->HDisplay > crtc_width) - crtc_width = mode->HDisplay; - if (mode->VDisplay > crtc_width) - crtc_width = mode->VDisplay; - if (mode->VDisplay > crtc_height) - crtc_height = mode->VDisplay; - if (mode->HDisplay > crtc_height) - crtc_height = mode->HDisplay; - } - } - } - } - if (crtc_width > width) - width = crtc_width; - if (crtc_height > height) - height = crtc_height; - } - if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; - if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; - if (config->minWidth && width < config->minWidth) width = config->minWidth; - if (config->minHeight && height < config->minHeight) height = config->minHeight; - *widthp = width; - *heightp = height; -} - -#define POSITION_UNSET -100000 - -/* - * check if the user configured any outputs at all - * with either a position or a relative setting or a mode. - */ -static Bool -xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - Bool user_conf = FALSE; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - char *position; - char *relative_name; - OutputOpts relation; - int r; - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; - - position = xf86GetOptValString (output->options, - OPTION_POSITION); - if (position) - user_conf = TRUE; - - relation = 0; - relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) - user_conf = TRUE; - - modes[o] = xf86OutputHasUserPreferredMode(output); - if (modes[o]) - user_conf = TRUE; - } - - return user_conf; -} - -static Bool -xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - int min_x, min_y; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->initial_x = output->initial_y = POSITION_UNSET; - } - - /* - * Loop until all outputs are set - */ - for (;;) - { - Bool any_set = FALSE; - Bool keep_going = FALSE; - - for (o = 0; o < config->num_output; o++) - { - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; - xf86OutputPtr output = config->output[o]; - xf86OutputPtr relative; - char *relative_name; - char *position; - OutputOpts relation; - int r; - - if (output->initial_x != POSITION_UNSET) - continue; - position = xf86GetOptValString (output->options, - OPTION_POSITION); - /* - * Absolute position wins - */ - if (position) - { - int x, y; - if (sscanf (position, "%d %d", &x, &y) == 2) - { - output->initial_x = x; - output->initial_y = y; - } - else - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output %s position not of form \"x y\"\n", - output->name); - output->initial_x = output->initial_y = 0; - } - any_set = TRUE; - continue; - } - /* - * Next comes relative positions - */ - relation = 0; - relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) - { - int or; - relative = NULL; - for (or = 0; or < config->num_output; or++) - { - xf86OutputPtr out_rel = config->output[or]; - XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; - - if (rel_mon) - { - if (xf86nameCompare (rel_mon->mon_identifier, - relative_name) == 0) - { - relative = config->output[or]; - break; - } - } - if (strcmp (out_rel->name, relative_name) == 0) - { - relative = config->output[or]; - break; - } - } - if (!relative) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Cannot position output %s relative to unknown output %s\n", - output->name, relative_name); - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - continue; - } - if (!modes[or]) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Cannot position output %s relative to output %s without modes\n", - output->name, relative_name); - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - continue; - } - if (relative->initial_x == POSITION_UNSET) - { - keep_going = TRUE; - continue; - } - output->initial_x = relative->initial_x; - output->initial_y = relative->initial_y; - switch (relation) { - case OPTION_BELOW: - output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation); - break; - case OPTION_RIGHT_OF: - output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); - break; - case OPTION_ABOVE: - if (modes[o]) - output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation); - break; - case OPTION_LEFT_OF: - if (modes[o]) - output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation); - break; - default: - break; - } - any_set = TRUE; - continue; - } - - /* Nothing set, just stick them at 0,0 */ - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - } - if (!keep_going) - break; - if (!any_set) - { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - if (output->initial_x == POSITION_UNSET) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output position loop. Moving %s to 0,0\n", - output->name); - output->initial_x = output->initial_y = 0; - break; - } - } - } - } - - /* - * normalize positions - */ - min_x = 1000000; - min_y = 1000000; - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - if (output->initial_x < min_x) - min_x = output->initial_x; - if (output->initial_y < min_y) - min_y = output->initial_y; - } - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->initial_x -= min_x; - output->initial_y -= min_y; - } - return TRUE; -} - -static void -xf86InitialPanning (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - char *panning = xf86GetOptValString (output->options, OPTION_PANNING); - int width, height, left, top; - int track_width, track_height, track_left, track_top; - int brdr[4]; - - memset (&output->initialTotalArea, 0, sizeof(BoxRec)); - memset (&output->initialTrackingArea, 0, sizeof(BoxRec)); - memset (output->initialBorder, 0, 4*sizeof(INT16)); - - if (! panning) - continue; - - switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", - &width, &height, &left, &top, - &track_width, &track_height, &track_left, &track_top, - &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { - case 12: - output->initialBorder[0] = brdr[0]; - output->initialBorder[1] = brdr[1]; - output->initialBorder[2] = brdr[2]; - output->initialBorder[3] = brdr[3]; - /* fall through */ - case 8: - output->initialTrackingArea.x1 = track_left; - output->initialTrackingArea.y1 = track_top; - output->initialTrackingArea.x2 = track_left + track_width; - output->initialTrackingArea.y2 = track_top + track_height; - /* fall through */ - case 4: - output->initialTotalArea.x1 = left; - output->initialTotalArea.y1 = top; - /* fall through */ - case 2: - output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; - output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; - break; - default: - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Broken panning specification '%s' for output %s in config file\n", - panning, output->name); - } - } -} - -/** Return - 0 + if a should be earlier, same or later than b in list - */ -static int -xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) -{ - int diff; - - diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); - if (diff) - return diff; - diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; - if (diff) - return diff; - diff = b->Clock - a->Clock; - return diff; -} - -/** - * Insertion sort input in-place and return the resulting head - */ -static DisplayModePtr -xf86SortModes (DisplayModePtr input) -{ - DisplayModePtr output = NULL, i, o, n, *op, prev; - - /* sort by preferred status and pixel area */ - while (input) - { - i = input; - input = input->next; - for (op = &output; (o = *op); op = &o->next) - if (xf86ModeCompare (o, i) > 0) - break; - i->next = *op; - *op = i; - } - /* prune identical modes */ - for (o = output; o && (n = o->next); o = n) - { - if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) - { - o->next = n->next; - free(n->name); - free(n); - n = o; - } - } - /* hook up backward links */ - prev = NULL; - for (o = output; o; o = o->next) - { - o->prev = prev; - prev = o; - } - return output; -} - -static char * -preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) -{ - char *preferred_mode = NULL; - - /* Check for a configured preference for a particular mode */ - preferred_mode = xf86GetOptValString (output->options, - OPTION_PREFERRED_MODE); - if (preferred_mode) - return preferred_mode; - - if (pScrn->display->modes && *pScrn->display->modes) - preferred_mode = *pScrn->display->modes; - - return preferred_mode; -} - -static void -GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) -{ - if (!mon || !mode) - return; - - mon->nHsync = 1; - mon->hsync[0].lo = 1024.0; - mon->hsync[0].hi = 0.0; - - mon->nVrefresh = 1; - mon->vrefresh[0].lo = 1024.0; - mon->vrefresh[0].hi = 0.0; - - while (mode) { - if (!mode->HSync) - mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal); - - if (!mode->VRefresh) - mode->VRefresh = (1000.0 * ((float) mode->Clock)) / - ((float) (mode->HTotal * mode->VTotal)); - - if (mode->HSync < mon->hsync[0].lo) - mon->hsync[0].lo = mode->HSync; - - if (mode->HSync > mon->hsync[0].hi) - mon->hsync[0].hi = mode->HSync; - - if (mode->VRefresh < mon->vrefresh[0].lo) - mon->vrefresh[0].lo = mode->VRefresh; - - if (mode->VRefresh > mon->vrefresh[0].hi) - mon->vrefresh[0].hi = mode->VRefresh; - - mode = mode->next; - } - - /* stretch out the bottom to fit 640x480@60 */ - if (mon->hsync[0].lo > 31.0) - mon->hsync[0].lo = 31.0; - if (mon->vrefresh[0].lo > 58.0) - mon->vrefresh[0].lo = 58.0; -} - -enum det_monrec_source { - sync_config, sync_edid, sync_default -}; - -struct det_monrec_parameter { - MonRec *mon_rec; - int *max_clock; - Bool set_hsync; - Bool set_vrefresh; - enum det_monrec_source *sync_source; -}; - -static void handle_detailed_monrec(struct detailed_monitor_section *det_mon, - void *data) -{ - struct det_monrec_parameter *p; - p = (struct det_monrec_parameter *)data; - - if (det_mon->type == DS_RANGES) { - struct monitor_ranges *ranges = &det_mon->section.ranges; - if (p->set_hsync && ranges->max_h) { - p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; - p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; - p->mon_rec->nHsync++; - if (*p->sync_source == sync_default) - *p->sync_source = sync_edid; - } - if (p->set_vrefresh && ranges->max_v) { - p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; - p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; - p->mon_rec->nVrefresh++; - if (*p->sync_source == sync_default) - *p->sync_source = sync_edid; - } - if (ranges->max_clock * 1000 > *p->max_clock) - *p->max_clock = ranges->max_clock * 1000; - } -} - -void -xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - /* When canGrow was TRUE in the initial configuration we have to - * compare against the maximum values so that we don't drop modes. - * When canGrow was FALSE, the maximum values would have been clamped - * anyway. - */ - if (maxX == 0 || maxY == 0) { - maxX = config->maxWidth; - maxY = config->maxHeight; - } - - /* Probe the list of modes for each output. */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode; - DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL; - char *preferred_mode; - xf86MonPtr edid_monitor; - XF86ConfMonitorPtr conf_monitor; - MonRec mon_rec; - int min_clock = 0; - int max_clock = 0; - double clock; - Bool add_default_modes; - Bool debug_modes = config->debug_modes || - xf86Initialising; - enum det_monrec_source sync_source = sync_default; - - while (output->probed_modes != NULL) - xf86DeleteMode(&output->probed_modes, output->probed_modes); - - /* - * Check connection status - */ - output->status = (*output->funcs->detect)(output); - - if (output->status == XF86OutputStatusDisconnected && - !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE)) - { - xf86OutputSetEDID (output, NULL); - continue; - } - - memset (&mon_rec, '\0', sizeof (mon_rec)); - - conf_monitor = output->conf_monitor; - - if (conf_monitor) - { - int i; - - for (i = 0; i < conf_monitor->mon_n_hsync; i++) - { - mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; - mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; - mon_rec.nHsync++; - sync_source = sync_config; - } - for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) - { - mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; - mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; - mon_rec.nVrefresh++; - sync_source = sync_config; - } - config_modes = xf86GetMonitorModes (scrn, conf_monitor); - } - - output_modes = (*output->funcs->get_modes) (output); - - /* - * If the user has a preference, respect it. - * Otherwise, don't second-guess the driver. - */ - if (!xf86GetOptValBool(output->options, OPTION_DEFAULT_MODES, - &add_default_modes)) - add_default_modes = (output_modes == NULL); - - edid_monitor = output->MonInfo; - - if (edid_monitor) - { - struct det_monrec_parameter p; - struct disp_features *features = &edid_monitor->features; - - /* if display is not continuous-frequency, don't add default modes */ - if (!GTF_SUPPORTED(features->msc)) - add_default_modes = FALSE; - - p.mon_rec = &mon_rec; - p.max_clock = &max_clock; - p.set_hsync = mon_rec.nHsync == 0; - p.set_vrefresh = mon_rec.nVrefresh == 0; - p.sync_source = &sync_source; - - xf86ForEachDetailedBlock(edid_monitor, - handle_detailed_monrec, - &p); - } - - if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, - OPTUNITS_KHZ, &clock)) - min_clock = (int) clock; - if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, - OPTUNITS_KHZ, &clock)) - max_clock = (int) clock; - - /* If we still don't have a sync range, guess wildly */ - if (!mon_rec.nHsync || !mon_rec.nVrefresh) - GuessRangeFromModes(&mon_rec, output_modes); - - /* - * These limits will end up setting a 1024x768@60Hz mode by default, - * which seems like a fairly good mode to use when nothing else is - * specified - */ - if (mon_rec.nHsync == 0) - { - mon_rec.hsync[0].lo = 31.0; - mon_rec.hsync[0].hi = 55.0; - mon_rec.nHsync = 1; - } - if (mon_rec.nVrefresh == 0) - { - mon_rec.vrefresh[0].lo = 58.0; - mon_rec.vrefresh[0].hi = 62.0; - mon_rec.nVrefresh = 1; - } - - if (add_default_modes) - default_modes = xf86GetDefaultModes (); - - /* - * If this is not an RB monitor, remove RB modes from the default - * pool. RB modes from the config or the monitor itself are fine. - */ - if (!mon_rec.reducedblanking) - xf86ValidateModesReducedBlanking (scrn, default_modes); - - if (sync_source == sync_config) - { - /* - * Check output and config modes against sync range from config file - */ - xf86ValidateModesSync (scrn, output_modes, &mon_rec); - xf86ValidateModesSync (scrn, config_modes, &mon_rec); - } - /* - * Check default modes against sync range - */ - xf86ValidateModesSync (scrn, default_modes, &mon_rec); - /* - * Check default modes against monitor max clock - */ - if (max_clock) { - xf86ValidateModesClocks(scrn, default_modes, - &min_clock, &max_clock, 1); - xf86ValidateModesClocks(scrn, output_modes, - &min_clock, &max_clock, 1); - } - - output->probed_modes = NULL; - output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); - output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); - output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); - - /* - * Check all modes against max size, interlace, and doublescan - */ - if (maxX && maxY) - xf86ValidateModesSize (scrn, output->probed_modes, - maxX, maxY, 0); - - { - int flags = (output->interlaceAllowed ? V_INTERLACE : 0) | - (output->doubleScanAllowed ? V_DBLSCAN : 0); - xf86ValidateModesFlags (scrn, output->probed_modes, flags); - } - - /* - * Check all modes against output - */ - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - if (mode->status == MODE_OK) - mode->status = (*output->funcs->mode_valid)(output, mode); - - xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); - - output->probed_modes = xf86SortModes (output->probed_modes); - - /* Check for a configured preference for a particular mode */ - preferred_mode = preferredMode(scrn, output); - - if (preferred_mode) - { - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (!strcmp (preferred_mode, mode->name)) - { - if (mode != output->probed_modes) - { - if (mode->prev) - mode->prev->next = mode->next; - if (mode->next) - mode->next->prev = mode->prev; - mode->next = output->probed_modes; - output->probed_modes->prev = mode; - mode->prev = NULL; - output->probed_modes = mode; - } - mode->type |= (M_T_PREFERRED|M_T_USERPREF); - break; - } - } - } - - output->initial_rotation = xf86OutputInitialRotation (output); - - if (debug_modes) { - if (output->probed_modes != NULL) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Printing probed modes for output %s\n", - output->name); - } else { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "No remaining probed modes for output %s\n", - output->name); - } - } - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - { - /* The code to choose the best mode per pipe later on will require - * VRefresh to be set. - */ - mode->VRefresh = xf86ModeVRefresh(mode); - xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - - if (debug_modes) - xf86PrintModeline(scrn->scrnIndex, mode); - } - } -} - - -/** - * Copy one of the output mode lists to the ScrnInfo record - */ - -/* XXX where does this function belong? Here? */ -void -xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y); - -static DisplayModePtr -biggestMode(DisplayModePtr a, DisplayModePtr b) -{ - int A, B; - - if (!a) - return b; - if (!b) - return a; - - A = a->HDisplay * a->VDisplay; - B = b->HDisplay * b->VDisplay; - - if (A > B) - return a; - - return b; -} - -static xf86OutputPtr -SetCompatOutput(xf86CrtcConfigPtr config) -{ - xf86OutputPtr output = NULL, test = NULL; - DisplayModePtr maxmode = NULL, testmode, mode; - int o, compat = -1, count, mincount = 0; - - /* Look for one that's definitely connected */ - for (o = 0; o < config->num_output; o++) - { - test = config->output[o]; - if (!test->crtc) - continue; - if (test->status != XF86OutputStatusConnected) - continue; - if (!test->probed_modes) - continue; - - testmode = mode = test->probed_modes; - for (count = 0; mode; mode = mode->next, count++) - testmode = biggestMode(testmode, mode); - - if (!output) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } else if (maxmode == biggestMode(maxmode, testmode)) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } else if ((maxmode->HDisplay == testmode->HDisplay) && - (maxmode->VDisplay == testmode->VDisplay) && - count <= mincount) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } - } - - /* If we didn't find one, take anything we can get */ - if (!output) - { - for (o = 0; o < config->num_output; o++) - { - test = config->output[o]; - if (!test->crtc) - continue; - if (!test->probed_modes) - continue; - - if (!output) { - output = test; - compat = o; - } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) { - output = test; - compat = o; - } - } - } - - if (compat >= 0) { - config->compat_output = compat; - } else { - /* Don't change the compat output when no valid outputs found */ - output = config->output[config->compat_output]; - } - - return output; -} - -void -xf86SetScrnInfoModes (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86OutputPtr output; - xf86CrtcPtr crtc; - DisplayModePtr last, mode = NULL; - - output = SetCompatOutput(config); - - if (!output) - return; /* punt */ - - crtc = output->crtc; - - /* Clear any existing modes from scrn->modes */ - while (scrn->modes != NULL) - xf86DeleteMode(&scrn->modes, scrn->modes); - - /* Set scrn->modes to the mode list for the 'compat' output */ - scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); - - if (crtc) { - for (mode = scrn->modes; mode; mode = mode->next) - if (xf86ModesEqual (mode, &crtc->desiredMode)) - break; - } - - if (scrn->modes != NULL) { - /* For some reason, scrn->modes is circular, unlike the other mode - * lists. How great is that? - */ - for (last = scrn->modes; last && last->next; last = last->next) - ; - last->next = scrn->modes; - scrn->modes->prev = last; - if (mode) { - while (scrn->modes != mode) - scrn->modes = scrn->modes->next; - } - } - scrn->currentMode = scrn->modes; -#ifdef XFreeXDGA - if (scrn->pScreen) - _xf86_di_dga_reinit_internal(scrn->pScreen); -#endif -} - -static Bool -xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - Bool *enabled) -{ - Bool any_enabled = FALSE; - int o; - - for (o = 0; o < config->num_output; o++) - any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE); - - if (!any_enabled) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "No outputs definitely connected, trying again...\n"); - - for (o = 0; o < config->num_output; o++) - any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], FALSE); - } - - return any_enabled; -} - -static Bool -nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) -{ - int o = *index; - - for (o++; o < config->num_output; o++) { - if (enabled[o]) { - *index = o; - return TRUE; - } - } - - return FALSE; -} - -static Bool -aspectMatch(float a, float b) -{ - return fabs(1 - (a / b)) < 0.05; -} - -static DisplayModePtr -nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) -{ - DisplayModePtr m = NULL; - - if (!o) - return NULL; - - if (!last) - m = o->probed_modes; - else - m = last->next; - - for (; m; m = m->next) - if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) - return m; - - return NULL; -} - -static DisplayModePtr -bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) -{ - int o = -1, p; - DisplayModePtr mode = NULL, test = NULL, match = NULL; - - if (!nextEnabledOutput(config, enabled, &o)) - return NULL; - while ((mode = nextAspectMode(config->output[o], mode, aspect))) { - test = mode; - for (p = o; nextEnabledOutput(config, enabled, &p); ) { - test = xf86OutputFindClosestMode(config->output[p], mode); - if (!test) - break; - if (test->HDisplay != mode->HDisplay || - test->VDisplay != mode->VDisplay) { - test = NULL; - break; - } - } - - /* if we didn't match it on all outputs, try the next one */ - if (!test) - continue; - - /* if it's bigger than the last one, save it */ - if (!match || (test->HDisplay > match->HDisplay)) - match = test; - } - - /* return the biggest one found */ - return match; -} - -static Bool -xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o, p; - int max_pref_width = 0, max_pref_height = 0; - DisplayModePtr *preferred, *preferred_match; - Bool ret = FALSE; - - preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); - preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); - - /* Check if the preferred mode is available on all outputs */ - for (p = -1; nextEnabledOutput(config, enabled, &p); ) { - Rotation r = config->output[p]->initial_rotation; - DisplayModePtr mode; - if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p], - width, height))) { - int pref_width = xf86ModeWidth(preferred[p], r); - int pref_height = xf86ModeHeight(preferred[p], r); - Bool all_match = TRUE; - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - Bool match = FALSE; - xf86OutputPtr output = config->output[o]; - if (o == p) - continue; - - for (mode = output->probed_modes; mode; mode = mode->next) { - Rotation r = output->initial_rotation; - if (xf86ModeWidth(mode, r) == pref_width && - xf86ModeHeight(mode, r) == pref_height) { - preferred[o] = mode; - match = TRUE; - } - } - - all_match &= match; - } - - if (all_match && - (pref_width*pref_height > max_pref_width*max_pref_height)) { - for (o = -1; nextEnabledOutput(config, enabled, &o); ) - preferred_match[o] = preferred[o]; - max_pref_width = pref_width; - max_pref_height = pref_height; - ret = TRUE; - } - } - } - - /* - * If there's no preferred mode, but only one monitor, pick the - * biggest mode for its aspect ratio, assuming one exists. - */ - if (!ret) do { - int i = 0; - float aspect = 0.0; - - /* count the number of enabled outputs */ - for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; - - if (i != 1) - break; - - p = -1; - nextEnabledOutput(config, enabled, &p); - if (config->output[p]->mm_height) - aspect = (float)config->output[p]->mm_width / - (float)config->output[p]->mm_height; - - if (aspect) - preferred_match[p] = bestModeForAspect(config, enabled, aspect); - - if (preferred_match[p]) - ret = TRUE; - - } while (0); - - if (ret) { - /* oh good, there is a match. stash the selected modes and return. */ - memcpy(modes, preferred_match, - config->num_output * sizeof(DisplayModePtr)); - } - - free(preferred); - free(preferred_match); - return ret; -} - -static Bool -xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o; - float aspect = 0.0, *aspects; - xf86OutputPtr output; - Bool ret = FALSE; - DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL; - - aspects = xnfcalloc(config->num_output, sizeof(float)); - - /* collect the aspect ratios */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - output = config->output[o]; - if (output->mm_height) - aspects[o] = (float)output->mm_width / (float)output->mm_height; - else - aspects[o] = 4.0 / 3.0; - } - - /* check that they're all the same */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - output = config->output[o]; - if (!aspect) { - aspect = aspects[o]; - } else if (!aspectMatch(aspect, aspects[o])) { - goto no_aspect_match; - } - } - - /* if they're all 4:3, just skip ahead and save effort */ - if (!aspectMatch(aspect, 4.0/3.0)) - aspect_guess = bestModeForAspect(config, enabled, aspect); - -no_aspect_match: - base_guess = bestModeForAspect(config, enabled, 4.0/3.0); - - guess = biggestMode(base_guess, aspect_guess); - - if (!guess) - goto out; - - /* found a mode that works everywhere, now apply it */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - modes[o] = xf86OutputFindClosestMode(config->output[o], guess); - } - ret = TRUE; - -out: - free(aspects); - return ret; -} - -static Bool -xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - DisplayModePtr target_mode = NULL; - Rotation target_rotation = RR_Rotate_0; - DisplayModePtr default_mode; - int default_preferred, target_preferred = 0, o; - - /* User preferred > preferred > other modes */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - default_mode = xf86DefaultMode (config->output[o], width, height); - if (!default_mode) - continue; - - default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) + - ((default_mode->type & M_T_USERPREF) != 0)); - - if (default_preferred > target_preferred || !target_mode) { - target_mode = default_mode; - target_preferred = default_preferred; - target_rotation = config->output[o]->initial_rotation; - config->compat_output = o; - } - } - - if (target_mode) - modes[config->compat_output] = target_mode; - - /* Fill in other output modes */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - if (!modes[o]) - modes[o] = xf86ClosestMode(config->output[o], target_mode, - target_rotation, width, height); - } - - return target_mode != NULL; -} - -static Bool -xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o; - - if (xf86UserConfiguredOutputs(scrn, modes)) - return xf86TargetFallback(scrn, config, modes, enabled, width, height); - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) - if (xf86OutputHasUserPreferredMode(config->output[o])) - return - xf86TargetFallback(scrn, config, modes, enabled, width, height); - - return FALSE; -} - -static Bool -xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, - float gamma_blue) -{ - int i, size = 256; - CARD16 *red, *green, *blue; - - red = malloc(3 * size * sizeof(CARD16)); - green = red + size; - blue = green + size; - - /* Only cause warning if user wanted gamma to be set. */ - if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { - free(red); - return FALSE; - } else if (!crtc->funcs->gamma_set) { - free(red); - return TRUE; - } - - /* At this early stage none of the randr-interface stuff is up. - * So take the default gamma size for lack of something better. - */ - for (i = 0; i < size; i++) { - if (gamma_red == 1.0) - red[i] = i << 8; - else - red[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_red) * (double)(size - 1) * 256); - - if (gamma_green == 1.0) - green[i] = i << 8; - else - green[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_green) * (double)(size - 1) * 256); - - if (gamma_blue == 1.0) - blue[i] = i << 8; - else - blue[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_blue) * (double)(size - 1) * 256); - } - - /* Default size is 256, so anything else is failure. */ - if (size != crtc->gamma_size) { - free(red); - return FALSE; - } - - crtc->gamma_size = size; - memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16)); - - /* Do not set gamma now, delay until the crtc is activated. */ - - free(red); - - return TRUE; -} - -static Bool -xf86OutputSetInitialGamma(xf86OutputPtr output) -{ - XF86ConfMonitorPtr mon = output->conf_monitor; - float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; - - if (!mon) - return TRUE; - - if (!output->crtc) - return FALSE; - - /* Get configured values, where they exist. */ - if (mon->mon_gamma_red >= GAMMA_MIN && - mon->mon_gamma_red <= GAMMA_MAX) - gamma_red = mon->mon_gamma_red; - - if (mon->mon_gamma_green >= GAMMA_MIN && - mon->mon_gamma_green <= GAMMA_MAX) - gamma_green = mon->mon_gamma_green; - - if (mon->mon_gamma_blue >= GAMMA_MIN && - mon->mon_gamma_blue <= GAMMA_MAX) - gamma_blue = mon->mon_gamma_blue; - - /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ - if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue); - return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue); - }else - return TRUE; -} - -/** - * Construct default screen configuration - * - * Given auto-detected (and, eventually, configured) values, - * construct a usable configuration for the system - * - * canGrow indicates that the driver can resize the screen to larger than its - * initially configured size via the config->funcs->resize hook. If TRUE, this - * function will set virtualX and virtualY to match the initial configuration - * and leave config->max{Width,Height} alone. If FALSE, it will bloat - * virtual[XY] to include the largest modes and set config->max{Width,Height} - * accordingly. - */ - -Bool -xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o, c; - xf86CrtcPtr *crtcs; - DisplayModePtr *modes; - Bool *enabled; - int width, height; - int i = scrn->scrnIndex; - Bool have_outputs = TRUE; - Bool ret; - - /* Set up the device options */ - config->options = xnfalloc (sizeof (xf86DeviceOptions)); - memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions)); - xf86ProcessOptions (scrn->scrnIndex, - scrn->options, - config->options); - config->debug_modes = xf86ReturnOptValBool (config->options, - OPTION_MODEDEBUG, FALSE); - - if (scrn->display->virtualX) - width = scrn->display->virtualX; - else - width = config->maxWidth; - if (scrn->display->virtualY) - height = scrn->display->virtualY; - else - height = config->maxHeight; - - xf86ProbeOutputModes (scrn, width, height); - - crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); - modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); - enabled = xnfcalloc (config->num_output, sizeof (Bool)); - - ret = xf86CollectEnabledOutputs(scrn, config, enabled); - if (ret == FALSE && canGrow) { - xf86DrvMsg(i, X_WARNING, "Unable to find connected outputs - setting %dx%d initial framebuffer\n", - NO_OUTPUT_DEFAULT_WIDTH, NO_OUTPUT_DEFAULT_HEIGHT); - have_outputs = FALSE; - } else { - if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); - else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); - else if (xf86TargetAspect(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n"); - else if (xf86TargetFallback(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n"); - else - xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n"); - } - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - if (!modes[o]) - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output %s enabled but has no modes\n", - config->output[o]->name); - else - xf86DrvMsg (scrn->scrnIndex, X_INFO, - "Output %s using initial mode %s\n", - config->output[o]->name, modes[o]->name); - } - - /* - * Set the position of each output - */ - if (!xf86InitialOutputPositions (scrn, modes)) - { - free(crtcs); - free(modes); - return FALSE; - } - - /* - * Set initial panning of each output - */ - xf86InitialPanning (scrn); - - /* - * Assign CRTCs to fit output configuration - */ - if (have_outputs && !xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) - { - free(crtcs); - free(modes); - return FALSE; - } - - /* XXX override xf86 common frame computation code */ - - scrn->display->frameX0 = 0; - scrn->display->frameY0 = 0; - - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->enabled = FALSE; - memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); - /* Set default gamma for all crtc's. */ - /* This is done to avoid problems later on with cloned outputs. */ - xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); - } - - if (xf86_crtc_supports_gamma(scrn)) - xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n"); - - /* - * Set initial configuration - */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode = modes[o]; - xf86CrtcPtr crtc = crtcs[o]; - - if (mode && crtc) - { - crtc->desiredMode = *mode; - crtc->desiredRotation = output->initial_rotation; - crtc->desiredX = output->initial_x; - crtc->desiredY = output->initial_y; - crtc->desiredTransformPresent = FALSE; - crtc->enabled = TRUE; - memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec)); - memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec)); - memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16)); - output->crtc = crtc; - if (!xf86OutputSetInitialGamma(output)) - xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name); - } else { - output->crtc = NULL; - } - } - - if (scrn->display->virtualX == 0) - { - /* - * Expand virtual size to cover the current config and potential mode - * switches, if the driver can't enlarge the screen later. - */ - xf86DefaultScreenLimits (scrn, &width, &height, canGrow); - - if (have_outputs == FALSE) { - if (width < NO_OUTPUT_DEFAULT_WIDTH && height < NO_OUTPUT_DEFAULT_HEIGHT) { - width = NO_OUTPUT_DEFAULT_WIDTH; - height = NO_OUTPUT_DEFAULT_HEIGHT; - } - } - - scrn->display->virtualX = width; - scrn->display->virtualY = height; - } - - if (width > scrn->virtualX) - scrn->virtualX = width; - if (height > scrn->virtualY) - scrn->virtualY = height; - - /* - * Make sure the configuration isn't too small. - */ - if (width < config->minWidth || height < config->minHeight) - return FALSE; - - /* - * Limit the crtc config to virtual[XY] if the driver can't grow the - * desktop. - */ - if (!canGrow) - { - xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight, - width, height); - } - - if (have_outputs) { - /* Mirror output modes to scrn mode list */ - xf86SetScrnInfoModes (scrn); - } else { - /* Clear any existing modes from scrn->modes */ - while (scrn->modes != NULL) - xf86DeleteMode(&scrn->modes, scrn->modes); - scrn->modes = xf86ModesAdd(scrn->modes, - xf86CVTMode(width, height, 60, 0, 0)); - } - - - free(crtcs); - free(modes); - return TRUE; -} - -/* - * Check the CRTC we're going to map each output to vs. it's current - * CRTC. If they don't match, we have to disable the output and the CRTC - * since the driver will have to re-route things. - */ -static void -xf86PrepareOutputs (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = config->output[o]; -#if RANDR_GET_CRTC_INTERFACE - /* Disable outputs that are unused or will be re-routed */ - if (!output->funcs->get_crtc || - output->crtc != (*output->funcs->get_crtc)(output) || - output->crtc == NULL) -#endif - (*output->funcs->dpms)(output, DPMSModeOff); - } -} - -static void -xf86PrepareCrtcs (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - for (c = 0; c < config->num_crtc; c++) { -#if RANDR_GET_CRTC_INTERFACE - xf86CrtcPtr crtc = config->crtc[c]; - xf86OutputPtr output = NULL; - uint32_t desired_outputs = 0, current_outputs = 0; - int o; - - for (o = 0; o < config->num_output; o++) { - output = config->output[o]; - if (output->crtc == crtc) - desired_outputs |= (1<funcs->get_crtc) { - desired_outputs = 0; - break; - } - if ((*output->funcs->get_crtc)(output) == crtc) - current_outputs |= (1<funcs->dpms)(crtc, DPMSModeOff); -#else - (*crtc->funcs->dpms)(crtc, DPMSModeOff); -#endif - } -} - -/* - * Using the desired mode information in each crtc, set - * modes (used in EnterVT functions, or at server startup) - */ - -Bool -xf86SetDesiredModes (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc = config->crtc[0]; - int c; - - /* A driver with this hook will take care of this */ - if (!crtc->funcs->set_mode_major) { - xf86PrepareOutputs(scrn); - xf86PrepareCrtcs(scrn); - } - - for (c = 0; c < config->num_crtc; c++) - { - xf86OutputPtr output = NULL; - int o; - RRTransformPtr transform; - - crtc = config->crtc[c]; - - /* Skip disabled CRTCs */ - if (!crtc->enabled) - continue; - - if (xf86CompatOutput(scrn) && xf86CompatCrtc(scrn) == crtc) - output = xf86CompatOutput(scrn); - else - { - for (o = 0; o < config->num_output; o++) - if (config->output[o]->crtc == crtc) - { - output = config->output[o]; - break; - } - } - /* paranoia */ - if (!output) - continue; - - /* Mark that we'll need to re-set the mode for sure */ - memset(&crtc->mode, 0, sizeof(crtc->mode)); - if (!crtc->desiredMode.CrtcHDisplay) - { - DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode); - - if (!mode) - return FALSE; - crtc->desiredMode = *mode; - crtc->desiredRotation = RR_Rotate_0; - crtc->desiredTransformPresent = FALSE; - crtc->desiredX = 0; - crtc->desiredY = 0; - } - - if (crtc->desiredTransformPresent) - transform = &crtc->desiredTransform; - else - transform = NULL; - if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation, - transform, crtc->desiredX, crtc->desiredY)) - return FALSE; - } - - xf86DisableUnusedFunctions(scrn); - return TRUE; -} - -/** - * In the current world order, there are lists of modes per output, which may - * or may not include the mode that was asked to be set by XFree86's mode - * selection. Find the closest one, in the following preference order: - * - * - Equality - * - Closer in size to the requested mode, but no larger - * - Closer in refresh rate to the requested mode. - */ - -DisplayModePtr -xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired) -{ - DisplayModePtr best = NULL, scan = NULL; - - for (scan = output->probed_modes; scan != NULL; scan = scan->next) - { - /* If there's an exact match, we're done. */ - if (xf86ModesEqual(scan, desired)) { - best = desired; - break; - } - - /* Reject if it's larger than the desired mode. */ - if (scan->HDisplay > desired->HDisplay || - scan->VDisplay > desired->VDisplay) - { - continue; - } - - /* - * If we haven't picked a best mode yet, use the first - * one in the size range - */ - if (best == NULL) - { - best = scan; - continue; - } - - /* Find if it's closer to the right size than the current best - * option. - */ - if ((scan->HDisplay > best->HDisplay && - scan->VDisplay >= best->VDisplay) || - (scan->HDisplay >= best->HDisplay && - scan->VDisplay > best->VDisplay)) - { - best = scan; - continue; - } - - /* Find if it's still closer to the right refresh than the current - * best resolution. - */ - if (scan->HDisplay == best->HDisplay && - scan->VDisplay == best->VDisplay && - (fabs(scan->VRefresh - desired->VRefresh) < - fabs(best->VRefresh - desired->VRefresh))) { - best = scan; - } - } - return best; -} - -/** - * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, - * take the specified mode and apply it to the crtc connected to the compat - * output. Then, find similar modes for the other outputs, as with the - * InitialConfiguration code above. The goal is to clone the desired - * mode across all outputs that are currently active. - */ - -Bool -xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - Bool ok = TRUE; - xf86OutputPtr compat_output; - DisplayModePtr compat_mode = NULL; - int c; - - /* - * Let the compat output drive the final mode selection - */ - compat_output = xf86CompatOutput(pScrn); - if (compat_output) - compat_mode = xf86OutputFindClosestMode (compat_output, desired); - if (compat_mode) - desired = compat_mode; - - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - DisplayModePtr crtc_mode = NULL; - int o; - - if (!crtc->enabled) - continue; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr output_mode; - - /* skip outputs not on this crtc */ - if (output->crtc != crtc) - continue; - - if (crtc_mode) - { - output_mode = xf86OutputFindClosestMode (output, crtc_mode); - if (output_mode != crtc_mode) - output->crtc = NULL; - } - else - crtc_mode = xf86OutputFindClosestMode (output, desired); - } - if (!crtc_mode) - { - crtc->enabled = FALSE; - continue; - } - if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0)) - ok = FALSE; - else - { - crtc->desiredMode = *crtc_mode; - crtc->desiredRotation = rotation; - crtc->desiredTransformPresent = FALSE; - crtc->desiredX = 0; - crtc->desiredY = 0; - } - } - xf86DisableUnusedFunctions(pScrn); -#ifdef RANDR_12_INTERFACE - xf86RandR12TellChanged (pScrn->pScreen); -#endif - return ok; -} - - -/** - * Set the DPMS power mode of all outputs and CRTCs. - * - * If the new mode is off, it will turn off outputs and then CRTCs. - * Otherwise, it will affect CRTCs before outputs. - */ -void -xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - - if (!scrn->vtSema) - return; - - if (mode == DPMSModeOff) { - for (i = 0; i < config->num_output; i++) { - xf86OutputPtr output = config->output[i]; - if (output->crtc != NULL) - (*output->funcs->dpms) (output, mode); - } - } - - for (i = 0; i < config->num_crtc; i++) { - xf86CrtcPtr crtc = config->crtc[i]; - if (crtc->enabled) - (*crtc->funcs->dpms) (crtc, mode); - } - - if (mode != DPMSModeOff) { - for (i = 0; i < config->num_output; i++) { - xf86OutputPtr output = config->output[i]; - if (output->crtc != NULL) - (*output->funcs->dpms) (output, mode); - } - } -} - -/** - * Implement the screensaver by just calling down into the driver DPMS hooks. - * - * Even for monitors with no DPMS support, by the definition of our DPMS hooks, - * the outputs will still get disabled (blanked). - */ -Bool -xf86SaveScreen(ScreenPtr pScreen, int mode) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (xf86IsUnblank(mode)) - xf86DPMSSet(pScrn, DPMSModeOn, 0); - else - xf86DPMSSet(pScrn, DPMSModeOff, 0); - - return TRUE; -} - -/** - * Disable all inactive crtcs and outputs - */ -void -xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o, c; - - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - if (!output->crtc) - (*output->funcs->dpms)(output, DPMSModeOff); - } - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - if (!crtc->enabled) - { - crtc->funcs->dpms(crtc, DPMSModeOff); - memset(&crtc->mode, 0, sizeof(crtc->mode)); - xf86RotateDestroy(crtc); - crtc->active = FALSE; - } - } - if (pScrn->pScreen) - xf86_crtc_notify(pScrn->pScreen); - if (pScrn->ModeSet) - pScrn->ModeSet(pScrn); -} - -#ifdef RANDR_12_INTERFACE - -#define EDID_ATOM_NAME "EDID" - -/** - * Set the RandR EDID property - */ -static void -xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) -{ - Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE); - - /* This may get called before the RandR resources have been created */ - if (output->randr_output == NULL) - return; - - if (data_len != 0) { - RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, - PropModeReplace, data_len, data, FALSE, TRUE); - } else { - RRDeleteOutputProperty(output->randr_output, edid_atom); - } -} - -#endif - -/* Pull out a phyiscal size from a detailed timing if available. */ -struct det_phySize_parameter { - xf86OutputPtr output; - ddc_quirk_t quirks; - Bool ret; -}; - -static void handle_detailed_physical_size(struct detailed_monitor_section - *det_mon, void *data) -{ - struct det_phySize_parameter *p; - p = (struct det_phySize_parameter *)data; - - if (p->ret == TRUE ) - return ; - - xf86DetTimingApplyQuirks(det_mon, p->quirks, - p->output->MonInfo->features.hsize, - p->output->MonInfo->features.vsize); - if (det_mon->type == DT && - det_mon->section.d_timings.h_size != 0 && - det_mon->section.d_timings.v_size != 0) { - - p->output->mm_width = det_mon->section.d_timings.h_size; - p->output->mm_height = det_mon->section.d_timings.v_size; - p->ret = TRUE; - } -} - -/** - * Set the EDID information for the specified output - */ -void -xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) -{ - ScrnInfoPtr scrn = output->scrn; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - Bool debug_modes = config->debug_modes || xf86Initialising; -#ifdef RANDR_12_INTERFACE - int size; -#endif - - free(output->MonInfo); - - output->MonInfo = edid_mon; - output->mm_width = 0; - output->mm_height = 0; - - if (debug_modes) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", - output->name); - xf86PrintEDID(edid_mon); - } - - /* Set the DDC properties for the 'compat' output */ - if (output == xf86CompatOutput(scrn)) - xf86SetDDCproperties(scrn, edid_mon); - -#ifdef RANDR_12_INTERFACE - /* Set the RandR output properties */ - size = 0; - if (edid_mon) - { - if (edid_mon->ver.version == 1) { - size = 128; - if (edid_mon->flags & EDID_COMPLETE_RAWDATA) - size += edid_mon->no_sections * 128; - } else if (edid_mon->ver.version == 2) - size = 256; - } - xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); -#endif - - if (edid_mon) { - - struct det_phySize_parameter p; - p.output = output; - p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE); - p.ret = FALSE; - xf86ForEachDetailedBlock(edid_mon, - handle_detailed_physical_size, &p); - - /* if no mm size is available from a detailed timing, check the max size field */ - if ((!output->mm_width || !output->mm_height) && - (edid_mon->features.hsize && edid_mon->features.vsize)) - { - output->mm_width = edid_mon->features.hsize * 10; - output->mm_height = edid_mon->features.vsize * 10; - } - } -} - -/** - * Return the list of modes supported by the EDID information - * stored in 'output' - */ -DisplayModePtr -xf86OutputGetEDIDModes (xf86OutputPtr output) -{ - ScrnInfoPtr scrn = output->scrn; - xf86MonPtr edid_mon = output->MonInfo; - - if (!edid_mon) - return NULL; - return xf86DDCGetModes(scrn->scrnIndex, edid_mon); -} - -/* maybe we should care about DDC1? meh. */ -xf86MonPtr -xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) -{ - ScrnInfoPtr scrn = output->scrn; - xf86MonPtr mon; - - mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE); - if (mon) - xf86DDCApplyQuirks(scrn->scrnIndex, mon); - - return mon; -} - -static char *_xf86ConnectorNames[] = { - "None", "VGA", "DVI-I", "DVI-D", - "DVI-A", "Composite", "S-Video", - "Component", "LFP", "Proprietary", - "HDMI", "DisplayPort", - }; -char * -xf86ConnectorGetName(xf86ConnectorType connector) -{ - return _xf86ConnectorNames[connector]; -} - -static void -x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) -{ - dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; - dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; - dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; - dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; - - if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) - dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; -} - -static void -x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) -{ - if (crtc->enabled) { - crtc_box->x1 = crtc->x; - crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); - crtc_box->y1 = crtc->y; - crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); - } else - crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; -} - -static int -xf86_crtc_box_area(BoxPtr box) -{ - return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); -} - -/* - * Return the crtc covering 'box'. If two crtcs cover a portion of - * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc - * with greater coverage - */ - -static xf86CrtcPtr -xf86_covering_crtc(ScrnInfoPtr pScrn, - BoxPtr box, - xf86CrtcPtr desired, - BoxPtr crtc_box_ret) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc, best_crtc; - int coverage, best_coverage; - int c; - BoxRec crtc_box, cover_box; - - best_crtc = NULL; - best_coverage = 0; - crtc_box_ret->x1 = 0; - crtc_box_ret->x2 = 0; - crtc_box_ret->y1 = 0; - crtc_box_ret->y2 = 0; - for (c = 0; c < xf86_config->num_crtc; c++) { - crtc = xf86_config->crtc[c]; - x86_crtc_box(crtc, &crtc_box); - x86_crtc_box_intersect(&cover_box, &crtc_box, box); - coverage = xf86_crtc_box_area(&cover_box); - if (coverage && crtc == desired) { - *crtc_box_ret = crtc_box; - return crtc; - } else if (coverage > best_coverage) { - *crtc_box_ret = crtc_box; - best_crtc = crtc; - best_coverage = coverage; - } - } - return best_crtc; -} - -/* - * For overlay video, compute the relevant CRTC and - * clip video to that. - * - * returning FALSE means there was a memory failure of some kind, - * not that the video shouldn't be displayed - */ - -Bool -xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, - xf86CrtcPtr *crtc_ret, - xf86CrtcPtr desired_crtc, - BoxPtr dst, - INT32 *xa, - INT32 *xb, - INT32 *ya, - INT32 *yb, - RegionPtr reg, - INT32 width, - INT32 height) -{ - Bool ret; - RegionRec crtc_region_local; - RegionPtr crtc_region = reg; - - if (crtc_ret) { - BoxRec crtc_box; - xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, - desired_crtc, - &crtc_box); - - if (crtc) { - RegionInit(&crtc_region_local, &crtc_box, 1); - crtc_region = &crtc_region_local; - RegionIntersect(crtc_region, crtc_region, reg); - } - *crtc_ret = crtc; - } - - ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, - crtc_region, width, height); - - if (crtc_region != reg) - RegionUninit(&crtc_region_local); - - return ret; -} - -xf86_crtc_notify_proc_ptr -xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new) -{ - if (xf86CrtcConfigPrivateIndex != -1) - { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86_crtc_notify_proc_ptr old; - - old = config->xf86_crtc_notify; - config->xf86_crtc_notify = new; - return old; - } - return NULL; -} - -void -xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) -{ - if (xf86CrtcConfigPrivateIndex != -1) - { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->xf86_crtc_notify = old; - } -} - -void -xf86_crtc_notify(ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - if (config->xf86_crtc_notify) - config->xf86_crtc_notify(screen); -} - -Bool -xf86_crtc_supports_gamma(ScrnInfoPtr pScrn) -{ - if (xf86CrtcConfigPrivateIndex != -1) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc; - - /* for multiple drivers loaded we need this */ - if (!xf86_config) - return FALSE; - if (xf86_config->num_crtc == 0) - return FALSE; - crtc = xf86_config->crtc[0]; - - return crtc->funcs->gamma_set != NULL; - } - - return FALSE; -} +/* + * Copyright © 2006 Keith Packard + * Copyright © 2008 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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 +#else +#ifdef HAVE_CONFIG_H +#include +#endif +#endif + +#include +#include +#include + +#include "xf86.h" +#include "xf86DDC.h" +#include "xf86Crtc.h" +#include "xf86Modes.h" +#include "xf86Priv.h" +#include "xf86RandR12.h" +#include "X11/extensions/render.h" +#include "X11/extensions/dpmsconst.h" +#include "X11/Xatom.h" +#include "picturestr.h" + +#include "xf86xv.h" + +#define NO_OUTPUT_DEFAULT_WIDTH 1024 +#define NO_OUTPUT_DEFAULT_HEIGHT 768 +/* + * Initialize xf86CrtcConfig structure + */ + +int xf86CrtcConfigPrivateIndex = -1; + +void +xf86CrtcConfigInit (ScrnInfoPtr scrn, + const xf86CrtcConfigFuncsRec *funcs) +{ + xf86CrtcConfigPtr config; + + if (xf86CrtcConfigPrivateIndex == -1) + xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); + + config->funcs = funcs; + + scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; +} + +void +xf86CrtcSetSizeRange (ScrnInfoPtr scrn, + int minWidth, int minHeight, + int maxWidth, int maxHeight) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->minWidth = minWidth; + config->minHeight = minHeight; + config->maxWidth = maxWidth; + config->maxHeight = maxHeight; +} + +/* + * Crtc functions + */ +xf86CrtcPtr +xf86CrtcCreate (ScrnInfoPtr scrn, + const xf86CrtcFuncsRec *funcs) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc, *crtcs; + + crtc = calloc(sizeof (xf86CrtcRec), 1); + if (!crtc) + return NULL; + crtc->version = XF86_CRTC_VERSION; + crtc->scrn = scrn; + crtc->funcs = funcs; +#ifdef RANDR_12_INTERFACE + crtc->randr_crtc = NULL; +#endif + crtc->rotation = RR_Rotate_0; + crtc->desiredRotation = RR_Rotate_0; + pixman_transform_init_identity (&crtc->crtc_to_framebuffer); + pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); + pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); + crtc->filter = NULL; + crtc->params = NULL; + crtc->nparams = 0; + crtc->filter_width = 0; + crtc->filter_height = 0; + crtc->transform_in_use = FALSE; + crtc->transformPresent = FALSE; + crtc->desiredTransformPresent = FALSE; + memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); + + /* Preallocate gamma at a sensible size. */ + crtc->gamma_size = 256; + crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16)); + if (!crtc->gamma_red) { + free(crtc); + return NULL; + } + crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; + crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; + + if (xf86_config->crtc) + crtcs = realloc(xf86_config->crtc, + (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + else + crtcs = malloc((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + if (!crtcs) + { + free(crtc); + return NULL; + } + xf86_config->crtc = crtcs; + xf86_config->crtc[xf86_config->num_crtc++] = crtc; + return crtc; +} + +void +xf86CrtcDestroy (xf86CrtcPtr crtc) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + int c; + + (*crtc->funcs->destroy) (crtc); + for (c = 0; c < xf86_config->num_crtc; c++) + if (xf86_config->crtc[c] == crtc) + { + memmove (&xf86_config->crtc[c], + &xf86_config->crtc[c+1], + ((xf86_config->num_crtc - (c + 1)) * sizeof(void*))); + xf86_config->num_crtc--; + break; + } + free(crtc->params); + free(crtc->gamma_red); + free(crtc); +} + + +/** + * Return whether any outputs are connected to the specified pipe + */ + +Bool +xf86CrtcInUse (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int o; + + for (o = 0; o < xf86_config->num_output; o++) + if (xf86_config->output[o]->crtc == crtc) + return TRUE; + return FALSE; +} + +void +xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen) +{ + int subpixel_order = SubPixelUnknown; + Bool has_none = FALSE; + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c, o; + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + for (o = 0; o < xf86_config->num_output; o++) + { + xf86OutputPtr output = xf86_config->output[o]; + + if (output->crtc == crtc) + { + switch (output->subpixel_order) { + case SubPixelNone: + has_none = TRUE; + break; + case SubPixelUnknown: + break; + default: + subpixel_order = output->subpixel_order; + break; + } + } + if (subpixel_order != SubPixelUnknown) + break; + } + if (subpixel_order != SubPixelUnknown) + { + static const int circle[4] = { + SubPixelHorizontalRGB, + SubPixelVerticalRGB, + SubPixelHorizontalBGR, + SubPixelVerticalBGR, + }; + int rotate; + int c; + for (rotate = 0; rotate < 4; rotate++) + if (crtc->rotation & (1 << rotate)) + break; + for (c = 0; c < 4; c++) + if (circle[c] == subpixel_order) + break; + c = (c + rotate) & 0x3; + if ((crtc->rotation & RR_Reflect_X) && !(c & 1)) + c ^= 2; + if ((crtc->rotation & RR_Reflect_Y) && (c & 1)) + c ^= 2; + subpixel_order = circle[c]; + break; + } + } + if (subpixel_order == SubPixelUnknown && has_none) + subpixel_order = SubPixelNone; + PictureSetSubpixelOrder (pScreen, subpixel_order); +} + +/** + * Sets the given video mode on the given crtc + */ +Bool +xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + RRTransformPtr transform, int x, int y) +{ + ScrnInfoPtr scrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + Bool ret = FALSE; + Bool didLock = FALSE; + DisplayModePtr adjusted_mode; + DisplayModeRec saved_mode; + int saved_x, saved_y; + Rotation saved_rotation; + RRTransformRec saved_transform; + Bool saved_transform_present; + + crtc->enabled = xf86CrtcInUse (crtc); + + /* We only hit this if someone explicitly sends a "disabled" modeset. */ + if (!crtc->enabled) + { + /* Check everything for stuff that should be off. */ + xf86DisableUnusedFunctions(scrn); + return TRUE; + } + + adjusted_mode = xf86DuplicateMode(mode); + + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + saved_rotation = crtc->rotation; + if (crtc->transformPresent) { + RRTransformInit (&saved_transform); + RRTransformCopy (&saved_transform, &crtc->transform); + } + saved_transform_present = crtc->transformPresent; + + /* Update crtc values up front so the driver can rely on them for mode + * setting. + */ + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + crtc->rotation = rotation; + if (transform) { + RRTransformCopy (&crtc->transform, transform); + crtc->transformPresent = TRUE; + } else + crtc->transformPresent = FALSE; + + if (crtc->funcs->set_mode_major) { + ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y); + goto done; + } + + didLock = crtc->funcs->lock (crtc); + /* Pass our mode to the outputs and the CRTC to give them a chance to + * adjust it according to limitations or output properties, and also + * a chance to reject the mode entirely. + */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { + goto done; + } + } + + if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { + goto done; + } + + if (!xf86CrtcRotate (crtc)) + goto done; + + /* Prepare the outputs and CRTCs before setting the mode. */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + /* Disable the output as the first thing we do. */ + output->funcs->prepare(output); + } + + crtc->funcs->prepare(crtc); + + /* Set up the DPLL and any output state that needs to adjust or depend + * on the DPLL. + */ + crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y); + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->mode_set(output, mode, adjusted_mode); + } + + /* Only upload when needed, to avoid unneeded delays. */ + if (!crtc->active && crtc->funcs->gamma_set) + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); + + /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ + crtc->funcs->commit(crtc); + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->commit(output); + } + + ret = TRUE; + +done: + if (ret) { + crtc->active = TRUE; + if (scrn->pScreen) + xf86CrtcSetScreenSubpixelOrder (scrn->pScreen); + if (scrn->ModeSet) + scrn->ModeSet(scrn); + } else { + crtc->x = saved_x; + crtc->y = saved_y; + crtc->rotation = saved_rotation; + crtc->mode = saved_mode; + if (saved_transform_present) + RRTransformCopy (&crtc->transform, &saved_transform); + crtc->transformPresent = saved_transform_present; + } + + free(adjusted_mode->name); + free(adjusted_mode); + + if (didLock) + crtc->funcs->unlock (crtc); + + return ret; +} + +/** + * Sets the given video mode on the given crtc, but without providing + * a transform + */ +Bool +xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y) +{ + return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y); +} + +/** + * Pans the screen, does not change the mode + */ +void +xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y) +{ + ScrnInfoPtr scrn = crtc->scrn; + + crtc->x = x; + crtc->y = y; + if (crtc->funcs->set_origin) { + if (!xf86CrtcRotate (crtc)) + return; + crtc->funcs->set_origin (crtc, x, y); + if (scrn->ModeSet) + scrn->ModeSet(scrn); + } + else + xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y); +} + +/* + * Output functions + */ + +extern XF86ConfigPtr xf86configptr; + +typedef enum { + OPTION_PREFERRED_MODE, + OPTION_POSITION, + OPTION_BELOW, + OPTION_RIGHT_OF, + OPTION_ABOVE, + OPTION_LEFT_OF, + OPTION_ENABLE, + OPTION_DISABLE, + OPTION_MIN_CLOCK, + OPTION_MAX_CLOCK, + OPTION_IGNORE, + OPTION_ROTATE, + OPTION_PANNING, + OPTION_PRIMARY, + OPTION_DEFAULT_MODES, +} OutputOpts; + +static OptionInfoRec xf86OutputOptions[] = { + {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, + {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, + {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, + {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, + {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, + {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, + {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, + {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE }, + {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_DEFAULT_MODES, "DefaultModes", OPTV_BOOLEAN, {0}, FALSE }, + {-1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +enum { + OPTION_MODEDEBUG, +}; + +static OptionInfoRec xf86DeviceOptions[] = { + {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE }, + {-1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +static void +xf86OutputSetMonitor (xf86OutputPtr output) +{ + char *option_name; + char *monitor; + + if (!output->name) + return; + + free(output->options); + + output->options = xnfalloc (sizeof (xf86OutputOptions)); + memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); + + XNFasprintf(&option_name, "monitor-%s", output->name); + monitor = xf86findOptionValue (output->scrn->options, option_name); + if (!monitor) + monitor = output->name; + else + xf86MarkOptionUsedByName (output->scrn->options, option_name); + free(option_name); + output->conf_monitor = xf86findMonitor (monitor, + xf86configptr->conf_monitor_lst); + /* + * Find the monitor section of the screen and use that + */ + if (!output->conf_monitor && output->use_screen_monitor) + output->conf_monitor = xf86findMonitor (output->scrn->monitor->id, + xf86configptr->conf_monitor_lst); + if (output->conf_monitor) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s using monitor section %s\n", + output->name, output->conf_monitor->mon_identifier); + xf86ProcessOptions (output->scrn->scrnIndex, + output->conf_monitor->mon_option_lst, + output->options); + } + else + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s has no monitor section\n", + output->name); +} + +static Bool +xf86OutputEnabled (xf86OutputPtr output, Bool strict) +{ + Bool enable, disable; + + /* check to see if this output was enabled in the config file */ + if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s enabled by config file\n", output->name); + return TRUE; + } + /* or if this output was disabled in the config file */ + if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s disabled by config file\n", output->name); + return FALSE; + } + + /* If not, try to only light up the ones we know are connected */ + if (strict) { + enable = output->status == XF86OutputStatusConnected; + } + /* But if that fails, try to light up even outputs we're unsure of */ + else { + enable = output->status != XF86OutputStatusDisconnected; + } + + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s %sconnected\n", output->name, enable ? "" : "dis"); + return enable; +} + +static Bool +xf86OutputIgnored (xf86OutputPtr output) +{ + return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE); +} + +static char *direction[4] = { + "normal", + "left", + "inverted", + "right" +}; + +static Rotation +xf86OutputInitialRotation (xf86OutputPtr output) +{ + char *rotate_name = xf86GetOptValString (output->options, + OPTION_ROTATE); + int i; + + if (!rotate_name) { + if (output->initial_rotation) + return output->initial_rotation; + return RR_Rotate_0; + } + + for (i = 0; i < 4; i++) + if (xf86nameCompare (direction[i], rotate_name) == 0) + return 1 << i; + return RR_Rotate_0; +} + +xf86OutputPtr +xf86OutputCreate (ScrnInfoPtr scrn, + const xf86OutputFuncsRec *funcs, + const char *name) +{ + xf86OutputPtr output, *outputs; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int len; + Bool primary; + + if (name) + len = strlen (name) + 1; + else + len = 0; + + output = calloc(sizeof (xf86OutputRec) + len, 1); + if (!output) + return NULL; + output->scrn = scrn; + output->funcs = funcs; + if (name) + { + output->name = (char *) (output + 1); + strcpy (output->name, name); + } + output->subpixel_order = SubPixelUnknown; + /* + * Use the old per-screen monitor section for the first output + */ + output->use_screen_monitor = (xf86_config->num_output == 0); +#ifdef RANDR_12_INTERFACE + output->randr_output = NULL; +#endif + if (name) + { + xf86OutputSetMonitor (output); + if (xf86OutputIgnored (output)) + { + free(output); + return FALSE; + } + } + + + if (xf86_config->output) + outputs = realloc(xf86_config->output, + (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + else + outputs = malloc((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + if (!outputs) + { + free(output); + return NULL; + } + + xf86_config->output = outputs; + + if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary) + { + memmove(xf86_config->output + 1, xf86_config->output, + xf86_config->num_output * sizeof (xf86OutputPtr)); + xf86_config->output[0] = output; + } + else + { + xf86_config->output[xf86_config->num_output] = output; + } + + xf86_config->num_output++; + + return output; +} + +Bool +xf86OutputRename (xf86OutputPtr output, const char *name) +{ + char *newname = strdup(name); + + if (!newname) + return FALSE; /* so sorry... */ + + if (output->name && output->name != (char *) (output + 1)) + free(output->name); + output->name = newname; + xf86OutputSetMonitor (output); + if (xf86OutputIgnored (output)) + return FALSE; + return TRUE; +} + +void +xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor) +{ + if (use_screen_monitor != output->use_screen_monitor) + { + output->use_screen_monitor = use_screen_monitor; + xf86OutputSetMonitor (output); + } +} + +void +xf86OutputDestroy (xf86OutputPtr output) +{ + ScrnInfoPtr scrn = output->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + (*output->funcs->destroy) (output); + while (output->probed_modes) + xf86DeleteMode (&output->probed_modes, output->probed_modes); + for (o = 0; o < xf86_config->num_output; o++) + if (xf86_config->output[o] == output) + { + memmove (&xf86_config->output[o], + &xf86_config->output[o+1], + ((xf86_config->num_output - (o + 1)) * sizeof(void*))); + xf86_config->num_output--; + break; + } + if (output->name && output->name != (char *) (output + 1)) + free(output->name); + free(output); +} + +/* + * Called during CreateScreenResources to hook up RandR + */ +static Bool +xf86CrtcCreateScreenResources (ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + screen->CreateScreenResources = config->CreateScreenResources; + + if (!(*screen->CreateScreenResources)(screen)) + return FALSE; + + if (!xf86RandR12CreateScreenResources (screen)) + return FALSE; + + return TRUE; +} + +/* + * Clean up config on server reset + */ +static Bool +xf86CrtcCloseScreen (int index, ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o, c; + + screen->CloseScreen = config->CloseScreen; + + xf86RotateCloseScreen (screen); + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->randr_output = NULL; + } + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->randr_crtc = NULL; + } + xf86RandR12CloseScreen (screen); + + return screen->CloseScreen (index, screen); +} + +/* + * Called at ScreenInit time to set up + */ +#ifdef RANDR_13_INTERFACE +int +#else +Bool +#endif +xf86CrtcScreenInit (ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + /* Rotation */ + xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); + xf86DisableRandR(); /* Disable old RandR extension support */ + xf86RandR12Init (screen); + + /* support all rotations if every crtc has the shadow alloc funcs */ + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) + break; + } + if (c == config->num_crtc) + { + xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | + RR_Rotate_180 | RR_Rotate_270 | + RR_Reflect_X | RR_Reflect_Y); + xf86RandR12SetTransformSupport (screen, TRUE); + } + else + { + xf86RandR12SetRotations (screen, RR_Rotate_0); + xf86RandR12SetTransformSupport (screen, FALSE); + } + + /* Wrap CreateScreenResources so we can initialize the RandR code */ + config->CreateScreenResources = screen->CreateScreenResources; + screen->CreateScreenResources = xf86CrtcCreateScreenResources; + + config->CloseScreen = screen->CloseScreen; + screen->CloseScreen = xf86CrtcCloseScreen; + +#ifdef XFreeXDGA + _xf86_di_dga_init_internal(screen); +#endif +#ifdef RANDR_13_INTERFACE + return RANDR_INTERFACE_VERSION; +#else + return TRUE; +#endif +} + +static DisplayModePtr +xf86DefaultMode (xf86OutputPtr output, int width, int height) +{ + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + int target_preferred = 0; + int mm_height; + + mm_height = output->mm_height; + if (!mm_height) + mm_height = (768 * 25.4) / DEFAULT_DPI; + /* + * Pick a mode closest to DEFAULT_DPI + */ + for (mode = output->probed_modes; mode; mode = mode->next) + { + int dpi; + int preferred = (((mode->type & M_T_PREFERRED) != 0) + + ((mode->type & M_T_USERPREF) != 0)); + int diff; + + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + /* yes, use VDisplay here, not xf86ModeHeight */ + dpi = (mode->VDisplay * 254) / (mm_height * 10); + diff = dpi - DEFAULT_DPI; + diff = diff < 0 ? -diff : diff; + if (target_mode == NULL || (preferred > target_preferred) || + (preferred == target_preferred && diff < target_diff)) + { + target_mode = mode; + target_diff = diff; + target_preferred = preferred; + } + } + return target_mode; +} + +static DisplayModePtr +xf86ClosestMode (xf86OutputPtr output, + DisplayModePtr match, Rotation match_rotation, + int width, int height) +{ + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + + /* + * Pick a mode closest to the specified mode + */ + for (mode = output->probed_modes; mode; mode = mode->next) + { + int dx, dy; + int diff; + + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + /* exact matches are preferred */ + if (output->initial_rotation == match_rotation && + xf86ModesEqual (mode, match)) + return mode; + + dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); + dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); + diff = dx * dx + dy * dy; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } + } + return target_mode; +} + +static DisplayModePtr +xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) +{ + DisplayModePtr mode; + + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + if (mode->type & M_T_PREFERRED) + return mode; + } + return NULL; +} + +static DisplayModePtr +xf86OutputHasUserPreferredMode (xf86OutputPtr output) +{ + DisplayModePtr mode, first = output->probed_modes; + + for (mode = first; mode && mode->next != first; mode = mode->next) + if (mode->type & M_T_USERPREF) + return mode; + + return NULL; +} + +static int +xf86PickCrtcs (ScrnInfoPtr scrn, + xf86CrtcPtr *best_crtcs, + DisplayModePtr *modes, + int n, + int width, + int height) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c, o; + xf86OutputPtr output; + xf86CrtcPtr crtc; + xf86CrtcPtr *crtcs; + xf86CrtcPtr best_crtc; + int best_score; + int score; + int my_score; + + if (n == config->num_output) + return 0; + output = config->output[n]; + + /* + * Compute score with this output disabled + */ + best_crtcs[n] = NULL; + best_crtc = NULL; + best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); + if (modes[n] == NULL) + return best_score; + + crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr)); + if (!crtcs) + return best_score; + + my_score = 1; + /* Score outputs that are known to be connected higher */ + if (output->status == XF86OutputStatusConnected) + my_score++; + /* Score outputs with preferred modes higher */ + if (xf86OutputHasPreferredMode (output, width, height)) + my_score++; + /* + * Select a crtc for this output and + * then attempt to configure the remaining + * outputs + */ + for (c = 0; c < config->num_crtc; c++) + { + if ((output->possible_crtcs & (1 << c)) == 0) + continue; + + crtc = config->crtc[c]; + /* + * Check to see if some other output is + * using this crtc + */ + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + if (o < n) + { + /* + * If the two outputs desire the same mode, + * see if they can be cloned + */ + if (xf86ModesEqual (modes[o], modes[n]) && + config->output[o]->initial_rotation == config->output[n]->initial_rotation && + config->output[o]->initial_x == config->output[n]->initial_x && + config->output[o]->initial_y == config->output[n]->initial_y) + { + if ((output->possible_clones & (1 << o)) == 0) + continue; /* nope, try next CRTC */ + } + else + continue; /* different modes, can't clone */ + } + crtcs[n] = crtc; + memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); + score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); + if (score > best_score) + { + best_crtc = crtc; + best_score = score; + memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); + } + } + free(crtcs); + return best_score; +} + + +/* + * Compute the virtual size necessary to place all of the available + * crtcs in the specified configuration. + * + * canGrow indicates that the driver can make the screen larger than its initial + * configuration. If FALSE, this function will enlarge the screen to include + * the largest available mode. + */ + +static void +xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp, + Bool canGrow) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int width = 0, height = 0; + int o; + int c; + int s; + + for (c = 0; c < config->num_crtc; c++) + { + int crtc_width = 0, crtc_height = 0; + xf86CrtcPtr crtc = config->crtc[c]; + + if (crtc->enabled) + { + crtc_width = crtc->desiredX + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation); + crtc_height = crtc->desiredY + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation); + } + if (!canGrow) { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + for (s = 0; s < config->num_crtc; s++) + if (output->possible_crtcs & (1 << s)) + { + DisplayModePtr mode; + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (mode->HDisplay > crtc_width) + crtc_width = mode->HDisplay; + if (mode->VDisplay > crtc_width) + crtc_width = mode->VDisplay; + if (mode->VDisplay > crtc_height) + crtc_height = mode->VDisplay; + if (mode->HDisplay > crtc_height) + crtc_height = mode->HDisplay; + } + } + } + } + if (crtc_width > width) + width = crtc_width; + if (crtc_height > height) + height = crtc_height; + } + if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; + if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; + if (config->minWidth && width < config->minWidth) width = config->minWidth; + if (config->minHeight && height < config->minHeight) height = config->minHeight; + *widthp = width; + *heightp = height; +} + +#define POSITION_UNSET -100000 + +/* + * check if the user configured any outputs at all + * with either a position or a relative setting or a mode. + */ +static Bool +xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + Bool user_conf = FALSE; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + char *position; + char *relative_name; + OutputOpts relation; + int r; + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + + position = xf86GetOptValString (output->options, + OPTION_POSITION); + if (position) + user_conf = TRUE; + + relation = 0; + relative_name = NULL; + for (r = 0; r < 4; r++) + { + relation = relations[r]; + relative_name = xf86GetOptValString (output->options, + relation); + if (relative_name) + break; + } + if (relative_name) + user_conf = TRUE; + + modes[o] = xf86OutputHasUserPreferredMode(output); + if (modes[o]) + user_conf = TRUE; + } + + return user_conf; +} + +static Bool +xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + int min_x, min_y; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x = output->initial_y = POSITION_UNSET; + } + + /* + * Loop until all outputs are set + */ + for (;;) + { + Bool any_set = FALSE; + Bool keep_going = FALSE; + + for (o = 0; o < config->num_output; o++) + { + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + xf86OutputPtr output = config->output[o]; + xf86OutputPtr relative; + char *relative_name; + char *position; + OutputOpts relation; + int r; + + if (output->initial_x != POSITION_UNSET) + continue; + position = xf86GetOptValString (output->options, + OPTION_POSITION); + /* + * Absolute position wins + */ + if (position) + { + int x, y; + if (sscanf (position, "%d %d", &x, &y) == 2) + { + output->initial_x = x; + output->initial_y = y; + } + else + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output %s position not of form \"x y\"\n", + output->name); + output->initial_x = output->initial_y = 0; + } + any_set = TRUE; + continue; + } + /* + * Next comes relative positions + */ + relation = 0; + relative_name = NULL; + for (r = 0; r < 4; r++) + { + relation = relations[r]; + relative_name = xf86GetOptValString (output->options, + relation); + if (relative_name) + break; + } + if (relative_name) + { + int or; + relative = NULL; + for (or = 0; or < config->num_output; or++) + { + xf86OutputPtr out_rel = config->output[or]; + XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; + + if (rel_mon) + { + if (xf86nameCompare (rel_mon->mon_identifier, + relative_name) == 0) + { + relative = config->output[or]; + break; + } + } + if (strcmp (out_rel->name, relative_name) == 0) + { + relative = config->output[or]; + break; + } + } + if (!relative) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Cannot position output %s relative to unknown output %s\n", + output->name, relative_name); + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + continue; + } + if (!modes[or]) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Cannot position output %s relative to output %s without modes\n", + output->name, relative_name); + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + continue; + } + if (relative->initial_x == POSITION_UNSET) + { + keep_going = TRUE; + continue; + } + output->initial_x = relative->initial_x; + output->initial_y = relative->initial_y; + switch (relation) { + case OPTION_BELOW: + output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation); + break; + case OPTION_RIGHT_OF: + output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); + break; + case OPTION_ABOVE: + if (modes[o]) + output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation); + break; + case OPTION_LEFT_OF: + if (modes[o]) + output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation); + break; + default: + break; + } + any_set = TRUE; + continue; + } + + /* Nothing set, just stick them at 0,0 */ + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + } + if (!keep_going) + break; + if (!any_set) + { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + if (output->initial_x == POSITION_UNSET) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output position loop. Moving %s to 0,0\n", + output->name); + output->initial_x = output->initial_y = 0; + break; + } + } + } + } + + /* + * normalize positions + */ + min_x = 1000000; + min_y = 1000000; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->initial_x < min_x) + min_x = output->initial_x; + if (output->initial_y < min_y) + min_y = output->initial_y; + } + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x -= min_x; + output->initial_y -= min_y; + } + return TRUE; +} + +static void +xf86InitialPanning (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + char *panning = xf86GetOptValString (output->options, OPTION_PANNING); + int width, height, left, top; + int track_width, track_height, track_left, track_top; + int brdr[4]; + + memset (&output->initialTotalArea, 0, sizeof(BoxRec)); + memset (&output->initialTrackingArea, 0, sizeof(BoxRec)); + memset (output->initialBorder, 0, 4*sizeof(INT16)); + + if (! panning) + continue; + + switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", + &width, &height, &left, &top, + &track_width, &track_height, &track_left, &track_top, + &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { + case 12: + output->initialBorder[0] = brdr[0]; + output->initialBorder[1] = brdr[1]; + output->initialBorder[2] = brdr[2]; + output->initialBorder[3] = brdr[3]; + /* fall through */ + case 8: + output->initialTrackingArea.x1 = track_left; + output->initialTrackingArea.y1 = track_top; + output->initialTrackingArea.x2 = track_left + track_width; + output->initialTrackingArea.y2 = track_top + track_height; + /* fall through */ + case 4: + output->initialTotalArea.x1 = left; + output->initialTotalArea.y1 = top; + /* fall through */ + case 2: + output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; + output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; + break; + default: + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Broken panning specification '%s' for output %s in config file\n", + panning, output->name); + } + } +} + +/** Return - 0 + if a should be earlier, same or later than b in list + */ +static int +xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) +{ + int diff; + + diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); + if (diff) + return diff; + diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; + if (diff) + return diff; + diff = b->Clock - a->Clock; + return diff; +} + +/** + * Insertion sort input in-place and return the resulting head + */ +static DisplayModePtr +xf86SortModes (DisplayModePtr input) +{ + DisplayModePtr output = NULL, i, o, n, *op, prev; + + /* sort by preferred status and pixel area */ + while (input) + { + i = input; + input = input->next; + for (op = &output; (o = *op); op = &o->next) + if (xf86ModeCompare (o, i) > 0) + break; + i->next = *op; + *op = i; + } + /* prune identical modes */ + for (o = output; o && (n = o->next); o = n) + { + if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) + { + o->next = n->next; + free(n->name); + free(n); + n = o; + } + } + /* hook up backward links */ + prev = NULL; + for (o = output; o; o = o->next) + { + o->prev = prev; + prev = o; + } + return output; +} + +static char * +preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + char *preferred_mode = NULL; + + /* Check for a configured preference for a particular mode */ + preferred_mode = xf86GetOptValString (output->options, + OPTION_PREFERRED_MODE); + if (preferred_mode) + return preferred_mode; + + if (pScrn->display->modes && *pScrn->display->modes) + preferred_mode = *pScrn->display->modes; + + return preferred_mode; +} + +static void +GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) +{ + if (!mon || !mode) + return; + + mon->nHsync = 1; + mon->hsync[0].lo = 1024.0; + mon->hsync[0].hi = 0.0; + + mon->nVrefresh = 1; + mon->vrefresh[0].lo = 1024.0; + mon->vrefresh[0].hi = 0.0; + + while (mode) { + if (!mode->HSync) + mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal); + + if (!mode->VRefresh) + mode->VRefresh = (1000.0 * ((float) mode->Clock)) / + ((float) (mode->HTotal * mode->VTotal)); + + if (mode->HSync < mon->hsync[0].lo) + mon->hsync[0].lo = mode->HSync; + + if (mode->HSync > mon->hsync[0].hi) + mon->hsync[0].hi = mode->HSync; + + if (mode->VRefresh < mon->vrefresh[0].lo) + mon->vrefresh[0].lo = mode->VRefresh; + + if (mode->VRefresh > mon->vrefresh[0].hi) + mon->vrefresh[0].hi = mode->VRefresh; + + mode = mode->next; + } + + /* stretch out the bottom to fit 640x480@60 */ + if (mon->hsync[0].lo > 31.0) + mon->hsync[0].lo = 31.0; + if (mon->vrefresh[0].lo > 58.0) + mon->vrefresh[0].lo = 58.0; +} + +enum det_monrec_source { + sync_config, sync_edid, sync_default +}; + +struct det_monrec_parameter { + MonRec *mon_rec; + int *max_clock; + Bool set_hsync; + Bool set_vrefresh; + enum det_monrec_source *sync_source; +}; + +static void handle_detailed_monrec(struct detailed_monitor_section *det_mon, + void *data) +{ + struct det_monrec_parameter *p; + p = (struct det_monrec_parameter *)data; + + if (det_mon->type == DS_RANGES) { + struct monitor_ranges *ranges = &det_mon->section.ranges; + if (p->set_hsync && ranges->max_h) { + p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; + p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; + p->mon_rec->nHsync++; + if (*p->sync_source == sync_default) + *p->sync_source = sync_edid; + } + if (p->set_vrefresh && ranges->max_v) { + p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; + p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; + p->mon_rec->nVrefresh++; + if (*p->sync_source == sync_default) + *p->sync_source = sync_edid; + } + if (ranges->max_clock * 1000 > *p->max_clock) + *p->max_clock = ranges->max_clock * 1000; + } +} + +void +xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + /* When canGrow was TRUE in the initial configuration we have to + * compare against the maximum values so that we don't drop modes. + * When canGrow was FALSE, the maximum values would have been clamped + * anyway. + */ + if (maxX == 0 || maxY == 0) { + maxX = config->maxWidth; + maxY = config->maxHeight; + } + + /* Probe the list of modes for each output. */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode; + DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL; + char *preferred_mode; + xf86MonPtr edid_monitor; + XF86ConfMonitorPtr conf_monitor; + MonRec mon_rec; + int min_clock = 0; + int max_clock = 0; + double clock; + Bool add_default_modes; + Bool debug_modes = config->debug_modes || + xf86Initialising; + enum det_monrec_source sync_source = sync_default; + + while (output->probed_modes != NULL) + xf86DeleteMode(&output->probed_modes, output->probed_modes); + + /* + * Check connection status + */ + output->status = (*output->funcs->detect)(output); + + if (output->status == XF86OutputStatusDisconnected && + !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE)) + { + xf86OutputSetEDID (output, NULL); + continue; + } + + memset (&mon_rec, '\0', sizeof (mon_rec)); + + conf_monitor = output->conf_monitor; + + if (conf_monitor) + { + int i; + + for (i = 0; i < conf_monitor->mon_n_hsync; i++) + { + mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; + mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; + mon_rec.nHsync++; + sync_source = sync_config; + } + for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) + { + mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; + mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; + mon_rec.nVrefresh++; + sync_source = sync_config; + } + config_modes = xf86GetMonitorModes (scrn, conf_monitor); + } + + output_modes = (*output->funcs->get_modes) (output); + + /* + * If the user has a preference, respect it. + * Otherwise, don't second-guess the driver. + */ + if (!xf86GetOptValBool(output->options, OPTION_DEFAULT_MODES, + &add_default_modes)) + add_default_modes = (output_modes == NULL); + + edid_monitor = output->MonInfo; + + if (edid_monitor) + { + struct det_monrec_parameter p; + struct disp_features *features = &edid_monitor->features; + + /* if display is not continuous-frequency, don't add default modes */ + if (!GTF_SUPPORTED(features->msc)) + add_default_modes = FALSE; + + p.mon_rec = &mon_rec; + p.max_clock = &max_clock; + p.set_hsync = mon_rec.nHsync == 0; + p.set_vrefresh = mon_rec.nVrefresh == 0; + p.sync_source = &sync_source; + + xf86ForEachDetailedBlock(edid_monitor, + handle_detailed_monrec, + &p); + } + + if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, + OPTUNITS_KHZ, &clock)) + min_clock = (int) clock; + if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, + OPTUNITS_KHZ, &clock)) + max_clock = (int) clock; + + /* If we still don't have a sync range, guess wildly */ + if (!mon_rec.nHsync || !mon_rec.nVrefresh) + GuessRangeFromModes(&mon_rec, output_modes); + + /* + * These limits will end up setting a 1024x768@60Hz mode by default, + * which seems like a fairly good mode to use when nothing else is + * specified + */ + if (mon_rec.nHsync == 0) + { + mon_rec.hsync[0].lo = 31.0; + mon_rec.hsync[0].hi = 55.0; + mon_rec.nHsync = 1; + } + if (mon_rec.nVrefresh == 0) + { + mon_rec.vrefresh[0].lo = 58.0; + mon_rec.vrefresh[0].hi = 62.0; + mon_rec.nVrefresh = 1; + } + + if (add_default_modes) + default_modes = xf86GetDefaultModes (); + + /* + * If this is not an RB monitor, remove RB modes from the default + * pool. RB modes from the config or the monitor itself are fine. + */ + if (!mon_rec.reducedblanking) + xf86ValidateModesReducedBlanking (scrn, default_modes); + + if (sync_source == sync_config) + { + /* + * Check output and config modes against sync range from config file + */ + xf86ValidateModesSync (scrn, output_modes, &mon_rec); + xf86ValidateModesSync (scrn, config_modes, &mon_rec); + } + /* + * Check default modes against sync range + */ + xf86ValidateModesSync (scrn, default_modes, &mon_rec); + /* + * Check default modes against monitor max clock + */ + if (max_clock) { + xf86ValidateModesClocks(scrn, default_modes, + &min_clock, &max_clock, 1); + xf86ValidateModesClocks(scrn, output_modes, + &min_clock, &max_clock, 1); + } + + output->probed_modes = NULL; + output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); + + /* + * Check all modes against max size, interlace, and doublescan + */ + if (maxX && maxY) + xf86ValidateModesSize (scrn, output->probed_modes, + maxX, maxY, 0); + + { + int flags = (output->interlaceAllowed ? V_INTERLACE : 0) | + (output->doubleScanAllowed ? V_DBLSCAN : 0); + xf86ValidateModesFlags (scrn, output->probed_modes, flags); + } + + /* + * Check all modes against output + */ + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + if (mode->status == MODE_OK) + mode->status = (*output->funcs->mode_valid)(output, mode); + + xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); + + output->probed_modes = xf86SortModes (output->probed_modes); + + /* Check for a configured preference for a particular mode */ + preferred_mode = preferredMode(scrn, output); + + if (preferred_mode) + { + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (!strcmp (preferred_mode, mode->name)) + { + if (mode != output->probed_modes) + { + if (mode->prev) + mode->prev->next = mode->next; + if (mode->next) + mode->next->prev = mode->prev; + mode->next = output->probed_modes; + output->probed_modes->prev = mode; + mode->prev = NULL; + output->probed_modes = mode; + } + mode->type |= (M_T_PREFERRED|M_T_USERPREF); + break; + } + } + } + + output->initial_rotation = xf86OutputInitialRotation (output); + + if (debug_modes) { + if (output->probed_modes != NULL) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "Printing probed modes for output %s\n", + output->name); + } else { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "No remaining probed modes for output %s\n", + output->name); + } + } + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + { + /* The code to choose the best mode per pipe later on will require + * VRefresh to be set. + */ + mode->VRefresh = xf86ModeVRefresh(mode); + xf86SetModeCrtc(mode, INTERLACE_HALVE_V); + + if (debug_modes) + xf86PrintModeline(scrn->scrnIndex, mode); + } + } +} + + +/** + * Copy one of the output mode lists to the ScrnInfo record + */ + +/* XXX where does this function belong? Here? */ +void +xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y); + +static DisplayModePtr +biggestMode(DisplayModePtr a, DisplayModePtr b) +{ + int A, B; + + if (!a) + return b; + if (!b) + return a; + + A = a->HDisplay * a->VDisplay; + B = b->HDisplay * b->VDisplay; + + if (A > B) + return a; + + return b; +} + +static xf86OutputPtr +SetCompatOutput(xf86CrtcConfigPtr config) +{ + xf86OutputPtr output = NULL, test = NULL; + DisplayModePtr maxmode = NULL, testmode, mode; + int o, compat = -1, count, mincount = 0; + + /* Look for one that's definitely connected */ + for (o = 0; o < config->num_output; o++) + { + test = config->output[o]; + if (!test->crtc) + continue; + if (test->status != XF86OutputStatusConnected) + continue; + if (!test->probed_modes) + continue; + + testmode = mode = test->probed_modes; + for (count = 0; mode; mode = mode->next, count++) + testmode = biggestMode(testmode, mode); + + if (!output) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } else if (maxmode == biggestMode(maxmode, testmode)) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } else if ((maxmode->HDisplay == testmode->HDisplay) && + (maxmode->VDisplay == testmode->VDisplay) && + count <= mincount) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } + } + + /* If we didn't find one, take anything we can get */ + if (!output) + { + for (o = 0; o < config->num_output; o++) + { + test = config->output[o]; + if (!test->crtc) + continue; + if (!test->probed_modes) + continue; + + if (!output) { + output = test; + compat = o; + } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) { + output = test; + compat = o; + } + } + } + + if (compat >= 0) { + config->compat_output = compat; + } else { + /* Don't change the compat output when no valid outputs found */ + output = config->output[config->compat_output]; + } + + return output; +} + +void +xf86SetScrnInfoModes (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + DisplayModePtr last, mode = NULL; + + output = SetCompatOutput(config); + + if (!output) + return; /* punt */ + + crtc = output->crtc; + + /* Clear any existing modes from scrn->modes */ + while (scrn->modes != NULL) + xf86DeleteMode(&scrn->modes, scrn->modes); + + /* Set scrn->modes to the mode list for the 'compat' output */ + scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); + + if (crtc) { + for (mode = scrn->modes; mode; mode = mode->next) + if (xf86ModesEqual (mode, &crtc->desiredMode)) + break; + } + + if (scrn->modes != NULL) { + /* For some reason, scrn->modes is circular, unlike the other mode + * lists. How great is that? + */ + for (last = scrn->modes; last && last->next; last = last->next) + ; + last->next = scrn->modes; + scrn->modes->prev = last; + if (mode) { + while (scrn->modes != mode) + scrn->modes = scrn->modes->next; + } + } + scrn->currentMode = scrn->modes; +#ifdef XFreeXDGA + if (scrn->pScreen) + _xf86_di_dga_reinit_internal(scrn->pScreen); +#endif +} + +static Bool +xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + Bool *enabled) +{ + Bool any_enabled = FALSE; + int o; + + for (o = 0; o < config->num_output; o++) + any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE); + + if (!any_enabled) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "No outputs definitely connected, trying again...\n"); + + for (o = 0; o < config->num_output; o++) + any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], FALSE); + } + + return any_enabled; +} + +static Bool +nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) +{ + int o = *index; + + for (o++; o < config->num_output; o++) { + if (enabled[o]) { + *index = o; + return TRUE; + } + } + + return FALSE; +} + +static Bool +aspectMatch(float a, float b) +{ + return fabs(1 - (a / b)) < 0.05; +} + +static DisplayModePtr +nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) +{ + DisplayModePtr m = NULL; + + if (!o) + return NULL; + + if (!last) + m = o->probed_modes; + else + m = last->next; + + for (; m; m = m->next) + if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) + return m; + + return NULL; +} + +static DisplayModePtr +bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) +{ + int o = -1, p; + DisplayModePtr mode = NULL, test = NULL, match = NULL; + + if (!nextEnabledOutput(config, enabled, &o)) + return NULL; + while ((mode = nextAspectMode(config->output[o], mode, aspect))) { + test = mode; + for (p = o; nextEnabledOutput(config, enabled, &p); ) { + test = xf86OutputFindClosestMode(config->output[p], mode); + if (!test) + break; + if (test->HDisplay != mode->HDisplay || + test->VDisplay != mode->VDisplay) { + test = NULL; + break; + } + } + + /* if we didn't match it on all outputs, try the next one */ + if (!test) + continue; + + /* if it's bigger than the last one, save it */ + if (!match || (test->HDisplay > match->HDisplay)) + match = test; + } + + /* return the biggest one found */ + return match; +} + +static Bool +xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o, p; + int max_pref_width = 0, max_pref_height = 0; + DisplayModePtr *preferred, *preferred_match; + Bool ret = FALSE; + + preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); + preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); + + /* Check if the preferred mode is available on all outputs */ + for (p = -1; nextEnabledOutput(config, enabled, &p); ) { + Rotation r = config->output[p]->initial_rotation; + DisplayModePtr mode; + if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p], + width, height))) { + int pref_width = xf86ModeWidth(preferred[p], r); + int pref_height = xf86ModeHeight(preferred[p], r); + Bool all_match = TRUE; + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + Bool match = FALSE; + xf86OutputPtr output = config->output[o]; + if (o == p) + continue; + + for (mode = output->probed_modes; mode; mode = mode->next) { + Rotation r = output->initial_rotation; + if (xf86ModeWidth(mode, r) == pref_width && + xf86ModeHeight(mode, r) == pref_height) { + preferred[o] = mode; + match = TRUE; + } + } + + all_match &= match; + } + + if (all_match && + (pref_width*pref_height > max_pref_width*max_pref_height)) { + for (o = -1; nextEnabledOutput(config, enabled, &o); ) + preferred_match[o] = preferred[o]; + max_pref_width = pref_width; + max_pref_height = pref_height; + ret = TRUE; + } + } + } + + /* + * If there's no preferred mode, but only one monitor, pick the + * biggest mode for its aspect ratio, assuming one exists. + */ + if (!ret) do { + int i = 0; + float aspect = 0.0; + + /* count the number of enabled outputs */ + for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; + + if (i != 1) + break; + + p = -1; + nextEnabledOutput(config, enabled, &p); + if (config->output[p]->mm_height) + aspect = (float)config->output[p]->mm_width / + (float)config->output[p]->mm_height; + + if (aspect) + preferred_match[p] = bestModeForAspect(config, enabled, aspect); + + if (preferred_match[p]) + ret = TRUE; + + } while (0); + + if (ret) { + /* oh good, there is a match. stash the selected modes and return. */ + memcpy(modes, preferred_match, + config->num_output * sizeof(DisplayModePtr)); + } + + free(preferred); + free(preferred_match); + return ret; +} + +static Bool +xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o; + float aspect = 0.0, *aspects; + xf86OutputPtr output; + Bool ret = FALSE; + DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL; + + aspects = xnfcalloc(config->num_output, sizeof(float)); + + /* collect the aspect ratios */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + output = config->output[o]; + if (output->mm_height) + aspects[o] = (float)output->mm_width / (float)output->mm_height; + else + aspects[o] = 4.0 / 3.0; + } + + /* check that they're all the same */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + output = config->output[o]; + if (!aspect) { + aspect = aspects[o]; + } else if (!aspectMatch(aspect, aspects[o])) { + goto no_aspect_match; + } + } + + /* if they're all 4:3, just skip ahead and save effort */ + if (!aspectMatch(aspect, 4.0/3.0)) + aspect_guess = bestModeForAspect(config, enabled, aspect); + +no_aspect_match: + base_guess = bestModeForAspect(config, enabled, 4.0/3.0); + + guess = biggestMode(base_guess, aspect_guess); + + if (!guess) + goto out; + + /* found a mode that works everywhere, now apply it */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + modes[o] = xf86OutputFindClosestMode(config->output[o], guess); + } + ret = TRUE; + +out: + free(aspects); + return ret; +} + +static Bool +xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + DisplayModePtr target_mode = NULL; + Rotation target_rotation = RR_Rotate_0; + DisplayModePtr default_mode; + int default_preferred, target_preferred = 0, o; + + /* User preferred > preferred > other modes */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + default_mode = xf86DefaultMode (config->output[o], width, height); + if (!default_mode) + continue; + + default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) + + ((default_mode->type & M_T_USERPREF) != 0)); + + if (default_preferred > target_preferred || !target_mode) { + target_mode = default_mode; + target_preferred = default_preferred; + target_rotation = config->output[o]->initial_rotation; + config->compat_output = o; + } + } + + if (target_mode) + modes[config->compat_output] = target_mode; + + /* Fill in other output modes */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + if (!modes[o]) + modes[o] = xf86ClosestMode(config->output[o], target_mode, + target_rotation, width, height); + } + + return target_mode != NULL; +} + +static Bool +xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o; + + if (xf86UserConfiguredOutputs(scrn, modes)) + return xf86TargetFallback(scrn, config, modes, enabled, width, height); + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) + if (xf86OutputHasUserPreferredMode(config->output[o])) + return + xf86TargetFallback(scrn, config, modes, enabled, width, height); + + return FALSE; +} + +static Bool +xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, + float gamma_blue) +{ + int i, size = 256; + CARD16 *red, *green, *blue; + + red = malloc(3 * size * sizeof(CARD16)); + green = red + size; + blue = green + size; + + /* Only cause warning if user wanted gamma to be set. */ + if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { + free(red); + return FALSE; + } else if (!crtc->funcs->gamma_set) { + free(red); + return TRUE; + } + + /* At this early stage none of the randr-interface stuff is up. + * So take the default gamma size for lack of something better. + */ + for (i = 0; i < size; i++) { + if (gamma_red == 1.0) + red[i] = i << 8; + else + red[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_red) * (double)(size - 1) * 256); + + if (gamma_green == 1.0) + green[i] = i << 8; + else + green[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_green) * (double)(size - 1) * 256); + + if (gamma_blue == 1.0) + blue[i] = i << 8; + else + blue[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_blue) * (double)(size - 1) * 256); + } + + /* Default size is 256, so anything else is failure. */ + if (size != crtc->gamma_size) { + free(red); + return FALSE; + } + + crtc->gamma_size = size; + memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16)); + + /* Do not set gamma now, delay until the crtc is activated. */ + + free(red); + + return TRUE; +} + +static Bool +xf86OutputSetInitialGamma(xf86OutputPtr output) +{ + XF86ConfMonitorPtr mon = output->conf_monitor; + float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; + + if (!mon) + return TRUE; + + if (!output->crtc) + return FALSE; + + /* Get configured values, where they exist. */ + if (mon->mon_gamma_red >= GAMMA_MIN && + mon->mon_gamma_red <= GAMMA_MAX) + gamma_red = mon->mon_gamma_red; + + if (mon->mon_gamma_green >= GAMMA_MIN && + mon->mon_gamma_green <= GAMMA_MAX) + gamma_green = mon->mon_gamma_green; + + if (mon->mon_gamma_blue >= GAMMA_MIN && + mon->mon_gamma_blue <= GAMMA_MAX) + gamma_blue = mon->mon_gamma_blue; + + /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ + if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { + xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue); + return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue); + }else + return TRUE; +} + +/** + * Construct default screen configuration + * + * Given auto-detected (and, eventually, configured) values, + * construct a usable configuration for the system + * + * canGrow indicates that the driver can resize the screen to larger than its + * initially configured size via the config->funcs->resize hook. If TRUE, this + * function will set virtualX and virtualY to match the initial configuration + * and leave config->max{Width,Height} alone. If FALSE, it will bloat + * virtual[XY] to include the largest modes and set config->max{Width,Height} + * accordingly. + */ + +Bool +xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o, c; + xf86CrtcPtr *crtcs; + DisplayModePtr *modes; + Bool *enabled; + int width, height; + int i = scrn->scrnIndex; + Bool have_outputs = TRUE; + Bool ret; + Bool success = FALSE; + + /* Set up the device options */ + config->options = xnfalloc (sizeof (xf86DeviceOptions)); + memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions)); + xf86ProcessOptions (scrn->scrnIndex, + scrn->options, + config->options); + config->debug_modes = xf86ReturnOptValBool (config->options, + OPTION_MODEDEBUG, FALSE); + + if (scrn->display->virtualX) + width = scrn->display->virtualX; + else + width = config->maxWidth; + if (scrn->display->virtualY) + height = scrn->display->virtualY; + else + height = config->maxHeight; + + xf86ProbeOutputModes (scrn, width, height); + + crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); + modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); + enabled = xnfcalloc (config->num_output, sizeof (Bool)); + + ret = xf86CollectEnabledOutputs(scrn, config, enabled); + if (ret == FALSE && canGrow) { + xf86DrvMsg(i, X_WARNING, "Unable to find connected outputs - setting %dx%d initial framebuffer\n", + NO_OUTPUT_DEFAULT_WIDTH, NO_OUTPUT_DEFAULT_HEIGHT); + have_outputs = FALSE; + } else { + if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); + else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); + else if (xf86TargetAspect(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n"); + else if (xf86TargetFallback(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n"); + else + xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n"); + } + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + if (!modes[o]) + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output %s enabled but has no modes\n", + config->output[o]->name); + else + xf86DrvMsg (scrn->scrnIndex, X_INFO, + "Output %s using initial mode %s\n", + config->output[o]->name, modes[o]->name); + } + + /* + * Set the position of each output + */ + if (!xf86InitialOutputPositions (scrn, modes)) + goto bailout; + + /* + * Set initial panning of each output + */ + xf86InitialPanning (scrn); + + /* + * Assign CRTCs to fit output configuration + */ + if (have_outputs && !xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) + goto bailout; + + /* XXX override xf86 common frame computation code */ + + scrn->display->frameX0 = 0; + scrn->display->frameY0 = 0; + + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->enabled = FALSE; + memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); + /* Set default gamma for all crtc's. */ + /* This is done to avoid problems later on with cloned outputs. */ + xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); + } + + if (xf86_crtc_supports_gamma(scrn)) + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n"); + + /* + * Set initial configuration + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode = modes[o]; + xf86CrtcPtr crtc = crtcs[o]; + + if (mode && crtc) + { + crtc->desiredMode = *mode; + crtc->desiredRotation = output->initial_rotation; + crtc->desiredX = output->initial_x; + crtc->desiredY = output->initial_y; + crtc->desiredTransformPresent = FALSE; + crtc->enabled = TRUE; + memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec)); + memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec)); + memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16)); + output->crtc = crtc; + if (!xf86OutputSetInitialGamma(output)) + xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name); + } else { + output->crtc = NULL; + } + } + + if (scrn->display->virtualX == 0) + { + /* + * Expand virtual size to cover the current config and potential mode + * switches, if the driver can't enlarge the screen later. + */ + xf86DefaultScreenLimits (scrn, &width, &height, canGrow); + + if (have_outputs == FALSE) { + if (width < NO_OUTPUT_DEFAULT_WIDTH && height < NO_OUTPUT_DEFAULT_HEIGHT) { + width = NO_OUTPUT_DEFAULT_WIDTH; + height = NO_OUTPUT_DEFAULT_HEIGHT; + } + } + + scrn->display->virtualX = width; + scrn->display->virtualY = height; + } + + if (width > scrn->virtualX) + scrn->virtualX = width; + if (height > scrn->virtualY) + scrn->virtualY = height; + + /* + * Make sure the configuration isn't too small. + */ + if (width < config->minWidth || height < config->minHeight) + goto bailout; + + /* + * Limit the crtc config to virtual[XY] if the driver can't grow the + * desktop. + */ + if (!canGrow) + { + xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight, + width, height); + } + + if (have_outputs) { + /* Mirror output modes to scrn mode list */ + xf86SetScrnInfoModes (scrn); + } else { + /* Clear any existing modes from scrn->modes */ + while (scrn->modes != NULL) + xf86DeleteMode(&scrn->modes, scrn->modes); + scrn->modes = xf86ModesAdd(scrn->modes, + xf86CVTMode(width, height, 60, 0, 0)); + } + + success = TRUE; + bailout: + free(crtcs); + free(modes); + free(enabled); + return success; +} + +/* + * Check the CRTC we're going to map each output to vs. it's current + * CRTC. If they don't match, we have to disable the output and the CRTC + * since the driver will have to re-route things. + */ +static void +xf86PrepareOutputs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr output = config->output[o]; +#if RANDR_GET_CRTC_INTERFACE + /* Disable outputs that are unused or will be re-routed */ + if (!output->funcs->get_crtc || + output->crtc != (*output->funcs->get_crtc)(output) || + output->crtc == NULL) +#endif + (*output->funcs->dpms)(output, DPMSModeOff); + } +} + +static void +xf86PrepareCrtcs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + for (c = 0; c < config->num_crtc; c++) { +#if RANDR_GET_CRTC_INTERFACE + xf86CrtcPtr crtc = config->crtc[c]; + xf86OutputPtr output = NULL; + uint32_t desired_outputs = 0, current_outputs = 0; + int o; + + for (o = 0; o < config->num_output; o++) { + output = config->output[o]; + if (output->crtc == crtc) + desired_outputs |= (1<funcs->get_crtc) { + desired_outputs = 0; + break; + } + if ((*output->funcs->get_crtc)(output) == crtc) + current_outputs |= (1<funcs->dpms)(crtc, DPMSModeOff); +#else + (*crtc->funcs->dpms)(crtc, DPMSModeOff); +#endif + } +} + +/* + * Using the desired mode information in each crtc, set + * modes (used in EnterVT functions, or at server startup) + */ + +Bool +xf86SetDesiredModes (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc = config->crtc[0]; + int c; + + /* A driver with this hook will take care of this */ + if (!crtc->funcs->set_mode_major) { + xf86PrepareOutputs(scrn); + xf86PrepareCrtcs(scrn); + } + + for (c = 0; c < config->num_crtc; c++) + { + xf86OutputPtr output = NULL; + int o; + RRTransformPtr transform; + + crtc = config->crtc[c]; + + /* Skip disabled CRTCs */ + if (!crtc->enabled) + continue; + + if (xf86CompatOutput(scrn) && xf86CompatCrtc(scrn) == crtc) + output = xf86CompatOutput(scrn); + else + { + for (o = 0; o < config->num_output; o++) + if (config->output[o]->crtc == crtc) + { + output = config->output[o]; + break; + } + } + /* paranoia */ + if (!output) + continue; + + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desiredMode.CrtcHDisplay) + { + DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode); + + if (!mode) + return FALSE; + crtc->desiredMode = *mode; + crtc->desiredRotation = RR_Rotate_0; + crtc->desiredTransformPresent = FALSE; + crtc->desiredX = 0; + crtc->desiredY = 0; + } + + if (crtc->desiredTransformPresent) + transform = &crtc->desiredTransform; + else + transform = NULL; + if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation, + transform, crtc->desiredX, crtc->desiredY)) + return FALSE; + } + + xf86DisableUnusedFunctions(scrn); + return TRUE; +} + +/** + * In the current world order, there are lists of modes per output, which may + * or may not include the mode that was asked to be set by XFree86's mode + * selection. Find the closest one, in the following preference order: + * + * - Equality + * - Closer in size to the requested mode, but no larger + * - Closer in refresh rate to the requested mode. + */ + +DisplayModePtr +xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired) +{ + DisplayModePtr best = NULL, scan = NULL; + + for (scan = output->probed_modes; scan != NULL; scan = scan->next) + { + /* If there's an exact match, we're done. */ + if (xf86ModesEqual(scan, desired)) { + best = desired; + break; + } + + /* Reject if it's larger than the desired mode. */ + if (scan->HDisplay > desired->HDisplay || + scan->VDisplay > desired->VDisplay) + { + continue; + } + + /* + * If we haven't picked a best mode yet, use the first + * one in the size range + */ + if (best == NULL) + { + best = scan; + continue; + } + + /* Find if it's closer to the right size than the current best + * option. + */ + if ((scan->HDisplay > best->HDisplay && + scan->VDisplay >= best->VDisplay) || + (scan->HDisplay >= best->HDisplay && + scan->VDisplay > best->VDisplay)) + { + best = scan; + continue; + } + + /* Find if it's still closer to the right refresh than the current + * best resolution. + */ + if (scan->HDisplay == best->HDisplay && + scan->VDisplay == best->VDisplay && + (fabs(scan->VRefresh - desired->VRefresh) < + fabs(best->VRefresh - desired->VRefresh))) { + best = scan; + } + } + return best; +} + +/** + * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, + * take the specified mode and apply it to the crtc connected to the compat + * output. Then, find similar modes for the other outputs, as with the + * InitialConfiguration code above. The goal is to clone the desired + * mode across all outputs that are currently active. + */ + +Bool +xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + Bool ok = TRUE; + xf86OutputPtr compat_output; + DisplayModePtr compat_mode = NULL; + int c; + + /* + * Let the compat output drive the final mode selection + */ + compat_output = xf86CompatOutput(pScrn); + if (compat_output) + compat_mode = xf86OutputFindClosestMode (compat_output, desired); + if (compat_mode) + desired = compat_mode; + + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + DisplayModePtr crtc_mode = NULL; + int o; + + if (!crtc->enabled) + continue; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr output_mode; + + /* skip outputs not on this crtc */ + if (output->crtc != crtc) + continue; + + if (crtc_mode) + { + output_mode = xf86OutputFindClosestMode (output, crtc_mode); + if (output_mode != crtc_mode) + output->crtc = NULL; + } + else + crtc_mode = xf86OutputFindClosestMode (output, desired); + } + if (!crtc_mode) + { + crtc->enabled = FALSE; + continue; + } + if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0)) + ok = FALSE; + else + { + crtc->desiredMode = *crtc_mode; + crtc->desiredRotation = rotation; + crtc->desiredTransformPresent = FALSE; + crtc->desiredX = 0; + crtc->desiredY = 0; + } + } + xf86DisableUnusedFunctions(pScrn); +#ifdef RANDR_12_INTERFACE + xf86RandR12TellChanged (pScrn->pScreen); +#endif + return ok; +} + + +/** + * Set the DPMS power mode of all outputs and CRTCs. + * + * If the new mode is off, it will turn off outputs and then CRTCs. + * Otherwise, it will affect CRTCs before outputs. + */ +void +xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + + if (!scrn->vtSema) + return; + + if (mode == DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } + + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + if (crtc->enabled) + (*crtc->funcs->dpms) (crtc, mode); + } + + if (mode != DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } +} + +/** + * Implement the screensaver by just calling down into the driver DPMS hooks. + * + * Even for monitors with no DPMS support, by the definition of our DPMS hooks, + * the outputs will still get disabled (blanked). + */ +Bool +xf86SaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (xf86IsUnblank(mode)) + xf86DPMSSet(pScrn, DPMSModeOn, 0); + else + xf86DPMSSet(pScrn, DPMSModeOff, 0); + + return TRUE; +} + +/** + * Disable all inactive crtcs and outputs + */ +void +xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int o, c; + + for (o = 0; o < xf86_config->num_output; o++) + { + xf86OutputPtr output = xf86_config->output[o]; + if (!output->crtc) + (*output->funcs->dpms)(output, DPMSModeOff); + } + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (!crtc->enabled) + { + crtc->funcs->dpms(crtc, DPMSModeOff); + memset(&crtc->mode, 0, sizeof(crtc->mode)); + xf86RotateDestroy(crtc); + crtc->active = FALSE; + } + } + if (pScrn->pScreen) + xf86_crtc_notify(pScrn->pScreen); + if (pScrn->ModeSet) + pScrn->ModeSet(pScrn); +} + +#ifdef RANDR_12_INTERFACE + +#define EDID_ATOM_NAME "EDID" + +/** + * Set the RandR EDID property + */ +static void +xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) +{ + Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE); + + /* This may get called before the RandR resources have been created */ + if (output->randr_output == NULL) + return; + + if (data_len != 0) { + RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, + PropModeReplace, data_len, data, FALSE, TRUE); + } else { + RRDeleteOutputProperty(output->randr_output, edid_atom); + } +} + +#endif + +/* Pull out a phyiscal size from a detailed timing if available. */ +struct det_phySize_parameter { + xf86OutputPtr output; + ddc_quirk_t quirks; + Bool ret; +}; + +static void handle_detailed_physical_size(struct detailed_monitor_section + *det_mon, void *data) +{ + struct det_phySize_parameter *p; + p = (struct det_phySize_parameter *)data; + + if (p->ret == TRUE ) + return ; + + xf86DetTimingApplyQuirks(det_mon, p->quirks, + p->output->MonInfo->features.hsize, + p->output->MonInfo->features.vsize); + if (det_mon->type == DT && + det_mon->section.d_timings.h_size != 0 && + det_mon->section.d_timings.v_size != 0) { + + p->output->mm_width = det_mon->section.d_timings.h_size; + p->output->mm_height = det_mon->section.d_timings.v_size; + p->ret = TRUE; + } +} + +/** + * Set the EDID information for the specified output + */ +void +xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) +{ + ScrnInfoPtr scrn = output->scrn; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + Bool debug_modes = config->debug_modes || xf86Initialising; +#ifdef RANDR_12_INTERFACE + int size; +#endif + + free(output->MonInfo); + + output->MonInfo = edid_mon; + output->mm_width = 0; + output->mm_height = 0; + + if (debug_modes) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", + output->name); + xf86PrintEDID(edid_mon); + } + + /* Set the DDC properties for the 'compat' output */ + if (output == xf86CompatOutput(scrn)) + xf86SetDDCproperties(scrn, edid_mon); + +#ifdef RANDR_12_INTERFACE + /* Set the RandR output properties */ + size = 0; + if (edid_mon) + { + if (edid_mon->ver.version == 1) { + size = 128; + if (edid_mon->flags & EDID_COMPLETE_RAWDATA) + size += edid_mon->no_sections * 128; + } else if (edid_mon->ver.version == 2) + size = 256; + } + xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); +#endif + + if (edid_mon) { + + struct det_phySize_parameter p; + p.output = output; + p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE); + p.ret = FALSE; + xf86ForEachDetailedBlock(edid_mon, + handle_detailed_physical_size, &p); + + /* if no mm size is available from a detailed timing, check the max size field */ + if ((!output->mm_width || !output->mm_height) && + (edid_mon->features.hsize && edid_mon->features.vsize)) + { + output->mm_width = edid_mon->features.hsize * 10; + output->mm_height = edid_mon->features.vsize * 10; + } + } +} + +/** + * Return the list of modes supported by the EDID information + * stored in 'output' + */ +DisplayModePtr +xf86OutputGetEDIDModes (xf86OutputPtr output) +{ + ScrnInfoPtr scrn = output->scrn; + xf86MonPtr edid_mon = output->MonInfo; + + if (!edid_mon) + return NULL; + return xf86DDCGetModes(scrn->scrnIndex, edid_mon); +} + +/* maybe we should care about DDC1? meh. */ +xf86MonPtr +xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) +{ + ScrnInfoPtr scrn = output->scrn; + xf86MonPtr mon; + + mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE); + if (mon) + xf86DDCApplyQuirks(scrn->scrnIndex, mon); + + return mon; +} + +static char *_xf86ConnectorNames[] = { + "None", "VGA", "DVI-I", "DVI-D", + "DVI-A", "Composite", "S-Video", + "Component", "LFP", "Proprietary", + "HDMI", "DisplayPort", + }; +char * +xf86ConnectorGetName(xf86ConnectorType connector) +{ + return _xf86ConnectorNames[connector]; +} + +static void +x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) +{ + dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; + dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; + dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; + + if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; +} + +static void +x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->enabled) { + crtc_box->x1 = crtc->x; + crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); + crtc_box->y1 = crtc->y; + crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static int +xf86_crtc_box_area(BoxPtr box) +{ + return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); +} + +/* + * Return the crtc covering 'box'. If two crtcs cover a portion of + * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc + * with greater coverage + */ + +static xf86CrtcPtr +xf86_covering_crtc(ScrnInfoPtr pScrn, + BoxPtr box, + xf86CrtcPtr desired, + BoxPtr crtc_box_ret) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc, best_crtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + best_crtc = NULL; + best_coverage = 0; + crtc_box_ret->x1 = 0; + crtc_box_ret->x2 = 0; + crtc_box_ret->y1 = 0; + crtc_box_ret->y2 = 0; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + x86_crtc_box(crtc, &crtc_box); + x86_crtc_box_intersect(&cover_box, &crtc_box, box); + coverage = xf86_crtc_box_area(&cover_box); + if (coverage && crtc == desired) { + *crtc_box_ret = crtc_box; + return crtc; + } else if (coverage > best_coverage) { + *crtc_box_ret = crtc_box; + best_crtc = crtc; + best_coverage = coverage; + } + } + return best_crtc; +} + +/* + * For overlay video, compute the relevant CRTC and + * clip video to that. + * + * returning FALSE means there was a memory failure of some kind, + * not that the video shouldn't be displayed + */ + +Bool +xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, + xf86CrtcPtr *crtc_ret, + xf86CrtcPtr desired_crtc, + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height) +{ + Bool ret; + RegionRec crtc_region_local; + RegionPtr crtc_region = reg; + + if (crtc_ret) { + BoxRec crtc_box; + xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, + desired_crtc, + &crtc_box); + + if (crtc) { + RegionInit(&crtc_region_local, &crtc_box, 1); + crtc_region = &crtc_region_local; + RegionIntersect(crtc_region, crtc_region, reg); + } + *crtc_ret = crtc; + } + + ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, + crtc_region, width, height); + + if (crtc_region != reg) + RegionUninit(&crtc_region_local); + + return ret; +} + +xf86_crtc_notify_proc_ptr +xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new) +{ + if (xf86CrtcConfigPrivateIndex != -1) + { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86_crtc_notify_proc_ptr old; + + old = config->xf86_crtc_notify; + config->xf86_crtc_notify = new; + return old; + } + return NULL; +} + +void +xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) +{ + if (xf86CrtcConfigPrivateIndex != -1) + { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->xf86_crtc_notify = old; + } +} + +void +xf86_crtc_notify(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + if (config->xf86_crtc_notify) + config->xf86_crtc_notify(screen); +} + +Bool +xf86_crtc_supports_gamma(ScrnInfoPtr pScrn) +{ + if (xf86CrtcConfigPrivateIndex != -1) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc; + + /* for multiple drivers loaded we need this */ + if (!xf86_config) + return FALSE; + if (xf86_config->num_crtc == 0) + return FALSE; + crtc = xf86_config->crtc[0]; + + return crtc->funcs->gamma_set != NULL; + } + + return FALSE; +} diff --git a/xorg-server/hw/xfree86/os-support/xf86_OSlib.h b/xorg-server/hw/xfree86/os-support/xf86_OSlib.h index 147a201ee..6374ccab3 100644 --- a/xorg-server/hw/xfree86/os-support/xf86_OSlib.h +++ b/xorg-server/hw/xfree86/os-support/xf86_OSlib.h @@ -1,419 +1,414 @@ -/* - * Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany - * Copyright 1992 by David Dawes - * Copyright 1992 by Jim Tsillas - * Copyright 1992 by Rich Murphey - * Copyright 1992 by Robert Baron - * Copyright 1992 by Orest Zborowski - * Copyright 1993 by Vrije Universiteit, The Netherlands - * Copyright 1993 by David Wexelblat - * Copyright 1994, 1996 by Holger Veit - * Copyright 1997 by Takis Psarogiannakopoulos - * Copyright 1994-2003 by The XFree86 Project, 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 names of the above listed copyright holders - * not be used in advertising or publicity pertaining to distribution of - * the software without specific, written prior permission. The above listed - * copyright holders make no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS 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 ARM32 code here carries the following copyright: - * - * Copyright 1997 - * Digital Equipment Corporation. All rights reserved. - * This software is furnished under license and may be used and copied only in - * accordance with the following terms and conditions. Subject to these - * conditions, you may download, copy, install, use, modify and distribute - * this software in source and/or binary form. No title or ownership is - * transferred hereby. - * - * 1) Any source code used, modified or distributed must reproduce and retain - * this copyright notice and list of conditions as they appear in the - * source file. - * - * 2) No right is granted to use any trade name, trademark, or logo of Digital - * Equipment Corporation. Neither the "Digital Equipment Corporation" - * name nor any trademark or logo of Digital Equipment Corporation may be - * used to endorse or promote products derived from this software without - * the prior written permission of Digital Equipment Corporation. - * - * 3) This software is provided "AS-IS" and any express or implied warranties, - * including but not limited to, any implied warranties of merchantability, - * fitness for a particular purpose, or non-infringement are disclaimed. - * In no event shall DIGITAL be liable for any damages whatsoever, and in - * particular, DIGITAL shall not be liable for special, indirect, - * consequential, or incidental damages or damages for lost profits, loss - * of revenue or loss of use, whether such damages arise in contract, - * negligence, tort, under statute, in equity, at law or otherwise, even - * if advised of the possibility of such damage. - * - */ - -/* - * This is private, and should not be included by any drivers. Drivers - * may include xf86_OSproc.h to get prototypes for public interfaces. - */ - -#ifndef _XF86_OSLIB_H -#define _XF86_OSLIB_H - -#include -#include - -#include -#include -#include - -/**************************************************************************/ -/* SYSV386 (SVR3, SVR4), including Solaris */ -/**************************************************************************/ -#if (defined(SYSV) || defined(SVR4)) && \ - (defined(sun) || defined(__i386__)) -# include -# include -# include -# include -# include - - -# include - -# if defined(_NEED_SYSI86) -# if !(defined (sun) && defined (SVR4)) -# include -# include -# endif -# include -# include -# include -# if defined(SVR4) && !defined(sun) -# include -# endif /* SVR4 && !sun */ -/* V86SC_IOPL was moved to on Solaris 7 and later */ -# if !defined(V86SC_IOPL) /* Solaris 7 or later? */ -# include /* Nope */ -# endif -# if defined(sun) && (defined (__i386__) || defined(__i386) || defined(__x86)) && defined (SVR4) -# include -# endif -# endif /* _NEED_SYSI86 */ - -# if defined(HAS_SVR3_MMAPDRV) -# include -# if !defined(_NEED_SYSI86) -# include -# include -# endif -# include /* MMAP driver header */ -# endif - -# if !defined(sun) || defined(HAVE_SYS_VT_H) -# define HAS_USL_VTS -# endif -# if !defined(sun) -# include -# endif -# if defined(HAS_USL_VTS) -# if !defined(sun) -# include -# endif -# include -# include -# endif - -# if defined(sun) -# include -# include -# include - -/* undefine symbols from we don't need that conflict with enum - definitions in parser/xf86tokens.h */ -# undef STRING -# undef LEFTALT -# undef RIGHTALT - -# define LED_CAP LED_CAPS_LOCK -# define LED_NUM LED_NUM_LOCK -# define LED_SCR LED_SCROLL_LOCK -# define LED_COMP LED_COMPOSE -# endif /* sun */ - -# if !defined(VT_ACKACQ) -# define VT_ACKACQ 2 -# endif /* !VT_ACKACQ */ - - -# if defined(SVR4) -# include -# if !(defined(sun) && defined (SVR4)) -# define DEV_MEM "/dev/pmem" -# endif -# define CLEARDTR_SUPPORT -# define POSIX_TTY -# endif /* SVR4 */ - - -# if defined(sun) && defined(HAS_USL_VTS) -# define USE_VT_SYSREQ -# endif - -#endif /* (SYSV || SVR4) */ - -/**************************************************************************/ -/* Linux or Glibc-based system */ -/**************************************************************************/ -#if defined(__linux__) || defined(__GLIBC__) -# include -# include -# include -# include -# include - -# ifdef __linux__ -# include -# else /* __GLIBC__ */ -# include -# endif -# ifdef __sparc__ -# include -# endif - -# include - -# include - -# include -# ifdef __linux__ -# define HAS_USL_VTS -# include -# include -# define LDGMAP GIO_SCRNMAP -# define LDSMAP PIO_SCRNMAP -# define LDNMAP LDSMAP -# define CLEARDTR_SUPPORT -# define USE_VT_SYSREQ -# endif - -# define POSIX_TTY - -#endif /* __linux__ || __GLIBC__ */ - -/**************************************************************************/ -/* 386BSD and derivatives, BSD/386 */ -/**************************************************************************/ - -#if defined(__386BSD__) && (defined(__FreeBSD__) || defined(__NetBSD__)) -# undef __386BSD__ -#endif - -#ifdef CSRG_BASED -# include -# include - -# include -# define termio termios -# define POSIX_TTY - -# include - -# include -# include -# include - -# if defined(__bsdi__) -# include -# if (_BSDI_VERSION < 199510) -# include -# endif -# endif /* __bsdi__ */ - -#endif /* CSRG_BASED */ - -/**************************************************************************/ -/* Kernel of *BSD */ -/**************************************************************************/ -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ - defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) - -# include -# if defined(__FreeBSD_version) && !defined(__FreeBSD_kernel_version) -# define __FreeBSD_kernel_version __FreeBSD_version -# endif - -# if !defined(LINKKIT) - /* Don't need this stuff for the Link Kit */ -# if defined(__bsdi__) -# include -# define CONSOLE_X_MODE_ON PCCONIOCRAW -# define CONSOLE_X_MODE_OFF PCCONIOCCOOK -# define CONSOLE_X_BELL PCCONIOCBEEP -# else /* __bsdi__ */ -# ifdef SYSCONS_SUPPORT -# define COMPAT_SYSCONS -# if defined(__NetBSD__) || defined(__OpenBSD__) -# include -# else -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) -# if defined(__DragonFly__) || (__FreeBSD_kernel_version >= 410000) -# include -# include -# else -# include -# endif /* FreeBSD 4.1 RELEASE or lator */ -# else -# include -# endif -# endif -# endif /* SYSCONS_SUPPORT */ -# if defined(PCVT_SUPPORT) -# if !defined(SYSCONS_SUPPORT) - /* no syscons, so include pcvt specific header file */ -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -# include -# else -# if defined(__NetBSD__) || defined(__OpenBSD__) -# if !defined(WSCONS_SUPPORT) -# include -# endif /* WSCONS_SUPPORT */ -# else -# include -# endif /* __NetBSD__ */ -# endif /* __FreeBSD_kernel__ || __OpenBSD__ */ -# else /* pcvt and syscons: hard-code the ID magic */ -# define VGAPCVTID _IOWR('V',113, struct pcvtid) - struct pcvtid { - char name[16]; - int rmajor, rminor; - }; -# endif /* PCVT_SUPPORT && SYSCONS_SUPPORT */ -# endif /* PCVT_SUPPORT */ -# ifdef WSCONS_SUPPORT -# include -# include -# endif /* WSCONS_SUPPORT */ -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) -# if defined(__FreeBSD_kernel_version) && (__FreeBSD_kernel_version >= 500013) -# include -# else -# undef MOUSE_GETINFO -# include -# endif -# endif - /* Include these definitions in case ioctl_pc.h didn't get included */ -# ifndef CONSOLE_X_MODE_ON -# define CONSOLE_X_MODE_ON _IO('t',121) -# endif -# ifndef CONSOLE_X_MODE_OFF -# define CONSOLE_X_MODE_OFF _IO('t',122) -# endif -# ifndef CONSOLE_X_BELL -# define CONSOLE_X_BELL _IOW('t',123,int[2]) -# endif -# ifndef CONSOLE_X_TV_ON -# define CONSOLE_X_TV_ON _IOW('t',155,int) -# define XMODE_RGB 0 -# define XMODE_NTSC 1 -# define XMODE_PAL 2 -# define XMODE_SECAM 3 -# endif -# ifndef CONSOLE_X_TV_OFF -# define CONSOLE_X_TV_OFF _IO('t',156) -# endif -#ifndef CONSOLE_GET_LINEAR_INFO -# define CONSOLE_GET_LINEAR_INFO _IOR('t',157,struct map_info) -#endif -#ifndef CONSOLE_GET_IO_INFO -# define CONSOLE_GET_IO_INFO _IOR('t',158,struct map_info) -#endif -#ifndef CONSOLE_GET_MEM_INFO -# define CONSOLE_GET_MEM_INFO _IOR('t',159,struct map_info) -#endif -# endif /* __bsdi__ */ -# endif /* !LINKKIT */ - -#if defined(USE_I386_IOPL) || defined(USE_AMD64_IOPL) -#include -#endif - -# define CLEARDTR_SUPPORT - -# if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) || defined(WSCONS_SUPPORT) -# define USE_VT_SYSREQ -# endif - -#endif -/* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ || __bsdi__ */ - -/**************************************************************************/ -/* IRIX */ -/**************************************************************************/ - -/**************************************************************************/ -/* Generic */ -/**************************************************************************/ - -#include /* May need to adjust this for other OSs */ - -/* - * Hack originally for ISC 2.2 POSIX headers, but may apply elsewhere, - * and it's safe, so just do it. - */ -#if !defined(O_NDELAY) && defined(O_NONBLOCK) -# define O_NDELAY O_NONBLOCK -#endif /* !O_NDELAY && O_NONBLOCK */ - -#if !defined(MAXHOSTNAMELEN) -# define MAXHOSTNAMELEN 32 -#endif /* !MAXHOSTNAMELEN */ - -#if defined(_POSIX_SOURCE) -# include -#else -# define _POSIX_SOURCE -# include -# undef _POSIX_SOURCE -#endif /* _POSIX_SOURCE */ - -#if !defined(PATH_MAX) -# if defined(MAXPATHLEN) -# define PATH_MAX MAXPATHLEN -# else -# define PATH_MAX 1024 -# endif /* MAXPATHLEN */ -#endif /* !PATH_MAX */ - - -#ifndef DEV_MEM -#define DEV_MEM "/dev/mem" -#endif - -#ifndef VT_SYSREQ_DEFAULT -#define VT_SYSREQ_DEFAULT FALSE -#endif - -#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) - -#define XF86_OS_PRIVS -#include "xf86_OSproc.h" - -#ifndef NO_COMPILER_H -#include "compiler.h" -#endif - -#endif /* _XF86_OSLIB_H */ +/* + * Copyright 1990, 1991 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1992 by David Dawes + * Copyright 1992 by Jim Tsillas + * Copyright 1992 by Rich Murphey + * Copyright 1992 by Robert Baron + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by Vrije Universiteit, The Netherlands + * Copyright 1993 by David Wexelblat + * Copyright 1994, 1996 by Holger Veit + * Copyright 1997 by Takis Psarogiannakopoulos + * Copyright 1994-2003 by The XFree86 Project, 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 names of the above listed copyright holders + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. The above listed + * copyright holders make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * THE ABOVE LISTED COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDERS 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 ARM32 code here carries the following copyright: + * + * Copyright 1997 + * Digital Equipment Corporation. All rights reserved. + * This software is furnished under license and may be used and copied only in + * accordance with the following terms and conditions. Subject to these + * conditions, you may download, copy, install, use, modify and distribute + * this software in source and/or binary form. No title or ownership is + * transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce and retain + * this copyright notice and list of conditions as they appear in the + * source file. + * + * 2) No right is granted to use any trade name, trademark, or logo of Digital + * Equipment Corporation. Neither the "Digital Equipment Corporation" + * name nor any trademark or logo of Digital Equipment Corporation may be + * used to endorse or promote products derived from this software without + * the prior written permission of Digital Equipment Corporation. + * + * 3) This software is provided "AS-IS" and any express or implied warranties, + * including but not limited to, any implied warranties of merchantability, + * fitness for a particular purpose, or non-infringement are disclaimed. + * In no event shall DIGITAL be liable for any damages whatsoever, and in + * particular, DIGITAL shall not be liable for special, indirect, + * consequential, or incidental damages or damages for lost profits, loss + * of revenue or loss of use, whether such damages arise in contract, + * negligence, tort, under statute, in equity, at law or otherwise, even + * if advised of the possibility of such damage. + * + */ + +/* + * This is private, and should not be included by any drivers. Drivers + * may include xf86_OSproc.h to get prototypes for public interfaces. + */ + +#ifndef _XF86_OSLIB_H +#define _XF86_OSLIB_H + +#include +#include + +#include +#include +#include + +/**************************************************************************/ +/* SYSV386 (SVR3, SVR4), including Solaris */ +/**************************************************************************/ +#if (defined(SYSV) || defined(SVR4)) && \ + (defined(sun) || defined(__i386__)) +# include +# include +# include +# include +# include + + +# include + +# if defined(_NEED_SYSI86) +# if !(defined (sun) && defined (SVR4)) +# include +# include +# endif +# include +# include +# include +# if defined(SVR4) && !defined(sun) +# include +# endif /* SVR4 && !sun */ +/* V86SC_IOPL was moved to on Solaris 7 and later */ +# if !defined(V86SC_IOPL) /* Solaris 7 or later? */ +# include /* Nope */ +# endif +# if defined(sun) && (defined (__i386__) || defined(__i386) || defined(__x86)) && defined (SVR4) +# include +# endif +# endif /* _NEED_SYSI86 */ + +# if defined(HAS_SVR3_MMAPDRV) +# include +# if !defined(_NEED_SYSI86) +# include +# include +# endif +# include /* MMAP driver header */ +# endif + +# if !defined(sun) || defined(HAVE_SYS_VT_H) +# define HAS_USL_VTS +# endif +# if !defined(sun) +# include +# endif +# if defined(HAS_USL_VTS) +# if !defined(sun) +# include +# endif +# include +# include +# endif + +# if defined(sun) +# include +# include +# include + +/* undefine symbols from we don't need that conflict with enum + definitions in parser/xf86tokens.h */ +# undef STRING +# undef LEFTALT +# undef RIGHTALT + +# define LED_CAP LED_CAPS_LOCK +# define LED_NUM LED_NUM_LOCK +# define LED_SCR LED_SCROLL_LOCK +# define LED_COMP LED_COMPOSE +# endif /* sun */ + +# if !defined(VT_ACKACQ) +# define VT_ACKACQ 2 +# endif /* !VT_ACKACQ */ + + +# if defined(SVR4) +# include +# if !(defined(sun) && defined (SVR4)) +# define DEV_MEM "/dev/pmem" +# endif +# define CLEARDTR_SUPPORT +# define POSIX_TTY +# endif /* SVR4 */ + + +# if defined(sun) && defined(HAS_USL_VTS) +# define USE_VT_SYSREQ +# endif + +#endif /* (SYSV || SVR4) */ + +/**************************************************************************/ +/* Linux or Glibc-based system */ +/**************************************************************************/ +#if defined(__linux__) || defined(__GLIBC__) +# include +# include +# include +# include +# include + +# ifdef __linux__ +# include +# else /* __GLIBC__ */ +# include +# endif +# ifdef __sparc__ +# include +# endif + +# include + +# include + +# include +# ifdef __linux__ +# define HAS_USL_VTS +# include +# include +# define LDGMAP GIO_SCRNMAP +# define LDSMAP PIO_SCRNMAP +# define LDNMAP LDSMAP +# define CLEARDTR_SUPPORT +# define USE_VT_SYSREQ +# endif + +# define POSIX_TTY + +#endif /* __linux__ || __GLIBC__ */ + +/**************************************************************************/ +/* 386BSD and derivatives, BSD/386 */ +/**************************************************************************/ + +#if defined(__386BSD__) && (defined(__FreeBSD__) || defined(__NetBSD__)) +# undef __386BSD__ +#endif + +#ifdef CSRG_BASED +# include +# include + +# include +# define termio termios +# define POSIX_TTY + +# include + +# include +# include +# include + +# if defined(__bsdi__) +# include +# if (_BSDI_VERSION < 199510) +# include +# endif +# endif /* __bsdi__ */ + +#endif /* CSRG_BASED */ + +/**************************************************************************/ +/* Kernel of *BSD */ +/**************************************************************************/ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ + defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) + +# include +# if defined(__FreeBSD_version) && !defined(__FreeBSD_kernel_version) +# define __FreeBSD_kernel_version __FreeBSD_version +# endif + +# if !defined(LINKKIT) + /* Don't need this stuff for the Link Kit */ +# if defined(__bsdi__) +# include +# define CONSOLE_X_MODE_ON PCCONIOCRAW +# define CONSOLE_X_MODE_OFF PCCONIOCCOOK +# define CONSOLE_X_BELL PCCONIOCBEEP +# else /* __bsdi__ */ +# ifdef SYSCONS_SUPPORT +# define COMPAT_SYSCONS +# if defined(__NetBSD__) || defined(__OpenBSD__) +# include +# else +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +# if defined(__DragonFly__) || (__FreeBSD_kernel_version >= 410000) +# include +# include +# else +# include +# endif /* FreeBSD 4.1 RELEASE or lator */ +# else +# include +# endif +# endif +# endif /* SYSCONS_SUPPORT */ +# if defined(PCVT_SUPPORT) +# if !defined(SYSCONS_SUPPORT) + /* no syscons, so include pcvt specific header file */ +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +# include +# else +# if defined(__NetBSD__) || defined(__OpenBSD__) +# if !defined(WSCONS_SUPPORT) +# include +# endif /* WSCONS_SUPPORT */ +# else +# include +# endif /* __NetBSD__ */ +# endif /* __FreeBSD_kernel__ || __OpenBSD__ */ +# else /* pcvt and syscons: hard-code the ID magic */ +# define VGAPCVTID _IOWR('V',113, struct pcvtid) + struct pcvtid { + char name[16]; + int rmajor, rminor; + }; +# endif /* PCVT_SUPPORT && SYSCONS_SUPPORT */ +# endif /* PCVT_SUPPORT */ +# ifdef WSCONS_SUPPORT +# include +# include +# endif /* WSCONS_SUPPORT */ +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +# if defined(__FreeBSD_kernel_version) && (__FreeBSD_kernel_version >= 500013) +# include +# else +# undef MOUSE_GETINFO +# include +# endif +# endif + /* Include these definitions in case ioctl_pc.h didn't get included */ +# ifndef CONSOLE_X_MODE_ON +# define CONSOLE_X_MODE_ON _IO('t',121) +# endif +# ifndef CONSOLE_X_MODE_OFF +# define CONSOLE_X_MODE_OFF _IO('t',122) +# endif +# ifndef CONSOLE_X_BELL +# define CONSOLE_X_BELL _IOW('t',123,int[2]) +# endif +# ifndef CONSOLE_X_TV_ON +# define CONSOLE_X_TV_ON _IOW('t',155,int) +# define XMODE_RGB 0 +# define XMODE_NTSC 1 +# define XMODE_PAL 2 +# define XMODE_SECAM 3 +# endif +# ifndef CONSOLE_X_TV_OFF +# define CONSOLE_X_TV_OFF _IO('t',156) +# endif +#ifndef CONSOLE_GET_LINEAR_INFO +# define CONSOLE_GET_LINEAR_INFO _IOR('t',157,struct map_info) +#endif +#ifndef CONSOLE_GET_IO_INFO +# define CONSOLE_GET_IO_INFO _IOR('t',158,struct map_info) +#endif +#ifndef CONSOLE_GET_MEM_INFO +# define CONSOLE_GET_MEM_INFO _IOR('t',159,struct map_info) +#endif +# endif /* __bsdi__ */ +# endif /* !LINKKIT */ + +#if defined(USE_I386_IOPL) || defined(USE_AMD64_IOPL) +#include +#endif + +# define CLEARDTR_SUPPORT + +# if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) || defined(WSCONS_SUPPORT) +# define USE_VT_SYSREQ +# endif + +#endif +/* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ || __bsdi__ */ + +/**************************************************************************/ +/* IRIX */ +/**************************************************************************/ + +/**************************************************************************/ +/* Generic */ +/**************************************************************************/ + +#include /* May need to adjust this for other OSs */ + +/* For PATH_MAX */ +#include "misc.h" + +/* + * Hack originally for ISC 2.2 POSIX headers, but may apply elsewhere, + * and it's safe, so just do it. + */ +#if !defined(O_NDELAY) && defined(O_NONBLOCK) +# define O_NDELAY O_NONBLOCK +#endif /* !O_NDELAY && O_NONBLOCK */ + +#if !defined(MAXHOSTNAMELEN) +# define MAXHOSTNAMELEN 32 +#endif /* !MAXHOSTNAMELEN */ + +#if defined(_POSIX_SOURCE) +# include +#else +# define _POSIX_SOURCE +# include +# undef _POSIX_SOURCE +#endif /* _POSIX_SOURCE */ + + +#ifndef DEV_MEM +#define DEV_MEM "/dev/mem" +#endif + +#ifndef VT_SYSREQ_DEFAULT +#define VT_SYSREQ_DEFAULT FALSE +#endif + +#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) + +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" + +#ifndef NO_COMPILER_H +#include "compiler.h" +#endif + +#endif /* _XF86_OSLIB_H */ diff --git a/xorg-server/hw/xfree86/parser/scan.c b/xorg-server/hw/xfree86/parser/scan.c index b829868f7..b36e58e0f 100644 --- a/xorg-server/hw/xfree86/parser/scan.c +++ b/xorg-server/hw/xfree86/parser/scan.c @@ -77,18 +77,13 @@ #undef _POSIX_SOURCE #endif /* _POSIX_SOURCE */ -#if !defined(PATH_MAX) -#if defined(MAXPATHLEN) -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif /* MAXPATHLEN */ -#endif /* !PATH_MAX */ - #if !defined(MAXHOSTNAMELEN) #define MAXHOSTNAMELEN 32 #endif /* !MAXHOSTNAMELEN */ +/* For PATH_MAX */ +#include "misc.h" + #include "Configint.h" #include "xf86tokens.h" diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h index 643866f98..ec915b37e 100644 --- a/xorg-server/include/input.h +++ b/xorg-server/include/input.h @@ -1,595 +1,593 @@ -/************************************************************ - -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. - -********************************************************/ - -#ifndef INPUT_H -#define INPUT_H - -#include "misc.h" -#include "screenint.h" -#include -#include -#include -#include "window.h" /* for WindowPtr */ -#include "xkbrules.h" -#include "events.h" - -#define DEVICE_INIT 0 -#define DEVICE_ON 1 -#define DEVICE_OFF 2 -#define DEVICE_CLOSE 3 - -#define POINTER_RELATIVE (1 << 1) -#define POINTER_ABSOLUTE (1 << 2) -#define POINTER_ACCELERATE (1 << 3) -#define POINTER_SCREEN (1 << 4) /* Data in screen coordinates */ - -/*int constants for pointer acceleration schemes*/ -#define PtrAccelNoOp 0 -#define PtrAccelPredictable 1 -#define PtrAccelLightweight 2 -#define PtrAccelDefault PtrAccelPredictable - -#define MAX_VALUATORS 36 -/* Maximum number of valuators, divided by six, rounded up, to get number - * of events. */ -#define MAX_VALUATOR_EVENTS 6 -#define MAX_BUTTONS 256 /* completely arbitrarily chosen */ - -#define NO_AXIS_LIMITS -1 - -#define MAP_LENGTH 256 -#define DOWN_LENGTH 32 /* 256/8 => number of bytes to hold 256 bits */ -#define NullGrab ((GrabPtr)NULL) -#define PointerRootWin ((WindowPtr)PointerRoot) -#define NoneWin ((WindowPtr)None) -#define NullDevice ((DevicePtr)NULL) - -#ifndef FollowKeyboard -#define FollowKeyboard 3 -#endif -#ifndef FollowKeyboardWin -#define FollowKeyboardWin ((WindowPtr) FollowKeyboard) -#endif -#ifndef RevertToFollowKeyboard -#define RevertToFollowKeyboard 3 -#endif - -typedef unsigned long Leds; -typedef struct _OtherClients *OtherClientsPtr; -typedef struct _InputClients *InputClientsPtr; -typedef struct _DeviceIntRec *DeviceIntPtr; -typedef struct _ClassesRec *ClassesPtr; -typedef struct _SpriteRec *SpritePtr; -typedef union _GrabMask GrabMask; - -typedef struct _EventList { - xEvent* event; - int evlen; /* length of allocated memory for event in bytes. This is not - the actual length of the event. The event's actual length is - 32 for standard events or 32 + - ((xGenericEvent*)event)->length * 4 for GenericEvents. - For events in the EQ, the length is - ((InternalEvent*)event)->u.any.length */ -} EventList, *EventListPtr; - -/* The DIX stores incoming input events in this list */ -extern EventListPtr InputEventList; -extern int InputEventListLen; - -typedef int (*DeviceProc)( - DeviceIntPtr /*device*/, - int /*what*/); - -typedef void (*ProcessInputProc)( - InternalEvent * /*event*/, - DeviceIntPtr /*device*/); - -typedef Bool (*DeviceHandleProc)( - DeviceIntPtr /*device*/, - void* /*data*/ - ); - -typedef void (*DeviceUnwrapProc)( - DeviceIntPtr /*device*/, - DeviceHandleProc /*proc*/, - void* /*data*/ - ); - -/* pointer acceleration handling */ -typedef void (*PointerAccelSchemeProc)( - DeviceIntPtr /*pDev*/, - int /*first_valuator*/, - int /*num_valuators*/, - int* /*valuators*/, - int /*evtime*/); - -typedef void (*DeviceCallbackProc)( - DeviceIntPtr /*pDev*/); - -struct _ValuatorAccelerationRec; -typedef Bool (*PointerAccelSchemeInitProc)( - DeviceIntPtr /*dev*/, - struct _ValuatorAccelerationRec* /*protoScheme*/); - -typedef struct _DeviceRec { - pointer devicePrivate; - ProcessInputProc processInputProc; /* current */ - ProcessInputProc realInputProc; /* deliver */ - ProcessInputProc enqueueInputProc; /* enqueue */ - Bool on; /* used by DDX to keep state */ -} DeviceRec, *DevicePtr; - -typedef struct _ValuatorMask ValuatorMask; - -typedef struct { - int click, bell, bell_pitch, bell_duration; - Bool autoRepeat; - unsigned char autoRepeats[32]; - Leds leds; - unsigned char id; -} KeybdCtrl; - -typedef struct { - KeySym *map; - KeyCode minKeyCode, - maxKeyCode; - int mapWidth; -} KeySymsRec, *KeySymsPtr; - -typedef struct { - int num, den, threshold; - unsigned char id; -} PtrCtrl; - -typedef struct { - int resolution, min_value, max_value; - int integer_displayed; - unsigned char id; -} IntegerCtrl; - -typedef struct { - int max_symbols, num_symbols_supported; - int num_symbols_displayed; - KeySym *symbols_supported; - KeySym *symbols_displayed; - unsigned char id; -} StringCtrl; - -typedef struct { - int percent, pitch, duration; - unsigned char id; -} BellCtrl; - -typedef struct { - Leds led_values; - Mask led_mask; - unsigned char id; -} LedCtrl; - -extern _X_EXPORT KeybdCtrl defaultKeyboardControl; -extern _X_EXPORT PtrCtrl defaultPointerControl; - -typedef struct _InputOption { - char *key; - char *value; - struct _InputOption *next; -} InputOption; - -typedef struct _InputAttributes { - char *product; - char *vendor; - char *device; - char *pnp_id; - char *usb_id; - char **tags; /* null-terminated */ - uint32_t flags; -} InputAttributes; - -#define ATTR_KEYBOARD (1<<0) -#define ATTR_POINTER (1<<1) -#define ATTR_JOYSTICK (1<<2) -#define ATTR_TABLET (1<<3) -#define ATTR_TOUCHPAD (1<<4) -#define ATTR_TOUCHSCREEN (1<<5) - -/* Key/Button has been run through all input processing and events sent to clients. */ -#define KEY_PROCESSED 1 -#define BUTTON_PROCESSED 1 -/* Key/Button has not been fully processed, no events have been sent. */ -#define KEY_POSTED 2 -#define BUTTON_POSTED 2 - -extern void set_key_down(DeviceIntPtr pDev, int key_code, int type); -extern void set_key_up(DeviceIntPtr pDev, int key_code, int type); -extern int key_is_down(DeviceIntPtr pDev, int key_code, int type); -extern void set_button_down(DeviceIntPtr pDev, int button, int type); -extern void set_button_up(DeviceIntPtr pDev, int button, int type); -extern int button_is_down(DeviceIntPtr pDev, int button, int type); - -extern void InitCoreDevices(void); -extern void InitXTestDevices(void); - -extern _X_EXPORT DeviceIntPtr AddInputDevice( - ClientPtr /*client*/, - DeviceProc /*deviceProc*/, - Bool /*autoStart*/); - -extern _X_EXPORT Bool EnableDevice( - DeviceIntPtr /*device*/, - BOOL /* sendevent */); - -extern _X_EXPORT Bool ActivateDevice( - DeviceIntPtr /*device*/, - BOOL /* sendevent */); - -extern _X_EXPORT Bool DisableDevice( - DeviceIntPtr /*device*/, - BOOL /* sendevent */); - -extern int InitAndStartDevices(void); - -extern void CloseDownDevices(void); - -extern void UndisplayDevices(void); - -extern _X_EXPORT int RemoveDevice( - DeviceIntPtr /*dev*/, - BOOL /* sendevent */); - -extern _X_EXPORT int NumMotionEvents(void); - -extern _X_EXPORT int dixLookupDevice( - DeviceIntPtr * /* dev */, - int /* id */, - ClientPtr /* client */, - Mask /* access_mode */); - -extern _X_EXPORT void QueryMinMaxKeyCodes( - KeyCode* /*minCode*/, - KeyCode* /*maxCode*/); - -extern _X_EXPORT Bool SetKeySymsMap( - KeySymsPtr /*dst*/, - KeySymsPtr /*src*/); - -extern _X_EXPORT Bool InitButtonClassDeviceStruct( - DeviceIntPtr /*device*/, - int /*numButtons*/, - Atom* /* labels */, - CARD8* /*map*/); - -extern _X_EXPORT Bool InitValuatorClassDeviceStruct( - DeviceIntPtr /*device*/, - int /*numAxes*/, - Atom* /* labels */, - int /*numMotionEvents*/, - int /*mode*/); - -extern _X_EXPORT Bool InitPointerAccelerationScheme( - DeviceIntPtr /*dev*/, - int /*scheme*/); - -extern _X_EXPORT Bool InitAbsoluteClassDeviceStruct( - DeviceIntPtr /*device*/); - -extern _X_EXPORT Bool InitFocusClassDeviceStruct( - DeviceIntPtr /*device*/); - -typedef void (*BellProcPtr)( - int /*percent*/, - DeviceIntPtr /*device*/, - pointer /*ctrl*/, - int); - -typedef void (*KbdCtrlProcPtr)( - DeviceIntPtr /*device*/, - KeybdCtrl * /*ctrl*/); - -typedef void (*PtrCtrlProcPtr)( - DeviceIntPtr /*device*/, - PtrCtrl * /*ctrl*/); - -extern _X_EXPORT Bool InitPtrFeedbackClassDeviceStruct( - DeviceIntPtr /*device*/, - PtrCtrlProcPtr /*controlProc*/); - -typedef void (*StringCtrlProcPtr)( - DeviceIntPtr /*device*/, - StringCtrl * /*ctrl*/); - -extern _X_EXPORT Bool InitStringFeedbackClassDeviceStruct( - DeviceIntPtr /*device*/, - StringCtrlProcPtr /*controlProc*/, - int /*max_symbols*/, - int /*num_symbols_supported*/, - KeySym* /*symbols*/); - -typedef void (*BellCtrlProcPtr)( - DeviceIntPtr /*device*/, - BellCtrl * /*ctrl*/); - -extern _X_EXPORT Bool InitBellFeedbackClassDeviceStruct( - DeviceIntPtr /*device*/, - BellProcPtr /*bellProc*/, - BellCtrlProcPtr /*controlProc*/); - -typedef void (*LedCtrlProcPtr)( - DeviceIntPtr /*device*/, - LedCtrl * /*ctrl*/); - -extern _X_EXPORT Bool InitLedFeedbackClassDeviceStruct( - DeviceIntPtr /*device*/, - LedCtrlProcPtr /*controlProc*/); - -typedef void (*IntegerCtrlProcPtr)( - DeviceIntPtr /*device*/, - IntegerCtrl * /*ctrl*/); - - -extern _X_EXPORT Bool InitIntegerFeedbackClassDeviceStruct( - DeviceIntPtr /*device*/, - IntegerCtrlProcPtr /*controlProc*/); - -extern _X_EXPORT Bool InitPointerDeviceStruct( - DevicePtr /*device*/, - CARD8* /*map*/, - int /*numButtons*/, - Atom* /* btn_labels */, - PtrCtrlProcPtr /*controlProc*/, - int /*numMotionEvents*/, - int /*numAxes*/, - Atom* /* axes_labels */); - -extern _X_EXPORT Bool InitKeyboardDeviceStruct( - DeviceIntPtr /*device*/, - XkbRMLVOSet * /*rmlvo*/, - BellProcPtr /*bellProc*/, - KbdCtrlProcPtr /*controlProc*/); - -extern int ApplyPointerMapping( - DeviceIntPtr /* pDev */, - CARD8 * /* map */, - int /* len */, - ClientPtr /* client */); - -extern Bool BadDeviceMap( - BYTE* /*buff*/, - int /*length*/, - unsigned /*low*/, - unsigned /*high*/, - XID* /*errval*/); - -extern void NoteLedState( - DeviceIntPtr /*keybd*/, - int /*led*/, - Bool /*on*/); - -extern void MaybeStopHint( - DeviceIntPtr /*device*/, - ClientPtr /*client*/); - -extern void ProcessPointerEvent( - InternalEvent* /* ev */, - DeviceIntPtr /*mouse*/); - -extern void ProcessKeyboardEvent( - InternalEvent* /*ev*/, - DeviceIntPtr /*keybd*/); - -extern Bool LegalModifier( - unsigned int /*key*/, - DeviceIntPtr /*pDev*/); - -extern _X_EXPORT void ProcessInputEvents(void); - -extern _X_EXPORT void InitInput( - int /*argc*/, - char ** /*argv*/); -extern _X_EXPORT void CloseInput(void); - -extern _X_EXPORT int GetMaximumEventsNum(void); - -extern _X_EXPORT int GetEventList(EventListPtr* list); -extern _X_EXPORT EventListPtr InitEventList(int num_events); -extern _X_EXPORT void FreeEventList(EventListPtr list, int num_events); - -extern void CreateClassesChangedEvent(EventListPtr event, - DeviceIntPtr master, - DeviceIntPtr slave, - int type); -extern EventListPtr UpdateFromMaster( - EventListPtr events, - DeviceIntPtr pDev, - int type, - int *num_events); - -extern _X_EXPORT int GetPointerEvents( - EventListPtr events, - DeviceIntPtr pDev, - int type, - int buttons, - int flags, - const ValuatorMask *mask); - -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); - -extern int GetProximityEvents( - EventListPtr events, - DeviceIntPtr pDev, - int type, - const ValuatorMask *mask); - -extern void PostSyntheticMotion( - DeviceIntPtr pDev, - int x, - int y, - int screen, - unsigned long time); - -extern _X_EXPORT int GetMotionHistorySize( - void); - -extern _X_EXPORT void AllocateMotionHistory( - DeviceIntPtr pDev); - -extern _X_EXPORT int GetMotionHistory( - DeviceIntPtr pDev, - xTimecoord **buff, - unsigned long start, - unsigned long stop, - ScreenPtr pScreen, - BOOL core); - -extern int AttachDevice(ClientPtr client, - DeviceIntPtr slave, - DeviceIntPtr master); - -extern _X_EXPORT DeviceIntPtr GetPairedDevice(DeviceIntPtr kbd); -extern DeviceIntPtr GetMaster(DeviceIntPtr dev, int type); - -extern _X_EXPORT int AllocDevicePair(ClientPtr client, - char* name, - DeviceIntPtr* ptr, - DeviceIntPtr* keybd, - DeviceProc ptr_proc, - DeviceProc keybd_proc, - Bool master); -extern void DeepCopyDeviceClasses(DeviceIntPtr from, - DeviceIntPtr to, - DeviceChangedEvent *dce); - -/* Helper functions. */ -extern _X_EXPORT int generate_modkeymap(ClientPtr client, DeviceIntPtr dev, - KeyCode **modkeymap, int *max_keys_per_mod); -extern int change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *map, - int max_keys_per_mod); -extern int AllocXTestDevice(ClientPtr client, - char* name, - DeviceIntPtr* ptr, - DeviceIntPtr* keybd, - DeviceIntPtr master_ptr, - DeviceIntPtr master_keybd); -extern BOOL IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master); -extern DeviceIntPtr GetXTestDevice(DeviceIntPtr master); -extern void SendDevicePresenceEvent(int deviceid, int type); -extern _X_EXPORT InputAttributes *DuplicateInputAttributes(InputAttributes *attrs); -extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs); - -/* misc event helpers */ -extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients); -extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event); -extern Mask GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev); -void FixUpEventFromWindow(SpritePtr pSprite, - xEvent *xE, - WindowPtr pWin, - Window child, - Bool calcChild); -extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y); -extern int EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, - WindowPtr win); -/** - * Masks specifying the type of event to deliver for an InternalEvent; used - * by EventIsDeliverable. - * @defgroup EventIsDeliverable return flags - * @{ - */ -#define EVENT_XI1_MASK (1 << 0) /**< XI1.x event */ -#define EVENT_CORE_MASK (1 << 1) /**< Core event */ -#define EVENT_DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set */ -#define EVENT_XI2_MASK (1 << 3) /**< XI2 mask set on window */ -/* @} */ - -/* Implemented by the DDX. */ -extern _X_EXPORT int NewInputDeviceRequest( - InputOption *options, - InputAttributes *attrs, - DeviceIntPtr *dev); -extern _X_EXPORT void DeleteInputDeviceRequest( - DeviceIntPtr dev); - -extern _X_EXPORT void DDXRingBell( - int volume, - int pitch, - int duration); - -#define VALUATOR_MODE_ALL_AXES -1 -extern _X_HIDDEN int valuator_get_mode(DeviceIntPtr dev, int axis); -extern _X_HIDDEN void valuator_set_mode(DeviceIntPtr dev, int axis, int mode); - -/* Set to TRUE by default - os/utils.c sets it to FALSE on user request, - xfixes/cursor.c uses it to determine if the cursor is enabled */ -extern Bool EnableCursor; - -extern _X_EXPORT ValuatorMask *valuator_mask_new(int num_valuators); -extern _X_EXPORT void valuator_mask_free(ValuatorMask **mask); -extern _X_EXPORT void valuator_mask_set_range(ValuatorMask *mask, - int first_valuator, int num_valuators, - const int* valuators); -extern _X_EXPORT void valuator_mask_set(ValuatorMask *mask, - int valuator, - int data); -extern _X_EXPORT void valuator_mask_zero(ValuatorMask *mask); -extern _X_EXPORT int valuator_mask_size(const ValuatorMask *mask); -extern _X_EXPORT int valuator_mask_isset(const ValuatorMask *mask, int bit); -extern _X_EXPORT void valuator_mask_unset(ValuatorMask *mask, int bit); -extern _X_EXPORT int valuator_mask_num_valuators(const ValuatorMask *mask); -extern _X_EXPORT void valuator_mask_copy(ValuatorMask *dest, - const ValuatorMask *src); -extern _X_EXPORT int valuator_mask_get(const ValuatorMask *mask, int valnum); - -#endif /* INPUT_H */ +/************************************************************ + +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. + +********************************************************/ + +#ifndef INPUT_H +#define INPUT_H + +#include "misc.h" +#include "screenint.h" +#include +#include +#include +#include "window.h" /* for WindowPtr */ +#include "xkbrules.h" +#include "events.h" + +#define DEVICE_INIT 0 +#define DEVICE_ON 1 +#define DEVICE_OFF 2 +#define DEVICE_CLOSE 3 + +#define POINTER_RELATIVE (1 << 1) +#define POINTER_ABSOLUTE (1 << 2) +#define POINTER_ACCELERATE (1 << 3) +#define POINTER_SCREEN (1 << 4) /* Data in screen coordinates */ + +/*int constants for pointer acceleration schemes*/ +#define PtrAccelNoOp 0 +#define PtrAccelPredictable 1 +#define PtrAccelLightweight 2 +#define PtrAccelDefault PtrAccelPredictable + +#define MAX_VALUATORS 36 +/* Maximum number of valuators, divided by six, rounded up, to get number + * of events. */ +#define MAX_VALUATOR_EVENTS 6 +#define MAX_BUTTONS 256 /* completely arbitrarily chosen */ + +#define NO_AXIS_LIMITS -1 + +#define MAP_LENGTH 256 +#define DOWN_LENGTH 32 /* 256/8 => number of bytes to hold 256 bits */ +#define NullGrab ((GrabPtr)NULL) +#define PointerRootWin ((WindowPtr)PointerRoot) +#define NoneWin ((WindowPtr)None) +#define NullDevice ((DevicePtr)NULL) + +#ifndef FollowKeyboard +#define FollowKeyboard 3 +#endif +#ifndef FollowKeyboardWin +#define FollowKeyboardWin ((WindowPtr) FollowKeyboard) +#endif +#ifndef RevertToFollowKeyboard +#define RevertToFollowKeyboard 3 +#endif + +typedef unsigned long Leds; +typedef struct _OtherClients *OtherClientsPtr; +typedef struct _InputClients *InputClientsPtr; +typedef struct _DeviceIntRec *DeviceIntPtr; +typedef struct _ClassesRec *ClassesPtr; +typedef struct _SpriteRec *SpritePtr; +typedef union _GrabMask GrabMask; + +typedef struct _ValuatorMask ValuatorMask; + +typedef struct _EventList { + xEvent* event; + int evlen; /* length of allocated memory for event in bytes. This is not + the actual length of the event. The event's actual length is + 32 for standard events or 32 + + ((xGenericEvent*)event)->length * 4 for GenericEvents. + For events in the EQ, the length is + ((InternalEvent*)event)->u.any.length */ +} EventList, *EventListPtr; + +/* The DIX stores incoming input events in this list */ +extern EventListPtr InputEventList; +extern int InputEventListLen; + +typedef int (*DeviceProc)( + DeviceIntPtr /*device*/, + int /*what*/); + +typedef void (*ProcessInputProc)( + InternalEvent * /*event*/, + DeviceIntPtr /*device*/); + +typedef Bool (*DeviceHandleProc)( + DeviceIntPtr /*device*/, + void* /*data*/ + ); + +typedef void (*DeviceUnwrapProc)( + DeviceIntPtr /*device*/, + DeviceHandleProc /*proc*/, + void* /*data*/ + ); + +/* pointer acceleration handling */ +typedef void (*PointerAccelSchemeProc)( + DeviceIntPtr /*device*/, + ValuatorMask* /*valuators*/, + CARD32 /*evtime*/); + +typedef void (*DeviceCallbackProc)( + DeviceIntPtr /*pDev*/); + +struct _ValuatorAccelerationRec; +typedef Bool (*PointerAccelSchemeInitProc)( + DeviceIntPtr /*dev*/, + struct _ValuatorAccelerationRec* /*protoScheme*/); + +typedef struct _DeviceRec { + pointer devicePrivate; + ProcessInputProc processInputProc; /* current */ + ProcessInputProc realInputProc; /* deliver */ + ProcessInputProc enqueueInputProc; /* enqueue */ + Bool on; /* used by DDX to keep state */ +} DeviceRec, *DevicePtr; + +typedef struct { + int click, bell, bell_pitch, bell_duration; + Bool autoRepeat; + unsigned char autoRepeats[32]; + Leds leds; + unsigned char id; +} KeybdCtrl; + +typedef struct { + KeySym *map; + KeyCode minKeyCode, + maxKeyCode; + int mapWidth; +} KeySymsRec, *KeySymsPtr; + +typedef struct { + int num, den, threshold; + unsigned char id; +} PtrCtrl; + +typedef struct { + int resolution, min_value, max_value; + int integer_displayed; + unsigned char id; +} IntegerCtrl; + +typedef struct { + int max_symbols, num_symbols_supported; + int num_symbols_displayed; + KeySym *symbols_supported; + KeySym *symbols_displayed; + unsigned char id; +} StringCtrl; + +typedef struct { + int percent, pitch, duration; + unsigned char id; +} BellCtrl; + +typedef struct { + Leds led_values; + Mask led_mask; + unsigned char id; +} LedCtrl; + +extern _X_EXPORT KeybdCtrl defaultKeyboardControl; +extern _X_EXPORT PtrCtrl defaultPointerControl; + +typedef struct _InputOption { + char *key; + char *value; + struct _InputOption *next; +} InputOption; + +typedef struct _InputAttributes { + char *product; + char *vendor; + char *device; + char *pnp_id; + char *usb_id; + char **tags; /* null-terminated */ + uint32_t flags; +} InputAttributes; + +#define ATTR_KEYBOARD (1<<0) +#define ATTR_POINTER (1<<1) +#define ATTR_JOYSTICK (1<<2) +#define ATTR_TABLET (1<<3) +#define ATTR_TOUCHPAD (1<<4) +#define ATTR_TOUCHSCREEN (1<<5) + +/* Key/Button has been run through all input processing and events sent to clients. */ +#define KEY_PROCESSED 1 +#define BUTTON_PROCESSED 1 +/* Key/Button has not been fully processed, no events have been sent. */ +#define KEY_POSTED 2 +#define BUTTON_POSTED 2 + +extern void set_key_down(DeviceIntPtr pDev, int key_code, int type); +extern void set_key_up(DeviceIntPtr pDev, int key_code, int type); +extern int key_is_down(DeviceIntPtr pDev, int key_code, int type); +extern void set_button_down(DeviceIntPtr pDev, int button, int type); +extern void set_button_up(DeviceIntPtr pDev, int button, int type); +extern int button_is_down(DeviceIntPtr pDev, int button, int type); + +extern void InitCoreDevices(void); +extern void InitXTestDevices(void); + +extern _X_EXPORT DeviceIntPtr AddInputDevice( + ClientPtr /*client*/, + DeviceProc /*deviceProc*/, + Bool /*autoStart*/); + +extern _X_EXPORT Bool EnableDevice( + DeviceIntPtr /*device*/, + BOOL /* sendevent */); + +extern _X_EXPORT Bool ActivateDevice( + DeviceIntPtr /*device*/, + BOOL /* sendevent */); + +extern _X_EXPORT Bool DisableDevice( + DeviceIntPtr /*device*/, + BOOL /* sendevent */); + +extern int InitAndStartDevices(void); + +extern void CloseDownDevices(void); + +extern void UndisplayDevices(void); + +extern _X_EXPORT int RemoveDevice( + DeviceIntPtr /*dev*/, + BOOL /* sendevent */); + +extern _X_EXPORT int NumMotionEvents(void); + +extern _X_EXPORT int dixLookupDevice( + DeviceIntPtr * /* dev */, + int /* id */, + ClientPtr /* client */, + Mask /* access_mode */); + +extern _X_EXPORT void QueryMinMaxKeyCodes( + KeyCode* /*minCode*/, + KeyCode* /*maxCode*/); + +extern _X_EXPORT Bool SetKeySymsMap( + KeySymsPtr /*dst*/, + KeySymsPtr /*src*/); + +extern _X_EXPORT Bool InitButtonClassDeviceStruct( + DeviceIntPtr /*device*/, + int /*numButtons*/, + Atom* /* labels */, + CARD8* /*map*/); + +extern _X_EXPORT Bool InitValuatorClassDeviceStruct( + DeviceIntPtr /*device*/, + int /*numAxes*/, + Atom* /* labels */, + int /*numMotionEvents*/, + int /*mode*/); + +extern _X_EXPORT Bool InitPointerAccelerationScheme( + DeviceIntPtr /*dev*/, + int /*scheme*/); + +extern _X_EXPORT Bool InitAbsoluteClassDeviceStruct( + DeviceIntPtr /*device*/); + +extern _X_EXPORT Bool InitFocusClassDeviceStruct( + DeviceIntPtr /*device*/); + +typedef void (*BellProcPtr)( + int /*percent*/, + DeviceIntPtr /*device*/, + pointer /*ctrl*/, + int); + +typedef void (*KbdCtrlProcPtr)( + DeviceIntPtr /*device*/, + KeybdCtrl * /*ctrl*/); + +typedef void (*PtrCtrlProcPtr)( + DeviceIntPtr /*device*/, + PtrCtrl * /*ctrl*/); + +extern _X_EXPORT Bool InitPtrFeedbackClassDeviceStruct( + DeviceIntPtr /*device*/, + PtrCtrlProcPtr /*controlProc*/); + +typedef void (*StringCtrlProcPtr)( + DeviceIntPtr /*device*/, + StringCtrl * /*ctrl*/); + +extern _X_EXPORT Bool InitStringFeedbackClassDeviceStruct( + DeviceIntPtr /*device*/, + StringCtrlProcPtr /*controlProc*/, + int /*max_symbols*/, + int /*num_symbols_supported*/, + KeySym* /*symbols*/); + +typedef void (*BellCtrlProcPtr)( + DeviceIntPtr /*device*/, + BellCtrl * /*ctrl*/); + +extern _X_EXPORT Bool InitBellFeedbackClassDeviceStruct( + DeviceIntPtr /*device*/, + BellProcPtr /*bellProc*/, + BellCtrlProcPtr /*controlProc*/); + +typedef void (*LedCtrlProcPtr)( + DeviceIntPtr /*device*/, + LedCtrl * /*ctrl*/); + +extern _X_EXPORT Bool InitLedFeedbackClassDeviceStruct( + DeviceIntPtr /*device*/, + LedCtrlProcPtr /*controlProc*/); + +typedef void (*IntegerCtrlProcPtr)( + DeviceIntPtr /*device*/, + IntegerCtrl * /*ctrl*/); + + +extern _X_EXPORT Bool InitIntegerFeedbackClassDeviceStruct( + DeviceIntPtr /*device*/, + IntegerCtrlProcPtr /*controlProc*/); + +extern _X_EXPORT Bool InitPointerDeviceStruct( + DevicePtr /*device*/, + CARD8* /*map*/, + int /*numButtons*/, + Atom* /* btn_labels */, + PtrCtrlProcPtr /*controlProc*/, + int /*numMotionEvents*/, + int /*numAxes*/, + Atom* /* axes_labels */); + +extern _X_EXPORT Bool InitKeyboardDeviceStruct( + DeviceIntPtr /*device*/, + XkbRMLVOSet * /*rmlvo*/, + BellProcPtr /*bellProc*/, + KbdCtrlProcPtr /*controlProc*/); + +extern int ApplyPointerMapping( + DeviceIntPtr /* pDev */, + CARD8 * /* map */, + int /* len */, + ClientPtr /* client */); + +extern Bool BadDeviceMap( + BYTE* /*buff*/, + int /*length*/, + unsigned /*low*/, + unsigned /*high*/, + XID* /*errval*/); + +extern void NoteLedState( + DeviceIntPtr /*keybd*/, + int /*led*/, + Bool /*on*/); + +extern void MaybeStopHint( + DeviceIntPtr /*device*/, + ClientPtr /*client*/); + +extern void ProcessPointerEvent( + InternalEvent* /* ev */, + DeviceIntPtr /*mouse*/); + +extern void ProcessKeyboardEvent( + InternalEvent* /*ev*/, + DeviceIntPtr /*keybd*/); + +extern Bool LegalModifier( + unsigned int /*key*/, + DeviceIntPtr /*pDev*/); + +extern _X_EXPORT void ProcessInputEvents(void); + +extern _X_EXPORT void InitInput( + int /*argc*/, + char ** /*argv*/); +extern _X_EXPORT void CloseInput(void); + +extern _X_EXPORT int GetMaximumEventsNum(void); + +extern _X_EXPORT int GetEventList(EventListPtr* list); +extern _X_EXPORT EventListPtr InitEventList(int num_events); +extern _X_EXPORT void FreeEventList(EventListPtr list, int num_events); + +extern void CreateClassesChangedEvent(EventListPtr event, + DeviceIntPtr master, + DeviceIntPtr slave, + int type); +extern EventListPtr UpdateFromMaster( + EventListPtr events, + DeviceIntPtr pDev, + int type, + int *num_events); + +extern _X_EXPORT int GetPointerEvents( + EventListPtr events, + DeviceIntPtr pDev, + int type, + int buttons, + int flags, + const ValuatorMask *mask); + +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); + +extern int GetProximityEvents( + EventListPtr events, + DeviceIntPtr pDev, + int type, + const ValuatorMask *mask); + +extern void PostSyntheticMotion( + DeviceIntPtr pDev, + int x, + int y, + int screen, + unsigned long time); + +extern _X_EXPORT int GetMotionHistorySize( + void); + +extern _X_EXPORT void AllocateMotionHistory( + DeviceIntPtr pDev); + +extern _X_EXPORT int GetMotionHistory( + DeviceIntPtr pDev, + xTimecoord **buff, + unsigned long start, + unsigned long stop, + ScreenPtr pScreen, + BOOL core); + +extern int AttachDevice(ClientPtr client, + DeviceIntPtr slave, + DeviceIntPtr master); + +extern _X_EXPORT DeviceIntPtr GetPairedDevice(DeviceIntPtr kbd); +extern DeviceIntPtr GetMaster(DeviceIntPtr dev, int type); + +extern _X_EXPORT int AllocDevicePair(ClientPtr client, + char* name, + DeviceIntPtr* ptr, + DeviceIntPtr* keybd, + DeviceProc ptr_proc, + DeviceProc keybd_proc, + Bool master); +extern void DeepCopyDeviceClasses(DeviceIntPtr from, + DeviceIntPtr to, + DeviceChangedEvent *dce); + +/* Helper functions. */ +extern _X_EXPORT int generate_modkeymap(ClientPtr client, DeviceIntPtr dev, + KeyCode **modkeymap, int *max_keys_per_mod); +extern int change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *map, + int max_keys_per_mod); +extern int AllocXTestDevice(ClientPtr client, + char* name, + DeviceIntPtr* ptr, + DeviceIntPtr* keybd, + DeviceIntPtr master_ptr, + DeviceIntPtr master_keybd); +extern BOOL IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master); +extern DeviceIntPtr GetXTestDevice(DeviceIntPtr master); +extern void SendDevicePresenceEvent(int deviceid, int type); +extern _X_EXPORT InputAttributes *DuplicateInputAttributes(InputAttributes *attrs); +extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs); + +/* misc event helpers */ +extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients); +extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event); +extern Mask GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev); +void FixUpEventFromWindow(SpritePtr pSprite, + xEvent *xE, + WindowPtr pWin, + Window child, + Bool calcChild); +extern WindowPtr XYToWindow(SpritePtr pSprite, int x, int y); +extern int EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, + WindowPtr win); +/** + * Masks specifying the type of event to deliver for an InternalEvent; used + * by EventIsDeliverable. + * @defgroup EventIsDeliverable return flags + * @{ + */ +#define EVENT_XI1_MASK (1 << 0) /**< XI1.x event */ +#define EVENT_CORE_MASK (1 << 1) /**< Core event */ +#define EVENT_DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set */ +#define EVENT_XI2_MASK (1 << 3) /**< XI2 mask set on window */ +/* @} */ + +/* Implemented by the DDX. */ +extern _X_EXPORT int NewInputDeviceRequest( + InputOption *options, + InputAttributes *attrs, + DeviceIntPtr *dev); +extern _X_EXPORT void DeleteInputDeviceRequest( + DeviceIntPtr dev); + +extern _X_EXPORT void DDXRingBell( + int volume, + int pitch, + int duration); + +#define VALUATOR_MODE_ALL_AXES -1 +extern _X_HIDDEN int valuator_get_mode(DeviceIntPtr dev, int axis); +extern _X_HIDDEN void valuator_set_mode(DeviceIntPtr dev, int axis, int mode); + +/* Set to TRUE by default - os/utils.c sets it to FALSE on user request, + xfixes/cursor.c uses it to determine if the cursor is enabled */ +extern Bool EnableCursor; + +extern _X_EXPORT ValuatorMask *valuator_mask_new(int num_valuators); +extern _X_EXPORT void valuator_mask_free(ValuatorMask **mask); +extern _X_EXPORT void valuator_mask_set_range(ValuatorMask *mask, + int first_valuator, int num_valuators, + const int* valuators); +extern _X_EXPORT void valuator_mask_set(ValuatorMask *mask, + int valuator, + int data); +extern _X_EXPORT void valuator_mask_zero(ValuatorMask *mask); +extern _X_EXPORT int valuator_mask_size(const ValuatorMask *mask); +extern _X_EXPORT int valuator_mask_isset(const ValuatorMask *mask, int bit); +extern _X_EXPORT void valuator_mask_unset(ValuatorMask *mask, int bit); +extern _X_EXPORT int valuator_mask_num_valuators(const ValuatorMask *mask); +extern _X_EXPORT void valuator_mask_copy(ValuatorMask *dest, + const ValuatorMask *src); +extern _X_EXPORT int valuator_mask_get(const ValuatorMask *mask, int valnum); + +#endif /* INPUT_H */ diff --git a/xorg-server/include/misc.h b/xorg-server/include/misc.h index 0717db64d..42f225b17 100644 --- a/xorg-server/include/misc.h +++ b/xorg-server/include/misc.h @@ -1,290 +1,302 @@ -/*********************************************************** - -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. - -Copyright 1992, 1993 Data General Corporation; -Copyright 1992, 1993 OMRON Corporation - -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 -neither the name OMRON or DATA GENERAL be used in advertising or publicity -pertaining to distribution of the software without specific, written prior -permission of the party whose name is to be used. Neither OMRON or -DATA GENERAL make any representation about the suitability of this software -for any purpose. It is provided "as is" without express or implied warranty. - -OMRON AND DATA GENERAL EACH DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -IN NO EVENT SHALL OMRON OR DATA GENERAL 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. - -******************************************************************/ -#ifndef MISC_H -#define MISC_H 1 -/* - * X internal definitions - * - */ - -#include -#include -#include -#include -#include - -#include - -#ifndef MAXSCREENS -#define MAXSCREENS 16 -#endif -#define MAXCLIENTS 256 -#define MAXEXTENSIONS 128 -#define MAXFORMATS 8 -#define MAXDEVICES 40 /* input devices */ - -#define EXTENSION_EVENT_BASE 64 -#define EXTENSION_BASE 128 - -typedef unsigned long ATOM; - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#ifndef _XTYPEDEF_CALLBACKLISTPTR -typedef struct _CallbackList *CallbackListPtr; /* also in dix.h */ -#define _XTYPEDEF_CALLBACKLISTPTR -#endif - -typedef struct _xReq *xReqPtr; - -#include "os.h" /* for ALLOCATE_LOCAL and DEALLOCATE_LOCAL */ -#include /* for bcopy, bzero, and bcmp */ - -#define NullBox ((BoxPtr)0) -#define MILLI_PER_MIN (1000 * 60) -#define MILLI_PER_SECOND (1000) - - /* this next is used with None and ParentRelative to tell - PaintWin() what to use to paint the background. Also used - in the macro IS_VALID_PIXMAP */ - -#define USE_BACKGROUND_PIXEL 3 -#define USE_BORDER_PIXEL 3 - - -/* byte swap a 32-bit literal */ -#define lswapl(x) ((((x) & 0xff) << 24) |\ - (((x) & 0xff00) << 8) |\ - (((x) & 0xff0000) >> 8) |\ - (((x) >> 24) & 0xff)) - -/* byte swap a short literal */ -#define lswaps(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff)) - -#undef min -#undef max - -#define min(a, b) (((a) < (b)) ? (a) : (b)) -#define max(a, b) (((a) > (b)) ? (a) : (b)) -/* abs() is a function, not a macro; include the file declaring - * it in case we haven't done that yet. - */ -#include -#ifndef Fabs -#define Fabs(a) ((a) > 0.0 ? (a) : -(a)) /* floating absolute value */ -#endif -#define sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0)) -/* this assumes b > 0 */ -#define modulus(a, b, d) if (((d) = (a) % (b)) < 0) (d) += (b) -/* - * return the least significant bit in x which is set - * - * This works on 1's complement and 2's complement machines. - * If you care about the extra instruction on 2's complement - * machines, change to ((x) & (-(x))) - */ -#define lowbit(x) ((x) & (~(x) + 1)) - -/* XXX Not for modules */ -#include -#if !defined(MAXSHORT) || !defined(MINSHORT) || \ - !defined(MAXINT) || !defined(MININT) -/* - * Some implementations #define these through , so preclude - * #include'ing it later. - */ - -#include -#undef MAXSHORT -#define MAXSHORT SHRT_MAX -#undef MINSHORT -#define MINSHORT SHRT_MIN -#undef MAXINT -#define MAXINT INT_MAX -#undef MININT -#define MININT INT_MIN - -#include -#include -#include /* for fopen, etc... */ - -#endif - -/** - * Calculate the number of bytes needed to hold bits. - * @param bits The minimum number of bits needed. - * @return The number of bytes needed to hold bits. - */ -static inline int -bits_to_bytes(const int bits) { - return ((bits + 7) >> 3); -} -/** - * Calculate the number of 4-byte units needed to hold the given number of - * bytes. - * @param bytes The minimum number of bytes needed. - * @return The number of 4-byte units needed to hold bytes. - */ -static inline int -bytes_to_int32(const int bytes) { - return (((bytes) + 3) >> 2); -} - -/** - * Calculate the number of bytes (in multiples of 4) needed to hold bytes. - * @param bytes The minimum number of bytes needed. - * @return The closest multiple of 4 that is equal or higher than bytes. - */ -static inline int -pad_to_int32(const int bytes) { - return (((bytes) + 3) & ~3); -} - -extern char** -xstrtokenize(const char *str, const char* separators); - -/* some macros to help swap requests, replies, and events */ - -#define LengthRestB(stuff) \ - ((client->req_len << 2) - sizeof(*stuff)) - -#define LengthRestS(stuff) \ - ((client->req_len << 1) - (sizeof(*stuff) >> 1)) - -#define LengthRestL(stuff) \ - (client->req_len - (sizeof(*stuff) >> 2)) - -#define SwapRestS(stuff) \ - SwapShorts((short *)(stuff + 1), LengthRestS(stuff)) - -#define SwapRestL(stuff) \ - SwapLongs((CARD32 *)(stuff + 1), LengthRestL(stuff)) - -/* byte swap a 32-bit value */ -#define swapl(x, n) { \ - n = ((char *) (x))[0];\ - ((char *) (x))[0] = ((char *) (x))[3];\ - ((char *) (x))[3] = n;\ - n = ((char *) (x))[1];\ - ((char *) (x))[1] = ((char *) (x))[2];\ - ((char *) (x))[2] = n; } - -/* byte swap a short */ -#define swaps(x, n) { \ - n = ((char *) (x))[0];\ - ((char *) (x))[0] = ((char *) (x))[1];\ - ((char *) (x))[1] = n; } - -/* copy 32-bit value from src to dst byteswapping on the way */ -#define cpswapl(src, dst) { \ - ((char *)&(dst))[0] = ((char *) &(src))[3];\ - ((char *)&(dst))[1] = ((char *) &(src))[2];\ - ((char *)&(dst))[2] = ((char *) &(src))[1];\ - ((char *)&(dst))[3] = ((char *) &(src))[0]; } - -/* copy short from src to dst byteswapping on the way */ -#define cpswaps(src, dst) { \ - ((char *) &(dst))[0] = ((char *) &(src))[1];\ - ((char *) &(dst))[1] = ((char *) &(src))[0]; } - -extern _X_EXPORT void SwapLongs( - CARD32 *list, - unsigned long count); - -extern _X_EXPORT void SwapShorts( - short *list, - unsigned long count); - -extern _X_EXPORT void MakePredeclaredAtoms(void); - -extern _X_EXPORT int Ones( - unsigned long /*mask*/); - -typedef struct _xPoint *DDXPointPtr; -typedef struct pixman_box16 *BoxPtr; -typedef struct _xEvent *xEventPtr; -typedef struct _xRectangle *xRectanglePtr; -typedef struct _GrabRec *GrabPtr; - -/* typedefs from other places - duplicated here to minimize the amount - * of unnecessary junk that one would normally have to include to get - * these symbols defined - */ - -#ifndef _XTYPEDEF_CHARINFOPTR -typedef struct _CharInfo *CharInfoPtr; /* also in fonts/include/font.h */ -#define _XTYPEDEF_CHARINFOPTR -#endif - -extern _X_EXPORT unsigned long globalSerialNumber; -extern _X_EXPORT unsigned long serverGeneration; - -#endif /* MISC_H */ +/*********************************************************** + +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. + +Copyright 1992, 1993 Data General Corporation; +Copyright 1992, 1993 OMRON Corporation + +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 +neither the name OMRON or DATA GENERAL be used in advertising or publicity +pertaining to distribution of the software without specific, written prior +permission of the party whose name is to be used. Neither OMRON or +DATA GENERAL make any representation about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +OMRON AND DATA GENERAL EACH DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL OMRON OR DATA GENERAL 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. + +******************************************************************/ +#ifndef MISC_H +#define MISC_H 1 +/* + * X internal definitions + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +#ifndef MAXSCREENS +#define MAXSCREENS 16 +#endif +#define MAXCLIENTS 256 +#define MAXEXTENSIONS 128 +#define MAXFORMATS 8 +#define MAXDEVICES 40 /* input devices */ + +#define EXTENSION_EVENT_BASE 64 +#define EXTENSION_BASE 128 + +typedef uint32_t ATOM; + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifndef _XTYPEDEF_CALLBACKLISTPTR +typedef struct _CallbackList *CallbackListPtr; /* also in dix.h */ +#define _XTYPEDEF_CALLBACKLISTPTR +#endif + +typedef struct _xReq *xReqPtr; + +#include "os.h" /* for ALLOCATE_LOCAL and DEALLOCATE_LOCAL */ +#include /* for bcopy, bzero, and bcmp */ + +#define NullBox ((BoxPtr)0) +#define MILLI_PER_MIN (1000 * 60) +#define MILLI_PER_SECOND (1000) + + /* this next is used with None and ParentRelative to tell + PaintWin() what to use to paint the background. Also used + in the macro IS_VALID_PIXMAP */ + +#define USE_BACKGROUND_PIXEL 3 +#define USE_BORDER_PIXEL 3 + + +/* byte swap a 32-bit literal */ +#define lswapl(x) ((((x) & 0xff) << 24) |\ + (((x) & 0xff00) << 8) |\ + (((x) & 0xff0000) >> 8) |\ + (((x) >> 24) & 0xff)) + +/* byte swap a short literal */ +#define lswaps(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff)) + +#undef min +#undef max + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) +/* abs() is a function, not a macro; include the file declaring + * it in case we haven't done that yet. + */ +#include +#ifndef Fabs +#define Fabs(a) ((a) > 0.0 ? (a) : -(a)) /* floating absolute value */ +#endif +#define sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0)) +/* this assumes b > 0 */ +#define modulus(a, b, d) if (((d) = (a) % (b)) < 0) (d) += (b) +/* + * return the least significant bit in x which is set + * + * This works on 1's complement and 2's complement machines. + * If you care about the extra instruction on 2's complement + * machines, change to ((x) & (-(x))) + */ +#define lowbit(x) ((x) & (~(x) + 1)) + +/* XXX Not for modules */ +#include +#if !defined(MAXSHORT) || !defined(MINSHORT) || \ + !defined(MAXINT) || !defined(MININT) +/* + * Some implementations #define these through , so preclude + * #include'ing it later. + */ + +#include +#undef MAXSHORT +#define MAXSHORT SHRT_MAX +#undef MINSHORT +#define MINSHORT SHRT_MIN +#undef MAXINT +#define MAXINT INT_MAX +#undef MININT +#define MININT INT_MIN + +#include +#include +#include /* for fopen, etc... */ + +#endif + +#ifndef PATH_MAX +#include +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif +#endif + +/** + * Calculate the number of bytes needed to hold bits. + * @param bits The minimum number of bits needed. + * @return The number of bytes needed to hold bits. + */ +static inline int +bits_to_bytes(const int bits) { + return ((bits + 7) >> 3); +} +/** + * Calculate the number of 4-byte units needed to hold the given number of + * bytes. + * @param bytes The minimum number of bytes needed. + * @return The number of 4-byte units needed to hold bytes. + */ +static inline int +bytes_to_int32(const int bytes) { + return (((bytes) + 3) >> 2); +} + +/** + * Calculate the number of bytes (in multiples of 4) needed to hold bytes. + * @param bytes The minimum number of bytes needed. + * @return The closest multiple of 4 that is equal or higher than bytes. + */ +static inline int +pad_to_int32(const int bytes) { + return (((bytes) + 3) & ~3); +} + +extern char** +xstrtokenize(const char *str, const char* separators); + +/* some macros to help swap requests, replies, and events */ + +#define LengthRestB(stuff) \ + ((client->req_len << 2) - sizeof(*stuff)) + +#define LengthRestS(stuff) \ + ((client->req_len << 1) - (sizeof(*stuff) >> 1)) + +#define LengthRestL(stuff) \ + (client->req_len - (sizeof(*stuff) >> 2)) + +#define SwapRestS(stuff) \ + SwapShorts((short *)(stuff + 1), LengthRestS(stuff)) + +#define SwapRestL(stuff) \ + SwapLongs((CARD32 *)(stuff + 1), LengthRestL(stuff)) + +/* byte swap a 32-bit value */ +#define swapl(x, n) { \ + n = ((char *) (x))[0];\ + ((char *) (x))[0] = ((char *) (x))[3];\ + ((char *) (x))[3] = n;\ + n = ((char *) (x))[1];\ + ((char *) (x))[1] = ((char *) (x))[2];\ + ((char *) (x))[2] = n; } + +/* byte swap a short */ +#define swaps(x, n) { \ + n = ((char *) (x))[0];\ + ((char *) (x))[0] = ((char *) (x))[1];\ + ((char *) (x))[1] = n; } + +/* copy 32-bit value from src to dst byteswapping on the way */ +#define cpswapl(src, dst) { \ + ((char *)&(dst))[0] = ((char *) &(src))[3];\ + ((char *)&(dst))[1] = ((char *) &(src))[2];\ + ((char *)&(dst))[2] = ((char *) &(src))[1];\ + ((char *)&(dst))[3] = ((char *) &(src))[0]; } + +/* copy short from src to dst byteswapping on the way */ +#define cpswaps(src, dst) { \ + ((char *) &(dst))[0] = ((char *) &(src))[1];\ + ((char *) &(dst))[1] = ((char *) &(src))[0]; } + +extern _X_EXPORT void SwapLongs( + CARD32 *list, + unsigned long count); + +extern _X_EXPORT void SwapShorts( + short *list, + unsigned long count); + +extern _X_EXPORT void MakePredeclaredAtoms(void); + +extern _X_EXPORT int Ones( + unsigned long /*mask*/); + +typedef struct _xPoint *DDXPointPtr; +typedef struct pixman_box16 *BoxPtr; +typedef struct _xEvent *xEventPtr; +typedef struct _xRectangle *xRectanglePtr; +typedef struct _GrabRec *GrabPtr; + +/* typedefs from other places - duplicated here to minimize the amount + * of unnecessary junk that one would normally have to include to get + * these symbols defined + */ + +#ifndef _XTYPEDEF_CHARINFOPTR +typedef struct _CharInfo *CharInfoPtr; /* also in fonts/include/font.h */ +#define _XTYPEDEF_CHARINFOPTR +#endif + +extern _X_EXPORT unsigned long globalSerialNumber; +extern _X_EXPORT unsigned long serverGeneration; + +#endif /* MISC_H */ diff --git a/xorg-server/include/propertyst.h b/xorg-server/include/propertyst.h index fd1148eb7..fd3e0118d 100644 --- a/xorg-server/include/propertyst.h +++ b/xorg-server/include/propertyst.h @@ -1,68 +1,68 @@ -/*********************************************************** - -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. - -******************************************************************/ - -#ifndef PROPERTYSTRUCT_H -#define PROPERTYSTRUCT_H -#include "misc.h" -#include "property.h" -#include "privates.h" -/* - * PROPERTY -- property element - */ - -typedef struct _Property { - struct _Property *next; - ATOM propertyName; - ATOM type; /* ignored by server */ - short format; /* format of data for swapping - 8,16,32 */ - long size; /* size of data in (format/8) bytes */ - pointer data; /* private to client */ - PrivateRec *devPrivates; -} PropertyRec; - -#endif /* PROPERTYSTRUCT_H */ - +/*********************************************************** + +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. + +******************************************************************/ + +#ifndef PROPERTYSTRUCT_H +#define PROPERTYSTRUCT_H +#include "misc.h" +#include "property.h" +#include "privates.h" +/* + * PROPERTY -- property element + */ + +typedef struct _Property { + struct _Property *next; + ATOM propertyName; + ATOM type; /* ignored by server */ + uint32_t format; /* format of data for swapping - 8,16,32 */ + uint32_t size; /* size of data in (format/8) bytes */ + pointer data; /* private to client */ + PrivateRec *devPrivates; +} PropertyRec; + +#endif /* PROPERTYSTRUCT_H */ + diff --git a/xorg-server/include/ptrveloc.h b/xorg-server/include/ptrveloc.h index 8c59c0361..1198146f1 100644 --- a/xorg-server/include/ptrveloc.h +++ b/xorg-server/include/ptrveloc.h @@ -1,138 +1,144 @@ -/* - * - * 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. - */ - -#ifndef POINTERVELOCITY_H -#define POINTERVELOCITY_H - -#include /* DeviceIntPtr */ - -/* 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; - -/* number of properties for predictable acceleration */ -#define NPROPS_PREDICTABLE_ACCEL 4 - -/** - * 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; - long prop_handlers[NPROPS_PREDICTABLE_ACCEL]; -} DeviceVelocityRec, *DeviceVelocityPtr; - -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, int first_valuator, - int num_valuators, int *valuators, int evtime); - -extern _X_INTERNAL void -acceleratePointerLightweight(DeviceIntPtr dev, int first_valuator, - int num_valuators, int *valuators, int ignored); - -#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 + +/* 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 */ diff --git a/xorg-server/include/resource.h b/xorg-server/include/resource.h index 763aa99d9..17bebe7d4 100644 --- a/xorg-server/include/resource.h +++ b/xorg-server/include/resource.h @@ -1,255 +1,255 @@ -/*********************************************************** - -Copyright 1987, 1989, 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, 1989 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. - -******************************************************************/ - -#ifndef RESOURCE_H -#define RESOURCE_H 1 -#include "misc.h" -#include "dixaccess.h" - -/***************************************************************** - * STUFF FOR RESOURCES - *****************************************************************/ - -/* classes for Resource routines */ - -typedef unsigned long RESTYPE; - -#define RC_VANILLA ((RESTYPE)0) -#define RC_CACHED ((RESTYPE)1<<31) -#define RC_DRAWABLE ((RESTYPE)1<<30) -/* Use class RC_NEVERRETAIN for resources that should not be retained - * regardless of the close down mode when the client dies. (A client's - * event selections on objects that it doesn't own are good candidates.) - * Extensions can use this too! - */ -#define RC_NEVERRETAIN ((RESTYPE)1<<29) -#define RC_LASTPREDEF RC_NEVERRETAIN -#define RC_ANY (~(RESTYPE)0) - -/* types for Resource routines */ - -#define RT_WINDOW ((RESTYPE)1|RC_DRAWABLE) -#define RT_PIXMAP ((RESTYPE)2|RC_DRAWABLE) -#define RT_GC ((RESTYPE)3) -#undef RT_FONT -#undef RT_CURSOR -#define RT_FONT ((RESTYPE)4) -#define RT_CURSOR ((RESTYPE)5) -#define RT_COLORMAP ((RESTYPE)6) -#define RT_CMAPENTRY ((RESTYPE)7) -#define RT_OTHERCLIENT ((RESTYPE)8|RC_NEVERRETAIN) -#define RT_PASSIVEGRAB ((RESTYPE)9|RC_NEVERRETAIN) -#define RT_LASTPREDEF ((RESTYPE)9) -#define RT_NONE ((RESTYPE)0) - -/* bits and fields within a resource id */ -#define RESOURCE_AND_CLIENT_COUNT 29 /* 29 bits for XIDs */ -#if MAXCLIENTS == 64 -#define RESOURCE_CLIENT_BITS 6 -#endif -#if MAXCLIENTS == 128 -#define RESOURCE_CLIENT_BITS 7 -#endif -#if MAXCLIENTS == 256 -#define RESOURCE_CLIENT_BITS 8 -#endif -#if MAXCLIENTS == 512 -#define RESOURCE_CLIENT_BITS 9 -#endif -/* client field offset */ -#define CLIENTOFFSET (RESOURCE_AND_CLIENT_COUNT - RESOURCE_CLIENT_BITS) -/* resource field */ -#define RESOURCE_ID_MASK ((1 << CLIENTOFFSET) - 1) -/* client field */ -#define RESOURCE_CLIENT_MASK (((1 << RESOURCE_CLIENT_BITS) - 1) << CLIENTOFFSET) -/* extract the client mask from an XID */ -#define CLIENT_BITS(id) ((id) & RESOURCE_CLIENT_MASK) -/* extract the client id from an XID */ -#define CLIENT_ID(id) ((int)(CLIENT_BITS(id) >> CLIENTOFFSET)) -#define SERVER_BIT (Mask)0x40000000 /* use illegal bit */ - -#ifdef INVALID -#undef INVALID /* needed on HP/UX */ -#endif - -/* Invalid resource id */ -#define INVALID (0) - -#define BAD_RESOURCE 0xe0000000 - -#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) - -/* Resource state callback */ -extern _X_EXPORT CallbackListPtr ResourceStateCallback; - -typedef enum {ResourceStateAdding, - ResourceStateFreeing} ResourceState; - -typedef struct { - ResourceState state; - XID id; - RESTYPE type; - pointer value; -} ResourceStateInfoRec; - -typedef int (*DeleteType)( - pointer /*value*/, - XID /*id*/); - -typedef void (*FindResType)( - pointer /*value*/, - XID /*id*/, - pointer /*cdata*/); - -typedef void (*FindAllRes)( - pointer /*value*/, - XID /*id*/, - RESTYPE /*type*/, - pointer /*cdata*/); - -typedef Bool (*FindComplexResType)( - pointer /*value*/, - XID /*id*/, - pointer /*cdata*/); - -extern _X_EXPORT RESTYPE CreateNewResourceType( - DeleteType /*deleteFunc*/, char * /*name*/); - -extern _X_EXPORT void SetResourceTypeErrorValue( - RESTYPE /*type*/, int /*errorValue*/); - -extern _X_EXPORT RESTYPE CreateNewResourceClass(void); - -extern _X_EXPORT Bool InitClientResources( - ClientPtr /*client*/); - -extern _X_EXPORT XID FakeClientID( - int /*client*/); - -/* Quartz support on Mac OS X uses the CarbonCore - framework whose AddResource function conflicts here. */ -#ifdef __APPLE__ -#define AddResource Darwin_X_AddResource -#endif -extern _X_EXPORT Bool AddResource( - XID /*id*/, - RESTYPE /*type*/, - pointer /*value*/); - -extern _X_EXPORT void FreeResource( - XID /*id*/, - RESTYPE /*skipDeleteFuncType*/); - -extern _X_EXPORT void FreeResourceByType( - XID /*id*/, - RESTYPE /*type*/, - Bool /*skipFree*/); - -extern _X_EXPORT Bool ChangeResourceValue( - XID /*id*/, - RESTYPE /*rtype*/, - pointer /*value*/); - -extern _X_EXPORT void FindClientResourcesByType( - ClientPtr /*client*/, - RESTYPE /*type*/, - FindResType /*func*/, - pointer /*cdata*/); - -extern _X_EXPORT void FindAllClientResources( - ClientPtr /*client*/, - FindAllRes /*func*/, - pointer /*cdata*/); - -extern _X_EXPORT void FreeClientNeverRetainResources( - ClientPtr /*client*/); - -extern _X_EXPORT void FreeClientResources( - ClientPtr /*client*/); - -extern _X_EXPORT void FreeAllResources(void); - -extern _X_EXPORT Bool LegalNewID( - XID /*id*/, - ClientPtr /*client*/); - -extern _X_EXPORT pointer LookupClientResourceComplex( - ClientPtr client, - RESTYPE type, - FindComplexResType func, - pointer cdata); - -extern _X_EXPORT int dixLookupResourceByType( - pointer *result, - XID id, - RESTYPE rtype, - ClientPtr client, - Mask access_mode); - -extern _X_EXPORT int dixLookupResourceByClass( - pointer *result, - XID id, - RESTYPE rclass, - ClientPtr client, - Mask access_mode); - -extern _X_EXPORT void GetXIDRange( - int /*client*/, - Bool /*server*/, - XID * /*minp*/, - XID * /*maxp*/); - -extern _X_EXPORT unsigned int GetXIDList( - ClientPtr /*client*/, - unsigned int /*count*/, - XID * /*pids*/); - -extern _X_EXPORT RESTYPE lastResourceType; -extern _X_EXPORT RESTYPE TypeMask; - -#endif /* RESOURCE_H */ - +/*********************************************************** + +Copyright 1987, 1989, 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, 1989 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. + +******************************************************************/ + +#ifndef RESOURCE_H +#define RESOURCE_H 1 +#include "misc.h" +#include "dixaccess.h" + +/***************************************************************** + * STUFF FOR RESOURCES + *****************************************************************/ + +/* classes for Resource routines */ + +typedef uint32_t RESTYPE; + +#define RC_VANILLA ((RESTYPE)0) +#define RC_CACHED ((RESTYPE)1<<31) +#define RC_DRAWABLE ((RESTYPE)1<<30) +/* Use class RC_NEVERRETAIN for resources that should not be retained + * regardless of the close down mode when the client dies. (A client's + * event selections on objects that it doesn't own are good candidates.) + * Extensions can use this too! + */ +#define RC_NEVERRETAIN ((RESTYPE)1<<29) +#define RC_LASTPREDEF RC_NEVERRETAIN +#define RC_ANY (~(RESTYPE)0) + +/* types for Resource routines */ + +#define RT_WINDOW ((RESTYPE)1|RC_DRAWABLE) +#define RT_PIXMAP ((RESTYPE)2|RC_DRAWABLE) +#define RT_GC ((RESTYPE)3) +#undef RT_FONT +#undef RT_CURSOR +#define RT_FONT ((RESTYPE)4) +#define RT_CURSOR ((RESTYPE)5) +#define RT_COLORMAP ((RESTYPE)6) +#define RT_CMAPENTRY ((RESTYPE)7) +#define RT_OTHERCLIENT ((RESTYPE)8|RC_NEVERRETAIN) +#define RT_PASSIVEGRAB ((RESTYPE)9|RC_NEVERRETAIN) +#define RT_LASTPREDEF ((RESTYPE)9) +#define RT_NONE ((RESTYPE)0) + +/* bits and fields within a resource id */ +#define RESOURCE_AND_CLIENT_COUNT 29 /* 29 bits for XIDs */ +#if MAXCLIENTS == 64 +#define RESOURCE_CLIENT_BITS 6 +#endif +#if MAXCLIENTS == 128 +#define RESOURCE_CLIENT_BITS 7 +#endif +#if MAXCLIENTS == 256 +#define RESOURCE_CLIENT_BITS 8 +#endif +#if MAXCLIENTS == 512 +#define RESOURCE_CLIENT_BITS 9 +#endif +/* client field offset */ +#define CLIENTOFFSET (RESOURCE_AND_CLIENT_COUNT - RESOURCE_CLIENT_BITS) +/* resource field */ +#define RESOURCE_ID_MASK ((1 << CLIENTOFFSET) - 1) +/* client field */ +#define RESOURCE_CLIENT_MASK (((1 << RESOURCE_CLIENT_BITS) - 1) << CLIENTOFFSET) +/* extract the client mask from an XID */ +#define CLIENT_BITS(id) ((id) & RESOURCE_CLIENT_MASK) +/* extract the client id from an XID */ +#define CLIENT_ID(id) ((int)(CLIENT_BITS(id) >> CLIENTOFFSET)) +#define SERVER_BIT (Mask)0x40000000 /* use illegal bit */ + +#ifdef INVALID +#undef INVALID /* needed on HP/UX */ +#endif + +/* Invalid resource id */ +#define INVALID (0) + +#define BAD_RESOURCE 0xe0000000 + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +/* Resource state callback */ +extern _X_EXPORT CallbackListPtr ResourceStateCallback; + +typedef enum {ResourceStateAdding, + ResourceStateFreeing} ResourceState; + +typedef struct { + ResourceState state; + XID id; + RESTYPE type; + pointer value; +} ResourceStateInfoRec; + +typedef int (*DeleteType)( + pointer /*value*/, + XID /*id*/); + +typedef void (*FindResType)( + pointer /*value*/, + XID /*id*/, + pointer /*cdata*/); + +typedef void (*FindAllRes)( + pointer /*value*/, + XID /*id*/, + RESTYPE /*type*/, + pointer /*cdata*/); + +typedef Bool (*FindComplexResType)( + pointer /*value*/, + XID /*id*/, + pointer /*cdata*/); + +extern _X_EXPORT RESTYPE CreateNewResourceType( + DeleteType /*deleteFunc*/, char * /*name*/); + +extern _X_EXPORT void SetResourceTypeErrorValue( + RESTYPE /*type*/, int /*errorValue*/); + +extern _X_EXPORT RESTYPE CreateNewResourceClass(void); + +extern _X_EXPORT Bool InitClientResources( + ClientPtr /*client*/); + +extern _X_EXPORT XID FakeClientID( + int /*client*/); + +/* Quartz support on Mac OS X uses the CarbonCore + framework whose AddResource function conflicts here. */ +#ifdef __APPLE__ +#define AddResource Darwin_X_AddResource +#endif +extern _X_EXPORT Bool AddResource( + XID /*id*/, + RESTYPE /*type*/, + pointer /*value*/); + +extern _X_EXPORT void FreeResource( + XID /*id*/, + RESTYPE /*skipDeleteFuncType*/); + +extern _X_EXPORT void FreeResourceByType( + XID /*id*/, + RESTYPE /*type*/, + Bool /*skipFree*/); + +extern _X_EXPORT Bool ChangeResourceValue( + XID /*id*/, + RESTYPE /*rtype*/, + pointer /*value*/); + +extern _X_EXPORT void FindClientResourcesByType( + ClientPtr /*client*/, + RESTYPE /*type*/, + FindResType /*func*/, + pointer /*cdata*/); + +extern _X_EXPORT void FindAllClientResources( + ClientPtr /*client*/, + FindAllRes /*func*/, + pointer /*cdata*/); + +extern _X_EXPORT void FreeClientNeverRetainResources( + ClientPtr /*client*/); + +extern _X_EXPORT void FreeClientResources( + ClientPtr /*client*/); + +extern _X_EXPORT void FreeAllResources(void); + +extern _X_EXPORT Bool LegalNewID( + XID /*id*/, + ClientPtr /*client*/); + +extern _X_EXPORT pointer LookupClientResourceComplex( + ClientPtr client, + RESTYPE type, + FindComplexResType func, + pointer cdata); + +extern _X_EXPORT int dixLookupResourceByType( + pointer *result, + XID id, + RESTYPE rtype, + ClientPtr client, + Mask access_mode); + +extern _X_EXPORT int dixLookupResourceByClass( + pointer *result, + XID id, + RESTYPE rclass, + ClientPtr client, + Mask access_mode); + +extern _X_EXPORT void GetXIDRange( + int /*client*/, + Bool /*server*/, + XID * /*minp*/, + XID * /*maxp*/); + +extern _X_EXPORT unsigned int GetXIDList( + ClientPtr /*client*/, + unsigned int /*count*/, + XID * /*pids*/); + +extern _X_EXPORT RESTYPE lastResourceType; +extern _X_EXPORT RESTYPE TypeMask; + +#endif /* RESOURCE_H */ + diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c index 209ea06be..e8ed106ea 100644 --- a/xorg-server/mi/mipointer.c +++ b/xorg-server/mi/mipointer.c @@ -1,688 +1,698 @@ -/* - -Copyright 1989, 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. -*/ - -/** - * @file - * This file contains functions to move the pointer on the screen and/or - * restrict its movement. These functions are divided into two sets: - * Screen-specific functions that are used as function pointers from other - * parts of the server (and end up heavily wrapped by e.g. animcur and - * xfixes): - * miPointerConstrainCursor - * miPointerCursorLimits - * miPointerDisplayCursor - * miPointerRealizeCursor - * miPointerUnrealizeCursor - * miPointerSetCursorPosition - * miRecolorCursor - * miPointerDeviceInitialize - * miPointerDeviceCleanup - * If wrapped, these are the last element in the wrapping chain. They may - * call into sprite-specific code through further function pointers though. - * - * The second type of functions are those that are directly called by the - * DIX, DDX and some drivers. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -# include -# include -# include -# include "misc.h" -# include "windowstr.h" -# include "pixmapstr.h" -# include "mi.h" -# include "scrnintstr.h" -# include "mipointrst.h" -# include "cursorstr.h" -# include "dixstruct.h" -# include "inputstr.h" -# include "inpututils.h" - -DevPrivateKeyRec miPointerScreenKeyRec; - -#define GetScreenPrivate(s) ((miPointerScreenPtr) \ - dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) -#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) - -DevPrivateKeyRec miPointerPrivKeyRec; - -#define MIPOINTER(dev) \ - (IsFloating(dev) ? \ - (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ - (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) - -static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - BoxPtr pBox); -static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, BoxPtr pHotBox, - BoxPtr pTopLeftBox); -static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, - Bool generateEvent); -static Bool miPointerCloseScreen(int index, ScreenPtr pScreen); -static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y); -static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); -static void miPointerDeviceCleanup(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); - -static EventList* events; /* for WarpPointer MotionNotifies */ - -Bool -miPointerInitialize (ScreenPtr pScreen, - miPointerSpriteFuncPtr spriteFuncs, - miPointerScreenFuncPtr screenFuncs, - Bool waitForUpdate) -{ - miPointerScreenPtr pScreenPriv; - - if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) - return FALSE; - - if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) - return FALSE; - - pScreenPriv = malloc(sizeof (miPointerScreenRec)); - if (!pScreenPriv) - return FALSE; - pScreenPriv->spriteFuncs = spriteFuncs; - pScreenPriv->screenFuncs = screenFuncs; - /* - * check for uninitialized methods - */ - if (!screenFuncs->EnqueueEvent) - screenFuncs->EnqueueEvent = mieqEnqueue; - if (!screenFuncs->NewEventScreen) - screenFuncs->NewEventScreen = mieqSwitchScreen; - pScreenPriv->waitForUpdate = waitForUpdate; - pScreenPriv->showTransparent = FALSE; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = miPointerCloseScreen; - dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); - /* - * set up screen cursor method table - */ - pScreen->ConstrainCursor = miPointerConstrainCursor; - pScreen->CursorLimits = miPointerCursorLimits; - pScreen->DisplayCursor = miPointerDisplayCursor; - pScreen->RealizeCursor = miPointerRealizeCursor; - pScreen->UnrealizeCursor = miPointerUnrealizeCursor; - pScreen->SetCursorPosition = miPointerSetCursorPosition; - pScreen->RecolorCursor = miRecolorCursor; - pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; - pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; - - events = NULL; - return TRUE; -} - -/** - * Destroy screen-specific information. - * - * @param index Screen index of the screen in screenInfo.screens[] - * @param pScreen The actual screen pointer - */ -static Bool -miPointerCloseScreen (int index, ScreenPtr pScreen) -{ - SetupScreen(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - free((pointer) pScreenPriv); - FreeEventList(events, GetMaximumEventsNum()); - events = NULL; - return (*pScreen->CloseScreen) (index, pScreen); -} - -/* - * DIX/DDX interface routines - */ - -static Bool -miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - SetupScreen(pScreen); - return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); -} - -static Bool -miPointerUnrealizeCursor (DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor) -{ - SetupScreen(pScreen); - return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); -} - -static Bool -miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - miPointerPtr pPointer; - - /* return for keyboards */ - if (!IsPointerDevice(pDev)) - return FALSE; - - pPointer = MIPOINTER(pDev); - - pPointer->pCursor = pCursor; - pPointer->pScreen = pScreen; - miPointerUpdateSprite(pDev); - return TRUE; -} - -/** - * Set up the constraints for the given device. This function does not - * actually constrain the cursor but merely copies the given box to the - * internal constraint storage. - * - * @param pDev The device to constrain to the box - * @param pBox The rectangle to constrain the cursor to - * @param pScreen Used for copying screen confinement - */ -static void -miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) -{ - miPointerPtr pPointer; - - pPointer = MIPOINTER(pDev); - - pPointer->limits = *pBox; - pPointer->confined = PointerConfinedToScreen(pDev); -} - -/** - * Should calculate the box for the given cursor, based on screen and the - * confinement given. But we assume that whatever box is passed in is valid - * anyway. - * - * @param pDev The device to calculate the cursor limits for - * @param pScreen The screen the confinement happens on - * @param pCursor The screen the confinement happens on - * @param pHotBox The confinement box for the cursor - * @param[out] pTopLeftBox The new confinement box, always *pHotBox. - */ -static void -miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, - BoxPtr pHotBox, BoxPtr pTopLeftBox) -{ - *pTopLeftBox = *pHotBox; -} - -/** - * Set the device's cursor position to the x/y position on the given screen. - * Generates and event if required. - * - * This function is called from: - * - sprite init code to place onto initial position - * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…) - * - during the cursor update path in CheckMotion - * - in the Xinerama part of NewCurrentScreen - * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so - * it's set back to the original pos) - * - * @param pDev The device to move - * @param pScreen The screen the device is on - * @param x The x coordinate in per-screen coordinates - * @param y The y coordinate in per-screen coordinates - * @param generateEvent True if the pointer movement should generate an - * event. - * - * @return TRUE in all cases - */ -static Bool -miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, Bool generateEvent) -{ - SetupScreen (pScreen); - miPointerPtr pPointer = MIPOINTER(pDev); - - pPointer->generateEvent = generateEvent; - - /* device dependent - must pend signal and call miPointerWarpCursor */ - (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); - if (!generateEvent) - miPointerUpdateSprite(pDev); - return TRUE; -} - -/** - * Set up sprite information for the device. - * This function will be called once for each device after it is initialized - * in the DIX. - * - * @param pDev The newly created device - * @param pScreen The initial sprite scree. - */ -static Bool -miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miPointerPtr pPointer; - SetupScreen (pScreen); - - pPointer = malloc(sizeof(miPointerRec)); - if (!pPointer) - return FALSE; - - pPointer->pScreen = NULL; - pPointer->pSpriteScreen = NULL; - pPointer->pCursor = NULL; - pPointer->pSpriteCursor = NULL; - pPointer->limits.x1 = 0; - pPointer->limits.x2 = 32767; - pPointer->limits.y1 = 0; - pPointer->limits.y2 = 32767; - pPointer->confined = FALSE; - pPointer->x = 0; - pPointer->y = 0; - pPointer->generateEvent = FALSE; - - if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) - { - free(pPointer); - return FALSE; - } - - dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); - return TRUE; -} - -/** - * Clean up after device. - * This function will be called once before the device is freed in the DIX - * - * @param pDev The device to be removed from the server - * @param pScreen Current screen of the device - */ -static void -miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - SetupScreen(pScreen); - - if (!IsMaster(pDev) && !IsFloating(pDev)) - return; - - (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); - free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); - dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); -} - - -/** - * Warp the pointer to the given position on the given screen. May generate - * an event, depending on whether we're coming from miPointerSetPosition. - * - * Once signals are ignored, the WarpCursor function can call this - * - * @param pDev The device to warp - * @param pScreen Screen to warp on - * @param x The x coordinate in per-screen coordinates - * @param y The y coordinate in per-screen coordinates - */ - -void -miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - miPointerPtr pPointer; - BOOL changedScreen = FALSE; - - SetupScreen (pScreen); - pPointer = MIPOINTER(pDev); - - if (pPointer->pScreen != pScreen) - { - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); - changedScreen = TRUE; - } - - if (pPointer->generateEvent) - miPointerMove (pDev, pScreen, x, y); - else - miPointerMoveNoEvent(pDev, pScreen, x, y); - - /* Don't call USFS if we use Xinerama, otherwise the root window is - * updated to the second screen, and we never receive any events. - * (FDO bug #18668) */ - if (changedScreen -#ifdef PANORAMIX - && noPanoramiXExtension -#endif - ) - UpdateSpriteForScreen (pDev, pScreen) ; -} - -/** - * Syncronize the sprite with the cursor. - * - * @param pDev The device to sync - */ -void -miPointerUpdateSprite (DeviceIntPtr pDev) -{ - ScreenPtr pScreen; - miPointerScreenPtr pScreenPriv; - CursorPtr pCursor; - int x, y, devx, devy; - miPointerPtr pPointer; - - if (!pDev || !pDev->coreEvents) - return; - - pPointer = MIPOINTER(pDev); - - if (!pPointer) - return; - - pScreen = pPointer->pScreen; - if (!pScreen) - return; - - x = pPointer->x; - y = pPointer->y; - devx = pPointer->devx; - devy = pPointer->devy; - - pScreenPriv = GetScreenPrivate (pScreen); - /* - * if the cursor has switched screens, disable the sprite - * on the old screen - */ - if (pScreen != pPointer->pSpriteScreen) - { - if (pPointer->pSpriteScreen) - { - miPointerScreenPtr pOldPriv; - - pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); - if (pPointer->pCursor) - { - (*pOldPriv->spriteFuncs->SetCursor) - (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); - } - (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); - } - (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); - (*pScreenPriv->spriteFuncs->SetCursor) - (pDev, pScreen, pPointer->pCursor, x, y); - pPointer->devx = x; - pPointer->devy = y; - pPointer->pSpriteCursor = pPointer->pCursor; - pPointer->pSpriteScreen = pScreen; - } - /* - * if the cursor has changed, display the new one - */ - else if (pPointer->pCursor != pPointer->pSpriteCursor) - { - pCursor = pPointer->pCursor; - if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) - pCursor = NullCursor; - (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); - - pPointer->devx = x; - pPointer->devy = y; - pPointer->pSpriteCursor = pPointer->pCursor; - } - else if (x != devx || y != devy) - { - pPointer->devx = x; - pPointer->devy = y; - if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); - } -} - -/** - * Set the device to the coordinates on the given screen. - * - * @param pDev The device to move - * @param screen_no Index of the screen to move to - * @param x The x coordinate in per-screen coordinates - * @param y The y coordinate in per-screen coordinates - */ -void -miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) -{ - miPointerScreenPtr pScreenPriv; - ScreenPtr pScreen; - miPointerPtr pPointer; - - pPointer = MIPOINTER(pDev); - - pScreen = screenInfo.screens[screen_no]; - pScreenPriv = GetScreenPrivate (pScreen); - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); - NewCurrentScreen (pDev, pScreen, x, y); - - pPointer->limits.x2 = pScreen->width; - pPointer->limits.y2 = pScreen->height; -} - -/** - * @return The current screen of the VCP - */ -ScreenPtr -miPointerCurrentScreen (void) -{ - return miPointerGetScreen(inputInfo.pointer); -} - -/** - * @return The current screen of the given device or NULL. - */ -ScreenPtr -miPointerGetScreen(DeviceIntPtr pDev) -{ - miPointerPtr pPointer = MIPOINTER(pDev); - return (pPointer) ? pPointer->pScreen : NULL; -} - -/* Controls whether the cursor image should be updated immediately when - moved (FALSE) or if something else will be responsible for updating - it later (TRUE). Returns current setting. - Caller is responsible for calling OsBlockSignal first. -*/ -Bool -miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) -{ - SetupScreen(pScreen); - Bool prevWait = pScreenPriv->waitForUpdate; - - pScreenPriv->waitForUpdate = wait; - return prevWait; -} - - -/* Move the pointer on the current screen, and update the sprite. */ -static void -miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y) -{ - miPointerPtr pPointer; - SetupScreen(pScreen); - - pPointer = MIPOINTER(pDev); - - /* Hack: We mustn't call into ->MoveCursor for anything but the - * VCP, as this may cause a non-HW rendered cursor to be rendered during - * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT. - */ - if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer - && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) - { - pPointer->devx = x; - pPointer->devy = y; - if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); - } - - pPointer->x = x; - pPointer->y = y; - pPointer->pScreen = pScreen; -} - -/** - * Set the devices' cursor position to the given x/y position. - * - * This function is called during the pointer update path in - * GetPointerEvents and friends (and the same in the xwin DDX). - * - * @param pDev The device to move - * @param[in,out] x The x coordiante in screen coordinates (in regards to total - * desktop size) - * @param[in,out] y The y coordiante in screen coordinates (in regards to total - * desktop size) - */ -void -miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y) -{ - miPointerScreenPtr pScreenPriv; - ScreenPtr pScreen; - ScreenPtr newScreen; - - miPointerPtr pPointer; - - if (!pDev || !pDev->coreEvents) - return; - - pPointer = MIPOINTER(pDev); - pScreen = pPointer->pScreen; - if (!pScreen) - return; /* called before ready */ - - if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) - { - pScreenPriv = GetScreenPrivate (pScreen); - if (!pPointer->confined) - { - newScreen = pScreen; - (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); - if (newScreen != pScreen) - { - pScreen = newScreen; - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, - FALSE); - pScreenPriv = GetScreenPrivate (pScreen); - /* Smash the confine to the new screen */ - pPointer->limits.x2 = pScreen->width; - pPointer->limits.y2 = pScreen->height; - } - } - } - /* Constrain the sprite to the current limits. */ - if (*x < pPointer->limits.x1) - *x = pPointer->limits.x1; - if (*x >= pPointer->limits.x2) - *x = pPointer->limits.x2 - 1; - if (*y < pPointer->limits.y1) - *y = pPointer->limits.y1; - if (*y >= pPointer->limits.y2) - *y = pPointer->limits.y2 - 1; - - if (pPointer->x == *x && pPointer->y == *y && - pPointer->pScreen == pScreen) - return; - - miPointerMoveNoEvent(pDev, pScreen, *x, *y); -} - -/** - * Get the current position of the device in desktop coordinates. - * - * @param x Return value for the current x coordinate in desktop coordiates. - * @param y Return value for the current y coordinate in desktop coordiates. - */ -void -miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) -{ - *x = MIPOINTER(pDev)->x; - *y = MIPOINTER(pDev)->y; -} - -#ifdef XQUARTZ -#include -void darwinEvents_lock(void); -void darwinEvents_unlock(void); -#endif - -/** - * Move the device's pointer to the x/y coordinates on the given screen. - * This function generates and enqueues pointer events. - * - * @param pDev The device to move - * @param pScreen The screen the device is on - * @param x The x coordinate in per-screen coordinates - * @param y The y coordinate in per-screen coordinates - */ -void -miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - int i, nevents; - int valuators[2]; - ValuatorMask mask; - - miPointerMoveNoEvent(pDev, pScreen, x, y); - - /* generate motion notify */ - valuators[0] = x; - valuators[1] = y; - - if (!events) - { - events = InitEventList(GetMaximumEventsNum()); - - if (!events) - { - FatalError("Could not allocate event store.\n"); - return; - } - } - - valuator_mask_set_range(&mask, 0, 2, valuators); - nevents = GetPointerEvents(events, pDev, MotionNotify, 0, - POINTER_SCREEN | POINTER_ABSOLUTE, &mask); - - OsBlockSignals(); -#ifdef XQUARTZ - darwinEvents_lock(); -#endif - for (i = 0; i < nevents; i++) - mieqEnqueue(pDev, (InternalEvent*)events[i].event); -#ifdef XQUARTZ - darwinEvents_unlock(); -#endif - OsReleaseSignals(); -} +/* + +Copyright 1989, 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. +*/ + +/** + * @file + * This file contains functions to move the pointer on the screen and/or + * restrict its movement. These functions are divided into two sets: + * Screen-specific functions that are used as function pointers from other + * parts of the server (and end up heavily wrapped by e.g. animcur and + * xfixes): + * miPointerConstrainCursor + * miPointerCursorLimits + * miPointerDisplayCursor + * miPointerRealizeCursor + * miPointerUnrealizeCursor + * miPointerSetCursorPosition + * miRecolorCursor + * miPointerDeviceInitialize + * miPointerDeviceCleanup + * If wrapped, these are the last element in the wrapping chain. They may + * call into sprite-specific code through further function pointers though. + * + * The second type of functions are those that are directly called by the + * DIX, DDX and some drivers. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +# include +# include +# include +# include "misc.h" +# include "windowstr.h" +# include "pixmapstr.h" +# include "mi.h" +# include "scrnintstr.h" +# include "mipointrst.h" +# include "cursorstr.h" +# include "dixstruct.h" +# include "inputstr.h" +# include "inpututils.h" + +DevPrivateKeyRec miPointerScreenKeyRec; + +#define GetScreenPrivate(s) ((miPointerScreenPtr) \ + dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) +#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) + +DevPrivateKeyRec miPointerPrivKeyRec; + +#define MIPOINTER(dev) \ + (IsFloating(dev) ? \ + (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ + (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) + +static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + BoxPtr pBox); +static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, BoxPtr pHotBox, + BoxPtr pTopLeftBox); +static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, + Bool generateEvent); +static Bool miPointerCloseScreen(int index, ScreenPtr pScreen); +static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); +static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); +static void miPointerDeviceCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); + +static EventList* events; /* for WarpPointer MotionNotifies */ + +Bool +miPointerInitialize (ScreenPtr pScreen, + miPointerSpriteFuncPtr spriteFuncs, + miPointerScreenFuncPtr screenFuncs, + Bool waitForUpdate) +{ + miPointerScreenPtr pScreenPriv; + + if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) + return FALSE; + + pScreenPriv = malloc(sizeof (miPointerScreenRec)); + if (!pScreenPriv) + return FALSE; + pScreenPriv->spriteFuncs = spriteFuncs; + pScreenPriv->screenFuncs = screenFuncs; + /* + * check for uninitialized methods + */ + if (!screenFuncs->EnqueueEvent) + screenFuncs->EnqueueEvent = mieqEnqueue; + if (!screenFuncs->NewEventScreen) + screenFuncs->NewEventScreen = mieqSwitchScreen; + pScreenPriv->waitForUpdate = waitForUpdate; + pScreenPriv->showTransparent = FALSE; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = miPointerCloseScreen; + dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); + /* + * set up screen cursor method table + */ + pScreen->ConstrainCursor = miPointerConstrainCursor; + pScreen->CursorLimits = miPointerCursorLimits; + pScreen->DisplayCursor = miPointerDisplayCursor; + pScreen->RealizeCursor = miPointerRealizeCursor; + pScreen->UnrealizeCursor = miPointerUnrealizeCursor; + pScreen->SetCursorPosition = miPointerSetCursorPosition; + pScreen->RecolorCursor = miRecolorCursor; + pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; + pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; + + events = NULL; + return TRUE; +} + +/** + * Destroy screen-specific information. + * + * @param index Screen index of the screen in screenInfo.screens[] + * @param pScreen The actual screen pointer + */ +static Bool +miPointerCloseScreen (int index, ScreenPtr pScreen) +{ + SetupScreen(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + free((pointer) pScreenPriv); + FreeEventList(events, GetMaximumEventsNum()); + events = NULL; + return (*pScreen->CloseScreen) (index, pScreen); +} + +/* + * DIX/DDX interface routines + */ + +static Bool +miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupScreen(pScreen); + return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); +} + +static Bool +miPointerUnrealizeCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + SetupScreen(pScreen); + return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); +} + +static Bool +miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + miPointerPtr pPointer; + + /* return for keyboards */ + if (!IsPointerDevice(pDev)) + return FALSE; + + pPointer = MIPOINTER(pDev); + + pPointer->pCursor = pCursor; + pPointer->pScreen = pScreen; + miPointerUpdateSprite(pDev); + return TRUE; +} + +/** + * Set up the constraints for the given device. This function does not + * actually constrain the cursor but merely copies the given box to the + * internal constraint storage. + * + * @param pDev The device to constrain to the box + * @param pBox The rectangle to constrain the cursor to + * @param pScreen Used for copying screen confinement + */ +static void +miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) +{ + miPointerPtr pPointer; + + pPointer = MIPOINTER(pDev); + + pPointer->limits = *pBox; + pPointer->confined = PointerConfinedToScreen(pDev); +} + +/** + * Should calculate the box for the given cursor, based on screen and the + * confinement given. But we assume that whatever box is passed in is valid + * anyway. + * + * @param pDev The device to calculate the cursor limits for + * @param pScreen The screen the confinement happens on + * @param pCursor The screen the confinement happens on + * @param pHotBox The confinement box for the cursor + * @param[out] pTopLeftBox The new confinement box, always *pHotBox. + */ +static void +miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, + BoxPtr pHotBox, BoxPtr pTopLeftBox) +{ + *pTopLeftBox = *pHotBox; +} + +/** + * Set the device's cursor position to the x/y position on the given screen. + * Generates and event if required. + * + * This function is called from: + * - sprite init code to place onto initial position + * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…) + * - during the cursor update path in CheckMotion + * - in the Xinerama part of NewCurrentScreen + * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so + * it's set back to the original pos) + * + * @param pDev The device to move + * @param pScreen The screen the device is on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + * @param generateEvent True if the pointer movement should generate an + * event. + * + * @return TRUE in all cases + */ +static Bool +miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, Bool generateEvent) +{ + SetupScreen (pScreen); + miPointerPtr pPointer = MIPOINTER(pDev); + + pPointer->generateEvent = generateEvent; + + if (pScreen->ConstrainCursorHarder) + pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y); + + /* device dependent - must pend signal and call miPointerWarpCursor */ + (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); + if (!generateEvent) + miPointerUpdateSprite(pDev); + return TRUE; +} + +/** + * Set up sprite information for the device. + * This function will be called once for each device after it is initialized + * in the DIX. + * + * @param pDev The newly created device + * @param pScreen The initial sprite scree. + */ +static Bool +miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miPointerPtr pPointer; + SetupScreen (pScreen); + + pPointer = malloc(sizeof(miPointerRec)); + if (!pPointer) + return FALSE; + + pPointer->pScreen = NULL; + pPointer->pSpriteScreen = NULL; + pPointer->pCursor = NULL; + pPointer->pSpriteCursor = NULL; + pPointer->limits.x1 = 0; + pPointer->limits.x2 = 32767; + pPointer->limits.y1 = 0; + pPointer->limits.y2 = 32767; + pPointer->confined = FALSE; + pPointer->x = 0; + pPointer->y = 0; + pPointer->generateEvent = FALSE; + + if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) + { + free(pPointer); + return FALSE; + } + + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); + return TRUE; +} + +/** + * Clean up after device. + * This function will be called once before the device is freed in the DIX + * + * @param pDev The device to be removed from the server + * @param pScreen Current screen of the device + */ +static void +miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + SetupScreen(pScreen); + + if (!IsMaster(pDev) && !IsFloating(pDev)) + return; + + (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); + free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); +} + + +/** + * Warp the pointer to the given position on the given screen. May generate + * an event, depending on whether we're coming from miPointerSetPosition. + * + * Once signals are ignored, the WarpCursor function can call this + * + * @param pDev The device to warp + * @param pScreen Screen to warp on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ + +void +miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + miPointerPtr pPointer; + BOOL changedScreen = FALSE; + + SetupScreen (pScreen); + pPointer = MIPOINTER(pDev); + + if (pPointer->pScreen != pScreen) + { + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); + changedScreen = TRUE; + } + + if (pPointer->generateEvent) + miPointerMove (pDev, pScreen, x, y); + else + miPointerMoveNoEvent(pDev, pScreen, x, y); + + /* Don't call USFS if we use Xinerama, otherwise the root window is + * updated to the second screen, and we never receive any events. + * (FDO bug #18668) */ + if (changedScreen +#ifdef PANORAMIX + && noPanoramiXExtension +#endif + ) + UpdateSpriteForScreen (pDev, pScreen) ; +} + +/** + * Syncronize the sprite with the cursor. + * + * @param pDev The device to sync + */ +void +miPointerUpdateSprite (DeviceIntPtr pDev) +{ + ScreenPtr pScreen; + miPointerScreenPtr pScreenPriv; + CursorPtr pCursor; + int x, y, devx, devy; + miPointerPtr pPointer; + + if (!pDev || !pDev->coreEvents) + return; + + pPointer = MIPOINTER(pDev); + + if (!pPointer) + return; + + pScreen = pPointer->pScreen; + if (!pScreen) + return; + + x = pPointer->x; + y = pPointer->y; + devx = pPointer->devx; + devy = pPointer->devy; + + pScreenPriv = GetScreenPrivate (pScreen); + /* + * if the cursor has switched screens, disable the sprite + * on the old screen + */ + if (pScreen != pPointer->pSpriteScreen) + { + if (pPointer->pSpriteScreen) + { + miPointerScreenPtr pOldPriv; + + pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); + if (pPointer->pCursor) + { + (*pOldPriv->spriteFuncs->SetCursor) + (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); + } + (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); + } + (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); + (*pScreenPriv->spriteFuncs->SetCursor) + (pDev, pScreen, pPointer->pCursor, x, y); + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + pPointer->pSpriteScreen = pScreen; + } + /* + * if the cursor has changed, display the new one + */ + else if (pPointer->pCursor != pPointer->pSpriteCursor) + { + pCursor = pPointer->pCursor; + if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) + pCursor = NullCursor; + (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); + + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + } + else if (x != devx || y != devy) + { + pPointer->devx = x; + pPointer->devy = y; + if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); + } +} + +/** + * Set the device to the coordinates on the given screen. + * + * @param pDev The device to move + * @param screen_no Index of the screen to move to + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ +void +miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + miPointerPtr pPointer; + + pPointer = MIPOINTER(pDev); + + pScreen = screenInfo.screens[screen_no]; + pScreenPriv = GetScreenPrivate (pScreen); + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); + NewCurrentScreen (pDev, pScreen, x, y); + + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; +} + +/** + * @return The current screen of the VCP + */ +ScreenPtr +miPointerCurrentScreen (void) +{ + return miPointerGetScreen(inputInfo.pointer); +} + +/** + * @return The current screen of the given device or NULL. + */ +ScreenPtr +miPointerGetScreen(DeviceIntPtr pDev) +{ + miPointerPtr pPointer = MIPOINTER(pDev); + return (pPointer) ? pPointer->pScreen : NULL; +} + +/* Controls whether the cursor image should be updated immediately when + moved (FALSE) or if something else will be responsible for updating + it later (TRUE). Returns current setting. + Caller is responsible for calling OsBlockSignal first. +*/ +Bool +miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) +{ + SetupScreen(pScreen); + Bool prevWait = pScreenPriv->waitForUpdate; + + pScreenPriv->waitForUpdate = wait; + return prevWait; +} + + +/* Move the pointer on the current screen, and update the sprite. */ +static void +miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y) +{ + miPointerPtr pPointer; + SetupScreen(pScreen); + + pPointer = MIPOINTER(pDev); + + /* Hack: We mustn't call into ->MoveCursor for anything but the + * VCP, as this may cause a non-HW rendered cursor to be rendered during + * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT. + */ + if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer + && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) + { + pPointer->devx = x; + pPointer->devy = y; + if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); + } + + pPointer->x = x; + pPointer->y = y; + pPointer->pScreen = pScreen; +} + +/** + * Set the devices' cursor position to the given x/y position. + * + * This function is called during the pointer update path in + * GetPointerEvents and friends (and the same in the xwin DDX). + * + * The coordinates provided are always absolute. The parameter mode whether + * it was relative or absolute movement that landed us at those coordinates. + * + * @param pDev The device to move + * @param mode Movement mode (Absolute or Relative) + * @param[in,out] x The x coordiante in screen coordinates (in regards to total + * desktop size) + * @param[in,out] y The y coordiante in screen coordinates (in regards to total + * desktop size) + */ +void +miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y) +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + ScreenPtr newScreen; + + miPointerPtr pPointer; + + if (!pDev || !pDev->coreEvents) + return; + + pPointer = MIPOINTER(pDev); + pScreen = pPointer->pScreen; + if (!pScreen) + return; /* called before ready */ + + if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) + { + pScreenPriv = GetScreenPrivate (pScreen); + if (!pPointer->confined) + { + newScreen = pScreen; + (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); + if (newScreen != pScreen) + { + pScreen = newScreen; + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, + FALSE); + pScreenPriv = GetScreenPrivate (pScreen); + /* Smash the confine to the new screen */ + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; + } + } + } + /* Constrain the sprite to the current limits. */ + if (*x < pPointer->limits.x1) + *x = pPointer->limits.x1; + if (*x >= pPointer->limits.x2) + *x = pPointer->limits.x2 - 1; + if (*y < pPointer->limits.y1) + *y = pPointer->limits.y1; + if (*y >= pPointer->limits.y2) + *y = pPointer->limits.y2 - 1; + + if (pScreen->ConstrainCursorHarder) + pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y); + + if (pPointer->x == *x && pPointer->y == *y && + pPointer->pScreen == pScreen) + return; + + miPointerMoveNoEvent(pDev, pScreen, *x, *y); +} + +/** + * Get the current position of the device in desktop coordinates. + * + * @param x Return value for the current x coordinate in desktop coordiates. + * @param y Return value for the current y coordinate in desktop coordiates. + */ +void +miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) +{ + *x = MIPOINTER(pDev)->x; + *y = MIPOINTER(pDev)->y; +} + +#ifdef XQUARTZ +#include +void darwinEvents_lock(void); +void darwinEvents_unlock(void); +#endif + +/** + * Move the device's pointer to the x/y coordinates on the given screen. + * This function generates and enqueues pointer events. + * + * @param pDev The device to move + * @param pScreen The screen the device is on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ +void +miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + int i, nevents; + int valuators[2]; + ValuatorMask mask; + + miPointerMoveNoEvent(pDev, pScreen, x, y); + + /* generate motion notify */ + valuators[0] = x; + valuators[1] = y; + + if (!events) + { + events = InitEventList(GetMaximumEventsNum()); + + if (!events) + { + FatalError("Could not allocate event store.\n"); + return; + } + } + + valuator_mask_set_range(&mask, 0, 2, valuators); + nevents = GetPointerEvents(events, pDev, MotionNotify, 0, + POINTER_SCREEN | POINTER_ABSOLUTE, &mask); + + OsBlockSignals(); +#ifdef XQUARTZ + darwinEvents_lock(); +#endif + for (i = 0; i < nevents; i++) + mieqEnqueue(pDev, (InternalEvent*)events[i].event); +#ifdef XQUARTZ + darwinEvents_unlock(); +#endif + OsReleaseSignals(); +} diff --git a/xorg-server/mi/mipointer.h b/xorg-server/mi/mipointer.h index caf505019..426ef1650 100644 --- a/xorg-server/mi/mipointer.h +++ b/xorg-server/mi/mipointer.h @@ -133,6 +133,7 @@ extern _X_EXPORT void miPointerGetPosition( * x and y are modified in-place. */ extern _X_EXPORT void miPointerSetPosition( DeviceIntPtr pDev, + int mode, int *x, int *y); diff --git a/xorg-server/mi/misprite.c b/xorg-server/mi/misprite.c index b0290af29..0b47592f0 100644 --- a/xorg-server/mi/misprite.c +++ b/xorg-server/mi/misprite.c @@ -1,1045 +1,1042 @@ -/* - * misprite.c - * - * machine independent software sprite routines - */ - -/* - -Copyright 1989, 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. -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "pixmapstr.h" -#include "input.h" -#include "mi.h" -#include "cursorstr.h" -#include -#include "scrnintstr.h" -#include "colormapst.h" -#include "windowstr.h" -#include "gcstruct.h" -#include "mipointer.h" -#include "misprite.h" -#include "dixfontstr.h" -#include -#include "inputstr.h" -#include "damage.h" - -typedef struct { - CursorPtr pCursor; - int x; /* cursor hotspot */ - int y; - BoxRec saved; /* saved area from the screen */ - Bool isUp; /* cursor in frame buffer */ - Bool shouldBeUp; /* cursor should be displayed */ - WindowPtr pCacheWin; /* window the cursor last seen in */ - Bool isInCacheWin; - Bool checkPixels; /* check colormap collision */ - ScreenPtr pScreen; -} miCursorInfoRec, *miCursorInfoPtr; - -/* - * per screen information - */ - -typedef struct { - /* screen procedures */ - CloseScreenProcPtr CloseScreen; - GetImageProcPtr GetImage; - GetSpansProcPtr GetSpans; - SourceValidateProcPtr SourceValidate; - - /* window procedures */ - CopyWindowProcPtr CopyWindow; - - /* colormap procedures */ - InstallColormapProcPtr InstallColormap; - StoreColorsProcPtr StoreColors; - - /* os layer procedures */ - ScreenBlockHandlerProcPtr BlockHandler; - - /* device cursor procedures */ - DeviceCursorInitializeProcPtr DeviceCursorInitialize; - DeviceCursorCleanupProcPtr DeviceCursorCleanup; - - xColorItem colors[2]; - ColormapPtr pInstalledMap; - ColormapPtr pColormap; - VisualPtr pVisual; - DamagePtr pDamage; /* damage tracking structure */ - Bool damageRegistered; - int numberOfCursors; -} miSpriteScreenRec, *miSpriteScreenPtr; - -#define SOURCE_COLOR 0 -#define MASK_COLOR 1 - -/* - * Overlap BoxPtr and Box elements - */ -#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ - (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ - ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) - -/* - * Overlap BoxPtr, origins, and rectangle - */ -#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ - BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) - -/* - * Overlap BoxPtr, origins and RectPtr - */ -#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ - ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ - (int)((pRect)->width), (int)((pRect)->height)) -/* - * Overlap BoxPtr and horizontal span - */ -#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) - -#define LINE_SORT(x1,y1,x2,y2) \ -{ int _t; \ - if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ - if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } - -#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ - BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) - - -#define SPRITE_DEBUG_ENABLE 0 -#if SPRITE_DEBUG_ENABLE -#define SPRITE_DEBUG(x) ErrorF x -#else -#define SPRITE_DEBUG(x) -#endif - -#define MISPRITE(dev) \ - (IsFloating(dev) ? \ - (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \ - (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey)) - -static void -miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) -{ - if (pScreenPriv->damageRegistered) { - DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable), - pScreenPriv->pDamage); - pScreenPriv->damageRegistered = 0; - } -} - -static void -miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) -{ - if (!pScreenPriv->damageRegistered) { - pScreenPriv->damageRegistered = 1; - DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable), - pScreenPriv->pDamage); - } -} - -static void -miSpriteIsUp(miCursorInfoPtr pDevCursor) -{ - pDevCursor->isUp = TRUE; -} - -static void -miSpriteIsDown(miCursorInfoPtr pDevCursor) -{ - pDevCursor->isUp = FALSE; -} - -/* - * screen wrappers - */ - -static DevPrivateKeyRec miSpriteScreenKeyRec; -#define miSpriteScreenKey (&miSpriteScreenKeyRec) -#define GetSpriteScreen(pScreen) \ - (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey)) -static DevPrivateKeyRec miSpriteDevPrivatesKeyRec; -#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec) - -static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); -static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, - int w, int h, unsigned int format, - unsigned long planemask, char *pdstLine); -static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, - DDXPointPtr ppt, int *pwidth, int nspans, - char *pdstStart); -static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, - int width, int height, - unsigned int subWindowMode); -static void miSpriteCopyWindow (WindowPtr pWindow, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc); -static void miSpriteBlockHandler(int i, pointer blockData, - pointer pTimeout, - pointer pReadMask); -static void miSpriteInstallColormap(ColormapPtr pMap); -static void miSpriteStoreColors(ColormapPtr pMap, int ndef, - xColorItem *pdef); - -static void miSpriteComputeSaved(DeviceIntPtr pDev, - ScreenPtr pScreen); - -static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, - ScreenPtr pScreen); - -#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \ - (pPriv)->field) -#define SCREEN_EPILOGUE(pPriv, pScreen, field)\ - ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field) - -/* - * pointer-sprite method table - */ - -static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y); -static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y); - -miPointerSpriteFuncRec miSpritePointerFuncs = { - miSpriteRealizeCursor, - miSpriteUnrealizeCursor, - miSpriteSetCursor, - miSpriteMoveCursor, - miSpriteDeviceCursorInitialize, - miSpriteDeviceCursorCleanup, -}; - -/* - * other misc functions - */ - -static void miSpriteRemoveCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteRestoreCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); - -static void -miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) -{ - if (!pScreenPriv->BlockHandler) { - pScreenPriv->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = miSpriteBlockHandler; - } -} - -static void -miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) -{ - ScreenPtr pScreen = closure; - miCursorInfoPtr pCursorInfo; - DeviceIntPtr pDev; - - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - - if (pCursorInfo->isUp && - pCursorInfo->pScreen == pScreen && - RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) - { - SPRITE_DEBUG(("Damage remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } -} - -/* - * miSpriteInitialize -- called from device-dependent screen - * initialization proc after all of the function pointers have - * been stored in the screen structure. - */ - -Bool -miSpriteInitialize (ScreenPtr pScreen, - miPointerScreenFuncPtr screenFuncs) -{ - miSpriteScreenPtr pScreenPriv; - VisualPtr pVisual; - - if (!DamageSetup (pScreen)) - return FALSE; - - if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0)) - return FALSE; - - if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0)) - return FALSE; - - pScreenPriv = malloc(sizeof (miSpriteScreenRec)); - if (!pScreenPriv) - return FALSE; - - pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, - NULL, - DamageReportRawRegion, - TRUE, - pScreen, - pScreen); - - if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) - { - free(pScreenPriv); - return FALSE; - } - for (pVisual = pScreen->visuals; - pVisual->vid != pScreen->rootVisual; - pVisual++) - ; - pScreenPriv->pVisual = pVisual; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreenPriv->GetImage = pScreen->GetImage; - pScreenPriv->GetSpans = pScreen->GetSpans; - pScreenPriv->SourceValidate = pScreen->SourceValidate; - - pScreenPriv->CopyWindow = pScreen->CopyWindow; - - pScreenPriv->InstallColormap = pScreen->InstallColormap; - pScreenPriv->StoreColors = pScreen->StoreColors; - - pScreenPriv->BlockHandler = NULL; - - pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize; - pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup; - - pScreenPriv->pInstalledMap = NULL; - pScreenPriv->pColormap = NULL; - pScreenPriv->colors[SOURCE_COLOR].red = 0; - pScreenPriv->colors[SOURCE_COLOR].green = 0; - pScreenPriv->colors[SOURCE_COLOR].blue = 0; - pScreenPriv->colors[MASK_COLOR].red = 0; - pScreenPriv->colors[MASK_COLOR].green = 0; - pScreenPriv->colors[MASK_COLOR].blue = 0; - pScreenPriv->damageRegistered = 0; - pScreenPriv->numberOfCursors = 0; - - dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv); - - pScreen->CloseScreen = miSpriteCloseScreen; - pScreen->GetImage = miSpriteGetImage; - pScreen->GetSpans = miSpriteGetSpans; - pScreen->SourceValidate = miSpriteSourceValidate; - - pScreen->CopyWindow = miSpriteCopyWindow; - pScreen->InstallColormap = miSpriteInstallColormap; - pScreen->StoreColors = miSpriteStoreColors; - - return TRUE; -} - -/* - * Screen wrappers - */ - -/* - * CloseScreen wrapper -- unwrap everything, free the private data - * and call the wrapped function - */ - -static Bool -miSpriteCloseScreen (int i, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->GetImage = pScreenPriv->GetImage; - pScreen->GetSpans = pScreenPriv->GetSpans; - pScreen->SourceValidate = pScreenPriv->SourceValidate; - pScreen->InstallColormap = pScreenPriv->InstallColormap; - pScreen->StoreColors = pScreenPriv->StoreColors; - - DamageDestroy (pScreenPriv->pDamage); - - free(pScreenPriv); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static void -miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, - unsigned int format, unsigned long planemask, - char *pdstLine) -{ - ScreenPtr pScreen = pDrawable->pScreen; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE (pPriv, pScreen, GetImage); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, - sx, sy, w, h)) - { - SPRITE_DEBUG (("GetImage remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } - - (*pScreen->GetImage) (pDrawable, sx, sy, w, h, - format, planemask, pdstLine); - - SCREEN_EPILOGUE (pPriv, pScreen, GetImage); -} - -static void -miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, - int *pwidth, int nspans, char *pdstStart) -{ - ScreenPtr pScreen = pDrawable->pScreen; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE (pPriv, pScreen, GetSpans); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - { - DDXPointPtr pts; - int *widths; - int nPts; - int xorg, - yorg; - - xorg = pDrawable->x; - yorg = pDrawable->y; - - for (pts = ppt, widths = pwidth, nPts = nspans; - nPts--; - pts++, widths++) - { - if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg, - pts->x+xorg,*widths)) - { - SPRITE_DEBUG (("GetSpans remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - break; - } - } - } - } - } - } - - (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); - - SCREEN_EPILOGUE (pPriv, pScreen, GetSpans); -} - -static void -miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, - int height, unsigned int subWindowMode) -{ - ScreenPtr pScreen = pDrawable->pScreen; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, - x, y, width, height)) - { - SPRITE_DEBUG (("SourceValidate remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } - - if (pScreen->SourceValidate) - (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode); - - SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate); -} - -static void -miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow); - - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - /* - * Damage will take care of destination check - */ - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) - { - SPRITE_DEBUG (("CopyWindow remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - - (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); - SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow); -} - -static void -miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout, - pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[i]; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - Bool WorkToDo = FALSE; - - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo && !pCursorInfo->isUp - && pCursorInfo->pScreen == pScreen - && pCursorInfo->shouldBeUp) - { - SPRITE_DEBUG (("BlockHandler save")); - miSpriteSaveUnderCursor (pDev, pScreen); - } - } - } - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo && !pCursorInfo->isUp && - pCursorInfo->pScreen == pScreen && - pCursorInfo->shouldBeUp) - { - SPRITE_DEBUG (("BlockHandler restore\n")); - miSpriteRestoreCursor (pDev, pScreen); - if (!pCursorInfo->isUp) - WorkToDo = TRUE; - } - } - } - - SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler); - - (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); - - if (WorkToDo) - SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler); - else - pPriv->BlockHandler = NULL; -} - -static void -miSpriteInstallColormap (ColormapPtr pMap) -{ - ScreenPtr pScreen = pMap->pScreen; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap); - - (*pScreen->InstallColormap) (pMap); - - SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap); - - /* InstallColormap can be called before devices are initialized. */ - pPriv->pInstalledMap = pMap; - if (pPriv->pColormap != pMap) - { - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - pCursorInfo->checkPixels = TRUE; - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - miSpriteRemoveCursor(pDev, pScreen); - } - } - - } -} - -static void -miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) -{ - ScreenPtr pScreen = pMap->pScreen; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - int i; - int updated; - VisualPtr pVisual; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - - SCREEN_PROLOGUE(pPriv, pScreen, StoreColors); - - (*pScreen->StoreColors) (pMap, ndef, pdef); - - SCREEN_EPILOGUE(pPriv, pScreen, StoreColors); - - if (pPriv->pColormap == pMap) - { - updated = 0; - pVisual = pMap->pVisual; - if (pVisual->class == DirectColor) - { - /* Direct color - match on any of the subfields */ - -#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) - -#define UpdateDAC(dev, plane,dac,mask) {\ - if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ - dev->colors[plane].dac = pdef[i].dac; \ - updated = 1; \ - } \ -} - -#define CheckDirect(dev, plane) \ - UpdateDAC(dev, plane,red,redMask) \ - UpdateDAC(dev, plane,green,greenMask) \ - UpdateDAC(dev, plane,blue,blueMask) - - for (i = 0; i < ndef; i++) - { - CheckDirect (pPriv, SOURCE_COLOR) - CheckDirect (pPriv, MASK_COLOR) - } - } - else - { - /* PseudoColor/GrayScale - match on exact pixel */ - for (i = 0; i < ndef; i++) - { - if (pdef[i].pixel == - pPriv->colors[SOURCE_COLOR].pixel) - { - pPriv->colors[SOURCE_COLOR] = pdef[i]; - if (++updated == 2) - break; - } - if (pdef[i].pixel == - pPriv->colors[MASK_COLOR].pixel) - { - pPriv->colors[MASK_COLOR] = pdef[i]; - if (++updated == 2) - break; - } - } - } - if (updated) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - pCursorInfo->checkPixels = TRUE; - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } -} - -static void -miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); - CursorPtr pCursor; - xColorItem *sourceColor, *maskColor; - - pCursor = pDevCursor->pCursor; - sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; - maskColor = &pScreenPriv->colors[MASK_COLOR]; - if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || - !(pCursor->foreRed == sourceColor->red && - pCursor->foreGreen == sourceColor->green && - pCursor->foreBlue == sourceColor->blue && - pCursor->backRed == maskColor->red && - pCursor->backGreen == maskColor->green && - pCursor->backBlue == maskColor->blue)) - { - pScreenPriv->pColormap = pScreenPriv->pInstalledMap; - sourceColor->red = pCursor->foreRed; - sourceColor->green = pCursor->foreGreen; - sourceColor->blue = pCursor->foreBlue; - FakeAllocColor (pScreenPriv->pColormap, sourceColor); - maskColor->red = pCursor->backRed; - maskColor->green = pCursor->backGreen; - maskColor->blue = pCursor->backBlue; - FakeAllocColor (pScreenPriv->pColormap, maskColor); - /* "free" the pixels right away, don't let this confuse you */ - FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); - FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); - } - - pDevCursor->checkPixels = FALSE; - -} - -/* - * miPointer interface routines - */ - -#define SPRITE_PAD 8 - -static Bool -miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - miCursorInfoPtr pCursorInfo; - - if (IsFloating(pDev)) - return FALSE; - - pCursorInfo = MISPRITE(pDev); - - if (pCursor == pCursorInfo->pCursor) - pCursorInfo->checkPixels = TRUE; - - return miDCRealizeCursor(pScreen, pCursor); -} - -static Bool -miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - return miDCUnrealizeCursor(pScreen, pCursor); -} - -static void -miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y) -{ - miCursorInfoPtr pPointer; - miSpriteScreenPtr pScreenPriv; - - if (IsFloating(pDev)) - return; - - pPointer = MISPRITE(pDev); - pScreenPriv = GetSpriteScreen(pScreen); - - if (!pCursor) - { - if (pPointer->shouldBeUp) - --pScreenPriv->numberOfCursors; - pPointer->shouldBeUp = FALSE; - if (pPointer->isUp) - miSpriteRemoveCursor (pDev, pScreen); - if (pScreenPriv->numberOfCursors == 0) - miSpriteDisableDamage(pScreen, pScreenPriv); - pPointer->pCursor = 0; - return; - } - if (!pPointer->shouldBeUp) - pScreenPriv->numberOfCursors++; - pPointer->shouldBeUp = TRUE; - if (!pPointer->isUp) - miSpriteRegisterBlockHandler(pScreen, pScreenPriv); - if (pPointer->x == x && - pPointer->y == y && - pPointer->pCursor == pCursor && - !pPointer->checkPixels) - { - return; - } - pPointer->x = x; - pPointer->y = y; - pPointer->pCacheWin = NullWindow; - if (pPointer->checkPixels || pPointer->pCursor != pCursor) - { - pPointer->pCursor = pCursor; - miSpriteFindColors (pPointer, pScreen); - } - if (pPointer->isUp) { - /* TODO: reimplement flicker-free MoveCursor */ - SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id)); - miSpriteRemoveCursor (pDev, pScreen); - } - - if (!pPointer->isUp && pPointer->pCursor) - { - SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id)); - miSpriteSaveUnderCursor(pDev, pScreen); - miSpriteRestoreCursor (pDev, pScreen); - } - -} - -static void -miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - CursorPtr pCursor; - - if (IsFloating(pDev)) - return; - - pCursor = MISPRITE(pDev)->pCursor; - - miSpriteSetCursor (pDev, pScreen, pCursor, x, y); -} - - -static Bool -miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miCursorInfoPtr pCursorInfo; - int ret = FALSE; - - pCursorInfo = malloc(sizeof(miCursorInfoRec)); - if (!pCursorInfo) - return FALSE; - - pCursorInfo->pCursor = NULL; - pCursorInfo->x = 0; - pCursorInfo->y = 0; - pCursorInfo->isUp = FALSE; - pCursorInfo->shouldBeUp = FALSE; - pCursorInfo->pCacheWin = NullWindow; - pCursorInfo->isInCacheWin = FALSE; - pCursorInfo->checkPixels = TRUE; - pCursorInfo->pScreen = FALSE; - - ret = miDCDeviceInitialize(pDev, pScreen); - if (!ret) - { - free(pCursorInfo); - pCursorInfo = NULL; - } - dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo); - return ret; -} - -static void -miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - if (DevHasCursor(pDev)) - miDCDeviceCleanup(pDev, pScreen); -} - -/* - * undraw/draw cursor - */ - -static void -miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - miCursorInfoPtr pCursorInfo; - - - if (IsFloating(pDev)) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = GetSpriteScreen(pScreen); - pCursorInfo = MISPRITE(pDev); - - miSpriteIsDown(pCursorInfo); - miSpriteRegisterBlockHandler(pScreen, pScreenPriv); - pCursorInfo->pCacheWin = NullWindow; - miSpriteDisableDamage(pScreen, pScreenPriv); - if (!miDCRestoreUnderCursor(pDev, - pScreen, - pCursorInfo->saved.x1, - pCursorInfo->saved.y1, - pCursorInfo->saved.x2 - - pCursorInfo->saved.x1, - pCursorInfo->saved.y2 - - pCursorInfo->saved.y1)) - { - miSpriteIsUp(pCursorInfo); - } - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - -/* - * Called from the block handler, saves area under cursor - * before waiting for something to do. - */ - -static void -miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - int x, y; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (IsFloating(pDev)) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = GetSpriteScreen(pScreen); - pCursorInfo = MISPRITE(pDev); - - miSpriteComputeSaved (pDev, pScreen); - pCursor = pCursorInfo->pCursor; - - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - miSpriteDisableDamage(pScreen, pScreenPriv); - - miDCSaveUnderCursor(pDev, - pScreen, - pCursorInfo->saved.x1, - pCursorInfo->saved.y1, - pCursorInfo->saved.x2 - - pCursorInfo->saved.x1, - pCursorInfo->saved.y2 - - pCursorInfo->saved.y1); - SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - - -/* - * Called from the block handler, restores the cursor - * before waiting for something to do. - */ - -static void -miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - int x, y; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (IsFloating(pDev)) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = GetSpriteScreen(pScreen); - pCursorInfo = MISPRITE(pDev); - - miSpriteComputeSaved (pDev, pScreen); - pCursor = pCursorInfo->pCursor; - - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - miSpriteDisableDamage(pScreen, pScreenPriv); - SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); - if (pCursorInfo->checkPixels) - miSpriteFindColors (pCursorInfo, pScreen); - if (miDCPutUpCursor(pDev, pScreen, - pCursor, x, y, - pScreenPriv->colors[SOURCE_COLOR].pixel, - pScreenPriv->colors[MASK_COLOR].pixel)) - { - miSpriteIsUp(pCursorInfo); - pCursorInfo->pScreen = pScreen; - } - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - -/* - * compute the desired area of the screen to save - */ - -static void -miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - int x, y, w, h; - int wpad, hpad; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (IsFloating(pDev)) - return; - - pCursorInfo = MISPRITE(pDev); - - pCursor = pCursorInfo->pCursor; - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - w = pCursor->bits->width; - h = pCursor->bits->height; - wpad = SPRITE_PAD; - hpad = SPRITE_PAD; - pCursorInfo->saved.x1 = x - wpad; - pCursorInfo->saved.y1 = y - hpad; - pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; - pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; -} - +/* + * misprite.c + * + * machine independent software sprite routines + */ + +/* + +Copyright 1989, 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. +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "pixmapstr.h" +#include "input.h" +#include "mi.h" +#include "cursorstr.h" +#include +#include "scrnintstr.h" +#include "colormapst.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "mipointer.h" +#include "misprite.h" +#include "dixfontstr.h" +#include +#include "inputstr.h" +#include "damage.h" + +typedef struct { + CursorPtr pCursor; + int x; /* cursor hotspot */ + int y; + BoxRec saved; /* saved area from the screen */ + Bool isUp; /* cursor in frame buffer */ + Bool shouldBeUp; /* cursor should be displayed */ + WindowPtr pCacheWin; /* window the cursor last seen in */ + Bool isInCacheWin; + Bool checkPixels; /* check colormap collision */ + ScreenPtr pScreen; +} miCursorInfoRec, *miCursorInfoPtr; + +/* + * per screen information + */ + +typedef struct { + /* screen procedures */ + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + SourceValidateProcPtr SourceValidate; + + /* window procedures */ + CopyWindowProcPtr CopyWindow; + + /* colormap procedures */ + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + + /* os layer procedures */ + ScreenBlockHandlerProcPtr BlockHandler; + + /* device cursor procedures */ + DeviceCursorInitializeProcPtr DeviceCursorInitialize; + DeviceCursorCleanupProcPtr DeviceCursorCleanup; + + xColorItem colors[2]; + ColormapPtr pInstalledMap; + ColormapPtr pColormap; + VisualPtr pVisual; + DamagePtr pDamage; /* damage tracking structure */ + Bool damageRegistered; + int numberOfCursors; +} miSpriteScreenRec, *miSpriteScreenPtr; + +#define SOURCE_COLOR 0 +#define MASK_COLOR 1 + +/* + * Overlap BoxPtr and Box elements + */ +#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ + (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ + ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) + +/* + * Overlap BoxPtr, origins, and rectangle + */ +#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ + BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) + +/* + * Overlap BoxPtr, origins and RectPtr + */ +#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ + ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ + (int)((pRect)->width), (int)((pRect)->height)) +/* + * Overlap BoxPtr and horizontal span + */ +#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) + +#define LINE_SORT(x1,y1,x2,y2) \ +{ int _t; \ + if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ + if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } + +#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ + BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) + + +#define SPRITE_DEBUG_ENABLE 0 +#if SPRITE_DEBUG_ENABLE +#define SPRITE_DEBUG(x) ErrorF x +#else +#define SPRITE_DEBUG(x) +#endif + +#define MISPRITE(dev) \ + (IsFloating(dev) ? \ + (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \ + (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey)) + +static void +miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (pScreenPriv->damageRegistered) { + DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable), + pScreenPriv->pDamage); + pScreenPriv->damageRegistered = 0; + } +} + +static void +miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (!pScreenPriv->damageRegistered) { + pScreenPriv->damageRegistered = 1; + DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable), + pScreenPriv->pDamage); + } +} + +static void +miSpriteIsUp(miCursorInfoPtr pDevCursor) +{ + pDevCursor->isUp = TRUE; +} + +static void +miSpriteIsDown(miCursorInfoPtr pDevCursor) +{ + pDevCursor->isUp = FALSE; +} + +/* + * screen wrappers + */ + +static DevPrivateKeyRec miSpriteScreenKeyRec; +#define miSpriteScreenKey (&miSpriteScreenKeyRec) +#define GetSpriteScreen(pScreen) \ + (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey)) +static DevPrivateKeyRec miSpriteDevPrivatesKeyRec; +#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec) + +static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); +static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, + int w, int h, unsigned int format, + unsigned long planemask, char *pdstLine); +static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, + char *pdstStart); +static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, + int width, int height, + unsigned int subWindowMode); +static void miSpriteCopyWindow (WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); +static void miSpriteBlockHandler(int i, pointer blockData, + pointer pTimeout, + pointer pReadMask); +static void miSpriteInstallColormap(ColormapPtr pMap); +static void miSpriteStoreColors(ColormapPtr pMap, int ndef, + xColorItem *pdef); + +static void miSpriteComputeSaved(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); + +#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \ + (pPriv)->field) +#define SCREEN_EPILOGUE(pPriv, pScreen, field)\ + ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field) + +/* + * pointer-sprite method table + */ + +static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y); +static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); + +miPointerSpriteFuncRec miSpritePointerFuncs = { + miSpriteRealizeCursor, + miSpriteUnrealizeCursor, + miSpriteSetCursor, + miSpriteMoveCursor, + miSpriteDeviceCursorInitialize, + miSpriteDeviceCursorCleanup, +}; + +/* + * other misc functions + */ + +static void miSpriteRemoveCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteRestoreCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static void +miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (!pScreenPriv->BlockHandler) { + pScreenPriv->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = miSpriteBlockHandler; + } +} + +static void +miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + ScreenPtr pScreen = closure; + miCursorInfoPtr pCursorInfo; + DeviceIntPtr pDev; + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG(("Damage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } +} + +/* + * miSpriteInitialize -- called from device-dependent screen + * initialization proc after all of the function pointers have + * been stored in the screen structure. + */ + +Bool +miSpriteInitialize (ScreenPtr pScreen, + miPointerScreenFuncPtr screenFuncs) +{ + miSpriteScreenPtr pScreenPriv; + VisualPtr pVisual; + + if (!DamageSetup (pScreen)) + return FALSE; + + if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, sizeof(miCursorInfoRec))) + return FALSE; + + pScreenPriv = malloc(sizeof (miSpriteScreenRec)); + if (!pScreenPriv) + return FALSE; + + pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, + NULL, + DamageReportRawRegion, + TRUE, + pScreen, + pScreen); + + if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) + { + free(pScreenPriv); + return FALSE; + } + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + pScreenPriv->pVisual = pVisual; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreenPriv->GetImage = pScreen->GetImage; + pScreenPriv->GetSpans = pScreen->GetSpans; + pScreenPriv->SourceValidate = pScreen->SourceValidate; + + pScreenPriv->CopyWindow = pScreen->CopyWindow; + + pScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreenPriv->StoreColors = pScreen->StoreColors; + + pScreenPriv->BlockHandler = NULL; + + pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize; + pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup; + + pScreenPriv->pInstalledMap = NULL; + pScreenPriv->pColormap = NULL; + pScreenPriv->colors[SOURCE_COLOR].red = 0; + pScreenPriv->colors[SOURCE_COLOR].green = 0; + pScreenPriv->colors[SOURCE_COLOR].blue = 0; + pScreenPriv->colors[MASK_COLOR].red = 0; + pScreenPriv->colors[MASK_COLOR].green = 0; + pScreenPriv->colors[MASK_COLOR].blue = 0; + pScreenPriv->damageRegistered = 0; + pScreenPriv->numberOfCursors = 0; + + dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv); + + pScreen->CloseScreen = miSpriteCloseScreen; + pScreen->GetImage = miSpriteGetImage; + pScreen->GetSpans = miSpriteGetSpans; + pScreen->SourceValidate = miSpriteSourceValidate; + + pScreen->CopyWindow = miSpriteCopyWindow; + pScreen->InstallColormap = miSpriteInstallColormap; + pScreen->StoreColors = miSpriteStoreColors; + + return TRUE; +} + +/* + * Screen wrappers + */ + +/* + * CloseScreen wrapper -- unwrap everything, free the private data + * and call the wrapped function + */ + +static Bool +miSpriteCloseScreen (int i, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->SourceValidate = pScreenPriv->SourceValidate; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->StoreColors = pScreenPriv->StoreColors; + + DamageDestroy (pScreenPriv->pDamage); + + free(pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planemask, + char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, GetImage); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, + sx, sy, w, h)) + { + SPRITE_DEBUG (("GetImage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } + + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, + format, planemask, pdstLine); + + SCREEN_EPILOGUE (pPriv, pScreen, GetImage); +} + +static void +miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, + int *pwidth, int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, GetSpans); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + { + DDXPointPtr pts; + int *widths; + int nPts; + int xorg, + yorg; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + for (pts = ppt, widths = pwidth, nPts = nspans; + nPts--; + pts++, widths++) + { + if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg, + pts->x+xorg,*widths)) + { + SPRITE_DEBUG (("GetSpans remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + break; + } + } + } + } + } + } + + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + + SCREEN_EPILOGUE (pPriv, pScreen, GetSpans); +} + +static void +miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, + int height, unsigned int subWindowMode) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, + x, y, width, height)) + { + SPRITE_DEBUG (("SourceValidate remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } + + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode); + + SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate); +} + +static void +miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow); + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + /* + * Damage will take care of destination check + */ + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG (("CopyWindow remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow); +} + +static void +miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + Bool WorkToDo = FALSE; + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo && !pCursorInfo->isUp + && pCursorInfo->pScreen == pScreen + && pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler save")); + miSpriteSaveUnderCursor (pDev, pScreen); + } + } + } + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo && !pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler restore\n")); + miSpriteRestoreCursor (pDev, pScreen); + if (!pCursorInfo->isUp) + WorkToDo = TRUE; + } + } + } + + SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler); + + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + if (WorkToDo) + SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler); + else + pPriv->BlockHandler = NULL; +} + +static void +miSpriteInstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap); + + (*pScreen->InstallColormap) (pMap); + + SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap); + + /* InstallColormap can be called before devices are initialized. */ + pPriv->pInstalledMap = pMap; + if (pPriv->pColormap != pMap) + { + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor(pDev, pScreen); + } + } + + } +} + +static void +miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + int i; + int updated; + VisualPtr pVisual; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + + SCREEN_PROLOGUE(pPriv, pScreen, StoreColors); + + (*pScreen->StoreColors) (pMap, ndef, pdef); + + SCREEN_EPILOGUE(pPriv, pScreen, StoreColors); + + if (pPriv->pColormap == pMap) + { + updated = 0; + pVisual = pMap->pVisual; + if (pVisual->class == DirectColor) + { + /* Direct color - match on any of the subfields */ + +#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) + +#define UpdateDAC(dev, plane,dac,mask) {\ + if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ + dev->colors[plane].dac = pdef[i].dac; \ + updated = 1; \ + } \ +} + +#define CheckDirect(dev, plane) \ + UpdateDAC(dev, plane,red,redMask) \ + UpdateDAC(dev, plane,green,greenMask) \ + UpdateDAC(dev, plane,blue,blueMask) + + for (i = 0; i < ndef; i++) + { + CheckDirect (pPriv, SOURCE_COLOR) + CheckDirect (pPriv, MASK_COLOR) + } + } + else + { + /* PseudoColor/GrayScale - match on exact pixel */ + for (i = 0; i < ndef; i++) + { + if (pdef[i].pixel == + pPriv->colors[SOURCE_COLOR].pixel) + { + pPriv->colors[SOURCE_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + if (pdef[i].pixel == + pPriv->colors[MASK_COLOR].pixel) + { + pPriv->colors[MASK_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + } + } + if (updated) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } +} + +static void +miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); + CursorPtr pCursor; + xColorItem *sourceColor, *maskColor; + + pCursor = pDevCursor->pCursor; + sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; + maskColor = &pScreenPriv->colors[MASK_COLOR]; + if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || + !(pCursor->foreRed == sourceColor->red && + pCursor->foreGreen == sourceColor->green && + pCursor->foreBlue == sourceColor->blue && + pCursor->backRed == maskColor->red && + pCursor->backGreen == maskColor->green && + pCursor->backBlue == maskColor->blue)) + { + pScreenPriv->pColormap = pScreenPriv->pInstalledMap; + sourceColor->red = pCursor->foreRed; + sourceColor->green = pCursor->foreGreen; + sourceColor->blue = pCursor->foreBlue; + FakeAllocColor (pScreenPriv->pColormap, sourceColor); + maskColor->red = pCursor->backRed; + maskColor->green = pCursor->backGreen; + maskColor->blue = pCursor->backBlue; + FakeAllocColor (pScreenPriv->pColormap, maskColor); + /* "free" the pixels right away, don't let this confuse you */ + FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); + FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); + } + + pDevCursor->checkPixels = FALSE; + +} + +/* + * miPointer interface routines + */ + +#define SPRITE_PAD 8 + +static Bool +miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return FALSE; + + pCursorInfo = MISPRITE(pDev); + + if (pCursor == pCursorInfo->pCursor) + pCursorInfo->checkPixels = TRUE; + + return miDCRealizeCursor(pScreen, pCursor); +} + +static Bool +miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + return miDCUnrealizeCursor(pScreen, pCursor); +} + +static void +miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y) +{ + miCursorInfoPtr pPointer; + miSpriteScreenPtr pScreenPriv; + + if (IsFloating(pDev)) + return; + + pPointer = MISPRITE(pDev); + pScreenPriv = GetSpriteScreen(pScreen); + + if (!pCursor) + { + if (pPointer->shouldBeUp) + --pScreenPriv->numberOfCursors; + pPointer->shouldBeUp = FALSE; + if (pPointer->isUp) + miSpriteRemoveCursor (pDev, pScreen); + if (pScreenPriv->numberOfCursors == 0) + miSpriteDisableDamage(pScreen, pScreenPriv); + pPointer->pCursor = 0; + return; + } + if (!pPointer->shouldBeUp) + pScreenPriv->numberOfCursors++; + pPointer->shouldBeUp = TRUE; + if (!pPointer->isUp) + miSpriteRegisterBlockHandler(pScreen, pScreenPriv); + if (pPointer->x == x && + pPointer->y == y && + pPointer->pCursor == pCursor && + !pPointer->checkPixels) + { + return; + } + pPointer->x = x; + pPointer->y = y; + pPointer->pCacheWin = NullWindow; + if (pPointer->checkPixels || pPointer->pCursor != pCursor) + { + pPointer->pCursor = pCursor; + miSpriteFindColors (pPointer, pScreen); + } + if (pPointer->isUp) { + /* TODO: reimplement flicker-free MoveCursor */ + SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id)); + miSpriteRemoveCursor (pDev, pScreen); + } + + if (!pPointer->isUp && pPointer->pCursor) + { + SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id)); + miSpriteSaveUnderCursor(pDev, pScreen); + miSpriteRestoreCursor (pDev, pScreen); + } + +} + +static void +miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + CursorPtr pCursor; + + if (IsFloating(pDev)) + return; + + pCursor = MISPRITE(pDev)->pCursor; + + miSpriteSetCursor (pDev, pScreen, pCursor, x, y); +} + + +static Bool +miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + int ret = miDCDeviceInitialize(pDev, pScreen); + + if (ret) + { + miCursorInfoPtr pCursorInfo; + pCursorInfo = dixLookupPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey); + pCursorInfo->pCursor = NULL; + pCursorInfo->x = 0; + pCursorInfo->y = 0; + pCursorInfo->isUp = FALSE; + pCursorInfo->shouldBeUp = FALSE; + pCursorInfo->pCacheWin = NullWindow; + pCursorInfo->isInCacheWin = FALSE; + pCursorInfo->checkPixels = TRUE; + pCursorInfo->pScreen = FALSE; + } + + return ret; +} + +static void +miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miCursorInfoPtr pCursorInfo = dixLookupPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey); + + if (DevHasCursor(pDev)) + miDCDeviceCleanup(pDev, pScreen); + + memset(pCursorInfo, 0, sizeof(miCursorInfoRec)); +} + +/* + * undraw/draw cursor + */ + +static void +miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + miCursorInfoPtr pCursorInfo; + + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteIsDown(pCursorInfo); + miSpriteRegisterBlockHandler(pScreen, pScreenPriv); + pCursorInfo->pCacheWin = NullWindow; + miSpriteDisableDamage(pScreen, pScreenPriv); + if (!miDCRestoreUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1)) + { + miSpriteIsUp(pCursorInfo); + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * Called from the block handler, saves area under cursor + * before waiting for something to do. + */ + +static void +miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + + miDCSaveUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1); + SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + + +/* + * Called from the block handler, restores the cursor + * before waiting for something to do. + */ + +static void +miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); + if (pCursorInfo->checkPixels) + miSpriteFindColors (pCursorInfo, pScreen); + if (miDCPutUpCursor(pDev, pScreen, + pCursor, x, y, + pScreenPriv->colors[SOURCE_COLOR].pixel, + pScreenPriv->colors[MASK_COLOR].pixel)) + { + miSpriteIsUp(pCursorInfo); + pCursorInfo->pScreen = pScreen; + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * compute the desired area of the screen to save + */ + +static void +miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + int x, y, w, h; + int wpad, hpad; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + pCursorInfo = MISPRITE(pDev); + + pCursor = pCursorInfo->pCursor; + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + w = pCursor->bits->width; + h = pCursor->bits->height; + wpad = SPRITE_PAD; + hpad = SPRITE_PAD; + pCursorInfo->saved.x1 = x - wpad; + pCursorInfo->saved.y1 = y - hpad; + pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; + pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; +} + diff --git a/xorg-server/miext/cw/cw.h b/xorg-server/miext/cw/cw.h index 555111c67..10d088ad2 100644 --- a/xorg-server/miext/cw/cw.h +++ b/xorg-server/miext/cw/cw.h @@ -106,8 +106,6 @@ typedef struct { TrapezoidsProcPtr Trapezoids; TrianglesProcPtr Triangles; - TriStripProcPtr TriStrip; - TriFanProcPtr TriFan; RasterizeTrapezoidProcPtr RasterizeTrapezoid; } cwScreenRec, *cwScreenPtr; diff --git a/xorg-server/miext/cw/cw_render.c b/xorg-server/miext/cw/cw_render.c index 260509ce0..25601f3e2 100644 --- a/xorg-server/miext/cw/cw_render.c +++ b/xorg-server/miext/cw/cw_render.c @@ -371,66 +371,6 @@ cwTriangles (CARD8 op, cwPsWrap(Triangles, cwTriangles); } -static void -cwTriStrip (CARD8 op, - PicturePtr pSrcPicture, - PicturePtr pDstPicture, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int npoint, - xPointFixed *points) -{ - ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; - cwPsDecl(pScreen); - cwSrcPictureDecl; - cwDstPictureDecl; - int i; - - cwPsUnwrap(TriStrip); - if (dst_picture_x_off || dst_picture_y_off) { - for (i = 0; i < npoint; i++) - { - points[i].x += dst_picture_x_off << 16; - points[i].y += dst_picture_y_off << 16; - } - } - (*ps->TriStrip) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, - xSrc + src_picture_x_off, ySrc + src_picture_y_off, - npoint, points); - cwPsWrap(TriStrip, cwTriStrip); -} - -static void -cwTriFan (CARD8 op, - PicturePtr pSrcPicture, - PicturePtr pDstPicture, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int npoint, - xPointFixed *points) -{ - ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; - cwPsDecl(pScreen); - cwSrcPictureDecl; - cwDstPictureDecl; - int i; - - cwPsUnwrap(TriFan); - if (dst_picture_x_off || dst_picture_y_off) { - for (i = 0; i < npoint; i++) - { - points[i].x += dst_picture_x_off << 16; - points[i].y += dst_picture_y_off << 16; - } - } - (*ps->TriFan) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, - xSrc + src_picture_x_off, ySrc + src_picture_y_off, - npoint, points); - cwPsWrap(TriFan, cwTriFan); -} - void cwInitializeRender (ScreenPtr pScreen) { @@ -443,8 +383,6 @@ cwInitializeRender (ScreenPtr pScreen) cwPsWrap(CompositeRects, cwCompositeRects); cwPsWrap(Trapezoids, cwTrapezoids); cwPsWrap(Triangles, cwTriangles); - cwPsWrap(TriStrip, cwTriStrip); - cwPsWrap(TriFan, cwTriFan); /* There is no need to wrap AddTraps as far as we can tell. AddTraps can * only be done on alpha-only pictures, and we won't be getting * alpha-only window pictures, so there's no need to translate. @@ -463,7 +401,5 @@ cwFiniRender (ScreenPtr pScreen) cwPsUnwrap(CompositeRects); cwPsUnwrap(Trapezoids); cwPsUnwrap(Triangles); - cwPsUnwrap(TriStrip); - cwPsUnwrap(TriFan); } diff --git a/xorg-server/os/access.c b/xorg-server/os/access.c index b7e698c3b..7ba4274ce 100644 --- a/xorg-server/os/access.c +++ b/xorg-server/os/access.c @@ -165,17 +165,6 @@ SOFTWARE. #endif /* WIN32 */ -#ifndef PATH_MAX -#include -#ifndef PATH_MAX -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif -#endif -#endif - #define X_INCLUDE_NETDB_H #include @@ -185,14 +174,6 @@ SOFTWARE. #include "xace.h" -#ifndef PATH_MAX -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif -#endif - Bool defeatAccessControl = FALSE; #define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len) diff --git a/xorg-server/os/osinit.c b/xorg-server/os/osinit.c index 018e4047d..69e4933e6 100644 --- a/xorg-server/os/osinit.c +++ b/xorg-server/os/osinit.c @@ -1,315 +1,308 @@ -/*********************************************************** - -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. - -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "os.h" -#include "osdep.h" -#include -#include -#include -#ifdef HAVE_DLFCN_H -# include -#endif -#ifdef HAVE_BACKTRACE -#include -#endif - - -#include "dixstruct.h" - -#ifndef PATH_MAX -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif -#endif - - -#if !defined(SYSV) && !defined(WIN32) -#include -#endif - -#ifndef ADMPATH -#define ADMPATH "/usr/adm/X%smsgs" -#endif - -extern char *display; -#ifdef RLIMIT_DATA -int limitDataSpace = -1; -#endif -#ifdef RLIMIT_STACK -int limitStackSpace = -1; -#endif -#ifdef RLIMIT_NOFILE -int limitNoFile = -1; -#endif - -static OsSigWrapperPtr OsSigWrapper = NULL; - -OsSigWrapperPtr -OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) -{ - OsSigWrapperPtr oldSigWrapper = OsSigWrapper; - - OsSigWrapper = newSigWrapper; - - return oldSigWrapper; -} - -/* - * OsSigHandler -- - * Catch unexpected signals and exit or continue cleanly. - */ -static void -#ifdef SA_SIGINFO -OsSigHandler(int signo, siginfo_t *sip, void *unused) -#else -OsSigHandler(int signo) -#endif -{ -#ifdef RTLD_DI_SETSIGNAL - const char *dlerr = dlerror(); - - if (dlerr) { - LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr); - } -#endif /* RTLD_DI_SETSIGNAL */ - - if (OsSigWrapper != NULL) { - if (OsSigWrapper(signo) == 0) { - /* ddx handled signal and wants us to continue */ - return; - } - } - - /* log, cleanup, and abort */ - xorg_backtrace(); - -#ifdef SA_SIGINFO - if (sip->si_code == SI_USER) { - ErrorF("Recieved signal %d sent by process %ld, uid %ld\n", - signo, (long) sip->si_pid, (long) sip->si_uid); - } else { - switch (signo) { - case SIGSEGV: - case SIGBUS: - case SIGILL: - case SIGFPE: - ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr); - } - } -#endif - - FatalError("Caught signal %d (%s). Server aborting\n", - signo, strsignal(signo)); -} - -void -OsInit(void) -{ - static Bool been_here = FALSE; - static char* devnull = "/dev/null"; - char fname[PATH_MAX]; - - if (!been_here) { - struct sigaction act, oact; - int i; - int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, - SIGSYS, - SIGXCPU, - SIGXFSZ, -#ifdef SIGEMT - SIGEMT, -#endif - 0 /* must be last */ }; - sigemptyset(&act.sa_mask); -#ifdef SA_SIGINFO - act.sa_sigaction = OsSigHandler; - act.sa_flags = SA_SIGINFO; -#else - act.sa_handler = OsSigHandler; - act.sa_flags = 0; -#endif - for (i = 0; siglist[i] != 0; i++) { - if (sigaction(siglist[i], &act, &oact)) { - ErrorF("failed to install signal handler for signal %d: %s\n", - siglist[i], strerror(errno)); - } - } -#ifdef HAVE_BACKTRACE - /* - * initialize the backtracer, since the ctor calls dlopen(), which - * calls malloc(), which isn't signal-safe. - */ - do { - void *array; - backtrace(&array, 1); - } while (0); -#endif - -#ifdef RTLD_DI_SETSIGNAL - /* Tell runtime linker to send a signal we can catch instead of SIGKILL - * for failures to load libraries/modules at runtime so we can clean up - * after ourselves. - */ - int failure_signal = SIGQUIT; - dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal); -#endif - -#if !defined(__CYGWIN__) - fclose(stdin); - fclose(stdout); -#endif - /* - * If a write of zero bytes to stderr returns non-zero, i.e. -1, - * then writing to stderr failed, and we'll write somewhere else - * instead. (Apparently this never happens in the Real World.) - */ - if (write (2, fname, 0) == -1) - { - FILE *err; - - if (strlen (display) + strlen (ADMPATH) + 1 < sizeof fname) - sprintf (fname, ADMPATH, display); - else - strcpy (fname, devnull); - /* - * uses stdio to avoid os dependencies here, - * a real os would use - * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) - */ - if (!(err = fopen (fname, "a+"))) - err = fopen (devnull, "w"); - if (err && (fileno(err) != 2)) { - dup2 (fileno (err), 2); - fclose (err); - } -#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) - { - static char buf[BUFSIZ]; - setvbuf (stderr, buf, _IOLBF, BUFSIZ); - } -#else - setlinebuf(stderr); -#endif - } - - if (getpgrp () == 0) - setpgid (0, 0); - -#ifdef RLIMIT_DATA - if (limitDataSpace >= 0) - { - struct rlimit rlim; - - if (!getrlimit(RLIMIT_DATA, &rlim)) - { - if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) - rlim.rlim_cur = limitDataSpace; - else - rlim.rlim_cur = rlim.rlim_max; - (void)setrlimit(RLIMIT_DATA, &rlim); - } - } -#endif -#ifdef RLIMIT_STACK - if (limitStackSpace >= 0) - { - struct rlimit rlim; - - if (!getrlimit(RLIMIT_STACK, &rlim)) - { - if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) - rlim.rlim_cur = limitStackSpace; - else - rlim.rlim_cur = rlim.rlim_max; - (void)setrlimit(RLIMIT_STACK, &rlim); - } - } -#endif -#ifdef RLIMIT_NOFILE - if (limitNoFile >= 0) - { - struct rlimit rlim; - - if (!getrlimit(RLIMIT_NOFILE, &rlim)) - { - if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) - rlim.rlim_cur = limitNoFile; - else - rlim.rlim_cur = rlim.rlim_max; - (void)setrlimit(RLIMIT_NOFILE, &rlim); - } - } -#endif - LockServer(); - been_here = TRUE; - } - TimerInit(); - OsVendorInit(); - /* - * No log file by default. OsVendorInit() should call LogInit() with the - * log file name if logging to a file is desired. - */ - LogInit(NULL, NULL); - SmartScheduleInit (); -} - -void -OsCleanup(Bool terminating) -{ - if (terminating) - { - UnlockServer(); - } -} +/*********************************************************** + +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. + +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "os.h" +#include "osdep.h" +#include +#include +#include +#ifdef HAVE_DLFCN_H +# include +#endif +#ifdef HAVE_BACKTRACE +#include +#endif + +#include "misc.h" + +#include "dixstruct.h" + + +#if !defined(SYSV) && !defined(WIN32) +#include +#endif + +#ifndef ADMPATH +#define ADMPATH "/usr/adm/X%smsgs" +#endif + +extern char *display; +#ifdef RLIMIT_DATA +int limitDataSpace = -1; +#endif +#ifdef RLIMIT_STACK +int limitStackSpace = -1; +#endif +#ifdef RLIMIT_NOFILE +int limitNoFile = -1; +#endif + +static OsSigWrapperPtr OsSigWrapper = NULL; + +OsSigWrapperPtr +OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper) +{ + OsSigWrapperPtr oldSigWrapper = OsSigWrapper; + + OsSigWrapper = newSigWrapper; + + return oldSigWrapper; +} + +/* + * OsSigHandler -- + * Catch unexpected signals and exit or continue cleanly. + */ +static void +#ifdef SA_SIGINFO +OsSigHandler(int signo, siginfo_t *sip, void *unused) +#else +OsSigHandler(int signo) +#endif +{ +#ifdef RTLD_DI_SETSIGNAL + const char *dlerr = dlerror(); + + if (dlerr) { + LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr); + } +#endif /* RTLD_DI_SETSIGNAL */ + + if (OsSigWrapper != NULL) { + if (OsSigWrapper(signo) == 0) { + /* ddx handled signal and wants us to continue */ + return; + } + } + + /* log, cleanup, and abort */ + xorg_backtrace(); + +#ifdef SA_SIGINFO + if (sip->si_code == SI_USER) { + ErrorF("Recieved signal %d sent by process %ld, uid %ld\n", + signo, (long) sip->si_pid, (long) sip->si_uid); + } else { + switch (signo) { + case SIGSEGV: + case SIGBUS: + case SIGILL: + case SIGFPE: + ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr); + } + } +#endif + + FatalError("Caught signal %d (%s). Server aborting\n", + signo, strsignal(signo)); +} + +void +OsInit(void) +{ + static Bool been_here = FALSE; + static char* devnull = "/dev/null"; + char fname[PATH_MAX]; + + if (!been_here) { + struct sigaction act, oact; + int i; + int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS, + SIGSYS, + SIGXCPU, + SIGXFSZ, +#ifdef SIGEMT + SIGEMT, +#endif + 0 /* must be last */ }; + sigemptyset(&act.sa_mask); +#ifdef SA_SIGINFO + act.sa_sigaction = OsSigHandler; + act.sa_flags = SA_SIGINFO; +#else + act.sa_handler = OsSigHandler; + act.sa_flags = 0; +#endif + for (i = 0; siglist[i] != 0; i++) { + if (sigaction(siglist[i], &act, &oact)) { + ErrorF("failed to install signal handler for signal %d: %s\n", + siglist[i], strerror(errno)); + } + } +#ifdef HAVE_BACKTRACE + /* + * initialize the backtracer, since the ctor calls dlopen(), which + * calls malloc(), which isn't signal-safe. + */ + do { + void *array; + backtrace(&array, 1); + } while (0); +#endif + +#ifdef RTLD_DI_SETSIGNAL + /* Tell runtime linker to send a signal we can catch instead of SIGKILL + * for failures to load libraries/modules at runtime so we can clean up + * after ourselves. + */ + int failure_signal = SIGQUIT; + dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal); +#endif + +#if !defined(__CYGWIN__) + fclose(stdin); + fclose(stdout); +#endif + /* + * If a write of zero bytes to stderr returns non-zero, i.e. -1, + * then writing to stderr failed, and we'll write somewhere else + * instead. (Apparently this never happens in the Real World.) + */ + if (write (2, fname, 0) == -1) + { + FILE *err; + + if (strlen (display) + strlen (ADMPATH) + 1 < sizeof fname) + sprintf (fname, ADMPATH, display); + else + strcpy (fname, devnull); + /* + * uses stdio to avoid os dependencies here, + * a real os would use + * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) + */ + if (!(err = fopen (fname, "a+"))) + err = fopen (devnull, "w"); + if (err && (fileno(err) != 2)) { + dup2 (fileno (err), 2); + fclose (err); + } +#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) + { + static char buf[BUFSIZ]; + setvbuf (stderr, buf, _IOLBF, BUFSIZ); + } +#else + setlinebuf(stderr); +#endif + } + + if (getpgrp () == 0) + setpgid (0, 0); + +#ifdef RLIMIT_DATA + if (limitDataSpace >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_DATA, &rlim)) + { + if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) + rlim.rlim_cur = limitDataSpace; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_DATA, &rlim); + } + } +#endif +#ifdef RLIMIT_STACK + if (limitStackSpace >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_STACK, &rlim)) + { + if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) + rlim.rlim_cur = limitStackSpace; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_STACK, &rlim); + } + } +#endif +#ifdef RLIMIT_NOFILE + if (limitNoFile >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_NOFILE, &rlim)) + { + if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) + rlim.rlim_cur = limitNoFile; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_NOFILE, &rlim); + } + } +#endif + LockServer(); + been_here = TRUE; + } + TimerInit(); + OsVendorInit(); + /* + * No log file by default. OsVendorInit() should call LogInit() with the + * log file name if logging to a file is desired. + */ + LogInit(NULL, NULL); + SmartScheduleInit (); +} + +void +OsCleanup(Bool terminating) +{ + if (terminating) + { + UnlockServer(); + } +} diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c index eb3ba91bb..30d14460a 100644 --- a/xorg-server/os/utils.c +++ b/xorg-server/os/utils.c @@ -231,17 +231,6 @@ OsSignal(int sig, OsSigHandlerPtr handler) #define LOCK_PREFIX "/.X" #define LOCK_SUFFIX "-lock" -#ifndef PATH_MAX -#include -#ifndef PATH_MAX -#ifdef MAXPATHLEN -#define PATH_MAX MAXPATHLEN -#else -#define PATH_MAX 1024 -#endif -#endif -#endif - static Bool StillLocking = FALSE; static char LockFile[PATH_MAX]; static Bool nolock = FALSE; diff --git a/xorg-server/os/xdmcp.c b/xorg-server/os/xdmcp.c index 3a6a3bb7d..8da2cb05c 100644 --- a/xorg-server/os/xdmcp.c +++ b/xorg-server/os/xdmcp.c @@ -486,7 +486,7 @@ XdmcpRegisterConnection ( } } #endif - if (fromAddr && memcmp(regAddr, fromAddr, regAddrlen) != 0) { + if (!fromAddr || memcmp(regAddr, fromAddr, regAddrlen) != 0) { return; } } diff --git a/xorg-server/randr/randr.c b/xorg-server/randr/randr.c index 607770520..1551c63b1 100644 --- a/xorg-server/randr/randr.c +++ b/xorg-server/randr/randr.c @@ -1,502 +1,504 @@ -/* - * Copyright © 2000 Compaq Computer Corporation - * Copyright © 2002 Hewlett-Packard Company - * Copyright © 2006 Intel Corporation - * - * 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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: Jim Gettys, Hewlett-Packard Company, Inc. - * Keith Packard, Intel Corporation - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "randrstr.h" - -/* From render.h */ -#ifndef SubPixelUnknown -#define SubPixelUnknown 0 -#endif - -#define RR_VALIDATE -static int RRNScreens; - -#define wrap(priv,real,mem,func) {\ - priv->mem = real->mem; \ - real->mem = func; \ -} - -#define unwrap(priv,real,mem) {\ - real->mem = priv->mem; \ -} - -static int ProcRRDispatch (ClientPtr pClient); -static int SProcRRDispatch (ClientPtr pClient); - -int RREventBase; -int RRErrorBase; -RESTYPE RRClientType, RREventType; /* resource types for event masks */ -DevPrivateKeyRec RRClientPrivateKeyRec; - -DevPrivateKeyRec rrPrivKeyRec; - -static void -RRClientCallback (CallbackListPtr *list, - pointer closure, - pointer data) -{ - NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; - ClientPtr pClient = clientinfo->client; - rrClientPriv(pClient); - RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); - int i; - - pRRClient->major_version = 0; - pRRClient->minor_version = 0; - for (i = 0; i < screenInfo.numScreens; i++) - { - ScreenPtr pScreen = screenInfo.screens[i]; - rrScrPriv(pScreen); - - if (pScrPriv) - { - pTimes[i].setTime = pScrPriv->lastSetTime; - pTimes[i].configTime = pScrPriv->lastConfigTime; - } - } -} - -static Bool -RRCloseScreen (int i, ScreenPtr pScreen) -{ - rrScrPriv(pScreen); - int j; - - unwrap (pScrPriv, pScreen, CloseScreen); - for (j = pScrPriv->numCrtcs - 1; j >= 0; j--) - RRCrtcDestroy (pScrPriv->crtcs[j]); - for (j = pScrPriv->numOutputs - 1; j >= 0; j--) - RROutputDestroy (pScrPriv->outputs[j]); - - free(pScrPriv->crtcs); - free(pScrPriv->outputs); - free(pScrPriv); - RRNScreens -= 1; /* ok, one fewer screen with RandR running */ - return (*pScreen->CloseScreen) (i, pScreen); -} - -static void -SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, - xRRScreenChangeNotifyEvent *to) -{ - to->type = from->type; - to->rotation = from->rotation; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->timestamp, to->timestamp); - cpswapl(from->configTimestamp, to->configTimestamp); - cpswapl(from->root, to->root); - cpswapl(from->window, to->window); - cpswaps(from->sizeID, to->sizeID); - cpswaps(from->subpixelOrder, to->subpixelOrder); - cpswaps(from->widthInPixels, to->widthInPixels); - cpswaps(from->heightInPixels, to->heightInPixels); - cpswaps(from->widthInMillimeters, to->widthInMillimeters); - cpswaps(from->heightInMillimeters, to->heightInMillimeters); -} - -static void -SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from, - xRRCrtcChangeNotifyEvent *to) -{ - to->type = from->type; - to->subCode = from->subCode; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->timestamp, to->timestamp); - cpswapl(from->window, to->window); - cpswapl(from->crtc, to->crtc); - cpswapl(from->mode, to->mode); - cpswaps(from->rotation, to->rotation); - /* pad1 */ - cpswaps(from->x, to->x); - cpswaps(from->y, to->y); - cpswaps(from->width, to->width); - cpswaps(from->height, to->height); -} - -static void -SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from, - xRROutputChangeNotifyEvent *to) -{ - to->type = from->type; - to->subCode = from->subCode; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->timestamp, to->timestamp); - cpswapl(from->configTimestamp, to->configTimestamp); - cpswapl(from->window, to->window); - cpswapl(from->output, to->output); - cpswapl(from->crtc, to->crtc); - cpswapl(from->mode, to->mode); - cpswaps(from->rotation, to->rotation); - to->connection = from->connection; - to->subpixelOrder = from->subpixelOrder; -} - -static void -SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from, - xRROutputPropertyNotifyEvent *to) -{ - to->type = from->type; - to->subCode = from->subCode; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->window, to->window); - cpswapl(from->output, to->output); - cpswapl(from->atom, to->atom); - cpswapl(from->timestamp, to->timestamp); - to->state = from->state; - /* pad1 */ - /* pad2 */ - /* pad3 */ - /* pad4 */ -} - -static void -SRRNotifyEvent (xEvent *from, - xEvent *to) -{ - switch (from->u.u.detail) { - case RRNotify_CrtcChange: - SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from, - (xRRCrtcChangeNotifyEvent *) to); - break; - case RRNotify_OutputChange: - SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from, - (xRROutputChangeNotifyEvent *) to); - break; - case RRNotify_OutputProperty: - SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from, - (xRROutputPropertyNotifyEvent *) to); - break; - default: - break; - } -} - -static int RRGeneration; - -Bool RRInit (void) -{ - if (RRGeneration != serverGeneration) - { - if (!RRModeInit ()) - return FALSE; - if (!RRCrtcInit ()) - return FALSE; - if (!RROutputInit ()) - return FALSE; - RRGeneration = serverGeneration; - } - if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0)) - return FALSE; - - return TRUE; -} - -Bool RRScreenInit(ScreenPtr pScreen) -{ - rrScrPrivPtr pScrPriv; - - if (!RRInit ()) - return FALSE; - - pScrPriv = (rrScrPrivPtr) calloc(1, sizeof (rrScrPrivRec)); - if (!pScrPriv) - return FALSE; - - SetRRScreen(pScreen, pScrPriv); - - /* - * Calling function best set these function vectors - */ - pScrPriv->rrGetInfo = 0; - pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width; - pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height; - - pScrPriv->width = pScreen->width; - pScrPriv->height = pScreen->height; - pScrPriv->mmWidth = pScreen->mmWidth; - pScrPriv->mmHeight = pScreen->mmHeight; -#if RANDR_12_INTERFACE - pScrPriv->rrScreenSetSize = NULL; - pScrPriv->rrCrtcSet = NULL; - pScrPriv->rrCrtcSetGamma = NULL; -#endif -#if RANDR_10_INTERFACE - pScrPriv->rrSetConfig = 0; - pScrPriv->rotations = RR_Rotate_0; - pScrPriv->reqWidth = pScreen->width; - pScrPriv->reqHeight = pScreen->height; - pScrPriv->nSizes = 0; - pScrPriv->pSizes = NULL; - pScrPriv->rotation = RR_Rotate_0; - pScrPriv->rate = 0; - pScrPriv->size = 0; -#endif - - /* - * This value doesn't really matter -- any client must call - * GetScreenInfo before reading it which will automatically update - * the time - */ - pScrPriv->lastSetTime = currentTime; - pScrPriv->lastConfigTime = currentTime; - - wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); - - pScrPriv->numOutputs = 0; - pScrPriv->outputs = NULL; - pScrPriv->numCrtcs = 0; - pScrPriv->crtcs = NULL; - - RRNScreens += 1; /* keep count of screens that implement randr */ - return TRUE; -} - -/*ARGSUSED*/ -static int -RRFreeClient (pointer data, XID id) -{ - RREventPtr pRREvent; - WindowPtr pWin; - RREventPtr *pHead, pCur, pPrev; - - pRREvent = (RREventPtr) data; - pWin = pRREvent->window; - dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - RREventType, serverClient, DixDestroyAccess); - if (pHead) { - pPrev = 0; - for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) - pPrev = pCur; - if (pCur) - { - if (pPrev) - pPrev->next = pRREvent->next; - else - *pHead = pRREvent->next; - } - } - free((pointer) pRREvent); - return 1; -} - -/*ARGSUSED*/ -static int -RRFreeEvents (pointer data, XID id) -{ - RREventPtr *pHead, pCur, pNext; - - pHead = (RREventPtr *) data; - for (pCur = *pHead; pCur; pCur = pNext) { - pNext = pCur->next; - FreeResource (pCur->clientResource, RRClientType); - free((pointer) pCur); - } - free((pointer) pHead); - return 1; -} - -void -RRExtensionInit (void) -{ - ExtensionEntry *extEntry; - - if (RRNScreens == 0) return; - - if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT, - sizeof (RRClientRec) + - screenInfo.numScreens * sizeof (RRTimesRec))) - return; - if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) - return; - - RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient"); - if (!RRClientType) - return; - RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent"); - if (!RREventType) - return; - extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, - ProcRRDispatch, SProcRRDispatch, - NULL, StandardMinorOpcode); - if (!extEntry) - return; - RRErrorBase = extEntry->errorBase; - RREventBase = extEntry->eventBase; - EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) - SRRScreenChangeNotifyEvent; - EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr) - SRRNotifyEvent; - - RRModeInitErrorValue(); - RRCrtcInitErrorValue(); - RROutputInitErrorValue(); - -#ifdef PANORAMIX - RRXineramaExtensionInit(); -#endif -} - -static int -TellChanged (WindowPtr pWin, pointer value) -{ - RREventPtr *pHead, pRREvent; - ClientPtr client; - ScreenPtr pScreen = pWin->drawable.pScreen; - rrScrPriv(pScreen); - int i; - - dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - RREventType, serverClient, DixReadAccess); - if (!pHead) - return WT_WALKCHILDREN; - - for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) - { - client = pRREvent->client; - if (client == serverClient || client->clientGone) - continue; - - if (pRREvent->mask & RRScreenChangeNotifyMask) - RRDeliverScreenEvent (client, pWin, pScreen); - - if (pRREvent->mask & RRCrtcChangeNotifyMask) - { - for (i = 0; i < pScrPriv->numCrtcs; i++) - { - RRCrtcPtr crtc = pScrPriv->crtcs[i]; - if (crtc->changed) - RRDeliverCrtcEvent (client, pWin, crtc); - } - } - - if (pRREvent->mask & RROutputChangeNotifyMask) - { - for (i = 0; i < pScrPriv->numOutputs; i++) - { - RROutputPtr output = pScrPriv->outputs[i]; - if (output->changed) - RRDeliverOutputEvent (client, pWin, output); - } - } - } - return WT_WALKCHILDREN; -} - -/* - * Something changed; send events and adjust pointer position - */ -void -RRTellChanged (ScreenPtr pScreen) -{ - rrScrPriv (pScreen); - int i; - - if (pScrPriv->changed) - { - UpdateCurrentTime (); - if (pScrPriv->configChanged) - { - pScrPriv->lastConfigTime = currentTime; - pScrPriv->configChanged = FALSE; - } - pScrPriv->changed = FALSE; - WalkTree (pScreen, TellChanged, (pointer) pScreen); - for (i = 0; i < pScrPriv->numOutputs; i++) - pScrPriv->outputs[i]->changed = FALSE; - for (i = 0; i < pScrPriv->numCrtcs; i++) - pScrPriv->crtcs[i]->changed = FALSE; - if (pScrPriv->layoutChanged) - { - pScrPriv->layoutChanged = FALSE; - RRPointerScreenConfigured (pScreen); - RRSendConfigNotify (pScreen); - } - } -} - -/* - * Return the first output which is connected to an active CRTC - * Used in emulating 1.0 behaviour - */ -RROutputPtr -RRFirstOutput (ScreenPtr pScreen) -{ - rrScrPriv(pScreen); - RROutputPtr output; - int i, j; - - if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) - return pScrPriv->primaryOutput; - - for (i = 0; i < pScrPriv->numCrtcs; i++) - { - RRCrtcPtr crtc = pScrPriv->crtcs[i]; - for (j = 0; j < pScrPriv->numOutputs; j++) - { - output = pScrPriv->outputs[j]; - if (output->crtc == crtc) - return output; - } - } - return NULL; -} - -CARD16 -RRVerticalRefresh (xRRModeInfo *mode) -{ - CARD32 refresh; - CARD32 dots = mode->hTotal * mode->vTotal; - if (!dots) - return 0; - refresh = (mode->dotClock + dots/2) / dots; - if (refresh > 0xffff) - refresh = 0xffff; - return (CARD16) refresh; -} - -static int -ProcRRDispatch (ClientPtr client) -{ - REQUEST(xReq); - if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) - return BadRequest; - return (*ProcRandrVector[stuff->data]) (client); -} - -static int -SProcRRDispatch (ClientPtr client) -{ - REQUEST(xReq); - if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) - return BadRequest; - return (*SProcRandrVector[stuff->data]) (client); -} - +/* + * Copyright © 2000 Compaq Computer Corporation + * Copyright © 2002 Hewlett-Packard Company + * Copyright © 2006 Intel Corporation + * + * 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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: Jim Gettys, Hewlett-Packard Company, Inc. + * Keith Packard, Intel Corporation + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "randrstr.h" + +/* From render.h */ +#ifndef SubPixelUnknown +#define SubPixelUnknown 0 +#endif + +#define RR_VALIDATE +static int RRNScreens; + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static int ProcRRDispatch (ClientPtr pClient); +static int SProcRRDispatch (ClientPtr pClient); + +int RREventBase; +int RRErrorBase; +RESTYPE RRClientType, RREventType; /* resource types for event masks */ +DevPrivateKeyRec RRClientPrivateKeyRec; + +DevPrivateKeyRec rrPrivKeyRec; + +static void +RRClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + rrClientPriv(pClient); + RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1); + int i; + + pRRClient->major_version = 0; + pRRClient->minor_version = 0; + for (i = 0; i < screenInfo.numScreens; i++) + { + ScreenPtr pScreen = screenInfo.screens[i]; + rrScrPriv(pScreen); + + if (pScrPriv) + { + pTimes[i].setTime = pScrPriv->lastSetTime; + pTimes[i].configTime = pScrPriv->lastConfigTime; + } + } +} + +static Bool +RRCloseScreen (int i, ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + int j; + + unwrap (pScrPriv, pScreen, CloseScreen); + for (j = pScrPriv->numCrtcs - 1; j >= 0; j--) + RRCrtcDestroy (pScrPriv->crtcs[j]); + for (j = pScrPriv->numOutputs - 1; j >= 0; j--) + RROutputDestroy (pScrPriv->outputs[j]); + + free(pScrPriv->crtcs); + free(pScrPriv->outputs); + free(pScrPriv); + RRNScreens -= 1; /* ok, one fewer screen with RandR running */ + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent *from, + xRRScreenChangeNotifyEvent *to) +{ + to->type = from->type; + to->rotation = from->rotation; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->root, to->root); + cpswapl(from->window, to->window); + cpswaps(from->sizeID, to->sizeID); + cpswaps(from->subpixelOrder, to->subpixelOrder); + cpswaps(from->widthInPixels, to->widthInPixels); + cpswaps(from->heightInPixels, to->heightInPixels); + cpswaps(from->widthInMillimeters, to->widthInMillimeters); + cpswaps(from->heightInMillimeters, to->heightInMillimeters); +} + +static void +SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent *from, + xRRCrtcChangeNotifyEvent *to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->window, to->window); + cpswapl(from->crtc, to->crtc); + cpswapl(from->mode, to->mode); + cpswaps(from->rotation, to->rotation); + /* pad1 */ + cpswaps(from->x, to->x); + cpswaps(from->y, to->y); + cpswaps(from->width, to->width); + cpswaps(from->height, to->height); +} + +static void +SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent *from, + xRROutputChangeNotifyEvent *to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->timestamp, to->timestamp); + cpswapl(from->configTimestamp, to->configTimestamp); + cpswapl(from->window, to->window); + cpswapl(from->output, to->output); + cpswapl(from->crtc, to->crtc); + cpswapl(from->mode, to->mode); + cpswaps(from->rotation, to->rotation); + to->connection = from->connection; + to->subpixelOrder = from->subpixelOrder; +} + +static void +SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent *from, + xRROutputPropertyNotifyEvent *to) +{ + to->type = from->type; + to->subCode = from->subCode; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->window, to->window); + cpswapl(from->output, to->output); + cpswapl(from->atom, to->atom); + cpswapl(from->timestamp, to->timestamp); + to->state = from->state; + /* pad1 */ + /* pad2 */ + /* pad3 */ + /* pad4 */ +} + +static void +SRRNotifyEvent (xEvent *from, + xEvent *to) +{ + switch (from->u.u.detail) { + case RRNotify_CrtcChange: + SRRCrtcChangeNotifyEvent ((xRRCrtcChangeNotifyEvent *) from, + (xRRCrtcChangeNotifyEvent *) to); + break; + case RRNotify_OutputChange: + SRROutputChangeNotifyEvent ((xRROutputChangeNotifyEvent *) from, + (xRROutputChangeNotifyEvent *) to); + break; + case RRNotify_OutputProperty: + SRROutputPropertyNotifyEvent ((xRROutputPropertyNotifyEvent *) from, + (xRROutputPropertyNotifyEvent *) to); + break; + default: + break; + } +} + +static int RRGeneration; + +Bool RRInit (void) +{ + if (RRGeneration != serverGeneration) + { + if (!RRModeInit ()) + return FALSE; + if (!RRCrtcInit ()) + return FALSE; + if (!RROutputInit ()) + return FALSE; + RRGeneration = serverGeneration; + } + if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + return TRUE; +} + +Bool RRScreenInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRInit ()) + return FALSE; + + pScrPriv = (rrScrPrivPtr) calloc(1, sizeof (rrScrPrivRec)); + if (!pScrPriv) + return FALSE; + + SetRRScreen(pScreen, pScrPriv); + + /* + * Calling function best set these function vectors + */ + pScrPriv->rrGetInfo = 0; + pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width; + pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height; + + pScrPriv->width = pScreen->width; + pScrPriv->height = pScreen->height; + pScrPriv->mmWidth = pScreen->mmWidth; + pScrPriv->mmHeight = pScreen->mmHeight; +#if RANDR_12_INTERFACE + pScrPriv->rrScreenSetSize = NULL; + pScrPriv->rrCrtcSet = NULL; + pScrPriv->rrCrtcSetGamma = NULL; +#endif +#if RANDR_10_INTERFACE + pScrPriv->rrSetConfig = 0; + pScrPriv->rotations = RR_Rotate_0; + pScrPriv->reqWidth = pScreen->width; + pScrPriv->reqHeight = pScreen->height; + pScrPriv->nSizes = 0; + pScrPriv->pSizes = NULL; + pScrPriv->rotation = RR_Rotate_0; + pScrPriv->rate = 0; + pScrPriv->size = 0; +#endif + + /* + * This value doesn't really matter -- any client must call + * GetScreenInfo before reading it which will automatically update + * the time + */ + pScrPriv->lastSetTime = currentTime; + pScrPriv->lastConfigTime = currentTime; + + wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); + + pScreen->ConstrainCursorHarder = RRConstrainCursorHarder; + + pScrPriv->numOutputs = 0; + pScrPriv->outputs = NULL; + pScrPriv->numCrtcs = 0; + pScrPriv->crtcs = NULL; + + RRNScreens += 1; /* keep count of screens that implement randr */ + return TRUE; +} + +/*ARGSUSED*/ +static int +RRFreeClient (pointer data, XID id) +{ + RREventPtr pRREvent; + WindowPtr pWin; + RREventPtr *pHead, pCur, pPrev; + + pRREvent = (RREventPtr) data; + pWin = pRREvent->window; + dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + RREventType, serverClient, DixDestroyAccess); + if (pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pRREvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pRREvent->next; + else + *pHead = pRREvent->next; + } + } + free((pointer) pRREvent); + return 1; +} + +/*ARGSUSED*/ +static int +RRFreeEvents (pointer data, XID id) +{ + RREventPtr *pHead, pCur, pNext; + + pHead = (RREventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, RRClientType); + free((pointer) pCur); + } + free((pointer) pHead); + return 1; +} + +void +RRExtensionInit (void) +{ + ExtensionEntry *extEntry; + + if (RRNScreens == 0) return; + + if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT, + sizeof (RRClientRec) + + screenInfo.numScreens * sizeof (RRTimesRec))) + return; + if (!AddCallback (&ClientStateCallback, RRClientCallback, 0)) + return; + + RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient"); + if (!RRClientType) + return; + RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent"); + if (!RREventType) + return; + extEntry = AddExtension (RANDR_NAME, RRNumberEvents, RRNumberErrors, + ProcRRDispatch, SProcRRDispatch, + NULL, StandardMinorOpcode); + if (!extEntry) + return; + RRErrorBase = extEntry->errorBase; + RREventBase = extEntry->eventBase; + EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) + SRRScreenChangeNotifyEvent; + EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr) + SRRNotifyEvent; + + RRModeInitErrorValue(); + RRCrtcInitErrorValue(); + RROutputInitErrorValue(); + +#ifdef PANORAMIX + RRXineramaExtensionInit(); +#endif +} + +static int +TellChanged (WindowPtr pWin, pointer value) +{ + RREventPtr *pHead, pRREvent; + ClientPtr client; + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv(pScreen); + int i; + + dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + RREventType, serverClient, DixReadAccess); + if (!pHead) + return WT_WALKCHILDREN; + + for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) + { + client = pRREvent->client; + if (client == serverClient || client->clientGone) + continue; + + if (pRREvent->mask & RRScreenChangeNotifyMask) + RRDeliverScreenEvent (client, pWin, pScreen); + + if (pRREvent->mask & RRCrtcChangeNotifyMask) + { + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + if (crtc->changed) + RRDeliverCrtcEvent (client, pWin, crtc); + } + } + + if (pRREvent->mask & RROutputChangeNotifyMask) + { + for (i = 0; i < pScrPriv->numOutputs; i++) + { + RROutputPtr output = pScrPriv->outputs[i]; + if (output->changed) + RRDeliverOutputEvent (client, pWin, output); + } + } + } + return WT_WALKCHILDREN; +} + +/* + * Something changed; send events and adjust pointer position + */ +void +RRTellChanged (ScreenPtr pScreen) +{ + rrScrPriv (pScreen); + int i; + + if (pScrPriv->changed) + { + UpdateCurrentTime (); + if (pScrPriv->configChanged) + { + pScrPriv->lastConfigTime = currentTime; + pScrPriv->configChanged = FALSE; + } + pScrPriv->changed = FALSE; + WalkTree (pScreen, TellChanged, (pointer) pScreen); + for (i = 0; i < pScrPriv->numOutputs; i++) + pScrPriv->outputs[i]->changed = FALSE; + for (i = 0; i < pScrPriv->numCrtcs; i++) + pScrPriv->crtcs[i]->changed = FALSE; + if (pScrPriv->layoutChanged) + { + pScrPriv->layoutChanged = FALSE; + RRPointerScreenConfigured (pScreen); + RRSendConfigNotify (pScreen); + } + } +} + +/* + * Return the first output which is connected to an active CRTC + * Used in emulating 1.0 behaviour + */ +RROutputPtr +RRFirstOutput (ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + RROutputPtr output; + int i, j; + + if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) + return pScrPriv->primaryOutput; + + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + for (j = 0; j < pScrPriv->numOutputs; j++) + { + output = pScrPriv->outputs[j]; + if (output->crtc == crtc) + return output; + } + } + return NULL; +} + +CARD16 +RRVerticalRefresh (xRRModeInfo *mode) +{ + CARD32 refresh; + CARD32 dots = mode->hTotal * mode->vTotal; + if (!dots) + return 0; + refresh = (mode->dotClock + dots/2) / dots; + if (refresh > 0xffff) + refresh = 0xffff; + return (CARD16) refresh; +} + +static int +ProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) + return BadRequest; + return (*ProcRandrVector[stuff->data]) (client); +} + +static int +SProcRRDispatch (ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data]) + return BadRequest; + return (*SProcRandrVector[stuff->data]) (client); +} + diff --git a/xorg-server/randr/randrstr.h b/xorg-server/randr/randrstr.h index 7ea608003..262a16420 100644 --- a/xorg-server/randr/randrstr.h +++ b/xorg-server/randr/randrstr.h @@ -1,970 +1,974 @@ -/* - * Copyright © 2000 Compaq Computer Corporation - * Copyright © 2002 Hewlett-Packard Company - * Copyright © 2006 Intel Corporation - * Copyright © 2008 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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: Jim Gettys, Hewlett-Packard Company, Inc. - * Keith Packard, Intel Corporation - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#ifndef _RANDRSTR_H_ -#define _RANDRSTR_H_ - -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "resource.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "extnsionst.h" -#include "servermd.h" -#include "rrtransform.h" -#include -#include -#include /* we share subpixel order information */ -#include "picturestr.h" -#include - -/* required for ABI compatibility for now */ -#define RANDR_10_INTERFACE 1 -#define RANDR_12_INTERFACE 1 -#define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */ -#define RANDR_GET_CRTC_INTERFACE 1 - -#define RANDR_INTERFACE_VERSION 0x0103 - -typedef XID RRMode; -typedef XID RROutput; -typedef XID RRCrtc; - -extern _X_EXPORT int RREventBase, RRErrorBase; - -extern _X_EXPORT int (*ProcRandrVector[RRNumberRequests])(ClientPtr); -extern _X_EXPORT int (*SProcRandrVector[RRNumberRequests])(ClientPtr); - -/* - * Modeline for a monitor. Name follows directly after this struct - */ - -#define RRModeName(pMode) ((char *) (pMode + 1)) -typedef struct _rrMode RRModeRec, *RRModePtr; -typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr; -typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; -typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; -typedef struct _rrOutput RROutputRec, *RROutputPtr; - -struct _rrMode { - int refcnt; - xRRModeInfo mode; - char *name; - ScreenPtr userScreen; -}; - -struct _rrPropertyValue { - Atom type; /* ignored by server */ - short format; /* format of data for swapping - 8,16,32 */ - long size; /* size of data in (format/8) bytes */ - pointer data; /* private to client */ -}; - -struct _rrProperty { - RRPropertyPtr next; - ATOM propertyName; - Bool is_pending; - Bool range; - Bool immutable; - int num_valid; - INT32 *valid_values; - RRPropertyValueRec current, pending; -}; - -struct _rrCrtc { - RRCrtc id; - ScreenPtr pScreen; - RRModePtr mode; - int x, y; - Rotation rotation; - Rotation rotations; - Bool changed; - int numOutputs; - RROutputPtr *outputs; - int gammaSize; - CARD16 *gammaRed; - CARD16 *gammaBlue; - CARD16 *gammaGreen; - void *devPrivate; - Bool transforms; - RRTransformRec client_pending_transform; - RRTransformRec client_current_transform; - PictTransform transform; - struct pict_f_transform f_transform; - struct pict_f_transform f_inverse; -}; - -struct _rrOutput { - RROutput id; - ScreenPtr pScreen; - char *name; - int nameLength; - CARD8 connection; - CARD8 subpixelOrder; - int mmWidth; - int mmHeight; - RRCrtcPtr crtc; - int numCrtcs; - RRCrtcPtr *crtcs; - int numClones; - RROutputPtr *clones; - int numModes; - int numPreferred; - RRModePtr *modes; - int numUserModes; - RRModePtr *userModes; - Bool changed; - RRPropertyPtr properties; - Bool pendingProperties; - void *devPrivate; -}; - -#if RANDR_12_INTERFACE -typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, - CARD32 mmHeight); - -typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen, - RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutputs, - RROutputPtr *outputs); - -typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen, - RRCrtcPtr crtc); - -typedef Bool (*RRCrtcGetGammaProcPtr) (ScreenPtr pScreen, - RRCrtcPtr crtc); - -typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen, - RROutputPtr output, - Atom property, - RRPropertyValuePtr value); - -typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen, - RROutputPtr output, - RRModePtr mode); - -typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen, - RRModePtr mode); - -#endif - -#if RANDR_13_INTERFACE -typedef Bool (*RROutputGetPropertyProcPtr) (ScreenPtr pScreen, - RROutputPtr output, - Atom property); -typedef Bool (*RRGetPanningProcPtr) (ScreenPtr pScrn, - RRCrtcPtr crtc, - BoxPtr totalArea, - BoxPtr trackingArea, - INT16 *border); -typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn, - RRCrtcPtr crtc, - BoxPtr totalArea, - BoxPtr trackingArea, - INT16 *border); - -#endif /* RANDR_13_INTERFACE */ - -typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations); -typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen); - -/* These are for 1.0 compatibility */ - -typedef struct _rrRefresh { - CARD16 rate; - RRModePtr mode; -} RRScreenRate, *RRScreenRatePtr; - -typedef struct _rrScreenSize { - int id; - short width, height; - short mmWidth, mmHeight; - int nRates; - RRScreenRatePtr pRates; -} RRScreenSize, *RRScreenSizePtr; - -#ifdef RANDR_10_INTERFACE - -typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, - Rotation rotation, - int rate, - RRScreenSizePtr pSize); - -#endif - - -typedef struct _rrScrPriv { - /* - * 'public' part of the structure; DDXen fill this in - * as they initialize - */ -#if RANDR_10_INTERFACE - RRSetConfigProcPtr rrSetConfig; -#endif - RRGetInfoProcPtr rrGetInfo; -#if RANDR_12_INTERFACE - RRScreenSetSizeProcPtr rrScreenSetSize; - RRCrtcSetProcPtr rrCrtcSet; - RRCrtcSetGammaProcPtr rrCrtcSetGamma; - RRCrtcGetGammaProcPtr rrCrtcGetGamma; - RROutputSetPropertyProcPtr rrOutputSetProperty; - RROutputValidateModeProcPtr rrOutputValidateMode; - RRModeDestroyProcPtr rrModeDestroy; -#endif -#if RANDR_13_INTERFACE - RROutputGetPropertyProcPtr rrOutputGetProperty; - RRGetPanningProcPtr rrGetPanning; - RRSetPanningProcPtr rrSetPanning; -#endif - - /* - * Private part of the structure; not considered part of the ABI - */ - TimeStamp lastSetTime; /* last changed by client */ - TimeStamp lastConfigTime; /* possible configs changed */ - RRCloseScreenProcPtr CloseScreen; - - Bool changed; /* some config changed */ - Bool configChanged; /* configuration changed */ - Bool layoutChanged; /* screen layout changed */ - - CARD16 minWidth, minHeight; - CARD16 maxWidth, maxHeight; - CARD16 width, height; /* last known screen size */ - CARD16 mmWidth, mmHeight; /* last known screen size */ - - int numOutputs; - RROutputPtr *outputs; - RROutputPtr primaryOutput; - - int numCrtcs; - RRCrtcPtr *crtcs; - - /* Last known pointer position */ - RRCrtcPtr pointerCrtc; - -#ifdef RANDR_10_INTERFACE - /* - * Configuration information - */ - Rotation rotations; - CARD16 reqWidth, reqHeight; - - int nSizes; - RRScreenSizePtr pSizes; - - Rotation rotation; - int rate; - int size; -#endif -} rrScrPrivRec, *rrScrPrivPtr; - -extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec; -#define rrPrivKey (&rrPrivKeyRec) - -#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey)) -#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr) -#define SetRRScreen(s,p) dixSetPrivate(&(s)->devPrivates, rrPrivKey, p) - -/* - * each window has a list of clients requesting - * RRNotify events. Each client has a resource - * for each window it selects RRNotify input for, - * this resource is used to delete the RRNotifyRec - * entry from the per-window queue. - */ - -typedef struct _RREvent *RREventPtr; - -typedef struct _RREvent { - RREventPtr next; - ClientPtr client; - WindowPtr window; - XID clientResource; - int mask; -} RREventRec; - -typedef struct _RRTimes { - TimeStamp setTime; - TimeStamp configTime; -} RRTimesRec, *RRTimesPtr; - -typedef struct _RRClient { - int major_version; - int minor_version; -/* RRTimesRec times[0]; */ -} RRClientRec, *RRClientPtr; - -extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for event masks */ -extern _X_EXPORT DevPrivateKeyRec RRClientPrivateKeyRec; -#define RRClientPrivateKey (&RRClientPrivateKeyRec) -extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType; - -#define VERIFY_RR_OUTPUT(id, ptr, a)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ - RROutputType, client, a);\ - if (rc != Success) {\ - client->errorValue = id;\ - return rc;\ - }\ - } - -#define VERIFY_RR_CRTC(id, ptr, a)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ - RRCrtcType, client, a);\ - if (rc != Success) {\ - client->errorValue = id;\ - return rc;\ - }\ - } - -#define VERIFY_RR_MODE(id, ptr, a)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ - RRModeType, client, a);\ - if (rc != Success) {\ - client->errorValue = id;\ - return rc;\ - }\ - } - -#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey)) -#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) - -/* Initialize the extension */ -extern _X_EXPORT void -RRExtensionInit (void); - -#ifdef RANDR_12_INTERFACE -/* - * Set the range of sizes for the screen - */ -extern _X_EXPORT void -RRScreenSetSizeRange (ScreenPtr pScreen, - CARD16 minWidth, - CARD16 minHeight, - CARD16 maxWidth, - CARD16 maxHeight); -#endif - -/* rrscreen.c */ -/* - * Notify the extension that the screen size has been changed. - * The driver is responsible for calling this whenever it has changed - * the size of the screen - */ -extern _X_EXPORT void -RRScreenSizeNotify (ScreenPtr pScreen); - -/* - * Request that the screen be resized - */ -extern _X_EXPORT Bool -RRScreenSizeSet (ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, - CARD32 mmHeight); - -/* - * Send ConfigureNotify event to root window when 'something' happens - */ -extern _X_EXPORT void -RRSendConfigNotify (ScreenPtr pScreen); - -/* - * screen dispatch - */ -extern _X_EXPORT int -ProcRRGetScreenSizeRange (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetScreenSize (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetScreenResources (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetScreenResourcesCurrent (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetScreenConfig (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetScreenInfo (ClientPtr client); - -/* - * Deliver a ScreenNotify event - */ -extern _X_EXPORT void -RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen); - -/* randr.c */ -/* - * Send all pending events - */ -extern _X_EXPORT void -RRTellChanged (ScreenPtr pScreen); - -/* - * Poll the driver for changed information - */ -extern _X_EXPORT Bool -RRGetInfo (ScreenPtr pScreen, Bool force_query); - -extern _X_EXPORT Bool RRInit (void); - -extern _X_EXPORT Bool RRScreenInit(ScreenPtr pScreen); - -extern _X_EXPORT RROutputPtr -RRFirstOutput (ScreenPtr pScreen); - -extern _X_EXPORT Rotation -RRGetRotation (ScreenPtr pScreen); - -extern _X_EXPORT CARD16 -RRVerticalRefresh (xRRModeInfo *mode); - -#ifdef RANDR_10_INTERFACE -/* - * This is the old interface, deprecated but left - * around for compatibility - */ - -/* - * Then, register the specific size with the screen - */ - -extern _X_EXPORT RRScreenSizePtr -RRRegisterSize (ScreenPtr pScreen, - short width, - short height, - short mmWidth, - short mmHeight); - -extern _X_EXPORT Bool -RRRegisterRate (ScreenPtr pScreen, - RRScreenSizePtr pSize, - int rate); - -/* - * Finally, set the current configuration of the screen - */ - -extern _X_EXPORT void -RRSetCurrentConfig (ScreenPtr pScreen, - Rotation rotation, - int rate, - RRScreenSizePtr pSize); - -extern _X_EXPORT Bool RRScreenInit (ScreenPtr pScreen); - -extern _X_EXPORT Rotation -RRGetRotation (ScreenPtr pScreen); - -#endif - -/* rrcrtc.c */ - -/* - * Notify the CRTC of some change; layoutChanged indicates that - * some position or size element changed - */ -extern _X_EXPORT void -RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged); - -/* - * Create a CRTC - */ -extern _X_EXPORT RRCrtcPtr -RRCrtcCreate (ScreenPtr pScreen, void *devPrivate); - -/* - * Set the allowed rotations on a CRTC - */ -extern _X_EXPORT void -RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations); - -/* - * Set whether transforms are allowed on a CRTC - */ -extern _X_EXPORT void -RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms); - -/* - * Notify the extension that the Crtc has been reconfigured, - * the driver calls this whenever it has updated the mode - */ -extern _X_EXPORT Bool -RRCrtcNotify (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - RRTransformPtr transform, - int numOutputs, - RROutputPtr *outputs); - -extern _X_EXPORT void -RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc); - -/* - * Request that the Crtc be reconfigured - */ -extern _X_EXPORT Bool -RRCrtcSet (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutput, - RROutputPtr *outputs); - -/* - * Request that the Crtc gamma be changed - */ - -extern _X_EXPORT Bool -RRCrtcGammaSet (RRCrtcPtr crtc, - CARD16 *red, - CARD16 *green, - CARD16 *blue); - -/* - * Request current gamma back from the DDX (if possible). - * This includes gamma size. - */ - -extern _X_EXPORT Bool -RRCrtcGammaGet(RRCrtcPtr crtc); - -/* - * Notify the extension that the Crtc gamma has been changed - * The driver calls this whenever it has changed the gamma values - * in the RRCrtcRec - */ - -extern _X_EXPORT Bool -RRCrtcGammaNotify (RRCrtcPtr crtc); - -/* - * Set the size of the gamma table at server startup time - */ - -extern _X_EXPORT Bool -RRCrtcGammaSetSize (RRCrtcPtr crtc, - int size); - -/* - * Return the area of the frame buffer scanned out by the crtc, - * taking into account the current mode and rotation - */ - -extern _X_EXPORT void -RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height); - -/* - * Compute the complete transformation matrix including - * client-specified transform, rotation/reflection values and the crtc - * offset. - * - * Return TRUE if the resulting transform is not a simple translation. - */ -extern _X_EXPORT Bool -RRTransformCompute (int x, - int y, - int width, - int height, - Rotation rotation, - RRTransformPtr rr_transform, - - PictTransformPtr transform, - struct pict_f_transform *f_transform, - struct pict_f_transform *f_inverse); - -/* - * Return crtc transform - */ -extern _X_EXPORT RRTransformPtr -RRCrtcGetTransform (RRCrtcPtr crtc); - -/* - * Check whether the pending and current transforms are the same - */ -extern _X_EXPORT Bool -RRCrtcPendingTransform (RRCrtcPtr crtc); - -/* - * Destroy a Crtc at shutdown - */ -extern _X_EXPORT void -RRCrtcDestroy (RRCrtcPtr crtc); - - -/* - * Set the pending CRTC transformation - */ - -extern _X_EXPORT int -RRCrtcTransformSet (RRCrtcPtr crtc, - PictTransformPtr transform, - struct pict_f_transform *f_transform, - struct pict_f_transform *f_inverse, - char *filter, - int filter_len, - xFixed *params, - int nparams); - -/* - * Initialize crtc type - */ -extern _X_EXPORT Bool -RRCrtcInit (void); - -/* - * Initialize crtc type error value - */ -extern _X_EXPORT void -RRCrtcInitErrorValue (void); - -/* - * Crtc dispatch - */ - -extern _X_EXPORT int -ProcRRGetCrtcInfo (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetCrtcConfig (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetCrtcGammaSize (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetCrtcGamma (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetCrtcGamma (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetCrtcTransform (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetCrtcTransform (ClientPtr client); - -int -ProcRRGetPanning (ClientPtr client); - -int -ProcRRSetPanning (ClientPtr client); - -/* rrdispatch.c */ -extern _X_EXPORT Bool -RRClientKnowsRates (ClientPtr pClient); - -/* rrmode.c */ -/* - * Find, and if necessary, create a mode - */ - -extern _X_EXPORT RRModePtr -RRModeGet (xRRModeInfo *modeInfo, - const char *name); - -/* - * Destroy a mode. - */ - -extern _X_EXPORT void -RRModeDestroy (RRModePtr mode); - -/* - * Return a list of modes that are valid for some output in pScreen - */ -extern _X_EXPORT RRModePtr * -RRModesForScreen (ScreenPtr pScreen, int *num_ret); - -/* - * Initialize mode type - */ -extern _X_EXPORT Bool -RRModeInit (void); - -/* - * Initialize mode type error value - */ -extern _X_EXPORT void -RRModeInitErrorValue (void); - -extern _X_EXPORT int -ProcRRCreateMode (ClientPtr client); - -extern _X_EXPORT int -ProcRRDestroyMode (ClientPtr client); - -extern _X_EXPORT int -ProcRRAddOutputMode (ClientPtr client); - -extern _X_EXPORT int -ProcRRDeleteOutputMode (ClientPtr client); - -/* rroutput.c */ - -/* - * Notify the output of some change. configChanged indicates whether - * any external configuration (mode list, clones, connected status) - * has changed, or whether the change was strictly internal - * (which crtc is in use) - */ -extern _X_EXPORT void -RROutputChanged (RROutputPtr output, Bool configChanged); - -/* - * Create an output - */ - -extern _X_EXPORT RROutputPtr -RROutputCreate (ScreenPtr pScreen, - const char *name, - int nameLength, - void *devPrivate); - -/* - * Notify extension that output parameters have been changed - */ -extern _X_EXPORT Bool -RROutputSetClones (RROutputPtr output, - RROutputPtr *clones, - int numClones); - -extern _X_EXPORT Bool -RROutputSetModes (RROutputPtr output, - RRModePtr *modes, - int numModes, - int numPreferred); - -extern _X_EXPORT int -RROutputAddUserMode (RROutputPtr output, - RRModePtr mode); - -extern _X_EXPORT int -RROutputDeleteUserMode (RROutputPtr output, - RRModePtr mode); - -extern _X_EXPORT Bool -RROutputSetCrtcs (RROutputPtr output, - RRCrtcPtr *crtcs, - int numCrtcs); - -extern _X_EXPORT Bool -RROutputSetConnection (RROutputPtr output, - CARD8 connection); - -extern _X_EXPORT Bool -RROutputSetSubpixelOrder (RROutputPtr output, - int subpixelOrder); - -extern _X_EXPORT Bool -RROutputSetPhysicalSize (RROutputPtr output, - int mmWidth, - int mmHeight); - -extern _X_EXPORT void -RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output); - -extern _X_EXPORT void -RROutputDestroy (RROutputPtr output); - -extern _X_EXPORT int -ProcRRGetOutputInfo (ClientPtr client); - -extern _X_EXPORT int -ProcRRSetOutputPrimary (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetOutputPrimary (ClientPtr client); - -/* - * Initialize output type - */ -extern _X_EXPORT Bool -RROutputInit (void); - -/* - * Initialize output type error value - */ -extern _X_EXPORT void -RROutputInitErrorValue (void); - -/* rrpointer.c */ -extern _X_EXPORT void -RRPointerMoved (ScreenPtr pScreen, int x, int y); - -extern _X_EXPORT void -RRPointerScreenConfigured (ScreenPtr pScreen); - -/* rrproperty.c */ - -extern _X_EXPORT void -RRDeleteAllOutputProperties (RROutputPtr output); - -extern _X_EXPORT RRPropertyValuePtr -RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending); - -extern _X_EXPORT RRPropertyPtr -RRQueryOutputProperty (RROutputPtr output, Atom property); - -extern _X_EXPORT void -RRDeleteOutputProperty (RROutputPtr output, Atom property); - -extern _X_EXPORT Bool -RRPostPendingProperties (RROutputPtr output); - -extern _X_EXPORT int -RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, - int format, int mode, unsigned long len, - pointer value, Bool sendevent, Bool pending); - -extern _X_EXPORT int -RRConfigureOutputProperty (RROutputPtr output, Atom property, - Bool pending, Bool range, Bool immutable, - int num_values, INT32 *values); -extern _X_EXPORT int -ProcRRChangeOutputProperty (ClientPtr client); - -extern _X_EXPORT int -ProcRRGetOutputProperty (ClientPtr client); - -extern _X_EXPORT int -ProcRRListOutputProperties (ClientPtr client); - -extern _X_EXPORT int -ProcRRQueryOutputProperty (ClientPtr client); - -extern _X_EXPORT int -ProcRRConfigureOutputProperty (ClientPtr client); - -extern _X_EXPORT int -ProcRRDeleteOutputProperty (ClientPtr client); - -/* rrxinerama.c */ -#ifdef XINERAMA -extern _X_EXPORT void -RRXineramaExtensionInit(void); -#endif - -#endif /* _RANDRSTR_H_ */ - -/* - -randr extension implementation structure - -Query state: - ProcRRGetScreenInfo/ProcRRGetScreenResources - RRGetInfo - - • Request configuration from driver, either 1.0 or 1.2 style - • These functions only record state changes, all - other actions are pended until RRTellChanged is called - - ->rrGetInfo - 1.0: - RRRegisterSize - RRRegisterRate - RRSetCurrentConfig - 1.2: - RRScreenSetSizeRange - RROutputSetCrtcs - RRModeGet - RROutputSetModes - RROutputSetConnection - RROutputSetSubpixelOrder - RROutputSetClones - RRCrtcNotify - - • Must delay scanning configuration until after ->rrGetInfo returns - because some drivers will call SetCurrentConfig in the middle - of the ->rrGetInfo operation. - - 1.0: - - • Scan old configuration, mirror to new structures - - RRScanOldConfig - RRCrtcCreate - RROutputCreate - RROutputSetCrtcs - RROutputSetConnection - RROutputSetSubpixelOrder - RROldModeAdd • This adds modes one-at-a-time - RRModeGet - RRCrtcNotify - - • send events, reset pointer if necessary - - RRTellChanged - WalkTree (sending events) - - • when layout has changed: - RRPointerScreenConfigured - RRSendConfigNotify - -Asynchronous state setting (1.2 only) - When setting state asynchronously, the driver invokes the - ->rrGetInfo function and then calls RRTellChanged to flush - the changes to the clients and reset pointer if necessary - -Set state - - ProcRRSetScreenConfig - RRCrtcSet - 1.2: - ->rrCrtcSet - RRCrtcNotify - 1.0: - ->rrSetConfig - RRCrtcNotify - RRTellChanged - */ +/* + * Copyright © 2000 Compaq Computer Corporation + * Copyright © 2002 Hewlett-Packard Company + * Copyright © 2006 Intel Corporation + * Copyright © 2008 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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: Jim Gettys, Hewlett-Packard Company, Inc. + * Keith Packard, Intel Corporation + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef _RANDRSTR_H_ +#define _RANDRSTR_H_ + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include "rrtransform.h" +#include +#include +#include /* we share subpixel order information */ +#include "picturestr.h" +#include + +/* required for ABI compatibility for now */ +#define RANDR_10_INTERFACE 1 +#define RANDR_12_INTERFACE 1 +#define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */ +#define RANDR_GET_CRTC_INTERFACE 1 + +#define RANDR_INTERFACE_VERSION 0x0103 + +typedef XID RRMode; +typedef XID RROutput; +typedef XID RRCrtc; + +extern _X_EXPORT int RREventBase, RRErrorBase; + +extern _X_EXPORT int (*ProcRandrVector[RRNumberRequests])(ClientPtr); +extern _X_EXPORT int (*SProcRandrVector[RRNumberRequests])(ClientPtr); + +/* + * Modeline for a monitor. Name follows directly after this struct + */ + +#define RRModeName(pMode) ((char *) (pMode + 1)) +typedef struct _rrMode RRModeRec, *RRModePtr; +typedef struct _rrPropertyValue RRPropertyValueRec, *RRPropertyValuePtr; +typedef struct _rrProperty RRPropertyRec, *RRPropertyPtr; +typedef struct _rrCrtc RRCrtcRec, *RRCrtcPtr; +typedef struct _rrOutput RROutputRec, *RROutputPtr; + +struct _rrMode { + int refcnt; + xRRModeInfo mode; + char *name; + ScreenPtr userScreen; +}; + +struct _rrPropertyValue { + Atom type; /* ignored by server */ + short format; /* format of data for swapping - 8,16,32 */ + long size; /* size of data in (format/8) bytes */ + pointer data; /* private to client */ +}; + +struct _rrProperty { + RRPropertyPtr next; + ATOM propertyName; + Bool is_pending; + Bool range; + Bool immutable; + int num_valid; + INT32 *valid_values; + RRPropertyValueRec current, pending; +}; + +struct _rrCrtc { + RRCrtc id; + ScreenPtr pScreen; + RRModePtr mode; + int x, y; + Rotation rotation; + Rotation rotations; + Bool changed; + int numOutputs; + RROutputPtr *outputs; + int gammaSize; + CARD16 *gammaRed; + CARD16 *gammaBlue; + CARD16 *gammaGreen; + void *devPrivate; + Bool transforms; + RRTransformRec client_pending_transform; + RRTransformRec client_current_transform; + PictTransform transform; + struct pict_f_transform f_transform; + struct pict_f_transform f_inverse; +}; + +struct _rrOutput { + RROutput id; + ScreenPtr pScreen; + char *name; + int nameLength; + CARD8 connection; + CARD8 subpixelOrder; + int mmWidth; + int mmHeight; + RRCrtcPtr crtc; + int numCrtcs; + RRCrtcPtr *crtcs; + int numClones; + RROutputPtr *clones; + int numModes; + int numPreferred; + RRModePtr *modes; + int numUserModes; + RRModePtr *userModes; + Bool changed; + RRPropertyPtr properties; + Bool pendingProperties; + void *devPrivate; +}; + +#if RANDR_12_INTERFACE +typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight); + +typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen, + RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutputs, + RROutputPtr *outputs); + +typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen, + RRCrtcPtr crtc); + +typedef Bool (*RRCrtcGetGammaProcPtr) (ScreenPtr pScreen, + RRCrtcPtr crtc); + +typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen, + RROutputPtr output, + Atom property, + RRPropertyValuePtr value); + +typedef Bool (*RROutputValidateModeProcPtr) (ScreenPtr pScreen, + RROutputPtr output, + RRModePtr mode); + +typedef void (*RRModeDestroyProcPtr) (ScreenPtr pScreen, + RRModePtr mode); + +#endif + +#if RANDR_13_INTERFACE +typedef Bool (*RROutputGetPropertyProcPtr) (ScreenPtr pScreen, + RROutputPtr output, + Atom property); +typedef Bool (*RRGetPanningProcPtr) (ScreenPtr pScrn, + RRCrtcPtr crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border); +typedef Bool (*RRSetPanningProcPtr) (ScreenPtr pScrn, + RRCrtcPtr crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border); + +#endif /* RANDR_13_INTERFACE */ + +typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations); +typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen); + +/* These are for 1.0 compatibility */ + +typedef struct _rrRefresh { + CARD16 rate; + RRModePtr mode; +} RRScreenRate, *RRScreenRatePtr; + +typedef struct _rrScreenSize { + int id; + short width, height; + short mmWidth, mmHeight; + int nRates; + RRScreenRatePtr pRates; +} RRScreenSize, *RRScreenSizePtr; + +#ifdef RANDR_10_INTERFACE + +typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize); + +#endif + + +typedef struct _rrScrPriv { + /* + * 'public' part of the structure; DDXen fill this in + * as they initialize + */ +#if RANDR_10_INTERFACE + RRSetConfigProcPtr rrSetConfig; +#endif + RRGetInfoProcPtr rrGetInfo; +#if RANDR_12_INTERFACE + RRScreenSetSizeProcPtr rrScreenSetSize; + RRCrtcSetProcPtr rrCrtcSet; + RRCrtcSetGammaProcPtr rrCrtcSetGamma; + RRCrtcGetGammaProcPtr rrCrtcGetGamma; + RROutputSetPropertyProcPtr rrOutputSetProperty; + RROutputValidateModeProcPtr rrOutputValidateMode; + RRModeDestroyProcPtr rrModeDestroy; +#endif +#if RANDR_13_INTERFACE + RROutputGetPropertyProcPtr rrOutputGetProperty; + RRGetPanningProcPtr rrGetPanning; + RRSetPanningProcPtr rrSetPanning; +#endif + + /* + * Private part of the structure; not considered part of the ABI + */ + TimeStamp lastSetTime; /* last changed by client */ + TimeStamp lastConfigTime; /* possible configs changed */ + RRCloseScreenProcPtr CloseScreen; + + Bool changed; /* some config changed */ + Bool configChanged; /* configuration changed */ + Bool layoutChanged; /* screen layout changed */ + + CARD16 minWidth, minHeight; + CARD16 maxWidth, maxHeight; + CARD16 width, height; /* last known screen size */ + CARD16 mmWidth, mmHeight; /* last known screen size */ + + int numOutputs; + RROutputPtr *outputs; + RROutputPtr primaryOutput; + + int numCrtcs; + RRCrtcPtr *crtcs; + + /* Last known pointer position */ + RRCrtcPtr pointerCrtc; + +#ifdef RANDR_10_INTERFACE + /* + * Configuration information + */ + Rotation rotations; + CARD16 reqWidth, reqHeight; + + int nSizes; + RRScreenSizePtr pSizes; + + Rotation rotation; + int rate; + int size; +#endif + Bool discontiguous; +} rrScrPrivRec, *rrScrPrivPtr; + +extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec; +#define rrPrivKey (&rrPrivKeyRec) + +#define rrGetScrPriv(pScr) ((rrScrPrivPtr)dixLookupPrivate(&(pScr)->devPrivates, rrPrivKey)) +#define rrScrPriv(pScr) rrScrPrivPtr pScrPriv = rrGetScrPriv(pScr) +#define SetRRScreen(s,p) dixSetPrivate(&(s)->devPrivates, rrPrivKey, p) + +/* + * each window has a list of clients requesting + * RRNotify events. Each client has a resource + * for each window it selects RRNotify input for, + * this resource is used to delete the RRNotifyRec + * entry from the per-window queue. + */ + +typedef struct _RREvent *RREventPtr; + +typedef struct _RREvent { + RREventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; + int mask; +} RREventRec; + +typedef struct _RRTimes { + TimeStamp setTime; + TimeStamp configTime; +} RRTimesRec, *RRTimesPtr; + +typedef struct _RRClient { + int major_version; + int minor_version; +/* RRTimesRec times[0]; */ +} RRClientRec, *RRClientPtr; + +extern _X_EXPORT RESTYPE RRClientType, RREventType; /* resource types for event masks */ +extern _X_EXPORT DevPrivateKeyRec RRClientPrivateKeyRec; +#define RRClientPrivateKey (&RRClientPrivateKeyRec) +extern _X_EXPORT RESTYPE RRCrtcType, RRModeType, RROutputType; + +#define VERIFY_RR_OUTPUT(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ + RROutputType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define VERIFY_RR_CRTC(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ + RRCrtcType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define VERIFY_RR_MODE(id, ptr, a)\ + {\ + int rc = dixLookupResourceByType((pointer *)&(ptr), id,\ + RRModeType, client, a);\ + if (rc != Success) {\ + client->errorValue = id;\ + return rc;\ + }\ + } + +#define GetRRClient(pClient) ((RRClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RRClientPrivateKey)) +#define rrClientPriv(pClient) RRClientPtr pRRClient = GetRRClient(pClient) + +/* Initialize the extension */ +extern _X_EXPORT void +RRExtensionInit (void); + +#ifdef RANDR_12_INTERFACE +/* + * Set the range of sizes for the screen + */ +extern _X_EXPORT void +RRScreenSetSizeRange (ScreenPtr pScreen, + CARD16 minWidth, + CARD16 minHeight, + CARD16 maxWidth, + CARD16 maxHeight); +#endif + +/* rrscreen.c */ +/* + * Notify the extension that the screen size has been changed. + * The driver is responsible for calling this whenever it has changed + * the size of the screen + */ +extern _X_EXPORT void +RRScreenSizeNotify (ScreenPtr pScreen); + +/* + * Request that the screen be resized + */ +extern _X_EXPORT Bool +RRScreenSizeSet (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight); + +/* + * Send ConfigureNotify event to root window when 'something' happens + */ +extern _X_EXPORT void +RRSendConfigNotify (ScreenPtr pScreen); + +/* + * screen dispatch + */ +extern _X_EXPORT int +ProcRRGetScreenSizeRange (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetScreenSize (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetScreenResources (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetScreenResourcesCurrent (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetScreenConfig (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetScreenInfo (ClientPtr client); + +/* + * Deliver a ScreenNotify event + */ +extern _X_EXPORT void +RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen); + +/* randr.c */ +/* + * Send all pending events + */ +extern _X_EXPORT void +RRTellChanged (ScreenPtr pScreen); + +/* + * Poll the driver for changed information + */ +extern _X_EXPORT Bool +RRGetInfo (ScreenPtr pScreen, Bool force_query); + +extern _X_EXPORT Bool RRInit (void); + +extern _X_EXPORT Bool RRScreenInit(ScreenPtr pScreen); + +extern _X_EXPORT RROutputPtr +RRFirstOutput (ScreenPtr pScreen); + +extern _X_EXPORT Rotation +RRGetRotation (ScreenPtr pScreen); + +extern _X_EXPORT CARD16 +RRVerticalRefresh (xRRModeInfo *mode); + +#ifdef RANDR_10_INTERFACE +/* + * This is the old interface, deprecated but left + * around for compatibility + */ + +/* + * Then, register the specific size with the screen + */ + +extern _X_EXPORT RRScreenSizePtr +RRRegisterSize (ScreenPtr pScreen, + short width, + short height, + short mmWidth, + short mmHeight); + +extern _X_EXPORT Bool +RRRegisterRate (ScreenPtr pScreen, + RRScreenSizePtr pSize, + int rate); + +/* + * Finally, set the current configuration of the screen + */ + +extern _X_EXPORT void +RRSetCurrentConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize); + +extern _X_EXPORT Bool RRScreenInit (ScreenPtr pScreen); + +extern _X_EXPORT Rotation +RRGetRotation (ScreenPtr pScreen); + +#endif + +/* rrcrtc.c */ + +/* + * Notify the CRTC of some change; layoutChanged indicates that + * some position or size element changed + */ +extern _X_EXPORT void +RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged); + +/* + * Create a CRTC + */ +extern _X_EXPORT RRCrtcPtr +RRCrtcCreate (ScreenPtr pScreen, void *devPrivate); + +/* + * Set the allowed rotations on a CRTC + */ +extern _X_EXPORT void +RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations); + +/* + * Set whether transforms are allowed on a CRTC + */ +extern _X_EXPORT void +RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms); + +/* + * Notify the extension that the Crtc has been reconfigured, + * the driver calls this whenever it has updated the mode + */ +extern _X_EXPORT Bool +RRCrtcNotify (RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + RRTransformPtr transform, + int numOutputs, + RROutputPtr *outputs); + +extern _X_EXPORT void +RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc); + +/* + * Request that the Crtc be reconfigured + */ +extern _X_EXPORT Bool +RRCrtcSet (RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutput, + RROutputPtr *outputs); + +/* + * Request that the Crtc gamma be changed + */ + +extern _X_EXPORT Bool +RRCrtcGammaSet (RRCrtcPtr crtc, + CARD16 *red, + CARD16 *green, + CARD16 *blue); + +/* + * Request current gamma back from the DDX (if possible). + * This includes gamma size. + */ + +extern _X_EXPORT Bool +RRCrtcGammaGet(RRCrtcPtr crtc); + +/* + * Notify the extension that the Crtc gamma has been changed + * The driver calls this whenever it has changed the gamma values + * in the RRCrtcRec + */ + +extern _X_EXPORT Bool +RRCrtcGammaNotify (RRCrtcPtr crtc); + +/* + * Set the size of the gamma table at server startup time + */ + +extern _X_EXPORT Bool +RRCrtcGammaSetSize (RRCrtcPtr crtc, + int size); + +/* + * Return the area of the frame buffer scanned out by the crtc, + * taking into account the current mode and rotation + */ + +extern _X_EXPORT void +RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height); + +/* + * Compute the complete transformation matrix including + * client-specified transform, rotation/reflection values and the crtc + * offset. + * + * Return TRUE if the resulting transform is not a simple translation. + */ +extern _X_EXPORT Bool +RRTransformCompute (int x, + int y, + int width, + int height, + Rotation rotation, + RRTransformPtr rr_transform, + + PictTransformPtr transform, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse); + +/* + * Return crtc transform + */ +extern _X_EXPORT RRTransformPtr +RRCrtcGetTransform (RRCrtcPtr crtc); + +/* + * Check whether the pending and current transforms are the same + */ +extern _X_EXPORT Bool +RRCrtcPendingTransform (RRCrtcPtr crtc); + +/* + * Destroy a Crtc at shutdown + */ +extern _X_EXPORT void +RRCrtcDestroy (RRCrtcPtr crtc); + + +/* + * Set the pending CRTC transformation + */ + +extern _X_EXPORT int +RRCrtcTransformSet (RRCrtcPtr crtc, + PictTransformPtr transform, + struct pict_f_transform *f_transform, + struct pict_f_transform *f_inverse, + char *filter, + int filter_len, + xFixed *params, + int nparams); + +/* + * Initialize crtc type + */ +extern _X_EXPORT Bool +RRCrtcInit (void); + +/* + * Initialize crtc type error value + */ +extern _X_EXPORT void +RRCrtcInitErrorValue (void); + +/* + * Crtc dispatch + */ + +extern _X_EXPORT int +ProcRRGetCrtcInfo (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetCrtcConfig (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetCrtcGammaSize (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetCrtcGamma (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetCrtcGamma (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetCrtcTransform (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetCrtcTransform (ClientPtr client); + +int +ProcRRGetPanning (ClientPtr client); + +int +ProcRRSetPanning (ClientPtr client); + +void +RRConstrainCursorHarder (DeviceIntPtr, ScreenPtr, int, int *, int *); + +/* rrdispatch.c */ +extern _X_EXPORT Bool +RRClientKnowsRates (ClientPtr pClient); + +/* rrmode.c */ +/* + * Find, and if necessary, create a mode + */ + +extern _X_EXPORT RRModePtr +RRModeGet (xRRModeInfo *modeInfo, + const char *name); + +/* + * Destroy a mode. + */ + +extern _X_EXPORT void +RRModeDestroy (RRModePtr mode); + +/* + * Return a list of modes that are valid for some output in pScreen + */ +extern _X_EXPORT RRModePtr * +RRModesForScreen (ScreenPtr pScreen, int *num_ret); + +/* + * Initialize mode type + */ +extern _X_EXPORT Bool +RRModeInit (void); + +/* + * Initialize mode type error value + */ +extern _X_EXPORT void +RRModeInitErrorValue (void); + +extern _X_EXPORT int +ProcRRCreateMode (ClientPtr client); + +extern _X_EXPORT int +ProcRRDestroyMode (ClientPtr client); + +extern _X_EXPORT int +ProcRRAddOutputMode (ClientPtr client); + +extern _X_EXPORT int +ProcRRDeleteOutputMode (ClientPtr client); + +/* rroutput.c */ + +/* + * Notify the output of some change. configChanged indicates whether + * any external configuration (mode list, clones, connected status) + * has changed, or whether the change was strictly internal + * (which crtc is in use) + */ +extern _X_EXPORT void +RROutputChanged (RROutputPtr output, Bool configChanged); + +/* + * Create an output + */ + +extern _X_EXPORT RROutputPtr +RROutputCreate (ScreenPtr pScreen, + const char *name, + int nameLength, + void *devPrivate); + +/* + * Notify extension that output parameters have been changed + */ +extern _X_EXPORT Bool +RROutputSetClones (RROutputPtr output, + RROutputPtr *clones, + int numClones); + +extern _X_EXPORT Bool +RROutputSetModes (RROutputPtr output, + RRModePtr *modes, + int numModes, + int numPreferred); + +extern _X_EXPORT int +RROutputAddUserMode (RROutputPtr output, + RRModePtr mode); + +extern _X_EXPORT int +RROutputDeleteUserMode (RROutputPtr output, + RRModePtr mode); + +extern _X_EXPORT Bool +RROutputSetCrtcs (RROutputPtr output, + RRCrtcPtr *crtcs, + int numCrtcs); + +extern _X_EXPORT Bool +RROutputSetConnection (RROutputPtr output, + CARD8 connection); + +extern _X_EXPORT Bool +RROutputSetSubpixelOrder (RROutputPtr output, + int subpixelOrder); + +extern _X_EXPORT Bool +RROutputSetPhysicalSize (RROutputPtr output, + int mmWidth, + int mmHeight); + +extern _X_EXPORT void +RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output); + +extern _X_EXPORT void +RROutputDestroy (RROutputPtr output); + +extern _X_EXPORT int +ProcRRGetOutputInfo (ClientPtr client); + +extern _X_EXPORT int +ProcRRSetOutputPrimary (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetOutputPrimary (ClientPtr client); + +/* + * Initialize output type + */ +extern _X_EXPORT Bool +RROutputInit (void); + +/* + * Initialize output type error value + */ +extern _X_EXPORT void +RROutputInitErrorValue (void); + +/* rrpointer.c */ +extern _X_EXPORT void +RRPointerMoved (ScreenPtr pScreen, int x, int y); + +extern _X_EXPORT void +RRPointerScreenConfigured (ScreenPtr pScreen); + +/* rrproperty.c */ + +extern _X_EXPORT void +RRDeleteAllOutputProperties (RROutputPtr output); + +extern _X_EXPORT RRPropertyValuePtr +RRGetOutputProperty (RROutputPtr output, Atom property, Bool pending); + +extern _X_EXPORT RRPropertyPtr +RRQueryOutputProperty (RROutputPtr output, Atom property); + +extern _X_EXPORT void +RRDeleteOutputProperty (RROutputPtr output, Atom property); + +extern _X_EXPORT Bool +RRPostPendingProperties (RROutputPtr output); + +extern _X_EXPORT int +RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type, + int format, int mode, unsigned long len, + pointer value, Bool sendevent, Bool pending); + +extern _X_EXPORT int +RRConfigureOutputProperty (RROutputPtr output, Atom property, + Bool pending, Bool range, Bool immutable, + int num_values, INT32 *values); +extern _X_EXPORT int +ProcRRChangeOutputProperty (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetOutputProperty (ClientPtr client); + +extern _X_EXPORT int +ProcRRListOutputProperties (ClientPtr client); + +extern _X_EXPORT int +ProcRRQueryOutputProperty (ClientPtr client); + +extern _X_EXPORT int +ProcRRConfigureOutputProperty (ClientPtr client); + +extern _X_EXPORT int +ProcRRDeleteOutputProperty (ClientPtr client); + +/* rrxinerama.c */ +#ifdef XINERAMA +extern _X_EXPORT void +RRXineramaExtensionInit(void); +#endif + +#endif /* _RANDRSTR_H_ */ + +/* + +randr extension implementation structure + +Query state: + ProcRRGetScreenInfo/ProcRRGetScreenResources + RRGetInfo + + • Request configuration from driver, either 1.0 or 1.2 style + • These functions only record state changes, all + other actions are pended until RRTellChanged is called + + ->rrGetInfo + 1.0: + RRRegisterSize + RRRegisterRate + RRSetCurrentConfig + 1.2: + RRScreenSetSizeRange + RROutputSetCrtcs + RRModeGet + RROutputSetModes + RROutputSetConnection + RROutputSetSubpixelOrder + RROutputSetClones + RRCrtcNotify + + • Must delay scanning configuration until after ->rrGetInfo returns + because some drivers will call SetCurrentConfig in the middle + of the ->rrGetInfo operation. + + 1.0: + + • Scan old configuration, mirror to new structures + + RRScanOldConfig + RRCrtcCreate + RROutputCreate + RROutputSetCrtcs + RROutputSetConnection + RROutputSetSubpixelOrder + RROldModeAdd • This adds modes one-at-a-time + RRModeGet + RRCrtcNotify + + • send events, reset pointer if necessary + + RRTellChanged + WalkTree (sending events) + + • when layout has changed: + RRPointerScreenConfigured + RRSendConfigNotify + +Asynchronous state setting (1.2 only) + When setting state asynchronously, the driver invokes the + ->rrGetInfo function and then calls RRTellChanged to flush + the changes to the clients and reset pointer if necessary + +Set state + + ProcRRSetScreenConfig + RRCrtcSet + 1.2: + ->rrCrtcSet + RRCrtcNotify + 1.0: + ->rrSetConfig + RRCrtcNotify + RRTellChanged + */ diff --git a/xorg-server/randr/rrcrtc.c b/xorg-server/randr/rrcrtc.c index 98206a2b9..a846ad3d1 100644 --- a/xorg-server/randr/rrcrtc.c +++ b/xorg-server/randr/rrcrtc.c @@ -1,1351 +1,1506 @@ -/* - * Copyright © 2006 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#include "randrstr.h" -#include "swaprep.h" - -RESTYPE RRCrtcType; - -/* - * Notify the CRTC of some change - */ -void -RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) -{ - ScreenPtr pScreen = crtc->pScreen; - - crtc->changed = TRUE; - if (pScreen) - { - rrScrPriv(pScreen); - - pScrPriv->changed = TRUE; - /* - * Send ConfigureNotify on any layout change - */ - if (layoutChanged) - pScrPriv->layoutChanged = TRUE; - } -} - -/* - * Create a CRTC - */ -RRCrtcPtr -RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) -{ - RRCrtcPtr crtc; - RRCrtcPtr *crtcs; - rrScrPrivPtr pScrPriv; - - if (!RRInit()) - return NULL; - - pScrPriv = rrGetScrPriv(pScreen); - - /* make space for the crtc pointer */ - if (pScrPriv->numCrtcs) - crtcs = realloc(pScrPriv->crtcs, - (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); - else - crtcs = malloc(sizeof (RRCrtcPtr)); - if (!crtcs) - return FALSE; - pScrPriv->crtcs = crtcs; - - crtc = calloc(1, sizeof (RRCrtcRec)); - if (!crtc) - return NULL; - crtc->id = FakeClientID (0); - crtc->pScreen = pScreen; - crtc->mode = NULL; - crtc->x = 0; - crtc->y = 0; - crtc->rotation = RR_Rotate_0; - crtc->rotations = RR_Rotate_0; - crtc->outputs = NULL; - crtc->numOutputs = 0; - crtc->gammaSize = 0; - crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; - crtc->changed = FALSE; - crtc->devPrivate = devPrivate; - RRTransformInit (&crtc->client_pending_transform); - RRTransformInit (&crtc->client_current_transform); - pixman_transform_init_identity (&crtc->transform); - pixman_f_transform_init_identity (&crtc->f_transform); - pixman_f_transform_init_identity (&crtc->f_inverse); - - if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) - return NULL; - - /* attach the screen and crtc together */ - crtc->pScreen = pScreen; - pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; - - return crtc; -} - -/* - * Set the allowed rotations on a CRTC - */ -void -RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) -{ - crtc->rotations = rotations; -} - -/* - * Set whether transforms are allowed on a CRTC - */ -void -RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms) -{ - crtc->transforms = transforms; -} - -/* - * Notify the extension that the Crtc has been reconfigured, - * the driver calls this whenever it has updated the mode - */ -Bool -RRCrtcNotify (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - RRTransformPtr transform, - int numOutputs, - RROutputPtr *outputs) -{ - int i, j; - - /* - * Check to see if any of the new outputs were - * not in the old list and mark them as changed - */ - for (i = 0; i < numOutputs; i++) - { - for (j = 0; j < crtc->numOutputs; j++) - if (outputs[i] == crtc->outputs[j]) - break; - if (j == crtc->numOutputs) - { - outputs[i]->crtc = crtc; - RROutputChanged (outputs[i], FALSE); - RRCrtcChanged (crtc, FALSE); - } - } - /* - * Check to see if any of the old outputs are - * not in the new list and mark them as changed - */ - for (j = 0; j < crtc->numOutputs; j++) - { - for (i = 0; i < numOutputs; i++) - if (outputs[i] == crtc->outputs[j]) - break; - if (i == numOutputs) - { - if (crtc->outputs[j]->crtc == crtc) - crtc->outputs[j]->crtc = NULL; - RROutputChanged (crtc->outputs[j], FALSE); - RRCrtcChanged (crtc, FALSE); - } - } - /* - * Reallocate the crtc output array if necessary - */ - if (numOutputs != crtc->numOutputs) - { - RROutputPtr *newoutputs; - - if (numOutputs) - { - if (crtc->numOutputs) - newoutputs = realloc(crtc->outputs, - numOutputs * sizeof (RROutputPtr)); - else - newoutputs = malloc(numOutputs * sizeof (RROutputPtr)); - if (!newoutputs) - return FALSE; - } - else - { - free(crtc->outputs); - newoutputs = NULL; - } - crtc->outputs = newoutputs; - crtc->numOutputs = numOutputs; - } - /* - * Copy the new list of outputs into the crtc - */ - memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); - /* - * Update remaining crtc fields - */ - if (mode != crtc->mode) - { - if (crtc->mode) - RRModeDestroy (crtc->mode); - crtc->mode = mode; - if (mode != NULL) - mode->refcnt++; - RRCrtcChanged (crtc, TRUE); - } - if (x != crtc->x) - { - crtc->x = x; - RRCrtcChanged (crtc, TRUE); - } - if (y != crtc->y) - { - crtc->y = y; - RRCrtcChanged (crtc, TRUE); - } - if (rotation != crtc->rotation) - { - crtc->rotation = rotation; - RRCrtcChanged (crtc, TRUE); - } - if (!RRTransformEqual (transform, &crtc->client_current_transform)) { - RRTransformCopy (&crtc->client_current_transform, transform); - RRCrtcChanged (crtc, TRUE); - } - if (crtc->changed && mode) - { - RRTransformCompute (x, y, - mode->mode.width, mode->mode.height, - rotation, - &crtc->client_current_transform, - &crtc->transform, &crtc->f_transform, - &crtc->f_inverse); - } - return TRUE; -} - -void -RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - rrScrPriv (pScreen); - xRRCrtcChangeNotifyEvent ce; - RRModePtr mode = crtc->mode; - - ce.type = RRNotify + RREventBase; - ce.subCode = RRNotify_CrtcChange; - ce.timestamp = pScrPriv->lastSetTime.milliseconds; - ce.window = pWin->drawable.id; - ce.crtc = crtc->id; - ce.rotation = crtc->rotation; - if (mode) - { - ce.mode = mode->mode.id; - ce.x = crtc->x; - ce.y = crtc->y; - ce.width = mode->mode.width; - ce.height = mode->mode.height; - } - else - { - ce.mode = None; - ce.x = 0; - ce.y = 0; - ce.width = 0; - ce.height = 0; - } - WriteEventsToClient (client, 1, (xEvent *) &ce); -} - -static Bool -RRCrtcPendingProperties (RRCrtcPtr crtc) -{ - ScreenPtr pScreen = crtc->pScreen; - rrScrPriv(pScreen); - int o; - - for (o = 0; o < pScrPriv->numOutputs; o++) - { - RROutputPtr output = pScrPriv->outputs[o]; - if (output->crtc == crtc && output->pendingProperties) - return TRUE; - } - return FALSE; -} - -/* - * Request that the Crtc be reconfigured - */ -Bool -RRCrtcSet (RRCrtcPtr crtc, - RRModePtr mode, - int x, - int y, - Rotation rotation, - int numOutputs, - RROutputPtr *outputs) -{ - ScreenPtr pScreen = crtc->pScreen; - Bool ret = FALSE; - rrScrPriv(pScreen); - - /* See if nothing changed */ - if (crtc->mode == mode && - crtc->x == x && - crtc->y == y && - crtc->rotation == rotation && - crtc->numOutputs == numOutputs && - !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && - !RRCrtcPendingProperties (crtc) && - !RRCrtcPendingTransform (crtc)) - { - ret = TRUE; - } - else - { -#if RANDR_12_INTERFACE - if (pScrPriv->rrCrtcSet) - { - ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, - rotation, numOutputs, outputs); - } - else -#endif - { -#if RANDR_10_INTERFACE - if (pScrPriv->rrSetConfig) - { - RRScreenSize size; - RRScreenRate rate; - - if (!mode) - { - RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL); - ret = TRUE; - } - else - { - size.width = mode->mode.width; - size.height = mode->mode.height; - if (outputs[0]->mmWidth && outputs[0]->mmHeight) - { - size.mmWidth = outputs[0]->mmWidth; - size.mmHeight = outputs[0]->mmHeight; - } - else - { - size.mmWidth = pScreen->mmWidth; - size.mmHeight = pScreen->mmHeight; - } - size.nRates = 1; - rate.rate = RRVerticalRefresh (&mode->mode); - size.pRates = &rate; - ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); - /* - * Old 1.0 interface tied screen size to mode size - */ - if (ret) - { - RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs); - RRScreenSizeNotify (pScreen); - } - } - } -#endif - } - if (ret) - { - int o; - RRTellChanged (pScreen); - - for (o = 0; o < numOutputs; o++) - RRPostPendingProperties (outputs[o]); - } - } - return ret; -} - -/* - * Return crtc transform - */ -RRTransformPtr -RRCrtcGetTransform (RRCrtcPtr crtc) -{ - RRTransformPtr transform = &crtc->client_pending_transform; - - if (pixman_transform_is_identity (&transform->transform)) - return NULL; - return transform; -} - -/* - * Check whether the pending and current transforms are the same - */ -Bool -RRCrtcPendingTransform (RRCrtcPtr crtc) -{ - return memcmp (&crtc->client_current_transform.transform, - &crtc->client_pending_transform.transform, - sizeof (PictTransform)) != 0; -} - -/* - * Destroy a Crtc at shutdown - */ -void -RRCrtcDestroy (RRCrtcPtr crtc) -{ - FreeResource (crtc->id, 0); -} - -static int -RRCrtcDestroyResource (pointer value, XID pid) -{ - RRCrtcPtr crtc = (RRCrtcPtr) value; - ScreenPtr pScreen = crtc->pScreen; - - if (pScreen) - { - rrScrPriv(pScreen); - int i; - - for (i = 0; i < pScrPriv->numCrtcs; i++) - { - if (pScrPriv->crtcs[i] == crtc) - { - memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, - (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); - --pScrPriv->numCrtcs; - break; - } - } - } - free(crtc->gammaRed); - if (crtc->mode) - RRModeDestroy (crtc->mode); - free(crtc); - return 1; -} - -/* - * Request that the Crtc gamma be changed - */ - -Bool -RRCrtcGammaSet (RRCrtcPtr crtc, - CARD16 *red, - CARD16 *green, - CARD16 *blue) -{ - Bool ret = TRUE; -#if RANDR_12_INTERFACE - ScreenPtr pScreen = crtc->pScreen; -#endif - - memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); - memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); - memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); -#if RANDR_12_INTERFACE - if (pScreen) - { - rrScrPriv(pScreen); - if (pScrPriv->rrCrtcSetGamma) - ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); - } -#endif - return ret; -} - -/* - * Request current gamma back from the DDX (if possible). - * This includes gamma size. - */ -Bool -RRCrtcGammaGet(RRCrtcPtr crtc) -{ - Bool ret = TRUE; -#if RANDR_12_INTERFACE - ScreenPtr pScreen = crtc->pScreen; -#endif - -#if RANDR_12_INTERFACE - if (pScreen) - { - rrScrPriv(pScreen); - if (pScrPriv->rrCrtcGetGamma) - ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc); - } -#endif - return ret; -} - -/* - * Notify the extension that the Crtc gamma has been changed - * The driver calls this whenever it has changed the gamma values - * in the RRCrtcRec - */ - -Bool -RRCrtcGammaNotify (RRCrtcPtr crtc) -{ - return TRUE; /* not much going on here */ -} - -static void -RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, - int *width, int *height) -{ - BoxRec box; - - if (mode == NULL) { - *width = 0; - *height = 0; - return; - } - - box.x1 = 0; - box.y1 = 0; - box.x2 = mode->mode.width; - box.y2 = mode->mode.height; - - pixman_transform_bounds (transform, &box); - *width = box.x2 - box.x1; - *height = box.y2 - box.y1; -} - -/** - * Returns the width/height that the crtc scans out from the framebuffer - */ -void -RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) -{ - return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height); -} - -/* - * Set the size of the gamma table at server startup time - */ - -Bool -RRCrtcGammaSetSize (RRCrtcPtr crtc, - int size) -{ - CARD16 *gamma; - - if (size == crtc->gammaSize) - return TRUE; - if (size) - { - gamma = malloc(size * 3 * sizeof (CARD16)); - if (!gamma) - return FALSE; - } - else - gamma = NULL; - free(crtc->gammaRed); - crtc->gammaRed = gamma; - crtc->gammaGreen = gamma + size; - crtc->gammaBlue = gamma + size*2; - crtc->gammaSize = size; - return TRUE; -} - -/* - * Set the pending CRTC transformation - */ - -int -RRCrtcTransformSet (RRCrtcPtr crtc, - PictTransformPtr transform, - struct pixman_f_transform *f_transform, - struct pixman_f_transform *f_inverse, - char *filter_name, - int filter_len, - xFixed *params, - int nparams) -{ - PictFilterPtr filter = NULL; - int width = 0, height = 0; - - if (!crtc->transforms) - return BadValue; - - if (filter_len) - { - filter = PictureFindFilter (crtc->pScreen, - filter_name, - filter_len); - if (!filter) - return BadName; - if (filter->ValidateParams) - { - if (!filter->ValidateParams (crtc->pScreen, filter->id, - params, nparams, &width, &height)) - return BadMatch; - } - else { - width = filter->width; - height = filter->height; - } - } - else - { - if (nparams) - return BadMatch; - } - if (!RRTransformSetFilter (&crtc->client_pending_transform, - filter, params, nparams, width, height)) - return BadAlloc; - - crtc->client_pending_transform.transform = *transform; - crtc->client_pending_transform.f_transform = *f_transform; - crtc->client_pending_transform.f_inverse = *f_inverse; - return Success; -} - -/* - * Initialize crtc type - */ -Bool -RRCrtcInit (void) -{ - RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC"); - if (!RRCrtcType) - return FALSE; - - return TRUE; -} - -/* - * Initialize crtc type error value - */ -void -RRCrtcInitErrorValue(void) -{ - SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc); -} - -int -ProcRRGetCrtcInfo (ClientPtr client) -{ - REQUEST(xRRGetCrtcInfoReq); - xRRGetCrtcInfoReply rep; - RRCrtcPtr crtc; - CARD8 *extra; - unsigned long extraLen; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRModePtr mode; - RROutput *outputs; - RROutput *possible; - int i, j, k, n; - int width, height; - BoxRec panned_area; - - REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - mode = crtc->mode; - - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - if (pScrPriv->rrGetPanning && - pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && - (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) - { - rep.x = panned_area.x1; - rep.y = panned_area.y1; - rep.width = panned_area.x2 - panned_area.x1; - rep.height = panned_area.y2 - panned_area.y1; - } - else - { - RRCrtcGetScanoutSize (crtc, &width, &height); - rep.x = crtc->x; - rep.y = crtc->y; - rep.width = width; - rep.height = height; - } - rep.mode = mode ? mode->mode.id : 0; - rep.rotation = crtc->rotation; - rep.rotations = crtc->rotations; - rep.nOutput = crtc->numOutputs; - k = 0; - for (i = 0; i < pScrPriv->numOutputs; i++) - for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) - if (pScrPriv->outputs[i]->crtcs[j] == crtc) - k++; - rep.nPossibleOutput = k; - - rep.length = rep.nOutput + rep.nPossibleOutput; - - extraLen = rep.length << 2; - if (extraLen) - { - extra = malloc(extraLen); - if (!extra) - return BadAlloc; - } - else - extra = NULL; - - outputs = (RROutput *) extra; - possible = (RROutput *) (outputs + rep.nOutput); - - for (i = 0; i < crtc->numOutputs; i++) - { - outputs[i] = crtc->outputs[i]->id; - if (client->swapped) - swapl (&outputs[i], n); - } - k = 0; - for (i = 0; i < pScrPriv->numOutputs; i++) - for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) - if (pScrPriv->outputs[i]->crtcs[j] == crtc) - { - possible[k] = pScrPriv->outputs[i]->id; - if (client->swapped) - swapl (&possible[k], n); - k++; - } - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.timestamp, n); - swaps(&rep.x, n); - swaps(&rep.y, n); - swaps(&rep.width, n); - swaps(&rep.height, n); - swapl(&rep.mode, n); - swaps(&rep.rotation, n); - swaps(&rep.rotations, n); - swaps(&rep.nOutput, n); - swaps(&rep.nPossibleOutput, n); - } - WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); - if (extraLen) - { - WriteToClient (client, extraLen, (char *) extra); - free(extra); - } - - return Success; -} - -int -ProcRRSetCrtcConfig (ClientPtr client) -{ - REQUEST(xRRSetCrtcConfigReq); - xRRSetCrtcConfigReply rep; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - RRCrtcPtr crtc; - RRModePtr mode; - int numOutputs; - RROutputPtr *outputs = NULL; - RROutput *outputIds; - TimeStamp configTime; - TimeStamp time; - Rotation rotation; - int rc, i, j; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); - numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq))); - - VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); - - if (stuff->mode == None) - { - mode = NULL; - if (numOutputs > 0) - return BadMatch; - } - else - { - VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); - if (numOutputs == 0) - return BadMatch; - } - if (numOutputs) - { - outputs = malloc(numOutputs * sizeof (RROutputPtr)); - if (!outputs) - return BadAlloc; - } - else - outputs = NULL; - - outputIds = (RROutput *) (stuff + 1); - for (i = 0; i < numOutputs; i++) - { - rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i], - RROutputType, client, DixSetAttrAccess); - if (rc != Success) - { - free(outputs); - return rc; - } - /* validate crtc for this output */ - for (j = 0; j < outputs[i]->numCrtcs; j++) - if (outputs[i]->crtcs[j] == crtc) - break; - if (j == outputs[i]->numCrtcs) - { - free(outputs); - return BadMatch; - } - /* validate mode for this output */ - for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) - { - RRModePtr m = (j < outputs[i]->numModes ? - outputs[i]->modes[j] : - outputs[i]->userModes[j - outputs[i]->numModes]); - if (m == mode) - break; - } - if (j == outputs[i]->numModes + outputs[i]->numUserModes) - { - free(outputs); - return BadMatch; - } - } - /* validate clones */ - for (i = 0; i < numOutputs; i++) - { - for (j = 0; j < numOutputs; j++) - { - int k; - if (i == j) - continue; - for (k = 0; k < outputs[i]->numClones; k++) - { - if (outputs[i]->clones[k] == outputs[j]) - break; - } - if (k == outputs[i]->numClones) - { - free(outputs); - return BadMatch; - } - } - } - - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - time = ClientTimeToServerTime(stuff->timestamp); - configTime = ClientTimeToServerTime(stuff->configTimestamp); - - if (!pScrPriv) - { - time = currentTime; - rep.status = RRSetConfigFailed; - goto sendReply; - } - - /* - * Validate requested rotation - */ - rotation = (Rotation) stuff->rotation; - - /* test the rotation bits only! */ - switch (rotation & 0xf) { - case RR_Rotate_0: - case RR_Rotate_90: - case RR_Rotate_180: - case RR_Rotate_270: - break; - default: - /* - * Invalid rotation - */ - client->errorValue = stuff->rotation; - free(outputs); - return BadValue; - } - - if (mode) - { - if ((~crtc->rotations) & rotation) - { - /* - * requested rotation or reflection not supported by screen - */ - client->errorValue = stuff->rotation; - free(outputs); - return BadMatch; - } - -#ifdef RANDR_12_INTERFACE - /* - * Check screen size bounds if the DDX provides a 1.2 interface - * for setting screen size. Else, assume the CrtcSet sets - * the size along with the mode. If the driver supports transforms, - * then it must allow crtcs to display a subset of the screen, so - * only do this check for drivers without transform support. - */ - if (pScrPriv->rrScreenSetSize && !crtc->transforms) - { - int source_width; - int source_height; - PictTransform transform; - struct pixman_f_transform f_transform, f_inverse; - - RRTransformCompute (stuff->x, stuff->y, - mode->mode.width, mode->mode.height, - rotation, - &crtc->client_pending_transform, - &transform, &f_transform, &f_inverse); - - RRModeGetScanoutSize (mode, &transform, &source_width, &source_height); - if (stuff->x + source_width > pScreen->width) - { - client->errorValue = stuff->x; - free(outputs); - return BadValue; - } - - if (stuff->y + source_height > pScreen->height) - { - client->errorValue = stuff->y; - free(outputs); - return BadValue; - } - } -#endif - } - - if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, - rotation, numOutputs, outputs)) - { - rep.status = RRSetConfigFailed; - goto sendReply; - } - rep.status = RRSetConfigSuccess; - pScrPriv->lastSetTime = time; - -sendReply: - free(outputs); - - rep.type = X_Reply; - /* rep.status has already been filled in */ - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; - - if (client->swapped) - { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.newTimestamp, n); - } - WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); - - return Success; -} - -int -ProcRRGetPanning (ClientPtr client) -{ - REQUEST(xRRGetPanningReq); - xRRGetPanningReply rep; - RRCrtcPtr crtc; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - BoxRec total; - BoxRec tracking; - INT16 border[4]; - int n; - - REQUEST_SIZE_MATCH(xRRGetPanningReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - if (!pScrPriv) - return RRErrorBase + BadRRCrtc; - - memset(&rep, 0, sizeof(rep)); - rep.type = X_Reply; - rep.status = RRSetConfigSuccess; - rep.sequenceNumber = client->sequence; - rep.length = 1; - rep.timestamp = pScrPriv->lastSetTime.milliseconds; - - if (pScrPriv->rrGetPanning && - pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) { - rep.left = total.x1; - rep.top = total.y1; - rep.width = total.x2 - total.x1; - rep.height = total.y2 - total.y1; - rep.track_left = tracking.x1; - rep.track_top = tracking.y1; - rep.track_width = tracking.x2 - tracking.x1; - rep.track_height = tracking.y2 - tracking.y1; - rep.border_left = border[0]; - rep.border_top = border[1]; - rep.border_right = border[2]; - rep.border_bottom = border[3]; - } - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.timestamp, n); - swaps(&rep.left, n); - swaps(&rep.top, n); - swaps(&rep.width, n); - swaps(&rep.height, n); - swaps(&rep.track_left, n); - swaps(&rep.track_top, n); - swaps(&rep.track_width, n); - swaps(&rep.track_height, n); - swaps(&rep.border_left, n); - swaps(&rep.border_top, n); - swaps(&rep.border_right, n); - swaps(&rep.border_bottom, n); - } - WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep); - return Success; -} - -int -ProcRRSetPanning (ClientPtr client) -{ - REQUEST(xRRSetPanningReq); - xRRSetPanningReply rep; - RRCrtcPtr crtc; - ScreenPtr pScreen; - rrScrPrivPtr pScrPriv; - TimeStamp time; - BoxRec total; - BoxRec tracking; - INT16 border[4]; - int n; - - REQUEST_SIZE_MATCH(xRRSetPanningReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* All crtcs must be associated with screens before client - * requests are processed - */ - pScreen = crtc->pScreen; - pScrPriv = rrGetScrPriv(pScreen); - - if (!pScrPriv) { - time = currentTime; - rep.status = RRSetConfigFailed; - goto sendReply; - } - - time = ClientTimeToServerTime(stuff->timestamp); - - if (!pScrPriv->rrGetPanning) - return RRErrorBase + BadRRCrtc; - - total.x1 = stuff->left; - total.y1 = stuff->top; - total.x2 = total.x1 + stuff->width; - total.y2 = total.y1 + stuff->height; - tracking.x1 = stuff->track_left; - tracking.y1 = stuff->track_top; - tracking.x2 = tracking.x1 + stuff->track_width; - tracking.y2 = tracking.y1 + stuff->track_height; - border[0] = stuff->border_left; - border[1] = stuff->border_top; - border[2] = stuff->border_right; - border[3] = stuff->border_bottom; - - if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border)) - return BadMatch; - - pScrPriv->lastSetTime = time; - - rep.status = RRSetConfigSuccess; - -sendReply: - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.newTimestamp, n); - } - WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep); - return Success; -} - -int -ProcRRGetCrtcGammaSize (ClientPtr client) -{ - REQUEST(xRRGetCrtcGammaSizeReq); - xRRGetCrtcGammaSizeReply reply; - RRCrtcPtr crtc; - int n; - - REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* Gamma retrieval failed, any better error? */ - if (!RRCrtcGammaGet(crtc)) - return RRErrorBase + BadRRCrtc; - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = 0; - reply.size = crtc->gammaSize; - if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - swaps (&reply.size, n); - } - WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); - return Success; -} - -int -ProcRRGetCrtcGamma (ClientPtr client) -{ - REQUEST(xRRGetCrtcGammaReq); - xRRGetCrtcGammaReply reply; - RRCrtcPtr crtc; - int n; - unsigned long len; - char *extra = NULL; - - REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - /* Gamma retrieval failed, any better error? */ - if (!RRCrtcGammaGet(crtc)) - return RRErrorBase + BadRRCrtc; - - len = crtc->gammaSize * 3 * 2; - - if (crtc->gammaSize) { - extra = malloc(len); - if (!extra) - return BadAlloc; - } - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = bytes_to_int32(len); - reply.size = crtc->gammaSize; - if (client->swapped) { - swaps (&reply.sequenceNumber, n); - swapl (&reply.length, n); - swaps (&reply.size, n); - } - WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); - if (crtc->gammaSize) - { - memcpy(extra, crtc->gammaRed, len); - client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; - WriteSwappedDataToClient (client, len, extra); - free(extra); - } - return Success; -} - -int -ProcRRSetCrtcGamma (ClientPtr client) -{ - REQUEST(xRRSetCrtcGammaReq); - RRCrtcPtr crtc; - unsigned long len; - CARD16 *red, *green, *blue; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq)); - if (len < (stuff->size * 3 + 1) >> 1) - return BadLength; - - if (stuff->size != crtc->gammaSize) - return BadMatch; - - red = (CARD16 *) (stuff + 1); - green = red + crtc->gammaSize; - blue = green + crtc->gammaSize; - - RRCrtcGammaSet (crtc, red, green, blue); - - return Success; -} - -/* Version 1.3 additions */ - -int -ProcRRSetCrtcTransform (ClientPtr client) -{ - REQUEST(xRRSetCrtcTransformReq); - RRCrtcPtr crtc; - PictTransform transform; - struct pixman_f_transform f_transform, f_inverse; - char *filter; - int nbytes; - xFixed *params; - int nparams; - - REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - PictTransform_from_xRenderTransform (&transform, &stuff->transform); - pixman_f_transform_from_pixman_transform (&f_transform, &transform); - if (!pixman_f_transform_invert (&f_inverse, &f_transform)) - return BadMatch; - - filter = (char *) (stuff + 1); - nbytes = stuff->nbytesFilter; - params = (xFixed *) (filter + pad_to_int32(nbytes)); - nparams = ((xFixed *) stuff + client->req_len) - params; - if (nparams < 0) - return BadLength; - - return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse, - filter, nbytes, params, nparams); -} - - -#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) - -static int -transform_filter_length (RRTransformPtr transform) -{ - int nbytes, nparams; - - if (transform->filter == NULL) - return 0; - nbytes = strlen (transform->filter->name); - nparams = transform->nparams; - return pad_to_int32(nbytes) + (nparams * sizeof (xFixed)); -} - -static int -transform_filter_encode (ClientPtr client, char *output, - CARD16 *nbytesFilter, - CARD16 *nparamsFilter, - RRTransformPtr transform) -{ - int nbytes, nparams; - int n; - - if (transform->filter == NULL) { - *nbytesFilter = 0; - *nparamsFilter = 0; - return 0; - } - nbytes = strlen (transform->filter->name); - nparams = transform->nparams; - *nbytesFilter = nbytes; - *nparamsFilter = nparams; - memcpy (output, transform->filter->name, nbytes); - while ((nbytes & 3) != 0) - output[nbytes++] = 0; - memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed)); - if (client->swapped) { - swaps (nbytesFilter, n); - swaps (nparamsFilter, n); - SwapLongs ((CARD32 *) (output + nbytes), nparams); - } - nbytes += nparams * sizeof (xFixed); - return nbytes; -} - -static void -transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict) -{ - xRenderTransform_from_PictTransform (wire, pict); - if (client->swapped) - SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform))); -} - -int -ProcRRGetCrtcTransform (ClientPtr client) -{ - REQUEST(xRRGetCrtcTransformReq); - xRRGetCrtcTransformReply *reply; - RRCrtcPtr crtc; - int n, nextra; - RRTransformPtr current, pending; - char *extra; - - REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq); - VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); - - pending = &crtc->client_pending_transform; - current = &crtc->client_current_transform; - - nextra = (transform_filter_length (pending) + - transform_filter_length (current)); - - reply = malloc(sizeof (xRRGetCrtcTransformReply) + nextra); - if (!reply) - return BadAlloc; - - extra = (char *) (reply + 1); - reply->type = X_Reply; - reply->sequenceNumber = client->sequence; - reply->length = bytes_to_int32(CrtcTransformExtra + nextra); - - reply->hasTransforms = crtc->transforms; - - transform_encode (client, &reply->pendingTransform, &pending->transform); - extra += transform_filter_encode (client, extra, - &reply->pendingNbytesFilter, - &reply->pendingNparamsFilter, - pending); - - transform_encode (client, &reply->currentTransform, ¤t->transform); - extra += transform_filter_encode (client, extra, - &reply->currentNbytesFilter, - &reply->currentNparamsFilter, - current); - - if (client->swapped) { - swaps (&reply->sequenceNumber, n); - swapl (&reply->length, n); - } - WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply); - free(reply); - return Success; -} +/* + * Copyright © 2006 Keith Packard + * Copyright 2010 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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. + */ + +#include "randrstr.h" +#include "swaprep.h" +#include "mipointer.h" + +RESTYPE RRCrtcType; + +/* + * Notify the CRTC of some change + */ +void +RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) +{ + ScreenPtr pScreen = crtc->pScreen; + + crtc->changed = TRUE; + if (pScreen) + { + rrScrPriv(pScreen); + + pScrPriv->changed = TRUE; + /* + * Send ConfigureNotify on any layout change + */ + if (layoutChanged) + pScrPriv->layoutChanged = TRUE; + } +} + +/* + * Create a CRTC + */ +RRCrtcPtr +RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) +{ + RRCrtcPtr crtc; + RRCrtcPtr *crtcs; + rrScrPrivPtr pScrPriv; + + if (!RRInit()) + return NULL; + + pScrPriv = rrGetScrPriv(pScreen); + + /* make space for the crtc pointer */ + if (pScrPriv->numCrtcs) + crtcs = realloc(pScrPriv->crtcs, + (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr)); + else + crtcs = malloc(sizeof (RRCrtcPtr)); + if (!crtcs) + return FALSE; + pScrPriv->crtcs = crtcs; + + crtc = calloc(1, sizeof (RRCrtcRec)); + if (!crtc) + return NULL; + crtc->id = FakeClientID (0); + crtc->pScreen = pScreen; + crtc->mode = NULL; + crtc->x = 0; + crtc->y = 0; + crtc->rotation = RR_Rotate_0; + crtc->rotations = RR_Rotate_0; + crtc->outputs = NULL; + crtc->numOutputs = 0; + crtc->gammaSize = 0; + crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL; + crtc->changed = FALSE; + crtc->devPrivate = devPrivate; + RRTransformInit (&crtc->client_pending_transform); + RRTransformInit (&crtc->client_current_transform); + pixman_transform_init_identity (&crtc->transform); + pixman_f_transform_init_identity (&crtc->f_transform); + pixman_f_transform_init_identity (&crtc->f_inverse); + + if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) + return NULL; + + /* attach the screen and crtc together */ + crtc->pScreen = pScreen; + pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; + + return crtc; +} + +/* + * Set the allowed rotations on a CRTC + */ +void +RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations) +{ + crtc->rotations = rotations; +} + +/* + * Set whether transforms are allowed on a CRTC + */ +void +RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms) +{ + crtc->transforms = transforms; +} + +/* + * Notify the extension that the Crtc has been reconfigured, + * the driver calls this whenever it has updated the mode + */ +Bool +RRCrtcNotify (RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + RRTransformPtr transform, + int numOutputs, + RROutputPtr *outputs) +{ + int i, j; + + /* + * Check to see if any of the new outputs were + * not in the old list and mark them as changed + */ + for (i = 0; i < numOutputs; i++) + { + for (j = 0; j < crtc->numOutputs; j++) + if (outputs[i] == crtc->outputs[j]) + break; + if (j == crtc->numOutputs) + { + outputs[i]->crtc = crtc; + RROutputChanged (outputs[i], FALSE); + RRCrtcChanged (crtc, FALSE); + } + } + /* + * Check to see if any of the old outputs are + * not in the new list and mark them as changed + */ + for (j = 0; j < crtc->numOutputs; j++) + { + for (i = 0; i < numOutputs; i++) + if (outputs[i] == crtc->outputs[j]) + break; + if (i == numOutputs) + { + if (crtc->outputs[j]->crtc == crtc) + crtc->outputs[j]->crtc = NULL; + RROutputChanged (crtc->outputs[j], FALSE); + RRCrtcChanged (crtc, FALSE); + } + } + /* + * Reallocate the crtc output array if necessary + */ + if (numOutputs != crtc->numOutputs) + { + RROutputPtr *newoutputs; + + if (numOutputs) + { + if (crtc->numOutputs) + newoutputs = realloc(crtc->outputs, + numOutputs * sizeof (RROutputPtr)); + else + newoutputs = malloc(numOutputs * sizeof (RROutputPtr)); + if (!newoutputs) + return FALSE; + } + else + { + free(crtc->outputs); + newoutputs = NULL; + } + crtc->outputs = newoutputs; + crtc->numOutputs = numOutputs; + } + /* + * Copy the new list of outputs into the crtc + */ + memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)); + /* + * Update remaining crtc fields + */ + if (mode != crtc->mode) + { + if (crtc->mode) + RRModeDestroy (crtc->mode); + crtc->mode = mode; + if (mode != NULL) + mode->refcnt++; + RRCrtcChanged (crtc, TRUE); + } + if (x != crtc->x) + { + crtc->x = x; + RRCrtcChanged (crtc, TRUE); + } + if (y != crtc->y) + { + crtc->y = y; + RRCrtcChanged (crtc, TRUE); + } + if (rotation != crtc->rotation) + { + crtc->rotation = rotation; + RRCrtcChanged (crtc, TRUE); + } + if (!RRTransformEqual (transform, &crtc->client_current_transform)) { + RRTransformCopy (&crtc->client_current_transform, transform); + RRCrtcChanged (crtc, TRUE); + } + if (crtc->changed && mode) + { + RRTransformCompute (x, y, + mode->mode.width, mode->mode.height, + rotation, + &crtc->client_current_transform, + &crtc->transform, &crtc->f_transform, + &crtc->f_inverse); + } + return TRUE; +} + +void +RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + rrScrPriv (pScreen); + xRRCrtcChangeNotifyEvent ce; + RRModePtr mode = crtc->mode; + + ce.type = RRNotify + RREventBase; + ce.subCode = RRNotify_CrtcChange; + ce.timestamp = pScrPriv->lastSetTime.milliseconds; + ce.window = pWin->drawable.id; + ce.crtc = crtc->id; + ce.rotation = crtc->rotation; + if (mode) + { + ce.mode = mode->mode.id; + ce.x = crtc->x; + ce.y = crtc->y; + ce.width = mode->mode.width; + ce.height = mode->mode.height; + } + else + { + ce.mode = None; + ce.x = 0; + ce.y = 0; + ce.width = 0; + ce.height = 0; + } + WriteEventsToClient (client, 1, (xEvent *) &ce); +} + +static Bool +RRCrtcPendingProperties (RRCrtcPtr crtc) +{ + ScreenPtr pScreen = crtc->pScreen; + rrScrPriv(pScreen); + int o; + + for (o = 0; o < pScrPriv->numOutputs; o++) + { + RROutputPtr output = pScrPriv->outputs[o]; + if (output->crtc == crtc && output->pendingProperties) + return TRUE; + } + return FALSE; +} + +static void +crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom) +{ + *left = crtc->x; + *top = crtc->y; + + switch (crtc->rotation) { + case RR_Rotate_0: + case RR_Rotate_180: + default: + *right = crtc->x + crtc->mode->mode.width; + *bottom = crtc->y + crtc->mode->mode.height; + return; + case RR_Rotate_90: + case RR_Rotate_270: + *right = crtc->x + crtc->mode->mode.height; + *bottom = crtc->y + crtc->mode->mode.width; + return; + } +} + +/* overlapping counts as adjacent */ +static Bool +crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b) +{ + /* left, right, top, bottom... */ + int al, ar, at, ab; + int bl, br, bt, bb; + int cl, cr, ct, cb; /* the overlap, if any */ + + crtc_bounds(a, &al, &ar, &at, &ab); + crtc_bounds(b, &bl, &br, &bt, &bb); + + cl = max(al, bl); + cr = min(ar, br); + ct = max(at, bt); + cb = min(ab, bb); + + return (cl <= cr) && (ct <= cb); +} + +/* Depth-first search and mark all CRTCs reachable from cur */ +static void +mark_crtcs (rrScrPrivPtr pScrPriv, int *reachable, int cur) +{ + int i; + reachable[cur] = TRUE; + for (i = 0; i < pScrPriv->numCrtcs; ++i) { + if (reachable[i] || !pScrPriv->crtcs[i]->mode) + continue; + if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i])) + mark_crtcs(pScrPriv, reachable, i); + } +} + +static void +RRComputeContiguity (ScreenPtr pScreen) +{ + rrScrPriv(pScreen); + Bool discontiguous = TRUE; + int i, n = pScrPriv->numCrtcs; + + int *reachable = calloc(n, sizeof(int)); + if (!reachable) + goto out; + + /* Find first enabled CRTC and start search for reachable CRTCs from it */ + for (i = 0; i < n; ++i) { + if (pScrPriv->crtcs[i]->mode) { + mark_crtcs(pScrPriv, reachable, i); + break; + } + } + + /* Check that all enabled CRTCs were marked as reachable */ + for (i = 0; i < n; ++i) + if (pScrPriv->crtcs[i]->mode && !reachable[i]) + goto out; + + discontiguous = FALSE; + +out: + free(reachable); + pScrPriv->discontiguous = discontiguous; +} + +/* + * Request that the Crtc be reconfigured + */ +Bool +RRCrtcSet (RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int numOutputs, + RROutputPtr *outputs) +{ + ScreenPtr pScreen = crtc->pScreen; + Bool ret = FALSE; + Bool recompute = TRUE; + rrScrPriv(pScreen); + + /* See if nothing changed */ + if (crtc->mode == mode && + crtc->x == x && + crtc->y == y && + crtc->rotation == rotation && + crtc->numOutputs == numOutputs && + !memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) && + !RRCrtcPendingProperties (crtc) && + !RRCrtcPendingTransform (crtc)) + { + recompute = FALSE; + ret = TRUE; + } + else + { +#if RANDR_12_INTERFACE + if (pScrPriv->rrCrtcSet) + { + ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, + rotation, numOutputs, outputs); + } + else +#endif + { +#if RANDR_10_INTERFACE + if (pScrPriv->rrSetConfig) + { + RRScreenSize size; + RRScreenRate rate; + + if (!mode) + { + RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL); + ret = TRUE; + } + else + { + size.width = mode->mode.width; + size.height = mode->mode.height; + if (outputs[0]->mmWidth && outputs[0]->mmHeight) + { + size.mmWidth = outputs[0]->mmWidth; + size.mmHeight = outputs[0]->mmHeight; + } + else + { + size.mmWidth = pScreen->mmWidth; + size.mmHeight = pScreen->mmHeight; + } + size.nRates = 1; + rate.rate = RRVerticalRefresh (&mode->mode); + size.pRates = &rate; + ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size); + /* + * Old 1.0 interface tied screen size to mode size + */ + if (ret) + { + RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs); + RRScreenSizeNotify (pScreen); + } + } + } +#endif + } + if (ret) + { + int o; + RRTellChanged (pScreen); + + for (o = 0; o < numOutputs; o++) + RRPostPendingProperties (outputs[o]); + } + } + + if (recompute) + RRComputeContiguity(pScreen); + + return ret; +} + +/* + * Return crtc transform + */ +RRTransformPtr +RRCrtcGetTransform (RRCrtcPtr crtc) +{ + RRTransformPtr transform = &crtc->client_pending_transform; + + if (pixman_transform_is_identity (&transform->transform)) + return NULL; + return transform; +} + +/* + * Check whether the pending and current transforms are the same + */ +Bool +RRCrtcPendingTransform (RRCrtcPtr crtc) +{ + return memcmp (&crtc->client_current_transform.transform, + &crtc->client_pending_transform.transform, + sizeof (PictTransform)) != 0; +} + +/* + * Destroy a Crtc at shutdown + */ +void +RRCrtcDestroy (RRCrtcPtr crtc) +{ + FreeResource (crtc->id, 0); +} + +static int +RRCrtcDestroyResource (pointer value, XID pid) +{ + RRCrtcPtr crtc = (RRCrtcPtr) value; + ScreenPtr pScreen = crtc->pScreen; + + if (pScreen) + { + rrScrPriv(pScreen); + int i; + + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + if (pScrPriv->crtcs[i] == crtc) + { + memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, + (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr)); + --pScrPriv->numCrtcs; + break; + } + } + } + free(crtc->gammaRed); + if (crtc->mode) + RRModeDestroy (crtc->mode); + free(crtc); + return 1; +} + +/* + * Request that the Crtc gamma be changed + */ + +Bool +RRCrtcGammaSet (RRCrtcPtr crtc, + CARD16 *red, + CARD16 *green, + CARD16 *blue) +{ + Bool ret = TRUE; +#if RANDR_12_INTERFACE + ScreenPtr pScreen = crtc->pScreen; +#endif + + memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); + memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); + memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); +#if RANDR_12_INTERFACE + if (pScreen) + { + rrScrPriv(pScreen); + if (pScrPriv->rrCrtcSetGamma) + ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); + } +#endif + return ret; +} + +/* + * Request current gamma back from the DDX (if possible). + * This includes gamma size. + */ +Bool +RRCrtcGammaGet(RRCrtcPtr crtc) +{ + Bool ret = TRUE; +#if RANDR_12_INTERFACE + ScreenPtr pScreen = crtc->pScreen; +#endif + +#if RANDR_12_INTERFACE + if (pScreen) + { + rrScrPriv(pScreen); + if (pScrPriv->rrCrtcGetGamma) + ret = (*pScrPriv->rrCrtcGetGamma) (pScreen, crtc); + } +#endif + return ret; +} + +/* + * Notify the extension that the Crtc gamma has been changed + * The driver calls this whenever it has changed the gamma values + * in the RRCrtcRec + */ + +Bool +RRCrtcGammaNotify (RRCrtcPtr crtc) +{ + return TRUE; /* not much going on here */ +} + +static void +RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, + int *width, int *height) +{ + BoxRec box; + + if (mode == NULL) { + *width = 0; + *height = 0; + return; + } + + box.x1 = 0; + box.y1 = 0; + box.x2 = mode->mode.width; + box.y2 = mode->mode.height; + + pixman_transform_bounds (transform, &box); + *width = box.x2 - box.x1; + *height = box.y2 - box.y1; +} + +/** + * Returns the width/height that the crtc scans out from the framebuffer + */ +void +RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) +{ + return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height); +} + +/* + * Set the size of the gamma table at server startup time + */ + +Bool +RRCrtcGammaSetSize (RRCrtcPtr crtc, + int size) +{ + CARD16 *gamma; + + if (size == crtc->gammaSize) + return TRUE; + if (size) + { + gamma = malloc(size * 3 * sizeof (CARD16)); + if (!gamma) + return FALSE; + } + else + gamma = NULL; + free(crtc->gammaRed); + crtc->gammaRed = gamma; + crtc->gammaGreen = gamma + size; + crtc->gammaBlue = gamma + size*2; + crtc->gammaSize = size; + return TRUE; +} + +/* + * Set the pending CRTC transformation + */ + +int +RRCrtcTransformSet (RRCrtcPtr crtc, + PictTransformPtr transform, + struct pixman_f_transform *f_transform, + struct pixman_f_transform *f_inverse, + char *filter_name, + int filter_len, + xFixed *params, + int nparams) +{ + PictFilterPtr filter = NULL; + int width = 0, height = 0; + + if (!crtc->transforms) + return BadValue; + + if (filter_len) + { + filter = PictureFindFilter (crtc->pScreen, + filter_name, + filter_len); + if (!filter) + return BadName; + if (filter->ValidateParams) + { + if (!filter->ValidateParams (crtc->pScreen, filter->id, + params, nparams, &width, &height)) + return BadMatch; + } + else { + width = filter->width; + height = filter->height; + } + } + else + { + if (nparams) + return BadMatch; + } + if (!RRTransformSetFilter (&crtc->client_pending_transform, + filter, params, nparams, width, height)) + return BadAlloc; + + crtc->client_pending_transform.transform = *transform; + crtc->client_pending_transform.f_transform = *f_transform; + crtc->client_pending_transform.f_inverse = *f_inverse; + return Success; +} + +/* + * Initialize crtc type + */ +Bool +RRCrtcInit (void) +{ + RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC"); + if (!RRCrtcType) + return FALSE; + + return TRUE; +} + +/* + * Initialize crtc type error value + */ +void +RRCrtcInitErrorValue(void) +{ + SetResourceTypeErrorValue(RRCrtcType, RRErrorBase + BadRRCrtc); +} + +int +ProcRRGetCrtcInfo (ClientPtr client) +{ + REQUEST(xRRGetCrtcInfoReq); + xRRGetCrtcInfoReply rep; + RRCrtcPtr crtc; + CARD8 *extra; + unsigned long extraLen; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + RRModePtr mode; + RROutput *outputs; + RROutput *possible; + int i, j, k, n; + int width, height; + BoxRec panned_area; + + REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* All crtcs must be associated with screens before client + * requests are processed + */ + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + mode = crtc->mode; + + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + if (pScrPriv->rrGetPanning && + pScrPriv->rrGetPanning (pScreen, crtc, &panned_area, NULL, NULL) && + (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) + { + rep.x = panned_area.x1; + rep.y = panned_area.y1; + rep.width = panned_area.x2 - panned_area.x1; + rep.height = panned_area.y2 - panned_area.y1; + } + else + { + RRCrtcGetScanoutSize (crtc, &width, &height); + rep.x = crtc->x; + rep.y = crtc->y; + rep.width = width; + rep.height = height; + } + rep.mode = mode ? mode->mode.id : 0; + rep.rotation = crtc->rotation; + rep.rotations = crtc->rotations; + rep.nOutput = crtc->numOutputs; + k = 0; + for (i = 0; i < pScrPriv->numOutputs; i++) + for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) + if (pScrPriv->outputs[i]->crtcs[j] == crtc) + k++; + rep.nPossibleOutput = k; + + rep.length = rep.nOutput + rep.nPossibleOutput; + + extraLen = rep.length << 2; + if (extraLen) + { + extra = malloc(extraLen); + if (!extra) + return BadAlloc; + } + else + extra = NULL; + + outputs = (RROutput *) extra; + possible = (RROutput *) (outputs + rep.nOutput); + + for (i = 0; i < crtc->numOutputs; i++) + { + outputs[i] = crtc->outputs[i]->id; + if (client->swapped) + swapl (&outputs[i], n); + } + k = 0; + for (i = 0; i < pScrPriv->numOutputs; i++) + for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++) + if (pScrPriv->outputs[i]->crtcs[j] == crtc) + { + possible[k] = pScrPriv->outputs[i]->id; + if (client->swapped) + swapl (&possible[k], n); + k++; + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.timestamp, n); + swaps(&rep.x, n); + swaps(&rep.y, n); + swaps(&rep.width, n); + swaps(&rep.height, n); + swapl(&rep.mode, n); + swaps(&rep.rotation, n); + swaps(&rep.rotations, n); + swaps(&rep.nOutput, n); + swaps(&rep.nPossibleOutput, n); + } + WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep); + if (extraLen) + { + WriteToClient (client, extraLen, (char *) extra); + free(extra); + } + + return Success; +} + +int +ProcRRSetCrtcConfig (ClientPtr client) +{ + REQUEST(xRRSetCrtcConfigReq); + xRRSetCrtcConfigReply rep; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + RRCrtcPtr crtc; + RRModePtr mode; + int numOutputs; + RROutputPtr *outputs = NULL; + RROutput *outputIds; + TimeStamp configTime; + TimeStamp time; + Rotation rotation; + int rc, i, j; + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq); + numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq))); + + VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); + + if (stuff->mode == None) + { + mode = NULL; + if (numOutputs > 0) + return BadMatch; + } + else + { + VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess); + if (numOutputs == 0) + return BadMatch; + } + if (numOutputs) + { + outputs = malloc(numOutputs * sizeof (RROutputPtr)); + if (!outputs) + return BadAlloc; + } + else + outputs = NULL; + + outputIds = (RROutput *) (stuff + 1); + for (i = 0; i < numOutputs; i++) + { + rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i], + RROutputType, client, DixSetAttrAccess); + if (rc != Success) + { + free(outputs); + return rc; + } + /* validate crtc for this output */ + for (j = 0; j < outputs[i]->numCrtcs; j++) + if (outputs[i]->crtcs[j] == crtc) + break; + if (j == outputs[i]->numCrtcs) + { + free(outputs); + return BadMatch; + } + /* validate mode for this output */ + for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++) + { + RRModePtr m = (j < outputs[i]->numModes ? + outputs[i]->modes[j] : + outputs[i]->userModes[j - outputs[i]->numModes]); + if (m == mode) + break; + } + if (j == outputs[i]->numModes + outputs[i]->numUserModes) + { + free(outputs); + return BadMatch; + } + } + /* validate clones */ + for (i = 0; i < numOutputs; i++) + { + for (j = 0; j < numOutputs; j++) + { + int k; + if (i == j) + continue; + for (k = 0; k < outputs[i]->numClones; k++) + { + if (outputs[i]->clones[k] == outputs[j]) + break; + } + if (k == outputs[i]->numClones) + { + free(outputs); + return BadMatch; + } + } + } + + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + time = ClientTimeToServerTime(stuff->timestamp); + configTime = ClientTimeToServerTime(stuff->configTimestamp); + + if (!pScrPriv) + { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + + /* + * Validate requested rotation + */ + rotation = (Rotation) stuff->rotation; + + /* test the rotation bits only! */ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_90: + case RR_Rotate_180: + case RR_Rotate_270: + break; + default: + /* + * Invalid rotation + */ + client->errorValue = stuff->rotation; + free(outputs); + return BadValue; + } + + if (mode) + { + if ((~crtc->rotations) & rotation) + { + /* + * requested rotation or reflection not supported by screen + */ + client->errorValue = stuff->rotation; + free(outputs); + return BadMatch; + } + +#ifdef RANDR_12_INTERFACE + /* + * Check screen size bounds if the DDX provides a 1.2 interface + * for setting screen size. Else, assume the CrtcSet sets + * the size along with the mode. If the driver supports transforms, + * then it must allow crtcs to display a subset of the screen, so + * only do this check for drivers without transform support. + */ + if (pScrPriv->rrScreenSetSize && !crtc->transforms) + { + int source_width; + int source_height; + PictTransform transform; + struct pixman_f_transform f_transform, f_inverse; + + RRTransformCompute (stuff->x, stuff->y, + mode->mode.width, mode->mode.height, + rotation, + &crtc->client_pending_transform, + &transform, &f_transform, &f_inverse); + + RRModeGetScanoutSize (mode, &transform, &source_width, &source_height); + if (stuff->x + source_width > pScreen->width) + { + client->errorValue = stuff->x; + free(outputs); + return BadValue; + } + + if (stuff->y + source_height > pScreen->height) + { + client->errorValue = stuff->y; + free(outputs); + return BadValue; + } + } +#endif + } + + if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y, + rotation, numOutputs, outputs)) + { + rep.status = RRSetConfigFailed; + goto sendReply; + } + rep.status = RRSetConfigSuccess; + pScrPriv->lastSetTime = time; + +sendReply: + free(outputs); + + rep.type = X_Reply; + /* rep.status has already been filled in */ + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + + if (client->swapped) + { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.newTimestamp, n); + } + WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep); + + return Success; +} + +int +ProcRRGetPanning (ClientPtr client) +{ + REQUEST(xRRGetPanningReq); + xRRGetPanningReply rep; + RRCrtcPtr crtc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + BoxRec total; + BoxRec tracking; + INT16 border[4]; + int n; + + REQUEST_SIZE_MATCH(xRRGetPanningReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* All crtcs must be associated with screens before client + * requests are processed + */ + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + if (!pScrPriv) + return RRErrorBase + BadRRCrtc; + + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.status = RRSetConfigSuccess; + rep.sequenceNumber = client->sequence; + rep.length = 1; + rep.timestamp = pScrPriv->lastSetTime.milliseconds; + + if (pScrPriv->rrGetPanning && + pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border)) { + rep.left = total.x1; + rep.top = total.y1; + rep.width = total.x2 - total.x1; + rep.height = total.y2 - total.y1; + rep.track_left = tracking.x1; + rep.track_top = tracking.y1; + rep.track_width = tracking.x2 - tracking.x1; + rep.track_height = tracking.y2 - tracking.y1; + rep.border_left = border[0]; + rep.border_top = border[1]; + rep.border_right = border[2]; + rep.border_bottom = border[3]; + } + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.timestamp, n); + swaps(&rep.left, n); + swaps(&rep.top, n); + swaps(&rep.width, n); + swaps(&rep.height, n); + swaps(&rep.track_left, n); + swaps(&rep.track_top, n); + swaps(&rep.track_width, n); + swaps(&rep.track_height, n); + swaps(&rep.border_left, n); + swaps(&rep.border_top, n); + swaps(&rep.border_right, n); + swaps(&rep.border_bottom, n); + } + WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep); + return Success; +} + +int +ProcRRSetPanning (ClientPtr client) +{ + REQUEST(xRRSetPanningReq); + xRRSetPanningReply rep; + RRCrtcPtr crtc; + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + TimeStamp time; + BoxRec total; + BoxRec tracking; + INT16 border[4]; + int n; + + REQUEST_SIZE_MATCH(xRRSetPanningReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* All crtcs must be associated with screens before client + * requests are processed + */ + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + if (!pScrPriv) { + time = currentTime; + rep.status = RRSetConfigFailed; + goto sendReply; + } + + time = ClientTimeToServerTime(stuff->timestamp); + + if (!pScrPriv->rrGetPanning) + return RRErrorBase + BadRRCrtc; + + total.x1 = stuff->left; + total.y1 = stuff->top; + total.x2 = total.x1 + stuff->width; + total.y2 = total.y1 + stuff->height; + tracking.x1 = stuff->track_left; + tracking.y1 = stuff->track_top; + tracking.x2 = tracking.x1 + stuff->track_width; + tracking.y2 = tracking.y1 + stuff->track_height; + border[0] = stuff->border_left; + border[1] = stuff->border_top; + border[2] = stuff->border_right; + border[3] = stuff->border_bottom; + + if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border)) + return BadMatch; + + pScrPriv->lastSetTime = time; + + rep.status = RRSetConfigSuccess; + +sendReply: + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.newTimestamp = pScrPriv->lastSetTime.milliseconds; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.newTimestamp, n); + } + WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep); + return Success; +} + +int +ProcRRGetCrtcGammaSize (ClientPtr client) +{ + REQUEST(xRRGetCrtcGammaSizeReq); + xRRGetCrtcGammaSizeReply reply; + RRCrtcPtr crtc; + int n; + + REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* Gamma retrieval failed, any better error? */ + if (!RRCrtcGammaGet(crtc)) + return RRErrorBase + BadRRCrtc; + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = 0; + reply.size = crtc->gammaSize; + if (client->swapped) { + swaps (&reply.sequenceNumber, n); + swapl (&reply.length, n); + swaps (&reply.size, n); + } + WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply); + return Success; +} + +int +ProcRRGetCrtcGamma (ClientPtr client) +{ + REQUEST(xRRGetCrtcGammaReq); + xRRGetCrtcGammaReply reply; + RRCrtcPtr crtc; + int n; + unsigned long len; + char *extra = NULL; + + REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + /* Gamma retrieval failed, any better error? */ + if (!RRCrtcGammaGet(crtc)) + return RRErrorBase + BadRRCrtc; + + len = crtc->gammaSize * 3 * 2; + + if (crtc->gammaSize) { + extra = malloc(len); + if (!extra) + return BadAlloc; + } + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = bytes_to_int32(len); + reply.size = crtc->gammaSize; + if (client->swapped) { + swaps (&reply.sequenceNumber, n); + swapl (&reply.length, n); + swaps (&reply.size, n); + } + WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply); + if (crtc->gammaSize) + { + memcpy(extra, crtc->gammaRed, len); + client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; + WriteSwappedDataToClient (client, len, extra); + free(extra); + } + return Success; +} + +int +ProcRRSetCrtcGamma (ClientPtr client) +{ + REQUEST(xRRSetCrtcGammaReq); + RRCrtcPtr crtc; + unsigned long len; + CARD16 *red, *green, *blue; + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq)); + if (len < (stuff->size * 3 + 1) >> 1) + return BadLength; + + if (stuff->size != crtc->gammaSize) + return BadMatch; + + red = (CARD16 *) (stuff + 1); + green = red + crtc->gammaSize; + blue = green + crtc->gammaSize; + + RRCrtcGammaSet (crtc, red, green, blue); + + return Success; +} + +/* Version 1.3 additions */ + +int +ProcRRSetCrtcTransform (ClientPtr client) +{ + REQUEST(xRRSetCrtcTransformReq); + RRCrtcPtr crtc; + PictTransform transform; + struct pixman_f_transform f_transform, f_inverse; + char *filter; + int nbytes; + xFixed *params; + int nparams; + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + PictTransform_from_xRenderTransform (&transform, &stuff->transform); + pixman_f_transform_from_pixman_transform (&f_transform, &transform); + if (!pixman_f_transform_invert (&f_inverse, &f_transform)) + return BadMatch; + + filter = (char *) (stuff + 1); + nbytes = stuff->nbytesFilter; + params = (xFixed *) (filter + pad_to_int32(nbytes)); + nparams = ((xFixed *) stuff + client->req_len) - params; + if (nparams < 0) + return BadLength; + + return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse, + filter, nbytes, params, nparams); +} + + +#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) + +static int +transform_filter_length (RRTransformPtr transform) +{ + int nbytes, nparams; + + if (transform->filter == NULL) + return 0; + nbytes = strlen (transform->filter->name); + nparams = transform->nparams; + return pad_to_int32(nbytes) + (nparams * sizeof (xFixed)); +} + +static int +transform_filter_encode (ClientPtr client, char *output, + CARD16 *nbytesFilter, + CARD16 *nparamsFilter, + RRTransformPtr transform) +{ + int nbytes, nparams; + int n; + + if (transform->filter == NULL) { + *nbytesFilter = 0; + *nparamsFilter = 0; + return 0; + } + nbytes = strlen (transform->filter->name); + nparams = transform->nparams; + *nbytesFilter = nbytes; + *nparamsFilter = nparams; + memcpy (output, transform->filter->name, nbytes); + while ((nbytes & 3) != 0) + output[nbytes++] = 0; + memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed)); + if (client->swapped) { + swaps (nbytesFilter, n); + swaps (nparamsFilter, n); + SwapLongs ((CARD32 *) (output + nbytes), nparams); + } + nbytes += nparams * sizeof (xFixed); + return nbytes; +} + +static void +transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict) +{ + xRenderTransform_from_PictTransform (wire, pict); + if (client->swapped) + SwapLongs ((CARD32 *) wire, bytes_to_int32(sizeof(xRenderTransform))); +} + +int +ProcRRGetCrtcTransform (ClientPtr client) +{ + REQUEST(xRRGetCrtcTransformReq); + xRRGetCrtcTransformReply *reply; + RRCrtcPtr crtc; + int n, nextra; + RRTransformPtr current, pending; + char *extra; + + REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + pending = &crtc->client_pending_transform; + current = &crtc->client_current_transform; + + nextra = (transform_filter_length (pending) + + transform_filter_length (current)); + + reply = malloc(sizeof (xRRGetCrtcTransformReply) + nextra); + if (!reply) + return BadAlloc; + + extra = (char *) (reply + 1); + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = bytes_to_int32(CrtcTransformExtra + nextra); + + reply->hasTransforms = crtc->transforms; + + transform_encode (client, &reply->pendingTransform, &pending->transform); + extra += transform_filter_encode (client, extra, + &reply->pendingNbytesFilter, + &reply->pendingNparamsFilter, + pending); + + transform_encode (client, &reply->currentTransform, ¤t->transform); + extra += transform_filter_encode (client, extra, + &reply->currentNbytesFilter, + &reply->currentNparamsFilter, + current); + + if (client->swapped) { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + } + WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply); + free(reply); + return Success; +} + +void +RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x, int *y) +{ + rrScrPriv (pScreen); + int i; + + /* intentional dead space -> let it float */ + if (pScrPriv->discontiguous) + return; + + /* if we're moving inside a crtc, we're fine */ + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + + int left, right, top, bottom; + + if (!crtc->mode) + continue; + + crtc_bounds(crtc, &left, &right, &top, &bottom); + + if ((*x >= left) && (*x <= right) && (*y >= top) && (*y <= bottom)) + return; + } + + /* if we're trying to escape, clamp to the CRTC we're coming from */ + for (i = 0; i < pScrPriv->numCrtcs; i++) { + RRCrtcPtr crtc = pScrPriv->crtcs[i]; + int nx, ny; + int left, right, top, bottom; + + if (!crtc->mode) + continue; + + crtc_bounds(crtc, &left, &right, &top, &bottom); + miPointerGetPosition(pDev, &nx, &ny); + + if ((nx >= left) && (nx <= right) && (ny >= top) && (ny <= bottom)) { + if ((*x <= left) || (*x >= right)) { + int dx = *x - nx; + + if (dx > 0) + *x = right; + else if (dx < 0) + *x = left; + } + + if ((*y <= top) || (*y >= bottom)) { + int dy = *y - ny; + + if (dy > 0) + *y = bottom; + else if (dy < 0) + *y = top; + } + + return; + } + } +} diff --git a/xorg-server/record/record.c b/xorg-server/record/record.c index df3f9c6ec..cafe02168 100644 --- a/xorg-server/record/record.c +++ b/xorg-server/record/record.c @@ -1,2937 +1,2936 @@ - -/* - -Copyright 1995, 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. - -Author: David P. Wiggins, The Open Group - -This work benefited from earlier work done by Martha Zimet of NCD -and Jim Haggerty of Metheus. - -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "dixstruct.h" -#include "extnsionst.h" -#include -#include "set.h" -#include "swaprep.h" -#include "inputstr.h" -#include "eventconvert.h" -#include "scrnintstr.h" - - -#include -#include - -#ifdef PANORAMIX -#include "globals.h" -#include "panoramiX.h" -#include "panoramiXsrv.h" -#include "cursor.h" -#endif - -#include "protocol-versions.h" - -static RESTYPE RTContext; /* internal resource type for Record contexts */ - -/* How many bytes of protocol data to buffer in a context. Don't set to less - * than 32. - */ -#define REPLY_BUF_SIZE 1024 - -/* Record Context structure */ - -typedef struct { - XID id; /* resource id of context */ - ClientPtr pRecordingClient; /* client that has context enabled */ - struct _RecordClientsAndProtocolRec *pListOfRCAP; /* all registered info */ - ClientPtr pBufClient; /* client whose protocol is in replyBuffer*/ - unsigned int continuedReply:1; /* recording a reply that is split up? */ - char elemHeaders; /* element header flags (time/seq no.) */ - char bufCategory; /* category of protocol in replyBuffer */ - int numBufBytes; /* number of bytes in replyBuffer */ - char replyBuffer[REPLY_BUF_SIZE]; /* buffered recorded protocol */ - int inFlush; /* are we inside RecordFlushReplyBuffer */ -} RecordContextRec, *RecordContextPtr; - -/* RecordMinorOpRec - to hold minor opcode selections for extension requests - * and replies - */ - -typedef union { - int count; /* first element of array: how many "major" structs to follow */ - struct { /* rest of array elements are this */ - short first; /* first major opcode */ - short last; /* last major opcode */ - RecordSetPtr pMinOpSet; /* minor opcode set for above major range */ - } major; -} RecordMinorOpRec, *RecordMinorOpPtr; - - -/* RecordClientsAndProtocolRec, nicknamed RCAP - holds all the client and - * protocol selections passed in a single CreateContext or RegisterClients. - * Generally, a context will have one of these from the create and an - * additional one for each RegisterClients. RCAPs are freed when all their - * clients are unregistered. - */ - -typedef struct _RecordClientsAndProtocolRec { - RecordContextPtr pContext; /* context that owns this RCAP */ - struct _RecordClientsAndProtocolRec *pNextRCAP; /* next RCAP on context */ - RecordSetPtr pRequestMajorOpSet; /* requests to record */ - RecordMinorOpPtr pRequestMinOpInfo; /* extension requests to record */ - RecordSetPtr pReplyMajorOpSet; /* replies to record */ - RecordMinorOpPtr pReplyMinOpInfo; /* extension replies to record */ - RecordSetPtr pDeviceEventSet; /* device events to record */ - RecordSetPtr pDeliveredEventSet; /* delivered events to record */ - RecordSetPtr pErrorSet; /* errors to record */ - XID * pClientIDs; /* array of clients to record */ - short numClients; /* number of clients in pClientIDs */ - short sizeClients; /* size of pClientIDs array */ - unsigned int clientStarted:1; /* record new client connections? */ - unsigned int clientDied:1; /* record client disconnections? */ - unsigned int clientIDsSeparatelyAllocated:1; /* pClientIDs malloced? */ -} RecordClientsAndProtocolRec, *RecordClientsAndProtocolPtr; - -/* how much bigger to make pRCAP->pClientIDs when reallocing */ -#define CLIENT_ARRAY_GROWTH_INCREMENT 4 - -/* counts the total number of RCAPs belonging to enabled contexts. */ -static int numEnabledRCAPs; - -/* void VERIFY_CONTEXT(RecordContextPtr, XID, ClientPtr) - * In the spirit of the VERIFY_* macros in dix.h, this macro fills in - * the context pointer if the given ID is a valid Record Context, else it - * returns an error. - */ -#define VERIFY_CONTEXT(_pContext, _contextid, _client) { \ - int rc = dixLookupResourceByType((pointer *)&(_pContext), _contextid, \ - RTContext, _client, DixUseAccess); \ - if (rc != Success) \ - return rc; \ -} - -static int RecordDeleteContext( - pointer /*value*/, - XID /*id*/ -); - -void RecordExtensionInit(void); - -/***************************************************************************/ - -/* client private stuff */ - -/* To make declarations less obfuscated, have a typedef for a pointer to a - * Proc function. - */ -typedef int (*ProcFunctionPtr)( - ClientPtr /*pClient*/ -); - -/* Record client private. Generally a client only has one of these if - * any of its requests are being recorded. - */ -typedef struct { -/* ptr to client's proc vector before Record stuck its nose in */ - ProcFunctionPtr *originalVector; - -/* proc vector with pointers for recorded requests redirected to the - * function RecordARequest - */ - ProcFunctionPtr recordVector[256]; -} RecordClientPrivateRec, *RecordClientPrivatePtr; - -static DevPrivateKeyRec RecordClientPrivateKeyRec; -#define RecordClientPrivateKey (&RecordClientPrivateKeyRec) - -/* RecordClientPrivatePtr RecordClientPrivate(ClientPtr) - * gets the client private of the given client. Syntactic sugar. - */ -#define RecordClientPrivate(_pClient) (RecordClientPrivatePtr) \ - dixLookupPrivate(&(_pClient)->devPrivates, RecordClientPrivateKey) - - -/***************************************************************************/ - -/* global list of all contexts */ - -static RecordContextPtr *ppAllContexts; - -static int numContexts;/* number of contexts in ppAllContexts */ - -/* number of currently enabled contexts. All enabled contexts are bunched - * up at the front of the ppAllContexts array, from ppAllContexts[0] to - * ppAllContexts[numEnabledContexts-1], to eliminate time spent skipping - * past disabled contexts. - */ -static int numEnabledContexts; - -/* RecordFindContextOnAllContexts - * - * Arguments: - * pContext is the context to search for. - * - * Returns: - * The index into the array ppAllContexts at which pContext is stored. - * If pContext is not found in ppAllContexts, returns -1. - * - * Side Effects: none. - */ -static int -RecordFindContextOnAllContexts(RecordContextPtr pContext) -{ - int i; - - assert(numContexts >= numEnabledContexts); - for (i = 0; i < numContexts; i++) - { - if (ppAllContexts[i] == pContext) - return i; - } - return -1; -} /* RecordFindContextOnAllContexts */ - - -/***************************************************************************/ - -/* RecordFlushReplyBuffer - * - * Arguments: - * pContext is the context to flush. - * data1 is a pointer to additional data, and len1 is its length in bytes. - * data2 is a pointer to additional data, and len2 is its length in bytes. - * - * Returns: nothing. - * - * Side Effects: - * If the context is enabled, any buffered (recorded) protocol is written - * to the recording client, and the number of buffered bytes is set to - * zero. If len1 is not zero, data1/len1 are then written to the - * recording client, and similarly for data2/len2 (written after - * data1/len1). - */ -static void -RecordFlushReplyBuffer( - RecordContextPtr pContext, - pointer data1, - int len1, - pointer data2, - int len2 -) -{ - if (!pContext->pRecordingClient || pContext->pRecordingClient->clientGone || pContext->inFlush) - return; - ++pContext->inFlush; - if (pContext->numBufBytes) - WriteToClient(pContext->pRecordingClient, pContext->numBufBytes, - (char *)pContext->replyBuffer); - pContext->numBufBytes = 0; - if (len1) - WriteToClient(pContext->pRecordingClient, len1, (char *)data1); - if (len2) - WriteToClient(pContext->pRecordingClient, len2, (char *)data2); - --pContext->inFlush; -} /* RecordFlushReplyBuffer */ - - -/* RecordAProtocolElement - * - * Arguments: - * pContext is the context that is recording a protocol element. - * pClient is the client whose protocol is being recorded. For - * device events and EndOfData, pClient is NULL. - * category is the category of the protocol element, as defined - * by the RECORD spec. - * data is a pointer to the protocol data, and datalen is its length - * in bytes. - * futurelen is the number of bytes that will be sent in subsequent - * calls to this function to complete this protocol element. - * In those subsequent calls, futurelen will be -1 to indicate - * that the current data is a continuation of the same protocol - * element. - * - * Returns: nothing. - * - * Side Effects: - * The context may be flushed. The new protocol element will be - * added to the context's protocol buffer with appropriate element - * headers prepended (sequence number and timestamp). If the data - * is continuation data (futurelen == -1), element headers won't - * be added. If the protocol element and headers won't fit in - * the context's buffer, it is sent directly to the recording - * client (after any buffered data). - */ -static void -RecordAProtocolElement(RecordContextPtr pContext, ClientPtr pClient, - int category, pointer data, int datalen, int futurelen) -{ - CARD32 elemHeaderData[2]; - int numElemHeaders = 0; - Bool recordingClientSwapped = pContext->pRecordingClient->swapped; - int n; - CARD32 serverTime = 0; - Bool gotServerTime = FALSE; - int replylen; - - if (futurelen >= 0) - { /* start of new protocol element */ - xRecordEnableContextReply *pRep = (xRecordEnableContextReply *) - pContext->replyBuffer; - if (pContext->pBufClient != pClient || - pContext->bufCategory != category) - { - RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); - pContext->pBufClient = pClient; - pContext->bufCategory = category; - } - - if (!pContext->numBufBytes) - { - serverTime = GetTimeInMillis(); - gotServerTime = TRUE; - pRep->type = X_Reply; - pRep->category = category; - pRep->sequenceNumber = pContext->pRecordingClient->sequence; - pRep->length = 0; - pRep->elementHeader = pContext->elemHeaders; - pRep->serverTime = serverTime; - if (pClient) - { - pRep->clientSwapped = - (pClient->swapped != recordingClientSwapped); - pRep->idBase = pClient->clientAsMask; - pRep->recordedSequenceNumber = pClient->sequence; - } - else /* it's a device event, StartOfData, or EndOfData */ - { - pRep->clientSwapped = (category != XRecordFromServer) && - recordingClientSwapped; - pRep->idBase = 0; - pRep->recordedSequenceNumber = 0; - } - - if (recordingClientSwapped) - { - swaps(&pRep->sequenceNumber, n); - swapl(&pRep->length, n); - swapl(&pRep->idBase, n); - swapl(&pRep->serverTime, n); - swapl(&pRep->recordedSequenceNumber, n); - } - pContext->numBufBytes = SIZEOF(xRecordEnableContextReply); - } - - /* generate element headers if needed */ - - if ( ( (pContext->elemHeaders & XRecordFromClientTime) - && category == XRecordFromClient) - || - ( (pContext->elemHeaders & XRecordFromServerTime) - && category == XRecordFromServer)) - { - if (gotServerTime) - elemHeaderData[numElemHeaders] = serverTime; - else - elemHeaderData[numElemHeaders] = GetTimeInMillis(); - if (recordingClientSwapped) - swapl(&elemHeaderData[numElemHeaders], n); - numElemHeaders++; - } - - if ( (pContext->elemHeaders & XRecordFromClientSequence) - && - (category == XRecordFromClient || category == XRecordClientDied)) - { - elemHeaderData[numElemHeaders] = pClient->sequence; - if (recordingClientSwapped) - swapl(&elemHeaderData[numElemHeaders], n); - numElemHeaders++; - } - - /* adjust reply length */ - - replylen = pRep->length; - if (recordingClientSwapped) swapl(&replylen, n); - replylen += numElemHeaders + bytes_to_int32(datalen) + - bytes_to_int32(futurelen); - if (recordingClientSwapped) swapl(&replylen, n); - pRep->length = replylen; - } /* end if not continued reply */ - - numElemHeaders *= 4; - - /* if space available >= space needed, buffer the data */ - - if (REPLY_BUF_SIZE - pContext->numBufBytes >= datalen + numElemHeaders) - { - if (numElemHeaders) - { - memcpy(pContext->replyBuffer + pContext->numBufBytes, - elemHeaderData, numElemHeaders); - pContext->numBufBytes += numElemHeaders; - } - if (datalen) - { - memcpy(pContext->replyBuffer + pContext->numBufBytes, - data, datalen); - pContext->numBufBytes += datalen; - } - } - else - RecordFlushReplyBuffer(pContext, (pointer)elemHeaderData, - numElemHeaders, (pointer)data, datalen); - -} /* RecordAProtocolElement */ - - -/* RecordFindClientOnContext - * - * Arguments: - * pContext is the context to search. - * clientspec is the resource ID mask identifying the client to search - * for, or XRecordFutureClients. - * pposition is a pointer to an int, or NULL. See Returns. - * - * Returns: - * The RCAP on which clientspec was found, or NULL if not found on - * any RCAP on the given context. - * If pposition was not NULL and the returned RCAP is not NULL, - * *pposition will be set to the index into the returned the RCAP's - * pClientIDs array that holds clientspec. - * - * Side Effects: none. - */ -static RecordClientsAndProtocolPtr -RecordFindClientOnContext( - RecordContextPtr pContext, - XID clientspec, - int *pposition -) -{ - RecordClientsAndProtocolPtr pRCAP; - - for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) - { - int i; - for (i = 0; i < pRCAP->numClients; i++) - { - if (pRCAP->pClientIDs[i] == clientspec) - { - if (pposition) - *pposition = i; - return pRCAP; - } - } - } - return NULL; -} /* RecordFindClientOnContext */ - - -/* RecordABigRequest - * - * Arguments: - * pContext is the recording context. - * client is the client being recorded. - * stuff is a pointer to the big request of client (see the Big Requests - * extension for details.) - * - * Returns: nothing. - * - * Side Effects: - * The big request is recorded with the correct length field re-inserted. - * - * Note: this function exists mainly to make RecordARequest smaller. - */ -static void -RecordABigRequest(RecordContextPtr pContext, ClientPtr client, xReq *stuff) -{ - CARD32 bigLength; - char n; - int bytesLeft; - - /* note: client->req_len has been frobbed by ReadRequestFromClient - * (os/io.c) to discount the extra 4 bytes taken by the extended length - * field in a big request. The actual request length to record is - * client->req_len + 1 (measured in CARD32s). - */ - - /* record the request header */ - bytesLeft = client->req_len << 2; - RecordAProtocolElement(pContext, client, XRecordFromClient, - (pointer)stuff, SIZEOF(xReq), bytesLeft); - - /* reinsert the extended length field that was squished out */ - bigLength = client->req_len + bytes_to_int32(sizeof(bigLength)); - if (client->swapped) - swapl(&bigLength, n); - RecordAProtocolElement(pContext, client, XRecordFromClient, - (pointer)&bigLength, sizeof(bigLength), /* continuation */ -1); - bytesLeft -= sizeof(bigLength); - - /* record the rest of the request after the length */ - RecordAProtocolElement(pContext, client, XRecordFromClient, - (pointer)(stuff + 1), bytesLeft, /* continuation */ -1); -} /* RecordABigRequest */ - - -/* RecordARequest - * - * Arguments: - * client is a client that the server has dispatched a request to by - * calling client->requestVector[request opcode] . - * The request is in client->requestBuffer. - * - * Returns: - * Whatever is returned by the "real" Proc function for this request. - * The "real" Proc function is the function that was in - * client->requestVector[request opcode] before it was replaced by - * RecordARequest. (See the function RecordInstallHooks.) - * - * Side Effects: - * The request is recorded by all contexts that have registered this - * request for this client. The real Proc function is called. - */ -static int -RecordARequest(ClientPtr client) -{ - RecordContextPtr pContext; - RecordClientsAndProtocolPtr pRCAP; - int i; - RecordClientPrivatePtr pClientPriv; - REQUEST(xReq); - int majorop; - - majorop = stuff->reqType; - for (i = 0; i < numEnabledContexts; i++) - { - pContext = ppAllContexts[i]; - pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, - NULL); - if (pRCAP && pRCAP->pRequestMajorOpSet && - RecordIsMemberOfSet(pRCAP->pRequestMajorOpSet, majorop)) - { - if (majorop <= 127) - { /* core request */ - - if (stuff->length == 0) - RecordABigRequest(pContext, client, stuff); - else - RecordAProtocolElement(pContext, client, XRecordFromClient, - (pointer)stuff, client->req_len << 2, 0); - } - else /* extension, check minor opcode */ - { - int minorop = MinorOpcodeOfRequest(client); - int numMinOpInfo; - RecordMinorOpPtr pMinorOpInfo = pRCAP->pRequestMinOpInfo; - - assert (pMinorOpInfo); - numMinOpInfo = pMinorOpInfo->count; - pMinorOpInfo++; - assert (numMinOpInfo); - for ( ; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) - { - if (majorop >= pMinorOpInfo->major.first && - majorop <= pMinorOpInfo->major.last && - RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet, - minorop)) - { - if (stuff->length == 0) - RecordABigRequest(pContext, client, stuff); - else - RecordAProtocolElement(pContext, client, - XRecordFromClient, (pointer)stuff, - client->req_len << 2, 0); - break; - } - } /* end for each minor op info */ - } /* end extension request */ - } /* end this RCAP wants this major opcode */ - } /* end for each context */ - pClientPriv = RecordClientPrivate(client); - assert(pClientPriv); - return (* pClientPriv->originalVector[majorop])(client); -} /* RecordARequest */ - -/* RecordAReply - * - * Arguments: - * pcbl is &ReplyCallback. - * nulldata is NULL. - * calldata is a pointer to a ReplyInfoRec (include/os.h) - * which provides information about replies that are being sent - * to clients. - * - * Returns: nothing. - * - * Side Effects: - * The reply is recorded by all contexts that have registered this - * reply type for this client. If more data belonging to the same - * reply is expected, and if the reply is being recorded by any - * context, pContext->continuedReply is set to 1. - * If pContext->continuedReply was already 1 and this is the last - * chunk of data belonging to this reply, it is set to 0. - */ -static void -RecordAReply(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) -{ - RecordContextPtr pContext; - RecordClientsAndProtocolPtr pRCAP; - int eci; - int majorop; - ReplyInfoRec *pri = (ReplyInfoRec *)calldata; - ClientPtr client = pri->client; - REQUEST(xReq); - - majorop = stuff->reqType; - for (eci = 0; eci < numEnabledContexts; eci++) - { - pContext = ppAllContexts[eci]; - pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, - NULL); - if (pRCAP) - { - if (pContext->continuedReply) - { - RecordAProtocolElement(pContext, client, XRecordFromServer, - (pointer)pri->replyData, pri->dataLenBytes, /* continuation */ -1); - if (!pri->bytesRemaining) - pContext->continuedReply = 0; - } - else if (pri->startOfReply && pRCAP->pReplyMajorOpSet && - RecordIsMemberOfSet(pRCAP->pReplyMajorOpSet, majorop)) - { - if (majorop <= 127) - { /* core reply */ - RecordAProtocolElement(pContext, client, XRecordFromServer, - (pointer)pri->replyData, pri->dataLenBytes, pri->bytesRemaining); - if (pri->bytesRemaining) - pContext->continuedReply = 1; - } - else /* extension, check minor opcode */ - { - int minorop = MinorOpcodeOfRequest(client); - int numMinOpInfo; - RecordMinorOpPtr pMinorOpInfo = pRCAP->pReplyMinOpInfo; - assert (pMinorOpInfo); - numMinOpInfo = pMinorOpInfo->count; - pMinorOpInfo++; - assert (numMinOpInfo); - for ( ; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) - { - if (majorop >= pMinorOpInfo->major.first && - majorop <= pMinorOpInfo->major.last && - RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet, - minorop)) - { - RecordAProtocolElement(pContext, client, - XRecordFromServer, (pointer)pri->replyData, - pri->dataLenBytes, pri->bytesRemaining); - if (pri->bytesRemaining) - pContext->continuedReply = 1; - break; - } - } /* end for each minor op info */ - } /* end extension reply */ - } /* end continued reply vs. start of reply */ - } /* end client is registered on this context */ - } /* end for each context */ -} /* RecordAReply */ - - -/* RecordADeliveredEventOrError - * - * Arguments: - * pcbl is &EventCallback. - * nulldata is NULL. - * calldata is a pointer to a EventInfoRec (include/dix.h) - * which provides information about events that are being sent - * to clients. - * - * Returns: nothing. - * - * Side Effects: - * The event or error is recorded by all contexts that have registered - * it for this client. - */ -static void -RecordADeliveredEventOrError(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) -{ - EventInfoRec *pei = (EventInfoRec *)calldata; - RecordContextPtr pContext; - RecordClientsAndProtocolPtr pRCAP; - int eci; /* enabled context index */ - ClientPtr pClient = pei->client; - - for (eci = 0; eci < numEnabledContexts; eci++) - { - pContext = ppAllContexts[eci]; - pRCAP = RecordFindClientOnContext(pContext, pClient->clientAsMask, - NULL); - if (pRCAP && (pRCAP->pDeliveredEventSet || pRCAP->pErrorSet)) - { - int ev; /* event index */ - xEvent *pev = pei->events; - for (ev = 0; ev < pei->count; ev++, pev++) - { - int recordit = 0; - if (pRCAP->pErrorSet) - { - recordit = RecordIsMemberOfSet(pRCAP->pErrorSet, - ((xError *)(pev))->errorCode); - } - else if (pRCAP->pDeliveredEventSet) - { - recordit = RecordIsMemberOfSet(pRCAP->pDeliveredEventSet, - pev->u.u.type & 0177); - } - if (recordit) - { - xEvent swappedEvent; - xEvent *pEvToRecord = pev; - - if (pClient->swapped) - { - (*EventSwapVector[pev->u.u.type & 0177]) - (pev, &swappedEvent); - pEvToRecord = &swappedEvent; - - } - RecordAProtocolElement(pContext, pClient, - XRecordFromServer, pEvToRecord, SIZEOF(xEvent), 0); - } - } /* end for each event */ - } /* end this client is on this context */ - } /* end for each enabled context */ -} /* RecordADeliveredEventOrError */ - - -static void -RecordSendProtocolEvents(RecordClientsAndProtocolPtr pRCAP, - RecordContextPtr pContext, - xEvent* pev, int count) -{ - int ev; /* event index */ - - for (ev = 0; ev < count; ev++, pev++) - { - if (RecordIsMemberOfSet(pRCAP->pDeviceEventSet, - pev->u.u.type & 0177)) - { - xEvent swappedEvent; - xEvent *pEvToRecord = pev; -#ifdef PANORAMIX - xEvent shiftedEvent; - - if (!noPanoramiXExtension && - (pev->u.u.type == MotionNotify || - pev->u.u.type == ButtonPress || - pev->u.u.type == ButtonRelease || - pev->u.u.type == KeyPress || - pev->u.u.type == KeyRelease)) { - int scr = XineramaGetCursorScreen(inputInfo.pointer); - memcpy(&shiftedEvent, pev, sizeof(xEvent)); - shiftedEvent.u.keyButtonPointer.rootX += - screenInfo.screens[scr]->x - - screenInfo.screens[0]->x; - shiftedEvent.u.keyButtonPointer.rootY += - screenInfo.screens[scr]->y - - screenInfo.screens[0]->y; - pEvToRecord = &shiftedEvent; - } -#endif /* PANORAMIX */ - - if (pContext->pRecordingClient->swapped) - { - (*EventSwapVector[pEvToRecord->u.u.type & 0177]) - (pEvToRecord, &swappedEvent); - pEvToRecord = &swappedEvent; - } - - RecordAProtocolElement(pContext, NULL, - XRecordFromServer, pEvToRecord, SIZEOF(xEvent), 0); - /* make sure device events get flushed in the absence - * of other client activity - */ - SetCriticalOutputPending(); - } - } /* end for each event */ - -} /* RecordADeviceEvent */ - -/* RecordADeviceEvent - * - * Arguments: - * pcbl is &DeviceEventCallback. - * nulldata is NULL. - * calldata is a pointer to a DeviceEventInfoRec (include/dix.h) - * which provides information about device events that occur. - * - * Returns: nothing. - * - * Side Effects: - * The device event is recorded by all contexts that have registered - * it for this client. - */ -static void -RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) -{ - DeviceEventInfoRec *pei = (DeviceEventInfoRec *)calldata; - RecordContextPtr pContext; - RecordClientsAndProtocolPtr pRCAP; - int eci; /* enabled context index */ - int count; - - for (eci = 0; eci < numEnabledContexts; eci++) - { - pContext = ppAllContexts[eci]; - for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) - { - if (pRCAP->pDeviceEventSet) - { - int count; - xEvent *xi_events = NULL; - - /* TODO check return values */ - if (IsMaster(pei->device)) - { - xEvent *core_events; - EventToCore(pei->event, &core_events, &count); - RecordSendProtocolEvents(pRCAP, pContext, core_events, - count); - free(core_events); - } - - EventToXI(pei->event, &xi_events, &count); - RecordSendProtocolEvents(pRCAP, pContext, xi_events, count); - free(xi_events); - } /* end this RCAP selects device events */ - } /* end for each RCAP on this context */ - } /* end for each enabled context */ -} - - -/* RecordFlushAllContexts - * - * Arguments: - * pcbl is &FlushCallback. - * nulldata and calldata are NULL. - * - * Returns: nothing. - * - * Side Effects: - * All buffered reply data of all enabled contexts is written to - * the recording clients. - */ -static void -RecordFlushAllContexts( - CallbackListPtr *pcbl, - pointer nulldata, - pointer calldata -) -{ - int eci; /* enabled context index */ - RecordContextPtr pContext; - - for (eci = 0; eci < numEnabledContexts; eci++) - { - pContext = ppAllContexts[eci]; - - /* In most cases we leave it to RecordFlushReplyBuffer to make - * this check, but this function could be called very often, so we - * check before calling hoping to save the function call cost - * most of the time. - */ - if (pContext->numBufBytes) - RecordFlushReplyBuffer(ppAllContexts[eci], NULL, 0, NULL, 0); - } -} /* RecordFlushAllContexts */ - - -/* RecordInstallHooks - * - * Arguments: - * pRCAP is an RCAP on an enabled or being-enabled context. - * oneclient can be zero or the resource ID mask identifying a client. - * - * Returns: BadAlloc if a memory allocation error occurred, else Success. - * - * Side Effects: - * Recording hooks needed by RCAP are installed. - * If oneclient is zero, recording hooks needed for all clients and - * protocol on the RCAP are installed. If oneclient is non-zero, - * only those hooks needed for the specified client are installed. - * - * Client requestVectors may be altered. numEnabledRCAPs will be - * incremented if oneclient == 0. Callbacks may be added to - * various callback lists. - */ -static int -RecordInstallHooks(RecordClientsAndProtocolPtr pRCAP, XID oneclient) -{ - int i = 0; - XID client; - - if (oneclient) - client = oneclient; - else - client = pRCAP->numClients ? pRCAP->pClientIDs[i++] : 0; - - while (client) - { - if (client != XRecordFutureClients) - { - if (pRCAP->pRequestMajorOpSet) - { - RecordSetIteratePtr pIter = NULL; - RecordSetInterval interval; - ClientPtr pClient = clients[CLIENT_ID(client)]; - - if (pClient && !RecordClientPrivate(pClient)) - { - RecordClientPrivatePtr pClientPriv; - /* no Record proc vector; allocate one */ - pClientPriv = (RecordClientPrivatePtr) - malloc(sizeof(RecordClientPrivateRec)); - if (!pClientPriv) - return BadAlloc; - /* copy old proc vector to new */ - memcpy(pClientPriv->recordVector, pClient->requestVector, - sizeof (pClientPriv->recordVector)); - pClientPriv->originalVector = pClient->requestVector; - dixSetPrivate(&pClient->devPrivates, - RecordClientPrivateKey, pClientPriv); - pClient->requestVector = pClientPriv->recordVector; - } - while ((pIter = RecordIterateSet(pRCAP->pRequestMajorOpSet, - pIter, &interval))) - { - unsigned int j; - for (j = interval.first; j <= interval.last; j++) - pClient->requestVector[j] = RecordARequest; - } - } - } - if (oneclient) - client = 0; - else - client = (i < pRCAP->numClients) ? pRCAP->pClientIDs[i++] : 0; - } - - assert(numEnabledRCAPs >= 0); - if (!oneclient && ++numEnabledRCAPs == 1) - { /* we're enabling the first context */ - if (!AddCallback(&EventCallback, RecordADeliveredEventOrError, NULL)) - return BadAlloc; - if (!AddCallback(&DeviceEventCallback, RecordADeviceEvent, NULL)) - return BadAlloc; - if (!AddCallback(&ReplyCallback, RecordAReply, NULL)) - return BadAlloc; - if (!AddCallback(&FlushCallback, RecordFlushAllContexts, NULL)) - return BadAlloc; - /* Alternate context flushing scheme: delete the line above - * and call RegisterBlockAndWakeupHandlers here passing - * RecordFlushAllContexts. Is this any better? - */ - } - return Success; -} /* RecordInstallHooks */ - - -/* RecordUninstallHooks - * - * Arguments: - * pRCAP is an RCAP on an enabled or being-disabled context. - * oneclient can be zero or the resource ID mask identifying a client. - * - * Returns: nothing. - * - * Side Effects: - * Recording hooks needed by RCAP may be uninstalled. - * If oneclient is zero, recording hooks needed for all clients and - * protocol on the RCAP may be uninstalled. If oneclient is non-zero, - * only those hooks needed for the specified client may be uninstalled. - * - * Client requestVectors may be altered. numEnabledRCAPs will be - * decremented if oneclient == 0. Callbacks may be deleted from - * various callback lists. - */ -static void -RecordUninstallHooks(RecordClientsAndProtocolPtr pRCAP, XID oneclient) -{ - int i = 0; - XID client; - - if (oneclient) - client = oneclient; - else - client = pRCAP->numClients ? pRCAP->pClientIDs[i++] : 0; - - while (client) - { - if (client != XRecordFutureClients) - { - if (pRCAP->pRequestMajorOpSet) - { - ClientPtr pClient = clients[CLIENT_ID(client)]; - int c; - Bool otherRCAPwantsProcVector = FALSE; - RecordClientPrivatePtr pClientPriv = NULL; - - assert (pClient); - pClientPriv = RecordClientPrivate(pClient); - assert (pClientPriv); - memcpy(pClientPriv->recordVector, pClientPriv->originalVector, - sizeof (pClientPriv->recordVector)); - - for (c = 0; c < numEnabledContexts; c++) - { - RecordClientsAndProtocolPtr pOtherRCAP; - RecordContextPtr pContext = ppAllContexts[c]; - - if (pContext == pRCAP->pContext) continue; - pOtherRCAP = RecordFindClientOnContext(pContext, client, - NULL); - if (pOtherRCAP && pOtherRCAP->pRequestMajorOpSet) - { - RecordSetIteratePtr pIter = NULL; - RecordSetInterval interval; - - otherRCAPwantsProcVector = TRUE; - while ((pIter = RecordIterateSet( - pOtherRCAP->pRequestMajorOpSet, - pIter, &interval))) - { - unsigned int j; - for (j = interval.first; j <= interval.last; j++) - pClient->requestVector[j] = RecordARequest; - } - } - } - if (!otherRCAPwantsProcVector) - { /* nobody needs it, so free it */ - pClient->requestVector = pClientPriv->originalVector; - dixSetPrivate(&pClient->devPrivates, - RecordClientPrivateKey, NULL); - free(pClientPriv); - } - } /* end if this RCAP specifies any requests */ - } /* end if not future clients */ - if (oneclient) - client = 0; - else - client = (i < pRCAP->numClients) ? pRCAP->pClientIDs[i++] : 0; - } - - assert(numEnabledRCAPs >= 1); - if (!oneclient && --numEnabledRCAPs == 0) - { /* we're disabling the last context */ - DeleteCallback(&EventCallback, RecordADeliveredEventOrError, NULL); - DeleteCallback(&DeviceEventCallback, RecordADeviceEvent, NULL); - DeleteCallback(&ReplyCallback, RecordAReply, NULL); - DeleteCallback(&FlushCallback, RecordFlushAllContexts, NULL); - /* Alternate context flushing scheme: delete the line above - * and call RemoveBlockAndWakeupHandlers here passing - * RecordFlushAllContexts. Is this any better? - */ - /* Having deleted the callback, call it one last time. -gildea */ - RecordFlushAllContexts(&FlushCallback, NULL, NULL); - } -} /* RecordUninstallHooks */ - - -/* RecordDeleteClientFromRCAP - * - * Arguments: - * pRCAP is an RCAP to delete the client from. - * position is the index into the array pRCAP->pClientIDs of the - * client to delete. - * - * Returns: nothing. - * - * Side Effects: - * Recording hooks needed by client will be uninstalled if the context - * is enabled. The designated client will be removed from the - * pRCAP->pClientIDs array. If it was the only client on the RCAP, - * the RCAP is removed from the context and freed. (Invariant: RCAPs - * have at least one client.) - */ -static void -RecordDeleteClientFromRCAP(RecordClientsAndProtocolPtr pRCAP, int position) -{ - if (pRCAP->pContext->pRecordingClient) - RecordUninstallHooks(pRCAP, pRCAP->pClientIDs[position]); - if (position != pRCAP->numClients - 1) - pRCAP->pClientIDs[position] = pRCAP->pClientIDs[pRCAP->numClients - 1]; - if (--pRCAP->numClients == 0) - { /* no more clients; remove RCAP from context's list */ - RecordContextPtr pContext = pRCAP->pContext; - if (pContext->pRecordingClient) - RecordUninstallHooks(pRCAP, 0); - if (pContext->pListOfRCAP == pRCAP) - pContext->pListOfRCAP = pRCAP->pNextRCAP; - else - { - RecordClientsAndProtocolPtr prevRCAP; - for (prevRCAP = pContext->pListOfRCAP; - prevRCAP->pNextRCAP != pRCAP; - prevRCAP = prevRCAP->pNextRCAP) - ; - prevRCAP->pNextRCAP = pRCAP->pNextRCAP; - } - /* free the RCAP */ - if (pRCAP->clientIDsSeparatelyAllocated) - free(pRCAP->pClientIDs); - free(pRCAP); - } -} /* RecordDeleteClientFromRCAP */ - - -/* RecordAddClientToRCAP - * - * Arguments: - * pRCAP is an RCAP to add the client to. - * clientspec is the resource ID mask identifying a client, or - * XRecordFutureClients. - * - * Returns: nothing. - * - * Side Effects: - * Recording hooks needed by client will be installed if the context - * is enabled. The designated client will be added to the - * pRCAP->pClientIDs array, which may be realloced. - * pRCAP->clientIDsSeparatelyAllocated may be set to 1 if there - * is no more room to hold clients internal to the RCAP. - */ -static void -RecordAddClientToRCAP(RecordClientsAndProtocolPtr pRCAP, XID clientspec) -{ - if (pRCAP->numClients == pRCAP->sizeClients) - { - if (pRCAP->clientIDsSeparatelyAllocated) - { - XID *pNewIDs = (XID *)realloc(pRCAP->pClientIDs, - (pRCAP->sizeClients + CLIENT_ARRAY_GROWTH_INCREMENT) * - sizeof(XID)); - if (!pNewIDs) - return; - pRCAP->pClientIDs = pNewIDs; - pRCAP->sizeClients += CLIENT_ARRAY_GROWTH_INCREMENT; - } - else - { - XID *pNewIDs = (XID *)malloc((pRCAP->sizeClients + - CLIENT_ARRAY_GROWTH_INCREMENT) * sizeof(XID)); - if (!pNewIDs) - return; - memcpy(pNewIDs, pRCAP->pClientIDs, pRCAP->numClients *sizeof(XID)); - pRCAP->pClientIDs = pNewIDs; - pRCAP->sizeClients += CLIENT_ARRAY_GROWTH_INCREMENT; - pRCAP->clientIDsSeparatelyAllocated = 1; - } - } - pRCAP->pClientIDs[pRCAP->numClients++] = clientspec; - if (pRCAP->pContext->pRecordingClient) - RecordInstallHooks(pRCAP, clientspec); -} /* RecordDeleteClientFromRCAP */ - - -/* RecordDeleteClientFromContext - * - * Arguments: - * pContext is the context to delete from. - * clientspec is the resource ID mask identifying a client, or - * XRecordFutureClients. - * - * Returns: nothing. - * - * Side Effects: - * If clientspec is on any RCAP of the context, it is deleted from that - * RCAP. (A given clientspec can only be on one RCAP of a context.) - */ -static void -RecordDeleteClientFromContext(RecordContextPtr pContext, XID clientspec) -{ - RecordClientsAndProtocolPtr pRCAP; - int position; - - if ((pRCAP = RecordFindClientOnContext(pContext, clientspec, &position))) - RecordDeleteClientFromRCAP(pRCAP, position); -} /* RecordDeleteClientFromContext */ - - -/* RecordSanityCheckClientSpecifiers - * - * Arguments: - * clientspecs is an array of alleged CLIENTSPECs passed by the client. - * nspecs is the number of elements in clientspecs. - * errorspec, if non-zero, is the resource id base of a client that - * must not appear in clienspecs. - * - * Returns: BadMatch if any of the clientspecs are invalid, else Success. - * - * Side Effects: none. - */ -static int -RecordSanityCheckClientSpecifiers(ClientPtr client, XID *clientspecs, int nspecs, XID errorspec) -{ - int i; - int clientIndex; - int rc; - pointer value; - - for (i = 0; i < nspecs; i++) - { - if (clientspecs[i] == XRecordCurrentClients || - clientspecs[i] == XRecordFutureClients || - clientspecs[i] == XRecordAllClients) - continue; - if (errorspec && (CLIENT_BITS(clientspecs[i]) == errorspec) ) - return BadMatch; - clientIndex = CLIENT_ID(clientspecs[i]); - if (clientIndex && clients[clientIndex] && - clients[clientIndex]->clientState == ClientStateRunning) - { - if (clientspecs[i] == clients[clientIndex]->clientAsMask) - continue; - rc = dixLookupResourceByClass(&value, clientspecs[i], RC_ANY, - client, DixGetAttrAccess); - if (rc != Success) - return rc; - } - else - return BadMatch; - } - return Success; -} /* RecordSanityCheckClientSpecifiers */ - - -/* RecordCanonicalizeClientSpecifiers - * - * Arguments: - * pClientspecs is an array of CLIENTSPECs that have been sanity - * checked. - * pNumClientspecs is a pointer to the number of elements in pClientspecs. - * excludespec, if non-zero, is the resource id base of a client that - * should not be included in the expansion of XRecordAllClients or - * XRecordCurrentClients. - * - * Returns: - * A pointer to an array of CLIENTSPECs that is the same as the - * passed array with the following modifications: - * - all but the client id bits of resource IDs are stripped off. - * - duplicates removed. - * - XRecordAllClients expanded to a list of all currently connected - * clients + XRecordFutureClients - excludespec (if non-zero) - * - XRecordCurrentClients expanded to a list of all currently - * connected clients - excludespec (if non-zero) - * The returned array may be the passed array modified in place, or - * it may be an malloc'ed array. The caller should keep a pointer to the - * original array and free the returned array if it is different. - * - * *pNumClientspecs is set to the number of elements in the returned - * array. - * - * Side Effects: - * pClientspecs may be modified in place. - */ -static XID * -RecordCanonicalizeClientSpecifiers(XID *pClientspecs, int *pNumClientspecs, XID excludespec) -{ - int i; - int numClients = *pNumClientspecs; - - /* first pass strips off the resource index bits, leaving just the - * client id bits. This makes searching for a particular client simpler - * (and faster.) - */ - for (i = 0; i < numClients; i++) - { - XID cs = pClientspecs[i]; - if (cs > XRecordAllClients) - pClientspecs[i] = CLIENT_BITS(cs); - } - - for (i = 0; i < numClients; i++) - { - if (pClientspecs[i] == XRecordAllClients || - pClientspecs[i] == XRecordCurrentClients) - { /* expand All/Current */ - int j, nc; - XID *pCanon = (XID *)malloc(sizeof(XID) * (currentMaxClients + 1)); - if (!pCanon) return NULL; - for (nc = 0, j = 1; j < currentMaxClients; j++) - { - ClientPtr client = clients[j]; - if (client != NullClient && - client->clientState == ClientStateRunning && - client->clientAsMask != excludespec) - { - pCanon[nc++] = client->clientAsMask; - } - } - if (pClientspecs[i] == XRecordAllClients) - pCanon[nc++] = XRecordFutureClients; - *pNumClientspecs = nc; - return pCanon; - } - else /* not All or Current */ - { - int j; - for (j = i + 1; j < numClients; ) - { - if (pClientspecs[i] == pClientspecs[j]) - { - pClientspecs[j] = pClientspecs[--numClients]; - } - else - j++; - } - } - } /* end for each clientspec */ - *pNumClientspecs = numClients; - return pClientspecs; -} /* RecordCanonicalizeClientSpecifiers */ - - -/****************************************************************************/ - -/* stuff for RegisterClients */ - -/* RecordPadAlign - * - * Arguments: - * size is the number of bytes taken by an object. - * align is a byte boundary (e.g. 4, 8) - * - * Returns: - * the number of pad bytes to add at the end of an object of the - * given size so that an object placed immediately behind it will - * begin on an -byte boundary. - * - * Side Effects: none. - */ -static int -RecordPadAlign(int size, int align) -{ - return (align - (size & (align - 1))) & (align - 1); -} /* RecordPadAlign */ - - -/* RecordSanityCheckRegisterClients - * - * Arguments: - * pContext is the context being registered on. - * client is the client that issued a RecordCreateContext or - * RecordRegisterClients request. - * stuff is a pointer to the request. - * - * Returns: - * Any one of several possible error values if any of the request - * arguments are invalid. Success if everything is OK. - * - * Side Effects: none. - */ -static int -RecordSanityCheckRegisterClients(RecordContextPtr pContext, ClientPtr client, xRecordRegisterClientsReq *stuff) -{ - int err; - xRecordRange *pRange; - int i; - XID recordingClient; - - if (((client->req_len << 2) - SIZEOF(xRecordRegisterClientsReq)) != - 4 * stuff->nClients + SIZEOF(xRecordRange) * stuff->nRanges) - return BadLength; - - if (stuff->elementHeader & - ~(XRecordFromClientSequence|XRecordFromClientTime|XRecordFromServerTime)) - { - client->errorValue = stuff->elementHeader; - return BadValue; - } - - recordingClient = pContext->pRecordingClient ? - pContext->pRecordingClient->clientAsMask : 0; - err = RecordSanityCheckClientSpecifiers(client, (XID *)&stuff[1], - stuff->nClients, recordingClient); - if (err != Success) return err; - - pRange = (xRecordRange *)(((XID *)&stuff[1]) + stuff->nClients); - for (i = 0; i < stuff->nRanges; i++, pRange++) - { - if (pRange->coreRequestsFirst > pRange->coreRequestsLast) - { - client->errorValue = pRange->coreRequestsFirst; - return BadValue; - } - if (pRange->coreRepliesFirst > pRange->coreRepliesLast) - { - client->errorValue = pRange->coreRepliesFirst; - return BadValue; - } - if ((pRange->extRequestsMajorFirst || pRange->extRequestsMajorLast) && - (pRange->extRequestsMajorFirst < 128 || - pRange->extRequestsMajorLast < 128 || - pRange->extRequestsMajorFirst > pRange->extRequestsMajorLast)) - { - client->errorValue = pRange->extRequestsMajorFirst; - return BadValue; - } - if (pRange->extRequestsMinorFirst > pRange->extRequestsMinorLast) - { - client->errorValue = pRange->extRequestsMinorFirst; - return BadValue; - } - if ((pRange->extRepliesMajorFirst || pRange->extRepliesMajorLast) && - (pRange->extRepliesMajorFirst < 128 || - pRange->extRepliesMajorLast < 128 || - pRange->extRepliesMajorFirst > pRange->extRepliesMajorLast)) - { - client->errorValue = pRange->extRepliesMajorFirst; - return BadValue; - } - if (pRange->extRepliesMinorFirst > pRange->extRepliesMinorLast) - { - client->errorValue = pRange->extRepliesMinorFirst; - return BadValue; - } - if ((pRange->deliveredEventsFirst || pRange->deliveredEventsLast) && - (pRange->deliveredEventsFirst < 2 || - pRange->deliveredEventsLast < 2 || - pRange->deliveredEventsFirst > pRange->deliveredEventsLast)) - { - client->errorValue = pRange->deliveredEventsFirst; - return BadValue; - } - if ((pRange->deviceEventsFirst || pRange->deviceEventsLast) && - (pRange->deviceEventsFirst < 2 || - pRange->deviceEventsLast < 2 || - pRange->deviceEventsFirst > pRange->deviceEventsLast)) - { - client->errorValue = pRange->deviceEventsFirst; - return BadValue; - } - if (pRange->errorsFirst > pRange->errorsLast) - { - client->errorValue = pRange->errorsFirst; - return BadValue; - } - if (pRange->clientStarted != xFalse && pRange->clientStarted != xTrue) - { - client->errorValue = pRange->clientStarted; - return BadValue; - } - if (pRange->clientDied != xFalse && pRange->clientDied != xTrue) - { - client->errorValue = pRange->clientDied; - return BadValue; - } - } /* end for each range */ - return Success; -} /* end RecordSanityCheckRegisterClients */ - -/* This is a tactical structure used to gather information about all the sets - * (RecordSetPtr) that need to be created for an RCAP in the process of - * digesting a list of RECORDRANGEs (converting it to the internal - * representation). - */ -typedef struct -{ - int nintervals; /* number of intervals in following array */ - RecordSetInterval *intervals; /* array of intervals for this set */ - int size; /* size of intevals array; >= nintervals */ - int align; /* alignment restriction for set */ - int offset; /* where to store set pointer rel. to start of RCAP */ - short first, last; /* if for extension, major opcode interval */ -} SetInfoRec, *SetInfoPtr; - -/* These constant are used to index into an array of SetInfoRec. */ -enum {REQ, /* set info for requests */ - REP, /* set info for replies */ - ERR, /* set info for errors */ - DEV, /* set info for device events */ - DLEV, /* set info for delivered events */ - PREDEFSETS}; /* number of predefined array entries */ - - -/* RecordAllocIntervals - * - * Arguments: - * psi is a pointer to a SetInfoRec whose intervals pointer is NULL. - * nIntervals is the desired size of the intervals array. - * - * Returns: BadAlloc if a memory allocation error occurred, else Success. - * - * Side Effects: - * If Success is returned, psi->intervals is a pointer to size - * RecordSetIntervals, all zeroed, and psi->size is set to size. - */ -static int -RecordAllocIntervals(SetInfoPtr psi, int nIntervals) -{ - assert(!psi->intervals); - psi->intervals = (RecordSetInterval *) - malloc(nIntervals * sizeof(RecordSetInterval)); - if (!psi->intervals) - return BadAlloc; - memset(psi->intervals, 0, nIntervals * sizeof(RecordSetInterval)); - psi->size = nIntervals; - return Success; -} /* end RecordAllocIntervals */ - - -/* RecordConvertRangesToIntervals - * - * Arguments: - * psi is a pointer to the SetInfoRec we are building. - * pRanges is an array of xRecordRanges. - * nRanges is the number of elements in pRanges. - * byteoffset is the offset from the start of an xRecordRange of the - * two bytes (1 for first, 1 for last) we are interested in. - * pExtSetInfo, if non-NULL, indicates that the two bytes mentioned - * above are followed by four bytes (2 for first, 2 for last) - * representing a minor opcode range, and this information should be - * stored in one of the SetInfoRecs starting at pExtSetInfo. - * pnExtSetInfo is the number of elements in the pExtSetInfo array. - * - * Returns: BadAlloc if a memory allocation error occurred, else Success. - * - * Side Effects: - * The slice of pRanges indicated by byteoffset is stored in psi. - * If pExtSetInfo is non-NULL, minor opcode intervals are stored - * in an existing SetInfoRec if the major opcode interval matches, else - * they are stored in a new SetInfoRec, and *pnExtSetInfo is - * increased accordingly. - */ -static int -RecordConvertRangesToIntervals( - SetInfoPtr psi, - xRecordRange *pRanges, - int nRanges, - int byteoffset, - SetInfoPtr pExtSetInfo, - int *pnExtSetInfo -) -{ - int i; - CARD8 *pCARD8; - int first, last; - int err; - - for (i = 0; i < nRanges; i++, pRanges++) - { - pCARD8 = ((CARD8 *)pRanges) + byteoffset; - first = pCARD8[0]; - last = pCARD8[1]; - if (first || last) - { - if (!psi->intervals) - { - err = RecordAllocIntervals(psi, 2 * (nRanges - i)); - if (err != Success) - return err; - } - psi->intervals[psi->nintervals].first = first; - psi->intervals[psi->nintervals].last = last; - psi->nintervals++; - assert(psi->nintervals <= psi->size); - if (pExtSetInfo) - { - SetInfoPtr pesi = pExtSetInfo; - CARD16 *pCARD16 = (CARD16 *)(pCARD8 + 2); - int j; - - for (j = 0; j < *pnExtSetInfo; j++, pesi++) - { - if ( (first == pesi->first) && (last == pesi->last) ) - break; - } - if (j == *pnExtSetInfo) - { - err = RecordAllocIntervals(pesi, 2 * (nRanges - i)); - if (err != Success) - return err; - pesi->first = first; - pesi->last = last; - (*pnExtSetInfo)++; - } - pesi->intervals[pesi->nintervals].first = pCARD16[0]; - pesi->intervals[pesi->nintervals].last = pCARD16[1]; - pesi->nintervals++; - assert(pesi->nintervals <= pesi->size); - } - } - } - return Success; -} /* end RecordConvertRangesToIntervals */ - -#define offset_of(_structure, _field) \ - ((char *)(& (_structure . _field)) - (char *)(&_structure)) - -/* RecordRegisterClients - * - * Arguments: - * pContext is the context on which to register the clients. - * client is the client that issued the RecordCreateContext or - * RecordRegisterClients request. - * stuff is a pointer to the request. - * - * Returns: - * Any one of several possible error values defined by the protocol. - * Success if everything is OK. - * - * Side Effects: - * If different element headers are specified, the context is flushed. - * If any of the specified clients are already registered on the - * context, they are first unregistered. A new RCAP is created to - * hold the specified protocol and clients, and it is linked onto the - * context. If the context is enabled, appropriate hooks are installed - * to record the new clients and protocol. - */ -static int -RecordRegisterClients(RecordContextPtr pContext, ClientPtr client, xRecordRegisterClientsReq *stuff) -{ - int err; - int i; - SetInfoPtr si; - int maxSets; - int nExtReqSets = 0; - int nExtRepSets = 0; - int extReqSetsOffset = 0; - int extRepSetsOffset = 0; - SetInfoPtr pExtReqSets, pExtRepSets; - int clientListOffset; - XID *pCanonClients; - int clientStarted = 0, clientDied = 0; - xRecordRange *pRanges, rr; - int nClients; - int sizeClients; - int totRCAPsize; - RecordClientsAndProtocolPtr pRCAP; - int pad; - XID recordingClient; - - /* do all sanity checking up front */ - - err = RecordSanityCheckRegisterClients(pContext, client, stuff); - if (err != Success) - return err; - - /* if element headers changed, flush buffer */ - - if (pContext->elemHeaders != stuff->elementHeader) - { - RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); - pContext->elemHeaders = stuff->elementHeader; - } - - nClients = stuff->nClients; - if (!nClients) - /* if empty clients list, we're done. */ - return Success; - - recordingClient = pContext->pRecordingClient ? - pContext->pRecordingClient->clientAsMask : 0; - pCanonClients = RecordCanonicalizeClientSpecifiers((XID *)&stuff[1], - &nClients, recordingClient); - if (!pCanonClients) - return BadAlloc; - - /* We may have to create as many as one set for each "predefined" - * protocol types, plus one per range for extension reuests, plus one per - * range for extension replies. - */ - maxSets = PREDEFSETS + 2 * stuff->nRanges; - si = (SetInfoPtr)malloc(sizeof(SetInfoRec) * maxSets); - if (!si) - { - err = BadAlloc; - goto bailout; - } - memset(si, 0, sizeof(SetInfoRec) * maxSets); - - /* theoretically you must do this because NULL may not be all-bits-zero */ - for (i = 0; i < maxSets; i++) - si[i].intervals = NULL; - - pExtReqSets = si + PREDEFSETS; - pExtRepSets = pExtReqSets + stuff->nRanges; - - pRanges = (xRecordRange *)(((XID *)&stuff[1]) + stuff->nClients); - - err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges, - offset_of(rr, coreRequestsFirst), NULL, NULL); - if (err != Success) goto bailout; - - err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges, - offset_of(rr, extRequestsMajorFirst), pExtReqSets, &nExtReqSets); - if (err != Success) goto bailout; - - err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges, - offset_of(rr, coreRepliesFirst), NULL, NULL); - if (err != Success) goto bailout; - - err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges, - offset_of(rr, extRepliesMajorFirst), pExtRepSets, &nExtRepSets); - if (err != Success) goto bailout; - - err = RecordConvertRangesToIntervals(&si[ERR], pRanges, stuff->nRanges, - offset_of(rr, errorsFirst), NULL, NULL); - if (err != Success) goto bailout; - - err = RecordConvertRangesToIntervals(&si[DLEV], pRanges, stuff->nRanges, - offset_of(rr, deliveredEventsFirst), NULL, NULL); - if (err != Success) goto bailout; - - err = RecordConvertRangesToIntervals(&si[DEV], pRanges, stuff->nRanges, - offset_of(rr, deviceEventsFirst), NULL, NULL); - if (err != Success) goto bailout; - - /* collect client-started and client-died */ - - for (i = 0; i < stuff->nRanges; i++) - { - if (pRanges[i].clientStarted) clientStarted = TRUE; - if (pRanges[i].clientDied) clientDied = TRUE; - } - - /* We now have all the information collected to create all the sets, - * and we can compute the total memory required for the RCAP. - */ - - totRCAPsize = sizeof(RecordClientsAndProtocolRec); - - /* leave a little room to grow before forcing a separate allocation */ - sizeClients = nClients + CLIENT_ARRAY_GROWTH_INCREMENT; - pad = RecordPadAlign(totRCAPsize, sizeof(XID)); - clientListOffset = totRCAPsize + pad; - totRCAPsize += pad + sizeClients * sizeof(XID); - - if (nExtReqSets) - { - pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr)); - extReqSetsOffset = totRCAPsize + pad; - totRCAPsize += pad + (nExtReqSets + 1) * sizeof(RecordMinorOpRec); - } - if (nExtRepSets) - { - pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr)); - extRepSetsOffset = totRCAPsize + pad; - totRCAPsize += pad + (nExtRepSets + 1) * sizeof(RecordMinorOpRec); - } - - for (i = 0; i < maxSets; i++) - { - if (si[i].nintervals) - { - si[i].size = RecordSetMemoryRequirements( - si[i].intervals, si[i].nintervals, &si[i].align); - pad = RecordPadAlign(totRCAPsize, si[i].align); - si[i].offset = pad + totRCAPsize; - totRCAPsize += pad + si[i].size; - } - } - - /* allocate memory for the whole RCAP */ - - pRCAP = (RecordClientsAndProtocolPtr)malloc(totRCAPsize); - if (!pRCAP) - { - err = BadAlloc; - goto bailout; - } - - /* fill in the RCAP */ - - pRCAP->pContext = pContext; - pRCAP->pClientIDs = (XID *)((char *)pRCAP + clientListOffset); - pRCAP->numClients = nClients; - pRCAP->sizeClients = sizeClients; - pRCAP->clientIDsSeparatelyAllocated = 0; - for (i = 0; i < nClients; i++) - { - RecordDeleteClientFromContext(pContext, pCanonClients[i]); - pRCAP->pClientIDs[i] = pCanonClients[i]; - } - - /* create all the sets */ - - if (si[REQ].intervals) - { - pRCAP->pRequestMajorOpSet = - RecordCreateSet(si[REQ].intervals, si[REQ].nintervals, - (RecordSetPtr)((char *)pRCAP + si[REQ].offset), si[REQ].size); - } - else pRCAP->pRequestMajorOpSet = NULL; - - if (si[REP].intervals) - { - pRCAP->pReplyMajorOpSet = - RecordCreateSet(si[REP].intervals, si[REP].nintervals, - (RecordSetPtr)((char *)pRCAP + si[REP].offset), si[REP].size); - } - else pRCAP->pReplyMajorOpSet = NULL; - - if (si[ERR].intervals) - { - pRCAP->pErrorSet = - RecordCreateSet(si[ERR].intervals, si[ERR].nintervals, - (RecordSetPtr)((char *)pRCAP + si[ERR].offset), si[ERR].size); - } - else pRCAP->pErrorSet = NULL; - - if (si[DEV].intervals) - { - pRCAP->pDeviceEventSet = - RecordCreateSet(si[DEV].intervals, si[DEV].nintervals, - (RecordSetPtr)((char *)pRCAP + si[DEV].offset), si[DEV].size); - } - else pRCAP->pDeviceEventSet = NULL; - - if (si[DLEV].intervals) - { - pRCAP->pDeliveredEventSet = - RecordCreateSet(si[DLEV].intervals, si[DLEV].nintervals, - (RecordSetPtr)((char *)pRCAP + si[DLEV].offset), si[DLEV].size); - } - else pRCAP->pDeliveredEventSet = NULL; - - if (nExtReqSets) - { - pRCAP->pRequestMinOpInfo = (RecordMinorOpPtr) - ((char *)pRCAP + extReqSetsOffset); - pRCAP->pRequestMinOpInfo[0].count = nExtReqSets; - for (i = 0; i < nExtReqSets; i++, pExtReqSets++) - { - pRCAP->pRequestMinOpInfo[i+1].major.first = pExtReqSets->first; - pRCAP->pRequestMinOpInfo[i+1].major.last = pExtReqSets->last; - pRCAP->pRequestMinOpInfo[i+1].major.pMinOpSet = - RecordCreateSet(pExtReqSets->intervals, - pExtReqSets->nintervals, - (RecordSetPtr)((char *)pRCAP + pExtReqSets->offset), - pExtReqSets->size); - } - } - else pRCAP->pRequestMinOpInfo = NULL; - - if (nExtRepSets) - { - pRCAP->pReplyMinOpInfo = (RecordMinorOpPtr) - ((char *)pRCAP + extRepSetsOffset); - pRCAP->pReplyMinOpInfo[0].count = nExtRepSets; - for (i = 0; i < nExtRepSets; i++, pExtRepSets++) - { - pRCAP->pReplyMinOpInfo[i+1].major.first = pExtRepSets->first; - pRCAP->pReplyMinOpInfo[i+1].major.last = pExtRepSets->last; - pRCAP->pReplyMinOpInfo[i+1].major.pMinOpSet = - RecordCreateSet(pExtRepSets->intervals, - pExtRepSets->nintervals, - (RecordSetPtr)((char *)pRCAP + pExtRepSets->offset), - pExtRepSets->size); - } - } - else pRCAP->pReplyMinOpInfo = NULL; - - pRCAP->clientStarted = clientStarted; - pRCAP->clientDied = clientDied; - - /* link the RCAP onto the context */ - - pRCAP->pNextRCAP = pContext->pListOfRCAP; - pContext->pListOfRCAP = pRCAP; - - if (pContext->pRecordingClient) /* context enabled */ - RecordInstallHooks(pRCAP, 0); - -bailout: - if (si) - { - for (i = 0; i < maxSets; i++) - free(si[i].intervals); - free(si); - } - if (pCanonClients && pCanonClients != (XID *)&stuff[1]) - free(pCanonClients); - return err; -} /* RecordRegisterClients */ - - -/* Proc functions all take a client argument, execute the request in - * client->requestBuffer, and return a protocol error status. - */ - -static int -ProcRecordQueryVersion(ClientPtr client) -{ - /* REQUEST(xRecordQueryVersionReq); */ - xRecordQueryVersionReply rep; - int n; - - REQUEST_SIZE_MATCH(xRecordQueryVersionReq); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.majorVersion = SERVER_RECORD_MAJOR_VERSION; - rep.minorVersion = SERVER_RECORD_MINOR_VERSION; - if(client->swapped) - { - swaps(&rep.sequenceNumber, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - (void)WriteToClient(client, sizeof(xRecordQueryVersionReply), - (char *)&rep); - return Success; -} /* ProcRecordQueryVersion */ - - -static int -ProcRecordCreateContext(ClientPtr client) -{ - REQUEST(xRecordCreateContextReq); - RecordContextPtr pContext; - RecordContextPtr *ppNewAllContexts = NULL; - int err = BadAlloc; - - REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq); - LEGAL_NEW_RESOURCE(stuff->context, client); - - pContext = (RecordContextPtr)malloc(sizeof(RecordContextRec)); - if (!pContext) - goto bailout; - - /* make sure there is room in ppAllContexts to store the new context */ - - ppNewAllContexts = (RecordContextPtr *) - realloc(ppAllContexts, sizeof(RecordContextPtr) * (numContexts + 1)); - if (!ppNewAllContexts) - goto bailout; - ppAllContexts = ppNewAllContexts; - - pContext->id = stuff->context; - pContext->pRecordingClient = NULL; - pContext->pListOfRCAP = NULL; - pContext->elemHeaders = 0; - pContext->bufCategory = 0; - pContext->numBufBytes = 0; - pContext->pBufClient = NULL; - pContext->continuedReply = 0; - pContext->inFlush = 0; - - err = RecordRegisterClients(pContext, client, - (xRecordRegisterClientsReq *)stuff); - if (err != Success) - goto bailout; - - if (AddResource(pContext->id, RTContext, pContext)) - { - ppAllContexts[numContexts++] = pContext; - return Success; - } - else - { - RecordDeleteContext((pointer)pContext, pContext->id); - err = BadAlloc; - } -bailout: - free(pContext); - return err; -} /* ProcRecordCreateContext */ - - -static int -ProcRecordRegisterClients(ClientPtr client) -{ - RecordContextPtr pContext; - REQUEST(xRecordRegisterClientsReq); - - REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq); - VERIFY_CONTEXT(pContext, stuff->context, client); - - return RecordRegisterClients(pContext, client, stuff); -} /* ProcRecordRegisterClients */ - - -static int -ProcRecordUnregisterClients(ClientPtr client) -{ - RecordContextPtr pContext; - int err; - REQUEST(xRecordUnregisterClientsReq); - XID *pCanonClients; - int nClients; - int i; - - REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq); - if ((client->req_len << 2) - SIZEOF(xRecordUnregisterClientsReq) != - 4 * stuff->nClients) - return BadLength; - VERIFY_CONTEXT(pContext, stuff->context, client); - err = RecordSanityCheckClientSpecifiers(client, (XID *)&stuff[1], - stuff->nClients, 0); - if (err != Success) - return err; - - nClients = stuff->nClients; - pCanonClients = RecordCanonicalizeClientSpecifiers((XID *)&stuff[1], - &nClients, 0); - if (!pCanonClients) - return BadAlloc; - - for (i = 0; i < nClients; i++) - { - RecordDeleteClientFromContext(pContext, pCanonClients[i]); - } - if (pCanonClients != (XID *)&stuff[1]) - free(pCanonClients); - return Success; -} /* ProcRecordUnregisterClients */ - - -/****************************************************************************/ - -/* stuff for GetContext */ - -/* This is a tactical structure used to hold the xRecordRanges as they are - * being reconstituted from the sets in the RCAPs. - */ - -typedef struct { - xRecordRange *pRanges; /* array of xRecordRanges for one RCAP */ - int size; /* number of elements in pRanges, >= nRanges */ - int nRanges; /* number of occupied element of pRanges */ -} GetContextRangeInfoRec, *GetContextRangeInfoPtr; - - -/* RecordAllocRanges - * - * Arguments: - * pri is a pointer to a GetContextRangeInfoRec to allocate for. - * nRanges is the number of xRecordRanges desired for pri. - * - * Returns: BadAlloc if a memory allocation error occurred, else Success. - * - * Side Effects: - * If Success is returned, pri->pRanges points to at least nRanges - * ranges. pri->nRanges is set to nRanges. pri->size is the actual - * number of ranges. Newly allocated ranges are zeroed. - */ -static int -RecordAllocRanges(GetContextRangeInfoPtr pri, int nRanges) -{ - int newsize; - xRecordRange *pNewRange; -#define SZINCR 8 - - newsize = max(pri->size + SZINCR, nRanges); - pNewRange = (xRecordRange *)realloc(pri->pRanges, - newsize * sizeof(xRecordRange)); - if (!pNewRange) - return BadAlloc; - - pri->pRanges = pNewRange; - pri->size = newsize; - memset(&pri->pRanges[pri->size - SZINCR], 0, SZINCR * sizeof(xRecordRange)); - if (pri->nRanges < nRanges) - pri->nRanges = nRanges; - return Success; -} /* RecordAllocRanges */ - - -/* RecordConvertSetToRanges - * - * Arguments: - * pSet is the set to be converted. - * pri is where the result should be stored. - * byteoffset is the offset from the start of an xRecordRange of the - * two vales (first, last) we are interested in. - * card8 is TRUE if the vales are one byte each and FALSE if two bytes - * each. - * imax is the largest set value to store in pri->pRanges. - * pStartIndex, if non-NULL, is the index of the first range in - * pri->pRanges that should be stored to. If NULL, - * start at index 0. - * - * Returns: BadAlloc if a memory allocation error occurred, else Success. - * - * Side Effects: - * If Success is returned, the slice of pri->pRanges indicated by - * byteoffset and card8 is filled in with the intervals from pSet. - * if pStartIndex was non-NULL, *pStartIndex is filled in with one - * more than the index of the last xRecordRange that was touched. - */ -static int -RecordConvertSetToRanges( - RecordSetPtr pSet, - GetContextRangeInfoPtr pri, - int byteoffset, - Bool card8, - unsigned int imax, - int *pStartIndex -) -{ - int nRanges; - RecordSetIteratePtr pIter = NULL; - RecordSetInterval interval; - CARD8 *pCARD8; - CARD16 *pCARD16; - int err; - - if (!pSet) - return Success; - - nRanges = pStartIndex ? *pStartIndex : 0; - while ((pIter = RecordIterateSet(pSet, pIter, &interval))) - { - if (interval.first > imax) break; - if (interval.last > imax) interval.last = imax; - nRanges++; - if (nRanges > pri->size) - { - err = RecordAllocRanges(pri, nRanges); - if (err != Success) - return err; - } - else - pri->nRanges = max(pri->nRanges, nRanges); - if (card8) - { - pCARD8 = ((CARD8 *)&pri->pRanges[nRanges-1]) + byteoffset; - *pCARD8++ = interval.first; - *pCARD8 = interval.last; - } - else - { - pCARD16 = (CARD16 *) - (((char *)&pri->pRanges[nRanges-1]) + byteoffset); - *pCARD16++ = interval.first; - *pCARD16 = interval.last; - } - } - if (pStartIndex) - *pStartIndex = nRanges; - return Success; -} /* RecordConvertSetToRanges */ - - -/* RecordConvertMinorOpInfoToRanges - * - * Arguments: - * pMinOpInfo is the minor opcode info to convert to xRecordRanges. - * pri is where the result should be stored. - * byteoffset is the offset from the start of an xRecordRange of the - * four vales (CARD8 major_first, CARD8 major_last, - * CARD16 minor_first, CARD16 minor_last) we are going to store. - * - * Returns: BadAlloc if a memory allocation error occurred, else Success. - * - * Side Effects: - * If Success is returned, the slice of pri->pRanges indicated by - * byteoffset is filled in with the information from pMinOpInfo. - */ -static int -RecordConvertMinorOpInfoToRanges( - RecordMinorOpPtr pMinOpInfo, - GetContextRangeInfoPtr pri, - int byteoffset -) -{ - int nsets; - int start; - int i; - int err; - - if (!pMinOpInfo) - return Success; - - nsets = pMinOpInfo->count; - pMinOpInfo++; - start = 0; - for (i = 0; i < nsets; i++) - { - int j, s; - s = start; - err = RecordConvertSetToRanges(pMinOpInfo[i].major.pMinOpSet, pri, - byteoffset + 2, FALSE, 65535, &start); - if (err != Success) return err; - for (j = s; j < start; j++) - { - CARD8 *pCARD8 = ((CARD8 *)&pri->pRanges[j]) + byteoffset; - *pCARD8++ = pMinOpInfo[i].major.first; - *pCARD8 = pMinOpInfo[i].major.last; - } - } - return Success; -} /* RecordConvertMinorOpInfoToRanges */ - - -/* RecordSwapRanges - * - * Arguments: - * pRanges is an array of xRecordRanges. - * nRanges is the number of elements in pRanges. - * - * Returns: nothing. - * - * Side Effects: - * The 16 bit fields of each xRecordRange are byte swapped. - */ -static void -RecordSwapRanges(xRecordRange *pRanges, int nRanges) -{ - int i; - register char n; - for (i = 0; i < nRanges; i++, pRanges++) - { - swaps(&pRanges->extRequestsMinorFirst, n); - swaps(&pRanges->extRequestsMinorLast, n); - swaps(&pRanges->extRepliesMinorFirst, n); - swaps(&pRanges->extRepliesMinorLast, n); - } -} /* RecordSwapRanges */ - - -static int -ProcRecordGetContext(ClientPtr client) -{ - RecordContextPtr pContext; - REQUEST(xRecordGetContextReq); - xRecordGetContextReply rep; - int n; - RecordClientsAndProtocolPtr pRCAP; - int nRCAPs = 0; - GetContextRangeInfoPtr pRangeInfo; - GetContextRangeInfoPtr pri; - int i; - int err; - - REQUEST_SIZE_MATCH(xRecordGetContextReq); - VERIFY_CONTEXT(pContext, stuff->context, client); - - /* how many RCAPs are there on this context? */ - - for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) - nRCAPs++; - - /* allocate and initialize space for record range info */ - - pRangeInfo = (GetContextRangeInfoPtr)malloc( - nRCAPs * sizeof(GetContextRangeInfoRec)); - if (!pRangeInfo && nRCAPs > 0) - return BadAlloc; - for (i = 0; i < nRCAPs; i++) - { - pRangeInfo[i].pRanges = NULL; - pRangeInfo[i].size = 0; - pRangeInfo[i].nRanges = 0; - } - - /* convert the RCAP (internal) representation of the recorded protocol - * to the wire protocol (external) representation, storing the information - * for the ith RCAP in pri[i] - */ - - for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; - pRCAP; - pRCAP = pRCAP->pNextRCAP, pri++) - { - xRecordRange rr; - - err = RecordConvertSetToRanges(pRCAP->pRequestMajorOpSet, pri, - offset_of(rr, coreRequestsFirst), TRUE, 127, NULL); - if (err != Success) goto bailout; - - err = RecordConvertSetToRanges(pRCAP->pReplyMajorOpSet, pri, - offset_of(rr, coreRepliesFirst), TRUE, 127, NULL); - if (err != Success) goto bailout; - - err = RecordConvertSetToRanges(pRCAP->pDeliveredEventSet, pri, - offset_of(rr, deliveredEventsFirst), TRUE, 255, NULL); - if (err != Success) goto bailout; - - err = RecordConvertSetToRanges(pRCAP->pDeviceEventSet, pri, - offset_of(rr, deviceEventsFirst), TRUE, 255, NULL); - if (err != Success) goto bailout; - - err = RecordConvertSetToRanges(pRCAP->pErrorSet, pri, - offset_of(rr, errorsFirst), TRUE, 255, NULL); - if (err != Success) goto bailout; - - err = RecordConvertMinorOpInfoToRanges(pRCAP->pRequestMinOpInfo, - pri, offset_of(rr, extRequestsMajorFirst)); - if (err != Success) goto bailout; - - err = RecordConvertMinorOpInfoToRanges(pRCAP->pReplyMinOpInfo, - pri, offset_of(rr, extRepliesMajorFirst)); - if (err != Success) goto bailout; - - if (pRCAP->clientStarted || pRCAP->clientDied) - { - if (pri->nRanges == 0) - RecordAllocRanges(pri, 1); - pri->pRanges[0].clientStarted = pRCAP->clientStarted; - pri->pRanges[0].clientDied = pRCAP->clientDied; - } - } - - /* calculate number of clients and reply length */ - - rep.nClients = 0; - rep.length = 0; - for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; - pRCAP; - pRCAP = pRCAP->pNextRCAP, pri++) - { - rep.nClients += pRCAP->numClients; - rep.length += pRCAP->numClients * - ( bytes_to_int32(sizeof(xRecordClientInfo)) + - pri->nRanges * bytes_to_int32(sizeof(xRecordRange))); - } - - /* write the reply header */ - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.enabled = pContext->pRecordingClient != NULL; - rep.elementHeader = pContext->elemHeaders; - if(client->swapped) - { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.nClients, n); - } - (void)WriteToClient(client, sizeof(xRecordGetContextReply), - (char *)&rep); - - /* write all the CLIENT_INFOs */ - - for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; - pRCAP; - pRCAP = pRCAP->pNextRCAP, pri++) - { - xRecordClientInfo rci; - rci.nRanges = pri->nRanges; - if (client->swapped) - { - swapl(&rci.nRanges, n); - RecordSwapRanges(pri->pRanges, pri->nRanges); - } - for (i = 0; i < pRCAP->numClients; i++) - { - rci.clientResource = pRCAP->pClientIDs[i]; - if (client->swapped) swapl(&rci.clientResource, n); - WriteToClient(client, sizeof(xRecordClientInfo), (char *)&rci); - WriteToClient(client, sizeof(xRecordRange) * pri->nRanges, - (char *)pri->pRanges); - } - } - err = Success; - -bailout: - for (i = 0; i < nRCAPs; i++) - { - free(pRangeInfo[i].pRanges); - } - free(pRangeInfo); - return err; -} /* ProcRecordGetContext */ - - -static int -ProcRecordEnableContext(ClientPtr client) -{ - RecordContextPtr pContext; - REQUEST(xRecordEnableContextReq); - int i; - RecordClientsAndProtocolPtr pRCAP; - - REQUEST_SIZE_MATCH(xRecordGetContextReq); - VERIFY_CONTEXT(pContext, stuff->context, client); - if (pContext->pRecordingClient) - return BadMatch; /* already enabled */ - - /* install record hooks for each RCAP */ - - for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) - { - int err = RecordInstallHooks(pRCAP, 0); - if (err != Success) - { /* undo the previous installs */ - RecordClientsAndProtocolPtr pUninstallRCAP; - for (pUninstallRCAP = pContext->pListOfRCAP; - pUninstallRCAP != pRCAP; - pUninstallRCAP = pUninstallRCAP->pNextRCAP) - { - RecordUninstallHooks(pUninstallRCAP, 0); - } - return err; - } - } - - /* Disallow further request processing on this connection until - * the context is disabled. - */ - IgnoreClient(client); - pContext->pRecordingClient = client; - - /* Don't allow the data connection to record itself; unregister it. */ - RecordDeleteClientFromContext(pContext, - pContext->pRecordingClient->clientAsMask); - - /* move the newly enabled context to the front part of ppAllContexts, - * where all the enabled contexts are - */ - i = RecordFindContextOnAllContexts(pContext); - assert(i >= numEnabledContexts); - if (i != numEnabledContexts) - { - ppAllContexts[i] = ppAllContexts[numEnabledContexts]; - ppAllContexts[numEnabledContexts] = pContext; - } - - ++numEnabledContexts; - assert(numEnabledContexts > 0); - - /* send StartOfData */ - RecordAProtocolElement(pContext, NULL, XRecordStartOfData, NULL, 0, 0); - RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); - return Success; -} /* ProcRecordEnableContext */ - - -/* RecordDisableContext - * - * Arguments: - * pContext is the context to disable. - * nRanges is the number of elements in pRanges. - * - * Returns: nothing. - * - * Side Effects: - * If the context was enabled, it is disabled. An EndOfData - * message is sent to the recording client. Recording hooks for - * this context are uninstalled. The context is moved to the - * rear part of the ppAllContexts array. numEnabledContexts is - * decremented. Request processing for the formerly recording client - * is resumed. - */ -static void -RecordDisableContext(RecordContextPtr pContext) -{ - RecordClientsAndProtocolPtr pRCAP; - int i; - - if (!pContext->pRecordingClient) return; - if (!pContext->pRecordingClient->clientGone) - { - RecordAProtocolElement(pContext, NULL, XRecordEndOfData, NULL, 0, 0); - RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); - /* Re-enable request processing on this connection. */ - AttendClient(pContext->pRecordingClient); - } - - for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) - { - RecordUninstallHooks(pRCAP, 0); - } - - pContext->pRecordingClient = NULL; - - /* move the newly disabled context to the rear part of ppAllContexts, - * where all the disabled contexts are - */ - i = RecordFindContextOnAllContexts(pContext); - assert( (i != -1) && (i < numEnabledContexts) ); - if (i != (numEnabledContexts - 1) ) - { - ppAllContexts[i] = ppAllContexts[numEnabledContexts-1]; - ppAllContexts[numEnabledContexts-1] = pContext; - } - --numEnabledContexts; - assert(numEnabledContexts >= 0); -} /* RecordDisableContext */ - - -static int -ProcRecordDisableContext(ClientPtr client) -{ - RecordContextPtr pContext; - REQUEST(xRecordDisableContextReq); - - REQUEST_SIZE_MATCH(xRecordDisableContextReq); - VERIFY_CONTEXT(pContext, stuff->context, client); - RecordDisableContext(pContext); - return Success; -} /* ProcRecordDisableContext */ - - -/* RecordDeleteContext - * - * Arguments: - * value is the context to delete. - * id is its resource ID. - * - * Returns: Success. - * - * Side Effects: - * Disables the context, frees all associated memory, and removes - * it from the ppAllContexts array. - */ -static int -RecordDeleteContext(pointer value, XID id) -{ - int i; - RecordContextPtr pContext = (RecordContextPtr)value; - RecordClientsAndProtocolPtr pRCAP; - - RecordDisableContext(pContext); - - /* Remove all the clients from all the RCAPs. - * As a result, the RCAPs will be freed. - */ - - while ((pRCAP = pContext->pListOfRCAP)) - { - int numClients = pRCAP->numClients; - /* when the last client is deleted, the RCAP will go away. */ - while(numClients--) - { - RecordDeleteClientFromRCAP(pRCAP, numClients); - } - } - - /* remove context from AllContexts list */ - - if (-1 != (i = RecordFindContextOnAllContexts(pContext))) - { - ppAllContexts[i] = ppAllContexts[numContexts - 1]; - if (--numContexts == 0) - { - free(ppAllContexts); - ppAllContexts = NULL; - } - } - free(pContext); - - return Success; -} /* RecordDeleteContext */ - - -static int -ProcRecordFreeContext(ClientPtr client) -{ - RecordContextPtr pContext; - REQUEST(xRecordFreeContextReq); - - REQUEST_SIZE_MATCH(xRecordFreeContextReq); - VERIFY_CONTEXT(pContext, stuff->context, client); - FreeResource(stuff->context, RT_NONE); - return Success; -} /* ProcRecordFreeContext */ - - -static int -ProcRecordDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_RecordQueryVersion: - return ProcRecordQueryVersion(client); - case X_RecordCreateContext: - return ProcRecordCreateContext(client); - case X_RecordRegisterClients: - return ProcRecordRegisterClients(client); - case X_RecordUnregisterClients: - return ProcRecordUnregisterClients(client); - case X_RecordGetContext: - return ProcRecordGetContext(client); - case X_RecordEnableContext: - return ProcRecordEnableContext(client); - case X_RecordDisableContext: - return ProcRecordDisableContext(client); - case X_RecordFreeContext: - return ProcRecordFreeContext(client); - default: - return BadRequest; - } -} /* ProcRecordDispatch */ - - -static int -SProcRecordQueryVersion(ClientPtr client) -{ - REQUEST(xRecordQueryVersionReq); - register char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xRecordQueryVersionReq); - swaps(&stuff->majorVersion, n); - swaps(&stuff->minorVersion,n); - return ProcRecordQueryVersion(client); -} /* SProcRecordQueryVersion */ - - -static int -SwapCreateRegister(xRecordRegisterClientsReq *stuff) -{ - register char n; - int i; - XID *pClientID; - - swapl(&stuff->context, n); - swapl(&stuff->nClients, n); - swapl(&stuff->nRanges, n); - pClientID = (XID *)&stuff[1]; - if (stuff->nClients > stuff->length - bytes_to_int32(sz_xRecordRegisterClientsReq)) - return BadLength; - for (i = 0; i < stuff->nClients; i++, pClientID++) - { - swapl(pClientID, n); - } - if (stuff->nRanges > stuff->length - bytes_to_int32(sz_xRecordRegisterClientsReq) - - stuff->nClients) - return BadLength; - RecordSwapRanges((xRecordRange *)pClientID, stuff->nRanges); - return Success; -} /* SwapCreateRegister */ - - -static int -SProcRecordCreateContext(ClientPtr client) -{ - REQUEST(xRecordCreateContextReq); - int status; - register char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq); - if ((status = SwapCreateRegister((pointer)stuff)) != Success) - return status; - return ProcRecordCreateContext(client); -} /* SProcRecordCreateContext */ - - -static int -SProcRecordRegisterClients(ClientPtr client) -{ - REQUEST(xRecordRegisterClientsReq); - int status; - register char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq); - if ((status = SwapCreateRegister((pointer)stuff)) != Success) - return status; - return ProcRecordRegisterClients(client); -} /* SProcRecordRegisterClients */ - - -static int -SProcRecordUnregisterClients(ClientPtr client) -{ - REQUEST(xRecordUnregisterClientsReq); - register char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq); - swapl(&stuff->context, n); - swapl(&stuff->nClients, n); - SwapRestL(stuff); - return ProcRecordUnregisterClients(client); -} /* SProcRecordUnregisterClients */ - - -static int -SProcRecordGetContext(ClientPtr client) -{ - REQUEST(xRecordGetContextReq); - register char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xRecordGetContextReq); - swapl(&stuff->context, n); - return ProcRecordGetContext(client); -} /* SProcRecordGetContext */ - -static int -SProcRecordEnableContext(ClientPtr client) -{ - REQUEST(xRecordEnableContextReq); - register char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xRecordEnableContextReq); - swapl(&stuff->context, n); - return ProcRecordEnableContext(client); -} /* SProcRecordEnableContext */ - - -static int -SProcRecordDisableContext(ClientPtr client) -{ - REQUEST(xRecordDisableContextReq); - register char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xRecordDisableContextReq); - swapl(&stuff->context, n); - return ProcRecordDisableContext(client); -} /* SProcRecordDisableContext */ - - -static int -SProcRecordFreeContext(ClientPtr client) -{ - REQUEST(xRecordFreeContextReq); - register char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xRecordFreeContextReq); - swapl(&stuff->context, n); - return ProcRecordFreeContext(client); -} /* SProcRecordFreeContext */ - - -static int -SProcRecordDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_RecordQueryVersion: - return SProcRecordQueryVersion(client); - case X_RecordCreateContext: - return SProcRecordCreateContext(client); - case X_RecordRegisterClients: - return SProcRecordRegisterClients(client); - case X_RecordUnregisterClients: - return SProcRecordUnregisterClients(client); - case X_RecordGetContext: - return SProcRecordGetContext(client); - case X_RecordEnableContext: - return SProcRecordEnableContext(client); - case X_RecordDisableContext: - return SProcRecordDisableContext(client); - case X_RecordFreeContext: - return SProcRecordFreeContext(client); - default: - return BadRequest; - } -} /* SProcRecordDispatch */ - -/* RecordConnectionSetupInfo - * - * Arguments: - * pContext is an enabled context that specifies recording of - * connection setup info. - * pci holds the connection setup info. - * - * Returns: nothing. - * - * Side Effects: - * The connection setup info is sent to the recording client. - */ -static void -RecordConnectionSetupInfo(RecordContextPtr pContext, NewClientInfoRec *pci) -{ - int prefixsize = SIZEOF(xConnSetupPrefix); - int restsize = pci->prefix->length * 4; - - if (pci->client->swapped) - { - char *pConnSetup = (char *)malloc(prefixsize + restsize); - if (!pConnSetup) - return; - SwapConnSetupPrefix(pci->prefix, (xConnSetupPrefix*)pConnSetup); - SwapConnSetupInfo((char*)pci->setup, (char*)(pConnSetup + prefixsize)); - RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, - (pointer)pConnSetup, prefixsize + restsize, 0); - free(pConnSetup); - } - else - { - /* don't alloc and copy as in the swapped case; just send the - * data in two pieces - */ - RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, - (pointer)pci->prefix, prefixsize, restsize); - RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, - (pointer)pci->setup, restsize, /* continuation */ -1); - } -} /* RecordConnectionSetupInfo */ - - -/* RecordDeleteContext - * - * Arguments: - * pcbl is &ClientStateCallback. - * nullata is NULL. - * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) - * which contains information about client state changes. - * - * Returns: nothing. - * - * Side Effects: - * If a new client has connected and any contexts have specified - * XRecordFutureClients, the new client is registered on those contexts. - * If any of those contexts specify recording of the connection setup - * info, it is recorded. - * - * If an existing client has disconnected, it is deleted from any - * contexts that it was registered on. If any of those contexts - * specified XRecordClientDied, they record a ClientDied protocol element. - * If the disconnectiong client happened to be the data connection of an - * enabled context, the context is disabled. - */ - -static void -RecordAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) -{ - NewClientInfoRec *pci = (NewClientInfoRec *)calldata; - int i; - ClientPtr pClient = pci->client; - RecordContextPtr *ppAllContextsCopy = NULL; - int numContextsCopy = 0; - - switch (pClient->clientState) - { - case ClientStateRunning: /* new client */ - for (i = 0; i < numContexts; i++) - { - RecordClientsAndProtocolPtr pRCAP; - RecordContextPtr pContext = ppAllContexts[i]; - - if ((pRCAP = RecordFindClientOnContext(pContext, - XRecordFutureClients, NULL))) - { - RecordAddClientToRCAP(pRCAP, pClient->clientAsMask); - if (pContext->pRecordingClient && pRCAP->clientStarted) - RecordConnectionSetupInfo(pContext, pci); - } - } - break; - - case ClientStateGone: - case ClientStateRetained: /* client disconnected */ - - /* RecordDisableContext modifies contents of ppAllContexts. */ - numContextsCopy = numContexts; - ppAllContextsCopy = malloc(numContextsCopy * sizeof(RecordContextPtr)); - assert(ppAllContextsCopy); - memcpy(ppAllContextsCopy, ppAllContexts, numContextsCopy * sizeof(RecordContextPtr)); - - for (i = 0; i < numContextsCopy; i++) - { - RecordClientsAndProtocolPtr pRCAP; - RecordContextPtr pContext = ppAllContextsCopy[i]; - int pos; - - if (pContext->pRecordingClient == pClient) - RecordDisableContext(pContext); - if ((pRCAP = RecordFindClientOnContext(pContext, - pClient->clientAsMask, &pos))) - { - if (pContext->pRecordingClient && pRCAP->clientDied) - RecordAProtocolElement(pContext, pClient, - XRecordClientDied, NULL, 0, 0); - RecordDeleteClientFromRCAP(pRCAP, pos); - } - } - - free(ppAllContextsCopy); - break; - - default: - break; - } /* end switch on client state */ -} /* RecordAClientStateChange */ - - -/* RecordCloseDown - * - * Arguments: - * extEntry is the extension information for RECORD. - * - * Returns: nothing. - * - * Side Effects: - * Performs any cleanup needed by RECORD at server shutdown time. - * - */ -static void -RecordCloseDown(ExtensionEntry *extEntry) -{ - DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL); -} /* RecordCloseDown */ - - -/* RecordExtensionInit - * - * Arguments: none. - * - * Returns: nothing. - * - * Side Effects: - * Enables the RECORD extension if possible. - */ -void -RecordExtensionInit(void) -{ - ExtensionEntry *extentry; - - RTContext = CreateNewResourceType(RecordDeleteContext, "RecordContext"); - if (!RTContext) - return; - - if (!dixRegisterPrivateKey(RecordClientPrivateKey, PRIVATE_CLIENT, 0)) - return; - - ppAllContexts = NULL; - numContexts = numEnabledContexts = numEnabledRCAPs = 0; - - if (!AddCallback(&ClientStateCallback, RecordAClientStateChange, NULL)) - return; - - extentry = AddExtension(RECORD_NAME, RecordNumEvents, RecordNumErrors, - ProcRecordDispatch, SProcRecordDispatch, - RecordCloseDown, StandardMinorOpcode); - if (!extentry) - { - DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL); - return; - } - SetResourceTypeErrorValue(RTContext, extentry->errorBase + XRecordBadContext); - -} /* RecordExtensionInit */ - + +/* + +Copyright 1995, 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. + +Author: David P. Wiggins, The Open Group + +This work benefited from earlier work done by Martha Zimet of NCD +and Jim Haggerty of Metheus. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "dixstruct.h" +#include "extnsionst.h" +#include +#include "set.h" +#include "swaprep.h" +#include "inputstr.h" +#include "eventconvert.h" +#include "scrnintstr.h" + + +#include +#include + +#ifdef PANORAMIX +#include "globals.h" +#include "panoramiX.h" +#include "panoramiXsrv.h" +#include "cursor.h" +#endif + +#include "protocol-versions.h" + +static RESTYPE RTContext; /* internal resource type for Record contexts */ + +/* How many bytes of protocol data to buffer in a context. Don't set to less + * than 32. + */ +#define REPLY_BUF_SIZE 1024 + +/* Record Context structure */ + +typedef struct { + XID id; /* resource id of context */ + ClientPtr pRecordingClient; /* client that has context enabled */ + struct _RecordClientsAndProtocolRec *pListOfRCAP; /* all registered info */ + ClientPtr pBufClient; /* client whose protocol is in replyBuffer*/ + unsigned int continuedReply:1; /* recording a reply that is split up? */ + char elemHeaders; /* element header flags (time/seq no.) */ + char bufCategory; /* category of protocol in replyBuffer */ + int numBufBytes; /* number of bytes in replyBuffer */ + char replyBuffer[REPLY_BUF_SIZE]; /* buffered recorded protocol */ + int inFlush; /* are we inside RecordFlushReplyBuffer */ +} RecordContextRec, *RecordContextPtr; + +/* RecordMinorOpRec - to hold minor opcode selections for extension requests + * and replies + */ + +typedef union { + int count; /* first element of array: how many "major" structs to follow */ + struct { /* rest of array elements are this */ + short first; /* first major opcode */ + short last; /* last major opcode */ + RecordSetPtr pMinOpSet; /* minor opcode set for above major range */ + } major; +} RecordMinorOpRec, *RecordMinorOpPtr; + + +/* RecordClientsAndProtocolRec, nicknamed RCAP - holds all the client and + * protocol selections passed in a single CreateContext or RegisterClients. + * Generally, a context will have one of these from the create and an + * additional one for each RegisterClients. RCAPs are freed when all their + * clients are unregistered. + */ + +typedef struct _RecordClientsAndProtocolRec { + RecordContextPtr pContext; /* context that owns this RCAP */ + struct _RecordClientsAndProtocolRec *pNextRCAP; /* next RCAP on context */ + RecordSetPtr pRequestMajorOpSet; /* requests to record */ + RecordMinorOpPtr pRequestMinOpInfo; /* extension requests to record */ + RecordSetPtr pReplyMajorOpSet; /* replies to record */ + RecordMinorOpPtr pReplyMinOpInfo; /* extension replies to record */ + RecordSetPtr pDeviceEventSet; /* device events to record */ + RecordSetPtr pDeliveredEventSet; /* delivered events to record */ + RecordSetPtr pErrorSet; /* errors to record */ + XID * pClientIDs; /* array of clients to record */ + short numClients; /* number of clients in pClientIDs */ + short sizeClients; /* size of pClientIDs array */ + unsigned int clientStarted:1; /* record new client connections? */ + unsigned int clientDied:1; /* record client disconnections? */ + unsigned int clientIDsSeparatelyAllocated:1; /* pClientIDs malloced? */ +} RecordClientsAndProtocolRec, *RecordClientsAndProtocolPtr; + +/* how much bigger to make pRCAP->pClientIDs when reallocing */ +#define CLIENT_ARRAY_GROWTH_INCREMENT 4 + +/* counts the total number of RCAPs belonging to enabled contexts. */ +static int numEnabledRCAPs; + +/* void VERIFY_CONTEXT(RecordContextPtr, XID, ClientPtr) + * In the spirit of the VERIFY_* macros in dix.h, this macro fills in + * the context pointer if the given ID is a valid Record Context, else it + * returns an error. + */ +#define VERIFY_CONTEXT(_pContext, _contextid, _client) { \ + int rc = dixLookupResourceByType((pointer *)&(_pContext), _contextid, \ + RTContext, _client, DixUseAccess); \ + if (rc != Success) \ + return rc; \ +} + +static int RecordDeleteContext( + pointer /*value*/, + XID /*id*/ +); + +void RecordExtensionInit(void); + +/***************************************************************************/ + +/* client private stuff */ + +/* To make declarations less obfuscated, have a typedef for a pointer to a + * Proc function. + */ +typedef int (*ProcFunctionPtr)( + ClientPtr /*pClient*/ +); + +/* Record client private. Generally a client only has one of these if + * any of its requests are being recorded. + */ +typedef struct { +/* ptr to client's proc vector before Record stuck its nose in */ + ProcFunctionPtr *originalVector; + +/* proc vector with pointers for recorded requests redirected to the + * function RecordARequest + */ + ProcFunctionPtr recordVector[256]; +} RecordClientPrivateRec, *RecordClientPrivatePtr; + +static DevPrivateKeyRec RecordClientPrivateKeyRec; +#define RecordClientPrivateKey (&RecordClientPrivateKeyRec) + +/* RecordClientPrivatePtr RecordClientPrivate(ClientPtr) + * gets the client private of the given client. Syntactic sugar. + */ +#define RecordClientPrivate(_pClient) (RecordClientPrivatePtr) \ + dixLookupPrivate(&(_pClient)->devPrivates, RecordClientPrivateKey) + + +/***************************************************************************/ + +/* global list of all contexts */ + +static RecordContextPtr *ppAllContexts; + +static int numContexts;/* number of contexts in ppAllContexts */ + +/* number of currently enabled contexts. All enabled contexts are bunched + * up at the front of the ppAllContexts array, from ppAllContexts[0] to + * ppAllContexts[numEnabledContexts-1], to eliminate time spent skipping + * past disabled contexts. + */ +static int numEnabledContexts; + +/* RecordFindContextOnAllContexts + * + * Arguments: + * pContext is the context to search for. + * + * Returns: + * The index into the array ppAllContexts at which pContext is stored. + * If pContext is not found in ppAllContexts, returns -1. + * + * Side Effects: none. + */ +static int +RecordFindContextOnAllContexts(RecordContextPtr pContext) +{ + int i; + + assert(numContexts >= numEnabledContexts); + for (i = 0; i < numContexts; i++) + { + if (ppAllContexts[i] == pContext) + return i; + } + return -1; +} /* RecordFindContextOnAllContexts */ + + +/***************************************************************************/ + +/* RecordFlushReplyBuffer + * + * Arguments: + * pContext is the context to flush. + * data1 is a pointer to additional data, and len1 is its length in bytes. + * data2 is a pointer to additional data, and len2 is its length in bytes. + * + * Returns: nothing. + * + * Side Effects: + * If the context is enabled, any buffered (recorded) protocol is written + * to the recording client, and the number of buffered bytes is set to + * zero. If len1 is not zero, data1/len1 are then written to the + * recording client, and similarly for data2/len2 (written after + * data1/len1). + */ +static void +RecordFlushReplyBuffer( + RecordContextPtr pContext, + pointer data1, + int len1, + pointer data2, + int len2 +) +{ + if (!pContext->pRecordingClient || pContext->pRecordingClient->clientGone || pContext->inFlush) + return; + ++pContext->inFlush; + if (pContext->numBufBytes) + WriteToClient(pContext->pRecordingClient, pContext->numBufBytes, + (char *)pContext->replyBuffer); + pContext->numBufBytes = 0; + if (len1) + WriteToClient(pContext->pRecordingClient, len1, (char *)data1); + if (len2) + WriteToClient(pContext->pRecordingClient, len2, (char *)data2); + --pContext->inFlush; +} /* RecordFlushReplyBuffer */ + + +/* RecordAProtocolElement + * + * Arguments: + * pContext is the context that is recording a protocol element. + * pClient is the client whose protocol is being recorded. For + * device events and EndOfData, pClient is NULL. + * category is the category of the protocol element, as defined + * by the RECORD spec. + * data is a pointer to the protocol data, and datalen is its length + * in bytes. + * futurelen is the number of bytes that will be sent in subsequent + * calls to this function to complete this protocol element. + * In those subsequent calls, futurelen will be -1 to indicate + * that the current data is a continuation of the same protocol + * element. + * + * Returns: nothing. + * + * Side Effects: + * The context may be flushed. The new protocol element will be + * added to the context's protocol buffer with appropriate element + * headers prepended (sequence number and timestamp). If the data + * is continuation data (futurelen == -1), element headers won't + * be added. If the protocol element and headers won't fit in + * the context's buffer, it is sent directly to the recording + * client (after any buffered data). + */ +static void +RecordAProtocolElement(RecordContextPtr pContext, ClientPtr pClient, + int category, pointer data, int datalen, int futurelen) +{ + CARD32 elemHeaderData[2]; + int numElemHeaders = 0; + Bool recordingClientSwapped = pContext->pRecordingClient->swapped; + int n; + CARD32 serverTime = 0; + Bool gotServerTime = FALSE; + int replylen; + + if (futurelen >= 0) + { /* start of new protocol element */ + xRecordEnableContextReply *pRep = (xRecordEnableContextReply *) + pContext->replyBuffer; + if (pContext->pBufClient != pClient || + pContext->bufCategory != category) + { + RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); + pContext->pBufClient = pClient; + pContext->bufCategory = category; + } + + if (!pContext->numBufBytes) + { + serverTime = GetTimeInMillis(); + gotServerTime = TRUE; + pRep->type = X_Reply; + pRep->category = category; + pRep->sequenceNumber = pContext->pRecordingClient->sequence; + pRep->length = 0; + pRep->elementHeader = pContext->elemHeaders; + pRep->serverTime = serverTime; + if (pClient) + { + pRep->clientSwapped = + (pClient->swapped != recordingClientSwapped); + pRep->idBase = pClient->clientAsMask; + pRep->recordedSequenceNumber = pClient->sequence; + } + else /* it's a device event, StartOfData, or EndOfData */ + { + pRep->clientSwapped = (category != XRecordFromServer) && + recordingClientSwapped; + pRep->idBase = 0; + pRep->recordedSequenceNumber = 0; + } + + if (recordingClientSwapped) + { + swaps(&pRep->sequenceNumber, n); + swapl(&pRep->length, n); + swapl(&pRep->idBase, n); + swapl(&pRep->serverTime, n); + swapl(&pRep->recordedSequenceNumber, n); + } + pContext->numBufBytes = SIZEOF(xRecordEnableContextReply); + } + + /* generate element headers if needed */ + + if ( ( (pContext->elemHeaders & XRecordFromClientTime) + && category == XRecordFromClient) + || + ( (pContext->elemHeaders & XRecordFromServerTime) + && category == XRecordFromServer)) + { + if (gotServerTime) + elemHeaderData[numElemHeaders] = serverTime; + else + elemHeaderData[numElemHeaders] = GetTimeInMillis(); + if (recordingClientSwapped) + swapl(&elemHeaderData[numElemHeaders], n); + numElemHeaders++; + } + + if ( (pContext->elemHeaders & XRecordFromClientSequence) + && + (category == XRecordFromClient || category == XRecordClientDied)) + { + elemHeaderData[numElemHeaders] = pClient->sequence; + if (recordingClientSwapped) + swapl(&elemHeaderData[numElemHeaders], n); + numElemHeaders++; + } + + /* adjust reply length */ + + replylen = pRep->length; + if (recordingClientSwapped) swapl(&replylen, n); + replylen += numElemHeaders + bytes_to_int32(datalen) + + bytes_to_int32(futurelen); + if (recordingClientSwapped) swapl(&replylen, n); + pRep->length = replylen; + } /* end if not continued reply */ + + numElemHeaders *= 4; + + /* if space available >= space needed, buffer the data */ + + if (REPLY_BUF_SIZE - pContext->numBufBytes >= datalen + numElemHeaders) + { + if (numElemHeaders) + { + memcpy(pContext->replyBuffer + pContext->numBufBytes, + elemHeaderData, numElemHeaders); + pContext->numBufBytes += numElemHeaders; + } + if (datalen) + { + memcpy(pContext->replyBuffer + pContext->numBufBytes, + data, datalen); + pContext->numBufBytes += datalen; + } + } + else + RecordFlushReplyBuffer(pContext, (pointer)elemHeaderData, + numElemHeaders, (pointer)data, datalen); + +} /* RecordAProtocolElement */ + + +/* RecordFindClientOnContext + * + * Arguments: + * pContext is the context to search. + * clientspec is the resource ID mask identifying the client to search + * for, or XRecordFutureClients. + * pposition is a pointer to an int, or NULL. See Returns. + * + * Returns: + * The RCAP on which clientspec was found, or NULL if not found on + * any RCAP on the given context. + * If pposition was not NULL and the returned RCAP is not NULL, + * *pposition will be set to the index into the returned the RCAP's + * pClientIDs array that holds clientspec. + * + * Side Effects: none. + */ +static RecordClientsAndProtocolPtr +RecordFindClientOnContext( + RecordContextPtr pContext, + XID clientspec, + int *pposition +) +{ + RecordClientsAndProtocolPtr pRCAP; + + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + { + int i; + for (i = 0; i < pRCAP->numClients; i++) + { + if (pRCAP->pClientIDs[i] == clientspec) + { + if (pposition) + *pposition = i; + return pRCAP; + } + } + } + return NULL; +} /* RecordFindClientOnContext */ + + +/* RecordABigRequest + * + * Arguments: + * pContext is the recording context. + * client is the client being recorded. + * stuff is a pointer to the big request of client (see the Big Requests + * extension for details.) + * + * Returns: nothing. + * + * Side Effects: + * The big request is recorded with the correct length field re-inserted. + * + * Note: this function exists mainly to make RecordARequest smaller. + */ +static void +RecordABigRequest(RecordContextPtr pContext, ClientPtr client, xReq *stuff) +{ + CARD32 bigLength; + char n; + int bytesLeft; + + /* note: client->req_len has been frobbed by ReadRequestFromClient + * (os/io.c) to discount the extra 4 bytes taken by the extended length + * field in a big request. The actual request length to record is + * client->req_len + 1 (measured in CARD32s). + */ + + /* record the request header */ + bytesLeft = client->req_len << 2; + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)stuff, SIZEOF(xReq), bytesLeft); + + /* reinsert the extended length field that was squished out */ + bigLength = client->req_len + bytes_to_int32(sizeof(bigLength)); + if (client->swapped) + swapl(&bigLength, n); + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)&bigLength, sizeof(bigLength), /* continuation */ -1); + bytesLeft -= sizeof(bigLength); + + /* record the rest of the request after the length */ + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)(stuff + 1), bytesLeft, /* continuation */ -1); +} /* RecordABigRequest */ + + +/* RecordARequest + * + * Arguments: + * client is a client that the server has dispatched a request to by + * calling client->requestVector[request opcode] . + * The request is in client->requestBuffer. + * + * Returns: + * Whatever is returned by the "real" Proc function for this request. + * The "real" Proc function is the function that was in + * client->requestVector[request opcode] before it was replaced by + * RecordARequest. (See the function RecordInstallHooks.) + * + * Side Effects: + * The request is recorded by all contexts that have registered this + * request for this client. The real Proc function is called. + */ +static int +RecordARequest(ClientPtr client) +{ + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + int i; + RecordClientPrivatePtr pClientPriv; + REQUEST(xReq); + int majorop; + + majorop = stuff->reqType; + for (i = 0; i < numEnabledContexts; i++) + { + pContext = ppAllContexts[i]; + pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, + NULL); + if (pRCAP && pRCAP->pRequestMajorOpSet && + RecordIsMemberOfSet(pRCAP->pRequestMajorOpSet, majorop)) + { + if (majorop <= 127) + { /* core request */ + + if (stuff->length == 0) + RecordABigRequest(pContext, client, stuff); + else + RecordAProtocolElement(pContext, client, XRecordFromClient, + (pointer)stuff, client->req_len << 2, 0); + } + else /* extension, check minor opcode */ + { + int minorop = MinorOpcodeOfRequest(client); + int numMinOpInfo; + RecordMinorOpPtr pMinorOpInfo = pRCAP->pRequestMinOpInfo; + + assert (pMinorOpInfo); + numMinOpInfo = pMinorOpInfo->count; + pMinorOpInfo++; + assert (numMinOpInfo); + for ( ; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) + { + if (majorop >= pMinorOpInfo->major.first && + majorop <= pMinorOpInfo->major.last && + RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet, + minorop)) + { + if (stuff->length == 0) + RecordABigRequest(pContext, client, stuff); + else + RecordAProtocolElement(pContext, client, + XRecordFromClient, (pointer)stuff, + client->req_len << 2, 0); + break; + } + } /* end for each minor op info */ + } /* end extension request */ + } /* end this RCAP wants this major opcode */ + } /* end for each context */ + pClientPriv = RecordClientPrivate(client); + assert(pClientPriv); + return (* pClientPriv->originalVector[majorop])(client); +} /* RecordARequest */ + +/* RecordAReply + * + * Arguments: + * pcbl is &ReplyCallback. + * nulldata is NULL. + * calldata is a pointer to a ReplyInfoRec (include/os.h) + * which provides information about replies that are being sent + * to clients. + * + * Returns: nothing. + * + * Side Effects: + * The reply is recorded by all contexts that have registered this + * reply type for this client. If more data belonging to the same + * reply is expected, and if the reply is being recorded by any + * context, pContext->continuedReply is set to 1. + * If pContext->continuedReply was already 1 and this is the last + * chunk of data belonging to this reply, it is set to 0. + */ +static void +RecordAReply(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) +{ + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + int eci; + int majorop; + ReplyInfoRec *pri = (ReplyInfoRec *)calldata; + ClientPtr client = pri->client; + REQUEST(xReq); + + majorop = stuff->reqType; + for (eci = 0; eci < numEnabledContexts; eci++) + { + pContext = ppAllContexts[eci]; + pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, + NULL); + if (pRCAP) + { + if (pContext->continuedReply) + { + RecordAProtocolElement(pContext, client, XRecordFromServer, + (pointer)pri->replyData, pri->dataLenBytes, /* continuation */ -1); + if (!pri->bytesRemaining) + pContext->continuedReply = 0; + } + else if (pri->startOfReply && pRCAP->pReplyMajorOpSet && + RecordIsMemberOfSet(pRCAP->pReplyMajorOpSet, majorop)) + { + if (majorop <= 127) + { /* core reply */ + RecordAProtocolElement(pContext, client, XRecordFromServer, + (pointer)pri->replyData, pri->dataLenBytes, pri->bytesRemaining); + if (pri->bytesRemaining) + pContext->continuedReply = 1; + } + else /* extension, check minor opcode */ + { + int minorop = MinorOpcodeOfRequest(client); + int numMinOpInfo; + RecordMinorOpPtr pMinorOpInfo = pRCAP->pReplyMinOpInfo; + assert (pMinorOpInfo); + numMinOpInfo = pMinorOpInfo->count; + pMinorOpInfo++; + assert (numMinOpInfo); + for ( ; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) + { + if (majorop >= pMinorOpInfo->major.first && + majorop <= pMinorOpInfo->major.last && + RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet, + minorop)) + { + RecordAProtocolElement(pContext, client, + XRecordFromServer, (pointer)pri->replyData, + pri->dataLenBytes, pri->bytesRemaining); + if (pri->bytesRemaining) + pContext->continuedReply = 1; + break; + } + } /* end for each minor op info */ + } /* end extension reply */ + } /* end continued reply vs. start of reply */ + } /* end client is registered on this context */ + } /* end for each context */ +} /* RecordAReply */ + + +/* RecordADeliveredEventOrError + * + * Arguments: + * pcbl is &EventCallback. + * nulldata is NULL. + * calldata is a pointer to a EventInfoRec (include/dix.h) + * which provides information about events that are being sent + * to clients. + * + * Returns: nothing. + * + * Side Effects: + * The event or error is recorded by all contexts that have registered + * it for this client. + */ +static void +RecordADeliveredEventOrError(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) +{ + EventInfoRec *pei = (EventInfoRec *)calldata; + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + int eci; /* enabled context index */ + ClientPtr pClient = pei->client; + + for (eci = 0; eci < numEnabledContexts; eci++) + { + pContext = ppAllContexts[eci]; + pRCAP = RecordFindClientOnContext(pContext, pClient->clientAsMask, + NULL); + if (pRCAP && (pRCAP->pDeliveredEventSet || pRCAP->pErrorSet)) + { + int ev; /* event index */ + xEvent *pev = pei->events; + for (ev = 0; ev < pei->count; ev++, pev++) + { + int recordit = 0; + if (pRCAP->pErrorSet) + { + recordit = RecordIsMemberOfSet(pRCAP->pErrorSet, + ((xError *)(pev))->errorCode); + } + else if (pRCAP->pDeliveredEventSet) + { + recordit = RecordIsMemberOfSet(pRCAP->pDeliveredEventSet, + pev->u.u.type & 0177); + } + if (recordit) + { + xEvent swappedEvent; + xEvent *pEvToRecord = pev; + + if (pClient->swapped) + { + (*EventSwapVector[pev->u.u.type & 0177]) + (pev, &swappedEvent); + pEvToRecord = &swappedEvent; + + } + RecordAProtocolElement(pContext, pClient, + XRecordFromServer, pEvToRecord, SIZEOF(xEvent), 0); + } + } /* end for each event */ + } /* end this client is on this context */ + } /* end for each enabled context */ +} /* RecordADeliveredEventOrError */ + + +static void +RecordSendProtocolEvents(RecordClientsAndProtocolPtr pRCAP, + RecordContextPtr pContext, + xEvent* pev, int count) +{ + int ev; /* event index */ + + for (ev = 0; ev < count; ev++, pev++) + { + if (RecordIsMemberOfSet(pRCAP->pDeviceEventSet, + pev->u.u.type & 0177)) + { + xEvent swappedEvent; + xEvent *pEvToRecord = pev; +#ifdef PANORAMIX + xEvent shiftedEvent; + + if (!noPanoramiXExtension && + (pev->u.u.type == MotionNotify || + pev->u.u.type == ButtonPress || + pev->u.u.type == ButtonRelease || + pev->u.u.type == KeyPress || + pev->u.u.type == KeyRelease)) { + int scr = XineramaGetCursorScreen(inputInfo.pointer); + memcpy(&shiftedEvent, pev, sizeof(xEvent)); + shiftedEvent.u.keyButtonPointer.rootX += + screenInfo.screens[scr]->x - + screenInfo.screens[0]->x; + shiftedEvent.u.keyButtonPointer.rootY += + screenInfo.screens[scr]->y - + screenInfo.screens[0]->y; + pEvToRecord = &shiftedEvent; + } +#endif /* PANORAMIX */ + + if (pContext->pRecordingClient->swapped) + { + (*EventSwapVector[pEvToRecord->u.u.type & 0177]) + (pEvToRecord, &swappedEvent); + pEvToRecord = &swappedEvent; + } + + RecordAProtocolElement(pContext, NULL, + XRecordFromServer, pEvToRecord, SIZEOF(xEvent), 0); + /* make sure device events get flushed in the absence + * of other client activity + */ + SetCriticalOutputPending(); + } + } /* end for each event */ + +} /* RecordADeviceEvent */ + +/* RecordADeviceEvent + * + * Arguments: + * pcbl is &DeviceEventCallback. + * nulldata is NULL. + * calldata is a pointer to a DeviceEventInfoRec (include/dix.h) + * which provides information about device events that occur. + * + * Returns: nothing. + * + * Side Effects: + * The device event is recorded by all contexts that have registered + * it for this client. + */ +static void +RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) +{ + DeviceEventInfoRec *pei = (DeviceEventInfoRec *)calldata; + RecordContextPtr pContext; + RecordClientsAndProtocolPtr pRCAP; + int eci; /* enabled context index */ + + for (eci = 0; eci < numEnabledContexts; eci++) + { + pContext = ppAllContexts[eci]; + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + { + if (pRCAP->pDeviceEventSet) + { + int count; + xEvent *xi_events = NULL; + + /* TODO check return values */ + if (IsMaster(pei->device)) + { + xEvent *core_events; + EventToCore(pei->event, &core_events, &count); + RecordSendProtocolEvents(pRCAP, pContext, core_events, + count); + free(core_events); + } + + EventToXI(pei->event, &xi_events, &count); + RecordSendProtocolEvents(pRCAP, pContext, xi_events, count); + free(xi_events); + } /* end this RCAP selects device events */ + } /* end for each RCAP on this context */ + } /* end for each enabled context */ +} + + +/* RecordFlushAllContexts + * + * Arguments: + * pcbl is &FlushCallback. + * nulldata and calldata are NULL. + * + * Returns: nothing. + * + * Side Effects: + * All buffered reply data of all enabled contexts is written to + * the recording clients. + */ +static void +RecordFlushAllContexts( + CallbackListPtr *pcbl, + pointer nulldata, + pointer calldata +) +{ + int eci; /* enabled context index */ + RecordContextPtr pContext; + + for (eci = 0; eci < numEnabledContexts; eci++) + { + pContext = ppAllContexts[eci]; + + /* In most cases we leave it to RecordFlushReplyBuffer to make + * this check, but this function could be called very often, so we + * check before calling hoping to save the function call cost + * most of the time. + */ + if (pContext->numBufBytes) + RecordFlushReplyBuffer(ppAllContexts[eci], NULL, 0, NULL, 0); + } +} /* RecordFlushAllContexts */ + + +/* RecordInstallHooks + * + * Arguments: + * pRCAP is an RCAP on an enabled or being-enabled context. + * oneclient can be zero or the resource ID mask identifying a client. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * Recording hooks needed by RCAP are installed. + * If oneclient is zero, recording hooks needed for all clients and + * protocol on the RCAP are installed. If oneclient is non-zero, + * only those hooks needed for the specified client are installed. + * + * Client requestVectors may be altered. numEnabledRCAPs will be + * incremented if oneclient == 0. Callbacks may be added to + * various callback lists. + */ +static int +RecordInstallHooks(RecordClientsAndProtocolPtr pRCAP, XID oneclient) +{ + int i = 0; + XID client; + + if (oneclient) + client = oneclient; + else + client = pRCAP->numClients ? pRCAP->pClientIDs[i++] : 0; + + while (client) + { + if (client != XRecordFutureClients) + { + if (pRCAP->pRequestMajorOpSet) + { + RecordSetIteratePtr pIter = NULL; + RecordSetInterval interval; + ClientPtr pClient = clients[CLIENT_ID(client)]; + + if (pClient && !RecordClientPrivate(pClient)) + { + RecordClientPrivatePtr pClientPriv; + /* no Record proc vector; allocate one */ + pClientPriv = (RecordClientPrivatePtr) + malloc(sizeof(RecordClientPrivateRec)); + if (!pClientPriv) + return BadAlloc; + /* copy old proc vector to new */ + memcpy(pClientPriv->recordVector, pClient->requestVector, + sizeof (pClientPriv->recordVector)); + pClientPriv->originalVector = pClient->requestVector; + dixSetPrivate(&pClient->devPrivates, + RecordClientPrivateKey, pClientPriv); + pClient->requestVector = pClientPriv->recordVector; + } + while ((pIter = RecordIterateSet(pRCAP->pRequestMajorOpSet, + pIter, &interval))) + { + unsigned int j; + for (j = interval.first; j <= interval.last; j++) + pClient->requestVector[j] = RecordARequest; + } + } + } + if (oneclient) + client = 0; + else + client = (i < pRCAP->numClients) ? pRCAP->pClientIDs[i++] : 0; + } + + assert(numEnabledRCAPs >= 0); + if (!oneclient && ++numEnabledRCAPs == 1) + { /* we're enabling the first context */ + if (!AddCallback(&EventCallback, RecordADeliveredEventOrError, NULL)) + return BadAlloc; + if (!AddCallback(&DeviceEventCallback, RecordADeviceEvent, NULL)) + return BadAlloc; + if (!AddCallback(&ReplyCallback, RecordAReply, NULL)) + return BadAlloc; + if (!AddCallback(&FlushCallback, RecordFlushAllContexts, NULL)) + return BadAlloc; + /* Alternate context flushing scheme: delete the line above + * and call RegisterBlockAndWakeupHandlers here passing + * RecordFlushAllContexts. Is this any better? + */ + } + return Success; +} /* RecordInstallHooks */ + + +/* RecordUninstallHooks + * + * Arguments: + * pRCAP is an RCAP on an enabled or being-disabled context. + * oneclient can be zero or the resource ID mask identifying a client. + * + * Returns: nothing. + * + * Side Effects: + * Recording hooks needed by RCAP may be uninstalled. + * If oneclient is zero, recording hooks needed for all clients and + * protocol on the RCAP may be uninstalled. If oneclient is non-zero, + * only those hooks needed for the specified client may be uninstalled. + * + * Client requestVectors may be altered. numEnabledRCAPs will be + * decremented if oneclient == 0. Callbacks may be deleted from + * various callback lists. + */ +static void +RecordUninstallHooks(RecordClientsAndProtocolPtr pRCAP, XID oneclient) +{ + int i = 0; + XID client; + + if (oneclient) + client = oneclient; + else + client = pRCAP->numClients ? pRCAP->pClientIDs[i++] : 0; + + while (client) + { + if (client != XRecordFutureClients) + { + if (pRCAP->pRequestMajorOpSet) + { + ClientPtr pClient = clients[CLIENT_ID(client)]; + int c; + Bool otherRCAPwantsProcVector = FALSE; + RecordClientPrivatePtr pClientPriv = NULL; + + assert (pClient); + pClientPriv = RecordClientPrivate(pClient); + assert (pClientPriv); + memcpy(pClientPriv->recordVector, pClientPriv->originalVector, + sizeof (pClientPriv->recordVector)); + + for (c = 0; c < numEnabledContexts; c++) + { + RecordClientsAndProtocolPtr pOtherRCAP; + RecordContextPtr pContext = ppAllContexts[c]; + + if (pContext == pRCAP->pContext) continue; + pOtherRCAP = RecordFindClientOnContext(pContext, client, + NULL); + if (pOtherRCAP && pOtherRCAP->pRequestMajorOpSet) + { + RecordSetIteratePtr pIter = NULL; + RecordSetInterval interval; + + otherRCAPwantsProcVector = TRUE; + while ((pIter = RecordIterateSet( + pOtherRCAP->pRequestMajorOpSet, + pIter, &interval))) + { + unsigned int j; + for (j = interval.first; j <= interval.last; j++) + pClient->requestVector[j] = RecordARequest; + } + } + } + if (!otherRCAPwantsProcVector) + { /* nobody needs it, so free it */ + pClient->requestVector = pClientPriv->originalVector; + dixSetPrivate(&pClient->devPrivates, + RecordClientPrivateKey, NULL); + free(pClientPriv); + } + } /* end if this RCAP specifies any requests */ + } /* end if not future clients */ + if (oneclient) + client = 0; + else + client = (i < pRCAP->numClients) ? pRCAP->pClientIDs[i++] : 0; + } + + assert(numEnabledRCAPs >= 1); + if (!oneclient && --numEnabledRCAPs == 0) + { /* we're disabling the last context */ + DeleteCallback(&EventCallback, RecordADeliveredEventOrError, NULL); + DeleteCallback(&DeviceEventCallback, RecordADeviceEvent, NULL); + DeleteCallback(&ReplyCallback, RecordAReply, NULL); + DeleteCallback(&FlushCallback, RecordFlushAllContexts, NULL); + /* Alternate context flushing scheme: delete the line above + * and call RemoveBlockAndWakeupHandlers here passing + * RecordFlushAllContexts. Is this any better? + */ + /* Having deleted the callback, call it one last time. -gildea */ + RecordFlushAllContexts(&FlushCallback, NULL, NULL); + } +} /* RecordUninstallHooks */ + + +/* RecordDeleteClientFromRCAP + * + * Arguments: + * pRCAP is an RCAP to delete the client from. + * position is the index into the array pRCAP->pClientIDs of the + * client to delete. + * + * Returns: nothing. + * + * Side Effects: + * Recording hooks needed by client will be uninstalled if the context + * is enabled. The designated client will be removed from the + * pRCAP->pClientIDs array. If it was the only client on the RCAP, + * the RCAP is removed from the context and freed. (Invariant: RCAPs + * have at least one client.) + */ +static void +RecordDeleteClientFromRCAP(RecordClientsAndProtocolPtr pRCAP, int position) +{ + if (pRCAP->pContext->pRecordingClient) + RecordUninstallHooks(pRCAP, pRCAP->pClientIDs[position]); + if (position != pRCAP->numClients - 1) + pRCAP->pClientIDs[position] = pRCAP->pClientIDs[pRCAP->numClients - 1]; + if (--pRCAP->numClients == 0) + { /* no more clients; remove RCAP from context's list */ + RecordContextPtr pContext = pRCAP->pContext; + if (pContext->pRecordingClient) + RecordUninstallHooks(pRCAP, 0); + if (pContext->pListOfRCAP == pRCAP) + pContext->pListOfRCAP = pRCAP->pNextRCAP; + else + { + RecordClientsAndProtocolPtr prevRCAP; + for (prevRCAP = pContext->pListOfRCAP; + prevRCAP->pNextRCAP != pRCAP; + prevRCAP = prevRCAP->pNextRCAP) + ; + prevRCAP->pNextRCAP = pRCAP->pNextRCAP; + } + /* free the RCAP */ + if (pRCAP->clientIDsSeparatelyAllocated) + free(pRCAP->pClientIDs); + free(pRCAP); + } +} /* RecordDeleteClientFromRCAP */ + + +/* RecordAddClientToRCAP + * + * Arguments: + * pRCAP is an RCAP to add the client to. + * clientspec is the resource ID mask identifying a client, or + * XRecordFutureClients. + * + * Returns: nothing. + * + * Side Effects: + * Recording hooks needed by client will be installed if the context + * is enabled. The designated client will be added to the + * pRCAP->pClientIDs array, which may be realloced. + * pRCAP->clientIDsSeparatelyAllocated may be set to 1 if there + * is no more room to hold clients internal to the RCAP. + */ +static void +RecordAddClientToRCAP(RecordClientsAndProtocolPtr pRCAP, XID clientspec) +{ + if (pRCAP->numClients == pRCAP->sizeClients) + { + if (pRCAP->clientIDsSeparatelyAllocated) + { + XID *pNewIDs = (XID *)realloc(pRCAP->pClientIDs, + (pRCAP->sizeClients + CLIENT_ARRAY_GROWTH_INCREMENT) * + sizeof(XID)); + if (!pNewIDs) + return; + pRCAP->pClientIDs = pNewIDs; + pRCAP->sizeClients += CLIENT_ARRAY_GROWTH_INCREMENT; + } + else + { + XID *pNewIDs = (XID *)malloc((pRCAP->sizeClients + + CLIENT_ARRAY_GROWTH_INCREMENT) * sizeof(XID)); + if (!pNewIDs) + return; + memcpy(pNewIDs, pRCAP->pClientIDs, pRCAP->numClients *sizeof(XID)); + pRCAP->pClientIDs = pNewIDs; + pRCAP->sizeClients += CLIENT_ARRAY_GROWTH_INCREMENT; + pRCAP->clientIDsSeparatelyAllocated = 1; + } + } + pRCAP->pClientIDs[pRCAP->numClients++] = clientspec; + if (pRCAP->pContext->pRecordingClient) + RecordInstallHooks(pRCAP, clientspec); +} /* RecordDeleteClientFromRCAP */ + + +/* RecordDeleteClientFromContext + * + * Arguments: + * pContext is the context to delete from. + * clientspec is the resource ID mask identifying a client, or + * XRecordFutureClients. + * + * Returns: nothing. + * + * Side Effects: + * If clientspec is on any RCAP of the context, it is deleted from that + * RCAP. (A given clientspec can only be on one RCAP of a context.) + */ +static void +RecordDeleteClientFromContext(RecordContextPtr pContext, XID clientspec) +{ + RecordClientsAndProtocolPtr pRCAP; + int position; + + if ((pRCAP = RecordFindClientOnContext(pContext, clientspec, &position))) + RecordDeleteClientFromRCAP(pRCAP, position); +} /* RecordDeleteClientFromContext */ + + +/* RecordSanityCheckClientSpecifiers + * + * Arguments: + * clientspecs is an array of alleged CLIENTSPECs passed by the client. + * nspecs is the number of elements in clientspecs. + * errorspec, if non-zero, is the resource id base of a client that + * must not appear in clienspecs. + * + * Returns: BadMatch if any of the clientspecs are invalid, else Success. + * + * Side Effects: none. + */ +static int +RecordSanityCheckClientSpecifiers(ClientPtr client, XID *clientspecs, int nspecs, XID errorspec) +{ + int i; + int clientIndex; + int rc; + pointer value; + + for (i = 0; i < nspecs; i++) + { + if (clientspecs[i] == XRecordCurrentClients || + clientspecs[i] == XRecordFutureClients || + clientspecs[i] == XRecordAllClients) + continue; + if (errorspec && (CLIENT_BITS(clientspecs[i]) == errorspec) ) + return BadMatch; + clientIndex = CLIENT_ID(clientspecs[i]); + if (clientIndex && clients[clientIndex] && + clients[clientIndex]->clientState == ClientStateRunning) + { + if (clientspecs[i] == clients[clientIndex]->clientAsMask) + continue; + rc = dixLookupResourceByClass(&value, clientspecs[i], RC_ANY, + client, DixGetAttrAccess); + if (rc != Success) + return rc; + } + else + return BadMatch; + } + return Success; +} /* RecordSanityCheckClientSpecifiers */ + + +/* RecordCanonicalizeClientSpecifiers + * + * Arguments: + * pClientspecs is an array of CLIENTSPECs that have been sanity + * checked. + * pNumClientspecs is a pointer to the number of elements in pClientspecs. + * excludespec, if non-zero, is the resource id base of a client that + * should not be included in the expansion of XRecordAllClients or + * XRecordCurrentClients. + * + * Returns: + * A pointer to an array of CLIENTSPECs that is the same as the + * passed array with the following modifications: + * - all but the client id bits of resource IDs are stripped off. + * - duplicates removed. + * - XRecordAllClients expanded to a list of all currently connected + * clients + XRecordFutureClients - excludespec (if non-zero) + * - XRecordCurrentClients expanded to a list of all currently + * connected clients - excludespec (if non-zero) + * The returned array may be the passed array modified in place, or + * it may be an malloc'ed array. The caller should keep a pointer to the + * original array and free the returned array if it is different. + * + * *pNumClientspecs is set to the number of elements in the returned + * array. + * + * Side Effects: + * pClientspecs may be modified in place. + */ +static XID * +RecordCanonicalizeClientSpecifiers(XID *pClientspecs, int *pNumClientspecs, XID excludespec) +{ + int i; + int numClients = *pNumClientspecs; + + /* first pass strips off the resource index bits, leaving just the + * client id bits. This makes searching for a particular client simpler + * (and faster.) + */ + for (i = 0; i < numClients; i++) + { + XID cs = pClientspecs[i]; + if (cs > XRecordAllClients) + pClientspecs[i] = CLIENT_BITS(cs); + } + + for (i = 0; i < numClients; i++) + { + if (pClientspecs[i] == XRecordAllClients || + pClientspecs[i] == XRecordCurrentClients) + { /* expand All/Current */ + int j, nc; + XID *pCanon = (XID *)malloc(sizeof(XID) * (currentMaxClients + 1)); + if (!pCanon) return NULL; + for (nc = 0, j = 1; j < currentMaxClients; j++) + { + ClientPtr client = clients[j]; + if (client != NullClient && + client->clientState == ClientStateRunning && + client->clientAsMask != excludespec) + { + pCanon[nc++] = client->clientAsMask; + } + } + if (pClientspecs[i] == XRecordAllClients) + pCanon[nc++] = XRecordFutureClients; + *pNumClientspecs = nc; + return pCanon; + } + else /* not All or Current */ + { + int j; + for (j = i + 1; j < numClients; ) + { + if (pClientspecs[i] == pClientspecs[j]) + { + pClientspecs[j] = pClientspecs[--numClients]; + } + else + j++; + } + } + } /* end for each clientspec */ + *pNumClientspecs = numClients; + return pClientspecs; +} /* RecordCanonicalizeClientSpecifiers */ + + +/****************************************************************************/ + +/* stuff for RegisterClients */ + +/* RecordPadAlign + * + * Arguments: + * size is the number of bytes taken by an object. + * align is a byte boundary (e.g. 4, 8) + * + * Returns: + * the number of pad bytes to add at the end of an object of the + * given size so that an object placed immediately behind it will + * begin on an -byte boundary. + * + * Side Effects: none. + */ +static int +RecordPadAlign(int size, int align) +{ + return (align - (size & (align - 1))) & (align - 1); +} /* RecordPadAlign */ + + +/* RecordSanityCheckRegisterClients + * + * Arguments: + * pContext is the context being registered on. + * client is the client that issued a RecordCreateContext or + * RecordRegisterClients request. + * stuff is a pointer to the request. + * + * Returns: + * Any one of several possible error values if any of the request + * arguments are invalid. Success if everything is OK. + * + * Side Effects: none. + */ +static int +RecordSanityCheckRegisterClients(RecordContextPtr pContext, ClientPtr client, xRecordRegisterClientsReq *stuff) +{ + int err; + xRecordRange *pRange; + int i; + XID recordingClient; + + if (((client->req_len << 2) - SIZEOF(xRecordRegisterClientsReq)) != + 4 * stuff->nClients + SIZEOF(xRecordRange) * stuff->nRanges) + return BadLength; + + if (stuff->elementHeader & + ~(XRecordFromClientSequence|XRecordFromClientTime|XRecordFromServerTime)) + { + client->errorValue = stuff->elementHeader; + return BadValue; + } + + recordingClient = pContext->pRecordingClient ? + pContext->pRecordingClient->clientAsMask : 0; + err = RecordSanityCheckClientSpecifiers(client, (XID *)&stuff[1], + stuff->nClients, recordingClient); + if (err != Success) return err; + + pRange = (xRecordRange *)(((XID *)&stuff[1]) + stuff->nClients); + for (i = 0; i < stuff->nRanges; i++, pRange++) + { + if (pRange->coreRequestsFirst > pRange->coreRequestsLast) + { + client->errorValue = pRange->coreRequestsFirst; + return BadValue; + } + if (pRange->coreRepliesFirst > pRange->coreRepliesLast) + { + client->errorValue = pRange->coreRepliesFirst; + return BadValue; + } + if ((pRange->extRequestsMajorFirst || pRange->extRequestsMajorLast) && + (pRange->extRequestsMajorFirst < 128 || + pRange->extRequestsMajorLast < 128 || + pRange->extRequestsMajorFirst > pRange->extRequestsMajorLast)) + { + client->errorValue = pRange->extRequestsMajorFirst; + return BadValue; + } + if (pRange->extRequestsMinorFirst > pRange->extRequestsMinorLast) + { + client->errorValue = pRange->extRequestsMinorFirst; + return BadValue; + } + if ((pRange->extRepliesMajorFirst || pRange->extRepliesMajorLast) && + (pRange->extRepliesMajorFirst < 128 || + pRange->extRepliesMajorLast < 128 || + pRange->extRepliesMajorFirst > pRange->extRepliesMajorLast)) + { + client->errorValue = pRange->extRepliesMajorFirst; + return BadValue; + } + if (pRange->extRepliesMinorFirst > pRange->extRepliesMinorLast) + { + client->errorValue = pRange->extRepliesMinorFirst; + return BadValue; + } + if ((pRange->deliveredEventsFirst || pRange->deliveredEventsLast) && + (pRange->deliveredEventsFirst < 2 || + pRange->deliveredEventsLast < 2 || + pRange->deliveredEventsFirst > pRange->deliveredEventsLast)) + { + client->errorValue = pRange->deliveredEventsFirst; + return BadValue; + } + if ((pRange->deviceEventsFirst || pRange->deviceEventsLast) && + (pRange->deviceEventsFirst < 2 || + pRange->deviceEventsLast < 2 || + pRange->deviceEventsFirst > pRange->deviceEventsLast)) + { + client->errorValue = pRange->deviceEventsFirst; + return BadValue; + } + if (pRange->errorsFirst > pRange->errorsLast) + { + client->errorValue = pRange->errorsFirst; + return BadValue; + } + if (pRange->clientStarted != xFalse && pRange->clientStarted != xTrue) + { + client->errorValue = pRange->clientStarted; + return BadValue; + } + if (pRange->clientDied != xFalse && pRange->clientDied != xTrue) + { + client->errorValue = pRange->clientDied; + return BadValue; + } + } /* end for each range */ + return Success; +} /* end RecordSanityCheckRegisterClients */ + +/* This is a tactical structure used to gather information about all the sets + * (RecordSetPtr) that need to be created for an RCAP in the process of + * digesting a list of RECORDRANGEs (converting it to the internal + * representation). + */ +typedef struct +{ + int nintervals; /* number of intervals in following array */ + RecordSetInterval *intervals; /* array of intervals for this set */ + int size; /* size of intevals array; >= nintervals */ + int align; /* alignment restriction for set */ + int offset; /* where to store set pointer rel. to start of RCAP */ + short first, last; /* if for extension, major opcode interval */ +} SetInfoRec, *SetInfoPtr; + +/* These constant are used to index into an array of SetInfoRec. */ +enum {REQ, /* set info for requests */ + REP, /* set info for replies */ + ERR, /* set info for errors */ + DEV, /* set info for device events */ + DLEV, /* set info for delivered events */ + PREDEFSETS}; /* number of predefined array entries */ + + +/* RecordAllocIntervals + * + * Arguments: + * psi is a pointer to a SetInfoRec whose intervals pointer is NULL. + * nIntervals is the desired size of the intervals array. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * If Success is returned, psi->intervals is a pointer to size + * RecordSetIntervals, all zeroed, and psi->size is set to size. + */ +static int +RecordAllocIntervals(SetInfoPtr psi, int nIntervals) +{ + assert(!psi->intervals); + psi->intervals = (RecordSetInterval *) + malloc(nIntervals * sizeof(RecordSetInterval)); + if (!psi->intervals) + return BadAlloc; + memset(psi->intervals, 0, nIntervals * sizeof(RecordSetInterval)); + psi->size = nIntervals; + return Success; +} /* end RecordAllocIntervals */ + + +/* RecordConvertRangesToIntervals + * + * Arguments: + * psi is a pointer to the SetInfoRec we are building. + * pRanges is an array of xRecordRanges. + * nRanges is the number of elements in pRanges. + * byteoffset is the offset from the start of an xRecordRange of the + * two bytes (1 for first, 1 for last) we are interested in. + * pExtSetInfo, if non-NULL, indicates that the two bytes mentioned + * above are followed by four bytes (2 for first, 2 for last) + * representing a minor opcode range, and this information should be + * stored in one of the SetInfoRecs starting at pExtSetInfo. + * pnExtSetInfo is the number of elements in the pExtSetInfo array. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * The slice of pRanges indicated by byteoffset is stored in psi. + * If pExtSetInfo is non-NULL, minor opcode intervals are stored + * in an existing SetInfoRec if the major opcode interval matches, else + * they are stored in a new SetInfoRec, and *pnExtSetInfo is + * increased accordingly. + */ +static int +RecordConvertRangesToIntervals( + SetInfoPtr psi, + xRecordRange *pRanges, + int nRanges, + int byteoffset, + SetInfoPtr pExtSetInfo, + int *pnExtSetInfo +) +{ + int i; + CARD8 *pCARD8; + int first, last; + int err; + + for (i = 0; i < nRanges; i++, pRanges++) + { + pCARD8 = ((CARD8 *)pRanges) + byteoffset; + first = pCARD8[0]; + last = pCARD8[1]; + if (first || last) + { + if (!psi->intervals) + { + err = RecordAllocIntervals(psi, 2 * (nRanges - i)); + if (err != Success) + return err; + } + psi->intervals[psi->nintervals].first = first; + psi->intervals[psi->nintervals].last = last; + psi->nintervals++; + assert(psi->nintervals <= psi->size); + if (pExtSetInfo) + { + SetInfoPtr pesi = pExtSetInfo; + CARD16 *pCARD16 = (CARD16 *)(pCARD8 + 2); + int j; + + for (j = 0; j < *pnExtSetInfo; j++, pesi++) + { + if ( (first == pesi->first) && (last == pesi->last) ) + break; + } + if (j == *pnExtSetInfo) + { + err = RecordAllocIntervals(pesi, 2 * (nRanges - i)); + if (err != Success) + return err; + pesi->first = first; + pesi->last = last; + (*pnExtSetInfo)++; + } + pesi->intervals[pesi->nintervals].first = pCARD16[0]; + pesi->intervals[pesi->nintervals].last = pCARD16[1]; + pesi->nintervals++; + assert(pesi->nintervals <= pesi->size); + } + } + } + return Success; +} /* end RecordConvertRangesToIntervals */ + +#define offset_of(_structure, _field) \ + ((char *)(& (_structure . _field)) - (char *)(&_structure)) + +/* RecordRegisterClients + * + * Arguments: + * pContext is the context on which to register the clients. + * client is the client that issued the RecordCreateContext or + * RecordRegisterClients request. + * stuff is a pointer to the request. + * + * Returns: + * Any one of several possible error values defined by the protocol. + * Success if everything is OK. + * + * Side Effects: + * If different element headers are specified, the context is flushed. + * If any of the specified clients are already registered on the + * context, they are first unregistered. A new RCAP is created to + * hold the specified protocol and clients, and it is linked onto the + * context. If the context is enabled, appropriate hooks are installed + * to record the new clients and protocol. + */ +static int +RecordRegisterClients(RecordContextPtr pContext, ClientPtr client, xRecordRegisterClientsReq *stuff) +{ + int err; + int i; + SetInfoPtr si; + int maxSets; + int nExtReqSets = 0; + int nExtRepSets = 0; + int extReqSetsOffset = 0; + int extRepSetsOffset = 0; + SetInfoPtr pExtReqSets, pExtRepSets; + int clientListOffset; + XID *pCanonClients; + int clientStarted = 0, clientDied = 0; + xRecordRange *pRanges, rr; + int nClients; + int sizeClients; + int totRCAPsize; + RecordClientsAndProtocolPtr pRCAP; + int pad; + XID recordingClient; + + /* do all sanity checking up front */ + + err = RecordSanityCheckRegisterClients(pContext, client, stuff); + if (err != Success) + return err; + + /* if element headers changed, flush buffer */ + + if (pContext->elemHeaders != stuff->elementHeader) + { + RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); + pContext->elemHeaders = stuff->elementHeader; + } + + nClients = stuff->nClients; + if (!nClients) + /* if empty clients list, we're done. */ + return Success; + + recordingClient = pContext->pRecordingClient ? + pContext->pRecordingClient->clientAsMask : 0; + pCanonClients = RecordCanonicalizeClientSpecifiers((XID *)&stuff[1], + &nClients, recordingClient); + if (!pCanonClients) + return BadAlloc; + + /* We may have to create as many as one set for each "predefined" + * protocol types, plus one per range for extension reuests, plus one per + * range for extension replies. + */ + maxSets = PREDEFSETS + 2 * stuff->nRanges; + si = (SetInfoPtr)malloc(sizeof(SetInfoRec) * maxSets); + if (!si) + { + err = BadAlloc; + goto bailout; + } + memset(si, 0, sizeof(SetInfoRec) * maxSets); + + /* theoretically you must do this because NULL may not be all-bits-zero */ + for (i = 0; i < maxSets; i++) + si[i].intervals = NULL; + + pExtReqSets = si + PREDEFSETS; + pExtRepSets = pExtReqSets + stuff->nRanges; + + pRanges = (xRecordRange *)(((XID *)&stuff[1]) + stuff->nClients); + + err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges, + offset_of(rr, coreRequestsFirst), NULL, NULL); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges, + offset_of(rr, extRequestsMajorFirst), pExtReqSets, &nExtReqSets); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges, + offset_of(rr, coreRepliesFirst), NULL, NULL); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges, + offset_of(rr, extRepliesMajorFirst), pExtRepSets, &nExtRepSets); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[ERR], pRanges, stuff->nRanges, + offset_of(rr, errorsFirst), NULL, NULL); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[DLEV], pRanges, stuff->nRanges, + offset_of(rr, deliveredEventsFirst), NULL, NULL); + if (err != Success) goto bailout; + + err = RecordConvertRangesToIntervals(&si[DEV], pRanges, stuff->nRanges, + offset_of(rr, deviceEventsFirst), NULL, NULL); + if (err != Success) goto bailout; + + /* collect client-started and client-died */ + + for (i = 0; i < stuff->nRanges; i++) + { + if (pRanges[i].clientStarted) clientStarted = TRUE; + if (pRanges[i].clientDied) clientDied = TRUE; + } + + /* We now have all the information collected to create all the sets, + * and we can compute the total memory required for the RCAP. + */ + + totRCAPsize = sizeof(RecordClientsAndProtocolRec); + + /* leave a little room to grow before forcing a separate allocation */ + sizeClients = nClients + CLIENT_ARRAY_GROWTH_INCREMENT; + pad = RecordPadAlign(totRCAPsize, sizeof(XID)); + clientListOffset = totRCAPsize + pad; + totRCAPsize += pad + sizeClients * sizeof(XID); + + if (nExtReqSets) + { + pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr)); + extReqSetsOffset = totRCAPsize + pad; + totRCAPsize += pad + (nExtReqSets + 1) * sizeof(RecordMinorOpRec); + } + if (nExtRepSets) + { + pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr)); + extRepSetsOffset = totRCAPsize + pad; + totRCAPsize += pad + (nExtRepSets + 1) * sizeof(RecordMinorOpRec); + } + + for (i = 0; i < maxSets; i++) + { + if (si[i].nintervals) + { + si[i].size = RecordSetMemoryRequirements( + si[i].intervals, si[i].nintervals, &si[i].align); + pad = RecordPadAlign(totRCAPsize, si[i].align); + si[i].offset = pad + totRCAPsize; + totRCAPsize += pad + si[i].size; + } + } + + /* allocate memory for the whole RCAP */ + + pRCAP = (RecordClientsAndProtocolPtr)malloc(totRCAPsize); + if (!pRCAP) + { + err = BadAlloc; + goto bailout; + } + + /* fill in the RCAP */ + + pRCAP->pContext = pContext; + pRCAP->pClientIDs = (XID *)((char *)pRCAP + clientListOffset); + pRCAP->numClients = nClients; + pRCAP->sizeClients = sizeClients; + pRCAP->clientIDsSeparatelyAllocated = 0; + for (i = 0; i < nClients; i++) + { + RecordDeleteClientFromContext(pContext, pCanonClients[i]); + pRCAP->pClientIDs[i] = pCanonClients[i]; + } + + /* create all the sets */ + + if (si[REQ].intervals) + { + pRCAP->pRequestMajorOpSet = + RecordCreateSet(si[REQ].intervals, si[REQ].nintervals, + (RecordSetPtr)((char *)pRCAP + si[REQ].offset), si[REQ].size); + } + else pRCAP->pRequestMajorOpSet = NULL; + + if (si[REP].intervals) + { + pRCAP->pReplyMajorOpSet = + RecordCreateSet(si[REP].intervals, si[REP].nintervals, + (RecordSetPtr)((char *)pRCAP + si[REP].offset), si[REP].size); + } + else pRCAP->pReplyMajorOpSet = NULL; + + if (si[ERR].intervals) + { + pRCAP->pErrorSet = + RecordCreateSet(si[ERR].intervals, si[ERR].nintervals, + (RecordSetPtr)((char *)pRCAP + si[ERR].offset), si[ERR].size); + } + else pRCAP->pErrorSet = NULL; + + if (si[DEV].intervals) + { + pRCAP->pDeviceEventSet = + RecordCreateSet(si[DEV].intervals, si[DEV].nintervals, + (RecordSetPtr)((char *)pRCAP + si[DEV].offset), si[DEV].size); + } + else pRCAP->pDeviceEventSet = NULL; + + if (si[DLEV].intervals) + { + pRCAP->pDeliveredEventSet = + RecordCreateSet(si[DLEV].intervals, si[DLEV].nintervals, + (RecordSetPtr)((char *)pRCAP + si[DLEV].offset), si[DLEV].size); + } + else pRCAP->pDeliveredEventSet = NULL; + + if (nExtReqSets) + { + pRCAP->pRequestMinOpInfo = (RecordMinorOpPtr) + ((char *)pRCAP + extReqSetsOffset); + pRCAP->pRequestMinOpInfo[0].count = nExtReqSets; + for (i = 0; i < nExtReqSets; i++, pExtReqSets++) + { + pRCAP->pRequestMinOpInfo[i+1].major.first = pExtReqSets->first; + pRCAP->pRequestMinOpInfo[i+1].major.last = pExtReqSets->last; + pRCAP->pRequestMinOpInfo[i+1].major.pMinOpSet = + RecordCreateSet(pExtReqSets->intervals, + pExtReqSets->nintervals, + (RecordSetPtr)((char *)pRCAP + pExtReqSets->offset), + pExtReqSets->size); + } + } + else pRCAP->pRequestMinOpInfo = NULL; + + if (nExtRepSets) + { + pRCAP->pReplyMinOpInfo = (RecordMinorOpPtr) + ((char *)pRCAP + extRepSetsOffset); + pRCAP->pReplyMinOpInfo[0].count = nExtRepSets; + for (i = 0; i < nExtRepSets; i++, pExtRepSets++) + { + pRCAP->pReplyMinOpInfo[i+1].major.first = pExtRepSets->first; + pRCAP->pReplyMinOpInfo[i+1].major.last = pExtRepSets->last; + pRCAP->pReplyMinOpInfo[i+1].major.pMinOpSet = + RecordCreateSet(pExtRepSets->intervals, + pExtRepSets->nintervals, + (RecordSetPtr)((char *)pRCAP + pExtRepSets->offset), + pExtRepSets->size); + } + } + else pRCAP->pReplyMinOpInfo = NULL; + + pRCAP->clientStarted = clientStarted; + pRCAP->clientDied = clientDied; + + /* link the RCAP onto the context */ + + pRCAP->pNextRCAP = pContext->pListOfRCAP; + pContext->pListOfRCAP = pRCAP; + + if (pContext->pRecordingClient) /* context enabled */ + RecordInstallHooks(pRCAP, 0); + +bailout: + if (si) + { + for (i = 0; i < maxSets; i++) + free(si[i].intervals); + free(si); + } + if (pCanonClients && pCanonClients != (XID *)&stuff[1]) + free(pCanonClients); + return err; +} /* RecordRegisterClients */ + + +/* Proc functions all take a client argument, execute the request in + * client->requestBuffer, and return a protocol error status. + */ + +static int +ProcRecordQueryVersion(ClientPtr client) +{ + /* REQUEST(xRecordQueryVersionReq); */ + xRecordQueryVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xRecordQueryVersionReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.majorVersion = SERVER_RECORD_MAJOR_VERSION; + rep.minorVersion = SERVER_RECORD_MINOR_VERSION; + if(client->swapped) + { + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + (void)WriteToClient(client, sizeof(xRecordQueryVersionReply), + (char *)&rep); + return Success; +} /* ProcRecordQueryVersion */ + + +static int +ProcRecordCreateContext(ClientPtr client) +{ + REQUEST(xRecordCreateContextReq); + RecordContextPtr pContext; + RecordContextPtr *ppNewAllContexts = NULL; + int err = BadAlloc; + + REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq); + LEGAL_NEW_RESOURCE(stuff->context, client); + + pContext = (RecordContextPtr)malloc(sizeof(RecordContextRec)); + if (!pContext) + goto bailout; + + /* make sure there is room in ppAllContexts to store the new context */ + + ppNewAllContexts = (RecordContextPtr *) + realloc(ppAllContexts, sizeof(RecordContextPtr) * (numContexts + 1)); + if (!ppNewAllContexts) + goto bailout; + ppAllContexts = ppNewAllContexts; + + pContext->id = stuff->context; + pContext->pRecordingClient = NULL; + pContext->pListOfRCAP = NULL; + pContext->elemHeaders = 0; + pContext->bufCategory = 0; + pContext->numBufBytes = 0; + pContext->pBufClient = NULL; + pContext->continuedReply = 0; + pContext->inFlush = 0; + + err = RecordRegisterClients(pContext, client, + (xRecordRegisterClientsReq *)stuff); + if (err != Success) + goto bailout; + + if (AddResource(pContext->id, RTContext, pContext)) + { + ppAllContexts[numContexts++] = pContext; + return Success; + } + else + { + RecordDeleteContext((pointer)pContext, pContext->id); + err = BadAlloc; + } +bailout: + free(pContext); + return err; +} /* ProcRecordCreateContext */ + + +static int +ProcRecordRegisterClients(ClientPtr client) +{ + RecordContextPtr pContext; + REQUEST(xRecordRegisterClientsReq); + + REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + + return RecordRegisterClients(pContext, client, stuff); +} /* ProcRecordRegisterClients */ + + +static int +ProcRecordUnregisterClients(ClientPtr client) +{ + RecordContextPtr pContext; + int err; + REQUEST(xRecordUnregisterClientsReq); + XID *pCanonClients; + int nClients; + int i; + + REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq); + if ((client->req_len << 2) - SIZEOF(xRecordUnregisterClientsReq) != + 4 * stuff->nClients) + return BadLength; + VERIFY_CONTEXT(pContext, stuff->context, client); + err = RecordSanityCheckClientSpecifiers(client, (XID *)&stuff[1], + stuff->nClients, 0); + if (err != Success) + return err; + + nClients = stuff->nClients; + pCanonClients = RecordCanonicalizeClientSpecifiers((XID *)&stuff[1], + &nClients, 0); + if (!pCanonClients) + return BadAlloc; + + for (i = 0; i < nClients; i++) + { + RecordDeleteClientFromContext(pContext, pCanonClients[i]); + } + if (pCanonClients != (XID *)&stuff[1]) + free(pCanonClients); + return Success; +} /* ProcRecordUnregisterClients */ + + +/****************************************************************************/ + +/* stuff for GetContext */ + +/* This is a tactical structure used to hold the xRecordRanges as they are + * being reconstituted from the sets in the RCAPs. + */ + +typedef struct { + xRecordRange *pRanges; /* array of xRecordRanges for one RCAP */ + int size; /* number of elements in pRanges, >= nRanges */ + int nRanges; /* number of occupied element of pRanges */ +} GetContextRangeInfoRec, *GetContextRangeInfoPtr; + + +/* RecordAllocRanges + * + * Arguments: + * pri is a pointer to a GetContextRangeInfoRec to allocate for. + * nRanges is the number of xRecordRanges desired for pri. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * If Success is returned, pri->pRanges points to at least nRanges + * ranges. pri->nRanges is set to nRanges. pri->size is the actual + * number of ranges. Newly allocated ranges are zeroed. + */ +static int +RecordAllocRanges(GetContextRangeInfoPtr pri, int nRanges) +{ + int newsize; + xRecordRange *pNewRange; +#define SZINCR 8 + + newsize = max(pri->size + SZINCR, nRanges); + pNewRange = (xRecordRange *)realloc(pri->pRanges, + newsize * sizeof(xRecordRange)); + if (!pNewRange) + return BadAlloc; + + pri->pRanges = pNewRange; + pri->size = newsize; + memset(&pri->pRanges[pri->size - SZINCR], 0, SZINCR * sizeof(xRecordRange)); + if (pri->nRanges < nRanges) + pri->nRanges = nRanges; + return Success; +} /* RecordAllocRanges */ + + +/* RecordConvertSetToRanges + * + * Arguments: + * pSet is the set to be converted. + * pri is where the result should be stored. + * byteoffset is the offset from the start of an xRecordRange of the + * two vales (first, last) we are interested in. + * card8 is TRUE if the vales are one byte each and FALSE if two bytes + * each. + * imax is the largest set value to store in pri->pRanges. + * pStartIndex, if non-NULL, is the index of the first range in + * pri->pRanges that should be stored to. If NULL, + * start at index 0. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * If Success is returned, the slice of pri->pRanges indicated by + * byteoffset and card8 is filled in with the intervals from pSet. + * if pStartIndex was non-NULL, *pStartIndex is filled in with one + * more than the index of the last xRecordRange that was touched. + */ +static int +RecordConvertSetToRanges( + RecordSetPtr pSet, + GetContextRangeInfoPtr pri, + int byteoffset, + Bool card8, + unsigned int imax, + int *pStartIndex +) +{ + int nRanges; + RecordSetIteratePtr pIter = NULL; + RecordSetInterval interval; + CARD8 *pCARD8; + CARD16 *pCARD16; + int err; + + if (!pSet) + return Success; + + nRanges = pStartIndex ? *pStartIndex : 0; + while ((pIter = RecordIterateSet(pSet, pIter, &interval))) + { + if (interval.first > imax) break; + if (interval.last > imax) interval.last = imax; + nRanges++; + if (nRanges > pri->size) + { + err = RecordAllocRanges(pri, nRanges); + if (err != Success) + return err; + } + else + pri->nRanges = max(pri->nRanges, nRanges); + if (card8) + { + pCARD8 = ((CARD8 *)&pri->pRanges[nRanges-1]) + byteoffset; + *pCARD8++ = interval.first; + *pCARD8 = interval.last; + } + else + { + pCARD16 = (CARD16 *) + (((char *)&pri->pRanges[nRanges-1]) + byteoffset); + *pCARD16++ = interval.first; + *pCARD16 = interval.last; + } + } + if (pStartIndex) + *pStartIndex = nRanges; + return Success; +} /* RecordConvertSetToRanges */ + + +/* RecordConvertMinorOpInfoToRanges + * + * Arguments: + * pMinOpInfo is the minor opcode info to convert to xRecordRanges. + * pri is where the result should be stored. + * byteoffset is the offset from the start of an xRecordRange of the + * four vales (CARD8 major_first, CARD8 major_last, + * CARD16 minor_first, CARD16 minor_last) we are going to store. + * + * Returns: BadAlloc if a memory allocation error occurred, else Success. + * + * Side Effects: + * If Success is returned, the slice of pri->pRanges indicated by + * byteoffset is filled in with the information from pMinOpInfo. + */ +static int +RecordConvertMinorOpInfoToRanges( + RecordMinorOpPtr pMinOpInfo, + GetContextRangeInfoPtr pri, + int byteoffset +) +{ + int nsets; + int start; + int i; + int err; + + if (!pMinOpInfo) + return Success; + + nsets = pMinOpInfo->count; + pMinOpInfo++; + start = 0; + for (i = 0; i < nsets; i++) + { + int j, s; + s = start; + err = RecordConvertSetToRanges(pMinOpInfo[i].major.pMinOpSet, pri, + byteoffset + 2, FALSE, 65535, &start); + if (err != Success) return err; + for (j = s; j < start; j++) + { + CARD8 *pCARD8 = ((CARD8 *)&pri->pRanges[j]) + byteoffset; + *pCARD8++ = pMinOpInfo[i].major.first; + *pCARD8 = pMinOpInfo[i].major.last; + } + } + return Success; +} /* RecordConvertMinorOpInfoToRanges */ + + +/* RecordSwapRanges + * + * Arguments: + * pRanges is an array of xRecordRanges. + * nRanges is the number of elements in pRanges. + * + * Returns: nothing. + * + * Side Effects: + * The 16 bit fields of each xRecordRange are byte swapped. + */ +static void +RecordSwapRanges(xRecordRange *pRanges, int nRanges) +{ + int i; + register char n; + for (i = 0; i < nRanges; i++, pRanges++) + { + swaps(&pRanges->extRequestsMinorFirst, n); + swaps(&pRanges->extRequestsMinorLast, n); + swaps(&pRanges->extRepliesMinorFirst, n); + swaps(&pRanges->extRepliesMinorLast, n); + } +} /* RecordSwapRanges */ + + +static int +ProcRecordGetContext(ClientPtr client) +{ + RecordContextPtr pContext; + REQUEST(xRecordGetContextReq); + xRecordGetContextReply rep; + int n; + RecordClientsAndProtocolPtr pRCAP; + int nRCAPs = 0; + GetContextRangeInfoPtr pRangeInfo; + GetContextRangeInfoPtr pri; + int i; + int err; + + REQUEST_SIZE_MATCH(xRecordGetContextReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + + /* how many RCAPs are there on this context? */ + + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + nRCAPs++; + + /* allocate and initialize space for record range info */ + + pRangeInfo = (GetContextRangeInfoPtr)malloc( + nRCAPs * sizeof(GetContextRangeInfoRec)); + if (!pRangeInfo && nRCAPs > 0) + return BadAlloc; + for (i = 0; i < nRCAPs; i++) + { + pRangeInfo[i].pRanges = NULL; + pRangeInfo[i].size = 0; + pRangeInfo[i].nRanges = 0; + } + + /* convert the RCAP (internal) representation of the recorded protocol + * to the wire protocol (external) representation, storing the information + * for the ith RCAP in pri[i] + */ + + for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; + pRCAP; + pRCAP = pRCAP->pNextRCAP, pri++) + { + xRecordRange rr; + + err = RecordConvertSetToRanges(pRCAP->pRequestMajorOpSet, pri, + offset_of(rr, coreRequestsFirst), TRUE, 127, NULL); + if (err != Success) goto bailout; + + err = RecordConvertSetToRanges(pRCAP->pReplyMajorOpSet, pri, + offset_of(rr, coreRepliesFirst), TRUE, 127, NULL); + if (err != Success) goto bailout; + + err = RecordConvertSetToRanges(pRCAP->pDeliveredEventSet, pri, + offset_of(rr, deliveredEventsFirst), TRUE, 255, NULL); + if (err != Success) goto bailout; + + err = RecordConvertSetToRanges(pRCAP->pDeviceEventSet, pri, + offset_of(rr, deviceEventsFirst), TRUE, 255, NULL); + if (err != Success) goto bailout; + + err = RecordConvertSetToRanges(pRCAP->pErrorSet, pri, + offset_of(rr, errorsFirst), TRUE, 255, NULL); + if (err != Success) goto bailout; + + err = RecordConvertMinorOpInfoToRanges(pRCAP->pRequestMinOpInfo, + pri, offset_of(rr, extRequestsMajorFirst)); + if (err != Success) goto bailout; + + err = RecordConvertMinorOpInfoToRanges(pRCAP->pReplyMinOpInfo, + pri, offset_of(rr, extRepliesMajorFirst)); + if (err != Success) goto bailout; + + if (pRCAP->clientStarted || pRCAP->clientDied) + { + if (pri->nRanges == 0) + RecordAllocRanges(pri, 1); + pri->pRanges[0].clientStarted = pRCAP->clientStarted; + pri->pRanges[0].clientDied = pRCAP->clientDied; + } + } + + /* calculate number of clients and reply length */ + + rep.nClients = 0; + rep.length = 0; + for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; + pRCAP; + pRCAP = pRCAP->pNextRCAP, pri++) + { + rep.nClients += pRCAP->numClients; + rep.length += pRCAP->numClients * + ( bytes_to_int32(sizeof(xRecordClientInfo)) + + pri->nRanges * bytes_to_int32(sizeof(xRecordRange))); + } + + /* write the reply header */ + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.enabled = pContext->pRecordingClient != NULL; + rep.elementHeader = pContext->elemHeaders; + if(client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.nClients, n); + } + (void)WriteToClient(client, sizeof(xRecordGetContextReply), + (char *)&rep); + + /* write all the CLIENT_INFOs */ + + for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo; + pRCAP; + pRCAP = pRCAP->pNextRCAP, pri++) + { + xRecordClientInfo rci; + rci.nRanges = pri->nRanges; + if (client->swapped) + { + swapl(&rci.nRanges, n); + RecordSwapRanges(pri->pRanges, pri->nRanges); + } + for (i = 0; i < pRCAP->numClients; i++) + { + rci.clientResource = pRCAP->pClientIDs[i]; + if (client->swapped) swapl(&rci.clientResource, n); + WriteToClient(client, sizeof(xRecordClientInfo), (char *)&rci); + WriteToClient(client, sizeof(xRecordRange) * pri->nRanges, + (char *)pri->pRanges); + } + } + err = Success; + +bailout: + for (i = 0; i < nRCAPs; i++) + { + free(pRangeInfo[i].pRanges); + } + free(pRangeInfo); + return err; +} /* ProcRecordGetContext */ + + +static int +ProcRecordEnableContext(ClientPtr client) +{ + RecordContextPtr pContext; + REQUEST(xRecordEnableContextReq); + int i; + RecordClientsAndProtocolPtr pRCAP; + + REQUEST_SIZE_MATCH(xRecordGetContextReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + if (pContext->pRecordingClient) + return BadMatch; /* already enabled */ + + /* install record hooks for each RCAP */ + + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + { + int err = RecordInstallHooks(pRCAP, 0); + if (err != Success) + { /* undo the previous installs */ + RecordClientsAndProtocolPtr pUninstallRCAP; + for (pUninstallRCAP = pContext->pListOfRCAP; + pUninstallRCAP != pRCAP; + pUninstallRCAP = pUninstallRCAP->pNextRCAP) + { + RecordUninstallHooks(pUninstallRCAP, 0); + } + return err; + } + } + + /* Disallow further request processing on this connection until + * the context is disabled. + */ + IgnoreClient(client); + pContext->pRecordingClient = client; + + /* Don't allow the data connection to record itself; unregister it. */ + RecordDeleteClientFromContext(pContext, + pContext->pRecordingClient->clientAsMask); + + /* move the newly enabled context to the front part of ppAllContexts, + * where all the enabled contexts are + */ + i = RecordFindContextOnAllContexts(pContext); + assert(i >= numEnabledContexts); + if (i != numEnabledContexts) + { + ppAllContexts[i] = ppAllContexts[numEnabledContexts]; + ppAllContexts[numEnabledContexts] = pContext; + } + + ++numEnabledContexts; + assert(numEnabledContexts > 0); + + /* send StartOfData */ + RecordAProtocolElement(pContext, NULL, XRecordStartOfData, NULL, 0, 0); + RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); + return Success; +} /* ProcRecordEnableContext */ + + +/* RecordDisableContext + * + * Arguments: + * pContext is the context to disable. + * nRanges is the number of elements in pRanges. + * + * Returns: nothing. + * + * Side Effects: + * If the context was enabled, it is disabled. An EndOfData + * message is sent to the recording client. Recording hooks for + * this context are uninstalled. The context is moved to the + * rear part of the ppAllContexts array. numEnabledContexts is + * decremented. Request processing for the formerly recording client + * is resumed. + */ +static void +RecordDisableContext(RecordContextPtr pContext) +{ + RecordClientsAndProtocolPtr pRCAP; + int i; + + if (!pContext->pRecordingClient) return; + if (!pContext->pRecordingClient->clientGone) + { + RecordAProtocolElement(pContext, NULL, XRecordEndOfData, NULL, 0, 0); + RecordFlushReplyBuffer(pContext, NULL, 0, NULL, 0); + /* Re-enable request processing on this connection. */ + AttendClient(pContext->pRecordingClient); + } + + for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) + { + RecordUninstallHooks(pRCAP, 0); + } + + pContext->pRecordingClient = NULL; + + /* move the newly disabled context to the rear part of ppAllContexts, + * where all the disabled contexts are + */ + i = RecordFindContextOnAllContexts(pContext); + assert( (i != -1) && (i < numEnabledContexts) ); + if (i != (numEnabledContexts - 1) ) + { + ppAllContexts[i] = ppAllContexts[numEnabledContexts-1]; + ppAllContexts[numEnabledContexts-1] = pContext; + } + --numEnabledContexts; + assert(numEnabledContexts >= 0); +} /* RecordDisableContext */ + + +static int +ProcRecordDisableContext(ClientPtr client) +{ + RecordContextPtr pContext; + REQUEST(xRecordDisableContextReq); + + REQUEST_SIZE_MATCH(xRecordDisableContextReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + RecordDisableContext(pContext); + return Success; +} /* ProcRecordDisableContext */ + + +/* RecordDeleteContext + * + * Arguments: + * value is the context to delete. + * id is its resource ID. + * + * Returns: Success. + * + * Side Effects: + * Disables the context, frees all associated memory, and removes + * it from the ppAllContexts array. + */ +static int +RecordDeleteContext(pointer value, XID id) +{ + int i; + RecordContextPtr pContext = (RecordContextPtr)value; + RecordClientsAndProtocolPtr pRCAP; + + RecordDisableContext(pContext); + + /* Remove all the clients from all the RCAPs. + * As a result, the RCAPs will be freed. + */ + + while ((pRCAP = pContext->pListOfRCAP)) + { + int numClients = pRCAP->numClients; + /* when the last client is deleted, the RCAP will go away. */ + while(numClients--) + { + RecordDeleteClientFromRCAP(pRCAP, numClients); + } + } + + /* remove context from AllContexts list */ + + if (-1 != (i = RecordFindContextOnAllContexts(pContext))) + { + ppAllContexts[i] = ppAllContexts[numContexts - 1]; + if (--numContexts == 0) + { + free(ppAllContexts); + ppAllContexts = NULL; + } + } + free(pContext); + + return Success; +} /* RecordDeleteContext */ + + +static int +ProcRecordFreeContext(ClientPtr client) +{ + RecordContextPtr pContext; + REQUEST(xRecordFreeContextReq); + + REQUEST_SIZE_MATCH(xRecordFreeContextReq); + VERIFY_CONTEXT(pContext, stuff->context, client); + FreeResource(stuff->context, RT_NONE); + return Success; +} /* ProcRecordFreeContext */ + + +static int +ProcRecordDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_RecordQueryVersion: + return ProcRecordQueryVersion(client); + case X_RecordCreateContext: + return ProcRecordCreateContext(client); + case X_RecordRegisterClients: + return ProcRecordRegisterClients(client); + case X_RecordUnregisterClients: + return ProcRecordUnregisterClients(client); + case X_RecordGetContext: + return ProcRecordGetContext(client); + case X_RecordEnableContext: + return ProcRecordEnableContext(client); + case X_RecordDisableContext: + return ProcRecordDisableContext(client); + case X_RecordFreeContext: + return ProcRecordFreeContext(client); + default: + return BadRequest; + } +} /* ProcRecordDispatch */ + + +static int +SProcRecordQueryVersion(ClientPtr client) +{ + REQUEST(xRecordQueryVersionReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordQueryVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion,n); + return ProcRecordQueryVersion(client); +} /* SProcRecordQueryVersion */ + + +static int +SwapCreateRegister(xRecordRegisterClientsReq *stuff) +{ + register char n; + int i; + XID *pClientID; + + swapl(&stuff->context, n); + swapl(&stuff->nClients, n); + swapl(&stuff->nRanges, n); + pClientID = (XID *)&stuff[1]; + if (stuff->nClients > stuff->length - bytes_to_int32(sz_xRecordRegisterClientsReq)) + return BadLength; + for (i = 0; i < stuff->nClients; i++, pClientID++) + { + swapl(pClientID, n); + } + if (stuff->nRanges > stuff->length - bytes_to_int32(sz_xRecordRegisterClientsReq) + - stuff->nClients) + return BadLength; + RecordSwapRanges((xRecordRange *)pClientID, stuff->nRanges); + return Success; +} /* SwapCreateRegister */ + + +static int +SProcRecordCreateContext(ClientPtr client) +{ + REQUEST(xRecordCreateContextReq); + int status; + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq); + if ((status = SwapCreateRegister((pointer)stuff)) != Success) + return status; + return ProcRecordCreateContext(client); +} /* SProcRecordCreateContext */ + + +static int +SProcRecordRegisterClients(ClientPtr client) +{ + REQUEST(xRecordRegisterClientsReq); + int status; + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq); + if ((status = SwapCreateRegister((pointer)stuff)) != Success) + return status; + return ProcRecordRegisterClients(client); +} /* SProcRecordRegisterClients */ + + +static int +SProcRecordUnregisterClients(ClientPtr client) +{ + REQUEST(xRecordUnregisterClientsReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq); + swapl(&stuff->context, n); + swapl(&stuff->nClients, n); + SwapRestL(stuff); + return ProcRecordUnregisterClients(client); +} /* SProcRecordUnregisterClients */ + + +static int +SProcRecordGetContext(ClientPtr client) +{ + REQUEST(xRecordGetContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordGetContextReq); + swapl(&stuff->context, n); + return ProcRecordGetContext(client); +} /* SProcRecordGetContext */ + +static int +SProcRecordEnableContext(ClientPtr client) +{ + REQUEST(xRecordEnableContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordEnableContextReq); + swapl(&stuff->context, n); + return ProcRecordEnableContext(client); +} /* SProcRecordEnableContext */ + + +static int +SProcRecordDisableContext(ClientPtr client) +{ + REQUEST(xRecordDisableContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordDisableContextReq); + swapl(&stuff->context, n); + return ProcRecordDisableContext(client); +} /* SProcRecordDisableContext */ + + +static int +SProcRecordFreeContext(ClientPtr client) +{ + REQUEST(xRecordFreeContextReq); + register char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xRecordFreeContextReq); + swapl(&stuff->context, n); + return ProcRecordFreeContext(client); +} /* SProcRecordFreeContext */ + + +static int +SProcRecordDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_RecordQueryVersion: + return SProcRecordQueryVersion(client); + case X_RecordCreateContext: + return SProcRecordCreateContext(client); + case X_RecordRegisterClients: + return SProcRecordRegisterClients(client); + case X_RecordUnregisterClients: + return SProcRecordUnregisterClients(client); + case X_RecordGetContext: + return SProcRecordGetContext(client); + case X_RecordEnableContext: + return SProcRecordEnableContext(client); + case X_RecordDisableContext: + return SProcRecordDisableContext(client); + case X_RecordFreeContext: + return SProcRecordFreeContext(client); + default: + return BadRequest; + } +} /* SProcRecordDispatch */ + +/* RecordConnectionSetupInfo + * + * Arguments: + * pContext is an enabled context that specifies recording of + * connection setup info. + * pci holds the connection setup info. + * + * Returns: nothing. + * + * Side Effects: + * The connection setup info is sent to the recording client. + */ +static void +RecordConnectionSetupInfo(RecordContextPtr pContext, NewClientInfoRec *pci) +{ + int prefixsize = SIZEOF(xConnSetupPrefix); + int restsize = pci->prefix->length * 4; + + if (pci->client->swapped) + { + char *pConnSetup = (char *)malloc(prefixsize + restsize); + if (!pConnSetup) + return; + SwapConnSetupPrefix(pci->prefix, (xConnSetupPrefix*)pConnSetup); + SwapConnSetupInfo((char*)pci->setup, (char*)(pConnSetup + prefixsize)); + RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, + (pointer)pConnSetup, prefixsize + restsize, 0); + free(pConnSetup); + } + else + { + /* don't alloc and copy as in the swapped case; just send the + * data in two pieces + */ + RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, + (pointer)pci->prefix, prefixsize, restsize); + RecordAProtocolElement(pContext, pci->client, XRecordClientStarted, + (pointer)pci->setup, restsize, /* continuation */ -1); + } +} /* RecordConnectionSetupInfo */ + + +/* RecordDeleteContext + * + * Arguments: + * pcbl is &ClientStateCallback. + * nullata is NULL. + * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) + * which contains information about client state changes. + * + * Returns: nothing. + * + * Side Effects: + * If a new client has connected and any contexts have specified + * XRecordFutureClients, the new client is registered on those contexts. + * If any of those contexts specify recording of the connection setup + * info, it is recorded. + * + * If an existing client has disconnected, it is deleted from any + * contexts that it was registered on. If any of those contexts + * specified XRecordClientDied, they record a ClientDied protocol element. + * If the disconnectiong client happened to be the data connection of an + * enabled context, the context is disabled. + */ + +static void +RecordAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) +{ + NewClientInfoRec *pci = (NewClientInfoRec *)calldata; + int i; + ClientPtr pClient = pci->client; + RecordContextPtr *ppAllContextsCopy = NULL; + int numContextsCopy = 0; + + switch (pClient->clientState) + { + case ClientStateRunning: /* new client */ + for (i = 0; i < numContexts; i++) + { + RecordClientsAndProtocolPtr pRCAP; + RecordContextPtr pContext = ppAllContexts[i]; + + if ((pRCAP = RecordFindClientOnContext(pContext, + XRecordFutureClients, NULL))) + { + RecordAddClientToRCAP(pRCAP, pClient->clientAsMask); + if (pContext->pRecordingClient && pRCAP->clientStarted) + RecordConnectionSetupInfo(pContext, pci); + } + } + break; + + case ClientStateGone: + case ClientStateRetained: /* client disconnected */ + + /* RecordDisableContext modifies contents of ppAllContexts. */ + numContextsCopy = numContexts; + ppAllContextsCopy = malloc(numContextsCopy * sizeof(RecordContextPtr)); + assert(ppAllContextsCopy); + memcpy(ppAllContextsCopy, ppAllContexts, numContextsCopy * sizeof(RecordContextPtr)); + + for (i = 0; i < numContextsCopy; i++) + { + RecordClientsAndProtocolPtr pRCAP; + RecordContextPtr pContext = ppAllContextsCopy[i]; + int pos; + + if (pContext->pRecordingClient == pClient) + RecordDisableContext(pContext); + if ((pRCAP = RecordFindClientOnContext(pContext, + pClient->clientAsMask, &pos))) + { + if (pContext->pRecordingClient && pRCAP->clientDied) + RecordAProtocolElement(pContext, pClient, + XRecordClientDied, NULL, 0, 0); + RecordDeleteClientFromRCAP(pRCAP, pos); + } + } + + free(ppAllContextsCopy); + break; + + default: + break; + } /* end switch on client state */ +} /* RecordAClientStateChange */ + + +/* RecordCloseDown + * + * Arguments: + * extEntry is the extension information for RECORD. + * + * Returns: nothing. + * + * Side Effects: + * Performs any cleanup needed by RECORD at server shutdown time. + * + */ +static void +RecordCloseDown(ExtensionEntry *extEntry) +{ + DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL); +} /* RecordCloseDown */ + + +/* RecordExtensionInit + * + * Arguments: none. + * + * Returns: nothing. + * + * Side Effects: + * Enables the RECORD extension if possible. + */ +void +RecordExtensionInit(void) +{ + ExtensionEntry *extentry; + + RTContext = CreateNewResourceType(RecordDeleteContext, "RecordContext"); + if (!RTContext) + return; + + if (!dixRegisterPrivateKey(RecordClientPrivateKey, PRIVATE_CLIENT, 0)) + return; + + ppAllContexts = NULL; + numContexts = numEnabledContexts = numEnabledRCAPs = 0; + + if (!AddCallback(&ClientStateCallback, RecordAClientStateChange, NULL)) + return; + + extentry = AddExtension(RECORD_NAME, RecordNumEvents, RecordNumErrors, + ProcRecordDispatch, SProcRecordDispatch, + RecordCloseDown, StandardMinorOpcode); + if (!extentry) + { + DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL); + return; + } + SetResourceTypeErrorValue(RTContext, extentry->errorBase + XRecordBadContext); + +} /* RecordExtensionInit */ + diff --git a/xorg-server/render/mipict.c b/xorg-server/render/mipict.c index 3b7388879..1623b335f 100644 --- a/xorg-server/render/mipict.c +++ b/xorg-server/render/mipict.c @@ -1,644 +1,610 @@ -/* - * - * Copyright © 1999 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 -#endif - -#include "scrnintstr.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "mi.h" -#include "picturestr.h" -#include "mipict.h" - -#ifndef __GNUC__ -#define __inline -#endif - -int -miCreatePicture (PicturePtr pPicture) -{ - return Success; -} - -void -miDestroyPicture (PicturePtr pPicture) -{ - if (pPicture->freeCompClip) - RegionDestroy(pPicture->pCompositeClip); -} - -void -miDestroyPictureClip (PicturePtr pPicture) -{ - switch (pPicture->clientClipType) { - case CT_NONE: - return; - case CT_PIXMAP: - (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip)); - break; - default: - /* - * we know we'll never have a list of rectangles, since ChangeClip - * immediately turns them into a region - */ - RegionDestroy(pPicture->clientClip); - break; - } - pPicture->clientClip = NULL; - pPicture->clientClipType = CT_NONE; -} - -int -miChangePictureClip (PicturePtr pPicture, - int type, - pointer value, - int n) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - pointer clientClip; - int clientClipType; - - switch (type) { - case CT_PIXMAP: - /* convert the pixmap to a region */ - clientClip = (pointer) BitmapToRegion(pScreen, (PixmapPtr) value); - if (!clientClip) - return BadAlloc; - clientClipType = CT_REGION; - (*pScreen->DestroyPixmap) ((PixmapPtr) value); - break; - case CT_REGION: - clientClip = value; - clientClipType = CT_REGION; - break; - case CT_NONE: - clientClip = 0; - clientClipType = CT_NONE; - break; - default: - clientClip = (pointer) RegionFromRects(n, - (xRectangle *) value, - type); - if (!clientClip) - return BadAlloc; - clientClipType = CT_REGION; - free(value); - break; - } - (*ps->DestroyPictureClip) (pPicture); - pPicture->clientClip = clientClip; - pPicture->clientClipType = clientClipType; - pPicture->stateChanges |= CPClipMask; - return Success; -} - -void -miChangePicture (PicturePtr pPicture, - Mask mask) -{ - return; -} - -void -miValidatePicture (PicturePtr pPicture, - Mask mask) -{ - DrawablePtr pDrawable = pPicture->pDrawable; - - if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) || - (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) - { - if (pDrawable->type == DRAWABLE_WINDOW) - { - WindowPtr pWin = (WindowPtr) pDrawable; - RegionPtr pregWin; - Bool freeTmpClip, freeCompClip; - - if (pPicture->subWindowMode == IncludeInferiors) - { - pregWin = NotClippedByChildren(pWin); - freeTmpClip = TRUE; - } - else - { - pregWin = &pWin->clipList; - freeTmpClip = FALSE; - } - freeCompClip = pPicture->freeCompClip; - - /* - * if there is no client clip, we can get by with just keeping the - * pointer we got, and remembering whether or not should destroy - * (or maybe re-use) it later. this way, we avoid unnecessary - * copying of regions. (this wins especially if many clients clip - * by children and have no client clip.) - */ - if (pPicture->clientClipType == CT_NONE) - { - if (freeCompClip) - RegionDestroy(pPicture->pCompositeClip); - pPicture->pCompositeClip = pregWin; - pPicture->freeCompClip = freeTmpClip; - } - else - { - /* - * we need one 'real' region to put into the composite clip. if - * pregWin the current composite clip are real, we can get rid of - * one. if pregWin is real and the current composite clip isn't, - * use pregWin for the composite clip. if the current composite - * clip is real and pregWin isn't, use the current composite - * clip. if neither is real, create a new region. - */ - - RegionTranslate(pPicture->clientClip, - pDrawable->x + pPicture->clipOrigin.x, - pDrawable->y + pPicture->clipOrigin.y); - - if (freeCompClip) - { - RegionIntersect(pPicture->pCompositeClip, - pregWin, pPicture->clientClip); - if (freeTmpClip) - RegionDestroy(pregWin); - } - else if (freeTmpClip) - { - RegionIntersect(pregWin, pregWin, pPicture->clientClip); - pPicture->pCompositeClip = pregWin; - } - else - { - pPicture->pCompositeClip = RegionCreate(NullBox, 0); - RegionIntersect(pPicture->pCompositeClip, - pregWin, pPicture->clientClip); - } - pPicture->freeCompClip = TRUE; - RegionTranslate(pPicture->clientClip, - -(pDrawable->x + pPicture->clipOrigin.x), - -(pDrawable->y + pPicture->clipOrigin.y)); - } - } /* end of composite clip for a window */ - else - { - BoxRec pixbounds; - - /* XXX should we translate by drawable.x/y here ? */ - /* If you want pixmaps in offscreen memory, yes */ - pixbounds.x1 = pDrawable->x; - pixbounds.y1 = pDrawable->y; - pixbounds.x2 = pDrawable->x + pDrawable->width; - pixbounds.y2 = pDrawable->y + pDrawable->height; - - if (pPicture->freeCompClip) - { - RegionReset(pPicture->pCompositeClip, &pixbounds); - } - else - { - pPicture->freeCompClip = TRUE; - pPicture->pCompositeClip = RegionCreate(&pixbounds, 1); - } - - if (pPicture->clientClipType == CT_REGION) - { - if(pDrawable->x || pDrawable->y) { - RegionTranslate(pPicture->clientClip, - pDrawable->x + pPicture->clipOrigin.x, - pDrawable->y + pPicture->clipOrigin.y); - RegionIntersect(pPicture->pCompositeClip, - pPicture->pCompositeClip, pPicture->clientClip); - RegionTranslate(pPicture->clientClip, - -(pDrawable->x + pPicture->clipOrigin.x), - -(pDrawable->y + pPicture->clipOrigin.y)); - } else { - RegionTranslate(pPicture->pCompositeClip, - -pPicture->clipOrigin.x, -pPicture->clipOrigin.y); - RegionIntersect(pPicture->pCompositeClip, - pPicture->pCompositeClip, pPicture->clientClip); - RegionTranslate(pPicture->pCompositeClip, - pPicture->clipOrigin.x, pPicture->clipOrigin.y); - } - } - } /* end of composite clip for pixmap */ - } -} - -int -miChangePictureTransform (PicturePtr pPicture, - PictTransform *transform) -{ - return Success; -} - -int -miChangePictureFilter (PicturePtr pPicture, - int filter, - xFixed *params, - int nparams) -{ - return Success; -} - -#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v)) - -static inline pixman_bool_t -miClipPictureReg (pixman_region16_t * pRegion, - pixman_region16_t * pClip, - int dx, - int dy) -{ - if (pixman_region_n_rects(pRegion) == 1 && - pixman_region_n_rects(pClip) == 1) - { - pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL); - pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL); - int v; - - if (pRbox->x1 < (v = pCbox->x1 + dx)) - pRbox->x1 = BOUND(v); - if (pRbox->x2 > (v = pCbox->x2 + dx)) - pRbox->x2 = BOUND(v); - if (pRbox->y1 < (v = pCbox->y1 + dy)) - pRbox->y1 = BOUND(v); - if (pRbox->y2 > (v = pCbox->y2 + dy)) - pRbox->y2 = BOUND(v); - if (pRbox->x1 >= pRbox->x2 || - pRbox->y1 >= pRbox->y2) - { - pixman_region_init (pRegion); - } - } - else if (!pixman_region_not_empty (pClip)) - return FALSE; - else - { - if (dx || dy) - pixman_region_translate (pRegion, -dx, -dy); - if (!pixman_region_intersect (pRegion, pRegion, pClip)) - return FALSE; - if (dx || dy) - pixman_region_translate(pRegion, dx, dy); - } - return pixman_region_not_empty(pRegion); -} - -static __inline Bool -miClipPictureSrc (RegionPtr pRegion, - PicturePtr pPicture, - int dx, - int dy) -{ - if (pPicture->clientClipType != CT_NONE) - { - Bool result; - - pixman_region_translate ( pPicture->clientClip, - pPicture->clipOrigin.x + dx, - pPicture->clipOrigin.y + dy); - - result = RegionIntersect(pRegion, pRegion, pPicture->clientClip); - - pixman_region_translate ( pPicture->clientClip, - - (pPicture->clipOrigin.x + dx), - - (pPicture->clipOrigin.y + dy)); - - if (!result) - return FALSE; - } - return TRUE; -} - -void -miCompositeSourceValidate (PicturePtr pPicture, - INT16 x, - INT16 y, - CARD16 width, - CARD16 height) -{ - DrawablePtr pDrawable = pPicture->pDrawable; - ScreenPtr pScreen; - - if (!pDrawable) - return; - - pScreen = pDrawable->pScreen; - - if (pScreen->SourceValidate) - { - if (pPicture->transform) - { - xPoint points[4]; - int i; - int xmin, ymin, xmax, ymax; - -#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; } - VectorSet (0, x, y); - VectorSet (1, x + width, y); - VectorSet (2, x, y + height); - VectorSet (3, x + width, y + height); - xmin = ymin = 32767; - xmax = ymax = -32737; - for (i = 0; i < 4; i++) - { - PictVector t; - t.vector[0] = IntToxFixed (points[i].x); - t.vector[1] = IntToxFixed (points[i].y); - t.vector[2] = xFixed1; - if (pixman_transform_point (pPicture->transform, &t)) - { - int tx = xFixedToInt (t.vector[0]); - int ty = xFixedToInt (t.vector[1]); - if (tx < xmin) xmin = tx; - if (tx > xmax) xmax = tx; - if (ty < ymin) ymin = ty; - if (ty > ymax) ymax = ty; - } - } - x = xmin; - y = ymin; - width = xmax - xmin; - height = ymax - ymin; - } - x += pPicture->pDrawable->x; - y += pPicture->pDrawable->y; - (*pScreen->SourceValidate) (pDrawable, x, y, width, height, - pPicture->subWindowMode); - } -} - -/* - * returns FALSE if the final region is empty. Indistinguishable from - * an allocation failure, but rendering ignores those anyways. - */ - -Bool -miComputeCompositeRegion (RegionPtr pRegion, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height) -{ - - int v; - - pRegion->extents.x1 = xDst; - v = xDst + width; - pRegion->extents.x2 = BOUND(v); - pRegion->extents.y1 = yDst; - v = yDst + height; - pRegion->extents.y2 = BOUND(v); - pRegion->data = 0; - /* Check for empty operation */ - if (pRegion->extents.x1 >= pRegion->extents.x2 || - pRegion->extents.y1 >= pRegion->extents.y2) - { - pixman_region_init (pRegion); - return FALSE; - } - /* clip against dst */ - if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0)) - { - pixman_region_fini (pRegion); - return FALSE; - } - if (pDst->alphaMap) - { - if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip, - -pDst->alphaOrigin.x, - -pDst->alphaOrigin.y)) - { - pixman_region_fini (pRegion); - return FALSE; - } - } - /* clip against src */ - if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc)) - { - pixman_region_fini (pRegion); - return FALSE; - } - if (pSrc->alphaMap) - { - if (!miClipPictureSrc (pRegion, pSrc->alphaMap, - xDst - (xSrc - pSrc->alphaOrigin.x), - yDst - (ySrc - pSrc->alphaOrigin.y))) - { - pixman_region_fini (pRegion); - return FALSE; - } - } - /* clip against mask */ - if (pMask) - { - if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask)) - { - pixman_region_fini (pRegion); - return FALSE; - } - if (pMask->alphaMap) - { - if (!miClipPictureSrc (pRegion, pMask->alphaMap, - xDst - (xMask - pMask->alphaOrigin.x), - yDst - (yMask - pMask->alphaOrigin.y))) - { - pixman_region_fini (pRegion); - return FALSE; - } - } - } - - - miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height); - if (pMask) - miCompositeSourceValidate (pMask, xMask, yMask, width, height); - - return TRUE; -} - -void -miRenderColorToPixel (PictFormatPtr format, - xRenderColor *color, - CARD32 *pixel) -{ - CARD32 r, g, b, a; - miIndexedPtr pIndexed; - - switch (format->type) { - case PictTypeDirect: - r = color->red >> (16 - Ones (format->direct.redMask)); - g = color->green >> (16 - Ones (format->direct.greenMask)); - b = color->blue >> (16 - Ones (format->direct.blueMask)); - a = color->alpha >> (16 - Ones (format->direct.alphaMask)); - r = r << format->direct.red; - g = g << format->direct.green; - b = b << format->direct.blue; - a = a << format->direct.alpha; - *pixel = r|g|b|a; - break; - case PictTypeIndexed: - pIndexed = (miIndexedPtr) (format->index.devPrivate); - if (pIndexed->color) - { - r = color->red >> 11; - g = color->green >> 11; - b = color->blue >> 11; - *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b); - } - else - { - r = color->red >> 8; - g = color->green >> 8; - b = color->blue >> 8; - *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b); - } - break; - } -} - -static CARD16 -miFillColor (CARD32 pixel, int bits) -{ - while (bits < 16) - { - pixel |= pixel << bits; - bits <<= 1; - } - return (CARD16) pixel; -} - -Bool -miIsSolidAlpha (PicturePtr pSrc) -{ - ScreenPtr pScreen; - char line[1]; - - if (!pSrc->pDrawable) - return FALSE; - - pScreen = pSrc->pDrawable->pScreen; - - /* Alpha-only */ - if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A) - return FALSE; - /* repeat */ - if (!pSrc->repeat) - return FALSE; - /* 1x1 */ - if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) - return FALSE; - line[0] = 1; - (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line); - switch (pSrc->pDrawable->bitsPerPixel) { - case 1: - return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80; - case 4: - return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0; - case 8: - return (CARD8) line[0] == 0xff; - default: - return FALSE; - } -} - -void -miRenderPixelToColor (PictFormatPtr format, - CARD32 pixel, - xRenderColor *color) -{ - CARD32 r, g, b, a; - miIndexedPtr pIndexed; - - switch (format->type) { - case PictTypeDirect: - r = (pixel >> format->direct.red) & format->direct.redMask; - g = (pixel >> format->direct.green) & format->direct.greenMask; - b = (pixel >> format->direct.blue) & format->direct.blueMask; - a = (pixel >> format->direct.alpha) & format->direct.alphaMask; - color->red = miFillColor (r, Ones (format->direct.redMask)); - color->green = miFillColor (g, Ones (format->direct.greenMask)); - color->blue = miFillColor (b, Ones (format->direct.blueMask)); - color->alpha = miFillColor (a, Ones (format->direct.alphaMask)); - break; - case PictTypeIndexed: - pIndexed = (miIndexedPtr) (format->index.devPrivate); - pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)]; - r = (pixel >> 16) & 0xff; - g = (pixel >> 8) & 0xff; - b = (pixel ) & 0xff; - color->red = miFillColor (r, 8); - color->green = miFillColor (g, 8); - color->blue = miFillColor (b, 8); - color->alpha = 0xffff; - break; - } -} - -Bool -miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) -{ - PictureScreenPtr ps; - - if (!PictureInit (pScreen, formats, nformats)) - return FALSE; - ps = GetPictureScreen(pScreen); - ps->CreatePicture = miCreatePicture; - ps->DestroyPicture = miDestroyPicture; - ps->ChangePictureClip = miChangePictureClip; - ps->DestroyPictureClip = miDestroyPictureClip; - ps->ChangePicture = miChangePicture; - ps->ValidatePicture = miValidatePicture; - ps->InitIndexed = miInitIndexed; - ps->CloseIndexed = miCloseIndexed; - ps->UpdateIndexed = miUpdateIndexed; - ps->ChangePictureTransform = miChangePictureTransform; - ps->ChangePictureFilter = miChangePictureFilter; - ps->RealizeGlyph = miRealizeGlyph; - ps->UnrealizeGlyph = miUnrealizeGlyph; - - /* MI rendering routines */ - ps->Composite = 0; /* requires DDX support */ - ps->Glyphs = miGlyphs; - ps->CompositeRects = miCompositeRects; - ps->Trapezoids = 0; - ps->Triangles = 0; - ps->TriStrip = miTriStrip; - ps->TriFan = miTriFan; - - ps->RasterizeTrapezoid = 0; /* requires DDX support */ - ps->AddTraps = 0; /* requires DDX support */ - ps->AddTriangles = 0; /* requires DDX support */ - - return TRUE; -} +/* + * + * Copyright © 1999 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 +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +#ifndef __GNUC__ +#define __inline +#endif + +int +miCreatePicture (PicturePtr pPicture) +{ + return Success; +} + +void +miDestroyPicture (PicturePtr pPicture) +{ + if (pPicture->freeCompClip) + RegionDestroy(pPicture->pCompositeClip); +} + +void +miDestroyPictureClip (PicturePtr pPicture) +{ + switch (pPicture->clientClipType) { + case CT_NONE: + return; + case CT_PIXMAP: + (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip)); + break; + default: + /* + * we know we'll never have a list of rectangles, since ChangeClip + * immediately turns them into a region + */ + RegionDestroy(pPicture->clientClip); + break; + } + pPicture->clientClip = NULL; + pPicture->clientClipType = CT_NONE; +} + +int +miChangePictureClip (PicturePtr pPicture, + int type, + pointer value, + int n) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + pointer clientClip; + int clientClipType; + + switch (type) { + case CT_PIXMAP: + /* convert the pixmap to a region */ + clientClip = (pointer) BitmapToRegion(pScreen, (PixmapPtr) value); + if (!clientClip) + return BadAlloc; + clientClipType = CT_REGION; + (*pScreen->DestroyPixmap) ((PixmapPtr) value); + break; + case CT_REGION: + clientClip = value; + clientClipType = CT_REGION; + break; + case CT_NONE: + clientClip = 0; + clientClipType = CT_NONE; + break; + default: + clientClip = (pointer) RegionFromRects(n, + (xRectangle *) value, + type); + if (!clientClip) + return BadAlloc; + clientClipType = CT_REGION; + free(value); + break; + } + (*ps->DestroyPictureClip) (pPicture); + pPicture->clientClip = clientClip; + pPicture->clientClipType = clientClipType; + pPicture->stateChanges |= CPClipMask; + return Success; +} + +void +miChangePicture (PicturePtr pPicture, + Mask mask) +{ + return; +} + +void +miValidatePicture (PicturePtr pPicture, + Mask mask) +{ + DrawablePtr pDrawable = pPicture->pDrawable; + + if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) || + (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) + { + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDrawable; + RegionPtr pregWin; + Bool freeTmpClip, freeCompClip; + + if (pPicture->subWindowMode == IncludeInferiors) + { + pregWin = NotClippedByChildren(pWin); + freeTmpClip = TRUE; + } + else + { + pregWin = &pWin->clipList; + freeTmpClip = FALSE; + } + freeCompClip = pPicture->freeCompClip; + + /* + * if there is no client clip, we can get by with just keeping the + * pointer we got, and remembering whether or not should destroy + * (or maybe re-use) it later. this way, we avoid unnecessary + * copying of regions. (this wins especially if many clients clip + * by children and have no client clip.) + */ + if (pPicture->clientClipType == CT_NONE) + { + if (freeCompClip) + RegionDestroy(pPicture->pCompositeClip); + pPicture->pCompositeClip = pregWin; + pPicture->freeCompClip = freeTmpClip; + } + else + { + /* + * we need one 'real' region to put into the composite clip. if + * pregWin the current composite clip are real, we can get rid of + * one. if pregWin is real and the current composite clip isn't, + * use pregWin for the composite clip. if the current composite + * clip is real and pregWin isn't, use the current composite + * clip. if neither is real, create a new region. + */ + + RegionTranslate(pPicture->clientClip, + pDrawable->x + pPicture->clipOrigin.x, + pDrawable->y + pPicture->clipOrigin.y); + + if (freeCompClip) + { + RegionIntersect(pPicture->pCompositeClip, + pregWin, pPicture->clientClip); + if (freeTmpClip) + RegionDestroy(pregWin); + } + else if (freeTmpClip) + { + RegionIntersect(pregWin, pregWin, pPicture->clientClip); + pPicture->pCompositeClip = pregWin; + } + else + { + pPicture->pCompositeClip = RegionCreate(NullBox, 0); + RegionIntersect(pPicture->pCompositeClip, + pregWin, pPicture->clientClip); + } + pPicture->freeCompClip = TRUE; + RegionTranslate(pPicture->clientClip, + -(pDrawable->x + pPicture->clipOrigin.x), + -(pDrawable->y + pPicture->clipOrigin.y)); + } + } /* end of composite clip for a window */ + else + { + BoxRec pixbounds; + + /* XXX should we translate by drawable.x/y here ? */ + /* If you want pixmaps in offscreen memory, yes */ + pixbounds.x1 = pDrawable->x; + pixbounds.y1 = pDrawable->y; + pixbounds.x2 = pDrawable->x + pDrawable->width; + pixbounds.y2 = pDrawable->y + pDrawable->height; + + if (pPicture->freeCompClip) + { + RegionReset(pPicture->pCompositeClip, &pixbounds); + } + else + { + pPicture->freeCompClip = TRUE; + pPicture->pCompositeClip = RegionCreate(&pixbounds, 1); + } + + if (pPicture->clientClipType == CT_REGION) + { + if(pDrawable->x || pDrawable->y) { + RegionTranslate(pPicture->clientClip, + pDrawable->x + pPicture->clipOrigin.x, + pDrawable->y + pPicture->clipOrigin.y); + RegionIntersect(pPicture->pCompositeClip, + pPicture->pCompositeClip, pPicture->clientClip); + RegionTranslate(pPicture->clientClip, + -(pDrawable->x + pPicture->clipOrigin.x), + -(pDrawable->y + pPicture->clipOrigin.y)); + } else { + RegionTranslate(pPicture->pCompositeClip, + -pPicture->clipOrigin.x, -pPicture->clipOrigin.y); + RegionIntersect(pPicture->pCompositeClip, + pPicture->pCompositeClip, pPicture->clientClip); + RegionTranslate(pPicture->pCompositeClip, + pPicture->clipOrigin.x, pPicture->clipOrigin.y); + } + } + } /* end of composite clip for pixmap */ + } +} + +int +miChangePictureTransform (PicturePtr pPicture, + PictTransform *transform) +{ + return Success; +} + +int +miChangePictureFilter (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams) +{ + return Success; +} + +#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v)) + +static inline pixman_bool_t +miClipPictureReg (pixman_region16_t * pRegion, + pixman_region16_t * pClip, + int dx, + int dy) +{ + if (pixman_region_n_rects(pRegion) == 1 && + pixman_region_n_rects(pClip) == 1) + { + pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL); + pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL); + int v; + + if (pRbox->x1 < (v = pCbox->x1 + dx)) + pRbox->x1 = BOUND(v); + if (pRbox->x2 > (v = pCbox->x2 + dx)) + pRbox->x2 = BOUND(v); + if (pRbox->y1 < (v = pCbox->y1 + dy)) + pRbox->y1 = BOUND(v); + if (pRbox->y2 > (v = pCbox->y2 + dy)) + pRbox->y2 = BOUND(v); + if (pRbox->x1 >= pRbox->x2 || + pRbox->y1 >= pRbox->y2) + { + pixman_region_init (pRegion); + } + } + else if (!pixman_region_not_empty (pClip)) + return FALSE; + else + { + if (dx || dy) + pixman_region_translate (pRegion, -dx, -dy); + if (!pixman_region_intersect (pRegion, pRegion, pClip)) + return FALSE; + if (dx || dy) + pixman_region_translate(pRegion, dx, dy); + } + return pixman_region_not_empty(pRegion); +} + +static __inline Bool +miClipPictureSrc (RegionPtr pRegion, + PicturePtr pPicture, + int dx, + int dy) +{ + if (pPicture->clientClipType != CT_NONE) + { + Bool result; + + pixman_region_translate ( pPicture->clientClip, + pPicture->clipOrigin.x + dx, + pPicture->clipOrigin.y + dy); + + result = RegionIntersect(pRegion, pRegion, pPicture->clientClip); + + pixman_region_translate ( pPicture->clientClip, + - (pPicture->clipOrigin.x + dx), + - (pPicture->clipOrigin.y + dy)); + + if (!result) + return FALSE; + } + return TRUE; +} + +static void +SourceValidateOnePicture (PicturePtr pPicture) +{ + DrawablePtr pDrawable = pPicture->pDrawable; + ScreenPtr pScreen; + + if (!pDrawable) + return; + + pScreen = pDrawable->pScreen; + + if (pScreen->SourceValidate) + { + pScreen->SourceValidate ( + pDrawable, 0, 0, pDrawable->width, pDrawable->height, pPicture->subWindowMode); + } +} + +void +miCompositeSourceValidate (PicturePtr pPicture) +{ + SourceValidateOnePicture (pPicture); + if (pPicture->alphaMap) + SourceValidateOnePicture (pPicture->alphaMap); +} + +/* + * returns FALSE if the final region is empty. Indistinguishable from + * an allocation failure, but rendering ignores those anyways. + */ + +Bool +miComputeCompositeRegion (RegionPtr pRegion, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + + int v; + + pRegion->extents.x1 = xDst; + v = xDst + width; + pRegion->extents.x2 = BOUND(v); + pRegion->extents.y1 = yDst; + v = yDst + height; + pRegion->extents.y2 = BOUND(v); + pRegion->data = 0; + /* Check for empty operation */ + if (pRegion->extents.x1 >= pRegion->extents.x2 || + pRegion->extents.y1 >= pRegion->extents.y2) + { + pixman_region_init (pRegion); + return FALSE; + } + /* clip against dst */ + if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0)) + { + pixman_region_fini (pRegion); + return FALSE; + } + if (pDst->alphaMap) + { + if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip, + -pDst->alphaOrigin.x, + -pDst->alphaOrigin.y)) + { + pixman_region_fini (pRegion); + return FALSE; + } + } + /* clip against src */ + if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc)) + { + pixman_region_fini (pRegion); + return FALSE; + } + if (pSrc->alphaMap) + { + if (!miClipPictureSrc (pRegion, pSrc->alphaMap, + xDst - (xSrc - pSrc->alphaOrigin.x), + yDst - (ySrc - pSrc->alphaOrigin.y))) + { + pixman_region_fini (pRegion); + return FALSE; + } + } + /* clip against mask */ + if (pMask) + { + if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask)) + { + pixman_region_fini (pRegion); + return FALSE; + } + if (pMask->alphaMap) + { + if (!miClipPictureSrc (pRegion, pMask->alphaMap, + xDst - (xMask - pMask->alphaOrigin.x), + yDst - (yMask - pMask->alphaOrigin.y))) + { + pixman_region_fini (pRegion); + return FALSE; + } + } + } + + + miCompositeSourceValidate (pSrc); + if (pMask) + miCompositeSourceValidate (pMask); + + return TRUE; +} + +void +miRenderColorToPixel (PictFormatPtr format, + xRenderColor *color, + CARD32 *pixel) +{ + CARD32 r, g, b, a; + miIndexedPtr pIndexed; + + switch (format->type) { + case PictTypeDirect: + r = color->red >> (16 - Ones (format->direct.redMask)); + g = color->green >> (16 - Ones (format->direct.greenMask)); + b = color->blue >> (16 - Ones (format->direct.blueMask)); + a = color->alpha >> (16 - Ones (format->direct.alphaMask)); + r = r << format->direct.red; + g = g << format->direct.green; + b = b << format->direct.blue; + a = a << format->direct.alpha; + *pixel = r|g|b|a; + break; + case PictTypeIndexed: + pIndexed = (miIndexedPtr) (format->index.devPrivate); + if (pIndexed->color) + { + r = color->red >> 11; + g = color->green >> 11; + b = color->blue >> 11; + *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b); + } + else + { + r = color->red >> 8; + g = color->green >> 8; + b = color->blue >> 8; + *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b); + } + break; + } +} + +static CARD16 +miFillColor (CARD32 pixel, int bits) +{ + while (bits < 16) + { + pixel |= pixel << bits; + bits <<= 1; + } + return (CARD16) pixel; +} + +Bool +miIsSolidAlpha (PicturePtr pSrc) +{ + ScreenPtr pScreen; + char line[1]; + + if (!pSrc->pDrawable) + return FALSE; + + pScreen = pSrc->pDrawable->pScreen; + + /* Alpha-only */ + if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A) + return FALSE; + /* repeat */ + if (!pSrc->repeat) + return FALSE; + /* 1x1 */ + if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) + return FALSE; + line[0] = 1; + (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line); + switch (pSrc->pDrawable->bitsPerPixel) { + case 1: + return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80; + case 4: + return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0; + case 8: + return (CARD8) line[0] == 0xff; + default: + return FALSE; + } +} + +void +miRenderPixelToColor (PictFormatPtr format, + CARD32 pixel, + xRenderColor *color) +{ + CARD32 r, g, b, a; + miIndexedPtr pIndexed; + + switch (format->type) { + case PictTypeDirect: + r = (pixel >> format->direct.red) & format->direct.redMask; + g = (pixel >> format->direct.green) & format->direct.greenMask; + b = (pixel >> format->direct.blue) & format->direct.blueMask; + a = (pixel >> format->direct.alpha) & format->direct.alphaMask; + color->red = miFillColor (r, Ones (format->direct.redMask)); + color->green = miFillColor (g, Ones (format->direct.greenMask)); + color->blue = miFillColor (b, Ones (format->direct.blueMask)); + color->alpha = miFillColor (a, Ones (format->direct.alphaMask)); + break; + case PictTypeIndexed: + pIndexed = (miIndexedPtr) (format->index.devPrivate); + pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)]; + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel ) & 0xff; + color->red = miFillColor (r, 8); + color->green = miFillColor (g, 8); + color->blue = miFillColor (b, 8); + color->alpha = 0xffff; + break; + } +} + +Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + PictureScreenPtr ps; + + if (!PictureInit (pScreen, formats, nformats)) + return FALSE; + ps = GetPictureScreen(pScreen); + ps->CreatePicture = miCreatePicture; + ps->DestroyPicture = miDestroyPicture; + ps->ChangePictureClip = miChangePictureClip; + ps->DestroyPictureClip = miDestroyPictureClip; + ps->ChangePicture = miChangePicture; + ps->ValidatePicture = miValidatePicture; + ps->InitIndexed = miInitIndexed; + ps->CloseIndexed = miCloseIndexed; + ps->UpdateIndexed = miUpdateIndexed; + ps->ChangePictureTransform = miChangePictureTransform; + ps->ChangePictureFilter = miChangePictureFilter; + ps->RealizeGlyph = miRealizeGlyph; + ps->UnrealizeGlyph = miUnrealizeGlyph; + + /* MI rendering routines */ + ps->Composite = 0; /* requires DDX support */ + ps->Glyphs = miGlyphs; + ps->CompositeRects = miCompositeRects; + ps->Trapezoids = 0; + ps->Triangles = 0; + + ps->RasterizeTrapezoid = 0; /* requires DDX support */ + ps->AddTraps = 0; /* requires DDX support */ + ps->AddTriangles = 0; /* requires DDX support */ + + return TRUE; +} diff --git a/xorg-server/render/mipict.h b/xorg-server/render/mipict.h index d1495891e..f2df601e4 100644 --- a/xorg-server/render/mipict.h +++ b/xorg-server/render/mipict.h @@ -1,188 +1,165 @@ -/* - * - * Copyright © 2000 SuSE, 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 SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * 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: Keith Packard, SuSE, Inc. - */ - -#ifndef _MIPICT_H_ -#define _MIPICT_H_ - -#include "picturestr.h" - -#define MI_MAX_INDEXED 256 /* XXX depth must be <= 8 */ - -#if MI_MAX_INDEXED <= 256 -typedef CARD8 miIndexType; -#endif - -typedef struct _miIndexed { - Bool color; - CARD32 rgba[MI_MAX_INDEXED]; - miIndexType ent[32768]; -} miIndexedRec, *miIndexedPtr; - -#define miCvtR8G8B8to15(s) ((((s) >> 3) & 0x001f) | \ - (((s) >> 6) & 0x03e0) | \ - (((s) >> 9) & 0x7c00)) -#define miIndexToEnt15(mif,rgb15) ((mif)->ent[rgb15]) -#define miIndexToEnt24(mif,rgb24) miIndexToEnt15(mif,miCvtR8G8B8to15(rgb24)) - -#define miIndexToEntY24(mif,rgb24) ((mif)->ent[CvtR8G8B8toY15(rgb24)]) - -extern _X_EXPORT int -miCreatePicture (PicturePtr pPicture); - -extern _X_EXPORT void -miDestroyPicture (PicturePtr pPicture); - -extern _X_EXPORT void -miDestroyPictureClip (PicturePtr pPicture); - -extern _X_EXPORT int -miChangePictureClip (PicturePtr pPicture, - int type, - pointer value, - int n); - -extern _X_EXPORT void -miChangePicture (PicturePtr pPicture, - Mask mask); - -extern _X_EXPORT void -miValidatePicture (PicturePtr pPicture, - Mask mask); - -extern _X_EXPORT int -miChangePictureTransform (PicturePtr pPicture, - PictTransform *transform); - -extern _X_EXPORT int -miChangePictureFilter (PicturePtr pPicture, - int filter, - xFixed *params, - int nparams); - -extern _X_EXPORT void -miCompositeSourceValidate (PicturePtr pPicture, - INT16 x, - INT16 y, - CARD16 width, - CARD16 height); -extern _X_EXPORT Bool -miComputeCompositeRegion (RegionPtr pRegion, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - -extern _X_EXPORT Bool -miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); - -extern _X_EXPORT Bool -miRealizeGlyph (ScreenPtr pScreen, - GlyphPtr glyph); - -extern _X_EXPORT void -miUnrealizeGlyph (ScreenPtr pScreen, - GlyphPtr glyph); - -extern _X_EXPORT void -miGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs); - -extern _X_EXPORT void -miRenderColorToPixel (PictFormatPtr pPict, - xRenderColor *color, - CARD32 *pixel); - -extern _X_EXPORT void -miRenderPixelToColor (PictFormatPtr pPict, - CARD32 pixel, - xRenderColor *color); - -extern _X_EXPORT Bool -miIsSolidAlpha (PicturePtr pSrc); - -extern _X_EXPORT void -miCompositeRects (CARD8 op, - PicturePtr pDst, - xRenderColor *color, - int nRect, - xRectangle *rects); - -extern _X_EXPORT void -miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box); - -extern _X_EXPORT void -miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds); - -extern _X_EXPORT void -miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds); - -extern _X_EXPORT void -miTriStrip (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int npoint, - xPointFixed *points); - -extern _X_EXPORT void -miTriFan (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int npoint, - xPointFixed *points); - -extern _X_EXPORT Bool -miInitIndexed (ScreenPtr pScreen, - PictFormatPtr pFormat); - -extern _X_EXPORT void -miCloseIndexed (ScreenPtr pScreen, - PictFormatPtr pFormat); - -extern _X_EXPORT void -miUpdateIndexed (ScreenPtr pScreen, - PictFormatPtr pFormat, - int ndef, - xColorItem *pdef); - -#endif /* _MIPICT_H_ */ +/* + * + * Copyright © 2000 SuSE, 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 SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * 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: Keith Packard, SuSE, Inc. + */ + +#ifndef _MIPICT_H_ +#define _MIPICT_H_ + +#include "picturestr.h" + +#define MI_MAX_INDEXED 256 /* XXX depth must be <= 8 */ + +#if MI_MAX_INDEXED <= 256 +typedef CARD8 miIndexType; +#endif + +typedef struct _miIndexed { + Bool color; + CARD32 rgba[MI_MAX_INDEXED]; + miIndexType ent[32768]; +} miIndexedRec, *miIndexedPtr; + +#define miCvtR8G8B8to15(s) ((((s) >> 3) & 0x001f) | \ + (((s) >> 6) & 0x03e0) | \ + (((s) >> 9) & 0x7c00)) +#define miIndexToEnt15(mif,rgb15) ((mif)->ent[rgb15]) +#define miIndexToEnt24(mif,rgb24) miIndexToEnt15(mif,miCvtR8G8B8to15(rgb24)) + +#define miIndexToEntY24(mif,rgb24) ((mif)->ent[CvtR8G8B8toY15(rgb24)]) + +extern _X_EXPORT int +miCreatePicture (PicturePtr pPicture); + +extern _X_EXPORT void +miDestroyPicture (PicturePtr pPicture); + +extern _X_EXPORT void +miDestroyPictureClip (PicturePtr pPicture); + +extern _X_EXPORT int +miChangePictureClip (PicturePtr pPicture, + int type, + pointer value, + int n); + +extern _X_EXPORT void +miChangePicture (PicturePtr pPicture, + Mask mask); + +extern _X_EXPORT void +miValidatePicture (PicturePtr pPicture, + Mask mask); + +extern _X_EXPORT int +miChangePictureTransform (PicturePtr pPicture, + PictTransform *transform); + +extern _X_EXPORT int +miChangePictureFilter (PicturePtr pPicture, + int filter, + xFixed *params, + int nparams); + +extern _X_EXPORT void +miCompositeSourceValidate (PicturePtr pPicture); + +extern _X_EXPORT Bool +miComputeCompositeRegion (RegionPtr pRegion, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +extern _X_EXPORT Bool +miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats); + +extern _X_EXPORT Bool +miRealizeGlyph (ScreenPtr pScreen, + GlyphPtr glyph); + +extern _X_EXPORT void +miUnrealizeGlyph (ScreenPtr pScreen, + GlyphPtr glyph); + +extern _X_EXPORT void +miGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + +extern _X_EXPORT void +miRenderColorToPixel (PictFormatPtr pPict, + xRenderColor *color, + CARD32 *pixel); + +extern _X_EXPORT void +miRenderPixelToColor (PictFormatPtr pPict, + CARD32 pixel, + xRenderColor *color); + +extern _X_EXPORT Bool +miIsSolidAlpha (PicturePtr pSrc); + +extern _X_EXPORT void +miCompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +extern _X_EXPORT void +miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box); + +extern _X_EXPORT void +miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds); + +extern _X_EXPORT void +miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds); + +extern _X_EXPORT Bool +miInitIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat); + +extern _X_EXPORT void +miCloseIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat); + +extern _X_EXPORT void +miUpdateIndexed (ScreenPtr pScreen, + PictFormatPtr pFormat, + int ndef, + xColorItem *pdef); + +#endif /* _MIPICT_H_ */ diff --git a/xorg-server/render/mitri.c b/xorg-server/render/mitri.c index b258c2156..8c5298e25 100644 --- a/xorg-server/render/mitri.c +++ b/xorg-server/render/mitri.c @@ -1,132 +1,68 @@ -/* - * - * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 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 -#endif - -#include "scrnintstr.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "mi.h" -#include "picturestr.h" -#include "mipict.h" - -void -miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds) -{ - bounds->x1 = xFixedToInt (points->x); - bounds->x2 = xFixedToInt (xFixedCeil (points->x)); - bounds->y1 = xFixedToInt (points->y); - bounds->y2 = xFixedToInt (xFixedCeil (points->y)); - points++; - npoint--; - while (npoint-- > 0) - { - INT16 x1 = xFixedToInt (points->x); - INT16 x2 = xFixedToInt (xFixedCeil (points->x)); - INT16 y1 = xFixedToInt (points->y); - INT16 y2 = xFixedToInt (xFixedCeil (points->y)); - - if (x1 < bounds->x1) - bounds->x1 = x1; - else if (x2 > bounds->x2) - bounds->x2 = x2; - if (y1 < bounds->y1) - bounds->y1 = y1; - else if (y2 > bounds->y2) - bounds->y2 = y2; - points++; - } -} - -void -miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds) -{ - miPointFixedBounds (ntri * 3, (xPointFixed *) tris, bounds); -} - -void -miTriStrip (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int npoint, - xPointFixed *points) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - xTriangle *tris, *tri; - int ntri; - - if (npoint < 3) - return; - ntri = npoint - 2; - tris = malloc(ntri * sizeof (xTriangle)); - if (!tris) - return; - for (tri = tris; npoint >= 3; npoint--, points++, tri++) - { - tri->p1 = points[0]; - tri->p2 = points[1]; - tri->p3 = points[2]; - } - (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); - free(tris); -} - -void -miTriFan (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int npoint, - xPointFixed *points) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - xTriangle *tris, *tri; - xPointFixed *first; - int ntri; - - if (npoint < 3) - return; - ntri = npoint - 2; - tris = malloc(ntri * sizeof (xTriangle)); - if (!tris) - return; - first = points++; - for (tri = tris; npoint >= 3; npoint--, points++, tri++) - { - tri->p1 = *first; - tri->p2 = points[0]; - tri->p3 = points[1]; - } - (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); - free(tris); -} +/* + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, 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 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 +#endif + +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "mi.h" +#include "picturestr.h" +#include "mipict.h" + +void +miPointFixedBounds (int npoint, xPointFixed *points, BoxPtr bounds) +{ + bounds->x1 = xFixedToInt (points->x); + bounds->x2 = xFixedToInt (xFixedCeil (points->x)); + bounds->y1 = xFixedToInt (points->y); + bounds->y2 = xFixedToInt (xFixedCeil (points->y)); + points++; + npoint--; + while (npoint-- > 0) + { + INT16 x1 = xFixedToInt (points->x); + INT16 x2 = xFixedToInt (xFixedCeil (points->x)); + INT16 y1 = xFixedToInt (points->y); + INT16 y2 = xFixedToInt (xFixedCeil (points->y)); + + if (x1 < bounds->x1) + bounds->x1 = x1; + else if (x2 > bounds->x2) + bounds->x2 = x2; + if (y1 < bounds->y1) + bounds->y1 = y1; + else if (y2 > bounds->y2) + bounds->y2 = y2; + points++; + } +} + +void +miTriangleBounds (int ntri, xTriangle *tris, BoxPtr bounds) +{ + miPointFixedBounds (ntri * 3, (xPointFixed *) tris, bounds); +} diff --git a/xorg-server/render/picture.c b/xorg-server/render/picture.c index d31b77466..ed7a1d8f1 100644 --- a/xorg-server/render/picture.c +++ b/xorg-server/render/picture.c @@ -1773,11 +1773,25 @@ CompositeTriStrip (CARD8 op, int npoints, xPointFixed *points) { - PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + xTriangle *tris, *tri; + int ntri; - ValidatePicture (pSrc); - ValidatePicture (pDst); - (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); + if (npoints < 3) + return; + ntri = npoints - 2; + tris = malloc(ntri * sizeof (xTriangle)); + if (!tris) + return; + for (tri = tris; npoints >= 3; npoints--, points++, tri++) + { + tri->p1 = points[0]; + tri->p2 = points[1]; + tri->p3 = points[2]; + } + CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); + free(tris); } void @@ -1790,11 +1804,26 @@ CompositeTriFan (CARD8 op, int npoints, xPointFixed *points) { - PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen); + ScreenPtr pScreen = pDst->pDrawable->pScreen; + xTriangle *tris, *tri; + xPointFixed *first; + int ntri; - ValidatePicture (pSrc); - ValidatePicture (pDst); - (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points); + if (npoints < 3) + return; + ntri = npoints - 2; + tris = malloc(ntri * sizeof (xTriangle)); + if (!tris) + return; + first = points++; + for (tri = tris; npoints >= 3; npoints--, points++, tri++) + { + tri->p1 = *first; + tri->p2 = points[0]; + tri->p3 = points[1]; + } + CompositeTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); + free(tris); } void diff --git a/xorg-server/render/picturestr.h b/xorg-server/render/picturestr.h index ee62e6a17..f642bf0df 100644 --- a/xorg-server/render/picturestr.h +++ b/xorg-server/render/picturestr.h @@ -381,8 +381,6 @@ typedef struct _PictureScreen { TrapezoidsProcPtr Trapezoids; TrianglesProcPtr Triangles; - TriStripProcPtr TriStrip; - TriFanProcPtr TriFan; RasterizeTrapezoidProcPtr RasterizeTrapezoid; diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am index 8bb3a0688..d93c7a223 100644 --- a/xorg-server/test/Makefile.am +++ b/xorg-server/test/Makefile.am @@ -1,6 +1,6 @@ if UNITTESTS SUBDIRS= . xi2 -check_PROGRAMS = xkb input xtest +check_PROGRAMS = xkb input xtest list check_LTLIBRARIES = libxservertest.la TESTS=$(check_PROGRAMS) @@ -16,6 +16,7 @@ endif xkb_LDADD=$(TEST_LDADD) input_LDADD=$(TEST_LDADD) xtest_LDADD=$(TEST_LDADD) +list_LDADD=$(TEST_LDADD) libxservertest_la_LIBADD = \ $(XSERVER_LIBS) \ diff --git a/xorg-server/test/list.c b/xorg-server/test/list.c new file mode 100644 index 000000000..7e035fe58 --- /dev/null +++ b/xorg-server/test/list.c @@ -0,0 +1,176 @@ +/** + * 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 +#endif + +#include +#include +#include +#include + +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(); +} diff --git a/xorg-server/xkb/xkbActions.c b/xorg-server/xkb/xkbActions.c index 65c678af8..8cd9b44a1 100644 --- a/xorg-server/xkb/xkbActions.c +++ b/xorg-server/xkb/xkbActions.c @@ -1,1441 +1,1434 @@ -/************************************************************ -Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. - -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 Silicon Graphics not be -used in advertising or publicity pertaining to distribution -of the software without specific prior written permission. -Silicon Graphics makes no representation about the suitability -of this software for any purpose. It is provided "as is" -without any express or implied warranty. - -SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON -GRAPHICS 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 -#endif - -#include -#include -#include -#include -#include -#include "misc.h" -#include "inputstr.h" -#include "exevents.h" -#include "eventstr.h" -#include -#include "xkb.h" -#include -#include "mi.h" -#include "mipointer.h" -#include "inpututils.h" -#define EXTENSION_EVENT_BASE 64 - -DevPrivateKeyRec xkbDevicePrivateKeyRec; - -void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button); -static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y); - -void -xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, - pointer data) -{ - xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device); - ProcessInputProc backupproc; - if(xkbPrivPtr->unwrapProc) - xkbPrivPtr->unwrapProc = NULL; - - UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc); - proc(device,data); - COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, - backupproc,xkbUnwrapProc); -} - -Bool -XkbInitPrivates(void) -{ - return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE, 0); -} - -void -XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc) -{ - xkbDeviceInfoPtr xkbPrivPtr; - - xkbPrivPtr = (xkbDeviceInfoPtr) calloc(1, sizeof(xkbDeviceInfoRec)); - if (!xkbPrivPtr) - return; - xkbPrivPtr->unwrapProc = NULL; - - dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr); - WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc); -} - -/***====================================================================***/ - -static XkbAction -_FixUpAction(XkbDescPtr xkb,XkbAction *act) -{ -static XkbAction fake; - - if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) { - fake.type = XkbSA_NoAction; - return fake; - } - if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) { - if (act->any.type==XkbSA_SetMods) { - fake.mods.type = XkbSA_LatchMods; - fake.mods.mask = act->mods.mask; - if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) - fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; - else fake.mods.flags= XkbSA_ClearLocks; - return fake; - } - if (act->any.type==XkbSA_SetGroup) { - fake.group.type = XkbSA_LatchGroup; - if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) - fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; - else fake.group.flags= XkbSA_ClearLocks; - XkbSASetGroup(&fake.group,XkbSAGroup(&act->group)); - return fake; - } - } - return *act; -} - -static XkbAction -XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key) -{ -int effectiveGroup; -int col; -XkbDescPtr xkb; -XkbKeyTypePtr type; -XkbAction * pActs; -static XkbAction fake; - - xkb= xkbi->desc; - if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) { - fake.type = XkbSA_NoAction; - return fake; - } - pActs= XkbKeyActionsPtr(xkb,key); - col= 0; - - effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key); - if (effectiveGroup != XkbGroup1Index) - col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key)); - - type= XkbKeyKeyType(xkb,key,effectiveGroup); - if (type->map!=NULL) { - register unsigned i,mods; - register XkbKTMapEntryPtr entry; - mods= xkbState->mods&type->mods.mask; - for (entry= type->map,i=0;imap_count;i++,entry++) { - if ((entry->active)&&(entry->mods.mask==mods)) { - col+= entry->level; - break; - } - } - } - if (pActs[col].any.type==XkbSA_NoAction) - return pActs[col]; - fake= _FixUpAction(xkb,&pActs[col]); - return fake; -} - -static XkbAction -XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button) -{ -XkbAction fake; - if ((dev->button)&&(dev->button->xkb_acts)) { - if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) { - fake= _FixUpAction(kbd->key->xkbInfo->desc, - &dev->button->xkb_acts[button-1]); - return fake; - } - } - fake.any.type= XkbSA_NoAction; - return fake; -} - -/***====================================================================***/ - -#define SYNTHETIC_KEYCODE 1 -#define BTN_ACT_FLAG 0x100 - -static int -_XkbFilterSetState( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction *pAction) -{ - if (filter->keycode==0) { /* initial press */ - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0); - filter->priv = 0; - filter->filter = _XkbFilterSetState; - if (pAction->type==XkbSA_SetMods) { - filter->upAction = *pAction; - xkbi->setMods= pAction->mods.mask; - } - else { - xkbi->groupChange = XkbSAGroup(&pAction->group); - if (pAction->group.flags&XkbSA_GroupAbsolute) - xkbi->groupChange-= xkbi->state.base_group; - filter->upAction= *pAction; - XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); - } - } - else if (filter->keycode==keycode) { - if (filter->upAction.type==XkbSA_SetMods) { - xkbi->clearMods = filter->upAction.mods.mask; - if (filter->upAction.mods.flags&XkbSA_ClearLocks) { - xkbi->state.locked_mods&= ~filter->upAction.mods.mask; - } - } - else { - if (filter->upAction.group.flags&XkbSA_ClearLocks) { - xkbi->state.locked_group = 0; - } - xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); - } - filter->active = 0; - } - else { - filter->upAction.mods.flags&= ~XkbSA_ClearLocks; - filter->filterOthers = 0; - } - return 1; -} - -#define LATCH_KEY_DOWN 1 -#define LATCH_PENDING 2 -#define NO_LATCH 3 - -static int -_XkbFilterLatchState( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ - - if (filter->keycode==0) { /* initial press */ - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 1; - filter->priv = LATCH_KEY_DOWN; - filter->filter = _XkbFilterLatchState; - if (pAction->type==XkbSA_LatchMods) { - filter->upAction = *pAction; - xkbi->setMods = pAction->mods.mask; - } - else { - xkbi->groupChange = XkbSAGroup(&pAction->group); - if (pAction->group.flags&XkbSA_GroupAbsolute) - xkbi->groupChange-= xkbi->state.base_group; - filter->upAction= *pAction; - XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); - } - } - else if ( pAction && (filter->priv==LATCH_PENDING) ) { - if (((1<type)&XkbSA_BreakLatch)!=0) { - filter->active = 0; - if (filter->upAction.type==XkbSA_LatchMods) - xkbi->state.latched_mods&= ~filter->upAction.mods.mask; - else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); - } - else if ((pAction->type==filter->upAction.type)&& - (pAction->mods.flags==filter->upAction.mods.flags)&& - (pAction->mods.mask==filter->upAction.mods.mask)) { - if (filter->upAction.mods.flags&XkbSA_LatchToLock) { - XkbControlsPtr ctrls= xkbi->desc->ctrls; - if (filter->upAction.type==XkbSA_LatchMods) - pAction->mods.type= XkbSA_LockMods; - else pAction->group.type= XkbSA_LockGroup; - if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&& - (ctrls->enabled_ctrls&XkbStickyKeysMask)) { - XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK, - XkbStickyKeysMask); - } - } - else { - if (filter->upAction.type==XkbSA_LatchMods) - pAction->mods.type= XkbSA_SetMods; - else pAction->group.type= XkbSA_SetGroup; - } - if (filter->upAction.type==XkbSA_LatchMods) - xkbi->state.latched_mods&= ~filter->upAction.mods.mask; - else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); - filter->active = 0; - } - } - else if (filter->keycode==keycode) { /* release */ - XkbControlsPtr ctrls= xkbi->desc->ctrls; - int needBeep; - int beepType= _BEEP_NONE; - - needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&& - XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)); - if (filter->upAction.type==XkbSA_LatchMods) { - xkbi->clearMods = filter->upAction.mods.mask; - if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&& - (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) { - xkbi->state.locked_mods&= ~xkbi->clearMods; - filter->priv= NO_LATCH; - beepType= _BEEP_STICKY_UNLOCK; - } - } - else { - xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); - if ((filter->upAction.group.flags&XkbSA_ClearLocks)&& - (xkbi->state.locked_group)) { - xkbi->state.locked_group = 0; - filter->priv = NO_LATCH; - beepType= _BEEP_STICKY_UNLOCK; - } - } - if (filter->priv==NO_LATCH) { - filter->active= 0; - } - else { - filter->priv= LATCH_PENDING; - if (filter->upAction.type==XkbSA_LatchMods) { - xkbi->state.latched_mods |= filter->upAction.mods.mask; - needBeep = xkbi->state.latched_mods ? needBeep : 0; - xkbi->state.latched_mods |= filter->upAction.mods.mask; - } - else { - xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group); - } - if (needBeep && (beepType==_BEEP_NONE)) - beepType= _BEEP_STICKY_LATCH; - } - if (needBeep && (beepType!=_BEEP_NONE)) - XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask); - } - else if (filter->priv==LATCH_KEY_DOWN) { - filter->priv= NO_LATCH; - filter->filterOthers = 0; - } - return 1; -} - -static int -_XkbFilterLockState( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ - if (pAction&&(pAction->type==XkbSA_LockGroup)) { - if (pAction->group.flags&XkbSA_GroupAbsolute) - xkbi->state.locked_group= XkbSAGroup(&pAction->group); - else xkbi->state.locked_group+= XkbSAGroup(&pAction->group); - return 1; - } - if (filter->keycode==0) { /* initial press */ - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - filter->priv = 0; - filter->filter = _XkbFilterLockState; - filter->upAction = *pAction; - xkbi->state.locked_mods^= pAction->mods.mask; - xkbi->setMods = pAction->mods.mask; - } - else if (filter->keycode==keycode) { - filter->active = 0; - xkbi->clearMods = filter->upAction.mods.mask; - } - return 1; -} - -#define ISO_KEY_DOWN 0 -#define NO_ISO_LOCK 1 - -static int -_XkbFilterISOLock( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ - - if (filter->keycode==0) { /* initial press */ - CARD8 flags= pAction->iso.flags; - - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 1; - filter->priv = ISO_KEY_DOWN; - filter->upAction = *pAction; - filter->filter = _XkbFilterISOLock; - if (flags&XkbSA_ISODfltIsGroup) { - xkbi->groupChange = XkbSAGroup(&pAction->iso); - xkbi->setMods = 0; - } - else { - xkbi->setMods = pAction->iso.mask; - xkbi->groupChange = 0; - } - if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) { - filter->priv= NO_ISO_LOCK; - xkbi->state.locked_mods^= xkbi->state.base_mods; - } - if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) { -/* 6/22/93 (ef) -- lock groups if group key is down first */ - } - if (!(flags&XkbSA_ISONoAffectPtr)) { -/* 6/22/93 (ef) -- lock mouse buttons if they're down */ - } - } - else if (filter->keycode==keycode) { - CARD8 flags= filter->upAction.iso.flags; - - if (flags&XkbSA_ISODfltIsGroup) { - xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso); - xkbi->clearMods = 0; - if (filter->priv==ISO_KEY_DOWN) - xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso); - } - else { - xkbi->clearMods= filter->upAction.iso.mask; - xkbi->groupChange= 0; - if (filter->priv==ISO_KEY_DOWN) - xkbi->state.locked_mods^= filter->upAction.iso.mask; - } - filter->active = 0; - } - else if (pAction) { - CARD8 flags= filter->upAction.iso.flags; - - switch (pAction->type) { - case XkbSA_SetMods: case XkbSA_LatchMods: - if (!(flags&XkbSA_ISONoAffectMods)) { - pAction->type= XkbSA_LockMods; - filter->priv= NO_ISO_LOCK; - } - break; - case XkbSA_SetGroup: case XkbSA_LatchGroup: - if (!(flags&XkbSA_ISONoAffectGroup)) { - pAction->type= XkbSA_LockGroup; - filter->priv= NO_ISO_LOCK; - } - break; - case XkbSA_PtrBtn: - if (!(flags&XkbSA_ISONoAffectPtr)) { - pAction->type= XkbSA_LockPtrBtn; - filter->priv= NO_ISO_LOCK; - } - break; - case XkbSA_SetControls: - if (!(flags&XkbSA_ISONoAffectCtrls)) { - pAction->type= XkbSA_LockControls; - filter->priv= NO_ISO_LOCK; - } - break; - } - } - return 1; -} - - -static CARD32 -_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg) -{ -XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg; -XkbControlsPtr ctrls= xkbi->desc->ctrls; -int dx,dy; - - if (xkbi->mouseKey==0) - return 0; - - if (xkbi->mouseKeysAccel) { - if ((xkbi->mouseKeysCounter)mk_time_to_max) { - double step; - xkbi->mouseKeysCounter++; - step= xkbi->mouseKeysCurveFactor* - pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve); - if (xkbi->mouseKeysDX<0) - dx= floor( ((double)xkbi->mouseKeysDX)*step ); - else dx= ceil( ((double)xkbi->mouseKeysDX)*step ); - if (xkbi->mouseKeysDY<0) - dy= floor( ((double)xkbi->mouseKeysDY)*step ); - else dy= ceil( ((double)xkbi->mouseKeysDY)*step ); - } - else { - dx= xkbi->mouseKeysDX*ctrls->mk_max_speed; - dy= xkbi->mouseKeysDY*ctrls->mk_max_speed; - } - if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX) - dx= xkbi->mouseKeysDX; - if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY) - dy= xkbi->mouseKeysDY; - } - else { - dx= xkbi->mouseKeysDX; - dy= xkbi->mouseKeysDY; - } - XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy); - return xkbi->desc->ctrls->mk_interval; -} - -static int -_XkbFilterPointerMove( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ -int x,y; -Bool accel; - - if (filter->keycode==0) { /* initial press */ - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - filter->priv=0; - filter->filter = _XkbFilterPointerMove; - filter->upAction= *pAction; - xkbi->mouseKeysCounter= 0; - xkbi->mouseKey= keycode; - accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0); - x= XkbPtrActionX(&pAction->ptr); - y= XkbPtrActionY(&pAction->ptr); - XkbFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y); - AccessXCancelRepeatKey(xkbi,keycode); - xkbi->mouseKeysAccel= accel&& - (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask); - xkbi->mouseKeysFlags= pAction->ptr.flags; - xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr); - xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr); - xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, - xkbi->desc->ctrls->mk_delay, - _XkbPtrAccelExpire,(pointer)xkbi); - } - else if (filter->keycode==keycode) { - filter->active = 0; - if (xkbi->mouseKey==keycode) { - xkbi->mouseKey= 0; - xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0, - NULL, NULL); - } - } - return 0; -} - -static int -_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ - if (filter->keycode==0) { /* initial press */ - int button= pAction->btn.button; - - if (button==XkbSA_UseDfltButton) - button = xkbi->desc->ctrls->mk_dflt_btn; - - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - filter->priv=0; - filter->filter = _XkbFilterPointerBtn; - filter->upAction= *pAction; - filter->upAction.btn.button= button; - switch (pAction->type) { - case XkbSA_LockPtrBtn: - if (((xkbi->lockedPtrButtons&(1<btn.flags&XkbSA_LockNoLock)==0)) { - xkbi->lockedPtrButtons|= (1<device, 1, button); - filter->upAction.type= XkbSA_NoAction; - } - break; - case XkbSA_PtrBtn: - { - register int i,nClicks; - AccessXCancelRepeatKey(xkbi,keycode); - if (pAction->btn.count>0) { - nClicks= pAction->btn.count; - for (i=0;idevice, 1, button); - XkbFakeDeviceButton(xkbi->device, 0, button); - } - filter->upAction.type= XkbSA_NoAction; - } - else XkbFakeDeviceButton(xkbi->device, 1, button); - } - break; - case XkbSA_SetPtrDflt: - { - XkbControlsPtr ctrls= xkbi->desc->ctrls; - XkbControlsRec old; - xkbControlsNotify cn; - - old= *ctrls; - AccessXCancelRepeatKey(xkbi,keycode); - switch (pAction->dflt.affect) { - case XkbSA_AffectDfltBtn: - if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute) - ctrls->mk_dflt_btn= - XkbSAPtrDfltValue(&pAction->dflt); - else { - ctrls->mk_dflt_btn+= - XkbSAPtrDfltValue(&pAction->dflt); - if (ctrls->mk_dflt_btn>5) - ctrls->mk_dflt_btn= 5; - else if (ctrls->mk_dflt_btn<1) - ctrls->mk_dflt_btn= 1; - } - break; - default: - ErrorF( - "Attempt to change unknown pointer default (%d) ignored\n", - pAction->dflt.affect); - break; - } - if (XkbComputeControlsNotify(xkbi->device, - &old,xkbi->desc->ctrls, - &cn,FALSE)) { - cn.keycode = keycode; - /* XXX: what about DeviceKeyPress? */ - cn.eventType = KeyPress; - cn.requestMajor = 0; - cn.requestMinor = 0; - XkbSendControlsNotify(xkbi->device,&cn); - } - } - break; - } - } - else if (filter->keycode==keycode) { - int button= filter->upAction.btn.button; - - switch (filter->upAction.type) { - case XkbSA_LockPtrBtn: - if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)|| - ((xkbi->lockedPtrButtons&(1<lockedPtrButtons&= ~(1<device)) - { - XkbMergeLockedPtrBtns(xkbi->device); - /* One SD still has lock set, don't post event */ - if ((xkbi->lockedPtrButtons & (1 << button)) != 0) - break; - } - - /* fallthrough */ - case XkbSA_PtrBtn: - XkbFakeDeviceButton(xkbi->device, 0, button); - break; - } - filter->active = 0; - } - return 0; -} - -static int -_XkbFilterControls( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ -XkbControlsRec old; -XkbControlsPtr ctrls; -DeviceIntPtr kbd; -unsigned int change; -XkbEventCauseRec cause; - - kbd= xkbi->device; - ctrls= xkbi->desc->ctrls; - old= *ctrls; - if (filter->keycode==0) { /* initial press */ - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - change= XkbActionCtrls(&pAction->ctrls); - filter->priv = change; - filter->filter = _XkbFilterControls; - filter->upAction = *pAction; - - if (pAction->type==XkbSA_LockControls) { - filter->priv= (ctrls->enabled_ctrls&change); - change&= ~ctrls->enabled_ctrls; - } - - if (change) { - xkbControlsNotify cn; - XkbSrvLedInfoPtr sli; - - ctrls->enabled_ctrls|= change; - if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) { - cn.keycode = keycode; - /* XXX: what about DeviceKeyPress? */ - cn.eventType = KeyPress; - cn.requestMajor = 0; - cn.requestMinor = 0; - XkbSendControlsNotify(kbd,&cn); - } - - XkbSetCauseKey(&cause,keycode,KeyPress); - - /* If sticky keys were disabled, clear all locks and latches */ - if ((old.enabled_ctrls&XkbStickyKeysMask)&& - (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { - XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause); - } - sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); - XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause); - if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) - XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change); - } - } - else if (filter->keycode==keycode) { - change= filter->priv; - if (change) { - xkbControlsNotify cn; - XkbSrvLedInfoPtr sli; - - ctrls->enabled_ctrls&= ~change; - if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) { - cn.keycode = keycode; - cn.eventType = KeyRelease; - cn.requestMajor = 0; - cn.requestMinor = 0; - XkbSendControlsNotify(kbd,&cn); - } - - XkbSetCauseKey(&cause,keycode,KeyRelease); - /* If sticky keys were disabled, clear all locks and latches */ - if ((old.enabled_ctrls&XkbStickyKeysMask)&& - (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { - XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause); - } - sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); - XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause); - if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) - XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change); - } - filter->keycode= 0; - filter->active= 0; - } - return 1; -} - -static int -_XkbFilterActionMessage(XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ -XkbMessageAction * pMsg; -DeviceIntPtr kbd; - - kbd= xkbi->device; - if (filter->keycode==0) { /* initial press */ - pMsg= &pAction->msg; - if ((pMsg->flags&XkbSA_MessageOnRelease)|| - ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) { - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - filter->priv = 0; - filter->filter = _XkbFilterActionMessage; - filter->upAction = *pAction; - } - if (pMsg->flags&XkbSA_MessageOnPress) { - xkbActionMessage msg; - - msg.keycode= keycode; - msg.press= 1; - msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); - memcpy((char *)msg.message, - (char *)pMsg->message,XkbActionMessageLength); - XkbSendActionMessage(kbd,&msg); - } - return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0); - } - else if (filter->keycode==keycode) { - pMsg= &filter->upAction.msg; - if (pMsg->flags&XkbSA_MessageOnRelease) { - xkbActionMessage msg; - - msg.keycode= keycode; - msg.press= 0; - msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); - memcpy((char *)msg.message,(char *)pMsg->message, - XkbActionMessageLength); - XkbSendActionMessage(kbd,&msg); - } - filter->keycode= 0; - filter->active= 0; - return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); - } - return 0; -} - -static int -_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ -DeviceEvent ev; -int x,y; -XkbStateRec old; -unsigned mods,mask; -xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device); -ProcessInputProc backupproc; - - /* never actually used uninitialised, but gcc isn't smart enough - * to work that out. */ - memset(&old, 0, sizeof(old)); - memset(&ev, 0, sizeof(ev)); - - if ((filter->keycode!=0)&&(filter->keycode!=keycode)) - return 1; - - GetSpritePosition(xkbi->device, &x,&y); - ev.header = ET_Internal; - ev.length = sizeof(DeviceEvent); - ev.time = GetTimeInMillis(); - ev.root_x = x; - ev.root_y = y; - - if (filter->keycode==0) { /* initial press */ - if ((pAction->redirect.new_keydesc->min_key_code)|| - (pAction->redirect.new_key>xkbi->desc->max_key_code)) { - return 1; - } - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - filter->priv = 0; - filter->filter = _XkbFilterRedirectKey; - filter->upAction = *pAction; - - ev.type = ET_KeyPress; - ev.detail.key = pAction->redirect.new_key; - - mask= XkbSARedirectVModsMask(&pAction->redirect); - mods= XkbSARedirectVMods(&pAction->redirect); - if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); - if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); - mask|= pAction->redirect.mods_mask; - mods|= pAction->redirect.mods; - - if ( mask || mods ) { - old= xkbi->state; - xkbi->state.base_mods&= ~mask; - xkbi->state.base_mods|= (mods&mask); - xkbi->state.latched_mods&= ~mask; - xkbi->state.latched_mods|= (mods&mask); - xkbi->state.locked_mods&= ~mask; - xkbi->state.locked_mods|= (mods&mask); - XkbComputeDerivedState(xkbi); - } - - UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); - xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device); - COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, - backupproc,xkbUnwrapProc); - - if ( mask || mods ) - xkbi->state= old; - } - else if (filter->keycode==keycode) { - - ev.type = ET_KeyRelease; - ev.detail.key = filter->upAction.redirect.new_key; - - mask= XkbSARedirectVModsMask(&filter->upAction.redirect); - mods= XkbSARedirectVMods(&filter->upAction.redirect); - if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); - if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); - mask|= filter->upAction.redirect.mods_mask; - mods|= filter->upAction.redirect.mods; - - if ( mask || mods ) { - old= xkbi->state; - xkbi->state.base_mods&= ~mask; - xkbi->state.base_mods|= (mods&mask); - xkbi->state.latched_mods&= ~mask; - xkbi->state.latched_mods|= (mods&mask); - xkbi->state.locked_mods&= ~mask; - xkbi->state.locked_mods|= (mods&mask); - XkbComputeDerivedState(xkbi); - } - - UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); - xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device); - COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, - backupproc,xkbUnwrapProc); - - if ( mask || mods ) - xkbi->state= old; - - filter->keycode= 0; - filter->active= 0; - } - return 0; -} - -static int -_XkbFilterSwitchScreen( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ - DeviceIntPtr dev = xkbi->device; - if (dev == inputInfo.keyboard) - return 0; - - if (filter->keycode==0) { /* initial press */ - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - filter->filter = _XkbFilterSwitchScreen; - AccessXCancelRepeatKey(xkbi, keycode); - XkbDDXSwitchScreen(dev,keycode,pAction); - return 0; - } - else if (filter->keycode==keycode) { - filter->active= 0; - return 0; - } - return 1; -} - -static int -_XkbFilterXF86Private( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ - DeviceIntPtr dev = xkbi->device; - if (dev == inputInfo.keyboard) - return 0; - - if (filter->keycode==0) { /* initial press */ - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - filter->filter = _XkbFilterXF86Private; - XkbDDXPrivate(dev,keycode,pAction); - return 0; - } - else if (filter->keycode==keycode) { - filter->active= 0; - return 0; - } - return 1; -} - - -static int -_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi, - XkbFilterPtr filter, - unsigned keycode, - XkbAction * pAction) -{ -DeviceIntPtr dev; -int button; - - if (xkbi->device == inputInfo.keyboard) - return 0; - - if (filter->keycode==0) { /* initial press */ - _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient, - DixUnknownAccess, &button); - if (!dev || !dev->public.on) - return 1; - - button= pAction->devbtn.button; - if ((button<1)||(button>dev->button->numButtons)) - return 1; - - filter->keycode = keycode; - filter->active = 1; - filter->filterOthers = 0; - filter->priv=0; - filter->filter = _XkbFilterDeviceBtn; - filter->upAction= *pAction; - switch (pAction->type) { - case XkbSA_LockDeviceBtn: - if ((pAction->devbtn.flags&XkbSA_LockNoLock)|| - BitIsOn(dev->button->down, button)) - return 0; - XkbFakeDeviceButton(dev,TRUE,button); - filter->upAction.type= XkbSA_NoAction; - break; - case XkbSA_DeviceBtn: - if (pAction->devbtn.count>0) { - int nClicks,i; - nClicks= pAction->btn.count; - for (i=0;iupAction.type= XkbSA_NoAction; - } - else XkbFakeDeviceButton(dev,TRUE,button); - break; - } - } - else if (filter->keycode==keycode) { - int button; - - filter->active= 0; - _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device, - serverClient, DixUnknownAccess, &button); - if (!dev || !dev->public.on) - return 1; - - button= filter->upAction.btn.button; - switch (filter->upAction.type) { - case XkbSA_LockDeviceBtn: - if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)|| - !BitIsOn(dev->button->down, button)) - return 0; - XkbFakeDeviceButton(dev,FALSE,button); - break; - case XkbSA_DeviceBtn: - XkbFakeDeviceButton(dev,FALSE,button); - break; - } - filter->active = 0; - } - return 0; -} - -static XkbFilterPtr -_XkbNextFreeFilter( - XkbSrvInfoPtr xkbi -) -{ -register int i; - - if (xkbi->szFilters==0) { - xkbi->szFilters = 4; - xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec)); - /* 6/21/93 (ef) -- XXX! deal with allocation failure */ - } - for (i=0;iszFilters;i++) { - if (!xkbi->filters[i].active) { - xkbi->filters[i].keycode = 0; - return &xkbi->filters[i]; - } - } - xkbi->szFilters*=2; - xkbi->filters= realloc(xkbi->filters, - xkbi->szFilters * sizeof(XkbFilterRec)); - /* 6/21/93 (ef) -- XXX! deal with allocation failure */ - memset(&xkbi->filters[xkbi->szFilters/2], 0, - (xkbi->szFilters/2)*sizeof(XkbFilterRec)); - return &xkbi->filters[xkbi->szFilters/2]; -} - -static int -_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction) -{ -register int i,send; - - send= 1; - for (i=0;iszFilters;i++) { - if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter)) - send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction) - && send); - } - return send; -} - -void -XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent* event) -{ -int key,bit,i; -XkbSrvInfoPtr xkbi; -KeyClassPtr keyc; -int changed,sendEvent; -Bool genStateNotify; -XkbAction act; -XkbFilterPtr filter; -Bool keyEvent; -Bool pressEvent; -ProcessInputProc backupproc; - -xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev); - - keyc= kbd->key; - xkbi= keyc->xkbInfo; - key= event->detail.key; - /* The state may change, so if we're not in the middle of sending a state - * notify, prepare for it */ - if ((xkbi->flags&_XkbStateNotifyInProgress)==0) { - xkbi->prev_state = xkbi->state; - xkbi->flags|= _XkbStateNotifyInProgress; - genStateNotify= TRUE; - } - else genStateNotify= FALSE; - - xkbi->clearMods = xkbi->setMods = 0; - xkbi->groupChange = 0; - - sendEvent = 1; - keyEvent= ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease)); - pressEvent= ((event->type == ET_KeyPress)|| (event->type == ET_ButtonPress)); - - if (pressEvent) { - if (keyEvent) - act = XkbGetKeyAction(xkbi,&xkbi->state,key); - else { - act = XkbGetButtonAction(kbd,dev,key); - key|= BTN_ACT_FLAG; - } - sendEvent = _XkbApplyFilters(xkbi,key,&act); - if (sendEvent) { - switch (act.type) { - case XkbSA_SetMods: - case XkbSA_SetGroup: - filter = _XkbNextFreeFilter(xkbi); - sendEvent = _XkbFilterSetState(xkbi,filter,key,&act); - break; - case XkbSA_LatchMods: - case XkbSA_LatchGroup: - filter = _XkbNextFreeFilter(xkbi); - sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act); - break; - case XkbSA_LockMods: - case XkbSA_LockGroup: - filter = _XkbNextFreeFilter(xkbi); - sendEvent=_XkbFilterLockState(xkbi,filter,key,&act); - break; - case XkbSA_ISOLock: - filter = _XkbNextFreeFilter(xkbi); - sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act); - break; - case XkbSA_MovePtr: - filter = _XkbNextFreeFilter(xkbi); - sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act); - break; - case XkbSA_PtrBtn: - case XkbSA_LockPtrBtn: - case XkbSA_SetPtrDflt: - filter = _XkbNextFreeFilter(xkbi); - sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act); - break; - case XkbSA_Terminate: - sendEvent= XkbDDXTerminateServer(dev,key,&act); - break; - case XkbSA_SwitchScreen: - filter = _XkbNextFreeFilter(xkbi); - sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act); - break; - case XkbSA_SetControls: - case XkbSA_LockControls: - filter = _XkbNextFreeFilter(xkbi); - sendEvent=_XkbFilterControls(xkbi,filter,key,&act); - break; - case XkbSA_ActionMessage: - filter = _XkbNextFreeFilter(xkbi); - sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act); - break; - case XkbSA_RedirectKey: - filter = _XkbNextFreeFilter(xkbi); - sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act); - break; - case XkbSA_DeviceBtn: - case XkbSA_LockDeviceBtn: - filter = _XkbNextFreeFilter(xkbi); - sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act); - break; - case XkbSA_XFree86Private: - filter = _XkbNextFreeFilter(xkbi); - sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act); - break; - } - } - } - else { - if (!keyEvent) - key|= BTN_ACT_FLAG; - sendEvent = _XkbApplyFilters(xkbi,key,NULL); - } - - if (xkbi->groupChange!=0) - xkbi->state.base_group+= xkbi->groupChange; - if (xkbi->setMods) { - for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) { - if (xkbi->setMods&bit) { - keyc->modifierKeyCount[i]++; - xkbi->state.base_mods|= bit; - xkbi->setMods&= ~bit; - } - } - } - if (xkbi->clearMods) { - for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) { - if (xkbi->clearMods&bit) { - keyc->modifierKeyCount[i]--; - if (keyc->modifierKeyCount[i]<=0) { - xkbi->state.base_mods&= ~bit; - keyc->modifierKeyCount[i] = 0; - } - xkbi->clearMods&= ~bit; - } - } - } - - if (sendEvent) { - DeviceIntPtr tmpdev; - if (keyEvent) - tmpdev = dev; - else - tmpdev = GetPairedDevice(dev); - - UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc); - dev->public.processInputProc((InternalEvent*)event, tmpdev); - COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, - backupproc,xkbUnwrapProc); - } - else if (keyEvent) { - FixKeyState(event, dev); - } - - XkbComputeDerivedState(xkbi); - changed = XkbStateChangedFlags(&xkbi->prev_state,&xkbi->state); - if (genStateNotify) { - if (changed) { - xkbStateNotify sn; - sn.keycode= key; - sn.eventType= event->type; - sn.requestMajor = sn.requestMinor = 0; - sn.changed= changed; - XkbSendStateNotify(dev,&sn); - } - xkbi->flags&= ~_XkbStateNotifyInProgress; - } - changed= XkbIndicatorsToUpdate(dev,changed,FALSE); - if (changed) { - XkbEventCauseRec cause; - XkbSetCauseKey(&cause, key, event->type); - XkbUpdateIndicators(dev,changed,FALSE,NULL,&cause); - } - return; -} - -int -XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches) -{ -XkbSrvInfoPtr xkbi; -XkbFilterPtr filter; -XkbAction act; -unsigned clear; - - if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { - xkbi = pXDev->key->xkbInfo; - clear= (mask&(~latches)); - xkbi->state.latched_mods&= ~clear; - /* Clear any pending latch to locks. - */ - act.type = XkbSA_NoAction; - _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act); - act.type = XkbSA_LatchMods; - act.mods.flags = 0; - act.mods.mask = mask&latches; - filter = _XkbNextFreeFilter(xkbi); - _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); - _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); - return Success; - } - return BadValue; -} - -int -XkbLatchGroup(DeviceIntPtr pXDev,int group) -{ -XkbSrvInfoPtr xkbi; -XkbFilterPtr filter; -XkbAction act; - - if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { - xkbi = pXDev->key->xkbInfo; - act.type = XkbSA_LatchGroup; - act.group.flags = 0; - XkbSASetGroup(&act.group,group); - filter = _XkbNextFreeFilter(xkbi); - _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); - _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); - return Success; - } - return BadValue; -} - -/***====================================================================***/ - -void -XkbClearAllLatchesAndLocks( DeviceIntPtr dev, - XkbSrvInfoPtr xkbi, - Bool genEv, - XkbEventCausePtr cause) -{ -XkbStateRec os; -xkbStateNotify sn; - - sn.changed= 0; - os= xkbi->state; - if (os.latched_mods) { /* clear all latches */ - XkbLatchModifiers(dev,~0,0); - sn.changed|= XkbModifierLatchMask; - } - if (os.latched_group) { - XkbLatchGroup(dev,0); - sn.changed|= XkbGroupLatchMask; - } - if (os.locked_mods) { - xkbi->state.locked_mods= 0; - sn.changed|= XkbModifierLockMask; - } - if (os.locked_group) { - xkbi->state.locked_group= 0; - sn.changed|= XkbGroupLockMask; - } - if ( genEv && sn.changed) { - CARD32 changed; - - XkbComputeDerivedState(xkbi); - sn.keycode= cause->kc; - sn.eventType= cause->event; - sn.requestMajor= cause->mjr; - sn.requestMinor= cause->mnr; - sn.changed= XkbStateChangedFlags(&os,&xkbi->state); - XkbSendStateNotify(dev,&sn); - changed= XkbIndicatorsToUpdate(dev,sn.changed,FALSE); - if (changed) { - XkbUpdateIndicators(dev,changed,TRUE,NULL,cause); - } - } - return; -} - -/* - * The event is injected into the event processing, not the EQ. Thus, - * ensure that we restore the master after the event sequence to the - * original set of classes. Otherwise, the master remains on the XTEST - * classes and drops events that don't fit into the XTEST layout (e.g. - * events with more than 2 valuators). - * - * FIXME: EQ injection in the processing stage is not designed for, so this - * is a rather awkward hack. The event list returned by GetPointerEvents() - * and friends is always prefixed with a DCE if the last _posted_ device was - * different. For normal events, this sequence then resets the master during - * the processing stage. Since we inject the PointerKey events in the - * processing stage though, we need to manually reset to restore the - * previous order, because the events already in the EQ must be sent for the - * right device. - * So we post-fix the event list we get from GPE with a DCE back to the - * previous slave device. - * - * First one on drinking island wins! - */ -static void -InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, ValuatorMask *mask) -{ - ScreenPtr pScreen; - EventListPtr events; - int nevents, i; - DeviceIntPtr ptr, mpointer, lastSlave = NULL; - Bool saveWait; - - if (IsMaster(dev)) { - mpointer = GetMaster(dev, MASTER_POINTER); - lastSlave = mpointer->lastSlave; - ptr = GetXTestDevice(mpointer); - } else if (IsFloating(dev)) - ptr = dev; - else - return; - - - events = InitEventList(GetMaximumEventsNum() + 1); - OsBlockSignals(); - pScreen = miPointerGetScreen(ptr); - saveWait = miPointerSetWaitForUpdate(pScreen, FALSE); - nevents = GetPointerEvents(events, ptr, type, button, flags, mask); - if (IsMaster(dev) && (lastSlave && lastSlave != ptr)) - UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT, &nevents); - miPointerSetWaitForUpdate(pScreen, saveWait); - OsReleaseSignals(); - - for (i = 0; i < nevents; i++) - mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); - - FreeEventList(events, GetMaximumEventsNum()); - -} - -static void -XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) -{ - ValuatorMask mask; - int gpe_flags = 0; - - /* ignore attached SDs */ - if (!IsMaster(dev) && !IsFloating(dev)) - return; - - if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY) - gpe_flags = POINTER_ABSOLUTE; - else - gpe_flags = POINTER_RELATIVE; - - valuator_mask_set_range(&mask, 0, 2, (int[]){x, y}); - - InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask); -} - -void -XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) -{ - DeviceIntPtr ptr; - int down; - - /* If dev is a slave device, and the SD is attached, do nothing. If we'd - * post through the attached master pointer we'd get duplicate events. - * - * if dev is a master keyboard, post through the XTEST device - * - * if dev is a floating slave, post through the device itself. - */ - - if (IsMaster(dev)) { - DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER); - ptr = GetXTestDevice(mpointer); - } else if (IsFloating(dev)) - ptr = dev; - else - return; - - down = button_is_down(ptr, button, BUTTON_PROCESSED); - if (press == down) - return; - - InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease, - button, 0, NULL); -} +/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +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 Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS 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 +#endif + +#include +#include +#include +#include +#include +#include "misc.h" +#include "inputstr.h" +#include "exevents.h" +#include "eventstr.h" +#include +#include "xkb.h" +#include +#include "mi.h" +#include "mipointer.h" +#include "inpututils.h" +#define EXTENSION_EVENT_BASE 64 + +DevPrivateKeyRec xkbDevicePrivateKeyRec; + +void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button); +static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y); + +void +xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, + pointer data) +{ + xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device); + ProcessInputProc backupproc; + if(xkbPrivPtr->unwrapProc) + xkbPrivPtr->unwrapProc = NULL; + + UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc); + proc(device,data); + COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, + backupproc,xkbUnwrapProc); +} + +Bool +XkbInitPrivates(void) +{ + return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE, sizeof(xkbDeviceInfoRec)); +} + +void +XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc) +{ + xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device); + WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc); +} + +/***====================================================================***/ + +static XkbAction +_FixUpAction(XkbDescPtr xkb,XkbAction *act) +{ +static XkbAction fake; + + if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) { + fake.type = XkbSA_NoAction; + return fake; + } + if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) { + if (act->any.type==XkbSA_SetMods) { + fake.mods.type = XkbSA_LatchMods; + fake.mods.mask = act->mods.mask; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.mods.flags= XkbSA_ClearLocks; + return fake; + } + if (act->any.type==XkbSA_SetGroup) { + fake.group.type = XkbSA_LatchGroup; + if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask)) + fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock; + else fake.group.flags= XkbSA_ClearLocks; + XkbSASetGroup(&fake.group,XkbSAGroup(&act->group)); + return fake; + } + } + return *act; +} + +static XkbAction +XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key) +{ +int effectiveGroup; +int col; +XkbDescPtr xkb; +XkbKeyTypePtr type; +XkbAction * pActs; +static XkbAction fake; + + xkb= xkbi->desc; + if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) { + fake.type = XkbSA_NoAction; + return fake; + } + pActs= XkbKeyActionsPtr(xkb,key); + col= 0; + + effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key); + if (effectiveGroup != XkbGroup1Index) + col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key)); + + type= XkbKeyKeyType(xkb,key,effectiveGroup); + if (type->map!=NULL) { + register unsigned i,mods; + register XkbKTMapEntryPtr entry; + mods= xkbState->mods&type->mods.mask; + for (entry= type->map,i=0;imap_count;i++,entry++) { + if ((entry->active)&&(entry->mods.mask==mods)) { + col+= entry->level; + break; + } + } + } + if (pActs[col].any.type==XkbSA_NoAction) + return pActs[col]; + fake= _FixUpAction(xkb,&pActs[col]); + return fake; +} + +static XkbAction +XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button) +{ +XkbAction fake; + if ((dev->button)&&(dev->button->xkb_acts)) { + if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) { + fake= _FixUpAction(kbd->key->xkbInfo->desc, + &dev->button->xkb_acts[button-1]); + return fake; + } + } + fake.any.type= XkbSA_NoAction; + return fake; +} + +/***====================================================================***/ + +#define SYNTHETIC_KEYCODE 1 +#define BTN_ACT_FLAG 0x100 + +static int +_XkbFilterSetState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction *pAction) +{ + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0); + filter->priv = 0; + filter->filter = _XkbFilterSetState; + if (pAction->type==XkbSA_SetMods) { + filter->upAction = *pAction; + xkbi->setMods= pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if (filter->keycode==keycode) { + if (filter->upAction.type==XkbSA_SetMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if (filter->upAction.mods.flags&XkbSA_ClearLocks) { + xkbi->state.locked_mods&= ~filter->upAction.mods.mask; + } + } + else { + if (filter->upAction.group.flags&XkbSA_ClearLocks) { + xkbi->state.locked_group = 0; + } + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + } + filter->active = 0; + } + else { + filter->upAction.mods.flags&= ~XkbSA_ClearLocks; + filter->filterOthers = 0; + } + return 1; +} + +#define LATCH_KEY_DOWN 1 +#define LATCH_PENDING 2 +#define NO_LATCH 3 + +static int +_XkbFilterLatchState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = LATCH_KEY_DOWN; + filter->filter = _XkbFilterLatchState; + if (pAction->type==XkbSA_LatchMods) { + filter->upAction = *pAction; + xkbi->setMods = pAction->mods.mask; + } + else { + xkbi->groupChange = XkbSAGroup(&pAction->group); + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->groupChange-= xkbi->state.base_group; + filter->upAction= *pAction; + XkbSASetGroup(&filter->upAction.group,xkbi->groupChange); + } + } + else if ( pAction && (filter->priv==LATCH_PENDING) ) { + if (((1<type)&XkbSA_BreakLatch)!=0) { + filter->active = 0; + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + } + else if ((pAction->type==filter->upAction.type)&& + (pAction->mods.flags==filter->upAction.mods.flags)&& + (pAction->mods.mask==filter->upAction.mods.mask)) { + if (filter->upAction.mods.flags&XkbSA_LatchToLock) { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_LockMods; + else pAction->group.type= XkbSA_LockGroup; + if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&& + (ctrls->enabled_ctrls&XkbStickyKeysMask)) { + XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK, + XkbStickyKeysMask); + } + } + else { + if (filter->upAction.type==XkbSA_LatchMods) + pAction->mods.type= XkbSA_SetMods; + else pAction->group.type= XkbSA_SetGroup; + } + if (filter->upAction.type==XkbSA_LatchMods) + xkbi->state.latched_mods&= ~filter->upAction.mods.mask; + else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group); + filter->active = 0; + } + } + else if (filter->keycode==keycode) { /* release */ + XkbControlsPtr ctrls= xkbi->desc->ctrls; + int needBeep; + int beepType= _BEEP_NONE; + + needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&& + XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)); + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->clearMods = filter->upAction.mods.mask; + if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&& + (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) { + xkbi->state.locked_mods&= ~xkbi->clearMods; + filter->priv= NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + else { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + if ((filter->upAction.group.flags&XkbSA_ClearLocks)&& + (xkbi->state.locked_group)) { + xkbi->state.locked_group = 0; + filter->priv = NO_LATCH; + beepType= _BEEP_STICKY_UNLOCK; + } + } + if (filter->priv==NO_LATCH) { + filter->active= 0; + } + else { + filter->priv= LATCH_PENDING; + if (filter->upAction.type==XkbSA_LatchMods) { + xkbi->state.latched_mods |= filter->upAction.mods.mask; + needBeep = xkbi->state.latched_mods ? needBeep : 0; + xkbi->state.latched_mods |= filter->upAction.mods.mask; + } + else { + xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group); + } + if (needBeep && (beepType==_BEEP_NONE)) + beepType= _BEEP_STICKY_LATCH; + } + if (needBeep && (beepType!=_BEEP_NONE)) + XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask); + } + else if (filter->priv==LATCH_KEY_DOWN) { + filter->priv= NO_LATCH; + filter->filterOthers = 0; + } + return 1; +} + +static int +_XkbFilterLockState( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + if (pAction&&(pAction->type==XkbSA_LockGroup)) { + if (pAction->group.flags&XkbSA_GroupAbsolute) + xkbi->state.locked_group= XkbSAGroup(&pAction->group); + else xkbi->state.locked_group+= XkbSAGroup(&pAction->group); + return 1; + } + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterLockState; + filter->upAction = *pAction; + xkbi->state.locked_mods^= pAction->mods.mask; + xkbi->setMods = pAction->mods.mask; + } + else if (filter->keycode==keycode) { + filter->active = 0; + xkbi->clearMods = filter->upAction.mods.mask; + } + return 1; +} + +#define ISO_KEY_DOWN 0 +#define NO_ISO_LOCK 1 + +static int +_XkbFilterISOLock( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + + if (filter->keycode==0) { /* initial press */ + CARD8 flags= pAction->iso.flags; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 1; + filter->priv = ISO_KEY_DOWN; + filter->upAction = *pAction; + filter->filter = _XkbFilterISOLock; + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = XkbSAGroup(&pAction->iso); + xkbi->setMods = 0; + } + else { + xkbi->setMods = pAction->iso.mask; + xkbi->groupChange = 0; + } + if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) { + filter->priv= NO_ISO_LOCK; + xkbi->state.locked_mods^= xkbi->state.base_mods; + } + if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) { +/* 6/22/93 (ef) -- lock groups if group key is down first */ + } + if (!(flags&XkbSA_ISONoAffectPtr)) { +/* 6/22/93 (ef) -- lock mouse buttons if they're down */ + } + } + else if (filter->keycode==keycode) { + CARD8 flags= filter->upAction.iso.flags; + + if (flags&XkbSA_ISODfltIsGroup) { + xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso); + xkbi->clearMods = 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso); + } + else { + xkbi->clearMods= filter->upAction.iso.mask; + xkbi->groupChange= 0; + if (filter->priv==ISO_KEY_DOWN) + xkbi->state.locked_mods^= filter->upAction.iso.mask; + } + filter->active = 0; + } + else if (pAction) { + CARD8 flags= filter->upAction.iso.flags; + + switch (pAction->type) { + case XkbSA_SetMods: case XkbSA_LatchMods: + if (!(flags&XkbSA_ISONoAffectMods)) { + pAction->type= XkbSA_LockMods; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetGroup: case XkbSA_LatchGroup: + if (!(flags&XkbSA_ISONoAffectGroup)) { + pAction->type= XkbSA_LockGroup; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_PtrBtn: + if (!(flags&XkbSA_ISONoAffectPtr)) { + pAction->type= XkbSA_LockPtrBtn; + filter->priv= NO_ISO_LOCK; + } + break; + case XkbSA_SetControls: + if (!(flags&XkbSA_ISONoAffectCtrls)) { + pAction->type= XkbSA_LockControls; + filter->priv= NO_ISO_LOCK; + } + break; + } + } + return 1; +} + + +static CARD32 +_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg) +{ +XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg; +XkbControlsPtr ctrls= xkbi->desc->ctrls; +int dx,dy; + + if (xkbi->mouseKey==0) + return 0; + + if (xkbi->mouseKeysAccel) { + if ((xkbi->mouseKeysCounter)mk_time_to_max) { + double step; + xkbi->mouseKeysCounter++; + step= xkbi->mouseKeysCurveFactor* + pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve); + if (xkbi->mouseKeysDX<0) + dx= floor( ((double)xkbi->mouseKeysDX)*step ); + else dx= ceil( ((double)xkbi->mouseKeysDX)*step ); + if (xkbi->mouseKeysDY<0) + dy= floor( ((double)xkbi->mouseKeysDY)*step ); + else dy= ceil( ((double)xkbi->mouseKeysDY)*step ); + } + else { + dx= xkbi->mouseKeysDX*ctrls->mk_max_speed; + dy= xkbi->mouseKeysDY*ctrls->mk_max_speed; + } + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX) + dx= xkbi->mouseKeysDX; + if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY) + dy= xkbi->mouseKeysDY; + } + else { + dx= xkbi->mouseKeysDX; + dy= xkbi->mouseKeysDY; + } + XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy); + return xkbi->desc->ctrls->mk_interval; +} + +static int +_XkbFilterPointerMove( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +int x,y; +Bool accel; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerMove; + filter->upAction= *pAction; + xkbi->mouseKeysCounter= 0; + xkbi->mouseKey= keycode; + accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0); + x= XkbPtrActionX(&pAction->ptr); + y= XkbPtrActionY(&pAction->ptr); + XkbFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y); + AccessXCancelRepeatKey(xkbi,keycode); + xkbi->mouseKeysAccel= accel&& + (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask); + xkbi->mouseKeysFlags= pAction->ptr.flags; + xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr); + xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr); + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, + xkbi->desc->ctrls->mk_delay, + _XkbPtrAccelExpire,(pointer)xkbi); + } + else if (filter->keycode==keycode) { + filter->active = 0; + if (xkbi->mouseKey==keycode) { + xkbi->mouseKey= 0; + xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0, + NULL, NULL); + } + } + return 0; +} + +static int +_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + if (filter->keycode==0) { /* initial press */ + int button= pAction->btn.button; + + if (button==XkbSA_UseDfltButton) + button = xkbi->desc->ctrls->mk_dflt_btn; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterPointerBtn; + filter->upAction= *pAction; + filter->upAction.btn.button= button; + switch (pAction->type) { + case XkbSA_LockPtrBtn: + if (((xkbi->lockedPtrButtons&(1<btn.flags&XkbSA_LockNoLock)==0)) { + xkbi->lockedPtrButtons|= (1<device, 1, button); + filter->upAction.type= XkbSA_NoAction; + } + break; + case XkbSA_PtrBtn: + { + register int i,nClicks; + AccessXCancelRepeatKey(xkbi,keycode); + if (pAction->btn.count>0) { + nClicks= pAction->btn.count; + for (i=0;idevice, 1, button); + XkbFakeDeviceButton(xkbi->device, 0, button); + } + filter->upAction.type= XkbSA_NoAction; + } + else XkbFakeDeviceButton(xkbi->device, 1, button); + } + break; + case XkbSA_SetPtrDflt: + { + XkbControlsPtr ctrls= xkbi->desc->ctrls; + XkbControlsRec old; + xkbControlsNotify cn; + + old= *ctrls; + AccessXCancelRepeatKey(xkbi,keycode); + switch (pAction->dflt.affect) { + case XkbSA_AffectDfltBtn: + if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute) + ctrls->mk_dflt_btn= + XkbSAPtrDfltValue(&pAction->dflt); + else { + ctrls->mk_dflt_btn+= + XkbSAPtrDfltValue(&pAction->dflt); + if (ctrls->mk_dflt_btn>5) + ctrls->mk_dflt_btn= 5; + else if (ctrls->mk_dflt_btn<1) + ctrls->mk_dflt_btn= 1; + } + break; + default: + ErrorF( + "Attempt to change unknown pointer default (%d) ignored\n", + pAction->dflt.affect); + break; + } + if (XkbComputeControlsNotify(xkbi->device, + &old,xkbi->desc->ctrls, + &cn,FALSE)) { + cn.keycode = keycode; + /* XXX: what about DeviceKeyPress? */ + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(xkbi->device,&cn); + } + } + break; + } + } + else if (filter->keycode==keycode) { + int button= filter->upAction.btn.button; + + switch (filter->upAction.type) { + case XkbSA_LockPtrBtn: + if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)|| + ((xkbi->lockedPtrButtons&(1<lockedPtrButtons&= ~(1<device)) + { + XkbMergeLockedPtrBtns(xkbi->device); + /* One SD still has lock set, don't post event */ + if ((xkbi->lockedPtrButtons & (1 << button)) != 0) + break; + } + + /* fallthrough */ + case XkbSA_PtrBtn: + XkbFakeDeviceButton(xkbi->device, 0, button); + break; + } + filter->active = 0; + } + return 0; +} + +static int +_XkbFilterControls( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +XkbControlsRec old; +XkbControlsPtr ctrls; +DeviceIntPtr kbd; +unsigned int change; +XkbEventCauseRec cause; + + kbd= xkbi->device; + ctrls= xkbi->desc->ctrls; + old= *ctrls; + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + change= XkbActionCtrls(&pAction->ctrls); + filter->priv = change; + filter->filter = _XkbFilterControls; + filter->upAction = *pAction; + + if (pAction->type==XkbSA_LockControls) { + filter->priv= (ctrls->enabled_ctrls&change); + change&= ~ctrls->enabled_ctrls; + } + + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls|= change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) { + cn.keycode = keycode; + /* XXX: what about DeviceKeyPress? */ + cn.eventType = KeyPress; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyPress); + + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change); + } + } + else if (filter->keycode==keycode) { + change= filter->priv; + if (change) { + xkbControlsNotify cn; + XkbSrvLedInfoPtr sli; + + ctrls->enabled_ctrls&= ~change; + if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) { + cn.keycode = keycode; + cn.eventType = KeyRelease; + cn.requestMajor = 0; + cn.requestMinor = 0; + XkbSendControlsNotify(kbd,&cn); + } + + XkbSetCauseKey(&cause,keycode,KeyRelease); + /* If sticky keys were disabled, clear all locks and latches */ + if ((old.enabled_ctrls&XkbStickyKeysMask)&& + (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) { + XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause); + } + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause); + if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) + XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change); + } + filter->keycode= 0; + filter->active= 0; + } + return 1; +} + +static int +_XkbFilterActionMessage(XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +XkbMessageAction * pMsg; +DeviceIntPtr kbd; + + kbd= xkbi->device; + if (filter->keycode==0) { /* initial press */ + pMsg= &pAction->msg; + if ((pMsg->flags&XkbSA_MessageOnRelease)|| + ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) { + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterActionMessage; + filter->upAction = *pAction; + } + if (pMsg->flags&XkbSA_MessageOnPress) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 1; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message, + (char *)pMsg->message,XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0); + } + else if (filter->keycode==keycode) { + pMsg= &filter->upAction.msg; + if (pMsg->flags&XkbSA_MessageOnRelease) { + xkbActionMessage msg; + + msg.keycode= keycode; + msg.press= 0; + msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + memcpy((char *)msg.message,(char *)pMsg->message, + XkbActionMessageLength); + XkbSendActionMessage(kbd,&msg); + } + filter->keycode= 0; + filter->active= 0; + return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0); + } + return 0; +} + +static int +_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +DeviceEvent ev; +int x,y; +XkbStateRec old; +unsigned mods,mask; +xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device); +ProcessInputProc backupproc; + + /* never actually used uninitialised, but gcc isn't smart enough + * to work that out. */ + memset(&old, 0, sizeof(old)); + memset(&ev, 0, sizeof(ev)); + + if ((filter->keycode!=0)&&(filter->keycode!=keycode)) + return 1; + + GetSpritePosition(xkbi->device, &x,&y); + ev.header = ET_Internal; + ev.length = sizeof(DeviceEvent); + ev.time = GetTimeInMillis(); + ev.root_x = x; + ev.root_y = y; + + if (filter->keycode==0) { /* initial press */ + if ((pAction->redirect.new_keydesc->min_key_code)|| + (pAction->redirect.new_key>xkbi->desc->max_key_code)) { + return 1; + } + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv = 0; + filter->filter = _XkbFilterRedirectKey; + filter->upAction = *pAction; + + ev.type = ET_KeyPress; + ev.detail.key = pAction->redirect.new_key; + + mask= XkbSARedirectVModsMask(&pAction->redirect); + mods= XkbSARedirectVMods(&pAction->redirect); + if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); + if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); + mask|= pAction->redirect.mods_mask; + mods|= pAction->redirect.mods; + + if ( mask || mods ) { + old= xkbi->state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + } + + UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); + xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device); + COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, + backupproc,xkbUnwrapProc); + + if ( mask || mods ) + xkbi->state= old; + } + else if (filter->keycode==keycode) { + + ev.type = ET_KeyRelease; + ev.detail.key = filter->upAction.redirect.new_key; + + mask= XkbSARedirectVModsMask(&filter->upAction.redirect); + mods= XkbSARedirectVMods(&filter->upAction.redirect); + if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask); + if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods); + mask|= filter->upAction.redirect.mods_mask; + mods|= filter->upAction.redirect.mods; + + if ( mask || mods ) { + old= xkbi->state; + xkbi->state.base_mods&= ~mask; + xkbi->state.base_mods|= (mods&mask); + xkbi->state.latched_mods&= ~mask; + xkbi->state.latched_mods|= (mods&mask); + xkbi->state.locked_mods&= ~mask; + xkbi->state.locked_mods|= (mods&mask); + XkbComputeDerivedState(xkbi); + } + + UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); + xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device); + COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, + backupproc,xkbUnwrapProc); + + if ( mask || mods ) + xkbi->state= old; + + filter->keycode= 0; + filter->active= 0; + } + return 0; +} + +static int +_XkbFilterSwitchScreen( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + DeviceIntPtr dev = xkbi->device; + if (dev == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->filter = _XkbFilterSwitchScreen; + AccessXCancelRepeatKey(xkbi, keycode); + XkbDDXSwitchScreen(dev,keycode,pAction); + return 0; + } + else if (filter->keycode==keycode) { + filter->active= 0; + return 0; + } + return 1; +} + +static int +_XkbFilterXF86Private( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ + DeviceIntPtr dev = xkbi->device; + if (dev == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->filter = _XkbFilterXF86Private; + XkbDDXPrivate(dev,keycode,pAction); + return 0; + } + else if (filter->keycode==keycode) { + filter->active= 0; + return 0; + } + return 1; +} + + +static int +_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ +DeviceIntPtr dev; +int button; + + if (xkbi->device == inputInfo.keyboard) + return 0; + + if (filter->keycode==0) { /* initial press */ + _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient, + DixUnknownAccess, &button); + if (!dev || !dev->public.on) + return 1; + + button= pAction->devbtn.button; + if ((button<1)||(button>dev->button->numButtons)) + return 1; + + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; + filter->priv=0; + filter->filter = _XkbFilterDeviceBtn; + filter->upAction= *pAction; + switch (pAction->type) { + case XkbSA_LockDeviceBtn: + if ((pAction->devbtn.flags&XkbSA_LockNoLock)|| + BitIsOn(dev->button->down, button)) + return 0; + XkbFakeDeviceButton(dev,TRUE,button); + filter->upAction.type= XkbSA_NoAction; + break; + case XkbSA_DeviceBtn: + if (pAction->devbtn.count>0) { + int nClicks,i; + nClicks= pAction->btn.count; + for (i=0;iupAction.type= XkbSA_NoAction; + } + else XkbFakeDeviceButton(dev,TRUE,button); + break; + } + } + else if (filter->keycode==keycode) { + int button; + + filter->active= 0; + _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device, + serverClient, DixUnknownAccess, &button); + if (!dev || !dev->public.on) + return 1; + + button= filter->upAction.btn.button; + switch (filter->upAction.type) { + case XkbSA_LockDeviceBtn: + if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)|| + !BitIsOn(dev->button->down, button)) + return 0; + XkbFakeDeviceButton(dev,FALSE,button); + break; + case XkbSA_DeviceBtn: + XkbFakeDeviceButton(dev,FALSE,button); + break; + } + filter->active = 0; + } + return 0; +} + +static XkbFilterPtr +_XkbNextFreeFilter( + XkbSrvInfoPtr xkbi +) +{ +register int i; + + if (xkbi->szFilters==0) { + xkbi->szFilters = 4; + xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec)); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + } + for (i=0;iszFilters;i++) { + if (!xkbi->filters[i].active) { + xkbi->filters[i].keycode = 0; + return &xkbi->filters[i]; + } + } + xkbi->szFilters*=2; + xkbi->filters= realloc(xkbi->filters, + xkbi->szFilters * sizeof(XkbFilterRec)); + /* 6/21/93 (ef) -- XXX! deal with allocation failure */ + memset(&xkbi->filters[xkbi->szFilters/2], 0, + (xkbi->szFilters/2)*sizeof(XkbFilterRec)); + return &xkbi->filters[xkbi->szFilters/2]; +} + +static int +_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction) +{ +register int i,send; + + send= 1; + for (i=0;iszFilters;i++) { + if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter)) + send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction) + && send); + } + return send; +} + +void +XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent* event) +{ +int key,bit,i; +XkbSrvInfoPtr xkbi; +KeyClassPtr keyc; +int changed,sendEvent; +Bool genStateNotify; +XkbAction act; +XkbFilterPtr filter; +Bool keyEvent; +Bool pressEvent; +ProcessInputProc backupproc; + +xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev); + + keyc= kbd->key; + xkbi= keyc->xkbInfo; + key= event->detail.key; + /* The state may change, so if we're not in the middle of sending a state + * notify, prepare for it */ + if ((xkbi->flags&_XkbStateNotifyInProgress)==0) { + xkbi->prev_state = xkbi->state; + xkbi->flags|= _XkbStateNotifyInProgress; + genStateNotify= TRUE; + } + else genStateNotify= FALSE; + + xkbi->clearMods = xkbi->setMods = 0; + xkbi->groupChange = 0; + + sendEvent = 1; + keyEvent= ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease)); + pressEvent= ((event->type == ET_KeyPress)|| (event->type == ET_ButtonPress)); + + if (pressEvent) { + if (keyEvent) + act = XkbGetKeyAction(xkbi,&xkbi->state,key); + else { + act = XkbGetButtonAction(kbd,dev,key); + key|= BTN_ACT_FLAG; + } + sendEvent = _XkbApplyFilters(xkbi,key,&act); + if (sendEvent) { + switch (act.type) { + case XkbSA_SetMods: + case XkbSA_SetGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent = _XkbFilterSetState(xkbi,filter,key,&act); + break; + case XkbSA_LatchMods: + case XkbSA_LatchGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act); + break; + case XkbSA_LockMods: + case XkbSA_LockGroup: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterLockState(xkbi,filter,key,&act); + break; + case XkbSA_ISOLock: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act); + break; + case XkbSA_MovePtr: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act); + break; + case XkbSA_PtrBtn: + case XkbSA_LockPtrBtn: + case XkbSA_SetPtrDflt: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act); + break; + case XkbSA_Terminate: + sendEvent= XkbDDXTerminateServer(dev,key,&act); + break; + case XkbSA_SwitchScreen: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act); + break; + case XkbSA_SetControls: + case XkbSA_LockControls: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterControls(xkbi,filter,key,&act); + break; + case XkbSA_ActionMessage: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act); + break; + case XkbSA_RedirectKey: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act); + break; + case XkbSA_DeviceBtn: + case XkbSA_LockDeviceBtn: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act); + break; + case XkbSA_XFree86Private: + filter = _XkbNextFreeFilter(xkbi); + sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act); + break; + } + } + } + else { + if (!keyEvent) + key|= BTN_ACT_FLAG; + sendEvent = _XkbApplyFilters(xkbi,key,NULL); + } + + if (xkbi->groupChange!=0) + xkbi->state.base_group+= xkbi->groupChange; + if (xkbi->setMods) { + for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) { + if (xkbi->setMods&bit) { + keyc->modifierKeyCount[i]++; + xkbi->state.base_mods|= bit; + xkbi->setMods&= ~bit; + } + } + } + if (xkbi->clearMods) { + for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) { + if (xkbi->clearMods&bit) { + keyc->modifierKeyCount[i]--; + if (keyc->modifierKeyCount[i]<=0) { + xkbi->state.base_mods&= ~bit; + keyc->modifierKeyCount[i] = 0; + } + xkbi->clearMods&= ~bit; + } + } + } + + if (sendEvent) { + DeviceIntPtr tmpdev; + if (keyEvent) + tmpdev = dev; + else + tmpdev = GetPairedDevice(dev); + + UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc); + dev->public.processInputProc((InternalEvent*)event, tmpdev); + COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, + backupproc,xkbUnwrapProc); + } + else if (keyEvent) { + FixKeyState(event, dev); + } + + XkbComputeDerivedState(xkbi); + changed = XkbStateChangedFlags(&xkbi->prev_state,&xkbi->state); + if (genStateNotify) { + if (changed) { + xkbStateNotify sn; + sn.keycode= key; + sn.eventType= event->type; + sn.requestMajor = sn.requestMinor = 0; + sn.changed= changed; + XkbSendStateNotify(dev,&sn); + } + xkbi->flags&= ~_XkbStateNotifyInProgress; + } + changed= XkbIndicatorsToUpdate(dev,changed,FALSE); + if (changed) { + XkbEventCauseRec cause; + XkbSetCauseKey(&cause, key, event->type); + XkbUpdateIndicators(dev,changed,FALSE,NULL,&cause); + } + return; +} + +int +XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches) +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; +unsigned clear; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + clear= (mask&(~latches)); + xkbi->state.latched_mods&= ~clear; + /* Clear any pending latch to locks. + */ + act.type = XkbSA_NoAction; + _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act); + act.type = XkbSA_LatchMods; + act.mods.flags = 0; + act.mods.mask = mask&latches; + filter = _XkbNextFreeFilter(xkbi); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +int +XkbLatchGroup(DeviceIntPtr pXDev,int group) +{ +XkbSrvInfoPtr xkbi; +XkbFilterPtr filter; +XkbAction act; + + if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) { + xkbi = pXDev->key->xkbInfo; + act.type = XkbSA_LatchGroup; + act.group.flags = 0; + XkbSASetGroup(&act.group,group); + filter = _XkbNextFreeFilter(xkbi); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act); + _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL); + return Success; + } + return BadValue; +} + +/***====================================================================***/ + +void +XkbClearAllLatchesAndLocks( DeviceIntPtr dev, + XkbSrvInfoPtr xkbi, + Bool genEv, + XkbEventCausePtr cause) +{ +XkbStateRec os; +xkbStateNotify sn; + + sn.changed= 0; + os= xkbi->state; + if (os.latched_mods) { /* clear all latches */ + XkbLatchModifiers(dev,~0,0); + sn.changed|= XkbModifierLatchMask; + } + if (os.latched_group) { + XkbLatchGroup(dev,0); + sn.changed|= XkbGroupLatchMask; + } + if (os.locked_mods) { + xkbi->state.locked_mods= 0; + sn.changed|= XkbModifierLockMask; + } + if (os.locked_group) { + xkbi->state.locked_group= 0; + sn.changed|= XkbGroupLockMask; + } + if ( genEv && sn.changed) { + CARD32 changed; + + XkbComputeDerivedState(xkbi); + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + sn.changed= XkbStateChangedFlags(&os,&xkbi->state); + XkbSendStateNotify(dev,&sn); + changed= XkbIndicatorsToUpdate(dev,sn.changed,FALSE); + if (changed) { + XkbUpdateIndicators(dev,changed,TRUE,NULL,cause); + } + } + return; +} + +/* + * The event is injected into the event processing, not the EQ. Thus, + * ensure that we restore the master after the event sequence to the + * original set of classes. Otherwise, the master remains on the XTEST + * classes and drops events that don't fit into the XTEST layout (e.g. + * events with more than 2 valuators). + * + * FIXME: EQ injection in the processing stage is not designed for, so this + * is a rather awkward hack. The event list returned by GetPointerEvents() + * and friends is always prefixed with a DCE if the last _posted_ device was + * different. For normal events, this sequence then resets the master during + * the processing stage. Since we inject the PointerKey events in the + * processing stage though, we need to manually reset to restore the + * previous order, because the events already in the EQ must be sent for the + * right device. + * So we post-fix the event list we get from GPE with a DCE back to the + * previous slave device. + * + * First one on drinking island wins! + */ +static void +InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, ValuatorMask *mask) +{ + ScreenPtr pScreen; + EventListPtr events; + int nevents, i; + DeviceIntPtr ptr, mpointer, lastSlave = NULL; + Bool saveWait; + + if (IsMaster(dev)) { + mpointer = GetMaster(dev, MASTER_POINTER); + lastSlave = mpointer->lastSlave; + ptr = GetXTestDevice(mpointer); + } else if (IsFloating(dev)) + ptr = dev; + else + return; + + + events = InitEventList(GetMaximumEventsNum() + 1); + OsBlockSignals(); + pScreen = miPointerGetScreen(ptr); + saveWait = miPointerSetWaitForUpdate(pScreen, FALSE); + nevents = GetPointerEvents(events, ptr, type, button, flags, mask); + if (IsMaster(dev) && (lastSlave && lastSlave != ptr)) + UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT, &nevents); + miPointerSetWaitForUpdate(pScreen, saveWait); + OsReleaseSignals(); + + for (i = 0; i < nevents; i++) + mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); + + FreeEventList(events, GetMaximumEventsNum()); + +} + +static void +XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) +{ + ValuatorMask mask; + int gpe_flags = 0; + + /* ignore attached SDs */ + if (!IsMaster(dev) && !IsFloating(dev)) + return; + + if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY) + gpe_flags = POINTER_ABSOLUTE; + else + gpe_flags = POINTER_RELATIVE; + + valuator_mask_set_range(&mask, 0, 2, (int[]){x, y}); + + InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask); +} + +void +XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) +{ + DeviceIntPtr ptr; + int down; + + /* If dev is a slave device, and the SD is attached, do nothing. If we'd + * post through the attached master pointer we'd get duplicate events. + * + * if dev is a master keyboard, post through the XTEST device + * + * if dev is a floating slave, post through the device itself. + */ + + if (IsMaster(dev)) { + DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER); + ptr = GetXTestDevice(mpointer); + } else if (IsFloating(dev)) + ptr = dev; + else + return; + + down = button_is_down(ptr, button, BUTTON_PROCESSED); + if (press == down) + return; + + InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease, + button, 0, NULL); +} -- cgit v1.2.3