aboutsummaryrefslogtreecommitdiff
path: root/xorg-server
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server')
-rw-r--r--xorg-server/Xi/exevents.c4353
-rw-r--r--xorg-server/Xi/extinit.c2617
-rw-r--r--xorg-server/Xi/xiwarppointer.c2
-rw-r--r--xorg-server/configure.ac4
-rw-r--r--xorg-server/dix/events.c11632
-rw-r--r--xorg-server/dix/inpututils.c1108
-rw-r--r--xorg-server/dix/resource.c1938
-rw-r--r--xorg-server/hw/dmx/config/xdmxconfig.c2
-rw-r--r--xorg-server/hw/dmx/dmxextension.c3238
-rw-r--r--xorg-server/hw/dmx/dmxgc.c837
-rw-r--r--xorg-server/hw/dmx/input/dmxinputinit.c2580
-rw-r--r--xorg-server/hw/xfree86/doc/man/Makefile.am2
-rw-r--r--xorg-server/hw/xfree86/doc/man/xorg.conf.d.man1
-rw-r--r--xorg-server/hw/xwin/InitOutput.c2219
-rw-r--r--xorg-server/hw/xwin/Makefile.am1
-rw-r--r--xorg-server/hw/xwin/man/XWin.man85
-rw-r--r--xorg-server/hw/xwin/win.h2950
-rw-r--r--xorg-server/hw/xwin/wincreatewnd.c48
-rw-r--r--xorg-server/hw/xwin/windialogs.c1547
-rw-r--r--xorg-server/hw/xwin/winmonitors.c92
-rw-r--r--xorg-server/hw/xwin/winmonitors.h14
-rw-r--r--xorg-server/hw/xwin/winnativegdi.c1073
-rw-r--r--xorg-server/hw/xwin/winpfbdd.c1354
-rw-r--r--xorg-server/hw/xwin/winprocarg.c2473
-rw-r--r--xorg-server/hw/xwin/winrandr.c302
-rw-r--r--xorg-server/hw/xwin/winscrinit.c1536
-rw-r--r--xorg-server/hw/xwin/winshaddd.c2766
-rw-r--r--xorg-server/hw/xwin/winshadddnl.c2808
-rw-r--r--xorg-server/hw/xwin/winshadgdi.c2526
-rw-r--r--xorg-server/hw/xwin/winvalargs.c360
-rw-r--r--xorg-server/hw/xwin/winwindow.c1273
-rw-r--r--xorg-server/hw/xwin/winwndproc.c2575
-rw-r--r--xorg-server/include/dix.h1211
-rw-r--r--xorg-server/include/input.h1174
-rw-r--r--xorg-server/include/inputstr.h1230
-rw-r--r--xorg-server/mi/miinitext.c2
-rw-r--r--xorg-server/os/WaitFor.c1368
-rw-r--r--xorg-server/test/input.c2172
-rw-r--r--xorg-server/test/xi2/protocol-eventconvert.c1824
-rw-r--r--xorg-server/test/xi2/protocol-xiselectevents.c18
-rw-r--r--xorg-server/xkb/XKBMisc.c1679
-rw-r--r--xorg-server/xkb/xkbUtils.c4247
42 files changed, 34777 insertions, 34464 deletions
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c
index 40e03337d..327873e29 100644
--- a/xorg-server/Xi/exevents.c
+++ b/xorg-server/Xi/exevents.c
@@ -1,2176 +1,2177 @@
-/************************************************************
-
-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.
-
-Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
-
- 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 Hewlett-Packard not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-HEWLETT-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.
-
-********************************************************/
-
-/********************************************************************
- *
- * Routines to register and initialize extension input devices.
- * This also contains ProcessOtherEvent, the routine called from DDX
- * to route extension events.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h"
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include <X11/extensions/XI2proto.h>
-#include <X11/extensions/geproto.h>
-#include "windowstr.h"
-#include "miscstruct.h"
-#include "region.h"
-#include "exevents.h"
-#include "extnsionst.h"
-#include "exglobals.h"
-#include "dixevents.h" /* DeliverFocusedEvent */
-#include "dixgrabs.h" /* CreateGrab() */
-#include "scrnintstr.h"
-#include "listdev.h" /* for CopySwapXXXClass */
-#include "xace.h"
-#include "xiquerydevice.h" /* For List*Info */
-#include "eventconvert.h"
-#include "eventstr.h"
-
-#include <X11/extensions/XKBproto.h>
-#include "xkbsrv.h"
-
-#define WID(w) ((w) ? ((w)->drawable.id) : 0)
-#define AllModifiersMask ( \
- ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
- Mod3Mask | Mod4Mask | Mod5Mask )
-#define AllButtonsMask ( \
- Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
-
-Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
- Bool /* ignoreSelectedEvents */
- );
-static Bool MakeInputMasks(WindowPtr /* pWin */
- );
-
-/*
- * Only let the given client know of core events which will affect its
- * interpretation of input events, if the client's ClientPointer (or the
- * paired keyboard) is the current device.
- */
-int
-XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
-{
- DeviceIntPtr current_ptr = PickPointer(client);
- DeviceIntPtr current_kbd = GetPairedDevice(current_ptr);
-
- if (dev == current_kbd || dev == current_ptr)
- return 1;
-
- return 0;
-}
-
-Bool
-IsPointerEvent(InternalEvent* event)
-{
- switch(event->any.type)
- {
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_Motion:
- /* XXX: enter/leave ?? */
- return TRUE;
- default:
- break;
- }
- return FALSE;
-}
-
-/**
- * @return the device matching the deviceid of the device set in the event, or
- * NULL if the event is not an XInput event.
- */
-DeviceIntPtr
-XIGetDevice(xEvent* xE)
-{
- DeviceIntPtr pDev = NULL;
-
- if (xE->u.u.type == DeviceButtonPress ||
- xE->u.u.type == DeviceButtonRelease ||
- xE->u.u.type == DeviceMotionNotify ||
- xE->u.u.type == ProximityIn ||
- xE->u.u.type == ProximityOut ||
- xE->u.u.type == DevicePropertyNotify)
- {
- int rc;
- int id;
-
- id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
-
- rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
- if (rc != Success)
- ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
- }
- return pDev;
-}
-
-
-/**
- * Copy the device->key into master->key and send a mapping notify to the
- * clients if appropriate.
- * master->key needs to be allocated by the caller.
- *
- * Device is the slave device. If it is attached to a master device, we may
- * need to send a mapping notify to the client because it causes the MD
- * to change state.
- *
- * Mapping notify needs to be sent in the following cases:
- * - different slave device on same master
- * - different master
- *
- * XXX: They way how the code is we also send a map notify if the slave device
- * stays the same, but the master changes. This isn't really necessary though.
- *
- * XXX: this gives you funny behaviour with the ClientPointer. When a
- * MappingNotify is sent to the client, the client usually responds with a
- * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
- * mapping, regardless of which keyboard sent the last mapping notify request.
- * So depending on the CP setting, your keyboard may change layout in each
- * app...
- *
- * This code is basically the old SwitchCoreKeyboard.
- */
-
-void
-CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
-{
- KeyClassPtr mk = master->key;
-
- if (device == master)
- return;
-
- mk->sourceid = device->id;
-
-
- if (!XkbCopyDeviceKeymap(master, device))
- FatalError("Couldn't pivot keymap from device to core!\n");
-}
-
-/**
- * Copies the feedback classes from device "from" into device "to". Classes
- * are duplicated (not just flipping the pointers). All feedback classes are
- * linked lists, the full list is duplicated.
- */
-static void
-DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
-{
- ClassesPtr classes;
-
-
- if (from->intfeed)
- {
- IntegerFeedbackPtr *i, it;
-
- if (!to->intfeed)
- {
- classes = to->unused_classes;
- to->intfeed = classes->intfeed;
- classes->intfeed = NULL;
- }
-
- i = &to->intfeed;
- for (it = from->intfeed; it; it = it->next)
- {
- if (!(*i))
- {
- *i = calloc(1, sizeof(IntegerFeedbackClassRec));
- if (!(*i))
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*i)->CtrlProc = it->CtrlProc;
- (*i)->ctrl = it->ctrl;
-
- i = &(*i)->next;
- }
- } else if (to->intfeed && !from->intfeed)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->intfeed = to->intfeed;
- to->intfeed = NULL;
- }
-
- if (from->stringfeed)
- {
- StringFeedbackPtr *s, it;
-
- if (!to->stringfeed)
- {
- classes = to->unused_classes;
- to->stringfeed = classes->stringfeed;
- classes->stringfeed = NULL;
- }
-
- s = &to->stringfeed;
- for (it = from->stringfeed; it; it = it->next)
- {
- if (!(*s))
- {
- *s = calloc(1, sizeof(StringFeedbackClassRec));
- if (!(*s))
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*s)->CtrlProc = it->CtrlProc;
- (*s)->ctrl = it->ctrl;
-
- s = &(*s)->next;
- }
- } else if (to->stringfeed && !from->stringfeed)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->stringfeed = to->stringfeed;
- to->stringfeed = NULL;
- }
-
- if (from->bell)
- {
- BellFeedbackPtr *b, it;
-
- if (!to->bell)
- {
- classes = to->unused_classes;
- to->bell = classes->bell;
- classes->bell = NULL;
- }
-
- b = &to->bell;
- for (it = from->bell; it; it = it->next)
- {
- if (!(*b))
- {
- *b = calloc(1, sizeof(BellFeedbackClassRec));
- if (!(*b))
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*b)->BellProc = it->BellProc;
- (*b)->CtrlProc = it->CtrlProc;
- (*b)->ctrl = it->ctrl;
-
- b = &(*b)->next;
- }
- } else if (to->bell && !from->bell)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->bell = to->bell;
- to->bell = NULL;
- }
-
- if (from->leds)
- {
- LedFeedbackPtr *l, it;
-
- if (!to->leds)
- {
- classes = to->unused_classes;
- to->leds = classes->leds;
- classes->leds = NULL;
- }
-
- l = &to->leds;
- for (it = from->leds; it; it = it->next)
- {
- if (!(*l))
- {
- *l = calloc(1, sizeof(LedFeedbackClassRec));
- if (!(*l))
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*l)->CtrlProc = it->CtrlProc;
- (*l)->ctrl = it->ctrl;
- if ((*l)->xkb_sli)
- XkbFreeSrvLedInfo((*l)->xkb_sli);
- (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
-
- l = &(*l)->next;
- }
- } else if (to->leds && !from->leds)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->leds = to->leds;
- to->leds = NULL;
- }
-}
-
-static void
-DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
-{
- ClassesPtr classes;
-
- /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
- * kbdfeed to be set up properly, so let's do the feedback classes first.
- */
- if (from->kbdfeed)
- {
- KbdFeedbackPtr *k, it;
-
- if (!to->kbdfeed)
- {
- classes = to->unused_classes;
-
- to->kbdfeed = classes->kbdfeed;
- if (!to->kbdfeed)
- InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
- classes->kbdfeed = NULL;
- }
-
- k = &to->kbdfeed;
- for(it = from->kbdfeed; it; it = it->next)
- {
- if (!(*k))
- {
- *k = calloc(1, sizeof(KbdFeedbackClassRec));
- if (!*k)
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*k)->BellProc = it->BellProc;
- (*k)->CtrlProc = it->CtrlProc;
- (*k)->ctrl = it->ctrl;
- if ((*k)->xkb_sli)
- XkbFreeSrvLedInfo((*k)->xkb_sli);
- (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
-
- k = &(*k)->next;
- }
- } else if (to->kbdfeed && !from->kbdfeed)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->kbdfeed = to->kbdfeed;
- to->kbdfeed = NULL;
- }
-
- if (from->key)
- {
- if (!to->key)
- {
- classes = to->unused_classes;
- to->key = classes->key;
- if (!to->key)
- InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
- else
- classes->key = NULL;
- }
-
- CopyKeyClass(from, to);
- } else if (to->key && !from->key)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->key = to->key;
- to->key = NULL;
- }
-
- /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
- * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo
- * didn't update the pointers so we need to do it manually here.
- */
- if (to->kbdfeed)
- {
- KbdFeedbackPtr k;
-
- for (k = to->kbdfeed; k; k = k->next)
- {
- if (!k->xkb_sli)
- continue;
- if (k->xkb_sli->flags & XkbSLI_IsDefault)
- {
- k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
- k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
- }
- }
- }
-
- /* We can't just copy over the focus class. When an app sets the focus,
- * it'll do so on the master device. Copying the SDs focus means losing
- * the focus.
- * So we only copy the focus class if the device didn't have one,
- * otherwise we leave it as it is.
- */
- if (from->focus)
- {
- if (!to->focus)
- {
- WindowPtr *oldTrace;
-
- classes = to->unused_classes;
- to->focus = classes->focus;
- if (!to->focus)
- {
- to->focus = calloc(1, sizeof(FocusClassRec));
- if (!to->focus)
- FatalError("[Xi] no memory for class shift.\n");
- } else
- classes->focus = NULL;
-
- oldTrace = to->focus->trace;
- memcpy(to->focus, from->focus, sizeof(FocusClassRec));
- to->focus->trace = realloc(oldTrace,
- to->focus->traceSize * sizeof(WindowPtr));
- if (!to->focus->trace && to->focus->traceSize)
- FatalError("[Xi] no memory for trace.\n");
- memcpy(to->focus->trace, from->focus->trace,
- from->focus->traceSize * sizeof(WindowPtr));
- to->focus->sourceid = from->id;
- }
- } else if (to->focus)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->focus = to->focus;
- to->focus = NULL;
- }
-
-}
-
-static void
-DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
-{
- ClassesPtr classes;
-
- /* Feedback classes must be copied first */
- if (from->ptrfeed)
- {
- PtrFeedbackPtr *p, it;
- if (!to->ptrfeed)
- {
- classes = to->unused_classes;
- to->ptrfeed = classes->ptrfeed;
- classes->ptrfeed = NULL;
- }
-
- p = &to->ptrfeed;
- for (it = from->ptrfeed; it; it = it->next)
- {
- if (!(*p))
- {
- *p = calloc(1, sizeof(PtrFeedbackClassRec));
- if (!*p)
- {
- ErrorF("[Xi] Cannot alloc memory for class copy.");
- return;
- }
- }
- (*p)->CtrlProc = it->CtrlProc;
- (*p)->ctrl = it->ctrl;
-
- p = &(*p)->next;
- }
- } else if (to->ptrfeed && !from->ptrfeed)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->ptrfeed = to->ptrfeed;
- to->ptrfeed = NULL;
- }
-
- if (from->valuator)
- {
- ValuatorClassPtr v;
- if (!to->valuator)
- {
- classes = to->unused_classes;
- to->valuator = classes->valuator;
- if (to->valuator)
- classes->valuator = NULL;
- }
-
- to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
- from->valuator->numAxes * sizeof(AxisInfo) +
- from->valuator->numAxes * sizeof(double));
- v = to->valuator;
- if (!v)
- FatalError("[Xi] no memory for class shift.\n");
-
- v->numAxes = from->valuator->numAxes;
- v->axes = (AxisInfoPtr)&v[1];
- memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
-
- v->axisVal = (double*)(v->axes + from->valuator->numAxes);
- v->sourceid = from->id;
- } else if (to->valuator && !from->valuator)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->valuator = to->valuator;
- to->valuator = NULL;
- }
-
- if (from->button)
- {
- if (!to->button)
- {
- classes = to->unused_classes;
- to->button = classes->button;
- if (!to->button)
- {
- to->button = calloc(1, sizeof(ButtonClassRec));
- if (!to->button)
- FatalError("[Xi] no memory for class shift.\n");
- } else
- classes->button = NULL;
- }
-
- if (from->button->xkb_acts)
- {
- if (!to->button->xkb_acts)
- {
- to->button->xkb_acts = calloc(1, sizeof(XkbAction));
- if (!to->button->xkb_acts)
- FatalError("[Xi] not enough memory for xkb_acts.\n");
- }
- memcpy(to->button->xkb_acts, from->button->xkb_acts,
- sizeof(XkbAction));
- } else
- free(to->button->xkb_acts);
-
- memcpy(to->button->labels, from->button->labels,
- from->button->numButtons * sizeof(Atom));
- to->button->sourceid = from->id;
- } else if (to->button && !from->button)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->button = to->button;
- to->button = NULL;
- }
-
- if (from->proximity)
- {
- if (!to->proximity)
- {
- classes = to->unused_classes;
- to->proximity = classes->proximity;
- if (!to->proximity)
- {
- to->proximity = calloc(1, sizeof(ProximityClassRec));
- if (!to->proximity)
- FatalError("[Xi] no memory for class shift.\n");
- } else
- classes->proximity = NULL;
- }
- memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
- to->proximity->sourceid = from->id;
- } else if (to->proximity)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->proximity = to->proximity;
- to->proximity = NULL;
- }
-
- if (from->absolute)
- {
- if (!to->absolute)
- {
- classes = to->unused_classes;
- to->absolute = classes->absolute;
- if (!to->absolute)
- {
- to->absolute = calloc(1, sizeof(AbsoluteClassRec));
- if (!to->absolute)
- FatalError("[Xi] no memory for class shift.\n");
- } else
- classes->absolute = NULL;
- }
- memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
- to->absolute->sourceid = from->id;
- } else if (to->absolute)
- {
- ClassesPtr classes;
- classes = to->unused_classes;
- classes->absolute = to->absolute;
- to->absolute = NULL;
- }
-}
-
-/**
- * Copies the CONTENT of the classes of device from into the classes in device
- * to. From and to are identical after finishing.
- *
- * If to does not have classes from currenly has, the classes are stored in
- * to's devPrivates system. Later, we recover it again from there if needed.
- * Saves a few memory allocations.
- */
-void
-DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
-{
- /* generic feedback classes, not tied to pointer and/or keyboard */
- DeepCopyFeedbackClasses(from, to);
-
- if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
- DeepCopyKeyboardClasses(from, to);
- if ((dce->flags & DEVCHANGE_POINTER_EVENT))
- DeepCopyPointerClasses(from, to);
-}
-
-
-/**
- * Send an XI2 DeviceChangedEvent to all interested clients.
- */
-void
-XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
-{
- xXIDeviceChangedEvent *dcce;
- int rc;
-
- rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
- if (rc != Success)
- {
- ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
- return;
- }
-
- /* we don't actually swap if there's a NullClient, swapping is done
- * later when event is delivered. */
- SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
- free(dcce);
-}
-
-static void
-ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
-{
- DeviceIntPtr slave;
- int rc;
-
- /* For now, we don't have devices that change physically. */
- if (!IsMaster(device))
- return;
-
- rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
-
- if (rc != Success)
- return; /* Device has disappeared */
-
- if (!slave->u.master)
- return; /* set floating since the event */
-
- if (slave->u.master->id != dce->masterid)
- return; /* not our slave anymore, don't care */
-
- /* FIXME: we probably need to send a DCE for the new slave now */
-
- device->public.devicePrivate = slave->public.devicePrivate;
-
- /* FIXME: the classes may have changed since we generated the event. */
- DeepCopyDeviceClasses(slave, device, dce);
- XISendDeviceChangedEvent(slave, device, dce);
-}
-
-/**
- * Update the device state according to the data in the event.
- *
- * return values are
- * DEFAULT ... process as normal
- * DONT_PROCESS ... return immediately from caller
- */
-#define DEFAULT 0
-#define DONT_PROCESS 1
-int
-UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
-{
- int i;
- int key = 0,
- bit = 0,
- last_valuator;
-
- KeyClassPtr k = NULL;
- ButtonClassPtr b = NULL;
- ValuatorClassPtr v = NULL;
-
- /* This event is always the first we get, before the actual events with
- * the data. However, the way how the DDX is set up, "device" will
- * actually be the slave device that caused the event.
- */
- switch(event->type)
- {
- case ET_DeviceChanged:
- ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
- return DONT_PROCESS; /* event has been sent already */
- case ET_Motion:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- break;
- default:
- /* other events don't update the device */
- return DEFAULT;
- }
-
- k = device->key;
- v = device->valuator;
- b = device->button;
-
- key = event->detail.key;
- bit = 1 << (key & 7);
-
- /* Update device axis */
- /* Check valuators first */
- last_valuator = -1;
- for (i = 0; i < MAX_VALUATORS; i++)
- {
- if (BitIsOn(&event->valuators.mask, i))
- {
- if (!v)
- {
- ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
- "Ignoring event.\n", device->name);
- return DONT_PROCESS;
- } else if (v->numAxes < i)
- {
- ErrorF("[Xi] Too many valuators reported for device '%s'. "
- "Ignoring event.\n", device->name);
- return DONT_PROCESS;
- }
- last_valuator = i;
- }
- }
-
- for (i = 0; i <= last_valuator && i < v->numAxes; i++)
- {
- if (BitIsOn(&event->valuators.mask, i))
- {
- /* XXX: Relative/Absolute mode */
- v->axisVal[i] = event->valuators.data[i];
- v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
- }
- }
-
- if (event->type == ET_KeyPress) {
- if (!k)
- return DONT_PROCESS;
-
- /* don't allow ddx to generate multiple downs, but repeats are okay */
- if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
- return DONT_PROCESS;
-
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- set_key_down(device, key, KEY_PROCESSED);
- } else if (event->type == ET_KeyRelease) {
- if (!k)
- return DONT_PROCESS;
-
- if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */
- return DONT_PROCESS;
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- set_key_up(device, key, KEY_PROCESSED);
- } else if (event->type == ET_ButtonPress) {
- Mask mask;
- if (!b)
- return DONT_PROCESS;
-
- if (button_is_down(device, key, BUTTON_PROCESSED))
- return DONT_PROCESS;
-
- set_button_down(device, key, BUTTON_PROCESSED);
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- if (!b->map[key])
- return DONT_PROCESS;
- b->buttonsDown++;
- b->motionMask = DeviceButtonMotionMask;
- if (b->map[key] <= 5)
- b->state |= (Button1Mask >> 1) << b->map[key];
-
- /* Add state and motionMask to the filter for this event */
- mask = DevicePointerMotionMask | b->state | b->motionMask;
- SetMaskForEvent(device->id, mask, DeviceMotionNotify);
- mask = PointerMotionMask | b->state | b->motionMask;
- SetMaskForEvent(device->id, mask, MotionNotify);
- } else if (event->type == ET_ButtonRelease) {
- Mask mask;
- if (!b)
- return DONT_PROCESS;
-
- if (!button_is_down(device, key, BUTTON_PROCESSED))
- return DONT_PROCESS;
- if (IsMaster(device)) {
- DeviceIntPtr sd;
-
- /*
- * Leave the button down if any slave has the
- * button still down. Note that this depends on the
- * event being delivered through the slave first
- */
- for (sd = inputInfo.devices; sd; sd = sd->next) {
- if (IsMaster(sd) || sd->u.master != device)
- continue;
- if (!sd->button)
- continue;
- for (i = 1; i <= sd->button->numButtons; i++)
- if (sd->button->map[i] == key &&
- button_is_down(sd, i, BUTTON_PROCESSED))
- return DONT_PROCESS;
- }
- }
- set_button_up(device, key, BUTTON_PROCESSED);
- if (device->valuator)
- device->valuator->motionHintWindow = NullWindow;
- if (!b->map[key])
- return DONT_PROCESS;
- if (b->buttonsDown >= 1 && !--b->buttonsDown)
- b->motionMask = 0;
- if (b->map[key] <= 5)
- b->state &= ~((Button1Mask >> 1) << b->map[key]);
-
- /* Add state and motionMask to the filter for this event */
- mask = DevicePointerMotionMask | b->state | b->motionMask;
- SetMaskForEvent(device->id, mask, DeviceMotionNotify);
- mask = PointerMotionMask | b->state | b->motionMask;
- SetMaskForEvent(device->id, mask, MotionNotify);
- } else if (event->type == ET_ProximityIn)
- device->proximity->in_proximity = TRUE;
- else if (event->type == ET_ProximityOut)
- device->proximity->in_proximity = FALSE;
-
- return DEFAULT;
-}
-
-static void
-ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
-{
- GrabPtr grab = device->deviceGrab.grab;
-
- if (grab)
- DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
- else { /* deliver to all root windows */
- xEvent *xi;
- int i;
-
- i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
- if (i != Success)
- {
- ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
- device->name, i);
- return;
- }
-
- for (i = 0; i < screenInfo.numScreens; i++)
- DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
- GetEventFilter(device, xi), NULL);
- free(xi);
- }
-}
-
-/**
- * Main device event processing function.
- * Called from when processing the events from the event queue.
- *
- */
-void
-ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
-{
- GrabPtr grab;
- Bool deactivateDeviceGrab = FALSE;
- int key = 0, rootX, rootY;
- ButtonClassPtr b;
- KeyClassPtr k;
- ValuatorClassPtr v;
- int ret = 0;
- int state, i;
- DeviceIntPtr mouse = NULL, kbd = NULL;
- DeviceEvent *event = &ev->device_event;
-
- CHECKEVENT(ev);
-
- if (ev->any.type == ET_RawKeyPress ||
- ev->any.type == ET_RawKeyRelease ||
- ev->any.type == ET_RawButtonPress ||
- ev->any.type == ET_RawButtonRelease ||
- ev->any.type == ET_RawMotion)
- {
- ProcessRawEvent(&ev->raw_event, device);
- return;
- }
-
- if (IsPointerDevice(device))
- {
- kbd = GetPairedDevice(device);
- mouse = device;
- if (!kbd->key) /* can happen with floating SDs */
- kbd = NULL;
- } else
- {
- mouse = GetPairedDevice(device);
- kbd = device;
- if (!mouse->valuator || !mouse->button) /* may be float. SDs */
- mouse = NULL;
- }
-
- /* State needs to be assembled BEFORE the device is updated. */
- state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
- state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
-
- for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
- if (BitIsOn(mouse->button->down, i))
- SetBit(event->buttons, i);
-
- if (kbd && kbd->key)
- {
- XkbStatePtr state;
- /* we need the state before the event happens */
- if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
- state = &kbd->key->xkbInfo->prev_state;
- else
- state = &kbd->key->xkbInfo->state;
-
- event->mods.base = state->base_mods;
- event->mods.latched = state->latched_mods;
- event->mods.locked = state->locked_mods;
- event->mods.effective = state->mods;
-
- event->group.base = state->base_group;
- event->group.latched = state->latched_group;
- event->group.locked = state->locked_group;
- event->group.effective = state->group;
- }
-
- ret = UpdateDeviceState(device, event);
- if (ret == DONT_PROCESS)
- return;
-
- v = device->valuator;
- b = device->button;
- k = device->key;
-
- if (IsMaster(device) || !device->u.master)
- CheckMotion(event, device);
-
- switch (event->type)
- {
- case ET_Motion:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- GetSpritePosition(device, &rootX, &rootY);
- event->root_x = rootX;
- event->root_y = rootY;
- NoticeEventTime((InternalEvent*)event);
- event->corestate = state;
- key = event->detail.key;
- break;
- default:
- break;
- }
-
- if (DeviceEventCallback && !syncEvents.playingEvents) {
- DeviceEventInfoRec eventinfo;
- SpritePtr pSprite = device->spriteInfo->sprite;
-
- /* see comment in EnqueueEvents regarding the next three lines */
- if (ev->any.type == ET_Motion)
- ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
-
- eventinfo.device = device;
- eventinfo.event = ev;
- CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
- }
-
- grab = device->deviceGrab.grab;
-
- switch(event->type)
- {
- case ET_KeyPress:
- if (!grab && CheckDeviceGrabs(device, event, 0)) {
- device->deviceGrab.activatingKey = key;
- return;
- }
- break;
- case ET_KeyRelease:
- if (grab && device->deviceGrab.fromPassiveGrab &&
- (key == device->deviceGrab.activatingKey) &&
- (device->deviceGrab.grab->type == KeyPress ||
- device->deviceGrab.grab->type == DeviceKeyPress ||
- device->deviceGrab.grab->type == XI_KeyPress))
- deactivateDeviceGrab = TRUE;
- break;
- case ET_ButtonPress:
- event->detail.button = b->map[key];
- if (!event->detail.button) { /* there's no button 0 */
- event->detail.button = key;
- return;
- }
- if (!grab && CheckDeviceGrabs(device, event, 0))
- {
- /* if a passive grab was activated, the event has been sent
- * already */
- return;
- }
- break;
- case ET_ButtonRelease:
- event->detail.button = b->map[key];
- if (!event->detail.button) { /* there's no button 0 */
- event->detail.button = key;
- return;
- }
- if (grab && !b->buttonsDown &&
- device->deviceGrab.fromPassiveGrab &&
- (device->deviceGrab.grab->type == ButtonPress ||
- device->deviceGrab.grab->type == DeviceButtonPress ||
- device->deviceGrab.grab->type == XI_ButtonPress))
- deactivateDeviceGrab = TRUE;
- default:
- break;
- }
-
-
- if (grab)
- DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
- else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
- DeliverFocusedEvent(device, (InternalEvent*)event,
- GetSpriteWindow(device));
- else
- DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
- NullGrab, NullWindow, device);
-
- if (deactivateDeviceGrab == TRUE)
- (*device->deviceGrab.DeactivateGrab) (device);
- event->detail.key = key;
-}
-
-int
-InitProximityClassDeviceStruct(DeviceIntPtr dev)
-{
- ProximityClassPtr proxc;
-
- proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
- if (!proxc)
- return FALSE;
- proxc->sourceid = dev->id;
- proxc->in_proximity = TRUE;
- dev->proximity = proxc;
- return TRUE;
-}
-
-/**
- * Initialise the device's valuators. The memory must already be allocated,
- * this function merely inits the matching axis (specified through axnum) to
- * sane values.
- *
- * It is a condition that (minval < maxval).
- *
- * @see InitValuatorClassDeviceStruct
- */
-void
-InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
- int resolution, int min_res, int max_res, int mode)
-{
- AxisInfoPtr ax;
-
- if (!dev || !dev->valuator || minval > maxval)
- return;
- if (axnum >= dev->valuator->numAxes)
- return;
-
- ax = dev->valuator->axes + axnum;
-
- ax->min_value = minval;
- ax->max_value = maxval;
- ax->resolution = resolution;
- ax->min_resolution = min_res;
- ax->max_resolution = max_res;
- ax->label = label;
- ax->mode = mode;
-
- if (mode & OutOfProximity)
- dev->proximity->in_proximity = FALSE;
-}
-
-static void
-FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
- ButtonClassPtr b, ValuatorClassPtr v, int first)
-{
- ev->type = DeviceStateNotify;
- ev->deviceid = dev->id;
- ev->time = currentTime.milliseconds;
- ev->classes_reported = 0;
- ev->num_keys = 0;
- ev->num_buttons = 0;
- ev->num_valuators = 0;
-
- if (b) {
- ev->classes_reported |= (1 << ButtonClass);
- ev->num_buttons = b->numButtons;
- memcpy((char*)ev->buttons, (char*)b->down, 4);
- } else if (k) {
- ev->classes_reported |= (1 << KeyClass);
- ev->num_keys = k->xkbInfo->desc->max_key_code -
- k->xkbInfo->desc->min_key_code;
- memmove((char *)&ev->keys[0], (char *)k->down, 4);
- }
- if (v) {
- int nval = v->numAxes - first;
-
- ev->classes_reported |= (1 << ValuatorClass);
- ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
- ev->num_valuators = nval < 3 ? nval : 3;
- switch (ev->num_valuators) {
- case 3:
- ev->valuator2 = v->axisVal[first + 2];
- case 2:
- ev->valuator1 = v->axisVal[first + 1];
- case 1:
- ev->valuator0 = v->axisVal[first];
- break;
- }
- }
-}
-
-static void
-FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
- int first)
-{
- int nval = v->numAxes - first;
-
- ev->type = DeviceValuator;
- ev->deviceid = dev->id;
- ev->num_valuators = nval < 3 ? nval : 3;
- ev->first_valuator = first;
- switch (ev->num_valuators) {
- case 3:
- ev->valuator2 = v->axisVal[first + 2];
- case 2:
- ev->valuator1 = v->axisVal[first + 1];
- case 1:
- ev->valuator0 = v->axisVal[first];
- break;
- }
- first += ev->num_valuators;
-}
-
-void
-DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
- WindowPtr pWin)
-{
- deviceFocus event;
- xXIFocusInEvent *xi2event;
- DeviceIntPtr mouse;
- int btlen, len, i;
-
- mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
-
- /* XI 2 event */
- btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
- btlen = bytes_to_int32(btlen);
- len = sizeof(xXIFocusInEvent) + btlen * 4;
-
- xi2event = calloc(1, len);
- xi2event->type = GenericEvent;
- xi2event->extension = IReqCode;
- xi2event->evtype = type;
- xi2event->length = bytes_to_int32(len - sizeof(xEvent));
- xi2event->buttons_len = btlen;
- xi2event->detail = detail;
- xi2event->time = currentTime.milliseconds;
- xi2event->deviceid = dev->id;
- xi2event->sourceid = dev->id; /* a device doesn't change focus by itself */
- xi2event->mode = mode;
- xi2event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
- xi2event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
-
- for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
- if (BitIsOn(mouse->button->down, i))
- SetBit(&xi2event[1], i);
-
- if (dev->key)
- {
- xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
- xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
- xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
- xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
-
- xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
- xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
- xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
- xi2event->group.effective_group = dev->key->xkbInfo->state.group;
- }
-
- FixUpEventFromWindow(dev, (xEvent*)xi2event, pWin, None, FALSE);
-
- DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
- GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
-
- free(xi2event);
-
- /* XI 1.x event */
- event.deviceid = dev->id;
- event.mode = mode;
- event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
- event.detail = detail;
- event.window = pWin->drawable.id;
- event.time = currentTime.milliseconds;
-
- DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
- DeviceFocusChangeMask, NullGrab);
-
- if ((type == DeviceFocusIn) &&
- (wOtherInputMasks(pWin)) &&
- (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
- {
- int evcount = 1;
- deviceStateNotify *ev, *sev;
- deviceKeyStateNotify *kev;
- deviceButtonStateNotify *bev;
-
- KeyClassPtr k;
- ButtonClassPtr b;
- ValuatorClassPtr v;
- int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
-
- if ((b = dev->button) != NULL) {
- nbuttons = b->numButtons;
- if (nbuttons > 32)
- evcount++;
- }
- if ((k = dev->key) != NULL) {
- nkeys = k->xkbInfo->desc->max_key_code -
- k->xkbInfo->desc->min_key_code;
- if (nkeys > 32)
- evcount++;
- if (nbuttons > 0) {
- evcount++;
- }
- }
- if ((v = dev->valuator) != NULL) {
- nval = v->numAxes;
-
- if (nval > 3)
- evcount++;
- if (nval > 6) {
- if (!(k && b))
- evcount++;
- if (nval > 9)
- evcount += ((nval - 7) / 3);
- }
- }
-
- sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
- FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
-
- if (b != NULL) {
- FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
- first += 3;
- nval -= 3;
- if (nbuttons > 32) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- bev = (deviceButtonStateNotify *) ev++;
- bev->type = DeviceButtonStateNotify;
- bev->deviceid = dev->id;
- memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
- }
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
- }
-
- if (k != NULL) {
- FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
- first += 3;
- nval -= 3;
- if (nkeys > 32) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- kev = (deviceKeyStateNotify *) ev++;
- kev->type = DeviceKeyStateNotify;
- kev->deviceid = dev->id;
- memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
- }
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
- }
-
- while (nval > 0) {
- FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
- first += 3;
- nval -= 3;
- if (nval > 0) {
- (ev - 1)->deviceid |= MORE_EVENTS;
- FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
- first += 3;
- nval -= 3;
- }
- }
-
- DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
- DeviceStateNotifyMask, NullGrab);
- free(sev);
- }
-}
-
-int
-CheckGrabValues(ClientPtr client, GrabParameters* param)
-{
- if (param->grabtype != GRABTYPE_CORE &&
- param->grabtype != GRABTYPE_XI &&
- param->grabtype != GRABTYPE_XI2)
- {
- ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
- return BadImplementation;
- }
-
- if ((param->this_device_mode != GrabModeSync) &&
- (param->this_device_mode != GrabModeAsync)) {
- client->errorValue = param->this_device_mode;
- return BadValue;
- }
- if ((param->other_devices_mode != GrabModeSync) &&
- (param->other_devices_mode != GrabModeAsync)) {
- client->errorValue = param->other_devices_mode;
- return BadValue;
- }
-
- if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
- (param->modifiers & ~AllModifiersMask)) {
- client->errorValue = param->modifiers;
- return BadValue;
- }
-
- if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
- client->errorValue = param->ownerEvents;
- return BadValue;
- }
- return Success;
-}
-
-int
-GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
- int button, GrabParameters *param, GrabType grabtype,
- GrabMask *mask)
-{
- WindowPtr pWin, confineTo;
- CursorPtr cursor;
- GrabPtr grab;
- int rc, type = -1;
- Mask access_mode = DixGrabAccess;
-
- rc = CheckGrabValues(client, param);
- if (rc != Success)
- return rc;
- if (param->confineTo == None)
- confineTo = NullWindow;
- else {
- rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- }
- if (param->cursor == None)
- cursor = NullCursor;
- else {
- rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
- RT_CURSOR, client, DixUseAccess);
- if (rc != Success)
- {
- client->errorValue = param->cursor;
- return rc;
- }
- access_mode |= DixForceAccess;
- }
- if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
- if (rc != Success)
- return rc;
- rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
-
- if (grabtype == GRABTYPE_XI)
- type = DeviceButtonPress;
- else if (grabtype == GRABTYPE_XI2)
- type = XI_ButtonPress;
-
- grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
- mask, param, type, button, confineTo, cursor);
- if (!grab)
- return BadAlloc;
- return AddPassiveGrabToList(client, grab);
-}
-
-/**
- * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
- * grabtype is GRABTYPE_XI2, the key is a keysym.
- */
-int
-GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
- int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
-{
- WindowPtr pWin;
- GrabPtr grab;
- KeyClassPtr k = dev->key;
- Mask access_mode = DixGrabAccess;
- int rc, type = -1;
-
- rc = CheckGrabValues(client, param);
- if (rc != Success)
- return rc;
- if (k == NULL)
- return BadMatch;
- if (grabtype == GRABTYPE_XI)
- {
- if ((key > k->xkbInfo->desc->max_key_code ||
- key < k->xkbInfo->desc->min_key_code)
- && (key != AnyKey)) {
- client->errorValue = key;
- return BadValue;
- }
- type = DeviceKeyPress;
- } else if (grabtype == GRABTYPE_XI2)
- type = XI_KeyPress;
-
- rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
- if (rc != Success)
- return rc;
-
- grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
- mask, param, type, key, NULL, NULL);
- if (!grab)
- return BadAlloc;
- return AddPassiveGrabToList(client, grab);
-}
-
-/* Enter/FocusIn grab */
-int
-GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
- GrabParameters *param, GrabMask *mask)
-{
- WindowPtr pWin;
- CursorPtr cursor;
- GrabPtr grab;
- Mask access_mode = DixGrabAccess;
- int rc;
-
- rc = CheckGrabValues(client, param);
- if (rc != Success)
- return rc;
-
- rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- if (param->cursor == None)
- cursor = NullCursor;
- else {
- rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
- RT_CURSOR, client, DixUseAccess);
- if (rc != Success)
- {
- client->errorValue = param->cursor;
- return rc;
- }
- access_mode |= DixForceAccess;
- }
- if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
- if (rc != Success)
- return rc;
-
- grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
- mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
- 0, NULL, cursor);
-
- if (!grab)
- return BadAlloc;
-
- return AddPassiveGrabToList(client, grab);
-}
-
-int
-SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
- Mask mask, Mask exclusivemasks)
-{
- int mskidx = dev->id;
- int i, ret;
- Mask check;
- InputClientsPtr others;
-
- check = (mask & exclusivemasks);
- if (wOtherInputMasks(pWin)) {
- if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different
- * clients to select on any of the
- * events for maskcheck. However,
- * it is OK, for some client to
- * continue selecting on one of those
- * events. */
- for (others = wOtherInputMasks(pWin)->inputClients; others;
- others = others->next) {
- if (!SameClient(others, client) && (check &
- others->mask[mskidx]))
- return BadAccess;
- }
- }
- for (others = wOtherInputMasks(pWin)->inputClients; others;
- others = others->next) {
- if (SameClient(others, client)) {
- check = others->mask[mskidx];
- others->mask[mskidx] = mask;
- if (mask == 0) {
- for (i = 0; i < EMASKSIZE; i++)
- if (i != mskidx && others->mask[i] != 0)
- break;
- if (i == EMASKSIZE) {
- RecalculateDeviceDeliverableEvents(pWin);
- if (ShouldFreeInputMasks(pWin, FALSE))
- FreeResource(others->resource, RT_NONE);
- return Success;
- }
- }
- goto maskSet;
- }
- }
- }
- check = 0;
- if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
- return ret;
- maskSet:
- if (dev->valuator)
- if ((dev->valuator->motionHintWindow == pWin) &&
- (mask & DevicePointerMotionHintMask) &&
- !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
- dev->valuator->motionHintWindow = NullWindow;
- RecalculateDeviceDeliverableEvents(pWin);
- return Success;
-}
-
-int
-AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
-{
- InputClientsPtr others;
-
- if (!pWin->optional && !MakeWindowOptional(pWin))
- return BadAlloc;
- others = calloc(1, sizeof(InputClients));
- if (!others)
- return BadAlloc;
- if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
- return BadAlloc;
- others->mask[mskidx] = mask;
- others->resource = FakeClientID(client->index);
- others->next = pWin->optional->inputMasks->inputClients;
- pWin->optional->inputMasks->inputClients = others;
- if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
- return BadAlloc;
- return Success;
-}
-
-static Bool
-MakeInputMasks(WindowPtr pWin)
-{
- struct _OtherInputMasks *imasks;
-
- imasks = calloc(1, sizeof(struct _OtherInputMasks));
- if (!imasks)
- return FALSE;
- pWin->optional->inputMasks = imasks;
- return TRUE;
-}
-
-void
-RecalculateDeviceDeliverableEvents(WindowPtr pWin)
-{
- InputClientsPtr others;
- struct _OtherInputMasks *inputMasks; /* default: NULL */
- WindowPtr pChild, tmp;
- int i, j;
-
- pChild = pWin;
- while (1) {
- if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
- for (i = 0; i < EMASKSIZE; i++)
- memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
- for (others = inputMasks->inputClients; others;
- others = others->next) {
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->inputEvents[i] |= others->mask[i];
- for (i = 0; i < EMASKSIZE; i++)
- for (j = 0; j < XI2MASKSIZE; j++)
- inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
- }
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
- for (tmp = pChild->parent; tmp; tmp = tmp->parent)
- if (wOtherInputMasks(tmp))
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->deliverableEvents[i] |=
- (wOtherInputMasks(tmp)->deliverableEvents[i]
- & ~inputMasks->
- dontPropagateMask[i] & PropagateMask[i]);
- }
- if (pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
- while (!pChild->nextSib && (pChild != pWin))
- pChild = pChild->parent;
- if (pChild == pWin)
- break;
- pChild = pChild->nextSib;
- }
-}
-
-int
-InputClientGone(WindowPtr pWin, XID id)
-{
- InputClientsPtr other, prev;
-
- if (!wOtherInputMasks(pWin))
- return Success;
- prev = 0;
- for (other = wOtherInputMasks(pWin)->inputClients; other;
- other = other->next) {
- if (other->resource == id) {
- if (prev) {
- prev->next = other->next;
- free(other);
- } else if (!(other->next)) {
- if (ShouldFreeInputMasks(pWin, TRUE)) {
- wOtherInputMasks(pWin)->inputClients = other->next;
- free(wOtherInputMasks(pWin));
- pWin->optional->inputMasks = (OtherInputMasks *) NULL;
- CheckWindowOptionalNeed(pWin);
- free(other);
- } else {
- other->resource = FakeClientID(0);
- if (!AddResource(other->resource, RT_INPUTCLIENT,
- (pointer) pWin))
- return BadAlloc;
- }
- } else {
- wOtherInputMasks(pWin)->inputClients = other->next;
- free(other);
- }
- RecalculateDeviceDeliverableEvents(pWin);
- return Success;
- }
- prev = other;
- }
- FatalError("client not on device event list");
-}
-
-int
-SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
- xEvent * ev, Mask mask, int count)
-{
- WindowPtr pWin;
- WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
- WindowPtr spriteWin = GetSpriteWindow(d);
-
- if (dest == PointerWindow)
- pWin = spriteWin;
- else if (dest == InputFocus) {
- WindowPtr inputFocus;
-
- if (!d->focus)
- inputFocus = spriteWin;
- else
- inputFocus = d->focus->win;
-
- if (inputFocus == FollowKeyboardWin)
- inputFocus = inputInfo.keyboard->focus->win;
-
- if (inputFocus == NoneWin)
- return Success;
-
- /* If the input focus is PointerRootWin, send the event to where
- * the pointer is if possible, then perhaps propogate up to root. */
- if (inputFocus == PointerRootWin)
- inputFocus = GetCurrentRootWindow(d);
-
- if (IsParent(inputFocus, spriteWin)) {
- effectiveFocus = inputFocus;
- pWin = spriteWin;
- } else
- effectiveFocus = pWin = inputFocus;
- } else
- dixLookupWindow(&pWin, dest, client, DixSendAccess);
- if (!pWin)
- return BadWindow;
- if ((propagate != xFalse) && (propagate != xTrue)) {
- client->errorValue = propagate;
- return BadValue;
- }
- ev->u.u.type |= 0x80;
- if (propagate) {
- for (; pWin; pWin = pWin->parent) {
- if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
- return Success;
- if (pWin == effectiveFocus)
- return Success;
- if (wOtherInputMasks(pWin))
- mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
- if (!mask)
- break;
- }
- } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
- DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
- return Success;
-}
-
-int
-SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
-{
- int i;
- ButtonClassPtr b = dev->button;
-
- if (b == NULL)
- return BadMatch;
-
- if (nElts != b->numButtons) {
- client->errorValue = nElts;
- return BadValue;
- }
- if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
- return BadValue;
- for (i = 0; i < nElts; i++)
- if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
- return MappingBusy;
- for (i = 0; i < nElts; i++)
- b->map[i + 1] = map[i];
- return Success;
-}
-
-int
-ChangeKeyMapping(ClientPtr client,
- DeviceIntPtr dev,
- unsigned len,
- int type,
- KeyCode firstKeyCode,
- CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
-{
- KeySymsRec keysyms;
- KeyClassPtr k = dev->key;
-
- if (k == NULL)
- return BadMatch;
-
- if (len != (keyCodes * keySymsPerKeyCode))
- return BadLength;
-
- if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
- (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
- client->errorValue = firstKeyCode;
- return BadValue;
- }
- if (keySymsPerKeyCode == 0) {
- client->errorValue = 0;
- return BadValue;
- }
- keysyms.minKeyCode = firstKeyCode;
- keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
- keysyms.mapWidth = keySymsPerKeyCode;
- keysyms.map = map;
-
- XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
- serverClient);
-
- return Success;
-}
-
-static void
-DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
-{
- WindowPtr parent;
-
- /* Deactivate any grabs performed on this window, before making
- * any input focus changes.
- * Deactivating a device grab should cause focus events. */
-
- if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
- (*dev->deviceGrab.DeactivateGrab) (dev);
-
- /* If the focus window is a root window (ie. has no parent)
- * then don't delete the focus from it. */
-
- if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
- int focusEventMode = NotifyNormal;
-
- /* If a grab is in progress, then alter the mode of focus events. */
-
- if (dev->deviceGrab.grab)
- focusEventMode = NotifyWhileGrabbed;
-
- switch (dev->focus->revert) {
- case RevertToNone:
- if (!ActivateFocusInGrab(dev, pWin, NoneWin))
- DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
- dev->focus->win = NoneWin;
- dev->focus->traceGood = 0;
- break;
- case RevertToParent:
- parent = pWin;
- do {
- parent = parent->parent;
- dev->focus->traceGood--;
- }
- while (!parent->realized);
- if (!ActivateFocusInGrab(dev, pWin, parent))
- DoFocusEvents(dev, pWin, parent, focusEventMode);
- dev->focus->win = parent;
- dev->focus->revert = RevertToNone;
- break;
- case RevertToPointerRoot:
- if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
- DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
- dev->focus->win = PointerRootWin;
- dev->focus->traceGood = 0;
- break;
- case RevertToFollowKeyboard:
- {
- DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
- if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
- kbd = inputInfo.keyboard;
- if (kbd->focus->win) {
- if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
- DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
- dev->focus->win = FollowKeyboardWin;
- dev->focus->traceGood = 0;
- } else {
- if (!ActivateFocusInGrab(dev, pWin, NoneWin))
- DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
- dev->focus->win = NoneWin;
- dev->focus->traceGood = 0;
- }
- }
- break;
- }
- }
-
- if (dev->valuator)
- if (dev->valuator->motionHintWindow == pWin)
- dev->valuator->motionHintWindow = NullWindow;
-}
-
-void
-DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
-{
- int i;
- DeviceIntPtr dev;
- InputClientsPtr ic;
- struct _OtherInputMasks *inputMasks;
-
- for (dev = inputInfo.devices; dev; dev = dev->next) {
- DeleteDeviceFromAnyExtEvents(pWin, dev);
- }
-
- for (dev = inputInfo.off_devices; dev; dev = dev->next)
- DeleteDeviceFromAnyExtEvents(pWin, dev);
-
- if (freeResources)
- while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
- ic = inputMasks->inputClients;
- for (i = 0; i < EMASKSIZE; i++)
- inputMasks->dontPropagateMask[i] = 0;
- FreeResource(ic->resource, RT_NONE);
- }
-}
-
-int
-MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
-{
- DeviceIntPtr dev;
-
- dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
- DixReadAccess);
- if (!dev)
- return 0;
-
- if (pEvents->type == DeviceMotionNotify) {
- if (mask & DevicePointerMotionHintMask) {
- if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
- return 1; /* don't send, but pretend we did */
- }
- pEvents->detail = NotifyHint;
- } else {
- pEvents->detail = NotifyNormal;
- }
- }
- return 0;
-}
-
-void
-CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
- deviceKeyButtonPointer * xE, GrabPtr grab,
- ClientPtr client, Mask deliveryMask)
-{
- DeviceIntPtr dev;
-
- dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
- DixGrabAccess);
- if (!dev)
- return;
-
- if (type == DeviceMotionNotify)
- dev->valuator->motionHintWindow = pWin;
- else if ((type == DeviceButtonPress) && (!grab) &&
- (deliveryMask & DeviceButtonGrabMask)) {
- GrabRec tempGrab;
-
- tempGrab.device = dev;
- tempGrab.resource = client->clientAsMask;
- tempGrab.window = pWin;
- tempGrab.ownerEvents =
- (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
- tempGrab.eventMask = deliveryMask;
- tempGrab.keyboardMode = GrabModeAsync;
- tempGrab.pointerMode = GrabModeAsync;
- tempGrab.confineTo = NullWindow;
- tempGrab.cursor = NullCursor;
- tempGrab.next = NULL;
- (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
- }
-}
-
-static Mask
-DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
-{
- InputClientsPtr other;
-
- if (!wOtherInputMasks(pWin))
- return 0;
- for (other = wOtherInputMasks(pWin)->inputClients; other;
- other = other->next) {
- if (SameClient(other, client))
- return other->mask[dev->id];
- }
- return 0;
-}
-
-void
-MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
-{
- WindowPtr pWin;
- GrabPtr grab = dev->deviceGrab.grab;
-
- pWin = dev->valuator->motionHintWindow;
-
- if ((grab && SameClient(grab, client) &&
- ((grab->eventMask & DevicePointerMotionHintMask) ||
- (grab->ownerEvents &&
- (DeviceEventMaskForClient(dev, pWin, client) &
- DevicePointerMotionHintMask)))) ||
- (!grab &&
- (DeviceEventMaskForClient(dev, pWin, client) &
- DevicePointerMotionHintMask)))
- dev->valuator->motionHintWindow = NullWindow;
-}
-
-int
-DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
- int maskndx)
-{
- struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
-
- if (mask & ~PropagateMask[maskndx]) {
- client->errorValue = mask;
- return BadValue;
- }
-
- if (mask == 0) {
- if (inputMasks)
- inputMasks->dontPropagateMask[maskndx] = mask;
- } else {
- if (!inputMasks)
- AddExtensionClient(pWin, client, 0, 0);
- inputMasks = wOtherInputMasks(pWin);
- inputMasks->dontPropagateMask[maskndx] = mask;
- }
- RecalculateDeviceDeliverableEvents(pWin);
- if (ShouldFreeInputMasks(pWin, FALSE))
- FreeResource(inputMasks->inputClients->resource, RT_NONE);
- return Success;
-}
-
-Bool
-ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
-{
- int i;
- Mask allInputEventMasks = 0;
- struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
-
- for (i = 0; i < EMASKSIZE; i++)
- allInputEventMasks |= inputMasks->dontPropagateMask[i];
- if (!ignoreSelectedEvents)
- for (i = 0; i < EMASKSIZE; i++)
- allInputEventMasks |= inputMasks->inputEvents[i];
- if (allInputEventMasks == 0)
- return TRUE;
- else
- return FALSE;
-}
-
-/***********************************************************************
- *
- * Walk through the window tree, finding all clients that want to know
- * about the Event.
- *
- */
-
-static void
-FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
- xEvent * ev, int count)
-{
- WindowPtr p2;
-
- while (p1) {
- p2 = p1->firstChild;
- DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
- FindInterestedChildren(dev, p2, mask, ev, count);
- p1 = p1->nextSib;
- }
-}
-
-/***********************************************************************
- *
- * Send an event to interested clients in all windows on all screens.
- *
- */
-
-void
-SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
-{
- int i;
- WindowPtr pWin, p1;
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- pWin = screenInfo.screens[i]->root;
- if (!pWin)
- continue;
- DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
- p1 = pWin->firstChild;
- FindInterestedChildren(dev, p1, mask, ev, count);
- }
-}
-
-/**
- * Set the XI2 mask for the given client on the given window.
- * @param dev The device to set the mask for.
- * @param win The window to set the mask on.
- * @param client The client setting the mask.
- * @param len Number of bytes in mask.
- * @param mask Event mask in the form of (1 << eventtype)
- */
-int
-XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
- unsigned int len, unsigned char* mask)
-{
- OtherInputMasks *masks;
- InputClientsPtr others = NULL;
-
- masks = wOtherInputMasks(win);
- if (masks)
- {
- for (others = wOtherInputMasks(win)->inputClients; others;
- others = others->next) {
- if (SameClient(others, client)) {
- memset(others->xi2mask[dev->id], 0,
- sizeof(others->xi2mask[dev->id]));
- break;
- }
- }
- }
-
- len = min(len, sizeof(others->xi2mask[dev->id]));
-
- if (len && !others)
- {
- if (AddExtensionClient(win, client, 0, 0) != Success)
- return BadAlloc;
- others= wOtherInputMasks(win)->inputClients;
- }
-
- if (others)
- memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
-
- if (len)
- memcpy(others->xi2mask[dev->id], mask, len);
-
- RecalculateDeviceDeliverableEvents(win);
-
- return Success;
-}
+/************************************************************
+
+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.
+
+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+
+ 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 Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-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.
+
+********************************************************/
+
+/********************************************************************
+ *
+ * Routines to register and initialize extension input devices.
+ * This also contains ProcessOtherEvent, the routine called from DDX
+ * to route extension events.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "inputstr.h"
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI2proto.h>
+#include <X11/extensions/geproto.h>
+#include "windowstr.h"
+#include "miscstruct.h"
+#include "region.h"
+#include "exevents.h"
+#include "extnsionst.h"
+#include "exglobals.h"
+#include "dixevents.h" /* DeliverFocusedEvent */
+#include "dixgrabs.h" /* CreateGrab() */
+#include "scrnintstr.h"
+#include "listdev.h" /* for CopySwapXXXClass */
+#include "xace.h"
+#include "xiquerydevice.h" /* For List*Info */
+#include "eventconvert.h"
+#include "eventstr.h"
+
+#include <X11/extensions/XKBproto.h>
+#include "xkbsrv.h"
+
+#define WID(w) ((w) ? ((w)->drawable.id) : 0)
+#define AllModifiersMask ( \
+ ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
+ Mod3Mask | Mod4Mask | Mod5Mask )
+#define AllButtonsMask ( \
+ Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
+
+Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
+ Bool /* ignoreSelectedEvents */
+ );
+static Bool MakeInputMasks(WindowPtr /* pWin */
+ );
+
+/*
+ * Only let the given client know of core events which will affect its
+ * interpretation of input events, if the client's ClientPointer (or the
+ * paired keyboard) is the current device.
+ */
+int
+XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
+{
+ DeviceIntPtr current_ptr = PickPointer(client);
+ DeviceIntPtr current_kbd = GetPairedDevice(current_ptr);
+
+ if (dev == current_kbd || dev == current_ptr)
+ return 1;
+
+ return 0;
+}
+
+Bool
+IsPointerEvent(InternalEvent* event)
+{
+ switch(event->any.type)
+ {
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_Motion:
+ /* XXX: enter/leave ?? */
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/**
+ * @return the device matching the deviceid of the device set in the event, or
+ * NULL if the event is not an XInput event.
+ */
+DeviceIntPtr
+XIGetDevice(xEvent* xE)
+{
+ DeviceIntPtr pDev = NULL;
+
+ if (xE->u.u.type == DeviceButtonPress ||
+ xE->u.u.type == DeviceButtonRelease ||
+ xE->u.u.type == DeviceMotionNotify ||
+ xE->u.u.type == ProximityIn ||
+ xE->u.u.type == ProximityOut ||
+ xE->u.u.type == DevicePropertyNotify)
+ {
+ int rc;
+ int id;
+
+ id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
+
+ rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
+ if (rc != Success)
+ ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
+ }
+ return pDev;
+}
+
+
+/**
+ * Copy the device->key into master->key and send a mapping notify to the
+ * clients if appropriate.
+ * master->key needs to be allocated by the caller.
+ *
+ * Device is the slave device. If it is attached to a master device, we may
+ * need to send a mapping notify to the client because it causes the MD
+ * to change state.
+ *
+ * Mapping notify needs to be sent in the following cases:
+ * - different slave device on same master
+ * - different master
+ *
+ * XXX: They way how the code is we also send a map notify if the slave device
+ * stays the same, but the master changes. This isn't really necessary though.
+ *
+ * XXX: this gives you funny behaviour with the ClientPointer. When a
+ * MappingNotify is sent to the client, the client usually responds with a
+ * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
+ * mapping, regardless of which keyboard sent the last mapping notify request.
+ * So depending on the CP setting, your keyboard may change layout in each
+ * app...
+ *
+ * This code is basically the old SwitchCoreKeyboard.
+ */
+
+void
+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
+{
+ KeyClassPtr mk = master->key;
+
+ if (device == master)
+ return;
+
+ mk->sourceid = device->id;
+
+
+ if (!XkbCopyDeviceKeymap(master, device))
+ FatalError("Couldn't pivot keymap from device to core!\n");
+}
+
+/**
+ * Copies the feedback classes from device "from" into device "to". Classes
+ * are duplicated (not just flipping the pointers). All feedback classes are
+ * linked lists, the full list is duplicated.
+ */
+static void
+DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+ ClassesPtr classes;
+
+
+ if (from->intfeed)
+ {
+ IntegerFeedbackPtr *i, it;
+
+ if (!to->intfeed)
+ {
+ classes = to->unused_classes;
+ to->intfeed = classes->intfeed;
+ classes->intfeed = NULL;
+ }
+
+ i = &to->intfeed;
+ for (it = from->intfeed; it; it = it->next)
+ {
+ if (!(*i))
+ {
+ *i = calloc(1, sizeof(IntegerFeedbackClassRec));
+ if (!(*i))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*i)->CtrlProc = it->CtrlProc;
+ (*i)->ctrl = it->ctrl;
+
+ i = &(*i)->next;
+ }
+ } else if (to->intfeed && !from->intfeed)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->intfeed = to->intfeed;
+ to->intfeed = NULL;
+ }
+
+ if (from->stringfeed)
+ {
+ StringFeedbackPtr *s, it;
+
+ if (!to->stringfeed)
+ {
+ classes = to->unused_classes;
+ to->stringfeed = classes->stringfeed;
+ classes->stringfeed = NULL;
+ }
+
+ s = &to->stringfeed;
+ for (it = from->stringfeed; it; it = it->next)
+ {
+ if (!(*s))
+ {
+ *s = calloc(1, sizeof(StringFeedbackClassRec));
+ if (!(*s))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*s)->CtrlProc = it->CtrlProc;
+ (*s)->ctrl = it->ctrl;
+
+ s = &(*s)->next;
+ }
+ } else if (to->stringfeed && !from->stringfeed)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->stringfeed = to->stringfeed;
+ to->stringfeed = NULL;
+ }
+
+ if (from->bell)
+ {
+ BellFeedbackPtr *b, it;
+
+ if (!to->bell)
+ {
+ classes = to->unused_classes;
+ to->bell = classes->bell;
+ classes->bell = NULL;
+ }
+
+ b = &to->bell;
+ for (it = from->bell; it; it = it->next)
+ {
+ if (!(*b))
+ {
+ *b = calloc(1, sizeof(BellFeedbackClassRec));
+ if (!(*b))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*b)->BellProc = it->BellProc;
+ (*b)->CtrlProc = it->CtrlProc;
+ (*b)->ctrl = it->ctrl;
+
+ b = &(*b)->next;
+ }
+ } else if (to->bell && !from->bell)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->bell = to->bell;
+ to->bell = NULL;
+ }
+
+ if (from->leds)
+ {
+ LedFeedbackPtr *l, it;
+
+ if (!to->leds)
+ {
+ classes = to->unused_classes;
+ to->leds = classes->leds;
+ classes->leds = NULL;
+ }
+
+ l = &to->leds;
+ for (it = from->leds; it; it = it->next)
+ {
+ if (!(*l))
+ {
+ *l = calloc(1, sizeof(LedFeedbackClassRec));
+ if (!(*l))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*l)->CtrlProc = it->CtrlProc;
+ (*l)->ctrl = it->ctrl;
+ if ((*l)->xkb_sli)
+ XkbFreeSrvLedInfo((*l)->xkb_sli);
+ (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
+
+ l = &(*l)->next;
+ }
+ } else if (to->leds && !from->leds)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->leds = to->leds;
+ to->leds = NULL;
+ }
+}
+
+static void
+DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+ ClassesPtr classes;
+
+ /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
+ * kbdfeed to be set up properly, so let's do the feedback classes first.
+ */
+ if (from->kbdfeed)
+ {
+ KbdFeedbackPtr *k, it;
+
+ if (!to->kbdfeed)
+ {
+ classes = to->unused_classes;
+
+ to->kbdfeed = classes->kbdfeed;
+ if (!to->kbdfeed)
+ InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
+ classes->kbdfeed = NULL;
+ }
+
+ k = &to->kbdfeed;
+ for(it = from->kbdfeed; it; it = it->next)
+ {
+ if (!(*k))
+ {
+ *k = calloc(1, sizeof(KbdFeedbackClassRec));
+ if (!*k)
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*k)->BellProc = it->BellProc;
+ (*k)->CtrlProc = it->CtrlProc;
+ (*k)->ctrl = it->ctrl;
+ if ((*k)->xkb_sli)
+ XkbFreeSrvLedInfo((*k)->xkb_sli);
+ (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
+
+ k = &(*k)->next;
+ }
+ } else if (to->kbdfeed && !from->kbdfeed)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->kbdfeed = to->kbdfeed;
+ to->kbdfeed = NULL;
+ }
+
+ if (from->key)
+ {
+ if (!to->key)
+ {
+ classes = to->unused_classes;
+ to->key = classes->key;
+ if (!to->key)
+ InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
+ else
+ classes->key = NULL;
+ }
+
+ CopyKeyClass(from, to);
+ } else if (to->key && !from->key)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->key = to->key;
+ to->key = NULL;
+ }
+
+ /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
+ * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo
+ * didn't update the pointers so we need to do it manually here.
+ */
+ if (to->kbdfeed)
+ {
+ KbdFeedbackPtr k;
+
+ for (k = to->kbdfeed; k; k = k->next)
+ {
+ if (!k->xkb_sli)
+ continue;
+ if (k->xkb_sli->flags & XkbSLI_IsDefault)
+ {
+ k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
+ k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
+ }
+ }
+ }
+
+ /* We can't just copy over the focus class. When an app sets the focus,
+ * it'll do so on the master device. Copying the SDs focus means losing
+ * the focus.
+ * So we only copy the focus class if the device didn't have one,
+ * otherwise we leave it as it is.
+ */
+ if (from->focus)
+ {
+ if (!to->focus)
+ {
+ WindowPtr *oldTrace;
+
+ classes = to->unused_classes;
+ to->focus = classes->focus;
+ if (!to->focus)
+ {
+ to->focus = calloc(1, sizeof(FocusClassRec));
+ if (!to->focus)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->focus = NULL;
+
+ oldTrace = to->focus->trace;
+ memcpy(to->focus, from->focus, sizeof(FocusClassRec));
+ to->focus->trace = realloc(oldTrace,
+ to->focus->traceSize * sizeof(WindowPtr));
+ if (!to->focus->trace && to->focus->traceSize)
+ FatalError("[Xi] no memory for trace.\n");
+ memcpy(to->focus->trace, from->focus->trace,
+ from->focus->traceSize * sizeof(WindowPtr));
+ to->focus->sourceid = from->id;
+ }
+ } else if (to->focus)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->focus = to->focus;
+ to->focus = NULL;
+ }
+
+}
+
+static void
+DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+ ClassesPtr classes;
+
+ /* Feedback classes must be copied first */
+ if (from->ptrfeed)
+ {
+ PtrFeedbackPtr *p, it;
+ if (!to->ptrfeed)
+ {
+ classes = to->unused_classes;
+ to->ptrfeed = classes->ptrfeed;
+ classes->ptrfeed = NULL;
+ }
+
+ p = &to->ptrfeed;
+ for (it = from->ptrfeed; it; it = it->next)
+ {
+ if (!(*p))
+ {
+ *p = calloc(1, sizeof(PtrFeedbackClassRec));
+ if (!*p)
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*p)->CtrlProc = it->CtrlProc;
+ (*p)->ctrl = it->ctrl;
+
+ p = &(*p)->next;
+ }
+ } else if (to->ptrfeed && !from->ptrfeed)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->ptrfeed = to->ptrfeed;
+ to->ptrfeed = NULL;
+ }
+
+ if (from->valuator)
+ {
+ ValuatorClassPtr v;
+ if (!to->valuator)
+ {
+ classes = to->unused_classes;
+ to->valuator = classes->valuator;
+ if (to->valuator)
+ classes->valuator = NULL;
+ }
+
+ to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
+ from->valuator->numAxes * sizeof(AxisInfo) +
+ from->valuator->numAxes * sizeof(double));
+ v = to->valuator;
+ if (!v)
+ FatalError("[Xi] no memory for class shift.\n");
+
+ v->numAxes = from->valuator->numAxes;
+ v->axes = (AxisInfoPtr)&v[1];
+ memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
+
+ v->axisVal = (double*)(v->axes + from->valuator->numAxes);
+ v->sourceid = from->id;
+ } else if (to->valuator && !from->valuator)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->valuator = to->valuator;
+ to->valuator = NULL;
+ }
+
+ if (from->button)
+ {
+ if (!to->button)
+ {
+ classes = to->unused_classes;
+ to->button = classes->button;
+ if (!to->button)
+ {
+ to->button = calloc(1, sizeof(ButtonClassRec));
+ if (!to->button)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->button = NULL;
+ }
+
+ if (from->button->xkb_acts)
+ {
+ if (!to->button->xkb_acts)
+ {
+ to->button->xkb_acts = calloc(1, sizeof(XkbAction));
+ if (!to->button->xkb_acts)
+ FatalError("[Xi] not enough memory for xkb_acts.\n");
+ }
+ memcpy(to->button->xkb_acts, from->button->xkb_acts,
+ sizeof(XkbAction));
+ } else
+ free(to->button->xkb_acts);
+
+ memcpy(to->button->labels, from->button->labels,
+ from->button->numButtons * sizeof(Atom));
+ to->button->sourceid = from->id;
+ } else if (to->button && !from->button)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->button = to->button;
+ to->button = NULL;
+ }
+
+ if (from->proximity)
+ {
+ if (!to->proximity)
+ {
+ classes = to->unused_classes;
+ to->proximity = classes->proximity;
+ if (!to->proximity)
+ {
+ to->proximity = calloc(1, sizeof(ProximityClassRec));
+ if (!to->proximity)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->proximity = NULL;
+ }
+ memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
+ to->proximity->sourceid = from->id;
+ } else if (to->proximity)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->proximity = to->proximity;
+ to->proximity = NULL;
+ }
+
+ if (from->absolute)
+ {
+ if (!to->absolute)
+ {
+ classes = to->unused_classes;
+ to->absolute = classes->absolute;
+ if (!to->absolute)
+ {
+ to->absolute = calloc(1, sizeof(AbsoluteClassRec));
+ if (!to->absolute)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->absolute = NULL;
+ }
+ memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
+ to->absolute->sourceid = from->id;
+ } else if (to->absolute)
+ {
+ ClassesPtr classes;
+ classes = to->unused_classes;
+ classes->absolute = to->absolute;
+ to->absolute = NULL;
+ }
+}
+
+/**
+ * Copies the CONTENT of the classes of device from into the classes in device
+ * to. From and to are identical after finishing.
+ *
+ * If to does not have classes from currenly has, the classes are stored in
+ * to's devPrivates system. Later, we recover it again from there if needed.
+ * Saves a few memory allocations.
+ */
+void
+DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
+{
+ /* generic feedback classes, not tied to pointer and/or keyboard */
+ DeepCopyFeedbackClasses(from, to);
+
+ if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
+ DeepCopyKeyboardClasses(from, to);
+ if ((dce->flags & DEVCHANGE_POINTER_EVENT))
+ DeepCopyPointerClasses(from, to);
+}
+
+
+/**
+ * Send an XI2 DeviceChangedEvent to all interested clients.
+ */
+void
+XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
+{
+ xXIDeviceChangedEvent *dcce;
+ int rc;
+
+ rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
+ if (rc != Success)
+ {
+ ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
+ return;
+ }
+
+ /* we don't actually swap if there's a NullClient, swapping is done
+ * later when event is delivered. */
+ SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
+ free(dcce);
+}
+
+static void
+ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
+{
+ DeviceIntPtr slave;
+ int rc;
+
+ /* For now, we don't have devices that change physically. */
+ if (!IsMaster(device))
+ return;
+
+ rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
+
+ if (rc != Success)
+ return; /* Device has disappeared */
+
+ if (!slave->u.master)
+ return; /* set floating since the event */
+
+ if (slave->u.master->id != dce->masterid)
+ return; /* not our slave anymore, don't care */
+
+ /* FIXME: we probably need to send a DCE for the new slave now */
+
+ device->public.devicePrivate = slave->public.devicePrivate;
+
+ /* FIXME: the classes may have changed since we generated the event. */
+ DeepCopyDeviceClasses(slave, device, dce);
+ XISendDeviceChangedEvent(slave, device, dce);
+}
+
+/**
+ * Update the device state according to the data in the event.
+ *
+ * return values are
+ * DEFAULT ... process as normal
+ * DONT_PROCESS ... return immediately from caller
+ */
+#define DEFAULT 0
+#define DONT_PROCESS 1
+int
+UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
+{
+ int i;
+ int key = 0,
+ bit = 0,
+ last_valuator;
+
+ KeyClassPtr k = NULL;
+ ButtonClassPtr b = NULL;
+ ValuatorClassPtr v = NULL;
+
+ /* This event is always the first we get, before the actual events with
+ * the data. However, the way how the DDX is set up, "device" will
+ * actually be the slave device that caused the event.
+ */
+ switch(event->type)
+ {
+ case ET_DeviceChanged:
+ ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
+ return DONT_PROCESS; /* event has been sent already */
+ case ET_Motion:
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_KeyPress:
+ case ET_KeyRelease:
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ break;
+ default:
+ /* other events don't update the device */
+ return DEFAULT;
+ }
+
+ k = device->key;
+ v = device->valuator;
+ b = device->button;
+
+ key = event->detail.key;
+ bit = 1 << (key & 7);
+
+ /* Update device axis */
+ /* Check valuators first */
+ last_valuator = -1;
+ for (i = 0; i < MAX_VALUATORS; i++)
+ {
+ if (BitIsOn(&event->valuators.mask, i))
+ {
+ if (!v)
+ {
+ ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
+ "Ignoring event.\n", device->name);
+ return DONT_PROCESS;
+ } else if (v->numAxes < i)
+ {
+ ErrorF("[Xi] Too many valuators reported for device '%s'. "
+ "Ignoring event.\n", device->name);
+ return DONT_PROCESS;
+ }
+ last_valuator = i;
+ }
+ }
+
+ for (i = 0; i <= last_valuator && i < v->numAxes; i++)
+ {
+ if (BitIsOn(&event->valuators.mask, i))
+ {
+ /* XXX: Relative/Absolute mode */
+ v->axisVal[i] = event->valuators.data[i];
+ v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
+ }
+ }
+
+ if (event->type == ET_KeyPress) {
+ if (!k)
+ return DONT_PROCESS;
+
+ /* don't allow ddx to generate multiple downs, but repeats are okay */
+ if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
+ return DONT_PROCESS;
+
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ set_key_down(device, key, KEY_PROCESSED);
+ } else if (event->type == ET_KeyRelease) {
+ if (!k)
+ return DONT_PROCESS;
+
+ if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */
+ return DONT_PROCESS;
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ set_key_up(device, key, KEY_PROCESSED);
+ } else if (event->type == ET_ButtonPress) {
+ Mask mask;
+ if (!b)
+ return DONT_PROCESS;
+
+ if (button_is_down(device, key, BUTTON_PROCESSED))
+ return DONT_PROCESS;
+
+ set_button_down(device, key, BUTTON_PROCESSED);
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ if (!b->map[key])
+ return DONT_PROCESS;
+ b->buttonsDown++;
+ b->motionMask = DeviceButtonMotionMask;
+ if (b->map[key] <= 5)
+ b->state |= (Button1Mask >> 1) << b->map[key];
+
+ /* Add state and motionMask to the filter for this event */
+ mask = DevicePointerMotionMask | b->state | b->motionMask;
+ SetMaskForEvent(device->id, mask, DeviceMotionNotify);
+ mask = PointerMotionMask | b->state | b->motionMask;
+ SetMaskForEvent(device->id, mask, MotionNotify);
+ } else if (event->type == ET_ButtonRelease) {
+ Mask mask;
+ if (!b)
+ return DONT_PROCESS;
+
+ if (!button_is_down(device, key, BUTTON_PROCESSED))
+ return DONT_PROCESS;
+ if (IsMaster(device)) {
+ DeviceIntPtr sd;
+
+ /*
+ * Leave the button down if any slave has the
+ * button still down. Note that this depends on the
+ * event being delivered through the slave first
+ */
+ for (sd = inputInfo.devices; sd; sd = sd->next) {
+ if (IsMaster(sd) || sd->u.master != device)
+ continue;
+ if (!sd->button)
+ continue;
+ for (i = 1; i <= sd->button->numButtons; i++)
+ if (sd->button->map[i] == key &&
+ button_is_down(sd, i, BUTTON_PROCESSED))
+ return DONT_PROCESS;
+ }
+ }
+ set_button_up(device, key, BUTTON_PROCESSED);
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ if (!b->map[key])
+ return DONT_PROCESS;
+ if (b->buttonsDown >= 1 && !--b->buttonsDown)
+ b->motionMask = 0;
+ if (b->map[key] <= 5)
+ b->state &= ~((Button1Mask >> 1) << b->map[key]);
+
+ /* Add state and motionMask to the filter for this event */
+ mask = DevicePointerMotionMask | b->state | b->motionMask;
+ SetMaskForEvent(device->id, mask, DeviceMotionNotify);
+ mask = PointerMotionMask | b->state | b->motionMask;
+ SetMaskForEvent(device->id, mask, MotionNotify);
+ } else if (event->type == ET_ProximityIn)
+ device->proximity->in_proximity = TRUE;
+ else if (event->type == ET_ProximityOut)
+ device->proximity->in_proximity = FALSE;
+
+ return DEFAULT;
+}
+
+static void
+ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
+{
+ GrabPtr grab = device->deviceGrab.grab;
+
+ if (grab)
+ DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
+ else { /* deliver to all root windows */
+ xEvent *xi;
+ int i;
+
+ i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
+ if (i != Success)
+ {
+ ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
+ device->name, i);
+ return;
+ }
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
+ GetEventFilter(device, xi), NULL);
+ free(xi);
+ }
+}
+
+/**
+ * Main device event processing function.
+ * Called from when processing the events from the event queue.
+ *
+ */
+void
+ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
+{
+ GrabPtr grab;
+ Bool deactivateDeviceGrab = FALSE;
+ int key = 0, rootX, rootY;
+ ButtonClassPtr b;
+ KeyClassPtr k;
+ ValuatorClassPtr v;
+ int ret = 0;
+ int state, i;
+ DeviceIntPtr mouse = NULL, kbd = NULL;
+ DeviceEvent *event = &ev->device_event;
+
+ CHECKEVENT(ev);
+
+ if (ev->any.type == ET_RawKeyPress ||
+ ev->any.type == ET_RawKeyRelease ||
+ ev->any.type == ET_RawButtonPress ||
+ ev->any.type == ET_RawButtonRelease ||
+ ev->any.type == ET_RawMotion)
+ {
+ ProcessRawEvent(&ev->raw_event, device);
+ return;
+ }
+
+ if (IsPointerDevice(device))
+ {
+ kbd = GetPairedDevice(device);
+ mouse = device;
+ if (!kbd->key) /* can happen with floating SDs */
+ kbd = NULL;
+ } else
+ {
+ mouse = GetPairedDevice(device);
+ kbd = device;
+ if (!mouse->valuator || !mouse->button) /* may be float. SDs */
+ mouse = NULL;
+ }
+
+ /* State needs to be assembled BEFORE the device is updated. */
+ state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
+ state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
+
+ for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
+ if (BitIsOn(mouse->button->down, i))
+ SetBit(event->buttons, i);
+
+ if (kbd && kbd->key)
+ {
+ XkbStatePtr state;
+ /* we need the state before the event happens */
+ if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
+ state = &kbd->key->xkbInfo->prev_state;
+ else
+ state = &kbd->key->xkbInfo->state;
+
+ event->mods.base = state->base_mods;
+ event->mods.latched = state->latched_mods;
+ event->mods.locked = state->locked_mods;
+ event->mods.effective = state->mods;
+
+ event->group.base = state->base_group;
+ event->group.latched = state->latched_group;
+ event->group.locked = state->locked_group;
+ event->group.effective = state->group;
+ }
+
+ ret = UpdateDeviceState(device, event);
+ if (ret == DONT_PROCESS)
+ return;
+
+ v = device->valuator;
+ b = device->button;
+ k = device->key;
+
+ if (IsMaster(device) || !device->u.master)
+ CheckMotion(event, device);
+
+ switch (event->type)
+ {
+ case ET_Motion:
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_KeyPress:
+ case ET_KeyRelease:
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ GetSpritePosition(device, &rootX, &rootY);
+ event->root_x = rootX;
+ event->root_y = rootY;
+ NoticeEventTime((InternalEvent*)event);
+ event->corestate = state;
+ key = event->detail.key;
+ break;
+ default:
+ break;
+ }
+
+ if (DeviceEventCallback && !syncEvents.playingEvents) {
+ DeviceEventInfoRec eventinfo;
+ SpritePtr pSprite = device->spriteInfo->sprite;
+
+ /* see comment in EnqueueEvents regarding the next three lines */
+ if (ev->any.type == ET_Motion)
+ ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
+
+ eventinfo.device = device;
+ eventinfo.event = ev;
+ CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
+ }
+
+ grab = device->deviceGrab.grab;
+
+ switch(event->type)
+ {
+ case ET_KeyPress:
+ if (!grab && CheckDeviceGrabs(device, event, 0)) {
+ device->deviceGrab.activatingKey = key;
+ return;
+ }
+ break;
+ case ET_KeyRelease:
+ if (grab && device->deviceGrab.fromPassiveGrab &&
+ (key == device->deviceGrab.activatingKey) &&
+ (device->deviceGrab.grab->type == KeyPress ||
+ device->deviceGrab.grab->type == DeviceKeyPress ||
+ device->deviceGrab.grab->type == XI_KeyPress))
+ deactivateDeviceGrab = TRUE;
+ break;
+ case ET_ButtonPress:
+ event->detail.button = b->map[key];
+ if (!event->detail.button) { /* there's no button 0 */
+ event->detail.button = key;
+ return;
+ }
+ if (!grab && CheckDeviceGrabs(device, event, 0))
+ {
+ /* if a passive grab was activated, the event has been sent
+ * already */
+ return;
+ }
+ break;
+ case ET_ButtonRelease:
+ event->detail.button = b->map[key];
+ if (!event->detail.button) { /* there's no button 0 */
+ event->detail.button = key;
+ return;
+ }
+ if (grab && !b->buttonsDown &&
+ device->deviceGrab.fromPassiveGrab &&
+ (device->deviceGrab.grab->type == ButtonPress ||
+ device->deviceGrab.grab->type == DeviceButtonPress ||
+ device->deviceGrab.grab->type == XI_ButtonPress))
+ deactivateDeviceGrab = TRUE;
+ default:
+ break;
+ }
+
+
+ if (grab)
+ DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
+ else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
+ DeliverFocusedEvent(device, (InternalEvent*)event,
+ GetSpriteWindow(device));
+ else
+ DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
+ NullGrab, NullWindow, device);
+
+ if (deactivateDeviceGrab == TRUE)
+ (*device->deviceGrab.DeactivateGrab) (device);
+ event->detail.key = key;
+}
+
+int
+InitProximityClassDeviceStruct(DeviceIntPtr dev)
+{
+ ProximityClassPtr proxc;
+
+ proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
+ if (!proxc)
+ return FALSE;
+ proxc->sourceid = dev->id;
+ proxc->in_proximity = TRUE;
+ dev->proximity = proxc;
+ return TRUE;
+}
+
+/**
+ * Initialise the device's valuators. The memory must already be allocated,
+ * this function merely inits the matching axis (specified through axnum) to
+ * sane values.
+ *
+ * It is a condition that (minval < maxval).
+ *
+ * @see InitValuatorClassDeviceStruct
+ */
+void
+InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
+ int resolution, int min_res, int max_res, int mode)
+{
+ AxisInfoPtr ax;
+
+ if (!dev || !dev->valuator || minval > maxval)
+ return;
+ if (axnum >= dev->valuator->numAxes)
+ return;
+
+ ax = dev->valuator->axes + axnum;
+
+ ax->min_value = minval;
+ ax->max_value = maxval;
+ ax->resolution = resolution;
+ ax->min_resolution = min_res;
+ ax->max_resolution = max_res;
+ ax->label = label;
+ ax->mode = mode;
+
+ if (mode & OutOfProximity)
+ dev->proximity->in_proximity = FALSE;
+}
+
+static void
+FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
+ ButtonClassPtr b, ValuatorClassPtr v, int first)
+{
+ ev->type = DeviceStateNotify;
+ ev->deviceid = dev->id;
+ ev->time = currentTime.milliseconds;
+ ev->classes_reported = 0;
+ ev->num_keys = 0;
+ ev->num_buttons = 0;
+ ev->num_valuators = 0;
+
+ if (b) {
+ ev->classes_reported |= (1 << ButtonClass);
+ ev->num_buttons = b->numButtons;
+ memcpy((char*)ev->buttons, (char*)b->down, 4);
+ } else if (k) {
+ ev->classes_reported |= (1 << KeyClass);
+ ev->num_keys = k->xkbInfo->desc->max_key_code -
+ k->xkbInfo->desc->min_key_code;
+ memmove((char *)&ev->keys[0], (char *)k->down, 4);
+ }
+ if (v) {
+ int nval = v->numAxes - first;
+
+ ev->classes_reported |= (1 << ValuatorClass);
+ ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
+ ev->num_valuators = nval < 3 ? nval : 3;
+ switch (ev->num_valuators) {
+ case 3:
+ ev->valuator2 = v->axisVal[first + 2];
+ case 2:
+ ev->valuator1 = v->axisVal[first + 1];
+ case 1:
+ ev->valuator0 = v->axisVal[first];
+ break;
+ }
+ }
+}
+
+static void
+FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
+ int first)
+{
+ int nval = v->numAxes - first;
+
+ ev->type = DeviceValuator;
+ ev->deviceid = dev->id;
+ ev->num_valuators = nval < 3 ? nval : 3;
+ ev->first_valuator = first;
+ switch (ev->num_valuators) {
+ case 3:
+ ev->valuator2 = v->axisVal[first + 2];
+ case 2:
+ ev->valuator1 = v->axisVal[first + 1];
+ case 1:
+ ev->valuator0 = v->axisVal[first];
+ break;
+ }
+ first += ev->num_valuators;
+}
+
+void
+DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
+ WindowPtr pWin)
+{
+ deviceFocus event;
+ xXIFocusInEvent *xi2event;
+ DeviceIntPtr mouse;
+ int btlen, len, i;
+
+ mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
+
+ /* XI 2 event */
+ btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
+ btlen = bytes_to_int32(btlen);
+ len = sizeof(xXIFocusInEvent) + btlen * 4;
+
+ xi2event = calloc(1, len);
+ xi2event->type = GenericEvent;
+ xi2event->extension = IReqCode;
+ xi2event->evtype = type;
+ xi2event->length = bytes_to_int32(len - sizeof(xEvent));
+ xi2event->buttons_len = btlen;
+ xi2event->detail = detail;
+ xi2event->time = currentTime.milliseconds;
+ xi2event->deviceid = dev->id;
+ xi2event->sourceid = dev->id; /* a device doesn't change focus by itself */
+ xi2event->mode = mode;
+ xi2event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
+ xi2event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
+
+ for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
+ if (BitIsOn(mouse->button->down, i))
+ SetBit(&xi2event[1], i);
+
+ if (dev->key)
+ {
+ xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
+ xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
+ xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
+ xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
+
+ xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
+ xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
+ xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
+ xi2event->group.effective_group = dev->key->xkbInfo->state.group;
+ }
+
+ FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
+ None, FALSE);
+
+ DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
+ GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
+
+ free(xi2event);
+
+ /* XI 1.x event */
+ event.deviceid = dev->id;
+ event.mode = mode;
+ event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
+ event.detail = detail;
+ event.window = pWin->drawable.id;
+ event.time = currentTime.milliseconds;
+
+ DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
+ DeviceFocusChangeMask, NullGrab);
+
+ if ((type == DeviceFocusIn) &&
+ (wOtherInputMasks(pWin)) &&
+ (wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
+ {
+ int evcount = 1;
+ deviceStateNotify *ev, *sev;
+ deviceKeyStateNotify *kev;
+ deviceButtonStateNotify *bev;
+
+ KeyClassPtr k;
+ ButtonClassPtr b;
+ ValuatorClassPtr v;
+ int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
+
+ if ((b = dev->button) != NULL) {
+ nbuttons = b->numButtons;
+ if (nbuttons > 32)
+ evcount++;
+ }
+ if ((k = dev->key) != NULL) {
+ nkeys = k->xkbInfo->desc->max_key_code -
+ k->xkbInfo->desc->min_key_code;
+ if (nkeys > 32)
+ evcount++;
+ if (nbuttons > 0) {
+ evcount++;
+ }
+ }
+ if ((v = dev->valuator) != NULL) {
+ nval = v->numAxes;
+
+ if (nval > 3)
+ evcount++;
+ if (nval > 6) {
+ if (!(k && b))
+ evcount++;
+ if (nval > 9)
+ evcount += ((nval - 7) / 3);
+ }
+ }
+
+ sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
+ FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
+
+ if (b != NULL) {
+ FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
+ first += 3;
+ nval -= 3;
+ if (nbuttons > 32) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ bev = (deviceButtonStateNotify *) ev++;
+ bev->type = DeviceButtonStateNotify;
+ bev->deviceid = dev->id;
+ memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
+ }
+ if (nval > 0) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
+ first += 3;
+ nval -= 3;
+ }
+ }
+
+ if (k != NULL) {
+ FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
+ first += 3;
+ nval -= 3;
+ if (nkeys > 32) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ kev = (deviceKeyStateNotify *) ev++;
+ kev->type = DeviceKeyStateNotify;
+ kev->deviceid = dev->id;
+ memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
+ }
+ if (nval > 0) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
+ first += 3;
+ nval -= 3;
+ }
+ }
+
+ while (nval > 0) {
+ FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
+ first += 3;
+ nval -= 3;
+ if (nval > 0) {
+ (ev - 1)->deviceid |= MORE_EVENTS;
+ FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
+ first += 3;
+ nval -= 3;
+ }
+ }
+
+ DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
+ DeviceStateNotifyMask, NullGrab);
+ free(sev);
+ }
+}
+
+int
+CheckGrabValues(ClientPtr client, GrabParameters* param)
+{
+ if (param->grabtype != GRABTYPE_CORE &&
+ param->grabtype != GRABTYPE_XI &&
+ param->grabtype != GRABTYPE_XI2)
+ {
+ ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
+ return BadImplementation;
+ }
+
+ if ((param->this_device_mode != GrabModeSync) &&
+ (param->this_device_mode != GrabModeAsync)) {
+ client->errorValue = param->this_device_mode;
+ return BadValue;
+ }
+ if ((param->other_devices_mode != GrabModeSync) &&
+ (param->other_devices_mode != GrabModeAsync)) {
+ client->errorValue = param->other_devices_mode;
+ return BadValue;
+ }
+
+ if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
+ (param->modifiers & ~AllModifiersMask)) {
+ client->errorValue = param->modifiers;
+ return BadValue;
+ }
+
+ if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
+ client->errorValue = param->ownerEvents;
+ return BadValue;
+ }
+ return Success;
+}
+
+int
+GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
+ int button, GrabParameters *param, GrabType grabtype,
+ GrabMask *mask)
+{
+ WindowPtr pWin, confineTo;
+ CursorPtr cursor;
+ GrabPtr grab;
+ int rc, type = -1;
+ Mask access_mode = DixGrabAccess;
+
+ rc = CheckGrabValues(client, param);
+ if (rc != Success)
+ return rc;
+ if (param->confineTo == None)
+ confineTo = NullWindow;
+ else {
+ rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+ if (param->cursor == None)
+ cursor = NullCursor;
+ else {
+ rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
+ RT_CURSOR, client, DixUseAccess);
+ if (rc != Success)
+ {
+ client->errorValue = param->cursor;
+ return rc;
+ }
+ access_mode |= DixForceAccess;
+ }
+ if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
+ access_mode |= DixFreezeAccess;
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
+ if (rc != Success)
+ return rc;
+ rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ if (grabtype == GRABTYPE_XI)
+ type = DeviceButtonPress;
+ else if (grabtype == GRABTYPE_XI2)
+ type = XI_ButtonPress;
+
+ grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
+ mask, param, type, button, confineTo, cursor);
+ if (!grab)
+ return BadAlloc;
+ return AddPassiveGrabToList(client, grab);
+}
+
+/**
+ * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
+ * grabtype is GRABTYPE_XI2, the key is a keysym.
+ */
+int
+GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
+ int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
+{
+ WindowPtr pWin;
+ GrabPtr grab;
+ KeyClassPtr k = dev->key;
+ Mask access_mode = DixGrabAccess;
+ int rc, type = -1;
+
+ rc = CheckGrabValues(client, param);
+ if (rc != Success)
+ return rc;
+ if (k == NULL)
+ return BadMatch;
+ if (grabtype == GRABTYPE_XI)
+ {
+ if ((key > k->xkbInfo->desc->max_key_code ||
+ key < k->xkbInfo->desc->min_key_code)
+ && (key != AnyKey)) {
+ client->errorValue = key;
+ return BadValue;
+ }
+ type = DeviceKeyPress;
+ } else if (grabtype == GRABTYPE_XI2)
+ type = XI_KeyPress;
+
+ rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
+ access_mode |= DixFreezeAccess;
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
+ if (rc != Success)
+ return rc;
+
+ grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
+ mask, param, type, key, NULL, NULL);
+ if (!grab)
+ return BadAlloc;
+ return AddPassiveGrabToList(client, grab);
+}
+
+/* Enter/FocusIn grab */
+int
+GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
+ GrabParameters *param, GrabMask *mask)
+{
+ WindowPtr pWin;
+ CursorPtr cursor;
+ GrabPtr grab;
+ Mask access_mode = DixGrabAccess;
+ int rc;
+
+ rc = CheckGrabValues(client, param);
+ if (rc != Success)
+ return rc;
+
+ rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ if (param->cursor == None)
+ cursor = NullCursor;
+ else {
+ rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
+ RT_CURSOR, client, DixUseAccess);
+ if (rc != Success)
+ {
+ client->errorValue = param->cursor;
+ return rc;
+ }
+ access_mode |= DixForceAccess;
+ }
+ if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
+ access_mode |= DixFreezeAccess;
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
+ if (rc != Success)
+ return rc;
+
+ grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
+ mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
+ 0, NULL, cursor);
+
+ if (!grab)
+ return BadAlloc;
+
+ return AddPassiveGrabToList(client, grab);
+}
+
+int
+SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
+ Mask mask, Mask exclusivemasks)
+{
+ int mskidx = dev->id;
+ int i, ret;
+ Mask check;
+ InputClientsPtr others;
+
+ check = (mask & exclusivemasks);
+ if (wOtherInputMasks(pWin)) {
+ if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different
+ * clients to select on any of the
+ * events for maskcheck. However,
+ * it is OK, for some client to
+ * continue selecting on one of those
+ * events. */
+ for (others = wOtherInputMasks(pWin)->inputClients; others;
+ others = others->next) {
+ if (!SameClient(others, client) && (check &
+ others->mask[mskidx]))
+ return BadAccess;
+ }
+ }
+ for (others = wOtherInputMasks(pWin)->inputClients; others;
+ others = others->next) {
+ if (SameClient(others, client)) {
+ check = others->mask[mskidx];
+ others->mask[mskidx] = mask;
+ if (mask == 0) {
+ for (i = 0; i < EMASKSIZE; i++)
+ if (i != mskidx && others->mask[i] != 0)
+ break;
+ if (i == EMASKSIZE) {
+ RecalculateDeviceDeliverableEvents(pWin);
+ if (ShouldFreeInputMasks(pWin, FALSE))
+ FreeResource(others->resource, RT_NONE);
+ return Success;
+ }
+ }
+ goto maskSet;
+ }
+ }
+ }
+ check = 0;
+ if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
+ return ret;
+ maskSet:
+ if (dev->valuator)
+ if ((dev->valuator->motionHintWindow == pWin) &&
+ (mask & DevicePointerMotionHintMask) &&
+ !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
+ dev->valuator->motionHintWindow = NullWindow;
+ RecalculateDeviceDeliverableEvents(pWin);
+ return Success;
+}
+
+int
+AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
+{
+ InputClientsPtr others;
+
+ if (!pWin->optional && !MakeWindowOptional(pWin))
+ return BadAlloc;
+ others = calloc(1, sizeof(InputClients));
+ if (!others)
+ return BadAlloc;
+ if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
+ return BadAlloc;
+ others->mask[mskidx] = mask;
+ others->resource = FakeClientID(client->index);
+ others->next = pWin->optional->inputMasks->inputClients;
+ pWin->optional->inputMasks->inputClients = others;
+ if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
+ return BadAlloc;
+ return Success;
+}
+
+static Bool
+MakeInputMasks(WindowPtr pWin)
+{
+ struct _OtherInputMasks *imasks;
+
+ imasks = calloc(1, sizeof(struct _OtherInputMasks));
+ if (!imasks)
+ return FALSE;
+ pWin->optional->inputMasks = imasks;
+ return TRUE;
+}
+
+void
+RecalculateDeviceDeliverableEvents(WindowPtr pWin)
+{
+ InputClientsPtr others;
+ struct _OtherInputMasks *inputMasks; /* default: NULL */
+ WindowPtr pChild, tmp;
+ int i, j;
+
+ pChild = pWin;
+ while (1) {
+ if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
+ for (i = 0; i < EMASKSIZE; i++)
+ memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
+ for (others = inputMasks->inputClients; others;
+ others = others->next) {
+ for (i = 0; i < EMASKSIZE; i++)
+ inputMasks->inputEvents[i] |= others->mask[i];
+ for (i = 0; i < EMASKSIZE; i++)
+ for (j = 0; j < XI2MASKSIZE; j++)
+ inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
+ }
+ for (i = 0; i < EMASKSIZE; i++)
+ inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
+ for (tmp = pChild->parent; tmp; tmp = tmp->parent)
+ if (wOtherInputMasks(tmp))
+ for (i = 0; i < EMASKSIZE; i++)
+ inputMasks->deliverableEvents[i] |=
+ (wOtherInputMasks(tmp)->deliverableEvents[i]
+ & ~inputMasks->
+ dontPropagateMask[i] & PropagateMask[i]);
+ }
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+int
+InputClientGone(WindowPtr pWin, XID id)
+{
+ InputClientsPtr other, prev;
+
+ if (!wOtherInputMasks(pWin))
+ return Success;
+ prev = 0;
+ for (other = wOtherInputMasks(pWin)->inputClients; other;
+ other = other->next) {
+ if (other->resource == id) {
+ if (prev) {
+ prev->next = other->next;
+ free(other);
+ } else if (!(other->next)) {
+ if (ShouldFreeInputMasks(pWin, TRUE)) {
+ wOtherInputMasks(pWin)->inputClients = other->next;
+ free(wOtherInputMasks(pWin));
+ pWin->optional->inputMasks = (OtherInputMasks *) NULL;
+ CheckWindowOptionalNeed(pWin);
+ free(other);
+ } else {
+ other->resource = FakeClientID(0);
+ if (!AddResource(other->resource, RT_INPUTCLIENT,
+ (pointer) pWin))
+ return BadAlloc;
+ }
+ } else {
+ wOtherInputMasks(pWin)->inputClients = other->next;
+ free(other);
+ }
+ RecalculateDeviceDeliverableEvents(pWin);
+ return Success;
+ }
+ prev = other;
+ }
+ FatalError("client not on device event list");
+}
+
+int
+SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
+ xEvent * ev, Mask mask, int count)
+{
+ WindowPtr pWin;
+ WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
+ WindowPtr spriteWin = GetSpriteWindow(d);
+
+ if (dest == PointerWindow)
+ pWin = spriteWin;
+ else if (dest == InputFocus) {
+ WindowPtr inputFocus;
+
+ if (!d->focus)
+ inputFocus = spriteWin;
+ else
+ inputFocus = d->focus->win;
+
+ if (inputFocus == FollowKeyboardWin)
+ inputFocus = inputInfo.keyboard->focus->win;
+
+ if (inputFocus == NoneWin)
+ return Success;
+
+ /* If the input focus is PointerRootWin, send the event to where
+ * the pointer is if possible, then perhaps propogate up to root. */
+ if (inputFocus == PointerRootWin)
+ inputFocus = GetCurrentRootWindow(d);
+
+ if (IsParent(inputFocus, spriteWin)) {
+ effectiveFocus = inputFocus;
+ pWin = spriteWin;
+ } else
+ effectiveFocus = pWin = inputFocus;
+ } else
+ dixLookupWindow(&pWin, dest, client, DixSendAccess);
+ if (!pWin)
+ return BadWindow;
+ if ((propagate != xFalse) && (propagate != xTrue)) {
+ client->errorValue = propagate;
+ return BadValue;
+ }
+ ev->u.u.type |= 0x80;
+ if (propagate) {
+ for (; pWin; pWin = pWin->parent) {
+ if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
+ return Success;
+ if (pWin == effectiveFocus)
+ return Success;
+ if (wOtherInputMasks(pWin))
+ mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
+ if (!mask)
+ break;
+ }
+ } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
+ DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
+ return Success;
+}
+
+int
+SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
+{
+ int i;
+ ButtonClassPtr b = dev->button;
+
+ if (b == NULL)
+ return BadMatch;
+
+ if (nElts != b->numButtons) {
+ client->errorValue = nElts;
+ return BadValue;
+ }
+ if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
+ return BadValue;
+ for (i = 0; i < nElts; i++)
+ if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
+ return MappingBusy;
+ for (i = 0; i < nElts; i++)
+ b->map[i + 1] = map[i];
+ return Success;
+}
+
+int
+ChangeKeyMapping(ClientPtr client,
+ DeviceIntPtr dev,
+ unsigned len,
+ int type,
+ KeyCode firstKeyCode,
+ CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
+{
+ KeySymsRec keysyms;
+ KeyClassPtr k = dev->key;
+
+ if (k == NULL)
+ return BadMatch;
+
+ if (len != (keyCodes * keySymsPerKeyCode))
+ return BadLength;
+
+ if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
+ (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
+ client->errorValue = firstKeyCode;
+ return BadValue;
+ }
+ if (keySymsPerKeyCode == 0) {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ keysyms.minKeyCode = firstKeyCode;
+ keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
+ keysyms.mapWidth = keySymsPerKeyCode;
+ keysyms.map = map;
+
+ XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
+ serverClient);
+
+ return Success;
+}
+
+static void
+DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
+{
+ WindowPtr parent;
+
+ /* Deactivate any grabs performed on this window, before making
+ * any input focus changes.
+ * Deactivating a device grab should cause focus events. */
+
+ if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
+ (*dev->deviceGrab.DeactivateGrab) (dev);
+
+ /* If the focus window is a root window (ie. has no parent)
+ * then don't delete the focus from it. */
+
+ if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
+ int focusEventMode = NotifyNormal;
+
+ /* If a grab is in progress, then alter the mode of focus events. */
+
+ if (dev->deviceGrab.grab)
+ focusEventMode = NotifyWhileGrabbed;
+
+ switch (dev->focus->revert) {
+ case RevertToNone:
+ if (!ActivateFocusInGrab(dev, pWin, NoneWin))
+ DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
+ dev->focus->win = NoneWin;
+ dev->focus->traceGood = 0;
+ break;
+ case RevertToParent:
+ parent = pWin;
+ do {
+ parent = parent->parent;
+ dev->focus->traceGood--;
+ }
+ while (!parent->realized);
+ if (!ActivateFocusInGrab(dev, pWin, parent))
+ DoFocusEvents(dev, pWin, parent, focusEventMode);
+ dev->focus->win = parent;
+ dev->focus->revert = RevertToNone;
+ break;
+ case RevertToPointerRoot:
+ if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
+ DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
+ dev->focus->win = PointerRootWin;
+ dev->focus->traceGood = 0;
+ break;
+ case RevertToFollowKeyboard:
+ {
+ DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
+ if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
+ kbd = inputInfo.keyboard;
+ if (kbd->focus->win) {
+ if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
+ DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
+ dev->focus->win = FollowKeyboardWin;
+ dev->focus->traceGood = 0;
+ } else {
+ if (!ActivateFocusInGrab(dev, pWin, NoneWin))
+ DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
+ dev->focus->win = NoneWin;
+ dev->focus->traceGood = 0;
+ }
+ }
+ break;
+ }
+ }
+
+ if (dev->valuator)
+ if (dev->valuator->motionHintWindow == pWin)
+ dev->valuator->motionHintWindow = NullWindow;
+}
+
+void
+DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
+{
+ int i;
+ DeviceIntPtr dev;
+ InputClientsPtr ic;
+ struct _OtherInputMasks *inputMasks;
+
+ for (dev = inputInfo.devices; dev; dev = dev->next) {
+ DeleteDeviceFromAnyExtEvents(pWin, dev);
+ }
+
+ for (dev = inputInfo.off_devices; dev; dev = dev->next)
+ DeleteDeviceFromAnyExtEvents(pWin, dev);
+
+ if (freeResources)
+ while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
+ ic = inputMasks->inputClients;
+ for (i = 0; i < EMASKSIZE; i++)
+ inputMasks->dontPropagateMask[i] = 0;
+ FreeResource(ic->resource, RT_NONE);
+ }
+}
+
+int
+MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
+{
+ DeviceIntPtr dev;
+
+ dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
+ DixReadAccess);
+ if (!dev)
+ return 0;
+
+ if (pEvents->type == DeviceMotionNotify) {
+ if (mask & DevicePointerMotionHintMask) {
+ if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
+ return 1; /* don't send, but pretend we did */
+ }
+ pEvents->detail = NotifyHint;
+ } else {
+ pEvents->detail = NotifyNormal;
+ }
+ }
+ return 0;
+}
+
+void
+CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
+ deviceKeyButtonPointer * xE, GrabPtr grab,
+ ClientPtr client, Mask deliveryMask)
+{
+ DeviceIntPtr dev;
+
+ dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
+ DixGrabAccess);
+ if (!dev)
+ return;
+
+ if (type == DeviceMotionNotify)
+ dev->valuator->motionHintWindow = pWin;
+ else if ((type == DeviceButtonPress) && (!grab) &&
+ (deliveryMask & DeviceButtonGrabMask)) {
+ GrabRec tempGrab;
+
+ tempGrab.device = dev;
+ tempGrab.resource = client->clientAsMask;
+ tempGrab.window = pWin;
+ tempGrab.ownerEvents =
+ (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
+ tempGrab.eventMask = deliveryMask;
+ tempGrab.keyboardMode = GrabModeAsync;
+ tempGrab.pointerMode = GrabModeAsync;
+ tempGrab.confineTo = NullWindow;
+ tempGrab.cursor = NullCursor;
+ tempGrab.next = NULL;
+ (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
+ }
+}
+
+static Mask
+DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
+{
+ InputClientsPtr other;
+
+ if (!wOtherInputMasks(pWin))
+ return 0;
+ for (other = wOtherInputMasks(pWin)->inputClients; other;
+ other = other->next) {
+ if (SameClient(other, client))
+ return other->mask[dev->id];
+ }
+ return 0;
+}
+
+void
+MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
+{
+ WindowPtr pWin;
+ GrabPtr grab = dev->deviceGrab.grab;
+
+ pWin = dev->valuator->motionHintWindow;
+
+ if ((grab && SameClient(grab, client) &&
+ ((grab->eventMask & DevicePointerMotionHintMask) ||
+ (grab->ownerEvents &&
+ (DeviceEventMaskForClient(dev, pWin, client) &
+ DevicePointerMotionHintMask)))) ||
+ (!grab &&
+ (DeviceEventMaskForClient(dev, pWin, client) &
+ DevicePointerMotionHintMask)))
+ dev->valuator->motionHintWindow = NullWindow;
+}
+
+int
+DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
+ int maskndx)
+{
+ struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
+
+ if (mask & ~PropagateMask[maskndx]) {
+ client->errorValue = mask;
+ return BadValue;
+ }
+
+ if (mask == 0) {
+ if (inputMasks)
+ inputMasks->dontPropagateMask[maskndx] = mask;
+ } else {
+ if (!inputMasks)
+ AddExtensionClient(pWin, client, 0, 0);
+ inputMasks = wOtherInputMasks(pWin);
+ inputMasks->dontPropagateMask[maskndx] = mask;
+ }
+ RecalculateDeviceDeliverableEvents(pWin);
+ if (ShouldFreeInputMasks(pWin, FALSE))
+ FreeResource(inputMasks->inputClients->resource, RT_NONE);
+ return Success;
+}
+
+Bool
+ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
+{
+ int i;
+ Mask allInputEventMasks = 0;
+ struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
+
+ for (i = 0; i < EMASKSIZE; i++)
+ allInputEventMasks |= inputMasks->dontPropagateMask[i];
+ if (!ignoreSelectedEvents)
+ for (i = 0; i < EMASKSIZE; i++)
+ allInputEventMasks |= inputMasks->inputEvents[i];
+ if (allInputEventMasks == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/***********************************************************************
+ *
+ * Walk through the window tree, finding all clients that want to know
+ * about the Event.
+ *
+ */
+
+static void
+FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
+ xEvent * ev, int count)
+{
+ WindowPtr p2;
+
+ while (p1) {
+ p2 = p1->firstChild;
+ DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
+ FindInterestedChildren(dev, p2, mask, ev, count);
+ p1 = p1->nextSib;
+ }
+}
+
+/***********************************************************************
+ *
+ * Send an event to interested clients in all windows on all screens.
+ *
+ */
+
+void
+SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
+{
+ int i;
+ WindowPtr pWin, p1;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pWin = screenInfo.screens[i]->root;
+ if (!pWin)
+ continue;
+ DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
+ p1 = pWin->firstChild;
+ FindInterestedChildren(dev, p1, mask, ev, count);
+ }
+}
+
+/**
+ * Set the XI2 mask for the given client on the given window.
+ * @param dev The device to set the mask for.
+ * @param win The window to set the mask on.
+ * @param client The client setting the mask.
+ * @param len Number of bytes in mask.
+ * @param mask Event mask in the form of (1 << eventtype)
+ */
+int
+XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
+ unsigned int len, unsigned char* mask)
+{
+ OtherInputMasks *masks;
+ InputClientsPtr others = NULL;
+
+ masks = wOtherInputMasks(win);
+ if (masks)
+ {
+ for (others = wOtherInputMasks(win)->inputClients; others;
+ others = others->next) {
+ if (SameClient(others, client)) {
+ memset(others->xi2mask[dev->id], 0,
+ sizeof(others->xi2mask[dev->id]));
+ break;
+ }
+ }
+ }
+
+ len = min(len, sizeof(others->xi2mask[dev->id]));
+
+ if (len && !others)
+ {
+ if (AddExtensionClient(win, client, 0, 0) != Success)
+ return BadAlloc;
+ others= wOtherInputMasks(win)->inputClients;
+ }
+
+ if (others)
+ memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
+
+ if (len)
+ memcpy(others->xi2mask[dev->id], mask, len);
+
+ RecalculateDeviceDeliverableEvents(win);
+
+ return Success;
+}
diff --git a/xorg-server/Xi/extinit.c b/xorg-server/Xi/extinit.c
index a6408fbb3..82df7eb02 100644
--- a/xorg-server/Xi/extinit.c
+++ b/xorg-server/Xi/extinit.c
@@ -1,1308 +1,1309 @@
-/************************************************************
-
-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.
-
-Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
-
- 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 Hewlett-Packard not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-HEWLETT-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.
-
-********************************************************/
-
-/********************************************************************
- *
- * Dispatch routines and initialization routines for the X input extension.
- *
- */
-
-#define NUMTYPES 15
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h"
-#include "gcstruct.h" /* pointer for extnsionst.h */
-#include "extnsionst.h" /* extension entry */
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include <X11/extensions/XI2proto.h>
-#include <X11/extensions/geproto.h>
-#include "geext.h" /* extension interfaces for ge */
-
-#include "dixevents.h"
-#include "exevents.h"
-#include "extinit.h"
-#include "exglobals.h"
-#include "swaprep.h"
-#include "privates.h"
-#include "protocol-versions.h"
-
-/* modules local to Xi */
-#include "allowev.h"
-#include "chgdctl.h"
-#include "chgfctl.h"
-#include "chgkbd.h"
-#include "chgprop.h"
-#include "chgptr.h"
-#include "closedev.h"
-#include "devbell.h"
-#include "getbmap.h"
-#include "getbmap.h"
-#include "getdctl.h"
-#include "getfctl.h"
-#include "getfocus.h"
-#include "getkmap.h"
-#include "getmmap.h"
-#include "getprop.h"
-#include "getselev.h"
-#include "getvers.h"
-#include "getvers.h"
-#include "grabdev.h"
-#include "grabdevb.h"
-#include "grabdevk.h"
-#include "gtmotion.h"
-#include "listdev.h"
-#include "opendev.h"
-#include "queryst.h"
-#include "selectev.h"
-#include "sendexev.h"
-#include "chgkmap.h"
-#include "setbmap.h"
-#include "setdval.h"
-#include "setfocus.h"
-#include "setmmap.h"
-#include "setmode.h"
-#include "ungrdev.h"
-#include "ungrdevb.h"
-#include "ungrdevk.h"
-#include "xiallowev.h"
-#include "xiselectev.h"
-#include "xigrabdev.h"
-#include "xipassivegrab.h"
-#include "xisetdevfocus.h"
-#include "xiproperty.h"
-#include "xichangecursor.h"
-#include "xichangehierarchy.h"
-#include "xigetclientpointer.h"
-#include "xiquerydevice.h"
-#include "xiquerypointer.h"
-#include "xiqueryversion.h"
-#include "xisetclientpointer.h"
-#include "xiwarppointer.h"
-
-
-/* Masks for XI events have to be aligned with core event (partially anyway).
- * If DeviceButtonMotionMask is != ButtonMotionMask, event delivery
- * breaks down. The device needs the dev->button->motionMask. If DBMM is
- * the same as BMM, we can ensure that both core and device events can be
- * delivered, without the need for extra structures in the DeviceIntRec. */
-const Mask DeviceKeyPressMask = KeyPressMask;
-const Mask DeviceKeyReleaseMask = KeyReleaseMask;
-const Mask DeviceButtonPressMask = ButtonPressMask;
-const Mask DeviceButtonReleaseMask = ButtonReleaseMask;
-const Mask DeviceProximityMask = (1L << 4);
-const Mask DeviceStateNotifyMask = (1L << 5);
-const Mask DevicePointerMotionMask = PointerMotionMask;
-const Mask DevicePointerMotionHintMask = PointerMotionHintMask;
-const Mask DeviceButton1MotionMask = Button1MotionMask;
-const Mask DeviceButton2MotionMask = Button2MotionMask;
-const Mask DeviceButton3MotionMask = Button3MotionMask;
-const Mask DeviceButton4MotionMask = Button4MotionMask;
-const Mask DeviceButton5MotionMask = Button5MotionMask;
-const Mask DeviceButtonMotionMask = ButtonMotionMask;
-const Mask DeviceFocusChangeMask = (1L << 14);
-const Mask DeviceMappingNotifyMask = (1L << 15);
-const Mask ChangeDeviceNotifyMask = (1L << 16);
-const Mask DeviceButtonGrabMask = (1L << 17);
-const Mask DeviceOwnerGrabButtonMask = (1L << 17);
-const Mask DevicePresenceNotifyMask = (1L << 18);
-const Mask DeviceEnterWindowMask = (1L << 18);
-const Mask DeviceLeaveWindowMask = (1L << 19);
-const Mask DevicePropertyNotifyMask = (1L << 20);
-const Mask XIAllMasks = (1L << 21) - 1;
-
-int ExtEventIndex;
-Mask ExtExclusiveMasks[EMASKSIZE];
-
-static struct dev_type
-{
- Atom type;
- char *name;
-} dev_type[] = {
- {
- 0, XI_KEYBOARD}, {
- 0, XI_MOUSE}, {
- 0, XI_TABLET}, {
- 0, XI_TOUCHSCREEN}, {
- 0, XI_TOUCHPAD}, {
- 0, XI_BARCODE}, {
- 0, XI_BUTTONBOX}, {
- 0, XI_KNOB_BOX}, {
- 0, XI_ONE_KNOB}, {
- 0, XI_NINE_KNOB}, {
- 0, XI_TRACKBALL}, {
- 0, XI_QUADRATURE}, {
- 0, XI_ID_MODULE}, {
- 0, XI_SPACEBALL}, {
- 0, XI_DATAGLOVE}, {
- 0, XI_EYETRACKER}, {
- 0, XI_CURSORKEYS}, {
-0, XI_FOOTMOUSE}};
-
-CARD8 event_base[numInputClasses];
-XExtEventInfo EventInfo[32];
-
-static DeviceIntRec xi_all_devices;
-static DeviceIntRec xi_all_master_devices;
-
-/**
- * Dispatch vector. Functions defined in here will be called when the matching
- * request arrives.
- */
-static int (*ProcIVector[])(ClientPtr) = {
- NULL, /* 0 */
- ProcXGetExtensionVersion, /* 1 */
- ProcXListInputDevices, /* 2 */
- ProcXOpenDevice, /* 3 */
- ProcXCloseDevice, /* 4 */
- ProcXSetDeviceMode, /* 5 */
- ProcXSelectExtensionEvent, /* 6 */
- ProcXGetSelectedExtensionEvents, /* 7 */
- ProcXChangeDeviceDontPropagateList, /* 8 */
- ProcXGetDeviceDontPropagateList, /* 9 */
- ProcXGetDeviceMotionEvents, /* 10 */
- ProcXChangeKeyboardDevice, /* 11 */
- ProcXChangePointerDevice, /* 12 */
- ProcXGrabDevice, /* 13 */
- ProcXUngrabDevice, /* 14 */
- ProcXGrabDeviceKey, /* 15 */
- ProcXUngrabDeviceKey, /* 16 */
- ProcXGrabDeviceButton, /* 17 */
- ProcXUngrabDeviceButton, /* 18 */
- ProcXAllowDeviceEvents, /* 19 */
- ProcXGetDeviceFocus, /* 20 */
- ProcXSetDeviceFocus, /* 21 */
- ProcXGetFeedbackControl, /* 22 */
- ProcXChangeFeedbackControl, /* 23 */
- ProcXGetDeviceKeyMapping, /* 24 */
- ProcXChangeDeviceKeyMapping, /* 25 */
- ProcXGetDeviceModifierMapping, /* 26 */
- ProcXSetDeviceModifierMapping, /* 27 */
- ProcXGetDeviceButtonMapping, /* 28 */
- ProcXSetDeviceButtonMapping, /* 29 */
- ProcXQueryDeviceState, /* 30 */
- ProcXSendExtensionEvent, /* 31 */
- ProcXDeviceBell, /* 32 */
- ProcXSetDeviceValuators, /* 33 */
- ProcXGetDeviceControl, /* 34 */
- ProcXChangeDeviceControl, /* 35 */
- /* XI 1.5 */
- ProcXListDeviceProperties, /* 36 */
- ProcXChangeDeviceProperty, /* 37 */
- ProcXDeleteDeviceProperty, /* 38 */
- ProcXGetDeviceProperty, /* 39 */
- /* XI 2 */
- ProcXIQueryPointer, /* 40 */
- ProcXIWarpPointer, /* 41 */
- ProcXIChangeCursor, /* 42 */
- ProcXIChangeHierarchy, /* 43 */
- ProcXISetClientPointer, /* 44 */
- ProcXIGetClientPointer, /* 45 */
- ProcXISelectEvents, /* 46 */
- ProcXIQueryVersion, /* 47 */
- ProcXIQueryDevice, /* 48 */
- ProcXISetFocus, /* 49 */
- ProcXIGetFocus, /* 50 */
- ProcXIGrabDevice, /* 51 */
- ProcXIUngrabDevice, /* 52 */
- ProcXIAllowEvents, /* 53 */
- ProcXIPassiveGrabDevice, /* 54 */
- ProcXIPassiveUngrabDevice, /* 55 */
- ProcXIListProperties, /* 56 */
- ProcXIChangeProperty, /* 57 */
- ProcXIDeleteProperty, /* 58 */
- ProcXIGetProperty, /* 59 */
- ProcXIGetSelectedEvents /* 60 */
-};
-
-/* For swapped clients */
-static int (*SProcIVector[])(ClientPtr) = {
- NULL, /* 0 */
- SProcXGetExtensionVersion, /* 1 */
- SProcXListInputDevices, /* 2 */
- SProcXOpenDevice, /* 3 */
- SProcXCloseDevice, /* 4 */
- SProcXSetDeviceMode, /* 5 */
- SProcXSelectExtensionEvent, /* 6 */
- SProcXGetSelectedExtensionEvents, /* 7 */
- SProcXChangeDeviceDontPropagateList, /* 8 */
- SProcXGetDeviceDontPropagateList, /* 9 */
- SProcXGetDeviceMotionEvents, /* 10 */
- SProcXChangeKeyboardDevice, /* 11 */
- SProcXChangePointerDevice, /* 12 */
- SProcXGrabDevice, /* 13 */
- SProcXUngrabDevice, /* 14 */
- SProcXGrabDeviceKey, /* 15 */
- SProcXUngrabDeviceKey, /* 16 */
- SProcXGrabDeviceButton, /* 17 */
- SProcXUngrabDeviceButton, /* 18 */
- SProcXAllowDeviceEvents, /* 19 */
- SProcXGetDeviceFocus, /* 20 */
- SProcXSetDeviceFocus, /* 21 */
- SProcXGetFeedbackControl, /* 22 */
- SProcXChangeFeedbackControl, /* 23 */
- SProcXGetDeviceKeyMapping, /* 24 */
- SProcXChangeDeviceKeyMapping, /* 25 */
- SProcXGetDeviceModifierMapping, /* 26 */
- SProcXSetDeviceModifierMapping, /* 27 */
- SProcXGetDeviceButtonMapping, /* 28 */
- SProcXSetDeviceButtonMapping, /* 29 */
- SProcXQueryDeviceState, /* 30 */
- SProcXSendExtensionEvent, /* 31 */
- SProcXDeviceBell, /* 32 */
- SProcXSetDeviceValuators, /* 33 */
- SProcXGetDeviceControl, /* 34 */
- SProcXChangeDeviceControl, /* 35 */
- SProcXListDeviceProperties, /* 36 */
- SProcXChangeDeviceProperty, /* 37 */
- SProcXDeleteDeviceProperty, /* 38 */
- SProcXGetDeviceProperty, /* 39 */
- SProcXIQueryPointer, /* 40 */
- SProcXIWarpPointer, /* 41 */
- SProcXIChangeCursor, /* 42 */
- SProcXIChangeHierarchy, /* 43 */
- SProcXISetClientPointer, /* 44 */
- SProcXIGetClientPointer, /* 45 */
- SProcXISelectEvents, /* 46 */
- SProcXIQueryVersion, /* 47 */
- SProcXIQueryDevice, /* 48 */
- SProcXISetFocus, /* 49 */
- SProcXIGetFocus, /* 50 */
- SProcXIGrabDevice, /* 51 */
- SProcXIUngrabDevice, /* 52 */
- SProcXIAllowEvents, /* 53 */
- SProcXIPassiveGrabDevice, /* 54 */
- SProcXIPassiveUngrabDevice, /* 55 */
- SProcXIListProperties, /* 56 */
- SProcXIChangeProperty, /* 57 */
- SProcXIDeleteProperty, /* 58 */
- SProcXIGetProperty, /* 59 */
- SProcXIGetSelectedEvents /* 60 */
-};
-
-/*****************************************************************
- *
- * Globals referenced elsewhere in the server.
- *
- */
-
-int IReqCode = 0;
-int IEventBase = 0;
-int BadDevice = 0;
-static int BadEvent = 1;
-int BadMode = 2;
-int DeviceBusy = 3;
-int BadClass = 4;
-
-int DeviceValuator;
-int DeviceKeyPress;
-int DeviceKeyRelease;
-int DeviceButtonPress;
-int DeviceButtonRelease;
-int DeviceMotionNotify;
-int DeviceFocusIn;
-int DeviceFocusOut;
-int ProximityIn;
-int ProximityOut;
-int DeviceStateNotify;
-int DeviceKeyStateNotify;
-int DeviceButtonStateNotify;
-int DeviceMappingNotify;
-int ChangeDeviceNotify;
-int DevicePresenceNotify;
-int DevicePropertyNotify;
-
-int RT_INPUTCLIENT;
-
-/*****************************************************************
- *
- * Externs defined elsewhere in the X server.
- *
- */
-
-extern XExtensionVersion XIVersion;
-
-
-Mask PropagateMask[MAXDEVICES];
-
-/*****************************************************************
- *
- * Versioning support
- *
- */
-
-DevPrivateKeyRec XIClientPrivateKeyRec;
-
-/*****************************************************************
- *
- * Declarations of local routines.
- *
- */
-
-static void
-XIClientCallback(CallbackListPtr *list,
- pointer closure,
- pointer data)
-{
- NewClientInfoRec *clientinfo = (NewClientInfoRec*)data;
- ClientPtr pClient = clientinfo->client;
- XIClientPtr pXIClient;
-
- pXIClient = dixLookupPrivate(&pClient->devPrivates, XIClientPrivateKey);
- pXIClient->major_version = 0;
- pXIClient->minor_version = 0;
-}
-
-/*************************************************************************
- *
- * ProcIDispatch - main dispatch routine for requests to this extension.
- * This routine is used if server and client have the same byte ordering.
- *
- */
-
-static int
-ProcIDispatch(ClientPtr client)
-{
- REQUEST(xReq);
- if (stuff->data > (IREQUESTS + XI2REQUESTS) || !ProcIVector[stuff->data])
- return BadRequest;
-
- return (*ProcIVector[stuff->data])(client);
-}
-
-/*******************************************************************************
- *
- * SProcXDispatch
- *
- * Main swapped dispatch routine for requests to this extension.
- * This routine is used if server and client do not have the same byte ordering.
- *
- */
-
-static int
-SProcIDispatch(ClientPtr client)
-{
- REQUEST(xReq);
- if (stuff->data > IREQUESTS || !SProcIVector[stuff->data])
- return BadRequest;
-
- return (*SProcIVector[stuff->data])(client);
-}
-
-/**********************************************************************
- *
- * SReplyIDispatch
- * Swap any replies defined in this extension.
- *
- */
-
-static void
-SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
- /* All we look at is the type field */
-{ /* This is common to all replies */
- if (rep->RepType == X_GetExtensionVersion)
- SRepXGetExtensionVersion(client, len,
- (xGetExtensionVersionReply *) rep);
- else if (rep->RepType == X_ListInputDevices)
- SRepXListInputDevices(client, len, (xListInputDevicesReply *) rep);
- else if (rep->RepType == X_OpenDevice)
- SRepXOpenDevice(client, len, (xOpenDeviceReply *) rep);
- else if (rep->RepType == X_SetDeviceMode)
- SRepXSetDeviceMode(client, len, (xSetDeviceModeReply *) rep);
- else if (rep->RepType == X_GetSelectedExtensionEvents)
- SRepXGetSelectedExtensionEvents(client, len,
- (xGetSelectedExtensionEventsReply *)
- rep);
- else if (rep->RepType == X_GetDeviceDontPropagateList)
- SRepXGetDeviceDontPropagateList(client, len,
- (xGetDeviceDontPropagateListReply *)
- rep);
- else if (rep->RepType == X_GetDeviceMotionEvents)
- SRepXGetDeviceMotionEvents(client, len,
- (xGetDeviceMotionEventsReply *) rep);
- else if (rep->RepType == X_GrabDevice)
- SRepXGrabDevice(client, len, (xGrabDeviceReply *) rep);
- else if (rep->RepType == X_GetDeviceFocus)
- SRepXGetDeviceFocus(client, len, (xGetDeviceFocusReply *) rep);
- else if (rep->RepType == X_GetFeedbackControl)
- SRepXGetFeedbackControl(client, len, (xGetFeedbackControlReply *) rep);
- else if (rep->RepType == X_GetDeviceKeyMapping)
- SRepXGetDeviceKeyMapping(client, len,
- (xGetDeviceKeyMappingReply *) rep);
- else if (rep->RepType == X_GetDeviceModifierMapping)
- SRepXGetDeviceModifierMapping(client, len,
- (xGetDeviceModifierMappingReply *) rep);
- else if (rep->RepType == X_SetDeviceModifierMapping)
- SRepXSetDeviceModifierMapping(client, len,
- (xSetDeviceModifierMappingReply *) rep);
- else if (rep->RepType == X_GetDeviceButtonMapping)
- SRepXGetDeviceButtonMapping(client, len,
- (xGetDeviceButtonMappingReply *) rep);
- else if (rep->RepType == X_SetDeviceButtonMapping)
- SRepXSetDeviceButtonMapping(client, len,
- (xSetDeviceButtonMappingReply *) rep);
- else if (rep->RepType == X_QueryDeviceState)
- SRepXQueryDeviceState(client, len, (xQueryDeviceStateReply *) rep);
- else if (rep->RepType == X_SetDeviceValuators)
- SRepXSetDeviceValuators(client, len, (xSetDeviceValuatorsReply *) rep);
- else if (rep->RepType == X_GetDeviceControl)
- SRepXGetDeviceControl(client, len, (xGetDeviceControlReply *) rep);
- else if (rep->RepType == X_ChangeDeviceControl)
- SRepXChangeDeviceControl(client, len,
- (xChangeDeviceControlReply *) rep);
- else if (rep->RepType == X_ListDeviceProperties)
- SRepXListDeviceProperties(client, len, (xListDevicePropertiesReply*)rep);
- else if (rep->RepType == X_GetDeviceProperty)
- SRepXGetDeviceProperty(client, len, (xGetDevicePropertyReply *) rep);
- else if (rep->RepType == X_XIQueryPointer)
- SRepXIQueryPointer(client, len, (xXIQueryPointerReply *) rep);
- else if (rep->RepType == X_XIGetClientPointer)
- SRepXIGetClientPointer(client, len, (xXIGetClientPointerReply*) rep);
- else if (rep->RepType == X_XIQueryVersion)
- SRepXIQueryVersion(client, len, (xXIQueryVersionReply*)rep);
- else if (rep->RepType == X_XIQueryDevice)
- SRepXIQueryDevice(client, len, (xXIQueryDeviceReply*)rep);
- else if (rep->RepType == X_XIGrabDevice)
- SRepXIGrabDevice(client, len, (xXIGrabDeviceReply *) rep);
- else if (rep->RepType == X_XIGrabDevice)
- SRepXIPassiveGrabDevice(client, len, (xXIPassiveGrabDeviceReply *) rep);
- else if (rep->RepType == X_XIListProperties)
- SRepXIListProperties(client, len, (xXIListPropertiesReply *) rep);
- else if (rep->RepType == X_XIGetProperty)
- SRepXIGetProperty(client, len, (xXIGetPropertyReply *) rep);
- else if (rep->RepType == X_XIGetSelectedEvents)
- SRepXIGetSelectedEvents(client, len, (xXIGetSelectedEventsReply *) rep);
- else if (rep->RepType == X_XIGetFocus)
- SRepXIGetFocus(client, len, (xXIGetFocusReply *) rep);
- else {
- FatalError("XINPUT confused sending swapped reply");
- }
-}
-
-/************************************************************************
- *
- * This function swaps the DeviceValuator event.
- *
- */
-
-static void
-SEventDeviceValuator(deviceValuator * from, deviceValuator * to)
-{
- char n;
- int i;
- INT32 *ip B32;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swaps(&to->device_state, n);
- ip = &to->valuator0;
- for (i = 0; i < 6; i++) {
- swapl((ip + i), n); /* macro - braces are required */
- }
-}
-
-static void
-SEventFocus(deviceFocus * from, deviceFocus * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->time, n);
- swapl(&to->window, n);
-}
-
-static void
-SDeviceStateNotifyEvent(deviceStateNotify * from, deviceStateNotify * to)
-{
- int i;
- char n;
- INT32 *ip B32;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->time, n);
- ip = &to->valuator0;
- for (i = 0; i < 3; i++) {
- swapl((ip + i), n); /* macro - braces are required */
- }
-}
-
-static void
-SDeviceKeyStateNotifyEvent(deviceKeyStateNotify * from,
- deviceKeyStateNotify * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
-}
-
-static void
-SDeviceButtonStateNotifyEvent(deviceButtonStateNotify * from,
- deviceButtonStateNotify * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
-}
-
-static void
-SChangeDeviceNotifyEvent(changeDeviceNotify * from, changeDeviceNotify * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->time, n);
-}
-
-static void
-SDeviceMappingNotifyEvent(deviceMappingNotify * from, deviceMappingNotify * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->time, n);
-}
-
-static void
-SDevicePresenceNotifyEvent (devicePresenceNotify *from, devicePresenceNotify *to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber,n);
- swapl(&to->time, n);
- swaps(&to->control, n);
-}
-
-static void
-SDevicePropertyNotifyEvent (devicePropertyNotify *from, devicePropertyNotify *to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber,n);
- swapl(&to->time, n);
- swapl(&to->atom, n);
-}
-
-static void
-SDeviceLeaveNotifyEvent (xXILeaveEvent *from, xXILeaveEvent *to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber,n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swapl(&to->root, n);
- swapl(&to->event, n);
- swapl(&to->child, n);
- swapl(&to->root_x, n);
- swapl(&to->root_y, n);
- swapl(&to->event_x, n);
- swapl(&to->event_y, n);
- swaps(&to->sourceid, n);
- swaps(&to->buttons_len, n);
- swapl(&to->mods.base_mods, n);
- swapl(&to->mods.latched_mods, n);
- swapl(&to->mods.locked_mods, n);
-}
-
-static void
-SDeviceChangedEvent(xXIDeviceChangedEvent* from, xXIDeviceChangedEvent* to)
-{
- char n;
- int i, j;
- xXIAnyInfo *any;
-
- *to = *from;
- memcpy(&to[1], &from[1], from->length * 4);
-
- any = (xXIAnyInfo*)&to[1];
- for (i = 0; i < to->num_classes; i++)
- {
- int length = any->length;
-
- switch(any->type)
- {
- case KeyClass:
- {
- xXIKeyInfo *ki = (xXIKeyInfo*)any;
- uint32_t *key = (uint32_t*)&ki[1];
- for (j = 0; j < ki->num_keycodes; j++, key++)
- swapl(key, n);
- swaps(&ki->num_keycodes, n);
- }
- break;
- case ButtonClass:
- {
- xXIButtonInfo *bi = (xXIButtonInfo*)any;
- Atom *labels = (Atom*)((char*)bi + sizeof(xXIButtonInfo) +
- pad_to_int32(bits_to_bytes(bi->num_buttons)));
- for (j = 0; j < bi->num_buttons; j++)
- swapl(&labels[j], n);
- swaps(&bi->num_buttons, n);
- }
- break;
- case ValuatorClass:
- {
- xXIValuatorInfo* ai = (xXIValuatorInfo*)any;
- swapl(&ai->label, n);
- swapl(&ai->min.integral, n);
- swapl(&ai->min.frac, n);
- swapl(&ai->max.integral, n);
- swapl(&ai->max.frac, n);
- swapl(&ai->resolution, n);
- swaps(&ai->number, n);
- }
- break;
- }
-
- swaps(&any->type, n);
- swaps(&any->length, n);
- swaps(&any->sourceid, n);
-
- any = (xXIAnyInfo*)((char*)any + length * 4);
- }
-
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swaps(&to->num_classes, n);
- swaps(&to->sourceid, n);
-
-}
-
-static void SDeviceEvent(xXIDeviceEvent *from, xXIDeviceEvent *to)
-{
- int i;
- char n;
- char *ptr;
- char *vmask;
-
- memcpy(to, from, sizeof(xEvent) + from->length * 4);
-
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swapl(&to->detail, n);
- swapl(&to->root, n);
- swapl(&to->event, n);
- swapl(&to->child, n);
- swapl(&to->root_x, n);
- swapl(&to->root_y, n);
- swapl(&to->event_x, n);
- swapl(&to->event_y, n);
- swaps(&to->buttons_len, n);
- swaps(&to->valuators_len, n);
- swaps(&to->sourceid, n);
- swapl(&to->mods.base_mods, n);
- swapl(&to->mods.latched_mods, n);
- swapl(&to->mods.locked_mods, n);
- swapl(&to->mods.effective_mods, n);
-
- ptr = (char*)(&to[1]);
- ptr += from->buttons_len * 4;
- vmask = ptr; /* valuator mask */
- ptr += from->valuators_len * 4;
- for (i = 0; i < from->valuators_len * 32; i++)
- {
- if (BitIsOn(vmask, i))
- {
- swapl(((uint32_t*)ptr), n);
- ptr += 4;
- swapl(((uint32_t*)ptr), n);
- ptr += 4;
- }
- }
-}
-
-static void SDeviceHierarchyEvent(xXIHierarchyEvent *from,
- xXIHierarchyEvent *to)
-{
- int i;
- char n;
- xXIHierarchyInfo *info;
-
- *to = *from;
- memcpy(&to[1], &from[1], from->length * 4);
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swapl(&to->flags, n);
- swaps(&to->num_info, n);
-
- info = (xXIHierarchyInfo*)&to[1];
- for (i = 0; i< from->num_info; i++)
- {
- swaps(&info->deviceid, n);
- swaps(&info->attachment, n);
- info++;
- }
-}
-
-static void SXIPropertyEvent(xXIPropertyEvent *from, xXIPropertyEvent *to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->property, n);
-}
-
-static void SRawEvent(xXIRawEvent *from, xXIRawEvent *to)
-{
- char n;
- int i;
- FP3232 *values;
- unsigned char *mask;
-
- memcpy(to, from, sizeof(xEvent) + from->length * 4);
-
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swapl(&to->detail, n);
-
-
- mask = (unsigned char*)&to[1];
- values = (FP3232*)(mask + from->valuators_len * 4);
-
- for (i = 0; i < from->valuators_len * 4 * 8; i++)
- {
- if (BitIsOn(mask, i))
- {
- /* for each bit set there are two FP3232 values on the wire, in
- * the order abcABC for data and data_raw. Here we swap as if
- * they were in aAbBcC order because it's easier and really
- * doesn't matter.
- */
- swapl(&values->integral, n);
- swapl(&values->frac, n);
- values++;
- swapl(&values->integral, n);
- swapl(&values->frac, n);
- values++;
- }
- }
-
- swaps(&to->valuators_len, n);
-}
-
-
-/** Event swapping function for XI2 events. */
-void
-XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
-{
- switch(from->evtype)
- {
- case XI_Enter:
- case XI_Leave:
- SDeviceLeaveNotifyEvent((xXILeaveEvent*)from, (xXILeaveEvent*)to);
- break;
- case XI_DeviceChanged:
- SDeviceChangedEvent((xXIDeviceChangedEvent*)from,
- (xXIDeviceChangedEvent*)to);
- break;
- case XI_HierarchyChanged:
- SDeviceHierarchyEvent((xXIHierarchyEvent*)from, (xXIHierarchyEvent*)to);
- break;
- case XI_PropertyEvent:
- SXIPropertyEvent((xXIPropertyEvent*)from,
- (xXIPropertyEvent*)to);
- break;
- case XI_Motion:
- case XI_KeyPress:
- case XI_KeyRelease:
- case XI_ButtonPress:
- case XI_ButtonRelease:
- SDeviceEvent((xXIDeviceEvent*)from, (xXIDeviceEvent*)to);
- break;
- case XI_RawMotion:
- case XI_RawKeyPress:
- case XI_RawKeyRelease:
- case XI_RawButtonPress:
- case XI_RawButtonRelease:
- SRawEvent((xXIRawEvent*)from, (xXIRawEvent*)to);
- break;
- default:
- ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
- break;
- }
-}
-
-/**************************************************************************
- *
- * Allow the specified event to have its propagation suppressed.
- * The default is to not allow suppression of propagation.
- *
- */
-
-static void
-AllowPropagateSuppress(Mask mask)
-{
- int i;
-
- for (i = 0; i < MAXDEVICES; i++)
- PropagateMask[i] |= mask;
-}
-
-/**************************************************************************
- *
- * Record an event mask where there is no unique corresponding event type.
- * We can't call SetMaskForEvent, since that would clobber the existing
- * mask for that event. MotionHint and ButtonMotion are examples.
- *
- * Since extension event types will never be less than 64, we can use
- * 0-63 in the EventInfo array as the "type" to be used to look up this
- * mask. This means that the corresponding macros such as
- * DevicePointerMotionHint must have access to the same constants.
- *
- */
-
-static void
-SetEventInfo(Mask mask, int constant)
-{
- EventInfo[ExtEventIndex].mask = mask;
- EventInfo[ExtEventIndex++].type = constant;
-}
-
-/**************************************************************************
- *
- * Allow the specified event to be restricted to being selected by one
- * client at a time.
- * The default is to allow more than one client to select the event.
- *
- */
-
-static void
-SetExclusiveAccess(Mask mask)
-{
- int i;
-
- for (i = 0; i < MAXDEVICES; i++)
- ExtExclusiveMasks[i] |= mask;
-}
-
-/**************************************************************************
- *
- * Assign the specified mask to the specified event.
- *
- */
-
-static void
-SetMaskForExtEvent(Mask mask, int event)
-{
- int i;
-
- EventInfo[ExtEventIndex].mask = mask;
- EventInfo[ExtEventIndex++].type = event;
-
- if ((event < LASTEvent) || (event >= 128))
- FatalError("MaskForExtensionEvent: bogus event number");
-
- for (i = 0; i < MAXDEVICES; i++)
- SetMaskForEvent(i, mask, event);
-}
-
-/************************************************************************
- *
- * This function sets up extension event types and masks.
- *
- */
-
-static void
-FixExtensionEvents(ExtensionEntry * extEntry)
-{
- DeviceValuator = extEntry->eventBase;
- DeviceKeyPress = DeviceValuator + 1;
- DeviceKeyRelease = DeviceKeyPress + 1;
- DeviceButtonPress = DeviceKeyRelease + 1;
- DeviceButtonRelease = DeviceButtonPress + 1;
- DeviceMotionNotify = DeviceButtonRelease + 1;
- DeviceFocusIn = DeviceMotionNotify + 1;
- DeviceFocusOut = DeviceFocusIn + 1;
- ProximityIn = DeviceFocusOut + 1;
- ProximityOut = ProximityIn + 1;
- DeviceStateNotify = ProximityOut + 1;
- DeviceMappingNotify = DeviceStateNotify + 1;
- ChangeDeviceNotify = DeviceMappingNotify + 1;
- DeviceKeyStateNotify = ChangeDeviceNotify + 1;
- DeviceButtonStateNotify = DeviceKeyStateNotify + 1;
- DevicePresenceNotify = DeviceButtonStateNotify + 1;
- DevicePropertyNotify = DevicePresenceNotify + 1;
-
- event_base[KeyClass] = DeviceKeyPress;
- event_base[ButtonClass] = DeviceButtonPress;
- event_base[ValuatorClass] = DeviceMotionNotify;
- event_base[ProximityClass] = ProximityIn;
- event_base[FocusClass] = DeviceFocusIn;
- event_base[OtherClass] = DeviceStateNotify;
-
- BadDevice += extEntry->errorBase;
- BadEvent += extEntry->errorBase;
- BadMode += extEntry->errorBase;
- DeviceBusy += extEntry->errorBase;
- BadClass += extEntry->errorBase;
-
- SetMaskForExtEvent(DeviceKeyPressMask, DeviceKeyPress);
- AllowPropagateSuppress(DeviceKeyPressMask);
- SetCriticalEvent(DeviceKeyPress);
-
- SetMaskForExtEvent(DeviceKeyReleaseMask, DeviceKeyRelease);
- AllowPropagateSuppress(DeviceKeyReleaseMask);
- SetCriticalEvent(DeviceKeyRelease);
-
- SetMaskForExtEvent(DeviceButtonPressMask, DeviceButtonPress);
- AllowPropagateSuppress(DeviceButtonPressMask);
- SetCriticalEvent(DeviceButtonPress);
-
- SetMaskForExtEvent(DeviceButtonReleaseMask, DeviceButtonRelease);
- AllowPropagateSuppress(DeviceButtonReleaseMask);
- SetCriticalEvent(DeviceButtonRelease);
-
- SetMaskForExtEvent(DeviceProximityMask, ProximityIn);
- SetMaskForExtEvent(DeviceProximityMask, ProximityOut);
-
- SetMaskForExtEvent(DeviceStateNotifyMask, DeviceStateNotify);
-
- SetMaskForExtEvent(DevicePointerMotionMask, DeviceMotionNotify);
- AllowPropagateSuppress(DevicePointerMotionMask);
- SetCriticalEvent(DeviceMotionNotify);
-
- SetEventInfo(DevicePointerMotionHintMask, _devicePointerMotionHint);
- SetEventInfo(DeviceButton1MotionMask, _deviceButton1Motion);
- SetEventInfo(DeviceButton2MotionMask, _deviceButton2Motion);
- SetEventInfo(DeviceButton3MotionMask, _deviceButton3Motion);
- SetEventInfo(DeviceButton4MotionMask, _deviceButton4Motion);
- SetEventInfo(DeviceButton5MotionMask, _deviceButton5Motion);
- SetEventInfo(DeviceButtonMotionMask, _deviceButtonMotion);
-
- SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusIn);
- SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusOut);
-
- SetMaskForExtEvent(DeviceMappingNotifyMask, DeviceMappingNotify);
- SetMaskForExtEvent(ChangeDeviceNotifyMask, ChangeDeviceNotify);
-
- SetEventInfo(DeviceButtonGrabMask, _deviceButtonGrab);
- SetExclusiveAccess(DeviceButtonGrabMask);
-
- SetEventInfo(DeviceOwnerGrabButtonMask, _deviceOwnerGrabButton);
- SetEventInfo(DevicePresenceNotifyMask, _devicePresence);
- SetMaskForExtEvent(DevicePropertyNotifyMask, DevicePropertyNotify);
-
- SetEventInfo(0, _noExtensionEvent);
-}
-
-/************************************************************************
- *
- * This function restores extension event types and masks to their
- * initial state.
- *
- */
-
-static void
-RestoreExtensionEvents(void)
-{
- int i, j;
-
- IReqCode = 0;
- IEventBase = 0;
-
- for (i = 0; i < ExtEventIndex - 1; i++) {
- if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
- {
- for (j = 0; j < MAXDEVICES; j++)
- SetMaskForEvent(j, 0, EventInfo[i].type);
- }
- EventInfo[i].mask = 0;
- EventInfo[i].type = 0;
- }
- ExtEventIndex = 0;
- DeviceValuator = 0;
- DeviceKeyPress = 1;
- DeviceKeyRelease = 2;
- DeviceButtonPress = 3;
- DeviceButtonRelease = 4;
- DeviceMotionNotify = 5;
- DeviceFocusIn = 6;
- DeviceFocusOut = 7;
- ProximityIn = 8;
- ProximityOut = 9;
- DeviceStateNotify = 10;
- DeviceMappingNotify = 11;
- ChangeDeviceNotify = 12;
- DeviceKeyStateNotify = 13;
- DeviceButtonStateNotify = 13;
- DevicePresenceNotify = 14;
- DevicePropertyNotify = 15;
-
- BadDevice = 0;
- BadEvent = 1;
- BadMode = 2;
- DeviceBusy = 3;
- BadClass = 4;
-
-}
-
-/***********************************************************************
- *
- * IResetProc.
- * Remove reply-swapping routine.
- * Remove event-swapping routine.
- *
- */
-
-static void
-IResetProc(ExtensionEntry * unused)
-{
- ReplySwapVector[IReqCode] = ReplyNotSwappd;
- EventSwapVector[DeviceValuator] = NotImplemented;
- EventSwapVector[DeviceKeyPress] = NotImplemented;
- EventSwapVector[DeviceKeyRelease] = NotImplemented;
- EventSwapVector[DeviceButtonPress] = NotImplemented;
- EventSwapVector[DeviceButtonRelease] = NotImplemented;
- EventSwapVector[DeviceMotionNotify] = NotImplemented;
- EventSwapVector[DeviceFocusIn] = NotImplemented;
- EventSwapVector[DeviceFocusOut] = NotImplemented;
- EventSwapVector[ProximityIn] = NotImplemented;
- EventSwapVector[ProximityOut] = NotImplemented;
- EventSwapVector[DeviceStateNotify] = NotImplemented;
- EventSwapVector[DeviceKeyStateNotify] = NotImplemented;
- EventSwapVector[DeviceButtonStateNotify] = NotImplemented;
- EventSwapVector[DeviceMappingNotify] = NotImplemented;
- EventSwapVector[ChangeDeviceNotify] = NotImplemented;
- EventSwapVector[DevicePresenceNotify] = NotImplemented;
- EventSwapVector[DevicePropertyNotify] = NotImplemented;
- RestoreExtensionEvents();
-}
-
-
-/***********************************************************************
- *
- * Assign an id and type to an input device.
- *
- */
-
-void
-AssignTypeAndName(DeviceIntPtr dev, Atom type, char *name)
-{
- dev->xinput_type = type;
- dev->name = strdup(name);
-}
-
-/***********************************************************************
- *
- * Make device type atoms.
- *
- */
-
-static void
-MakeDeviceTypeAtoms(void)
-{
- int i;
-
- for (i = 0; i < NUMTYPES; i++)
- dev_type[i].type =
- MakeAtom(dev_type[i].name, strlen(dev_type[i].name), 1);
-}
-
-/*****************************************************************************
- *
- * SEventIDispatch
- *
- * Swap any events defined in this extension.
- */
-#define DO_SWAP(func,type) func ((type *)from, (type *)to)
-
-static void
-SEventIDispatch(xEvent * from, xEvent * to)
-{
- int type = from->u.u.type & 0177;
-
- if (type == DeviceValuator)
- DO_SWAP(SEventDeviceValuator, deviceValuator);
- else if (type == DeviceKeyPress) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceKeyRelease) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceButtonPress) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceButtonRelease) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceMotionNotify) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceFocusIn)
- DO_SWAP(SEventFocus, deviceFocus);
- else if (type == DeviceFocusOut)
- DO_SWAP(SEventFocus, deviceFocus);
- else if (type == ProximityIn) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == ProximityOut) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceStateNotify)
- DO_SWAP(SDeviceStateNotifyEvent, deviceStateNotify);
- else if (type == DeviceKeyStateNotify)
- DO_SWAP(SDeviceKeyStateNotifyEvent, deviceKeyStateNotify);
- else if (type == DeviceButtonStateNotify)
- DO_SWAP(SDeviceButtonStateNotifyEvent, deviceButtonStateNotify);
- else if (type == DeviceMappingNotify)
- DO_SWAP(SDeviceMappingNotifyEvent, deviceMappingNotify);
- else if (type == ChangeDeviceNotify)
- DO_SWAP(SChangeDeviceNotifyEvent, changeDeviceNotify);
- else if (type == DevicePresenceNotify)
- DO_SWAP(SDevicePresenceNotifyEvent, devicePresenceNotify);
- else if (type == DevicePropertyNotify)
- DO_SWAP(SDevicePropertyNotifyEvent, devicePropertyNotify);
- else {
- FatalError("XInputExtension: Impossible event!\n");
- }
-}
-
-/**********************************************************************
- *
- * IExtensionInit - initialize the input extension.
- *
- * Called from InitExtensions in main() or from QueryExtension() if the
- * extension is dynamically loaded.
- *
- * This extension has several events and errors.
- *
- * XI is mandatory nowadays, so if we fail to init XI, we die.
- */
-
-void
-XInputExtensionInit(void)
-{
- ExtensionEntry *extEntry;
- XExtensionVersion thisversion = { XI_Present,
- SERVER_XI_MAJOR_VERSION,
- SERVER_XI_MINOR_VERSION,
- };
-
- if (!dixRegisterPrivateKey(&XIClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(XIClientRec)))
- FatalError("Cannot request private for XI.\n");
-
- if (!AddCallback(&ClientStateCallback, XIClientCallback, 0))
- FatalError("Failed to add callback to XI.\n");
-
- extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
- SProcIDispatch, IResetProc, StandardMinorOpcode);
- if (extEntry) {
- IReqCode = extEntry->base;
- IEventBase = extEntry->eventBase;
- XIVersion = thisversion;
- MakeDeviceTypeAtoms();
- RT_INPUTCLIENT = CreateNewResourceType((DeleteType) InputClientGone,
- "INPUTCLIENT");
- if (!RT_INPUTCLIENT)
- FatalError("Failed to add resource type for XI.\n");
- FixExtensionEvents(extEntry);
- ReplySwapVector[IReqCode] = (ReplySwapPtr) SReplyIDispatch;
- EventSwapVector[DeviceValuator] = SEventIDispatch;
- EventSwapVector[DeviceKeyPress] = SEventIDispatch;
- EventSwapVector[DeviceKeyRelease] = SEventIDispatch;
- EventSwapVector[DeviceButtonPress] = SEventIDispatch;
- EventSwapVector[DeviceButtonRelease] = SEventIDispatch;
- EventSwapVector[DeviceMotionNotify] = SEventIDispatch;
- EventSwapVector[DeviceFocusIn] = SEventIDispatch;
- EventSwapVector[DeviceFocusOut] = SEventIDispatch;
- EventSwapVector[ProximityIn] = SEventIDispatch;
- EventSwapVector[ProximityOut] = SEventIDispatch;
- EventSwapVector[DeviceStateNotify] = SEventIDispatch;
- EventSwapVector[DeviceKeyStateNotify] = SEventIDispatch;
- EventSwapVector[DeviceButtonStateNotify] = SEventIDispatch;
- EventSwapVector[DeviceMappingNotify] = SEventIDispatch;
- EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
- EventSwapVector[DevicePresenceNotify] = SEventIDispatch;
-
- GERegisterExtension(IReqCode, XI2EventSwap);
-
-
- memset(&xi_all_devices, 0, sizeof(xi_all_devices));
- memset(&xi_all_master_devices, 0, sizeof(xi_all_master_devices));
- xi_all_devices.id = XIAllDevices;
- xi_all_devices.name = "XIAllDevices";
- xi_all_master_devices.id = XIAllMasterDevices;
- xi_all_master_devices.name = "XIAllMasterDevices";
-
- inputInfo.all_devices = &xi_all_devices;
- inputInfo.all_master_devices = &xi_all_master_devices;
-
- XIResetProperties();
- } else {
- FatalError("IExtensionInit: AddExtensions failed\n");
- }
-}
-
+/************************************************************
+
+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.
+
+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+
+ 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 Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-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.
+
+********************************************************/
+
+/********************************************************************
+ *
+ * Dispatch routines and initialization routines for the X input extension.
+ *
+ */
+
+#define NUMTYPES 15
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "inputstr.h"
+#include "gcstruct.h" /* pointer for extnsionst.h */
+#include "extnsionst.h" /* extension entry */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI2proto.h>
+#include <X11/extensions/geproto.h>
+#include "geext.h" /* extension interfaces for ge */
+
+#include "dixevents.h"
+#include "exevents.h"
+#include "extinit.h"
+#include "exglobals.h"
+#include "swaprep.h"
+#include "privates.h"
+#include "protocol-versions.h"
+
+/* modules local to Xi */
+#include "allowev.h"
+#include "chgdctl.h"
+#include "chgfctl.h"
+#include "chgkbd.h"
+#include "chgprop.h"
+#include "chgptr.h"
+#include "closedev.h"
+#include "devbell.h"
+#include "getbmap.h"
+#include "getbmap.h"
+#include "getdctl.h"
+#include "getfctl.h"
+#include "getfocus.h"
+#include "getkmap.h"
+#include "getmmap.h"
+#include "getprop.h"
+#include "getselev.h"
+#include "getvers.h"
+#include "getvers.h"
+#include "grabdev.h"
+#include "grabdevb.h"
+#include "grabdevk.h"
+#include "gtmotion.h"
+#include "listdev.h"
+#include "opendev.h"
+#include "queryst.h"
+#include "selectev.h"
+#include "sendexev.h"
+#include "chgkmap.h"
+#include "setbmap.h"
+#include "setdval.h"
+#include "setfocus.h"
+#include "setmmap.h"
+#include "setmode.h"
+#include "ungrdev.h"
+#include "ungrdevb.h"
+#include "ungrdevk.h"
+#include "xiallowev.h"
+#include "xiselectev.h"
+#include "xigrabdev.h"
+#include "xipassivegrab.h"
+#include "xisetdevfocus.h"
+#include "xiproperty.h"
+#include "xichangecursor.h"
+#include "xichangehierarchy.h"
+#include "xigetclientpointer.h"
+#include "xiquerydevice.h"
+#include "xiquerypointer.h"
+#include "xiqueryversion.h"
+#include "xisetclientpointer.h"
+#include "xiwarppointer.h"
+
+
+/* Masks for XI events have to be aligned with core event (partially anyway).
+ * If DeviceButtonMotionMask is != ButtonMotionMask, event delivery
+ * breaks down. The device needs the dev->button->motionMask. If DBMM is
+ * the same as BMM, we can ensure that both core and device events can be
+ * delivered, without the need for extra structures in the DeviceIntRec. */
+const Mask DeviceKeyPressMask = KeyPressMask;
+const Mask DeviceKeyReleaseMask = KeyReleaseMask;
+const Mask DeviceButtonPressMask = ButtonPressMask;
+const Mask DeviceButtonReleaseMask = ButtonReleaseMask;
+const Mask DeviceProximityMask = (1L << 4);
+const Mask DeviceStateNotifyMask = (1L << 5);
+const Mask DevicePointerMotionMask = PointerMotionMask;
+const Mask DevicePointerMotionHintMask = PointerMotionHintMask;
+const Mask DeviceButton1MotionMask = Button1MotionMask;
+const Mask DeviceButton2MotionMask = Button2MotionMask;
+const Mask DeviceButton3MotionMask = Button3MotionMask;
+const Mask DeviceButton4MotionMask = Button4MotionMask;
+const Mask DeviceButton5MotionMask = Button5MotionMask;
+const Mask DeviceButtonMotionMask = ButtonMotionMask;
+const Mask DeviceFocusChangeMask = (1L << 14);
+const Mask DeviceMappingNotifyMask = (1L << 15);
+const Mask ChangeDeviceNotifyMask = (1L << 16);
+const Mask DeviceButtonGrabMask = (1L << 17);
+const Mask DeviceOwnerGrabButtonMask = (1L << 17);
+const Mask DevicePresenceNotifyMask = (1L << 18);
+const Mask DeviceEnterWindowMask = (1L << 18);
+const Mask DeviceLeaveWindowMask = (1L << 19);
+const Mask DevicePropertyNotifyMask = (1L << 20);
+const Mask XIAllMasks = (1L << 21) - 1;
+
+int ExtEventIndex;
+Mask ExtExclusiveMasks[EMASKSIZE];
+
+static struct dev_type
+{
+ Atom type;
+ char *name;
+} dev_type[] = {
+ {
+ 0, XI_KEYBOARD}, {
+ 0, XI_MOUSE}, {
+ 0, XI_TABLET}, {
+ 0, XI_TOUCHSCREEN}, {
+ 0, XI_TOUCHPAD}, {
+ 0, XI_BARCODE}, {
+ 0, XI_BUTTONBOX}, {
+ 0, XI_KNOB_BOX}, {
+ 0, XI_ONE_KNOB}, {
+ 0, XI_NINE_KNOB}, {
+ 0, XI_TRACKBALL}, {
+ 0, XI_QUADRATURE}, {
+ 0, XI_ID_MODULE}, {
+ 0, XI_SPACEBALL}, {
+ 0, XI_DATAGLOVE}, {
+ 0, XI_EYETRACKER}, {
+ 0, XI_CURSORKEYS}, {
+0, XI_FOOTMOUSE}};
+
+CARD8 event_base[numInputClasses];
+XExtEventInfo EventInfo[32];
+
+static DeviceIntRec xi_all_devices;
+static DeviceIntRec xi_all_master_devices;
+
+/**
+ * Dispatch vector. Functions defined in here will be called when the matching
+ * request arrives.
+ */
+static int (*ProcIVector[])(ClientPtr) = {
+ NULL, /* 0 */
+ ProcXGetExtensionVersion, /* 1 */
+ ProcXListInputDevices, /* 2 */
+ ProcXOpenDevice, /* 3 */
+ ProcXCloseDevice, /* 4 */
+ ProcXSetDeviceMode, /* 5 */
+ ProcXSelectExtensionEvent, /* 6 */
+ ProcXGetSelectedExtensionEvents, /* 7 */
+ ProcXChangeDeviceDontPropagateList, /* 8 */
+ ProcXGetDeviceDontPropagateList, /* 9 */
+ ProcXGetDeviceMotionEvents, /* 10 */
+ ProcXChangeKeyboardDevice, /* 11 */
+ ProcXChangePointerDevice, /* 12 */
+ ProcXGrabDevice, /* 13 */
+ ProcXUngrabDevice, /* 14 */
+ ProcXGrabDeviceKey, /* 15 */
+ ProcXUngrabDeviceKey, /* 16 */
+ ProcXGrabDeviceButton, /* 17 */
+ ProcXUngrabDeviceButton, /* 18 */
+ ProcXAllowDeviceEvents, /* 19 */
+ ProcXGetDeviceFocus, /* 20 */
+ ProcXSetDeviceFocus, /* 21 */
+ ProcXGetFeedbackControl, /* 22 */
+ ProcXChangeFeedbackControl, /* 23 */
+ ProcXGetDeviceKeyMapping, /* 24 */
+ ProcXChangeDeviceKeyMapping, /* 25 */
+ ProcXGetDeviceModifierMapping, /* 26 */
+ ProcXSetDeviceModifierMapping, /* 27 */
+ ProcXGetDeviceButtonMapping, /* 28 */
+ ProcXSetDeviceButtonMapping, /* 29 */
+ ProcXQueryDeviceState, /* 30 */
+ ProcXSendExtensionEvent, /* 31 */
+ ProcXDeviceBell, /* 32 */
+ ProcXSetDeviceValuators, /* 33 */
+ ProcXGetDeviceControl, /* 34 */
+ ProcXChangeDeviceControl, /* 35 */
+ /* XI 1.5 */
+ ProcXListDeviceProperties, /* 36 */
+ ProcXChangeDeviceProperty, /* 37 */
+ ProcXDeleteDeviceProperty, /* 38 */
+ ProcXGetDeviceProperty, /* 39 */
+ /* XI 2 */
+ ProcXIQueryPointer, /* 40 */
+ ProcXIWarpPointer, /* 41 */
+ ProcXIChangeCursor, /* 42 */
+ ProcXIChangeHierarchy, /* 43 */
+ ProcXISetClientPointer, /* 44 */
+ ProcXIGetClientPointer, /* 45 */
+ ProcXISelectEvents, /* 46 */
+ ProcXIQueryVersion, /* 47 */
+ ProcXIQueryDevice, /* 48 */
+ ProcXISetFocus, /* 49 */
+ ProcXIGetFocus, /* 50 */
+ ProcXIGrabDevice, /* 51 */
+ ProcXIUngrabDevice, /* 52 */
+ ProcXIAllowEvents, /* 53 */
+ ProcXIPassiveGrabDevice, /* 54 */
+ ProcXIPassiveUngrabDevice, /* 55 */
+ ProcXIListProperties, /* 56 */
+ ProcXIChangeProperty, /* 57 */
+ ProcXIDeleteProperty, /* 58 */
+ ProcXIGetProperty, /* 59 */
+ ProcXIGetSelectedEvents /* 60 */
+};
+
+/* For swapped clients */
+static int (*SProcIVector[])(ClientPtr) = {
+ NULL, /* 0 */
+ SProcXGetExtensionVersion, /* 1 */
+ SProcXListInputDevices, /* 2 */
+ SProcXOpenDevice, /* 3 */
+ SProcXCloseDevice, /* 4 */
+ SProcXSetDeviceMode, /* 5 */
+ SProcXSelectExtensionEvent, /* 6 */
+ SProcXGetSelectedExtensionEvents, /* 7 */
+ SProcXChangeDeviceDontPropagateList, /* 8 */
+ SProcXGetDeviceDontPropagateList, /* 9 */
+ SProcXGetDeviceMotionEvents, /* 10 */
+ SProcXChangeKeyboardDevice, /* 11 */
+ SProcXChangePointerDevice, /* 12 */
+ SProcXGrabDevice, /* 13 */
+ SProcXUngrabDevice, /* 14 */
+ SProcXGrabDeviceKey, /* 15 */
+ SProcXUngrabDeviceKey, /* 16 */
+ SProcXGrabDeviceButton, /* 17 */
+ SProcXUngrabDeviceButton, /* 18 */
+ SProcXAllowDeviceEvents, /* 19 */
+ SProcXGetDeviceFocus, /* 20 */
+ SProcXSetDeviceFocus, /* 21 */
+ SProcXGetFeedbackControl, /* 22 */
+ SProcXChangeFeedbackControl, /* 23 */
+ SProcXGetDeviceKeyMapping, /* 24 */
+ SProcXChangeDeviceKeyMapping, /* 25 */
+ SProcXGetDeviceModifierMapping, /* 26 */
+ SProcXSetDeviceModifierMapping, /* 27 */
+ SProcXGetDeviceButtonMapping, /* 28 */
+ SProcXSetDeviceButtonMapping, /* 29 */
+ SProcXQueryDeviceState, /* 30 */
+ SProcXSendExtensionEvent, /* 31 */
+ SProcXDeviceBell, /* 32 */
+ SProcXSetDeviceValuators, /* 33 */
+ SProcXGetDeviceControl, /* 34 */
+ SProcXChangeDeviceControl, /* 35 */
+ SProcXListDeviceProperties, /* 36 */
+ SProcXChangeDeviceProperty, /* 37 */
+ SProcXDeleteDeviceProperty, /* 38 */
+ SProcXGetDeviceProperty, /* 39 */
+ SProcXIQueryPointer, /* 40 */
+ SProcXIWarpPointer, /* 41 */
+ SProcXIChangeCursor, /* 42 */
+ SProcXIChangeHierarchy, /* 43 */
+ SProcXISetClientPointer, /* 44 */
+ SProcXIGetClientPointer, /* 45 */
+ SProcXISelectEvents, /* 46 */
+ SProcXIQueryVersion, /* 47 */
+ SProcXIQueryDevice, /* 48 */
+ SProcXISetFocus, /* 49 */
+ SProcXIGetFocus, /* 50 */
+ SProcXIGrabDevice, /* 51 */
+ SProcXIUngrabDevice, /* 52 */
+ SProcXIAllowEvents, /* 53 */
+ SProcXIPassiveGrabDevice, /* 54 */
+ SProcXIPassiveUngrabDevice, /* 55 */
+ SProcXIListProperties, /* 56 */
+ SProcXIChangeProperty, /* 57 */
+ SProcXIDeleteProperty, /* 58 */
+ SProcXIGetProperty, /* 59 */
+ SProcXIGetSelectedEvents /* 60 */
+};
+
+/*****************************************************************
+ *
+ * Globals referenced elsewhere in the server.
+ *
+ */
+
+int IReqCode = 0;
+int IEventBase = 0;
+int BadDevice = 0;
+static int BadEvent = 1;
+int BadMode = 2;
+int DeviceBusy = 3;
+int BadClass = 4;
+
+int DeviceValuator;
+int DeviceKeyPress;
+int DeviceKeyRelease;
+int DeviceButtonPress;
+int DeviceButtonRelease;
+int DeviceMotionNotify;
+int DeviceFocusIn;
+int DeviceFocusOut;
+int ProximityIn;
+int ProximityOut;
+int DeviceStateNotify;
+int DeviceKeyStateNotify;
+int DeviceButtonStateNotify;
+int DeviceMappingNotify;
+int ChangeDeviceNotify;
+int DevicePresenceNotify;
+int DevicePropertyNotify;
+
+int RT_INPUTCLIENT;
+
+/*****************************************************************
+ *
+ * Externs defined elsewhere in the X server.
+ *
+ */
+
+extern XExtensionVersion XIVersion;
+
+
+Mask PropagateMask[MAXDEVICES];
+
+/*****************************************************************
+ *
+ * Versioning support
+ *
+ */
+
+DevPrivateKeyRec XIClientPrivateKeyRec;
+
+/*****************************************************************
+ *
+ * Declarations of local routines.
+ *
+ */
+
+static void
+XIClientCallback(CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec*)data;
+ ClientPtr pClient = clientinfo->client;
+ XIClientPtr pXIClient;
+
+ pXIClient = dixLookupPrivate(&pClient->devPrivates, XIClientPrivateKey);
+ pXIClient->major_version = 0;
+ pXIClient->minor_version = 0;
+}
+
+/*************************************************************************
+ *
+ * ProcIDispatch - main dispatch routine for requests to this extension.
+ * This routine is used if server and client have the same byte ordering.
+ *
+ */
+
+static int
+ProcIDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data > (IREQUESTS + XI2REQUESTS) || !ProcIVector[stuff->data])
+ return BadRequest;
+
+ return (*ProcIVector[stuff->data])(client);
+}
+
+/*******************************************************************************
+ *
+ * SProcXDispatch
+ *
+ * Main swapped dispatch routine for requests to this extension.
+ * This routine is used if server and client do not have the same byte ordering.
+ *
+ */
+
+static int
+SProcIDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data > IREQUESTS || !SProcIVector[stuff->data])
+ return BadRequest;
+
+ return (*SProcIVector[stuff->data])(client);
+}
+
+/**********************************************************************
+ *
+ * SReplyIDispatch
+ * Swap any replies defined in this extension.
+ *
+ */
+
+static void
+SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
+ /* All we look at is the type field */
+{ /* This is common to all replies */
+ if (rep->RepType == X_GetExtensionVersion)
+ SRepXGetExtensionVersion(client, len,
+ (xGetExtensionVersionReply *) rep);
+ else if (rep->RepType == X_ListInputDevices)
+ SRepXListInputDevices(client, len, (xListInputDevicesReply *) rep);
+ else if (rep->RepType == X_OpenDevice)
+ SRepXOpenDevice(client, len, (xOpenDeviceReply *) rep);
+ else if (rep->RepType == X_SetDeviceMode)
+ SRepXSetDeviceMode(client, len, (xSetDeviceModeReply *) rep);
+ else if (rep->RepType == X_GetSelectedExtensionEvents)
+ SRepXGetSelectedExtensionEvents(client, len,
+ (xGetSelectedExtensionEventsReply *)
+ rep);
+ else if (rep->RepType == X_GetDeviceDontPropagateList)
+ SRepXGetDeviceDontPropagateList(client, len,
+ (xGetDeviceDontPropagateListReply *)
+ rep);
+ else if (rep->RepType == X_GetDeviceMotionEvents)
+ SRepXGetDeviceMotionEvents(client, len,
+ (xGetDeviceMotionEventsReply *) rep);
+ else if (rep->RepType == X_GrabDevice)
+ SRepXGrabDevice(client, len, (xGrabDeviceReply *) rep);
+ else if (rep->RepType == X_GetDeviceFocus)
+ SRepXGetDeviceFocus(client, len, (xGetDeviceFocusReply *) rep);
+ else if (rep->RepType == X_GetFeedbackControl)
+ SRepXGetFeedbackControl(client, len, (xGetFeedbackControlReply *) rep);
+ else if (rep->RepType == X_GetDeviceKeyMapping)
+ SRepXGetDeviceKeyMapping(client, len,
+ (xGetDeviceKeyMappingReply *) rep);
+ else if (rep->RepType == X_GetDeviceModifierMapping)
+ SRepXGetDeviceModifierMapping(client, len,
+ (xGetDeviceModifierMappingReply *) rep);
+ else if (rep->RepType == X_SetDeviceModifierMapping)
+ SRepXSetDeviceModifierMapping(client, len,
+ (xSetDeviceModifierMappingReply *) rep);
+ else if (rep->RepType == X_GetDeviceButtonMapping)
+ SRepXGetDeviceButtonMapping(client, len,
+ (xGetDeviceButtonMappingReply *) rep);
+ else if (rep->RepType == X_SetDeviceButtonMapping)
+ SRepXSetDeviceButtonMapping(client, len,
+ (xSetDeviceButtonMappingReply *) rep);
+ else if (rep->RepType == X_QueryDeviceState)
+ SRepXQueryDeviceState(client, len, (xQueryDeviceStateReply *) rep);
+ else if (rep->RepType == X_SetDeviceValuators)
+ SRepXSetDeviceValuators(client, len, (xSetDeviceValuatorsReply *) rep);
+ else if (rep->RepType == X_GetDeviceControl)
+ SRepXGetDeviceControl(client, len, (xGetDeviceControlReply *) rep);
+ else if (rep->RepType == X_ChangeDeviceControl)
+ SRepXChangeDeviceControl(client, len,
+ (xChangeDeviceControlReply *) rep);
+ else if (rep->RepType == X_ListDeviceProperties)
+ SRepXListDeviceProperties(client, len, (xListDevicePropertiesReply*)rep);
+ else if (rep->RepType == X_GetDeviceProperty)
+ SRepXGetDeviceProperty(client, len, (xGetDevicePropertyReply *) rep);
+ else if (rep->RepType == X_XIQueryPointer)
+ SRepXIQueryPointer(client, len, (xXIQueryPointerReply *) rep);
+ else if (rep->RepType == X_XIGetClientPointer)
+ SRepXIGetClientPointer(client, len, (xXIGetClientPointerReply*) rep);
+ else if (rep->RepType == X_XIQueryVersion)
+ SRepXIQueryVersion(client, len, (xXIQueryVersionReply*)rep);
+ else if (rep->RepType == X_XIQueryDevice)
+ SRepXIQueryDevice(client, len, (xXIQueryDeviceReply*)rep);
+ else if (rep->RepType == X_XIGrabDevice)
+ SRepXIGrabDevice(client, len, (xXIGrabDeviceReply *) rep);
+ else if (rep->RepType == X_XIGrabDevice)
+ SRepXIPassiveGrabDevice(client, len, (xXIPassiveGrabDeviceReply *) rep);
+ else if (rep->RepType == X_XIListProperties)
+ SRepXIListProperties(client, len, (xXIListPropertiesReply *) rep);
+ else if (rep->RepType == X_XIGetProperty)
+ SRepXIGetProperty(client, len, (xXIGetPropertyReply *) rep);
+ else if (rep->RepType == X_XIGetSelectedEvents)
+ SRepXIGetSelectedEvents(client, len, (xXIGetSelectedEventsReply *) rep);
+ else if (rep->RepType == X_XIGetFocus)
+ SRepXIGetFocus(client, len, (xXIGetFocusReply *) rep);
+ else {
+ FatalError("XINPUT confused sending swapped reply");
+ }
+}
+
+/************************************************************************
+ *
+ * This function swaps the DeviceValuator event.
+ *
+ */
+
+static void
+SEventDeviceValuator(deviceValuator * from, deviceValuator * to)
+{
+ char n;
+ int i;
+ INT32 *ip B32;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swaps(&to->device_state, n);
+ ip = &to->valuator0;
+ for (i = 0; i < 6; i++) {
+ swapl((ip + i), n); /* macro - braces are required */
+ }
+}
+
+static void
+SEventFocus(deviceFocus * from, deviceFocus * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->time, n);
+ swapl(&to->window, n);
+}
+
+static void
+SDeviceStateNotifyEvent(deviceStateNotify * from, deviceStateNotify * to)
+{
+ int i;
+ char n;
+ INT32 *ip B32;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->time, n);
+ ip = &to->valuator0;
+ for (i = 0; i < 3; i++) {
+ swapl((ip + i), n); /* macro - braces are required */
+ }
+}
+
+static void
+SDeviceKeyStateNotifyEvent(deviceKeyStateNotify * from,
+ deviceKeyStateNotify * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+}
+
+static void
+SDeviceButtonStateNotifyEvent(deviceButtonStateNotify * from,
+ deviceButtonStateNotify * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+}
+
+static void
+SChangeDeviceNotifyEvent(changeDeviceNotify * from, changeDeviceNotify * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->time, n);
+}
+
+static void
+SDeviceMappingNotifyEvent(deviceMappingNotify * from, deviceMappingNotify * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->time, n);
+}
+
+static void
+SDevicePresenceNotifyEvent (devicePresenceNotify *from, devicePresenceNotify *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber,n);
+ swapl(&to->time, n);
+ swaps(&to->control, n);
+}
+
+static void
+SDevicePropertyNotifyEvent (devicePropertyNotify *from, devicePropertyNotify *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber,n);
+ swapl(&to->time, n);
+ swapl(&to->atom, n);
+}
+
+static void
+SDeviceLeaveNotifyEvent (xXILeaveEvent *from, xXILeaveEvent *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber,n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swapl(&to->root, n);
+ swapl(&to->event, n);
+ swapl(&to->child, n);
+ swapl(&to->root_x, n);
+ swapl(&to->root_y, n);
+ swapl(&to->event_x, n);
+ swapl(&to->event_y, n);
+ swaps(&to->sourceid, n);
+ swaps(&to->buttons_len, n);
+ swapl(&to->mods.base_mods, n);
+ swapl(&to->mods.latched_mods, n);
+ swapl(&to->mods.locked_mods, n);
+}
+
+static void
+SDeviceChangedEvent(xXIDeviceChangedEvent* from, xXIDeviceChangedEvent* to)
+{
+ char n;
+ int i, j;
+ xXIAnyInfo *any;
+
+ *to = *from;
+ memcpy(&to[1], &from[1], from->length * 4);
+
+ any = (xXIAnyInfo*)&to[1];
+ for (i = 0; i < to->num_classes; i++)
+ {
+ int length = any->length;
+
+ switch(any->type)
+ {
+ case KeyClass:
+ {
+ xXIKeyInfo *ki = (xXIKeyInfo*)any;
+ uint32_t *key = (uint32_t*)&ki[1];
+ for (j = 0; j < ki->num_keycodes; j++, key++)
+ swapl(key, n);
+ swaps(&ki->num_keycodes, n);
+ }
+ break;
+ case ButtonClass:
+ {
+ xXIButtonInfo *bi = (xXIButtonInfo*)any;
+ Atom *labels = (Atom*)((char*)bi + sizeof(xXIButtonInfo) +
+ pad_to_int32(bits_to_bytes(bi->num_buttons)));
+ for (j = 0; j < bi->num_buttons; j++)
+ swapl(&labels[j], n);
+ swaps(&bi->num_buttons, n);
+ }
+ break;
+ case ValuatorClass:
+ {
+ xXIValuatorInfo* ai = (xXIValuatorInfo*)any;
+ swapl(&ai->label, n);
+ swapl(&ai->min.integral, n);
+ swapl(&ai->min.frac, n);
+ swapl(&ai->max.integral, n);
+ swapl(&ai->max.frac, n);
+ swapl(&ai->resolution, n);
+ swaps(&ai->number, n);
+ }
+ break;
+ }
+
+ swaps(&any->type, n);
+ swaps(&any->length, n);
+ swaps(&any->sourceid, n);
+
+ any = (xXIAnyInfo*)((char*)any + length * 4);
+ }
+
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swaps(&to->num_classes, n);
+ swaps(&to->sourceid, n);
+
+}
+
+static void SDeviceEvent(xXIDeviceEvent *from, xXIDeviceEvent *to)
+{
+ int i;
+ char n;
+ char *ptr;
+ char *vmask;
+
+ memcpy(to, from, sizeof(xEvent) + from->length * 4);
+
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swapl(&to->detail, n);
+ swapl(&to->root, n);
+ swapl(&to->event, n);
+ swapl(&to->child, n);
+ swapl(&to->root_x, n);
+ swapl(&to->root_y, n);
+ swapl(&to->event_x, n);
+ swapl(&to->event_y, n);
+ swaps(&to->buttons_len, n);
+ swaps(&to->valuators_len, n);
+ swaps(&to->sourceid, n);
+ swapl(&to->mods.base_mods, n);
+ swapl(&to->mods.latched_mods, n);
+ swapl(&to->mods.locked_mods, n);
+ swapl(&to->mods.effective_mods, n);
+ swapl(&to->flags, n);
+
+ ptr = (char*)(&to[1]);
+ ptr += from->buttons_len * 4;
+ vmask = ptr; /* valuator mask */
+ ptr += from->valuators_len * 4;
+ for (i = 0; i < from->valuators_len * 32; i++)
+ {
+ if (BitIsOn(vmask, i))
+ {
+ swapl(((uint32_t*)ptr), n);
+ ptr += 4;
+ swapl(((uint32_t*)ptr), n);
+ ptr += 4;
+ }
+ }
+}
+
+static void SDeviceHierarchyEvent(xXIHierarchyEvent *from,
+ xXIHierarchyEvent *to)
+{
+ int i;
+ char n;
+ xXIHierarchyInfo *info;
+
+ *to = *from;
+ memcpy(&to[1], &from[1], from->length * 4);
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swapl(&to->flags, n);
+ swaps(&to->num_info, n);
+
+ info = (xXIHierarchyInfo*)&to[1];
+ for (i = 0; i< from->num_info; i++)
+ {
+ swaps(&info->deviceid, n);
+ swaps(&info->attachment, n);
+ info++;
+ }
+}
+
+static void SXIPropertyEvent(xXIPropertyEvent *from, xXIPropertyEvent *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->property, n);
+}
+
+static void SRawEvent(xXIRawEvent *from, xXIRawEvent *to)
+{
+ char n;
+ int i;
+ FP3232 *values;
+ unsigned char *mask;
+
+ memcpy(to, from, sizeof(xEvent) + from->length * 4);
+
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swapl(&to->detail, n);
+
+
+ mask = (unsigned char*)&to[1];
+ values = (FP3232*)(mask + from->valuators_len * 4);
+
+ for (i = 0; i < from->valuators_len * 4 * 8; i++)
+ {
+ if (BitIsOn(mask, i))
+ {
+ /* for each bit set there are two FP3232 values on the wire, in
+ * the order abcABC for data and data_raw. Here we swap as if
+ * they were in aAbBcC order because it's easier and really
+ * doesn't matter.
+ */
+ swapl(&values->integral, n);
+ swapl(&values->frac, n);
+ values++;
+ swapl(&values->integral, n);
+ swapl(&values->frac, n);
+ values++;
+ }
+ }
+
+ swaps(&to->valuators_len, n);
+}
+
+
+/** Event swapping function for XI2 events. */
+void
+XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
+{
+ switch(from->evtype)
+ {
+ case XI_Enter:
+ case XI_Leave:
+ SDeviceLeaveNotifyEvent((xXILeaveEvent*)from, (xXILeaveEvent*)to);
+ break;
+ case XI_DeviceChanged:
+ SDeviceChangedEvent((xXIDeviceChangedEvent*)from,
+ (xXIDeviceChangedEvent*)to);
+ break;
+ case XI_HierarchyChanged:
+ SDeviceHierarchyEvent((xXIHierarchyEvent*)from, (xXIHierarchyEvent*)to);
+ break;
+ case XI_PropertyEvent:
+ SXIPropertyEvent((xXIPropertyEvent*)from,
+ (xXIPropertyEvent*)to);
+ break;
+ case XI_Motion:
+ case XI_KeyPress:
+ case XI_KeyRelease:
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ SDeviceEvent((xXIDeviceEvent*)from, (xXIDeviceEvent*)to);
+ break;
+ case XI_RawMotion:
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ SRawEvent((xXIRawEvent*)from, (xXIRawEvent*)to);
+ break;
+ default:
+ ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
+ break;
+ }
+}
+
+/**************************************************************************
+ *
+ * Allow the specified event to have its propagation suppressed.
+ * The default is to not allow suppression of propagation.
+ *
+ */
+
+static void
+AllowPropagateSuppress(Mask mask)
+{
+ int i;
+
+ for (i = 0; i < MAXDEVICES; i++)
+ PropagateMask[i] |= mask;
+}
+
+/**************************************************************************
+ *
+ * Record an event mask where there is no unique corresponding event type.
+ * We can't call SetMaskForEvent, since that would clobber the existing
+ * mask for that event. MotionHint and ButtonMotion are examples.
+ *
+ * Since extension event types will never be less than 64, we can use
+ * 0-63 in the EventInfo array as the "type" to be used to look up this
+ * mask. This means that the corresponding macros such as
+ * DevicePointerMotionHint must have access to the same constants.
+ *
+ */
+
+static void
+SetEventInfo(Mask mask, int constant)
+{
+ EventInfo[ExtEventIndex].mask = mask;
+ EventInfo[ExtEventIndex++].type = constant;
+}
+
+/**************************************************************************
+ *
+ * Allow the specified event to be restricted to being selected by one
+ * client at a time.
+ * The default is to allow more than one client to select the event.
+ *
+ */
+
+static void
+SetExclusiveAccess(Mask mask)
+{
+ int i;
+
+ for (i = 0; i < MAXDEVICES; i++)
+ ExtExclusiveMasks[i] |= mask;
+}
+
+/**************************************************************************
+ *
+ * Assign the specified mask to the specified event.
+ *
+ */
+
+static void
+SetMaskForExtEvent(Mask mask, int event)
+{
+ int i;
+
+ EventInfo[ExtEventIndex].mask = mask;
+ EventInfo[ExtEventIndex++].type = event;
+
+ if ((event < LASTEvent) || (event >= 128))
+ FatalError("MaskForExtensionEvent: bogus event number");
+
+ for (i = 0; i < MAXDEVICES; i++)
+ SetMaskForEvent(i, mask, event);
+}
+
+/************************************************************************
+ *
+ * This function sets up extension event types and masks.
+ *
+ */
+
+static void
+FixExtensionEvents(ExtensionEntry * extEntry)
+{
+ DeviceValuator = extEntry->eventBase;
+ DeviceKeyPress = DeviceValuator + 1;
+ DeviceKeyRelease = DeviceKeyPress + 1;
+ DeviceButtonPress = DeviceKeyRelease + 1;
+ DeviceButtonRelease = DeviceButtonPress + 1;
+ DeviceMotionNotify = DeviceButtonRelease + 1;
+ DeviceFocusIn = DeviceMotionNotify + 1;
+ DeviceFocusOut = DeviceFocusIn + 1;
+ ProximityIn = DeviceFocusOut + 1;
+ ProximityOut = ProximityIn + 1;
+ DeviceStateNotify = ProximityOut + 1;
+ DeviceMappingNotify = DeviceStateNotify + 1;
+ ChangeDeviceNotify = DeviceMappingNotify + 1;
+ DeviceKeyStateNotify = ChangeDeviceNotify + 1;
+ DeviceButtonStateNotify = DeviceKeyStateNotify + 1;
+ DevicePresenceNotify = DeviceButtonStateNotify + 1;
+ DevicePropertyNotify = DevicePresenceNotify + 1;
+
+ event_base[KeyClass] = DeviceKeyPress;
+ event_base[ButtonClass] = DeviceButtonPress;
+ event_base[ValuatorClass] = DeviceMotionNotify;
+ event_base[ProximityClass] = ProximityIn;
+ event_base[FocusClass] = DeviceFocusIn;
+ event_base[OtherClass] = DeviceStateNotify;
+
+ BadDevice += extEntry->errorBase;
+ BadEvent += extEntry->errorBase;
+ BadMode += extEntry->errorBase;
+ DeviceBusy += extEntry->errorBase;
+ BadClass += extEntry->errorBase;
+
+ SetMaskForExtEvent(DeviceKeyPressMask, DeviceKeyPress);
+ AllowPropagateSuppress(DeviceKeyPressMask);
+ SetCriticalEvent(DeviceKeyPress);
+
+ SetMaskForExtEvent(DeviceKeyReleaseMask, DeviceKeyRelease);
+ AllowPropagateSuppress(DeviceKeyReleaseMask);
+ SetCriticalEvent(DeviceKeyRelease);
+
+ SetMaskForExtEvent(DeviceButtonPressMask, DeviceButtonPress);
+ AllowPropagateSuppress(DeviceButtonPressMask);
+ SetCriticalEvent(DeviceButtonPress);
+
+ SetMaskForExtEvent(DeviceButtonReleaseMask, DeviceButtonRelease);
+ AllowPropagateSuppress(DeviceButtonReleaseMask);
+ SetCriticalEvent(DeviceButtonRelease);
+
+ SetMaskForExtEvent(DeviceProximityMask, ProximityIn);
+ SetMaskForExtEvent(DeviceProximityMask, ProximityOut);
+
+ SetMaskForExtEvent(DeviceStateNotifyMask, DeviceStateNotify);
+
+ SetMaskForExtEvent(DevicePointerMotionMask, DeviceMotionNotify);
+ AllowPropagateSuppress(DevicePointerMotionMask);
+ SetCriticalEvent(DeviceMotionNotify);
+
+ SetEventInfo(DevicePointerMotionHintMask, _devicePointerMotionHint);
+ SetEventInfo(DeviceButton1MotionMask, _deviceButton1Motion);
+ SetEventInfo(DeviceButton2MotionMask, _deviceButton2Motion);
+ SetEventInfo(DeviceButton3MotionMask, _deviceButton3Motion);
+ SetEventInfo(DeviceButton4MotionMask, _deviceButton4Motion);
+ SetEventInfo(DeviceButton5MotionMask, _deviceButton5Motion);
+ SetEventInfo(DeviceButtonMotionMask, _deviceButtonMotion);
+
+ SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusIn);
+ SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusOut);
+
+ SetMaskForExtEvent(DeviceMappingNotifyMask, DeviceMappingNotify);
+ SetMaskForExtEvent(ChangeDeviceNotifyMask, ChangeDeviceNotify);
+
+ SetEventInfo(DeviceButtonGrabMask, _deviceButtonGrab);
+ SetExclusiveAccess(DeviceButtonGrabMask);
+
+ SetEventInfo(DeviceOwnerGrabButtonMask, _deviceOwnerGrabButton);
+ SetEventInfo(DevicePresenceNotifyMask, _devicePresence);
+ SetMaskForExtEvent(DevicePropertyNotifyMask, DevicePropertyNotify);
+
+ SetEventInfo(0, _noExtensionEvent);
+}
+
+/************************************************************************
+ *
+ * This function restores extension event types and masks to their
+ * initial state.
+ *
+ */
+
+static void
+RestoreExtensionEvents(void)
+{
+ int i, j;
+
+ IReqCode = 0;
+ IEventBase = 0;
+
+ for (i = 0; i < ExtEventIndex - 1; i++) {
+ if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
+ {
+ for (j = 0; j < MAXDEVICES; j++)
+ SetMaskForEvent(j, 0, EventInfo[i].type);
+ }
+ EventInfo[i].mask = 0;
+ EventInfo[i].type = 0;
+ }
+ ExtEventIndex = 0;
+ DeviceValuator = 0;
+ DeviceKeyPress = 1;
+ DeviceKeyRelease = 2;
+ DeviceButtonPress = 3;
+ DeviceButtonRelease = 4;
+ DeviceMotionNotify = 5;
+ DeviceFocusIn = 6;
+ DeviceFocusOut = 7;
+ ProximityIn = 8;
+ ProximityOut = 9;
+ DeviceStateNotify = 10;
+ DeviceMappingNotify = 11;
+ ChangeDeviceNotify = 12;
+ DeviceKeyStateNotify = 13;
+ DeviceButtonStateNotify = 13;
+ DevicePresenceNotify = 14;
+ DevicePropertyNotify = 15;
+
+ BadDevice = 0;
+ BadEvent = 1;
+ BadMode = 2;
+ DeviceBusy = 3;
+ BadClass = 4;
+
+}
+
+/***********************************************************************
+ *
+ * IResetProc.
+ * Remove reply-swapping routine.
+ * Remove event-swapping routine.
+ *
+ */
+
+static void
+IResetProc(ExtensionEntry * unused)
+{
+ ReplySwapVector[IReqCode] = ReplyNotSwappd;
+ EventSwapVector[DeviceValuator] = NotImplemented;
+ EventSwapVector[DeviceKeyPress] = NotImplemented;
+ EventSwapVector[DeviceKeyRelease] = NotImplemented;
+ EventSwapVector[DeviceButtonPress] = NotImplemented;
+ EventSwapVector[DeviceButtonRelease] = NotImplemented;
+ EventSwapVector[DeviceMotionNotify] = NotImplemented;
+ EventSwapVector[DeviceFocusIn] = NotImplemented;
+ EventSwapVector[DeviceFocusOut] = NotImplemented;
+ EventSwapVector[ProximityIn] = NotImplemented;
+ EventSwapVector[ProximityOut] = NotImplemented;
+ EventSwapVector[DeviceStateNotify] = NotImplemented;
+ EventSwapVector[DeviceKeyStateNotify] = NotImplemented;
+ EventSwapVector[DeviceButtonStateNotify] = NotImplemented;
+ EventSwapVector[DeviceMappingNotify] = NotImplemented;
+ EventSwapVector[ChangeDeviceNotify] = NotImplemented;
+ EventSwapVector[DevicePresenceNotify] = NotImplemented;
+ EventSwapVector[DevicePropertyNotify] = NotImplemented;
+ RestoreExtensionEvents();
+}
+
+
+/***********************************************************************
+ *
+ * Assign an id and type to an input device.
+ *
+ */
+
+void
+AssignTypeAndName(DeviceIntPtr dev, Atom type, char *name)
+{
+ dev->xinput_type = type;
+ dev->name = strdup(name);
+}
+
+/***********************************************************************
+ *
+ * Make device type atoms.
+ *
+ */
+
+static void
+MakeDeviceTypeAtoms(void)
+{
+ int i;
+
+ for (i = 0; i < NUMTYPES; i++)
+ dev_type[i].type =
+ MakeAtom(dev_type[i].name, strlen(dev_type[i].name), 1);
+}
+
+/*****************************************************************************
+ *
+ * SEventIDispatch
+ *
+ * Swap any events defined in this extension.
+ */
+#define DO_SWAP(func,type) func ((type *)from, (type *)to)
+
+static void
+SEventIDispatch(xEvent * from, xEvent * to)
+{
+ int type = from->u.u.type & 0177;
+
+ if (type == DeviceValuator)
+ DO_SWAP(SEventDeviceValuator, deviceValuator);
+ else if (type == DeviceKeyPress) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceKeyRelease) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceButtonPress) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceButtonRelease) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceMotionNotify) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceFocusIn)
+ DO_SWAP(SEventFocus, deviceFocus);
+ else if (type == DeviceFocusOut)
+ DO_SWAP(SEventFocus, deviceFocus);
+ else if (type == ProximityIn) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == ProximityOut) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceStateNotify)
+ DO_SWAP(SDeviceStateNotifyEvent, deviceStateNotify);
+ else if (type == DeviceKeyStateNotify)
+ DO_SWAP(SDeviceKeyStateNotifyEvent, deviceKeyStateNotify);
+ else if (type == DeviceButtonStateNotify)
+ DO_SWAP(SDeviceButtonStateNotifyEvent, deviceButtonStateNotify);
+ else if (type == DeviceMappingNotify)
+ DO_SWAP(SDeviceMappingNotifyEvent, deviceMappingNotify);
+ else if (type == ChangeDeviceNotify)
+ DO_SWAP(SChangeDeviceNotifyEvent, changeDeviceNotify);
+ else if (type == DevicePresenceNotify)
+ DO_SWAP(SDevicePresenceNotifyEvent, devicePresenceNotify);
+ else if (type == DevicePropertyNotify)
+ DO_SWAP(SDevicePropertyNotifyEvent, devicePropertyNotify);
+ else {
+ FatalError("XInputExtension: Impossible event!\n");
+ }
+}
+
+/**********************************************************************
+ *
+ * IExtensionInit - initialize the input extension.
+ *
+ * Called from InitExtensions in main() or from QueryExtension() if the
+ * extension is dynamically loaded.
+ *
+ * This extension has several events and errors.
+ *
+ * XI is mandatory nowadays, so if we fail to init XI, we die.
+ */
+
+void
+XInputExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ XExtensionVersion thisversion = { XI_Present,
+ SERVER_XI_MAJOR_VERSION,
+ SERVER_XI_MINOR_VERSION,
+ };
+
+ if (!dixRegisterPrivateKey(&XIClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(XIClientRec)))
+ FatalError("Cannot request private for XI.\n");
+
+ if (!AddCallback(&ClientStateCallback, XIClientCallback, 0))
+ FatalError("Failed to add callback to XI.\n");
+
+ extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
+ SProcIDispatch, IResetProc, StandardMinorOpcode);
+ if (extEntry) {
+ IReqCode = extEntry->base;
+ IEventBase = extEntry->eventBase;
+ XIVersion = thisversion;
+ MakeDeviceTypeAtoms();
+ RT_INPUTCLIENT = CreateNewResourceType((DeleteType) InputClientGone,
+ "INPUTCLIENT");
+ if (!RT_INPUTCLIENT)
+ FatalError("Failed to add resource type for XI.\n");
+ FixExtensionEvents(extEntry);
+ ReplySwapVector[IReqCode] = (ReplySwapPtr) SReplyIDispatch;
+ EventSwapVector[DeviceValuator] = SEventIDispatch;
+ EventSwapVector[DeviceKeyPress] = SEventIDispatch;
+ EventSwapVector[DeviceKeyRelease] = SEventIDispatch;
+ EventSwapVector[DeviceButtonPress] = SEventIDispatch;
+ EventSwapVector[DeviceButtonRelease] = SEventIDispatch;
+ EventSwapVector[DeviceMotionNotify] = SEventIDispatch;
+ EventSwapVector[DeviceFocusIn] = SEventIDispatch;
+ EventSwapVector[DeviceFocusOut] = SEventIDispatch;
+ EventSwapVector[ProximityIn] = SEventIDispatch;
+ EventSwapVector[ProximityOut] = SEventIDispatch;
+ EventSwapVector[DeviceStateNotify] = SEventIDispatch;
+ EventSwapVector[DeviceKeyStateNotify] = SEventIDispatch;
+ EventSwapVector[DeviceButtonStateNotify] = SEventIDispatch;
+ EventSwapVector[DeviceMappingNotify] = SEventIDispatch;
+ EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
+ EventSwapVector[DevicePresenceNotify] = SEventIDispatch;
+
+ GERegisterExtension(IReqCode, XI2EventSwap);
+
+
+ memset(&xi_all_devices, 0, sizeof(xi_all_devices));
+ memset(&xi_all_master_devices, 0, sizeof(xi_all_master_devices));
+ xi_all_devices.id = XIAllDevices;
+ xi_all_devices.name = "XIAllDevices";
+ xi_all_master_devices.id = XIAllMasterDevices;
+ xi_all_master_devices.name = "XIAllMasterDevices";
+
+ inputInfo.all_devices = &xi_all_devices;
+ inputInfo.all_master_devices = &xi_all_master_devices;
+
+ XIResetProperties();
+ } else {
+ FatalError("IExtensionInit: AddExtensions failed\n");
+ }
+}
+
diff --git a/xorg-server/Xi/xiwarppointer.c b/xorg-server/Xi/xiwarppointer.c
index 7276e6faf..c01b115f3 100644
--- a/xorg-server/Xi/xiwarppointer.c
+++ b/xorg-server/Xi/xiwarppointer.c
@@ -192,6 +192,8 @@ ProcXIWarpPointer(ClientPtr client)
/* if we don't update the device, we get a jump next time it moves */
pDev->last.valuators[0] = x;
pDev->last.valuators[1] = y;
+ pDev->last.remainder[0] = 0;
+ pDev->last.remainder[1] = 0;
miPointerUpdateSprite(pDev);
/* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac
index 45286eaf4..120321e7c 100644
--- a/xorg-server/configure.ac
+++ b/xorg-server/configure.ac
@@ -1903,8 +1903,8 @@ 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 && false])
-AM_CONDITIONAL(XWIN_PRIMARYFB, [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])
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index 361d6102a..07f8b05ea 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -1,5819 +1,5813 @@
-/************************************************************
-
-Copyright 1987, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-********************************************************/
-
-/* The panoramix components contained the following notice */
-/*****************************************************************
-
-Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-******************************************************************/
-
-/*
- * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/** @file events.c
- * This file handles event delivery and a big part of the server-side protocol
- * handling (the parts for input devices).
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include "misc.h"
-#include "resource.h"
-#include <X11/Xproto.h>
-#include "windowstr.h"
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "cursorstr.h"
-
-#include "dixstruct.h"
-#ifdef PANORAMIX
-#include "panoramiX.h"
-#include "panoramiXsrv.h"
-#endif
-#include "globals.h"
-
-#include <X11/extensions/XKBproto.h>
-#include "xkbsrv.h"
-#include "xace.h"
-
-#ifdef XSERVER_DTRACE
-#include <sys/types.h>
-typedef const char *string;
-#include "Xserver-dtrace.h"
-#endif
-
-#include <X11/extensions/XIproto.h>
-#include <X11/extensions/XI2proto.h>
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XI2.h>
-#include "exglobals.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "extnsionst.h"
-
-#include "dixevents.h"
-#include "dixgrabs.h"
-#include "dispatch.h"
-
-#include <X11/extensions/ge.h>
-#include "geext.h"
-#include "geint.h"
-
-#include "eventstr.h"
-#include "enterleave.h"
-#include "eventconvert.h"
-
-/* Extension events type numbering starts at EXTENSION_EVENT_BASE. */
-#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
-#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
-#define AllButtonsMask ( \
- Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
-#define MotionMask ( \
- PointerMotionMask | Button1MotionMask | \
- Button2MotionMask | Button3MotionMask | Button4MotionMask | \
- Button5MotionMask | ButtonMotionMask )
-#define PropagateMask ( \
- KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
- MotionMask )
-#define PointerGrabMask ( \
- ButtonPressMask | ButtonReleaseMask | \
- EnterWindowMask | LeaveWindowMask | \
- PointerMotionHintMask | KeymapStateMask | \
- MotionMask )
-#define AllModifiersMask ( \
- ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
- Mod3Mask | Mod4Mask | Mod5Mask )
-#define LastEventMask OwnerGrabButtonMask
-#define AllEventMasks (LastEventMask|(LastEventMask-1))
-
-
-#define CORE_EVENT(event) \
- (!((event)->u.u.type & EXTENSION_EVENT_BASE) && \
- (event)->u.u.type != GenericEvent)
-#define XI2_EVENT(event) \
- (((event)->u.u.type == GenericEvent) && \
- ((xGenericEvent*)(event))->extension == IReqCode)
-
-/**
- * Used to indicate a implicit passive grab created by a ButtonPress event.
- * See DeliverEventsToWindow().
- */
-#define ImplicitGrabMask (1 << 7)
-
-#define WID(w) ((w) ? ((w)->drawable.id) : 0)
-
-#define XE_KBPTR (xE->u.keyButtonPointer)
-
-
-CallbackListPtr EventCallback;
-CallbackListPtr DeviceEventCallback;
-
-#define DNPMCOUNT 8
-
-Mask DontPropagateMasks[DNPMCOUNT];
-static int DontPropagateRefCnts[DNPMCOUNT];
-
-static void CheckVirtualMotion( DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin);
-static void CheckPhysLimits(DeviceIntPtr pDev,
- CursorPtr cursor,
- Bool generateEvents,
- Bool confineToScreen,
- ScreenPtr pScreen);
-static Bool CheckPassiveGrabsOnWindow(WindowPtr pWin,
- DeviceIntPtr device,
- DeviceEvent *event,
- BOOL checkCore);
-
-/** Key repeat hack. Do not use but in TryClientEvents */
-extern BOOL EventIsKeyRepeat(xEvent *event);
-
-/**
- * Main input device struct.
- * inputInfo.pointer
- * is the core pointer. Referred to as "virtual core pointer", "VCP",
- * "core pointer" or inputInfo.pointer. The VCP is the first master
- * pointer device and cannot be deleted.
- *
- * inputInfo.keyboard
- * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
- * See inputInfo.pointer.
- *
- * inputInfo.devices
- * linked list containing all devices including VCP and VCK.
- *
- * inputInfo.off_devices
- * Devices that have not been initialized and are thus turned off.
- *
- * inputInfo.numDevices
- * Total number of devices.
- *
- * inputInfo.all_devices
- * Virtual device used for XIAllDevices passive grabs. This device is
- * not part of the inputInfo.devices list and mostly unset except for
- * the deviceid. It exists because passivegrabs need a valid device
- * reference.
- *
- * inputInfo.all_master_devices
- * Virtual device used for XIAllMasterDevices passive grabs. This device
- * is not part of the inputInfo.devices list and mostly unset except for
- * the deviceid. It exists because passivegrabs need a valid device
- * reference.
- */
-InputInfo inputInfo;
-
-EventSyncInfoRec syncEvents;
-
-/**
- * The root window the given device is currently on.
- */
-#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
-
-static xEvent* swapEvent = NULL;
-static int swapEventLen = 0;
-
-void
-NotImplemented(xEvent *from, xEvent *to)
-{
- FatalError("Not implemented");
-}
-
-/**
- * Convert the given event type from an XI event to a core event.
- * @param[in] The XI 1.x event type.
- * @return The matching core event type or 0 if there is none.
- */
-int
-XItoCoreType(int xitype)
-{
- int coretype = 0;
- if (xitype == DeviceMotionNotify)
- coretype = MotionNotify;
- else if (xitype == DeviceButtonPress)
- coretype = ButtonPress;
- else if (xitype == DeviceButtonRelease)
- coretype = ButtonRelease;
- else if (xitype == DeviceKeyPress)
- coretype = KeyPress;
- else if (xitype == DeviceKeyRelease)
- coretype = KeyRelease;
-
- return coretype;
-}
-
-/**
- * @return true if the device owns a cursor, false if device shares a cursor
- * sprite with another device.
- */
-Bool
-DevHasCursor(DeviceIntPtr pDev)
-{
- return pDev->spriteInfo->spriteOwner;
-}
-
-/*
- * @return true if a device is a pointer, check is the same as used by XI to
- * fill the 'use' field.
- */
-Bool
-IsPointerDevice(DeviceIntPtr dev)
-{
- return (dev->type == MASTER_POINTER) ||
- (dev->valuator && dev->button) ||
- (dev->valuator && !dev->key);
-}
-
-/*
- * @return true if a device is a keyboard, check is the same as used by XI to
- * fill the 'use' field.
- *
- * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
- * count them as keyboard devices.
- */
-Bool
-IsKeyboardDevice(DeviceIntPtr dev)
-{
- return (dev->type == MASTER_KEYBOARD) ||
- ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
-}
-
-Bool
-IsMaster(DeviceIntPtr dev)
-{
- return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
-}
-
-static WindowPtr XYToWindow(
- DeviceIntPtr pDev,
- int x,
- int y
-);
-
-/**
- * Max event opcode.
- */
-extern int lastEvent;
-
-extern int DeviceMotionNotify;
-
-#define CantBeFiltered NoEventMask
-/**
- * Event masks for each event type.
- *
- * One set of filters for each device, but only the first layer
- * is initialized. The rest is memcpy'd in InitEvents.
- *
- * Filters are used whether a given event may be delivered to a client,
- * usually in the form of if (window-event-mask & filter); then deliver event.
- *
- * One notable filter is for PointerMotion/DevicePointerMotion events. Each
- * time a button is pressed, the filter is modified to also contain the
- * matching ButtonXMotion mask.
- */
-static Mask filters[MAXDEVICES][128] = {
-{
- NoSuchEvent, /* 0 */
- NoSuchEvent, /* 1 */
- KeyPressMask, /* KeyPress */
- KeyReleaseMask, /* KeyRelease */
- ButtonPressMask, /* ButtonPress */
- ButtonReleaseMask, /* ButtonRelease */
- PointerMotionMask, /* MotionNotify (initial state) */
- EnterWindowMask, /* EnterNotify */
- LeaveWindowMask, /* LeaveNotify */
- FocusChangeMask, /* FocusIn */
- FocusChangeMask, /* FocusOut */
- KeymapStateMask, /* KeymapNotify */
- ExposureMask, /* Expose */
- CantBeFiltered, /* GraphicsExpose */
- CantBeFiltered, /* NoExpose */
- VisibilityChangeMask, /* VisibilityNotify */
- SubstructureNotifyMask, /* CreateNotify */
- StructureAndSubMask, /* DestroyNotify */
- StructureAndSubMask, /* UnmapNotify */
- StructureAndSubMask, /* MapNotify */
- SubstructureRedirectMask, /* MapRequest */
- StructureAndSubMask, /* ReparentNotify */
- StructureAndSubMask, /* ConfigureNotify */
- SubstructureRedirectMask, /* ConfigureRequest */
- StructureAndSubMask, /* GravityNotify */
- ResizeRedirectMask, /* ResizeRequest */
- StructureAndSubMask, /* CirculateNotify */
- SubstructureRedirectMask, /* CirculateRequest */
- PropertyChangeMask, /* PropertyNotify */
- CantBeFiltered, /* SelectionClear */
- CantBeFiltered, /* SelectionRequest */
- CantBeFiltered, /* SelectionNotify */
- ColormapChangeMask, /* ColormapNotify */
- CantBeFiltered, /* ClientMessage */
- CantBeFiltered /* MappingNotify */
-}};
-
-/**
- * For the given event, return the matching event filter. This filter may then
- * be AND'ed with the selected event mask.
- *
- * For XI2 events, the returned filter is simply the byte containing the event
- * mask we're interested in. E.g. for a mask of (1 << 13), this would be
- * byte[1].
- *
- * @param[in] dev The device the event belongs to, may be NULL.
- * @param[in] event The event to get the filter for. Only the type of the
- * event matters, or the extension + evtype for GenericEvents.
- * @return The filter mask for the given event.
- *
- * @see GetEventMask
- */
-Mask
-GetEventFilter(DeviceIntPtr dev, xEvent *event)
-{
- if (event->u.u.type != GenericEvent)
- return filters[dev ? dev->id : 0][event->u.u.type];
- else if (XI2_EVENT(event))
- return (1 << (((xXIDeviceEvent*)event)->evtype % 8));
- ErrorF("[dix] Unknown device type %d. No filter\n", event->u.u.type);
- return 0;
-}
-
-/**
- * Return the windows complete XI2 mask for the given XI2 event type.
- */
-Mask
-GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
-{
- OtherInputMasks *inputMasks = wOtherInputMasks(win);
- int filter;
- int evtype;
-
- if (!inputMasks || !XI2_EVENT(ev))
- return 0;
-
- evtype = ((xGenericEvent*)ev)->evtype;
- filter = GetEventFilter(dev, ev);
-
- return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) ||
- inputMasks->xi2mask[XIAllDevices][evtype/8] ||
- (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev)));
-}
-
-static Mask
-GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
-{
- /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
- if (XI2_EVENT(event))
- {
- int byte = ((xGenericEvent*)event)->evtype / 8;
- return (other->xi2mask[dev->id][byte] |
- other->xi2mask[XIAllDevices][byte] |
- (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0));
- } else if (CORE_EVENT(event))
- return other->mask[XIAllDevices];
- else
- return other->mask[dev->id];
-}
-
-
-static CARD8 criticalEvents[32] =
-{
- 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */
-};
-
-static void
-SyntheticMotion(DeviceIntPtr dev, int x, int y) {
- int screenno = 0;
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- screenno = dev->spriteInfo->sprite->screen->myNum;
-#endif
- PostSyntheticMotion(dev, x, y, screenno,
- (syncEvents.playingEvents) ? syncEvents.time.milliseconds : currentTime.milliseconds);
-
-}
-
-#ifdef PANORAMIX
-static void PostNewCursor(DeviceIntPtr pDev);
-
-static Bool
-pointOnScreen(ScreenPtr pScreen, int x, int y)
-{
- return x >= pScreen->x && x < pScreen->x + pScreen->width &&
- y >= pScreen->y && y < pScreen->y + pScreen->height;
-}
-
-static Bool
-XineramaSetCursorPosition(
- DeviceIntPtr pDev,
- int x,
- int y,
- Bool generateEvent
-){
- ScreenPtr pScreen;
- int i;
- SpritePtr pSprite = pDev->spriteInfo->sprite;
-
- /* x,y are in Screen 0 coordinates. We need to decide what Screen
- to send the message too and what the coordinates relative to
- that screen are. */
-
- pScreen = pSprite->screen;
- x += screenInfo.screens[0]->x;
- y += screenInfo.screens[0]->y;
-
- if(!pointOnScreen(pScreen, x, y))
- {
- FOR_NSCREENS(i)
- {
- if(i == pScreen->myNum)
- continue;
- if(pointOnScreen(screenInfo.screens[i], x, y))
- {
- pScreen = screenInfo.screens[i];
- break;
- }
- }
- }
-
- pSprite->screen = pScreen;
- pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
- pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
- x -= pScreen->x;
- y -= pScreen->y;
-
- return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
-}
-
-
-static void
-XineramaConstrainCursor(DeviceIntPtr pDev)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
- ScreenPtr pScreen;
- BoxRec newBox;
-
- pScreen = pSprite->screen;
- newBox = pSprite->physLimits;
-
- /* Translate the constraining box to the screen
- the sprite is actually on */
- newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
- newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
- newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
- newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
-
- (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
-}
-
-
-static Bool
-XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
-
- if(pWin == screenInfo.screens[0]->root) {
- int i;
- for (i = 0; i < PanoramiXNumScreens; i++)
- pSprite->windows[i] = screenInfo.screens[i]->root;
- } else {
- PanoramiXRes *win;
- int rc, i;
-
- rc = dixLookupResourceByType((pointer *)&win, pWin->drawable.id,
- XRT_WINDOW, serverClient, DixReadAccess);
- if (rc != Success)
- return FALSE;
-
- for(i = 0; i < PanoramiXNumScreens; i++) {
- rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
- serverClient, DixReadAccess);
- if (rc != Success) /* window is being unmapped */
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static void
-XineramaConfineCursorToWindow(DeviceIntPtr pDev,
- WindowPtr pWin,
- Bool generateEvents)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
-
- int x, y, off_x, off_y, i;
-
- if(!XineramaSetWindowPntrs(pDev, pWin))
- return;
-
- i = PanoramiXNumScreens - 1;
-
- RegionCopy(&pSprite->Reg1,
- &pSprite->windows[i]->borderSize);
- off_x = screenInfo.screens[i]->x;
- off_y = screenInfo.screens[i]->y;
-
- while(i--) {
- x = off_x - screenInfo.screens[i]->x;
- y = off_y - screenInfo.screens[i]->y;
-
- if(x || y)
- RegionTranslate(&pSprite->Reg1, x, y);
-
- RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
- &pSprite->windows[i]->borderSize);
-
- off_x = screenInfo.screens[i]->x;
- off_y = screenInfo.screens[i]->y;
- }
-
- pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
-
- if(RegionNumRects(&pSprite->Reg1) > 1)
- pSprite->hotShape = &pSprite->Reg1;
- else
- pSprite->hotShape = NullRegion;
-
- pSprite->confined = FALSE;
- pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
-
- CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
-}
-
-#endif /* PANORAMIX */
-
-/**
- * Modifies the filter for the given protocol event type to the given masks.
- *
- * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
- * The latter initialises masks for the matching XI events, it's a once-off
- * setting.
- * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
- * time a button is pressed to include the matching ButtonXMotion mask in the
- * filter.
- *
- * @param[in] deviceid The device to modify the filter for.
- * @param[in] mask The new filter mask.
- * @param[in] event Protocol event type.
- */
-void
-SetMaskForEvent(int deviceid, Mask mask, int event)
-{
- if (deviceid < 0 || deviceid >= MAXDEVICES)
- FatalError("SetMaskForEvent: bogus device id");
- filters[deviceid][event] = mask;
-}
-
-void
-SetCriticalEvent(int event)
-{
- if (event >= 128)
- FatalError("SetCriticalEvent: bogus event number");
- criticalEvents[event >> 3] |= 1 << (event & 7);
-}
-
-void
-ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
-{
- BoxRec box;
- int x = *px, y = *py;
- int incx = 1, incy = 1;
- SpritePtr pSprite;
-
- pSprite = pDev->spriteInfo->sprite;
- if (RegionContainsPoint(shape, x, y, &box))
- return;
- box = *RegionExtents(shape);
- /* this is rather crude */
- do {
- x += incx;
- if (x >= box.x2)
- {
- incx = -1;
- x = *px - 1;
- }
- else if (x < box.x1)
- {
- incx = 1;
- x = *px;
- y += incy;
- if (y >= box.y2)
- {
- incy = -1;
- y = *py - 1;
- }
- else if (y < box.y1)
- return; /* should never get here! */
- }
- } while (!RegionContainsPoint(shape, x, y, &box));
- *px = x;
- *py = y;
-}
-
-static void
-CheckPhysLimits(
- DeviceIntPtr pDev,
- CursorPtr cursor,
- Bool generateEvents,
- Bool confineToScreen, /* unused if PanoramiX on */
- ScreenPtr pScreen) /* unused if PanoramiX on */
-{
- HotSpot new;
- SpritePtr pSprite = pDev->spriteInfo->sprite;
-
- if (!cursor)
- return;
- new = pSprite->hotPhys;
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- /* I don't care what the DDX has to say about it */
- pSprite->physLimits = pSprite->hotLimits;
- else
-#endif
- {
- if (pScreen)
- new.pScreen = pScreen;
- else
- pScreen = new.pScreen;
- (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
- &pSprite->physLimits);
- pSprite->confined = confineToScreen;
- (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
- }
-
- /* constrain the pointer to those limits */
- if (new.x < pSprite->physLimits.x1)
- new.x = pSprite->physLimits.x1;
- else
- if (new.x >= pSprite->physLimits.x2)
- new.x = pSprite->physLimits.x2 - 1;
- if (new.y < pSprite->physLimits.y1)
- new.y = pSprite->physLimits.y1;
- else
- if (new.y >= pSprite->physLimits.y2)
- new.y = pSprite->physLimits.y2 - 1;
- if (pSprite->hotShape)
- ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
- if ((
-#ifdef PANORAMIX
- noPanoramiXExtension &&
-#endif
- (pScreen != pSprite->hotPhys.pScreen)) ||
- (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
- {
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
- else
-#endif
- {
- if (pScreen != pSprite->hotPhys.pScreen)
- pSprite->hotPhys = new;
- (*pScreen->SetCursorPosition)
- (pDev, pScreen, new.x, new.y, generateEvents);
- }
- if (!generateEvents)
- SyntheticMotion(pDev, new.x, new.y);
- }
-
-#ifdef PANORAMIX
- /* Tell DDX what the limits are */
- if (!noPanoramiXExtension)
- XineramaConstrainCursor(pDev);
-#endif
-}
-
-static void
-CheckVirtualMotion(
- DeviceIntPtr pDev,
- QdEventPtr qe,
- WindowPtr pWin)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
- RegionPtr reg = NULL;
- DeviceEvent *ev = NULL;
-
- if (qe)
- {
- ev = &qe->event->device_event;
- switch(ev->type)
- {
- case ET_Motion:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- pSprite->hot.pScreen = qe->pScreen;
- pSprite->hot.x = ev->root_x;
- pSprite->hot.y = ev->root_y;
- pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
- break;
- default:
- break;
- }
- }
- if (pWin)
- {
- BoxRec lims;
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension) {
- int x, y, off_x, off_y, i;
-
- if(!XineramaSetWindowPntrs(pDev, pWin))
- return;
-
- i = PanoramiXNumScreens - 1;
-
- RegionCopy(&pSprite->Reg2,
- &pSprite->windows[i]->borderSize);
- off_x = screenInfo.screens[i]->x;
- off_y = screenInfo.screens[i]->y;
-
- while(i--) {
- x = off_x - screenInfo.screens[i]->x;
- y = off_y - screenInfo.screens[i]->y;
-
- if(x || y)
- RegionTranslate(&pSprite->Reg2, x, y);
-
- RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
- &pSprite->windows[i]->borderSize);
-
- off_x = screenInfo.screens[i]->x;
- off_y = screenInfo.screens[i]->y;
- }
- } else
-#endif
- {
- if (pSprite->hot.pScreen != pWin->drawable.pScreen)
- {
- pSprite->hot.pScreen = pWin->drawable.pScreen;
- pSprite->hot.x = pSprite->hot.y = 0;
- }
- }
-
- lims = *RegionExtents(&pWin->borderSize);
- if (pSprite->hot.x < lims.x1)
- pSprite->hot.x = lims.x1;
- else if (pSprite->hot.x >= lims.x2)
- pSprite->hot.x = lims.x2 - 1;
- if (pSprite->hot.y < lims.y1)
- pSprite->hot.y = lims.y1;
- else if (pSprite->hot.y >= lims.y2)
- pSprite->hot.y = lims.y2 - 1;
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- {
- if (RegionNumRects(&pSprite->Reg2) > 1)
- reg = &pSprite->Reg2;
-
- } else
-#endif
- {
- if (wBoundingShape(pWin))
- reg = &pWin->borderSize;
- }
-
- if (reg)
- ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
-
- if (qe && ev)
- {
- qe->pScreen = pSprite->hot.pScreen;
- ev->root_x = pSprite->hot.x;
- ev->root_y = pSprite->hot.y;
- }
- }
-#ifdef PANORAMIX
- if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */
-#endif
- RootWindow(pDev) = pSprite->hot.pScreen->root;
-}
-
-static void
-ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
-
- if (syncEvents.playingEvents)
- {
- CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
- SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
- }
- else
- {
-#ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
- return;
- }
-#endif
- pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
- pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
- : NullRegion;
- CheckPhysLimits(pDev, pSprite->current, generateEvents,
- confineToScreen, pWin->drawable.pScreen);
- }
-}
-
-Bool
-PointerConfinedToScreen(DeviceIntPtr pDev)
-{
- return pDev->spriteInfo->sprite->confined;
-}
-
-/**
- * Update the sprite cursor to the given cursor.
- *
- * ChangeToCursor() will display the new cursor and free the old cursor (if
- * applicable). If the provided cursor is already the updated cursor, nothing
- * happens.
- */
-static void
-ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
- ScreenPtr pScreen;
-
- if (cursor != pSprite->current)
- {
- if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
- (pSprite->current->bits->yhot != cursor->bits->yhot))
- CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
- (ScreenPtr)NULL);
-#ifdef PANORAMIX
- /* XXX: is this really necessary?? (whot) */
- if (!noPanoramiXExtension)
- pScreen = pSprite->screen;
- else
-#endif
- pScreen = pSprite->hotPhys.pScreen;
-
- (*pScreen->DisplayCursor)(pDev, pScreen, cursor);
- FreeCursor(pSprite->current, (Cursor)0);
- pSprite->current = cursor;
- pSprite->current->refcnt++;
- }
-}
-
-/**
- * @returns true if b is a descendent of a
- */
-Bool
-IsParent(WindowPtr a, WindowPtr b)
-{
- for (b = b->parent; b; b = b->parent)
- if (b == a) return TRUE;
- return FALSE;
-}
-
-/**
- * Update the cursor displayed on the screen.
- *
- * Called whenever a cursor may have changed shape or position.
- */
-static void
-PostNewCursor(DeviceIntPtr pDev)
-{
- WindowPtr win;
- GrabPtr grab = pDev->deviceGrab.grab;
- SpritePtr pSprite = pDev->spriteInfo->sprite;
- CursorPtr pCursor;
-
- if (syncEvents.playingEvents)
- return;
- if (grab)
- {
- if (grab->cursor)
- {
- ChangeToCursor(pDev, grab->cursor);
- return;
- }
- if (IsParent(grab->window, pSprite->win))
- win = pSprite->win;
- else
- win = grab->window;
- }
- else
- win = pSprite->win;
- for (; win; win = win->parent)
- {
- if (win->optional)
- {
- pCursor = WindowGetDeviceCursor(win, pDev);
- if (!pCursor && win->optional->cursor != NullCursor)
- pCursor = win->optional->cursor;
- if (pCursor)
- {
- ChangeToCursor(pDev, pCursor);
- return;
- }
- }
- }
-}
-
-
-/**
- * @param dev device which you want to know its current root window
- * @return root window where dev's sprite is located
- */
-WindowPtr
-GetCurrentRootWindow(DeviceIntPtr dev)
-{
- return RootWindow(dev);
-}
-
-/**
- * @return window underneath the cursor sprite.
- */
-WindowPtr
-GetSpriteWindow(DeviceIntPtr pDev)
-{
- return pDev->spriteInfo->sprite->win;
-}
-
-/**
- * @return current sprite cursor.
- */
-CursorPtr
-GetSpriteCursor(DeviceIntPtr pDev)
-{
- return pDev->spriteInfo->sprite->current;
-}
-
-/**
- * Set x/y current sprite position in screen coordinates.
- */
-void
-GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
- *px = pSprite->hotPhys.x;
- *py = pSprite->hotPhys.y;
-}
-
-#ifdef PANORAMIX
-int
-XineramaGetCursorScreen(DeviceIntPtr pDev)
-{
- if(!noPanoramiXExtension) {
- return pDev->spriteInfo->sprite->screen->myNum;
- } else {
- return 0;
- }
-}
-#endif /* PANORAMIX */
-
-#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
-
-static void
-MonthChangedOrBadTime(InternalEvent *ev)
-{
- /* If the ddx/OS is careless about not processing timestamped events from
- * different sources in sorted order, then it's possible for time to go
- * backwards when it should not. Here we ensure a decent time.
- */
- if ((currentTime.milliseconds - ev->any.time) > TIMESLOP)
- currentTime.months++;
- else
- ev->any.time = currentTime.milliseconds;
-}
-
-static void
-NoticeTime(InternalEvent *ev)
-{
- if (ev->any.time < currentTime.milliseconds)
- MonthChangedOrBadTime(ev);
- currentTime.milliseconds = ev->any.time;
- lastDeviceEventTime = currentTime;
-}
-
-void
-NoticeEventTime(InternalEvent *ev)
-{
- if (!syncEvents.playingEvents)
- NoticeTime(ev);
-}
-
-/**************************************************************************
- * The following procedures deal with synchronous events *
- **************************************************************************/
-
-/**
- * EnqueueEvent is a device's processInputProc if a device is frozen.
- * Instead of delivering the events to the client, the event is tacked onto a
- * linked list for later delivery.
- */
-void
-EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
-{
- QdEventPtr tail = *syncEvents.pendtail;
- QdEventPtr qe;
- SpritePtr pSprite = device->spriteInfo->sprite;
- int eventlen;
- DeviceEvent *event = &ev->device_event;
-
- NoticeTime((InternalEvent*)event);
-
- /* Fix for key repeating bug. */
- if (device->key != NULL && device->key->xkbInfo != NULL &&
- event->type == ET_KeyRelease)
- AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
-
- if (DeviceEventCallback)
- {
- DeviceEventInfoRec eventinfo;
-
- /* The RECORD spec says that the root window field of motion events
- * must be valid. At this point, it hasn't been filled in yet, so
- * we do it here. The long expression below is necessary to get
- * the current root window; the apparently reasonable alternative
- * GetCurrentRootWindow()->drawable.id doesn't give you the right
- * answer on the first motion event after a screen change because
- * the data that GetCurrentRootWindow relies on hasn't been
- * updated yet.
- */
- if (ev->any.type == ET_Motion)
- ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
-
- eventinfo.event = ev;
- eventinfo.device = device;
- CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
- }
-
- if (event->type == ET_Motion)
- {
-#ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
- event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
- }
-#endif
- pSprite->hotPhys.x = event->root_x;
- pSprite->hotPhys.y = event->root_y;
- /* do motion compression, but not if from different devices */
- if (tail &&
- (tail->event->any.type == ET_Motion) &&
- (tail->device == device) &&
- (tail->pScreen == pSprite->hotPhys.pScreen))
- {
- DeviceEvent *tailev = &tail->event->device_event;
- tailev->root_x = pSprite->hotPhys.x;
- tailev->root_y = pSprite->hotPhys.y;
- tailev->time = event->time;
- tail->months = currentTime.months;
- return;
- }
- }
-
- eventlen = event->length;
-
- qe = malloc(sizeof(QdEventRec) + eventlen);
- if (!qe)
- return;
- qe->next = (QdEventPtr)NULL;
- qe->device = device;
- qe->pScreen = pSprite->hotPhys.pScreen;
- qe->months = currentTime.months;
- qe->event = (InternalEvent *)(qe + 1);
- memcpy(qe->event, event, eventlen);
- if (tail)
- syncEvents.pendtail = &tail->next;
- *syncEvents.pendtail = qe;
-}
-
-/**
- * Run through the list of events queued up in syncEvents.
- * For each event do:
- * If the device for this event is not frozen anymore, take it and process it
- * as usually.
- * After that, check if there's any devices in the list that are not frozen.
- * If there is none, we're done. If there is at least one device that is not
- * frozen, then re-run from the beginning of the event queue.
- */
-static void
-PlayReleasedEvents(void)
-{
- QdEventPtr *prev, qe;
- DeviceIntPtr dev;
- DeviceIntPtr pDev;
-
- prev = &syncEvents.pending;
- while ( (qe = *prev) )
- {
- if (!qe->device->deviceGrab.sync.frozen)
- {
- *prev = qe->next;
- pDev = qe->device;
- if (*syncEvents.pendtail == *prev)
- syncEvents.pendtail = prev;
- if (qe->event->any.type == ET_Motion)
- CheckVirtualMotion(pDev, qe, NullWindow);
- syncEvents.time.months = qe->months;
- syncEvents.time.milliseconds = qe->event->any.time;
-#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) {
- DeviceEvent *ev = &qe->event->device_event;
- switch(ev->type)
- {
- case ET_Motion:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- ev->root_x += screenInfo.screens[0]->x -
- pDev->spriteInfo->sprite->screen->x;
- ev->root_y += screenInfo.screens[0]->y -
- pDev->spriteInfo->sprite->screen->y;
- break;
- default:
- break;
- }
-
- }
-#endif
- (*qe->device->public.processInputProc)(qe->event, qe->device);
- free(qe);
- for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
- ;
- if (!dev)
- break;
- /* Playing the event may have unfrozen another device. */
- /* So to play it safe, restart at the head of the queue */
- prev = &syncEvents.pending;
- }
- else
- prev = &qe->next;
- }
-}
-
-/**
- * Freeze or thaw the given devices. The device's processing proc is
- * switched to either the real processing proc (in case of thawing) or an
- * enqueuing processing proc (usually EnqueueEvent()).
- *
- * @param dev The device to freeze/thaw
- * @param frozen True to freeze or false to thaw.
- */
-static void
-FreezeThaw(DeviceIntPtr dev, Bool frozen)
-{
- dev->deviceGrab.sync.frozen = frozen;
- if (frozen)
- dev->public.processInputProc = dev->public.enqueueInputProc;
- else
- dev->public.processInputProc = dev->public.realInputProc;
-}
-
-/**
- * Unfreeze devices and replay all events to the respective clients.
- *
- * ComputeFreezes takes the first event in the device's frozen event queue. It
- * runs up the sprite tree (spriteTrace) and searches for the window to replay
- * the events from. If it is found, it checks for passive grabs one down from
- * the window or delivers the events.
- */
-static void
-ComputeFreezes(void)
-{
- DeviceIntPtr replayDev = syncEvents.replayDev;
- WindowPtr w;
- GrabPtr grab;
- DeviceIntPtr dev;
-
- for (dev = inputInfo.devices; dev; dev = dev->next)
- FreezeThaw(dev, dev->deviceGrab.sync.other ||
- (dev->deviceGrab.sync.state >= FROZEN));
- if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
- return;
- syncEvents.playingEvents = TRUE;
- if (replayDev)
- {
- DeviceEvent* event = replayDev->deviceGrab.sync.event;
-
- syncEvents.replayDev = (DeviceIntPtr)NULL;
-
- w = XYToWindow(replayDev, event->root_x, event->root_y);
- if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin))
- {
- if (replayDev->focus && !IsPointerEvent((InternalEvent*)event))
- DeliverFocusedEvent(replayDev, (InternalEvent*)event, w);
- else
- DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab,
- NullWindow, replayDev);
- }
- }
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (!dev->deviceGrab.sync.frozen)
- {
- PlayReleasedEvents();
- break;
- }
- }
- syncEvents.playingEvents = FALSE;
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (DevHasCursor(dev))
- {
- /* the following may have been skipped during replay,
- so do it now */
- if ((grab = dev->deviceGrab.grab) && grab->confineTo)
- {
- if (grab->confineTo->drawable.pScreen !=
- dev->spriteInfo->sprite->hotPhys.pScreen)
- dev->spriteInfo->sprite->hotPhys.x =
- dev->spriteInfo->sprite->hotPhys.y = 0;
- ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
- }
- else
- ConfineCursorToWindow(dev,
- dev->spriteInfo->sprite->hotPhys.pScreen->root,
- TRUE, FALSE);
- PostNewCursor(dev);
- }
- }
-}
-
-#ifdef RANDR
-void
-ScreenRestructured (ScreenPtr pScreen)
-{
- GrabPtr grab;
- DeviceIntPtr pDev;
-
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (!DevHasCursor(pDev))
- continue;
-
- /* GrabDevice doesn't have a confineTo field, so we don't need to
- * worry about it. */
- if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
- {
- if (grab->confineTo->drawable.pScreen
- != pDev->spriteInfo->sprite->hotPhys.pScreen)
- pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
- ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
- }
- else
- ConfineCursorToWindow(pDev,
- pDev->spriteInfo->sprite->hotPhys.pScreen->root,
- TRUE, FALSE);
- }
-}
-#endif
-
-static void
-CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
-{
- GrabPtr grab = thisDev->deviceGrab.grab;
- DeviceIntPtr dev;
-
- if (thisMode == GrabModeSync)
- thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
- else
- { /* free both if same client owns both */
- thisDev->deviceGrab.sync.state = THAWED;
- if (thisDev->deviceGrab.sync.other &&
- (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
- CLIENT_BITS(grab->resource)))
- thisDev->deviceGrab.sync.other = NullGrab;
- }
-
- if (IsMaster(thisDev))
- {
- dev = GetPairedDevice(thisDev);
- if (otherMode == GrabModeSync)
- dev->deviceGrab.sync.other = grab;
- else
- { /* free both if same client owns both */
- if (dev->deviceGrab.sync.other &&
- (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
- CLIENT_BITS(grab->resource)))
- dev->deviceGrab.sync.other = NullGrab;
- }
- }
- ComputeFreezes();
-}
-
-/**
- * Save the device's master device id. This needs to be done
- * if a client directly grabs a slave device that is attached to a master. For
- * the duration of the grab, the device is detached, ungrabbing re-attaches it
- * though.
- *
- * We store the ID of the master device only in case the master disappears
- * while the device has a grab.
- */
-static void
-DetachFromMaster(DeviceIntPtr dev)
-{
- if (!dev->u.master)
- return;
-
- dev->saved_master_id = dev->u.master->id;
-
- AttachDevice(NULL, dev, NULL);
-}
-
-static void
-ReattachToOldMaster(DeviceIntPtr dev)
-{
- DeviceIntPtr master = NULL;
-
- if (IsMaster(dev))
- return;
-
- dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
-
- if (master)
- {
- AttachDevice(serverClient, dev, master);
- dev->saved_master_id = 0;
- }
-}
-
-/**
- * Activate a pointer grab on the given device. A pointer grab will cause all
- * core pointer events of this device to be delivered to the grabbing client only.
- * No other device will send core events to the grab client while the grab is
- * on, but core events will be sent to other clients.
- * Can cause the cursor to change if a grab cursor is set.
- *
- * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
- * is an implicit grab caused by a ButtonPress event.
- *
- * @param mouse The device to grab.
- * @param grab The grab structure, needs to be setup.
- * @param autoGrab True if the grab was caused by a button down event and not
- * explicitely by a client.
- */
-void
-ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
- TimeStamp time, Bool autoGrab)
-{
- GrabInfoPtr grabinfo = &mouse->deviceGrab;
- WindowPtr oldWin = (grabinfo->grab) ?
- grabinfo->grab->window
- : mouse->spriteInfo->sprite->win;
- Bool isPassive = autoGrab & ~ImplicitGrabMask;
-
- /* slave devices need to float for the duration of the grab. */
- if (grab->grabtype == GRABTYPE_XI2 &&
- !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
- DetachFromMaster(mouse);
-
- if (grab->confineTo)
- {
- if (grab->confineTo->drawable.pScreen
- != mouse->spriteInfo->sprite->hotPhys.pScreen)
- mouse->spriteInfo->sprite->hotPhys.x =
- mouse->spriteInfo->sprite->hotPhys.y = 0;
- ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
- }
- DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
- mouse->valuator->motionHintWindow = NullWindow;
- if (syncEvents.playingEvents)
- grabinfo->grabTime = syncEvents.time;
- else
- grabinfo->grabTime = time;
- if (grab->cursor)
- grab->cursor->refcnt++;
- grabinfo->activeGrab = *grab;
- grabinfo->grab = &grabinfo->activeGrab;
- grabinfo->fromPassiveGrab = isPassive;
- grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
- PostNewCursor(mouse);
- CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
-}
-
-/**
- * Delete grab on given device, update the sprite.
- *
- * Extension devices are set up for ActivateKeyboardGrab().
- */
-void
-DeactivatePointerGrab(DeviceIntPtr mouse)
-{
- GrabPtr grab = mouse->deviceGrab.grab;
- DeviceIntPtr dev;
- Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
- mouse->deviceGrab.implicitGrab);
-
- mouse->valuator->motionHintWindow = NullWindow;
- mouse->deviceGrab.grab = NullGrab;
- mouse->deviceGrab.sync.state = NOT_GRABBED;
- mouse->deviceGrab.fromPassiveGrab = FALSE;
-
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->deviceGrab.sync.other == grab)
- dev->deviceGrab.sync.other = NullGrab;
- }
- DoEnterLeaveEvents(mouse, mouse->id, grab->window,
- mouse->spriteInfo->sprite->win, NotifyUngrab);
- if (grab->confineTo)
- ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE);
- PostNewCursor(mouse);
- if (grab->cursor)
- FreeCursor(grab->cursor, (Cursor)0);
-
- if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
- ReattachToOldMaster(mouse);
-
- ComputeFreezes();
-}
-
-/**
- * Activate a keyboard grab on the given device.
- *
- * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
- */
-void
-ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
-{
- GrabInfoPtr grabinfo = &keybd->deviceGrab;
- WindowPtr oldWin;
-
- /* slave devices need to float for the duration of the grab. */
- if (grab->grabtype == GRABTYPE_XI2 &&
- !(passive & ImplicitGrabMask) &&
- !IsMaster(keybd))
- DetachFromMaster(keybd);
-
- if (grabinfo->grab)
- oldWin = grabinfo->grab->window;
- else if (keybd->focus)
- oldWin = keybd->focus->win;
- else
- oldWin = keybd->spriteInfo->sprite->win;
- if (oldWin == FollowKeyboardWin)
- oldWin = keybd->focus->win;
- if (keybd->valuator)
- keybd->valuator->motionHintWindow = NullWindow;
- DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
- if (syncEvents.playingEvents)
- grabinfo->grabTime = syncEvents.time;
- else
- grabinfo->grabTime = time;
- grabinfo->activeGrab = *grab;
- grabinfo->grab = &grabinfo->activeGrab;
- grabinfo->fromPassiveGrab = passive;
- grabinfo->implicitGrab = passive & ImplicitGrabMask;
- CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
-}
-
-/**
- * Delete keyboard grab for the given device.
- */
-void
-DeactivateKeyboardGrab(DeviceIntPtr keybd)
-{
- GrabPtr grab = keybd->deviceGrab.grab;
- DeviceIntPtr dev;
- WindowPtr focusWin = keybd->focus ? keybd->focus->win
- : keybd->spriteInfo->sprite->win;
- Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
- keybd->deviceGrab.implicitGrab);
-
- if (focusWin == FollowKeyboardWin)
- focusWin = inputInfo.keyboard->focus->win;
- if (keybd->valuator)
- keybd->valuator->motionHintWindow = NullWindow;
- keybd->deviceGrab.grab = NullGrab;
- keybd->deviceGrab.sync.state = NOT_GRABBED;
- keybd->deviceGrab.fromPassiveGrab = FALSE;
-
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->deviceGrab.sync.other == grab)
- dev->deviceGrab.sync.other = NullGrab;
- }
- DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
-
- if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
- ReattachToOldMaster(keybd);
-
- ComputeFreezes();
-}
-
-void
-AllowSome(ClientPtr client,
- TimeStamp time,
- DeviceIntPtr thisDev,
- int newState)
-{
- Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
- TimeStamp grabTime;
- DeviceIntPtr dev;
- GrabInfoPtr devgrabinfo,
- grabinfo = &thisDev->deviceGrab;
-
- thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
- thisSynced = FALSE;
- otherGrabbed = FALSE;
- othersFrozen = FALSE;
- grabTime = grabinfo->grabTime;
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- devgrabinfo = &dev->deviceGrab;
-
- if (dev == thisDev)
- continue;
- if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
- {
- if (!(thisGrabbed || otherGrabbed) ||
- (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
- grabTime = devgrabinfo->grabTime;
- otherGrabbed = TRUE;
- if (grabinfo->sync.other == devgrabinfo->grab)
- thisSynced = TRUE;
- if (devgrabinfo->sync.state >= FROZEN)
- othersFrozen = TRUE;
- }
- }
- if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
- return;
- if ((CompareTimeStamps(time, currentTime) == LATER) ||
- (CompareTimeStamps(time, grabTime) == EARLIER))
- return;
- switch (newState)
- {
- case THAWED: /* Async */
- if (thisGrabbed)
- grabinfo->sync.state = THAWED;
- if (thisSynced)
- grabinfo->sync.other = NullGrab;
- ComputeFreezes();
- break;
- case FREEZE_NEXT_EVENT: /* Sync */
- if (thisGrabbed)
- {
- grabinfo->sync.state = FREEZE_NEXT_EVENT;
- if (thisSynced)
- grabinfo->sync.other = NullGrab;
- ComputeFreezes();
- }
- break;
- case THAWED_BOTH: /* AsyncBoth */
- if (othersFrozen)
- {
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- devgrabinfo = &dev->deviceGrab;
- if (devgrabinfo->grab
- && SameClient(devgrabinfo->grab, client))
- devgrabinfo->sync.state = THAWED;
- if (devgrabinfo->sync.other &&
- SameClient(devgrabinfo->sync.other, client))
- devgrabinfo->sync.other = NullGrab;
- }
- ComputeFreezes();
- }
- break;
- case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */
- if (othersFrozen)
- {
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- devgrabinfo = &dev->deviceGrab;
- if (devgrabinfo->grab
- && SameClient(devgrabinfo->grab, client))
- devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
- if (devgrabinfo->sync.other
- && SameClient(devgrabinfo->sync.other, client))
- devgrabinfo->sync.other = NullGrab;
- }
- ComputeFreezes();
- }
- break;
- case NOT_GRABBED: /* Replay */
- if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
- {
- if (thisSynced)
- grabinfo->sync.other = NullGrab;
- syncEvents.replayDev = thisDev;
- syncEvents.replayWin = grabinfo->grab->window;
- (*grabinfo->DeactivateGrab)(thisDev);
- syncEvents.replayDev = (DeviceIntPtr)NULL;
- }
- break;
- case THAW_OTHERS: /* AsyncOthers */
- if (othersFrozen)
- {
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev == thisDev)
- continue;
- devgrabinfo = &dev->deviceGrab;
- if (devgrabinfo->grab
- && SameClient(devgrabinfo->grab, client))
- devgrabinfo->sync.state = THAWED;
- if (devgrabinfo->sync.other
- && SameClient(devgrabinfo->sync.other, client))
- devgrabinfo->sync.other = NullGrab;
- }
- ComputeFreezes();
- }
- break;
- }
-}
-
-/**
- * Server-side protocol handling for AllowEvents request.
- *
- * Release some events from a frozen device.
- */
-int
-ProcAllowEvents(ClientPtr client)
-{
- TimeStamp time;
- DeviceIntPtr mouse = NULL;
- DeviceIntPtr keybd = NULL;
- REQUEST(xAllowEventsReq);
-
- REQUEST_SIZE_MATCH(xAllowEventsReq);
- time = ClientTimeToServerTime(stuff->time);
-
- mouse = PickPointer(client);
- keybd = PickKeyboard(client);
-
- switch (stuff->mode)
- {
- case ReplayPointer:
- AllowSome(client, time, mouse, NOT_GRABBED);
- break;
- case SyncPointer:
- AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
- break;
- case AsyncPointer:
- AllowSome(client, time, mouse, THAWED);
- break;
- case ReplayKeyboard:
- AllowSome(client, time, keybd, NOT_GRABBED);
- break;
- case SyncKeyboard:
- AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
- break;
- case AsyncKeyboard:
- AllowSome(client, time, keybd, THAWED);
- break;
- case SyncBoth:
- AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
- break;
- case AsyncBoth:
- AllowSome(client, time, keybd, THAWED_BOTH);
- break;
- default:
- client->errorValue = stuff->mode;
- return BadValue;
- }
- return Success;
-}
-
-/**
- * Deactivate grabs from any device that has been grabbed by the client.
- */
-void
-ReleaseActiveGrabs(ClientPtr client)
-{
- DeviceIntPtr dev;
- Bool done;
-
- /* XXX CloseDownClient should remove passive grabs before
- * releasing active grabs.
- */
- do {
- done = TRUE;
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
- {
- (*dev->deviceGrab.DeactivateGrab)(dev);
- done = FALSE;
- }
- }
- } while (!done);
-}
-
-/**************************************************************************
- * The following procedures deal with delivering events *
- **************************************************************************/
-
-/**
- * Deliver the given events to the given client.
- *
- * More than one event may be delivered at a time. This is the case with
- * DeviceMotionNotifies which may be followed by DeviceValuator events.
- *
- * TryClientEvents() is the last station before actually writing the events to
- * the socket. Anything that is not filtered here, will get delivered to the
- * client.
- * An event is only delivered if
- * - mask and filter match up.
- * - no other client has a grab on the device that caused the event.
- *
- *
- * @param client The target client to deliver to.
- * @param dev The device the event came from. May be NULL.
- * @param pEvents The events to be delivered.
- * @param count Number of elements in pEvents.
- * @param mask Event mask as set by the window.
- * @param filter Mask based on event type.
- * @param grab Possible grab on the device that caused the event.
- *
- * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
- * client.
- */
-int
-TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
- int count, Mask mask, Mask filter, GrabPtr grab)
-{
- int type;
-
-#ifdef DEBUG_EVENTS
- ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
- pEvents->u.u.type, pEvents->u.u.detail, mask,
- client ? client->index : -1,
- (client && client->clientGone) ? " (gone)" : "");
-#endif
-
- if (!client || client == serverClient || client->clientGone) {
-#ifdef DEBUG_EVENTS
- ErrorF(" not delivered to fake/dead client\n");
-#endif
- return 0;
- }
-
- if (filter != CantBeFiltered && !(mask & filter))
- {
- #ifdef DEBUG_EVENTS
- ErrorF(" filtered\n");
- #endif
- return 0;
- }
-
- if (grab && !SameClient(grab, client))
- {
-#ifdef DEBUG_EVENTS
- ErrorF(" not delivered due to grab\n");
-#endif
- return -1; /* don't send, but notify caller */
- }
-
- type = pEvents->u.u.type;
- if (type == MotionNotify)
- {
- if (mask & PointerMotionHintMask)
- {
- if (WID(dev->valuator->motionHintWindow) ==
- pEvents->u.keyButtonPointer.event)
- {
-#ifdef DEBUG_EVENTS
- ErrorF("[dix] \n");
- ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
-#endif
- return 1; /* don't send, but pretend we did */
- }
- pEvents->u.u.detail = NotifyHint;
- }
- else
- {
- pEvents->u.u.detail = NotifyNormal;
- }
- }
- else if (type == DeviceMotionNotify)
- {
- if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents,
- mask) != 0)
- return 1;
- } else if (type == KeyPress)
- {
- if (EventIsKeyRepeat(pEvents))
- {
- if (!_XkbWantsDetectableAutoRepeat(client))
- {
- xEvent release = *pEvents;
- release.u.u.type = KeyRelease;
- WriteEventsToClient(client, 1, &release);
-#ifdef DEBUG_EVENTS
- ErrorF(" (plus fake core release for repeat)");
-#endif
- } else
- {
-#ifdef DEBUG_EVENTS
- ErrorF(" (detectable autorepeat for core)");
-#endif
- }
- }
-
- } else if (type == DeviceKeyPress)
- {
- if (EventIsKeyRepeat(pEvents))
- {
- if (!_XkbWantsDetectableAutoRepeat(client))
- {
- deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents;
- release.type = DeviceKeyRelease;
-#ifdef DEBUG_EVENTS
- ErrorF(" (plus fake xi1 release for repeat)");
-#endif
- WriteEventsToClient(client, 1, (xEvent *) &release);
- }
- else {
-#ifdef DEBUG_EVENTS
- ErrorF(" (detectable autorepeat for core)");
-#endif
- }
- }
- }
-
- if (BitIsOn(criticalEvents, type))
- {
- if (client->smart_priority < SMART_MAX_PRIORITY)
- client->smart_priority++;
- SetCriticalOutputPending();
- }
-
- WriteEventsToClient(client, count, pEvents);
-#ifdef DEBUG_EVENTS
- ErrorF("[dix] delivered\n");
-#endif
- return 1;
-}
-
-/**
- * Deliver events to a window. At this point, we do not yet know if the event
- * actually needs to be delivered. May activate a grab if the event is a
- * button press.
- *
- * Core events are always delivered to the window owner. If the filter is
- * something other than CantBeFiltered, the event is also delivered to other
- * clients with the matching mask on the window.
- *
- * More than one event may be delivered at a time. This is the case with
- * DeviceMotionNotifies which may be followed by DeviceValuator events.
- *
- * @param pWin The window that would get the event.
- * @param pEvents The events to be delivered.
- * @param count Number of elements in pEvents.
- * @param filter Mask based on event type.
- * @param grab Possible grab on the device that caused the event.
- *
- * @return Number of events delivered to various clients.
- */
-int
-DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
- *pEvents, int count, Mask filter, GrabPtr grab)
-{
- int deliveries = 0, nondeliveries = 0;
- int attempt;
- InputClients *other;
- ClientPtr client = NullClient;
- Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
- this mask is the mask of the grab. */
- int type = pEvents->u.u.type;
-
-
- /* Deliver to window owner */
- if ((filter == CantBeFiltered) || CORE_EVENT(pEvents))
- {
- /* if nobody ever wants to see this event, skip some work */
- if (filter != CantBeFiltered &&
- !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
- return 0;
-
- if (IsInterferingGrab(wClient(pWin), pDev, pEvents))
- return 0;
-
- if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
- /* do nothing */;
- else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents,
- count, pWin->eventMask,
- filter, grab)) )
- {
- if (attempt > 0)
- {
- deliveries++;
- client = wClient(pWin);
- deliveryMask = pWin->eventMask;
- } else
- nondeliveries--;
- }
- }
-
- /* CantBeFiltered means only window owner gets the event */
- if (filter != CantBeFiltered)
- {
- if (CORE_EVENT(pEvents))
- other = (InputClients *)wOtherClients(pWin);
- else if (XI2_EVENT(pEvents))
- {
- OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
- /* Has any client selected for the event? */
- if (!GetWindowXI2Mask(pDev, pWin, pEvents))
- return 0;
- other = inputMasks->inputClients;
- } else {
- OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
- /* Has any client selected for the event? */
- if (!inputMasks ||
- !(inputMasks->inputEvents[pDev->id] & filter))
- return 0;
-
- other = inputMasks->inputClients;
- }
-
- for (; other; other = other->next)
- {
- Mask mask;
- if (IsInterferingGrab(rClient(other), pDev, pEvents))
- continue;
-
- mask = GetEventMask(pDev, pEvents, other);
-
- if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
- pEvents, count))
- /* do nothing */;
- else if ( (attempt = TryClientEvents(rClient(other), pDev,
- pEvents, count,
- mask, filter, grab)) )
- {
- if (attempt > 0)
- {
- deliveries++;
- client = rClient(other);
- deliveryMask = mask;
- } else
- nondeliveries--;
- }
- }
- }
- /*
- * Note that since core events are delivered first, an implicit grab may
- * be activated on a core grab, stopping the XI events.
- */
- if ((type == DeviceButtonPress || type == ButtonPress ||
- ((XI2_EVENT(pEvents) && ((xGenericEvent*)pEvents)->evtype == XI_ButtonPress)))
- && deliveries
- && (!grab))
- {
- GrabRec tempGrab;
- OtherInputMasks *inputMasks;
-
- memset(&tempGrab, 0, sizeof(GrabRec));
- tempGrab.next = NULL;
- tempGrab.device = pDev;
- tempGrab.resource = client->clientAsMask;
- tempGrab.window = pWin;
- tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
- tempGrab.eventMask = deliveryMask;
- tempGrab.keyboardMode = GrabModeAsync;
- tempGrab.pointerMode = GrabModeAsync;
- tempGrab.confineTo = NullWindow;
- tempGrab.cursor = NullCursor;
- tempGrab.type = type;
- if (type == ButtonPress)
- tempGrab.grabtype = GRABTYPE_CORE;
- else if (type == DeviceButtonPress)
- tempGrab.grabtype = GRABTYPE_XI;
- else
- {
- tempGrab.type = ((xGenericEvent*)pEvents)->evtype;
- tempGrab.grabtype = GRABTYPE_XI2;
- }
-
- /* get the XI and XI2 device mask */
- inputMasks = wOtherInputMasks(pWin);
- tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
-
- if (inputMasks)
- memcpy(tempGrab.xi2mask, inputMasks->xi2mask,
- sizeof(tempGrab.xi2mask));
-
- (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab,
- currentTime, TRUE | ImplicitGrabMask);
- }
- else if ((type == MotionNotify) && deliveries)
- pDev->valuator->motionHintWindow = pWin;
- else
- {
- if ((type == DeviceMotionNotify || type == DeviceButtonPress) &&
- deliveries)
- CheckDeviceGrabAndHintWindow (pWin, type,
- (deviceKeyButtonPointer*) pEvents,
- grab, client, deliveryMask);
- }
- if (deliveries)
- return deliveries;
- return nondeliveries;
-}
-
-/* If the event goes to dontClient, don't send it and return 0. if
- send works, return 1 or if send didn't work, return 2.
- Only works for core events.
-*/
-
-#ifdef PANORAMIX
-static int
-XineramaTryClientEventsResult(
- ClientPtr client,
- GrabPtr grab,
- Mask mask,
- Mask filter
-){
- if ((client) && (client != serverClient) && (!client->clientGone) &&
- ((filter == CantBeFiltered) || (mask & filter)))
- {
- if (grab && !SameClient(grab, client)) return -1;
- else return 1;
- }
- return 0;
-}
-#endif
-
-/**
- * Try to deliver events to the interested parties.
- *
- * @param pWin The window that would get the event.
- * @param pEvents The events to be delivered.
- * @param count Number of elements in pEvents.
- * @param filter Mask based on event type.
- * @param dontClient Don't deliver to the dontClient.
- */
-int
-MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
- int count, Mask filter, ClientPtr dontClient)
-{
- OtherClients *other;
-
-
- if (pWin->eventMask & filter)
- {
- if (wClient(pWin) == dontClient)
- return 0;
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
- return XineramaTryClientEventsResult(
- wClient(pWin), NullGrab, pWin->eventMask, filter);
-#endif
- if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
- return 1; /* don't send, but pretend we did */
- return TryClientEvents(wClient(pWin), NULL, pEvents, count,
- pWin->eventMask, filter, NullGrab);
- }
- for (other = wOtherClients(pWin); other; other = other->next)
- {
- if (other->mask & filter)
- {
- if (SameClient(other, dontClient))
- return 0;
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
- return XineramaTryClientEventsResult(
- rClient(other), NullGrab, other->mask, filter);
-#endif
- if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
- count))
- return 1; /* don't send, but pretend we did */
- return TryClientEvents(rClient(other), NULL, pEvents, count,
- other->mask, filter, NullGrab);
- }
- }
- return 2;
-}
-
-static Window FindChildForEvent(DeviceIntPtr dev, WindowPtr event)
-{
- SpritePtr pSprite = dev->spriteInfo->sprite;
- WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1];
- Window child = None;
-
- /* If the search ends up past the root should the child field be
- set to none or should the value in the argument be passed
- through. It probably doesn't matter since everyone calls
- this function with child == None anyway. */
- while (w)
- {
- /* If the source window is same as event window, child should be
- none. Don't bother going all all the way back to the root. */
-
- if (w == event)
- {
- child = None;
- break;
- }
-
- if (w->parent == event)
- {
- child = w->drawable.id;
- break;
- }
- w = w->parent;
- }
- return child;
-}
-
-/**
- * Adjust event fields to comply with the window properties.
- *
- * @param xE Event to be modified in place
- * @param pWin The window to get the information from.
- * @param child Child window setting for event (if applicable)
- * @param calcChild If True, calculate the child window.
- */
-void
-FixUpEventFromWindow(
- DeviceIntPtr pDev,
- xEvent *xE,
- WindowPtr pWin,
- Window child,
- Bool calcChild)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
-
- if (calcChild)
- child = FindChildForEvent(pDev, pWin);
-
- if (XI2_EVENT(xE))
- {
- xXIDeviceEvent* event = (xXIDeviceEvent*)xE;
-
- if (event->evtype == XI_RawKeyPress ||
- event->evtype == XI_RawKeyRelease ||
- event->evtype == XI_RawButtonPress ||
- event->evtype == XI_RawButtonRelease ||
- event->evtype == XI_RawMotion ||
- event->evtype == XI_DeviceChanged ||
- event->evtype == XI_HierarchyChanged ||
- event->evtype == XI_PropertyEvent)
- return;
-
- event->root = RootWindow(pDev)->drawable.id;
- event->event = pWin->drawable.id;
- if (pSprite->hot.pScreen == pWin->drawable.pScreen)
- {
- event->event_x = event->root_x - FP1616(pWin->drawable.x, 0);
- event->event_y = event->root_y - FP1616(pWin->drawable.y, 0);
- event->child = child;
- } else
- {
- event->event_x = 0;
- event->event_y = 0;
- event->child = None;
- }
-
- if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
- event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
- ((xXIEnterEvent*)event)->same_screen =
- (pSprite->hot.pScreen == pWin->drawable.pScreen);
-
- } else
- {
- XE_KBPTR.root = RootWindow(pDev)->drawable.id;
- XE_KBPTR.event = pWin->drawable.id;
- if (pSprite->hot.pScreen == pWin->drawable.pScreen)
- {
- XE_KBPTR.sameScreen = xTrue;
- XE_KBPTR.child = child;
- XE_KBPTR.eventX =
- XE_KBPTR.rootX - pWin->drawable.x;
- XE_KBPTR.eventY =
- XE_KBPTR.rootY - pWin->drawable.y;
- }
- else
- {
- XE_KBPTR.sameScreen = xFalse;
- XE_KBPTR.child = None;
- XE_KBPTR.eventX = 0;
- XE_KBPTR.eventY = 0;
- }
- }
-}
-
-/**
- * Check if a given event is deliverable at all on a given window.
- *
- * This function only checks if any client wants it, not for a specific
- * client.
- *
- * @param[in] dev The device this event is being sent for.
- * @param[in] event The event that is to be sent.
- * @param[in] win The current event window.
- *
- * @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and
- * ::DONT_PROPAGATE_MASK.
- */
-int
-EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
-{
- int rc = 0;
- int filter = 0;
- int type;
- OtherInputMasks *inputMasks = wOtherInputMasks(win);
- xEvent ev;
-
- /* XXX: this makes me gag */
- type = GetXI2Type(event);
- ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/
- ((xGenericEvent*)&ev)->extension = IReqCode;
- ((xGenericEvent*)&ev)->evtype = type;
- filter = GetEventFilter(dev, &ev);
- if (type && inputMasks &&
- ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) ||
- ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) ||
- (inputMasks->xi2mask[dev->id][type/8] & filter)))
- rc |= XI2_MASK;
-
- type = GetXIType(event);
- ev.u.u.type = type;
- filter = GetEventFilter(dev, &ev);
-
- /* Check for XI mask */
- if (type && inputMasks &&
- (inputMasks->deliverableEvents[dev->id] & filter) &&
- (inputMasks->inputEvents[dev->id] & filter))
- rc |= XI_MASK;
-
- /* Check for XI DontPropagate mask */
- if (type && inputMasks &&
- (inputMasks->dontPropagateMask[dev->id] & filter))
- rc |= DONT_PROPAGATE_MASK;
-
- /* Check for core mask */
- type = GetCoreType(event);
- if (type && (win->deliverableEvents & filter) &&
- ((wOtherEventMasks(win) | win->eventMask) & filter))
- rc |= CORE_MASK;
-
- /* Check for core DontPropagate mask */
- if (type && (filter & wDontPropagateMask(win)))
- rc |= DONT_PROPAGATE_MASK;
-
- return rc;
-}
-
-/**
- * Deliver events caused by input devices.
- *
- * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
- * called directly from the processInputProc.
- * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
- * DeliverDeviceEvents.
- * For focused events, DeliverFocusedEvent is called first, and _may_ call
- * DeliverDeviceEvents.
- *
- * @param pWin Window to deliver event to.
- * @param event The events to deliver, not yet in wire format.
- * @param grab Possible grab on a device.
- * @param stopAt Don't recurse up to the root window.
- * @param dev The device that is responsible for the event.
- *
- * @see DeliverGrabbedEvent
- * @see DeliverFocusedEvent
- */
-int
-DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
- WindowPtr stopAt, DeviceIntPtr dev)
-{
- Window child = None;
- Mask filter;
- int deliveries = 0;
- xEvent core;
- xEvent *xE = NULL;
- int rc, mask, count = 0;
-
- CHECKEVENT(event);
-
- while (pWin)
- {
- if ((mask = EventIsDeliverable(dev, event, pWin)))
- {
- /* XI2 events first */
- if (mask & XI2_MASK)
- {
- xEvent *xi2 = NULL;
- rc = EventToXI2(event, &xi2);
- if (rc == Success)
- {
- /* XXX: XACE */
- filter = GetEventFilter(dev, xi2);
- FixUpEventFromWindow(dev, xi2, pWin, child, FALSE);
- deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1,
- filter, grab);
- free(xi2);
- if (deliveries > 0)
- goto unwind;
- } else if (rc != BadMatch)
- ErrorF("[dix] %s: XI2 conversion failed in DDE (%d).\n",
- dev->name, rc);
- }
-
- /* XI events */
- if (mask & XI_MASK)
- {
- rc = EventToXI(event, &xE, &count);
- if (rc == Success) {
- if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) {
- filter = GetEventFilter(dev, xE);
- FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
- deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
- filter, grab);
- if (deliveries > 0)
- goto unwind;
- }
- } else if (rc != BadMatch)
- ErrorF("[dix] %s: XI conversion failed in DDE (%d, %d). Skipping delivery.\n",
- dev->name, event->any.type, rc);
- }
-
- /* Core event */
- if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents)
- {
- rc = EventToCore(event, &core);
- if (rc == Success) {
- if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) {
- filter = GetEventFilter(dev, &core);
- FixUpEventFromWindow(dev, &core, pWin, child, FALSE);
- deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
- filter, grab);
- if (deliveries > 0)
- goto unwind;
- }
- } else if (rc != BadMatch)
- ErrorF("[dix] %s: Core conversion failed in DDE (%d, %d).\n",
- dev->name, event->any.type, rc);
- }
-
- if ((deliveries < 0) || (pWin == stopAt) ||
- (mask & DONT_PROPAGATE_MASK))
- {
- deliveries = 0;
- goto unwind;
- }
- }
-
- child = pWin->drawable.id;
- pWin = pWin->parent;
- }
-
-unwind:
- free(xE);
- return deliveries;
-}
-
-#undef XI_MASK
-#undef CORE_MASK
-#undef DONT_PROPAGATE_MASK
-
-/**
- * Deliver event to a window and it's immediate parent. Used for most window
- * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
- * propagate up the tree or extension events
- *
- * In case of a ReparentNotify event, the event will be delivered to the
- * otherParent as well.
- *
- * @param pWin Window to deliver events to.
- * @param xE Events to deliver.
- * @param count number of events in xE.
- * @param otherParent Used for ReparentNotify events.
- */
-int
-DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
- WindowPtr otherParent)
-{
- Mask filter;
- int deliveries;
- DeviceIntRec dummy;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
- return count;
-#endif
-
- if (!count)
- return 0;
-
- dummy.id = XIAllDevices;
- filter = GetEventFilter(&dummy, xE);
- if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
- xE->u.destroyNotify.event = pWin->drawable.id;
- if (filter != StructureAndSubMask)
- return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
- deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
- StructureNotifyMask, NullGrab);
- if (pWin->parent)
- {
- xE->u.destroyNotify.event = pWin->parent->drawable.id;
- deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
- SubstructureNotifyMask, NullGrab);
- if (xE->u.u.type == ReparentNotify)
- {
- xE->u.destroyNotify.event = otherParent->drawable.id;
- deliveries += DeliverEventsToWindow(&dummy,
- otherParent, xE, count, SubstructureNotifyMask,
- NullGrab);
- }
- }
- return deliveries;
-}
-
-
-static Bool
-PointInBorderSize(WindowPtr pWin, int x, int y)
-{
- BoxRec box;
-
- if(RegionContainsPoint(&pWin->borderSize, x, y, &box))
- return TRUE;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension &&
- XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
- SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
- int i;
-
- for(i = 1; i < PanoramiXNumScreens; i++) {
- if(RegionContainsPoint(&pSprite->windows[i]->borderSize,
- x + screenInfo.screens[0]->x - screenInfo.screens[i]->x,
- y + screenInfo.screens[0]->y - screenInfo.screens[i]->y,
- &box))
- return TRUE;
- }
- }
-#endif
- return FALSE;
-}
-
-/**
- * Traversed from the root window to the window at the position x/y. While
- * traversing, it sets up the traversal history in the spriteTrace array.
- * After completing, the spriteTrace history is set in the following way:
- * spriteTrace[0] ... root window
- * spriteTrace[1] ... top level window that encloses x/y
- * ...
- * spriteTrace[spriteTraceGood - 1] ... window at x/y
- *
- * @returns the window at the given coordinates.
- */
-static WindowPtr
-XYToWindow(DeviceIntPtr pDev, int x, int y)
-{
- WindowPtr pWin;
- BoxRec box;
- SpritePtr pSprite;
-
- pSprite = pDev->spriteInfo->sprite;
- pSprite->spriteTraceGood = 1; /* root window still there */
- pWin = RootWindow(pDev)->firstChild;
- while (pWin)
- {
- if ((pWin->mapped) &&
- (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
- (x < pWin->drawable.x + (int)pWin->drawable.width +
- wBorderWidth(pWin)) &&
- (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
- (y < pWin->drawable.y + (int)pWin->drawable.height +
- wBorderWidth (pWin))
- /* When a window is shaped, a further check
- * is made to see if the point is inside
- * borderSize
- */
- && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
- && (!wInputShape(pWin) ||
- RegionContainsPoint(wInputShape(pWin),
- x - pWin->drawable.x,
- y - pWin->drawable.y, &box))
-#ifdef ROOTLESS
- /* In rootless mode windows may be offscreen, even when
- * they're in X's stack. (E.g. if the native window system
- * implements some form of virtual desktop system).
- */
- && !pWin->rootlessUnhittable
-#endif
- )
- {
- if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
- {
- pSprite->spriteTraceSize += 10;
- pSprite->spriteTrace = realloc(pSprite->spriteTrace,
- pSprite->spriteTraceSize*sizeof(WindowPtr));
- }
- pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
- pWin = pWin->firstChild;
- }
- else
- pWin = pWin->nextSib;
- }
- return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
-}
-
-/**
- * Ungrab a currently FocusIn grabbed device and grab the device on the
- * given window. If the win given is the NoneWin, the device is ungrabbed if
- * applicable and FALSE is returned.
- *
- * @returns TRUE if the device has been grabbed, or FALSE otherwise.
- */
-BOOL
-ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
-{
- BOOL rc = FALSE;
- DeviceEvent event;
-
- if (dev->deviceGrab.grab)
- {
- if (!dev->deviceGrab.fromPassiveGrab ||
- dev->deviceGrab.grab->type != XI_Enter ||
- dev->deviceGrab.grab->window == win ||
- IsParent(dev->deviceGrab.grab->window, win))
- return FALSE;
- DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
- (*dev->deviceGrab.DeactivateGrab)(dev);
- }
-
- if (win == NoneWin || win == PointerRootWin)
- return FALSE;
-
- memset(&event, 0, sizeof(DeviceEvent));
- event.header = ET_Internal;
- event.type = ET_FocusIn;
- event.length = sizeof(DeviceEvent);
- event.time = GetTimeInMillis();
- event.deviceid = dev->id;
- event.sourceid = dev->id;
- event.detail.button = 0;
- rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE);
- if (rc)
- DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
- return rc;
-}
-
-/**
- * Ungrab a currently Enter grabbed device and grab the device for the given
- * window.
- *
- * @returns TRUE if the device has been grabbed, or FALSE otherwise.
- */
-static BOOL
-ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
-{
- BOOL rc = FALSE;
- DeviceEvent event;
-
- if (dev->deviceGrab.grab)
- {
- if (!dev->deviceGrab.fromPassiveGrab ||
- dev->deviceGrab.grab->type != XI_Enter ||
- dev->deviceGrab.grab->window == win ||
- IsParent(dev->deviceGrab.grab->window, win))
- return FALSE;
- DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
- (*dev->deviceGrab.DeactivateGrab)(dev);
- }
-
- memset(&event, 0, sizeof(DeviceEvent));
- event.header = ET_Internal;
- event.type = ET_Enter;
- event.length = sizeof(DeviceEvent);
- event.time = GetTimeInMillis();
- event.deviceid = dev->id;
- event.sourceid = dev->id;
- event.detail.button = 0;
- rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE);
- if (rc)
- DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
-
- return rc;
-}
-
-/**
- * Update the sprite coordinates based on the event. Update the cursor
- * position, then update the event with the new coordinates that may have been
- * changed. If the window underneath the sprite has changed, change to new
- * cursor and send enter/leave events.
- *
- * CheckMotion() will not do anything and return FALSE if the event is not a
- * pointer event.
- *
- * @return TRUE if the sprite has moved or FALSE otherwise.
- */
-Bool
-CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
-{
- WindowPtr prevSpriteWin, newSpriteWin;
- SpritePtr pSprite = pDev->spriteInfo->sprite;
-
- CHECKEVENT(ev);
-
- prevSpriteWin = pSprite->win;
-
- if (ev && !syncEvents.playingEvents)
- {
- /* GetPointerEvents() guarantees that pointer events have the correct
- rootX/Y set already. */
- switch (ev->type)
- {
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_Motion:
- break;
- default:
- /* all other events return FALSE */
- return FALSE;
- }
-
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- {
- /* Motion events entering DIX get translated to Screen 0
- coordinates. Replayed events have already been
- translated since they've entered DIX before */
- ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
- ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
- } else
-#endif
- {
- if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
- {
- pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
- RootWindow(pDev) = pSprite->hot.pScreen->root;
- }
- }
-
- pSprite->hot.x = ev->root_x;
- pSprite->hot.y = ev->root_y;
- if (pSprite->hot.x < pSprite->physLimits.x1)
- pSprite->hot.x = pSprite->physLimits.x1;
- else if (pSprite->hot.x >= pSprite->physLimits.x2)
- pSprite->hot.x = pSprite->physLimits.x2 - 1;
- if (pSprite->hot.y < pSprite->physLimits.y1)
- pSprite->hot.y = pSprite->physLimits.y1;
- else if (pSprite->hot.y >= pSprite->physLimits.y2)
- pSprite->hot.y = pSprite->physLimits.y2 - 1;
- if (pSprite->hotShape)
- ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
- pSprite->hotPhys = pSprite->hot;
-
- if ((pSprite->hotPhys.x != ev->root_x) ||
- (pSprite->hotPhys.y != ev->root_y))
- {
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- {
- XineramaSetCursorPosition(
- pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
- } else
-#endif
- {
- (*pSprite->hotPhys.pScreen->SetCursorPosition)(
- pDev, pSprite->hotPhys.pScreen,
- pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
- }
- }
-
- ev->root_x = pSprite->hot.x;
- ev->root_y = pSprite->hot.y;
- }
-
- newSpriteWin = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y);
-
- if (newSpriteWin != prevSpriteWin)
- {
- int sourceid;
- if (!ev) {
- UpdateCurrentTimeIf();
- sourceid = pDev->id; /* when from WindowsRestructured */
- } else
- sourceid = ev->sourceid;
-
- if (prevSpriteWin != NullWindow) {
- if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
- DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
- newSpriteWin, NotifyNormal);
- }
- /* set pSprite->win after ActivateEnterGrab, otherwise
- sprite window == grab_window and no enter/leave events are
- sent. */
- pSprite->win = newSpriteWin;
- PostNewCursor(pDev);
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Windows have restructured, we need to update the sprite position and the
- * sprite's cursor.
- */
-void
-WindowsRestructured(void)
-{
- DeviceIntPtr pDev = inputInfo.devices;
- while(pDev)
- {
- if (IsMaster(pDev) || !pDev->u.master)
- CheckMotion(NULL, pDev);
- pDev = pDev->next;
- }
-}
-
-#ifdef PANORAMIX
-/* This was added to support reconfiguration under Xdmx. The problem is
- * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
- * other than 0,0, the information in the private sprite structure must
- * be updated accordingly, or XYToWindow (and other routines) will not
- * compute correctly. */
-void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
-{
- GrabPtr grab;
- DeviceIntPtr pDev;
- SpritePtr pSprite;
-
- if (noPanoramiXExtension) return;
-
- pDev = inputInfo.devices;
- while(pDev)
- {
- if (DevHasCursor(pDev))
- {
- pSprite = pDev->spriteInfo->sprite;
- pSprite->hot.x -= xoff;
- pSprite->hot.y -= yoff;
-
- pSprite->hotPhys.x -= xoff;
- pSprite->hotPhys.y -= yoff;
-
- pSprite->hotLimits.x1 -= xoff;
- pSprite->hotLimits.y1 -= yoff;
- pSprite->hotLimits.x2 -= xoff;
- pSprite->hotLimits.y2 -= yoff;
-
- if (RegionNotEmpty(&pSprite->Reg1))
- RegionTranslate(&pSprite->Reg1, xoff, yoff);
- if (RegionNotEmpty(&pSprite->Reg2))
- RegionTranslate(&pSprite->Reg2, xoff, yoff);
-
- /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
- if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
- if (grab->confineTo->drawable.pScreen
- != pSprite->hotPhys.pScreen)
- pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
- ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
- } else
- ConfineCursorToWindow(
- pDev,
- pSprite->hotPhys.pScreen->root,
- TRUE, FALSE);
-
- }
- pDev = pDev->next;
- }
-}
-#endif
-
-/**
- * Initialize a sprite for the given device and set it to some sane values. If
- * the device already has a sprite alloc'd, don't realloc but just reset to
- * default values.
- * If a window is supplied, the sprite will be initialized with the window's
- * cursor and positioned in the center of the window's screen. The root window
- * is a good choice to pass in here.
- *
- * It's a good idea to call it only for pointer devices, unless you have a
- * really talented keyboard.
- *
- * @param pDev The device to initialize.
- * @param pWin The window where to generate the sprite in.
- *
- */
-void
-InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
-{
- SpritePtr pSprite;
- ScreenPtr pScreen;
- CursorPtr pCursor;
-
- if (!pDev->spriteInfo->sprite)
- {
- DeviceIntPtr it;
-
- pDev->spriteInfo->sprite = (SpritePtr)calloc(1, sizeof(SpriteRec));
- if (!pDev->spriteInfo->sprite)
- FatalError("InitializeSprite: failed to allocate sprite struct");
-
- /* We may have paired another device with this device before our
- * device had a actual sprite. We need to check for this and reset the
- * sprite field for all paired devices.
- *
- * The VCK is always paired with the VCP before the VCP has a sprite.
- */
- for (it = inputInfo.devices; it; it = it->next)
- {
- if (it->spriteInfo->paired == pDev)
- it->spriteInfo->sprite = pDev->spriteInfo->sprite;
- }
- if (inputInfo.keyboard->spriteInfo->paired == pDev)
- inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
- }
-
- pSprite = pDev->spriteInfo->sprite;
- pDev->spriteInfo->spriteOwner = TRUE;
-
- pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
- pSprite->hot.pScreen = pScreen;
- pSprite->hotPhys.pScreen = pScreen;
- if (pScreen)
- {
- pSprite->hotPhys.x = pScreen->width / 2;
- pSprite->hotPhys.y = pScreen->height / 2;
- pSprite->hotLimits.x2 = pScreen->width;
- pSprite->hotLimits.y2 = pScreen->height;
- }
-
- pSprite->hot = pSprite->hotPhys;
- pSprite->win = pWin;
-
- if (pWin)
- {
- pCursor = wCursor(pWin);
- pSprite->spriteTrace = (WindowPtr *)calloc(1, 32*sizeof(WindowPtr));
- if (!pSprite->spriteTrace)
- FatalError("Failed to allocate spriteTrace");
- pSprite->spriteTraceSize = 32;
-
- RootWindow(pDev) = pWin;
- pSprite->spriteTraceGood = 1;
-
- pSprite->pEnqueueScreen = pScreen;
- pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
-
- } else {
- pCursor = NullCursor;
- pSprite->spriteTrace = NULL;
- pSprite->spriteTraceSize = 0;
- pSprite->spriteTraceGood = 0;
- pSprite->pEnqueueScreen = screenInfo.screens[0];
- pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
- }
- if (pCursor)
- pCursor->refcnt++;
- if (pSprite->current)
- FreeCursor(pSprite->current, None);
- pSprite->current = pCursor;
-
- if (pScreen)
- {
- (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current);
- (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
- &pSprite->hotLimits, &pSprite->physLimits);
- pSprite->confined = FALSE;
-
- (*pScreen->ConstrainCursor) (pDev, pScreen,
- &pSprite->physLimits);
- (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
- pSprite->hot.y,
- FALSE);
- (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
- }
-#ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
- pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
- pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
- pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
- pSprite->physLimits = pSprite->hotLimits;
- pSprite->confineWin = NullWindow;
- pSprite->hotShape = NullRegion;
- pSprite->screen = pScreen;
- /* gotta UNINIT these someplace */
- RegionNull(&pSprite->Reg1);
- RegionNull(&pSprite->Reg2);
- }
-#endif
-}
-
-/**
- * Update the mouse sprite info when the server switches from a pScreen to another.
- * Otherwise, the pScreen of the mouse sprite is never updated when we switch
- * from a pScreen to another. Never updating the pScreen of the mouse sprite
- * implies that windows that are in pScreen whose pScreen->myNum >0 will never
- * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen
- * always points to the first pScreen it has been set by
- * DefineInitialRootWindow().
- *
- * Calling this function is useful for use cases where the server
- * has more than one pScreen.
- * This function is similar to DefineInitialRootWindow() but it does not
- * reset the mouse pointer position.
- * @param win must be the new pScreen we are switching to.
- */
-void
-UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- SpritePtr pSprite = NULL;
- WindowPtr win = NULL;
- CursorPtr pCursor;
- if (!pScreen)
- return ;
-
- if (!pDev->spriteInfo->sprite)
- return;
-
- pSprite = pDev->spriteInfo->sprite;
-
- win = pScreen->root;
-
- pSprite->hotPhys.pScreen = pScreen;
- pSprite->hot = pSprite->hotPhys;
- pSprite->hotLimits.x2 = pScreen->width;
- pSprite->hotLimits.y2 = pScreen->height;
- pSprite->win = win;
- pCursor = wCursor(win);
- if (pCursor)
- pCursor->refcnt++;
- if (pSprite->current)
- FreeCursor(pSprite->current, 0);
- pSprite->current = pCursor;
- pSprite->spriteTraceGood = 1;
- pSprite->spriteTrace[0] = win;
- (*pScreen->CursorLimits) (pDev,
- pScreen,
- pSprite->current,
- &pSprite->hotLimits,
- &pSprite->physLimits);
- pSprite->confined = FALSE;
- (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
- (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
- pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
- pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
- pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
- pSprite->physLimits = pSprite->hotLimits;
- pSprite->screen = pScreen;
- }
-#endif
-}
-
-/*
- * This does not take any shortcuts, and even ignores its argument, since
- * it does not happen very often, and one has to walk up the tree since
- * this might be a newly instantiated cursor for an intermediate window
- * between the one the pointer is in and the one that the last cursor was
- * instantiated from.
- */
-void
-WindowHasNewCursor(WindowPtr pWin)
-{
- DeviceIntPtr pDev;
-
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- if (DevHasCursor(pDev))
- PostNewCursor(pDev);
-}
-
-void
-NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
-{
- SpritePtr pSprite = pDev->spriteInfo->sprite;
-
- pSprite->hotPhys.x = x;
- pSprite->hotPhys.y = y;
-#ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
- pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
- if (newScreen != pSprite->screen) {
- pSprite->screen = newScreen;
- /* Make sure we tell the DDX to update its copy of the screen */
- if(pSprite->confineWin)
- XineramaConfineCursorToWindow(pDev,
- pSprite->confineWin, TRUE);
- else
- XineramaConfineCursorToWindow(pDev, screenInfo.screens[0]->root, TRUE);
- /* if the pointer wasn't confined, the DDX won't get
- told of the pointer warp so we reposition it here */
- if(!syncEvents.playingEvents)
- (*pSprite->screen->SetCursorPosition)(
- pDev,
- pSprite->screen,
- pSprite->hotPhys.x + screenInfo.screens[0]->x -
- pSprite->screen->x,
- pSprite->hotPhys.y + screenInfo.screens[0]->y -
- pSprite->screen->y, FALSE);
- }
- } else
-#endif
- if (newScreen != pSprite->hotPhys.pScreen)
- ConfineCursorToWindow(pDev, newScreen->root, TRUE, FALSE);
-}
-
-#ifdef PANORAMIX
-
-static Bool
-XineramaPointInWindowIsVisible(
- WindowPtr pWin,
- int x,
- int y
-)
-{
- BoxRec box;
- int i, xoff, yoff;
-
- if (!pWin->realized) return FALSE;
-
- if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
- return TRUE;
-
- if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
-
- xoff = x + screenInfo.screens[0]->x;
- yoff = y + screenInfo.screens[0]->y;
-
- for(i = 1; i < PanoramiXNumScreens; i++) {
- pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
- x = xoff - screenInfo.screens[i]->x;
- y = yoff - screenInfo.screens[i]->y;
-
- if(RegionContainsPoint(&pWin->borderClip, x, y, &box)
- && (!wInputShape(pWin) ||
- RegionContainsPoint(wInputShape(pWin),
- x - pWin->drawable.x,
- y - pWin->drawable.y, &box)))
- return TRUE;
-
- }
-
- return FALSE;
-}
-
-static int
-XineramaWarpPointer(ClientPtr client)
-{
- WindowPtr dest = NULL;
- int x, y, rc;
- SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
-
- REQUEST(xWarpPointerReq);
-
-
- if (stuff->dstWid != None) {
- rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
- if (rc != Success)
- return rc;
- }
- x = pSprite->hotPhys.x;
- y = pSprite->hotPhys.y;
-
- if (stuff->srcWid != None)
- {
- int winX, winY;
- XID winID = stuff->srcWid;
- WindowPtr source;
-
- rc = dixLookupWindow(&source, winID, client, DixReadAccess);
- if (rc != Success)
- return rc;
-
- winX = source->drawable.x;
- winY = source->drawable.y;
- if(source == screenInfo.screens[0]->root) {
- winX -= screenInfo.screens[0]->x;
- winY -= screenInfo.screens[0]->y;
- }
- if (x < winX + stuff->srcX ||
- y < winY + stuff->srcY ||
- (stuff->srcWidth != 0 &&
- winX + stuff->srcX + (int)stuff->srcWidth < x) ||
- (stuff->srcHeight != 0 &&
- winY + stuff->srcY + (int)stuff->srcHeight < y) ||
- !XineramaPointInWindowIsVisible(source, x, y))
- return Success;
- }
- if (dest) {
- x = dest->drawable.x;
- y = dest->drawable.y;
- if(dest == screenInfo.screens[0]->root) {
- x -= screenInfo.screens[0]->x;
- y -= screenInfo.screens[0]->y;
- }
- }
-
- x += stuff->dstX;
- y += stuff->dstY;
-
- if (x < pSprite->physLimits.x1)
- x = pSprite->physLimits.x1;
- else if (x >= pSprite->physLimits.x2)
- x = pSprite->physLimits.x2 - 1;
- if (y < pSprite->physLimits.y1)
- y = pSprite->physLimits.y1;
- else if (y >= pSprite->physLimits.y2)
- y = pSprite->physLimits.y2 - 1;
- if (pSprite->hotShape)
- ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
-
- XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
-
- return Success;
-}
-
-#endif
-
-
-/**
- * Server-side protocol handling for WarpPointer request.
- * Warps the cursor position to the coordinates given in the request.
- */
-int
-ProcWarpPointer(ClientPtr client)
-{
- WindowPtr dest = NULL;
- int x, y, rc;
- ScreenPtr newScreen;
- DeviceIntPtr dev, tmp;
- SpritePtr pSprite;
-
- REQUEST(xWarpPointerReq);
- REQUEST_SIZE_MATCH(xWarpPointerReq);
-
- dev = PickPointer(client);
-
- for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
- if ((tmp == dev) || (!IsMaster(tmp) && tmp->u.master == dev)) {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
- if (rc != Success)
- return rc;
- }
- }
-
- if (dev->u.lastSlave)
- dev = dev->u.lastSlave;
- pSprite = dev->spriteInfo->sprite;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension)
- return XineramaWarpPointer(client);
-#endif
-
- if (stuff->dstWid != None) {
- rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
- }
- x = pSprite->hotPhys.x;
- y = pSprite->hotPhys.y;
-
- if (stuff->srcWid != None)
- {
- int winX, winY;
- XID winID = stuff->srcWid;
- WindowPtr source;
-
- rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- winX = source->drawable.x;
- winY = source->drawable.y;
- if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
- x < winX + stuff->srcX ||
- y < winY + stuff->srcY ||
- (stuff->srcWidth != 0 &&
- winX + stuff->srcX + (int)stuff->srcWidth < x) ||
- (stuff->srcHeight != 0 &&
- winY + stuff->srcY + (int)stuff->srcHeight < y) ||
- !PointInWindowIsVisible(source, x, y))
- return Success;
- }
- if (dest)
- {
- x = dest->drawable.x;
- y = dest->drawable.y;
- newScreen = dest->drawable.pScreen;
- } else
- newScreen = pSprite->hotPhys.pScreen;
-
- x += stuff->dstX;
- y += stuff->dstY;
-
- if (x < 0)
- x = 0;
- else if (x >= newScreen->width)
- x = newScreen->width - 1;
- if (y < 0)
- y = 0;
- else if (y >= newScreen->height)
- y = newScreen->height - 1;
-
- if (newScreen == pSprite->hotPhys.pScreen)
- {
- if (x < pSprite->physLimits.x1)
- x = pSprite->physLimits.x1;
- else if (x >= pSprite->physLimits.x2)
- x = pSprite->physLimits.x2 - 1;
- if (y < pSprite->physLimits.y1)
- y = pSprite->physLimits.y1;
- else if (y >= pSprite->physLimits.y2)
- y = pSprite->physLimits.y2 - 1;
- if (pSprite->hotShape)
- ConfineToShape(dev, pSprite->hotShape, &x, &y);
- (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE);
- }
- else if (!PointerConfinedToScreen(dev))
- {
- NewCurrentScreen(dev, newScreen, x, y);
- }
- return Success;
-}
-
-static Bool
-BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
-{
- if(RegionNotEmpty(&pWin->borderSize))
- return TRUE;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
- int i;
-
- for(i = 1; i < PanoramiXNumScreens; i++) {
- if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize))
- return TRUE;
- }
- }
-#endif
- return FALSE;
-}
-
-/**
- * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
- * passive grab set on the window to be activated.
- * If a passive grab is activated, the event will be delivered to the client.
- *
- * @param pWin The window that may be subject to a passive grab.
- * @param device Device that caused the event.
- * @param event The current device event.
- * @param checkCore Check for core grabs too.
- */
-
-static Bool
-CheckPassiveGrabsOnWindow(
- WindowPtr pWin,
- DeviceIntPtr device,
- DeviceEvent *event,
- BOOL checkCore)
-{
- GrabPtr grab = wPassiveGrabs(pWin);
- GrabRec tempGrab;
- GrabInfoPtr grabinfo;
-#define CORE_MATCH 0x1
-#define XI_MATCH 0x2
-#define XI2_MATCH 0x4
- int match = 0;
-
- if (!grab)
- return FALSE;
- /* Fill out the grab details, but leave the type for later before
- * comparing */
- tempGrab.window = pWin;
- tempGrab.device = device;
- tempGrab.detail.exact = event->detail.key;
- tempGrab.detail.pMask = NULL;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.next = NULL;
- for (; grab; grab = grab->next)
- {
- DeviceIntPtr gdev;
- XkbSrvInfoPtr xkbi = NULL;
-
- gdev= grab->modifierDevice;
- if (grab->grabtype == GRABTYPE_CORE)
- {
- if (IsPointerDevice(device))
- gdev = GetPairedDevice(device);
- else
- gdev = device;
- } else if (grab->grabtype == GRABTYPE_XI2)
- {
- /* if the device is an attached slave device, gdev must be the
- * attached master keyboard. Since the slave may have been
- * reattached after the grab, the modifier device may not be the
- * same. */
- if (!IsMaster(grab->device) && device->u.master)
- gdev = GetMaster(device, MASTER_KEYBOARD);
- }
-
-
- if (gdev && gdev->key)
- xkbi= gdev->key->xkbInfo;
- tempGrab.modifierDevice = grab->modifierDevice;
- tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
-
- /* Check for XI2 and XI grabs first */
- tempGrab.type = GetXI2Type((InternalEvent*)event);
- tempGrab.grabtype = GRABTYPE_XI2;
- if (GrabMatchesSecond(&tempGrab, grab, FALSE))
- match = XI2_MATCH;
-
- tempGrab.detail.exact = event->detail.key;
- if (!match)
- {
- tempGrab.type = GetXIType((InternalEvent*)event);
- tempGrab.grabtype = GRABTYPE_XI;
- if (GrabMatchesSecond(&tempGrab, grab, FALSE))
- match = XI_MATCH;
- }
-
- /* Check for a core grab (ignore the device when comparing) */
- if (!match && checkCore)
- {
- tempGrab.grabtype = GRABTYPE_CORE;
- if ((tempGrab.type = GetCoreType((InternalEvent*)event)) &&
- (GrabMatchesSecond(&tempGrab, grab, TRUE)))
- match = CORE_MATCH;
- }
-
- if (match && (!grab->confineTo ||
- (grab->confineTo->realized &&
- BorderSizeNotEmpty(device, grab->confineTo))))
- {
- int rc, count = 0;
- xEvent *xE = NULL;
- xEvent core;
-
- event->corestate &= 0x1f00;
- event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00);
- grabinfo = &device->deviceGrab;
- /* In some cases a passive core grab may exist, but the client
- * already has a core grab on some other device. In this case we
- * must not get the grab, otherwise we may never ungrab the
- * device.
- */
-
- if (grab->grabtype == GRABTYPE_CORE)
- {
- DeviceIntPtr other;
- BOOL interfering = FALSE;
-
- /* A passive grab may have been created for a different device
- than it is assigned to at this point in time.
- Update the grab's device and modifier device to reflect the
- current state.
- Since XGrabDeviceButton requires to specify the
- modifierDevice explicitly, we don't override this choice.
- */
- if (tempGrab.type < GenericEvent)
- {
- grab->device = device;
- grab->modifierDevice = GetPairedDevice(device);
- }
-
- for (other = inputInfo.devices; other; other = other->next)
- {
- GrabPtr othergrab = other->deviceGrab.grab;
- if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
- SameClient(grab, rClient(othergrab)) &&
- ((IsPointerDevice(grab->device) &&
- IsPointerDevice(othergrab->device)) ||
- (IsKeyboardDevice(grab->device) &&
- IsKeyboardDevice(othergrab->device))))
- {
- interfering = TRUE;
- break;
- }
- }
- if (interfering)
- continue;
- }
-
-
- if (match & CORE_MATCH)
- {
- rc = EventToCore((InternalEvent*)event, &core);
- if (rc != Success)
- {
- if (rc != BadMatch)
- ErrorF("[dix] %s: core conversion failed in CPGFW "
- "(%d, %d).\n", device->name, event->type, rc);
- continue;
- }
- xE = &core;
- count = 1;
- } else if (match & XI2_MATCH)
- {
- rc = EventToXI2((InternalEvent*)event, &xE);
- if (rc != Success)
- {
- if (rc != BadMatch)
- ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
- "(%d, %d).\n", device->name, event->type, rc);
- continue;
- }
- count = 1;
- } else
- {
- rc = EventToXI((InternalEvent*)event, &xE, &count);
- if (rc != Success)
- {
- if (rc != BadMatch)
- ErrorF("[dix] %s: XI conversion failed in CPGFW "
- "(%d, %d).\n", device->name, event->type, rc);
- continue;
- }
- }
-
- (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
-
- if (xE)
- {
- FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
-
- TryClientEvents(rClient(grab), device, xE, count,
- GetEventFilter(device, xE),
- GetEventFilter(device, xE), grab);
- }
-
- if (grabinfo->sync.state == FROZEN_NO_EVENT)
- {
- if (!grabinfo->sync.event)
- grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
- *grabinfo->sync.event = *event;
- grabinfo->sync.state = FROZEN_WITH_EVENT;
- }
-
- if (match & (XI_MATCH | XI2_MATCH))
- free(xE); /* on core match xE == &core */
- return TRUE;
- }
- }
- return FALSE;
-#undef CORE_MATCH
-#undef XI_MATCH
-#undef XI2_MATCH
-}
-
-/**
- * CheckDeviceGrabs handles both keyboard and pointer events that may cause
- * a passive grab to be activated.
- *
- * If the event is a keyboard event, the ancestors of the focus window are
- * traced down and tried to see if they have any passive grabs to be
- * activated. If the focus window itself is reached and it's descendants
- * contain the pointer, the ancestors of the window that the pointer is in
- * are then traced down starting at the focus window, otherwise no grabs are
- * activated.
- * If the event is a pointer event, the ancestors of the window that the
- * pointer is in are traced down starting at the root until CheckPassiveGrabs
- * causes a passive grab to activate or all the windows are
- * tried. PRH
- *
- * If a grab is activated, the event has been sent to the client already!
- *
- * The event we pass in must always be an XI event. From this, we then emulate
- * the core event and then check for grabs.
- *
- * @param device The device that caused the event.
- * @param xE The event to handle (Device{Button|Key}Press).
- * @param count Number of events in list.
- * @return TRUE if a grab has been activated or false otherwise.
-*/
-
-Bool
-CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
-{
- int i;
- WindowPtr pWin = NULL;
- FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
- BOOL sendCore = (IsMaster(device) && device->coreEvents);
-
- if (event->type != ET_ButtonPress &&
- event->type != ET_KeyPress)
- return FALSE;
-
- if (event->type == ET_ButtonPress
- && (device->button->buttonsDown != 1))
- return FALSE;
-
- if (device->deviceGrab.grab)
- return FALSE;
-
- i = 0;
- if (ancestor)
- {
- while (i < device->spriteInfo->sprite->spriteTraceGood)
- if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
- break;
- if (i == device->spriteInfo->sprite->spriteTraceGood)
- return FALSE;
- }
-
- if (focus)
- {
- for (; i < focus->traceGood; i++)
- {
- pWin = focus->trace[i];
- if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore))
- return TRUE;
- }
-
- if ((focus->win == NoneWin) ||
- (i >= device->spriteInfo->sprite->spriteTraceGood) ||
- (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i-1]))
- return FALSE;
- }
-
- for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
- {
- pWin = device->spriteInfo->sprite->spriteTrace[i];
- if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore))
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * Called for keyboard events to deliver event to whatever client owns the
- * focus.
- *
- * The event is delivered to the keyboard's focus window, the root window or
- * to the window owning the input focus.
- *
- * @param keybd The keyboard originating the event.
- * @param event The event, not yet in wire format.
- * @param window Window underneath the sprite.
- */
-void
-DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
-{
- DeviceIntPtr ptr;
- WindowPtr focus = keybd->focus->win;
- BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
- xEvent core;
- xEvent *xE = NULL, *xi2 = NULL;
- int count, rc;
- int deliveries = 0;
-
- if (focus == FollowKeyboardWin)
- focus = inputInfo.keyboard->focus->win;
- if (!focus)
- return;
- if (focus == PointerRootWin)
- {
- DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
- return;
- }
- if ((focus == window) || IsParent(focus, window))
- {
- if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
- return;
- }
-
- /* just deliver it to the focus window */
- ptr = GetPairedDevice(keybd);
-
-
- rc = EventToXI2(event, &xi2);
- if (rc == Success)
- {
- /* XXX: XACE */
- int filter = GetEventFilter(keybd, xi2);
- FixUpEventFromWindow(ptr, xi2, focus, None, FALSE);
- deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
- filter, NullGrab);
- if (deliveries > 0)
- goto unwind;
- } else if (rc != BadMatch)
- ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
- keybd->name, event->any.type, rc);
-
- rc = EventToXI(event, &xE, &count);
- if (rc == Success &&
- XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success)
- {
- FixUpEventFromWindow(ptr, xE, focus, None, FALSE);
- deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
- GetEventFilter(keybd, xE),
- NullGrab);
-
- if (deliveries > 0)
- goto unwind;
- } else if (rc != BadMatch)
- ErrorF("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
- keybd->name, event->any.type, rc);
-
- if (sendCore)
- {
- rc = EventToCore(event, &core);
- if (rc == Success) {
- if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) {
- FixUpEventFromWindow(keybd, &core, focus, None, FALSE);
- deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
- GetEventFilter(keybd, &core),
- NullGrab);
- }
- } else if (rc != BadMatch)
- ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
- keybd->name, event->any.type, rc);
- }
-
-unwind:
- free(xE);
- free(xi2);
- return;
-}
-
-/**
- * Deliver an event from a device that is currently grabbed. Uses
- * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
- * grab. If not, TryClientEvents() is used.
- *
- * @param deactivateGrab True if the device's grab should be deactivated.
- */
-void
-DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
- Bool deactivateGrab)
-{
- GrabPtr grab;
- GrabInfoPtr grabinfo;
- int deliveries = 0;
- DeviceIntPtr dev;
- SpritePtr pSprite = thisDev->spriteInfo->sprite;
- BOOL sendCore = FALSE;
- int rc, count = 0;
- xEvent *xi = NULL;
- xEvent *xi2 = NULL;
-
- grabinfo = &thisDev->deviceGrab;
- grab = grabinfo->grab;
-
- if (grab->ownerEvents)
- {
- WindowPtr focus;
-
- /* Hack: Some pointer device have a focus class. So we need to check
- * for the type of event, to see if we really want to deliver it to
- * the focus window. For pointer events, the answer is no.
- */
- if (IsPointerEvent(event))
- focus = PointerRootWin;
- else if (thisDev->focus)
- {
- focus = thisDev->focus->win;
- if (focus == FollowKeyboardWin)
- focus = inputInfo.keyboard->focus->win;
- }
- else
- focus = PointerRootWin;
- if (focus == PointerRootWin)
- deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
- NullWindow, thisDev);
- else if (focus && (focus == pSprite->win ||
- IsParent(focus, pSprite->win)))
- deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
- thisDev);
- else if (focus)
- deliveries = DeliverDeviceEvents(focus, event, grab, focus,
- thisDev);
- }
- if (!deliveries)
- {
- Mask mask;
-
- /* XXX: In theory, we could pass the internal events through to
- * everything and only convert just before hitting the wire. We can't
- * do that yet, so DGE is the last stop for internal events. From here
- * onwards, we deal with core/XI events.
- */
-
- mask = grab->eventMask;
-
- sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
- /* try core event */
- if (sendCore && grab->grabtype == GRABTYPE_CORE)
- {
- xEvent core;
-
- rc = EventToCore(event, &core);
- if (rc == Success)
- {
- FixUpEventFromWindow(thisDev, &core, grab->window,
- None, TRUE);
- if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
- grab->window, &core, 1) ||
- XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
- grab->window, &core, 1))
- deliveries = 1; /* don't send, but pretend we did */
- else if (!IsInterferingGrab(rClient(grab), thisDev, &core))
- {
- deliveries = TryClientEvents(rClient(grab), thisDev,
- &core, 1, mask,
- GetEventFilter(thisDev, &core),
- grab);
- }
- } else if (rc != BadMatch)
- ErrorF("[dix] DeliverGrabbedEvent. Core conversion failed.\n");
- }
-
- if (!deliveries)
- {
- rc = EventToXI2(event, &xi2);
- if (rc == Success)
- {
- int evtype = ((xGenericEvent*)xi2)->evtype;
- mask = grab->xi2mask[XIAllDevices][evtype/8] |
- grab->xi2mask[XIAllMasterDevices][evtype/8] |
- grab->xi2mask[thisDev->id][evtype/8];
- /* try XI2 event */
- FixUpEventFromWindow(thisDev, xi2, grab->window, None, TRUE);
- /* XXX: XACE */
- deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask,
- GetEventFilter(thisDev, xi2), grab);
- } else if (rc != BadMatch)
- ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n",
- thisDev->name, event->any.type, rc);
- }
-
- if (!deliveries)
- {
- rc = EventToXI(event, &xi, &count);
- if (rc == Success)
- {
- /* try XI event */
- if (grabinfo->fromPassiveGrab &&
- grabinfo->implicitGrab)
- mask = grab->deviceMask;
- else
- mask = grab->eventMask;
-
- FixUpEventFromWindow(thisDev, xi, grab->window,
- None, TRUE);
-
- if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
- grab->window, xi, count) ||
- XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
- grab->window, xi, count))
- deliveries = 1; /* don't send, but pretend we did */
- else
- {
- deliveries =
- TryClientEvents(rClient(grab), thisDev,
- xi, count,
- mask,
- GetEventFilter(thisDev, xi),
- grab);
- }
- } else if (rc != BadMatch)
- ErrorF("[dix] %s: XI conversion failed in DGE (%d, %d). Skipping delivery.\n",
- thisDev->name, event->any.type, rc);
- }
-
- if (deliveries && (event->any.type == ET_Motion))
- thisDev->valuator->motionHintWindow = grab->window;
- }
- if (deliveries && !deactivateGrab && event->any.type != ET_Motion)
- {
- switch (grabinfo->sync.state)
- {
- case FREEZE_BOTH_NEXT_EVENT:
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev == thisDev)
- continue;
- FreezeThaw(dev, TRUE);
- if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
- (CLIENT_BITS(grab->resource) ==
- CLIENT_BITS(dev->deviceGrab.grab->resource)))
- dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
- else
- dev->deviceGrab.sync.other = grab;
- }
- /* fall through */
- case FREEZE_NEXT_EVENT:
- grabinfo->sync.state = FROZEN_WITH_EVENT;
- FreezeThaw(thisDev, TRUE);
- if (!grabinfo->sync.event)
- grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
- *grabinfo->sync.event = event->device_event;
- break;
- }
- }
-
- free(xi);
- free(xi2);
-}
-
-/* This function is used to set the key pressed or key released state -
- this is only used when the pressing of keys does not cause
- the device's processInputProc to be called, as in for example Mouse Keys.
-*/
-void
-FixKeyState (DeviceEvent *event, DeviceIntPtr keybd)
-{
- int key = event->detail.key;
-
- if (event->type == ET_KeyPress) {
- DebugF("FixKeyState: Key %d %s\n",key,
- ((event->type == ET_KeyPress) ? "down" : "up"));
- }
-
- if (event->type == ET_KeyPress)
- set_key_down(keybd, key, KEY_PROCESSED);
- else if (event->type == ET_KeyRelease)
- set_key_up(keybd, key, KEY_PROCESSED);
- else
- FatalError("Impossible keyboard event");
-}
-
-#define AtMostOneClient \
- (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
-#define ManagerMask \
- (SubstructureRedirectMask | ResizeRedirectMask)
-
-/**
- * Recalculate which events may be deliverable for the given window.
- * Recalculated mask is used for quicker determination which events may be
- * delivered to a window.
- *
- * The otherEventMasks on a WindowOptional is the combination of all event
- * masks set by all clients on the window.
- * deliverableEventMask is the combination of the eventMask and the
- * otherEventMask plus the events that may be propagated to the parent.
- *
- * Traverses to siblings and parents of the window.
- */
-void
-RecalculateDeliverableEvents(WindowPtr pWin)
-{
- OtherClients *others;
- WindowPtr pChild;
-
- pChild = pWin;
- while (1)
- {
- if (pChild->optional)
- {
- pChild->optional->otherEventMasks = 0;
- for (others = wOtherClients(pChild); others; others = others->next)
- {
- pChild->optional->otherEventMasks |= others->mask;
- }
- }
- pChild->deliverableEvents = pChild->eventMask|
- wOtherEventMasks(pChild);
- if (pChild->parent)
- pChild->deliverableEvents |=
- (pChild->parent->deliverableEvents &
- ~wDontPropagateMask(pChild) & PropagateMask);
- if (pChild->firstChild)
- {
- pChild = pChild->firstChild;
- continue;
- }
- while (!pChild->nextSib && (pChild != pWin))
- pChild = pChild->parent;
- if (pChild == pWin)
- break;
- pChild = pChild->nextSib;
- }
-}
-
-/**
- *
- * \param value must conform to DeleteType
- */
-int
-OtherClientGone(pointer value, XID id)
-{
- OtherClientsPtr other, prev;
- WindowPtr pWin = (WindowPtr)value;
-
- prev = 0;
- for (other = wOtherClients(pWin); other; other = other->next)
- {
- if (other->resource == id)
- {
- if (prev)
- prev->next = other->next;
- else
- {
- if (!(pWin->optional->otherClients = other->next))
- CheckWindowOptionalNeed (pWin);
- }
- free(other);
- RecalculateDeliverableEvents(pWin);
- return Success;
- }
- prev = other;
- }
- FatalError("client not on event list");
- /*NOTREACHED*/
- return -1; /* make compiler happy */
-}
-
-int
-EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
-{
- Mask check;
- OtherClients * others;
- DeviceIntPtr dev;
- int rc;
-
- if (mask & ~AllEventMasks)
- {
- client->errorValue = mask;
- return BadValue;
- }
- check = (mask & ManagerMask);
- if (check) {
- rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
- RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
- if (rc != Success)
- return rc;
- }
- check = (mask & AtMostOneClient);
- if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
- { /* It is illegal for two different
- clients to select on any of the
- events for AtMostOneClient. However,
- it is OK, for some client to
- continue selecting on one of those
- events. */
- if ((wClient(pWin) != client) && (check & pWin->eventMask))
- return BadAccess;
- for (others = wOtherClients (pWin); others; others = others->next)
- {
- if (!SameClient(others, client) && (check & others->mask))
- return BadAccess;
- }
- }
- if (wClient (pWin) == client)
- {
- check = pWin->eventMask;
- pWin->eventMask = mask;
- }
- else
- {
- for (others = wOtherClients (pWin); others; others = others->next)
- {
- if (SameClient(others, client))
- {
- check = others->mask;
- if (mask == 0)
- {
- FreeResource(others->resource, RT_NONE);
- return Success;
- }
- else
- others->mask = mask;
- goto maskSet;
- }
- }
- check = 0;
- if (!pWin->optional && !MakeWindowOptional (pWin))
- return BadAlloc;
- others = malloc(sizeof(OtherClients));
- if (!others)
- return BadAlloc;
- others->mask = mask;
- others->resource = FakeClientID(client->index);
- others->next = pWin->optional->otherClients;
- pWin->optional->otherClients = others;
- if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
- return BadAlloc;
- }
-maskSet:
- if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
- {
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->valuator && dev->valuator->motionHintWindow == pWin)
- dev->valuator->motionHintWindow = NullWindow;
- }
- }
- RecalculateDeliverableEvents(pWin);
- return Success;
-}
-
-int
-EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
- Mask mask, Bool *checkOptional)
-{
- int i, free;
-
- if (mask & ~PropagateMask)
- {
- client->errorValue = mask;
- return BadValue;
- }
- if (pWin->dontPropagate)
- DontPropagateRefCnts[pWin->dontPropagate]--;
- if (!mask)
- i = 0;
- else
- {
- for (i = DNPMCOUNT, free = 0; --i > 0; )
- {
- if (!DontPropagateRefCnts[i])
- free = i;
- else if (mask == DontPropagateMasks[i])
- break;
- }
- if (!i && free)
- {
- i = free;
- DontPropagateMasks[i] = mask;
- }
- }
- if (i || !mask)
- {
- pWin->dontPropagate = i;
- if (i)
- DontPropagateRefCnts[i]++;
- if (pWin->optional)
- {
- pWin->optional->dontPropagateMask = mask;
- *checkOptional = TRUE;
- }
- }
- else
- {
- if (!pWin->optional && !MakeWindowOptional (pWin))
- {
- if (pWin->dontPropagate)
- DontPropagateRefCnts[pWin->dontPropagate]++;
- return BadAlloc;
- }
- pWin->dontPropagate = 0;
- pWin->optional->dontPropagateMask = mask;
- }
- RecalculateDeliverableEvents(pWin);
- return Success;
-}
-
-/**
- * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
- * Uses the paired keyboard to get some additional information.
- */
-void
-CoreEnterLeaveEvent(
- DeviceIntPtr mouse,
- int type,
- int mode,
- int detail,
- WindowPtr pWin,
- Window child)
-{
- xEvent event;
- WindowPtr focus;
- DeviceIntPtr keybd;
- GrabPtr grab = mouse->deviceGrab.grab;
- Mask mask;
-
- keybd = GetPairedDevice(mouse);
-
- if ((pWin == mouse->valuator->motionHintWindow) &&
- (detail != NotifyInferior))
- mouse->valuator->motionHintWindow = NullWindow;
- if (grab)
- {
- mask = (pWin == grab->window) ? grab->eventMask : 0;
- if (grab->ownerEvents)
- mask |= EventMaskForClient(pWin, rClient(grab));
- }
- else
- {
- mask = pWin->eventMask | wOtherEventMasks(pWin);
- }
-
- memset(&event, 0, sizeof(xEvent));
- event.u.u.type = type;
- event.u.u.detail = detail;
- event.u.enterLeave.time = currentTime.milliseconds;
- event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
- event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
- /* Counts on the same initial structure of crossing & button events! */
- FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
- /* Enter/Leave events always set child */
- event.u.enterLeave.child = child;
- event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
- ELFlagSameScreen : 0;
- event.u.enterLeave.state = mouse->button ? (mouse->button->state & 0x1f00) : 0;
- if (keybd)
- event.u.enterLeave.state |=
- XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
- event.u.enterLeave.mode = mode;
- focus = (keybd) ? keybd->focus->win : None;
- if ((focus != NoneWin) &&
- ((pWin == focus) || (focus == PointerRootWin) ||
- IsParent(focus, pWin)))
- event.u.enterLeave.flags |= ELFlagFocus;
-
- if ((mask & GetEventFilter(mouse, &event)))
- {
- if (grab)
- TryClientEvents(rClient(grab), mouse, &event, 1, mask,
- GetEventFilter(mouse, &event), grab);
- else
- DeliverEventsToWindow(mouse, pWin, &event, 1,
- GetEventFilter(mouse, &event),
- NullGrab);
- }
-
- if ((type == EnterNotify) && (mask & KeymapStateMask))
- {
- xKeymapEvent ke;
- ClientPtr client = grab ? rClient(grab) : wClient(pWin);
- if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
- memset((char *)&ke.map[0], 0, 31);
- else
- memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
-
- ke.type = KeymapNotify;
- if (grab)
- TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
- mask, KeymapStateMask, grab);
- else
- DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
- KeymapStateMask, NullGrab);
- }
-}
-
-void
-DeviceEnterLeaveEvent(
- DeviceIntPtr mouse,
- int sourceid,
- int type,
- int mode,
- int detail,
- WindowPtr pWin,
- Window child)
-{
- GrabPtr grab = mouse->deviceGrab.grab;
- xXIEnterEvent *event;
- int filter;
- int btlen, len, i;
- DeviceIntPtr kbd;
-
- if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
- (mode == XINotifyPassiveUngrab && type == XI_Enter))
- return;
-
- btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
- btlen = bytes_to_int32(btlen);
- len = sizeof(xXIEnterEvent) + btlen * 4;
-
- event = calloc(1, len);
- event->type = GenericEvent;
- event->extension = IReqCode;
- event->evtype = type;
- event->length = (len - sizeof(xEvent))/4;
- event->buttons_len = btlen;
- event->detail = detail;
- event->time = currentTime.milliseconds;
- event->deviceid = mouse->id;
- event->sourceid = sourceid;
- event->mode = mode;
- event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
- event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
-
- for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
- if (BitIsOn(mouse->button->down, i))
- SetBit(&event[1], i);
-
- kbd = (IsMaster(mouse) || mouse->u.master) ? GetPairedDevice(mouse) : NULL;
- if (kbd && kbd->key)
- {
- event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
- event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
- event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
-
- event->group.base_group = kbd->key->xkbInfo->state.base_group;
- event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
- event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
- }
-
- FixUpEventFromWindow(mouse, (xEvent*)event, pWin, None, FALSE);
-
- filter = GetEventFilter(mouse, (xEvent*)event);
-
- if (grab)
- {
- Mask mask;
- mask = grab->xi2mask[XIAllDevices][type/8] |
- grab->xi2mask[XIAllMasterDevices][type/8] |
- grab->xi2mask[mouse->id][type/8];
- TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask,
- filter, grab);
- } else {
- if (!GetWindowXI2Mask(mouse, pWin, (xEvent*)event))
- goto out;
- DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter,
- NullGrab);
- }
-
-out:
- free(event);
-}
-
-void
-CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
-{
- xEvent event;
-
- memset(&event, 0, sizeof(xEvent));
- event.u.focus.mode = mode;
- event.u.u.type = type;
- event.u.u.detail = detail;
- event.u.focus.window = pWin->drawable.id;
-
- DeliverEventsToWindow(dev, pWin, &event, 1,
- GetEventFilter(dev, &event), NullGrab);
- if ((type == FocusIn) &&
- ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
- {
- xKeymapEvent ke;
- ClientPtr client = wClient(pWin);
- if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess))
- memset((char *)&ke.map[0], 0, 31);
- else
- memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
-
- ke.type = KeymapNotify;
- DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
- KeymapStateMask, NullGrab);
- }
-}
-
-/**
- * Set the input focus to the given window. Subsequent keyboard events will be
- * delivered to the given window.
- *
- * Usually called from ProcSetInputFocus as result of a client request. If so,
- * the device is the inputInfo.keyboard.
- * If called from ProcXSetInputFocus as result of a client xinput request, the
- * device is set to the device specified by the client.
- *
- * @param client Client that requested input focus change.
- * @param dev Focus device.
- * @param focusID The window to obtain the focus. Can be PointerRoot or None.
- * @param revertTo Specifies where the focus reverts to when window becomes
- * unviewable.
- * @param ctime Specifies the time.
- * @param followOK True if pointer is allowed to follow the keyboard.
- */
-int
-SetInputFocus(
- ClientPtr client,
- DeviceIntPtr dev,
- Window focusID,
- CARD8 revertTo,
- Time ctime,
- Bool followOK)
-{
- FocusClassPtr focus;
- WindowPtr focusWin;
- int mode, rc;
- TimeStamp time;
- DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
-
-
- UpdateCurrentTime();
- if ((revertTo != RevertToParent) &&
- (revertTo != RevertToPointerRoot) &&
- (revertTo != RevertToNone) &&
- ((revertTo != RevertToFollowKeyboard) || !followOK))
- {
- client->errorValue = revertTo;
- return BadValue;
- }
- time = ClientTimeToServerTime(ctime);
-
- if (IsKeyboardDevice(dev))
- keybd = dev;
- else
- keybd = GetPairedDevice(dev);
-
- if ((focusID == None) || (focusID == PointerRoot))
- focusWin = (WindowPtr)(long)focusID;
- else if ((focusID == FollowKeyboard) && followOK)
- {
- focusWin = keybd->focus->win;
- }
- else {
- rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- /* It is a match error to try to set the input focus to an
- unviewable window. */
- if(!focusWin->realized)
- return BadMatch;
- }
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
- if (rc != Success)
- return Success;
-
- focus = dev->focus;
- if ((CompareTimeStamps(time, currentTime) == LATER) ||
- (CompareTimeStamps(time, focus->time) == EARLIER))
- return Success;
- mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
- if (focus->win == FollowKeyboardWin)
- {
- if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
- DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
- } else
- {
- if (!ActivateFocusInGrab(dev, focus->win, focusWin))
- DoFocusEvents(dev, focus->win, focusWin, mode);
- }
- focus->time = time;
- focus->revert = revertTo;
- if (focusID == FollowKeyboard)
- focus->win = FollowKeyboardWin;
- else
- focus->win = focusWin;
- if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
- focus->traceGood = 0;
- else
- {
- int depth = 0;
- WindowPtr pWin;
-
- for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
- if (depth > focus->traceSize)
- {
- focus->traceSize = depth+1;
- focus->trace = realloc(focus->trace,
- focus->traceSize * sizeof(WindowPtr));
- }
- focus->traceGood = depth;
- for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
- focus->trace[depth] = pWin;
- }
- return Success;
-}
-
-/**
- * Server-side protocol handling for SetInputFocus request.
- *
- * Sets the input focus for the virtual core keyboard.
- */
-int
-ProcSetInputFocus(ClientPtr client)
-{
- DeviceIntPtr kbd = PickKeyboard(client);
- REQUEST(xSetInputFocusReq);
-
- REQUEST_SIZE_MATCH(xSetInputFocusReq);
-
- return SetInputFocus(client, kbd, stuff->focus,
- stuff->revertTo, stuff->time, FALSE);
-}
-
-/**
- * Server-side protocol handling for GetInputFocus request.
- *
- * Sends the current input focus for the client's keyboard back to the
- * client.
- */
-int
-ProcGetInputFocus(ClientPtr client)
-{
- DeviceIntPtr kbd = PickKeyboard(client);
- xGetInputFocusReply rep;
- FocusClassPtr focus = kbd->focus;
- int rc;
- /* REQUEST(xReq); */
- REQUEST_SIZE_MATCH(xReq);
-
- rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
- if (rc != Success)
- return rc;
-
- memset(&rep, 0, sizeof(xGetInputFocusReply));
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- if (focus->win == NoneWin)
- rep.focus = None;
- else if (focus->win == PointerRootWin)
- rep.focus = PointerRoot;
- else rep.focus = focus->win->drawable.id;
- rep.revertTo = focus->revert;
- WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
- return Success;
-}
-
-/**
- * Server-side protocol handling for GrabPointer request.
- *
- * Sets an active grab on the client's ClientPointer and returns success
- * status to client.
- */
-int
-ProcGrabPointer(ClientPtr client)
-{
- xGrabPointerReply rep;
- DeviceIntPtr device = PickPointer(client);
- GrabPtr grab;
- GrabMask mask;
- WindowPtr confineTo;
- CursorPtr oldCursor;
- REQUEST(xGrabPointerReq);
- TimeStamp time;
- int rc;
-
- REQUEST_SIZE_MATCH(xGrabPointerReq);
- UpdateCurrentTime();
-
- if (stuff->eventMask & ~PointerGrabMask)
- {
- client->errorValue = stuff->eventMask;
- return BadValue;
- }
-
- if (stuff->confineTo == None)
- confineTo = NullWindow;
- else
- {
- rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
- DixSetAttrAccess);
- if (rc != Success)
- return rc;
- }
-
- memset(&rep, 0, sizeof(xGrabPointerReply));
- oldCursor = NullCursor;
- grab = device->deviceGrab.grab;
-
- if (grab)
- {
- if (grab->confineTo && !confineTo)
- ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE);
- oldCursor = grab->cursor;
- }
-
- mask.core = stuff->eventMask;
-
- rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
- stuff->grabWindow, stuff->ownerEvents, stuff->time,
- &mask, GRABTYPE_CORE, stuff->cursor,
- stuff->confineTo, &rep.status);
- if (rc != Success)
- return rc;
-
- if (oldCursor && rep.status == GrabSuccess)
- FreeCursor (oldCursor, (Cursor)0);
-
- time = ClientTimeToServerTime(stuff->time);
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
- return Success;
-}
-
-/**
- * Server-side protocol handling for ChangeActivePointerGrab request.
- *
- * Changes properties of the grab hold by the client. If the client does not
- * hold an active grab on the device, nothing happens.
- */
-int
-ProcChangeActivePointerGrab(ClientPtr client)
-{
- DeviceIntPtr device;
- GrabPtr grab;
- CursorPtr newCursor, oldCursor;
- REQUEST(xChangeActivePointerGrabReq);
- TimeStamp time;
-
- REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
- if (stuff->eventMask & ~PointerGrabMask)
- {
- client->errorValue = stuff->eventMask;
- return BadValue;
- }
- if (stuff->cursor == None)
- newCursor = NullCursor;
- else
- {
- int rc = dixLookupResourceByType((pointer *)&newCursor, stuff->cursor,
- RT_CURSOR, client, DixUseAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->cursor;
- return rc;
- }
- }
-
- device = PickPointer(client);
- grab = device->deviceGrab.grab;
-
- if (!grab)
- return Success;
- if (!SameClient(grab, client))
- return Success;
- time = ClientTimeToServerTime(stuff->time);
- if ((CompareTimeStamps(time, currentTime) == LATER) ||
- (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
- return Success;
- oldCursor = grab->cursor;
- grab->cursor = newCursor;
- if (newCursor)
- newCursor->refcnt++;
- PostNewCursor(device);
- if (oldCursor)
- FreeCursor(oldCursor, (Cursor)0);
- grab->eventMask = stuff->eventMask;
- return Success;
-}
-
-/**
- * Server-side protocol handling for UngrabPointer request.
- *
- * Deletes a pointer grab on a device the client has grabbed.
- */
-int
-ProcUngrabPointer(ClientPtr client)
-{
- DeviceIntPtr device = PickPointer(client);
- GrabPtr grab;
- TimeStamp time;
- REQUEST(xResourceReq);
-
- REQUEST_SIZE_MATCH(xResourceReq);
- UpdateCurrentTime();
- grab = device->deviceGrab.grab;
-
- time = ClientTimeToServerTime(stuff->id);
- if ((CompareTimeStamps(time, currentTime) != LATER) &&
- (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
- (grab) && SameClient(grab, client))
- (*device->deviceGrab.DeactivateGrab)(device);
- return Success;
-}
-
-/**
- * Sets a grab on the given device.
- *
- * Called from ProcGrabKeyboard to work on the client's keyboard.
- * Called from ProcXGrabDevice to work on the device specified by the client.
- *
- * The parameters this_mode and other_mode represent the keyboard_mode and
- * pointer_mode parameters of XGrabKeyboard().
- * See man page for details on all the parameters
- *
- * @param client Client that owns the grab.
- * @param dev The device to grab.
- * @param this_mode GrabModeSync or GrabModeAsync
- * @param other_mode GrabModeSync or GrabModeAsync
- * @param status Return code to be returned to the caller.
- *
- * @returns Success or BadValue.
- */
-int
-GrabDevice(ClientPtr client, DeviceIntPtr dev,
- unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
- unsigned ownerEvents, Time ctime, GrabMask *mask,
- int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
-{
- WindowPtr pWin, confineTo;
- GrabPtr grab;
- TimeStamp time;
- Mask access_mode = DixGrabAccess;
- int rc;
- GrabInfoPtr grabInfo = &dev->deviceGrab;
- CursorPtr cursor;
-
- UpdateCurrentTime();
- if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync))
- {
- client->errorValue = keyboard_mode;
- return BadValue;
- }
- if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync))
- {
- client->errorValue = pointer_mode;
- return BadValue;
- }
- if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
- {
- client->errorValue = ownerEvents;
- return BadValue;
- }
-
- rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
-
- if (confineToWin == None)
- confineTo = NullWindow;
- else
- {
- rc = dixLookupWindow(&confineTo, confineToWin, client,
- DixSetAttrAccess);
- if (rc != Success)
- return rc;
- }
-
- if (curs == None)
- cursor = NullCursor;
- else
- {
- rc = dixLookupResourceByType((pointer *)&cursor, curs, RT_CURSOR,
- client, DixUseAccess);
- if (rc != Success)
- {
- client->errorValue = curs;
- return rc;
- }
- access_mode |= DixForceAccess;
- }
-
- if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
- if (rc != Success)
- return rc;
-
- time = ClientTimeToServerTime(ctime);
- grab = grabInfo->grab;
- if (grab && grab->grabtype != grabtype)
- *status = AlreadyGrabbed;
- if (grab && !SameClient(grab, client))
- *status = AlreadyGrabbed;
- else if ((!pWin->realized) ||
- (confineTo &&
- !(confineTo->realized
- && BorderSizeNotEmpty(dev, confineTo))))
- *status = GrabNotViewable;
- else if ((CompareTimeStamps(time, currentTime) == LATER) ||
- (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
- *status = GrabInvalidTime;
- else if (grabInfo->sync.frozen &&
- grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
- *status = GrabFrozen;
- else
- {
- GrabRec tempGrab;
-
- /* Otherwise segfaults happen on grabbed MPX devices */
- memset(&tempGrab, 0, sizeof(GrabRec));
-
- tempGrab.next = NULL;
- tempGrab.window = pWin;
- tempGrab.resource = client->clientAsMask;
- tempGrab.ownerEvents = ownerEvents;
- tempGrab.keyboardMode = keyboard_mode;
- tempGrab.pointerMode = pointer_mode;
- if (grabtype == GRABTYPE_CORE)
- tempGrab.eventMask = mask->core;
- else if (grabtype == GRABTYPE_XI)
- tempGrab.eventMask = mask->xi;
- else
- memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask));
- tempGrab.device = dev;
- tempGrab.cursor = cursor;
- tempGrab.confineTo = confineTo;
- tempGrab.grabtype = grabtype;
- (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
- *status = GrabSuccess;
- }
- return Success;
-}
-
-/**
- * Server-side protocol handling for GrabKeyboard request.
- *
- * Grabs the client's keyboard and returns success status to client.
- */
-int
-ProcGrabKeyboard(ClientPtr client)
-{
- xGrabKeyboardReply rep;
- REQUEST(xGrabKeyboardReq);
- int result;
- DeviceIntPtr keyboard = PickKeyboard(client);
- GrabMask mask;
-
- REQUEST_SIZE_MATCH(xGrabKeyboardReq);
-
- memset(&rep, 0, sizeof(xGrabKeyboardReply));
- mask.core = KeyPressMask | KeyReleaseMask;
-
- result = GrabDevice(client, keyboard, stuff->pointerMode,
- stuff->keyboardMode, stuff->grabWindow, stuff->ownerEvents,
- stuff->time, &mask, GRABTYPE_CORE, None, None,
- &rep.status);
-
- if (result != Success)
- return result;
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = 0;
- WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
- return Success;
-}
-
-/**
- * Server-side protocol handling for UngrabKeyboard request.
- *
- * Deletes a possible grab on the client's keyboard.
- */
-int
-ProcUngrabKeyboard(ClientPtr client)
-{
- DeviceIntPtr device = PickKeyboard(client);
- GrabPtr grab;
- TimeStamp time;
- REQUEST(xResourceReq);
-
- REQUEST_SIZE_MATCH(xResourceReq);
- UpdateCurrentTime();
-
- grab = device->deviceGrab.grab;
-
- time = ClientTimeToServerTime(stuff->id);
- if ((CompareTimeStamps(time, currentTime) != LATER) &&
- (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
- (grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_CORE)
- (*device->deviceGrab.DeactivateGrab)(device);
- return Success;
-}
-
-/**
- * Server-side protocol handling for QueryPointer request.
- *
- * Returns the current state and position of the client's ClientPointer to the
- * client.
- */
-int
-ProcQueryPointer(ClientPtr client)
-{
- xQueryPointerReply rep;
- WindowPtr pWin, t;
- DeviceIntPtr mouse = PickPointer(client);
- DeviceIntPtr keyboard;
- SpritePtr pSprite;
- int rc;
- REQUEST(xResourceReq);
- REQUEST_SIZE_MATCH(xResourceReq);
-
- rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
- if (rc != Success && rc != BadAccess)
- return rc;
-
- keyboard = GetPairedDevice(mouse);
-
- pSprite = mouse->spriteInfo->sprite;
- if (mouse->valuator->motionHintWindow)
- MaybeStopHint(mouse, client);
- memset(&rep, 0, sizeof(xQueryPointerReply));
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.mask = mouse->button ? (mouse->button->state) : 0;
- rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
- rep.length = 0;
- rep.root = (RootWindow(mouse))->drawable.id;
- rep.rootX = pSprite->hot.x;
- rep.rootY = pSprite->hot.y;
- rep.child = None;
- if (pSprite->hot.pScreen == pWin->drawable.pScreen)
- {
- rep.sameScreen = xTrue;
- rep.winX = pSprite->hot.x - pWin->drawable.x;
- rep.winY = pSprite->hot.y - pWin->drawable.y;
- for (t = pSprite->win; t; t = t->parent)
- if (t->parent == pWin)
- {
- rep.child = t->drawable.id;
- break;
- }
- }
- else
- {
- rep.sameScreen = xFalse;
- rep.winX = 0;
- rep.winY = 0;
- }
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- rep.rootX += screenInfo.screens[0]->x;
- rep.rootY += screenInfo.screens[0]->y;
- if(stuff->id == rep.root) {
- rep.winX += screenInfo.screens[0]->x;
- rep.winY += screenInfo.screens[0]->y;
- }
- }
-#endif
-
- if (rc == BadAccess) {
- rep.mask = 0;
- rep.child = None;
- rep.rootX = 0;
- rep.rootY = 0;
- rep.winX = 0;
- rep.winY = 0;
- }
-
- WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
-
- return Success;
-}
-
-/**
- * Initializes the device list and the DIX sprite to sane values. Allocates
- * trace memory used for quick window traversal.
- */
-void
-InitEvents(void)
-{
- int i;
-
- inputInfo.numDevices = 0;
- inputInfo.devices = (DeviceIntPtr)NULL;
- inputInfo.off_devices = (DeviceIntPtr)NULL;
- inputInfo.keyboard = (DeviceIntPtr)NULL;
- inputInfo.pointer = (DeviceIntPtr)NULL;
- /* The mask for pointer motion events may have changed in the last server
- * generation. See comment above definition of filters. */
- filters[0][PointerMotionMask] = MotionNotify;
- for (i = 1; i < MAXDEVICES; i++)
- {
- memcpy(&filters[i], filters[0], sizeof(filters[0]));
- }
-
- syncEvents.replayDev = (DeviceIntPtr)NULL;
- syncEvents.replayWin = NullWindow;
- while (syncEvents.pending)
- {
- QdEventPtr next = syncEvents.pending->next;
- free(syncEvents.pending);
- syncEvents.pending = next;
- }
- syncEvents.pendtail = &syncEvents.pending;
- syncEvents.playingEvents = FALSE;
- syncEvents.time.months = 0;
- syncEvents.time.milliseconds = 0; /* hardly matters */
- currentTime.months = 0;
- currentTime.milliseconds = GetTimeInMillis();
- lastDeviceEventTime = currentTime;
- for (i = 0; i < DNPMCOUNT; i++)
- {
- DontPropagateMasks[i] = 0;
- DontPropagateRefCnts[i] = 0;
- }
-
- InputEventListLen = GetMaximumEventsNum();
- InputEventList = InitEventList(InputEventListLen);
- if (!InputEventList)
- FatalError("[dix] Failed to allocate input event list.\n");
-}
-
-void
-CloseDownEvents(void)
-{
- FreeEventList(InputEventList, InputEventListLen);
- InputEventListLen = 0;
- InputEventList = NULL;
-}
-
-/**
- * Server-side protocol handling for SendEvent request.
- *
- * Locates the window to send the event to and forwards the event.
- */
-int
-ProcSendEvent(ClientPtr client)
-{
- WindowPtr pWin;
- WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
- DeviceIntPtr dev = PickPointer(client);
- DeviceIntPtr keybd = GetPairedDevice(dev);
- SpritePtr pSprite = dev->spriteInfo->sprite;
- REQUEST(xSendEventReq);
-
- REQUEST_SIZE_MATCH(xSendEventReq);
-
- /* The client's event type must be a core event type or one defined by an
- extension. */
-
- if ( ! ((stuff->event.u.u.type > X_Reply &&
- stuff->event.u.u.type < LASTEvent) ||
- (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
- stuff->event.u.u.type < (unsigned)lastEvent)))
- {
- client->errorValue = stuff->event.u.u.type;
- return BadValue;
- }
- if (stuff->event.u.u.type == ClientMessage &&
- stuff->event.u.u.detail != 8 &&
- stuff->event.u.u.detail != 16 &&
- stuff->event.u.u.detail != 32)
- {
- client->errorValue = stuff->event.u.u.detail;
- return BadValue;
- }
- if (stuff->eventMask & ~AllEventMasks)
- {
- client->errorValue = stuff->eventMask;
- return BadValue;
- }
-
- if (stuff->destination == PointerWindow)
- pWin = pSprite->win;
- else if (stuff->destination == InputFocus)
- {
- WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
-
- if (inputFocus == NoneWin)
- return Success;
-
- /* If the input focus is PointerRootWin, send the event to where
- the pointer is if possible, then perhaps propogate up to root. */
- if (inputFocus == PointerRootWin)
- inputFocus = RootWindow(dev);
-
- if (IsParent(inputFocus, pSprite->win))
- {
- effectiveFocus = inputFocus;
- pWin = pSprite->win;
- }
- else
- effectiveFocus = pWin = inputFocus;
- }
- else
- dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
-
- if (!pWin)
- return BadWindow;
- if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
- {
- client->errorValue = stuff->propagate;
- return BadValue;
- }
- stuff->event.u.u.type |= 0x80;
- if (stuff->propagate)
- {
- for (;pWin; pWin = pWin->parent)
- {
- if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
- &stuff->event, 1))
- return Success;
- if (DeliverEventsToWindow(dev, pWin,
- &stuff->event, 1, stuff->eventMask, NullGrab))
- return Success;
- if (pWin == effectiveFocus)
- return Success;
- stuff->eventMask &= ~wDontPropagateMask(pWin);
- if (!stuff->eventMask)
- break;
- }
- }
- else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
- DeliverEventsToWindow(dev, pWin, &stuff->event,
- 1, stuff->eventMask, NullGrab);
- return Success;
-}
-
-/**
- * Server-side protocol handling for UngrabKey request.
- *
- * Deletes a passive grab for the given key. Works on the
- * client's keyboard.
- */
-int
-ProcUngrabKey(ClientPtr client)
-{
- REQUEST(xUngrabKeyReq);
- WindowPtr pWin;
- GrabRec tempGrab;
- DeviceIntPtr keybd = PickKeyboard(client);
- int rc;
-
- REQUEST_SIZE_MATCH(xUngrabKeyReq);
- rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
- (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
- && (stuff->key != AnyKey))
- {
- client->errorValue = stuff->key;
- return BadValue;
- }
- if ((stuff->modifiers != AnyModifier) &&
- (stuff->modifiers & ~AllModifiersMask))
- {
- client->errorValue = stuff->modifiers;
- return BadValue;
- }
- tempGrab.resource = client->clientAsMask;
- tempGrab.device = keybd;
- tempGrab.window = pWin;
- tempGrab.modifiersDetail.exact = stuff->modifiers;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.modifierDevice = GetPairedDevice(keybd);
- tempGrab.type = KeyPress;
- tempGrab.grabtype = GRABTYPE_CORE;
- tempGrab.detail.exact = stuff->key;
- tempGrab.detail.pMask = NULL;
- tempGrab.next = NULL;
-
- if (!DeletePassiveGrabFromList(&tempGrab))
- return BadAlloc;
- return Success;
-}
-
-/**
- * Server-side protocol handling for GrabKey request.
- *
- * Creates a grab for the client's keyboard and adds it to the list of passive
- * grabs.
- */
-int
-ProcGrabKey(ClientPtr client)
-{
- WindowPtr pWin;
- REQUEST(xGrabKeyReq);
- GrabPtr grab;
- DeviceIntPtr keybd = PickKeyboard(client);
- int rc;
- GrabParameters param;
- GrabMask mask;
-
- REQUEST_SIZE_MATCH(xGrabKeyReq);
-
- memset(&param, 0, sizeof(param));
- param.grabtype = GRABTYPE_CORE;
- param.ownerEvents = stuff->ownerEvents;
- param.this_device_mode = stuff->keyboardMode;
- param.other_devices_mode = stuff->pointerMode;
- param.modifiers = stuff->modifiers;
-
- rc = CheckGrabValues(client, &param);
- if (rc != Success)
- return rc;
-
- if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
- (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
- && (stuff->key != AnyKey))
- {
- client->errorValue = stuff->key;
- return BadValue;
- }
- rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
-
-
- mask.core = (KeyPressMask | KeyReleaseMask);
-
- grab = CreateGrab(client->index, keybd, keybd, pWin, GRABTYPE_CORE, &mask,
- &param, KeyPress, stuff->key, NullWindow, NullCursor);
- if (!grab)
- return BadAlloc;
- return AddPassiveGrabToList(client, grab);
-}
-
-
-/**
- * Server-side protocol handling for GrabButton request.
- *
- * Creates a grab for the client's ClientPointer and adds it as a passive grab
- * to the list.
- */
-int
-ProcGrabButton(ClientPtr client)
-{
- WindowPtr pWin, confineTo;
- REQUEST(xGrabButtonReq);
- CursorPtr cursor;
- GrabPtr grab;
- DeviceIntPtr ptr, modifierDevice;
- Mask access_mode = DixGrabAccess;
- GrabMask mask;
- GrabParameters param;
- int rc;
-
- REQUEST_SIZE_MATCH(xGrabButtonReq);
- if ((stuff->pointerMode != GrabModeSync) &&
- (stuff->pointerMode != GrabModeAsync))
- {
- client->errorValue = stuff->pointerMode;
- return BadValue;
- }
- if ((stuff->keyboardMode != GrabModeSync) &&
- (stuff->keyboardMode != GrabModeAsync))
- {
- client->errorValue = stuff->keyboardMode;
- return BadValue;
- }
- if ((stuff->modifiers != AnyModifier) &&
- (stuff->modifiers & ~AllModifiersMask))
- {
- client->errorValue = stuff->modifiers;
- return BadValue;
- }
- if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
- {
- client->errorValue = stuff->ownerEvents;
- return BadValue;
- }
- if (stuff->eventMask & ~PointerGrabMask)
- {
- client->errorValue = stuff->eventMask;
- return BadValue;
- }
- rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
- if (stuff->confineTo == None)
- confineTo = NullWindow;
- else {
- rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
- DixSetAttrAccess);
- if (rc != Success)
- return rc;
- }
- if (stuff->cursor == None)
- cursor = NullCursor;
- else
- {
- rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR,
- client, DixUseAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->cursor;
- return rc;
- }
- access_mode |= DixForceAccess;
- }
-
- ptr = PickPointer(client);
- modifierDevice = GetPairedDevice(ptr);
- if (stuff->pointerMode == GrabModeSync ||
- stuff->keyboardMode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
- if (rc != Success)
- return rc;
-
- memset(&param, 0, sizeof(param));
- param.grabtype = GRABTYPE_CORE;
- param.ownerEvents = stuff->ownerEvents;
- param.this_device_mode = stuff->keyboardMode;
- param.other_devices_mode = stuff->pointerMode;
- param.modifiers = stuff->modifiers;
-
- mask.core = stuff->eventMask;
-
- grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
- GRABTYPE_CORE, &mask, &param, ButtonPress,
- stuff->button, confineTo, cursor);
- if (!grab)
- return BadAlloc;
- return AddPassiveGrabToList(client, grab);
-}
-
-/**
- * Server-side protocol handling for UngrabButton request.
- *
- * Deletes a passive grab on the client's ClientPointer from the list.
- */
-int
-ProcUngrabButton(ClientPtr client)
-{
- REQUEST(xUngrabButtonReq);
- WindowPtr pWin;
- GrabRec tempGrab;
- int rc;
- DeviceIntPtr ptr;
-
- REQUEST_SIZE_MATCH(xUngrabButtonReq);
- if ((stuff->modifiers != AnyModifier) &&
- (stuff->modifiers & ~AllModifiersMask))
- {
- client->errorValue = stuff->modifiers;
- return BadValue;
- }
- rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
- if (rc != Success)
- return rc;
-
- ptr = PickPointer(client);
-
- tempGrab.resource = client->clientAsMask;
- tempGrab.device = ptr;
- tempGrab.window = pWin;
- tempGrab.modifiersDetail.exact = stuff->modifiers;
- tempGrab.modifiersDetail.pMask = NULL;
- tempGrab.modifierDevice = GetPairedDevice(ptr);
- tempGrab.type = ButtonPress;
- tempGrab.detail.exact = stuff->button;
- tempGrab.grabtype = GRABTYPE_CORE;
- tempGrab.detail.pMask = NULL;
- tempGrab.next = NULL;
-
- if (!DeletePassiveGrabFromList(&tempGrab))
- return BadAlloc;
- return Success;
-}
-
-/**
- * Deactivate any grab that may be on the window, remove the focus.
- * Delete any XInput extension events from the window too. Does not change the
- * window mask. Use just before the window is deleted.
- *
- * If freeResources is set, passive grabs on the window are deleted.
- *
- * @param pWin The window to delete events from.
- * @param freeResources True if resources associated with the window should be
- * deleted.
- */
-void
-DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
-{
- WindowPtr parent;
- DeviceIntPtr mouse = inputInfo.pointer;
- DeviceIntPtr keybd = inputInfo.keyboard;
- FocusClassPtr focus;
- OtherClientsPtr oc;
- GrabPtr passive;
- GrabPtr grab;
-
-
- /* Deactivate any grabs performed on this window, before making any
- input focus changes. */
- grab = mouse->deviceGrab.grab;
- if (grab &&
- ((grab->window == pWin) || (grab->confineTo == pWin)))
- (*mouse->deviceGrab.DeactivateGrab)(mouse);
-
-
- /* Deactivating a keyboard grab should cause focus events. */
- grab = keybd->deviceGrab.grab;
- if (grab && (grab->window == pWin))
- (*keybd->deviceGrab.DeactivateGrab)(keybd);
-
- /* And now the real devices */
- for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
- {
- grab = mouse->deviceGrab.grab;
- if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
- (*mouse->deviceGrab.DeactivateGrab)(mouse);
- }
-
-
- for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
- {
- if (IsKeyboardDevice(keybd))
- {
- focus = keybd->focus;
-
- /* If the focus window is a root window (ie. has no parent) then don't
- delete the focus from it. */
-
- if ((pWin == focus->win) && (pWin->parent != NullWindow))
- {
- int focusEventMode = NotifyNormal;
-
- /* If a grab is in progress, then alter the mode of focus events. */
-
- if (keybd->deviceGrab.grab)
- focusEventMode = NotifyWhileGrabbed;
-
- switch (focus->revert)
- {
- case RevertToNone:
- DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
- focus->win = NoneWin;
- focus->traceGood = 0;
- break;
- case RevertToParent:
- parent = pWin;
- do
- {
- parent = parent->parent;
- focus->traceGood--;
- } while (!parent->realized
- /* This would be a good protocol change -- windows being reparented
- during SaveSet processing would cause the focus to revert to the
- nearest enclosing window which will survive the death of the exiting
- client, instead of ending up reverting to a dying window and thence
- to None
- */
-#ifdef NOTDEF
- || wClient(parent)->clientGone
-#endif
- );
- if (!ActivateFocusInGrab(keybd, pWin, parent))
- DoFocusEvents(keybd, pWin, parent, focusEventMode);
- focus->win = parent;
- focus->revert = RevertToNone;
- break;
- case RevertToPointerRoot:
- if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
- DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
- focus->win = PointerRootWin;
- focus->traceGood = 0;
- break;
- }
- }
- }
-
- if (IsPointerDevice(keybd))
- {
- if (keybd->valuator->motionHintWindow == pWin)
- keybd->valuator->motionHintWindow = NullWindow;
- }
- }
-
- if (freeResources)
- {
- if (pWin->dontPropagate)
- DontPropagateRefCnts[pWin->dontPropagate]--;
- while ( (oc = wOtherClients(pWin)) )
- FreeResource(oc->resource, RT_NONE);
- while ( (passive = wPassiveGrabs(pWin)) )
- FreeResource(passive->resource, RT_NONE);
- }
-
- DeleteWindowFromAnyExtEvents(pWin, freeResources);
-}
-
-/**
- * Call this whenever some window at or below pWin has changed geometry. If
- * there is a grab on the window, the cursor will be re-confined into the
- * window.
- */
-void
-CheckCursorConfinement(WindowPtr pWin)
-{
- GrabPtr grab;
- WindowPtr confineTo;
- DeviceIntPtr pDev;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
-#endif
-
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- grab = pDev->deviceGrab.grab;
- if (grab && (confineTo = grab->confineTo))
- {
- if (!BorderSizeNotEmpty(pDev, confineTo))
- (*pDev->deviceGrab.DeactivateGrab)(pDev);
- else if ((pWin == confineTo) || IsParent(pWin, confineTo))
- ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
- }
- }
- }
-}
-
-Mask
-EventMaskForClient(WindowPtr pWin, ClientPtr client)
-{
- OtherClientsPtr other;
-
- if (wClient (pWin) == client)
- return pWin->eventMask;
- for (other = wOtherClients(pWin); other; other = other->next)
- {
- if (SameClient(other, client))
- return other->mask;
- }
- return 0;
-}
-
-/**
- * Server-side protocol handling for RecolorCursor request.
- */
-int
-ProcRecolorCursor(ClientPtr client)
-{
- CursorPtr pCursor;
- int rc, nscr;
- ScreenPtr pscr;
- Bool displayed;
- SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
- REQUEST(xRecolorCursorReq);
-
- REQUEST_SIZE_MATCH(xRecolorCursorReq);
- rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
- client, DixWriteAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->cursor;
- return rc;
- }
-
- pCursor->foreRed = stuff->foreRed;
- pCursor->foreGreen = stuff->foreGreen;
- pCursor->foreBlue = stuff->foreBlue;
-
- pCursor->backRed = stuff->backRed;
- pCursor->backGreen = stuff->backGreen;
- pCursor->backBlue = stuff->backBlue;
-
- for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
- {
- pscr = screenInfo.screens[nscr];
-#ifdef PANORAMIX
- if(!noPanoramiXExtension)
- displayed = (pscr == pSprite->screen);
- else
-#endif
- displayed = (pscr == pSprite->hotPhys.pScreen);
- ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
- (pCursor == pSprite->current) && displayed);
- }
- return Success;
-}
-
-/**
- * Write the given events to a client, swapping the byte order if necessary.
- * To swap the byte ordering, a callback is called that has to be set up for
- * the given event type.
- *
- * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
- * can be more than one. Usually it's just one event.
- *
- * Do not modify the event structure passed in. See comment below.
- *
- * @param pClient Client to send events to.
- * @param count Number of events.
- * @param events The event list.
- */
-void
-WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
-{
-#ifdef PANORAMIX
- xEvent eventCopy;
-#endif
- xEvent *eventTo, *eventFrom;
- int i,
- eventlength = sizeof(xEvent);
-
- if (!pClient || pClient == serverClient || pClient->clientGone)
- return;
-
- for (i = 0; i < count; i++)
- if ((events[i].u.u.type & 0x7f) != KeymapNotify)
- events[i].u.u.sequenceNumber = pClient->sequence;
-
- /* Let XKB rewrite the state, as it depends on client preferences. */
- XkbFilterEvents(pClient, count, events);
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension &&
- (screenInfo.screens[0]->x || screenInfo.screens[0]->y))
- {
- switch(events->u.u.type) {
- case MotionNotify:
- case ButtonPress:
- case ButtonRelease:
- case KeyPress:
- case KeyRelease:
- case EnterNotify:
- case LeaveNotify:
- /*
- When multiple clients want the same event DeliverEventsToWindow
- passes the same event structure multiple times so we can't
- modify the one passed to us
- */
- count = 1; /* should always be 1 */
- memcpy(&eventCopy, events, sizeof(xEvent));
- eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
- eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
- if(eventCopy.u.keyButtonPointer.event ==
- eventCopy.u.keyButtonPointer.root)
- {
- eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
- eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
- }
- events = &eventCopy;
- break;
- default: break;
- }
- }
-#endif
-
- if (EventCallback)
- {
- EventInfoRec eventinfo;
- eventinfo.client = pClient;
- eventinfo.events = events;
- eventinfo.count = count;
- CallCallbacks(&EventCallback, (pointer)&eventinfo);
- }
-#ifdef XSERVER_DTRACE
- if (XSERVER_SEND_EVENT_ENABLED()) {
- for (i = 0; i < count; i++)
- {
- XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
- }
- }
-#endif
- /* Just a safety check to make sure we only have one GenericEvent, it just
- * makes things easier for me right now. (whot) */
- for (i = 1; i < count; i++)
- {
- if (events[i].u.u.type == GenericEvent)
- {
- ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
- return;
- }
- }
-
- if (events->u.u.type == GenericEvent)
- {
- eventlength += ((xGenericEvent*)events)->length * 4;
- }
-
- if(pClient->swapped)
- {
- if (eventlength > swapEventLen)
- {
- swapEventLen = eventlength;
- swapEvent = realloc(swapEvent, swapEventLen);
- if (!swapEvent)
- {
- FatalError("WriteEventsToClient: Out of memory.\n");
- return;
- }
- }
-
- for(i = 0; i < count; i++)
- {
- eventFrom = &events[i];
- eventTo = swapEvent;
-
- /* Remember to strip off the leading bit of type in case
- this event was sent with "SendEvent." */
- (*EventSwapVector[eventFrom->u.u.type & 0177])
- (eventFrom, eventTo);
-
- WriteToClient(pClient, eventlength, (char *)eventTo);
- }
- }
- else
- {
- /* only one GenericEvent, remember? that means either count is 1 and
- * eventlength is arbitrary or eventlength is 32 and count doesn't
- * matter. And we're all set. Woohoo. */
- WriteToClient(pClient, count * eventlength, (char *) events);
- }
-}
-
-/*
- * Set the client pointer for the given client.
- *
- * A client can have exactly one ClientPointer. Each time a
- * request/reply/event is processed and the choice of devices is ambiguous
- * (e.g. QueryPointer request), the server will pick the ClientPointer (see
- * PickPointer()).
- * If a keyboard is needed, the first keyboard paired with the CP is used.
- */
-int
-SetClientPointer(ClientPtr client, DeviceIntPtr device)
-{
- int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
- if (rc != Success)
- return rc;
-
- if (!IsMaster(device))
- {
- ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
- return BadDevice;
- } else if (!device->spriteInfo->spriteOwner)
- {
- ErrorF("[dix] Device %d does not have a sprite. "
- "Cannot be ClientPointer\n", device->id);
- return BadDevice;
- }
- client->clientPtr = device;
- return Success;
-}
-
-/* PickPointer will pick an appropriate pointer for the given client.
- *
- * An "appropriate device" is (in order of priority):
- * 1) A device the given client has a core grab on.
- * 2) A device set as ClientPointer for the given client.
- * 3) The first master device.
- */
-DeviceIntPtr
-PickPointer(ClientPtr client)
-{
- DeviceIntPtr it = inputInfo.devices;
-
- /* First, check if the client currently has a grab on a device. Even
- * keyboards count. */
- for(it = inputInfo.devices; it; it = it->next)
- {
- GrabPtr grab = it->deviceGrab.grab;
- if (grab && grab->grabtype == GRABTYPE_CORE && SameClient(grab, client))
- {
- it = GetMaster(it, MASTER_POINTER);
- return it; /* Always return a core grabbed device */
- }
- }
-
- if (!client->clientPtr)
- {
- DeviceIntPtr it = inputInfo.devices;
- while (it)
- {
- if (IsMaster(it) && it->spriteInfo->spriteOwner)
- {
- client->clientPtr = it;
- break;
- }
- it = it->next;
- }
- }
- return client->clientPtr;
-}
-
-/* PickKeyboard will pick an appropriate keyboard for the given client by
- * searching the list of devices for the keyboard device that is paired with
- * the client's pointer.
- */
-DeviceIntPtr
-PickKeyboard(ClientPtr client)
-{
- DeviceIntPtr ptr = PickPointer(client);
- DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
-
- if (!kbd)
- {
- ErrorF("[dix] ClientPointer not paired with a keyboard. This "
- "is a bug.\n");
- }
-
- return kbd;
-}
-
-/* A client that has one or more core grabs does not get core events from
- * devices it does not have a grab on. Legacy applications behave bad
- * otherwise because they are not used to it and the events interfere.
- * Only applies for core events.
- *
- * Return true if a core event from the device would interfere and should not
- * be delivered.
- */
-Bool
-IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
-{
- DeviceIntPtr it = inputInfo.devices;
-
- switch(event->u.u.type)
- {
- case KeyPress:
- case KeyRelease:
- case ButtonPress:
- case ButtonRelease:
- case MotionNotify:
- case EnterNotify:
- case LeaveNotify:
- break;
- default:
- return FALSE;
- }
-
- if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
- return FALSE;
-
- while(it)
- {
- if (it != dev)
- {
- if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
- && !it->deviceGrab.fromPassiveGrab)
- {
- if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
- (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
- return TRUE;
- }
- }
- it = it->next;
- }
-
- return FALSE;
-}
-
+/************************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+
+/* The panoramix components contained the following notice */
+/*****************************************************************
+
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+
+/*
+ * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file events.c
+ * This file handles event delivery and a big part of the server-side protocol
+ * handling (the parts for input devices).
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "misc.h"
+#include "resource.h"
+#include <X11/Xproto.h>
+#include "windowstr.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "cursorstr.h"
+
+#include "dixstruct.h"
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+#include "globals.h"
+
+#include <X11/extensions/XKBproto.h>
+#include "xkbsrv.h"
+#include "xace.h"
+
+#ifdef XSERVER_DTRACE
+#include <sys/types.h>
+typedef const char *string;
+#include "Xserver-dtrace.h"
+#endif
+
+#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI2proto.h>
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XI2.h>
+#include "exglobals.h"
+#include "exevents.h"
+#include "exglobals.h"
+#include "extnsionst.h"
+
+#include "dixevents.h"
+#include "dixgrabs.h"
+#include "dispatch.h"
+
+#include <X11/extensions/ge.h>
+#include "geext.h"
+#include "geint.h"
+
+#include "eventstr.h"
+#include "enterleave.h"
+#include "eventconvert.h"
+
+/* Extension events type numbering starts at EXTENSION_EVENT_BASE. */
+#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
+#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
+#define AllButtonsMask ( \
+ Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
+#define MotionMask ( \
+ PointerMotionMask | Button1MotionMask | \
+ Button2MotionMask | Button3MotionMask | Button4MotionMask | \
+ Button5MotionMask | ButtonMotionMask )
+#define PropagateMask ( \
+ KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
+ MotionMask )
+#define PointerGrabMask ( \
+ ButtonPressMask | ButtonReleaseMask | \
+ EnterWindowMask | LeaveWindowMask | \
+ PointerMotionHintMask | KeymapStateMask | \
+ MotionMask )
+#define AllModifiersMask ( \
+ ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
+ Mod3Mask | Mod4Mask | Mod5Mask )
+#define LastEventMask OwnerGrabButtonMask
+#define AllEventMasks (LastEventMask|(LastEventMask-1))
+
+
+#define CORE_EVENT(event) \
+ (!((event)->u.u.type & EXTENSION_EVENT_BASE) && \
+ (event)->u.u.type != GenericEvent)
+#define XI2_EVENT(event) \
+ (((event)->u.u.type == GenericEvent) && \
+ ((xGenericEvent*)(event))->extension == IReqCode)
+
+/**
+ * Used to indicate a implicit passive grab created by a ButtonPress event.
+ * See DeliverEventsToWindow().
+ */
+#define ImplicitGrabMask (1 << 7)
+
+#define WID(w) ((w) ? ((w)->drawable.id) : 0)
+
+#define XE_KBPTR (xE->u.keyButtonPointer)
+
+
+CallbackListPtr EventCallback;
+CallbackListPtr DeviceEventCallback;
+
+#define DNPMCOUNT 8
+
+Mask DontPropagateMasks[DNPMCOUNT];
+static int DontPropagateRefCnts[DNPMCOUNT];
+
+static void CheckVirtualMotion( DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin);
+static void CheckPhysLimits(DeviceIntPtr pDev,
+ CursorPtr cursor,
+ Bool generateEvents,
+ Bool confineToScreen,
+ ScreenPtr pScreen);
+
+/** Key repeat hack. Do not use but in TryClientEvents */
+extern BOOL EventIsKeyRepeat(xEvent *event);
+
+/**
+ * Main input device struct.
+ * inputInfo.pointer
+ * is the core pointer. Referred to as "virtual core pointer", "VCP",
+ * "core pointer" or inputInfo.pointer. The VCP is the first master
+ * pointer device and cannot be deleted.
+ *
+ * inputInfo.keyboard
+ * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
+ * See inputInfo.pointer.
+ *
+ * inputInfo.devices
+ * linked list containing all devices including VCP and VCK.
+ *
+ * inputInfo.off_devices
+ * Devices that have not been initialized and are thus turned off.
+ *
+ * inputInfo.numDevices
+ * Total number of devices.
+ *
+ * inputInfo.all_devices
+ * Virtual device used for XIAllDevices passive grabs. This device is
+ * not part of the inputInfo.devices list and mostly unset except for
+ * the deviceid. It exists because passivegrabs need a valid device
+ * reference.
+ *
+ * inputInfo.all_master_devices
+ * Virtual device used for XIAllMasterDevices passive grabs. This device
+ * is not part of the inputInfo.devices list and mostly unset except for
+ * the deviceid. It exists because passivegrabs need a valid device
+ * reference.
+ */
+InputInfo inputInfo;
+
+EventSyncInfoRec syncEvents;
+
+/**
+ * The root window the given device is currently on.
+ */
+#define RootWindow(sprite) sprite->spriteTrace[0]
+
+static xEvent* swapEvent = NULL;
+static int swapEventLen = 0;
+
+void
+NotImplemented(xEvent *from, xEvent *to)
+{
+ FatalError("Not implemented");
+}
+
+/**
+ * Convert the given event type from an XI event to a core event.
+ * @param[in] The XI 1.x event type.
+ * @return The matching core event type or 0 if there is none.
+ */
+int
+XItoCoreType(int xitype)
+{
+ int coretype = 0;
+ if (xitype == DeviceMotionNotify)
+ coretype = MotionNotify;
+ else if (xitype == DeviceButtonPress)
+ coretype = ButtonPress;
+ else if (xitype == DeviceButtonRelease)
+ coretype = ButtonRelease;
+ else if (xitype == DeviceKeyPress)
+ coretype = KeyPress;
+ else if (xitype == DeviceKeyRelease)
+ coretype = KeyRelease;
+
+ return coretype;
+}
+
+/**
+ * @return true if the device owns a cursor, false if device shares a cursor
+ * sprite with another device.
+ */
+Bool
+DevHasCursor(DeviceIntPtr pDev)
+{
+ return pDev->spriteInfo->spriteOwner;
+}
+
+/*
+ * @return true if a device is a pointer, check is the same as used by XI to
+ * fill the 'use' field.
+ */
+Bool
+IsPointerDevice(DeviceIntPtr dev)
+{
+ return (dev->type == MASTER_POINTER) ||
+ (dev->valuator && dev->button) ||
+ (dev->valuator && !dev->key);
+}
+
+/*
+ * @return true if a device is a keyboard, check is the same as used by XI to
+ * fill the 'use' field.
+ *
+ * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
+ * count them as keyboard devices.
+ */
+Bool
+IsKeyboardDevice(DeviceIntPtr dev)
+{
+ return (dev->type == MASTER_KEYBOARD) ||
+ ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
+}
+
+Bool
+IsMaster(DeviceIntPtr dev)
+{
+ return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
+}
+
+/**
+ * Max event opcode.
+ */
+extern int lastEvent;
+
+extern int DeviceMotionNotify;
+
+#define CantBeFiltered NoEventMask
+/**
+ * Event masks for each event type.
+ *
+ * One set of filters for each device, but only the first layer
+ * is initialized. The rest is memcpy'd in InitEvents.
+ *
+ * Filters are used whether a given event may be delivered to a client,
+ * usually in the form of if (window-event-mask & filter); then deliver event.
+ *
+ * One notable filter is for PointerMotion/DevicePointerMotion events. Each
+ * time a button is pressed, the filter is modified to also contain the
+ * matching ButtonXMotion mask.
+ */
+static Mask filters[MAXDEVICES][128] = {
+{
+ NoSuchEvent, /* 0 */
+ NoSuchEvent, /* 1 */
+ KeyPressMask, /* KeyPress */
+ KeyReleaseMask, /* KeyRelease */
+ ButtonPressMask, /* ButtonPress */
+ ButtonReleaseMask, /* ButtonRelease */
+ PointerMotionMask, /* MotionNotify (initial state) */
+ EnterWindowMask, /* EnterNotify */
+ LeaveWindowMask, /* LeaveNotify */
+ FocusChangeMask, /* FocusIn */
+ FocusChangeMask, /* FocusOut */
+ KeymapStateMask, /* KeymapNotify */
+ ExposureMask, /* Expose */
+ CantBeFiltered, /* GraphicsExpose */
+ CantBeFiltered, /* NoExpose */
+ VisibilityChangeMask, /* VisibilityNotify */
+ SubstructureNotifyMask, /* CreateNotify */
+ StructureAndSubMask, /* DestroyNotify */
+ StructureAndSubMask, /* UnmapNotify */
+ StructureAndSubMask, /* MapNotify */
+ SubstructureRedirectMask, /* MapRequest */
+ StructureAndSubMask, /* ReparentNotify */
+ StructureAndSubMask, /* ConfigureNotify */
+ SubstructureRedirectMask, /* ConfigureRequest */
+ StructureAndSubMask, /* GravityNotify */
+ ResizeRedirectMask, /* ResizeRequest */
+ StructureAndSubMask, /* CirculateNotify */
+ SubstructureRedirectMask, /* CirculateRequest */
+ PropertyChangeMask, /* PropertyNotify */
+ CantBeFiltered, /* SelectionClear */
+ CantBeFiltered, /* SelectionRequest */
+ CantBeFiltered, /* SelectionNotify */
+ ColormapChangeMask, /* ColormapNotify */
+ CantBeFiltered, /* ClientMessage */
+ CantBeFiltered /* MappingNotify */
+}};
+
+/**
+ * For the given event, return the matching event filter. This filter may then
+ * be AND'ed with the selected event mask.
+ *
+ * For XI2 events, the returned filter is simply the byte containing the event
+ * mask we're interested in. E.g. for a mask of (1 << 13), this would be
+ * byte[1].
+ *
+ * @param[in] dev The device the event belongs to, may be NULL.
+ * @param[in] event The event to get the filter for. Only the type of the
+ * event matters, or the extension + evtype for GenericEvents.
+ * @return The filter mask for the given event.
+ *
+ * @see GetEventMask
+ */
+Mask
+GetEventFilter(DeviceIntPtr dev, xEvent *event)
+{
+ if (event->u.u.type != GenericEvent)
+ return filters[dev ? dev->id : 0][event->u.u.type];
+ else if (XI2_EVENT(event))
+ return (1 << (((xXIDeviceEvent*)event)->evtype % 8));
+ ErrorF("[dix] Unknown device type %d. No filter\n", event->u.u.type);
+ return 0;
+}
+
+/**
+ * Return the windows complete XI2 mask for the given XI2 event type.
+ */
+Mask
+GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
+{
+ OtherInputMasks *inputMasks = wOtherInputMasks(win);
+ int filter;
+ int evtype;
+
+ if (!inputMasks || !XI2_EVENT(ev))
+ return 0;
+
+ evtype = ((xGenericEvent*)ev)->evtype;
+ filter = GetEventFilter(dev, ev);
+
+ return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) ||
+ inputMasks->xi2mask[XIAllDevices][evtype/8] ||
+ (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev)));
+}
+
+Mask
+GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
+{
+ /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
+ if (XI2_EVENT(event))
+ {
+ int byte = ((xGenericEvent*)event)->evtype / 8;
+ return (other->xi2mask[dev->id][byte] |
+ other->xi2mask[XIAllDevices][byte] |
+ (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0));
+ } else if (CORE_EVENT(event))
+ return other->mask[XIAllDevices];
+ else
+ return other->mask[dev->id];
+}
+
+
+static CARD8 criticalEvents[32] =
+{
+ 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */
+};
+
+static void
+SyntheticMotion(DeviceIntPtr dev, int x, int y) {
+ int screenno = 0;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ screenno = dev->spriteInfo->sprite->screen->myNum;
+#endif
+ PostSyntheticMotion(dev, x, y, screenno,
+ (syncEvents.playingEvents) ? syncEvents.time.milliseconds : currentTime.milliseconds);
+
+}
+
+#ifdef PANORAMIX
+static void PostNewCursor(DeviceIntPtr pDev);
+
+static Bool
+pointOnScreen(ScreenPtr pScreen, int x, int y)
+{
+ return x >= pScreen->x && x < pScreen->x + pScreen->width &&
+ y >= pScreen->y && y < pScreen->y + pScreen->height;
+}
+
+static Bool
+XineramaSetCursorPosition(
+ DeviceIntPtr pDev,
+ int x,
+ int y,
+ Bool generateEvent
+){
+ ScreenPtr pScreen;
+ int i;
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+
+ /* x,y are in Screen 0 coordinates. We need to decide what Screen
+ to send the message too and what the coordinates relative to
+ that screen are. */
+
+ pScreen = pSprite->screen;
+ x += screenInfo.screens[0]->x;
+ y += screenInfo.screens[0]->y;
+
+ if(!pointOnScreen(pScreen, x, y))
+ {
+ FOR_NSCREENS(i)
+ {
+ if(i == pScreen->myNum)
+ continue;
+ if(pointOnScreen(screenInfo.screens[i], x, y))
+ {
+ pScreen = screenInfo.screens[i];
+ break;
+ }
+ }
+ }
+
+ pSprite->screen = pScreen;
+ pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
+ pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
+ x -= pScreen->x;
+ y -= pScreen->y;
+
+ return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
+}
+
+
+static void
+XineramaConstrainCursor(DeviceIntPtr pDev)
+{
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+ ScreenPtr pScreen;
+ BoxRec newBox;
+
+ pScreen = pSprite->screen;
+ newBox = pSprite->physLimits;
+
+ /* Translate the constraining box to the screen
+ the sprite is actually on */
+ newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
+ newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
+ newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
+ newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
+
+ (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
+}
+
+
+static Bool
+XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
+{
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+
+ if(pWin == screenInfo.screens[0]->root) {
+ int i;
+ for (i = 0; i < PanoramiXNumScreens; i++)
+ pSprite->windows[i] = screenInfo.screens[i]->root;
+ } else {
+ PanoramiXRes *win;
+ int rc, i;
+
+ rc = dixLookupResourceByType((pointer *)&win, pWin->drawable.id,
+ XRT_WINDOW, serverClient, DixReadAccess);
+ if (rc != Success)
+ return FALSE;
+
+ for(i = 0; i < PanoramiXNumScreens; i++) {
+ rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
+ serverClient, DixReadAccess);
+ if (rc != Success) /* window is being unmapped */
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void
+XineramaConfineCursorToWindow(DeviceIntPtr pDev,
+ WindowPtr pWin,
+ Bool generateEvents)
+{
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+
+ int x, y, off_x, off_y, i;
+
+ if(!XineramaSetWindowPntrs(pDev, pWin))
+ return;
+
+ i = PanoramiXNumScreens - 1;
+
+ RegionCopy(&pSprite->Reg1,
+ &pSprite->windows[i]->borderSize);
+ off_x = screenInfo.screens[i]->x;
+ off_y = screenInfo.screens[i]->y;
+
+ while(i--) {
+ x = off_x - screenInfo.screens[i]->x;
+ y = off_y - screenInfo.screens[i]->y;
+
+ if(x || y)
+ RegionTranslate(&pSprite->Reg1, x, y);
+
+ RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
+ &pSprite->windows[i]->borderSize);
+
+ off_x = screenInfo.screens[i]->x;
+ off_y = screenInfo.screens[i]->y;
+ }
+
+ pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
+
+ if(RegionNumRects(&pSprite->Reg1) > 1)
+ pSprite->hotShape = &pSprite->Reg1;
+ else
+ pSprite->hotShape = NullRegion;
+
+ pSprite->confined = FALSE;
+ pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
+
+ CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
+}
+
+#endif /* PANORAMIX */
+
+/**
+ * Modifies the filter for the given protocol event type to the given masks.
+ *
+ * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
+ * The latter initialises masks for the matching XI events, it's a once-off
+ * setting.
+ * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
+ * time a button is pressed to include the matching ButtonXMotion mask in the
+ * filter.
+ *
+ * @param[in] deviceid The device to modify the filter for.
+ * @param[in] mask The new filter mask.
+ * @param[in] event Protocol event type.
+ */
+void
+SetMaskForEvent(int deviceid, Mask mask, int event)
+{
+ if (deviceid < 0 || deviceid >= MAXDEVICES)
+ FatalError("SetMaskForEvent: bogus device id");
+ filters[deviceid][event] = mask;
+}
+
+void
+SetCriticalEvent(int event)
+{
+ if (event >= 128)
+ FatalError("SetCriticalEvent: bogus event number");
+ criticalEvents[event >> 3] |= 1 << (event & 7);
+}
+
+void
+ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
+{
+ BoxRec box;
+ int x = *px, y = *py;
+ int incx = 1, incy = 1;
+ SpritePtr pSprite;
+
+ pSprite = pDev->spriteInfo->sprite;
+ if (RegionContainsPoint(shape, x, y, &box))
+ return;
+ box = *RegionExtents(shape);
+ /* this is rather crude */
+ do {
+ x += incx;
+ if (x >= box.x2)
+ {
+ incx = -1;
+ x = *px - 1;
+ }
+ else if (x < box.x1)
+ {
+ incx = 1;
+ x = *px;
+ y += incy;
+ if (y >= box.y2)
+ {
+ incy = -1;
+ y = *py - 1;
+ }
+ else if (y < box.y1)
+ return; /* should never get here! */
+ }
+ } while (!RegionContainsPoint(shape, x, y, &box));
+ *px = x;
+ *py = y;
+}
+
+static void
+CheckPhysLimits(
+ DeviceIntPtr pDev,
+ CursorPtr cursor,
+ Bool generateEvents,
+ Bool confineToScreen, /* unused if PanoramiX on */
+ ScreenPtr pScreen) /* unused if PanoramiX on */
+{
+ HotSpot new;
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+
+ if (!cursor)
+ return;
+ new = pSprite->hotPhys;
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ /* I don't care what the DDX has to say about it */
+ pSprite->physLimits = pSprite->hotLimits;
+ else
+#endif
+ {
+ if (pScreen)
+ new.pScreen = pScreen;
+ else
+ pScreen = new.pScreen;
+ (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
+ &pSprite->physLimits);
+ pSprite->confined = confineToScreen;
+ (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
+ }
+
+ /* constrain the pointer to those limits */
+ if (new.x < pSprite->physLimits.x1)
+ new.x = pSprite->physLimits.x1;
+ else
+ if (new.x >= pSprite->physLimits.x2)
+ new.x = pSprite->physLimits.x2 - 1;
+ if (new.y < pSprite->physLimits.y1)
+ new.y = pSprite->physLimits.y1;
+ else
+ if (new.y >= pSprite->physLimits.y2)
+ new.y = pSprite->physLimits.y2 - 1;
+ if (pSprite->hotShape)
+ ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
+ if ((
+#ifdef PANORAMIX
+ noPanoramiXExtension &&
+#endif
+ (pScreen != pSprite->hotPhys.pScreen)) ||
+ (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
+ {
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
+ else
+#endif
+ {
+ if (pScreen != pSprite->hotPhys.pScreen)
+ pSprite->hotPhys = new;
+ (*pScreen->SetCursorPosition)
+ (pDev, pScreen, new.x, new.y, generateEvents);
+ }
+ if (!generateEvents)
+ SyntheticMotion(pDev, new.x, new.y);
+ }
+
+#ifdef PANORAMIX
+ /* Tell DDX what the limits are */
+ if (!noPanoramiXExtension)
+ XineramaConstrainCursor(pDev);
+#endif
+}
+
+static void
+CheckVirtualMotion(
+ DeviceIntPtr pDev,
+ QdEventPtr qe,
+ WindowPtr pWin)
+{
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+ RegionPtr reg = NULL;
+ DeviceEvent *ev = NULL;
+
+ if (qe)
+ {
+ ev = &qe->event->device_event;
+ switch(ev->type)
+ {
+ case ET_Motion:
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_KeyPress:
+ case ET_KeyRelease:
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ pSprite->hot.pScreen = qe->pScreen;
+ pSprite->hot.x = ev->root_x;
+ pSprite->hot.y = ev->root_y;
+ pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
+ break;
+ default:
+ break;
+ }
+ }
+ if (pWin)
+ {
+ BoxRec lims;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) {
+ int x, y, off_x, off_y, i;
+
+ if(!XineramaSetWindowPntrs(pDev, pWin))
+ return;
+
+ i = PanoramiXNumScreens - 1;
+
+ RegionCopy(&pSprite->Reg2,
+ &pSprite->windows[i]->borderSize);
+ off_x = screenInfo.screens[i]->x;
+ off_y = screenInfo.screens[i]->y;
+
+ while(i--) {
+ x = off_x - screenInfo.screens[i]->x;
+ y = off_y - screenInfo.screens[i]->y;
+
+ if(x || y)
+ RegionTranslate(&pSprite->Reg2, x, y);
+
+ RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
+ &pSprite->windows[i]->borderSize);
+
+ off_x = screenInfo.screens[i]->x;
+ off_y = screenInfo.screens[i]->y;
+ }
+ } else
+#endif
+ {
+ if (pSprite->hot.pScreen != pWin->drawable.pScreen)
+ {
+ pSprite->hot.pScreen = pWin->drawable.pScreen;
+ pSprite->hot.x = pSprite->hot.y = 0;
+ }
+ }
+
+ lims = *RegionExtents(&pWin->borderSize);
+ if (pSprite->hot.x < lims.x1)
+ pSprite->hot.x = lims.x1;
+ else if (pSprite->hot.x >= lims.x2)
+ pSprite->hot.x = lims.x2 - 1;
+ if (pSprite->hot.y < lims.y1)
+ pSprite->hot.y = lims.y1;
+ else if (pSprite->hot.y >= lims.y2)
+ pSprite->hot.y = lims.y2 - 1;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ if (RegionNumRects(&pSprite->Reg2) > 1)
+ reg = &pSprite->Reg2;
+
+ } else
+#endif
+ {
+ if (wBoundingShape(pWin))
+ reg = &pWin->borderSize;
+ }
+
+ if (reg)
+ ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
+
+ if (qe && ev)
+ {
+ qe->pScreen = pSprite->hot.pScreen;
+ ev->root_x = pSprite->hot.x;
+ ev->root_y = pSprite->hot.y;
+ }
+ }
+#ifdef PANORAMIX
+ if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */
+#endif
+ RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
+}
+
+static void
+ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
+{
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+
+ if (syncEvents.playingEvents)
+ {
+ CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
+ SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
+ }
+ else
+ {
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
+ return;
+ }
+#endif
+ pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
+ pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
+ : NullRegion;
+ CheckPhysLimits(pDev, pSprite->current, generateEvents,
+ confineToScreen, pWin->drawable.pScreen);
+ }
+}
+
+Bool
+PointerConfinedToScreen(DeviceIntPtr pDev)
+{
+ return pDev->spriteInfo->sprite->confined;
+}
+
+/**
+ * Update the sprite cursor to the given cursor.
+ *
+ * ChangeToCursor() will display the new cursor and free the old cursor (if
+ * applicable). If the provided cursor is already the updated cursor, nothing
+ * happens.
+ */
+static void
+ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
+{
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+ ScreenPtr pScreen;
+
+ if (cursor != pSprite->current)
+ {
+ if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
+ (pSprite->current->bits->yhot != cursor->bits->yhot))
+ CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
+ (ScreenPtr)NULL);
+#ifdef PANORAMIX
+ /* XXX: is this really necessary?? (whot) */
+ if (!noPanoramiXExtension)
+ pScreen = pSprite->screen;
+ else
+#endif
+ pScreen = pSprite->hotPhys.pScreen;
+
+ (*pScreen->DisplayCursor)(pDev, pScreen, cursor);
+ FreeCursor(pSprite->current, (Cursor)0);
+ pSprite->current = cursor;
+ pSprite->current->refcnt++;
+ }
+}
+
+/**
+ * @returns true if b is a descendent of a
+ */
+Bool
+IsParent(WindowPtr a, WindowPtr b)
+{
+ for (b = b->parent; b; b = b->parent)
+ if (b == a) return TRUE;
+ return FALSE;
+}
+
+/**
+ * Update the cursor displayed on the screen.
+ *
+ * Called whenever a cursor may have changed shape or position.
+ */
+static void
+PostNewCursor(DeviceIntPtr pDev)
+{
+ WindowPtr win;
+ GrabPtr grab = pDev->deviceGrab.grab;
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+ CursorPtr pCursor;
+
+ if (syncEvents.playingEvents)
+ return;
+ if (grab)
+ {
+ if (grab->cursor)
+ {
+ ChangeToCursor(pDev, grab->cursor);
+ return;
+ }
+ if (IsParent(grab->window, pSprite->win))
+ win = pSprite->win;
+ else
+ win = grab->window;
+ }
+ else
+ win = pSprite->win;
+ for (; win; win = win->parent)
+ {
+ if (win->optional)
+ {
+ pCursor = WindowGetDeviceCursor(win, pDev);
+ if (!pCursor && win->optional->cursor != NullCursor)
+ pCursor = win->optional->cursor;
+ if (pCursor)
+ {
+ ChangeToCursor(pDev, pCursor);
+ return;
+ }
+ }
+ }
+}
+
+
+/**
+ * @param dev device which you want to know its current root window
+ * @return root window where dev's sprite is located
+ */
+WindowPtr
+GetCurrentRootWindow(DeviceIntPtr dev)
+{
+ return RootWindow(dev->spriteInfo->sprite);
+}
+
+/**
+ * @return window underneath the cursor sprite.
+ */
+WindowPtr
+GetSpriteWindow(DeviceIntPtr pDev)
+{
+ return pDev->spriteInfo->sprite->win;
+}
+
+/**
+ * @return current sprite cursor.
+ */
+CursorPtr
+GetSpriteCursor(DeviceIntPtr pDev)
+{
+ return pDev->spriteInfo->sprite->current;
+}
+
+/**
+ * Set x/y current sprite position in screen coordinates.
+ */
+void
+GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
+{
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+ *px = pSprite->hotPhys.x;
+ *py = pSprite->hotPhys.y;
+}
+
+#ifdef PANORAMIX
+int
+XineramaGetCursorScreen(DeviceIntPtr pDev)
+{
+ if(!noPanoramiXExtension) {
+ return pDev->spriteInfo->sprite->screen->myNum;
+ } else {
+ return 0;
+ }
+}
+#endif /* PANORAMIX */
+
+#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
+
+static void
+MonthChangedOrBadTime(InternalEvent *ev)
+{
+ /* If the ddx/OS is careless about not processing timestamped events from
+ * different sources in sorted order, then it's possible for time to go
+ * backwards when it should not. Here we ensure a decent time.
+ */
+ if ((currentTime.milliseconds - ev->any.time) > TIMESLOP)
+ currentTime.months++;
+ else
+ ev->any.time = currentTime.milliseconds;
+}
+
+static void
+NoticeTime(InternalEvent *ev)
+{
+ if (ev->any.time < currentTime.milliseconds)
+ MonthChangedOrBadTime(ev);
+ currentTime.milliseconds = ev->any.time;
+ lastDeviceEventTime = currentTime;
+}
+
+void
+NoticeEventTime(InternalEvent *ev)
+{
+ if (!syncEvents.playingEvents)
+ NoticeTime(ev);
+}
+
+/**************************************************************************
+ * The following procedures deal with synchronous events *
+ **************************************************************************/
+
+/**
+ * EnqueueEvent is a device's processInputProc if a device is frozen.
+ * Instead of delivering the events to the client, the event is tacked onto a
+ * linked list for later delivery.
+ */
+void
+EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
+{
+ QdEventPtr tail = *syncEvents.pendtail;
+ QdEventPtr qe;
+ SpritePtr pSprite = device->spriteInfo->sprite;
+ int eventlen;
+ DeviceEvent *event = &ev->device_event;
+
+ NoticeTime((InternalEvent*)event);
+
+ /* Fix for key repeating bug. */
+ if (device->key != NULL && device->key->xkbInfo != NULL &&
+ event->type == ET_KeyRelease)
+ AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
+
+ if (DeviceEventCallback)
+ {
+ DeviceEventInfoRec eventinfo;
+
+ /* The RECORD spec says that the root window field of motion events
+ * must be valid. At this point, it hasn't been filled in yet, so
+ * we do it here. The long expression below is necessary to get
+ * the current root window; the apparently reasonable alternative
+ * GetCurrentRootWindow()->drawable.id doesn't give you the right
+ * answer on the first motion event after a screen change because
+ * the data that GetCurrentRootWindow relies on hasn't been
+ * updated yet.
+ */
+ if (ev->any.type == ET_Motion)
+ ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
+
+ eventinfo.event = ev;
+ eventinfo.device = device;
+ CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
+ }
+
+ if (event->type == ET_Motion)
+ {
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
+ event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
+ }
+#endif
+ pSprite->hotPhys.x = event->root_x;
+ pSprite->hotPhys.y = event->root_y;
+ /* do motion compression, but not if from different devices */
+ if (tail &&
+ (tail->event->any.type == ET_Motion) &&
+ (tail->device == device) &&
+ (tail->pScreen == pSprite->hotPhys.pScreen))
+ {
+ DeviceEvent *tailev = &tail->event->device_event;
+ tailev->root_x = pSprite->hotPhys.x;
+ tailev->root_y = pSprite->hotPhys.y;
+ tailev->time = event->time;
+ tail->months = currentTime.months;
+ return;
+ }
+ }
+
+ eventlen = event->length;
+
+ qe = malloc(sizeof(QdEventRec) + eventlen);
+ if (!qe)
+ return;
+ qe->next = (QdEventPtr)NULL;
+ qe->device = device;
+ qe->pScreen = pSprite->hotPhys.pScreen;
+ qe->months = currentTime.months;
+ qe->event = (InternalEvent *)(qe + 1);
+ memcpy(qe->event, event, eventlen);
+ if (tail)
+ syncEvents.pendtail = &tail->next;
+ *syncEvents.pendtail = qe;
+}
+
+/**
+ * Run through the list of events queued up in syncEvents.
+ * For each event do:
+ * If the device for this event is not frozen anymore, take it and process it
+ * as usually.
+ * After that, check if there's any devices in the list that are not frozen.
+ * If there is none, we're done. If there is at least one device that is not
+ * frozen, then re-run from the beginning of the event queue.
+ */
+static void
+PlayReleasedEvents(void)
+{
+ QdEventPtr *prev, qe;
+ DeviceIntPtr dev;
+ DeviceIntPtr pDev;
+
+ prev = &syncEvents.pending;
+ while ( (qe = *prev) )
+ {
+ if (!qe->device->deviceGrab.sync.frozen)
+ {
+ *prev = qe->next;
+ pDev = qe->device;
+ if (*syncEvents.pendtail == *prev)
+ syncEvents.pendtail = prev;
+ if (qe->event->any.type == ET_Motion)
+ CheckVirtualMotion(pDev, qe, NullWindow);
+ syncEvents.time.months = qe->months;
+ syncEvents.time.milliseconds = qe->event->any.time;
+#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) {
+ DeviceEvent *ev = &qe->event->device_event;
+ switch(ev->type)
+ {
+ case ET_Motion:
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_KeyPress:
+ case ET_KeyRelease:
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ ev->root_x += screenInfo.screens[0]->x -
+ pDev->spriteInfo->sprite->screen->x;
+ ev->root_y += screenInfo.screens[0]->y -
+ pDev->spriteInfo->sprite->screen->y;
+ break;
+ default:
+ break;
+ }
+
+ }
+#endif
+ (*qe->device->public.processInputProc)(qe->event, qe->device);
+ free(qe);
+ for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
+ ;
+ if (!dev)
+ break;
+ /* Playing the event may have unfrozen another device. */
+ /* So to play it safe, restart at the head of the queue */
+ prev = &syncEvents.pending;
+ }
+ else
+ prev = &qe->next;
+ }
+}
+
+/**
+ * Freeze or thaw the given devices. The device's processing proc is
+ * switched to either the real processing proc (in case of thawing) or an
+ * enqueuing processing proc (usually EnqueueEvent()).
+ *
+ * @param dev The device to freeze/thaw
+ * @param frozen True to freeze or false to thaw.
+ */
+static void
+FreezeThaw(DeviceIntPtr dev, Bool frozen)
+{
+ dev->deviceGrab.sync.frozen = frozen;
+ if (frozen)
+ dev->public.processInputProc = dev->public.enqueueInputProc;
+ else
+ dev->public.processInputProc = dev->public.realInputProc;
+}
+
+/**
+ * Unfreeze devices and replay all events to the respective clients.
+ *
+ * ComputeFreezes takes the first event in the device's frozen event queue. It
+ * runs up the sprite tree (spriteTrace) and searches for the window to replay
+ * the events from. If it is found, it checks for passive grabs one down from
+ * the window or delivers the events.
+ */
+static void
+ComputeFreezes(void)
+{
+ DeviceIntPtr replayDev = syncEvents.replayDev;
+ WindowPtr w;
+ GrabPtr grab;
+ DeviceIntPtr dev;
+
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ FreezeThaw(dev, dev->deviceGrab.sync.other ||
+ (dev->deviceGrab.sync.state >= FROZEN));
+ if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
+ return;
+ syncEvents.playingEvents = TRUE;
+ if (replayDev)
+ {
+ DeviceEvent* event = replayDev->deviceGrab.sync.event;
+
+ syncEvents.replayDev = (DeviceIntPtr)NULL;
+
+ w = XYToWindow(replayDev->spriteInfo->sprite,
+ event->root_x, event->root_y);
+ if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin))
+ {
+ if (replayDev->focus && !IsPointerEvent((InternalEvent*)event))
+ DeliverFocusedEvent(replayDev, (InternalEvent*)event, w);
+ else
+ DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab,
+ NullWindow, replayDev);
+ }
+ }
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (!dev->deviceGrab.sync.frozen)
+ {
+ PlayReleasedEvents();
+ break;
+ }
+ }
+ syncEvents.playingEvents = FALSE;
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (DevHasCursor(dev))
+ {
+ /* the following may have been skipped during replay,
+ so do it now */
+ if ((grab = dev->deviceGrab.grab) && grab->confineTo)
+ {
+ if (grab->confineTo->drawable.pScreen !=
+ dev->spriteInfo->sprite->hotPhys.pScreen)
+ dev->spriteInfo->sprite->hotPhys.x =
+ dev->spriteInfo->sprite->hotPhys.y = 0;
+ ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
+ }
+ else
+ ConfineCursorToWindow(dev,
+ dev->spriteInfo->sprite->hotPhys.pScreen->root,
+ TRUE, FALSE);
+ PostNewCursor(dev);
+ }
+ }
+}
+
+#ifdef RANDR
+void
+ScreenRestructured (ScreenPtr pScreen)
+{
+ GrabPtr grab;
+ DeviceIntPtr pDev;
+
+ for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (!DevHasCursor(pDev))
+ continue;
+
+ /* GrabDevice doesn't have a confineTo field, so we don't need to
+ * worry about it. */
+ if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
+ {
+ if (grab->confineTo->drawable.pScreen
+ != pDev->spriteInfo->sprite->hotPhys.pScreen)
+ pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
+ ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
+ }
+ else
+ ConfineCursorToWindow(pDev,
+ pDev->spriteInfo->sprite->hotPhys.pScreen->root,
+ TRUE, FALSE);
+ }
+}
+#endif
+
+static void
+CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
+{
+ GrabPtr grab = thisDev->deviceGrab.grab;
+ DeviceIntPtr dev;
+
+ if (thisMode == GrabModeSync)
+ thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
+ else
+ { /* free both if same client owns both */
+ thisDev->deviceGrab.sync.state = THAWED;
+ if (thisDev->deviceGrab.sync.other &&
+ (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
+ CLIENT_BITS(grab->resource)))
+ thisDev->deviceGrab.sync.other = NullGrab;
+ }
+
+ if (IsMaster(thisDev))
+ {
+ dev = GetPairedDevice(thisDev);
+ if (otherMode == GrabModeSync)
+ dev->deviceGrab.sync.other = grab;
+ else
+ { /* free both if same client owns both */
+ if (dev->deviceGrab.sync.other &&
+ (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
+ CLIENT_BITS(grab->resource)))
+ dev->deviceGrab.sync.other = NullGrab;
+ }
+ }
+ ComputeFreezes();
+}
+
+/**
+ * Save the device's master device id. This needs to be done
+ * if a client directly grabs a slave device that is attached to a master. For
+ * the duration of the grab, the device is detached, ungrabbing re-attaches it
+ * though.
+ *
+ * We store the ID of the master device only in case the master disappears
+ * while the device has a grab.
+ */
+static void
+DetachFromMaster(DeviceIntPtr dev)
+{
+ if (!dev->u.master)
+ return;
+
+ dev->saved_master_id = dev->u.master->id;
+
+ AttachDevice(NULL, dev, NULL);
+}
+
+static void
+ReattachToOldMaster(DeviceIntPtr dev)
+{
+ DeviceIntPtr master = NULL;
+
+ if (IsMaster(dev))
+ return;
+
+ dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
+
+ if (master)
+ {
+ AttachDevice(serverClient, dev, master);
+ dev->saved_master_id = 0;
+ }
+}
+
+/**
+ * Activate a pointer grab on the given device. A pointer grab will cause all
+ * core pointer events of this device to be delivered to the grabbing client only.
+ * No other device will send core events to the grab client while the grab is
+ * on, but core events will be sent to other clients.
+ * Can cause the cursor to change if a grab cursor is set.
+ *
+ * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
+ * is an implicit grab caused by a ButtonPress event.
+ *
+ * @param mouse The device to grab.
+ * @param grab The grab structure, needs to be setup.
+ * @param autoGrab True if the grab was caused by a button down event and not
+ * explicitely by a client.
+ */
+void
+ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
+ TimeStamp time, Bool autoGrab)
+{
+ GrabInfoPtr grabinfo = &mouse->deviceGrab;
+ WindowPtr oldWin = (grabinfo->grab) ?
+ grabinfo->grab->window
+ : mouse->spriteInfo->sprite->win;
+ Bool isPassive = autoGrab & ~ImplicitGrabMask;
+
+ /* slave devices need to float for the duration of the grab. */
+ if (grab->grabtype == GRABTYPE_XI2 &&
+ !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
+ DetachFromMaster(mouse);
+
+ if (grab->confineTo)
+ {
+ if (grab->confineTo->drawable.pScreen
+ != mouse->spriteInfo->sprite->hotPhys.pScreen)
+ mouse->spriteInfo->sprite->hotPhys.x =
+ mouse->spriteInfo->sprite->hotPhys.y = 0;
+ ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
+ }
+ DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
+ mouse->valuator->motionHintWindow = NullWindow;
+ if (syncEvents.playingEvents)
+ grabinfo->grabTime = syncEvents.time;
+ else
+ grabinfo->grabTime = time;
+ if (grab->cursor)
+ grab->cursor->refcnt++;
+ grabinfo->activeGrab = *grab;
+ grabinfo->grab = &grabinfo->activeGrab;
+ grabinfo->fromPassiveGrab = isPassive;
+ grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
+ PostNewCursor(mouse);
+ CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
+}
+
+/**
+ * Delete grab on given device, update the sprite.
+ *
+ * Extension devices are set up for ActivateKeyboardGrab().
+ */
+void
+DeactivatePointerGrab(DeviceIntPtr mouse)
+{
+ GrabPtr grab = mouse->deviceGrab.grab;
+ DeviceIntPtr dev;
+ Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
+ mouse->deviceGrab.implicitGrab);
+
+ mouse->valuator->motionHintWindow = NullWindow;
+ mouse->deviceGrab.grab = NullGrab;
+ mouse->deviceGrab.sync.state = NOT_GRABBED;
+ mouse->deviceGrab.fromPassiveGrab = FALSE;
+
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (dev->deviceGrab.sync.other == grab)
+ dev->deviceGrab.sync.other = NullGrab;
+ }
+ DoEnterLeaveEvents(mouse, mouse->id, grab->window,
+ mouse->spriteInfo->sprite->win, NotifyUngrab);
+ if (grab->confineTo)
+ ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
+ PostNewCursor(mouse);
+ if (grab->cursor)
+ FreeCursor(grab->cursor, (Cursor)0);
+
+ if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
+ ReattachToOldMaster(mouse);
+
+ ComputeFreezes();
+}
+
+/**
+ * Activate a keyboard grab on the given device.
+ *
+ * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
+ */
+void
+ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
+{
+ GrabInfoPtr grabinfo = &keybd->deviceGrab;
+ WindowPtr oldWin;
+
+ /* slave devices need to float for the duration of the grab. */
+ if (grab->grabtype == GRABTYPE_XI2 &&
+ !(passive & ImplicitGrabMask) &&
+ !IsMaster(keybd))
+ DetachFromMaster(keybd);
+
+ if (grabinfo->grab)
+ oldWin = grabinfo->grab->window;
+ else if (keybd->focus)
+ oldWin = keybd->focus->win;
+ else
+ oldWin = keybd->spriteInfo->sprite->win;
+ if (oldWin == FollowKeyboardWin)
+ oldWin = keybd->focus->win;
+ if (keybd->valuator)
+ keybd->valuator->motionHintWindow = NullWindow;
+ DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
+ if (syncEvents.playingEvents)
+ grabinfo->grabTime = syncEvents.time;
+ else
+ grabinfo->grabTime = time;
+ grabinfo->activeGrab = *grab;
+ grabinfo->grab = &grabinfo->activeGrab;
+ grabinfo->fromPassiveGrab = passive;
+ grabinfo->implicitGrab = passive & ImplicitGrabMask;
+ CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
+}
+
+/**
+ * Delete keyboard grab for the given device.
+ */
+void
+DeactivateKeyboardGrab(DeviceIntPtr keybd)
+{
+ GrabPtr grab = keybd->deviceGrab.grab;
+ DeviceIntPtr dev;
+ WindowPtr focusWin = keybd->focus ? keybd->focus->win
+ : keybd->spriteInfo->sprite->win;
+ Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
+ keybd->deviceGrab.implicitGrab);
+
+ if (focusWin == FollowKeyboardWin)
+ focusWin = inputInfo.keyboard->focus->win;
+ if (keybd->valuator)
+ keybd->valuator->motionHintWindow = NullWindow;
+ keybd->deviceGrab.grab = NullGrab;
+ keybd->deviceGrab.sync.state = NOT_GRABBED;
+ keybd->deviceGrab.fromPassiveGrab = FALSE;
+
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (dev->deviceGrab.sync.other == grab)
+ dev->deviceGrab.sync.other = NullGrab;
+ }
+ DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
+
+ if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
+ ReattachToOldMaster(keybd);
+
+ ComputeFreezes();
+}
+
+void
+AllowSome(ClientPtr client,
+ TimeStamp time,
+ DeviceIntPtr thisDev,
+ int newState)
+{
+ Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
+ TimeStamp grabTime;
+ DeviceIntPtr dev;
+ GrabInfoPtr devgrabinfo,
+ grabinfo = &thisDev->deviceGrab;
+
+ thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
+ thisSynced = FALSE;
+ otherGrabbed = FALSE;
+ othersFrozen = FALSE;
+ grabTime = grabinfo->grabTime;
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ devgrabinfo = &dev->deviceGrab;
+
+ if (dev == thisDev)
+ continue;
+ if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
+ {
+ if (!(thisGrabbed || otherGrabbed) ||
+ (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
+ grabTime = devgrabinfo->grabTime;
+ otherGrabbed = TRUE;
+ if (grabinfo->sync.other == devgrabinfo->grab)
+ thisSynced = TRUE;
+ if (devgrabinfo->sync.state >= FROZEN)
+ othersFrozen = TRUE;
+ }
+ }
+ if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
+ return;
+ if ((CompareTimeStamps(time, currentTime) == LATER) ||
+ (CompareTimeStamps(time, grabTime) == EARLIER))
+ return;
+ switch (newState)
+ {
+ case THAWED: /* Async */
+ if (thisGrabbed)
+ grabinfo->sync.state = THAWED;
+ if (thisSynced)
+ grabinfo->sync.other = NullGrab;
+ ComputeFreezes();
+ break;
+ case FREEZE_NEXT_EVENT: /* Sync */
+ if (thisGrabbed)
+ {
+ grabinfo->sync.state = FREEZE_NEXT_EVENT;
+ if (thisSynced)
+ grabinfo->sync.other = NullGrab;
+ ComputeFreezes();
+ }
+ break;
+ case THAWED_BOTH: /* AsyncBoth */
+ if (othersFrozen)
+ {
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ devgrabinfo = &dev->deviceGrab;
+ if (devgrabinfo->grab
+ && SameClient(devgrabinfo->grab, client))
+ devgrabinfo->sync.state = THAWED;
+ if (devgrabinfo->sync.other &&
+ SameClient(devgrabinfo->sync.other, client))
+ devgrabinfo->sync.other = NullGrab;
+ }
+ ComputeFreezes();
+ }
+ break;
+ case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */
+ if (othersFrozen)
+ {
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ devgrabinfo = &dev->deviceGrab;
+ if (devgrabinfo->grab
+ && SameClient(devgrabinfo->grab, client))
+ devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
+ if (devgrabinfo->sync.other
+ && SameClient(devgrabinfo->sync.other, client))
+ devgrabinfo->sync.other = NullGrab;
+ }
+ ComputeFreezes();
+ }
+ break;
+ case NOT_GRABBED: /* Replay */
+ if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
+ {
+ if (thisSynced)
+ grabinfo->sync.other = NullGrab;
+ syncEvents.replayDev = thisDev;
+ syncEvents.replayWin = grabinfo->grab->window;
+ (*grabinfo->DeactivateGrab)(thisDev);
+ syncEvents.replayDev = (DeviceIntPtr)NULL;
+ }
+ break;
+ case THAW_OTHERS: /* AsyncOthers */
+ if (othersFrozen)
+ {
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (dev == thisDev)
+ continue;
+ devgrabinfo = &dev->deviceGrab;
+ if (devgrabinfo->grab
+ && SameClient(devgrabinfo->grab, client))
+ devgrabinfo->sync.state = THAWED;
+ if (devgrabinfo->sync.other
+ && SameClient(devgrabinfo->sync.other, client))
+ devgrabinfo->sync.other = NullGrab;
+ }
+ ComputeFreezes();
+ }
+ break;
+ }
+}
+
+/**
+ * Server-side protocol handling for AllowEvents request.
+ *
+ * Release some events from a frozen device.
+ */
+int
+ProcAllowEvents(ClientPtr client)
+{
+ TimeStamp time;
+ DeviceIntPtr mouse = NULL;
+ DeviceIntPtr keybd = NULL;
+ REQUEST(xAllowEventsReq);
+
+ REQUEST_SIZE_MATCH(xAllowEventsReq);
+ time = ClientTimeToServerTime(stuff->time);
+
+ mouse = PickPointer(client);
+ keybd = PickKeyboard(client);
+
+ switch (stuff->mode)
+ {
+ case ReplayPointer:
+ AllowSome(client, time, mouse, NOT_GRABBED);
+ break;
+ case SyncPointer:
+ AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
+ break;
+ case AsyncPointer:
+ AllowSome(client, time, mouse, THAWED);
+ break;
+ case ReplayKeyboard:
+ AllowSome(client, time, keybd, NOT_GRABBED);
+ break;
+ case SyncKeyboard:
+ AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
+ break;
+ case AsyncKeyboard:
+ AllowSome(client, time, keybd, THAWED);
+ break;
+ case SyncBoth:
+ AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
+ break;
+ case AsyncBoth:
+ AllowSome(client, time, keybd, THAWED_BOTH);
+ break;
+ default:
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
+ return Success;
+}
+
+/**
+ * Deactivate grabs from any device that has been grabbed by the client.
+ */
+void
+ReleaseActiveGrabs(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ Bool done;
+
+ /* XXX CloseDownClient should remove passive grabs before
+ * releasing active grabs.
+ */
+ do {
+ done = TRUE;
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
+ {
+ (*dev->deviceGrab.DeactivateGrab)(dev);
+ done = FALSE;
+ }
+ }
+ } while (!done);
+}
+
+/**************************************************************************
+ * The following procedures deal with delivering events *
+ **************************************************************************/
+
+/**
+ * Deliver the given events to the given client.
+ *
+ * More than one event may be delivered at a time. This is the case with
+ * DeviceMotionNotifies which may be followed by DeviceValuator events.
+ *
+ * TryClientEvents() is the last station before actually writing the events to
+ * the socket. Anything that is not filtered here, will get delivered to the
+ * client.
+ * An event is only delivered if
+ * - mask and filter match up.
+ * - no other client has a grab on the device that caused the event.
+ *
+ *
+ * @param client The target client to deliver to.
+ * @param dev The device the event came from. May be NULL.
+ * @param pEvents The events to be delivered.
+ * @param count Number of elements in pEvents.
+ * @param mask Event mask as set by the window.
+ * @param filter Mask based on event type.
+ * @param grab Possible grab on the device that caused the event.
+ *
+ * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
+ * client.
+ */
+int
+TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
+ int count, Mask mask, Mask filter, GrabPtr grab)
+{
+ int type;
+
+#ifdef DEBUG_EVENTS
+ ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
+ pEvents->u.u.type, pEvents->u.u.detail, mask,
+ client ? client->index : -1,
+ (client && client->clientGone) ? " (gone)" : "");
+#endif
+
+ if (!client || client == serverClient || client->clientGone) {
+#ifdef DEBUG_EVENTS
+ ErrorF(" not delivered to fake/dead client\n");
+#endif
+ return 0;
+ }
+
+ if (filter != CantBeFiltered && !(mask & filter))
+ {
+ #ifdef DEBUG_EVENTS
+ ErrorF(" filtered\n");
+ #endif
+ return 0;
+ }
+
+ if (grab && !SameClient(grab, client))
+ {
+#ifdef DEBUG_EVENTS
+ ErrorF(" not delivered due to grab\n");
+#endif
+ return -1; /* don't send, but notify caller */
+ }
+
+ type = pEvents->u.u.type;
+ if (type == MotionNotify)
+ {
+ if (mask & PointerMotionHintMask)
+ {
+ if (WID(dev->valuator->motionHintWindow) ==
+ pEvents->u.keyButtonPointer.event)
+ {
+#ifdef DEBUG_EVENTS
+ ErrorF("[dix] \n");
+ ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
+#endif
+ return 1; /* don't send, but pretend we did */
+ }
+ pEvents->u.u.detail = NotifyHint;
+ }
+ else
+ {
+ pEvents->u.u.detail = NotifyNormal;
+ }
+ }
+ else if (type == DeviceMotionNotify)
+ {
+ if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents,
+ mask) != 0)
+ return 1;
+ } else if (type == KeyPress)
+ {
+ if (EventIsKeyRepeat(pEvents))
+ {
+ if (!_XkbWantsDetectableAutoRepeat(client))
+ {
+ xEvent release = *pEvents;
+ release.u.u.type = KeyRelease;
+ WriteEventsToClient(client, 1, &release);
+#ifdef DEBUG_EVENTS
+ ErrorF(" (plus fake core release for repeat)");
+#endif
+ } else
+ {
+#ifdef DEBUG_EVENTS
+ ErrorF(" (detectable autorepeat for core)");
+#endif
+ }
+ }
+
+ } else if (type == DeviceKeyPress)
+ {
+ if (EventIsKeyRepeat(pEvents))
+ {
+ if (!_XkbWantsDetectableAutoRepeat(client))
+ {
+ deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents;
+ release.type = DeviceKeyRelease;
+#ifdef DEBUG_EVENTS
+ ErrorF(" (plus fake xi1 release for repeat)");
+#endif
+ WriteEventsToClient(client, 1, (xEvent *) &release);
+ }
+ else {
+#ifdef DEBUG_EVENTS
+ ErrorF(" (detectable autorepeat for core)");
+#endif
+ }
+ }
+ }
+
+ if (BitIsOn(criticalEvents, type))
+ {
+ if (client->smart_priority < SMART_MAX_PRIORITY)
+ client->smart_priority++;
+ SetCriticalOutputPending();
+ }
+
+ WriteEventsToClient(client, count, pEvents);
+#ifdef DEBUG_EVENTS
+ ErrorF("[dix] delivered\n");
+#endif
+ return 1;
+}
+
+/**
+ * Deliver events to a window. At this point, we do not yet know if the event
+ * actually needs to be delivered. May activate a grab if the event is a
+ * button press.
+ *
+ * Core events are always delivered to the window owner. If the filter is
+ * something other than CantBeFiltered, the event is also delivered to other
+ * clients with the matching mask on the window.
+ *
+ * More than one event may be delivered at a time. This is the case with
+ * DeviceMotionNotifies which may be followed by DeviceValuator events.
+ *
+ * @param pWin The window that would get the event.
+ * @param pEvents The events to be delivered.
+ * @param count Number of elements in pEvents.
+ * @param filter Mask based on event type.
+ * @param grab Possible grab on the device that caused the event.
+ *
+ * @return Number of events delivered to various clients.
+ */
+int
+DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
+ *pEvents, int count, Mask filter, GrabPtr grab)
+{
+ int deliveries = 0, nondeliveries = 0;
+ int attempt;
+ InputClients *other;
+ ClientPtr client = NullClient;
+ Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
+ this mask is the mask of the grab. */
+ int type = pEvents->u.u.type;
+
+
+ /* Deliver to window owner */
+ if ((filter == CantBeFiltered) || CORE_EVENT(pEvents))
+ {
+ /* if nobody ever wants to see this event, skip some work */
+ if (filter != CantBeFiltered &&
+ !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
+ return 0;
+
+ if (IsInterferingGrab(wClient(pWin), pDev, pEvents))
+ return 0;
+
+ if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
+ /* do nothing */;
+ else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents,
+ count, pWin->eventMask,
+ filter, grab)) )
+ {
+ if (attempt > 0)
+ {
+ deliveries++;
+ client = wClient(pWin);
+ deliveryMask = pWin->eventMask;
+ } else
+ nondeliveries--;
+ }
+ }
+
+ /* CantBeFiltered means only window owner gets the event */
+ if (filter != CantBeFiltered)
+ {
+ if (CORE_EVENT(pEvents))
+ other = (InputClients *)wOtherClients(pWin);
+ else if (XI2_EVENT(pEvents))
+ {
+ OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
+ /* Has any client selected for the event? */
+ if (!GetWindowXI2Mask(pDev, pWin, pEvents))
+ return 0;
+ other = inputMasks->inputClients;
+ } else {
+ OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
+ /* Has any client selected for the event? */
+ if (!inputMasks ||
+ !(inputMasks->inputEvents[pDev->id] & filter))
+ return 0;
+
+ other = inputMasks->inputClients;
+ }
+
+ for (; other; other = other->next)
+ {
+ Mask mask;
+ if (IsInterferingGrab(rClient(other), pDev, pEvents))
+ continue;
+
+ mask = GetEventMask(pDev, pEvents, other);
+
+ if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
+ pEvents, count))
+ /* do nothing */;
+ else if ( (attempt = TryClientEvents(rClient(other), pDev,
+ pEvents, count,
+ mask, filter, grab)) )
+ {
+ if (attempt > 0)
+ {
+ deliveries++;
+ client = rClient(other);
+ deliveryMask = mask;
+ } else
+ nondeliveries--;
+ }
+ }
+ }
+ /*
+ * Note that since core events are delivered first, an implicit grab may
+ * be activated on a core grab, stopping the XI events.
+ */
+ if ((type == DeviceButtonPress || type == ButtonPress ||
+ ((XI2_EVENT(pEvents) && ((xGenericEvent*)pEvents)->evtype == XI_ButtonPress)))
+ && deliveries
+ && (!grab))
+ {
+ GrabRec tempGrab;
+ OtherInputMasks *inputMasks;
+
+ memset(&tempGrab, 0, sizeof(GrabRec));
+ tempGrab.next = NULL;
+ tempGrab.device = pDev;
+ tempGrab.resource = client->clientAsMask;
+ tempGrab.window = pWin;
+ tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
+ tempGrab.eventMask = deliveryMask;
+ tempGrab.keyboardMode = GrabModeAsync;
+ tempGrab.pointerMode = GrabModeAsync;
+ tempGrab.confineTo = NullWindow;
+ tempGrab.cursor = NullCursor;
+ tempGrab.type = type;
+ if (type == ButtonPress)
+ tempGrab.grabtype = GRABTYPE_CORE;
+ else if (type == DeviceButtonPress)
+ tempGrab.grabtype = GRABTYPE_XI;
+ else
+ {
+ tempGrab.type = ((xGenericEvent*)pEvents)->evtype;
+ tempGrab.grabtype = GRABTYPE_XI2;
+ }
+
+ /* get the XI and XI2 device mask */
+ inputMasks = wOtherInputMasks(pWin);
+ tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
+
+ if (inputMasks)
+ memcpy(tempGrab.xi2mask, inputMasks->xi2mask,
+ sizeof(tempGrab.xi2mask));
+
+ (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab,
+ currentTime, TRUE | ImplicitGrabMask);
+ }
+ else if ((type == MotionNotify) && deliveries)
+ pDev->valuator->motionHintWindow = pWin;
+ else
+ {
+ if ((type == DeviceMotionNotify || type == DeviceButtonPress) &&
+ deliveries)
+ CheckDeviceGrabAndHintWindow (pWin, type,
+ (deviceKeyButtonPointer*) pEvents,
+ grab, client, deliveryMask);
+ }
+ if (deliveries)
+ return deliveries;
+ return nondeliveries;
+}
+
+/* If the event goes to dontClient, don't send it and return 0. if
+ send works, return 1 or if send didn't work, return 2.
+ Only works for core events.
+*/
+
+#ifdef PANORAMIX
+static int
+XineramaTryClientEventsResult(
+ ClientPtr client,
+ GrabPtr grab,
+ Mask mask,
+ Mask filter
+){
+ if ((client) && (client != serverClient) && (!client->clientGone) &&
+ ((filter == CantBeFiltered) || (mask & filter)))
+ {
+ if (grab && !SameClient(grab, client)) return -1;
+ else return 1;
+ }
+ return 0;
+}
+#endif
+
+/**
+ * Try to deliver events to the interested parties.
+ *
+ * @param pWin The window that would get the event.
+ * @param pEvents The events to be delivered.
+ * @param count Number of elements in pEvents.
+ * @param filter Mask based on event type.
+ * @param dontClient Don't deliver to the dontClient.
+ */
+int
+MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
+ int count, Mask filter, ClientPtr dontClient)
+{
+ OtherClients *other;
+
+
+ if (pWin->eventMask & filter)
+ {
+ if (wClient(pWin) == dontClient)
+ return 0;
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
+ return XineramaTryClientEventsResult(
+ wClient(pWin), NullGrab, pWin->eventMask, filter);
+#endif
+ if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
+ return 1; /* don't send, but pretend we did */
+ return TryClientEvents(wClient(pWin), NULL, pEvents, count,
+ pWin->eventMask, filter, NullGrab);
+ }
+ for (other = wOtherClients(pWin); other; other = other->next)
+ {
+ if (other->mask & filter)
+ {
+ if (SameClient(other, dontClient))
+ return 0;
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
+ return XineramaTryClientEventsResult(
+ rClient(other), NullGrab, other->mask, filter);
+#endif
+ if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
+ count))
+ return 1; /* don't send, but pretend we did */
+ return TryClientEvents(rClient(other), NULL, pEvents, count,
+ other->mask, filter, NullGrab);
+ }
+ }
+ return 2;
+}
+
+static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event)
+{
+ WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1];
+ Window child = None;
+
+ /* If the search ends up past the root should the child field be
+ set to none or should the value in the argument be passed
+ through. It probably doesn't matter since everyone calls
+ this function with child == None anyway. */
+ while (w)
+ {
+ /* If the source window is same as event window, child should be
+ none. Don't bother going all all the way back to the root. */
+
+ if (w == event)
+ {
+ child = None;
+ break;
+ }
+
+ if (w->parent == event)
+ {
+ child = w->drawable.id;
+ break;
+ }
+ w = w->parent;
+ }
+ return child;
+}
+
+/**
+ * Adjust event fields to comply with the window properties.
+ *
+ * @param xE Event to be modified in place
+ * @param pWin The window to get the information from.
+ * @param child Child window setting for event (if applicable)
+ * @param calcChild If True, calculate the child window.
+ */
+void
+FixUpEventFromWindow(
+ SpritePtr pSprite,
+ xEvent *xE,
+ WindowPtr pWin,
+ Window child,
+ Bool calcChild)
+{
+ if (calcChild)
+ child = FindChildForEvent(pSprite, pWin);
+
+ if (XI2_EVENT(xE))
+ {
+ xXIDeviceEvent* event = (xXIDeviceEvent*)xE;
+
+ if (event->evtype == XI_RawKeyPress ||
+ event->evtype == XI_RawKeyRelease ||
+ event->evtype == XI_RawButtonPress ||
+ event->evtype == XI_RawButtonRelease ||
+ event->evtype == XI_RawMotion ||
+ event->evtype == XI_DeviceChanged ||
+ event->evtype == XI_HierarchyChanged ||
+ event->evtype == XI_PropertyEvent)
+ return;
+
+ event->root = RootWindow(pSprite)->drawable.id;
+ event->event = pWin->drawable.id;
+ if (pSprite->hot.pScreen == pWin->drawable.pScreen)
+ {
+ event->event_x = event->root_x - FP1616(pWin->drawable.x, 0);
+ event->event_y = event->root_y - FP1616(pWin->drawable.y, 0);
+ event->child = child;
+ } else
+ {
+ event->event_x = 0;
+ event->event_y = 0;
+ event->child = None;
+ }
+
+ if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
+ event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
+ ((xXIEnterEvent*)event)->same_screen =
+ (pSprite->hot.pScreen == pWin->drawable.pScreen);
+
+ } else
+ {
+ XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
+ XE_KBPTR.event = pWin->drawable.id;
+ if (pSprite->hot.pScreen == pWin->drawable.pScreen)
+ {
+ XE_KBPTR.sameScreen = xTrue;
+ XE_KBPTR.child = child;
+ XE_KBPTR.eventX =
+ XE_KBPTR.rootX - pWin->drawable.x;
+ XE_KBPTR.eventY =
+ XE_KBPTR.rootY - pWin->drawable.y;
+ }
+ else
+ {
+ XE_KBPTR.sameScreen = xFalse;
+ XE_KBPTR.child = None;
+ XE_KBPTR.eventX = 0;
+ XE_KBPTR.eventY = 0;
+ }
+ }
+}
+
+/**
+ * Check if a given event is deliverable at all on a given window.
+ *
+ * This function only checks if any client wants it, not for a specific
+ * client.
+ *
+ * @param[in] dev The device this event is being sent for.
+ * @param[in] event The event that is to be sent.
+ * @param[in] win The current event window.
+ *
+ * @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and
+ * ::DONT_PROPAGATE_MASK.
+ */
+int
+EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
+{
+ int rc = 0;
+ int filter = 0;
+ int type;
+ OtherInputMasks *inputMasks = wOtherInputMasks(win);
+ xEvent ev;
+
+ /* XXX: this makes me gag */
+ type = GetXI2Type(event);
+ ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/
+ ((xGenericEvent*)&ev)->extension = IReqCode;
+ ((xGenericEvent*)&ev)->evtype = type;
+ filter = GetEventFilter(dev, &ev);
+ if (type && inputMasks &&
+ ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) ||
+ ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) ||
+ (inputMasks->xi2mask[dev->id][type/8] & filter)))
+ rc |= XI2_MASK;
+
+ type = GetXIType(event);
+ ev.u.u.type = type;
+ filter = GetEventFilter(dev, &ev);
+
+ /* Check for XI mask */
+ if (type && inputMasks &&
+ (inputMasks->deliverableEvents[dev->id] & filter) &&
+ (inputMasks->inputEvents[dev->id] & filter))
+ rc |= XI_MASK;
+
+ /* Check for XI DontPropagate mask */
+ if (type && inputMasks &&
+ (inputMasks->dontPropagateMask[dev->id] & filter))
+ rc |= DONT_PROPAGATE_MASK;
+
+ /* Check for core mask */
+ type = GetCoreType(event);
+ if (type && (win->deliverableEvents & filter) &&
+ ((wOtherEventMasks(win) | win->eventMask) & filter))
+ rc |= CORE_MASK;
+
+ /* Check for core DontPropagate mask */
+ if (type && (filter & wDontPropagateMask(win)))
+ rc |= DONT_PROPAGATE_MASK;
+
+ return rc;
+}
+
+/**
+ * Deliver events caused by input devices.
+ *
+ * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
+ * called directly from the processInputProc.
+ * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
+ * DeliverDeviceEvents.
+ * For focused events, DeliverFocusedEvent is called first, and _may_ call
+ * DeliverDeviceEvents.
+ *
+ * @param pWin Window to deliver event to.
+ * @param event The events to deliver, not yet in wire format.
+ * @param grab Possible grab on a device.
+ * @param stopAt Don't recurse up to the root window.
+ * @param dev The device that is responsible for the event.
+ *
+ * @see DeliverGrabbedEvent
+ * @see DeliverFocusedEvent
+ */
+int
+DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
+ WindowPtr stopAt, DeviceIntPtr dev)
+{
+ SpritePtr pSprite = dev->spriteInfo->sprite;
+ Window child = None;
+ Mask filter;
+ int deliveries = 0;
+ xEvent core;
+ xEvent *xE = NULL;
+ int rc, mask, count = 0;
+
+ CHECKEVENT(event);
+
+ while (pWin)
+ {
+ if ((mask = EventIsDeliverable(dev, event, pWin)))
+ {
+ /* XI2 events first */
+ if (mask & XI2_MASK)
+ {
+ xEvent *xi2 = NULL;
+ rc = EventToXI2(event, &xi2);
+ if (rc == Success)
+ {
+ /* XXX: XACE */
+ filter = GetEventFilter(dev, xi2);
+ FixUpEventFromWindow(pSprite, xi2, pWin, child, FALSE);
+ deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1,
+ filter, grab);
+ free(xi2);
+ if (deliveries > 0)
+ goto unwind;
+ } else if (rc != BadMatch)
+ ErrorF("[dix] %s: XI2 conversion failed in DDE (%d).\n",
+ dev->name, rc);
+ }
+
+ /* XI events */
+ if (mask & XI_MASK)
+ {
+ rc = EventToXI(event, &xE, &count);
+ if (rc == Success) {
+ if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) {
+ filter = GetEventFilter(dev, xE);
+ FixUpEventFromWindow(pSprite, xE, pWin, child, FALSE);
+ deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
+ filter, grab);
+ if (deliveries > 0)
+ goto unwind;
+ }
+ } else if (rc != BadMatch)
+ ErrorF("[dix] %s: XI conversion failed in DDE (%d, %d). Skipping delivery.\n",
+ dev->name, event->any.type, rc);
+ }
+
+ /* Core event */
+ if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents)
+ {
+ rc = EventToCore(event, &core);
+ if (rc == Success) {
+ if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) {
+ filter = GetEventFilter(dev, &core);
+ FixUpEventFromWindow(pSprite, &core, pWin, child, FALSE);
+ deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
+ filter, grab);
+ if (deliveries > 0)
+ goto unwind;
+ }
+ } else if (rc != BadMatch)
+ ErrorF("[dix] %s: Core conversion failed in DDE (%d, %d).\n",
+ dev->name, event->any.type, rc);
+ }
+
+ if ((deliveries < 0) || (pWin == stopAt) ||
+ (mask & DONT_PROPAGATE_MASK))
+ {
+ deliveries = 0;
+ goto unwind;
+ }
+ }
+
+ child = pWin->drawable.id;
+ pWin = pWin->parent;
+ }
+
+unwind:
+ free(xE);
+ return deliveries;
+}
+
+#undef XI_MASK
+#undef CORE_MASK
+#undef DONT_PROPAGATE_MASK
+
+/**
+ * Deliver event to a window and it's immediate parent. Used for most window
+ * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
+ * propagate up the tree or extension events
+ *
+ * In case of a ReparentNotify event, the event will be delivered to the
+ * otherParent as well.
+ *
+ * @param pWin Window to deliver events to.
+ * @param xE Events to deliver.
+ * @param count number of events in xE.
+ * @param otherParent Used for ReparentNotify events.
+ */
+int
+DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
+ WindowPtr otherParent)
+{
+ Mask filter;
+ int deliveries;
+ DeviceIntRec dummy;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
+ return count;
+#endif
+
+ if (!count)
+ return 0;
+
+ dummy.id = XIAllDevices;
+ filter = GetEventFilter(&dummy, xE);
+ if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
+ xE->u.destroyNotify.event = pWin->drawable.id;
+ if (filter != StructureAndSubMask)
+ return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
+ deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
+ StructureNotifyMask, NullGrab);
+ if (pWin->parent)
+ {
+ xE->u.destroyNotify.event = pWin->parent->drawable.id;
+ deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
+ SubstructureNotifyMask, NullGrab);
+ if (xE->u.u.type == ReparentNotify)
+ {
+ xE->u.destroyNotify.event = otherParent->drawable.id;
+ deliveries += DeliverEventsToWindow(&dummy,
+ otherParent, xE, count, SubstructureNotifyMask,
+ NullGrab);
+ }
+ }
+ return deliveries;
+}
+
+
+static Bool
+PointInBorderSize(WindowPtr pWin, int x, int y)
+{
+ BoxRec box;
+
+ if(RegionContainsPoint(&pWin->borderSize, x, y, &box))
+ return TRUE;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension &&
+ XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
+ SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
+ int i;
+
+ for(i = 1; i < PanoramiXNumScreens; i++) {
+ if(RegionContainsPoint(&pSprite->windows[i]->borderSize,
+ x + screenInfo.screens[0]->x - screenInfo.screens[i]->x,
+ y + screenInfo.screens[0]->y - screenInfo.screens[i]->y,
+ &box))
+ return TRUE;
+ }
+ }
+#endif
+ return FALSE;
+}
+
+/**
+ * Traversed from the root window to the window at the position x/y. While
+ * traversing, it sets up the traversal history in the spriteTrace array.
+ * After completing, the spriteTrace history is set in the following way:
+ * spriteTrace[0] ... root window
+ * spriteTrace[1] ... top level window that encloses x/y
+ * ...
+ * spriteTrace[spriteTraceGood - 1] ... window at x/y
+ *
+ * @returns the window at the given coordinates.
+ */
+WindowPtr
+XYToWindow(SpritePtr pSprite, int x, int y)
+{
+ WindowPtr pWin;
+ BoxRec box;
+
+ pSprite->spriteTraceGood = 1; /* root window still there */
+ pWin = RootWindow(pSprite)->firstChild;
+ while (pWin)
+ {
+ if ((pWin->mapped) &&
+ (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
+ (x < pWin->drawable.x + (int)pWin->drawable.width +
+ wBorderWidth(pWin)) &&
+ (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
+ (y < pWin->drawable.y + (int)pWin->drawable.height +
+ wBorderWidth (pWin))
+ /* When a window is shaped, a further check
+ * is made to see if the point is inside
+ * borderSize
+ */
+ && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+ && (!wInputShape(pWin) ||
+ RegionContainsPoint(wInputShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box))
+#ifdef ROOTLESS
+ /* In rootless mode windows may be offscreen, even when
+ * they're in X's stack. (E.g. if the native window system
+ * implements some form of virtual desktop system).
+ */
+ && !pWin->rootlessUnhittable
+#endif
+ )
+ {
+ if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
+ {
+ pSprite->spriteTraceSize += 10;
+ pSprite->spriteTrace = realloc(pSprite->spriteTrace,
+ pSprite->spriteTraceSize*sizeof(WindowPtr));
+ }
+ pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
+ pWin = pWin->firstChild;
+ }
+ else
+ pWin = pWin->nextSib;
+ }
+ return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
+}
+
+/**
+ * Ungrab a currently FocusIn grabbed device and grab the device on the
+ * given window. If the win given is the NoneWin, the device is ungrabbed if
+ * applicable and FALSE is returned.
+ *
+ * @returns TRUE if the device has been grabbed, or FALSE otherwise.
+ */
+BOOL
+ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
+{
+ BOOL rc = FALSE;
+ DeviceEvent event;
+
+ if (dev->deviceGrab.grab)
+ {
+ if (!dev->deviceGrab.fromPassiveGrab ||
+ dev->deviceGrab.grab->type != XI_Enter ||
+ dev->deviceGrab.grab->window == win ||
+ IsParent(dev->deviceGrab.grab->window, win))
+ return FALSE;
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
+ (*dev->deviceGrab.DeactivateGrab)(dev);
+ }
+
+ if (win == NoneWin || win == PointerRootWin)
+ return FALSE;
+
+ memset(&event, 0, sizeof(DeviceEvent));
+ event.header = ET_Internal;
+ event.type = ET_FocusIn;
+ event.length = sizeof(DeviceEvent);
+ event.time = GetTimeInMillis();
+ event.deviceid = dev->id;
+ event.sourceid = dev->id;
+ event.detail.button = 0;
+ rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL);
+ if (rc)
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
+ return rc;
+}
+
+/**
+ * Ungrab a currently Enter grabbed device and grab the device for the given
+ * window.
+ *
+ * @returns TRUE if the device has been grabbed, or FALSE otherwise.
+ */
+static BOOL
+ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
+{
+ BOOL rc = FALSE;
+ DeviceEvent event;
+
+ if (dev->deviceGrab.grab)
+ {
+ if (!dev->deviceGrab.fromPassiveGrab ||
+ dev->deviceGrab.grab->type != XI_Enter ||
+ dev->deviceGrab.grab->window == win ||
+ IsParent(dev->deviceGrab.grab->window, win))
+ return FALSE;
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
+ (*dev->deviceGrab.DeactivateGrab)(dev);
+ }
+
+ memset(&event, 0, sizeof(DeviceEvent));
+ event.header = ET_Internal;
+ event.type = ET_Enter;
+ event.length = sizeof(DeviceEvent);
+ event.time = GetTimeInMillis();
+ event.deviceid = dev->id;
+ event.sourceid = dev->id;
+ event.detail.button = 0;
+ rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL);
+ if (rc)
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
+ return rc;
+}
+
+/**
+ * Update the sprite coordinates based on the event. Update the cursor
+ * position, then update the event with the new coordinates that may have been
+ * changed. If the window underneath the sprite has changed, change to new
+ * cursor and send enter/leave events.
+ *
+ * CheckMotion() will not do anything and return FALSE if the event is not a
+ * pointer event.
+ *
+ * @return TRUE if the sprite has moved or FALSE otherwise.
+ */
+Bool
+CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
+{
+ WindowPtr prevSpriteWin, newSpriteWin;
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+
+ CHECKEVENT(ev);
+
+ prevSpriteWin = pSprite->win;
+
+ if (ev && !syncEvents.playingEvents)
+ {
+ /* GetPointerEvents() guarantees that pointer events have the correct
+ rootX/Y set already. */
+ switch (ev->type)
+ {
+ case ET_ButtonPress:
+ case ET_ButtonRelease:
+ case ET_Motion:
+ break;
+ default:
+ /* all other events return FALSE */
+ return FALSE;
+ }
+
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ /* Motion events entering DIX get translated to Screen 0
+ coordinates. Replayed events have already been
+ translated since they've entered DIX before */
+ ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
+ ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
+ } else
+#endif
+ {
+ if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
+ {
+ pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
+ RootWindow(pDev->spriteInfo->sprite) =
+ pSprite->hot.pScreen->root;
+ }
+ }
+
+ pSprite->hot.x = ev->root_x;
+ pSprite->hot.y = ev->root_y;
+ if (pSprite->hot.x < pSprite->physLimits.x1)
+ pSprite->hot.x = pSprite->physLimits.x1;
+ else if (pSprite->hot.x >= pSprite->physLimits.x2)
+ pSprite->hot.x = pSprite->physLimits.x2 - 1;
+ if (pSprite->hot.y < pSprite->physLimits.y1)
+ pSprite->hot.y = pSprite->physLimits.y1;
+ else if (pSprite->hot.y >= pSprite->physLimits.y2)
+ pSprite->hot.y = pSprite->physLimits.y2 - 1;
+ if (pSprite->hotShape)
+ ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
+ pSprite->hotPhys = pSprite->hot;
+
+ if ((pSprite->hotPhys.x != ev->root_x) ||
+ (pSprite->hotPhys.y != ev->root_y))
+ {
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ XineramaSetCursorPosition(
+ pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
+ } else
+#endif
+ {
+ (*pSprite->hotPhys.pScreen->SetCursorPosition)(
+ pDev, pSprite->hotPhys.pScreen,
+ pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
+ }
+ }
+
+ ev->root_x = pSprite->hot.x;
+ ev->root_y = pSprite->hot.y;
+ }
+
+ newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
+
+ if (newSpriteWin != prevSpriteWin)
+ {
+ int sourceid;
+ if (!ev) {
+ UpdateCurrentTimeIf();
+ sourceid = pDev->id; /* when from WindowsRestructured */
+ } else
+ sourceid = ev->sourceid;
+
+ if (prevSpriteWin != NullWindow) {
+ if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
+ DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
+ newSpriteWin, NotifyNormal);
+ }
+ /* set pSprite->win after ActivateEnterGrab, otherwise
+ sprite window == grab_window and no enter/leave events are
+ sent. */
+ pSprite->win = newSpriteWin;
+ PostNewCursor(pDev);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Windows have restructured, we need to update the sprite position and the
+ * sprite's cursor.
+ */
+void
+WindowsRestructured(void)
+{
+ DeviceIntPtr pDev = inputInfo.devices;
+ while(pDev)
+ {
+ if (IsMaster(pDev) || !pDev->u.master)
+ CheckMotion(NULL, pDev);
+ pDev = pDev->next;
+ }
+}
+
+#ifdef PANORAMIX
+/* This was added to support reconfiguration under Xdmx. The problem is
+ * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
+ * other than 0,0, the information in the private sprite structure must
+ * be updated accordingly, or XYToWindow (and other routines) will not
+ * compute correctly. */
+void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
+{
+ GrabPtr grab;
+ DeviceIntPtr pDev;
+ SpritePtr pSprite;
+
+ if (noPanoramiXExtension) return;
+
+ pDev = inputInfo.devices;
+ while(pDev)
+ {
+ if (DevHasCursor(pDev))
+ {
+ pSprite = pDev->spriteInfo->sprite;
+ pSprite->hot.x -= xoff;
+ pSprite->hot.y -= yoff;
+
+ pSprite->hotPhys.x -= xoff;
+ pSprite->hotPhys.y -= yoff;
+
+ pSprite->hotLimits.x1 -= xoff;
+ pSprite->hotLimits.y1 -= yoff;
+ pSprite->hotLimits.x2 -= xoff;
+ pSprite->hotLimits.y2 -= yoff;
+
+ if (RegionNotEmpty(&pSprite->Reg1))
+ RegionTranslate(&pSprite->Reg1, xoff, yoff);
+ if (RegionNotEmpty(&pSprite->Reg2))
+ RegionTranslate(&pSprite->Reg2, xoff, yoff);
+
+ /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
+ if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
+ if (grab->confineTo->drawable.pScreen
+ != pSprite->hotPhys.pScreen)
+ pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
+ ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
+ } else
+ ConfineCursorToWindow(
+ pDev,
+ pSprite->hotPhys.pScreen->root,
+ TRUE, FALSE);
+
+ }
+ pDev = pDev->next;
+ }
+}
+#endif
+
+/**
+ * Initialize a sprite for the given device and set it to some sane values. If
+ * the device already has a sprite alloc'd, don't realloc but just reset to
+ * default values.
+ * If a window is supplied, the sprite will be initialized with the window's
+ * cursor and positioned in the center of the window's screen. The root window
+ * is a good choice to pass in here.
+ *
+ * It's a good idea to call it only for pointer devices, unless you have a
+ * really talented keyboard.
+ *
+ * @param pDev The device to initialize.
+ * @param pWin The window where to generate the sprite in.
+ *
+ */
+void
+InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
+{
+ SpritePtr pSprite;
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+
+ if (!pDev->spriteInfo->sprite)
+ {
+ DeviceIntPtr it;
+
+ pDev->spriteInfo->sprite = (SpritePtr)calloc(1, sizeof(SpriteRec));
+ if (!pDev->spriteInfo->sprite)
+ FatalError("InitializeSprite: failed to allocate sprite struct");
+
+ /* We may have paired another device with this device before our
+ * device had a actual sprite. We need to check for this and reset the
+ * sprite field for all paired devices.
+ *
+ * The VCK is always paired with the VCP before the VCP has a sprite.
+ */
+ for (it = inputInfo.devices; it; it = it->next)
+ {
+ if (it->spriteInfo->paired == pDev)
+ it->spriteInfo->sprite = pDev->spriteInfo->sprite;
+ }
+ if (inputInfo.keyboard->spriteInfo->paired == pDev)
+ inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
+ }
+
+ pSprite = pDev->spriteInfo->sprite;
+ pDev->spriteInfo->spriteOwner = TRUE;
+
+ pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
+ pSprite->hot.pScreen = pScreen;
+ pSprite->hotPhys.pScreen = pScreen;
+ if (pScreen)
+ {
+ pSprite->hotPhys.x = pScreen->width / 2;
+ pSprite->hotPhys.y = pScreen->height / 2;
+ pSprite->hotLimits.x2 = pScreen->width;
+ pSprite->hotLimits.y2 = pScreen->height;
+ }
+
+ pSprite->hot = pSprite->hotPhys;
+ pSprite->win = pWin;
+
+ if (pWin)
+ {
+ pCursor = wCursor(pWin);
+ pSprite->spriteTrace = (WindowPtr *)calloc(1, 32*sizeof(WindowPtr));
+ if (!pSprite->spriteTrace)
+ FatalError("Failed to allocate spriteTrace");
+ pSprite->spriteTraceSize = 32;
+
+ RootWindow(pDev->spriteInfo->sprite) = pWin;
+ pSprite->spriteTraceGood = 1;
+
+ pSprite->pEnqueueScreen = pScreen;
+ pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
+
+ } else {
+ pCursor = NullCursor;
+ pSprite->spriteTrace = NULL;
+ pSprite->spriteTraceSize = 0;
+ pSprite->spriteTraceGood = 0;
+ pSprite->pEnqueueScreen = screenInfo.screens[0];
+ pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
+ }
+ if (pCursor)
+ pCursor->refcnt++;
+ if (pSprite->current)
+ FreeCursor(pSprite->current, None);
+ pSprite->current = pCursor;
+
+ if (pScreen)
+ {
+ (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current);
+ (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
+ &pSprite->hotLimits, &pSprite->physLimits);
+ pSprite->confined = FALSE;
+
+ (*pScreen->ConstrainCursor) (pDev, pScreen,
+ &pSprite->physLimits);
+ (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
+ pSprite->hot.y,
+ FALSE);
+ (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
+ }
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
+ pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
+ pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
+ pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
+ pSprite->physLimits = pSprite->hotLimits;
+ pSprite->confineWin = NullWindow;
+ pSprite->hotShape = NullRegion;
+ pSprite->screen = pScreen;
+ /* gotta UNINIT these someplace */
+ RegionNull(&pSprite->Reg1);
+ RegionNull(&pSprite->Reg2);
+ }
+#endif
+}
+
+/**
+ * Update the mouse sprite info when the server switches from a pScreen to another.
+ * Otherwise, the pScreen of the mouse sprite is never updated when we switch
+ * from a pScreen to another. Never updating the pScreen of the mouse sprite
+ * implies that windows that are in pScreen whose pScreen->myNum >0 will never
+ * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen
+ * always points to the first pScreen it has been set by
+ * DefineInitialRootWindow().
+ *
+ * Calling this function is useful for use cases where the server
+ * has more than one pScreen.
+ * This function is similar to DefineInitialRootWindow() but it does not
+ * reset the mouse pointer position.
+ * @param win must be the new pScreen we are switching to.
+ */
+void
+UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ SpritePtr pSprite = NULL;
+ WindowPtr win = NULL;
+ CursorPtr pCursor;
+ if (!pScreen)
+ return ;
+
+ if (!pDev->spriteInfo->sprite)
+ return;
+
+ pSprite = pDev->spriteInfo->sprite;
+
+ win = pScreen->root;
+
+ pSprite->hotPhys.pScreen = pScreen;
+ pSprite->hot = pSprite->hotPhys;
+ pSprite->hotLimits.x2 = pScreen->width;
+ pSprite->hotLimits.y2 = pScreen->height;
+ pSprite->win = win;
+ pCursor = wCursor(win);
+ if (pCursor)
+ pCursor->refcnt++;
+ if (pSprite->current)
+ FreeCursor(pSprite->current, 0);
+ pSprite->current = pCursor;
+ pSprite->spriteTraceGood = 1;
+ pSprite->spriteTrace[0] = win;
+ (*pScreen->CursorLimits) (pDev,
+ pScreen,
+ pSprite->current,
+ &pSprite->hotLimits,
+ &pSprite->physLimits);
+ pSprite->confined = FALSE;
+ (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
+ (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
+ pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
+ pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
+ pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
+ pSprite->physLimits = pSprite->hotLimits;
+ pSprite->screen = pScreen;
+ }
+#endif
+}
+
+/*
+ * This does not take any shortcuts, and even ignores its argument, since
+ * it does not happen very often, and one has to walk up the tree since
+ * this might be a newly instantiated cursor for an intermediate window
+ * between the one the pointer is in and the one that the last cursor was
+ * instantiated from.
+ */
+void
+WindowHasNewCursor(WindowPtr pWin)
+{
+ DeviceIntPtr pDev;
+
+ for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ if (DevHasCursor(pDev))
+ PostNewCursor(pDev);
+}
+
+void
+NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
+{
+ SpritePtr pSprite = pDev->spriteInfo->sprite;
+
+ pSprite->hotPhys.x = x;
+ pSprite->hotPhys.y = y;
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
+ pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
+ if (newScreen != pSprite->screen) {
+ pSprite->screen = newScreen;
+ /* Make sure we tell the DDX to update its copy of the screen */
+ if(pSprite->confineWin)
+ XineramaConfineCursorToWindow(pDev,
+ pSprite->confineWin, TRUE);
+ else
+ XineramaConfineCursorToWindow(pDev, screenInfo.screens[0]->root, TRUE);
+ /* if the pointer wasn't confined, the DDX won't get
+ told of the pointer warp so we reposition it here */
+ if(!syncEvents.playingEvents)
+ (*pSprite->screen->SetCursorPosition)(
+ pDev,
+ pSprite->screen,
+ pSprite->hotPhys.x + screenInfo.screens[0]->x -
+ pSprite->screen->x,
+ pSprite->hotPhys.y + screenInfo.screens[0]->y -
+ pSprite->screen->y, FALSE);
+ }
+ } else
+#endif
+ if (newScreen != pSprite->hotPhys.pScreen)
+ ConfineCursorToWindow(pDev, newScreen->root, TRUE, FALSE);
+}
+
+#ifdef PANORAMIX
+
+static Bool
+XineramaPointInWindowIsVisible(
+ WindowPtr pWin,
+ int x,
+ int y
+)
+{
+ BoxRec box;
+ int i, xoff, yoff;
+
+ if (!pWin->realized) return FALSE;
+
+ if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
+ return TRUE;
+
+ if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
+
+ xoff = x + screenInfo.screens[0]->x;
+ yoff = y + screenInfo.screens[0]->y;
+
+ for(i = 1; i < PanoramiXNumScreens; i++) {
+ pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
+ x = xoff - screenInfo.screens[i]->x;
+ y = yoff - screenInfo.screens[i]->y;
+
+ if(RegionContainsPoint(&pWin->borderClip, x, y, &box)
+ && (!wInputShape(pWin) ||
+ RegionContainsPoint(wInputShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box)))
+ return TRUE;
+
+ }
+
+ return FALSE;
+}
+
+static int
+XineramaWarpPointer(ClientPtr client)
+{
+ WindowPtr dest = NULL;
+ int x, y, rc;
+ SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
+
+ REQUEST(xWarpPointerReq);
+
+
+ if (stuff->dstWid != None) {
+ rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+ }
+ x = pSprite->hotPhys.x;
+ y = pSprite->hotPhys.y;
+
+ if (stuff->srcWid != None)
+ {
+ int winX, winY;
+ XID winID = stuff->srcWid;
+ WindowPtr source;
+
+ rc = dixLookupWindow(&source, winID, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ winX = source->drawable.x;
+ winY = source->drawable.y;
+ if(source == screenInfo.screens[0]->root) {
+ winX -= screenInfo.screens[0]->x;
+ winY -= screenInfo.screens[0]->y;
+ }
+ if (x < winX + stuff->srcX ||
+ y < winY + stuff->srcY ||
+ (stuff->srcWidth != 0 &&
+ winX + stuff->srcX + (int)stuff->srcWidth < x) ||
+ (stuff->srcHeight != 0 &&
+ winY + stuff->srcY + (int)stuff->srcHeight < y) ||
+ !XineramaPointInWindowIsVisible(source, x, y))
+ return Success;
+ }
+ if (dest) {
+ x = dest->drawable.x;
+ y = dest->drawable.y;
+ if(dest == screenInfo.screens[0]->root) {
+ x -= screenInfo.screens[0]->x;
+ y -= screenInfo.screens[0]->y;
+ }
+ }
+
+ x += stuff->dstX;
+ y += stuff->dstY;
+
+ if (x < pSprite->physLimits.x1)
+ x = pSprite->physLimits.x1;
+ else if (x >= pSprite->physLimits.x2)
+ x = pSprite->physLimits.x2 - 1;
+ if (y < pSprite->physLimits.y1)
+ y = pSprite->physLimits.y1;
+ else if (y >= pSprite->physLimits.y2)
+ y = pSprite->physLimits.y2 - 1;
+ if (pSprite->hotShape)
+ ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
+
+ XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
+
+ return Success;
+}
+
+#endif
+
+
+/**
+ * Server-side protocol handling for WarpPointer request.
+ * Warps the cursor position to the coordinates given in the request.
+ */
+int
+ProcWarpPointer(ClientPtr client)
+{
+ WindowPtr dest = NULL;
+ int x, y, rc;
+ ScreenPtr newScreen;
+ DeviceIntPtr dev, tmp;
+ SpritePtr pSprite;
+
+ REQUEST(xWarpPointerReq);
+ REQUEST_SIZE_MATCH(xWarpPointerReq);
+
+ dev = PickPointer(client);
+
+ for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
+ if ((tmp == dev) || (!IsMaster(tmp) && tmp->u.master == dev)) {
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+ }
+ }
+
+ if (dev->u.lastSlave)
+ dev = dev->u.lastSlave;
+ pSprite = dev->spriteInfo->sprite;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+ return XineramaWarpPointer(client);
+#endif
+
+ if (stuff->dstWid != None) {
+ rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+ x = pSprite->hotPhys.x;
+ y = pSprite->hotPhys.y;
+
+ if (stuff->srcWid != None)
+ {
+ int winX, winY;
+ XID winID = stuff->srcWid;
+ WindowPtr source;
+
+ rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ winX = source->drawable.x;
+ winY = source->drawable.y;
+ if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
+ x < winX + stuff->srcX ||
+ y < winY + stuff->srcY ||
+ (stuff->srcWidth != 0 &&
+ winX + stuff->srcX + (int)stuff->srcWidth < x) ||
+ (stuff->srcHeight != 0 &&
+ winY + stuff->srcY + (int)stuff->srcHeight < y) ||
+ !PointInWindowIsVisible(source, x, y))
+ return Success;
+ }
+ if (dest)
+ {
+ x = dest->drawable.x;
+ y = dest->drawable.y;
+ newScreen = dest->drawable.pScreen;
+ } else
+ newScreen = pSprite->hotPhys.pScreen;
+
+ x += stuff->dstX;
+ y += stuff->dstY;
+
+ if (x < 0)
+ x = 0;
+ else if (x >= newScreen->width)
+ x = newScreen->width - 1;
+ if (y < 0)
+ y = 0;
+ else if (y >= newScreen->height)
+ y = newScreen->height - 1;
+
+ if (newScreen == pSprite->hotPhys.pScreen)
+ {
+ if (x < pSprite->physLimits.x1)
+ x = pSprite->physLimits.x1;
+ else if (x >= pSprite->physLimits.x2)
+ x = pSprite->physLimits.x2 - 1;
+ if (y < pSprite->physLimits.y1)
+ y = pSprite->physLimits.y1;
+ else if (y >= pSprite->physLimits.y2)
+ y = pSprite->physLimits.y2 - 1;
+ if (pSprite->hotShape)
+ ConfineToShape(dev, pSprite->hotShape, &x, &y);
+ (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE);
+ }
+ else if (!PointerConfinedToScreen(dev))
+ {
+ NewCurrentScreen(dev, newScreen, x, y);
+ }
+ return Success;
+}
+
+static Bool
+BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
+{
+ if(RegionNotEmpty(&pWin->borderSize))
+ return TRUE;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
+ int i;
+
+ for(i = 1; i < PanoramiXNumScreens; i++) {
+ if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize))
+ return TRUE;
+ }
+ }
+#endif
+ return FALSE;
+}
+
+/**
+ * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
+ * passive grab set on the window to be activated.
+ * If activate is true and a passive grab is found, it will be activated,
+ * and the event will be delivered to the client.
+ *
+ * @param pWin The window that may be subject to a passive grab.
+ * @param device Device that caused the event.
+ * @param event The current device event.
+ * @param checkCore Check for core grabs too.
+ * @param activate If a grab is found, activate it and deliver the event.
+ */
+
+GrabPtr
+CheckPassiveGrabsOnWindow(
+ WindowPtr pWin,
+ DeviceIntPtr device,
+ DeviceEvent *event,
+ BOOL checkCore,
+ BOOL activate)
+{
+ SpritePtr pSprite = device->spriteInfo->sprite;
+ GrabPtr grab = wPassiveGrabs(pWin);
+ GrabRec tempGrab;
+ GrabInfoPtr grabinfo;
+#define CORE_MATCH 0x1
+#define XI_MATCH 0x2
+#define XI2_MATCH 0x4
+ int match = 0;
+
+ if (!grab)
+ return NULL;
+ /* Fill out the grab details, but leave the type for later before
+ * comparing */
+ tempGrab.window = pWin;
+ tempGrab.device = device;
+ tempGrab.detail.exact = event->detail.key;
+ tempGrab.detail.pMask = NULL;
+ tempGrab.modifiersDetail.pMask = NULL;
+ tempGrab.next = NULL;
+ for (; grab; grab = grab->next)
+ {
+ DeviceIntPtr gdev;
+ XkbSrvInfoPtr xkbi = NULL;
+
+ gdev= grab->modifierDevice;
+ if (grab->grabtype == GRABTYPE_CORE)
+ {
+ if (IsPointerDevice(device))
+ gdev = GetPairedDevice(device);
+ else
+ gdev = device;
+ } else if (grab->grabtype == GRABTYPE_XI2)
+ {
+ /* if the device is an attached slave device, gdev must be the
+ * attached master keyboard. Since the slave may have been
+ * reattached after the grab, the modifier device may not be the
+ * same. */
+ if (!IsMaster(grab->device) && device->u.master)
+ gdev = GetMaster(device, MASTER_KEYBOARD);
+ }
+
+
+ if (gdev && gdev->key)
+ xkbi= gdev->key->xkbInfo;
+ tempGrab.modifierDevice = grab->modifierDevice;
+ tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
+
+ /* Check for XI2 and XI grabs first */
+ tempGrab.type = GetXI2Type((InternalEvent*)event);
+ tempGrab.grabtype = GRABTYPE_XI2;
+ if (GrabMatchesSecond(&tempGrab, grab, FALSE))
+ match = XI2_MATCH;
+
+ tempGrab.detail.exact = event->detail.key;
+ if (!match)
+ {
+ tempGrab.grabtype = GRABTYPE_XI;
+ if ((tempGrab.type = GetXIType((InternalEvent*)event)) &&
+ (GrabMatchesSecond(&tempGrab, grab, FALSE)))
+ match = XI_MATCH;
+ }
+
+ /* Check for a core grab (ignore the device when comparing) */
+ if (!match && checkCore)
+ {
+ tempGrab.grabtype = GRABTYPE_CORE;
+ if ((tempGrab.type = GetCoreType((InternalEvent*)event)) &&
+ (GrabMatchesSecond(&tempGrab, grab, TRUE)))
+ match = CORE_MATCH;
+ }
+
+ if (match && (!grab->confineTo ||
+ (grab->confineTo->realized &&
+ BorderSizeNotEmpty(device, grab->confineTo))))
+ {
+ int rc, count = 0;
+ xEvent *xE = NULL;
+ xEvent core;
+
+ event->corestate &= 0x1f00;
+ event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00);
+ grabinfo = &device->deviceGrab;
+ /* In some cases a passive core grab may exist, but the client
+ * already has a core grab on some other device. In this case we
+ * must not get the grab, otherwise we may never ungrab the
+ * device.
+ */
+
+ if (grab->grabtype == GRABTYPE_CORE)
+ {
+ DeviceIntPtr other;
+ BOOL interfering = FALSE;
+
+ /* A passive grab may have been created for a different device
+ than it is assigned to at this point in time.
+ Update the grab's device and modifier device to reflect the
+ current state.
+ Since XGrabDeviceButton requires to specify the
+ modifierDevice explicitly, we don't override this choice.
+ */
+ if (tempGrab.type < GenericEvent)
+ {
+ grab->device = device;
+ grab->modifierDevice = GetPairedDevice(device);
+ }
+
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ GrabPtr othergrab = other->deviceGrab.grab;
+ if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
+ SameClient(grab, rClient(othergrab)) &&
+ ((IsPointerDevice(grab->device) &&
+ IsPointerDevice(othergrab->device)) ||
+ (IsKeyboardDevice(grab->device) &&
+ IsKeyboardDevice(othergrab->device))))
+ {
+ interfering = TRUE;
+ break;
+ }
+ }
+ if (interfering)
+ continue;
+ }
+
+ if (!activate)
+ return grab;
+
+ if (match & CORE_MATCH)
+ {
+ rc = EventToCore((InternalEvent*)event, &core);
+ if (rc != Success)
+ {
+ if (rc != BadMatch)
+ ErrorF("[dix] %s: core conversion failed in CPGFW "
+ "(%d, %d).\n", device->name, event->type, rc);
+ continue;
+ }
+ xE = &core;
+ count = 1;
+ } else if (match & XI2_MATCH)
+ {
+ rc = EventToXI2((InternalEvent*)event, &xE);
+ if (rc != Success)
+ {
+ if (rc != BadMatch)
+ ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
+ "(%d, %d).\n", device->name, event->type, rc);
+ continue;
+ }
+ count = 1;
+ } else
+ {
+ rc = EventToXI((InternalEvent*)event, &xE, &count);
+ if (rc != Success)
+ {
+ if (rc != BadMatch)
+ ErrorF("[dix] %s: XI conversion failed in CPGFW "
+ "(%d, %d).\n", device->name, event->type, rc);
+ continue;
+ }
+ }
+
+ (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
+
+ if (xE)
+ {
+ FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
+
+ TryClientEvents(rClient(grab), device, xE, count,
+ GetEventFilter(device, xE),
+ GetEventFilter(device, xE), grab);
+ }
+
+ if (grabinfo->sync.state == FROZEN_NO_EVENT)
+ {
+ if (!grabinfo->sync.event)
+ grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
+ *grabinfo->sync.event = *event;
+ grabinfo->sync.state = FROZEN_WITH_EVENT;
+ }
+
+ if (match & (XI_MATCH | XI2_MATCH))
+ free(xE); /* on core match xE == &core */
+ return grab;
+ }
+ }
+ return NULL;
+#undef CORE_MATCH
+#undef XI_MATCH
+#undef XI2_MATCH
+}
+
+/**
+ * CheckDeviceGrabs handles both keyboard and pointer events that may cause
+ * a passive grab to be activated.
+ *
+ * If the event is a keyboard event, the ancestors of the focus window are
+ * traced down and tried to see if they have any passive grabs to be
+ * activated. If the focus window itself is reached and it's descendants
+ * contain the pointer, the ancestors of the window that the pointer is in
+ * are then traced down starting at the focus window, otherwise no grabs are
+ * activated.
+ * If the event is a pointer event, the ancestors of the window that the
+ * pointer is in are traced down starting at the root until CheckPassiveGrabs
+ * causes a passive grab to activate or all the windows are
+ * tried. PRH
+ *
+ * If a grab is activated, the event has been sent to the client already!
+ *
+ * The event we pass in must always be an XI event. From this, we then emulate
+ * the core event and then check for grabs.
+ *
+ * @param device The device that caused the event.
+ * @param xE The event to handle (Device{Button|Key}Press).
+ * @param count Number of events in list.
+ * @return TRUE if a grab has been activated or false otherwise.
+*/
+
+Bool
+CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
+{
+ int i;
+ WindowPtr pWin = NULL;
+ FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
+ BOOL sendCore = (IsMaster(device) && device->coreEvents);
+
+ if (event->type != ET_ButtonPress &&
+ event->type != ET_KeyPress)
+ return FALSE;
+
+ if (event->type == ET_ButtonPress
+ && (device->button->buttonsDown != 1))
+ return FALSE;
+
+ if (device->deviceGrab.grab)
+ return FALSE;
+
+ i = 0;
+ if (ancestor)
+ {
+ while (i < device->spriteInfo->sprite->spriteTraceGood)
+ if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
+ break;
+ if (i == device->spriteInfo->sprite->spriteTraceGood)
+ return FALSE;
+ }
+
+ if (focus)
+ {
+ for (; i < focus->traceGood; i++)
+ {
+ pWin = focus->trace[i];
+ if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
+ return TRUE;
+ }
+
+ if ((focus->win == NoneWin) ||
+ (i >= device->spriteInfo->sprite->spriteTraceGood) ||
+ (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i-1]))
+ return FALSE;
+ }
+
+ for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
+ {
+ pWin = device->spriteInfo->sprite->spriteTrace[i];
+ if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Called for keyboard events to deliver event to whatever client owns the
+ * focus.
+ *
+ * The event is delivered to the keyboard's focus window, the root window or
+ * to the window owning the input focus.
+ *
+ * @param keybd The keyboard originating the event.
+ * @param event The event, not yet in wire format.
+ * @param window Window underneath the sprite.
+ */
+void
+DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
+{
+ DeviceIntPtr ptr;
+ WindowPtr focus = keybd->focus->win;
+ BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
+ xEvent core;
+ xEvent *xE = NULL, *xi2 = NULL;
+ int count, rc;
+ int deliveries = 0;
+
+ if (focus == FollowKeyboardWin)
+ focus = inputInfo.keyboard->focus->win;
+ if (!focus)
+ return;
+ if (focus == PointerRootWin)
+ {
+ DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
+ return;
+ }
+ if ((focus == window) || IsParent(focus, window))
+ {
+ if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
+ return;
+ }
+
+ /* just deliver it to the focus window */
+ ptr = GetPairedDevice(keybd);
+
+
+ rc = EventToXI2(event, &xi2);
+ if (rc == Success)
+ {
+ /* XXX: XACE */
+ int filter = GetEventFilter(keybd, xi2);
+ FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
+ deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
+ filter, NullGrab);
+ if (deliveries > 0)
+ goto unwind;
+ } else if (rc != BadMatch)
+ ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
+ keybd->name, event->any.type, rc);
+
+ rc = EventToXI(event, &xE, &count);
+ if (rc == Success &&
+ XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success)
+ {
+ FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
+ deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
+ GetEventFilter(keybd, xE),
+ NullGrab);
+
+ if (deliveries > 0)
+ goto unwind;
+ } else if (rc != BadMatch)
+ ErrorF("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
+ keybd->name, event->any.type, rc);
+
+ if (sendCore)
+ {
+ rc = EventToCore(event, &core);
+ if (rc == Success) {
+ if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) {
+ FixUpEventFromWindow(keybd->spriteInfo->sprite, &core, focus,
+ None, FALSE);
+ deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
+ GetEventFilter(keybd, &core),
+ NullGrab);
+ }
+ } else if (rc != BadMatch)
+ ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
+ keybd->name, event->any.type, rc);
+ }
+
+unwind:
+ free(xE);
+ free(xi2);
+ return;
+}
+
+/**
+ * Deliver an event from a device that is currently grabbed. Uses
+ * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
+ * grab. If not, TryClientEvents() is used.
+ *
+ * @param deactivateGrab True if the device's grab should be deactivated.
+ */
+void
+DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
+ Bool deactivateGrab)
+{
+ GrabPtr grab;
+ GrabInfoPtr grabinfo;
+ int deliveries = 0;
+ DeviceIntPtr dev;
+ SpritePtr pSprite = thisDev->spriteInfo->sprite;
+ BOOL sendCore = FALSE;
+ int rc, count = 0;
+ xEvent *xi = NULL;
+ xEvent *xi2 = NULL;
+
+ grabinfo = &thisDev->deviceGrab;
+ grab = grabinfo->grab;
+
+ if (grab->ownerEvents)
+ {
+ WindowPtr focus;
+
+ /* Hack: Some pointer device have a focus class. So we need to check
+ * for the type of event, to see if we really want to deliver it to
+ * the focus window. For pointer events, the answer is no.
+ */
+ if (IsPointerEvent(event))
+ focus = PointerRootWin;
+ else if (thisDev->focus)
+ {
+ focus = thisDev->focus->win;
+ if (focus == FollowKeyboardWin)
+ focus = inputInfo.keyboard->focus->win;
+ }
+ else
+ focus = PointerRootWin;
+ if (focus == PointerRootWin)
+ deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
+ NullWindow, thisDev);
+ else if (focus && (focus == pSprite->win ||
+ IsParent(focus, pSprite->win)))
+ deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
+ thisDev);
+ else if (focus)
+ deliveries = DeliverDeviceEvents(focus, event, grab, focus,
+ thisDev);
+ }
+ if (!deliveries)
+ {
+ Mask mask;
+
+ /* XXX: In theory, we could pass the internal events through to
+ * everything and only convert just before hitting the wire. We can't
+ * do that yet, so DGE is the last stop for internal events. From here
+ * onwards, we deal with core/XI events.
+ */
+
+ mask = grab->eventMask;
+
+ sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
+ /* try core event */
+ if (sendCore && grab->grabtype == GRABTYPE_CORE)
+ {
+ xEvent core;
+
+ rc = EventToCore(event, &core);
+ if (rc == Success)
+ {
+ FixUpEventFromWindow(pSprite, &core, grab->window, None, TRUE);
+ if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
+ grab->window, &core, 1) ||
+ XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
+ grab->window, &core, 1))
+ deliveries = 1; /* don't send, but pretend we did */
+ else if (!IsInterferingGrab(rClient(grab), thisDev, &core))
+ {
+ deliveries = TryClientEvents(rClient(grab), thisDev,
+ &core, 1, mask,
+ GetEventFilter(thisDev, &core),
+ grab);
+ }
+ } else if (rc != BadMatch)
+ ErrorF("[dix] DeliverGrabbedEvent. Core conversion failed.\n");
+ }
+
+ if (!deliveries)
+ {
+ rc = EventToXI2(event, &xi2);
+ if (rc == Success)
+ {
+ int evtype = ((xGenericEvent*)xi2)->evtype;
+ mask = grab->xi2mask[XIAllDevices][evtype/8] |
+ grab->xi2mask[XIAllMasterDevices][evtype/8] |
+ grab->xi2mask[thisDev->id][evtype/8];
+ /* try XI2 event */
+ FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
+ /* XXX: XACE */
+ deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask,
+ GetEventFilter(thisDev, xi2), grab);
+ } else if (rc != BadMatch)
+ ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n",
+ thisDev->name, event->any.type, rc);
+ }
+
+ if (!deliveries)
+ {
+ rc = EventToXI(event, &xi, &count);
+ if (rc == Success)
+ {
+ /* try XI event */
+ if (grabinfo->fromPassiveGrab &&
+ grabinfo->implicitGrab)
+ mask = grab->deviceMask;
+ else
+ mask = grab->eventMask;
+
+ FixUpEventFromWindow(pSprite, xi, grab->window, None, TRUE);
+
+ if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
+ grab->window, xi, count) ||
+ XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
+ grab->window, xi, count))
+ deliveries = 1; /* don't send, but pretend we did */
+ else
+ {
+ deliveries =
+ TryClientEvents(rClient(grab), thisDev,
+ xi, count,
+ mask,
+ GetEventFilter(thisDev, xi),
+ grab);
+ }
+ } else if (rc != BadMatch)
+ ErrorF("[dix] %s: XI conversion failed in DGE (%d, %d). Skipping delivery.\n",
+ thisDev->name, event->any.type, rc);
+ }
+
+ if (deliveries && (event->any.type == ET_Motion))
+ thisDev->valuator->motionHintWindow = grab->window;
+ }
+ if (deliveries && !deactivateGrab && event->any.type != ET_Motion)
+ {
+ switch (grabinfo->sync.state)
+ {
+ case FREEZE_BOTH_NEXT_EVENT:
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (dev == thisDev)
+ continue;
+ FreezeThaw(dev, TRUE);
+ if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
+ (CLIENT_BITS(grab->resource) ==
+ CLIENT_BITS(dev->deviceGrab.grab->resource)))
+ dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
+ else if (GetPairedDevice(thisDev) == dev)
+ dev->deviceGrab.sync.other = grab;
+ }
+ /* fall through */
+ case FREEZE_NEXT_EVENT:
+ grabinfo->sync.state = FROZEN_WITH_EVENT;
+ FreezeThaw(thisDev, TRUE);
+ if (!grabinfo->sync.event)
+ grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
+ *grabinfo->sync.event = event->device_event;
+ break;
+ }
+ }
+
+ free(xi);
+ free(xi2);
+}
+
+/* This function is used to set the key pressed or key released state -
+ this is only used when the pressing of keys does not cause
+ the device's processInputProc to be called, as in for example Mouse Keys.
+*/
+void
+FixKeyState (DeviceEvent *event, DeviceIntPtr keybd)
+{
+ int key = event->detail.key;
+
+ if (event->type == ET_KeyPress) {
+ DebugF("FixKeyState: Key %d %s\n",key,
+ ((event->type == ET_KeyPress) ? "down" : "up"));
+ }
+
+ if (event->type == ET_KeyPress)
+ set_key_down(keybd, key, KEY_PROCESSED);
+ else if (event->type == ET_KeyRelease)
+ set_key_up(keybd, key, KEY_PROCESSED);
+ else
+ FatalError("Impossible keyboard event");
+}
+
+#define AtMostOneClient \
+ (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
+#define ManagerMask \
+ (SubstructureRedirectMask | ResizeRedirectMask)
+
+/**
+ * Recalculate which events may be deliverable for the given window.
+ * Recalculated mask is used for quicker determination which events may be
+ * delivered to a window.
+ *
+ * The otherEventMasks on a WindowOptional is the combination of all event
+ * masks set by all clients on the window.
+ * deliverableEventMask is the combination of the eventMask and the
+ * otherEventMask plus the events that may be propagated to the parent.
+ *
+ * Traverses to siblings and parents of the window.
+ */
+void
+RecalculateDeliverableEvents(WindowPtr pWin)
+{
+ OtherClients *others;
+ WindowPtr pChild;
+
+ pChild = pWin;
+ while (1)
+ {
+ if (pChild->optional)
+ {
+ pChild->optional->otherEventMasks = 0;
+ for (others = wOtherClients(pChild); others; others = others->next)
+ {
+ pChild->optional->otherEventMasks |= others->mask;
+ }
+ }
+ pChild->deliverableEvents = pChild->eventMask|
+ wOtherEventMasks(pChild);
+ if (pChild->parent)
+ pChild->deliverableEvents |=
+ (pChild->parent->deliverableEvents &
+ ~wDontPropagateMask(pChild) & PropagateMask);
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+/**
+ *
+ * \param value must conform to DeleteType
+ */
+int
+OtherClientGone(pointer value, XID id)
+{
+ OtherClientsPtr other, prev;
+ WindowPtr pWin = (WindowPtr)value;
+
+ prev = 0;
+ for (other = wOtherClients(pWin); other; other = other->next)
+ {
+ if (other->resource == id)
+ {
+ if (prev)
+ prev->next = other->next;
+ else
+ {
+ if (!(pWin->optional->otherClients = other->next))
+ CheckWindowOptionalNeed (pWin);
+ }
+ free(other);
+ RecalculateDeliverableEvents(pWin);
+ return Success;
+ }
+ prev = other;
+ }
+ FatalError("client not on event list");
+ /*NOTREACHED*/
+ return -1; /* make compiler happy */
+}
+
+int
+EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
+{
+ Mask check;
+ OtherClients * others;
+ DeviceIntPtr dev;
+ int rc;
+
+ if (mask & ~AllEventMasks)
+ {
+ client->errorValue = mask;
+ return BadValue;
+ }
+ check = (mask & ManagerMask);
+ if (check) {
+ rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
+ RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
+ if (rc != Success)
+ return rc;
+ }
+ check = (mask & AtMostOneClient);
+ if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
+ { /* It is illegal for two different
+ clients to select on any of the
+ events for AtMostOneClient. However,
+ it is OK, for some client to
+ continue selecting on one of those
+ events. */
+ if ((wClient(pWin) != client) && (check & pWin->eventMask))
+ return BadAccess;
+ for (others = wOtherClients (pWin); others; others = others->next)
+ {
+ if (!SameClient(others, client) && (check & others->mask))
+ return BadAccess;
+ }
+ }
+ if (wClient (pWin) == client)
+ {
+ check = pWin->eventMask;
+ pWin->eventMask = mask;
+ }
+ else
+ {
+ for (others = wOtherClients (pWin); others; others = others->next)
+ {
+ if (SameClient(others, client))
+ {
+ check = others->mask;
+ if (mask == 0)
+ {
+ FreeResource(others->resource, RT_NONE);
+ return Success;
+ }
+ else
+ others->mask = mask;
+ goto maskSet;
+ }
+ }
+ check = 0;
+ if (!pWin->optional && !MakeWindowOptional (pWin))
+ return BadAlloc;
+ others = malloc(sizeof(OtherClients));
+ if (!others)
+ return BadAlloc;
+ others->mask = mask;
+ others->resource = FakeClientID(client->index);
+ others->next = pWin->optional->otherClients;
+ pWin->optional->otherClients = others;
+ if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
+ return BadAlloc;
+ }
+maskSet:
+ if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
+ {
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (dev->valuator && dev->valuator->motionHintWindow == pWin)
+ dev->valuator->motionHintWindow = NullWindow;
+ }
+ }
+ RecalculateDeliverableEvents(pWin);
+ return Success;
+}
+
+int
+EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
+ Mask mask, Bool *checkOptional)
+{
+ int i, free;
+
+ if (mask & ~PropagateMask)
+ {
+ client->errorValue = mask;
+ return BadValue;
+ }
+ if (pWin->dontPropagate)
+ DontPropagateRefCnts[pWin->dontPropagate]--;
+ if (!mask)
+ i = 0;
+ else
+ {
+ for (i = DNPMCOUNT, free = 0; --i > 0; )
+ {
+ if (!DontPropagateRefCnts[i])
+ free = i;
+ else if (mask == DontPropagateMasks[i])
+ break;
+ }
+ if (!i && free)
+ {
+ i = free;
+ DontPropagateMasks[i] = mask;
+ }
+ }
+ if (i || !mask)
+ {
+ pWin->dontPropagate = i;
+ if (i)
+ DontPropagateRefCnts[i]++;
+ if (pWin->optional)
+ {
+ pWin->optional->dontPropagateMask = mask;
+ *checkOptional = TRUE;
+ }
+ }
+ else
+ {
+ if (!pWin->optional && !MakeWindowOptional (pWin))
+ {
+ if (pWin->dontPropagate)
+ DontPropagateRefCnts[pWin->dontPropagate]++;
+ return BadAlloc;
+ }
+ pWin->dontPropagate = 0;
+ pWin->optional->dontPropagateMask = mask;
+ }
+ RecalculateDeliverableEvents(pWin);
+ return Success;
+}
+
+/**
+ * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
+ * Uses the paired keyboard to get some additional information.
+ */
+void
+CoreEnterLeaveEvent(
+ DeviceIntPtr mouse,
+ int type,
+ int mode,
+ int detail,
+ WindowPtr pWin,
+ Window child)
+{
+ xEvent event;
+ WindowPtr focus;
+ DeviceIntPtr keybd;
+ GrabPtr grab = mouse->deviceGrab.grab;
+ Mask mask;
+
+ keybd = GetPairedDevice(mouse);
+
+ if ((pWin == mouse->valuator->motionHintWindow) &&
+ (detail != NotifyInferior))
+ mouse->valuator->motionHintWindow = NullWindow;
+ if (grab)
+ {
+ mask = (pWin == grab->window) ? grab->eventMask : 0;
+ if (grab->ownerEvents)
+ mask |= EventMaskForClient(pWin, rClient(grab));
+ }
+ else
+ {
+ mask = pWin->eventMask | wOtherEventMasks(pWin);
+ }
+
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = type;
+ event.u.u.detail = detail;
+ event.u.enterLeave.time = currentTime.milliseconds;
+ event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
+ event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
+ /* Counts on the same initial structure of crossing & button events! */
+ FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
+ /* Enter/Leave events always set child */
+ event.u.enterLeave.child = child;
+ event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
+ ELFlagSameScreen : 0;
+ event.u.enterLeave.state = mouse->button ? (mouse->button->state & 0x1f00) : 0;
+ if (keybd)
+ event.u.enterLeave.state |=
+ XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
+ event.u.enterLeave.mode = mode;
+ focus = (keybd) ? keybd->focus->win : None;
+ if ((focus != NoneWin) &&
+ ((pWin == focus) || (focus == PointerRootWin) ||
+ IsParent(focus, pWin)))
+ event.u.enterLeave.flags |= ELFlagFocus;
+
+ if ((mask & GetEventFilter(mouse, &event)))
+ {
+ if (grab)
+ TryClientEvents(rClient(grab), mouse, &event, 1, mask,
+ GetEventFilter(mouse, &event), grab);
+ else
+ DeliverEventsToWindow(mouse, pWin, &event, 1,
+ GetEventFilter(mouse, &event),
+ NullGrab);
+ }
+
+ if ((type == EnterNotify) && (mask & KeymapStateMask))
+ {
+ xKeymapEvent ke;
+ ClientPtr client = grab ? rClient(grab) : wClient(pWin);
+ if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
+ memset((char *)&ke.map[0], 0, 31);
+ else
+ memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
+
+ ke.type = KeymapNotify;
+ if (grab)
+ TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
+ mask, KeymapStateMask, grab);
+ else
+ DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
+ KeymapStateMask, NullGrab);
+ }
+}
+
+void
+DeviceEnterLeaveEvent(
+ DeviceIntPtr mouse,
+ int sourceid,
+ int type,
+ int mode,
+ int detail,
+ WindowPtr pWin,
+ Window child)
+{
+ GrabPtr grab = mouse->deviceGrab.grab;
+ xXIEnterEvent *event;
+ int filter;
+ int btlen, len, i;
+ DeviceIntPtr kbd;
+
+ if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
+ (mode == XINotifyPassiveUngrab && type == XI_Enter))
+ return;
+
+ btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
+ btlen = bytes_to_int32(btlen);
+ len = sizeof(xXIEnterEvent) + btlen * 4;
+
+ event = calloc(1, len);
+ event->type = GenericEvent;
+ event->extension = IReqCode;
+ event->evtype = type;
+ event->length = (len - sizeof(xEvent))/4;
+ event->buttons_len = btlen;
+ event->detail = detail;
+ event->time = currentTime.milliseconds;
+ event->deviceid = mouse->id;
+ event->sourceid = sourceid;
+ event->mode = mode;
+ event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
+ event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
+
+ for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
+ if (BitIsOn(mouse->button->down, i))
+ SetBit(&event[1], i);
+
+ kbd = (IsMaster(mouse) || mouse->u.master) ? GetPairedDevice(mouse) : NULL;
+ if (kbd && kbd->key)
+ {
+ event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
+ event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
+ event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
+
+ event->group.base_group = kbd->key->xkbInfo->state.base_group;
+ event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
+ event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
+ }
+
+ FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent*)event, pWin,
+ None, FALSE);
+
+ filter = GetEventFilter(mouse, (xEvent*)event);
+
+ if (grab)
+ {
+ Mask mask;
+ mask = grab->xi2mask[XIAllDevices][type/8] |
+ grab->xi2mask[XIAllMasterDevices][type/8] |
+ grab->xi2mask[mouse->id][type/8];
+ TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask,
+ filter, grab);
+ } else {
+ if (!GetWindowXI2Mask(mouse, pWin, (xEvent*)event))
+ goto out;
+ DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter,
+ NullGrab);
+ }
+
+out:
+ free(event);
+}
+
+void
+CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
+{
+ xEvent event;
+
+ memset(&event, 0, sizeof(xEvent));
+ event.u.focus.mode = mode;
+ event.u.u.type = type;
+ event.u.u.detail = detail;
+ event.u.focus.window = pWin->drawable.id;
+
+ DeliverEventsToWindow(dev, pWin, &event, 1,
+ GetEventFilter(dev, &event), NullGrab);
+ if ((type == FocusIn) &&
+ ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
+ {
+ xKeymapEvent ke;
+ ClientPtr client = wClient(pWin);
+ if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess))
+ memset((char *)&ke.map[0], 0, 31);
+ else
+ memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
+
+ ke.type = KeymapNotify;
+ DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
+ KeymapStateMask, NullGrab);
+ }
+}
+
+/**
+ * Set the input focus to the given window. Subsequent keyboard events will be
+ * delivered to the given window.
+ *
+ * Usually called from ProcSetInputFocus as result of a client request. If so,
+ * the device is the inputInfo.keyboard.
+ * If called from ProcXSetInputFocus as result of a client xinput request, the
+ * device is set to the device specified by the client.
+ *
+ * @param client Client that requested input focus change.
+ * @param dev Focus device.
+ * @param focusID The window to obtain the focus. Can be PointerRoot or None.
+ * @param revertTo Specifies where the focus reverts to when window becomes
+ * unviewable.
+ * @param ctime Specifies the time.
+ * @param followOK True if pointer is allowed to follow the keyboard.
+ */
+int
+SetInputFocus(
+ ClientPtr client,
+ DeviceIntPtr dev,
+ Window focusID,
+ CARD8 revertTo,
+ Time ctime,
+ Bool followOK)
+{
+ FocusClassPtr focus;
+ WindowPtr focusWin;
+ int mode, rc;
+ TimeStamp time;
+ DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
+
+
+ UpdateCurrentTime();
+ if ((revertTo != RevertToParent) &&
+ (revertTo != RevertToPointerRoot) &&
+ (revertTo != RevertToNone) &&
+ ((revertTo != RevertToFollowKeyboard) || !followOK))
+ {
+ client->errorValue = revertTo;
+ return BadValue;
+ }
+ time = ClientTimeToServerTime(ctime);
+
+ if (IsKeyboardDevice(dev))
+ keybd = dev;
+ else
+ keybd = GetPairedDevice(dev);
+
+ if ((focusID == None) || (focusID == PointerRoot))
+ focusWin = (WindowPtr)(long)focusID;
+ else if ((focusID == FollowKeyboard) && followOK)
+ {
+ focusWin = keybd->focus->win;
+ }
+ else {
+ rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ /* It is a match error to try to set the input focus to an
+ unviewable window. */
+ if(!focusWin->realized)
+ return BadMatch;
+ }
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
+ if (rc != Success)
+ return Success;
+
+ focus = dev->focus;
+ if ((CompareTimeStamps(time, currentTime) == LATER) ||
+ (CompareTimeStamps(time, focus->time) == EARLIER))
+ return Success;
+ mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
+ if (focus->win == FollowKeyboardWin)
+ {
+ if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
+ DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
+ } else
+ {
+ if (!ActivateFocusInGrab(dev, focus->win, focusWin))
+ DoFocusEvents(dev, focus->win, focusWin, mode);
+ }
+ focus->time = time;
+ focus->revert = revertTo;
+ if (focusID == FollowKeyboard)
+ focus->win = FollowKeyboardWin;
+ else
+ focus->win = focusWin;
+ if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
+ focus->traceGood = 0;
+ else
+ {
+ int depth = 0;
+ WindowPtr pWin;
+
+ for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
+ if (depth > focus->traceSize)
+ {
+ focus->traceSize = depth+1;
+ focus->trace = realloc(focus->trace,
+ focus->traceSize * sizeof(WindowPtr));
+ }
+ focus->traceGood = depth;
+ for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
+ focus->trace[depth] = pWin;
+ }
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for SetInputFocus request.
+ *
+ * Sets the input focus for the virtual core keyboard.
+ */
+int
+ProcSetInputFocus(ClientPtr client)
+{
+ DeviceIntPtr kbd = PickKeyboard(client);
+ REQUEST(xSetInputFocusReq);
+
+ REQUEST_SIZE_MATCH(xSetInputFocusReq);
+
+ return SetInputFocus(client, kbd, stuff->focus,
+ stuff->revertTo, stuff->time, FALSE);
+}
+
+/**
+ * Server-side protocol handling for GetInputFocus request.
+ *
+ * Sends the current input focus for the client's keyboard back to the
+ * client.
+ */
+int
+ProcGetInputFocus(ClientPtr client)
+{
+ DeviceIntPtr kbd = PickKeyboard(client);
+ xGetInputFocusReply rep;
+ FocusClassPtr focus = kbd->focus;
+ int rc;
+ /* REQUEST(xReq); */
+ REQUEST_SIZE_MATCH(xReq);
+
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
+ if (rc != Success)
+ return rc;
+
+ memset(&rep, 0, sizeof(xGetInputFocusReply));
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ if (focus->win == NoneWin)
+ rep.focus = None;
+ else if (focus->win == PointerRootWin)
+ rep.focus = PointerRoot;
+ else rep.focus = focus->win->drawable.id;
+ rep.revertTo = focus->revert;
+ WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for GrabPointer request.
+ *
+ * Sets an active grab on the client's ClientPointer and returns success
+ * status to client.
+ */
+int
+ProcGrabPointer(ClientPtr client)
+{
+ xGrabPointerReply rep;
+ DeviceIntPtr device = PickPointer(client);
+ GrabPtr grab;
+ GrabMask mask;
+ WindowPtr confineTo;
+ CursorPtr oldCursor;
+ REQUEST(xGrabPointerReq);
+ TimeStamp time;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xGrabPointerReq);
+ UpdateCurrentTime();
+
+ if (stuff->eventMask & ~PointerGrabMask)
+ {
+ client->errorValue = stuff->eventMask;
+ return BadValue;
+ }
+
+ if (stuff->confineTo == None)
+ confineTo = NullWindow;
+ else
+ {
+ rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
+ DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ memset(&rep, 0, sizeof(xGrabPointerReply));
+ oldCursor = NullCursor;
+ grab = device->deviceGrab.grab;
+
+ if (grab)
+ {
+ if (grab->confineTo && !confineTo)
+ ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE,
+ FALSE);
+ oldCursor = grab->cursor;
+ }
+
+ mask.core = stuff->eventMask;
+
+ rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
+ stuff->grabWindow, stuff->ownerEvents, stuff->time,
+ &mask, GRABTYPE_CORE, stuff->cursor,
+ stuff->confineTo, &rep.status);
+ if (rc != Success)
+ return rc;
+
+ if (oldCursor && rep.status == GrabSuccess)
+ FreeCursor (oldCursor, (Cursor)0);
+
+ time = ClientTimeToServerTime(stuff->time);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for ChangeActivePointerGrab request.
+ *
+ * Changes properties of the grab hold by the client. If the client does not
+ * hold an active grab on the device, nothing happens.
+ */
+int
+ProcChangeActivePointerGrab(ClientPtr client)
+{
+ DeviceIntPtr device;
+ GrabPtr grab;
+ CursorPtr newCursor, oldCursor;
+ REQUEST(xChangeActivePointerGrabReq);
+ TimeStamp time;
+
+ REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
+ if (stuff->eventMask & ~PointerGrabMask)
+ {
+ client->errorValue = stuff->eventMask;
+ return BadValue;
+ }
+ if (stuff->cursor == None)
+ newCursor = NullCursor;
+ else
+ {
+ int rc = dixLookupResourceByType((pointer *)&newCursor, stuff->cursor,
+ RT_CURSOR, client, DixUseAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->cursor;
+ return rc;
+ }
+ }
+
+ device = PickPointer(client);
+ grab = device->deviceGrab.grab;
+
+ if (!grab)
+ return Success;
+ if (!SameClient(grab, client))
+ return Success;
+ time = ClientTimeToServerTime(stuff->time);
+ if ((CompareTimeStamps(time, currentTime) == LATER) ||
+ (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
+ return Success;
+ oldCursor = grab->cursor;
+ grab->cursor = newCursor;
+ if (newCursor)
+ newCursor->refcnt++;
+ PostNewCursor(device);
+ if (oldCursor)
+ FreeCursor(oldCursor, (Cursor)0);
+ grab->eventMask = stuff->eventMask;
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for UngrabPointer request.
+ *
+ * Deletes a pointer grab on a device the client has grabbed.
+ */
+int
+ProcUngrabPointer(ClientPtr client)
+{
+ DeviceIntPtr device = PickPointer(client);
+ GrabPtr grab;
+ TimeStamp time;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ UpdateCurrentTime();
+ grab = device->deviceGrab.grab;
+
+ time = ClientTimeToServerTime(stuff->id);
+ if ((CompareTimeStamps(time, currentTime) != LATER) &&
+ (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
+ (grab) && SameClient(grab, client))
+ (*device->deviceGrab.DeactivateGrab)(device);
+ return Success;
+}
+
+/**
+ * Sets a grab on the given device.
+ *
+ * Called from ProcGrabKeyboard to work on the client's keyboard.
+ * Called from ProcXGrabDevice to work on the device specified by the client.
+ *
+ * The parameters this_mode and other_mode represent the keyboard_mode and
+ * pointer_mode parameters of XGrabKeyboard().
+ * See man page for details on all the parameters
+ *
+ * @param client Client that owns the grab.
+ * @param dev The device to grab.
+ * @param this_mode GrabModeSync or GrabModeAsync
+ * @param other_mode GrabModeSync or GrabModeAsync
+ * @param status Return code to be returned to the caller.
+ *
+ * @returns Success or BadValue.
+ */
+int
+GrabDevice(ClientPtr client, DeviceIntPtr dev,
+ unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
+ unsigned ownerEvents, Time ctime, GrabMask *mask,
+ int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
+{
+ WindowPtr pWin, confineTo;
+ GrabPtr grab;
+ TimeStamp time;
+ Mask access_mode = DixGrabAccess;
+ int rc;
+ GrabInfoPtr grabInfo = &dev->deviceGrab;
+ CursorPtr cursor;
+
+ UpdateCurrentTime();
+ if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync))
+ {
+ client->errorValue = keyboard_mode;
+ return BadValue;
+ }
+ if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync))
+ {
+ client->errorValue = pointer_mode;
+ return BadValue;
+ }
+ if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
+ {
+ client->errorValue = ownerEvents;
+ return BadValue;
+ }
+
+ rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ if (confineToWin == None)
+ confineTo = NullWindow;
+ else
+ {
+ rc = dixLookupWindow(&confineTo, confineToWin, client,
+ DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ if (curs == None)
+ cursor = NullCursor;
+ else
+ {
+ rc = dixLookupResourceByType((pointer *)&cursor, curs, RT_CURSOR,
+ client, DixUseAccess);
+ if (rc != Success)
+ {
+ client->errorValue = curs;
+ return rc;
+ }
+ access_mode |= DixForceAccess;
+ }
+
+ if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
+ access_mode |= DixFreezeAccess;
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
+ if (rc != Success)
+ return rc;
+
+ time = ClientTimeToServerTime(ctime);
+ grab = grabInfo->grab;
+ if (grab && grab->grabtype != grabtype)
+ *status = AlreadyGrabbed;
+ if (grab && !SameClient(grab, client))
+ *status = AlreadyGrabbed;
+ else if ((!pWin->realized) ||
+ (confineTo &&
+ !(confineTo->realized
+ && BorderSizeNotEmpty(dev, confineTo))))
+ *status = GrabNotViewable;
+ else if ((CompareTimeStamps(time, currentTime) == LATER) ||
+ (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
+ *status = GrabInvalidTime;
+ else if (grabInfo->sync.frozen &&
+ grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
+ *status = GrabFrozen;
+ else
+ {
+ GrabRec tempGrab;
+
+ /* Otherwise segfaults happen on grabbed MPX devices */
+ memset(&tempGrab, 0, sizeof(GrabRec));
+
+ tempGrab.next = NULL;
+ tempGrab.window = pWin;
+ tempGrab.resource = client->clientAsMask;
+ tempGrab.ownerEvents = ownerEvents;
+ tempGrab.keyboardMode = keyboard_mode;
+ tempGrab.pointerMode = pointer_mode;
+ if (grabtype == GRABTYPE_CORE)
+ tempGrab.eventMask = mask->core;
+ else if (grabtype == GRABTYPE_XI)
+ tempGrab.eventMask = mask->xi;
+ else
+ memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask));
+ tempGrab.device = dev;
+ tempGrab.cursor = cursor;
+ tempGrab.confineTo = confineTo;
+ tempGrab.grabtype = grabtype;
+ (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
+ *status = GrabSuccess;
+ }
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for GrabKeyboard request.
+ *
+ * Grabs the client's keyboard and returns success status to client.
+ */
+int
+ProcGrabKeyboard(ClientPtr client)
+{
+ xGrabKeyboardReply rep;
+ REQUEST(xGrabKeyboardReq);
+ int result;
+ DeviceIntPtr keyboard = PickKeyboard(client);
+ GrabMask mask;
+
+ REQUEST_SIZE_MATCH(xGrabKeyboardReq);
+
+ memset(&rep, 0, sizeof(xGrabKeyboardReply));
+ mask.core = KeyPressMask | KeyReleaseMask;
+
+ result = GrabDevice(client, keyboard, stuff->pointerMode,
+ stuff->keyboardMode, stuff->grabWindow, stuff->ownerEvents,
+ stuff->time, &mask, GRABTYPE_CORE, None, None,
+ &rep.status);
+
+ if (result != Success)
+ return result;
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for UngrabKeyboard request.
+ *
+ * Deletes a possible grab on the client's keyboard.
+ */
+int
+ProcUngrabKeyboard(ClientPtr client)
+{
+ DeviceIntPtr device = PickKeyboard(client);
+ GrabPtr grab;
+ TimeStamp time;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ UpdateCurrentTime();
+
+ grab = device->deviceGrab.grab;
+
+ time = ClientTimeToServerTime(stuff->id);
+ if ((CompareTimeStamps(time, currentTime) != LATER) &&
+ (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
+ (grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_CORE)
+ (*device->deviceGrab.DeactivateGrab)(device);
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for QueryPointer request.
+ *
+ * Returns the current state and position of the client's ClientPointer to the
+ * client.
+ */
+int
+ProcQueryPointer(ClientPtr client)
+{
+ xQueryPointerReply rep;
+ WindowPtr pWin, t;
+ DeviceIntPtr mouse = PickPointer(client);
+ DeviceIntPtr keyboard;
+ SpritePtr pSprite;
+ int rc;
+ REQUEST(xResourceReq);
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
+ if (rc != Success && rc != BadAccess)
+ return rc;
+
+ keyboard = GetPairedDevice(mouse);
+
+ pSprite = mouse->spriteInfo->sprite;
+ if (mouse->valuator->motionHintWindow)
+ MaybeStopHint(mouse, client);
+ memset(&rep, 0, sizeof(xQueryPointerReply));
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.mask = mouse->button ? (mouse->button->state) : 0;
+ rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
+ rep.length = 0;
+ rep.root = (GetCurrentRootWindow(mouse))->drawable.id;
+ rep.rootX = pSprite->hot.x;
+ rep.rootY = pSprite->hot.y;
+ rep.child = None;
+ if (pSprite->hot.pScreen == pWin->drawable.pScreen)
+ {
+ rep.sameScreen = xTrue;
+ rep.winX = pSprite->hot.x - pWin->drawable.x;
+ rep.winY = pSprite->hot.y - pWin->drawable.y;
+ for (t = pSprite->win; t; t = t->parent)
+ if (t->parent == pWin)
+ {
+ rep.child = t->drawable.id;
+ break;
+ }
+ }
+ else
+ {
+ rep.sameScreen = xFalse;
+ rep.winX = 0;
+ rep.winY = 0;
+ }
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ rep.rootX += screenInfo.screens[0]->x;
+ rep.rootY += screenInfo.screens[0]->y;
+ if(stuff->id == rep.root) {
+ rep.winX += screenInfo.screens[0]->x;
+ rep.winY += screenInfo.screens[0]->y;
+ }
+ }
+#endif
+
+ if (rc == BadAccess) {
+ rep.mask = 0;
+ rep.child = None;
+ rep.rootX = 0;
+ rep.rootY = 0;
+ rep.winX = 0;
+ rep.winY = 0;
+ }
+
+ WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
+
+ return Success;
+}
+
+/**
+ * Initializes the device list and the DIX sprite to sane values. Allocates
+ * trace memory used for quick window traversal.
+ */
+void
+InitEvents(void)
+{
+ int i;
+
+ inputInfo.numDevices = 0;
+ inputInfo.devices = (DeviceIntPtr)NULL;
+ inputInfo.off_devices = (DeviceIntPtr)NULL;
+ inputInfo.keyboard = (DeviceIntPtr)NULL;
+ inputInfo.pointer = (DeviceIntPtr)NULL;
+ /* The mask for pointer motion events may have changed in the last server
+ * generation. See comment above definition of filters. */
+ filters[0][PointerMotionMask] = MotionNotify;
+ for (i = 1; i < MAXDEVICES; i++)
+ {
+ memcpy(&filters[i], filters[0], sizeof(filters[0]));
+ }
+
+ syncEvents.replayDev = (DeviceIntPtr)NULL;
+ syncEvents.replayWin = NullWindow;
+ while (syncEvents.pending)
+ {
+ QdEventPtr next = syncEvents.pending->next;
+ free(syncEvents.pending);
+ syncEvents.pending = next;
+ }
+ syncEvents.pendtail = &syncEvents.pending;
+ syncEvents.playingEvents = FALSE;
+ syncEvents.time.months = 0;
+ syncEvents.time.milliseconds = 0; /* hardly matters */
+ currentTime.months = 0;
+ currentTime.milliseconds = GetTimeInMillis();
+ lastDeviceEventTime = currentTime;
+ for (i = 0; i < DNPMCOUNT; i++)
+ {
+ DontPropagateMasks[i] = 0;
+ DontPropagateRefCnts[i] = 0;
+ }
+
+ InputEventListLen = GetMaximumEventsNum();
+ InputEventList = InitEventList(InputEventListLen);
+ if (!InputEventList)
+ FatalError("[dix] Failed to allocate input event list.\n");
+}
+
+void
+CloseDownEvents(void)
+{
+ FreeEventList(InputEventList, InputEventListLen);
+ InputEventListLen = 0;
+ InputEventList = NULL;
+}
+
+/**
+ * Server-side protocol handling for SendEvent request.
+ *
+ * Locates the window to send the event to and forwards the event.
+ */
+int
+ProcSendEvent(ClientPtr client)
+{
+ WindowPtr pWin;
+ WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
+ DeviceIntPtr dev = PickPointer(client);
+ DeviceIntPtr keybd = GetPairedDevice(dev);
+ SpritePtr pSprite = dev->spriteInfo->sprite;
+ REQUEST(xSendEventReq);
+
+ REQUEST_SIZE_MATCH(xSendEventReq);
+
+ /* The client's event type must be a core event type or one defined by an
+ extension. */
+
+ if ( ! ((stuff->event.u.u.type > X_Reply &&
+ stuff->event.u.u.type < LASTEvent) ||
+ (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
+ stuff->event.u.u.type < (unsigned)lastEvent)))
+ {
+ client->errorValue = stuff->event.u.u.type;
+ return BadValue;
+ }
+ if (stuff->event.u.u.type == ClientMessage &&
+ stuff->event.u.u.detail != 8 &&
+ stuff->event.u.u.detail != 16 &&
+ stuff->event.u.u.detail != 32)
+ {
+ client->errorValue = stuff->event.u.u.detail;
+ return BadValue;
+ }
+ if (stuff->eventMask & ~AllEventMasks)
+ {
+ client->errorValue = stuff->eventMask;
+ return BadValue;
+ }
+
+ if (stuff->destination == PointerWindow)
+ pWin = pSprite->win;
+ else if (stuff->destination == InputFocus)
+ {
+ WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
+
+ if (inputFocus == NoneWin)
+ return Success;
+
+ /* If the input focus is PointerRootWin, send the event to where
+ the pointer is if possible, then perhaps propogate up to root. */
+ if (inputFocus == PointerRootWin)
+ inputFocus = GetCurrentRootWindow(dev);
+
+ if (IsParent(inputFocus, pSprite->win))
+ {
+ effectiveFocus = inputFocus;
+ pWin = pSprite->win;
+ }
+ else
+ effectiveFocus = pWin = inputFocus;
+ }
+ else
+ dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
+
+ if (!pWin)
+ return BadWindow;
+ if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
+ {
+ client->errorValue = stuff->propagate;
+ return BadValue;
+ }
+ stuff->event.u.u.type |= 0x80;
+ if (stuff->propagate)
+ {
+ for (;pWin; pWin = pWin->parent)
+ {
+ if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
+ &stuff->event, 1))
+ return Success;
+ if (DeliverEventsToWindow(dev, pWin,
+ &stuff->event, 1, stuff->eventMask, NullGrab))
+ return Success;
+ if (pWin == effectiveFocus)
+ return Success;
+ stuff->eventMask &= ~wDontPropagateMask(pWin);
+ if (!stuff->eventMask)
+ break;
+ }
+ }
+ else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
+ DeliverEventsToWindow(dev, pWin, &stuff->event,
+ 1, stuff->eventMask, NullGrab);
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for UngrabKey request.
+ *
+ * Deletes a passive grab for the given key. Works on the
+ * client's keyboard.
+ */
+int
+ProcUngrabKey(ClientPtr client)
+{
+ REQUEST(xUngrabKeyReq);
+ WindowPtr pWin;
+ GrabRec tempGrab;
+ DeviceIntPtr keybd = PickKeyboard(client);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xUngrabKeyReq);
+ rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
+ (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
+ && (stuff->key != AnyKey))
+ {
+ client->errorValue = stuff->key;
+ return BadValue;
+ }
+ if ((stuff->modifiers != AnyModifier) &&
+ (stuff->modifiers & ~AllModifiersMask))
+ {
+ client->errorValue = stuff->modifiers;
+ return BadValue;
+ }
+ tempGrab.resource = client->clientAsMask;
+ tempGrab.device = keybd;
+ tempGrab.window = pWin;
+ tempGrab.modifiersDetail.exact = stuff->modifiers;
+ tempGrab.modifiersDetail.pMask = NULL;
+ tempGrab.modifierDevice = GetPairedDevice(keybd);
+ tempGrab.type = KeyPress;
+ tempGrab.grabtype = GRABTYPE_CORE;
+ tempGrab.detail.exact = stuff->key;
+ tempGrab.detail.pMask = NULL;
+ tempGrab.next = NULL;
+
+ if (!DeletePassiveGrabFromList(&tempGrab))
+ return BadAlloc;
+ return Success;
+}
+
+/**
+ * Server-side protocol handling for GrabKey request.
+ *
+ * Creates a grab for the client's keyboard and adds it to the list of passive
+ * grabs.
+ */
+int
+ProcGrabKey(ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xGrabKeyReq);
+ GrabPtr grab;
+ DeviceIntPtr keybd = PickKeyboard(client);
+ int rc;
+ GrabParameters param;
+ GrabMask mask;
+
+ REQUEST_SIZE_MATCH(xGrabKeyReq);
+
+ memset(&param, 0, sizeof(param));
+ param.grabtype = GRABTYPE_CORE;
+ param.ownerEvents = stuff->ownerEvents;
+ param.this_device_mode = stuff->keyboardMode;
+ param.other_devices_mode = stuff->pointerMode;
+ param.modifiers = stuff->modifiers;
+
+ rc = CheckGrabValues(client, &param);
+ if (rc != Success)
+ return rc;
+
+ if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
+ (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
+ && (stuff->key != AnyKey))
+ {
+ client->errorValue = stuff->key;
+ return BadValue;
+ }
+ rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+
+ mask.core = (KeyPressMask | KeyReleaseMask);
+
+ grab = CreateGrab(client->index, keybd, keybd, pWin, GRABTYPE_CORE, &mask,
+ &param, KeyPress, stuff->key, NullWindow, NullCursor);
+ if (!grab)
+ return BadAlloc;
+ return AddPassiveGrabToList(client, grab);
+}
+
+
+/**
+ * Server-side protocol handling for GrabButton request.
+ *
+ * Creates a grab for the client's ClientPointer and adds it as a passive grab
+ * to the list.
+ */
+int
+ProcGrabButton(ClientPtr client)
+{
+ WindowPtr pWin, confineTo;
+ REQUEST(xGrabButtonReq);
+ CursorPtr cursor;
+ GrabPtr grab;
+ DeviceIntPtr ptr, modifierDevice;
+ Mask access_mode = DixGrabAccess;
+ GrabMask mask;
+ GrabParameters param;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xGrabButtonReq);
+ if ((stuff->pointerMode != GrabModeSync) &&
+ (stuff->pointerMode != GrabModeAsync))
+ {
+ client->errorValue = stuff->pointerMode;
+ return BadValue;
+ }
+ if ((stuff->keyboardMode != GrabModeSync) &&
+ (stuff->keyboardMode != GrabModeAsync))
+ {
+ client->errorValue = stuff->keyboardMode;
+ return BadValue;
+ }
+ if ((stuff->modifiers != AnyModifier) &&
+ (stuff->modifiers & ~AllModifiersMask))
+ {
+ client->errorValue = stuff->modifiers;
+ return BadValue;
+ }
+ if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
+ {
+ client->errorValue = stuff->ownerEvents;
+ return BadValue;
+ }
+ if (stuff->eventMask & ~PointerGrabMask)
+ {
+ client->errorValue = stuff->eventMask;
+ return BadValue;
+ }
+ rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ if (stuff->confineTo == None)
+ confineTo = NullWindow;
+ else {
+ rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
+ DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+ if (stuff->cursor == None)
+ cursor = NullCursor;
+ else
+ {
+ rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR,
+ client, DixUseAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->cursor;
+ return rc;
+ }
+ access_mode |= DixForceAccess;
+ }
+
+ ptr = PickPointer(client);
+ modifierDevice = GetPairedDevice(ptr);
+ if (stuff->pointerMode == GrabModeSync ||
+ stuff->keyboardMode == GrabModeSync)
+ access_mode |= DixFreezeAccess;
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
+ if (rc != Success)
+ return rc;
+
+ memset(&param, 0, sizeof(param));
+ param.grabtype = GRABTYPE_CORE;
+ param.ownerEvents = stuff->ownerEvents;
+ param.this_device_mode = stuff->keyboardMode;
+ param.other_devices_mode = stuff->pointerMode;
+ param.modifiers = stuff->modifiers;
+
+ mask.core = stuff->eventMask;
+
+ grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
+ GRABTYPE_CORE, &mask, &param, ButtonPress,
+ stuff->button, confineTo, cursor);
+ if (!grab)
+ return BadAlloc;
+ return AddPassiveGrabToList(client, grab);
+}
+
+/**
+ * Server-side protocol handling for UngrabButton request.
+ *
+ * Deletes a passive grab on the client's ClientPointer from the list.
+ */
+int
+ProcUngrabButton(ClientPtr client)
+{
+ REQUEST(xUngrabButtonReq);
+ WindowPtr pWin;
+ GrabRec tempGrab;
+ int rc;
+ DeviceIntPtr ptr;
+
+ REQUEST_SIZE_MATCH(xUngrabButtonReq);
+ if ((stuff->modifiers != AnyModifier) &&
+ (stuff->modifiers & ~AllModifiersMask))
+ {
+ client->errorValue = stuff->modifiers;
+ return BadValue;
+ }
+ rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ ptr = PickPointer(client);
+
+ tempGrab.resource = client->clientAsMask;
+ tempGrab.device = ptr;
+ tempGrab.window = pWin;
+ tempGrab.modifiersDetail.exact = stuff->modifiers;
+ tempGrab.modifiersDetail.pMask = NULL;
+ tempGrab.modifierDevice = GetPairedDevice(ptr);
+ tempGrab.type = ButtonPress;
+ tempGrab.detail.exact = stuff->button;
+ tempGrab.grabtype = GRABTYPE_CORE;
+ tempGrab.detail.pMask = NULL;
+ tempGrab.next = NULL;
+
+ if (!DeletePassiveGrabFromList(&tempGrab))
+ return BadAlloc;
+ return Success;
+}
+
+/**
+ * Deactivate any grab that may be on the window, remove the focus.
+ * Delete any XInput extension events from the window too. Does not change the
+ * window mask. Use just before the window is deleted.
+ *
+ * If freeResources is set, passive grabs on the window are deleted.
+ *
+ * @param pWin The window to delete events from.
+ * @param freeResources True if resources associated with the window should be
+ * deleted.
+ */
+void
+DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
+{
+ WindowPtr parent;
+ DeviceIntPtr mouse = inputInfo.pointer;
+ DeviceIntPtr keybd = inputInfo.keyboard;
+ FocusClassPtr focus;
+ OtherClientsPtr oc;
+ GrabPtr passive;
+ GrabPtr grab;
+
+
+ /* Deactivate any grabs performed on this window, before making any
+ input focus changes. */
+ grab = mouse->deviceGrab.grab;
+ if (grab &&
+ ((grab->window == pWin) || (grab->confineTo == pWin)))
+ (*mouse->deviceGrab.DeactivateGrab)(mouse);
+
+
+ /* Deactivating a keyboard grab should cause focus events. */
+ grab = keybd->deviceGrab.grab;
+ if (grab && (grab->window == pWin))
+ (*keybd->deviceGrab.DeactivateGrab)(keybd);
+
+ /* And now the real devices */
+ for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
+ {
+ grab = mouse->deviceGrab.grab;
+ if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
+ (*mouse->deviceGrab.DeactivateGrab)(mouse);
+ }
+
+
+ for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
+ {
+ if (IsKeyboardDevice(keybd))
+ {
+ focus = keybd->focus;
+
+ /* If the focus window is a root window (ie. has no parent) then don't
+ delete the focus from it. */
+
+ if ((pWin == focus->win) && (pWin->parent != NullWindow))
+ {
+ int focusEventMode = NotifyNormal;
+
+ /* If a grab is in progress, then alter the mode of focus events. */
+
+ if (keybd->deviceGrab.grab)
+ focusEventMode = NotifyWhileGrabbed;
+
+ switch (focus->revert)
+ {
+ case RevertToNone:
+ DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
+ focus->win = NoneWin;
+ focus->traceGood = 0;
+ break;
+ case RevertToParent:
+ parent = pWin;
+ do
+ {
+ parent = parent->parent;
+ focus->traceGood--;
+ } while (!parent->realized
+ /* This would be a good protocol change -- windows being reparented
+ during SaveSet processing would cause the focus to revert to the
+ nearest enclosing window which will survive the death of the exiting
+ client, instead of ending up reverting to a dying window and thence
+ to None
+ */
+#ifdef NOTDEF
+ || wClient(parent)->clientGone
+#endif
+ );
+ if (!ActivateFocusInGrab(keybd, pWin, parent))
+ DoFocusEvents(keybd, pWin, parent, focusEventMode);
+ focus->win = parent;
+ focus->revert = RevertToNone;
+ break;
+ case RevertToPointerRoot:
+ if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
+ DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
+ focus->win = PointerRootWin;
+ focus->traceGood = 0;
+ break;
+ }
+ }
+ }
+
+ if (IsPointerDevice(keybd))
+ {
+ if (keybd->valuator->motionHintWindow == pWin)
+ keybd->valuator->motionHintWindow = NullWindow;
+ }
+ }
+
+ if (freeResources)
+ {
+ if (pWin->dontPropagate)
+ DontPropagateRefCnts[pWin->dontPropagate]--;
+ while ( (oc = wOtherClients(pWin)) )
+ FreeResource(oc->resource, RT_NONE);
+ while ( (passive = wPassiveGrabs(pWin)) )
+ FreeResource(passive->resource, RT_NONE);
+ }
+
+ DeleteWindowFromAnyExtEvents(pWin, freeResources);
+}
+
+/**
+ * Call this whenever some window at or below pWin has changed geometry. If
+ * there is a grab on the window, the cursor will be re-confined into the
+ * window.
+ */
+void
+CheckCursorConfinement(WindowPtr pWin)
+{
+ GrabPtr grab;
+ WindowPtr confineTo;
+ DeviceIntPtr pDev;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
+#endif
+
+ for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+ {
+ if (DevHasCursor(pDev))
+ {
+ grab = pDev->deviceGrab.grab;
+ if (grab && (confineTo = grab->confineTo))
+ {
+ if (!BorderSizeNotEmpty(pDev, confineTo))
+ (*pDev->deviceGrab.DeactivateGrab)(pDev);
+ else if ((pWin == confineTo) || IsParent(pWin, confineTo))
+ ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
+ }
+ }
+ }
+}
+
+Mask
+EventMaskForClient(WindowPtr pWin, ClientPtr client)
+{
+ OtherClientsPtr other;
+
+ if (wClient (pWin) == client)
+ return pWin->eventMask;
+ for (other = wOtherClients(pWin); other; other = other->next)
+ {
+ if (SameClient(other, client))
+ return other->mask;
+ }
+ return 0;
+}
+
+/**
+ * Server-side protocol handling for RecolorCursor request.
+ */
+int
+ProcRecolorCursor(ClientPtr client)
+{
+ CursorPtr pCursor;
+ int rc, nscr;
+ ScreenPtr pscr;
+ Bool displayed;
+ SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
+ REQUEST(xRecolorCursorReq);
+
+ REQUEST_SIZE_MATCH(xRecolorCursorReq);
+ rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
+ client, DixWriteAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->cursor;
+ return rc;
+ }
+
+ pCursor->foreRed = stuff->foreRed;
+ pCursor->foreGreen = stuff->foreGreen;
+ pCursor->foreBlue = stuff->foreBlue;
+
+ pCursor->backRed = stuff->backRed;
+ pCursor->backGreen = stuff->backGreen;
+ pCursor->backBlue = stuff->backBlue;
+
+ for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
+ {
+ pscr = screenInfo.screens[nscr];
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+ displayed = (pscr == pSprite->screen);
+ else
+#endif
+ displayed = (pscr == pSprite->hotPhys.pScreen);
+ ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
+ (pCursor == pSprite->current) && displayed);
+ }
+ return Success;
+}
+
+/**
+ * Write the given events to a client, swapping the byte order if necessary.
+ * To swap the byte ordering, a callback is called that has to be set up for
+ * the given event type.
+ *
+ * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
+ * can be more than one. Usually it's just one event.
+ *
+ * Do not modify the event structure passed in. See comment below.
+ *
+ * @param pClient Client to send events to.
+ * @param count Number of events.
+ * @param events The event list.
+ */
+void
+WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
+{
+#ifdef PANORAMIX
+ xEvent eventCopy;
+#endif
+ xEvent *eventTo, *eventFrom;
+ int i,
+ eventlength = sizeof(xEvent);
+
+ if (!pClient || pClient == serverClient || pClient->clientGone)
+ return;
+
+ for (i = 0; i < count; i++)
+ if ((events[i].u.u.type & 0x7f) != KeymapNotify)
+ events[i].u.u.sequenceNumber = pClient->sequence;
+
+ /* Let XKB rewrite the state, as it depends on client preferences. */
+ XkbFilterEvents(pClient, count, events);
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension &&
+ (screenInfo.screens[0]->x || screenInfo.screens[0]->y))
+ {
+ switch(events->u.u.type) {
+ case MotionNotify:
+ case ButtonPress:
+ case ButtonRelease:
+ case KeyPress:
+ case KeyRelease:
+ case EnterNotify:
+ case LeaveNotify:
+ /*
+ When multiple clients want the same event DeliverEventsToWindow
+ passes the same event structure multiple times so we can't
+ modify the one passed to us
+ */
+ count = 1; /* should always be 1 */
+ memcpy(&eventCopy, events, sizeof(xEvent));
+ eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
+ eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
+ if(eventCopy.u.keyButtonPointer.event ==
+ eventCopy.u.keyButtonPointer.root)
+ {
+ eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
+ eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
+ }
+ events = &eventCopy;
+ break;
+ default: break;
+ }
+ }
+#endif
+
+ if (EventCallback)
+ {
+ EventInfoRec eventinfo;
+ eventinfo.client = pClient;
+ eventinfo.events = events;
+ eventinfo.count = count;
+ CallCallbacks(&EventCallback, (pointer)&eventinfo);
+ }
+#ifdef XSERVER_DTRACE
+ if (XSERVER_SEND_EVENT_ENABLED()) {
+ for (i = 0; i < count; i++)
+ {
+ XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
+ }
+ }
+#endif
+ /* Just a safety check to make sure we only have one GenericEvent, it just
+ * makes things easier for me right now. (whot) */
+ for (i = 1; i < count; i++)
+ {
+ if (events[i].u.u.type == GenericEvent)
+ {
+ ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
+ return;
+ }
+ }
+
+ if (events->u.u.type == GenericEvent)
+ {
+ eventlength += ((xGenericEvent*)events)->length * 4;
+ }
+
+ if(pClient->swapped)
+ {
+ if (eventlength > swapEventLen)
+ {
+ swapEventLen = eventlength;
+ swapEvent = realloc(swapEvent, swapEventLen);
+ if (!swapEvent)
+ {
+ FatalError("WriteEventsToClient: Out of memory.\n");
+ return;
+ }
+ }
+
+ for(i = 0; i < count; i++)
+ {
+ eventFrom = &events[i];
+ eventTo = swapEvent;
+
+ /* Remember to strip off the leading bit of type in case
+ this event was sent with "SendEvent." */
+ (*EventSwapVector[eventFrom->u.u.type & 0177])
+ (eventFrom, eventTo);
+
+ WriteToClient(pClient, eventlength, (char *)eventTo);
+ }
+ }
+ else
+ {
+ /* only one GenericEvent, remember? that means either count is 1 and
+ * eventlength is arbitrary or eventlength is 32 and count doesn't
+ * matter. And we're all set. Woohoo. */
+ WriteToClient(pClient, count * eventlength, (char *) events);
+ }
+}
+
+/*
+ * Set the client pointer for the given client.
+ *
+ * A client can have exactly one ClientPointer. Each time a
+ * request/reply/event is processed and the choice of devices is ambiguous
+ * (e.g. QueryPointer request), the server will pick the ClientPointer (see
+ * PickPointer()).
+ * If a keyboard is needed, the first keyboard paired with the CP is used.
+ */
+int
+SetClientPointer(ClientPtr client, DeviceIntPtr device)
+{
+ int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!IsMaster(device))
+ {
+ ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
+ return BadDevice;
+ } else if (!device->spriteInfo->spriteOwner)
+ {
+ ErrorF("[dix] Device %d does not have a sprite. "
+ "Cannot be ClientPointer\n", device->id);
+ return BadDevice;
+ }
+ client->clientPtr = device;
+ return Success;
+}
+
+/* PickPointer will pick an appropriate pointer for the given client.
+ *
+ * An "appropriate device" is (in order of priority):
+ * 1) A device the given client has a core grab on.
+ * 2) A device set as ClientPointer for the given client.
+ * 3) The first master device.
+ */
+DeviceIntPtr
+PickPointer(ClientPtr client)
+{
+ DeviceIntPtr it = inputInfo.devices;
+
+ /* First, check if the client currently has a grab on a device. Even
+ * keyboards count. */
+ for(it = inputInfo.devices; it; it = it->next)
+ {
+ GrabPtr grab = it->deviceGrab.grab;
+ if (grab && grab->grabtype == GRABTYPE_CORE && SameClient(grab, client))
+ {
+ it = GetMaster(it, MASTER_POINTER);
+ return it; /* Always return a core grabbed device */
+ }
+ }
+
+ if (!client->clientPtr)
+ {
+ DeviceIntPtr it = inputInfo.devices;
+ while (it)
+ {
+ if (IsMaster(it) && it->spriteInfo->spriteOwner)
+ {
+ client->clientPtr = it;
+ break;
+ }
+ it = it->next;
+ }
+ }
+ return client->clientPtr;
+}
+
+/* PickKeyboard will pick an appropriate keyboard for the given client by
+ * searching the list of devices for the keyboard device that is paired with
+ * the client's pointer.
+ */
+DeviceIntPtr
+PickKeyboard(ClientPtr client)
+{
+ DeviceIntPtr ptr = PickPointer(client);
+ DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
+
+ if (!kbd)
+ {
+ ErrorF("[dix] ClientPointer not paired with a keyboard. This "
+ "is a bug.\n");
+ }
+
+ return kbd;
+}
+
+/* A client that has one or more core grabs does not get core events from
+ * devices it does not have a grab on. Legacy applications behave bad
+ * otherwise because they are not used to it and the events interfere.
+ * Only applies for core events.
+ *
+ * Return true if a core event from the device would interfere and should not
+ * be delivered.
+ */
+Bool
+IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
+{
+ DeviceIntPtr it = inputInfo.devices;
+
+ switch(event->u.u.type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ case EnterNotify:
+ case LeaveNotify:
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
+ return FALSE;
+
+ while(it)
+ {
+ if (it != dev)
+ {
+ if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
+ && !it->deviceGrab.fromPassiveGrab)
+ {
+ if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
+ (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
+ return TRUE;
+ }
+ }
+ it = it->next;
+ }
+
+ return FALSE;
+}
+
diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c
index 80275bd40..ef3142c84 100644
--- a/xorg-server/dix/inpututils.c
+++ b/xorg-server/dix/inpututils.c
@@ -1,550 +1,558 @@
-/*
- * Copyright © 2008 Daniel Stone
- *
- * 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: Daniel Stone <daniel@fooishbar.org>
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include "dix-config.h"
-#endif
-
-#include "exevents.h"
-#include "exglobals.h"
-#include "misc.h"
-#include "input.h"
-#include "inputstr.h"
-#include "xace.h"
-#include "xkbsrv.h"
-#include "xkbstr.h"
-#include "inpututils.h"
-
-/* Check if a button map change is okay with the device.
- * Returns -1 for BadValue, as it collides with MappingBusy. */
-static int
-check_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out,
- ClientPtr client)
-{
- int i, ret;
-
- if (!dev || !dev->button)
- {
- client->errorValue = (dev) ? dev->id : 0;
- return BadDevice;
- }
-
- ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
- if (ret != Success)
- {
- client->errorValue = dev->id;
- return ret;
- }
-
- for (i = 0; i < len; i++) {
- if (dev->button->map[i + 1] != map[i] && dev->button->down[i + 1])
- return MappingBusy;
- }
-
- return Success;
-}
-
-static void
-do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
-{
- int i;
- xEvent core_mn;
- deviceMappingNotify xi_mn;
-
- /* The map in ButtonClassRec refers to button numbers, whereas the
- * protocol is zero-indexed. Sigh. */
- memcpy(&(dev->button->map[1]), map, len);
-
- core_mn.u.u.type = MappingNotify;
- core_mn.u.mappingNotify.request = MappingPointer;
-
- /* 0 is the server client. */
- for (i = 1; i < currentMaxClients; i++) {
- /* Don't send irrelevant events to naïve clients. */
- if (!clients[i] || clients[i]->clientState != ClientStateRunning)
- continue;
-
- if (!XIShouldNotify(clients[i], dev))
- continue;
-
- WriteEventsToClient(clients[i], 1, &core_mn);
- }
-
- xi_mn.type = DeviceMappingNotify;
- xi_mn.request = MappingPointer;
- xi_mn.deviceid = dev->id;
- xi_mn.time = GetTimeInMillis();
-
- SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1);
-}
-
-/*
- * Does what it says on the box, both for core and Xi.
- *
- * Faithfully reports any errors encountered while trying to apply the map
- * to the requested device, faithfully ignores any errors encountered while
- * trying to apply the map to its master/slaves.
- */
-int
-ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
-{
- int ret;
-
- /* If we can't perform the change on the requested device, bail out. */
- ret = check_butmap_change(dev, map, len, &client->errorValue, client);
- if (ret != Success)
- return ret;
- do_butmap_change(dev, map, len, client);
-
- return Success;
-}
-
-/* Check if a modifier map change is okay with the device.
- * Returns -1 for BadValue, as it collides with MappingBusy; this particular
- * caveat can be removed with LegalModifier, as we have no other reason to
- * set MappingFailed. Sigh. */
-static int
-check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap)
-{
- int ret, i;
- XkbDescPtr xkb;
-
- ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
- if (ret != Success)
- return ret;
-
- if (!dev->key)
- return BadMatch;
- xkb = dev->key->xkbInfo->desc;
-
- for (i = 0; i < MAP_LENGTH; i++) {
- if (!modmap[i])
- continue;
-
- /* Check that all the new modifiers fall within the advertised
- * keycode range. */
- if (i < xkb->min_key_code || i > xkb->max_key_code) {
- client->errorValue = i;
- return -1;
- }
-
- /* Make sure the mapping is okay with the DDX. */
- if (!LegalModifier(i, dev)) {
- client->errorValue = i;
- return MappingFailed;
- }
-
- /* None of the new modifiers may be down while we change the
- * map. */
- if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
- client->errorValue = i;
- return MappingBusy;
- }
- }
-
- /* None of the old modifiers may be down while we change the map,
- * either. */
- for (i = xkb->min_key_code; i < xkb->max_key_code; i++) {
- if (!xkb->map->modmap[i])
- continue;
- if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
- client->errorValue = i;
- return MappingBusy;
- }
- }
-
- return Success;
-}
-
-static int
-check_modmap_change_slave(ClientPtr client, DeviceIntPtr master,
- DeviceIntPtr slave, CARD8 *modmap)
-{
- XkbDescPtr master_xkb, slave_xkb;
- int i, j;
-
- if (!slave->key || !master->key)
- return 0;
-
- master_xkb = master->key->xkbInfo->desc;
- slave_xkb = slave->key->xkbInfo->desc;
-
- /* Ignore devices with a clearly different keymap. */
- if (slave_xkb->min_key_code != master_xkb->min_key_code ||
- slave_xkb->max_key_code != master_xkb->max_key_code)
- return 0;
-
- for (i = 0; i < MAP_LENGTH; i++) {
- if (!modmap[i])
- continue;
-
- /* If we have different symbols for any modifier on an
- * extended keyboard, ignore the whole remap request. */
- for (j = 0;
- j < XkbKeyNumSyms(slave_xkb, i) &&
- j < XkbKeyNumSyms(master_xkb, i);
- j++)
- if (XkbKeySymsPtr(slave_xkb, i)[j] != XkbKeySymsPtr(master_xkb, i)[j])
- return 0;
- }
-
- if (check_modmap_change(client, slave, modmap) != Success)
- return 0;
-
- return 1;
-}
-
-/* Actually change the modifier map, and send notifications. Cannot fail. */
-static void
-do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap)
-{
- XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient);
-}
-
-/* Rebuild modmap (key -> mod) from map (mod -> key). */
-static int build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap,
- int max_keys_per_mod)
-{
- int i, len = max_keys_per_mod * 8;
-
- memset(modmap, 0, MAP_LENGTH);
-
- for (i = 0; i < len; i++) {
- if (!modkeymap[i])
- continue;
-
- if (modkeymap[i] >= MAP_LENGTH)
- return BadValue;
-
- if (modmap[modkeymap[i]])
- return BadValue;
-
- modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod);
- }
-
- return Success;
-}
-
-int
-change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
- int max_keys_per_mod)
-{
- int ret;
- CARD8 modmap[MAP_LENGTH];
- DeviceIntPtr tmp;
-
- ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod);
- if (ret != Success)
- return ret;
-
- /* If we can't perform the change on the requested device, bail out. */
- ret = check_modmap_change(client, dev, modmap);
- if (ret != Success)
- return ret;
- do_modmap_change(client, dev, modmap);
-
- /* Change any attached masters/slaves. */
- if (IsMaster(dev)) {
- for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
- if (!IsMaster(tmp) && tmp->u.master == dev)
- if (check_modmap_change_slave(client, dev, tmp, modmap))
- do_modmap_change(client, tmp, modmap);
- }
- }
- else if (dev->u.master && dev->u.master->u.lastSlave == dev) {
- /* If this fails, expect the results to be weird. */
- if (check_modmap_change(client, dev->u.master, modmap))
- do_modmap_change(client, dev->u.master, modmap);
- }
-
- return Success;
-}
-
-int generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
- KeyCode **modkeymap_out, int *max_keys_per_mod_out)
-{
- CARD8 keys_per_mod[8];
- int max_keys_per_mod;
- KeyCode *modkeymap = NULL;
- int i, j, ret;
-
- ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
- if (ret != Success)
- return ret;
-
- if (!dev->key)
- return BadMatch;
-
- /* Count the number of keys per modifier to determine how wide we
- * should make the map. */
- max_keys_per_mod = 0;
- for (i = 0; i < 8; i++)
- keys_per_mod[i] = 0;
- for (i = 8; i < MAP_LENGTH; i++) {
- for (j = 0; j < 8; j++) {
- if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
- if (++keys_per_mod[j] > max_keys_per_mod)
- max_keys_per_mod = keys_per_mod[j];
- }
- }
- }
-
- if (max_keys_per_mod != 0) {
- modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode));
- if (!modkeymap)
- return BadAlloc;
-
- for (i = 0; i < 8; i++)
- keys_per_mod[i] = 0;
-
- for (i = 8; i < MAP_LENGTH; i++) {
- for (j = 0; j < 8; j++) {
- if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
- modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i;
- keys_per_mod[j]++;
- }
- }
- }
- }
-
- *max_keys_per_mod_out = max_keys_per_mod;
- *modkeymap_out = modkeymap;
-
- return Success;
-}
-
-/**
- * Duplicate the InputAttributes in the most obvious way.
- * No special memory handling is used to give drivers the maximum
- * flexibility with the data. Drivers should be able to call realloc on the
- * product string if needed and perform similar operations.
- */
-InputAttributes*
-DuplicateInputAttributes(InputAttributes *attrs)
-{
- InputAttributes *new_attr;
- int ntags = 0;
- char **tags, **new_tags;
-
- if (!attrs)
- return NULL;
-
- if (!(new_attr = calloc(1, sizeof(InputAttributes))))
- goto unwind;
-
- if (attrs->product && !(new_attr->product = strdup(attrs->product)))
- goto unwind;
- if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor)))
- goto unwind;
- if (attrs->device && !(new_attr->device = strdup(attrs->device)))
- goto unwind;
- if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id)))
- goto unwind;
- if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id)))
- goto unwind;
-
- new_attr->flags = attrs->flags;
-
- if ((tags = attrs->tags))
- {
- while(*tags++)
- ntags++;
-
- new_attr->tags = calloc(ntags + 1, sizeof(char*));
- if (!new_attr->tags)
- goto unwind;
-
- tags = attrs->tags;
- new_tags = new_attr->tags;
-
- while(*tags)
- {
- *new_tags = strdup(*tags);
- if (!*new_tags)
- goto unwind;
-
- tags++;
- new_tags++;
- }
- }
-
- return new_attr;
-
-unwind:
- FreeInputAttributes(new_attr);
- return NULL;
-}
-
-void
-FreeInputAttributes(InputAttributes *attrs)
-{
- char **tags;
-
- if (!attrs)
- return;
-
- free(attrs->product);
- free(attrs->vendor);
- free(attrs->device);
- free(attrs->pnp_id);
- free(attrs->usb_id);
-
- if ((tags = attrs->tags))
- while(*tags)
- free(*tags++);
-
- free(attrs->tags);
- free(attrs);
-}
-
-/**
- * Alloc a valuator mask large enough for num_valuators.
- */
-ValuatorMask*
-valuator_mask_new(int num_valuators)
-{
- /* alloc a fixed size mask for now and ignore num_valuators. in the
- * flying-car future, when we can dynamically alloc the masks and are
- * not constrained by signals, we can start using num_valuators */
- ValuatorMask *mask = calloc(1, sizeof(ValuatorMask));
- mask->last_bit = -1;
- return mask;
-}
-
-/**
- * Sets a range of valuators between first_valuator and num_valuators with
- * the data in the valuators array. All other values are set to 0.
- */
-void
-valuator_mask_set_range(ValuatorMask *mask, int first_valuator, int num_valuators,
- const int* valuators)
-{
- int i;
-
- valuator_mask_zero(mask);
-
- for (i = first_valuator; i < min(first_valuator + num_valuators, MAX_VALUATORS); i++)
- valuator_mask_set(mask, i, valuators[i - first_valuator]);
-}
-
-/**
- * Reset mask to zero.
- */
-void
-valuator_mask_zero(ValuatorMask *mask)
-{
- memset(mask, 0, sizeof(*mask));
- mask->last_bit = -1;
-}
-
-/**
- * Returns the current size of the mask (i.e. the highest number of
- * valuators currently set + 1).
- */
-int
-valuator_mask_size(const ValuatorMask *mask)
-{
- return mask->last_bit + 1;
-}
-
-/**
- * Returns the number of valuators set in the given mask.
- */
-int
-valuator_mask_num_valuators(const ValuatorMask *mask)
-{
- return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS));
-}
-
-/**
- * Return true if the valuator is set in the mask, or false otherwise.
- */
-int
-valuator_mask_isset(const ValuatorMask *mask, int valuator)
-{
- return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator);
-}
-
-/**
- * Set the valuator to the given data.
- */
-void
-valuator_mask_set(ValuatorMask *mask, int valuator, int data)
-{
- mask->last_bit = max(valuator, mask->last_bit);
- SetBit(mask->mask, valuator);
- mask->valuators[valuator] = data;
-}
-
-/**
- * Return the requested valuator value. If the mask bit is not set for the
- * given valuator, the returned value is undefined.
- */
-int
-valuator_mask_get(const ValuatorMask *mask, int valuator)
-{
- return mask->valuators[valuator];
-}
-
-/**
- * Remove the valuator from the mask.
- */
-void
-valuator_mask_unset(ValuatorMask *mask, int valuator)
-{
- if (mask->last_bit >= valuator) {
- int i, lastbit = -1;
-
- ClearBit(mask->mask, valuator);
- mask->valuators[valuator] = 0;
-
- for (i = 0; i <= mask->last_bit; i++)
- if (valuator_mask_isset(mask, i))
- lastbit = max(lastbit, i);
- mask->last_bit = lastbit;
- }
-}
-
-void
-valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
-{
- if (src)
- memcpy(dest, src, sizeof(*dest));
- else
- valuator_mask_zero(dest);
-}
-
-int
-CountBits(const uint8_t *mask, int len)
-{
- int i;
- int ret = 0;
-
- for (i = 0; i < len; i++)
- if (BitIsOn(mask, i))
- ret++;
-
- return ret;
-}
+/*
+ * Copyright © 2008 Daniel Stone
+ *
+ * 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: Daniel Stone <daniel@fooishbar.org>
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include "exevents.h"
+#include "exglobals.h"
+#include "misc.h"
+#include "input.h"
+#include "inputstr.h"
+#include "xace.h"
+#include "xkbsrv.h"
+#include "xkbstr.h"
+#include "inpututils.h"
+
+/* Check if a button map change is okay with the device.
+ * Returns -1 for BadValue, as it collides with MappingBusy. */
+static int
+check_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out,
+ ClientPtr client)
+{
+ int i, ret;
+
+ if (!dev || !dev->button)
+ {
+ client->errorValue = (dev) ? dev->id : 0;
+ return BadDevice;
+ }
+
+ ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
+ if (ret != Success)
+ {
+ client->errorValue = dev->id;
+ return ret;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (dev->button->map[i + 1] != map[i] && dev->button->down[i + 1])
+ return MappingBusy;
+ }
+
+ return Success;
+}
+
+static void
+do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
+{
+ int i;
+ xEvent core_mn;
+ deviceMappingNotify xi_mn;
+
+ /* The map in ButtonClassRec refers to button numbers, whereas the
+ * protocol is zero-indexed. Sigh. */
+ memcpy(&(dev->button->map[1]), map, len);
+
+ core_mn.u.u.type = MappingNotify;
+ core_mn.u.mappingNotify.request = MappingPointer;
+
+ /* 0 is the server client. */
+ for (i = 1; i < currentMaxClients; i++) {
+ /* Don't send irrelevant events to naïve clients. */
+ if (!clients[i] || clients[i]->clientState != ClientStateRunning)
+ continue;
+
+ if (!XIShouldNotify(clients[i], dev))
+ continue;
+
+ WriteEventsToClient(clients[i], 1, &core_mn);
+ }
+
+ xi_mn.type = DeviceMappingNotify;
+ xi_mn.request = MappingPointer;
+ xi_mn.deviceid = dev->id;
+ xi_mn.time = GetTimeInMillis();
+
+ SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1);
+}
+
+/*
+ * Does what it says on the box, both for core and Xi.
+ *
+ * Faithfully reports any errors encountered while trying to apply the map
+ * to the requested device, faithfully ignores any errors encountered while
+ * trying to apply the map to its master/slaves.
+ */
+int
+ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
+{
+ int ret;
+
+ /* If we can't perform the change on the requested device, bail out. */
+ ret = check_butmap_change(dev, map, len, &client->errorValue, client);
+ if (ret != Success)
+ return ret;
+ do_butmap_change(dev, map, len, client);
+
+ return Success;
+}
+
+/* Check if a modifier map change is okay with the device.
+ * Returns -1 for BadValue, as it collides with MappingBusy; this particular
+ * caveat can be removed with LegalModifier, as we have no other reason to
+ * set MappingFailed. Sigh. */
+static int
+check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap)
+{
+ int ret, i;
+ XkbDescPtr xkb;
+
+ ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
+ if (ret != Success)
+ return ret;
+
+ if (!dev->key)
+ return BadMatch;
+ xkb = dev->key->xkbInfo->desc;
+
+ for (i = 0; i < MAP_LENGTH; i++) {
+ if (!modmap[i])
+ continue;
+
+ /* Check that all the new modifiers fall within the advertised
+ * keycode range. */
+ if (i < xkb->min_key_code || i > xkb->max_key_code) {
+ client->errorValue = i;
+ return -1;
+ }
+
+ /* Make sure the mapping is okay with the DDX. */
+ if (!LegalModifier(i, dev)) {
+ client->errorValue = i;
+ return MappingFailed;
+ }
+
+ /* None of the new modifiers may be down while we change the
+ * map. */
+ if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
+ client->errorValue = i;
+ return MappingBusy;
+ }
+ }
+
+ /* None of the old modifiers may be down while we change the map,
+ * either. */
+ for (i = xkb->min_key_code; i < xkb->max_key_code; i++) {
+ if (!xkb->map->modmap[i])
+ continue;
+ if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
+ client->errorValue = i;
+ return MappingBusy;
+ }
+ }
+
+ return Success;
+}
+
+static int
+check_modmap_change_slave(ClientPtr client, DeviceIntPtr master,
+ DeviceIntPtr slave, CARD8 *modmap)
+{
+ XkbDescPtr master_xkb, slave_xkb;
+ int i, j;
+
+ if (!slave->key || !master->key)
+ return 0;
+
+ master_xkb = master->key->xkbInfo->desc;
+ slave_xkb = slave->key->xkbInfo->desc;
+
+ /* Ignore devices with a clearly different keymap. */
+ if (slave_xkb->min_key_code != master_xkb->min_key_code ||
+ slave_xkb->max_key_code != master_xkb->max_key_code)
+ return 0;
+
+ for (i = 0; i < MAP_LENGTH; i++) {
+ if (!modmap[i])
+ continue;
+
+ /* If we have different symbols for any modifier on an
+ * extended keyboard, ignore the whole remap request. */
+ for (j = 0;
+ j < XkbKeyNumSyms(slave_xkb, i) &&
+ j < XkbKeyNumSyms(master_xkb, i);
+ j++)
+ if (XkbKeySymsPtr(slave_xkb, i)[j] != XkbKeySymsPtr(master_xkb, i)[j])
+ return 0;
+ }
+
+ if (check_modmap_change(client, slave, modmap) != Success)
+ return 0;
+
+ return 1;
+}
+
+/* Actually change the modifier map, and send notifications. Cannot fail. */
+static void
+do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap)
+{
+ XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient);
+}
+
+/* Rebuild modmap (key -> mod) from map (mod -> key). */
+static int build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap,
+ int max_keys_per_mod)
+{
+ int i, len = max_keys_per_mod * 8;
+
+ memset(modmap, 0, MAP_LENGTH);
+
+ for (i = 0; i < len; i++) {
+ if (!modkeymap[i])
+ continue;
+
+ if (modkeymap[i] >= MAP_LENGTH)
+ return BadValue;
+
+ if (modmap[modkeymap[i]])
+ return BadValue;
+
+ modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod);
+ }
+
+ return Success;
+}
+
+int
+change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
+ int max_keys_per_mod)
+{
+ int ret;
+ CARD8 modmap[MAP_LENGTH];
+ DeviceIntPtr tmp;
+
+ ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod);
+ if (ret != Success)
+ return ret;
+
+ /* If we can't perform the change on the requested device, bail out. */
+ ret = check_modmap_change(client, dev, modmap);
+ if (ret != Success)
+ return ret;
+ do_modmap_change(client, dev, modmap);
+
+ /* Change any attached masters/slaves. */
+ if (IsMaster(dev)) {
+ for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
+ if (!IsMaster(tmp) && tmp->u.master == dev)
+ if (check_modmap_change_slave(client, dev, tmp, modmap))
+ do_modmap_change(client, tmp, modmap);
+ }
+ }
+ else if (dev->u.master && dev->u.master->u.lastSlave == dev) {
+ /* If this fails, expect the results to be weird. */
+ if (check_modmap_change(client, dev->u.master, modmap))
+ do_modmap_change(client, dev->u.master, modmap);
+ }
+
+ return Success;
+}
+
+int generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
+ KeyCode **modkeymap_out, int *max_keys_per_mod_out)
+{
+ CARD8 keys_per_mod[8];
+ int max_keys_per_mod;
+ KeyCode *modkeymap = NULL;
+ int i, j, ret;
+
+ ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
+ if (ret != Success)
+ return ret;
+
+ if (!dev->key)
+ return BadMatch;
+
+ /* Count the number of keys per modifier to determine how wide we
+ * should make the map. */
+ max_keys_per_mod = 0;
+ for (i = 0; i < 8; i++)
+ keys_per_mod[i] = 0;
+ for (i = 8; i < MAP_LENGTH; i++) {
+ for (j = 0; j < 8; j++) {
+ if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
+ if (++keys_per_mod[j] > max_keys_per_mod)
+ max_keys_per_mod = keys_per_mod[j];
+ }
+ }
+ }
+
+ if (max_keys_per_mod != 0) {
+ modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode));
+ if (!modkeymap)
+ return BadAlloc;
+
+ for (i = 0; i < 8; i++)
+ keys_per_mod[i] = 0;
+
+ for (i = 8; i < MAP_LENGTH; i++) {
+ for (j = 0; j < 8; j++) {
+ if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
+ modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i;
+ keys_per_mod[j]++;
+ }
+ }
+ }
+ }
+
+ *max_keys_per_mod_out = max_keys_per_mod;
+ *modkeymap_out = modkeymap;
+
+ return Success;
+}
+
+/**
+ * Duplicate the InputAttributes in the most obvious way.
+ * No special memory handling is used to give drivers the maximum
+ * flexibility with the data. Drivers should be able to call realloc on the
+ * product string if needed and perform similar operations.
+ */
+InputAttributes*
+DuplicateInputAttributes(InputAttributes *attrs)
+{
+ InputAttributes *new_attr;
+ int ntags = 0;
+ char **tags, **new_tags;
+
+ if (!attrs)
+ return NULL;
+
+ if (!(new_attr = calloc(1, sizeof(InputAttributes))))
+ goto unwind;
+
+ if (attrs->product && !(new_attr->product = strdup(attrs->product)))
+ goto unwind;
+ if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor)))
+ goto unwind;
+ if (attrs->device && !(new_attr->device = strdup(attrs->device)))
+ goto unwind;
+ if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id)))
+ goto unwind;
+ if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id)))
+ goto unwind;
+
+ new_attr->flags = attrs->flags;
+
+ if ((tags = attrs->tags))
+ {
+ while(*tags++)
+ ntags++;
+
+ new_attr->tags = calloc(ntags + 1, sizeof(char*));
+ if (!new_attr->tags)
+ goto unwind;
+
+ tags = attrs->tags;
+ new_tags = new_attr->tags;
+
+ while(*tags)
+ {
+ *new_tags = strdup(*tags);
+ if (!*new_tags)
+ goto unwind;
+
+ tags++;
+ new_tags++;
+ }
+ }
+
+ return new_attr;
+
+unwind:
+ FreeInputAttributes(new_attr);
+ return NULL;
+}
+
+void
+FreeInputAttributes(InputAttributes *attrs)
+{
+ char **tags;
+
+ if (!attrs)
+ return;
+
+ free(attrs->product);
+ free(attrs->vendor);
+ free(attrs->device);
+ free(attrs->pnp_id);
+ free(attrs->usb_id);
+
+ if ((tags = attrs->tags))
+ while(*tags)
+ free(*tags++);
+
+ free(attrs->tags);
+ free(attrs);
+}
+
+/**
+ * Alloc a valuator mask large enough for num_valuators.
+ */
+ValuatorMask*
+valuator_mask_new(int num_valuators)
+{
+ /* alloc a fixed size mask for now and ignore num_valuators. in the
+ * flying-car future, when we can dynamically alloc the masks and are
+ * not constrained by signals, we can start using num_valuators */
+ ValuatorMask *mask = calloc(1, sizeof(ValuatorMask));
+ mask->last_bit = -1;
+ return mask;
+}
+
+void
+valuator_mask_free(ValuatorMask **mask)
+{
+ free(*mask);
+ *mask = NULL;
+}
+
+
+/**
+ * Sets a range of valuators between first_valuator and num_valuators with
+ * the data in the valuators array. All other values are set to 0.
+ */
+void
+valuator_mask_set_range(ValuatorMask *mask, int first_valuator, int num_valuators,
+ const int* valuators)
+{
+ int i;
+
+ valuator_mask_zero(mask);
+
+ for (i = first_valuator; i < min(first_valuator + num_valuators, MAX_VALUATORS); i++)
+ valuator_mask_set(mask, i, valuators[i - first_valuator]);
+}
+
+/**
+ * Reset mask to zero.
+ */
+void
+valuator_mask_zero(ValuatorMask *mask)
+{
+ memset(mask, 0, sizeof(*mask));
+ mask->last_bit = -1;
+}
+
+/**
+ * Returns the current size of the mask (i.e. the highest number of
+ * valuators currently set + 1).
+ */
+int
+valuator_mask_size(const ValuatorMask *mask)
+{
+ return mask->last_bit + 1;
+}
+
+/**
+ * Returns the number of valuators set in the given mask.
+ */
+int
+valuator_mask_num_valuators(const ValuatorMask *mask)
+{
+ return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS));
+}
+
+/**
+ * Return true if the valuator is set in the mask, or false otherwise.
+ */
+int
+valuator_mask_isset(const ValuatorMask *mask, int valuator)
+{
+ return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator);
+}
+
+/**
+ * Set the valuator to the given data.
+ */
+void
+valuator_mask_set(ValuatorMask *mask, int valuator, int data)
+{
+ mask->last_bit = max(valuator, mask->last_bit);
+ SetBit(mask->mask, valuator);
+ mask->valuators[valuator] = data;
+}
+
+/**
+ * Return the requested valuator value. If the mask bit is not set for the
+ * given valuator, the returned value is undefined.
+ */
+int
+valuator_mask_get(const ValuatorMask *mask, int valuator)
+{
+ return mask->valuators[valuator];
+}
+
+/**
+ * Remove the valuator from the mask.
+ */
+void
+valuator_mask_unset(ValuatorMask *mask, int valuator)
+{
+ if (mask->last_bit >= valuator) {
+ int i, lastbit = -1;
+
+ ClearBit(mask->mask, valuator);
+ mask->valuators[valuator] = 0;
+
+ for (i = 0; i <= mask->last_bit; i++)
+ if (valuator_mask_isset(mask, i))
+ lastbit = max(lastbit, i);
+ mask->last_bit = lastbit;
+ }
+}
+
+void
+valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
+{
+ if (src)
+ memcpy(dest, src, sizeof(*dest));
+ else
+ valuator_mask_zero(dest);
+}
+
+int
+CountBits(const uint8_t *mask, int len)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < len; i++)
+ if (BitIsOn(mask, i))
+ ret++;
+
+ return ret;
+}
diff --git a/xorg-server/dix/resource.c b/xorg-server/dix/resource.c
index bec68753e..26d2c72aa 100644
--- a/xorg-server/dix/resource.c
+++ b/xorg-server/dix/resource.c
@@ -1,973 +1,965 @@
-/************************************************************
-
-Copyright 1987, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-********************************************************/
-/* The panoramix components contained the following notice */
-/*****************************************************************
-
-Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-******************************************************************/
-/* XSERVER_DTRACE additions:
- * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/* Routines to manage various kinds of resources:
- *
- * CreateNewResourceType, CreateNewResourceClass, InitClientResources,
- * FakeClientID, AddResource, FreeResource, FreeClientResources,
- * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange
- */
-
-/*
- * A resource ID is a 32 bit quantity, the upper 2 bits of which are
- * off-limits for client-visible resources. The next 8 bits are
- * used as client ID, and the low 22 bits come from the client.
- * A resource ID is "hashed" by extracting and xoring subfields
- * (varying with the size of the hash table).
- *
- * It is sometimes necessary for the server to create an ID that looks
- * like it belongs to a client. This ID, however, must not be one
- * the client actually can create, or we have the potential for conflict.
- * The 31st bit of the ID is reserved for the server's use for this
- * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to
- * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a
- * resource "owned" by the client.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include "misc.h"
-#include "os.h"
-#include "resource.h"
-#include "dixstruct.h"
-#include "opaque.h"
-#include "windowstr.h"
-#include "dixfont.h"
-#include "colormap.h"
-#include "inputstr.h"
-#include "dixevents.h"
-#include "dixgrabs.h"
-#include "cursor.h"
-#ifdef PANORAMIX
-#include "panoramiX.h"
-#include "panoramiXsrv.h"
-#endif
-#include "xace.h"
-#include <assert.h>
-#include "registry.h"
-
-#ifdef XSERVER_DTRACE
-#include <sys/types.h>
-typedef const char *string;
-#include "Xserver-dtrace.h"
-
-#define TypeNameString(t) LookupResourceName(t)
-#endif
-
-static void RebuildTable(
- int /*client*/
-);
-
-#define SERVER_MINID 32
-
-#define INITBUCKETS 64
-#define INITHASHSIZE 6
-#define MAXHASHSIZE 11
-
-typedef struct _Resource {
- struct _Resource *next;
- XID id;
- RESTYPE type;
- pointer value;
-} ResourceRec, *ResourcePtr;
-#define NullResource ((ResourcePtr)NULL)
-
-typedef struct _ClientResource {
- ResourcePtr *resources;
- int elements;
- int buckets;
- int hashsize; /* log(2)(buckets) */
- XID fakeID;
- XID endFakeID;
- XID expectID;
-} ClientResourceRec;
-
-RESTYPE lastResourceType;
-static RESTYPE lastResourceClass;
-RESTYPE TypeMask;
-
-struct ResourceType {
- DeleteType deleteFunc;
- int errorValue;
-};
-
-static struct ResourceType *resourceTypes;
-static const struct ResourceType predefTypes[] = {
- [RT_NONE & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = (DeleteType)NoopDDA,
- .errorValue = BadValue,
- },
- [RT_WINDOW & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = DeleteWindow,
- .errorValue = BadWindow,
- },
- [RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = dixDestroyPixmap,
- .errorValue = BadPixmap,
- },
- [RT_GC & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = FreeGC,
- .errorValue = BadGC,
- },
- [RT_FONT & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = CloseFont,
- .errorValue = BadFont,
- },
- [RT_CURSOR & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = FreeCursor,
- .errorValue = BadCursor,
- },
- [RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = FreeColormap,
- .errorValue = BadColor,
- },
- [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = FreeClientPixels,
- .errorValue = BadColor,
- },
- [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = OtherClientGone,
- .errorValue = BadValue,
- },
- [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
- .deleteFunc = DeletePassiveGrab,
- .errorValue = BadValue,
- },
-};
-
-CallbackListPtr ResourceStateCallback;
-
-static _X_INLINE void
-CallResourceStateCallback(ResourceState state, ResourceRec *res)
-{
- if (ResourceStateCallback) {
- ResourceStateInfoRec rsi = { state, res->id, res->type, res->value };
- CallCallbacks(&ResourceStateCallback, &rsi);
- }
-}
-
-RESTYPE
-CreateNewResourceType(DeleteType deleteFunc, char *name)
-{
- RESTYPE next = lastResourceType + 1;
- struct ResourceType *types;
-
- if (next & lastResourceClass)
- return 0;
- types = realloc(resourceTypes, (next + 1) * sizeof(*resourceTypes));
- if (!types)
- return 0;
-
- lastResourceType = next;
- resourceTypes = types;
- resourceTypes[next].deleteFunc = deleteFunc;
- resourceTypes[next].errorValue = BadValue;
-
- /* Called even if name is NULL, to remove any previous entry */
- RegisterResourceName(next, name);
-
- return next;
-}
-
-void
-SetResourceTypeErrorValue(RESTYPE type, int errorValue)
-{
- resourceTypes[type & TypeMask].errorValue = errorValue;
-}
-
-RESTYPE
-CreateNewResourceClass(void)
-{
- RESTYPE next = lastResourceClass >> 1;
-
- if (next & lastResourceType)
- return 0;
- lastResourceClass = next;
- TypeMask = next - 1;
- return next;
-}
-
-static ClientResourceRec clientTable[MAXCLIENTS];
-
-/*****************
- * InitClientResources
- * When a new client is created, call this to allocate space
- * in resource table
- *****************/
-
-Bool
-InitClientResources(ClientPtr client)
-{
- int i, j;
-
- if (client == serverClient)
- {
- lastResourceType = RT_LASTPREDEF;
- lastResourceClass = RC_LASTPREDEF;
- TypeMask = RC_LASTPREDEF - 1;
- free(resourceTypes);
- resourceTypes = malloc(sizeof(predefTypes));
- if (!resourceTypes)
- return FALSE;
- memcpy(resourceTypes, predefTypes, sizeof(predefTypes));
- }
- clientTable[i = client->index].resources =
- malloc(INITBUCKETS*sizeof(ResourcePtr));
- if (!clientTable[i].resources)
- return FALSE;
- clientTable[i].buckets = INITBUCKETS;
- clientTable[i].elements = 0;
- clientTable[i].hashsize = INITHASHSIZE;
- /* Many IDs allocated from the server client are visible to clients,
- * so we don't use the SERVER_BIT for them, but we have to start
- * past the magic value constants used in the protocol. For normal
- * clients, we can start from zero, with SERVER_BIT set.
- */
- clientTable[i].fakeID = client->clientAsMask |
- (client->index ? SERVER_BIT : SERVER_MINID);
- clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1;
- clientTable[i].expectID = client->clientAsMask;
- for (j=0; j<INITBUCKETS; j++)
- {
- clientTable[i].resources[j] = NullResource;
- }
- return TRUE;
-}
-
-
-static int
-Hash(int client, XID id)
-{
- id &= RESOURCE_ID_MASK;
- switch (clientTable[client].hashsize)
- {
- case 6:
- return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));
- case 7:
- return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));
- case 8:
- return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));
- case 9:
- return ((int)(0x1FF & (id ^ (id>>9))));
- case 10:
- return ((int)(0x3FF & (id ^ (id>>10))));
- case 11:
- return ((int)(0x7FF & (id ^ (id>>11))));
- }
- return -1;
-}
-
-static XID
-AvailableID(
- int client,
- XID id,
- XID maxid,
- XID goodid)
-{
- ResourcePtr res;
-
- if ((goodid >= id) && (goodid <= maxid))
- return goodid;
- for (; id <= maxid; id++)
- {
- res = clientTable[client].resources[Hash(client, id)];
- while (res && (res->id != id))
- res = res->next;
- if (!res)
- return id;
- }
- return 0;
-}
-
-void
-GetXIDRange(int client, Bool server, XID *minp, XID *maxp)
-{
- XID id, maxid;
- ResourcePtr *resp;
- ResourcePtr res;
- int i;
- XID goodid;
-
- id = (Mask)client << CLIENTOFFSET;
- if (server)
- id |= client ? SERVER_BIT : SERVER_MINID;
- maxid = id | RESOURCE_ID_MASK;
- goodid = 0;
- for (resp = clientTable[client].resources, i = clientTable[client].buckets;
- --i >= 0;)
- {
- for (res = *resp++; res; res = res->next)
- {
- if ((res->id < id) || (res->id > maxid))
- continue;
- if (((res->id - id) >= (maxid - res->id)) ?
- (goodid = AvailableID(client, id, res->id - 1, goodid)) :
- !(goodid = AvailableID(client, res->id + 1, maxid, goodid)))
- maxid = res->id - 1;
- else
- id = res->id + 1;
- }
- }
- if (id > maxid)
- id = maxid = 0;
- *minp = id;
- *maxp = maxid;
-}
-
-/**
- * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function.
- * This function tries to find count unused XIDs for the given client. It
- * puts the IDs in the array pids and returns the number found, which should
- * almost always be the number requested.
- *
- * The circumstances that lead to a call to this function are very rare.
- * Xlib must run out of IDs while trying to generate a request that wants
- * multiple ID's, like the Multi-buffering CreateImageBuffers request.
- *
- * No rocket science in the implementation; just iterate over all
- * possible IDs for the given client and pick the first count IDs
- * that aren't in use. A more efficient algorithm could probably be
- * invented, but this will be used so rarely that this should suffice.
- */
-
-unsigned int
-GetXIDList(ClientPtr pClient, unsigned count, XID *pids)
-{
- unsigned int found = 0;
- XID rc, id = pClient->clientAsMask;
- XID maxid;
- pointer val;
-
- maxid = id | RESOURCE_ID_MASK;
- while ( (found < count) && (id <= maxid) )
- {
- rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
- DixGetAttrAccess);
- if (rc == BadValue)
- {
- pids[found++] = id;
- }
- id++;
- }
- return found;
-}
-
-/*
- * Return the next usable fake client ID.
- *
- * Normally this is just the next one in line, but if we've used the last
- * in the range, we need to find a new range of safe IDs to avoid
- * over-running another client.
- */
-
-XID
-FakeClientID(int client)
-{
- XID id, maxid;
-
- id = clientTable[client].fakeID++;
- if (id != clientTable[client].endFakeID)
- return id;
- GetXIDRange(client, TRUE, &id, &maxid);
- if (!id) {
- if (!client)
- FatalError("FakeClientID: server internal ids exhausted\n");
- MarkClientException(clients[client]);
- id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3);
- maxid = id | RESOURCE_ID_MASK;
- }
- clientTable[client].fakeID = id + 1;
- clientTable[client].endFakeID = maxid + 1;
- return id;
-}
-
-Bool
-AddResource(XID id, RESTYPE type, pointer value)
-{
- int client;
- ClientResourceRec *rrec;
- ResourcePtr res, *head;
-
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_ALLOC(id, type, value, TypeNameString(type));
-#endif
- client = CLIENT_ID(id);
- rrec = &clientTable[client];
- if (!rrec->buckets)
- {
- ErrorF("[dix] AddResource(%lx, %lx, %lx), client=%d \n",
- (unsigned long)id, type, (unsigned long)value, client);
- FatalError("client not in use\n");
- }
- if ((rrec->elements >= 4*rrec->buckets) &&
- (rrec->hashsize < MAXHASHSIZE))
- RebuildTable(client);
- head = &rrec->resources[Hash(client, id)];
- res = malloc(sizeof(ResourceRec));
- if (!res)
- {
- (*resourceTypes[type & TypeMask].deleteFunc)(value, id);
- return FALSE;
- }
- res->next = *head;
- res->id = id;
- res->type = type;
- res->value = value;
- *head = res;
- rrec->elements++;
- if (!(id & SERVER_BIT) && (id >= rrec->expectID))
- rrec->expectID = id + 1;
- CallResourceStateCallback(ResourceStateAdding, res);
- return TRUE;
-}
-
-static void
-RebuildTable(int client)
-{
- int j;
- ResourcePtr res, next;
- ResourcePtr **tails, *resources;
- ResourcePtr **tptr, *rptr;
-
- /*
- * For now, preserve insertion order, since some ddx layers depend
- * on resources being free in the opposite order they are added.
- */
-
- j = 2 * clientTable[client].buckets;
- tails = malloc(j * sizeof(ResourcePtr *));
- if (!tails)
- return;
- resources = malloc(j * sizeof(ResourcePtr));
- if (!resources)
- {
- free(tails);
- return;
- }
- for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++)
- {
- *rptr = NullResource;
- *tptr = rptr;
- }
- clientTable[client].hashsize++;
- for (j = clientTable[client].buckets,
- rptr = clientTable[client].resources;
- --j >= 0;
- rptr++)
- {
- for (res = *rptr; res; res = next)
- {
- next = res->next;
- res->next = NullResource;
- tptr = &tails[Hash(client, res->id)];
- **tptr = res;
- *tptr = &res->next;
- }
- }
- free(tails);
- clientTable[client].buckets *= 2;
- free(clientTable[client].resources);
- clientTable[client].resources = resources;
-}
-
-void
-FreeResource(XID id, RESTYPE skipDeleteFuncType)
-{
- int cid;
- ResourcePtr res;
- ResourcePtr *prev, *head;
- int *eltptr;
- int elements;
-
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
- {
- head = &clientTable[cid].resources[Hash(cid, id)];
- eltptr = &clientTable[cid].elements;
-
- prev = head;
- while ( (res = *prev) )
- {
- if (res->id == id)
- {
- RESTYPE rtype = res->type;
-
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_FREE(res->id, res->type,
- res->value, TypeNameString(res->type));
-#endif
- *prev = res->next;
- elements = --*eltptr;
-
- CallResourceStateCallback(ResourceStateFreeing, res);
-
- if (rtype != skipDeleteFuncType)
- (*resourceTypes[rtype & TypeMask].deleteFunc)(res->value, res->id);
- free(res);
- if (*eltptr != elements)
- prev = head; /* prev may no longer be valid */
- }
- else
- prev = &res->next;
- }
- }
-}
-
-
-void
-FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
-{
- int cid;
- ResourcePtr res;
- ResourcePtr *prev, *head;
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
- {
- head = &clientTable[cid].resources[Hash(cid, id)];
-
- prev = head;
- while ( (res = *prev) )
- {
- if (res->id == id && res->type == type)
- {
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_FREE(res->id, res->type,
- res->value, TypeNameString(res->type));
-#endif
- *prev = res->next;
- clientTable[cid].elements--;
-
- CallResourceStateCallback(ResourceStateFreeing, res);
-
- if (!skipFree)
- (*resourceTypes[type & TypeMask].deleteFunc)(res->value, res->id);
- free(res);
- break;
- }
- else
- prev = &res->next;
- }
- }
-}
-
-/*
- * Change the value associated with a resource id. Caller
- * is responsible for "doing the right thing" with the old
- * data
- */
-
-Bool
-ChangeResourceValue (XID id, RESTYPE rtype, pointer value)
-{
- int cid;
- ResourcePtr res;
-
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
- {
- res = clientTable[cid].resources[Hash(cid, id)];
-
- for (; res; res = res->next)
- if ((res->id == id) && (res->type == rtype))
- {
- res->value = value;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/* Note: if func adds or deletes resources, then func can get called
- * more than once for some resources. If func adds new resources,
- * func might or might not get called for them. func cannot both
- * add and delete an equal number of resources!
- */
-
-void
-FindClientResourcesByType(
- ClientPtr client,
- RESTYPE type,
- FindResType func,
- pointer cdata
-){
- ResourcePtr *resources;
- ResourcePtr this, next;
- int i, elements;
- int *eltptr;
-
- if (!client)
- client = serverClient;
-
- resources = clientTable[client->index].resources;
- eltptr = &clientTable[client->index].elements;
- for (i = 0; i < clientTable[client->index].buckets; i++)
- {
- for (this = resources[i]; this; this = next)
- {
- next = this->next;
- if (!type || this->type == type) {
- elements = *eltptr;
- (*func)(this->value, this->id, cdata);
- if (*eltptr != elements)
- next = resources[i]; /* start over */
- }
- }
- }
-}
-
-void
-FindAllClientResources(
- ClientPtr client,
- FindAllRes func,
- pointer cdata
-){
- ResourcePtr *resources;
- ResourcePtr this, next;
- int i, elements;
- int *eltptr;
-
- if (!client)
- client = serverClient;
-
- resources = clientTable[client->index].resources;
- eltptr = &clientTable[client->index].elements;
- for (i = 0; i < clientTable[client->index].buckets; i++)
- {
- for (this = resources[i]; this; this = next)
- {
- next = this->next;
- elements = *eltptr;
- (*func)(this->value, this->id, this->type, cdata);
- if (*eltptr != elements)
- next = resources[i]; /* start over */
- }
- }
-}
-
-
-pointer
-LookupClientResourceComplex(
- ClientPtr client,
- RESTYPE type,
- FindComplexResType func,
- pointer cdata
-){
- ResourcePtr *resources;
- ResourcePtr this, next;
- pointer value;
- int i;
-
- if (!client)
- client = serverClient;
-
- resources = clientTable[client->index].resources;
- for (i = 0; i < clientTable[client->index].buckets; i++) {
- for (this = resources[i]; this; this = next) {
- next = this->next;
- if (!type || this->type == type) {
- /* workaround func freeing the type as DRI1 does */
- value = this->value;
- if((*func)(value, this->id, cdata))
- return value;
- }
- }
- }
- return NULL;
-}
-
-
-void
-FreeClientNeverRetainResources(ClientPtr client)
-{
- ResourcePtr *resources;
- ResourcePtr this;
- ResourcePtr *prev;
- int j, elements;
- int *eltptr;
-
- if (!client)
- return;
-
- resources = clientTable[client->index].resources;
- eltptr = &clientTable[client->index].elements;
- for (j=0; j < clientTable[client->index].buckets; j++)
- {
- prev = &resources[j];
- while ( (this = *prev) )
- {
- RESTYPE rtype = this->type;
- if (rtype & RC_NEVERRETAIN)
- {
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_FREE(this->id, this->type,
- this->value, TypeNameString(this->type));
-#endif
- *prev = this->next;
- clientTable[client->index].elements--;
-
- CallResourceStateCallback(ResourceStateFreeing, this);
-
- elements = *eltptr;
- (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id);
- free(this);
- if (*eltptr != elements)
- prev = &resources[j]; /* prev may no longer be valid */
- }
- else
- prev = &this->next;
- }
- }
-}
-
-void
-FreeClientResources(ClientPtr client)
-{
- ResourcePtr *resources;
- ResourcePtr this;
- int j;
-
- /* This routine shouldn't be called with a null client, but just in
- case ... */
-
- if (!client)
- return;
-
- HandleSaveSet(client);
-
- resources = clientTable[client->index].resources;
- for (j=0; j < clientTable[client->index].buckets; j++)
- {
- /* It may seem silly to update the head of this resource list as
- we delete the members, since the entire list will be deleted any way,
- but there are some resource deletion functions "FreeClientPixels" for
- one which do a LookupID on another resource id (a Colormap id in this
- case), so the resource list must be kept valid up to the point that
- it is deleted, so every time we delete a resource, we must update the
- head, just like in FreeResource. I hope that this doesn't slow down
- mass deletion appreciably. PRH */
-
- ResourcePtr *head;
-
- head = &resources[j];
-
- for (this = *head; this; this = *head)
- {
- RESTYPE rtype = this->type;
-#ifdef XSERVER_DTRACE
- XSERVER_RESOURCE_FREE(this->id, this->type,
- this->value, TypeNameString(this->type));
-#endif
- *head = this->next;
- clientTable[client->index].elements--;
-
- CallResourceStateCallback(ResourceStateFreeing, this);
-
- (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id);
- free(this);
- }
- }
- free(clientTable[client->index].resources);
- clientTable[client->index].resources = NULL;
- clientTable[client->index].buckets = 0;
-}
-
-void
-FreeAllResources(void)
-{
- int i;
-
- for (i = currentMaxClients; --i >= 0; )
- {
- if (clientTable[i].buckets)
- FreeClientResources(clients[i]);
- }
-}
-
-Bool
-LegalNewID(XID id, ClientPtr client)
-{
- pointer val;
- int rc;
-
-#ifdef PANORAMIX
- XID minid, maxid;
-
- if (!noPanoramiXExtension) {
- minid = client->clientAsMask | (client->index ?
- SERVER_BIT : SERVER_MINID);
- maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1;
- if ((id >= minid) && (id <= maxid))
- return TRUE;
- }
-#endif /* PANORAMIX */
- if (client->clientAsMask == (id & ~RESOURCE_ID_MASK))
- {
- if (clientTable[client->index].expectID <= id)
- return TRUE;
-
- rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
- DixGetAttrAccess);
- return rc == BadValue;
- }
- return FALSE;
-}
-
-int
-dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype,
- ClientPtr client, Mask mode)
-{
- int cid = CLIENT_ID(id);
- ResourcePtr res = NULL;
-
- *result = NULL;
- if ((rtype & TypeMask) > lastResourceType)
- return BadImplementation;
-
- if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
-
- for (; res; res = res->next)
- if (res->id == id && res->type == rtype)
- break;
- }
- if (!res)
- return resourceTypes[rtype & TypeMask].errorValue;
-
- if (client) {
- client->errorValue = id;
- cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
- res->value, RT_NONE, NULL, mode);
- if (cid == BadValue)
- return resourceTypes[rtype & TypeMask].errorValue;
- if (cid != Success)
- return cid;
- }
-
- *result = res->value;
- return Success;
-}
-
-int
-dixLookupResourceByClass(pointer *result, XID id, RESTYPE rclass,
- ClientPtr client, Mask mode)
-{
- int cid = CLIENT_ID(id);
- ResourcePtr res = NULL;
-
- *result = NULL;
-
- if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
-
- for (; res; res = res->next)
- if (res->id == id && (res->type & rclass))
- break;
- }
- if (!res)
- return BadValue;
-
- if (client) {
- client->errorValue = id;
- cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
- res->value, RT_NONE, NULL, mode);
- if (cid != Success)
- return cid;
- }
-
- *result = res->value;
- return Success;
-}
+/************************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+/* The panoramix components contained the following notice */
+/*****************************************************************
+
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+/* XSERVER_DTRACE additions:
+ * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* Routines to manage various kinds of resources:
+ *
+ * CreateNewResourceType, CreateNewResourceClass, InitClientResources,
+ * FakeClientID, AddResource, FreeResource, FreeClientResources,
+ * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange
+ */
+
+/*
+ * A resource ID is a 32 bit quantity, the upper 2 bits of which are
+ * off-limits for client-visible resources. The next 8 bits are
+ * used as client ID, and the low 22 bits come from the client.
+ * A resource ID is "hashed" by extracting and xoring subfields
+ * (varying with the size of the hash table).
+ *
+ * It is sometimes necessary for the server to create an ID that looks
+ * like it belongs to a client. This ID, however, must not be one
+ * the client actually can create, or we have the potential for conflict.
+ * The 31st bit of the ID is reserved for the server's use for this
+ * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to
+ * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a
+ * resource "owned" by the client.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "misc.h"
+#include "os.h"
+#include "resource.h"
+#include "dixstruct.h"
+#include "opaque.h"
+#include "windowstr.h"
+#include "dixfont.h"
+#include "colormap.h"
+#include "inputstr.h"
+#include "dixevents.h"
+#include "dixgrabs.h"
+#include "cursor.h"
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+#include "xace.h"
+#include <assert.h>
+#include "registry.h"
+
+#ifdef XSERVER_DTRACE
+#include <sys/types.h>
+typedef const char *string;
+#include "Xserver-dtrace.h"
+
+#define TypeNameString(t) LookupResourceName(t)
+#endif
+
+static void RebuildTable(
+ int /*client*/
+);
+
+#define SERVER_MINID 32
+
+#define INITBUCKETS 64
+#define INITHASHSIZE 6
+#define MAXHASHSIZE 11
+
+typedef struct _Resource {
+ struct _Resource *next;
+ XID id;
+ RESTYPE type;
+ pointer value;
+} ResourceRec, *ResourcePtr;
+
+typedef struct _ClientResource {
+ ResourcePtr *resources;
+ int elements;
+ int buckets;
+ int hashsize; /* log(2)(buckets) */
+ XID fakeID;
+ XID endFakeID;
+} ClientResourceRec;
+
+RESTYPE lastResourceType;
+static RESTYPE lastResourceClass;
+RESTYPE TypeMask;
+
+struct ResourceType {
+ DeleteType deleteFunc;
+ int errorValue;
+};
+
+static struct ResourceType *resourceTypes;
+static const struct ResourceType predefTypes[] = {
+ [RT_NONE & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = (DeleteType)NoopDDA,
+ .errorValue = BadValue,
+ },
+ [RT_WINDOW & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = DeleteWindow,
+ .errorValue = BadWindow,
+ },
+ [RT_PIXMAP & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = dixDestroyPixmap,
+ .errorValue = BadPixmap,
+ },
+ [RT_GC & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = FreeGC,
+ .errorValue = BadGC,
+ },
+ [RT_FONT & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = CloseFont,
+ .errorValue = BadFont,
+ },
+ [RT_CURSOR & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = FreeCursor,
+ .errorValue = BadCursor,
+ },
+ [RT_COLORMAP & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = FreeColormap,
+ .errorValue = BadColor,
+ },
+ [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = FreeClientPixels,
+ .errorValue = BadColor,
+ },
+ [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = OtherClientGone,
+ .errorValue = BadValue,
+ },
+ [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = {
+ .deleteFunc = DeletePassiveGrab,
+ .errorValue = BadValue,
+ },
+};
+
+CallbackListPtr ResourceStateCallback;
+
+static _X_INLINE void
+CallResourceStateCallback(ResourceState state, ResourceRec *res)
+{
+ if (ResourceStateCallback) {
+ ResourceStateInfoRec rsi = { state, res->id, res->type, res->value };
+ CallCallbacks(&ResourceStateCallback, &rsi);
+ }
+}
+
+RESTYPE
+CreateNewResourceType(DeleteType deleteFunc, char *name)
+{
+ RESTYPE next = lastResourceType + 1;
+ struct ResourceType *types;
+
+ if (next & lastResourceClass)
+ return 0;
+ types = realloc(resourceTypes, (next + 1) * sizeof(*resourceTypes));
+ if (!types)
+ return 0;
+
+ lastResourceType = next;
+ resourceTypes = types;
+ resourceTypes[next].deleteFunc = deleteFunc;
+ resourceTypes[next].errorValue = BadValue;
+
+ /* Called even if name is NULL, to remove any previous entry */
+ RegisterResourceName(next, name);
+
+ return next;
+}
+
+void
+SetResourceTypeErrorValue(RESTYPE type, int errorValue)
+{
+ resourceTypes[type & TypeMask].errorValue = errorValue;
+}
+
+RESTYPE
+CreateNewResourceClass(void)
+{
+ RESTYPE next = lastResourceClass >> 1;
+
+ if (next & lastResourceType)
+ return 0;
+ lastResourceClass = next;
+ TypeMask = next - 1;
+ return next;
+}
+
+static ClientResourceRec clientTable[MAXCLIENTS];
+
+/*****************
+ * InitClientResources
+ * When a new client is created, call this to allocate space
+ * in resource table
+ *****************/
+
+Bool
+InitClientResources(ClientPtr client)
+{
+ int i, j;
+
+ if (client == serverClient)
+ {
+ lastResourceType = RT_LASTPREDEF;
+ lastResourceClass = RC_LASTPREDEF;
+ TypeMask = RC_LASTPREDEF - 1;
+ free(resourceTypes);
+ resourceTypes = malloc(sizeof(predefTypes));
+ if (!resourceTypes)
+ return FALSE;
+ memcpy(resourceTypes, predefTypes, sizeof(predefTypes));
+ }
+ clientTable[i = client->index].resources =
+ malloc(INITBUCKETS*sizeof(ResourcePtr));
+ if (!clientTable[i].resources)
+ return FALSE;
+ clientTable[i].buckets = INITBUCKETS;
+ clientTable[i].elements = 0;
+ clientTable[i].hashsize = INITHASHSIZE;
+ /* Many IDs allocated from the server client are visible to clients,
+ * so we don't use the SERVER_BIT for them, but we have to start
+ * past the magic value constants used in the protocol. For normal
+ * clients, we can start from zero, with SERVER_BIT set.
+ */
+ clientTable[i].fakeID = client->clientAsMask |
+ (client->index ? SERVER_BIT : SERVER_MINID);
+ clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1;
+ for (j=0; j<INITBUCKETS; j++)
+ {
+ clientTable[i].resources[j] = NULL;
+ }
+ return TRUE;
+}
+
+
+static int
+Hash(int client, XID id)
+{
+ id &= RESOURCE_ID_MASK;
+ switch (clientTable[client].hashsize)
+ {
+ case 6:
+ return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12))));
+ case 7:
+ return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13))));
+ case 8:
+ return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16))));
+ case 9:
+ return ((int)(0x1FF & (id ^ (id>>9))));
+ case 10:
+ return ((int)(0x3FF & (id ^ (id>>10))));
+ case 11:
+ return ((int)(0x7FF & (id ^ (id>>11))));
+ }
+ return -1;
+}
+
+static XID
+AvailableID(
+ int client,
+ XID id,
+ XID maxid,
+ XID goodid)
+{
+ ResourcePtr res;
+
+ if ((goodid >= id) && (goodid <= maxid))
+ return goodid;
+ for (; id <= maxid; id++)
+ {
+ res = clientTable[client].resources[Hash(client, id)];
+ while (res && (res->id != id))
+ res = res->next;
+ if (!res)
+ return id;
+ }
+ return 0;
+}
+
+void
+GetXIDRange(int client, Bool server, XID *minp, XID *maxp)
+{
+ XID id, maxid;
+ ResourcePtr *resp;
+ ResourcePtr res;
+ int i;
+ XID goodid;
+
+ id = (Mask)client << CLIENTOFFSET;
+ if (server)
+ id |= client ? SERVER_BIT : SERVER_MINID;
+ maxid = id | RESOURCE_ID_MASK;
+ goodid = 0;
+ for (resp = clientTable[client].resources, i = clientTable[client].buckets;
+ --i >= 0;)
+ {
+ for (res = *resp++; res; res = res->next)
+ {
+ if ((res->id < id) || (res->id > maxid))
+ continue;
+ if (((res->id - id) >= (maxid - res->id)) ?
+ (goodid = AvailableID(client, id, res->id - 1, goodid)) :
+ !(goodid = AvailableID(client, res->id + 1, maxid, goodid)))
+ maxid = res->id - 1;
+ else
+ id = res->id + 1;
+ }
+ }
+ if (id > maxid)
+ id = maxid = 0;
+ *minp = id;
+ *maxp = maxid;
+}
+
+/**
+ * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function.
+ * This function tries to find count unused XIDs for the given client. It
+ * puts the IDs in the array pids and returns the number found, which should
+ * almost always be the number requested.
+ *
+ * The circumstances that lead to a call to this function are very rare.
+ * Xlib must run out of IDs while trying to generate a request that wants
+ * multiple ID's, like the Multi-buffering CreateImageBuffers request.
+ *
+ * No rocket science in the implementation; just iterate over all
+ * possible IDs for the given client and pick the first count IDs
+ * that aren't in use. A more efficient algorithm could probably be
+ * invented, but this will be used so rarely that this should suffice.
+ */
+
+unsigned int
+GetXIDList(ClientPtr pClient, unsigned count, XID *pids)
+{
+ unsigned int found = 0;
+ XID rc, id = pClient->clientAsMask;
+ XID maxid;
+ pointer val;
+
+ maxid = id | RESOURCE_ID_MASK;
+ while ( (found < count) && (id <= maxid) )
+ {
+ rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
+ DixGetAttrAccess);
+ if (rc == BadValue)
+ {
+ pids[found++] = id;
+ }
+ id++;
+ }
+ return found;
+}
+
+/*
+ * Return the next usable fake client ID.
+ *
+ * Normally this is just the next one in line, but if we've used the last
+ * in the range, we need to find a new range of safe IDs to avoid
+ * over-running another client.
+ */
+
+XID
+FakeClientID(int client)
+{
+ XID id, maxid;
+
+ id = clientTable[client].fakeID++;
+ if (id != clientTable[client].endFakeID)
+ return id;
+ GetXIDRange(client, TRUE, &id, &maxid);
+ if (!id) {
+ if (!client)
+ FatalError("FakeClientID: server internal ids exhausted\n");
+ MarkClientException(clients[client]);
+ id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3);
+ maxid = id | RESOURCE_ID_MASK;
+ }
+ clientTable[client].fakeID = id + 1;
+ clientTable[client].endFakeID = maxid + 1;
+ return id;
+}
+
+Bool
+AddResource(XID id, RESTYPE type, pointer value)
+{
+ int client;
+ ClientResourceRec *rrec;
+ ResourcePtr res, *head;
+
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_ALLOC(id, type, value, TypeNameString(type));
+#endif
+ client = CLIENT_ID(id);
+ rrec = &clientTable[client];
+ if (!rrec->buckets)
+ {
+ ErrorF("[dix] AddResource(%lx, %lx, %lx), client=%d \n",
+ (unsigned long)id, type, (unsigned long)value, client);
+ FatalError("client not in use\n");
+ }
+ if ((rrec->elements >= 4*rrec->buckets) &&
+ (rrec->hashsize < MAXHASHSIZE))
+ RebuildTable(client);
+ head = &rrec->resources[Hash(client, id)];
+ res = malloc(sizeof(ResourceRec));
+ if (!res)
+ {
+ (*resourceTypes[type & TypeMask].deleteFunc)(value, id);
+ return FALSE;
+ }
+ res->next = *head;
+ res->id = id;
+ res->type = type;
+ res->value = value;
+ *head = res;
+ rrec->elements++;
+ CallResourceStateCallback(ResourceStateAdding, res);
+ return TRUE;
+}
+
+static void
+RebuildTable(int client)
+{
+ int j;
+ ResourcePtr res, next;
+ ResourcePtr **tails, *resources;
+ ResourcePtr **tptr, *rptr;
+
+ /*
+ * For now, preserve insertion order, since some ddx layers depend
+ * on resources being free in the opposite order they are added.
+ */
+
+ j = 2 * clientTable[client].buckets;
+ tails = malloc(j * sizeof(ResourcePtr *));
+ if (!tails)
+ return;
+ resources = malloc(j * sizeof(ResourcePtr));
+ if (!resources)
+ {
+ free(tails);
+ return;
+ }
+ for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++)
+ {
+ *rptr = NULL;
+ *tptr = rptr;
+ }
+ clientTable[client].hashsize++;
+ for (j = clientTable[client].buckets,
+ rptr = clientTable[client].resources;
+ --j >= 0;
+ rptr++)
+ {
+ for (res = *rptr; res; res = next)
+ {
+ next = res->next;
+ res->next = NULL;
+ tptr = &tails[Hash(client, res->id)];
+ **tptr = res;
+ *tptr = &res->next;
+ }
+ }
+ free(tails);
+ clientTable[client].buckets *= 2;
+ free(clientTable[client].resources);
+ clientTable[client].resources = resources;
+}
+
+void
+FreeResource(XID id, RESTYPE skipDeleteFuncType)
+{
+ int cid;
+ ResourcePtr res;
+ ResourcePtr *prev, *head;
+ int *eltptr;
+ int elements;
+
+ if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
+ {
+ head = &clientTable[cid].resources[Hash(cid, id)];
+ eltptr = &clientTable[cid].elements;
+
+ prev = head;
+ while ( (res = *prev) )
+ {
+ if (res->id == id)
+ {
+ RESTYPE rtype = res->type;
+
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_FREE(res->id, res->type,
+ res->value, TypeNameString(res->type));
+#endif
+ *prev = res->next;
+ elements = --*eltptr;
+
+ CallResourceStateCallback(ResourceStateFreeing, res);
+
+ if (rtype != skipDeleteFuncType)
+ (*resourceTypes[rtype & TypeMask].deleteFunc)(res->value, res->id);
+ free(res);
+ if (*eltptr != elements)
+ prev = head; /* prev may no longer be valid */
+ }
+ else
+ prev = &res->next;
+ }
+ }
+}
+
+
+void
+FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
+{
+ int cid;
+ ResourcePtr res;
+ ResourcePtr *prev, *head;
+ if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
+ {
+ head = &clientTable[cid].resources[Hash(cid, id)];
+
+ prev = head;
+ while ( (res = *prev) )
+ {
+ if (res->id == id && res->type == type)
+ {
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_FREE(res->id, res->type,
+ res->value, TypeNameString(res->type));
+#endif
+ *prev = res->next;
+ clientTable[cid].elements--;
+
+ CallResourceStateCallback(ResourceStateFreeing, res);
+
+ if (!skipFree)
+ (*resourceTypes[type & TypeMask].deleteFunc)(res->value, res->id);
+ free(res);
+ break;
+ }
+ else
+ prev = &res->next;
+ }
+ }
+}
+
+/*
+ * Change the value associated with a resource id. Caller
+ * is responsible for "doing the right thing" with the old
+ * data
+ */
+
+Bool
+ChangeResourceValue (XID id, RESTYPE rtype, pointer value)
+{
+ int cid;
+ ResourcePtr res;
+
+ if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
+ {
+ res = clientTable[cid].resources[Hash(cid, id)];
+
+ for (; res; res = res->next)
+ if ((res->id == id) && (res->type == rtype))
+ {
+ res->value = value;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* Note: if func adds or deletes resources, then func can get called
+ * more than once for some resources. If func adds new resources,
+ * func might or might not get called for them. func cannot both
+ * add and delete an equal number of resources!
+ */
+
+void
+FindClientResourcesByType(
+ ClientPtr client,
+ RESTYPE type,
+ FindResType func,
+ pointer cdata
+){
+ ResourcePtr *resources;
+ ResourcePtr this, next;
+ int i, elements;
+ int *eltptr;
+
+ if (!client)
+ client = serverClient;
+
+ resources = clientTable[client->index].resources;
+ eltptr = &clientTable[client->index].elements;
+ for (i = 0; i < clientTable[client->index].buckets; i++)
+ {
+ for (this = resources[i]; this; this = next)
+ {
+ next = this->next;
+ if (!type || this->type == type) {
+ elements = *eltptr;
+ (*func)(this->value, this->id, cdata);
+ if (*eltptr != elements)
+ next = resources[i]; /* start over */
+ }
+ }
+ }
+}
+
+void
+FindAllClientResources(
+ ClientPtr client,
+ FindAllRes func,
+ pointer cdata
+){
+ ResourcePtr *resources;
+ ResourcePtr this, next;
+ int i, elements;
+ int *eltptr;
+
+ if (!client)
+ client = serverClient;
+
+ resources = clientTable[client->index].resources;
+ eltptr = &clientTable[client->index].elements;
+ for (i = 0; i < clientTable[client->index].buckets; i++)
+ {
+ for (this = resources[i]; this; this = next)
+ {
+ next = this->next;
+ elements = *eltptr;
+ (*func)(this->value, this->id, this->type, cdata);
+ if (*eltptr != elements)
+ next = resources[i]; /* start over */
+ }
+ }
+}
+
+
+pointer
+LookupClientResourceComplex(
+ ClientPtr client,
+ RESTYPE type,
+ FindComplexResType func,
+ pointer cdata
+){
+ ResourcePtr *resources;
+ ResourcePtr this, next;
+ pointer value;
+ int i;
+
+ if (!client)
+ client = serverClient;
+
+ resources = clientTable[client->index].resources;
+ for (i = 0; i < clientTable[client->index].buckets; i++) {
+ for (this = resources[i]; this; this = next) {
+ next = this->next;
+ if (!type || this->type == type) {
+ /* workaround func freeing the type as DRI1 does */
+ value = this->value;
+ if((*func)(value, this->id, cdata))
+ return value;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+void
+FreeClientNeverRetainResources(ClientPtr client)
+{
+ ResourcePtr *resources;
+ ResourcePtr this;
+ ResourcePtr *prev;
+ int j, elements;
+ int *eltptr;
+
+ if (!client)
+ return;
+
+ resources = clientTable[client->index].resources;
+ eltptr = &clientTable[client->index].elements;
+ for (j=0; j < clientTable[client->index].buckets; j++)
+ {
+ prev = &resources[j];
+ while ( (this = *prev) )
+ {
+ RESTYPE rtype = this->type;
+ if (rtype & RC_NEVERRETAIN)
+ {
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_FREE(this->id, this->type,
+ this->value, TypeNameString(this->type));
+#endif
+ *prev = this->next;
+ clientTable[client->index].elements--;
+
+ CallResourceStateCallback(ResourceStateFreeing, this);
+
+ elements = *eltptr;
+ (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id);
+ free(this);
+ if (*eltptr != elements)
+ prev = &resources[j]; /* prev may no longer be valid */
+ }
+ else
+ prev = &this->next;
+ }
+ }
+}
+
+void
+FreeClientResources(ClientPtr client)
+{
+ ResourcePtr *resources;
+ ResourcePtr this;
+ int j;
+
+ /* This routine shouldn't be called with a null client, but just in
+ case ... */
+
+ if (!client)
+ return;
+
+ HandleSaveSet(client);
+
+ resources = clientTable[client->index].resources;
+ for (j=0; j < clientTable[client->index].buckets; j++)
+ {
+ /* It may seem silly to update the head of this resource list as
+ we delete the members, since the entire list will be deleted any way,
+ but there are some resource deletion functions "FreeClientPixels" for
+ one which do a LookupID on another resource id (a Colormap id in this
+ case), so the resource list must be kept valid up to the point that
+ it is deleted, so every time we delete a resource, we must update the
+ head, just like in FreeResource. I hope that this doesn't slow down
+ mass deletion appreciably. PRH */
+
+ ResourcePtr *head;
+
+ head = &resources[j];
+
+ for (this = *head; this; this = *head)
+ {
+ RESTYPE rtype = this->type;
+#ifdef XSERVER_DTRACE
+ XSERVER_RESOURCE_FREE(this->id, this->type,
+ this->value, TypeNameString(this->type));
+#endif
+ *head = this->next;
+ clientTable[client->index].elements--;
+
+ CallResourceStateCallback(ResourceStateFreeing, this);
+
+ (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id);
+ free(this);
+ }
+ }
+ free(clientTable[client->index].resources);
+ clientTable[client->index].resources = NULL;
+ clientTable[client->index].buckets = 0;
+}
+
+void
+FreeAllResources(void)
+{
+ int i;
+
+ for (i = currentMaxClients; --i >= 0; )
+ {
+ if (clientTable[i].buckets)
+ FreeClientResources(clients[i]);
+ }
+}
+
+Bool
+LegalNewID(XID id, ClientPtr client)
+{
+ pointer val;
+ int rc;
+
+#ifdef PANORAMIX
+ XID minid, maxid;
+
+ if (!noPanoramiXExtension) {
+ minid = client->clientAsMask | (client->index ?
+ SERVER_BIT : SERVER_MINID);
+ maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1;
+ if ((id >= minid) && (id <= maxid))
+ return TRUE;
+ }
+#endif /* PANORAMIX */
+ if (client->clientAsMask == (id & ~RESOURCE_ID_MASK))
+ {
+ rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient,
+ DixGetAttrAccess);
+ return rc == BadValue;
+ }
+ return FALSE;
+}
+
+int
+dixLookupResourceByType(pointer *result, XID id, RESTYPE rtype,
+ ClientPtr client, Mask mode)
+{
+ int cid = CLIENT_ID(id);
+ ResourcePtr res = NULL;
+
+ *result = NULL;
+ if ((rtype & TypeMask) > lastResourceType)
+ return BadImplementation;
+
+ if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
+ res = clientTable[cid].resources[Hash(cid, id)];
+
+ for (; res; res = res->next)
+ if (res->id == id && res->type == rtype)
+ break;
+ }
+ if (!res)
+ return resourceTypes[rtype & TypeMask].errorValue;
+
+ if (client) {
+ client->errorValue = id;
+ cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
+ res->value, RT_NONE, NULL, mode);
+ if (cid == BadValue)
+ return resourceTypes[rtype & TypeMask].errorValue;
+ if (cid != Success)
+ return cid;
+ }
+
+ *result = res->value;
+ return Success;
+}
+
+int
+dixLookupResourceByClass(pointer *result, XID id, RESTYPE rclass,
+ ClientPtr client, Mask mode)
+{
+ int cid = CLIENT_ID(id);
+ ResourcePtr res = NULL;
+
+ *result = NULL;
+
+ if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
+ res = clientTable[cid].resources[Hash(cid, id)];
+
+ for (; res; res = res->next)
+ if (res->id == id && (res->type & rclass))
+ break;
+ }
+ if (!res)
+ return BadValue;
+
+ if (client) {
+ client->errorValue = id;
+ cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type,
+ res->value, RT_NONE, NULL, mode);
+ if (cid != Success)
+ return cid;
+ }
+
+ *result = res->value;
+ return Success;
+}
diff --git a/xorg-server/hw/dmx/config/xdmxconfig.c b/xorg-server/hw/dmx/config/xdmxconfig.c
index 033b52512..c67077aec 100644
--- a/xorg-server/hw/dmx/config/xdmxconfig.c
+++ b/xorg-server/hw/dmx/config/xdmxconfig.c
@@ -142,7 +142,7 @@ static void dmxConfigGetDims(int *maxWidth, int *maxHeight)
DMXConfigEntryPtr e;
*maxWidth = dmxConfigWallWidth = 0;
- *maxWidth = dmxConfigWallHeight = 0;
+ *maxHeight = dmxConfigWallHeight = 0;
if (!dmxConfigCurrent) return;
dmxConfigWallWidth = dmxConfigCurrent->width;
diff --git a/xorg-server/hw/dmx/dmxextension.c b/xorg-server/hw/dmx/dmxextension.c
index 97f2a04b0..bd326ce2a 100644
--- a/xorg-server/hw/dmx/dmxextension.c
+++ b/xorg-server/hw/dmx/dmxextension.c
@@ -1,1618 +1,1620 @@
-/*
- * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation on the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
- * Author:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- * Kevin E. Martin <kem@redhat.com>
- *
- */
-
-/** \file
- * This file provides the only interface to the X server extension support
- * in programs/Xserver/Xext. Those programs should only include dmxext.h
- */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include <stdlib.h>
-
-#include "dmx.h"
-#include "dmxinit.h"
-#include "dmxextension.h"
-#include "dmxwindow.h"
-#include "dmxcb.h"
-#include "dmxcursor.h"
-#include "dmxpixmap.h"
-#include "dmxgc.h"
-#include "dmxfont.h"
-#include "dmxcmap.h"
-#include "dmxpict.h"
-#include "dmxinput.h"
-#include "dmxsync.h"
-#include "dmxscrinit.h"
-#include "input/dmxinputinit.h"
-
-#include "windowstr.h"
-#include "inputstr.h" /* For DeviceIntRec */
-#include <X11/extensions/dmxproto.h> /* For DMX_BAD_* */
-#include "cursorstr.h"
-
-/* The default font is declared in dix/globals.c, but is not included in
- * _any_ header files. */
-extern FontPtr defaultFont;
-
-/** This routine provides information to the DMX protocol extension
- * about a particular screen. */
-Bool dmxGetScreenAttributes(int physical, DMXScreenAttributesPtr attr)
-{
- DMXScreenInfo *dmxScreen;
-
- if (physical < 0 || physical >= dmxNumScreens) return FALSE;
-
- dmxScreen = &dmxScreens[physical];
- attr->displayName = dmxScreen->name;
-#ifdef PANORAMIX
- attr->logicalScreen = noPanoramiXExtension ? dmxScreen->index : 0;
-#else
- attr->logicalScreen = dmxScreen->index;
-#endif
-
- attr->screenWindowWidth = dmxScreen->scrnWidth;
- attr->screenWindowHeight = dmxScreen->scrnHeight;
- attr->screenWindowXoffset = dmxScreen->scrnX;
- attr->screenWindowYoffset = dmxScreen->scrnY;
-
- attr->rootWindowWidth = dmxScreen->rootWidth;
- attr->rootWindowHeight = dmxScreen->rootHeight;
- attr->rootWindowXoffset = dmxScreen->rootX;
- attr->rootWindowYoffset = dmxScreen->rootY;
-
- attr->rootWindowXorigin = dmxScreen->rootXOrigin;
- attr->rootWindowYorigin = dmxScreen->rootYOrigin;
-
- return TRUE;
-}
-
-/** This routine provides information to the DMX protocol extension
- * about a particular window. */
-Bool dmxGetWindowAttributes(WindowPtr pWindow, DMXWindowAttributesPtr attr)
-{
- dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
-
- attr->screen = pWindow->drawable.pScreen->myNum;
- attr->window = pWinPriv->window;
-
- attr->pos.x = pWindow->drawable.x;
- attr->pos.y = pWindow->drawable.y;
- attr->pos.width = pWindow->drawable.width;
- attr->pos.height = pWindow->drawable.height;
-
- if (!pWinPriv->window || pWinPriv->offscreen) {
- attr->vis.x = 0;
- attr->vis.y = 0;
- attr->vis.height = 0;
- attr->vis.width = 0;
- return pWinPriv->window ? TRUE : FALSE;
- }
-
- /* Compute display-relative coordinates */
- attr->vis.x = pWindow->drawable.x;
- attr->vis.y = pWindow->drawable.y;
- attr->vis.width = pWindow->drawable.width;
- attr->vis.height = pWindow->drawable.height;
-
- if (attr->pos.x < 0) {
- attr->vis.x -= attr->pos.x;
- attr->vis.width = attr->pos.x + attr->pos.width - attr->vis.x;
- }
- if (attr->pos.x + attr->pos.width > pWindow->drawable.pScreen->width) {
- if (attr->pos.x < 0)
- attr->vis.width = pWindow->drawable.pScreen->width;
- else
- attr->vis.width = pWindow->drawable.pScreen->width - attr->pos.x;
- }
- if (attr->pos.y < 0) {
- attr->vis.y -= attr->pos.y;
- attr->vis.height = attr->pos.y + attr->pos.height - attr->vis.y;
- }
- if (attr->pos.y + attr->pos.height > pWindow->drawable.pScreen->height) {
- if (attr->pos.y < 0)
- attr->vis.height = pWindow->drawable.pScreen->height;
- else
- attr->vis.height = pWindow->drawable.pScreen->height - attr->pos.y;
- }
-
- /* Convert to window-relative coordinates */
- attr->vis.x -= attr->pos.x;
- attr->vis.y -= attr->pos.y;
-
- return TRUE;
-}
-
-void dmxGetDesktopAttributes(DMXDesktopAttributesPtr attr)
-{
- attr->width = dmxGlobalWidth;
- attr->height = dmxGlobalHeight;
- attr->shiftX = 0; /* NOTE: The upper left hand corner of */
- attr->shiftY = 0; /* the desktop is always <0,0>. */
-}
-
-/** Return the total number of devices, not just #dmxNumInputs. The
- * number returned should be the same as that returned by
- * XListInputDevices. */
-int dmxGetInputCount(void)
-{
- int i, total;
-
- for (total = i = 0; i < dmxNumInputs; i++) total += dmxInputs[i].numDevs;
- return total;
-}
-
-/** Return information about the device with id = \a deviceId. This
- * information is primarily for the #ProcDMXGetInputAttributes()
- * function, which does not have access to the appropriate data
- * structure. */
-int dmxGetInputAttributes(int deviceId, DMXInputAttributesPtr attr)
-{
- int i, j;
- DMXInputInfo *dmxInput;
-
- if (deviceId < 0) return -1;
- for (i = 0; i < dmxNumInputs; i++) {
- dmxInput = &dmxInputs[i];
- for (j = 0; j < dmxInput->numDevs; j++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
- if (deviceId != dmxLocal->pDevice->id) continue;
- attr->isCore = !!dmxLocal->isCore;
- attr->sendsCore = !!dmxLocal->sendsCore;
- attr->detached = !!dmxInput->detached;
- attr->physicalScreen = -1;
- attr->physicalId = -1;
- attr->name = NULL;
- switch (dmxLocal->extType) {
- case DMX_LOCAL_TYPE_LOCAL:
- attr->inputType = 0;
- break;
- case DMX_LOCAL_TYPE_CONSOLE:
- attr->inputType = 1;
- attr->name = dmxInput->name;
- attr->physicalId = dmxLocal->deviceId;
- break;
- case DMX_LOCAL_TYPE_BACKEND:
- case DMX_LOCAL_TYPE_COMMON:
- attr->inputType = 2;
- attr->physicalScreen = dmxInput->scrnIdx;
- attr->name = dmxInput->name;
- attr->physicalId = dmxLocal->deviceId;
- break;
- }
- return 0; /* Success */
- }
- }
- return -1; /* Failure */
-}
-
-/** Reinitialized the cursor boundaries. */
-static void dmxAdjustCursorBoundaries(void)
-{
- int i;
-
- dmxReInitOrigins();
- dmxInitOverlap();
- dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
- dmxConnectionBlockCallback();
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- if (!dmxInput->detached) dmxInputReInit(dmxInput);
- }
-
- dmxCheckCursor();
-
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- if (!dmxInput->detached) dmxInputLateReInit(dmxInput);
- }
-}
-
-/** Add an input with the specified attributes. If the input is added,
- * the physical id is returned in \a deviceId. */
-int dmxAddInput(DMXInputAttributesPtr attr, int *id)
-{
- int retcode = BadValue;
-
- if (attr->inputType == 1) /* console */
- retcode = dmxInputAttachConsole(attr->name, attr->sendsCore, id);
- else if (attr->inputType == 2) /* backend */
- retcode = dmxInputAttachBackend(attr->physicalScreen,
- attr->sendsCore,id);
-
- if (retcode == Success) {
- /* Adjust the cursor boundaries */
- dmxAdjustCursorBoundaries();
-
- /* Force completion of the changes */
- dmxSync(NULL, TRUE);
- }
-
- return retcode;
-}
-
-/** Remove the input with physical id \a id. */
-int dmxRemoveInput(int id)
-{
- return dmxInputDetachId(id);
-}
-
-/** Return the value of #dmxNumScreens -- the total number of backend
- * screens in use (these are logical screens and may be larger than the
- * number of backend displays). */
-unsigned long dmxGetNumScreens(void)
-{
- return dmxNumScreens;
-}
-
-/** Make sure that #dmxCreateAndRealizeWindow has been called for \a
- * pWindow. */
-void dmxForceWindowCreation(WindowPtr pWindow)
-{
- dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
- if (!pWinPriv->window) dmxCreateAndRealizeWindow(pWindow, TRUE);
-}
-
-/** Flush pending syncs for all screens. */
-void dmxFlushPendingSyncs(void)
-{
- dmxSync(NULL, TRUE);
-}
-
-/** Update DMX's screen resources to match those of the newly moved
- * and/or resized "root" window. */
-void dmxUpdateScreenResources(ScreenPtr pScreen, int x, int y, int w, int h)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- WindowPtr pRoot = pScreen->root;
- WindowPtr pChild;
- Bool anyMarked = FALSE;
-
- /* Handle special case where width and/or height are zero */
- if (w == 0 || h == 0) {
- w = 1;
- h = 1;
- }
-
- /* Change screen size */
- pScreen->width = w;
- pScreen->height = h;
-
- /* Reset the root window's drawable's size */
- pRoot->drawable.width = w;
- pRoot->drawable.height = h;
-
- /* Set the root window's new winSize and borderSize */
- pRoot->winSize.extents.x1 = 0;
- pRoot->winSize.extents.y1 = 0;
- pRoot->winSize.extents.x2 = w;
- pRoot->winSize.extents.y2 = h;
-
- pRoot->borderSize.extents.x1 = 0;
- pRoot->borderSize.extents.y1 = 0;
- pRoot->borderSize.extents.x2 = w;
- pRoot->borderSize.extents.y2 = h;
-
- /* Recompute this screen's mmWidth & mmHeight */
- pScreen->mmWidth =
- (w * 254 + dmxScreen->beXDPI * 5) / (dmxScreen->beXDPI * 10);
- pScreen->mmHeight =
- (h * 254 + dmxScreen->beYDPI * 5) / (dmxScreen->beYDPI * 10);
-
- /* Recompute this screen's window's clip rects as follows: */
- /* 1. Mark all of root's children's windows */
- for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
- anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
- (WindowPtr *)NULL);
-
- /* 2. Set the root window's borderClip */
- pRoot->borderClip.extents.x1 = 0;
- pRoot->borderClip.extents.y1 = 0;
- pRoot->borderClip.extents.x2 = w;
- pRoot->borderClip.extents.y2 = h;
-
- /* 3. Set the root window's clipList */
- if (anyMarked) {
- /* If any windows have been marked, set the root window's
- * clipList to be broken since it will be recalculated in
- * ValidateTree()
- */
- RegionBreak(&pRoot->clipList);
- } else {
- /* Otherwise, we just set it directly since there are no
- * windows visible on this screen
- */
- pRoot->clipList.extents.x1 = 0;
- pRoot->clipList.extents.y1 = 0;
- pRoot->clipList.extents.x2 = w;
- pRoot->clipList.extents.y2 = h;
- }
-
- /* 4. Revalidate all clip rects and generate expose events */
- if (anyMarked) {
- pScreen->ValidateTree(pRoot, NULL, VTBroken);
- pScreen->HandleExposures(pRoot);
- if (pScreen->PostValidateTree)
- pScreen->PostValidateTree(pRoot, NULL, VTBroken);
- }
-}
-
-#ifdef PANORAMIX
-#include "panoramiXsrv.h"
-
-/** Change the "screen" window attributes by resizing the actual window
- * on the back-end display (if necessary). */
-static void dmxConfigureScreenWindow(int idx,
- int x, int y, int w, int h)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- ScreenPtr pScreen = screenInfo.screens[idx];
-
- /* Resize "screen" window */
- if (dmxScreen->scrnX != x ||
- dmxScreen->scrnY != y ||
- dmxScreen->scrnWidth != w ||
- dmxScreen->scrnHeight != h) {
- dmxResizeScreenWindow(pScreen, x, y, w, h);
- }
-
- /* Change "screen" window values */
- dmxScreen->scrnX = x;
- dmxScreen->scrnY = y;
- dmxScreen->scrnWidth = w;
- dmxScreen->scrnHeight = h;
-}
-
-/** Change the "root" window position and size by resizing the actual
- * window on the back-end display (if necessary) and updating all of
- * DMX's resources by calling #dmxUpdateScreenResources. */
-static void dmxConfigureRootWindow(int idx, int x, int y, int w, int h)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- WindowPtr pRoot = screenInfo.screens[idx]->root;
-
- /* NOTE: Either this function or the ones that it calls must handle
- * the case where w == 0 || h == 0. Currently, the functions that
- * this one calls handle that case. */
-
- /* 1. Resize "root" window */
- if (dmxScreen->rootX != x ||
- dmxScreen->rootY != y ||
- dmxScreen->rootWidth != w ||
- dmxScreen->rootHeight != h) {
- dmxResizeRootWindow(pRoot, x, y, w, h);
- }
-
- /* 2. Update all of the screen's resources associated with this root
- * window */
- if (dmxScreen->rootWidth != w ||
- dmxScreen->rootHeight != h) {
- dmxUpdateScreenResources(screenInfo.screens[idx], x, y, w, h);
- }
-
- /* Change "root" window values */
- dmxScreen->rootX = x;
- dmxScreen->rootY = y;
- dmxScreen->rootWidth = w;
- dmxScreen->rootHeight = h;
-}
-
-/** Change the "root" window's origin by updating DMX's internal data
- * structures (dix and Xinerama) to use the new origin and adjust the
- * positions of windows that overlap this "root" window. */
-static void dmxSetRootWindowOrigin(int idx, int x, int y)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- ScreenPtr pScreen = screenInfo.screens[idx];
- WindowPtr pRoot = pScreen->root;
- WindowPtr pChild;
- int xoff;
- int yoff;
-
- /* Change "root" window's origin */
- dmxScreen->rootXOrigin = x;
- dmxScreen->rootYOrigin = y;
-
- /* Compute offsets here in case <x,y> has been changed above */
- xoff = x - pScreen->x;
- yoff = y - pScreen->y;
-
- /* Adjust the root window's position */
- pScreen->x = dmxScreen->rootXOrigin;
- pScreen->y = dmxScreen->rootYOrigin;
-
- /* Recalculate the Xinerama regions and data structs */
- XineramaReinitData(pScreen);
-
- /* Adjust each of the root window's children */
- if (!idx) ReinitializeRootWindow(screenInfo.screens[0]->root, xoff, yoff);
- pChild = pRoot->firstChild;
- while (pChild) {
- /* Adjust child window's position */
- pScreen->MoveWindow(pChild,
- pChild->origin.x - wBorderWidth(pChild) - xoff,
- pChild->origin.y - wBorderWidth(pChild) - yoff,
- pChild->nextSib,
- VTMove);
-
- /* Note that the call to MoveWindow will eventually call
- * dmxPositionWindow which will automatically create a
- * window if it is now exposed on screen (for lazy window
- * creation optimization) and it will properly set the
- * offscreen flag.
- */
-
- pChild = pChild->nextSib;
- }
-}
-
-/** Configure the attributes of each "screen" and "root" window. */
-int dmxConfigureScreenWindows(int nscreens,
- CARD32 *screens,
- DMXScreenAttributesPtr attribs,
- int *errorScreen)
-{
- int i;
-
- for (i = 0; i < nscreens; i++) {
- DMXScreenAttributesPtr attr = &attribs[i];
- int idx = screens[i];
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-
- if (errorScreen) *errorScreen = i;
-
- if (!dmxScreen->beDisplay) return DMX_BAD_VALUE;
-
- /* Check for illegal values */
- if (idx < 0 || idx >= dmxNumScreens) return BadValue;
-
- /* The "screen" and "root" windows must have valid sizes */
- if (attr->screenWindowWidth <= 0 || attr->screenWindowHeight <= 0 ||
- attr->rootWindowWidth < 0 || attr->rootWindowHeight < 0)
- return DMX_BAD_VALUE;
-
- /* The "screen" window must fit entirely within the BE display */
- if (attr->screenWindowXoffset < 0 ||
- attr->screenWindowYoffset < 0 ||
- attr->screenWindowXoffset
- + attr->screenWindowWidth > (unsigned)dmxScreen->beWidth ||
- attr->screenWindowYoffset
- + attr->screenWindowHeight > (unsigned)dmxScreen->beHeight)
- return DMX_BAD_VALUE;
-
- /* The "root" window must fit entirely within the "screen" window */
- if (attr->rootWindowXoffset < 0 ||
- attr->rootWindowYoffset < 0 ||
- attr->rootWindowXoffset
- + attr->rootWindowWidth > attr->screenWindowWidth ||
- attr->rootWindowYoffset
- + attr->rootWindowHeight > attr->screenWindowHeight)
- return DMX_BAD_VALUE;
-
- /* The "root" window must not expose unaddressable coordinates */
- if (attr->rootWindowXorigin < 0 ||
- attr->rootWindowYorigin < 0 ||
- attr->rootWindowXorigin + attr->rootWindowWidth > 32767 ||
- attr->rootWindowYorigin + attr->rootWindowHeight > 32767)
- return DMX_BAD_VALUE;
-
- /* The "root" window must fit within the global bounding box */
- if (attr->rootWindowXorigin
- + attr->rootWindowWidth > (unsigned)dmxGlobalWidth ||
- attr->rootWindowYorigin
- + attr->rootWindowHeight > (unsigned)dmxGlobalHeight)
- return DMX_BAD_VALUE;
-
- /* FIXME: Handle the rest of the illegal value checking */
- }
-
- /* No illegal values found */
- if (errorScreen) *errorScreen = 0;
-
- for (i = 0; i < nscreens; i++) {
- DMXScreenAttributesPtr attr = &attribs[i];
- int idx = screens[i];
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-
- dmxLog(dmxInfo, "Changing screen #%d attributes "
- "from %dx%d+%d+%d %dx%d+%d+%d +%d+%d "
- "to %dx%d+%d+%d %dx%d+%d+%d +%d+%d\n",
- idx,
- dmxScreen->scrnWidth, dmxScreen->scrnHeight,
- dmxScreen->scrnX, dmxScreen->scrnY,
- dmxScreen->rootWidth, dmxScreen->rootHeight,
- dmxScreen->rootX, dmxScreen->rootY,
- dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
- attr->screenWindowWidth, attr->screenWindowHeight,
- attr->screenWindowXoffset, attr->screenWindowYoffset,
- attr->rootWindowWidth, attr->rootWindowHeight,
- attr->rootWindowXoffset, attr->rootWindowYoffset,
- attr->rootWindowXorigin, attr->rootWindowYorigin);
-
- /* Configure "screen" window */
- dmxConfigureScreenWindow(idx,
- attr->screenWindowXoffset,
- attr->screenWindowYoffset,
- attr->screenWindowWidth,
- attr->screenWindowHeight);
-
- /* Configure "root" window */
- dmxConfigureRootWindow(idx,
- attr->rootWindowXoffset,
- attr->rootWindowYoffset,
- attr->rootWindowWidth,
- attr->rootWindowHeight);
-
-
- /* Set "root" window's origin */
- dmxSetRootWindowOrigin(idx,
- attr->rootWindowXorigin,
- attr->rootWindowYorigin);
- }
-
- /* Adjust the cursor boundaries */
- dmxAdjustCursorBoundaries();
-
- /* Force completion of the changes */
- dmxSync(NULL, TRUE);
-
- return Success;
-}
-
-/** Configure the attributes of the global desktop. */
-int dmxConfigureDesktop(DMXDesktopAttributesPtr attribs)
-{
- if (attribs->width <= 0 || attribs->width >= 32767 ||
- attribs->height <= 0 || attribs->height >= 32767)
- return DMX_BAD_VALUE;
-
- /* If the desktop is shrinking, adjust the "root" windows on each
- * "screen" window to only show the visible desktop. Also, handle
- * the special case where the desktop shrinks such that the it no
- * longer overlaps an portion of a "screen" window. */
- if (attribs->width < dmxGlobalWidth || attribs->height < dmxGlobalHeight) {
- int i;
- for (i = 0; i < dmxNumScreens; i++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[i];
- if (dmxScreen->rootXOrigin
- + dmxScreen->rootWidth > attribs->width ||
- dmxScreen->rootYOrigin
- + dmxScreen->rootHeight > attribs->height) {
- int w, h;
- if ((w = attribs->width - dmxScreen->rootXOrigin) < 0) w = 0;
- if ((h = attribs->height - dmxScreen->rootYOrigin) < 0) h = 0;
- if (w > dmxScreen->scrnWidth) w = dmxScreen->scrnWidth;
- if (h > dmxScreen->scrnHeight) h = dmxScreen->scrnHeight;
- if (w > dmxScreen->rootWidth) w = dmxScreen->rootWidth;
- if (h > dmxScreen->rootHeight) h = dmxScreen->rootHeight;
- dmxConfigureRootWindow(i,
- dmxScreen->rootX,
- dmxScreen->rootY,
- w, h);
- }
- }
- }
-
- /* Set the global width/height */
- dmxSetWidthHeight(attribs->width, attribs->height);
-
- /* Handle shift[XY] changes */
- if (attribs->shiftX || attribs->shiftY) {
- int i;
- for (i = 0; i < dmxNumScreens; i++) {
- ScreenPtr pScreen = screenInfo.screens[i];
- WindowPtr pChild = pScreen->root->firstChild;
- while (pChild) {
- /* Adjust child window's position */
- pScreen->MoveWindow(pChild,
- pChild->origin.x - wBorderWidth(pChild)
- - attribs->shiftX,
- pChild->origin.y - wBorderWidth(pChild)
- - attribs->shiftY,
- pChild->nextSib,
- VTMove);
-
- /* Note that the call to MoveWindow will eventually call
- * dmxPositionWindow which will automatically create a
- * window if it is now exposed on screen (for lazy
- * window creation optimization) and it will properly
- * set the offscreen flag.
- */
-
- pChild = pChild->nextSib;
- }
- }
- }
-
- /* Update connection block, Xinerama, etc. -- these appears to
- * already be handled in dmxConnectionBlockCallback(), which is
- * called from dmxAdjustCursorBoundaries() [below]. */
-
- /* Adjust the cursor boundaries */
- dmxAdjustCursorBoundaries();
-
- /* Force completion of the changes */
- dmxSync(NULL, TRUE);
-
- return Success;
-}
-#endif
-
-/** Create the scratch GCs per depth. */
-static void dmxBECreateScratchGCs(int scrnNum)
-{
- ScreenPtr pScreen = screenInfo.screens[scrnNum];
- GCPtr *ppGC = pScreen->GCperDepth;
- int i;
-
- for (i = 0; i <= pScreen->numDepths; i++)
- dmxBECreateGC(pScreen, ppGC[i]);
-}
-
-#ifdef PANORAMIX
-static Bool FoundPixImage;
-
-/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
- * to have its image restored. When it is found, see if there is
- * another screen with the same image. If so, copy the pixmap image
- * from the existing screen to the newly created pixmap. */
-static void dmxBERestorePixmapImage(pointer value, XID id, RESTYPE type,
- pointer p)
-{
- if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
- PixmapPtr pDst = (PixmapPtr)p;
- int idx = pDst->drawable.pScreen->myNum;
- PanoramiXRes *pXinPix = (PanoramiXRes *)value;
- PixmapPtr pPix;
- int i;
-
- dixLookupResourceByType((pointer*) &pPix, pXinPix->info[idx].id,
- RT_PIXMAP, NullClient, DixUnknownAccess);
- if (pPix != pDst) return; /* Not a match.... Next! */
-
- for (i = 0; i < PanoramiXNumScreens; i++) {
- PixmapPtr pSrc;
- dmxPixPrivPtr pSrcPriv = NULL;
-
- if (i == idx) continue; /* Self replication is bad */
-
- dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id,
- RT_PIXMAP, NullClient, DixUnknownAccess);
- pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
- if (pSrcPriv->pixmap) {
- DMXScreenInfo *dmxSrcScreen = &dmxScreens[i];
- DMXScreenInfo *dmxDstScreen = &dmxScreens[idx];
- dmxPixPrivPtr pDstPriv = DMX_GET_PIXMAP_PRIV(pDst);
- XImage *img;
- int j;
- XlibGC gc = NULL;
-
- /* This should never happen, but just in case.... */
- if (pSrc->drawable.width != pDst->drawable.width ||
- pSrc->drawable.height != pDst->drawable.height)
- return;
-
- /* Copy from src pixmap to dst pixmap */
- img = XGetImage(dmxSrcScreen->beDisplay,
- pSrcPriv->pixmap,
- 0, 0,
- pSrc->drawable.width, pSrc->drawable.height,
- -1,
- ZPixmap);
-
- for (j = 0; j < dmxDstScreen->beNumPixmapFormats; j++) {
- if (dmxDstScreen->bePixmapFormats[j].depth == img->depth) {
- unsigned long m;
- XGCValues v;
-
- m = GCFunction | GCPlaneMask | GCClipMask;
- v.function = GXcopy;
- v.plane_mask = AllPlanes;
- v.clip_mask = None;
-
- gc = XCreateGC(dmxDstScreen->beDisplay,
- dmxDstScreen->scrnDefDrawables[j],
- m, &v);
- break;
- }
- }
-
- if (gc) {
- XPutImage(dmxDstScreen->beDisplay,
- pDstPriv->pixmap,
- gc, img, 0, 0, 0, 0,
- pDst->drawable.width, pDst->drawable.height);
- XFreeGC(dmxDstScreen->beDisplay, gc);
- FoundPixImage = True;
- } else {
- dmxLog(dmxWarning, "Could not create GC\n");
- }
-
- XDestroyImage(img);
- return;
- }
- }
- }
-}
-#endif
-
-/** Restore the pixmap image either from another screen or from an image
- * that was saved when the screen was previously detached. */
-static void dmxBERestorePixmap(PixmapPtr pPixmap)
-{
-#ifdef PANORAMIX
- int i;
-
- /* If Xinerama is not active, there's nothing we can do (see comment
- * in #else below for more info). */
- if (noPanoramiXExtension) {
- dmxLog(dmxWarning, "Cannot restore pixmap image\n");
- return;
- }
-
- FoundPixImage = False;
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindAllClientResources(clients[i], dmxBERestorePixmapImage,
- (pointer)pPixmap);
-
- /* No corresponding pixmap image was found on other screens, so we
- * need to copy it from the saved image when the screen was detached
- * (if available). */
- if (!FoundPixImage) {
- dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
-
- if (pPixPriv->detachedImage) {
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- XlibGC gc = NULL;
-
- for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
- if (dmxScreen->bePixmapFormats[i].depth ==
- pPixPriv->detachedImage->depth) {
- unsigned long m;
- XGCValues v;
-
- m = GCFunction | GCPlaneMask | GCClipMask;
- v.function = GXcopy;
- v.plane_mask = AllPlanes;
- v.clip_mask = None;
-
- gc = XCreateGC(dmxScreen->beDisplay,
- dmxScreen->scrnDefDrawables[i],
- m, &v);
- break;
- }
- }
-
- if (gc) {
- XPutImage(dmxScreen->beDisplay,
- pPixPriv->pixmap,
- gc,
- pPixPriv->detachedImage,
- 0, 0, 0, 0,
- pPixmap->drawable.width, pPixmap->drawable.height);
- XFreeGC(dmxScreen->beDisplay, gc);
- } else {
- dmxLog(dmxWarning, "Cannot restore pixmap image\n");
- }
-
- XDestroyImage(pPixPriv->detachedImage);
- pPixPriv->detachedImage = NULL;
- } else {
- dmxLog(dmxWarning, "Cannot restore pixmap image\n");
- }
- }
-#else
- /* If Xinerama is not enabled, then there is no other copy of the
- * pixmap image that we can restore. Saving all pixmap data is not
- * a feasible option since there is no mechanism for updating pixmap
- * data when a screen is detached, which means that the data that
- * was previously saved would most likely be out of date. */
- dmxLog(dmxWarning, "Cannot restore pixmap image\n");
- return;
-#endif
-}
-
-/** Create resources on the back-end server. This function is called
- * from #dmxAttachScreen() via the dix layer's FindAllResources
- * function. It walks all resources, compares them to the screen
- * number passed in as \a n and calls the appropriate DMX function to
- * create the associated resource on the back-end server. */
-static void dmxBECreateResources(pointer value, XID id, RESTYPE type,
- pointer n)
-{
- int scrnNum = (int)n;
- ScreenPtr pScreen = screenInfo.screens[scrnNum];
-
- if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
- /* Window resources are created below in dmxBECreateWindowTree */
- } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
- PixmapPtr pPix = value;
- if (pPix->drawable.pScreen->myNum == scrnNum) {
- dmxBECreatePixmap(pPix);
- dmxBERestorePixmap(pPix);
- }
- } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
- GCPtr pGC = value;
- if (pGC->pScreen->myNum == scrnNum) {
- /* Create the GC on the back-end server */
- dmxBECreateGC(pScreen, pGC);
- /* Create any pixmaps associated with this GC */
- if (!pGC->tileIsPixel) {
- dmxBECreatePixmap(pGC->tile.pixmap);
- dmxBERestorePixmap(pGC->tile.pixmap);
- }
- if (pGC->stipple != pScreen->PixmapPerDepth[0]) {
- dmxBECreatePixmap(pGC->stipple);
- dmxBERestorePixmap(pGC->stipple);
- }
- if (pGC->font != defaultFont) {
- (void)dmxBELoadFont(pScreen, pGC->font);
- }
- /* Update the GC on the back-end server */
- dmxChangeGC(pGC, -1L);
- }
- } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
- (void)dmxBELoadFont(pScreen, (FontPtr)value);
- } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
- dmxBECreateCursor(pScreen, (CursorPtr)value);
- } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
- ColormapPtr pCmap = value;
- if (pCmap->pScreen->myNum == scrnNum)
- (void)dmxBECreateColormap((ColormapPtr)value);
-#if 0
- /* TODO: Recreate Picture and GlyphSet resources */
- } else if ((type & TypeMask) == (PictureType & TypeMask)) {
- /* Picture resources are created when windows are created */
- } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
- dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
-#endif
- } else {
- /* Other resource types??? */
- }
-}
-
-/** Create window hierachy on back-end server. The window tree is
- * created in a special order (bottom most subwindow first) so that the
- * #dmxCreateNonRootWindow() function does not need to recursively call
- * itself to create each window's parents. This is required so that we
- * have the opportunity to create each window's border and background
- * pixmaps (where appropriate) before the window is created. */
-static void dmxBECreateWindowTree(int idx)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- WindowPtr pRoot = screenInfo.screens[idx]->root;
- dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
- WindowPtr pWin;
-
- /* Create the pixmaps associated with the root window */
- if (!pRoot->borderIsPixel) {
- dmxBECreatePixmap(pRoot->border.pixmap);
- dmxBERestorePixmap(pRoot->border.pixmap);
- }
- if (pRoot->backgroundState == BackgroundPixmap) {
- dmxBECreatePixmap(pRoot->background.pixmap);
- dmxBERestorePixmap(pRoot->background.pixmap);
- }
-
- /* Create root window first */
- dmxScreen->rootWin = pWinPriv->window = dmxCreateRootWindow(pRoot);
- XMapWindow(dmxScreen->beDisplay, dmxScreen->rootWin);
-
- pWin = pRoot->lastChild;
- while (pWin) {
- pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
-
- /* Create the pixmaps regardless of whether or not the
- * window is created or not due to lazy window creation.
- */
- if (!pWin->borderIsPixel) {
- dmxBECreatePixmap(pWin->border.pixmap);
- dmxBERestorePixmap(pWin->border.pixmap);
- }
- if (pWin->backgroundState == BackgroundPixmap) {
- dmxBECreatePixmap(pWin->background.pixmap);
- dmxBERestorePixmap(pWin->background.pixmap);
- }
-
- /* Reset the window attributes */
- dmxGetDefaultWindowAttributes(pWin,
- &pWinPriv->cmap,
- &pWinPriv->visual);
-
- /* Create the window */
- if (pWinPriv->mapped && !pWinPriv->offscreen)
- dmxCreateAndRealizeWindow(pWin, TRUE);
-
- /* Next, create the bottom-most child */
- if (pWin->lastChild) {
- pWin = pWin->lastChild;
- continue;
- }
-
- /* If the window has no children, move on to the next higher window */
- while (!pWin->prevSib && (pWin != pRoot))
- pWin = pWin->parent;
-
- if (pWin->prevSib) {
- pWin = pWin->prevSib;
- continue;
- }
-
- /* When we reach the root window, we are finished */
- if (pWin == pRoot)
- break;
- }
-}
-
-/* Refresh screen by generating exposure events for all windows */
-static void dmxForceExposures(int idx)
-{
- ScreenPtr pScreen = screenInfo.screens[idx];
- WindowPtr pRoot = pScreen->root;
- Bool anyMarked = FALSE;
- WindowPtr pChild;
-
- for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
- anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
- (WindowPtr *)NULL);
- if (anyMarked) {
- /* If any windows have been marked, set the root window's
- * clipList to be broken since it will be recalculated in
- * ValidateTree()
- */
- RegionBreak(&pRoot->clipList);
- pScreen->ValidateTree(pRoot, NULL, VTBroken);
- pScreen->HandleExposures(pRoot);
- if (pScreen->PostValidateTree)
- pScreen->PostValidateTree(pRoot, NULL, VTBroken);
- }
-}
-
-/** Compare the new and old screens to see if they are compatible. */
-static Bool dmxCompareScreens(DMXScreenInfo *new, DMXScreenInfo *old)
-{
- int i;
-
- if (new->beWidth != old->beWidth) return FALSE;
- if (new->beHeight != old->beHeight) return FALSE;
- if (new->beDepth != old->beDepth) return FALSE;
- if (new->beBPP != old->beBPP) return FALSE;
-
- if (new->beNumDepths != old->beNumDepths) return FALSE;
- for (i = 0; i < old->beNumDepths; i++)
- if (new->beDepths[i] != old->beDepths[i]) return FALSE;
-
- if (new->beNumPixmapFormats != old->beNumPixmapFormats) return FALSE;
- for (i = 0; i < old->beNumPixmapFormats; i++) {
- if (new->bePixmapFormats[i].depth !=
- old->bePixmapFormats[i].depth) return FALSE;
- if (new->bePixmapFormats[i].bits_per_pixel !=
- old->bePixmapFormats[i].bits_per_pixel) return FALSE;
- if (new->bePixmapFormats[i].scanline_pad !=
- old->bePixmapFormats[i].scanline_pad) return FALSE;
- }
-
- if (new->beNumVisuals != old->beNumVisuals) return FALSE;
- for (i = 0; i < old->beNumVisuals; i++) {
- if (new->beVisuals[i].visualid !=
- old->beVisuals[i].visualid) return FALSE;
- if (new->beVisuals[i].screen !=
- old->beVisuals[i].screen) return FALSE;
- if (new->beVisuals[i].depth !=
- old->beVisuals[i].depth) return FALSE;
- if (new->beVisuals[i].class !=
- old->beVisuals[i].class) return FALSE;
- if (new->beVisuals[i].red_mask !=
- old->beVisuals[i].red_mask) return FALSE;
- if (new->beVisuals[i].green_mask !=
- old->beVisuals[i].green_mask) return FALSE;
- if (new->beVisuals[i].blue_mask !=
- old->beVisuals[i].blue_mask) return FALSE;
- if (new->beVisuals[i].colormap_size !=
- old->beVisuals[i].colormap_size) return FALSE;
- if (new->beVisuals[i].bits_per_rgb !=
- old->beVisuals[i].bits_per_rgb) return FALSE;
- }
-
- if (new->beDefVisualIndex != old->beDefVisualIndex) return FALSE;
-
- return TRUE;
-}
-
-/** Restore Render's picture */
-static void dmxBERestoreRenderPict(pointer value, XID id, pointer n)
-{
- PicturePtr pPicture = value; /* The picture */
- DrawablePtr pDraw = pPicture->pDrawable; /* The picture's drawable */
- int scrnNum = (int)n;
-
- if (pDraw->pScreen->myNum != scrnNum) {
- /* Picture not on the screen we are restoring*/
- return;
- }
-
- if (pDraw->type == DRAWABLE_PIXMAP) {
- PixmapPtr pPixmap = (PixmapPtr)pDraw;
-
- /* Create and restore the pixmap drawable */
- dmxBECreatePixmap(pPixmap);
- dmxBERestorePixmap(pPixmap);
- }
-
- dmxBECreatePicture(pPicture);
-}
-
-/** Restore Render's glyphs */
-static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n)
-{
- GlyphSetPtr glyphSet = value;
- int scrnNum = (int)n;
- dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
- DMXScreenInfo *dmxScreen = &dmxScreens[scrnNum];
- GlyphRefPtr table;
- char *images;
- Glyph *gids;
- XGlyphInfo *glyphs;
- char *pos;
- int beret;
- int len_images = 0;
- int i;
- int ctr;
-
- if (glyphPriv->glyphSets[scrnNum]) {
- /* Only restore glyphs on the screen we are attaching */
- return;
- }
-
- /* First we must create the glyph set on the backend. */
- if ((beret = dmxBECreateGlyphSet(scrnNum, glyphSet)) != Success) {
- dmxLog(dmxWarning,
- "\tdmxBERestoreRenderGlyph failed to create glyphset!\n");
- return;
- }
-
- /* Now for the complex part, restore the glyph data */
- table = glyphSet->hash.table;
-
- /* We need to know how much memory to allocate for this part */
- for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
- GlyphRefPtr gr = &table[i];
- GlyphPtr gl = gr->glyph;
-
- if (!gl || gl == DeletedGlyph) continue;
- len_images += gl->size - sizeof(gl->info);
- }
-
- /* Now allocate the memory we need */
- images = calloc(len_images, sizeof(char));
- gids = malloc(glyphSet->hash.tableEntries*sizeof(Glyph));
- glyphs = malloc(glyphSet->hash.tableEntries*sizeof(XGlyphInfo));
-
- pos = images;
- ctr = 0;
-
- /* Fill the allocated memory with the proper data */
- for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
- GlyphRefPtr gr = &table[i];
- GlyphPtr gl = gr->glyph;
-
- if (!gl || gl == DeletedGlyph) continue;
-
- /* First lets put the data into gids */
- gids[ctr] = gr->signature;
-
- /* Next do the glyphs data structures */
- glyphs[ctr].width = gl->info.width;
- glyphs[ctr].height = gl->info.height;
- glyphs[ctr].x = gl->info.x;
- glyphs[ctr].y = gl->info.y;
- glyphs[ctr].xOff = gl->info.xOff;
- glyphs[ctr].yOff = gl->info.yOff;
-
- /* Copy the images from the DIX's data into the buffer */
- memcpy(pos, gl+1, gl->size - sizeof(gl->info));
- pos += gl->size - sizeof(gl->info);
- ctr++;
- }
-
- /* Now restore the glyph data */
- XRenderAddGlyphs(dmxScreen->beDisplay, glyphPriv->glyphSets[scrnNum],
- gids,glyphs, glyphSet->hash.tableEntries, images,
- len_images);
-
- /* Clean up */
- free(images);
- free(gids);
- free(glyphs);
-}
-
-/** Reattach previously detached back-end screen. */
-int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
-{
- ScreenPtr pScreen;
- DMXScreenInfo *dmxScreen;
- CARD32 scrnNum = idx;
- DMXScreenInfo oldDMXScreen;
- int i;
-
- /* Return failure if dynamic addition/removal of screens is disabled */
- if (!dmxAddRemoveScreens) {
- dmxLog(dmxWarning,
- "Attempting to add a screen, but the AddRemoveScreen\n");
- dmxLog(dmxWarning,
- "extension has not been enabled. To enable this extension\n");
- dmxLog(dmxWarning,
- "add the \"-addremovescreens\" option either to the command\n");
- dmxLog(dmxWarning,
- "line or in the configuration file.\n");
- return 1;
- }
-
- /* Cannot add a screen that does not exist */
- if (idx < 0 || idx >= dmxNumScreens) return 1;
- pScreen = screenInfo.screens[idx];
- dmxScreen = &dmxScreens[idx];
-
- /* Cannot attach to a screen that is already opened */
- if (dmxScreen->beDisplay) {
- dmxLog(dmxWarning,
- "Attempting to add screen #%d but a screen already exists\n",
- idx);
- return 1;
- }
-
- dmxLogOutput(dmxScreen, "Attaching screen #%d\n", idx);
-
- /* Save old info */
- oldDMXScreen = *dmxScreen;
-
- /* Copy the name to the new screen */
- dmxScreen->name = strdup(attr->displayName);
-
- /* Open display and get all of the screen info */
- if (!dmxOpenDisplay(dmxScreen)) {
- dmxLog(dmxWarning,
- "dmxOpenDisplay: Unable to open display %s\n",
- dmxScreen->name);
-
- /* Restore the old screen */
- *dmxScreen = oldDMXScreen;
- return 1;
- }
-
- dmxSetErrorHandler(dmxScreen);
- dmxCheckForWM(dmxScreen);
- dmxGetScreenAttribs(dmxScreen);
-
- if (!dmxGetVisualInfo(dmxScreen)) {
- dmxLog(dmxWarning, "dmxGetVisualInfo: No matching visuals found\n");
- XFree(dmxScreen->beVisuals);
- XCloseDisplay(dmxScreen->beDisplay);
-
- /* Restore the old screen */
- *dmxScreen = oldDMXScreen;
- return 1;
- }
-
- dmxGetColormaps(dmxScreen);
- dmxGetPixmapFormats(dmxScreen);
-
- /* Verify that the screen to be added has the same info as the
- * previously added screen. */
- if (!dmxCompareScreens(dmxScreen, &oldDMXScreen)) {
- dmxLog(dmxWarning,
- "New screen data (%s) does not match previously\n",
- dmxScreen->name);
- dmxLog(dmxWarning,
- "attached screen data (%s)\n",
- oldDMXScreen.name);
- dmxLog(dmxWarning,
- "All data must match in order to attach to screen #%d\n",
- idx);
- XFree(dmxScreen->beVisuals);
- XFree(dmxScreen->beDepths);
- XFree(dmxScreen->bePixmapFormats);
- XCloseDisplay(dmxScreen->beDisplay);
-
- /* Restore the old screen */
- *dmxScreen = oldDMXScreen;
- return 1;
- }
-
- /* Initialize the BE screen resources */
- dmxBEScreenInit(idx, screenInfo.screens[idx]);
-
- /* TODO: Handle GLX visual initialization. GLXProxy needs to be
- * updated to handle dynamic addition/removal of screens. */
-
- /* Create default stipple */
- dmxBECreatePixmap(pScreen->PixmapPerDepth[0]);
- dmxBERestorePixmap(pScreen->PixmapPerDepth[0]);
-
- /* Create the scratch GCs */
- dmxBECreateScratchGCs(idx);
-
- /* Create the default font */
- (void)dmxBELoadFont(pScreen, defaultFont);
-
- /* Create all resources that don't depend on windows */
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindAllClientResources(clients[i], dmxBECreateResources,
- (pointer)idx);
-
- /* Create window hierarchy (top down) */
- dmxBECreateWindowTree(idx);
-
- /* Restore the picture state for RENDER */
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindClientResourcesByType(clients[i],PictureType,
- dmxBERestoreRenderPict,(pointer)idx);
-
- /* Restore the glyph state for RENDER */
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindClientResourcesByType(clients[i],GlyphSetType,
- dmxBERestoreRenderGlyph,(pointer)idx);
-
- /* Refresh screen by generating exposure events for all windows */
- dmxForceExposures(idx);
-
- dmxSync(&dmxScreens[idx], TRUE);
-
- /* We used these to compare the old and new screens. They are no
- * longer needed since we have a newly attached screen, so we can
- * now free the old screen's resources. */
- XFree(oldDMXScreen.beVisuals);
- XFree(oldDMXScreen.beDepths);
- XFree(oldDMXScreen.bePixmapFormats);
- /* TODO: should oldDMXScreen.name be freed?? */
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension)
- return dmxConfigureScreenWindows(1, &scrnNum, attr, NULL);
- else
-#endif
- return 0; /* Success */
-}
-
-/*
- * Resources that may have state on the BE server and need to be freed:
- *
- * RT_NONE
- * RT_WINDOW
- * RT_PIXMAP
- * RT_GC
- * RT_FONT
- * RT_CURSOR
- * RT_COLORMAP
- * RT_CMAPENTRY
- * RT_OTHERCLIENT
- * RT_PASSIVEGRAB
- * XRT_WINDOW
- * XRT_PIXMAP
- * XRT_GC
- * XRT_COLORMAP
- * XRT_PICTURE
- * PictureType
- * PictFormatType
- * GlyphSetType
- * ClientType
- * EventType
- * RT_INPUTCLIENT
- * XETrapType
- * RTCounter
- * RTAwait
- * RTAlarmClient
- * RT_XKBCLIENT
- * RTContext
- * TagResType
- * StalledResType
- * SecurityAuthorizationResType
- * RTEventClient
- * __glXContextRes
- * __glXClientRes
- * __glXPixmapRes
- * __glXWindowRes
- * __glXPbufferRes
- */
-
-#ifdef PANORAMIX
-/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
- * to have its image saved. */
-static void dmxBEFindPixmapImage(pointer value, XID id, RESTYPE type,
- pointer p)
-{
- if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
- PixmapPtr pDst = (PixmapPtr)p;
- int idx = pDst->drawable.pScreen->myNum;
- PanoramiXRes *pXinPix = (PanoramiXRes *)value;
- PixmapPtr pPix;
- int i;
-
- dixLookupResourceByType((pointer*) &pPix, pXinPix->info[idx].id,
- RT_PIXMAP, NullClient, DixUnknownAccess);
- if (pPix != pDst) return; /* Not a match.... Next! */
-
- for (i = 0; i < PanoramiXNumScreens; i++) {
- PixmapPtr pSrc;
- dmxPixPrivPtr pSrcPriv = NULL;
-
- if (i == idx) continue; /* Self replication is bad */
-
- dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id,
- RT_PIXMAP, NullClient, DixUnknownAccess);
- pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
- if (pSrcPriv->pixmap) {
- FoundPixImage = True;
- return;
- }
- }
- }
-}
-#endif
-
-/** Save the pixmap image only when there is not another screen with
- * that pixmap from which the image can be read when the screen is
- * reattached. To do this, we first try to find a pixmap on another
- * screen corresponding to the one we are trying to save. If we find
- * one, then we do not need to save the image data since during
- * reattachment, the image data can be read from that other pixmap.
- * However, if we do not find one, then we need to save the image data.
- * The common case for these are for the default stipple and root
- * tile. */
-static void dmxBESavePixmap(PixmapPtr pPixmap)
-{
-#ifdef PANORAMIX
- int i;
-
- /* If Xinerama is not active, there's nothing we can do (see comment
- * in #else below for more info). */
- if (noPanoramiXExtension) return;
-
- FoundPixImage = False;
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindAllClientResources(clients[i], dmxBEFindPixmapImage,
- (pointer)pPixmap);
-
- /* Save the image only if there is no other screens that have a
- * pixmap that corresponds to the one we are trying to save. */
- if (!FoundPixImage) {
- dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
-
- if (!pPixPriv->detachedImage) {
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
-
- pPixPriv->detachedImage = XGetImage(dmxScreen->beDisplay,
- pPixPriv->pixmap,
- 0, 0,
- pPixmap->drawable.width,
- pPixmap->drawable.height,
- -1,
- ZPixmap);
- if (!pPixPriv->detachedImage)
- dmxLog(dmxWarning, "Cannot save pixmap image\n");
- }
- }
-#else
- /* NOTE: The only time there is a pixmap on another screen that
- * corresponds to the one we are trying to save is when Xinerama is
- * active. Otherwise, the pixmap image data is only stored on a
- * single screen, which means that once it is detached, that data is
- * lost. We could save the data here, but then that would require
- * us to implement the ability for Xdmx to keep the pixmap up to
- * date while the screen is detached, which is beyond the scope of
- * the current project. */
- return;
-#endif
-}
-
-/** Destroy resources on the back-end server. This function is called
- * from #dmxDetachScreen() via the dix layer's FindAllResources
- * function. It walks all resources, compares them to the screen
- * number passed in as \a n and calls the appropriate DMX function to
- * free the associated resource on the back-end server. */
-static void dmxBEDestroyResources(pointer value, XID id, RESTYPE type,
- pointer n)
-{
- int scrnNum = (int)n;
- ScreenPtr pScreen = screenInfo.screens[scrnNum];
-
- if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
- /* Window resources are destroyed below in dmxBEDestroyWindowTree */
- } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
- PixmapPtr pPix = value;
- if (pPix->drawable.pScreen->myNum == scrnNum) {
- dmxBESavePixmap(pPix);
- dmxBEFreePixmap(pPix);
- }
- } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
- GCPtr pGC = value;
- if (pGC->pScreen->myNum == scrnNum)
- dmxBEFreeGC(pGC);
- } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
- dmxBEFreeFont(pScreen, (FontPtr)value);
- } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
- dmxBEFreeCursor(pScreen, (CursorPtr)value);
- } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
- ColormapPtr pCmap = value;
- if (pCmap->pScreen->myNum == scrnNum)
- dmxBEFreeColormap((ColormapPtr)value);
- } else if ((type & TypeMask) == (PictureType & TypeMask)) {
- PicturePtr pPict = value;
- if (pPict->pDrawable->pScreen->myNum == scrnNum) {
- /* Free the pixmaps on the backend if needed */
- if (pPict->pDrawable->type == DRAWABLE_PIXMAP) {
- PixmapPtr pPixmap = (PixmapPtr)(pPict->pDrawable);
- dmxBESavePixmap(pPixmap);
- dmxBEFreePixmap(pPixmap);
- }
- dmxBEFreePicture((PicturePtr)value);
- }
- } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
- dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
- } else {
- /* Other resource types??? */
- }
-}
-
-/** Destroy the scratch GCs that are created per depth. */
-static void dmxBEDestroyScratchGCs(int scrnNum)
-{
- ScreenPtr pScreen = screenInfo.screens[scrnNum];
- GCPtr *ppGC = pScreen->GCperDepth;
- int i;
-
- for (i = 0; i <= pScreen->numDepths; i++)
- dmxBEFreeGC(ppGC[i]);
-}
-
-/** Destroy window hierachy on back-end server. To ensure that all
- * XDestroyWindow() calls succeed, they must be performed in a bottom
- * up order so that windows are not destroyed before their children.
- * XDestroyWindow(), which is called from #dmxBEDestroyWindow(), will
- * destroy a window as well as all of it's children. */
-static void dmxBEDestroyWindowTree(int idx)
-{
- WindowPtr pWin = screenInfo.screens[idx]->root;
- WindowPtr pChild = pWin;
-
- while (1) {
- if (pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
-
- /* Destroy the window */
- dmxBEDestroyWindow(pChild);
-
- /* Make sure we destroy the window's border and background
- * pixmaps if they exist */
- if (!pChild->borderIsPixel) {
- dmxBESavePixmap(pChild->border.pixmap);
- dmxBEFreePixmap(pChild->border.pixmap);
- }
- if (pChild->backgroundState == BackgroundPixmap) {
- dmxBESavePixmap(pChild->background.pixmap);
- dmxBEFreePixmap(pChild->background.pixmap);
- }
-
- while (!pChild->nextSib && (pChild != pWin)) {
- pChild = pChild->parent;
- dmxBEDestroyWindow(pChild);
- if (!pChild->borderIsPixel) {
- dmxBESavePixmap(pChild->border.pixmap);
- dmxBEFreePixmap(pChild->border.pixmap);
- }
- if (pChild->backgroundState == BackgroundPixmap) {
- dmxBESavePixmap(pChild->background.pixmap);
- dmxBEFreePixmap(pChild->background.pixmap);
- }
- }
-
- if (pChild == pWin)
- break;
-
- pChild = pChild->nextSib;
- }
-}
-
-/** Detach back-end screen. */
-int dmxDetachScreen(int idx)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- int i;
-
- /* Return failure if dynamic addition/removal of screens is disabled */
- if (!dmxAddRemoveScreens) {
- dmxLog(dmxWarning,
- "Attempting to remove a screen, but the AddRemoveScreen\n");
- dmxLog(dmxWarning,
- "extension has not been enabled. To enable this extension\n");
- dmxLog(dmxWarning,
- "add the \"-addremovescreens\" option either to the command\n");
- dmxLog(dmxWarning,
- "line or in the configuration file.\n");
- return 1;
- }
-
- /* Cannot remove a screen that does not exist */
- if (idx < 0 || idx >= dmxNumScreens) return 1;
-
- /* Cannot detach from a screen that is not opened */
- if (!dmxScreen->beDisplay) {
- dmxLog(dmxWarning,
- "Attempting to remove screen #%d but it has not been opened\n",
- idx);
- return 1;
- }
-
- dmxLogOutput(dmxScreen, "Detaching screen #%d\n", idx);
-
- /* Detach input */
- dmxInputDetachAll(dmxScreen);
-
- /* Save all relevant state (TODO) */
-
- /* Free all non-window resources related to this screen */
- for (i = currentMaxClients; --i >= 0; )
- if (clients[i])
- FindAllClientResources(clients[i], dmxBEDestroyResources,
- (pointer)idx);
-
- /* Free scratch GCs */
- dmxBEDestroyScratchGCs(idx);
-
- /* Free window resources related to this screen */
- dmxBEDestroyWindowTree(idx);
-
- /* Free default stipple */
- dmxBESavePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
- dmxBEFreePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
-
- /* Free the remaining screen resources and close the screen */
- dmxBECloseScreen(screenInfo.screens[idx]);
-
- /* Adjust the cursor boundaries (paints detached console window) */
- dmxAdjustCursorBoundaries();
-
- return 0; /* Success */
-}
+/*
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Author:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+/** \file
+ * This file provides the only interface to the X server extension support
+ * in programs/Xserver/Xext. Those programs should only include dmxext.h
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "dmx.h"
+#include "dmxinit.h"
+#include "dmxextension.h"
+#include "dmxwindow.h"
+#include "dmxcb.h"
+#include "dmxcursor.h"
+#include "dmxpixmap.h"
+#include "dmxgc.h"
+#include "dmxfont.h"
+#include "dmxcmap.h"
+#include "dmxpict.h"
+#include "dmxinput.h"
+#include "dmxsync.h"
+#include "dmxscrinit.h"
+#include "input/dmxinputinit.h"
+
+#include "windowstr.h"
+#include "inputstr.h" /* For DeviceIntRec */
+#include <X11/extensions/dmxproto.h> /* For DMX_BAD_* */
+#include "cursorstr.h"
+
+/* The default font is declared in dix/globals.c, but is not included in
+ * _any_ header files. */
+extern FontPtr defaultFont;
+
+/** This routine provides information to the DMX protocol extension
+ * about a particular screen. */
+Bool dmxGetScreenAttributes(int physical, DMXScreenAttributesPtr attr)
+{
+ DMXScreenInfo *dmxScreen;
+
+ if (physical < 0 || physical >= dmxNumScreens) return FALSE;
+
+ dmxScreen = &dmxScreens[physical];
+ attr->displayName = dmxScreen->name;
+#ifdef PANORAMIX
+ attr->logicalScreen = noPanoramiXExtension ? dmxScreen->index : 0;
+#else
+ attr->logicalScreen = dmxScreen->index;
+#endif
+
+ attr->screenWindowWidth = dmxScreen->scrnWidth;
+ attr->screenWindowHeight = dmxScreen->scrnHeight;
+ attr->screenWindowXoffset = dmxScreen->scrnX;
+ attr->screenWindowYoffset = dmxScreen->scrnY;
+
+ attr->rootWindowWidth = dmxScreen->rootWidth;
+ attr->rootWindowHeight = dmxScreen->rootHeight;
+ attr->rootWindowXoffset = dmxScreen->rootX;
+ attr->rootWindowYoffset = dmxScreen->rootY;
+
+ attr->rootWindowXorigin = dmxScreen->rootXOrigin;
+ attr->rootWindowYorigin = dmxScreen->rootYOrigin;
+
+ return TRUE;
+}
+
+/** This routine provides information to the DMX protocol extension
+ * about a particular window. */
+Bool dmxGetWindowAttributes(WindowPtr pWindow, DMXWindowAttributesPtr attr)
+{
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ attr->screen = pWindow->drawable.pScreen->myNum;
+ attr->window = pWinPriv->window;
+
+ attr->pos.x = pWindow->drawable.x;
+ attr->pos.y = pWindow->drawable.y;
+ attr->pos.width = pWindow->drawable.width;
+ attr->pos.height = pWindow->drawable.height;
+
+ if (!pWinPriv->window || pWinPriv->offscreen) {
+ attr->vis.x = 0;
+ attr->vis.y = 0;
+ attr->vis.height = 0;
+ attr->vis.width = 0;
+ return pWinPriv->window ? TRUE : FALSE;
+ }
+
+ /* Compute display-relative coordinates */
+ attr->vis.x = pWindow->drawable.x;
+ attr->vis.y = pWindow->drawable.y;
+ attr->vis.width = pWindow->drawable.width;
+ attr->vis.height = pWindow->drawable.height;
+
+ if (attr->pos.x < 0) {
+ attr->vis.x -= attr->pos.x;
+ attr->vis.width = attr->pos.x + attr->pos.width - attr->vis.x;
+ }
+ if (attr->pos.x + attr->pos.width > pWindow->drawable.pScreen->width) {
+ if (attr->pos.x < 0)
+ attr->vis.width = pWindow->drawable.pScreen->width;
+ else
+ attr->vis.width = pWindow->drawable.pScreen->width - attr->pos.x;
+ }
+ if (attr->pos.y < 0) {
+ attr->vis.y -= attr->pos.y;
+ attr->vis.height = attr->pos.y + attr->pos.height - attr->vis.y;
+ }
+ if (attr->pos.y + attr->pos.height > pWindow->drawable.pScreen->height) {
+ if (attr->pos.y < 0)
+ attr->vis.height = pWindow->drawable.pScreen->height;
+ else
+ attr->vis.height = pWindow->drawable.pScreen->height - attr->pos.y;
+ }
+
+ /* Convert to window-relative coordinates */
+ attr->vis.x -= attr->pos.x;
+ attr->vis.y -= attr->pos.y;
+
+ return TRUE;
+}
+
+void dmxGetDesktopAttributes(DMXDesktopAttributesPtr attr)
+{
+ attr->width = dmxGlobalWidth;
+ attr->height = dmxGlobalHeight;
+ attr->shiftX = 0; /* NOTE: The upper left hand corner of */
+ attr->shiftY = 0; /* the desktop is always <0,0>. */
+}
+
+/** Return the total number of devices, not just #dmxNumInputs. The
+ * number returned should be the same as that returned by
+ * XListInputDevices. */
+int dmxGetInputCount(void)
+{
+ int i, total;
+
+ for (total = i = 0; i < dmxNumInputs; i++) total += dmxInputs[i].numDevs;
+ return total;
+}
+
+/** Return information about the device with id = \a deviceId. This
+ * information is primarily for the #ProcDMXGetInputAttributes()
+ * function, which does not have access to the appropriate data
+ * structure. */
+int dmxGetInputAttributes(int deviceId, DMXInputAttributesPtr attr)
+{
+ int i, j;
+ DMXInputInfo *dmxInput;
+
+ if (deviceId < 0) return -1;
+ for (i = 0; i < dmxNumInputs; i++) {
+ dmxInput = &dmxInputs[i];
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
+ if (deviceId != dmxLocal->pDevice->id) continue;
+ attr->isCore = !!dmxLocal->isCore;
+ attr->sendsCore = !!dmxLocal->sendsCore;
+ attr->detached = !!dmxInput->detached;
+ attr->physicalScreen = -1;
+ attr->physicalId = -1;
+ attr->name = NULL;
+ switch (dmxLocal->extType) {
+ case DMX_LOCAL_TYPE_LOCAL:
+ attr->inputType = 0;
+ break;
+ case DMX_LOCAL_TYPE_CONSOLE:
+ attr->inputType = 1;
+ attr->name = dmxInput->name;
+ attr->physicalId = dmxLocal->deviceId;
+ break;
+ case DMX_LOCAL_TYPE_BACKEND:
+ case DMX_LOCAL_TYPE_COMMON:
+ attr->inputType = 2;
+ attr->physicalScreen = dmxInput->scrnIdx;
+ attr->name = dmxInput->name;
+ attr->physicalId = dmxLocal->deviceId;
+ break;
+ }
+ return 0; /* Success */
+ }
+ }
+ return -1; /* Failure */
+}
+
+/** Reinitialized the cursor boundaries. */
+static void dmxAdjustCursorBoundaries(void)
+{
+ int i;
+
+ dmxReInitOrigins();
+ dmxInitOverlap();
+ dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
+ dmxConnectionBlockCallback();
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (!dmxInput->detached) dmxInputReInit(dmxInput);
+ }
+
+ dmxCheckCursor();
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (!dmxInput->detached) dmxInputLateReInit(dmxInput);
+ }
+}
+
+/** Add an input with the specified attributes. If the input is added,
+ * the physical id is returned in \a deviceId. */
+int dmxAddInput(DMXInputAttributesPtr attr, int *id)
+{
+ int retcode = BadValue;
+
+ if (attr->inputType == 1) /* console */
+ retcode = dmxInputAttachConsole(attr->name, attr->sendsCore, id);
+ else if (attr->inputType == 2) /* backend */
+ retcode = dmxInputAttachBackend(attr->physicalScreen,
+ attr->sendsCore,id);
+
+ if (retcode == Success) {
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+ }
+
+ return retcode;
+}
+
+/** Remove the input with physical id \a id. */
+int dmxRemoveInput(int id)
+{
+ return dmxInputDetachId(id);
+}
+
+/** Return the value of #dmxNumScreens -- the total number of backend
+ * screens in use (these are logical screens and may be larger than the
+ * number of backend displays). */
+unsigned long dmxGetNumScreens(void)
+{
+ return dmxNumScreens;
+}
+
+/** Make sure that #dmxCreateAndRealizeWindow has been called for \a
+ * pWindow. */
+void dmxForceWindowCreation(WindowPtr pWindow)
+{
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ if (!pWinPriv->window) dmxCreateAndRealizeWindow(pWindow, TRUE);
+}
+
+/** Flush pending syncs for all screens. */
+void dmxFlushPendingSyncs(void)
+{
+ dmxSync(NULL, TRUE);
+}
+
+/** Update DMX's screen resources to match those of the newly moved
+ * and/or resized "root" window. */
+void dmxUpdateScreenResources(ScreenPtr pScreen, int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ WindowPtr pRoot = pScreen->root;
+ WindowPtr pChild;
+ Bool anyMarked = FALSE;
+
+ /* Handle special case where width and/or height are zero */
+ if (w == 0 || h == 0) {
+ w = 1;
+ h = 1;
+ }
+
+ /* Change screen size */
+ pScreen->width = w;
+ pScreen->height = h;
+
+ /* Reset the root window's drawable's size */
+ pRoot->drawable.width = w;
+ pRoot->drawable.height = h;
+
+ /* Set the root window's new winSize and borderSize */
+ pRoot->winSize.extents.x1 = 0;
+ pRoot->winSize.extents.y1 = 0;
+ pRoot->winSize.extents.x2 = w;
+ pRoot->winSize.extents.y2 = h;
+
+ pRoot->borderSize.extents.x1 = 0;
+ pRoot->borderSize.extents.y1 = 0;
+ pRoot->borderSize.extents.x2 = w;
+ pRoot->borderSize.extents.y2 = h;
+
+ /* Recompute this screen's mmWidth & mmHeight */
+ pScreen->mmWidth =
+ (w * 254 + dmxScreen->beXDPI * 5) / (dmxScreen->beXDPI * 10);
+ pScreen->mmHeight =
+ (h * 254 + dmxScreen->beYDPI * 5) / (dmxScreen->beYDPI * 10);
+
+ /* Recompute this screen's window's clip rects as follows: */
+ /* 1. Mark all of root's children's windows */
+ for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
+ anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
+ (WindowPtr *)NULL);
+
+ /* 2. Set the root window's borderClip */
+ pRoot->borderClip.extents.x1 = 0;
+ pRoot->borderClip.extents.y1 = 0;
+ pRoot->borderClip.extents.x2 = w;
+ pRoot->borderClip.extents.y2 = h;
+
+ /* 3. Set the root window's clipList */
+ if (anyMarked) {
+ /* If any windows have been marked, set the root window's
+ * clipList to be broken since it will be recalculated in
+ * ValidateTree()
+ */
+ RegionBreak(&pRoot->clipList);
+ } else {
+ /* Otherwise, we just set it directly since there are no
+ * windows visible on this screen
+ */
+ pRoot->clipList.extents.x1 = 0;
+ pRoot->clipList.extents.y1 = 0;
+ pRoot->clipList.extents.x2 = w;
+ pRoot->clipList.extents.y2 = h;
+ }
+
+ /* 4. Revalidate all clip rects and generate expose events */
+ if (anyMarked) {
+ pScreen->ValidateTree(pRoot, NULL, VTBroken);
+ pScreen->HandleExposures(pRoot);
+ if (pScreen->PostValidateTree)
+ pScreen->PostValidateTree(pRoot, NULL, VTBroken);
+ }
+}
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+
+/** Change the "screen" window attributes by resizing the actual window
+ * on the back-end display (if necessary). */
+static void dmxConfigureScreenWindow(int idx,
+ int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ ScreenPtr pScreen = screenInfo.screens[idx];
+
+ /* Resize "screen" window */
+ if (dmxScreen->scrnX != x ||
+ dmxScreen->scrnY != y ||
+ dmxScreen->scrnWidth != w ||
+ dmxScreen->scrnHeight != h) {
+ dmxResizeScreenWindow(pScreen, x, y, w, h);
+ }
+
+ /* Change "screen" window values */
+ dmxScreen->scrnX = x;
+ dmxScreen->scrnY = y;
+ dmxScreen->scrnWidth = w;
+ dmxScreen->scrnHeight = h;
+}
+
+/** Change the "root" window position and size by resizing the actual
+ * window on the back-end display (if necessary) and updating all of
+ * DMX's resources by calling #dmxUpdateScreenResources. */
+static void dmxConfigureRootWindow(int idx, int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ WindowPtr pRoot = screenInfo.screens[idx]->root;
+
+ /* NOTE: Either this function or the ones that it calls must handle
+ * the case where w == 0 || h == 0. Currently, the functions that
+ * this one calls handle that case. */
+
+ /* 1. Resize "root" window */
+ if (dmxScreen->rootX != x ||
+ dmxScreen->rootY != y ||
+ dmxScreen->rootWidth != w ||
+ dmxScreen->rootHeight != h) {
+ dmxResizeRootWindow(pRoot, x, y, w, h);
+ }
+
+ /* 2. Update all of the screen's resources associated with this root
+ * window */
+ if (dmxScreen->rootWidth != w ||
+ dmxScreen->rootHeight != h) {
+ dmxUpdateScreenResources(screenInfo.screens[idx], x, y, w, h);
+ }
+
+ /* Change "root" window values */
+ dmxScreen->rootX = x;
+ dmxScreen->rootY = y;
+ dmxScreen->rootWidth = w;
+ dmxScreen->rootHeight = h;
+}
+
+/** Change the "root" window's origin by updating DMX's internal data
+ * structures (dix and Xinerama) to use the new origin and adjust the
+ * positions of windows that overlap this "root" window. */
+static void dmxSetRootWindowOrigin(int idx, int x, int y)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ ScreenPtr pScreen = screenInfo.screens[idx];
+ WindowPtr pRoot = pScreen->root;
+ WindowPtr pChild;
+ int xoff;
+ int yoff;
+
+ /* Change "root" window's origin */
+ dmxScreen->rootXOrigin = x;
+ dmxScreen->rootYOrigin = y;
+
+ /* Compute offsets here in case <x,y> has been changed above */
+ xoff = x - pScreen->x;
+ yoff = y - pScreen->y;
+
+ /* Adjust the root window's position */
+ pScreen->x = dmxScreen->rootXOrigin;
+ pScreen->y = dmxScreen->rootYOrigin;
+
+ /* Recalculate the Xinerama regions and data structs */
+ XineramaReinitData(pScreen);
+
+ /* Adjust each of the root window's children */
+ if (!idx) ReinitializeRootWindow(screenInfo.screens[0]->root, xoff, yoff);
+ pChild = pRoot->firstChild;
+ while (pChild) {
+ /* Adjust child window's position */
+ pScreen->MoveWindow(pChild,
+ pChild->origin.x - wBorderWidth(pChild) - xoff,
+ pChild->origin.y - wBorderWidth(pChild) - yoff,
+ pChild->nextSib,
+ VTMove);
+
+ /* Note that the call to MoveWindow will eventually call
+ * dmxPositionWindow which will automatically create a
+ * window if it is now exposed on screen (for lazy window
+ * creation optimization) and it will properly set the
+ * offscreen flag.
+ */
+
+ pChild = pChild->nextSib;
+ }
+}
+
+/** Configure the attributes of each "screen" and "root" window. */
+int dmxConfigureScreenWindows(int nscreens,
+ CARD32 *screens,
+ DMXScreenAttributesPtr attribs,
+ int *errorScreen)
+{
+ int i;
+
+ for (i = 0; i < nscreens; i++) {
+ DMXScreenAttributesPtr attr = &attribs[i];
+ int idx = screens[i];
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+
+ if (errorScreen) *errorScreen = i;
+
+ if (!dmxScreen->beDisplay) return DMX_BAD_VALUE;
+
+ /* Check for illegal values */
+ if (idx < 0 || idx >= dmxNumScreens) return BadValue;
+
+ /* The "screen" and "root" windows must have valid sizes */
+ if (attr->screenWindowWidth <= 0 || attr->screenWindowHeight <= 0 ||
+ attr->rootWindowWidth < 0 || attr->rootWindowHeight < 0)
+ return DMX_BAD_VALUE;
+
+ /* The "screen" window must fit entirely within the BE display */
+ if (attr->screenWindowXoffset < 0 ||
+ attr->screenWindowYoffset < 0 ||
+ attr->screenWindowXoffset
+ + attr->screenWindowWidth > (unsigned)dmxScreen->beWidth ||
+ attr->screenWindowYoffset
+ + attr->screenWindowHeight > (unsigned)dmxScreen->beHeight)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must fit entirely within the "screen" window */
+ if (attr->rootWindowXoffset < 0 ||
+ attr->rootWindowYoffset < 0 ||
+ attr->rootWindowXoffset
+ + attr->rootWindowWidth > attr->screenWindowWidth ||
+ attr->rootWindowYoffset
+ + attr->rootWindowHeight > attr->screenWindowHeight)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must not expose unaddressable coordinates */
+ if (attr->rootWindowXorigin < 0 ||
+ attr->rootWindowYorigin < 0 ||
+ attr->rootWindowXorigin + attr->rootWindowWidth > 32767 ||
+ attr->rootWindowYorigin + attr->rootWindowHeight > 32767)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must fit within the global bounding box */
+ if (attr->rootWindowXorigin
+ + attr->rootWindowWidth > (unsigned)dmxGlobalWidth ||
+ attr->rootWindowYorigin
+ + attr->rootWindowHeight > (unsigned)dmxGlobalHeight)
+ return DMX_BAD_VALUE;
+
+ /* FIXME: Handle the rest of the illegal value checking */
+ }
+
+ /* No illegal values found */
+ if (errorScreen) *errorScreen = 0;
+
+ for (i = 0; i < nscreens; i++) {
+ DMXScreenAttributesPtr attr = &attribs[i];
+ int idx = screens[i];
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+
+ dmxLog(dmxInfo, "Changing screen #%d attributes "
+ "from %dx%d+%d+%d %dx%d+%d+%d +%d+%d "
+ "to %dx%d+%d+%d %dx%d+%d+%d +%d+%d\n",
+ idx,
+ dmxScreen->scrnWidth, dmxScreen->scrnHeight,
+ dmxScreen->scrnX, dmxScreen->scrnY,
+ dmxScreen->rootWidth, dmxScreen->rootHeight,
+ dmxScreen->rootX, dmxScreen->rootY,
+ dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
+ attr->screenWindowWidth, attr->screenWindowHeight,
+ attr->screenWindowXoffset, attr->screenWindowYoffset,
+ attr->rootWindowWidth, attr->rootWindowHeight,
+ attr->rootWindowXoffset, attr->rootWindowYoffset,
+ attr->rootWindowXorigin, attr->rootWindowYorigin);
+
+ /* Configure "screen" window */
+ dmxConfigureScreenWindow(idx,
+ attr->screenWindowXoffset,
+ attr->screenWindowYoffset,
+ attr->screenWindowWidth,
+ attr->screenWindowHeight);
+
+ /* Configure "root" window */
+ dmxConfigureRootWindow(idx,
+ attr->rootWindowXoffset,
+ attr->rootWindowYoffset,
+ attr->rootWindowWidth,
+ attr->rootWindowHeight);
+
+
+ /* Set "root" window's origin */
+ dmxSetRootWindowOrigin(idx,
+ attr->rootWindowXorigin,
+ attr->rootWindowYorigin);
+ }
+
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+
+ return Success;
+}
+
+/** Configure the attributes of the global desktop. */
+int dmxConfigureDesktop(DMXDesktopAttributesPtr attribs)
+{
+ if (attribs->width <= 0 || attribs->width >= 32767 ||
+ attribs->height <= 0 || attribs->height >= 32767)
+ return DMX_BAD_VALUE;
+
+ /* If the desktop is shrinking, adjust the "root" windows on each
+ * "screen" window to only show the visible desktop. Also, handle
+ * the special case where the desktop shrinks such that the it no
+ * longer overlaps an portion of a "screen" window. */
+ if (attribs->width < dmxGlobalWidth || attribs->height < dmxGlobalHeight) {
+ int i;
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ if (dmxScreen->rootXOrigin
+ + dmxScreen->rootWidth > attribs->width ||
+ dmxScreen->rootYOrigin
+ + dmxScreen->rootHeight > attribs->height) {
+ int w, h;
+ if ((w = attribs->width - dmxScreen->rootXOrigin) < 0) w = 0;
+ if ((h = attribs->height - dmxScreen->rootYOrigin) < 0) h = 0;
+ if (w > dmxScreen->scrnWidth) w = dmxScreen->scrnWidth;
+ if (h > dmxScreen->scrnHeight) h = dmxScreen->scrnHeight;
+ if (w > dmxScreen->rootWidth) w = dmxScreen->rootWidth;
+ if (h > dmxScreen->rootHeight) h = dmxScreen->rootHeight;
+ dmxConfigureRootWindow(i,
+ dmxScreen->rootX,
+ dmxScreen->rootY,
+ w, h);
+ }
+ }
+ }
+
+ /* Set the global width/height */
+ dmxSetWidthHeight(attribs->width, attribs->height);
+
+ /* Handle shift[XY] changes */
+ if (attribs->shiftX || attribs->shiftY) {
+ int i;
+ for (i = 0; i < dmxNumScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ WindowPtr pChild = pScreen->root->firstChild;
+ while (pChild) {
+ /* Adjust child window's position */
+ pScreen->MoveWindow(pChild,
+ pChild->origin.x - wBorderWidth(pChild)
+ - attribs->shiftX,
+ pChild->origin.y - wBorderWidth(pChild)
+ - attribs->shiftY,
+ pChild->nextSib,
+ VTMove);
+
+ /* Note that the call to MoveWindow will eventually call
+ * dmxPositionWindow which will automatically create a
+ * window if it is now exposed on screen (for lazy
+ * window creation optimization) and it will properly
+ * set the offscreen flag.
+ */
+
+ pChild = pChild->nextSib;
+ }
+ }
+ }
+
+ /* Update connection block, Xinerama, etc. -- these appears to
+ * already be handled in dmxConnectionBlockCallback(), which is
+ * called from dmxAdjustCursorBoundaries() [below]. */
+
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+
+ return Success;
+}
+#endif
+
+/** Create the scratch GCs per depth. */
+static void dmxBECreateScratchGCs(int scrnNum)
+{
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+ GCPtr *ppGC = pScreen->GCperDepth;
+ int i;
+
+ for (i = 0; i <= pScreen->numDepths; i++)
+ dmxBECreateGC(pScreen, ppGC[i]);
+}
+
+#ifdef PANORAMIX
+static Bool FoundPixImage;
+
+/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
+ * to have its image restored. When it is found, see if there is
+ * another screen with the same image. If so, copy the pixmap image
+ * from the existing screen to the newly created pixmap. */
+static void dmxBERestorePixmapImage(pointer value, XID id, RESTYPE type,
+ pointer p)
+{
+ if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
+ PixmapPtr pDst = (PixmapPtr)p;
+ int idx = pDst->drawable.pScreen->myNum;
+ PanoramiXRes *pXinPix = (PanoramiXRes *)value;
+ PixmapPtr pPix;
+ int i;
+
+ dixLookupResourceByType((pointer*) &pPix, pXinPix->info[idx].id,
+ RT_PIXMAP, NullClient, DixUnknownAccess);
+ if (pPix != pDst) return; /* Not a match.... Next! */
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ PixmapPtr pSrc;
+ dmxPixPrivPtr pSrcPriv = NULL;
+
+ if (i == idx) continue; /* Self replication is bad */
+
+ dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id,
+ RT_PIXMAP, NullClient, DixUnknownAccess);
+ pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
+ if (pSrcPriv->pixmap) {
+ DMXScreenInfo *dmxSrcScreen = &dmxScreens[i];
+ DMXScreenInfo *dmxDstScreen = &dmxScreens[idx];
+ dmxPixPrivPtr pDstPriv = DMX_GET_PIXMAP_PRIV(pDst);
+ XImage *img;
+ int j;
+ XlibGC gc = NULL;
+
+ /* This should never happen, but just in case.... */
+ if (pSrc->drawable.width != pDst->drawable.width ||
+ pSrc->drawable.height != pDst->drawable.height)
+ return;
+
+ /* Copy from src pixmap to dst pixmap */
+ img = XGetImage(dmxSrcScreen->beDisplay,
+ pSrcPriv->pixmap,
+ 0, 0,
+ pSrc->drawable.width, pSrc->drawable.height,
+ -1,
+ ZPixmap);
+
+ for (j = 0; j < dmxDstScreen->beNumPixmapFormats; j++) {
+ if (dmxDstScreen->bePixmapFormats[j].depth == img->depth) {
+ unsigned long m;
+ XGCValues v;
+
+ m = GCFunction | GCPlaneMask | GCClipMask;
+ v.function = GXcopy;
+ v.plane_mask = AllPlanes;
+ v.clip_mask = None;
+
+ gc = XCreateGC(dmxDstScreen->beDisplay,
+ dmxDstScreen->scrnDefDrawables[j],
+ m, &v);
+ break;
+ }
+ }
+
+ if (gc) {
+ XPutImage(dmxDstScreen->beDisplay,
+ pDstPriv->pixmap,
+ gc, img, 0, 0, 0, 0,
+ pDst->drawable.width, pDst->drawable.height);
+ XFreeGC(dmxDstScreen->beDisplay, gc);
+ FoundPixImage = True;
+ } else {
+ dmxLog(dmxWarning, "Could not create GC\n");
+ }
+
+ XDestroyImage(img);
+ return;
+ }
+ }
+ }
+}
+#endif
+
+/** Restore the pixmap image either from another screen or from an image
+ * that was saved when the screen was previously detached. */
+static void dmxBERestorePixmap(PixmapPtr pPixmap)
+{
+#ifdef PANORAMIX
+ int i;
+
+ /* If Xinerama is not active, there's nothing we can do (see comment
+ * in #else below for more info). */
+ if (noPanoramiXExtension) {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ return;
+ }
+
+ FoundPixImage = False;
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBERestorePixmapImage,
+ (pointer)pPixmap);
+
+ /* No corresponding pixmap image was found on other screens, so we
+ * need to copy it from the saved image when the screen was detached
+ * (if available). */
+ if (!FoundPixImage) {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
+
+ if (pPixPriv->detachedImage) {
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ XlibGC gc = NULL;
+
+ for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
+ if (dmxScreen->bePixmapFormats[i].depth ==
+ pPixPriv->detachedImage->depth) {
+ unsigned long m;
+ XGCValues v;
+
+ m = GCFunction | GCPlaneMask | GCClipMask;
+ v.function = GXcopy;
+ v.plane_mask = AllPlanes;
+ v.clip_mask = None;
+
+ gc = XCreateGC(dmxScreen->beDisplay,
+ dmxScreen->scrnDefDrawables[i],
+ m, &v);
+ break;
+ }
+ }
+
+ if (gc) {
+ XPutImage(dmxScreen->beDisplay,
+ pPixPriv->pixmap,
+ gc,
+ pPixPriv->detachedImage,
+ 0, 0, 0, 0,
+ pPixmap->drawable.width, pPixmap->drawable.height);
+ XFreeGC(dmxScreen->beDisplay, gc);
+ } else {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ }
+
+ XDestroyImage(pPixPriv->detachedImage);
+ pPixPriv->detachedImage = NULL;
+ } else {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ }
+ }
+#else
+ /* If Xinerama is not enabled, then there is no other copy of the
+ * pixmap image that we can restore. Saving all pixmap data is not
+ * a feasible option since there is no mechanism for updating pixmap
+ * data when a screen is detached, which means that the data that
+ * was previously saved would most likely be out of date. */
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ return;
+#endif
+}
+
+/** Create resources on the back-end server. This function is called
+ * from #dmxAttachScreen() via the dix layer's FindAllResources
+ * function. It walks all resources, compares them to the screen
+ * number passed in as \a n and calls the appropriate DMX function to
+ * create the associated resource on the back-end server. */
+static void dmxBECreateResources(pointer value, XID id, RESTYPE type,
+ pointer n)
+{
+ int scrnNum = (uintptr_t)n;
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+
+ if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
+ /* Window resources are created below in dmxBECreateWindowTree */
+ } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
+ PixmapPtr pPix = value;
+ if (pPix->drawable.pScreen->myNum == scrnNum) {
+ dmxBECreatePixmap(pPix);
+ dmxBERestorePixmap(pPix);
+ }
+ } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
+ GCPtr pGC = value;
+ if (pGC->pScreen->myNum == scrnNum) {
+ /* Create the GC on the back-end server */
+ dmxBECreateGC(pScreen, pGC);
+ /* Create any pixmaps associated with this GC */
+ if (!pGC->tileIsPixel) {
+ dmxBECreatePixmap(pGC->tile.pixmap);
+ dmxBERestorePixmap(pGC->tile.pixmap);
+ }
+ if (pGC->stipple != pScreen->PixmapPerDepth[0]) {
+ dmxBECreatePixmap(pGC->stipple);
+ dmxBERestorePixmap(pGC->stipple);
+ }
+ if (pGC->font != defaultFont) {
+ (void)dmxBELoadFont(pScreen, pGC->font);
+ }
+ /* Update the GC on the back-end server */
+ dmxChangeGC(pGC, -1L);
+ }
+ } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
+ (void)dmxBELoadFont(pScreen, (FontPtr)value);
+ } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
+ dmxBECreateCursor(pScreen, (CursorPtr)value);
+ } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
+ ColormapPtr pCmap = value;
+ if (pCmap->pScreen->myNum == scrnNum)
+ (void)dmxBECreateColormap((ColormapPtr)value);
+#if 0
+ /* TODO: Recreate Picture and GlyphSet resources */
+ } else if ((type & TypeMask) == (PictureType & TypeMask)) {
+ /* Picture resources are created when windows are created */
+ } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
+ dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
+#endif
+ } else {
+ /* Other resource types??? */
+ }
+}
+
+/** Create window hierachy on back-end server. The window tree is
+ * created in a special order (bottom most subwindow first) so that the
+ * #dmxCreateNonRootWindow() function does not need to recursively call
+ * itself to create each window's parents. This is required so that we
+ * have the opportunity to create each window's border and background
+ * pixmaps (where appropriate) before the window is created. */
+static void dmxBECreateWindowTree(int idx)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ WindowPtr pRoot = screenInfo.screens[idx]->root;
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
+ WindowPtr pWin;
+
+ /* Create the pixmaps associated with the root window */
+ if (!pRoot->borderIsPixel) {
+ dmxBECreatePixmap(pRoot->border.pixmap);
+ dmxBERestorePixmap(pRoot->border.pixmap);
+ }
+ if (pRoot->backgroundState == BackgroundPixmap) {
+ dmxBECreatePixmap(pRoot->background.pixmap);
+ dmxBERestorePixmap(pRoot->background.pixmap);
+ }
+
+ /* Create root window first */
+ dmxScreen->rootWin = pWinPriv->window = dmxCreateRootWindow(pRoot);
+ XMapWindow(dmxScreen->beDisplay, dmxScreen->rootWin);
+
+ pWin = pRoot->lastChild;
+ while (pWin) {
+ pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
+
+ /* Create the pixmaps regardless of whether or not the
+ * window is created or not due to lazy window creation.
+ */
+ if (!pWin->borderIsPixel) {
+ dmxBECreatePixmap(pWin->border.pixmap);
+ dmxBERestorePixmap(pWin->border.pixmap);
+ }
+ if (pWin->backgroundState == BackgroundPixmap) {
+ dmxBECreatePixmap(pWin->background.pixmap);
+ dmxBERestorePixmap(pWin->background.pixmap);
+ }
+
+ /* Reset the window attributes */
+ dmxGetDefaultWindowAttributes(pWin,
+ &pWinPriv->cmap,
+ &pWinPriv->visual);
+
+ /* Create the window */
+ if (pWinPriv->mapped && !pWinPriv->offscreen)
+ dmxCreateAndRealizeWindow(pWin, TRUE);
+
+ /* Next, create the bottom-most child */
+ if (pWin->lastChild) {
+ pWin = pWin->lastChild;
+ continue;
+ }
+
+ /* If the window has no children, move on to the next higher window */
+ while (!pWin->prevSib && (pWin != pRoot))
+ pWin = pWin->parent;
+
+ if (pWin->prevSib) {
+ pWin = pWin->prevSib;
+ continue;
+ }
+
+ /* When we reach the root window, we are finished */
+ if (pWin == pRoot)
+ break;
+ }
+}
+
+/* Refresh screen by generating exposure events for all windows */
+static void dmxForceExposures(int idx)
+{
+ ScreenPtr pScreen = screenInfo.screens[idx];
+ WindowPtr pRoot = pScreen->root;
+ Bool anyMarked = FALSE;
+ WindowPtr pChild;
+
+ for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
+ anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
+ (WindowPtr *)NULL);
+ if (anyMarked) {
+ /* If any windows have been marked, set the root window's
+ * clipList to be broken since it will be recalculated in
+ * ValidateTree()
+ */
+ RegionBreak(&pRoot->clipList);
+ pScreen->ValidateTree(pRoot, NULL, VTBroken);
+ pScreen->HandleExposures(pRoot);
+ if (pScreen->PostValidateTree)
+ pScreen->PostValidateTree(pRoot, NULL, VTBroken);
+ }
+}
+
+/** Compare the new and old screens to see if they are compatible. */
+static Bool dmxCompareScreens(DMXScreenInfo *new, DMXScreenInfo *old)
+{
+ int i;
+
+ if (new->beWidth != old->beWidth) return FALSE;
+ if (new->beHeight != old->beHeight) return FALSE;
+ if (new->beDepth != old->beDepth) return FALSE;
+ if (new->beBPP != old->beBPP) return FALSE;
+
+ if (new->beNumDepths != old->beNumDepths) return FALSE;
+ for (i = 0; i < old->beNumDepths; i++)
+ if (new->beDepths[i] != old->beDepths[i]) return FALSE;
+
+ if (new->beNumPixmapFormats != old->beNumPixmapFormats) return FALSE;
+ for (i = 0; i < old->beNumPixmapFormats; i++) {
+ if (new->bePixmapFormats[i].depth !=
+ old->bePixmapFormats[i].depth) return FALSE;
+ if (new->bePixmapFormats[i].bits_per_pixel !=
+ old->bePixmapFormats[i].bits_per_pixel) return FALSE;
+ if (new->bePixmapFormats[i].scanline_pad !=
+ old->bePixmapFormats[i].scanline_pad) return FALSE;
+ }
+
+ if (new->beNumVisuals != old->beNumVisuals) return FALSE;
+ for (i = 0; i < old->beNumVisuals; i++) {
+ if (new->beVisuals[i].visualid !=
+ old->beVisuals[i].visualid) return FALSE;
+ if (new->beVisuals[i].screen !=
+ old->beVisuals[i].screen) return FALSE;
+ if (new->beVisuals[i].depth !=
+ old->beVisuals[i].depth) return FALSE;
+ if (new->beVisuals[i].class !=
+ old->beVisuals[i].class) return FALSE;
+ if (new->beVisuals[i].red_mask !=
+ old->beVisuals[i].red_mask) return FALSE;
+ if (new->beVisuals[i].green_mask !=
+ old->beVisuals[i].green_mask) return FALSE;
+ if (new->beVisuals[i].blue_mask !=
+ old->beVisuals[i].blue_mask) return FALSE;
+ if (new->beVisuals[i].colormap_size !=
+ old->beVisuals[i].colormap_size) return FALSE;
+ if (new->beVisuals[i].bits_per_rgb !=
+ old->beVisuals[i].bits_per_rgb) return FALSE;
+ }
+
+ if (new->beDefVisualIndex != old->beDefVisualIndex) return FALSE;
+
+ return TRUE;
+}
+
+/** Restore Render's picture */
+static void dmxBERestoreRenderPict(pointer value, XID id, pointer n)
+{
+ PicturePtr pPicture = value; /* The picture */
+ DrawablePtr pDraw = pPicture->pDrawable; /* The picture's drawable */
+ int scrnNum = (uintptr_t)n;
+
+ if (pDraw->pScreen->myNum != scrnNum) {
+ /* Picture not on the screen we are restoring*/
+ return;
+ }
+
+ if (pDraw->type == DRAWABLE_PIXMAP) {
+ PixmapPtr pPixmap = (PixmapPtr)pDraw;
+
+ /* Create and restore the pixmap drawable */
+ dmxBECreatePixmap(pPixmap);
+ dmxBERestorePixmap(pPixmap);
+ }
+
+ dmxBECreatePicture(pPicture);
+}
+
+/** Restore Render's glyphs */
+static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n)
+{
+ GlyphSetPtr glyphSet = value;
+ int scrnNum = (uintptr_t)n;
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ DMXScreenInfo *dmxScreen = &dmxScreens[scrnNum];
+ GlyphRefPtr table;
+ char *images;
+ Glyph *gids;
+ XGlyphInfo *glyphs;
+ char *pos;
+ int beret;
+ int len_images = 0;
+ int i;
+ int ctr;
+
+ if (glyphPriv->glyphSets[scrnNum]) {
+ /* Only restore glyphs on the screen we are attaching */
+ return;
+ }
+
+ /* First we must create the glyph set on the backend. */
+ if ((beret = dmxBECreateGlyphSet(scrnNum, glyphSet)) != Success) {
+ dmxLog(dmxWarning,
+ "\tdmxBERestoreRenderGlyph failed to create glyphset!\n");
+ return;
+ }
+
+ /* Now for the complex part, restore the glyph data */
+ table = glyphSet->hash.table;
+
+ /* We need to know how much memory to allocate for this part */
+ for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
+ GlyphRefPtr gr = &table[i];
+ GlyphPtr gl = gr->glyph;
+
+ if (!gl || gl == DeletedGlyph) continue;
+ len_images += gl->size - sizeof(gl->info);
+ }
+
+ /* Now allocate the memory we need */
+ images = calloc(len_images, sizeof(char));
+ gids = malloc(glyphSet->hash.tableEntries*sizeof(Glyph));
+ glyphs = malloc(glyphSet->hash.tableEntries*sizeof(XGlyphInfo));
+
+ pos = images;
+ ctr = 0;
+
+ /* Fill the allocated memory with the proper data */
+ for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
+ GlyphRefPtr gr = &table[i];
+ GlyphPtr gl = gr->glyph;
+
+ if (!gl || gl == DeletedGlyph) continue;
+
+ /* First lets put the data into gids */
+ gids[ctr] = gr->signature;
+
+ /* Next do the glyphs data structures */
+ glyphs[ctr].width = gl->info.width;
+ glyphs[ctr].height = gl->info.height;
+ glyphs[ctr].x = gl->info.x;
+ glyphs[ctr].y = gl->info.y;
+ glyphs[ctr].xOff = gl->info.xOff;
+ glyphs[ctr].yOff = gl->info.yOff;
+
+ /* Copy the images from the DIX's data into the buffer */
+ memcpy(pos, gl+1, gl->size - sizeof(gl->info));
+ pos += gl->size - sizeof(gl->info);
+ ctr++;
+ }
+
+ /* Now restore the glyph data */
+ XRenderAddGlyphs(dmxScreen->beDisplay, glyphPriv->glyphSets[scrnNum],
+ gids,glyphs, glyphSet->hash.tableEntries, images,
+ len_images);
+
+ /* Clean up */
+ free(images);
+ free(gids);
+ free(glyphs);
+}
+
+/** Reattach previously detached back-end screen. */
+int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
+{
+ ScreenPtr pScreen;
+ DMXScreenInfo *dmxScreen;
+ CARD32 scrnNum = idx;
+ DMXScreenInfo oldDMXScreen;
+ int i;
+
+ /* Return failure if dynamic addition/removal of screens is disabled */
+ if (!dmxAddRemoveScreens) {
+ dmxLog(dmxWarning,
+ "Attempting to add a screen, but the AddRemoveScreen\n");
+ dmxLog(dmxWarning,
+ "extension has not been enabled. To enable this extension\n");
+ dmxLog(dmxWarning,
+ "add the \"-addremovescreens\" option either to the command\n");
+ dmxLog(dmxWarning,
+ "line or in the configuration file.\n");
+ return 1;
+ }
+
+ /* Cannot add a screen that does not exist */
+ if (idx < 0 || idx >= dmxNumScreens) return 1;
+ pScreen = screenInfo.screens[idx];
+ dmxScreen = &dmxScreens[idx];
+
+ /* Cannot attach to a screen that is already opened */
+ if (dmxScreen->beDisplay) {
+ dmxLog(dmxWarning,
+ "Attempting to add screen #%d but a screen already exists\n",
+ idx);
+ return 1;
+ }
+
+ dmxLogOutput(dmxScreen, "Attaching screen #%d\n", idx);
+
+ /* Save old info */
+ oldDMXScreen = *dmxScreen;
+
+ /* Copy the name to the new screen */
+ dmxScreen->name = strdup(attr->displayName);
+
+ /* Open display and get all of the screen info */
+ if (!dmxOpenDisplay(dmxScreen)) {
+ dmxLog(dmxWarning,
+ "dmxOpenDisplay: Unable to open display %s\n",
+ dmxScreen->name);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ dmxSetErrorHandler(dmxScreen);
+ dmxCheckForWM(dmxScreen);
+ dmxGetScreenAttribs(dmxScreen);
+
+ if (!dmxGetVisualInfo(dmxScreen)) {
+ dmxLog(dmxWarning, "dmxGetVisualInfo: No matching visuals found\n");
+ XFree(dmxScreen->beVisuals);
+ XCloseDisplay(dmxScreen->beDisplay);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ dmxGetColormaps(dmxScreen);
+ dmxGetPixmapFormats(dmxScreen);
+
+ /* Verify that the screen to be added has the same info as the
+ * previously added screen. */
+ if (!dmxCompareScreens(dmxScreen, &oldDMXScreen)) {
+ dmxLog(dmxWarning,
+ "New screen data (%s) does not match previously\n",
+ dmxScreen->name);
+ dmxLog(dmxWarning,
+ "attached screen data (%s)\n",
+ oldDMXScreen.name);
+ dmxLog(dmxWarning,
+ "All data must match in order to attach to screen #%d\n",
+ idx);
+ XFree(dmxScreen->beVisuals);
+ XFree(dmxScreen->beDepths);
+ XFree(dmxScreen->bePixmapFormats);
+ XCloseDisplay(dmxScreen->beDisplay);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ /* Initialize the BE screen resources */
+ dmxBEScreenInit(idx, screenInfo.screens[idx]);
+
+ /* TODO: Handle GLX visual initialization. GLXProxy needs to be
+ * updated to handle dynamic addition/removal of screens. */
+
+ /* Create default stipple */
+ dmxBECreatePixmap(pScreen->PixmapPerDepth[0]);
+ dmxBERestorePixmap(pScreen->PixmapPerDepth[0]);
+
+ /* Create the scratch GCs */
+ dmxBECreateScratchGCs(idx);
+
+ /* Create the default font */
+ (void)dmxBELoadFont(pScreen, defaultFont);
+
+ /* Create all resources that don't depend on windows */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBECreateResources,
+ (pointer)(uintptr_t)idx);
+
+ /* Create window hierarchy (top down) */
+ dmxBECreateWindowTree(idx);
+
+ /* Restore the picture state for RENDER */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindClientResourcesByType(clients[i],PictureType,
+ dmxBERestoreRenderPict,
+ (pointer)(uintptr_t)idx);
+
+ /* Restore the glyph state for RENDER */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindClientResourcesByType(clients[i],GlyphSetType,
+ dmxBERestoreRenderGlyph,
+ (pointer)(uintptr_t)idx);
+
+ /* Refresh screen by generating exposure events for all windows */
+ dmxForceExposures(idx);
+
+ dmxSync(&dmxScreens[idx], TRUE);
+
+ /* We used these to compare the old and new screens. They are no
+ * longer needed since we have a newly attached screen, so we can
+ * now free the old screen's resources. */
+ XFree(oldDMXScreen.beVisuals);
+ XFree(oldDMXScreen.beDepths);
+ XFree(oldDMXScreen.bePixmapFormats);
+ /* TODO: should oldDMXScreen.name be freed?? */
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ return dmxConfigureScreenWindows(1, &scrnNum, attr, NULL);
+ else
+#endif
+ return 0; /* Success */
+}
+
+/*
+ * Resources that may have state on the BE server and need to be freed:
+ *
+ * RT_NONE
+ * RT_WINDOW
+ * RT_PIXMAP
+ * RT_GC
+ * RT_FONT
+ * RT_CURSOR
+ * RT_COLORMAP
+ * RT_CMAPENTRY
+ * RT_OTHERCLIENT
+ * RT_PASSIVEGRAB
+ * XRT_WINDOW
+ * XRT_PIXMAP
+ * XRT_GC
+ * XRT_COLORMAP
+ * XRT_PICTURE
+ * PictureType
+ * PictFormatType
+ * GlyphSetType
+ * ClientType
+ * EventType
+ * RT_INPUTCLIENT
+ * XETrapType
+ * RTCounter
+ * RTAwait
+ * RTAlarmClient
+ * RT_XKBCLIENT
+ * RTContext
+ * TagResType
+ * StalledResType
+ * SecurityAuthorizationResType
+ * RTEventClient
+ * __glXContextRes
+ * __glXClientRes
+ * __glXPixmapRes
+ * __glXWindowRes
+ * __glXPbufferRes
+ */
+
+#ifdef PANORAMIX
+/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
+ * to have its image saved. */
+static void dmxBEFindPixmapImage(pointer value, XID id, RESTYPE type,
+ pointer p)
+{
+ if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
+ PixmapPtr pDst = (PixmapPtr)p;
+ int idx = pDst->drawable.pScreen->myNum;
+ PanoramiXRes *pXinPix = (PanoramiXRes *)value;
+ PixmapPtr pPix;
+ int i;
+
+ dixLookupResourceByType((pointer*) &pPix, pXinPix->info[idx].id,
+ RT_PIXMAP, NullClient, DixUnknownAccess);
+ if (pPix != pDst) return; /* Not a match.... Next! */
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ PixmapPtr pSrc;
+ dmxPixPrivPtr pSrcPriv = NULL;
+
+ if (i == idx) continue; /* Self replication is bad */
+
+ dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id,
+ RT_PIXMAP, NullClient, DixUnknownAccess);
+ pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
+ if (pSrcPriv->pixmap) {
+ FoundPixImage = True;
+ return;
+ }
+ }
+ }
+}
+#endif
+
+/** Save the pixmap image only when there is not another screen with
+ * that pixmap from which the image can be read when the screen is
+ * reattached. To do this, we first try to find a pixmap on another
+ * screen corresponding to the one we are trying to save. If we find
+ * one, then we do not need to save the image data since during
+ * reattachment, the image data can be read from that other pixmap.
+ * However, if we do not find one, then we need to save the image data.
+ * The common case for these are for the default stipple and root
+ * tile. */
+static void dmxBESavePixmap(PixmapPtr pPixmap)
+{
+#ifdef PANORAMIX
+ int i;
+
+ /* If Xinerama is not active, there's nothing we can do (see comment
+ * in #else below for more info). */
+ if (noPanoramiXExtension) return;
+
+ FoundPixImage = False;
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBEFindPixmapImage,
+ (pointer)pPixmap);
+
+ /* Save the image only if there is no other screens that have a
+ * pixmap that corresponds to the one we are trying to save. */
+ if (!FoundPixImage) {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
+
+ if (!pPixPriv->detachedImage) {
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+ pPixPriv->detachedImage = XGetImage(dmxScreen->beDisplay,
+ pPixPriv->pixmap,
+ 0, 0,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height,
+ -1,
+ ZPixmap);
+ if (!pPixPriv->detachedImage)
+ dmxLog(dmxWarning, "Cannot save pixmap image\n");
+ }
+ }
+#else
+ /* NOTE: The only time there is a pixmap on another screen that
+ * corresponds to the one we are trying to save is when Xinerama is
+ * active. Otherwise, the pixmap image data is only stored on a
+ * single screen, which means that once it is detached, that data is
+ * lost. We could save the data here, but then that would require
+ * us to implement the ability for Xdmx to keep the pixmap up to
+ * date while the screen is detached, which is beyond the scope of
+ * the current project. */
+ return;
+#endif
+}
+
+/** Destroy resources on the back-end server. This function is called
+ * from #dmxDetachScreen() via the dix layer's FindAllResources
+ * function. It walks all resources, compares them to the screen
+ * number passed in as \a n and calls the appropriate DMX function to
+ * free the associated resource on the back-end server. */
+static void dmxBEDestroyResources(pointer value, XID id, RESTYPE type,
+ pointer n)
+{
+ int scrnNum = (uintptr_t)n;
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+
+ if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
+ /* Window resources are destroyed below in dmxBEDestroyWindowTree */
+ } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
+ PixmapPtr pPix = value;
+ if (pPix->drawable.pScreen->myNum == scrnNum) {
+ dmxBESavePixmap(pPix);
+ dmxBEFreePixmap(pPix);
+ }
+ } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
+ GCPtr pGC = value;
+ if (pGC->pScreen->myNum == scrnNum)
+ dmxBEFreeGC(pGC);
+ } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
+ dmxBEFreeFont(pScreen, (FontPtr)value);
+ } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
+ dmxBEFreeCursor(pScreen, (CursorPtr)value);
+ } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
+ ColormapPtr pCmap = value;
+ if (pCmap->pScreen->myNum == scrnNum)
+ dmxBEFreeColormap((ColormapPtr)value);
+ } else if ((type & TypeMask) == (PictureType & TypeMask)) {
+ PicturePtr pPict = value;
+ if (pPict->pDrawable->pScreen->myNum == scrnNum) {
+ /* Free the pixmaps on the backend if needed */
+ if (pPict->pDrawable->type == DRAWABLE_PIXMAP) {
+ PixmapPtr pPixmap = (PixmapPtr)(pPict->pDrawable);
+ dmxBESavePixmap(pPixmap);
+ dmxBEFreePixmap(pPixmap);
+ }
+ dmxBEFreePicture((PicturePtr)value);
+ }
+ } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
+ dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
+ } else {
+ /* Other resource types??? */
+ }
+}
+
+/** Destroy the scratch GCs that are created per depth. */
+static void dmxBEDestroyScratchGCs(int scrnNum)
+{
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+ GCPtr *ppGC = pScreen->GCperDepth;
+ int i;
+
+ for (i = 0; i <= pScreen->numDepths; i++)
+ dmxBEFreeGC(ppGC[i]);
+}
+
+/** Destroy window hierachy on back-end server. To ensure that all
+ * XDestroyWindow() calls succeed, they must be performed in a bottom
+ * up order so that windows are not destroyed before their children.
+ * XDestroyWindow(), which is called from #dmxBEDestroyWindow(), will
+ * destroy a window as well as all of it's children. */
+static void dmxBEDestroyWindowTree(int idx)
+{
+ WindowPtr pWin = screenInfo.screens[idx]->root;
+ WindowPtr pChild = pWin;
+
+ while (1) {
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+
+ /* Destroy the window */
+ dmxBEDestroyWindow(pChild);
+
+ /* Make sure we destroy the window's border and background
+ * pixmaps if they exist */
+ if (!pChild->borderIsPixel) {
+ dmxBESavePixmap(pChild->border.pixmap);
+ dmxBEFreePixmap(pChild->border.pixmap);
+ }
+ if (pChild->backgroundState == BackgroundPixmap) {
+ dmxBESavePixmap(pChild->background.pixmap);
+ dmxBEFreePixmap(pChild->background.pixmap);
+ }
+
+ while (!pChild->nextSib && (pChild != pWin)) {
+ pChild = pChild->parent;
+ dmxBEDestroyWindow(pChild);
+ if (!pChild->borderIsPixel) {
+ dmxBESavePixmap(pChild->border.pixmap);
+ dmxBEFreePixmap(pChild->border.pixmap);
+ }
+ if (pChild->backgroundState == BackgroundPixmap) {
+ dmxBESavePixmap(pChild->background.pixmap);
+ dmxBEFreePixmap(pChild->background.pixmap);
+ }
+ }
+
+ if (pChild == pWin)
+ break;
+
+ pChild = pChild->nextSib;
+ }
+}
+
+/** Detach back-end screen. */
+int dmxDetachScreen(int idx)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ int i;
+
+ /* Return failure if dynamic addition/removal of screens is disabled */
+ if (!dmxAddRemoveScreens) {
+ dmxLog(dmxWarning,
+ "Attempting to remove a screen, but the AddRemoveScreen\n");
+ dmxLog(dmxWarning,
+ "extension has not been enabled. To enable this extension\n");
+ dmxLog(dmxWarning,
+ "add the \"-addremovescreens\" option either to the command\n");
+ dmxLog(dmxWarning,
+ "line or in the configuration file.\n");
+ return 1;
+ }
+
+ /* Cannot remove a screen that does not exist */
+ if (idx < 0 || idx >= dmxNumScreens) return 1;
+
+ /* Cannot detach from a screen that is not opened */
+ if (!dmxScreen->beDisplay) {
+ dmxLog(dmxWarning,
+ "Attempting to remove screen #%d but it has not been opened\n",
+ idx);
+ return 1;
+ }
+
+ dmxLogOutput(dmxScreen, "Detaching screen #%d\n", idx);
+
+ /* Detach input */
+ dmxInputDetachAll(dmxScreen);
+
+ /* Save all relevant state (TODO) */
+
+ /* Free all non-window resources related to this screen */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBEDestroyResources,
+ (pointer)(uintptr_t)idx);
+
+ /* Free scratch GCs */
+ dmxBEDestroyScratchGCs(idx);
+
+ /* Free window resources related to this screen */
+ dmxBEDestroyWindowTree(idx);
+
+ /* Free default stipple */
+ dmxBESavePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
+ dmxBEFreePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
+
+ /* Free the remaining screen resources and close the screen */
+ dmxBECloseScreen(screenInfo.screens[idx]);
+
+ /* Adjust the cursor boundaries (paints detached console window) */
+ dmxAdjustCursorBoundaries();
+
+ return 0; /* Success */
+}
diff --git a/xorg-server/hw/dmx/dmxgc.c b/xorg-server/hw/dmx/dmxgc.c
index 10e93c110..f10f9a074 100644
--- a/xorg-server/hw/dmx/dmxgc.c
+++ b/xorg-server/hw/dmx/dmxgc.c
@@ -1,421 +1,416 @@
-/*
- * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation on the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
- * Authors:
- * Kevin E. Martin <kem@redhat.com>
- *
- */
-
-/** \file
- * This file provides support for GCs. */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "dmx.h"
-#include "dmxsync.h"
-#include "dmxgc.h"
-#include "dmxgcops.h"
-#include "dmxpixmap.h"
-#include "dmxfont.h"
-
-#include "gcstruct.h"
-#include "pixmapstr.h"
-#include "migc.h"
-
-static GCFuncs dmxGCFuncs = {
- dmxValidateGC,
- dmxChangeGC,
- dmxCopyGC,
- dmxDestroyGC,
- dmxChangeClip,
- dmxDestroyClip,
- dmxCopyClip,
-};
-
-static GCOps dmxGCOps = {
- dmxFillSpans,
- dmxSetSpans,
- dmxPutImage,
- dmxCopyArea,
- dmxCopyPlane,
- dmxPolyPoint,
- dmxPolylines,
- dmxPolySegment,
- dmxPolyRectangle,
- dmxPolyArc,
- dmxFillPolygon,
- dmxPolyFillRect,
- dmxPolyFillArc,
- dmxPolyText8,
- dmxPolyText16,
- dmxImageText8,
- dmxImageText16,
- dmxImageGlyphBlt,
- dmxPolyGlyphBlt,
- dmxPushPixels
-};
-
-/** Initialize the GC on \a pScreen */
-Bool dmxInitGC(ScreenPtr pScreen)
-{
- if (!dixRegisterPrivateKey(&dmxGCPrivateKeyRec, PRIVATE_GC, sizeof(dmxGCPrivRec)))
- return FALSE;
- return TRUE;
-}
-
-/** Create the GC on the back-end server. */
-void dmxBECreateGC(ScreenPtr pScreen, GCPtr pGC)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
- int i;
-
- for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
- if (pGC->depth == dmxScreen->bePixmapFormats[i].depth) {
- unsigned long mask;
- XGCValues gcvals;
-
- mask = GCGraphicsExposures;
- gcvals.graphics_exposures = FALSE;
-
- /* Create GC in the back-end servers */
- pGCPriv->gc = XCreateGC(dmxScreen->beDisplay,
- dmxScreen->scrnDefDrawables[i],
- mask, &gcvals);
- break;
- }
- }
-}
-
-/** Create a graphics context on the back-end server associated /a pGC's
- * screen. */
-Bool dmxCreateGC(GCPtr pGC)
-{
- ScreenPtr pScreen = pGC->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
- Bool ret;
-
- DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
- if ((ret = pScreen->CreateGC(pGC))) {
- /* Save the old funcs */
- pGCPriv->funcs = pGC->funcs;
- pGCPriv->ops = NULL;
-
- pGC->funcs = &dmxGCFuncs;
-
- if (dmxScreen->beDisplay) {
- dmxBECreateGC(pScreen, pGC);
- } else {
- pGCPriv->gc = NULL;
- }
-
- /* Check for "magic special case"
- * 1. see CreateGC in dix/gc.c for more info
- * 2. see dmxChangeGC for more info
- */
- pGCPriv->msc = (!pGC->tileIsPixel && !pGC->tile.pixmap);
- }
- DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
-
- return ret;
-}
-
-/** Validate a graphics context, \a pGC, locally in the DMX server and
- * recompute the composite clip, if necessary. */
-void dmxValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
-{
- dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
-
- DMX_GC_FUNC_PROLOGUE(pGC);
-#if 0
- pGC->funcs->ValidateGC(pGC, changes, pDrawable);
-#endif
-
- if (pDrawable->type == DRAWABLE_WINDOW ||
- pDrawable->type == DRAWABLE_PIXMAP) {
- /* Save the old ops, since we're about to change the ops in the
- * epilogue.
- */
- pGCPriv->ops = pGC->ops;
- } else {
- pGCPriv->ops = NULL;
- }
-
- /* If the client clip is different or moved OR the subwindowMode has
- * changed OR the window's clip has changed since the last
- * validation, then we need to recompute the composite clip.
- */
- if ((changes & (GCClipXOrigin |
- GCClipYOrigin |
- GCClipMask |
- GCSubwindowMode)) ||
- (pDrawable->serialNumber !=
- (pGC->serialNumber & DRAWABLE_SERIAL_BITS))) {
- miComputeCompositeClip(pGC, pDrawable);
- }
-
- DMX_GC_FUNC_EPILOGUE(pGC);
-}
-
-/** Set the values in the graphics context on the back-end server
- * associated with \a pGC's screen. */
-void dmxChangeGC(GCPtr pGC, unsigned long mask)
-{
- ScreenPtr pScreen = pGC->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
- XGCValues v;
-
- DMX_GC_FUNC_PROLOGUE(pGC);
-#if 0
- pGC->funcs->ChangeGC(pGC, mask);
-#endif
-
- /* Handle "magic special case" from CreateGC */
- if (pGCPriv->msc) {
- /* The "magic special case" is used to handle the case where a
- * foreground pixel is set when the GC is created so that a
- * "pseudo default-tile" can be created and used in case the
- * fillstyle was set to FillTiled. This specific case is tested
- * in xtest (XCreateGC test #3). What has happened in dix by
- * the time it reaches here is (1) the pGC->tile.pixel has been
- * set to pGC->fgPixel and pGC->tileIsPixel is set, (2) if a
- * tile has also been set, then pGC->tileIsPixel is unset and
- * pGC->tile.pixmap is initialized; else, the default tile is
- * created and pGC->tileIsPixel is unset and pGC->tile.pixmap is
- * initialized to the "pseudo default-tile". In either case,
- * pGC->tile.pixmap is set; however, in the "magic special case"
- * the mask is not updated to allow us to detect that we should
- * initialize the GCTile in the back-end server. Thus, we catch
- * this case in dmxCreateGC and add GCTile to the mask here.
- * Are there any cases that I've missed?
- */
-
- /* Make sure that the tile.pixmap is set, just in case the user
- * set GCTile in the mask but forgot to set vals.pixmap
- */
- if (pGC->tile.pixmap) mask |= GCTile;
-
- /* This only happens once when the GC is created */
- pGCPriv->msc = FALSE;
- }
-
- /* Update back-end server's gc */
- if (mask & GCFunction) v.function = pGC->alu;
- if (mask & GCPlaneMask) v.plane_mask = pGC->planemask;
- if (mask & GCForeground) v.foreground = pGC->fgPixel;
- if (mask & GCBackground) v.background = pGC->bgPixel;
- if (mask & GCLineWidth) v.line_width = pGC->lineWidth;
- if (mask & GCLineStyle) v.line_style = pGC->lineStyle;
- if (mask & GCCapStyle) v.cap_style = pGC->capStyle;
- if (mask & GCJoinStyle) v.join_style = pGC->joinStyle;
- if (mask & GCFillStyle) v.fill_style = pGC->fillStyle;
- if (mask & GCFillRule) v.fill_rule = pGC->fillRule;
- if (mask & GCTile) {
- if (pGC->tileIsPixel) {
- mask &= ~GCTile;
- } else {
- dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->tile.pixmap);
- v.tile = (Drawable)pPixPriv->pixmap;
- }
- }
- if (mask & GCStipple) {
- dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->stipple);
- v.stipple = (Drawable)pPixPriv->pixmap;
- }
- if (mask & GCTileStipXOrigin) v.ts_x_origin = pGC->patOrg.x;
- if (mask & GCTileStipYOrigin) v.ts_y_origin = pGC->patOrg.y;
- if (mask & GCFont) {
- if (dmxScreen->beDisplay) {
- dmxFontPrivPtr pFontPriv;
- pFontPriv = FontGetPrivate(pGC->font, dmxFontPrivateIndex);
- v.font = pFontPriv->font[pScreen->myNum]->fid;
- } else {
- mask &= ~GCFont;
- }
- }
- if (mask & GCSubwindowMode) v.subwindow_mode = pGC->subWindowMode;
-
- /* Graphics exposures are not needed on the back-ends since they can
- be generated on the front-end thereby saving bandwidth. */
- if (mask & GCGraphicsExposures) mask &= ~GCGraphicsExposures;
-
- if (mask & GCClipXOrigin) v.clip_x_origin = pGC->clipOrg.x;
- if (mask & GCClipYOrigin) v.clip_y_origin = pGC->clipOrg.y;
- if (mask & GCClipMask) mask &= ~GCClipMask; /* See ChangeClip */
- if (mask & GCDashOffset) v.dash_offset = pGC->dashOffset;
- if (mask & GCDashList) {
- mask &= ~GCDashList;
- if (dmxScreen->beDisplay)
- XSetDashes(dmxScreen->beDisplay, pGCPriv->gc,
- pGC->dashOffset, (char *)pGC->dash,
- pGC->numInDashList);
- }
- if (mask & GCArcMode) v.arc_mode = pGC->arcMode;
-
- if (mask && dmxScreen->beDisplay) {
- XChangeGC(dmxScreen->beDisplay, pGCPriv->gc, mask, &v);
- dmxSync(dmxScreen, FALSE);
- }
-
- DMX_GC_FUNC_EPILOGUE(pGC);
-}
-
-/** Copy \a pGCSrc to \a pGCDst on the back-end server associated with
- * \a pGCSrc's screen. */
-void dmxCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst)
-{
- ScreenPtr pScreen = pGCSrc->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- dmxGCPrivPtr pGCSrcPriv = DMX_GET_GC_PRIV(pGCSrc);
- dmxGCPrivPtr pGCDstPriv = DMX_GET_GC_PRIV(pGCDst);
-
- DMX_GC_FUNC_PROLOGUE(pGCDst);
- pGCDst->funcs->CopyGC(pGCSrc, changes, pGCDst);
-
- /* Copy the GC on the back-end server */
- if (dmxScreen->beDisplay)
- XCopyGC(dmxScreen->beDisplay, pGCSrcPriv->gc, changes, pGCDstPriv->gc);
-
- DMX_GC_FUNC_EPILOGUE(pGCDst);
-}
-
-/** Free the \a pGC on the back-end server. */
-Bool dmxBEFreeGC(GCPtr pGC)
-{
- ScreenPtr pScreen = pGC->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
-
- if (pGCPriv->gc) {
- XFreeGC(dmxScreen->beDisplay, pGCPriv->gc);
- pGCPriv->gc = NULL;
- return TRUE;
- }
-
- return FALSE;
-}
-
-/** Destroy the graphics context, \a pGC and free the corresponding GC
- * on the back-end server. */
-void dmxDestroyGC(GCPtr pGC)
-{
- ScreenPtr pScreen = pGC->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
-
- DMX_GC_FUNC_PROLOGUE(pGC);
-
- /* Free the GC on the back-end server */
- if (dmxScreen->beDisplay)
- dmxBEFreeGC(pGC);
-
- pGC->funcs->DestroyGC(pGC);
- DMX_GC_FUNC_EPILOGUE(pGC);
-}
-
-/** Change the clip rects for a GC. */
-void dmxChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
-{
- ScreenPtr pScreen = pGC->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
- XRectangle *pRects;
- BoxPtr pBox;
- int i, nRects;
-
- DMX_GC_FUNC_PROLOGUE(pGC);
- pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
-
- /* Set the client clip on the back-end server */
- switch (pGC->clientClipType) {
- case CT_NONE:
- if (dmxScreen->beDisplay)
- XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None);
- break;
-
- case CT_REGION:
- if (dmxScreen->beDisplay) {
- nRects = RegionNumRects((RegionPtr)pGC->clientClip);
- pRects = malloc(nRects * sizeof(*pRects));
- pBox = RegionRects((RegionPtr)pGC->clientClip);
-
- for (i = 0; i < nRects; i++) {
- pRects[i].x = pBox[i].x1;
- pRects[i].y = pBox[i].y1;
- pRects[i].width = pBox[i].x2 - pBox[i].x1;
- pRects[i].height = pBox[i].y2 - pBox[i].y1;
- }
-
- XSetClipRectangles(dmxScreen->beDisplay, pGCPriv->gc,
- pGC->clipOrg.x, pGC->clipOrg.y,
- pRects, nRects, Unsorted);
-
- free(pRects);
- }
- break;
-
- case CT_PIXMAP:
- case CT_UNSORTED:
- case CT_YSORTED:
- case CT_YXSORTED:
- case CT_YXBANDED:
- /* These clip types are condensed down to either NONE or REGION
- in the mi code */
- break;
- }
-
- DMX_GC_FUNC_EPILOGUE(pGC);
-}
-
-/** Destroy a GC's clip rects. */
-void dmxDestroyClip(GCPtr pGC)
-{
- ScreenPtr pScreen = pGC->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
-
- DMX_GC_FUNC_PROLOGUE(pGC);
- pGC->funcs->DestroyClip(pGC);
-
- /* Set the client clip on the back-end server to None */
- if (dmxScreen->beDisplay)
- XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None);
-
- DMX_GC_FUNC_EPILOGUE(pGC);
-}
-
-/** Copy a GC's clip rects. */
-void dmxCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
-{
- DMX_GC_FUNC_PROLOGUE(pGCDst);
- pGCDst->funcs->CopyClip(pGCDst, pGCSrc);
- DMX_GC_FUNC_EPILOGUE(pGCDst);
-}
+/*
+ * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+/** \file
+ * This file provides support for GCs. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxsync.h"
+#include "dmxgc.h"
+#include "dmxgcops.h"
+#include "dmxpixmap.h"
+#include "dmxfont.h"
+
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "migc.h"
+
+static GCFuncs dmxGCFuncs = {
+ dmxValidateGC,
+ dmxChangeGC,
+ dmxCopyGC,
+ dmxDestroyGC,
+ dmxChangeClip,
+ dmxDestroyClip,
+ dmxCopyClip,
+};
+
+static GCOps dmxGCOps = {
+ dmxFillSpans,
+ dmxSetSpans,
+ dmxPutImage,
+ dmxCopyArea,
+ dmxCopyPlane,
+ dmxPolyPoint,
+ dmxPolylines,
+ dmxPolySegment,
+ dmxPolyRectangle,
+ dmxPolyArc,
+ dmxFillPolygon,
+ dmxPolyFillRect,
+ dmxPolyFillArc,
+ dmxPolyText8,
+ dmxPolyText16,
+ dmxImageText8,
+ dmxImageText16,
+ dmxImageGlyphBlt,
+ dmxPolyGlyphBlt,
+ dmxPushPixels
+};
+
+/** Initialize the GC on \a pScreen */
+Bool dmxInitGC(ScreenPtr pScreen)
+{
+ if (!dixRegisterPrivateKey(&dmxGCPrivateKeyRec, PRIVATE_GC, sizeof(dmxGCPrivRec)))
+ return FALSE;
+ return TRUE;
+}
+
+/** Create the GC on the back-end server. */
+void dmxBECreateGC(ScreenPtr pScreen, GCPtr pGC)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
+ int i;
+
+ for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
+ if (pGC->depth == dmxScreen->bePixmapFormats[i].depth) {
+ unsigned long mask;
+ XGCValues gcvals;
+
+ mask = GCGraphicsExposures;
+ gcvals.graphics_exposures = FALSE;
+
+ /* Create GC in the back-end servers */
+ pGCPriv->gc = XCreateGC(dmxScreen->beDisplay,
+ dmxScreen->scrnDefDrawables[i],
+ mask, &gcvals);
+ break;
+ }
+ }
+}
+
+/** Create a graphics context on the back-end server associated /a pGC's
+ * screen. */
+Bool dmxCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
+ Bool ret;
+
+ DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
+ if ((ret = pScreen->CreateGC(pGC))) {
+ /* Save the old funcs */
+ pGCPriv->funcs = pGC->funcs;
+ pGCPriv->ops = NULL;
+
+ pGC->funcs = &dmxGCFuncs;
+
+ if (dmxScreen->beDisplay) {
+ dmxBECreateGC(pScreen, pGC);
+ } else {
+ pGCPriv->gc = NULL;
+ }
+
+ /* Check for "magic special case"
+ * 1. see CreateGC in dix/gc.c for more info
+ * 2. see dmxChangeGC for more info
+ */
+ pGCPriv->msc = (!pGC->tileIsPixel && !pGC->tile.pixmap);
+ }
+ DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
+
+ return ret;
+}
+
+/** Validate a graphics context, \a pGC, locally in the DMX server and
+ * recompute the composite clip, if necessary. */
+void dmxValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
+
+ DMX_GC_FUNC_PROLOGUE(pGC);
+#if 0
+ pGC->funcs->ValidateGC(pGC, changes, pDrawable);
+#endif
+
+ if (pDrawable->type == DRAWABLE_WINDOW ||
+ pDrawable->type == DRAWABLE_PIXMAP) {
+ /* Save the old ops, since we're about to change the ops in the
+ * epilogue.
+ */
+ pGCPriv->ops = pGC->ops;
+ } else {
+ pGCPriv->ops = NULL;
+ }
+
+ /* If the client clip is different or moved OR the subwindowMode has
+ * changed OR the window's clip has changed since the last
+ * validation, then we need to recompute the composite clip.
+ */
+ if ((changes & (GCClipXOrigin |
+ GCClipYOrigin |
+ GCClipMask |
+ GCSubwindowMode)) ||
+ (pDrawable->serialNumber !=
+ (pGC->serialNumber & DRAWABLE_SERIAL_BITS))) {
+ miComputeCompositeClip(pGC, pDrawable);
+ }
+
+ DMX_GC_FUNC_EPILOGUE(pGC);
+}
+
+/** Set the values in the graphics context on the back-end server
+ * associated with \a pGC's screen. */
+void dmxChangeGC(GCPtr pGC, unsigned long mask)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
+ XGCValues v;
+
+ DMX_GC_FUNC_PROLOGUE(pGC);
+#if 0
+ pGC->funcs->ChangeGC(pGC, mask);
+#endif
+
+ /* Handle "magic special case" from CreateGC */
+ if (pGCPriv->msc) {
+ /* The "magic special case" is used to handle the case where a
+ * foreground pixel is set when the GC is created so that a
+ * "pseudo default-tile" can be created and used in case the
+ * fillstyle was set to FillTiled. This specific case is tested
+ * in xtest (XCreateGC test #3). What has happened in dix by
+ * the time it reaches here is (1) the pGC->tile.pixel has been
+ * set to pGC->fgPixel and pGC->tileIsPixel is set, (2) if a
+ * tile has also been set, then pGC->tileIsPixel is unset and
+ * pGC->tile.pixmap is initialized; else, the default tile is
+ * created and pGC->tileIsPixel is unset and pGC->tile.pixmap is
+ * initialized to the "pseudo default-tile". In either case,
+ * pGC->tile.pixmap is set; however, in the "magic special case"
+ * the mask is not updated to allow us to detect that we should
+ * initialize the GCTile in the back-end server. Thus, we catch
+ * this case in dmxCreateGC and add GCTile to the mask here.
+ * Are there any cases that I've missed?
+ */
+
+ /* Make sure that the tile.pixmap is set, just in case the user
+ * set GCTile in the mask but forgot to set vals.pixmap
+ */
+ if (pGC->tile.pixmap) mask |= GCTile;
+
+ /* This only happens once when the GC is created */
+ pGCPriv->msc = FALSE;
+ }
+
+ /* Update back-end server's gc */
+ if (mask & GCFunction) v.function = pGC->alu;
+ if (mask & GCPlaneMask) v.plane_mask = pGC->planemask;
+ if (mask & GCForeground) v.foreground = pGC->fgPixel;
+ if (mask & GCBackground) v.background = pGC->bgPixel;
+ if (mask & GCLineWidth) v.line_width = pGC->lineWidth;
+ if (mask & GCLineStyle) v.line_style = pGC->lineStyle;
+ if (mask & GCCapStyle) v.cap_style = pGC->capStyle;
+ if (mask & GCJoinStyle) v.join_style = pGC->joinStyle;
+ if (mask & GCFillStyle) v.fill_style = pGC->fillStyle;
+ if (mask & GCFillRule) v.fill_rule = pGC->fillRule;
+ if (mask & GCTile) {
+ if (pGC->tileIsPixel) {
+ mask &= ~GCTile;
+ } else {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->tile.pixmap);
+ v.tile = (Drawable)pPixPriv->pixmap;
+ }
+ }
+ if (mask & GCStipple) {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->stipple);
+ v.stipple = (Drawable)pPixPriv->pixmap;
+ }
+ if (mask & GCTileStipXOrigin) v.ts_x_origin = pGC->patOrg.x;
+ if (mask & GCTileStipYOrigin) v.ts_y_origin = pGC->patOrg.y;
+ if (mask & GCFont) {
+ if (dmxScreen->beDisplay) {
+ dmxFontPrivPtr pFontPriv;
+ pFontPriv = FontGetPrivate(pGC->font, dmxFontPrivateIndex);
+ v.font = pFontPriv->font[pScreen->myNum]->fid;
+ } else {
+ mask &= ~GCFont;
+ }
+ }
+ if (mask & GCSubwindowMode) v.subwindow_mode = pGC->subWindowMode;
+
+ /* Graphics exposures are not needed on the back-ends since they can
+ be generated on the front-end thereby saving bandwidth. */
+ if (mask & GCGraphicsExposures) mask &= ~GCGraphicsExposures;
+
+ if (mask & GCClipXOrigin) v.clip_x_origin = pGC->clipOrg.x;
+ if (mask & GCClipYOrigin) v.clip_y_origin = pGC->clipOrg.y;
+ if (mask & GCClipMask) mask &= ~GCClipMask; /* See ChangeClip */
+ if (mask & GCDashOffset) v.dash_offset = pGC->dashOffset;
+ if (mask & GCDashList) {
+ mask &= ~GCDashList;
+ if (dmxScreen->beDisplay)
+ XSetDashes(dmxScreen->beDisplay, pGCPriv->gc,
+ pGC->dashOffset, (char *)pGC->dash,
+ pGC->numInDashList);
+ }
+ if (mask & GCArcMode) v.arc_mode = pGC->arcMode;
+
+ if (mask && dmxScreen->beDisplay) {
+ XChangeGC(dmxScreen->beDisplay, pGCPriv->gc, mask, &v);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_GC_FUNC_EPILOGUE(pGC);
+}
+
+/** Copy \a pGCSrc to \a pGCDst on the back-end server associated with
+ * \a pGCSrc's screen. */
+void dmxCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst)
+{
+ ScreenPtr pScreen = pGCSrc->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxGCPrivPtr pGCSrcPriv = DMX_GET_GC_PRIV(pGCSrc);
+ dmxGCPrivPtr pGCDstPriv = DMX_GET_GC_PRIV(pGCDst);
+
+ DMX_GC_FUNC_PROLOGUE(pGCDst);
+ pGCDst->funcs->CopyGC(pGCSrc, changes, pGCDst);
+
+ /* Copy the GC on the back-end server */
+ if (dmxScreen->beDisplay)
+ XCopyGC(dmxScreen->beDisplay, pGCSrcPriv->gc, changes, pGCDstPriv->gc);
+
+ DMX_GC_FUNC_EPILOGUE(pGCDst);
+}
+
+/** Free the \a pGC on the back-end server. */
+Bool dmxBEFreeGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
+
+ if (pGCPriv->gc) {
+ XFreeGC(dmxScreen->beDisplay, pGCPriv->gc);
+ pGCPriv->gc = NULL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** Destroy the graphics context, \a pGC and free the corresponding GC
+ * on the back-end server. */
+void dmxDestroyGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+ DMX_GC_FUNC_PROLOGUE(pGC);
+
+ /* Free the GC on the back-end server */
+ if (dmxScreen->beDisplay)
+ dmxBEFreeGC(pGC);
+
+ pGC->funcs->DestroyGC(pGC);
+ DMX_GC_FUNC_EPILOGUE(pGC);
+}
+
+/** Change the clip rects for a GC. */
+void dmxChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
+ XRectangle *pRects;
+ BoxPtr pBox;
+ int i, nRects;
+
+ DMX_GC_FUNC_PROLOGUE(pGC);
+ pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
+
+ /* Set the client clip on the back-end server */
+ switch (pGC->clientClipType) {
+ case CT_NONE:
+ if (dmxScreen->beDisplay)
+ XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None);
+ break;
+
+ case CT_REGION:
+ if (dmxScreen->beDisplay) {
+ nRects = RegionNumRects((RegionPtr)pGC->clientClip);
+ pRects = malloc(nRects * sizeof(*pRects));
+ pBox = RegionRects((RegionPtr)pGC->clientClip);
+
+ for (i = 0; i < nRects; i++) {
+ pRects[i].x = pBox[i].x1;
+ pRects[i].y = pBox[i].y1;
+ pRects[i].width = pBox[i].x2 - pBox[i].x1;
+ pRects[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+
+ XSetClipRectangles(dmxScreen->beDisplay, pGCPriv->gc,
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ pRects, nRects, Unsorted);
+
+ free(pRects);
+ }
+ break;
+
+ case CT_PIXMAP:
+ /* Condensed down to REGION in the mi code */
+ break;
+ }
+
+ DMX_GC_FUNC_EPILOGUE(pGC);
+}
+
+/** Destroy a GC's clip rects. */
+void dmxDestroyClip(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC);
+
+ DMX_GC_FUNC_PROLOGUE(pGC);
+ pGC->funcs->DestroyClip(pGC);
+
+ /* Set the client clip on the back-end server to None */
+ if (dmxScreen->beDisplay)
+ XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None);
+
+ DMX_GC_FUNC_EPILOGUE(pGC);
+}
+
+/** Copy a GC's clip rects. */
+void dmxCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
+{
+ DMX_GC_FUNC_PROLOGUE(pGCDst);
+ pGCDst->funcs->CopyClip(pGCDst, pGCSrc);
+ DMX_GC_FUNC_EPILOGUE(pGCDst);
+}
diff --git a/xorg-server/hw/dmx/input/dmxinputinit.c b/xorg-server/hw/dmx/input/dmxinputinit.c
index 4b10ecb17..5cbd620c9 100644
--- a/xorg-server/hw/dmx/input/dmxinputinit.c
+++ b/xorg-server/hw/dmx/input/dmxinputinit.c
@@ -1,1306 +1,1274 @@
-/*
- * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation on the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
- * Authors:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- * This file provides generic input support. Functions here set up
- * input and lead to the calling of low-level device drivers for
- * input. */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#define DMX_WINDOW_DEBUG 0
-
-#include "dmxinputinit.h"
-#include "dmxextension.h" /* For dmxInputCount */
-
-#include "dmxdummy.h"
-#include "dmxbackend.h"
-#include "dmxconsole.h"
-#include "dmxcommon.h"
-#include "dmxevents.h"
-#include "dmxmotion.h"
-#include "dmxprop.h"
-#include "config/dmxconfig.h"
-#include "dmxcursor.h"
-
-#include "lnx-keyboard.h"
-#include "lnx-ms.h"
-#include "lnx-ps2.h"
-#include "usb-keyboard.h"
-#include "usb-mouse.h"
-#include "usb-other.h"
-#include "usb-common.h"
-
-#include "dmxsigio.h"
-#include "dmxarg.h"
-
-#include "inputstr.h"
-#include "input.h"
-#include "mipointer.h"
-#include "windowstr.h"
-#include "mi.h"
-#include "xkbsrv.h"
-
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "exevents.h"
-#include "extinit.h"
-
-DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard;
-
-static DMXLocalInputInfoRec DMXDummyMou = {
- "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
- NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo
-};
-
-static DMXLocalInputInfoRec DMXDummyKbd = {
- "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
- NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo
-};
-
-static DMXLocalInputInfoRec DMXBackendMou = {
- "backend-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_BACKEND, 2,
- dmxBackendCreatePrivate, dmxBackendDestroyPrivate,
- dmxBackendInit, NULL, dmxBackendLateReInit, dmxBackendMouGetInfo,
- dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition,
- NULL, NULL, NULL,
- dmxBackendCollectEvents, dmxBackendProcessInput, dmxBackendFunctions, NULL,
- dmxCommonMouCtrl
-};
-
-static DMXLocalInputInfoRec DMXBackendKbd = {
- "backend-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_BACKEND,
- 1, /* With backend-mou or console-mou */
- dmxCommonCopyPrivate, NULL,
- dmxBackendInit, NULL, NULL, dmxBackendKbdGetInfo,
- dmxCommonKbdOn, dmxCommonKbdOff, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
-};
-
-static DMXLocalInputInfoRec DMXConsoleMou = {
- "console-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_CONSOLE, 2,
- dmxConsoleCreatePrivate, dmxConsoleDestroyPrivate,
- dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleMouGetInfo,
- dmxCommonMouOn, dmxCommonMouOff, dmxConsoleUpdatePosition,
- NULL, NULL, NULL,
- dmxConsoleCollectEvents, NULL, dmxConsoleFunctions, dmxConsoleUpdateInfo,
- dmxCommonMouCtrl
-};
-
-static DMXLocalInputInfoRec DMXConsoleKbd = {
- "console-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_CONSOLE,
- 1, /* With backend-mou or console-mou */
- dmxCommonCopyPrivate, NULL,
- dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo,
- dmxCommonKbdOn, dmxCommonKbdOff, NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
-};
-
-static DMXLocalInputInfoRec DMXCommonOth = {
- "common-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_COMMON, 1,
- dmxCommonCopyPrivate, NULL,
- NULL, NULL, NULL, dmxCommonOthGetInfo,
- dmxCommonOthOn, dmxCommonOthOff
-};
-
-
-static DMXLocalInputInfoRec DMXLocalDevices[] = {
- /* Dummy drivers that can compile on any OS */
-#ifdef __linux__
- /* Linux-specific drivers */
- {
- "kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
- kbdLinuxCreatePrivate, kbdLinuxDestroyPrivate,
- kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo,
- kbdLinuxOn, kbdLinuxOff, NULL,
- kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch,
- kbdLinuxRead, NULL, NULL, NULL,
- NULL, kbdLinuxCtrl, kbdLinuxBell
- },
- {
- "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
- msLinuxCreatePrivate, msLinuxDestroyPrivate,
- msLinuxInit, NULL, NULL, msLinuxGetInfo,
- msLinuxOn, msLinuxOff, NULL,
- msLinuxVTPreSwitch, msLinuxVTPostSwitch, NULL,
- msLinuxRead
- },
- {
- "ps2", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
- ps2LinuxCreatePrivate, ps2LinuxDestroyPrivate,
- ps2LinuxInit, NULL, NULL, ps2LinuxGetInfo,
- ps2LinuxOn, ps2LinuxOff, NULL,
- ps2LinuxVTPreSwitch, ps2LinuxVTPostSwitch, NULL,
- ps2LinuxRead
- },
-#endif
-#ifdef __linux__
- /* USB drivers, currently only for
- Linux, but relatively easy to port to
- other OSs */
- {
- "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
- usbCreatePrivate, usbDestroyPrivate,
- kbdUSBInit, NULL, NULL, kbdUSBGetInfo,
- kbdUSBOn, usbOff, NULL,
- NULL, NULL, NULL,
- kbdUSBRead, NULL, NULL, NULL,
- NULL, kbdUSBCtrl
- },
- {
- "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
- usbCreatePrivate, usbDestroyPrivate,
- mouUSBInit, NULL, NULL, mouUSBGetInfo,
- mouUSBOn, usbOff, NULL,
- NULL, NULL, NULL,
- mouUSBRead
- },
- {
- "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1,
- usbCreatePrivate, usbDestroyPrivate,
- othUSBInit, NULL, NULL, othUSBGetInfo,
- othUSBOn, usbOff, NULL,
- NULL, NULL, NULL,
- othUSBRead
- },
-#endif
- {
- "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
- NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo
- },
- {
- "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
- NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo
- },
- { NULL } /* Must be last */
-};
-
-
-#if 11 /*BP*/
-void
-DDXRingBell(int volume, int pitch, int duration)
-{
- /* NO-OP */
-}
-
-/* taken from kdrive/src/kinput.c: */
-static void
-dmxKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl)
-{
-#if 0
- KdKeyboardInfo *ki;
-
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki->dixdev && ki->dixdev->id == pDevice->id)
- break;
- }
-
- if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver)
- return;
-
- KdSetLeds(ki, ctrl->leds);
- ki->bellPitch = ctrl->bell_pitch;
- ki->bellDuration = ctrl->bell_duration;
-#endif
-}
-
-/* taken from kdrive/src/kinput.c: */
-static void
-dmxBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
-{
-#if 0
- KeybdCtrl *ctrl = arg;
- KdKeyboardInfo *ki = NULL;
-
- for (ki = kdKeyboards; ki; ki = ki->next) {
- if (ki->dixdev && ki->dixdev->id == pDev->id)
- break;
- }
-
- if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver)
- return;
-
- KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration);
-#endif
-}
-
-#endif /*BP*/
-
-static void _dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal,
- PtrCtrl *ctrl)
-{
- if (!dmxLocal) return;
- dmxLocal->mctrl = *ctrl;
- if (dmxLocal->mCtrl) dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl);
-}
-
-/** Change the pointer control information for the \a pDevice. If the
- * device sends core events, then also change the control information
- * for all of the pointer devices that send core events. */
-void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl)
-{
- GETDMXLOCALFROMPDEVICE;
- int i, j;
-
- if (dmxLocal->sendsCore) { /* Do for all core devices */
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- if (dmxInput->detached) continue;
- for (j = 0; j < dmxInput->numDevs; j++)
- if (dmxInput->devs[j]->sendsCore)
- _dmxChangePointerControl(dmxInput->devs[j], ctrl);
- }
- } else { /* Do for this device only */
- _dmxChangePointerControl(dmxLocal, ctrl);
- }
-}
-
-static void _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal,
- KeybdCtrl *ctrl)
-{
- dmxLocal->kctrl = *ctrl;
- if (dmxLocal->kCtrl) {
- dmxLocal->kCtrl(&dmxLocal->pDevice->public, ctrl);
- if (dmxLocal->pDevice->kbdfeed) {
- XkbEventCauseRec cause;
- XkbSetCauseUnknown(&cause);
- /* Generate XKB events, as necessary */
- XkbUpdateIndicators(dmxLocal->pDevice, XkbAllIndicatorsMask, False,
- NULL, &cause);
- }
- }
-}
-
-
-/** Change the keyboard control information for the \a pDevice. If the
- * device sends core events, then also change the control information
- * for all of the keyboard devices that send core events. */
-void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl)
-{
- GETDMXLOCALFROMPDEVICE;
- int i, j;
-
- if (dmxLocal->sendsCore) { /* Do for all core devices */
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- if (dmxInput->detached) continue;
- for (j = 0; j < dmxInput->numDevs; j++)
- if (dmxInput->devs[j]->sendsCore)
- _dmxKeyboardKbdCtrlProc(dmxInput->devs[j], ctrl);
- }
- } else { /* Do for this device only */
- _dmxKeyboardKbdCtrlProc(dmxLocal, ctrl);
- }
-}
-
-static void _dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent)
-{
- if (dmxLocal->kBell) dmxLocal->kBell(&dmxLocal->pDevice->public,
- percent,
- dmxLocal->kctrl.bell,
- dmxLocal->kctrl.bell_pitch,
- dmxLocal->kctrl.bell_duration);
-}
-
-/** Sound the bell on the device. If the device send core events, then
- * sound the bell on all of the devices that send core events. */
-void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice,
- pointer ctrl, int unknown)
-{
- GETDMXLOCALFROMPDEVICE;
- int i, j;
-
- if (dmxLocal->sendsCore) { /* Do for all core devices */
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- if (dmxInput->detached) continue;
- for (j = 0; j < dmxInput->numDevs; j++)
- if (dmxInput->devs[j]->sendsCore)
- _dmxKeyboardBellProc(dmxInput->devs[j], percent);
- }
- } else { /* Do for this device only */
- _dmxKeyboardBellProc(dmxLocal, percent);
- }
-}
-
-static void dmxKeyboardFreeNames(XkbComponentNamesPtr names)
-{
- if (names->keycodes) XFree(names->keycodes);
- if (names->types) XFree(names->types);
- if (names->compat) XFree(names->compat);
- if (names->symbols) XFree(names->symbols);
- if (names->geometry) XFree(names->geometry);
-}
-
-
-static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info)
-{
- GETDMXINPUTFROMPDEVICE;
- XkbRMLVOSet rmlvo;
-
- rmlvo.rules = dmxConfigGetXkbRules();
- rmlvo.model = dmxConfigGetXkbModel();
- rmlvo.layout = dmxConfigGetXkbLayout();
- rmlvo.variant = dmxConfigGetXkbVariant();
- rmlvo.options = dmxConfigGetXkbOptions();
-
- XkbSetRulesDflts(&rmlvo);
- if (!info->force && (dmxInput->keycodes
- || dmxInput->symbols
- || dmxInput->geometry)) {
- if (info->freenames) dmxKeyboardFreeNames(&info->names);
- info->freenames = 0;
- info->names.keycodes = dmxInput->keycodes;
- info->names.types = NULL;
- info->names.compat = NULL;
- info->names.symbols = dmxInput->symbols;
- info->names.geometry = dmxInput->geometry;
-
- dmxLogInput(dmxInput, "XKEYBOARD: From command line: %s",
- info->names.keycodes);
- if (info->names.symbols && *info->names.symbols)
- dmxLogInputCont(dmxInput, " %s", info->names.symbols);
- if (info->names.geometry && *info->names.geometry)
- dmxLogInputCont(dmxInput, " %s", info->names.geometry);
- dmxLogInputCont(dmxInput, "\n");
- } else if (info->names.keycodes) {
- dmxLogInput(dmxInput, "XKEYBOARD: From device: %s",
- info->names.keycodes);
- if (info->names.symbols && *info->names.symbols)
- dmxLogInputCont(dmxInput, " %s", info->names.symbols);
- if (info->names.geometry && *info->names.geometry)
- dmxLogInputCont(dmxInput, " %s", info->names.geometry);
- dmxLogInputCont(dmxInput, "\n");
- } else {
- dmxLogInput(dmxInput, "XKEYBOARD: Defaults: %s %s %s %s %s\n",
- dmxConfigGetXkbRules(),
- dmxConfigGetXkbLayout(),
- dmxConfigGetXkbModel(),
- dmxConfigGetXkbVariant()
- ? dmxConfigGetXkbVariant() : "",
- dmxConfigGetXkbOptions()
- ? dmxConfigGetXkbOptions() : "");
- }
- InitKeyboardDeviceStruct(pDevice, &rmlvo,
- dmxKeyboardBellProc,
- dmxKeyboardKbdCtrlProc);
-
- if (info->freenames) dmxKeyboardFreeNames(&info->names);
-
- return Success;
-}
-
-
-static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
-{
- GETDMXINPUTFROMPDEVICE;
- int fd;
- DMXLocalInitInfo info;
- int i;
- Atom btn_labels[MAX_BUTTONS] = {0}; /* FIXME */
- Atom axis_labels[MAX_VALUATORS] = {0}; /* FIXME */
-
- if (dmxInput->detached) return Success;
-
- memset(&info, 0, sizeof(info));
- switch (what) {
- case DEVICE_INIT:
- if (dmxLocal->init)
- dmxLocal->init(pDev);
- if (dmxLocal->get_info)
- dmxLocal->get_info(pDev, &info);
- if (info.keyboard) { /* XKEYBOARD makes this a special case */
- dmxKeyboardOn(pDevice, &info);
- break;
- }
- if (info.keyClass) {
- XkbRMLVOSet rmlvo;
-
- rmlvo.rules = dmxConfigGetXkbRules();
- rmlvo.model = dmxConfigGetXkbModel();
- rmlvo.layout = dmxConfigGetXkbLayout();
- rmlvo.variant = dmxConfigGetXkbVariant();
- rmlvo.options = dmxConfigGetXkbOptions();
-
- InitKeyboardDeviceStruct(pDevice,
- &rmlvo,
- dmxBell, dmxKbdCtrl);
- }
- if (info.buttonClass) {
- InitButtonClassDeviceStruct(pDevice, info.numButtons,
- btn_labels, info.map);
- }
- if (info.valuatorClass) {
- if (info.numRelAxes && dmxLocal->sendsCore) {
- InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
- axis_labels,
- GetMaximumEventsNum(),
- Relative);
- for (i = 0; i < info.numRelAxes; i++)
- InitValuatorAxisStruct(pDevice, i, axis_labels[i],
- info.minval[i], info.maxval[i],
- info.res[i],
- info.minres[i], info.maxres[i],
- Relative);
- } else if (info.numRelAxes) {
- InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
- axis_labels,
- dmxPointerGetMotionBufferSize(),
- Relative);
- for (i = 0; i < info.numRelAxes; i++)
- InitValuatorAxisStruct(pDevice, i, axis_labels[i],
- info.minval[i],
- info.maxval[i], info.res[i],
- info.minres[i], info.maxres[i],
- Relative);
- } else if (info.numAbsAxes) {
- InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes,
- axis_labels,
- dmxPointerGetMotionBufferSize(),
- Absolute);
- for (i = 0; i < info.numAbsAxes; i++)
- InitValuatorAxisStruct(pDevice, i,
- axis_labels[i],
- info.minval[i], info.maxval[i],
- info.res[i], info.minres[i],
- info.maxres[i], Absolute);
- }
- }
- if (info.focusClass) InitFocusClassDeviceStruct(pDevice);
- if (info.proximityClass) InitProximityClassDeviceStruct(pDevice);
- if (info.ptrFeedbackClass)
- InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl);
- if (info.intFeedbackClass || info.strFeedbackClass)
- dmxLog(dmxWarning,
- "Integer and string feedback not supported for %s\n",
- pDevice->name);
- if (!info.keyboard && (info.ledFeedbackClass || info.belFeedbackClass))
- dmxLog(dmxWarning,
- "Led and bel feedback not supported for non-keyboard %s\n",
- pDevice->name);
- break;
- case DEVICE_ON:
- if (!pDev->on) {
- if (dmxLocal->on && (fd = dmxLocal->on(pDev)) >= 0)
- dmxSigioRegister(dmxInput, fd);
- pDev->on = TRUE;
- }
- break;
- case DEVICE_OFF:
- case DEVICE_CLOSE:
- /* This can get called twice consecutively: once for a
- * detached screen (DEVICE_OFF), and then again at server
- * generation time (DEVICE_CLOSE). */
- if (pDev->on) {
- dmxSigioUnregister(dmxInput);
- if (dmxLocal->off) dmxLocal->off(pDev);
- pDev->on = FALSE;
- }
- break;
- }
- if (info.keySyms.map && info.freemap) {
- XFree(info.keySyms.map);
- info.keySyms.map = NULL;
- }
- if (info.xkb) XkbFreeKeyboard(info.xkb, 0, True);
- return Success;
-}
-
-static void dmxProcessInputEvents(DMXInputInfo *dmxInput)
-{
- int i;
-
- mieqProcessInputEvents();
-#if 00 /*BP*/
- miPointerUpdate();
-#endif
- if (dmxInput->detached)
- return;
- for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
- if (dmxInput->devs[i]->process_input) {
-#if 11 /*BP*/
- miPointerUpdateSprite(dmxInput->devs[i]->pDevice);
-#endif
- dmxInput->devs[i]->process_input(dmxInput->devs[i]->private);
- }
-
-#if 11 /*BP*/
- mieqProcessInputEvents();
-#endif
-}
-
-static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput,
- DMXUpdateType type,
- WindowPtr pWindow)
-{
- int i;
-
-#ifdef PANORAMIX
- if (!noPanoramiXExtension && pWindow && pWindow->parent != screenInfo.screens[0]->root)
- return;
-#endif
-#if DMX_WINDOW_DEBUG
- {
- const char *name = "Unknown";
- switch (type) {
- case DMX_UPDATE_REALIZE: name = "Realize"; break;
- case DMX_UPDATE_UNREALIZE: name = "Unrealize"; break;
- case DMX_UPDATE_RESTACK: name = "Restack"; break;
- case DMX_UPDATE_COPY: name = "Copy"; break;
- case DMX_UPDATE_RESIZE: name = "Resize"; break;
- case DMX_UPDATE_REPARENT: name = "Repaint"; break;
- }
- dmxLog(dmxDebug, "Window %p changed: %s\n", pWindow, name);
- }
-#endif
-
- if (dmxInput->detached)
- return;
- for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
- if (dmxInput->devs[i]->update_info)
- dmxInput->devs[i]->update_info(dmxInput->devs[i]->private,
- type, pWindow);
-}
-
-static void dmxCollectAll(DMXInputInfo *dmxInput)
-{
- int i;
-
- if (dmxInput->detached)
- return;
- for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
- if (dmxInput->devs[i]->collect_events)
- dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice->public,
- dmxMotion,
- dmxEnqueue,
- dmxCheckSpecialKeys, DMX_BLOCK);
-}
-
-static void dmxBlockHandler(pointer blockData, OSTimePtr pTimeout,
- pointer pReadMask)
-{
- DMXInputInfo *dmxInput = &dmxInputs[(int)blockData];
- static unsigned long generation = 0;
-
- if (generation != serverGeneration) {
- generation = serverGeneration;
- dmxCollectAll(dmxInput);
- }
-}
-
-static void dmxSwitchReturn(pointer p)
-{
- DMXInputInfo *dmxInput = p;
- int i;
-
- dmxLog(dmxInfo, "Returning from VT %d\n", dmxInput->vt_switched);
-
- if (!dmxInput->vt_switched)
- dmxLog(dmxFatal, "dmxSwitchReturn called, but not switched\n");
- dmxSigioEnableInput();
- for (i = 0; i < dmxInput->numDevs; i++)
- if (dmxInput->devs[i]->vt_post_switch)
- dmxInput->devs[i]->vt_post_switch(dmxInput->devs[i]->private);
- dmxInput->vt_switched = 0;
-}
-
-static void dmxWakeupHandler(pointer blockData, int result, pointer pReadMask)
-{
- DMXInputInfo *dmxInput = &dmxInputs[(int)blockData];
- int i;
-
- if (dmxInput->vt_switch_pending) {
- dmxLog(dmxInfo, "Switching to VT %d\n", dmxInput->vt_switch_pending);
- for (i = 0; i < dmxInput->numDevs; i++)
- if (dmxInput->devs[i]->vt_pre_switch)
- dmxInput->devs[i]->vt_pre_switch(dmxInput->devs[i]->private);
- dmxInput->vt_switched = dmxInput->vt_switch_pending;
- dmxInput->vt_switch_pending = 0;
- for (i = 0; i < dmxInput->numDevs; i++) {
- if (dmxInput->devs[i]->vt_switch) {
- dmxSigioDisableInput();
- if (!dmxInput->devs[i]->vt_switch(dmxInput->devs[i]->private,
- dmxInput->vt_switched,
- dmxSwitchReturn,
- dmxInput))
- dmxSwitchReturn(dmxInput);
- break; /* Only call one vt_switch routine */
- }
- }
- }
- dmxCollectAll(dmxInput);
-}
-
-static char *dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal)
-{
- static int k = 0;
- static int m = 0;
- static int o = 0;
- static unsigned long dmxGeneration = 0;
-#define LEN 32
- char * buf = malloc(LEN);
-
- if (dmxGeneration != serverGeneration) {
- k = m = o = 0;
- dmxGeneration = serverGeneration;
- }
-
- switch (dmxLocal->type) {
- case DMX_LOCAL_KEYBOARD: XmuSnprintf(buf, LEN, "Keyboard%d", k++); break;
- case DMX_LOCAL_MOUSE: XmuSnprintf(buf, LEN, "Mouse%d", m++); break;
- default: XmuSnprintf(buf, LEN, "Other%d", o++); break;
- }
-
- return buf;
-}
-
-static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal)
-{
- DeviceIntPtr pDevice;
- Atom atom;
- const char *name = NULL;
- char *devname;
- DMXInputInfo *dmxInput;
-
- if (!dmxLocal)
- return NULL;
- dmxInput = &dmxInputs[dmxLocal->inputIdx];
-
- if (dmxLocal->sendsCore) {
- if (dmxLocal->type == DMX_LOCAL_KEYBOARD && !dmxLocalCoreKeyboard) {
- dmxLocal->isCore = 1;
- dmxLocalCoreKeyboard = dmxLocal;
- name = "keyboard";
- }
- if (dmxLocal->type == DMX_LOCAL_MOUSE && !dmxLocalCorePointer) {
- dmxLocal->isCore = 1;
- dmxLocalCorePointer = dmxLocal;
- name = "pointer";
- }
- }
-
- if (!name) {
- name = "extension";
- }
-
- if (!name)
- dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name);
-
- pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE);
- if (!pDevice) {
- dmxLog(dmxError, "Too many devices -- cannot add device %s\n",
- dmxLocal->name);
- return NULL;
- }
- pDevice->public.devicePrivate = dmxLocal;
- dmxLocal->pDevice = pDevice;
-
- devname = dmxMakeUniqueDeviceName(dmxLocal);
- atom = MakeAtom((char *)devname, strlen(devname), TRUE);
- pDevice->type = atom;
- pDevice->name = devname;
-
- if (dmxLocal->isCore && dmxLocal->type == DMX_LOCAL_MOUSE) {
-#if 00 /*BP*/
- miRegisterPointerDevice(screenInfo.screens[0], pDevice);
-#else
- /* Nothing? dmxDeviceOnOff() should get called to init, right? */
-#endif
- }
-
- if (dmxLocal->create_private)
- dmxLocal->private = dmxLocal->create_private(pDevice);
-
- dmxLogInput(dmxInput, "Added %s as %s device called %s%s\n",
- dmxLocal->name, name, devname,
- dmxLocal->isCore
- ? " [core]"
- : (dmxLocal->sendsCore
- ? " [sends core events]"
- : ""));
-
- return pDevice;
-}
-
-static DMXLocalInputInfoPtr dmxLookupLocal(const char *name)
-{
- DMXLocalInputInfoPtr pt;
-
- for (pt = &DMXLocalDevices[0]; pt->name; ++pt)
- if (!strcmp(pt->name, name)) return pt; /* search for device name */
- return NULL;
-}
-
-/** Copy the local input information from \a s into a new \a devs slot
- * in \a dmxInput. */
-DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput,
- DMXLocalInputInfoPtr s)
-{
- DMXLocalInputInfoPtr dmxLocal = malloc(sizeof(*dmxLocal));
-
- if (!dmxLocal)
- dmxLog(dmxFatal, "DMXLocalInputInfoPtr: out of memory\n");
-
- memcpy(dmxLocal, s, sizeof(*dmxLocal));
- dmxLocal->inputIdx = dmxInput->inputIdx;
- dmxLocal->sendsCore = dmxInput->core;
- dmxLocal->savedSendsCore = dmxInput->core;
- dmxLocal->deviceId = -1;
-
- ++dmxInput->numDevs;
- dmxInput->devs = realloc(dmxInput->devs,
- dmxInput->numDevs * sizeof(*dmxInput->devs));
- dmxInput->devs[dmxInput->numDevs-1] = dmxLocal;
-
- return dmxLocal;
-}
-
-static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a)
-{
- int i;
- int help = 0;
- DMXLocalInputInfoRec *pt;
-
- for (i = 1; i < dmxArgC(a); i++) {
- const char *name = dmxArgV(a, i);
- if ((pt = dmxLookupLocal(name))) {
- dmxInputCopyLocal(dmxInput, pt);
- } else {
- if (strlen(name))
- dmxLog(dmxWarning,
- "Could not find a driver called %s\n", name);
- ++help;
- }
- }
- if (help) {
- dmxLog(dmxInfo, "Available local device drivers:\n");
- for (pt = &DMXLocalDevices[0]; pt->name; ++pt) {
- const char *type;
- switch (pt->type) {
- case DMX_LOCAL_KEYBOARD: type = "keyboard"; break;
- case DMX_LOCAL_MOUSE: type = "pointer"; break;
- default: type = "unknown"; break;
- }
- dmxLog(dmxInfo, " %s (%s)\n", pt->name, type);
- }
- dmxLog(dmxFatal, "Must have valid local device driver\n");
- }
-}
-
-int dmxInputExtensionErrorHandler(Display *dsp, _Xconst char *name, _Xconst char *reason)
-{
- return 0;
-}
-
-static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI)
-{
- XExtensionVersion *ext;
- XDeviceInfo *devices;
- Display *display;
- int num;
- int i, j;
- XextErrorHandler handler;
-
- if (!(display = XOpenDisplay(dmxInput->name))) return;
-
- /* Print out information about the XInput Extension. */
- handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler);
- ext = XGetExtensionVersion(display, INAME);
- XSetExtensionErrorHandler(handler);
-
- if (!ext || ext == (XExtensionVersion *)NoSuchExtension) {
- dmxLogInput(dmxInput, "%s is not available\n", INAME);
- } else {
- dmxLogInput(dmxInput, "Locating devices on %s (%s version %d.%d)\n",
- dmxInput->name, INAME,
- ext->major_version, ext->minor_version);
- devices = XListInputDevices(display, &num);
-
- XFree(ext);
- ext = NULL;
-
- /* Print a list of all devices */
- for (i = 0; i < num; i++) {
- const char *use = "Unknown";
- switch (devices[i].use) {
- case IsXPointer: use = "XPointer"; break;
- case IsXKeyboard: use = "XKeyboard"; break;
- case IsXExtensionDevice: use = "XExtensionDevice"; break;
- case IsXExtensionPointer: use = "XExtensionPointer"; break;
- case IsXExtensionKeyboard: use = "XExtensionKeyboard"; break;
- }
- dmxLogInput(dmxInput, " %2d %-10.10s %-16.16s\n",
- devices[i].id,
- devices[i].name ? devices[i].name : "",
- use);
- }
-
- /* Search for extensions */
- for (i = 0; i < num; i++) {
- switch (devices[i].use) {
- case IsXKeyboard:
- for (j = 0; j < dmxInput->numDevs; j++) {
- DMXLocalInputInfoPtr dmxL = dmxInput->devs[j];
- if (dmxL->type == DMX_LOCAL_KEYBOARD
- && dmxL->deviceId < 0) {
- dmxL->deviceId = devices[i].id;
- dmxL->deviceName = (devices[i].name
- ? strdup(devices[i].name)
- : NULL);
- }
- }
- break;
- case IsXPointer:
- for (j = 0; j < dmxInput->numDevs; j++) {
- DMXLocalInputInfoPtr dmxL = dmxInput->devs[j];
- if (dmxL->type == DMX_LOCAL_MOUSE && dmxL->deviceId < 0) {
- dmxL->deviceId = devices[i].id;
- dmxL->deviceName = (devices[i].name
- ? xstrdup(devices[i].name)
- : NULL);
- }
- }
- break;
-#if 0
- case IsXExtensionDevice:
- case IsXExtensionKeyboard:
- case IsXExtensionPointer:
- if (doXI) {
- if (!dmxInput->numDevs) {
- dmxLog(dmxWarning,
- "Cannot use remote (%s) XInput devices if"
- " not also using core devices\n",
- dmxInput->name);
- } else {
- dmxLocal = dmxInputCopyLocal(dmxInput,
- &DMXCommonOth);
- dmxLocal->isCore = FALSE;
- dmxLocal->sendsCore = FALSE;
- dmxLocal->deviceId = devices[i].id;
- dmxLocal->deviceName = (devices[i].name
- ? strdup(devices[i].name)
- : NULL);
- }
- }
- break;
-#endif
- }
- }
- XFreeDeviceList(devices);
- }
- XCloseDisplay(display);
-}
-
-/** Re-initialize all the devices described in \a dmxInput. Called from
- #dmxAdjustCursorBoundaries before the cursor is redisplayed. */
-void dmxInputReInit(DMXInputInfo *dmxInput)
-{
- int i;
-
- for (i = 0; i < dmxInput->numDevs; i++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
- if (dmxLocal->reinit)
- dmxLocal->reinit(&dmxLocal->pDevice->public);
- }
-}
-
-/** Re-initialize all the devices described in \a dmxInput. Called from
- #dmxAdjustCursorBoundaries after the cursor is redisplayed. */
-void dmxInputLateReInit(DMXInputInfo *dmxInput)
-{
- int i;
-
- for (i = 0; i < dmxInput->numDevs; i++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
- if (dmxLocal->latereinit)
- dmxLocal->latereinit(&dmxLocal->pDevice->public);
- }
-}
-
-/** Initialize all of the devices described in \a dmxInput. */
-void dmxInputInit(DMXInputInfo *dmxInput)
-{
- DeviceIntPtr pPointer = NULL, pKeyboard = NULL;
- dmxArg a;
- const char *name;
- int i;
- int doXI = 1; /* Include by default */
- int forceConsole = 0;
- int doWindows = 1; /* On by default */
- int hasXkb = 0;
-
- a = dmxArgParse(dmxInput->name);
-
- for (i = 1; i < dmxArgC(a); i++) {
- switch (hasXkb) {
- case 1:
- dmxInput->keycodes = xstrdup(dmxArgV(a, i));
- ++hasXkb;
- break;
- case 2:
- dmxInput->symbols = xstrdup(dmxArgV(a, i));
- ++hasXkb;
- break;
- case 3:
- dmxInput->geometry = xstrdup(dmxArgV(a, i));
- hasXkb = 0;
- break;
- case 0:
- if (!strcmp(dmxArgV(a, i), "noxi")) doXI = 0;
- else if (!strcmp(dmxArgV(a, i), "xi")) doXI = 1;
- else if (!strcmp(dmxArgV(a, i), "console")) forceConsole = 1;
- else if (!strcmp(dmxArgV(a, i), "noconsole")) forceConsole = 0;
- else if (!strcmp(dmxArgV(a, i), "windows")) doWindows = 1;
- else if (!strcmp(dmxArgV(a, i), "nowindows")) doWindows = 0;
- else if (!strcmp(dmxArgV(a, i), "xkb")) hasXkb = 1;
- else {
- dmxLog(dmxFatal,
- "Unknown input argument: %s\n", dmxArgV(a, i));
- }
- }
- }
-
- name = dmxArgV(a, 0);
-
- if (!strcmp(name, "local")) {
- dmxPopulateLocal(dmxInput, a);
- } else if (!strcmp(name, "dummy")) {
- dmxInputCopyLocal(dmxInput, &DMXDummyMou);
- dmxInputCopyLocal(dmxInput, &DMXDummyKbd);
- dmxLogInput(dmxInput, "Using dummy input\n");
- } else {
- int found;
-
- for (found = 0, i = 0; i < dmxNumScreens; i++) {
- if (dmxPropertySameDisplay(&dmxScreens[i], name)) {
- if (dmxScreens[i].shared)
- dmxLog(dmxFatal,
- "Cannot take input from shared backend (%s)\n",
- name);
- if (!dmxInput->core) {
- dmxLog(dmxWarning,
- "Cannot use core devices on a backend (%s)"
- " as XInput devices\n", name);
- } else {
- char *pt;
- for (pt = (char *)dmxInput->name; pt && *pt; pt++)
- if (*pt == ',') *pt = '\0';
- dmxInputCopyLocal(dmxInput, &DMXBackendMou);
- dmxInputCopyLocal(dmxInput, &DMXBackendKbd);
- dmxInput->scrnIdx = i;
- dmxLogInput(dmxInput,
- "Using backend input from %s\n", name);
- }
- ++found;
- break;
- }
- }
- if (!found || forceConsole) {
- char *pt;
- if (found) dmxInput->console = TRUE;
- for (pt = (char *)dmxInput->name; pt && *pt; pt++)
- if (*pt == ',') *pt = '\0';
- dmxInputCopyLocal(dmxInput, &DMXConsoleMou);
- dmxInputCopyLocal(dmxInput, &DMXConsoleKbd);
- if (doWindows) {
- dmxInput->windows = TRUE;
- dmxInput->updateWindowInfo = dmxUpdateWindowInformation;
- }
- dmxLogInput(dmxInput,
- "Using console input from %s (%s windows)\n",
- name, doWindows ? "with" : "without");
- }
- }
-
- dmxArgFree(a);
-
- /* Locate extensions we may be interested in */
- dmxInputScanForExtensions(dmxInput, doXI);
-
- for (i = 0; i < dmxInput->numDevs; i++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
- dmxLocal->pDevice = dmxAddDevice(dmxLocal);
- if (dmxLocal->isCore) {
- if (dmxLocal->type == DMX_LOCAL_MOUSE)
- pPointer = dmxLocal->pDevice;
- if (dmxLocal->type == DMX_LOCAL_KEYBOARD)
- pKeyboard = dmxLocal->pDevice;
- }
- }
-
- dmxInput->processInputEvents = dmxProcessInputEvents;
- dmxInput->detached = False;
-
- RegisterBlockAndWakeupHandlers(dmxBlockHandler,
- dmxWakeupHandler,
- (void *)dmxInput->inputIdx);
-}
-
-static void dmxInputFreeLocal(DMXLocalInputInfoRec *local)
-{
- if (!local) return;
- if (local->isCore && local->type == DMX_LOCAL_MOUSE)
- dmxLocalCorePointer = NULL;
- if (local->isCore && local->type == DMX_LOCAL_KEYBOARD)
- dmxLocalCoreKeyboard = NULL;
- if (local->destroy_private) local->destroy_private(local->private);
- free(local->history);
- free(local->valuators);
- free(local->deviceName);
- local->private = NULL;
- local->history = NULL;
- local->deviceName = NULL;
- free(local);
-}
-
-/** Free all of the memory associated with \a dmxInput */
-void dmxInputFree(DMXInputInfo *dmxInput)
-{
- int i;
-
- if (!dmxInput) return;
-
- free(dmxInput->keycodes);
- free(dmxInput->symbols);
- free(dmxInput->geometry);
-
- for (i = 0; i < dmxInput->numDevs; i++) {
- dmxInputFreeLocal(dmxInput->devs[i]);
- dmxInput->devs[i] = NULL;
- }
- free(dmxInput->devs);
- dmxInput->devs = NULL;
- dmxInput->numDevs = 0;
- if (dmxInput->freename) free(dmxInput->name);
- dmxInput->name = NULL;
-}
-
-/** Log information about all of the known devices using #dmxLog(). */
-void dmxInputLogDevices(void)
-{
- int i, j;
-
- dmxLog(dmxInfo, "%d devices:\n", dmxGetInputCount());
- dmxLog(dmxInfo, " Id Name Classes\n");
- for (j = 0; j < dmxNumInputs; j++) {
- DMXInputInfo *dmxInput = &dmxInputs[j];
- const char *pt = strchr(dmxInput->name, ',');
- int len = (pt
- ? (size_t)(pt-dmxInput->name)
- : strlen(dmxInput->name));
-
- for (i = 0; i < dmxInput->numDevs; i++) {
- DeviceIntPtr pDevice = dmxInput->devs[i]->pDevice;
- if (pDevice) {
- dmxLog(dmxInfo, " %2d%c %-20.20s",
- pDevice->id,
- dmxInput->detached ? 'D' : ' ',
- pDevice->name);
- if (pDevice->key) dmxLogCont(dmxInfo, " key");
- if (pDevice->valuator) dmxLogCont(dmxInfo, " val");
- if (pDevice->button) dmxLogCont(dmxInfo, " btn");
- if (pDevice->focus) dmxLogCont(dmxInfo, " foc");
- if (pDevice->kbdfeed) dmxLogCont(dmxInfo, " fb/kbd");
- if (pDevice->ptrfeed) dmxLogCont(dmxInfo, " fb/ptr");
- if (pDevice->intfeed) dmxLogCont(dmxInfo, " fb/int");
- if (pDevice->stringfeed) dmxLogCont(dmxInfo, " fb/str");
- if (pDevice->bell) dmxLogCont(dmxInfo, " fb/bel");
- if (pDevice->leds) dmxLogCont(dmxInfo, " fb/led");
- if (!pDevice->key && !pDevice->valuator && !pDevice->button
- && !pDevice->focus && !pDevice->kbdfeed
- && !pDevice->ptrfeed && !pDevice->intfeed
- && !pDevice->stringfeed && !pDevice->bell
- && !pDevice->leds) dmxLogCont(dmxInfo, " (none)");
-
- dmxLogCont(dmxInfo, "\t[i%d/%*.*s",
- dmxInput->inputIdx, len, len, dmxInput->name);
- if (dmxInput->devs[i]->deviceId >= 0)
- dmxLogCont(dmxInfo, "/id%d", dmxInput->devs[i]->deviceId);
- if (dmxInput->devs[i]->deviceName)
- dmxLogCont(dmxInfo, "=%s", dmxInput->devs[i]->deviceName);
- dmxLogCont(dmxInfo, "] %s\n",
- dmxInput->devs[i]->isCore
- ? "core"
- : (dmxInput->devs[i]->sendsCore
- ? "extension (sends core events)"
- : "extension"));
- }
- }
- }
-}
-
-/** Detach an input */
-int dmxInputDetach(DMXInputInfo *dmxInput)
-{
- int i;
-
- if (dmxInput->detached) return BadAccess;
-
- for (i = 0; i < dmxInput->numDevs; i++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
- dmxLogInput(dmxInput, "Detaching device id %d: %s%s\n",
- dmxLocal->pDevice->id,
- dmxLocal->pDevice->name,
- dmxLocal->isCore
- ? " [core]"
- : (dmxLocal->sendsCore
- ? " [sends core events]"
- : ""));
- DisableDevice(dmxLocal->pDevice, TRUE);
- }
- dmxInput->detached = True;
- dmxInputLogDevices();
- return 0;
-}
-
-/** Search for input associated with \a dmxScreen, and detach. */
-void dmxInputDetachAll(DMXScreenInfo *dmxScreen)
-{
- int i;
-
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- if (dmxInput->scrnIdx == dmxScreen->index) dmxInputDetach(dmxInput);
- }
-}
-
-/** Search for input associated with \a deviceId, and detach. */
-int dmxInputDetachId(int id)
-{
- DMXInputInfo *dmxInput = dmxInputLocateId(id);
-
- if (!dmxInput) return BadValue;
-
- return dmxInputDetach(dmxInput);
-}
-
-DMXInputInfo *dmxInputLocateId(int id)
-{
- int i, j;
-
- for (i = 0; i < dmxNumInputs; i++) {
- DMXInputInfo *dmxInput = &dmxInputs[i];
- for (j = 0; j < dmxInput->numDevs; j++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
- if (dmxLocal->pDevice->id == id) return dmxInput;
- }
- }
- return NULL;
-}
-
-static int dmxInputAttachNew(DMXInputInfo *dmxInput, int *id)
-{
- dmxInputInit(dmxInput);
- InitAndStartDevices();
- if (id && dmxInput->devs) *id = dmxInput->devs[0]->pDevice->id;
- dmxInputLogDevices();
- return 0;
-}
-
-static int dmxInputAttachOld(DMXInputInfo *dmxInput, int *id)
-{
- int i;
-
- dmxInput->detached = False;
- for (i = 0; i < dmxInput->numDevs; i++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
- if (id) *id = dmxLocal->pDevice->id;
- dmxLogInput(dmxInput,
- "Attaching device id %d: %s%s\n",
- dmxLocal->pDevice->id,
- dmxLocal->pDevice->name,
- dmxLocal->isCore
- ? " [core]"
- : (dmxLocal->sendsCore
- ? " [sends core events]"
- : ""));
- EnableDevice(dmxLocal->pDevice, TRUE);
- }
- dmxInputLogDevices();
- return 0;
-}
-
-int dmxInputAttachConsole(const char *name, int isCore, int *id)
-{
- DMXInputInfo *dmxInput;
- int i;
-
- for (i = 0; i < dmxNumInputs; i++) {
- dmxInput = &dmxInputs[i];
- if (dmxInput->scrnIdx == -1
- && dmxInput->detached
- && !strcmp(dmxInput->name, name)) {
- /* Found match */
- dmxLogInput(dmxInput, "Reattaching detached console input\n");
- return dmxInputAttachOld(dmxInput, id);
- }
- }
-
- /* No match found */
- dmxInput = dmxConfigAddInput(xstrdup(name), isCore);
- dmxInput->freename = TRUE;
- dmxLogInput(dmxInput, "Attaching new console input\n");
- return dmxInputAttachNew(dmxInput, id);
-}
-
-int dmxInputAttachBackend(int physicalScreen, int isCore, int *id)
-{
- DMXInputInfo *dmxInput;
- DMXScreenInfo *dmxScreen;
- int i;
-
- if (physicalScreen < 0 || physicalScreen >= dmxNumScreens) return BadValue;
- for (i = 0; i < dmxNumInputs; i++) {
- dmxInput = &dmxInputs[i];
- if (dmxInput->scrnIdx != -1 && dmxInput->scrnIdx == physicalScreen) {
- /* Found match */
- if (!dmxInput->detached) return BadAccess; /* Already attached */
- dmxScreen = &dmxScreens[physicalScreen];
- if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */
- dmxLogInput(dmxInput, "Reattaching detached backend input\n");
- return dmxInputAttachOld(dmxInput, id);
- }
- }
- /* No match found */
- dmxScreen = &dmxScreens[physicalScreen];
- if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */
- dmxInput = dmxConfigAddInput(dmxScreen->name, isCore);
- dmxLogInput(dmxInput, "Attaching new backend input\n");
- return dmxInputAttachNew(dmxInput, id);
-}
+/*
+ * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * This file provides generic input support. Functions here set up
+ * input and lead to the calling of low-level device drivers for
+ * input. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#define DMX_WINDOW_DEBUG 0
+
+#include "dmxinputinit.h"
+#include "dmxextension.h" /* For dmxInputCount */
+
+#include "dmxdummy.h"
+#include "dmxbackend.h"
+#include "dmxconsole.h"
+#include "dmxcommon.h"
+#include "dmxevents.h"
+#include "dmxmotion.h"
+#include "dmxprop.h"
+#include "config/dmxconfig.h"
+#include "dmxcursor.h"
+
+#include "lnx-keyboard.h"
+#include "lnx-ms.h"
+#include "lnx-ps2.h"
+#include "usb-keyboard.h"
+#include "usb-mouse.h"
+#include "usb-other.h"
+#include "usb-common.h"
+
+#include "dmxsigio.h"
+#include "dmxarg.h"
+
+#include "inputstr.h"
+#include "input.h"
+#include "mipointer.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "xkbsrv.h"
+
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "exevents.h"
+#include "extinit.h"
+
+DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard;
+
+static DMXLocalInputInfoRec DMXDummyMou = {
+ "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo
+};
+
+static DMXLocalInputInfoRec DMXDummyKbd = {
+ "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
+ NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo
+};
+
+static DMXLocalInputInfoRec DMXBackendMou = {
+ "backend-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_BACKEND, 2,
+ dmxBackendCreatePrivate, dmxBackendDestroyPrivate,
+ dmxBackendInit, NULL, dmxBackendLateReInit, dmxBackendMouGetInfo,
+ dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition,
+ NULL, NULL, NULL,
+ dmxBackendCollectEvents, dmxBackendProcessInput, dmxBackendFunctions, NULL,
+ dmxCommonMouCtrl
+};
+
+static DMXLocalInputInfoRec DMXBackendKbd = {
+ "backend-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_BACKEND,
+ 1, /* With backend-mou or console-mou */
+ dmxCommonCopyPrivate, NULL,
+ dmxBackendInit, NULL, NULL, dmxBackendKbdGetInfo,
+ dmxCommonKbdOn, dmxCommonKbdOff, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
+};
+
+static DMXLocalInputInfoRec DMXConsoleMou = {
+ "console-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_CONSOLE, 2,
+ dmxConsoleCreatePrivate, dmxConsoleDestroyPrivate,
+ dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleMouGetInfo,
+ dmxCommonMouOn, dmxCommonMouOff, dmxConsoleUpdatePosition,
+ NULL, NULL, NULL,
+ dmxConsoleCollectEvents, NULL, dmxConsoleFunctions, dmxConsoleUpdateInfo,
+ dmxCommonMouCtrl
+};
+
+static DMXLocalInputInfoRec DMXConsoleKbd = {
+ "console-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_CONSOLE,
+ 1, /* With backend-mou or console-mou */
+ dmxCommonCopyPrivate, NULL,
+ dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo,
+ dmxCommonKbdOn, dmxCommonKbdOff, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
+};
+
+static DMXLocalInputInfoRec DMXLocalDevices[] = {
+ /* Dummy drivers that can compile on any OS */
+#ifdef __linux__
+ /* Linux-specific drivers */
+ {
+ "kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
+ kbdLinuxCreatePrivate, kbdLinuxDestroyPrivate,
+ kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo,
+ kbdLinuxOn, kbdLinuxOff, NULL,
+ kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch,
+ kbdLinuxRead, NULL, NULL, NULL,
+ NULL, kbdLinuxCtrl, kbdLinuxBell
+ },
+ {
+ "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ msLinuxCreatePrivate, msLinuxDestroyPrivate,
+ msLinuxInit, NULL, NULL, msLinuxGetInfo,
+ msLinuxOn, msLinuxOff, NULL,
+ msLinuxVTPreSwitch, msLinuxVTPostSwitch, NULL,
+ msLinuxRead
+ },
+ {
+ "ps2", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ ps2LinuxCreatePrivate, ps2LinuxDestroyPrivate,
+ ps2LinuxInit, NULL, NULL, ps2LinuxGetInfo,
+ ps2LinuxOn, ps2LinuxOff, NULL,
+ ps2LinuxVTPreSwitch, ps2LinuxVTPostSwitch, NULL,
+ ps2LinuxRead
+ },
+#endif
+#ifdef __linux__
+ /* USB drivers, currently only for
+ Linux, but relatively easy to port to
+ other OSs */
+ {
+ "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
+ usbCreatePrivate, usbDestroyPrivate,
+ kbdUSBInit, NULL, NULL, kbdUSBGetInfo,
+ kbdUSBOn, usbOff, NULL,
+ NULL, NULL, NULL,
+ kbdUSBRead, NULL, NULL, NULL,
+ NULL, kbdUSBCtrl
+ },
+ {
+ "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ usbCreatePrivate, usbDestroyPrivate,
+ mouUSBInit, NULL, NULL, mouUSBGetInfo,
+ mouUSBOn, usbOff, NULL,
+ NULL, NULL, NULL,
+ mouUSBRead
+ },
+ {
+ "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1,
+ usbCreatePrivate, usbDestroyPrivate,
+ othUSBInit, NULL, NULL, othUSBGetInfo,
+ othUSBOn, usbOff, NULL,
+ NULL, NULL, NULL,
+ othUSBRead
+ },
+#endif
+ {
+ "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1,
+ NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo
+ },
+ {
+ "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1,
+ NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo
+ },
+ { NULL } /* Must be last */
+};
+
+
+#if 11 /*BP*/
+void
+DDXRingBell(int volume, int pitch, int duration)
+{
+ /* NO-OP */
+}
+
+/* taken from kdrive/src/kinput.c: */
+static void
+dmxKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl)
+{
+#if 0
+ KdKeyboardInfo *ki;
+
+ for (ki = kdKeyboards; ki; ki = ki->next) {
+ if (ki->dixdev && ki->dixdev->id == pDevice->id)
+ break;
+ }
+
+ if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver)
+ return;
+
+ KdSetLeds(ki, ctrl->leds);
+ ki->bellPitch = ctrl->bell_pitch;
+ ki->bellDuration = ctrl->bell_duration;
+#endif
+}
+
+/* taken from kdrive/src/kinput.c: */
+static void
+dmxBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
+{
+#if 0
+ KeybdCtrl *ctrl = arg;
+ KdKeyboardInfo *ki = NULL;
+
+ for (ki = kdKeyboards; ki; ki = ki->next) {
+ if (ki->dixdev && ki->dixdev->id == pDev->id)
+ break;
+ }
+
+ if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver)
+ return;
+
+ KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration);
+#endif
+}
+
+#endif /*BP*/
+
+static void _dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal,
+ PtrCtrl *ctrl)
+{
+ if (!dmxLocal) return;
+ dmxLocal->mctrl = *ctrl;
+ if (dmxLocal->mCtrl) dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl);
+}
+
+/** Change the pointer control information for the \a pDevice. If the
+ * device sends core events, then also change the control information
+ * for all of the pointer devices that send core events. */
+void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl)
+{
+ GETDMXLOCALFROMPDEVICE;
+ int i, j;
+
+ if (dmxLocal->sendsCore) { /* Do for all core devices */
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (dmxInput->detached) continue;
+ for (j = 0; j < dmxInput->numDevs; j++)
+ if (dmxInput->devs[j]->sendsCore)
+ _dmxChangePointerControl(dmxInput->devs[j], ctrl);
+ }
+ } else { /* Do for this device only */
+ _dmxChangePointerControl(dmxLocal, ctrl);
+ }
+}
+
+static void _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal,
+ KeybdCtrl *ctrl)
+{
+ dmxLocal->kctrl = *ctrl;
+ if (dmxLocal->kCtrl) {
+ dmxLocal->kCtrl(&dmxLocal->pDevice->public, ctrl);
+ if (dmxLocal->pDevice->kbdfeed) {
+ XkbEventCauseRec cause;
+ XkbSetCauseUnknown(&cause);
+ /* Generate XKB events, as necessary */
+ XkbUpdateIndicators(dmxLocal->pDevice, XkbAllIndicatorsMask, False,
+ NULL, &cause);
+ }
+ }
+}
+
+
+/** Change the keyboard control information for the \a pDevice. If the
+ * device sends core events, then also change the control information
+ * for all of the keyboard devices that send core events. */
+void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl)
+{
+ GETDMXLOCALFROMPDEVICE;
+ int i, j;
+
+ if (dmxLocal->sendsCore) { /* Do for all core devices */
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (dmxInput->detached) continue;
+ for (j = 0; j < dmxInput->numDevs; j++)
+ if (dmxInput->devs[j]->sendsCore)
+ _dmxKeyboardKbdCtrlProc(dmxInput->devs[j], ctrl);
+ }
+ } else { /* Do for this device only */
+ _dmxKeyboardKbdCtrlProc(dmxLocal, ctrl);
+ }
+}
+
+static void _dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent)
+{
+ if (dmxLocal->kBell) dmxLocal->kBell(&dmxLocal->pDevice->public,
+ percent,
+ dmxLocal->kctrl.bell,
+ dmxLocal->kctrl.bell_pitch,
+ dmxLocal->kctrl.bell_duration);
+}
+
+/** Sound the bell on the device. If the device send core events, then
+ * sound the bell on all of the devices that send core events. */
+void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice,
+ pointer ctrl, int unknown)
+{
+ GETDMXLOCALFROMPDEVICE;
+ int i, j;
+
+ if (dmxLocal->sendsCore) { /* Do for all core devices */
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (dmxInput->detached) continue;
+ for (j = 0; j < dmxInput->numDevs; j++)
+ if (dmxInput->devs[j]->sendsCore)
+ _dmxKeyboardBellProc(dmxInput->devs[j], percent);
+ }
+ } else { /* Do for this device only */
+ _dmxKeyboardBellProc(dmxLocal, percent);
+ }
+}
+
+static void dmxKeyboardFreeNames(XkbComponentNamesPtr names)
+{
+ if (names->keycodes) XFree(names->keycodes);
+ if (names->types) XFree(names->types);
+ if (names->compat) XFree(names->compat);
+ if (names->symbols) XFree(names->symbols);
+ if (names->geometry) XFree(names->geometry);
+}
+
+
+static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info)
+{
+ GETDMXINPUTFROMPDEVICE;
+ XkbRMLVOSet rmlvo;
+
+ rmlvo.rules = dmxConfigGetXkbRules();
+ rmlvo.model = dmxConfigGetXkbModel();
+ rmlvo.layout = dmxConfigGetXkbLayout();
+ rmlvo.variant = dmxConfigGetXkbVariant();
+ rmlvo.options = dmxConfigGetXkbOptions();
+
+ XkbSetRulesDflts(&rmlvo);
+ if (!info->force && (dmxInput->keycodes
+ || dmxInput->symbols
+ || dmxInput->geometry)) {
+ if (info->freenames) dmxKeyboardFreeNames(&info->names);
+ info->freenames = 0;
+ info->names.keycodes = dmxInput->keycodes;
+ info->names.types = NULL;
+ info->names.compat = NULL;
+ info->names.symbols = dmxInput->symbols;
+ info->names.geometry = dmxInput->geometry;
+
+ dmxLogInput(dmxInput, "XKEYBOARD: From command line: %s",
+ info->names.keycodes);
+ if (info->names.symbols && *info->names.symbols)
+ dmxLogInputCont(dmxInput, " %s", info->names.symbols);
+ if (info->names.geometry && *info->names.geometry)
+ dmxLogInputCont(dmxInput, " %s", info->names.geometry);
+ dmxLogInputCont(dmxInput, "\n");
+ } else if (info->names.keycodes) {
+ dmxLogInput(dmxInput, "XKEYBOARD: From device: %s",
+ info->names.keycodes);
+ if (info->names.symbols && *info->names.symbols)
+ dmxLogInputCont(dmxInput, " %s", info->names.symbols);
+ if (info->names.geometry && *info->names.geometry)
+ dmxLogInputCont(dmxInput, " %s", info->names.geometry);
+ dmxLogInputCont(dmxInput, "\n");
+ } else {
+ dmxLogInput(dmxInput, "XKEYBOARD: Defaults: %s %s %s %s %s\n",
+ dmxConfigGetXkbRules(),
+ dmxConfigGetXkbLayout(),
+ dmxConfigGetXkbModel(),
+ dmxConfigGetXkbVariant()
+ ? dmxConfigGetXkbVariant() : "",
+ dmxConfigGetXkbOptions()
+ ? dmxConfigGetXkbOptions() : "");
+ }
+ InitKeyboardDeviceStruct(pDevice, &rmlvo,
+ dmxKeyboardBellProc,
+ dmxKeyboardKbdCtrlProc);
+
+ if (info->freenames) dmxKeyboardFreeNames(&info->names);
+
+ return Success;
+}
+
+
+static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
+{
+ GETDMXINPUTFROMPDEVICE;
+ int fd;
+ DMXLocalInitInfo info;
+ int i;
+ Atom btn_labels[MAX_BUTTONS] = {0}; /* FIXME */
+ Atom axis_labels[MAX_VALUATORS] = {0}; /* FIXME */
+
+ if (dmxInput->detached) return Success;
+
+ memset(&info, 0, sizeof(info));
+ switch (what) {
+ case DEVICE_INIT:
+ if (dmxLocal->init)
+ dmxLocal->init(pDev);
+ if (dmxLocal->get_info)
+ dmxLocal->get_info(pDev, &info);
+ if (info.keyboard) { /* XKEYBOARD makes this a special case */
+ dmxKeyboardOn(pDevice, &info);
+ break;
+ }
+ if (info.keyClass) {
+ XkbRMLVOSet rmlvo;
+
+ rmlvo.rules = dmxConfigGetXkbRules();
+ rmlvo.model = dmxConfigGetXkbModel();
+ rmlvo.layout = dmxConfigGetXkbLayout();
+ rmlvo.variant = dmxConfigGetXkbVariant();
+ rmlvo.options = dmxConfigGetXkbOptions();
+
+ InitKeyboardDeviceStruct(pDevice,
+ &rmlvo,
+ dmxBell, dmxKbdCtrl);
+ }
+ if (info.buttonClass) {
+ InitButtonClassDeviceStruct(pDevice, info.numButtons,
+ btn_labels, info.map);
+ }
+ if (info.valuatorClass) {
+ if (info.numRelAxes && dmxLocal->sendsCore) {
+ InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
+ axis_labels,
+ GetMaximumEventsNum(),
+ Relative);
+ for (i = 0; i < info.numRelAxes; i++)
+ InitValuatorAxisStruct(pDevice, i, axis_labels[i],
+ info.minval[i], info.maxval[i],
+ info.res[i],
+ info.minres[i], info.maxres[i],
+ Relative);
+ } else if (info.numRelAxes) {
+ InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
+ axis_labels,
+ dmxPointerGetMotionBufferSize(),
+ Relative);
+ for (i = 0; i < info.numRelAxes; i++)
+ InitValuatorAxisStruct(pDevice, i, axis_labels[i],
+ info.minval[i],
+ info.maxval[i], info.res[i],
+ info.minres[i], info.maxres[i],
+ Relative);
+ } else if (info.numAbsAxes) {
+ InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes,
+ axis_labels,
+ dmxPointerGetMotionBufferSize(),
+ Absolute);
+ for (i = 0; i < info.numAbsAxes; i++)
+ InitValuatorAxisStruct(pDevice, i,
+ axis_labels[i],
+ info.minval[i], info.maxval[i],
+ info.res[i], info.minres[i],
+ info.maxres[i], Absolute);
+ }
+ }
+ if (info.focusClass) InitFocusClassDeviceStruct(pDevice);
+ if (info.proximityClass) InitProximityClassDeviceStruct(pDevice);
+ if (info.ptrFeedbackClass)
+ InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl);
+ if (info.intFeedbackClass || info.strFeedbackClass)
+ dmxLog(dmxWarning,
+ "Integer and string feedback not supported for %s\n",
+ pDevice->name);
+ if (!info.keyboard && (info.ledFeedbackClass || info.belFeedbackClass))
+ dmxLog(dmxWarning,
+ "Led and bel feedback not supported for non-keyboard %s\n",
+ pDevice->name);
+ break;
+ case DEVICE_ON:
+ if (!pDev->on) {
+ if (dmxLocal->on && (fd = dmxLocal->on(pDev)) >= 0)
+ dmxSigioRegister(dmxInput, fd);
+ pDev->on = TRUE;
+ }
+ break;
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ /* This can get called twice consecutively: once for a
+ * detached screen (DEVICE_OFF), and then again at server
+ * generation time (DEVICE_CLOSE). */
+ if (pDev->on) {
+ dmxSigioUnregister(dmxInput);
+ if (dmxLocal->off) dmxLocal->off(pDev);
+ pDev->on = FALSE;
+ }
+ break;
+ }
+ if (info.keySyms.map && info.freemap) {
+ XFree(info.keySyms.map);
+ info.keySyms.map = NULL;
+ }
+ if (info.xkb) XkbFreeKeyboard(info.xkb, 0, True);
+ return Success;
+}
+
+static void dmxProcessInputEvents(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ mieqProcessInputEvents();
+#if 00 /*BP*/
+ miPointerUpdate();
+#endif
+ if (dmxInput->detached)
+ return;
+ for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
+ if (dmxInput->devs[i]->process_input) {
+#if 11 /*BP*/
+ miPointerUpdateSprite(dmxInput->devs[i]->pDevice);
+#endif
+ dmxInput->devs[i]->process_input(dmxInput->devs[i]->private);
+ }
+
+#if 11 /*BP*/
+ mieqProcessInputEvents();
+#endif
+}
+
+static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput,
+ DMXUpdateType type,
+ WindowPtr pWindow)
+{
+ int i;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension && pWindow && pWindow->parent != screenInfo.screens[0]->root)
+ return;
+#endif
+#if DMX_WINDOW_DEBUG
+ {
+ const char *name = "Unknown";
+ switch (type) {
+ case DMX_UPDATE_REALIZE: name = "Realize"; break;
+ case DMX_UPDATE_UNREALIZE: name = "Unrealize"; break;
+ case DMX_UPDATE_RESTACK: name = "Restack"; break;
+ case DMX_UPDATE_COPY: name = "Copy"; break;
+ case DMX_UPDATE_RESIZE: name = "Resize"; break;
+ case DMX_UPDATE_REPARENT: name = "Repaint"; break;
+ }
+ dmxLog(dmxDebug, "Window %p changed: %s\n", pWindow, name);
+ }
+#endif
+
+ if (dmxInput->detached)
+ return;
+ for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
+ if (dmxInput->devs[i]->update_info)
+ dmxInput->devs[i]->update_info(dmxInput->devs[i]->private,
+ type, pWindow);
+}
+
+static void dmxCollectAll(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ if (dmxInput->detached)
+ return;
+ for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
+ if (dmxInput->devs[i]->collect_events)
+ dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice->public,
+ dmxMotion,
+ dmxEnqueue,
+ dmxCheckSpecialKeys, DMX_BLOCK);
+}
+
+static void dmxBlockHandler(pointer blockData, OSTimePtr pTimeout,
+ pointer pReadMask)
+{
+ DMXInputInfo *dmxInput = &dmxInputs[(uintptr_t)blockData];
+ static unsigned long generation = 0;
+
+ if (generation != serverGeneration) {
+ generation = serverGeneration;
+ dmxCollectAll(dmxInput);
+ }
+}
+
+static void dmxSwitchReturn(pointer p)
+{
+ DMXInputInfo *dmxInput = p;
+ int i;
+
+ dmxLog(dmxInfo, "Returning from VT %d\n", dmxInput->vt_switched);
+
+ if (!dmxInput->vt_switched)
+ dmxLog(dmxFatal, "dmxSwitchReturn called, but not switched\n");
+ dmxSigioEnableInput();
+ for (i = 0; i < dmxInput->numDevs; i++)
+ if (dmxInput->devs[i]->vt_post_switch)
+ dmxInput->devs[i]->vt_post_switch(dmxInput->devs[i]->private);
+ dmxInput->vt_switched = 0;
+}
+
+static void dmxWakeupHandler(pointer blockData, int result, pointer pReadMask)
+{
+ DMXInputInfo *dmxInput = &dmxInputs[(uintptr_t)blockData];
+ int i;
+
+ if (dmxInput->vt_switch_pending) {
+ dmxLog(dmxInfo, "Switching to VT %d\n", dmxInput->vt_switch_pending);
+ for (i = 0; i < dmxInput->numDevs; i++)
+ if (dmxInput->devs[i]->vt_pre_switch)
+ dmxInput->devs[i]->vt_pre_switch(dmxInput->devs[i]->private);
+ dmxInput->vt_switched = dmxInput->vt_switch_pending;
+ dmxInput->vt_switch_pending = 0;
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ if (dmxInput->devs[i]->vt_switch) {
+ dmxSigioDisableInput();
+ if (!dmxInput->devs[i]->vt_switch(dmxInput->devs[i]->private,
+ dmxInput->vt_switched,
+ dmxSwitchReturn,
+ dmxInput))
+ dmxSwitchReturn(dmxInput);
+ break; /* Only call one vt_switch routine */
+ }
+ }
+ }
+ dmxCollectAll(dmxInput);
+}
+
+static char *dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal)
+{
+ static int k = 0;
+ static int m = 0;
+ static int o = 0;
+ static unsigned long dmxGeneration = 0;
+#define LEN 32
+ char * buf = malloc(LEN);
+
+ if (dmxGeneration != serverGeneration) {
+ k = m = o = 0;
+ dmxGeneration = serverGeneration;
+ }
+
+ switch (dmxLocal->type) {
+ case DMX_LOCAL_KEYBOARD: XmuSnprintf(buf, LEN, "Keyboard%d", k++); break;
+ case DMX_LOCAL_MOUSE: XmuSnprintf(buf, LEN, "Mouse%d", m++); break;
+ default: XmuSnprintf(buf, LEN, "Other%d", o++); break;
+ }
+
+ return buf;
+}
+
+static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal)
+{
+ DeviceIntPtr pDevice;
+ Atom atom;
+ const char *name = NULL;
+ char *devname;
+ DMXInputInfo *dmxInput;
+
+ if (!dmxLocal)
+ return NULL;
+ dmxInput = &dmxInputs[dmxLocal->inputIdx];
+
+ if (dmxLocal->sendsCore) {
+ if (dmxLocal->type == DMX_LOCAL_KEYBOARD && !dmxLocalCoreKeyboard) {
+ dmxLocal->isCore = 1;
+ dmxLocalCoreKeyboard = dmxLocal;
+ name = "keyboard";
+ }
+ if (dmxLocal->type == DMX_LOCAL_MOUSE && !dmxLocalCorePointer) {
+ dmxLocal->isCore = 1;
+ dmxLocalCorePointer = dmxLocal;
+ name = "pointer";
+ }
+ }
+
+ if (!name) {
+ name = "extension";
+ }
+
+ if (!name)
+ dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name);
+
+ pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE);
+ if (!pDevice) {
+ dmxLog(dmxError, "Too many devices -- cannot add device %s\n",
+ dmxLocal->name);
+ return NULL;
+ }
+ pDevice->public.devicePrivate = dmxLocal;
+ dmxLocal->pDevice = pDevice;
+
+ devname = dmxMakeUniqueDeviceName(dmxLocal);
+ atom = MakeAtom((char *)devname, strlen(devname), TRUE);
+ pDevice->type = atom;
+ pDevice->name = devname;
+
+ if (dmxLocal->isCore && dmxLocal->type == DMX_LOCAL_MOUSE) {
+#if 00 /*BP*/
+ miRegisterPointerDevice(screenInfo.screens[0], pDevice);
+#else
+ /* Nothing? dmxDeviceOnOff() should get called to init, right? */
+#endif
+ }
+
+ if (dmxLocal->create_private)
+ dmxLocal->private = dmxLocal->create_private(pDevice);
+
+ dmxLogInput(dmxInput, "Added %s as %s device called %s%s\n",
+ dmxLocal->name, name, devname,
+ dmxLocal->isCore
+ ? " [core]"
+ : (dmxLocal->sendsCore
+ ? " [sends core events]"
+ : ""));
+
+ return pDevice;
+}
+
+static DMXLocalInputInfoPtr dmxLookupLocal(const char *name)
+{
+ DMXLocalInputInfoPtr pt;
+
+ for (pt = &DMXLocalDevices[0]; pt->name; ++pt)
+ if (!strcmp(pt->name, name)) return pt; /* search for device name */
+ return NULL;
+}
+
+/** Copy the local input information from \a s into a new \a devs slot
+ * in \a dmxInput. */
+DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput,
+ DMXLocalInputInfoPtr s)
+{
+ DMXLocalInputInfoPtr dmxLocal = malloc(sizeof(*dmxLocal));
+
+ if (!dmxLocal)
+ dmxLog(dmxFatal, "DMXLocalInputInfoPtr: out of memory\n");
+
+ memcpy(dmxLocal, s, sizeof(*dmxLocal));
+ dmxLocal->inputIdx = dmxInput->inputIdx;
+ dmxLocal->sendsCore = dmxInput->core;
+ dmxLocal->savedSendsCore = dmxInput->core;
+ dmxLocal->deviceId = -1;
+
+ ++dmxInput->numDevs;
+ dmxInput->devs = realloc(dmxInput->devs,
+ dmxInput->numDevs * sizeof(*dmxInput->devs));
+ dmxInput->devs[dmxInput->numDevs-1] = dmxLocal;
+
+ return dmxLocal;
+}
+
+static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a)
+{
+ int i;
+ int help = 0;
+ DMXLocalInputInfoRec *pt;
+
+ for (i = 1; i < dmxArgC(a); i++) {
+ const char *name = dmxArgV(a, i);
+ if ((pt = dmxLookupLocal(name))) {
+ dmxInputCopyLocal(dmxInput, pt);
+ } else {
+ if (strlen(name))
+ dmxLog(dmxWarning,
+ "Could not find a driver called %s\n", name);
+ ++help;
+ }
+ }
+ if (help) {
+ dmxLog(dmxInfo, "Available local device drivers:\n");
+ for (pt = &DMXLocalDevices[0]; pt->name; ++pt) {
+ const char *type;
+ switch (pt->type) {
+ case DMX_LOCAL_KEYBOARD: type = "keyboard"; break;
+ case DMX_LOCAL_MOUSE: type = "pointer"; break;
+ default: type = "unknown"; break;
+ }
+ dmxLog(dmxInfo, " %s (%s)\n", pt->name, type);
+ }
+ dmxLog(dmxFatal, "Must have valid local device driver\n");
+ }
+}
+
+int dmxInputExtensionErrorHandler(Display *dsp, _Xconst char *name, _Xconst char *reason)
+{
+ return 0;
+}
+
+static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI)
+{
+ XExtensionVersion *ext;
+ XDeviceInfo *devices;
+ Display *display;
+ int num;
+ int i, j;
+ XextErrorHandler handler;
+
+ if (!(display = XOpenDisplay(dmxInput->name))) return;
+
+ /* Print out information about the XInput Extension. */
+ handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler);
+ ext = XGetExtensionVersion(display, INAME);
+ XSetExtensionErrorHandler(handler);
+
+ if (!ext || ext == (XExtensionVersion *)NoSuchExtension) {
+ dmxLogInput(dmxInput, "%s is not available\n", INAME);
+ } else {
+ dmxLogInput(dmxInput, "Locating devices on %s (%s version %d.%d)\n",
+ dmxInput->name, INAME,
+ ext->major_version, ext->minor_version);
+ devices = XListInputDevices(display, &num);
+
+ XFree(ext);
+ ext = NULL;
+
+ /* Print a list of all devices */
+ for (i = 0; i < num; i++) {
+ const char *use = "Unknown";
+ switch (devices[i].use) {
+ case IsXPointer: use = "XPointer"; break;
+ case IsXKeyboard: use = "XKeyboard"; break;
+ case IsXExtensionDevice: use = "XExtensionDevice"; break;
+ case IsXExtensionPointer: use = "XExtensionPointer"; break;
+ case IsXExtensionKeyboard: use = "XExtensionKeyboard"; break;
+ }
+ dmxLogInput(dmxInput, " %2d %-10.10s %-16.16s\n",
+ devices[i].id,
+ devices[i].name ? devices[i].name : "",
+ use);
+ }
+
+ /* Search for extensions */
+ for (i = 0; i < num; i++) {
+ switch (devices[i].use) {
+ case IsXKeyboard:
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxL = dmxInput->devs[j];
+ if (dmxL->type == DMX_LOCAL_KEYBOARD
+ && dmxL->deviceId < 0) {
+ dmxL->deviceId = devices[i].id;
+ dmxL->deviceName = (devices[i].name
+ ? strdup(devices[i].name)
+ : NULL);
+ }
+ }
+ break;
+ case IsXPointer:
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxL = dmxInput->devs[j];
+ if (dmxL->type == DMX_LOCAL_MOUSE && dmxL->deviceId < 0) {
+ dmxL->deviceId = devices[i].id;
+ dmxL->deviceName = (devices[i].name
+ ? xstrdup(devices[i].name)
+ : NULL);
+ }
+ }
+ break;
+ }
+ }
+ XFreeDeviceList(devices);
+ }
+ XCloseDisplay(display);
+}
+
+/** Re-initialize all the devices described in \a dmxInput. Called from
+ #dmxAdjustCursorBoundaries before the cursor is redisplayed. */
+void dmxInputReInit(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ if (dmxLocal->reinit)
+ dmxLocal->reinit(&dmxLocal->pDevice->public);
+ }
+}
+
+/** Re-initialize all the devices described in \a dmxInput. Called from
+ #dmxAdjustCursorBoundaries after the cursor is redisplayed. */
+void dmxInputLateReInit(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ if (dmxLocal->latereinit)
+ dmxLocal->latereinit(&dmxLocal->pDevice->public);
+ }
+}
+
+/** Initialize all of the devices described in \a dmxInput. */
+void dmxInputInit(DMXInputInfo *dmxInput)
+{
+ DeviceIntPtr pPointer = NULL, pKeyboard = NULL;
+ dmxArg a;
+ const char *name;
+ int i;
+ int doXI = 1; /* Include by default */
+ int forceConsole = 0;
+ int doWindows = 1; /* On by default */
+ int hasXkb = 0;
+
+ a = dmxArgParse(dmxInput->name);
+
+ for (i = 1; i < dmxArgC(a); i++) {
+ switch (hasXkb) {
+ case 1:
+ dmxInput->keycodes = xstrdup(dmxArgV(a, i));
+ ++hasXkb;
+ break;
+ case 2:
+ dmxInput->symbols = xstrdup(dmxArgV(a, i));
+ ++hasXkb;
+ break;
+ case 3:
+ dmxInput->geometry = xstrdup(dmxArgV(a, i));
+ hasXkb = 0;
+ break;
+ case 0:
+ if (!strcmp(dmxArgV(a, i), "noxi")) doXI = 0;
+ else if (!strcmp(dmxArgV(a, i), "xi")) doXI = 1;
+ else if (!strcmp(dmxArgV(a, i), "console")) forceConsole = 1;
+ else if (!strcmp(dmxArgV(a, i), "noconsole")) forceConsole = 0;
+ else if (!strcmp(dmxArgV(a, i), "windows")) doWindows = 1;
+ else if (!strcmp(dmxArgV(a, i), "nowindows")) doWindows = 0;
+ else if (!strcmp(dmxArgV(a, i), "xkb")) hasXkb = 1;
+ else {
+ dmxLog(dmxFatal,
+ "Unknown input argument: %s\n", dmxArgV(a, i));
+ }
+ }
+ }
+
+ name = dmxArgV(a, 0);
+
+ if (!strcmp(name, "local")) {
+ dmxPopulateLocal(dmxInput, a);
+ } else if (!strcmp(name, "dummy")) {
+ dmxInputCopyLocal(dmxInput, &DMXDummyMou);
+ dmxInputCopyLocal(dmxInput, &DMXDummyKbd);
+ dmxLogInput(dmxInput, "Using dummy input\n");
+ } else {
+ int found;
+
+ for (found = 0, i = 0; i < dmxNumScreens; i++) {
+ if (dmxPropertySameDisplay(&dmxScreens[i], name)) {
+ if (dmxScreens[i].shared)
+ dmxLog(dmxFatal,
+ "Cannot take input from shared backend (%s)\n",
+ name);
+ if (!dmxInput->core) {
+ dmxLog(dmxWarning,
+ "Cannot use core devices on a backend (%s)"
+ " as XInput devices\n", name);
+ } else {
+ char *pt;
+ for (pt = (char *)dmxInput->name; pt && *pt; pt++)
+ if (*pt == ',') *pt = '\0';
+ dmxInputCopyLocal(dmxInput, &DMXBackendMou);
+ dmxInputCopyLocal(dmxInput, &DMXBackendKbd);
+ dmxInput->scrnIdx = i;
+ dmxLogInput(dmxInput,
+ "Using backend input from %s\n", name);
+ }
+ ++found;
+ break;
+ }
+ }
+ if (!found || forceConsole) {
+ char *pt;
+ if (found) dmxInput->console = TRUE;
+ for (pt = (char *)dmxInput->name; pt && *pt; pt++)
+ if (*pt == ',') *pt = '\0';
+ dmxInputCopyLocal(dmxInput, &DMXConsoleMou);
+ dmxInputCopyLocal(dmxInput, &DMXConsoleKbd);
+ if (doWindows) {
+ dmxInput->windows = TRUE;
+ dmxInput->updateWindowInfo = dmxUpdateWindowInformation;
+ }
+ dmxLogInput(dmxInput,
+ "Using console input from %s (%s windows)\n",
+ name, doWindows ? "with" : "without");
+ }
+ }
+
+ dmxArgFree(a);
+
+ /* Locate extensions we may be interested in */
+ dmxInputScanForExtensions(dmxInput, doXI);
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ dmxLocal->pDevice = dmxAddDevice(dmxLocal);
+ if (dmxLocal->isCore) {
+ if (dmxLocal->type == DMX_LOCAL_MOUSE)
+ pPointer = dmxLocal->pDevice;
+ if (dmxLocal->type == DMX_LOCAL_KEYBOARD)
+ pKeyboard = dmxLocal->pDevice;
+ }
+ }
+
+ dmxInput->processInputEvents = dmxProcessInputEvents;
+ dmxInput->detached = False;
+
+ RegisterBlockAndWakeupHandlers(dmxBlockHandler, dmxWakeupHandler,
+ (void *)(uintptr_t)dmxInput->inputIdx);
+}
+
+static void dmxInputFreeLocal(DMXLocalInputInfoRec *local)
+{
+ if (!local) return;
+ if (local->isCore && local->type == DMX_LOCAL_MOUSE)
+ dmxLocalCorePointer = NULL;
+ if (local->isCore && local->type == DMX_LOCAL_KEYBOARD)
+ dmxLocalCoreKeyboard = NULL;
+ if (local->destroy_private) local->destroy_private(local->private);
+ free(local->history);
+ free(local->valuators);
+ free(local->deviceName);
+ local->private = NULL;
+ local->history = NULL;
+ local->deviceName = NULL;
+ free(local);
+}
+
+/** Free all of the memory associated with \a dmxInput */
+void dmxInputFree(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ if (!dmxInput) return;
+
+ free(dmxInput->keycodes);
+ free(dmxInput->symbols);
+ free(dmxInput->geometry);
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ dmxInputFreeLocal(dmxInput->devs[i]);
+ dmxInput->devs[i] = NULL;
+ }
+ free(dmxInput->devs);
+ dmxInput->devs = NULL;
+ dmxInput->numDevs = 0;
+ if (dmxInput->freename) free(dmxInput->name);
+ dmxInput->name = NULL;
+}
+
+/** Log information about all of the known devices using #dmxLog(). */
+void dmxInputLogDevices(void)
+{
+ int i, j;
+
+ dmxLog(dmxInfo, "%d devices:\n", dmxGetInputCount());
+ dmxLog(dmxInfo, " Id Name Classes\n");
+ for (j = 0; j < dmxNumInputs; j++) {
+ DMXInputInfo *dmxInput = &dmxInputs[j];
+ const char *pt = strchr(dmxInput->name, ',');
+ int len = (pt
+ ? (size_t)(pt-dmxInput->name)
+ : strlen(dmxInput->name));
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DeviceIntPtr pDevice = dmxInput->devs[i]->pDevice;
+ if (pDevice) {
+ dmxLog(dmxInfo, " %2d%c %-20.20s",
+ pDevice->id,
+ dmxInput->detached ? 'D' : ' ',
+ pDevice->name);
+ if (pDevice->key) dmxLogCont(dmxInfo, " key");
+ if (pDevice->valuator) dmxLogCont(dmxInfo, " val");
+ if (pDevice->button) dmxLogCont(dmxInfo, " btn");
+ if (pDevice->focus) dmxLogCont(dmxInfo, " foc");
+ if (pDevice->kbdfeed) dmxLogCont(dmxInfo, " fb/kbd");
+ if (pDevice->ptrfeed) dmxLogCont(dmxInfo, " fb/ptr");
+ if (pDevice->intfeed) dmxLogCont(dmxInfo, " fb/int");
+ if (pDevice->stringfeed) dmxLogCont(dmxInfo, " fb/str");
+ if (pDevice->bell) dmxLogCont(dmxInfo, " fb/bel");
+ if (pDevice->leds) dmxLogCont(dmxInfo, " fb/led");
+ if (!pDevice->key && !pDevice->valuator && !pDevice->button
+ && !pDevice->focus && !pDevice->kbdfeed
+ && !pDevice->ptrfeed && !pDevice->intfeed
+ && !pDevice->stringfeed && !pDevice->bell
+ && !pDevice->leds) dmxLogCont(dmxInfo, " (none)");
+
+ dmxLogCont(dmxInfo, "\t[i%d/%*.*s",
+ dmxInput->inputIdx, len, len, dmxInput->name);
+ if (dmxInput->devs[i]->deviceId >= 0)
+ dmxLogCont(dmxInfo, "/id%d", dmxInput->devs[i]->deviceId);
+ if (dmxInput->devs[i]->deviceName)
+ dmxLogCont(dmxInfo, "=%s", dmxInput->devs[i]->deviceName);
+ dmxLogCont(dmxInfo, "] %s\n",
+ dmxInput->devs[i]->isCore
+ ? "core"
+ : (dmxInput->devs[i]->sendsCore
+ ? "extension (sends core events)"
+ : "extension"));
+ }
+ }
+ }
+}
+
+/** Detach an input */
+int dmxInputDetach(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ if (dmxInput->detached) return BadAccess;
+
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ dmxLogInput(dmxInput, "Detaching device id %d: %s%s\n",
+ dmxLocal->pDevice->id,
+ dmxLocal->pDevice->name,
+ dmxLocal->isCore
+ ? " [core]"
+ : (dmxLocal->sendsCore
+ ? " [sends core events]"
+ : ""));
+ DisableDevice(dmxLocal->pDevice, TRUE);
+ }
+ dmxInput->detached = True;
+ dmxInputLogDevices();
+ return 0;
+}
+
+/** Search for input associated with \a dmxScreen, and detach. */
+void dmxInputDetachAll(DMXScreenInfo *dmxScreen)
+{
+ int i;
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (dmxInput->scrnIdx == dmxScreen->index) dmxInputDetach(dmxInput);
+ }
+}
+
+/** Search for input associated with \a deviceId, and detach. */
+int dmxInputDetachId(int id)
+{
+ DMXInputInfo *dmxInput = dmxInputLocateId(id);
+
+ if (!dmxInput) return BadValue;
+
+ return dmxInputDetach(dmxInput);
+}
+
+DMXInputInfo *dmxInputLocateId(int id)
+{
+ int i, j;
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
+ if (dmxLocal->pDevice->id == id) return dmxInput;
+ }
+ }
+ return NULL;
+}
+
+static int dmxInputAttachNew(DMXInputInfo *dmxInput, int *id)
+{
+ dmxInputInit(dmxInput);
+ InitAndStartDevices();
+ if (id && dmxInput->devs) *id = dmxInput->devs[0]->pDevice->id;
+ dmxInputLogDevices();
+ return 0;
+}
+
+static int dmxInputAttachOld(DMXInputInfo *dmxInput, int *id)
+{
+ int i;
+
+ dmxInput->detached = False;
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ if (id) *id = dmxLocal->pDevice->id;
+ dmxLogInput(dmxInput,
+ "Attaching device id %d: %s%s\n",
+ dmxLocal->pDevice->id,
+ dmxLocal->pDevice->name,
+ dmxLocal->isCore
+ ? " [core]"
+ : (dmxLocal->sendsCore
+ ? " [sends core events]"
+ : ""));
+ EnableDevice(dmxLocal->pDevice, TRUE);
+ }
+ dmxInputLogDevices();
+ return 0;
+}
+
+int dmxInputAttachConsole(const char *name, int isCore, int *id)
+{
+ DMXInputInfo *dmxInput;
+ int i;
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ dmxInput = &dmxInputs[i];
+ if (dmxInput->scrnIdx == -1
+ && dmxInput->detached
+ && !strcmp(dmxInput->name, name)) {
+ /* Found match */
+ dmxLogInput(dmxInput, "Reattaching detached console input\n");
+ return dmxInputAttachOld(dmxInput, id);
+ }
+ }
+
+ /* No match found */
+ dmxInput = dmxConfigAddInput(xstrdup(name), isCore);
+ dmxInput->freename = TRUE;
+ dmxLogInput(dmxInput, "Attaching new console input\n");
+ return dmxInputAttachNew(dmxInput, id);
+}
+
+int dmxInputAttachBackend(int physicalScreen, int isCore, int *id)
+{
+ DMXInputInfo *dmxInput;
+ DMXScreenInfo *dmxScreen;
+ int i;
+
+ if (physicalScreen < 0 || physicalScreen >= dmxNumScreens) return BadValue;
+ for (i = 0; i < dmxNumInputs; i++) {
+ dmxInput = &dmxInputs[i];
+ if (dmxInput->scrnIdx != -1 && dmxInput->scrnIdx == physicalScreen) {
+ /* Found match */
+ if (!dmxInput->detached) return BadAccess; /* Already attached */
+ dmxScreen = &dmxScreens[physicalScreen];
+ if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */
+ dmxLogInput(dmxInput, "Reattaching detached backend input\n");
+ return dmxInputAttachOld(dmxInput, id);
+ }
+ }
+ /* No match found */
+ dmxScreen = &dmxScreens[physicalScreen];
+ if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */
+ dmxInput = dmxConfigAddInput(dmxScreen->name, isCore);
+ dmxLogInput(dmxInput, "Attaching new backend input\n");
+ return dmxInputAttachNew(dmxInput, id);
+}
diff --git a/xorg-server/hw/xfree86/doc/man/Makefile.am b/xorg-server/hw/xfree86/doc/man/Makefile.am
index fe330a72c..80e22cbab 100644
--- a/xorg-server/hw/xfree86/doc/man/Makefile.am
+++ b/xorg-server/hw/xfree86/doc/man/Makefile.am
@@ -1,3 +1,3 @@
include $(top_srcdir)/manpages.am
appman_PRE = Xorg.man
-fileman_PRE = xorg.conf.man
+fileman_PRE = xorg.conf.man xorg.conf.d.man
diff --git a/xorg-server/hw/xfree86/doc/man/xorg.conf.d.man b/xorg-server/hw/xfree86/doc/man/xorg.conf.d.man
new file mode 100644
index 000000000..6b3379ece
--- /dev/null
+++ b/xorg-server/hw/xfree86/doc/man/xorg.conf.d.man
@@ -0,0 +1 @@
+.so man__filemansuffix__/xorg.conf.__filemansuffix__
diff --git a/xorg-server/hw/xwin/InitOutput.c b/xorg-server/hw/xwin/InitOutput.c
index fea4a34f9..7faed0170 100644
--- a/xorg-server/hw/xwin/InitOutput.c
+++ b/xorg-server/hw/xwin/InitOutput.c
@@ -1,1108 +1,1111 @@
-
-/*
-
-Copyright 1993, 1998 The Open Group
-Copyright (C) Colin Harrison 2005-2008
-
-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_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include "winmsg.h"
-#include "winconfig.h"
-#include "winprefs.h"
-#ifdef XWIN_CLIPBOARD
-#include "X11/Xlocale.h"
-#endif
-#ifdef DPMSExtension
-#include "dpmsproc.h"
-#endif
-#ifdef __CYGWIN__
-#include <mntent.h>
-#endif
-#if defined(WIN32)
-#include "xkbsrv.h"
-#endif
-#ifdef RELOCATE_PROJECTROOT
-#include <shlobj.h>
-typedef HRESULT (*SHGETFOLDERPATHPROC)(
- HWND hwndOwner,
- int nFolder,
- HANDLE hToken,
- DWORD dwFlags,
- LPTSTR pszPath
-);
-#endif
-
-/*
- * References to external symbols
- */
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboardStarted;
-extern pthread_t g_ptClipboardProc;
-extern HWND g_hwndClipboard;
-extern Bool g_fClipboard;
-#endif
-
-
-/*
- module handle for dynamically loaded comctl32 library
-*/
-static HMODULE g_hmodCommonControls = NULL;
-
-/*
- * Function prototypes
- */
-
-#ifdef XWIN_CLIPBOARD
-static void
-winClipboardShutdown (void);
-#endif
-
-#if defined(DDXOSVERRORF)
-void
-OsVendorVErrorF (const char *pszFormat, va_list va_args);
-#endif
-
-static Bool
-winCheckDisplayNumber (void);
-
-void
-winLogCommandLine (int argc, char *argv[]);
-
-void
-winLogVersionInfo (void);
-
-Bool
-winValidateArgs (void);
-
-#ifdef RELOCATE_PROJECTROOT
-const char *
-winGetBaseDir(void);
-#endif
-
-/*
- * For the depth 24 pixmap we default to 32 bits per pixel, but
- * we change this pixmap format later if we detect that the display
- * is going to be running at 24 bits per pixel.
- *
- * FIXME: On second thought, don't DIBs only support 32 bits per pixel?
- * DIBs are the underlying bitmap used for DirectDraw surfaces, so it
- * seems that all pixmap formats with depth 24 would be 32 bits per pixel.
- * Confirm whether depth 24 DIBs can have 24 bits per pixel, then remove/keep
- * the bits per pixel adjustment and update this comment to reflect the
- * situation. Harold Hunt - 2002/07/02
- */
-
-static PixmapFormatRec g_PixmapFormats[] = {
- { 1, 1, BITMAP_SCANLINE_PAD },
- { 4, 8, BITMAP_SCANLINE_PAD },
- { 8, 8, BITMAP_SCANLINE_PAD },
- { 15, 16, BITMAP_SCANLINE_PAD },
- { 16, 16, BITMAP_SCANLINE_PAD },
- { 24, 32, BITMAP_SCANLINE_PAD },
- { 32, 32, BITMAP_SCANLINE_PAD }
-};
-
-const int NUMFORMATS = sizeof (g_PixmapFormats) / sizeof (g_PixmapFormats[0]);
-
-#ifdef XWIN_CLIPBOARD
-static void
-winClipboardShutdown (void)
-{
- /* Close down clipboard resources */
- if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted)
- {
- /* Synchronously destroy the clipboard window */
- if (g_hwndClipboard != NULL)
- {
- SendMessage (g_hwndClipboard, WM_DESTROY, 0, 0);
- /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
- }
- else
- return;
-
- /* Wait for the clipboard thread to exit */
- pthread_join (g_ptClipboardProc, NULL);
-
- g_fClipboardLaunched = FALSE;
- g_fClipboardStarted = FALSE;
-
- winDebug ("winClipboardShutdown - Clipboard thread has exited.\n");
- }
-}
-#endif
-
-void
-ddxPushProviders(void)
-{
-#ifdef XWIN_GLX_WINDOWS
- if (g_fNativeGl)
- {
- /* install the native GL provider */
- glxWinPushNativeProvider();
- }
-#endif
-}
-
-#if defined(DDXBEFORERESET)
-/*
- * Called right before KillAllClients when the server is going to reset,
- * allows us to shutdown our seperate threads cleanly.
- */
-
-void
-ddxBeforeReset (void)
-{
- winDebug ("ddxBeforeReset - Hello\n");
-
-#ifdef XWIN_CLIPBOARD
- winClipboardShutdown ();
-#endif
-}
-#endif
-
-
-/* See Porting Layer Definition - p. 57 */
-void
-ddxGiveUp (void)
-{
- int i;
-
-#if CYGDEBUG
- winDebug ("ddxGiveUp\n");
-#endif
-
- /* Perform per-screen deinitialization */
- for (i = 0; i < g_iNumScreens; ++i)
- {
- /* Delete the tray icon */
- if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen)
- winDeleteNotifyIcon (winGetScreenPriv (g_ScreenInfo[i].pScreen));
- }
-
-#ifdef XWIN_MULTIWINDOW
- /* Notify the worker threads we're exiting */
- winDeinitMultiWindowWM ();
-#endif
-
-#ifdef HAS_DEVWINDOWS
- /* Close our handle to our message queue */
- if (g_fdMessageQueue != WIN_FD_INVALID)
- {
- /* Close /dev/windows */
- close (g_fdMessageQueue);
-
- /* Set the file handle to invalid */
- g_fdMessageQueue = WIN_FD_INVALID;
- }
-#endif
-
- if (!g_fLogInited) {
- g_pszLogFile = LogInit (g_pszLogFile, NULL);
- g_fLogInited = TRUE;
- }
- LogClose ();
-
- /*
- * At this point we aren't creating any new screens, so
- * we are guaranteed to not need the DirectDraw functions.
- */
- winReleaseDDProcAddresses();
-
- /* Unload our TrackMouseEvent function pointer */
- if (g_hmodCommonControls != NULL)
- {
- FreeLibrary (g_hmodCommonControls);
- g_hmodCommonControls = NULL;
- g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
- }
-
- /* Free concatenated command line */
- free(g_pszCommandLine);
- g_pszCommandLine = NULL;
-
- /* Remove our keyboard hook if it is installed */
- winRemoveKeyboardHookLL ();
-
- /* Tell Windows that we want to end the app */
- PostQuitMessage (0);
-}
-
-
-/* See Porting Layer Definition - p. 57 */
-void
-AbortDDX (void)
-{
-#if CYGDEBUG
- winDebug ("AbortDDX\n");
-#endif
- ddxGiveUp ();
-}
-
-#ifdef __CYGWIN__
-/* hasmntopt is currently not implemented for cygwin */
-static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt)
-{
- const char *s;
- size_t len;
- if (mnt == NULL)
- return NULL;
- if (opt == NULL)
- return NULL;
- if (mnt->mnt_opts == NULL)
- return NULL;
-
- len = strlen(opt);
- s = strstr(mnt->mnt_opts, opt);
- if (s == NULL)
- return NULL;
- if ((s == mnt->mnt_opts || *(s-1) == ',') && (s[len] == 0 || s[len] == ','))
- return (char *)opt;
- return NULL;
-}
-
-static void
-winCheckMount(void)
-{
- FILE *mnt;
- struct mntent *ent;
-
- enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
- level = none, curlevel;
- BOOL binary = TRUE;
-
- mnt = setmntent("/etc/mtab", "r");
- if (mnt == NULL)
- {
- ErrorF("setmntent failed");
- return;
- }
-
- while ((ent = getmntent(mnt)) != NULL)
- {
- BOOL system = (winCheckMntOpt(ent, "user") != NULL);
- BOOL root = (strcmp(ent->mnt_dir, "/") == 0);
- BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0);
-
- if (system)
- {
- if (root)
- curlevel = sys_root;
- else if (tmp)
- curlevel = sys_tmp;
- else
- continue;
- }
- else
- {
- if (root)
- curlevel = user_root;
- else if (tmp)
- curlevel = user_tmp;
- else
- continue;
- }
-
- if (curlevel <= level)
- continue;
- level = curlevel;
-
- if ((winCheckMntOpt(ent, "binary") == NULL) &&
- (winCheckMntOpt(ent, "binmode") == NULL))
- binary = FALSE;
- else
- binary = TRUE;
- }
-
- if (endmntent(mnt) != 1)
- {
- ErrorF("endmntent failed");
- return;
- }
-
- if (!binary)
- winMsg(X_WARNING, "/tmp mounted in textmode\n");
-}
-#else
-static void
-winCheckMount(void)
-{
-}
-#endif
-
-#ifdef RELOCATE_PROJECTROOT
-const char *
-winGetBaseDir(void)
-{
- static BOOL inited = FALSE;
- static char buffer[MAX_PATH];
- if (!inited)
- {
- char *fendptr;
- HMODULE module = GetModuleHandle(NULL);
- DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
- if (sizeof(buffer) > 0)
- buffer[sizeof(buffer)-1] = 0;
-
- fendptr = buffer + size;
- while (fendptr > buffer)
- {
- if (*fendptr == '\\' || *fendptr == '/')
- {
- *fendptr = 0;
- break;
- }
- fendptr--;
- }
- inited = TRUE;
- }
- return buffer;
-}
-#endif
-
-static void
-winFixupPaths (void)
-{
- BOOL changed_fontpath = FALSE;
- MessageType font_from = X_DEFAULT;
-#ifdef RELOCATE_PROJECTROOT
- const char *basedir = winGetBaseDir();
- size_t basedirlen = strlen(basedir);
-#endif
-
-#ifdef READ_FONTDIRS
- {
- /* Open fontpath configuration file */
- FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt");
- if (fontdirs != NULL)
- {
- char buffer[256];
- int needs_sep = TRUE;
- int comment_block = FALSE;
-
- /* get default fontpath */
- char *fontpath = strdup(defaultFontPath);
- size_t size = strlen(fontpath);
-
- /* read all lines */
- while (!feof(fontdirs))
- {
- size_t blen;
- char *hashchar;
- char *str;
- int has_eol = FALSE;
-
- /* read one line */
- str = fgets(buffer, sizeof(buffer), fontdirs);
- if (str == NULL) /* stop on error or eof */
- break;
-
- if (strchr(str, '\n') != NULL)
- has_eol = TRUE;
-
- /* check if block is continued comment */
- if (comment_block)
- {
- /* ignore all input */
- *str = 0;
- blen = 0;
- if (has_eol) /* check if line ended in this block */
- comment_block = FALSE;
- }
- else
- {
- /* find comment character. ignore all trailing input */
- hashchar = strchr(str, '#');
- if (hashchar != NULL)
- {
- *hashchar = 0;
- if (!has_eol) /* mark next block as continued comment */
- comment_block = TRUE;
- }
- }
-
- /* strip whitespaces from beginning */
- while (*str == ' ' || *str == '\t')
- str++;
-
- /* get size, strip whitespaces from end */
- blen = strlen(str);
- while (blen > 0 && (str[blen-1] == ' ' ||
- str[blen-1] == '\t' || str[blen-1] == '\n'))
- {
- str[--blen] = 0;
- }
-
- /* still something left to add? */
- if (blen > 0)
- {
- size_t newsize = size + blen;
- /* reserve one character more for ',' */
- if (needs_sep)
- newsize++;
-
- /* allocate memory */
- if (fontpath == NULL)
- fontpath = malloc(newsize+1);
- else
- fontpath = realloc(fontpath, newsize+1);
-
- /* add separator */
- if (needs_sep)
- {
- fontpath[size] = ',';
- size++;
- needs_sep = FALSE;
- }
-
- /* mark next line as new entry */
- if (has_eol)
- needs_sep = TRUE;
-
- /* add block */
- strncpy(fontpath + size, str, blen);
- fontpath[newsize] = 0;
- size = newsize;
- }
- }
-
- /* cleanup */
- fclose(fontdirs);
- defaultFontPath = strdup(fontpath);
- free(fontpath);
- changed_fontpath = TRUE;
- font_from = X_CONFIG;
- }
- }
-#endif /* READ_FONTDIRS */
-#ifdef RELOCATE_PROJECTROOT
- {
- const char *libx11dir = PROJECTROOT "/lib/X11";
- size_t libx11dir_len = strlen(libx11dir);
- char *newfp = NULL;
- size_t newfp_len = 0;
- const char *endptr, *ptr, *oldptr = defaultFontPath;
-
- endptr = oldptr + strlen(oldptr);
- ptr = strchr(oldptr, ',');
- if (ptr == NULL)
- ptr = endptr;
- while (ptr != NULL)
- {
- size_t oldfp_len = (ptr - oldptr);
- size_t newsize = oldfp_len;
- char *newpath = malloc(newsize + 1);
- strncpy(newpath, oldptr, newsize);
- newpath[newsize] = 0;
-
-
- if (strncmp(libx11dir, newpath, libx11dir_len) == 0)
- {
- char *compose;
- newsize = newsize - libx11dir_len + basedirlen;
- compose = malloc(newsize + 1);
- strcpy(compose, basedir);
- strncat(compose, newpath + libx11dir_len, newsize - basedirlen);
- compose[newsize] = 0;
- free(newpath);
- newpath = compose;
- }
-
- oldfp_len = newfp_len;
- if (oldfp_len > 0)
- newfp_len ++; /* space for separator */
- newfp_len += newsize;
-
- if (newfp == NULL)
- newfp = malloc(newfp_len + 1);
- else
- newfp = realloc(newfp, newfp_len + 1);
-
- if (oldfp_len > 0)
- {
- strcpy(newfp + oldfp_len, ",");
- oldfp_len++;
- }
- strcpy(newfp + oldfp_len, newpath);
-
- free(newpath);
-
- if (*ptr == 0)
- {
- oldptr = ptr;
- ptr = NULL;
- } else
- {
- oldptr = ptr + 1;
- ptr = strchr(oldptr, ',');
- if (ptr == NULL)
- ptr = endptr;
- }
- }
-
- defaultFontPath = strdup(newfp);
- free(newfp);
- changed_fontpath = TRUE;
- }
-#endif /* RELOCATE_PROJECTROOT */
- if (changed_fontpath)
- winMsg (font_from, "FontPath set to \"%s\"\n", defaultFontPath);
-
-#ifdef RELOCATE_PROJECTROOT
- if (getenv("XKEYSYMDB") == NULL)
- {
- char buffer[MAX_PATH];
- snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB",
- basedir);
- buffer[sizeof(buffer)-1] = 0;
- putenv(buffer);
- }
- if (getenv("XERRORDB") == NULL)
- {
- char buffer[MAX_PATH];
- snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB",
- basedir);
- buffer[sizeof(buffer)-1] = 0;
- putenv(buffer);
- }
- if (getenv("XLOCALEDIR") == NULL)
- {
- char buffer[MAX_PATH];
- snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale",
- basedir);
- buffer[sizeof(buffer)-1] = 0;
- putenv(buffer);
- }
- if (getenv("HOME") == NULL)
- {
- HMODULE shfolder;
- SHGETFOLDERPATHPROC shgetfolderpath = NULL;
- char buffer[MAX_PATH + 5];
- strncpy(buffer, "HOME=", 5);
-
- /* Try to load SHGetFolderPath from shfolder.dll and shell32.dll */
-
- shfolder = LoadLibrary("shfolder.dll");
- /* fallback to shell32.dll */
- if (shfolder == NULL)
- shfolder = LoadLibrary("shell32.dll");
-
- /* resolve SHGetFolderPath */
- if (shfolder != NULL)
- shgetfolderpath = (SHGETFOLDERPATHPROC)GetProcAddress(shfolder, "SHGetFolderPathA");
-
- /* query appdata directory */
- if (shgetfolderpath &&
- shgetfolderpath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0,
- buffer + 5) == 0)
- {
- putenv(buffer);
- } else
- {
- winMsg (X_ERROR, "Can not determine HOME directory\n");
- }
- if (shfolder != NULL)
- FreeLibrary(shfolder);
- }
- if (!g_fLogFileChanged) {
- static char buffer[MAX_PATH];
- DWORD size = GetTempPath(sizeof(buffer), buffer);
- if (size && size < sizeof(buffer))
- {
- snprintf(buffer + size, sizeof(buffer) - size,
- "XWin.%s.log", display);
- buffer[sizeof(buffer)-1] = 0;
- g_pszLogFile = buffer;
- winMsg (X_DEFAULT, "Logfile set to \"%s\"\n", g_pszLogFile);
- }
- }
- {
- static char xkbbasedir[MAX_PATH];
-
- snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkb", basedir);
- if (sizeof(xkbbasedir) > 0)
- xkbbasedir[sizeof(xkbbasedir)-1] = 0;
- XkbBaseDirectory = xkbbasedir;
- XkbBinDirectory = basedir;
- }
-#endif /* RELOCATE_PROJECTROOT */
-}
-
-void
-OsVendorInit (void)
-{
- /* Re-initialize global variables on server reset */
- winInitializeGlobals ();
-
- winFixupPaths();
-
-#ifdef DDXOSVERRORF
- if (!OsVendorVErrorFProc)
- OsVendorVErrorFProc = OsVendorVErrorF;
-#endif
-
- if (!g_fLogInited) {
- /* keep this order. If LogInit fails it calls Abort which then calls
- * ddxGiveUp where LogInit is called again and creates an infinite
- * recursion. If we set g_fLogInited to TRUE before the init we
- * avoid the second call
- */
- g_fLogInited = TRUE;
- g_pszLogFile = LogInit (g_pszLogFile, NULL);
- }
- LogSetParameter (XLOG_FLUSH, 1);
- LogSetParameter (XLOG_VERBOSITY, g_iLogVerbose);
- LogSetParameter (XLOG_FILE_VERBOSITY, g_iLogVerbose);
-
- /* Log the version information */
- if (serverGeneration == 1)
- winLogVersionInfo ();
-
- winCheckMount();
-
- /* Add a default screen if no screens were specified */
- if (g_iNumScreens == 0)
- {
- winDebug ("OsVendorInit - Creating default screen 0\n");
-
- /*
- * We need to initialize the default screen 0 if no -screen
- * arguments were processed.
- *
- * Add a screen 0 using the defaults set by winInitializeDefaultScreens()
- * and any additional default screen parameters given
- */
- winInitializeScreens(1);
-
- /* We have to flag this as an explicit screen, even though it isn't */
- g_ScreenInfo[0].fExplicitScreen = TRUE;
- }
-}
-
-
-static void
-winUseMsg (void)
-{
- ErrorF("\n");
- ErrorF("\n");
- ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n");
- ErrorF("\n");
-
-#ifdef XWIN_CLIPBOARD
- ErrorF ("-[no]clipboard\n"
- "\tEnable [disable] the clipboard integration. Default is enabled.\n");
-#endif
-
- ErrorF ("-clipupdates num_boxes\n"
- "\tUse a clipping region to constrain shadow update blits to\n"
- "\tthe updated region when num_boxes, or more, are in the\n"
- "\tupdated region.\n");
-
-#ifdef XWIN_XF86CONFIG
- ErrorF ("-config\n"
- "\tSpecify a configuration file.\n");
-
- ErrorF ("-configdir\n"
- "\tSpecify a configuration directory.\n");
-#endif
-
- ErrorF ("-depth bits_per_pixel\n"
- "\tSpecify an optional bitdepth to use in fullscreen mode\n"
- "\twith a DirectDraw engine.\n");
-
- ErrorF ("-emulate3buttons [timeout]\n"
- "\tEmulate 3 button mouse with an optional timeout in\n"
- "\tmilliseconds.\n");
-
-#ifdef XWIN_EMULATEPSEUDO
- ErrorF ("-emulatepseudo\n"
- "\tCreate a depth 8 PseudoColor visual when running in\n"
- "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n"
- "\tdepths. The PseudoColor visual does not have correct colors,\n"
- "\tand it may crash, but it at least allows you to run your\n"
- "\tapplication in TrueColor modes.\n");
-#endif
-
- ErrorF ("-engine engine_type_id\n"
- "\tOverride the server's automatically selected engine type:\n"
- "\t\t1 - Shadow GDI\n"
- "\t\t2 - Shadow DirectDraw\n"
- "\t\t4 - Shadow DirectDraw4 Non-Locking\n"
-#ifdef XWIN_NATIVEGDI
- "\t\t16 - Native GDI - experimental\n"
-#endif
- );
-
- ErrorF ("-fullscreen\n"
- "\tRun the server in fullscreen mode.\n");
-
- ErrorF ("-ignoreinput\n"
- "\tIgnore keyboard and mouse input.\n");
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- ErrorF ("-internalwm\n"
- "\tRun the internal window manager.\n");
-#endif
-
-#ifdef XWIN_XF86CONFIG
- ErrorF ("-keyboard\n"
- "\tSpecify a keyboard device from the configuration file.\n");
-#endif
-
- ErrorF ("-[no]keyhook\n"
- "\tGrab special Windows keypresses like Alt-Tab or the Menu "
- "key.\n");
-
- ErrorF ("-lesspointer\n"
- "\tHide the windows mouse pointer when it is over any\n"
- "\t" EXECUTABLE_NAME " window. This prevents ghost cursors appearing when\n"
- "\tthe Windows cursor is drawn on top of the X cursor\n");
-
- ErrorF ("-logfile filename\n"
- "\tWrite log messages to <filename>.\n");
-
- ErrorF ("-logverbose verbosity\n"
- "\tSet the verbosity of log messages. [NOTE: Only a few messages\n"
- "\trespect the settings yet]\n"
- "\t\t0 - only print fatal error.\n"
- "\t\t1 - print additional configuration information.\n"
- "\t\t2 - print additional runtime information [default].\n"
- "\t\t3 - print debugging and tracing information.\n");
-
- ErrorF ("-[no]multimonitors or -[no]multiplemonitors\n"
- "\tUse the entire virtual screen if multiple\n"
- "\tmonitors are present.\n");
-
-#ifdef XWIN_MULTIWINDOW
- ErrorF ("-multiwindow\n"
- "\tRun the server in multi-window mode.\n");
-#endif
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- ErrorF ("-mwextwm\n"
- "\tRun the server in multi-window external window manager mode.\n");
-#endif
-
- ErrorF ("-nodecoration\n"
- "\tDo not draw a window border, title bar, etc. Windowed\n"
- "\tmode only.\n");
-
-#ifdef XWIN_CLIPBOARD
- ErrorF ("-nounicodeclipboard\n"
- "\tDo not use Unicode clipboard even if on a NT-based platform.\n");
-#endif
-
- ErrorF ("-refresh rate_in_Hz\n"
- "\tSpecify an optional refresh rate to use in fullscreen mode\n"
- "\twith a DirectDraw engine.\n");
-
- ErrorF ("-rootless\n"
- "\tRun the server in rootless mode.\n");
-
- ErrorF ("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n"
- "\tEnable screen scr_num and optionally specify a width and\n"
- "\theight and initial position for that screen. Additionally\n"
- "\ta monitor number can be specified to start the server on,\n"
- "\tat which point, all coordinates become relative to that\n"
- "\tmonitor (Not for Windows NT4 and 95). Examples:\n"
- "\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n"
- "\t -screen 0 1024x768@3 ; 3rd monitor size 1024x768\n"
- "\t -screen 0 @1 ; on 1st monitor using its full resolution (the default)\n");
-
- ErrorF ("-scrollbars\n"
- "\tIn windowed mode, allow screens bigger than the Windows desktop.\n"
- "\tMoreover, if the window has decorations, one can now resize\n"
- "\tit.\n");
-
- ErrorF ("-silent-dup-error\n"
- "\tIf another instance of " EXECUTABLE_NAME " with the same display number is running\n"
- "\texit silently and don't display any error message.\n");
-
- ErrorF ("-swcursor\n"
- "\tDisable the usage of the Windows cursor and use the X11 software\n"
- "\tcursor instead.\n");
-
- ErrorF ("-[no]trayicon\n"
- "\tDo not create a tray icon. Default is to create one\n"
- "\ticon per screen. You can globally disable tray icons with\n"
- "\t-notrayicon, then enable it for specific screens with\n"
- "\t-trayicon for those screens.\n");
-
- ErrorF ("-[no]unixkill\n"
- "\tCtrl+Alt+Backspace exits the X Server.\n");
-
-#ifdef XWIN_GLX_WINDOWS
- ErrorF ("-[no]wgl\n"
- "\tEnable the GLX extension to use the native Windows WGL interface for accelerated OpenGL\n");
-#endif
-
- ErrorF ("-[no]winkill\n"
- "\tAlt+F4 exits the X Server.\n");
-
- ErrorF ("-xkblayout XKBLayout\n"
- "\tEquivalent to XKBLayout in XF86Config files.\n"
- "\tFor example: -xkblayout de\n");
-
- ErrorF ("-xkbmodel XKBModel\n"
- "\tEquivalent to XKBModel in XF86Config files.\n");
-
- ErrorF ("-xkboptions XKBOptions\n"
- "\tEquivalent to XKBOptions in XF86Config files.\n");
-
- ErrorF ("-xkbrules XKBRules\n"
- "\tEquivalent to XKBRules in XF86Config files.\n");
-
- ErrorF ("-xkbvariant XKBVariant\n"
- "\tEquivalent to XKBVariant in XF86Config files.\n"
- "\tFor example: -xkbvariant nodeadkeys\n");
-}
-
-/* See Porting Layer Definition - p. 57 */
-void
-ddxUseMsg(void)
-{
- /* Set a flag so that FatalError won't give duplicate warning message */
- g_fSilentFatalError = TRUE;
-
- winUseMsg();
-
- /* Log file will not be opened for UseMsg unless we open it now */
- if (!g_fLogInited) {
- g_pszLogFile = LogInit (g_pszLogFile, NULL);
- g_fLogInited = TRUE;
- }
- LogClose ();
-
- /* Notify user where UseMsg text can be found.*/
- if (!g_fNoHelpMessageBox)
- winMessageBoxF ("The " PROJECT_NAME " help text has been printed to "
- "%s.\n"
- "Please open %s to read the help text.\n",
- MB_ICONINFORMATION, g_pszLogFile, g_pszLogFile);
-}
-
-/* See Porting Layer Definition - p. 20 */
-/*
- * Do any global initialization, then initialize each screen.
- *
- * NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv
- */
-
-void
-InitOutput (ScreenInfo *screenInfo, int argc, char *argv[])
-{
- int i;
-
- /* Log the command line */
- winLogCommandLine (argc, argv);
-
-#if CYGDEBUG
- winDebug ("InitOutput\n");
-#endif
-
- /* Validate command-line arguments */
- if (serverGeneration == 1 && !winValidateArgs ())
- {
- FatalError ("InitOutput - Invalid command-line arguments found. "
- "Exiting.\n");
- }
-
- /* Check for duplicate invocation on same display number.*/
- if (serverGeneration == 1 && !winCheckDisplayNumber ())
- {
- if (g_fSilentDupError)
- g_fSilentFatalError = TRUE;
- FatalError ("InitOutput - Duplicate invocation on display "
- "number: %s. Exiting.\n", display);
- }
-
-#ifdef XWIN_XF86CONFIG
- /* Try to read the xorg.conf-style configuration file */
- if (!winReadConfigfile ())
- winErrorFVerb (1, "InitOutput - Error reading config file\n");
-#else
- winMsg(X_INFO, "xorg.conf is not supported\n");
- winMsg(X_INFO, "See http://x.cygwin.com/docs/faq/cygwin-x-faq.html "
- "for more information\n");
- winConfigFiles ();
-#endif
-
- /* Load preferences from XWinrc file */
- LoadPreferences();
-
- /* Setup global screen info parameters */
- screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
- screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
- screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
- screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
- screenInfo->numPixmapFormats = NUMFORMATS;
-
- /* Describe how we want common pixmap formats padded */
- for (i = 0; i < NUMFORMATS; i++)
- {
- screenInfo->formats[i] = g_PixmapFormats[i];
- }
-
- /* Load pointers to DirectDraw functions */
- winGetDDProcAddresses ();
-
- /* Detect supported engines */
- winDetectSupportedEngines ();
-
- /* Load common controls library */
- g_hmodCommonControls = LoadLibraryEx ("comctl32.dll", NULL, 0);
-
- /* Load TrackMouseEvent function pointer */
- g_fpTrackMouseEvent = GetProcAddress (g_hmodCommonControls,
- "_TrackMouseEvent");
- if (g_fpTrackMouseEvent == NULL)
- {
- winErrorFVerb (1, "InitOutput - Could not get pointer to function\n"
- "\t_TrackMouseEvent in comctl32.dll. Try installing\n"
- "\tInternet Explorer 3.0 or greater if you have not\n"
- "\talready.\n");
-
- /* Free the library since we won't need it */
- FreeLibrary (g_hmodCommonControls);
- g_hmodCommonControls = NULL;
-
- /* Set function pointer to point to no operation function */
- g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
- }
-
- /* Store the instance handle */
- g_hInstance = GetModuleHandle (NULL);
-
- /* Initialize each screen */
- for (i = 0; i < g_iNumScreens; ++i)
- {
- /* Initialize the screen */
- if (-1 == AddScreen (winScreenInit, argc, argv))
- {
- FatalError ("InitOutput - Couldn't add screen %d", i);
- }
- }
-
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
-
- /* Generate a cookie used by internal clients for authorization */
- if (g_fXdmcpEnabled || g_fAuthEnabled)
- winGenerateAuthorization ();
-
- /* Perform some one time initialization */
- if (1 == serverGeneration)
- {
- /*
- * setlocale applies to all threads in the current process.
- * Apply locale specified in LANG environment variable.
- */
- setlocale (LC_ALL, "");
- }
-#endif
-
-#if CYGDEBUG || YES
- winDebug ("InitOutput - Returning.\n");
-#endif
-}
-
-
-/*
- * winCheckDisplayNumber - Check if another instance of Cygwin/X is
- * already running on the same display number. If no one exists,
- * make a mutex to prevent new instances from running on the same display.
- *
- * return FALSE if the display number is already used.
- */
-
-static Bool
-winCheckDisplayNumber (void)
-{
- int nDisp;
- HANDLE mutex;
- char name[MAX_PATH];
- char * pszPrefix = '\0';
- OSVERSIONINFO osvi = {0};
-
- /* Check display range */
- nDisp = atoi (display);
- if (nDisp < 0 || nDisp > 65535)
- {
- ErrorF ("winCheckDisplayNumber - Bad display number: %d\n", nDisp);
- return FALSE;
- }
-
- /* Set first character of mutex name to null */
- name[0] = '\0';
-
- /* Get operating system version information */
- osvi.dwOSVersionInfoSize = sizeof (osvi);
- GetVersionEx (&osvi);
-
- /* Want a mutex shared among all terminals on NT > 4.0 */
- if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT
- && osvi.dwMajorVersion >= 5)
- {
- pszPrefix = "Global\\";
- }
-
- /* Setup Cygwin/X specific part of name */
- snprintf (name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp);
-
- /* Windows automatically releases the mutex when this process exits */
- mutex = CreateMutex (NULL, FALSE, name);
- if (!mutex)
- {
- LPVOID lpMsgBuf;
-
- /* Display a fancy error message */
- FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError (),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0, NULL);
- ErrorF ("winCheckDisplayNumber - CreateMutex failed: %s\n",
- (LPSTR)lpMsgBuf);
- LocalFree (lpMsgBuf);
-
- return FALSE;
- }
- if (GetLastError () == ERROR_ALREADY_EXISTS)
- {
- ErrorF ("winCheckDisplayNumber - "
- PROJECT_NAME " is already running on display %d\n",
- nDisp);
- return FALSE;
- }
-
- return TRUE;
-}
+
+/*
+
+Copyright 1993, 1998 The Open Group
+Copyright (C) Colin Harrison 2005-2008
+
+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_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include "winmsg.h"
+#include "winconfig.h"
+#include "winprefs.h"
+#ifdef XWIN_CLIPBOARD
+#include "X11/Xlocale.h"
+#endif
+#ifdef DPMSExtension
+#include "dpmsproc.h"
+#endif
+#ifdef __CYGWIN__
+#include <mntent.h>
+#endif
+#if defined(WIN32)
+#include "xkbsrv.h"
+#endif
+#ifdef RELOCATE_PROJECTROOT
+#include <shlobj.h>
+typedef HRESULT (*SHGETFOLDERPATHPROC)(
+ HWND hwndOwner,
+ int nFolder,
+ HANDLE hToken,
+ DWORD dwFlags,
+ LPTSTR pszPath
+);
+#endif
+
+/*
+ * References to external symbols
+ */
+#ifdef XWIN_CLIPBOARD
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboardLaunched;
+extern Bool g_fClipboardStarted;
+extern pthread_t g_ptClipboardProc;
+extern HWND g_hwndClipboard;
+extern Bool g_fClipboard;
+#endif
+
+
+/*
+ module handle for dynamically loaded comctl32 library
+*/
+static HMODULE g_hmodCommonControls = NULL;
+
+/*
+ * Function prototypes
+ */
+
+#ifdef XWIN_CLIPBOARD
+static void
+winClipboardShutdown (void);
+#endif
+
+#if defined(DDXOSVERRORF)
+void
+OsVendorVErrorF (const char *pszFormat, va_list va_args);
+#endif
+
+static Bool
+winCheckDisplayNumber (void);
+
+void
+winLogCommandLine (int argc, char *argv[]);
+
+void
+winLogVersionInfo (void);
+
+Bool
+winValidateArgs (void);
+
+#ifdef RELOCATE_PROJECTROOT
+const char *
+winGetBaseDir(void);
+#endif
+
+/*
+ * For the depth 24 pixmap we default to 32 bits per pixel, but
+ * we change this pixmap format later if we detect that the display
+ * is going to be running at 24 bits per pixel.
+ *
+ * FIXME: On second thought, don't DIBs only support 32 bits per pixel?
+ * DIBs are the underlying bitmap used for DirectDraw surfaces, so it
+ * seems that all pixmap formats with depth 24 would be 32 bits per pixel.
+ * Confirm whether depth 24 DIBs can have 24 bits per pixel, then remove/keep
+ * the bits per pixel adjustment and update this comment to reflect the
+ * situation. Harold Hunt - 2002/07/02
+ */
+
+static PixmapFormatRec g_PixmapFormats[] = {
+ { 1, 1, BITMAP_SCANLINE_PAD },
+ { 4, 8, BITMAP_SCANLINE_PAD },
+ { 8, 8, BITMAP_SCANLINE_PAD },
+ { 15, 16, BITMAP_SCANLINE_PAD },
+ { 16, 16, BITMAP_SCANLINE_PAD },
+ { 24, 32, BITMAP_SCANLINE_PAD },
+ { 32, 32, BITMAP_SCANLINE_PAD }
+};
+
+const int NUMFORMATS = sizeof (g_PixmapFormats) / sizeof (g_PixmapFormats[0]);
+
+#ifdef XWIN_CLIPBOARD
+static void
+winClipboardShutdown (void)
+{
+ /* Close down clipboard resources */
+ if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted)
+ {
+ /* Synchronously destroy the clipboard window */
+ if (g_hwndClipboard != NULL)
+ {
+ SendMessage (g_hwndClipboard, WM_DESTROY, 0, 0);
+ /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
+ }
+ else
+ return;
+
+ /* Wait for the clipboard thread to exit */
+ pthread_join (g_ptClipboardProc, NULL);
+
+ g_fClipboardLaunched = FALSE;
+ g_fClipboardStarted = FALSE;
+
+ winDebug ("winClipboardShutdown - Clipboard thread has exited.\n");
+ }
+}
+#endif
+
+void
+ddxPushProviders(void)
+{
+#ifdef XWIN_GLX_WINDOWS
+ if (g_fNativeGl)
+ {
+ /* install the native GL provider */
+ glxWinPushNativeProvider();
+ }
+#endif
+}
+
+#if defined(DDXBEFORERESET)
+/*
+ * Called right before KillAllClients when the server is going to reset,
+ * allows us to shutdown our seperate threads cleanly.
+ */
+
+void
+ddxBeforeReset (void)
+{
+ winDebug ("ddxBeforeReset - Hello\n");
+
+#ifdef XWIN_CLIPBOARD
+ winClipboardShutdown ();
+#endif
+}
+#endif
+
+
+/* See Porting Layer Definition - p. 57 */
+void
+ddxGiveUp (void)
+{
+ int i;
+
+#if CYGDEBUG
+ winDebug ("ddxGiveUp\n");
+#endif
+
+ /* Perform per-screen deinitialization */
+ for (i = 0; i < g_iNumScreens; ++i)
+ {
+ /* Delete the tray icon */
+ if (!g_ScreenInfo[i].fNoTrayIcon && g_ScreenInfo[i].pScreen)
+ winDeleteNotifyIcon (winGetScreenPriv (g_ScreenInfo[i].pScreen));
+ }
+
+#ifdef XWIN_MULTIWINDOW
+ /* Notify the worker threads we're exiting */
+ winDeinitMultiWindowWM ();
+#endif
+
+#ifdef HAS_DEVWINDOWS
+ /* Close our handle to our message queue */
+ if (g_fdMessageQueue != WIN_FD_INVALID)
+ {
+ /* Close /dev/windows */
+ close (g_fdMessageQueue);
+
+ /* Set the file handle to invalid */
+ g_fdMessageQueue = WIN_FD_INVALID;
+ }
+#endif
+
+ if (!g_fLogInited) {
+ g_pszLogFile = LogInit (g_pszLogFile, NULL);
+ g_fLogInited = TRUE;
+ }
+ LogClose ();
+
+ /*
+ * At this point we aren't creating any new screens, so
+ * we are guaranteed to not need the DirectDraw functions.
+ */
+ winReleaseDDProcAddresses();
+
+ /* Unload our TrackMouseEvent function pointer */
+ if (g_hmodCommonControls != NULL)
+ {
+ FreeLibrary (g_hmodCommonControls);
+ g_hmodCommonControls = NULL;
+ g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
+ }
+
+ /* Free concatenated command line */
+ free(g_pszCommandLine);
+ g_pszCommandLine = NULL;
+
+ /* Remove our keyboard hook if it is installed */
+ winRemoveKeyboardHookLL ();
+
+ /* Tell Windows that we want to end the app */
+ PostQuitMessage (0);
+}
+
+
+/* See Porting Layer Definition - p. 57 */
+void
+AbortDDX (void)
+{
+#if CYGDEBUG
+ winDebug ("AbortDDX\n");
+#endif
+ ddxGiveUp ();
+}
+
+#ifdef __CYGWIN__
+/* hasmntopt is currently not implemented for cygwin */
+static const char *winCheckMntOpt(const struct mntent *mnt, const char *opt)
+{
+ const char *s;
+ size_t len;
+ if (mnt == NULL)
+ return NULL;
+ if (opt == NULL)
+ return NULL;
+ if (mnt->mnt_opts == NULL)
+ return NULL;
+
+ len = strlen(opt);
+ s = strstr(mnt->mnt_opts, opt);
+ if (s == NULL)
+ return NULL;
+ if ((s == mnt->mnt_opts || *(s-1) == ',') && (s[len] == 0 || s[len] == ','))
+ return (char *)opt;
+ return NULL;
+}
+
+static void
+winCheckMount(void)
+{
+ FILE *mnt;
+ struct mntent *ent;
+
+ enum { none = 0, sys_root, user_root, sys_tmp, user_tmp }
+ level = none, curlevel;
+ BOOL binary = TRUE;
+
+ mnt = setmntent("/etc/mtab", "r");
+ if (mnt == NULL)
+ {
+ ErrorF("setmntent failed");
+ return;
+ }
+
+ while ((ent = getmntent(mnt)) != NULL)
+ {
+ BOOL system = (winCheckMntOpt(ent, "user") != NULL);
+ BOOL root = (strcmp(ent->mnt_dir, "/") == 0);
+ BOOL tmp = (strcmp(ent->mnt_dir, "/tmp") == 0);
+
+ if (system)
+ {
+ if (root)
+ curlevel = sys_root;
+ else if (tmp)
+ curlevel = sys_tmp;
+ else
+ continue;
+ }
+ else
+ {
+ if (root)
+ curlevel = user_root;
+ else if (tmp)
+ curlevel = user_tmp;
+ else
+ continue;
+ }
+
+ if (curlevel <= level)
+ continue;
+ level = curlevel;
+
+ if ((winCheckMntOpt(ent, "binary") == NULL) &&
+ (winCheckMntOpt(ent, "binmode") == NULL))
+ binary = FALSE;
+ else
+ binary = TRUE;
+ }
+
+ if (endmntent(mnt) != 1)
+ {
+ ErrorF("endmntent failed");
+ return;
+ }
+
+ if (!binary)
+ winMsg(X_WARNING, "/tmp mounted in textmode\n");
+}
+#else
+static void
+winCheckMount(void)
+{
+}
+#endif
+
+#ifdef RELOCATE_PROJECTROOT
+const char *
+winGetBaseDir(void)
+{
+ static BOOL inited = FALSE;
+ static char buffer[MAX_PATH];
+ if (!inited)
+ {
+ char *fendptr;
+ HMODULE module = GetModuleHandle(NULL);
+ DWORD size = GetModuleFileName(module, buffer, sizeof(buffer));
+ if (sizeof(buffer) > 0)
+ buffer[sizeof(buffer)-1] = 0;
+
+ fendptr = buffer + size;
+ while (fendptr > buffer)
+ {
+ if (*fendptr == '\\' || *fendptr == '/')
+ {
+ *fendptr = 0;
+ break;
+ }
+ fendptr--;
+ }
+ inited = TRUE;
+ }
+ return buffer;
+}
+#endif
+
+static void
+winFixupPaths (void)
+{
+ BOOL changed_fontpath = FALSE;
+ MessageType font_from = X_DEFAULT;
+#ifdef RELOCATE_PROJECTROOT
+ const char *basedir = winGetBaseDir();
+ size_t basedirlen = strlen(basedir);
+#endif
+
+#ifdef READ_FONTDIRS
+ {
+ /* Open fontpath configuration file */
+ FILE *fontdirs = fopen(ETCX11DIR "/font-dirs", "rt");
+ if (fontdirs != NULL)
+ {
+ char buffer[256];
+ int needs_sep = TRUE;
+ int comment_block = FALSE;
+
+ /* get default fontpath */
+ char *fontpath = strdup(defaultFontPath);
+ size_t size = strlen(fontpath);
+
+ /* read all lines */
+ while (!feof(fontdirs))
+ {
+ size_t blen;
+ char *hashchar;
+ char *str;
+ int has_eol = FALSE;
+
+ /* read one line */
+ str = fgets(buffer, sizeof(buffer), fontdirs);
+ if (str == NULL) /* stop on error or eof */
+ break;
+
+ if (strchr(str, '\n') != NULL)
+ has_eol = TRUE;
+
+ /* check if block is continued comment */
+ if (comment_block)
+ {
+ /* ignore all input */
+ *str = 0;
+ blen = 0;
+ if (has_eol) /* check if line ended in this block */
+ comment_block = FALSE;
+ }
+ else
+ {
+ /* find comment character. ignore all trailing input */
+ hashchar = strchr(str, '#');
+ if (hashchar != NULL)
+ {
+ *hashchar = 0;
+ if (!has_eol) /* mark next block as continued comment */
+ comment_block = TRUE;
+ }
+ }
+
+ /* strip whitespaces from beginning */
+ while (*str == ' ' || *str == '\t')
+ str++;
+
+ /* get size, strip whitespaces from end */
+ blen = strlen(str);
+ while (blen > 0 && (str[blen-1] == ' ' ||
+ str[blen-1] == '\t' || str[blen-1] == '\n'))
+ {
+ str[--blen] = 0;
+ }
+
+ /* still something left to add? */
+ if (blen > 0)
+ {
+ size_t newsize = size + blen;
+ /* reserve one character more for ',' */
+ if (needs_sep)
+ newsize++;
+
+ /* allocate memory */
+ if (fontpath == NULL)
+ fontpath = malloc(newsize+1);
+ else
+ fontpath = realloc(fontpath, newsize+1);
+
+ /* add separator */
+ if (needs_sep)
+ {
+ fontpath[size] = ',';
+ size++;
+ needs_sep = FALSE;
+ }
+
+ /* mark next line as new entry */
+ if (has_eol)
+ needs_sep = TRUE;
+
+ /* add block */
+ strncpy(fontpath + size, str, blen);
+ fontpath[newsize] = 0;
+ size = newsize;
+ }
+ }
+
+ /* cleanup */
+ fclose(fontdirs);
+ defaultFontPath = strdup(fontpath);
+ free(fontpath);
+ changed_fontpath = TRUE;
+ font_from = X_CONFIG;
+ }
+ }
+#endif /* READ_FONTDIRS */
+#ifdef RELOCATE_PROJECTROOT
+ {
+ const char *libx11dir = PROJECTROOT "/lib/X11";
+ size_t libx11dir_len = strlen(libx11dir);
+ char *newfp = NULL;
+ size_t newfp_len = 0;
+ const char *endptr, *ptr, *oldptr = defaultFontPath;
+
+ endptr = oldptr + strlen(oldptr);
+ ptr = strchr(oldptr, ',');
+ if (ptr == NULL)
+ ptr = endptr;
+ while (ptr != NULL)
+ {
+ size_t oldfp_len = (ptr - oldptr);
+ size_t newsize = oldfp_len;
+ char *newpath = malloc(newsize + 1);
+ strncpy(newpath, oldptr, newsize);
+ newpath[newsize] = 0;
+
+
+ if (strncmp(libx11dir, newpath, libx11dir_len) == 0)
+ {
+ char *compose;
+ newsize = newsize - libx11dir_len + basedirlen;
+ compose = malloc(newsize + 1);
+ strcpy(compose, basedir);
+ strncat(compose, newpath + libx11dir_len, newsize - basedirlen);
+ compose[newsize] = 0;
+ free(newpath);
+ newpath = compose;
+ }
+
+ oldfp_len = newfp_len;
+ if (oldfp_len > 0)
+ newfp_len ++; /* space for separator */
+ newfp_len += newsize;
+
+ if (newfp == NULL)
+ newfp = malloc(newfp_len + 1);
+ else
+ newfp = realloc(newfp, newfp_len + 1);
+
+ if (oldfp_len > 0)
+ {
+ strcpy(newfp + oldfp_len, ",");
+ oldfp_len++;
+ }
+ strcpy(newfp + oldfp_len, newpath);
+
+ free(newpath);
+
+ if (*ptr == 0)
+ {
+ oldptr = ptr;
+ ptr = NULL;
+ } else
+ {
+ oldptr = ptr + 1;
+ ptr = strchr(oldptr, ',');
+ if (ptr == NULL)
+ ptr = endptr;
+ }
+ }
+
+ defaultFontPath = strdup(newfp);
+ free(newfp);
+ changed_fontpath = TRUE;
+ }
+#endif /* RELOCATE_PROJECTROOT */
+ if (changed_fontpath)
+ winMsg (font_from, "FontPath set to \"%s\"\n", defaultFontPath);
+
+#ifdef RELOCATE_PROJECTROOT
+ if (getenv("XKEYSYMDB") == NULL)
+ {
+ char buffer[MAX_PATH];
+ snprintf(buffer, sizeof(buffer), "XKEYSYMDB=%s\\XKeysymDB",
+ basedir);
+ buffer[sizeof(buffer)-1] = 0;
+ putenv(buffer);
+ }
+ if (getenv("XERRORDB") == NULL)
+ {
+ char buffer[MAX_PATH];
+ snprintf(buffer, sizeof(buffer), "XERRORDB=%s\\XErrorDB",
+ basedir);
+ buffer[sizeof(buffer)-1] = 0;
+ putenv(buffer);
+ }
+ if (getenv("XLOCALEDIR") == NULL)
+ {
+ char buffer[MAX_PATH];
+ snprintf(buffer, sizeof(buffer), "XLOCALEDIR=%s\\locale",
+ basedir);
+ buffer[sizeof(buffer)-1] = 0;
+ putenv(buffer);
+ }
+ if (getenv("HOME") == NULL)
+ {
+ HMODULE shfolder;
+ SHGETFOLDERPATHPROC shgetfolderpath = NULL;
+ char buffer[MAX_PATH + 5];
+ strncpy(buffer, "HOME=", 5);
+
+ /* Try to load SHGetFolderPath from shfolder.dll and shell32.dll */
+
+ shfolder = LoadLibrary("shfolder.dll");
+ /* fallback to shell32.dll */
+ if (shfolder == NULL)
+ shfolder = LoadLibrary("shell32.dll");
+
+ /* resolve SHGetFolderPath */
+ if (shfolder != NULL)
+ shgetfolderpath = (SHGETFOLDERPATHPROC)GetProcAddress(shfolder, "SHGetFolderPathA");
+
+ /* query appdata directory */
+ if (shgetfolderpath &&
+ shgetfolderpath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0,
+ buffer + 5) == 0)
+ {
+ putenv(buffer);
+ } else
+ {
+ winMsg (X_ERROR, "Can not determine HOME directory\n");
+ }
+ if (shfolder != NULL)
+ FreeLibrary(shfolder);
+ }
+ if (!g_fLogFileChanged) {
+ static char buffer[MAX_PATH];
+ DWORD size = GetTempPath(sizeof(buffer), buffer);
+ if (size && size < sizeof(buffer))
+ {
+ snprintf(buffer + size, sizeof(buffer) - size,
+ "XWin.%s.log", display);
+ buffer[sizeof(buffer)-1] = 0;
+ g_pszLogFile = buffer;
+ winMsg (X_DEFAULT, "Logfile set to \"%s\"\n", g_pszLogFile);
+ }
+ }
+ {
+ static char xkbbasedir[MAX_PATH];
+
+ snprintf(xkbbasedir, sizeof(xkbbasedir), "%s\\xkb", basedir);
+ if (sizeof(xkbbasedir) > 0)
+ xkbbasedir[sizeof(xkbbasedir)-1] = 0;
+ XkbBaseDirectory = xkbbasedir;
+ XkbBinDirectory = basedir;
+ }
+#endif /* RELOCATE_PROJECTROOT */
+}
+
+void
+OsVendorInit (void)
+{
+ /* Re-initialize global variables on server reset */
+ winInitializeGlobals ();
+
+ winFixupPaths();
+
+#ifdef DDXOSVERRORF
+ if (!OsVendorVErrorFProc)
+ OsVendorVErrorFProc = OsVendorVErrorF;
+#endif
+
+ if (!g_fLogInited) {
+ /* keep this order. If LogInit fails it calls Abort which then calls
+ * ddxGiveUp where LogInit is called again and creates an infinite
+ * recursion. If we set g_fLogInited to TRUE before the init we
+ * avoid the second call
+ */
+ g_fLogInited = TRUE;
+ g_pszLogFile = LogInit (g_pszLogFile, NULL);
+ }
+ LogSetParameter (XLOG_FLUSH, 1);
+ LogSetParameter (XLOG_VERBOSITY, g_iLogVerbose);
+ LogSetParameter (XLOG_FILE_VERBOSITY, g_iLogVerbose);
+
+ /* Log the version information */
+ if (serverGeneration == 1)
+ winLogVersionInfo ();
+
+ winCheckMount();
+
+ /* Add a default screen if no screens were specified */
+ if (g_iNumScreens == 0)
+ {
+ winDebug ("OsVendorInit - Creating default screen 0\n");
+
+ /*
+ * We need to initialize the default screen 0 if no -screen
+ * arguments were processed.
+ *
+ * Add a screen 0 using the defaults set by winInitializeDefaultScreens()
+ * and any additional default screen parameters given
+ */
+ winInitializeScreens(1);
+
+ /* We have to flag this as an explicit screen, even though it isn't */
+ g_ScreenInfo[0].fExplicitScreen = TRUE;
+ }
+}
+
+
+static void
+winUseMsg (void)
+{
+ ErrorF("\n");
+ ErrorF("\n");
+ ErrorF(EXECUTABLE_NAME " Device Dependent Usage:\n");
+ ErrorF("\n");
+
+#ifdef XWIN_CLIPBOARD
+ ErrorF ("-[no]clipboard\n"
+ "\tEnable [disable] the clipboard integration. Default is enabled.\n");
+#endif
+
+ ErrorF ("-clipupdates num_boxes\n"
+ "\tUse a clipping region to constrain shadow update blits to\n"
+ "\tthe updated region when num_boxes, or more, are in the\n"
+ "\tupdated region.\n");
+
+#ifdef XWIN_XF86CONFIG
+ ErrorF ("-config\n"
+ "\tSpecify a configuration file.\n");
+
+ ErrorF ("-configdir\n"
+ "\tSpecify a configuration directory.\n");
+#endif
+
+ ErrorF ("-depth bits_per_pixel\n"
+ "\tSpecify an optional bitdepth to use in fullscreen mode\n"
+ "\twith a DirectDraw engine.\n");
+
+ ErrorF ("-emulate3buttons [timeout]\n"
+ "\tEmulate 3 button mouse with an optional timeout in\n"
+ "\tmilliseconds.\n");
+
+#ifdef XWIN_EMULATEPSEUDO
+ ErrorF ("-emulatepseudo\n"
+ "\tCreate a depth 8 PseudoColor visual when running in\n"
+ "\tdepths 15, 16, 24, or 32, collectively known as TrueColor\n"
+ "\tdepths. The PseudoColor visual does not have correct colors,\n"
+ "\tand it may crash, but it at least allows you to run your\n"
+ "\tapplication in TrueColor modes.\n");
+#endif
+
+ ErrorF ("-engine engine_type_id\n"
+ "\tOverride the server's automatically selected engine type:\n"
+ "\t\t1 - Shadow GDI\n"
+ "\t\t2 - Shadow DirectDraw\n"
+ "\t\t4 - Shadow DirectDraw4 Non-Locking\n"
+#ifdef XWIN_PRIMARYFB
+ "\t\t8 - Primary DirectDraw - obsolete\n"
+#endif
+#ifdef XWIN_NATIVEGDI
+ "\t\t16 - Native GDI - experimental\n"
+#endif
+ );
+
+ ErrorF ("-fullscreen\n"
+ "\tRun the server in fullscreen mode.\n");
+
+ ErrorF ("-ignoreinput\n"
+ "\tIgnore keyboard and mouse input.\n");
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ ErrorF ("-internalwm\n"
+ "\tRun the internal window manager.\n");
+#endif
+
+#ifdef XWIN_XF86CONFIG
+ ErrorF ("-keyboard\n"
+ "\tSpecify a keyboard device from the configuration file.\n");
+#endif
+
+ ErrorF ("-[no]keyhook\n"
+ "\tGrab special Windows keypresses like Alt-Tab or the Menu "
+ "key.\n");
+
+ ErrorF ("-lesspointer\n"
+ "\tHide the windows mouse pointer when it is over any\n"
+ "\t" EXECUTABLE_NAME " window. This prevents ghost cursors appearing when\n"
+ "\tthe Windows cursor is drawn on top of the X cursor\n");
+
+ ErrorF ("-logfile filename\n"
+ "\tWrite log messages to <filename>.\n");
+
+ ErrorF ("-logverbose verbosity\n"
+ "\tSet the verbosity of log messages. [NOTE: Only a few messages\n"
+ "\trespect the settings yet]\n"
+ "\t\t0 - only print fatal error.\n"
+ "\t\t1 - print additional configuration information.\n"
+ "\t\t2 - print additional runtime information [default].\n"
+ "\t\t3 - print debugging and tracing information.\n");
+
+ ErrorF ("-[no]multimonitors or -[no]multiplemonitors\n"
+ "\tUse the entire virtual screen if multiple\n"
+ "\tmonitors are present.\n");
+
+#ifdef XWIN_MULTIWINDOW
+ ErrorF ("-multiwindow\n"
+ "\tRun the server in multi-window mode.\n");
+#endif
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ ErrorF ("-mwextwm\n"
+ "\tRun the server in multi-window external window manager mode.\n");
+#endif
+
+ ErrorF ("-nodecoration\n"
+ "\tDo not draw a window border, title bar, etc. Windowed\n"
+ "\tmode only.\n");
+
+#ifdef XWIN_CLIPBOARD
+ ErrorF ("-nounicodeclipboard\n"
+ "\tDo not use Unicode clipboard even if on a NT-based platform.\n");
+#endif
+
+ ErrorF ("-refresh rate_in_Hz\n"
+ "\tSpecify an optional refresh rate to use in fullscreen mode\n"
+ "\twith a DirectDraw engine.\n");
+
+ ErrorF ("-resize=none|scrollbars|randr"
+ "\tIn windowed mode, [don't] allow resizing of the window. 'scrollbars'\n"
+ "\tmode gives the window scrollbars as needed, 'randr' mode uses the RANR\n"
+ "\textension to resize the X screen.\n");
+
+ ErrorF ("-rootless\n"
+ "\tRun the server in rootless mode.\n");
+
+ ErrorF ("-screen scr_num [width height [x y] | [[WxH[+X+Y]][@m]] ]\n"
+ "\tEnable screen scr_num and optionally specify a width and\n"
+ "\theight and initial position for that screen. Additionally\n"
+ "\ta monitor number can be specified to start the server on,\n"
+ "\tat which point, all coordinates become relative to that\n"
+ "\tmonitor (Not for Windows NT4 and 95). Examples:\n"
+ "\t -screen 0 800x600+100+100@2 ; 2nd monitor offset 100,100 size 800x600\n"
+ "\t -screen 0 1024x768@3 ; 3rd monitor size 1024x768\n"
+ "\t -screen 0 @1 ; on 1st monitor using its full resolution (the default)\n");
+
+ ErrorF ("-silent-dup-error\n"
+ "\tIf another instance of " EXECUTABLE_NAME " with the same display number is running\n"
+ "\texit silently and don't display any error message.\n");
+
+ ErrorF ("-swcursor\n"
+ "\tDisable the usage of the Windows cursor and use the X11 software\n"
+ "\tcursor instead.\n");
+
+ ErrorF ("-[no]trayicon\n"
+ "\tDo not create a tray icon. Default is to create one\n"
+ "\ticon per screen. You can globally disable tray icons with\n"
+ "\t-notrayicon, then enable it for specific screens with\n"
+ "\t-trayicon for those screens.\n");
+
+ ErrorF ("-[no]unixkill\n"
+ "\tCtrl+Alt+Backspace exits the X Server.\n");
+
+#ifdef XWIN_GLX_WINDOWS
+ ErrorF ("-[no]wgl\n"
+ "\tEnable the GLX extension to use the native Windows WGL interface for accelerated OpenGL\n");
+#endif
+
+ ErrorF ("-[no]winkill\n"
+ "\tAlt+F4 exits the X Server.\n");
+
+ ErrorF ("-xkblayout XKBLayout\n"
+ "\tEquivalent to XKBLayout in XF86Config files.\n"
+ "\tFor example: -xkblayout de\n");
+
+ ErrorF ("-xkbmodel XKBModel\n"
+ "\tEquivalent to XKBModel in XF86Config files.\n");
+
+ ErrorF ("-xkboptions XKBOptions\n"
+ "\tEquivalent to XKBOptions in XF86Config files.\n");
+
+ ErrorF ("-xkbrules XKBRules\n"
+ "\tEquivalent to XKBRules in XF86Config files.\n");
+
+ ErrorF ("-xkbvariant XKBVariant\n"
+ "\tEquivalent to XKBVariant in XF86Config files.\n"
+ "\tFor example: -xkbvariant nodeadkeys\n");
+}
+
+/* See Porting Layer Definition - p. 57 */
+void
+ddxUseMsg(void)
+{
+ /* Set a flag so that FatalError won't give duplicate warning message */
+ g_fSilentFatalError = TRUE;
+
+ winUseMsg();
+
+ /* Log file will not be opened for UseMsg unless we open it now */
+ if (!g_fLogInited) {
+ g_pszLogFile = LogInit (g_pszLogFile, NULL);
+ g_fLogInited = TRUE;
+ }
+ LogClose ();
+
+ /* Notify user where UseMsg text can be found.*/
+ if (!g_fNoHelpMessageBox)
+ winMessageBoxF ("The " PROJECT_NAME " help text has been printed to "
+ "%s.\n"
+ "Please open %s to read the help text.\n",
+ MB_ICONINFORMATION, g_pszLogFile, g_pszLogFile);
+}
+
+/* See Porting Layer Definition - p. 20 */
+/*
+ * Do any global initialization, then initialize each screen.
+ *
+ * NOTE: We use ddxProcessArgument, so we don't need to touch argc and argv
+ */
+
+void
+InitOutput (ScreenInfo *screenInfo, int argc, char *argv[])
+{
+ int i;
+
+ /* Log the command line */
+ winLogCommandLine (argc, argv);
+
+#if CYGDEBUG
+ winDebug ("InitOutput\n");
+#endif
+
+ /* Validate command-line arguments */
+ if (serverGeneration == 1 && !winValidateArgs ())
+ {
+ FatalError ("InitOutput - Invalid command-line arguments found. "
+ "Exiting.\n");
+ }
+
+ /* Check for duplicate invocation on same display number.*/
+ if (serverGeneration == 1 && !winCheckDisplayNumber ())
+ {
+ if (g_fSilentDupError)
+ g_fSilentFatalError = TRUE;
+ FatalError ("InitOutput - Duplicate invocation on display "
+ "number: %s. Exiting.\n", display);
+ }
+
+#ifdef XWIN_XF86CONFIG
+ /* Try to read the xorg.conf-style configuration file */
+ if (!winReadConfigfile ())
+ winErrorFVerb (1, "InitOutput - Error reading config file\n");
+#else
+ winMsg(X_INFO, "xorg.conf is not supported\n");
+ winMsg(X_INFO, "See http://x.cygwin.com/docs/faq/cygwin-x-faq.html "
+ "for more information\n");
+ winConfigFiles ();
+#endif
+
+ /* Load preferences from XWinrc file */
+ LoadPreferences();
+
+ /* Setup global screen info parameters */
+ screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+ screenInfo->numPixmapFormats = NUMFORMATS;
+
+ /* Describe how we want common pixmap formats padded */
+ for (i = 0; i < NUMFORMATS; i++)
+ {
+ screenInfo->formats[i] = g_PixmapFormats[i];
+ }
+
+ /* Load pointers to DirectDraw functions */
+ winGetDDProcAddresses ();
+
+ /* Detect supported engines */
+ winDetectSupportedEngines ();
+
+ /* Load common controls library */
+ g_hmodCommonControls = LoadLibraryEx ("comctl32.dll", NULL, 0);
+
+ /* Load TrackMouseEvent function pointer */
+ g_fpTrackMouseEvent = GetProcAddress (g_hmodCommonControls,
+ "_TrackMouseEvent");
+ if (g_fpTrackMouseEvent == NULL)
+ {
+ winErrorFVerb (1, "InitOutput - Could not get pointer to function\n"
+ "\t_TrackMouseEvent in comctl32.dll. Try installing\n"
+ "\tInternet Explorer 3.0 or greater if you have not\n"
+ "\talready.\n");
+
+ /* Free the library since we won't need it */
+ FreeLibrary (g_hmodCommonControls);
+ g_hmodCommonControls = NULL;
+
+ /* Set function pointer to point to no operation function */
+ g_fpTrackMouseEvent = (FARPROC) (void (*)(void))NoopDDA;
+ }
+
+ /* Store the instance handle */
+ g_hInstance = GetModuleHandle (NULL);
+
+ /* Initialize each screen */
+ for (i = 0; i < g_iNumScreens; ++i)
+ {
+ /* Initialize the screen */
+ if (-1 == AddScreen (winScreenInit, argc, argv))
+ {
+ FatalError ("InitOutput - Couldn't add screen %d", i);
+ }
+ }
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+
+ /* Generate a cookie used by internal clients for authorization */
+ if (g_fXdmcpEnabled || g_fAuthEnabled)
+ winGenerateAuthorization ();
+
+ /* Perform some one time initialization */
+ if (1 == serverGeneration)
+ {
+ /*
+ * setlocale applies to all threads in the current process.
+ * Apply locale specified in LANG environment variable.
+ */
+ setlocale (LC_ALL, "");
+ }
+#endif
+
+#if CYGDEBUG || YES
+ winDebug ("InitOutput - Returning.\n");
+#endif
+}
+
+
+/*
+ * winCheckDisplayNumber - Check if another instance of Cygwin/X is
+ * already running on the same display number. If no one exists,
+ * make a mutex to prevent new instances from running on the same display.
+ *
+ * return FALSE if the display number is already used.
+ */
+
+static Bool
+winCheckDisplayNumber (void)
+{
+ int nDisp;
+ HANDLE mutex;
+ char name[MAX_PATH];
+ char * pszPrefix = '\0';
+ OSVERSIONINFO osvi = {0};
+
+ /* Check display range */
+ nDisp = atoi (display);
+ if (nDisp < 0 || nDisp > 65535)
+ {
+ ErrorF ("winCheckDisplayNumber - Bad display number: %d\n", nDisp);
+ return FALSE;
+ }
+
+ /* Set first character of mutex name to null */
+ name[0] = '\0';
+
+ /* Get operating system version information */
+ osvi.dwOSVersionInfoSize = sizeof (osvi);
+ GetVersionEx (&osvi);
+
+ /* Want a mutex shared among all terminals on NT > 4.0 */
+ if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && osvi.dwMajorVersion >= 5)
+ {
+ pszPrefix = "Global\\";
+ }
+
+ /* Setup Cygwin/X specific part of name */
+ snprintf (name, sizeof(name), "%sCYGWINX_DISPLAY:%d", pszPrefix, nDisp);
+
+ /* Windows automatically releases the mutex when this process exits */
+ mutex = CreateMutex (NULL, FALSE, name);
+ if (!mutex)
+ {
+ LPVOID lpMsgBuf;
+
+ /* Display a fancy error message */
+ FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError (),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0, NULL);
+ ErrorF ("winCheckDisplayNumber - CreateMutex failed: %s\n",
+ (LPSTR)lpMsgBuf);
+ LocalFree (lpMsgBuf);
+
+ return FALSE;
+ }
+ if (GetLastError () == ERROR_ALREADY_EXISTS)
+ {
+ ErrorF ("winCheckDisplayNumber - "
+ PROJECT_NAME " is already running on display %d\n",
+ nDisp);
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/Makefile.am b/xorg-server/hw/xwin/Makefile.am
index f6a75df2c..ce2edb2e6 100644
--- a/xorg-server/hw/xwin/Makefile.am
+++ b/xorg-server/hw/xwin/Makefile.am
@@ -87,6 +87,7 @@ SRCS = InitInput.c \
winkeybd.c \
winkeyhook.c \
winmisc.c \
+ winmonitors.c \
winmouse.c \
winmsg.c \
winmultiwindowclass.c \
diff --git a/xorg-server/hw/xwin/man/XWin.man b/xorg-server/hw/xwin/man/XWin.man
index 51268f69a..e7933c9c8 100644
--- a/xorg-server/hw/xwin/man/XWin.man
+++ b/xorg-server/hw/xwin/man/XWin.man
@@ -103,7 +103,7 @@ Examples:
.SH OPTIONS CONTROLLING THE APPEARANCE OF THE X SCREEN WINDOWS
These parameters only apply to windowed mode screens i.e. not
-in \fB-multwindow\fP or \fB-rootless\fP mode
+in \fB-multiwindow\fP or \fB-rootless\fP mode.
.TP 8
.B "\-fullscreen"
The X server window takes the full screen, covering completely the
@@ -115,10 +115,52 @@ etc.
This parameter is ignored when the \fB\-fullscreen\fP parameter is specified.
.TP 8
.B \-scrollbars
-In windowed mode, allow screens bigger than the \fIWindows\fP desktop.
-Moreover, if the window has decorations, one can now resize it.
-This parameter is ignored when the \fB\-fullscreen\fP parameter is specified.
+Alternative name for \fB\-resize=scrollbars\fP.
+
+.SH OPTIONS CONTROLLING RESIZE BEHAVIOUR
+.TP 8
+.B \-resize[=none|scrollbars|randr]
+Select the resize mode of an X screen.
+
+.RS
+.IP \fB\-resize=none\fP 8
+(default). The screen is not resizable.
+
+In windowed mode, if the window has decorations, a fixed frame is used.
+
+.IP \fB\-resize=scrollbars\fP 8
+The screen window is resizeable, but the screen is not resizable.
+
+In windowed mode, if the window has decorations, a resizing frame is used.
+Scrollbars are drawn when needed to allow the entire X screen
+to viewed by adjusting them.
+
+This also permits screens bigger than the \fIWindows\fP virtual desktop to be used.
+
+This parameter is ignored in \fB-multiwindow\fP or \fB-rootless\fP mode.
+Alternative name is \fB\-scrollbars\fP.
+
+.IP \fB\-resize=randr\fP 8
+The screen is resizable and the screen window is resizeable.
+In windowed mode, if the window has decorations, a resizing frame is used.
+
+Resizing the \fIWindows\fP window will use the RANDR extension to change
+the size of the X screen. Likewise, changing the size of
+the X screen using the RANDR extension will cause the size
+of the \fIWindows\fP window containing the X screen to be changed.
+
+In \fB-multiwindow\fP or \fB-rootless\fP mode, if the X screen is
+of the same dimensions as a Windows monitor or the virtual desktop,
+the X server will respond to the WM_DISPLAYCHANGED sent when those
+dimensions change by resizing the X screen. Changing the size
+of the X screen using the RANDR extension is not permitted.
+
+The maximum dimensions of the screen are the dimensions of the \fIWindows\fP virtual desktop.
+
+.IP \fB\--resize\fP 8
+on its own is equivalent to \fB\--resize=randr\fP
+.RE
.SH OPTIONS CONTROLLING WINDOWS INTEGRATION
.TP 8
@@ -190,15 +232,27 @@ respectively).
.TP 8
.B "\-engine \fIengine_type_id\fP"
This option, which is intended for Cygwin/X developers,
-overrides the server's automatically selected engine type. This
-parameter will be ignored if the specified engine type is not
-supported on the current system. The supported engine type ids are 1
-- Shadow GDI, 2 - Shadow DirectDraw, and 4 - Shadow DirectDraw Non-Locking.
-Additionally, there are engines with type ids
-8 - Primary DirectDraw (obsolete) and 16 - Native GDI (experimental and barely functional).
-Default behavior is to determine the engine with optimum performance that
+overrides the server's automatically selected drawing engine type. This
+parameter will be ignored if the specified drawing engine type is not
+supported on the current system.
+
+Default behavior is to select the drawing engine with optimum performance that
supports the specified depth and window configuration.
+The engine type ids are:
+.RS
+.IP 1 4
+Shadow GDI
+.IP 2 4
+Shadow DirectDraw
+.IP 4 4
+Shadow DirectDraw Non-Locking
+.IP 8 4
+Primary DirectDraw (unsupported, obsolete)
+.IP 16 4
+Native GDI (unsupported, experimental and barely functional)
+.RE
+
.SH FULLSCREEN OPTIONS
.TP 8
.B "\-depth \fIdepth\fP"
@@ -322,12 +376,9 @@ X(__miscmansuffix__), Xserver(1), xdm(1), xinit(1), XWinrc(__filemansuffix__), s
.SH BUGS
.I XWin
-and this man page still have many limitations. Some of the more obvious
-ones are:
-.br
-- The display mode can not be changed once the X server has started.
-.br
-- The \fIXWin\fP software is continuously developing; it is therefore possible that
+and this man page still have many limitations.
+
+The \fIXWin\fP software is continuously developing; it is therefore possible that
this man page is not up to date. It is always prudent to
look also at the output of \fIXWin -help\fP in order to
check the options that are operative.
diff --git a/xorg-server/hw/xwin/win.h b/xorg-server/hw/xwin/win.h
index e790d2d73..3f40fdbe0 100644
--- a/xorg-server/hw/xwin/win.h
+++ b/xorg-server/hw/xwin/win.h
@@ -1,1459 +1,1491 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Dakshinamurthy Karra
- * Suhaib M Siddiqi
- * Peter Busch
- * Harold L Hunt II
- * Kensuke Matsuzaki
- */
-
-#ifndef _WIN_H_
-#define _WIN_H_
-
-#ifndef NO
-#define NO 0
-#endif
-#ifndef YES
-#define YES 1
-#endif
-
-/* Turn debug messages on or off */
-#ifndef CYGDEBUG
-#define CYGDEBUG NO
-#endif
-
-/* WM_XBUTTON Messages. They should go into w32api. */
-#ifndef WM_XBUTTONDOWN
-# define WM_XBUTTONDOWN 523
-#endif
-#ifndef WM_XBUTTONUP
-# define WM_XBUTTONUP 524
-#endif
-#ifndef WM_XBUTTONDBLCLK
-# define WM_XBUTTONDBLCLK 525
-#endif
-
-
-#define WIN_DEFAULT_BPP 0
-#define WIN_DEFAULT_WHITEPIXEL 255
-#define WIN_DEFAULT_BLACKPIXEL 0
-#define WIN_DEFAULT_LINEBIAS 0
-#define WIN_DEFAULT_E3B_TIME 50 /* milliseconds */
-#define WIN_DEFAULT_DPI 75
-#define WIN_DEFAULT_REFRESH 0
-#define WIN_DEFAULT_WIN_KILL TRUE
-#define WIN_DEFAULT_UNIX_KILL FALSE
-#define WIN_DEFAULT_CLIP_UPDATES_NBOXES 0
-#ifdef XWIN_EMULATEPSEUDO
-#define WIN_DEFAULT_EMULATE_PSEUDO FALSE
-#endif
-#define WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH FALSE
-
-#define WIN_DIB_MAXIMUM_SIZE 0x08000000 /* 16 MB on Windows 95, 98, Me */
-#define WIN_DIB_MAXIMUM_SIZE_MB (WIN_DIB_MAXIMUM_SIZE / 8 / 1024 / 1024)
-
-/*
- * Windows only supports 256 color palettes
- */
-#define WIN_NUM_PALETTE_ENTRIES 256
-
-/*
- * Number of times to call Restore in an attempt to restore the primary surface
- */
-#define WIN_REGAIN_SURFACE_RETRIES 1
-
-/*
- * Build a supported display depths mask by shifting one to the left
- * by the number of bits in the supported depth.
- */
-#define WIN_SUPPORTED_BPPS ( (1 << (32 - 1)) | (1 << (24 - 1)) \
- | (1 << (16 - 1)) | (1 << (15 - 1)) \
- | (1 << ( 8 - 1)))
-#define WIN_CHECK_DEPTH YES
-
-/*
- * Timer IDs for WM_TIMER
- */
-#define WIN_E3B_TIMER_ID 1
-#define WIN_POLLING_MOUSE_TIMER_ID 2
-
-#define MOUSE_POLLING_INTERVAL 50
-
-#define WIN_E3B_OFF -1
-#define WIN_FD_INVALID -1
-
-#define WIN_SERVER_NONE 0x0L /* 0 */
-#define WIN_SERVER_SHADOW_GDI 0x1L /* 1 */
-#define WIN_SERVER_SHADOW_DD 0x2L /* 2 */
-#define WIN_SERVER_SHADOW_DDNL 0x4L /* 4 */
-#ifdef XWIN_PRIMARYFB
-#define WIN_SERVER_PRIMARY_DD 0x8L /* 8 */
-#endif
-#ifdef XWIN_NATIVEGDI
-# define WIN_SERVER_NATIVE_GDI 0x10L /* 16 */
-#endif
-
-#define AltMapIndex Mod1MapIndex
-#define NumLockMapIndex Mod2MapIndex
-#define AltLangMapIndex Mod3MapIndex
-#define KanaMapIndex Mod4MapIndex
-#define ScrollLockMapIndex Mod5MapIndex
-
-#define WIN_MOD_LALT 0x00000001
-#define WIN_MOD_RALT 0x00000002
-#define WIN_MOD_LCONTROL 0x00000004
-#define WIN_MOD_RCONTROL 0x00000008
-
-#define WIN_24BPP_MASK_RED 0x00FF0000
-#define WIN_24BPP_MASK_GREEN 0x0000FF00
-#define WIN_24BPP_MASK_BLUE 0x000000FF
-
-#define WIN_MAX_KEYS_PER_KEY 4
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-
-#include <errno.h>
-#if defined(XWIN_MULTIWINDOWEXTWM) || defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
-#define HANDLE void *
-#include <pthread.h>
-#undef HANDLE
-#endif
-
-#ifdef HAS_MMAP
-#include <sys/mman.h>
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif /* MAP_FILE */
-#endif /* HAS_MMAP */
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xos.h>
-#include <X11/Xprotostr.h>
-#include "scrnintstr.h"
-#include "pixmapstr.h"
-#include "pixmap.h"
-#include "region.h"
-#include "gcstruct.h"
-#include "colormap.h"
-#include "colormapst.h"
-#include "miscstruct.h"
-#include "servermd.h"
-#include "windowstr.h"
-#include "mi.h"
-#include "micmap.h"
-#include "mifillarc.h"
-#include "mifpoly.h"
-#include "mibstore.h"
-#include "input.h"
-#include "mipointer.h"
-#include "X11/keysym.h"
-#include "mibstore.h"
-#include "micoord.h"
-#include "dix.h"
-#include "miline.h"
-#include "shadow.h"
-#include "fb.h"
-#include "rootless.h"
-
-#include "mipict.h"
-#include "picturestr.h"
-
-#ifdef RANDR
-#include "randrstr.h"
-#endif
-
-/*
- * Windows headers
- */
-#include "winms.h"
-#include "winresource.h"
-
-
-/*
- * Define Windows constants
- */
-
-#define WM_TRAYICON (WM_USER + 1000)
-#define WM_INIT_SYS_MENU (WM_USER + 1001)
-#define WM_GIVEUP (WM_USER + 1002)
-
-
-/* Local includes */
-#include "winwindow.h"
-#include "winmsg.h"
-
-
-/*
- * Debugging macros
- */
-
-#if CYGDEBUG
-#define DEBUG_MSG(str,...) \
-if (fDebugProcMsg) \
-{ \
- char *pszTemp; \
- int iLength; \
- if (asprintf (&pszTemp, str, ##__VA_ARGS__) != -1) { \
- MessageBox (NULL, pszTemp, szFunctionName, MB_OK); \
- free (pszTemp); \
- } \
-}
-#else
-#define DEBUG_MSG(str,...)
-#endif
-
-#if CYGDEBUG
-#define DEBUG_FN_NAME(str) PTSTR szFunctionName = str
-#else
-#define DEBUG_FN_NAME(str)
-#endif
-
-#if CYGDEBUG || YES
-#define DEBUGVARS BOOL fDebugProcMsg = FALSE
-#else
-#define DEBUGVARS
-#endif
-
-#if CYGDEBUG || YES
-#define DEBUGPROC_MSG fDebugProcMsg = TRUE
-#else
-#define DEBUGPROC_MSG
-#endif
-
-#define PROFILEPOINT(point,thresh)\
-{\
-static unsigned int PROFPT##point = 0;\
-if (++PROFPT##point % thresh == 0)\
-ErrorF (#point ": PROFILEPOINT hit %u times\n", PROFPT##point);\
-}
-
-
-/* We use xor this macro for detecting toggle key state changes */
-#define WIN_XOR(a,b) ((!(a) && (b)) || ((a) && !(b)))
-
-#define DEFINE_ATOM_HELPER(func,atom_name) \
-static Atom func (void) { \
- static int generation; \
- static Atom atom; \
- if (generation != serverGeneration) { \
- generation = serverGeneration; \
- atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
- } \
- return atom; \
-}
-
-/*
- * Typedefs for engine dependent function pointers
- */
-
-typedef Bool (*winAllocateFBProcPtr)(ScreenPtr);
-
-typedef void (*winShadowUpdateProcPtr)(ScreenPtr, shadowBufPtr);
-
-typedef Bool (*winCloseScreenProcPtr)(int, ScreenPtr);
-
-typedef Bool (*winInitVisualsProcPtr)(ScreenPtr);
-
-typedef Bool (*winAdjustVideoModeProcPtr)(ScreenPtr);
-
-typedef Bool (*winCreateBoundingWindowProcPtr)(ScreenPtr);
-
-typedef Bool (*winFinishScreenInitProcPtr)(int, ScreenPtr, int, char **);
-
-typedef Bool (*winBltExposedRegionsProcPtr)(ScreenPtr);
-
-typedef Bool (*winActivateAppProcPtr)(ScreenPtr);
-
-typedef Bool (*winRedrawScreenProcPtr)(ScreenPtr pScreen);
-
-typedef Bool (*winRealizeInstalledPaletteProcPtr)(ScreenPtr pScreen);
-
-typedef Bool (*winInstallColormapProcPtr)(ColormapPtr pColormap);
-
-typedef Bool (*winStoreColorsProcPtr)(ColormapPtr pmap,
- int ndef, xColorItem *pdefs);
-
-typedef Bool (*winCreateColormapProcPtr)(ColormapPtr pColormap);
-
-typedef Bool (*winDestroyColormapProcPtr)(ColormapPtr pColormap);
-
-typedef Bool (*winHotKeyAltTabProcPtr)(ScreenPtr);
-
-typedef Bool (*winCreatePrimarySurfaceProcPtr)(ScreenPtr);
-
-typedef Bool (*winReleasePrimarySurfaceProcPtr)(ScreenPtr);
-
-typedef Bool (*winFinishCreateWindowsWindowProcPtr)(WindowPtr pWin);
-
-typedef Bool (*winCreateScreenResourcesProc)(ScreenPtr);
-
-
-/*
- * GC (graphics context) privates
- */
-
-typedef struct
-{
- HDC hdc;
- HDC hdcMem;
-} winPrivGCRec, *winPrivGCPtr;
-
-
-/*
- * Pixmap privates
- */
-
-typedef struct
-{
- HDC hdcSelected;
- HBITMAP hBitmap;
- BYTE *pbBits;
- DWORD dwScanlineBytes;
- BITMAPINFOHEADER *pbmih;
-} winPrivPixmapRec, *winPrivPixmapPtr;
-
-
-/*
- * Colormap privates
- */
-
-typedef struct
-{
- HPALETTE hPalette;
- LPDIRECTDRAWPALETTE lpDDPalette;
- RGBQUAD rgbColors[WIN_NUM_PALETTE_ENTRIES];
- PALETTEENTRY peColors[WIN_NUM_PALETTE_ENTRIES];
-} winPrivCmapRec, *winPrivCmapPtr;
-
-/*
- * Windows Cursor handling.
- */
-
-typedef struct {
- /* from GetSystemMetrics */
- int sm_cx;
- int sm_cy;
-
- BOOL visible;
- HCURSOR handle;
- QueryBestSizeProcPtr QueryBestSize;
- miPointerSpriteFuncPtr spriteFuncs;
-} winCursorRec;
-
-/*
- * Screen information structure that we need before privates are available
- * in the server startup sequence.
- */
-
-typedef struct
-{
- ScreenPtr pScreen;
-
- /* Did the user specify a height and width? */
- Bool fUserGaveHeightAndWidth;
-
- DWORD dwScreen;
- DWORD dwUserWidth;
- DWORD dwUserHeight;
- DWORD dwWidth;
- DWORD dwHeight;
- DWORD dwWidth_mm;
- DWORD dwHeight_mm;
- DWORD dwPaddedWidth;
-
- /* Did the user specify a screen position? */
- Bool fUserGavePosition;
- DWORD dwInitialX;
- DWORD dwInitialY;
-
- /*
- * dwStride is the number of whole pixels that occupy a scanline,
- * including those pixels that are not displayed. This is basically
- * a rounding up of the width.
- */
- DWORD dwStride;
-
- /* Offset of the screen in the window when using scrollbars */
- DWORD dwXOffset;
- DWORD dwYOffset;
-
- DWORD dwBPP;
- DWORD dwDepth;
- DWORD dwRefreshRate;
- char *pfb;
- DWORD dwEngine;
- DWORD dwEnginePreferred;
- DWORD dwClipUpdatesNBoxes;
-#ifdef XWIN_EMULATEPSEUDO
- Bool fEmulatePseudo;
-#endif
- Bool fFullScreen;
- Bool fDecoration;
-#ifdef XWIN_MULTIWINDOWEXTWM
- Bool fMWExtWM;
- Bool fInternalWM;
- Bool fAnotherWMRunning;
-#endif
- Bool fRootless;
-#ifdef XWIN_MULTIWINDOW
- Bool fMultiWindow;
-#endif
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- Bool fMultiMonitorOverride;
-#endif
- Bool fMultipleMonitors;
- Bool fLessPointer;
- Bool fScrollbars;
- Bool fNoTrayIcon;
- int iE3BTimeout;
- /* Windows (Alt+F4) and Unix (Ctrl+Alt+Backspace) Killkey */
- Bool fUseWinKillKey;
- Bool fUseUnixKillKey;
- Bool fIgnoreInput;
-
- /* Did the user explicitly set this screen? */
- Bool fExplicitScreen;
-} winScreenInfo, *winScreenInfoPtr;
-
-
-/*
- * Screen privates
- */
-
-typedef struct _winPrivScreenRec
-{
- winScreenInfoPtr pScreenInfo;
-
- Bool fEnabled;
- Bool fClosed;
- Bool fActive;
- Bool fBadDepth;
-
- int iDeltaZ;
-
- int iConnectedClients;
-
- CloseScreenProcPtr CloseScreen;
-
- DWORD dwRedMask;
- DWORD dwGreenMask;
- DWORD dwBlueMask;
- DWORD dwBitsPerRGB;
-
- DWORD dwModeKeyStates;
-
- /* Handle to icons that must be freed */
- HICON hiconNotifyIcon;
-
- /* Last width, height, and depth of the Windows display */
- DWORD dwLastWindowsWidth;
- DWORD dwLastWindowsHeight;
- DWORD dwLastWindowsBitsPixel;
-
- /* Palette management */
- ColormapPtr pcmapInstalled;
-
- /* Pointer to the root visual so we only have to look it up once */
- VisualPtr pRootVisual;
-
- /* 3 button emulation variables */
- int iE3BCachedPress;
- Bool fE3BFakeButton2Sent;
-
- /* Privates used by shadow fb GDI server */
- HBITMAP hbmpShadow;
- HDC hdcScreen;
- HDC hdcShadow;
- HWND hwndScreen;
-
- /* Privates used by shadow fb and primary fb DirectDraw servers */
- LPDIRECTDRAW pdd;
- LPDIRECTDRAWSURFACE2 pddsPrimary;
- LPDIRECTDRAW2 pdd2;
-
- /* Privates used by shadow fb DirectDraw server */
- LPDIRECTDRAWSURFACE2 pddsShadow;
- LPDDSURFACEDESC pddsdShadow;
-
- /* Privates used by primary fb DirectDraw server */
- LPDIRECTDRAWSURFACE2 pddsOffscreen;
- LPDDSURFACEDESC pddsdOffscreen;
- LPDDSURFACEDESC pddsdPrimary;
-
- /* Privates used by shadow fb DirectDraw Nonlocking server */
- LPDIRECTDRAW4 pdd4;
- LPDIRECTDRAWSURFACE4 pddsShadow4;
- LPDIRECTDRAWSURFACE4 pddsPrimary4;
- BOOL fRetryCreateSurface;
-
- /* Privates used by both shadow fb DirectDraw servers */
- LPDIRECTDRAWCLIPPER pddcPrimary;
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- /* Privates used by multi-window external window manager */
- RootlessFrameID widTop;
- Bool fRestacking;
-#endif
-
-#ifdef XWIN_MULTIWINDOW
- /* Privates used by multi-window */
- pthread_t ptWMProc;
- pthread_t ptXMsgProc;
- void *pWMInfo;
-#endif
-
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- /* Privates used by both multi-window and rootless */
- Bool fRootWindowShown;
-#endif
-
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
- /* Privates used for any module running in a seperate thread */
- pthread_mutex_t pmServerStarted;
- Bool fServerStarted;
-#endif
-
- /* Engine specific functions */
- winAllocateFBProcPtr pwinAllocateFB;
- winShadowUpdateProcPtr pwinShadowUpdate;
- winCloseScreenProcPtr pwinCloseScreen;
- winInitVisualsProcPtr pwinInitVisuals;
- winAdjustVideoModeProcPtr pwinAdjustVideoMode;
- winCreateBoundingWindowProcPtr pwinCreateBoundingWindow;
- winFinishScreenInitProcPtr pwinFinishScreenInit;
- winBltExposedRegionsProcPtr pwinBltExposedRegions;
- winActivateAppProcPtr pwinActivateApp;
- winRedrawScreenProcPtr pwinRedrawScreen;
- winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette;
- winInstallColormapProcPtr pwinInstallColormap;
- winStoreColorsProcPtr pwinStoreColors;
- winCreateColormapProcPtr pwinCreateColormap;
- winDestroyColormapProcPtr pwinDestroyColormap;
- winHotKeyAltTabProcPtr pwinHotKeyAltTab;
- winCreatePrimarySurfaceProcPtr pwinCreatePrimarySurface;
- winReleasePrimarySurfaceProcPtr pwinReleasePrimarySurface;
-
- winCreateScreenResourcesProc pwinCreateScreenResources;
-
-#ifdef XWIN_MULTIWINDOW
- /* Window Procedures for MultiWindow mode */
- winFinishCreateWindowsWindowProcPtr pwinFinishCreateWindowsWindow;
-#endif
-
- /* Window Procedures for Rootless mode */
- CreateWindowProcPtr CreateWindow;
- DestroyWindowProcPtr DestroyWindow;
- PositionWindowProcPtr PositionWindow;
- ChangeWindowAttributesProcPtr ChangeWindowAttributes;
- RealizeWindowProcPtr RealizeWindow;
- UnrealizeWindowProcPtr UnrealizeWindow;
- ValidateTreeProcPtr ValidateTree;
- PostValidateTreeProcPtr PostValidateTree;
- WindowExposuresProcPtr WindowExposures;
- CopyWindowProcPtr CopyWindow;
- ClearToBackgroundProcPtr ClearToBackground;
- ClipNotifyProcPtr ClipNotify;
- RestackWindowProcPtr RestackWindow;
- ReparentWindowProcPtr ReparentWindow;
- ResizeWindowProcPtr ResizeWindow;
- MoveWindowProcPtr MoveWindow;
- SetShapeProcPtr SetShape;
-
- winCursorRec cursor;
-} winPrivScreenRec;
-
-
-#ifdef XWIN_MULTIWINDOWEXTWM
-typedef struct {
- RootlessWindowPtr pFrame;
- HWND hWnd;
- int dwWidthBytes;
- BITMAPINFOHEADER *pbmihShadow;
- HBITMAP hbmpShadow;
- HDC hdcShadow;
- HDC hdcScreen;
- BOOL fResized;
- BOOL fRestackingNow;
- BOOL fClose;
- BOOL fMovingOrSizing;
- BOOL fDestroyed;//for debug
- char *pfb;
-} win32RootlessWindowRec, *win32RootlessWindowPtr;
-#endif
-
-
-typedef struct {
- pointer value;
- XID id;
-} WindowIDPairRec, *WindowIDPairPtr;
-
-
-/*
- * Extern declares for general global variables
- */
-
-#include "winglobals.h"
-
-extern winScreenInfo * g_ScreenInfo;
-extern miPointerScreenFuncRec g_winPointerCursorFuncs;
-extern DWORD g_dwEvents;
-#ifdef HAS_DEVWINDOWS
-extern int g_fdMessageQueue;
-#endif
-extern DevPrivateKeyRec g_iScreenPrivateKeyRec;
-#define g_iScreenPrivateKey (&g_iScreenPrivateKeyRec)
-extern DevPrivateKeyRec g_iCmapPrivateKeyRec;
-#define g_iCmapPrivateKey (&g_iCmapPrivateKeyRec)
-extern DevPrivateKeyRec g_iGCPrivateKeyRec;
-#define g_iGCPrivateKey (&g_iGCPrivateKeyRec)
-extern DevPrivateKeyRec g_iPixmapPrivateKeyRec;
-#define g_iPixmapPrivateKey (&g_iPixmapPrivateKeyRec)
-extern DevPrivateKeyRec g_iWindowPrivateKeyRec;
-#define g_iWindowPrivateKey (&g_iWindowPrivateKeyRec)
-
-extern unsigned long g_ulServerGeneration;
-extern DWORD g_dwEnginesSupported;
-extern HINSTANCE g_hInstance;
-extern int g_copyROP[];
-extern int g_patternROP[];
-extern const char * g_pszQueryHost;
-extern DeviceIntPtr g_pwinPointer;
-extern DeviceIntPtr g_pwinKeyboard;
-
-/*
- * Extern declares for dynamically loaded library function pointers
- */
-
-extern FARPROC g_fpDirectDrawCreate;
-extern FARPROC g_fpDirectDrawCreateClipper;
-extern FARPROC g_fpTrackMouseEvent;
-
-
-/*
- * Screen privates macros
- */
-
-#define winGetScreenPriv(pScreen) ((winPrivScreenPtr) \
- dixLookupPrivate(&(pScreen)->devPrivates, g_iScreenPrivateKey))
-
-#define winSetScreenPriv(pScreen,v) \
- dixSetPrivate(&(pScreen)->devPrivates, g_iScreenPrivateKey, v)
-
-#define winScreenPriv(pScreen) \
- winPrivScreenPtr pScreenPriv = winGetScreenPriv(pScreen)
-
-
-/*
- * Colormap privates macros
- */
-
-#define winGetCmapPriv(pCmap) ((winPrivCmapPtr) \
- dixLookupPrivate(&(pCmap)->devPrivates, g_iCmapPrivateKey))
-
-#define winSetCmapPriv(pCmap,v) \
- dixSetPrivate(&(pCmap)->devPrivates, g_iCmapPrivateKey, v)
-
-#define winCmapPriv(pCmap) \
- winPrivCmapPtr pCmapPriv = winGetCmapPriv(pCmap)
-
-
-/*
- * GC privates macros
- */
-
-#define winGetGCPriv(pGC) ((winPrivGCPtr) \
- dixLookupPrivate(&(pGC)->devPrivates, g_iGCPrivateKey))
-
-#define winSetGCPriv(pGC,v) \
- dixSetPrivate(&(pGC)->devPrivates, g_iGCPrivateKey, v)
-
-#define winGCPriv(pGC) \
- winPrivGCPtr pGCPriv = winGetGCPriv(pGC)
-
-
-/*
- * Pixmap privates macros
- */
-
-#define winGetPixmapPriv(pPixmap) ((winPrivPixmapPtr) \
- dixLookupPrivate(&(pPixmap)->devPrivates, g_iPixmapPrivateKey))
-
-#define winSetPixmapPriv(pPixmap,v) \
- dixLookupPrivate(&(pPixmap)->devPrivates, g_iPixmapPrivateKey, v)
-
-#define winPixmapPriv(pPixmap) \
- winPrivPixmapPtr pPixmapPriv = winGetPixmapPriv(pPixmap)
-
-
-/*
- * Window privates macros
- */
-
-#define winGetWindowPriv(pWin) ((winPrivWinPtr) \
- dixLookupPrivate(&(pWin)->devPrivates, g_iWindowPrivateKey))
-
-#define winSetWindowPriv(pWin,v) \
- dixLookupPrivate(&(pWin)->devPrivates, g_iWindowPrivateKey, v)
-
-#define winWindowPriv(pWin) \
- winPrivWinPtr pWinPriv = winGetWindowPriv(pWin)
-
-/*
- * wrapper macros
- */
-#define _WIN_WRAP(priv, real, mem, func) {\
- priv->mem = real->mem; \
- real->mem = func; \
-}
-
-#define _WIN_UNWRAP(priv, real, mem) {\
- real->mem = priv->mem; \
-}
-
-#define WIN_WRAP(mem, func) _WIN_WRAP(pScreenPriv, pScreen, mem, func)
-
-#define WIN_UNWRAP(mem) _WIN_UNWRAP(pScreenPriv, pScreen, mem)
-
-/*
- * BEGIN DDX and DIX Function Prototypes
- */
-
-
-/*
- * winallpriv.c
- */
-
-Bool
-winAllocatePrivates (ScreenPtr pScreen);
-
-Bool
-winInitCmapPrivates (ColormapPtr pCmap, int index);
-
-Bool
-winAllocateCmapPrivates (ColormapPtr pCmap);
-
-
-/*
- * winauth.c
- */
-
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
-Bool
-winGenerateAuthorization (void);
-void winSetAuthorization(void);
-#endif
-
-
-/*
- * winblock.c
- */
-
-void
-winBlockHandler (int nScreen,
- pointer pBlockData,
- pointer pTimeout,
- pointer pReadMask);
-
-
-#ifdef XWIN_NATIVEGDI
-/*
- * winclip.c
- */
-
-RegionPtr
-winPixmapToRegionNativeGDI (PixmapPtr pPix);
-#endif
-
-
-#ifdef XWIN_CLIPBOARD
-/*
- * winclipboardinit.c
- */
-
-Bool
-winInitClipboard (void);
-
-void
-winFixClipboardChain (void);
-#endif
-
-
-/*
- * wincmap.c
- */
-
-void
-winSetColormapFunctions (ScreenPtr pScreen);
-
-Bool
-winCreateDefColormap (ScreenPtr pScreen);
-
-
-/*
- * wincreatewnd.c
- */
-
-Bool
-winCreateBoundingWindowFullScreen (ScreenPtr pScreen);
-
-Bool
-winCreateBoundingWindowWindowed (ScreenPtr pScreen);
-
-
-/*
- * windialogs.c
- */
-
-void
-winDisplayExitDialog (winPrivScreenPtr pScreenPriv);
-
-void
-winDisplayDepthChangeDialog (winPrivScreenPtr pScreenPriv);
-
-void
-winDisplayAboutDialog (winPrivScreenPtr pScreenPriv);
-
-
-/*
- * winengine.c
- */
-
-void
-winDetectSupportedEngines (void);
-
-Bool
-winSetEngine (ScreenPtr pScreen);
-
-Bool
-winGetDDProcAddresses (void);
-
-void
-winReleaseDDProcAddresses(void);
-
-
-/*
- * winerror.c
- */
-
-#ifdef DDXOSVERRORF
-void
-OSVenderVErrorF (const char *pszFormat, va_list va_args);
-#endif
-
-void
-winMessageBoxF (const char *pszError, UINT uType, ...);
-
-
-#ifdef XWIN_NATIVEGDI
-/*
- * winfillsp.c
- */
-
-void
-winFillSpansNativeGDI (DrawablePtr pDrawable,
- GCPtr pGC,
- int nSpans,
- DDXPointPtr pPoints,
- int *pWidths,
- int fSorted);
-#endif
-
-
-#ifdef XWIN_NATIVEGDI
-/*
- * winfont.c
- */
-
-Bool
-winRealizeFontNativeGDI (ScreenPtr pScreen, FontPtr pFont);
-
-Bool
-winUnrealizeFontNativeGDI (ScreenPtr pScreen, FontPtr pFont);
-#endif
-
-
-#ifdef XWIN_NATIVEGDI
-/*
- * wingc.c
- */
-
-Bool
-winCreateGCNativeGDI (GCPtr pGC);
-#endif
-
-
-#ifdef XWIN_NATIVEGDI
-/*
- * wingetsp.c
- */
-
-void
-winGetSpansNativeGDI (DrawablePtr pDrawable,
- int wMax,
- DDXPointPtr pPoints,
- int *pWidths,
- int nSpans,
- char *pDst);
-#endif
-
-
-/*
- * winglobals.c
- */
-
-void
-winInitializeGlobals (void);
-
-
-/*
- * winkeybd.c
- */
-
-void
-winTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode);
-
-int
-winKeybdProc (DeviceIntPtr pDeviceInt, int iState);
-
-void
-winInitializeModeKeyStates (void);
-
-void
-winRestoreModeKeyStates (void);
-
-Bool
-winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam);
-
-void
-winKeybdReleaseKeys (void);
-
-void
-winSendKeyEvent (DWORD dwKey, Bool fDown);
-
-BOOL
-winCheckKeyPressed(WPARAM wParam, LPARAM lParam);
-
-void
-winFixShiftKeys (int iScanCode);
-
-/*
- * winkeyhook.c
- */
-
-Bool
-winInstallKeyboardHookLL (void);
-
-void
-winRemoveKeyboardHookLL (void);
-
-
-/*
- * winmisc.c
- */
-
-#ifdef XWIN_NATIVEGDI
-void
-winQueryBestSizeNativeGDI (int class, unsigned short *pWidth,
- unsigned short *pHeight, ScreenPtr pScreen);
-#endif
-
-CARD8
-winCountBits (DWORD dw);
-
-Bool
-winUpdateFBPointer (ScreenPtr pScreen, void *pbits);
-
-#ifdef XWIN_NATIVEGDI
-BOOL
-winPaintBackground (HWND hwnd, COLORREF colorref);
-#endif
-
-
-/*
- * winmouse.c
- */
-
-int
-winMouseProc (DeviceIntPtr pDeviceInt, int iState);
-
-int
-winMouseWheel (ScreenPtr pScreen, int iDeltaZ);
-
-void
-winMouseButtonsSendEvent (int iEventType, int iButton);
-
-int
-winMouseButtonsHandle (ScreenPtr pScreen,
- int iEventType, int iButton,
- WPARAM wParam);
-
-void
-winEnqueueMotion(int x, int y);
-
-#ifdef XWIN_NATIVEGDI
-/*
- * winnativegdi.c
- */
-
-HBITMAP
-winCreateDIBNativeGDI (int iWidth, int iHeight, int iDepth,
- BYTE **ppbBits, BITMAPINFO **ppbmi);
-
-Bool
-winSetEngineFunctionsNativeGDI (ScreenPtr pScreen);
-#endif
-
-
-#ifdef XWIN_PRIMARYFB
-/*
- * winpfbddd.c
- */
-
-Bool
-winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen);
-#endif
-
-
-#ifdef XWIN_NATIVEGDI
-/*
- * winpixmap.c
- */
-
-PixmapPtr
-winCreatePixmapNativeGDI (ScreenPtr pScreen, int width, int height, int depth,
- unsigned usage_hint);
-
-Bool
-winDestroyPixmapNativeGDI (PixmapPtr pPixmap);
-
-Bool
-winModifyPixmapHeaderNativeGDI (PixmapPtr pPixmap,
- int iWidth, int iHeight,
- int iDepth,
- int iBitsPerPixel,
- int devKind,
- pointer pPixData);
-#endif
-
-#ifdef XWIN_NATIVEGDI
-/*
- * winpolyline.c
- */
-
-void
-winPolyLineNativeGDI (DrawablePtr pDrawable,
- GCPtr pGC,
- int mode,
- int npt,
- DDXPointPtr ppt);
-#endif
-
-
-#ifdef XWIN_NATIVEGDI
-/*
- * winpushpxl.c
- */
-
-void
-winPushPixels (GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable,
- int dx, int dy, int xOrg, int yOrg);
-#endif
-
-
-/*
- * winscrinit.c
- */
-
-Bool
-winScreenInit (int index,
- ScreenPtr pScreen,
- int argc, char **argv);
-
-Bool
-winFinishScreenInitFB (int index,
- ScreenPtr pScreen,
- int argc, char **argv);
-
-#if defined(XWIN_NATIVEGDI)
-Bool
-winFinishScreenInitNativeGDI (int index,
- ScreenPtr pScreen,
- int argc, char **argv);
-#endif
-
-
-#ifdef XWIN_NATIVEGDI
-/*
- * winsetsp.c
- */
-
-void
-winSetSpansNativeGDI (DrawablePtr pDrawable,
- GCPtr pGC,
- char *pSrc,
- DDXPointPtr pPoints,
- int *pWidth,
- int nSpans,
- int fSorted);
-#endif
-
-
-/*
- * winshaddd.c
- */
-
-Bool
-winSetEngineFunctionsShadowDD (ScreenPtr pScreen);
-
-
-/*
- * winshadddnl.c
- */
-
-Bool
-winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen);
-
-
-/*
- * winshadgdi.c
- */
-
-Bool
-winSetEngineFunctionsShadowGDI (ScreenPtr pScreen);
-
-
-/*
- * winwakeup.c
- */
-
-void
-winWakeupHandler (int nScreen,
- pointer pWakeupData,
- unsigned long ulResult,
- pointer pReadmask);
-
-
-/*
- * winwindow.c
- */
-
-#ifdef XWIN_NATIVEGDI
-Bool
-winCreateWindowNativeGDI (WindowPtr pWin);
-
-Bool
-winDestroyWindowNativeGDI (WindowPtr pWin);
-
-Bool
-winPositionWindowNativeGDI (WindowPtr pWin, int x, int y);
-
-void
-winCopyWindowNativeGDI (WindowPtr pWin,
- DDXPointRec ptOldOrg,
- RegionPtr prgnSrc);
-
-Bool
-winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask);
-
-Bool
-winUnmapWindowNativeGDI (WindowPtr pWindow);
-
-Bool
-winMapWindowNativeGDI (WindowPtr pWindow);
-#endif
-
-Bool
-winCreateWindowRootless (WindowPtr pWindow);
-
-Bool
-winDestroyWindowRootless (WindowPtr pWindow);
-
-Bool
-winPositionWindowRootless (WindowPtr pWindow, int x, int y);
-
-Bool
-winChangeWindowAttributesRootless (WindowPtr pWindow, unsigned long mask);
-
-Bool
-winUnmapWindowRootless (WindowPtr pWindow);
-
-Bool
-winMapWindowRootless (WindowPtr pWindow);
-
-void
-winSetShapeRootless (WindowPtr pWindow, int kind);
-
-
-/*
- * winmultiwindowicons.c - Used by both multi-window and Win32Rootless
- */
-
-HICON
-winXIconToHICON (WindowPtr pWin, int iconSize);
-
-void
-winSelectIcons(WindowPtr pWin, HICON *pIcon, HICON *pSmallIcon);
-
-#ifdef XWIN_MULTIWINDOW
-/*
- * winmultiwindowshape.c
- */
-
-void
-winReshapeMultiWindow (WindowPtr pWin);
-
-void
-winSetShapeMultiWindow (WindowPtr pWindow, int kind);
-
-void
-winUpdateRgnMultiWindow (WindowPtr pWindow);
-#endif
-
-
-#ifdef XWIN_MULTIWINDOW
-/*
- * winmultiwindowwindow.c
- */
-
-Bool
-winCreateWindowMultiWindow (WindowPtr pWindow);
-
-Bool
-winDestroyWindowMultiWindow (WindowPtr pWindow);
-
-Bool
-winPositionWindowMultiWindow (WindowPtr pWindow, int x, int y);
-
-Bool
-winChangeWindowAttributesMultiWindow (WindowPtr pWindow, unsigned long mask);
-
-Bool
-winUnmapWindowMultiWindow (WindowPtr pWindow);
-
-Bool
-winMapWindowMultiWindow (WindowPtr pWindow);
-
-void
-winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent);
-
-void
-winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib);
-
-void
-winReorderWindowsMultiWindow (void);
-
-void
-winResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w,
- unsigned int h, WindowPtr pSib);
-void
-winMoveWindowMultiWindow (WindowPtr pWin, int x, int y,
- WindowPtr pSib, VTKind kind);
-
-void
-winCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt,
- RegionPtr oldRegion);
-
-XID
-winGetWindowID (WindowPtr pWin);
-
-int
-winAdjustXWindow (WindowPtr pWin, HWND hwnd);
-#endif
-
-
-#ifdef XWIN_MULTIWINDOW
-/*
- * winmultiwindowwndproc.c
- */
-
-LRESULT CALLBACK
-winTopLevelWindowProc (HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam);
-#endif
-
-
-/*
- * wintrayicon.c
- */
-
-void
-winInitNotifyIcon (winPrivScreenPtr pScreenPriv);
-
-void
-winDeleteNotifyIcon (winPrivScreenPtr pScreenPriv);
-
-LRESULT
-winHandleIconMessage (HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam,
- winPrivScreenPtr pScreenPriv);
-
-
-/*
- * winwndproc.c
- */
-
-LRESULT CALLBACK
-winWindowProc (HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam);
-
-
-#ifdef XWIN_MULTIWINDOWEXTWM
-/*
- * winwin32rootless.c
- */
-
-Bool
-winMWExtWMCreateFrame (RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape);
-
-void
-winMWExtWMDestroyFrame (RootlessFrameID wid);
-
-void
-winMWExtWMMoveFrame (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
-
-void
-winMWExtWMResizeFrame (RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity);
-
-void
-winMWExtWMRestackFrame (RootlessFrameID wid, RootlessFrameID nextWid);
-
-void
-winMWExtWMReshapeFrame (RootlessFrameID wid, RegionPtr pShape);
-
-void
-winMWExtWMUnmapFrame (RootlessFrameID wid);
-
-void
-winMWExtWMStartDrawing (RootlessFrameID wid, char **pixelData, int *bytesPerRow);
-
-void
-winMWExtWMStopDrawing (RootlessFrameID wid, Bool flush);
-
-void
-winMWExtWMUpdateRegion (RootlessFrameID wid, RegionPtr pDamage);
-
-void
-winMWExtWMDamageRects (RootlessFrameID wid, int count, const BoxRec *rects,
- int shift_x, int shift_y);
-
-void
-winMWExtWMRootlessSwitchWindow (RootlessWindowPtr pFrame, WindowPtr oldWin);
-
-void
-winMWExtWMCopyBytes (unsigned int width, unsigned int height,
- const void *src, unsigned int srcRowBytes,
- void *dst, unsigned int dstRowBytes);
-
-void
-winMWExtWMCopyWindow (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy);
-#endif
-
-
-#ifdef XWIN_MULTIWINDOWEXTWM
-/*
- * winwin32rootlesswindow.c
- */
-
-void
-winMWExtWMReorderWindows (ScreenPtr pScreen);
-
-void
-winMWExtWMMoveXWindow (WindowPtr pWin, int x, int y);
-
-void
-winMWExtWMResizeXWindow (WindowPtr pWin, int w, int h);
-
-void
-winMWExtWMMoveResizeXWindow (WindowPtr pWin, int x, int y, int w, int h);
-
-void
-winMWExtWMUpdateIcon (Window id);
-
-void
-winMWExtWMUpdateWindowDecoration (win32RootlessWindowPtr pRLWinPriv,
- winScreenInfoPtr pScreenInfo);
-
-wBOOL CALLBACK
-winMWExtWMDecorateWindow (HWND hwnd, LPARAM lParam);
-
-Bool
-winIsInternalWMRunning (winScreenInfoPtr pScreenInfo);
-
-void
-winMWExtWMRestackWindows (ScreenPtr pScreen);
-#endif
-
-
-#ifdef XWIN_MULTIWINDOWEXTWM
-/*
- * winwin32rootlesswndproc.c
- */
-
-LRESULT CALLBACK
-winMWExtWMWindowProc (HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam);
-#endif
-
-
-/*
- * winwindowswm.c
- */
-
-void
-winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg,
- Window window, int x, int y, int w, int h);
-
-void
-winWindowsWMExtensionInit (void);
-
-/*
- * wincursor.c
- */
-
-Bool
-winInitCursor (ScreenPtr pScreen);
-
-/*
- * winprocarg.c
- */
-void
-winInitializeScreens(int maxscreens);
-
-/*
- * END DDX and DIX Function Prototypes
- */
-
-#endif /* _WIN_H_ */
-
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ * Kensuke Matsuzaki
+ */
+
+#ifndef _WIN_H_
+#define _WIN_H_
+
+#ifndef NO
+#define NO 0
+#endif
+#ifndef YES
+#define YES 1
+#endif
+
+/* Turn debug messages on or off */
+#ifndef CYGDEBUG
+#define CYGDEBUG NO
+#endif
+
+/* WM_XBUTTON Messages. They should go into w32api. */
+#ifndef WM_XBUTTONDOWN
+# define WM_XBUTTONDOWN 523
+#endif
+#ifndef WM_XBUTTONUP
+# define WM_XBUTTONUP 524
+#endif
+#ifndef WM_XBUTTONDBLCLK
+# define WM_XBUTTONDBLCLK 525
+#endif
+
+
+#define WIN_DEFAULT_BPP 0
+#define WIN_DEFAULT_WHITEPIXEL 255
+#define WIN_DEFAULT_BLACKPIXEL 0
+#define WIN_DEFAULT_LINEBIAS 0
+#define WIN_DEFAULT_E3B_TIME 50 /* milliseconds */
+#define WIN_DEFAULT_DPI 75
+#define WIN_DEFAULT_REFRESH 0
+#define WIN_DEFAULT_WIN_KILL TRUE
+#define WIN_DEFAULT_UNIX_KILL FALSE
+#define WIN_DEFAULT_CLIP_UPDATES_NBOXES 0
+#ifdef XWIN_EMULATEPSEUDO
+#define WIN_DEFAULT_EMULATE_PSEUDO FALSE
+#endif
+#define WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH FALSE
+
+/*
+ * Windows only supports 256 color palettes
+ */
+#define WIN_NUM_PALETTE_ENTRIES 256
+
+/*
+ * Number of times to call Restore in an attempt to restore the primary surface
+ */
+#define WIN_REGAIN_SURFACE_RETRIES 1
+
+/*
+ * Build a supported display depths mask by shifting one to the left
+ * by the number of bits in the supported depth.
+ */
+#define WIN_SUPPORTED_BPPS ( (1 << (32 - 1)) | (1 << (24 - 1)) \
+ | (1 << (16 - 1)) | (1 << (15 - 1)) \
+ | (1 << ( 8 - 1)))
+#define WIN_CHECK_DEPTH YES
+
+/*
+ * Timer IDs for WM_TIMER
+ */
+#define WIN_E3B_TIMER_ID 1
+#define WIN_POLLING_MOUSE_TIMER_ID 2
+
+#define MOUSE_POLLING_INTERVAL 50
+
+#define WIN_E3B_OFF -1
+#define WIN_FD_INVALID -1
+
+#define WIN_SERVER_NONE 0x0L /* 0 */
+#define WIN_SERVER_SHADOW_GDI 0x1L /* 1 */
+#define WIN_SERVER_SHADOW_DD 0x2L /* 2 */
+#define WIN_SERVER_SHADOW_DDNL 0x4L /* 4 */
+#ifdef XWIN_PRIMARYFB
+#define WIN_SERVER_PRIMARY_DD 0x8L /* 8 */
+#endif
+#ifdef XWIN_NATIVEGDI
+# define WIN_SERVER_NATIVE_GDI 0x10L /* 16 */
+#endif
+
+#define AltMapIndex Mod1MapIndex
+#define NumLockMapIndex Mod2MapIndex
+#define AltLangMapIndex Mod3MapIndex
+#define KanaMapIndex Mod4MapIndex
+#define ScrollLockMapIndex Mod5MapIndex
+
+#define WIN_MOD_LALT 0x00000001
+#define WIN_MOD_RALT 0x00000002
+#define WIN_MOD_LCONTROL 0x00000004
+#define WIN_MOD_RCONTROL 0x00000008
+
+#define WIN_24BPP_MASK_RED 0x00FF0000
+#define WIN_24BPP_MASK_GREEN 0x0000FF00
+#define WIN_24BPP_MASK_BLUE 0x000000FF
+
+#define WIN_MAX_KEYS_PER_KEY 4
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#include <errno.h>
+#if defined(XWIN_MULTIWINDOWEXTWM) || defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+#define HANDLE void *
+#include <pthread.h>
+#undef HANDLE
+#endif
+
+#ifdef HAS_MMAP
+#include <sys/mman.h>
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif /* MAP_FILE */
+#endif /* HAS_MMAP */
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xos.h>
+#include <X11/Xprotostr.h>
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "pixmap.h"
+#include "region.h"
+#include "gcstruct.h"
+#include "colormap.h"
+#include "colormapst.h"
+#include "miscstruct.h"
+#include "servermd.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "micmap.h"
+#include "mifillarc.h"
+#include "mifpoly.h"
+#include "mibstore.h"
+#include "input.h"
+#include "mipointer.h"
+#include "X11/keysym.h"
+#include "mibstore.h"
+#include "micoord.h"
+#include "dix.h"
+#include "miline.h"
+#include "shadow.h"
+#include "fb.h"
+#include "rootless.h"
+
+#include "mipict.h"
+#include "picturestr.h"
+
+#ifdef RANDR
+#include "randrstr.h"
+#endif
+
+/*
+ * Windows headers
+ */
+#include "winms.h"
+#include "winresource.h"
+
+
+/*
+ * Define Windows constants
+ */
+
+#define WM_TRAYICON (WM_USER + 1000)
+#define WM_INIT_SYS_MENU (WM_USER + 1001)
+#define WM_GIVEUP (WM_USER + 1002)
+
+
+/* Local includes */
+#include "winwindow.h"
+#include "winmsg.h"
+
+
+/*
+ * Debugging macros
+ */
+
+#if CYGDEBUG
+#define DEBUG_MSG(str,...) \
+if (fDebugProcMsg) \
+{ \
+ char *pszTemp; \
+ int iLength; \
+ if (asprintf (&pszTemp, str, ##__VA_ARGS__) != -1) { \
+ MessageBox (NULL, pszTemp, szFunctionName, MB_OK); \
+ free (pszTemp); \
+ } \
+}
+#else
+#define DEBUG_MSG(str,...)
+#endif
+
+#if CYGDEBUG
+#define DEBUG_FN_NAME(str) PTSTR szFunctionName = str
+#else
+#define DEBUG_FN_NAME(str)
+#endif
+
+#if CYGDEBUG || YES
+#define DEBUGVARS BOOL fDebugProcMsg = FALSE
+#else
+#define DEBUGVARS
+#endif
+
+#if CYGDEBUG || YES
+#define DEBUGPROC_MSG fDebugProcMsg = TRUE
+#else
+#define DEBUGPROC_MSG
+#endif
+
+#define PROFILEPOINT(point,thresh)\
+{\
+static unsigned int PROFPT##point = 0;\
+if (++PROFPT##point % thresh == 0)\
+ErrorF (#point ": PROFILEPOINT hit %u times\n", PROFPT##point);\
+}
+
+
+/* We use xor this macro for detecting toggle key state changes */
+#define WIN_XOR(a,b) ((!(a) && (b)) || ((a) && !(b)))
+
+#define DEFINE_ATOM_HELPER(func,atom_name) \
+static Atom func (void) { \
+ static int generation; \
+ static Atom atom; \
+ if (generation != serverGeneration) { \
+ generation = serverGeneration; \
+ atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
+ } \
+ return atom; \
+}
+
+/*
+ * Typedefs for engine dependent function pointers
+ */
+
+typedef Bool (*winAllocateFBProcPtr)(ScreenPtr);
+
+typedef void (*winFreeFBProcPtr)(ScreenPtr);
+
+typedef void (*winShadowUpdateProcPtr)(ScreenPtr, shadowBufPtr);
+
+typedef Bool (*winInitScreenProcPtr)(ScreenPtr);
+
+typedef Bool (*winCloseScreenProcPtr)(int, ScreenPtr);
+
+typedef Bool (*winInitVisualsProcPtr)(ScreenPtr);
+
+typedef Bool (*winAdjustVideoModeProcPtr)(ScreenPtr);
+
+typedef Bool (*winCreateBoundingWindowProcPtr)(ScreenPtr);
+
+typedef Bool (*winFinishScreenInitProcPtr)(int, ScreenPtr, int, char **);
+
+typedef Bool (*winBltExposedRegionsProcPtr)(ScreenPtr);
+
+typedef Bool (*winActivateAppProcPtr)(ScreenPtr);
+
+typedef Bool (*winRedrawScreenProcPtr)(ScreenPtr pScreen);
+
+typedef Bool (*winRealizeInstalledPaletteProcPtr)(ScreenPtr pScreen);
+
+typedef Bool (*winInstallColormapProcPtr)(ColormapPtr pColormap);
+
+typedef Bool (*winStoreColorsProcPtr)(ColormapPtr pmap,
+ int ndef, xColorItem *pdefs);
+
+typedef Bool (*winCreateColormapProcPtr)(ColormapPtr pColormap);
+
+typedef Bool (*winDestroyColormapProcPtr)(ColormapPtr pColormap);
+
+typedef Bool (*winHotKeyAltTabProcPtr)(ScreenPtr);
+
+typedef Bool (*winCreatePrimarySurfaceProcPtr)(ScreenPtr);
+
+typedef Bool (*winReleasePrimarySurfaceProcPtr)(ScreenPtr);
+
+typedef Bool (*winFinishCreateWindowsWindowProcPtr)(WindowPtr pWin);
+
+typedef Bool (*winCreateScreenResourcesProc)(ScreenPtr);
+
+#ifdef XWIN_NATIVEGDI
+/* Typedefs for native GDI wrappers */
+typedef Bool (*RealizeFontPtr) (ScreenPtr pScreen, FontPtr pFont);
+typedef Bool (*UnrealizeFontPtr)(ScreenPtr pScreen, FontPtr pFont);
+#endif
+
+
+/*
+ * GC (graphics context) privates
+ */
+
+typedef struct
+{
+ HDC hdc;
+ HDC hdcMem;
+} winPrivGCRec, *winPrivGCPtr;
+
+
+/*
+ * Pixmap privates
+ */
+
+typedef struct
+{
+ HDC hdcSelected;
+ HBITMAP hBitmap;
+ BYTE *pbBits;
+ DWORD dwScanlineBytes;
+ BITMAPINFOHEADER *pbmih;
+} winPrivPixmapRec, *winPrivPixmapPtr;
+
+
+/*
+ * Colormap privates
+ */
+
+typedef struct
+{
+ HPALETTE hPalette;
+ LPDIRECTDRAWPALETTE lpDDPalette;
+ RGBQUAD rgbColors[WIN_NUM_PALETTE_ENTRIES];
+ PALETTEENTRY peColors[WIN_NUM_PALETTE_ENTRIES];
+} winPrivCmapRec, *winPrivCmapPtr;
+
+/*
+ * Windows Cursor handling.
+ */
+
+typedef struct {
+ /* from GetSystemMetrics */
+ int sm_cx;
+ int sm_cy;
+
+ BOOL visible;
+ HCURSOR handle;
+ QueryBestSizeProcPtr QueryBestSize;
+ miPointerSpriteFuncPtr spriteFuncs;
+} winCursorRec;
+
+/*
+ * Resize modes
+ */
+typedef enum {
+ notAllowed,
+ resizeWithScrollbars,
+ resizeWithRandr
+} winResizeMode;
+
+/*
+ * Screen information structure that we need before privates are available
+ * in the server startup sequence.
+ */
+
+typedef struct
+{
+ ScreenPtr pScreen;
+
+ /* Did the user specify a height and width? */
+ Bool fUserGaveHeightAndWidth;
+
+ DWORD dwScreen;
+
+ int iMonitor;
+ DWORD dwUserWidth;
+ DWORD dwUserHeight;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DWORD dwPaddedWidth;
+
+ /* Did the user specify a screen position? */
+ Bool fUserGavePosition;
+ DWORD dwInitialX;
+ DWORD dwInitialY;
+
+ /*
+ * dwStride is the number of whole pixels that occupy a scanline,
+ * including those pixels that are not displayed. This is basically
+ * a rounding up of the width.
+ */
+ DWORD dwStride;
+
+ /* Offset of the screen in the window when using scrollbars */
+ DWORD dwXOffset;
+ DWORD dwYOffset;
+
+ DWORD dwBPP;
+ DWORD dwDepth;
+ DWORD dwRefreshRate;
+ char *pfb;
+ DWORD dwEngine;
+ DWORD dwEnginePreferred;
+ DWORD dwClipUpdatesNBoxes;
+#ifdef XWIN_EMULATEPSEUDO
+ Bool fEmulatePseudo;
+#endif
+ Bool fFullScreen;
+ Bool fDecoration;
+#ifdef XWIN_MULTIWINDOWEXTWM
+ Bool fMWExtWM;
+ Bool fInternalWM;
+ Bool fAnotherWMRunning;
+#endif
+ Bool fRootless;
+#ifdef XWIN_MULTIWINDOW
+ Bool fMultiWindow;
+#endif
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ Bool fMultiMonitorOverride;
+#endif
+ Bool fMultipleMonitors;
+ Bool fLessPointer;
+ winResizeMode iResizeMode;
+ Bool fNoTrayIcon;
+ int iE3BTimeout;
+ /* Windows (Alt+F4) and Unix (Ctrl+Alt+Backspace) Killkey */
+ Bool fUseWinKillKey;
+ Bool fUseUnixKillKey;
+ Bool fIgnoreInput;
+
+ /* Did the user explicitly set this screen? */
+ Bool fExplicitScreen;
+} winScreenInfo, *winScreenInfoPtr;
+
+
+/*
+ * Screen privates
+ */
+
+typedef struct _winPrivScreenRec
+{
+ winScreenInfoPtr pScreenInfo;
+
+ Bool fEnabled;
+ Bool fClosed;
+ Bool fActive;
+ Bool fBadDepth;
+
+ int iDeltaZ;
+
+ int iConnectedClients;
+
+ CloseScreenProcPtr CloseScreen;
+
+ DWORD dwRedMask;
+ DWORD dwGreenMask;
+ DWORD dwBlueMask;
+ DWORD dwBitsPerRGB;
+
+ DWORD dwModeKeyStates;
+
+ /* Handle to icons that must be freed */
+ HICON hiconNotifyIcon;
+
+ /* Palette management */
+ ColormapPtr pcmapInstalled;
+
+ /* Pointer to the root visual so we only have to look it up once */
+ VisualPtr pRootVisual;
+
+ /* 3 button emulation variables */
+ int iE3BCachedPress;
+ Bool fE3BFakeButton2Sent;
+
+ /* Privates used by shadow fb GDI server */
+ HBITMAP hbmpShadow;
+ HDC hdcScreen;
+ HDC hdcShadow;
+ HWND hwndScreen;
+ BITMAPINFOHEADER *pbmih;
+
+ /* Privates used by shadow fb and primary fb DirectDraw servers */
+ LPDIRECTDRAW pdd;
+ LPDIRECTDRAWSURFACE2 pddsPrimary;
+ LPDIRECTDRAW2 pdd2;
+
+ /* Privates used by shadow fb DirectDraw server */
+ LPDIRECTDRAWSURFACE2 pddsShadow;
+ LPDDSURFACEDESC pddsdShadow;
+
+ /* Privates used by primary fb DirectDraw server */
+ LPDIRECTDRAWSURFACE2 pddsOffscreen;
+ LPDDSURFACEDESC pddsdOffscreen;
+ LPDDSURFACEDESC pddsdPrimary;
+
+ /* Privates used by shadow fb DirectDraw Nonlocking server */
+ LPDIRECTDRAW4 pdd4;
+ LPDIRECTDRAWSURFACE4 pddsShadow4;
+ LPDIRECTDRAWSURFACE4 pddsPrimary4;
+ BOOL fRetryCreateSurface;
+
+ /* Privates used by both shadow fb DirectDraw servers */
+ LPDIRECTDRAWCLIPPER pddcPrimary;
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ /* Privates used by multi-window external window manager */
+ RootlessFrameID widTop;
+ Bool fRestacking;
+#endif
+
+#ifdef XWIN_MULTIWINDOW
+ /* Privates used by multi-window */
+ pthread_t ptWMProc;
+ pthread_t ptXMsgProc;
+ void *pWMInfo;
+#endif
+
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ /* Privates used by both multi-window and rootless */
+ Bool fRootWindowShown;
+#endif
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Privates used for any module running in a seperate thread */
+ pthread_mutex_t pmServerStarted;
+ Bool fServerStarted;
+#endif
+
+ /* Engine specific functions */
+ winAllocateFBProcPtr pwinAllocateFB;
+ winFreeFBProcPtr pwinFreeFB;
+ winShadowUpdateProcPtr pwinShadowUpdate;
+ winInitScreenProcPtr pwinInitScreen;
+ winCloseScreenProcPtr pwinCloseScreen;
+ winInitVisualsProcPtr pwinInitVisuals;
+ winAdjustVideoModeProcPtr pwinAdjustVideoMode;
+ winCreateBoundingWindowProcPtr pwinCreateBoundingWindow;
+ winFinishScreenInitProcPtr pwinFinishScreenInit;
+ winBltExposedRegionsProcPtr pwinBltExposedRegions;
+ winActivateAppProcPtr pwinActivateApp;
+ winRedrawScreenProcPtr pwinRedrawScreen;
+ winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette;
+ winInstallColormapProcPtr pwinInstallColormap;
+ winStoreColorsProcPtr pwinStoreColors;
+ winCreateColormapProcPtr pwinCreateColormap;
+ winDestroyColormapProcPtr pwinDestroyColormap;
+ winHotKeyAltTabProcPtr pwinHotKeyAltTab;
+ winCreatePrimarySurfaceProcPtr pwinCreatePrimarySurface;
+ winReleasePrimarySurfaceProcPtr pwinReleasePrimarySurface;
+
+ winCreateScreenResourcesProc pwinCreateScreenResources;
+
+#ifdef XWIN_MULTIWINDOW
+ /* Window Procedures for MultiWindow mode */
+ winFinishCreateWindowsWindowProcPtr pwinFinishCreateWindowsWindow;
+#endif
+
+ /* Window Procedures for Rootless mode */
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ PositionWindowProcPtr PositionWindow;
+ ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ ValidateTreeProcPtr ValidateTree;
+ PostValidateTreeProcPtr PostValidateTree;
+ WindowExposuresProcPtr WindowExposures;
+ CopyWindowProcPtr CopyWindow;
+ ClearToBackgroundProcPtr ClearToBackground;
+ ClipNotifyProcPtr ClipNotify;
+ RestackWindowProcPtr RestackWindow;
+ ReparentWindowProcPtr ReparentWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ MoveWindowProcPtr MoveWindow;
+ SetShapeProcPtr SetShape;
+
+ winCursorRec cursor;
+
+#ifdef XWIN_NATIVEGDI
+ RealizeFontPtr RealizeFont;
+ UnrealizeFontPtr UnrealizeFont;
+#endif
+
+} winPrivScreenRec;
+
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+typedef struct {
+ RootlessWindowPtr pFrame;
+ HWND hWnd;
+ int dwWidthBytes;
+ BITMAPINFOHEADER *pbmihShadow;
+ HBITMAP hbmpShadow;
+ HDC hdcShadow;
+ HDC hdcScreen;
+ BOOL fResized;
+ BOOL fRestackingNow;
+ BOOL fClose;
+ BOOL fMovingOrSizing;
+ BOOL fDestroyed;//for debug
+ char *pfb;
+} win32RootlessWindowRec, *win32RootlessWindowPtr;
+#endif
+
+
+typedef struct {
+ pointer value;
+ XID id;
+} WindowIDPairRec, *WindowIDPairPtr;
+
+
+/*
+ * Extern declares for general global variables
+ */
+
+#include "winglobals.h"
+
+extern winScreenInfo * g_ScreenInfo;
+extern miPointerScreenFuncRec g_winPointerCursorFuncs;
+extern DWORD g_dwEvents;
+#ifdef HAS_DEVWINDOWS
+extern int g_fdMessageQueue;
+#endif
+extern DevPrivateKeyRec g_iScreenPrivateKeyRec;
+#define g_iScreenPrivateKey (&g_iScreenPrivateKeyRec)
+extern DevPrivateKeyRec g_iCmapPrivateKeyRec;
+#define g_iCmapPrivateKey (&g_iCmapPrivateKeyRec)
+extern DevPrivateKeyRec g_iGCPrivateKeyRec;
+#define g_iGCPrivateKey (&g_iGCPrivateKeyRec)
+extern DevPrivateKeyRec g_iPixmapPrivateKeyRec;
+#define g_iPixmapPrivateKey (&g_iPixmapPrivateKeyRec)
+extern DevPrivateKeyRec g_iWindowPrivateKeyRec;
+#define g_iWindowPrivateKey (&g_iWindowPrivateKeyRec)
+
+extern unsigned long g_ulServerGeneration;
+extern DWORD g_dwEnginesSupported;
+extern HINSTANCE g_hInstance;
+extern int g_copyROP[];
+extern int g_patternROP[];
+extern const char * g_pszQueryHost;
+extern DeviceIntPtr g_pwinPointer;
+extern DeviceIntPtr g_pwinKeyboard;
+
+/*
+ * Extern declares for dynamically loaded library function pointers
+ */
+
+extern FARPROC g_fpDirectDrawCreate;
+extern FARPROC g_fpDirectDrawCreateClipper;
+extern FARPROC g_fpTrackMouseEvent;
+
+
+/*
+ * Screen privates macros
+ */
+
+#define winGetScreenPriv(pScreen) ((winPrivScreenPtr) \
+ dixLookupPrivate(&(pScreen)->devPrivates, g_iScreenPrivateKey))
+
+#define winSetScreenPriv(pScreen,v) \
+ dixSetPrivate(&(pScreen)->devPrivates, g_iScreenPrivateKey, v)
+
+#define winScreenPriv(pScreen) \
+ winPrivScreenPtr pScreenPriv = winGetScreenPriv(pScreen)
+
+
+/*
+ * Colormap privates macros
+ */
+
+#define winGetCmapPriv(pCmap) ((winPrivCmapPtr) \
+ dixLookupPrivate(&(pCmap)->devPrivates, g_iCmapPrivateKey))
+
+#define winSetCmapPriv(pCmap,v) \
+ dixSetPrivate(&(pCmap)->devPrivates, g_iCmapPrivateKey, v)
+
+#define winCmapPriv(pCmap) \
+ winPrivCmapPtr pCmapPriv = winGetCmapPriv(pCmap)
+
+
+/*
+ * GC privates macros
+ */
+
+#define winGetGCPriv(pGC) ((winPrivGCPtr) \
+ dixLookupPrivate(&(pGC)->devPrivates, g_iGCPrivateKey))
+
+#define winSetGCPriv(pGC,v) \
+ dixSetPrivate(&(pGC)->devPrivates, g_iGCPrivateKey, v)
+
+#define winGCPriv(pGC) \
+ winPrivGCPtr pGCPriv = winGetGCPriv(pGC)
+
+
+/*
+ * Pixmap privates macros
+ */
+
+#define winGetPixmapPriv(pPixmap) ((winPrivPixmapPtr) \
+ dixLookupPrivate(&(pPixmap)->devPrivates, g_iPixmapPrivateKey))
+
+#define winSetPixmapPriv(pPixmap,v) \
+ dixLookupPrivate(&(pPixmap)->devPrivates, g_iPixmapPrivateKey, v)
+
+#define winPixmapPriv(pPixmap) \
+ winPrivPixmapPtr pPixmapPriv = winGetPixmapPriv(pPixmap)
+
+
+/*
+ * Window privates macros
+ */
+
+#define winGetWindowPriv(pWin) ((winPrivWinPtr) \
+ dixLookupPrivate(&(pWin)->devPrivates, g_iWindowPrivateKey))
+
+#define winSetWindowPriv(pWin,v) \
+ dixLookupPrivate(&(pWin)->devPrivates, g_iWindowPrivateKey, v)
+
+#define winWindowPriv(pWin) \
+ winPrivWinPtr pWinPriv = winGetWindowPriv(pWin)
+
+/*
+ * wrapper macros
+ */
+#define _WIN_WRAP(priv, real, mem, func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#define _WIN_UNWRAP(priv, real, mem) {\
+ real->mem = priv->mem; \
+}
+
+#define WIN_WRAP(mem, func) _WIN_WRAP(pScreenPriv, pScreen, mem, func)
+
+#define WIN_UNWRAP(mem) _WIN_UNWRAP(pScreenPriv, pScreen, mem)
+
+/*
+ * BEGIN DDX and DIX Function Prototypes
+ */
+
+
+/*
+ * winallpriv.c
+ */
+
+Bool
+winAllocatePrivates (ScreenPtr pScreen);
+
+Bool
+winInitCmapPrivates (ColormapPtr pCmap, int index);
+
+Bool
+winAllocateCmapPrivates (ColormapPtr pCmap);
+
+
+/*
+ * winauth.c
+ */
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+Bool
+winGenerateAuthorization (void);
+void winSetAuthorization(void);
+#endif
+
+
+/*
+ * winblock.c
+ */
+
+void
+winBlockHandler (int nScreen,
+ pointer pBlockData,
+ pointer pTimeout,
+ pointer pReadMask);
+
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * winclip.c
+ */
+
+RegionPtr
+winPixmapToRegionNativeGDI (PixmapPtr pPix);
+#endif
+
+
+#ifdef XWIN_CLIPBOARD
+/*
+ * winclipboardinit.c
+ */
+
+Bool
+winInitClipboard (void);
+
+void
+winFixClipboardChain (void);
+#endif
+
+
+/*
+ * wincmap.c
+ */
+
+void
+winSetColormapFunctions (ScreenPtr pScreen);
+
+Bool
+winCreateDefColormap (ScreenPtr pScreen);
+
+
+/*
+ * wincreatewnd.c
+ */
+
+Bool
+winCreateBoundingWindowFullScreen (ScreenPtr pScreen);
+
+Bool
+winCreateBoundingWindowWindowed (ScreenPtr pScreen);
+
+
+/*
+ * windialogs.c
+ */
+
+void
+winDisplayExitDialog (winPrivScreenPtr pScreenPriv);
+
+void
+winDisplayDepthChangeDialog (winPrivScreenPtr pScreenPriv);
+
+void
+winDisplayAboutDialog (winPrivScreenPtr pScreenPriv);
+
+
+/*
+ * winengine.c
+ */
+
+void
+winDetectSupportedEngines (void);
+
+Bool
+winSetEngine (ScreenPtr pScreen);
+
+Bool
+winGetDDProcAddresses (void);
+
+void
+winReleaseDDProcAddresses(void);
+
+
+/*
+ * winerror.c
+ */
+
+#ifdef DDXOSVERRORF
+void
+OSVenderVErrorF (const char *pszFormat, va_list va_args);
+#endif
+
+void
+winMessageBoxF (const char *pszError, UINT uType, ...);
+
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * winfillsp.c
+ */
+
+void
+winFillSpansNativeGDI (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nSpans,
+ DDXPointPtr pPoints,
+ int *pWidths,
+ int fSorted);
+#endif
+
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * winfont.c
+ */
+
+Bool
+winRealizeFontNativeGDI (ScreenPtr pScreen, FontPtr pFont);
+
+Bool
+winUnrealizeFontNativeGDI (ScreenPtr pScreen, FontPtr pFont);
+#endif
+
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * wingc.c
+ */
+
+Bool
+winCreateGCNativeGDI (GCPtr pGC);
+#endif
+
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * wingetsp.c
+ */
+
+void
+winGetSpansNativeGDI (DrawablePtr pDrawable,
+ int wMax,
+ DDXPointPtr pPoints,
+ int *pWidths,
+ int nSpans,
+ char *pDst);
+#endif
+
+
+/*
+ * winglobals.c
+ */
+
+void
+winInitializeGlobals (void);
+
+
+/*
+ * winkeybd.c
+ */
+
+void
+winTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode);
+
+int
+winKeybdProc (DeviceIntPtr pDeviceInt, int iState);
+
+void
+winInitializeModeKeyStates (void);
+
+void
+winRestoreModeKeyStates (void);
+
+Bool
+winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam);
+
+void
+winKeybdReleaseKeys (void);
+
+void
+winSendKeyEvent (DWORD dwKey, Bool fDown);
+
+BOOL
+winCheckKeyPressed(WPARAM wParam, LPARAM lParam);
+
+void
+winFixShiftKeys (int iScanCode);
+
+/*
+ * winkeyhook.c
+ */
+
+Bool
+winInstallKeyboardHookLL (void);
+
+void
+winRemoveKeyboardHookLL (void);
+
+
+/*
+ * winmisc.c
+ */
+
+#ifdef XWIN_NATIVEGDI
+void
+winQueryBestSizeNativeGDI (int class, unsigned short *pWidth,
+ unsigned short *pHeight, ScreenPtr pScreen);
+#endif
+
+CARD8
+winCountBits (DWORD dw);
+
+Bool
+winUpdateFBPointer (ScreenPtr pScreen, void *pbits);
+
+#ifdef XWIN_NATIVEGDI
+BOOL
+winPaintBackground (HWND hwnd, COLORREF colorref);
+#endif
+
+
+/*
+ * winmouse.c
+ */
+
+int
+winMouseProc (DeviceIntPtr pDeviceInt, int iState);
+
+int
+winMouseWheel (ScreenPtr pScreen, int iDeltaZ);
+
+void
+winMouseButtonsSendEvent (int iEventType, int iButton);
+
+int
+winMouseButtonsHandle (ScreenPtr pScreen,
+ int iEventType, int iButton,
+ WPARAM wParam);
+
+void
+winEnqueueMotion(int x, int y);
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * winnativegdi.c
+ */
+
+HBITMAP
+winCreateDIBNativeGDI (int iWidth, int iHeight, int iDepth,
+ BYTE **ppbBits, BITMAPINFO **ppbmi);
+
+Bool
+winSetEngineFunctionsNativeGDI (ScreenPtr pScreen);
+#endif
+
+
+#ifdef XWIN_PRIMARYFB
+/*
+ * winpfbddd.c
+ */
+
+Bool
+winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen);
+#endif
+
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * winpixmap.c
+ */
+
+PixmapPtr
+winCreatePixmapNativeGDI (ScreenPtr pScreen, int width, int height, int depth,
+ unsigned usage_hint);
+
+Bool
+winDestroyPixmapNativeGDI (PixmapPtr pPixmap);
+
+Bool
+winModifyPixmapHeaderNativeGDI (PixmapPtr pPixmap,
+ int iWidth, int iHeight,
+ int iDepth,
+ int iBitsPerPixel,
+ int devKind,
+ pointer pPixData);
+#endif
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * winpolyline.c
+ */
+
+void
+winPolyLineNativeGDI (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ DDXPointPtr ppt);
+#endif
+
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * winpushpxl.c
+ */
+
+void
+winPushPixels (GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable,
+ int dx, int dy, int xOrg, int yOrg);
+#endif
+
+
+/*
+ * winscrinit.c
+ */
+
+Bool
+winScreenInit (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv);
+
+Bool
+winFinishScreenInitFB (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv);
+
+#if defined(XWIN_NATIVEGDI)
+Bool
+winFinishScreenInitNativeGDI (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv);
+#endif
+
+
+#ifdef XWIN_NATIVEGDI
+/*
+ * winsetsp.c
+ */
+
+void
+winSetSpansNativeGDI (DrawablePtr pDrawable,
+ GCPtr pGC,
+ char *pSrc,
+ DDXPointPtr pPoints,
+ int *pWidth,
+ int nSpans,
+ int fSorted);
+#endif
+
+
+/*
+ * winshaddd.c
+ */
+
+Bool
+winSetEngineFunctionsShadowDD (ScreenPtr pScreen);
+
+
+/*
+ * winshadddnl.c
+ */
+
+Bool
+winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen);
+
+
+/*
+ * winshadgdi.c
+ */
+
+Bool
+winSetEngineFunctionsShadowGDI (ScreenPtr pScreen);
+
+
+/*
+ * winwakeup.c
+ */
+
+void
+winWakeupHandler (int nScreen,
+ pointer pWakeupData,
+ unsigned long ulResult,
+ pointer pReadmask);
+
+
+/*
+ * winwindow.c
+ */
+
+#ifdef XWIN_NATIVEGDI
+Bool
+winCreateWindowNativeGDI (WindowPtr pWin);
+
+Bool
+winDestroyWindowNativeGDI (WindowPtr pWin);
+
+Bool
+winPositionWindowNativeGDI (WindowPtr pWin, int x, int y);
+
+void
+winCopyWindowNativeGDI (WindowPtr pWin,
+ DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc);
+
+Bool
+winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask);
+
+Bool
+winUnmapWindowNativeGDI (WindowPtr pWindow);
+
+Bool
+winMapWindowNativeGDI (WindowPtr pWindow);
+#endif
+
+Bool
+winCreateWindowRootless (WindowPtr pWindow);
+
+Bool
+winDestroyWindowRootless (WindowPtr pWindow);
+
+Bool
+winPositionWindowRootless (WindowPtr pWindow, int x, int y);
+
+Bool
+winChangeWindowAttributesRootless (WindowPtr pWindow, unsigned long mask);
+
+Bool
+winUnmapWindowRootless (WindowPtr pWindow);
+
+Bool
+winMapWindowRootless (WindowPtr pWindow);
+
+void
+winSetShapeRootless (WindowPtr pWindow, int kind);
+
+
+/*
+ * winmultiwindowicons.c - Used by both multi-window and Win32Rootless
+ */
+
+HICON
+winXIconToHICON (WindowPtr pWin, int iconSize);
+
+void
+winSelectIcons(WindowPtr pWin, HICON *pIcon, HICON *pSmallIcon);
+
+#ifdef XWIN_MULTIWINDOW
+/*
+ * winmultiwindowshape.c
+ */
+
+void
+winReshapeMultiWindow (WindowPtr pWin);
+
+void
+winSetShapeMultiWindow (WindowPtr pWindow, int kind);
+
+void
+winUpdateRgnMultiWindow (WindowPtr pWindow);
+#endif
+
+
+#ifdef XWIN_MULTIWINDOW
+/*
+ * winmultiwindowwindow.c
+ */
+
+Bool
+winCreateWindowMultiWindow (WindowPtr pWindow);
+
+Bool
+winDestroyWindowMultiWindow (WindowPtr pWindow);
+
+Bool
+winPositionWindowMultiWindow (WindowPtr pWindow, int x, int y);
+
+Bool
+winChangeWindowAttributesMultiWindow (WindowPtr pWindow, unsigned long mask);
+
+Bool
+winUnmapWindowMultiWindow (WindowPtr pWindow);
+
+Bool
+winMapWindowMultiWindow (WindowPtr pWindow);
+
+void
+winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent);
+
+void
+winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib);
+
+void
+winReorderWindowsMultiWindow (void);
+
+void
+winResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w,
+ unsigned int h, WindowPtr pSib);
+void
+winMoveWindowMultiWindow (WindowPtr pWin, int x, int y,
+ WindowPtr pSib, VTKind kind);
+
+void
+winCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt,
+ RegionPtr oldRegion);
+
+XID
+winGetWindowID (WindowPtr pWin);
+
+int
+winAdjustXWindow (WindowPtr pWin, HWND hwnd);
+#endif
+
+
+#ifdef XWIN_MULTIWINDOW
+/*
+ * winmultiwindowwndproc.c
+ */
+
+LRESULT CALLBACK
+winTopLevelWindowProc (HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam);
+#endif
+
+
+/*
+ * wintrayicon.c
+ */
+
+void
+winInitNotifyIcon (winPrivScreenPtr pScreenPriv);
+
+void
+winDeleteNotifyIcon (winPrivScreenPtr pScreenPriv);
+
+LRESULT
+winHandleIconMessage (HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam,
+ winPrivScreenPtr pScreenPriv);
+
+
+/*
+ * winwndproc.c
+ */
+
+LRESULT CALLBACK
+winWindowProc (HWND hWnd, UINT message,
+ WPARAM wParam, LPARAM lParam);
+
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+/*
+ * winwin32rootless.c
+ */
+
+Bool
+winMWExtWMCreateFrame (RootlessWindowPtr pFrame, ScreenPtr pScreen,
+ int newX, int newY, RegionPtr pShape);
+
+void
+winMWExtWMDestroyFrame (RootlessFrameID wid);
+
+void
+winMWExtWMMoveFrame (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
+
+void
+winMWExtWMResizeFrame (RootlessFrameID wid, ScreenPtr pScreen,
+ int newX, int newY, unsigned int newW, unsigned int newH,
+ unsigned int gravity);
+
+void
+winMWExtWMRestackFrame (RootlessFrameID wid, RootlessFrameID nextWid);
+
+void
+winMWExtWMReshapeFrame (RootlessFrameID wid, RegionPtr pShape);
+
+void
+winMWExtWMUnmapFrame (RootlessFrameID wid);
+
+void
+winMWExtWMStartDrawing (RootlessFrameID wid, char **pixelData, int *bytesPerRow);
+
+void
+winMWExtWMStopDrawing (RootlessFrameID wid, Bool flush);
+
+void
+winMWExtWMUpdateRegion (RootlessFrameID wid, RegionPtr pDamage);
+
+void
+winMWExtWMDamageRects (RootlessFrameID wid, int count, const BoxRec *rects,
+ int shift_x, int shift_y);
+
+void
+winMWExtWMRootlessSwitchWindow (RootlessWindowPtr pFrame, WindowPtr oldWin);
+
+void
+winMWExtWMCopyBytes (unsigned int width, unsigned int height,
+ const void *src, unsigned int srcRowBytes,
+ void *dst, unsigned int dstRowBytes);
+
+void
+winMWExtWMCopyWindow (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
+ int dx, int dy);
+#endif
+
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+/*
+ * winwin32rootlesswindow.c
+ */
+
+void
+winMWExtWMReorderWindows (ScreenPtr pScreen);
+
+void
+winMWExtWMMoveXWindow (WindowPtr pWin, int x, int y);
+
+void
+winMWExtWMResizeXWindow (WindowPtr pWin, int w, int h);
+
+void
+winMWExtWMMoveResizeXWindow (WindowPtr pWin, int x, int y, int w, int h);
+
+void
+winMWExtWMUpdateIcon (Window id);
+
+void
+winMWExtWMUpdateWindowDecoration (win32RootlessWindowPtr pRLWinPriv,
+ winScreenInfoPtr pScreenInfo);
+
+wBOOL CALLBACK
+winMWExtWMDecorateWindow (HWND hwnd, LPARAM lParam);
+
+Bool
+winIsInternalWMRunning (winScreenInfoPtr pScreenInfo);
+
+void
+winMWExtWMRestackWindows (ScreenPtr pScreen);
+#endif
+
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+/*
+ * winwin32rootlesswndproc.c
+ */
+
+LRESULT CALLBACK
+winMWExtWMWindowProc (HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam);
+#endif
+
+
+/*
+ * winwindowswm.c
+ */
+
+void
+winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg,
+ Window window, int x, int y, int w, int h);
+
+void
+winWindowsWMExtensionInit (void);
+
+/*
+ * wincursor.c
+ */
+
+Bool
+winInitCursor (ScreenPtr pScreen);
+
+/*
+ * winprocarg.c
+ */
+void
+winInitializeScreens(int maxscreens);
+
+/*
+ * winrandr.c
+ */
+Bool
+winRandRInit (ScreenPtr pScreen);
+void
+winDoRandRScreenSetSize (ScreenPtr pScreen,
+ CARD16 width,
+ CARD16 height,
+ CARD32 mmWidth,
+ CARD32 mmHeight);
+
+/*
+ * END DDX and DIX Function Prototypes
+ */
+
+#endif /* _WIN_H_ */
+
diff --git a/xorg-server/hw/xwin/wincreatewnd.c b/xorg-server/hw/xwin/wincreatewnd.c
index 0c342e1ae..755373965 100644
--- a/xorg-server/hw/xwin/wincreatewnd.c
+++ b/xorg-server/hw/xwin/wincreatewnd.c
@@ -192,7 +192,7 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen)
fForceShowWindow = TRUE;
}
dwWindowStyle |= WS_CAPTION;
- if (pScreenInfo->fScrollbars)
+ if (pScreenInfo->iResizeMode != notAllowed)
dwWindowStyle |= WS_THICKFRAME | WS_MAXIMIZEBOX;
}
else
@@ -233,6 +233,22 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen)
iPosY = rcWorkArea.top;
}
+ /* Clean up the scrollbars flag, if necessary */
+ if ((!pScreenInfo->fDecoration
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || pScreenInfo->fMWExtWM
+#endif
+ || pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOW
+ || pScreenInfo->fMultiWindow
+#endif
+ )
+ && (pScreenInfo->iResizeMode == resizeWithScrollbars))
+ {
+ /* We cannot have scrollbars if we do not have a window border */
+ pScreenInfo->iResizeMode = notAllowed;
+ }
+
/* Did the user specify a height and width? */
if (pScreenInfo->fUserGaveHeightAndWidth)
{
@@ -256,12 +272,12 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen)
#if CYGDEBUG
winDebug ("winCreateBoundingWindowWindowed - Window has decoration\n");
#endif
- /* Are we using scrollbars? */
- if (pScreenInfo->fScrollbars)
+
+ /* Are we resizable */
+ if (pScreenInfo->iResizeMode != notAllowed)
{
#if CYGDEBUG
- winDebug ("winCreateBoundingWindowWindowed - Window has "
- "scrollbars\n");
+ winDebug ("winCreateBoundingWindowWindowed - Window is resizable\n");
#endif
iWidth += 2 * GetSystemMetrics (SM_CXSIZEFRAME);
@@ -271,8 +287,7 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen)
else
{
#if CYGDEBUG
- winDebug ("winCreateBoundingWindowWindowed - Window does not have "
- "scrollbars\n");
+ winDebug ("winCreateBoundingWindowWindowed - Window is not resizable\n");
#endif
iWidth += 2 * GetSystemMetrics (SM_CXFIXEDFRAME);
@@ -296,22 +311,7 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen)
}
}
- /* Clean up the scrollbars flag, if necessary */
- if ((!pScreenInfo->fDecoration
-#ifdef XWIN_MULTIWINDOWEXTWM
- || pScreenInfo->fMWExtWM
-#endif
- || pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOW
- || pScreenInfo->fMultiWindow
-#endif
- )
- && pScreenInfo->fScrollbars)
- {
- /* We cannot have scrollbars if we do not have a window border */
- pScreenInfo->fScrollbars = FALSE;
- }
-
+ /* Make sure window is no bigger than work area */
if (TRUE
#ifdef XWIN_MULTIWINDOWEXTWM
&& !pScreenInfo->fMWExtWM
@@ -396,7 +396,7 @@ winCreateBoundingWindowWindowed (ScreenPtr pScreen)
rcClient.bottom, rcClient.top);
/* We adjust the visual size if the user did not specify it */
- if (!(pScreenInfo->fScrollbars && pScreenInfo->fUserGaveHeightAndWidth))
+ if (!((pScreenInfo->iResizeMode == resizeWithScrollbars) && pScreenInfo->fUserGaveHeightAndWidth))
{
/*
* User did not give a height and width with scrollbars enabled,
diff --git a/xorg-server/hw/xwin/windialogs.c b/xorg-server/hw/xwin/windialogs.c
index 8c648e84a..c3a149762 100644
--- a/xorg-server/hw/xwin/windialogs.c
+++ b/xorg-server/hw/xwin/windialogs.c
@@ -1,774 +1,773 @@
-/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II 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 Harold L Hunt II
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from Harold L Hunt II.
- *
- * Authors: Harold L Hunt II
- * Earle F. Philhower III
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#ifdef __CYGWIN__
-#include <sys/cygwin.h>
-#endif
-#include <shellapi.h>
-#include "winprefs.h"
-
-
-/*
- * References to external globals
- */
-
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fClipboardStarted;
-#endif
-/*
- * Local function prototypes
- */
-
-static wBOOL CALLBACK
-winExitDlgProc (HWND hDialog, UINT message,
- WPARAM wParam, LPARAM lParam);
-
-static wBOOL CALLBACK
-winChangeDepthDlgProc (HWND hDialog, UINT message,
- WPARAM wParam, LPARAM lParam);
-
-static wBOOL CALLBACK
-winAboutDlgProc (HWND hDialog, UINT message,
- WPARAM wParam, LPARAM lParam);
-
-
-static void
-winDrawURLWindow (LPARAM lParam);
-
-static LRESULT CALLBACK
-winURLWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
-
-static void
-winOverrideURLButton (HWND hdlg, int id);
-
-static void
-winUnoverrideURLButton (HWND hdlg, int id);
-
-
-/*
- * Owner-draw a button as a URL
- */
-
-static void
-winDrawURLWindow (LPARAM lParam)
-{
- DRAWITEMSTRUCT *draw;
- char str[256];
- RECT rect;
- HFONT font;
- COLORREF crText;
-
- draw = (DRAWITEMSTRUCT *) lParam;
- GetWindowText (draw->hwndItem, str, sizeof(str));
- str[255] = 0;
- GetClientRect (draw->hwndItem, &rect);
-
- /* Color the button depending upon its state */
- if (draw->itemState & ODS_SELECTED)
- crText = RGB(128+64,0,0);
- else if (draw->itemState & ODS_FOCUS)
- crText = RGB(0,128+64,0);
- else
- crText = RGB(0,0,128+64);
- SetTextColor (draw->hDC, crText);
-
- /* Create font 8 high, standard dialog font */
- font = CreateFont (-8, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
- 0, 0, 0, 0, 0, "MS Sans Serif");
- if (!font)
- {
- ErrorF ("winDrawURLWindow: Unable to create URL font, bailing.\n");
- return;
- }
- /* Draw it */
- SetBkMode (draw->hDC, OPAQUE);
- SelectObject (draw->hDC, font);
- DrawText (draw->hDC, str, strlen (str),&rect,DT_CENTER | DT_VCENTER);
- /* Delete the created font, replace it with stock font */
- DeleteObject (SelectObject (draw->hDC, GetStockObject (ANSI_VAR_FONT)));
-}
-
-
-/*
- * WndProc for overridden buttons
- */
-
-static LRESULT CALLBACK
-winURLWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
-{
- WNDPROC origCB = NULL;
- HCURSOR cursor;
-
- /* If it's a SetCursor message, tell it to the hand */
- if (msg==WM_SETCURSOR) {
- cursor = LoadCursor (NULL, IDC_HAND);
- if (cursor)
- SetCursor (cursor);
- return TRUE;
- }
- origCB = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA);
- /* Otherwise fall through to original WndProc */
- if (origCB)
- return CallWindowProc (origCB, hwnd, msg, wParam, lParam);
- else
- return FALSE;
-}
-
-
-/*
- * Register and unregister the custom WndProc
- */
-
-static void
-winOverrideURLButton (HWND hwnd, int id)
-{
- WNDPROC origCB;
- origCB = (WNDPROC)SetWindowLongPtr(GetDlgItem (hwnd, id),
- GWLP_WNDPROC, (LONG_PTR)winURLWndProc);
- SetWindowLongPtr(GetDlgItem (hwnd, id), GWLP_USERDATA, (LONG_PTR)origCB);
-}
-
-static void
-winUnoverrideURLButton (HWND hwnd, int id)
-{
- WNDPROC origCB;
- origCB = (WNDPROC)SetWindowLongPtr(GetDlgItem (hwnd, id),
- GWLP_USERDATA, 0);
- if (origCB)
- SetWindowLongPtr(GetDlgItem (hwnd, id), GWLP_WNDPROC, (LONG_PTR)origCB);
-}
-
-
-/*
- * Center a dialog window in the desktop window
- * and set small and large icons to X icons.
- */
-
-static void
-winInitDialog (HWND hwndDlg)
-{
- HWND hwndDesk;
- RECT rc, rcDlg, rcDesk;
- HICON hIcon, hIconSmall;
-
- hwndDesk = GetParent (hwndDlg);
- if (!hwndDesk || IsIconic (hwndDesk))
- hwndDesk = GetDesktopWindow ();
-
- /* Remove minimize and maximize buttons */
- SetWindowLongPtr(hwndDlg, GWL_STYLE,
- GetWindowLongPtr(hwndDlg, GWL_STYLE)
- & ~(WS_MAXIMIZEBOX | WS_MINIMIZEBOX));
-
- /* Set Window not to show in the task bar */
- SetWindowLongPtr(hwndDlg, GWL_EXSTYLE,
- GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_APPWINDOW );
-
- /* Center dialog window in the screen. Not done for multi-monitor systems, where
- * it is likely to end up split across the screens. In that case, it appears
- * near the Tray icon.
- */
- if (GetSystemMetrics(SM_CMONITORS)>1) {
- /* Still need to refresh the frame change. */
- SetWindowPos (hwndDlg, HWND_TOPMOST, 0,0,0,0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
- } else {
- GetWindowRect (hwndDesk, &rcDesk);
- GetWindowRect (hwndDlg, &rcDlg);
- CopyRect (&rc, &rcDesk);
-
- OffsetRect (&rcDlg, -rcDlg.left, -rcDlg.top);
- OffsetRect (&rc, -rc.left, -rc.top);
- OffsetRect (&rc, -rcDlg.right, -rcDlg.bottom);
-
- SetWindowPos (hwndDlg,
- HWND_TOPMOST,
- rcDesk.left + (rc.right / 2),
- rcDesk.top + (rc.bottom / 2),
- 0, 0,
- SWP_NOSIZE | SWP_FRAMECHANGED);
- }
-
-#ifdef XWIN_MULTIWINDOW
- if (g_hIconX) hIcon=g_hIconX;
- else
-#endif
- hIcon = LoadIcon (g_hInstance, MAKEINTRESOURCE(IDI_XWIN));
-
-#ifdef XWIN_MULTIWINDOW
- if (g_hSmallIconX) hIconSmall=g_hSmallIconX;
- else
-#endif
- hIconSmall = LoadImage (g_hInstance,
- MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON),
- GetSystemMetrics(SM_CYSMICON),
- LR_SHARED);
-
- PostMessage (hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
- PostMessage (hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
-}
-
-
-/*
- * Display the Exit dialog box
- */
-
-void
-winDisplayExitDialog (winPrivScreenPtr pScreenPriv)
-{
- int i;
- int liveClients = 0;
-
- /* Count up running clients (clients[0] is serverClient) */
- for (i = 1; i < currentMaxClients; i++)
- if (clients[i] != NullClient)
- liveClients++;
-#if defined(XWIN_MULTIWINDOW)
- /* Count down server internal clients */
- if (pScreenPriv->pScreenInfo->fMultiWindow)
- liveClients -= 2; /* multiwindow window manager & XMsgProc */
-#endif
-#if defined(XWIN_CLIPBOARD)
- if (g_fClipboardStarted)
- liveClients--; /* clipboard manager */
-#endif
-
- /* A user reported that this sometimes drops below zero. just eye-candy. */
- if (liveClients < 0)
- liveClients = 0;
-
- /* Don't show the exit confirmation dialog if SilentExit & no clients,
- or ForceExit, is enabled */
- if ((pref.fSilentExit && liveClients <= 0) || pref.fForceExit)
- {
- if (g_hDlgExit != NULL)
- {
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
- }
- PostMessage (pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
- return;
- }
-
- pScreenPriv->iConnectedClients = liveClients;
-
- /* Check if dialog already exists */
- if (g_hDlgExit != NULL)
- {
- /* Dialog box already exists, display it */
- ShowWindow (g_hDlgExit, SW_SHOWDEFAULT);
-
- /* User has lost the dialog. Show them where it is. */
- SetForegroundWindow (g_hDlgExit);
-
- return;
- }
-
- /* Create dialog box */
- g_hDlgExit = CreateDialogParam (g_hInstance,
- "EXIT_DIALOG",
- pScreenPriv->hwndScreen,
- winExitDlgProc,
- (int) pScreenPriv);
-
- /* Show the dialog box */
- ShowWindow (g_hDlgExit, SW_SHOW);
-
- /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
- SetForegroundWindow (g_hDlgExit);
-
- /* Set focus to the Cancel button */
- PostMessage (g_hDlgExit, WM_NEXTDLGCTL,
- (WPARAM)GetDlgItem (g_hDlgExit, IDCANCEL), TRUE);
-}
-
-#define CONNECTED_CLIENTS_FORMAT "There %s currently %d client%s connected."
-
-
-/*
- * Exit dialog window procedure
- */
-
-static wBOOL CALLBACK
-winExitDlgProc (HWND hDialog, UINT message,
- WPARAM wParam, LPARAM lParam)
-{
- static winPrivScreenPtr s_pScreenPriv = NULL;
-
- /* Branch on message type */
- switch (message)
- {
- case WM_INITDIALOG:
- {
- char *pszConnectedClients;
-
- /* Store pointers to private structures for future use */
- s_pScreenPriv = (winPrivScreenPtr) lParam;
-
- winInitDialog (hDialog);
-
- /* Format the connected clients string */
- if (asprintf (&pszConnectedClients, CONNECTED_CLIENTS_FORMAT,
- (s_pScreenPriv->iConnectedClients == 1) ? "is" : "are",
- s_pScreenPriv->iConnectedClients,
- (s_pScreenPriv->iConnectedClients == 1) ? "" : "s") == -1)
- return TRUE;
-
-
-
- /* Set the number of connected clients */
- SetWindowText (GetDlgItem (hDialog, IDC_CLIENTS_CONNECTED),
- pszConnectedClients);
- free(pszConnectedClients);
- }
- return TRUE;
-
- case WM_COMMAND:
- switch (LOWORD (wParam))
- {
- case IDOK:
- /* Send message to call the GiveUp function */
- PostMessage (s_pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
-
- /* Fix to make sure keyboard focus isn't trapped */
- PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
- return TRUE;
-
- case IDCANCEL:
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
-
- /* Fix to make sure keyboard focus isn't trapped */
- PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
- return TRUE;
- }
- break;
-
- case WM_MOUSEMOVE:
- case WM_NCMOUSEMOVE:
- /* Show the cursor if it is hidden */
- if (g_fSoftwareCursor && !g_fCursor)
- {
- g_fCursor = TRUE;
- ShowCursor (TRUE);
- }
- return TRUE;
-
- case WM_CLOSE:
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
-
- /* Fix to make sure keyboard focus isn't trapped */
- PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/*
- * Display the Depth Change dialog box
- */
-
-void
-winDisplayDepthChangeDialog (winPrivScreenPtr pScreenPriv)
-{
- /* Check if dialog already exists */
- if (g_hDlgDepthChange != NULL)
- {
- /* Dialog box already exists, display it */
- ShowWindow (g_hDlgDepthChange, SW_SHOWDEFAULT);
-
- /* User has lost the dialog. Show them where it is. */
- SetForegroundWindow (g_hDlgDepthChange);
-
- return;
- }
-
- /*
- * Display a notification to the user that the visual
- * will not be displayed until the Windows display depth
- * is restored to the original value.
- */
- g_hDlgDepthChange = CreateDialogParam (g_hInstance,
- "DEPTH_CHANGE_BOX",
- pScreenPriv->hwndScreen,
- winChangeDepthDlgProc,
- (int) pScreenPriv);
- /* Show the dialog box */
- ShowWindow (g_hDlgDepthChange, SW_SHOW);
-
- ErrorF ("winDisplayDepthChangeDialog - DialogBox returned: %d\n",
- (int) g_hDlgDepthChange);
- ErrorF ("winDisplayDepthChangeDialog - GetLastError: %d\n",
- (int) GetLastError ());
-
- /* Minimize the display window */
- ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE);
-}
-
-
-/*
- * Process messages for the dialog that is displayed for
- * disruptive screen depth changes.
- */
-
-static wBOOL CALLBACK
-winChangeDepthDlgProc (HWND hwndDialog, UINT message,
- WPARAM wParam, LPARAM lParam)
-{
- static winPrivScreenPtr s_pScreenPriv = NULL;
- static winScreenInfo *s_pScreenInfo = NULL;
- static ScreenPtr s_pScreen = NULL;
-
-#if CYGDEBUG
- winDebug ("winChangeDepthDlgProc\n");
-#endif
-
- /* Branch on message type */
- switch (message)
- {
- case WM_INITDIALOG:
-#if CYGDEBUG
- winDebug ("winChangeDepthDlgProc - WM_INITDIALOG\n");
-#endif
-
- /* Store pointers to private structures for future use */
- s_pScreenPriv = (winPrivScreenPtr) lParam;
- s_pScreenInfo = s_pScreenPriv->pScreenInfo;
- s_pScreen = s_pScreenInfo->pScreen;
-
-#if CYGDEBUG
- winDebug ("winChangeDepthDlgProc - WM_INITDIALOG - s_pScreenPriv: %08x, "
- "s_pScreenInfo: %08x, s_pScreen: %08x\n",
- s_pScreenPriv, s_pScreenInfo, s_pScreen);
-#endif
-
-#if CYGDEBUG
- winDebug ("winChangeDepthDlgProc - WM_INITDIALOG - orig bpp: %d, "
- "last bpp: %d\n",
- s_pScreenInfo->dwBPP,
- s_pScreenPriv->dwLastWindowsBitsPixel);
-#endif
-
- winInitDialog( hwndDialog );
-
- return TRUE;
-
- case WM_DISPLAYCHANGE:
-#if CYGDEBUG
- winDebug ("winChangeDepthDlgProc - WM_DISPLAYCHANGE - orig bpp: %d, "
- "last bpp: %d, new bpp: %d\n",
- s_pScreenInfo->dwBPP,
- s_pScreenPriv->dwLastWindowsBitsPixel,
- wParam);
-#endif
-
- /* Dismiss the dialog if the display returns to the original depth */
- if (wParam == s_pScreenInfo->dwBPP)
- {
- ErrorF ("winChangeDelthDlgProc - wParam == s_pScreenInfo->dwBPP\n");
-
- /* Depth has been restored, dismiss dialog */
- DestroyWindow (g_hDlgDepthChange);
- g_hDlgDepthChange = NULL;
-
- /* Flag that we have a valid screen depth */
- s_pScreenPriv->fBadDepth = FALSE;
- }
- return TRUE;
-
- case WM_COMMAND:
- switch (LOWORD (wParam))
- {
- case IDOK:
- case IDCANCEL:
- ErrorF ("winChangeDepthDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
-
- /*
- * User dismissed the dialog, hide it until the
- * display mode is restored.
- */
- ShowWindow (g_hDlgDepthChange, SW_HIDE);
- return TRUE;
- }
- break;
-
- case WM_CLOSE:
- ErrorF ("winChangeDepthDlgProc - WM_CLOSE\n");
-
- DestroyWindow (g_hDlgAbout);
- g_hDlgAbout = NULL;
-
- /* Fix to make sure keyboard focus isn't trapped */
- PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/*
- * Display the About dialog box
- */
-
-void
-winDisplayAboutDialog (winPrivScreenPtr pScreenPriv)
-{
- /* Check if dialog already exists */
- if (g_hDlgAbout != NULL)
- {
- /* Dialog box already exists, display it */
- ShowWindow (g_hDlgAbout, SW_SHOWDEFAULT);
-
- /* User has lost the dialog. Show them where it is. */
- SetForegroundWindow (g_hDlgAbout);
-
- return;
- }
-
- /*
- * Display the about box
- */
- g_hDlgAbout = CreateDialogParam (g_hInstance,
- "ABOUT_BOX",
- pScreenPriv->hwndScreen,
- winAboutDlgProc,
- (int) pScreenPriv);
-
- /* Show the dialog box */
- ShowWindow (g_hDlgAbout, SW_SHOW);
-
- /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
- SetForegroundWindow (g_hDlgAbout);
-
- /* Set focus to the OK button */
- PostMessage (g_hDlgAbout, WM_NEXTDLGCTL,
- (WPARAM)GetDlgItem (g_hDlgAbout, IDOK), TRUE);
-}
-
-
-/*
- * Process messages for the about dialog.
- */
-
-static wBOOL CALLBACK
-winAboutDlgProc (HWND hwndDialog, UINT message,
- WPARAM wParam, LPARAM lParam)
-{
- static winPrivScreenPtr s_pScreenPriv = NULL;
- static winScreenInfo *s_pScreenInfo = NULL;
- static ScreenPtr s_pScreen = NULL;
-
-#if CYGDEBUG
- winDebug ("winAboutDlgProc\n");
-#endif
-
- /* Branch on message type */
- switch (message)
- {
- case WM_INITDIALOG:
-#if CYGDEBUG
- winDebug ("winAboutDlgProc - WM_INITDIALOG\n");
-#endif
-
- /* Store pointers to private structures for future use */
- s_pScreenPriv = (winPrivScreenPtr) lParam;
- s_pScreenInfo = s_pScreenPriv->pScreenInfo;
- s_pScreen = s_pScreenInfo->pScreen;
-
- winInitDialog (hwndDialog);
-
- /* Override the URL buttons */
- winOverrideURLButton (hwndDialog, ID_ABOUT_CHANGELOG);
- winOverrideURLButton (hwndDialog, ID_ABOUT_WEBSITE);
- winOverrideURLButton (hwndDialog, ID_ABOUT_UG);
- winOverrideURLButton (hwndDialog, ID_ABOUT_FAQ);
-
- return TRUE;
-
- case WM_DRAWITEM:
- /* Draw the URL buttons as needed */
- winDrawURLWindow (lParam);
- return TRUE;
-
- case WM_MOUSEMOVE:
- case WM_NCMOUSEMOVE:
- /* Show the cursor if it is hidden */
- if (g_fSoftwareCursor && !g_fCursor)
- {
- g_fCursor = TRUE;
- ShowCursor (TRUE);
- }
- return TRUE;
-
- case WM_COMMAND:
- switch (LOWORD (wParam))
- {
- case IDOK:
- case IDCANCEL:
- ErrorF ("winAboutDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
-
- DestroyWindow (g_hDlgAbout);
- g_hDlgAbout = NULL;
-
- /* Fix to make sure keyboard focus isn't trapped */
- PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
-
- /* Restore window procedures for URL buttons */
- winUnoverrideURLButton (hwndDialog, ID_ABOUT_CHANGELOG);
- winUnoverrideURLButton (hwndDialog, ID_ABOUT_WEBSITE);
- winUnoverrideURLButton (hwndDialog, ID_ABOUT_UG);
- winUnoverrideURLButton (hwndDialog, ID_ABOUT_FAQ);
-
- return TRUE;
-
- case ID_ABOUT_CHANGELOG:
- {
- int iReturn;
-#ifdef __CYGWIN__
- const char * pszCygPath = "/usr/X11R6/share/doc/"
- "xorg-x11-xwin/changelog.html";
- char pszWinPath[MAX_PATH + 1];
-
- /* Convert the POSIX path to a Win32 path */
- cygwin_conv_to_win32_path (pszCygPath, pszWinPath);
-#else
- const char * pszWinPath = "http://x.cygwin.com/"
- "devel/server/changelog.html";
-#endif
-
- iReturn = (int)ShellExecute (NULL,
- "open",
- pszWinPath,
- NULL,
- NULL,
- SW_MAXIMIZE);
- if (iReturn < 32)
- {
- ErrorF ("winAboutDlgProc - WM_COMMAND - ID_ABOUT_CHANGELOG - "
- "ShellExecute failed: %d\n",
- iReturn);
- }
- }
- return TRUE;
-
- case ID_ABOUT_WEBSITE:
- {
- const char * pszPath = __VENDORDWEBSUPPORT__;
- int iReturn;
-
- iReturn = (int)ShellExecute (NULL,
- "open",
- pszPath,
- NULL,
- NULL,
- SW_MAXIMIZE);
- if (iReturn < 32)
- {
- ErrorF ("winAboutDlgProc - WM_COMMAND - ID_ABOUT_WEBSITE - "
- "ShellExecute failed: %d\n",
- iReturn);
- }
- }
- return TRUE;
-
- case ID_ABOUT_UG:
- {
- const char * pszPath = "http://x.cygwin.com/docs/ug/";
- int iReturn;
-
- iReturn = (int)ShellExecute (NULL,
- "open",
- pszPath,
- NULL,
- NULL,
- SW_MAXIMIZE);
- if (iReturn < 32)
- {
- ErrorF ("winAboutDlgProc - WM_COMMAND - ID_ABOUT_UG - "
- "ShellExecute failed: %d\n",
- iReturn);
- }
- }
- return TRUE;
-
- case ID_ABOUT_FAQ:
- {
- const char * pszPath = "http://x.cygwin.com/docs/faq/";
- int iReturn;
-
- iReturn = (int)ShellExecute (NULL,
- "open",
- pszPath,
- NULL,
- NULL,
- SW_MAXIMIZE);
- if (iReturn < 32)
- {
- ErrorF ("winAboutDlgProc - WM_COMMAND - ID_ABOUT_FAQ - "
- "ShellExecute failed: %d\n",
- iReturn);
- }
- }
- return TRUE;
- }
- break;
-
- case WM_CLOSE:
- ErrorF ("winAboutDlgProc - WM_CLOSE\n");
-
- DestroyWindow (g_hDlgAbout);
- g_hDlgAbout = NULL;
-
- /* Fix to make sure keyboard focus isn't trapped */
- PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
-
- /* Restore window procedures for URL buttons */
- winUnoverrideURLButton (hwndDialog, ID_ABOUT_CHANGELOG);
- winUnoverrideURLButton (hwndDialog, ID_ABOUT_WEBSITE);
- winUnoverrideURLButton (hwndDialog, ID_ABOUT_UG);
- winUnoverrideURLButton (hwndDialog, ID_ABOUT_FAQ);
-
- return TRUE;
- }
-
- return FALSE;
-}
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II 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 Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors: Harold L Hunt II
+ * Earle F. Philhower III
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+#endif
+#include <shellapi.h>
+#include "winprefs.h"
+
+
+/*
+ * References to external globals
+ */
+
+#ifdef XWIN_CLIPBOARD
+extern Bool g_fClipboardStarted;
+#endif
+/*
+ * Local function prototypes
+ */
+
+static wBOOL CALLBACK
+winExitDlgProc (HWND hDialog, UINT message,
+ WPARAM wParam, LPARAM lParam);
+
+static wBOOL CALLBACK
+winChangeDepthDlgProc (HWND hDialog, UINT message,
+ WPARAM wParam, LPARAM lParam);
+
+static wBOOL CALLBACK
+winAboutDlgProc (HWND hDialog, UINT message,
+ WPARAM wParam, LPARAM lParam);
+
+
+static void
+winDrawURLWindow (LPARAM lParam);
+
+static LRESULT CALLBACK
+winURLWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static void
+winOverrideURLButton (HWND hdlg, int id);
+
+static void
+winUnoverrideURLButton (HWND hdlg, int id);
+
+
+/*
+ * Owner-draw a button as a URL
+ */
+
+static void
+winDrawURLWindow (LPARAM lParam)
+{
+ DRAWITEMSTRUCT *draw;
+ char str[256];
+ RECT rect;
+ HFONT font;
+ COLORREF crText;
+
+ draw = (DRAWITEMSTRUCT *) lParam;
+ GetWindowText (draw->hwndItem, str, sizeof(str));
+ str[255] = 0;
+ GetClientRect (draw->hwndItem, &rect);
+
+ /* Color the button depending upon its state */
+ if (draw->itemState & ODS_SELECTED)
+ crText = RGB(128+64,0,0);
+ else if (draw->itemState & ODS_FOCUS)
+ crText = RGB(0,128+64,0);
+ else
+ crText = RGB(0,0,128+64);
+ SetTextColor (draw->hDC, crText);
+
+ /* Create font 8 high, standard dialog font */
+ font = CreateFont (-8, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
+ 0, 0, 0, 0, 0, "MS Sans Serif");
+ if (!font)
+ {
+ ErrorF ("winDrawURLWindow: Unable to create URL font, bailing.\n");
+ return;
+ }
+ /* Draw it */
+ SetBkMode (draw->hDC, OPAQUE);
+ SelectObject (draw->hDC, font);
+ DrawText (draw->hDC, str, strlen (str),&rect,DT_CENTER | DT_VCENTER);
+ /* Delete the created font, replace it with stock font */
+ DeleteObject (SelectObject (draw->hDC, GetStockObject (ANSI_VAR_FONT)));
+}
+
+
+/*
+ * WndProc for overridden buttons
+ */
+
+static LRESULT CALLBACK
+winURLWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC origCB = NULL;
+ HCURSOR cursor;
+
+ /* If it's a SetCursor message, tell it to the hand */
+ if (msg==WM_SETCURSOR) {
+ cursor = LoadCursor (NULL, IDC_HAND);
+ if (cursor)
+ SetCursor (cursor);
+ return TRUE;
+ }
+ origCB = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ /* Otherwise fall through to original WndProc */
+ if (origCB)
+ return CallWindowProc (origCB, hwnd, msg, wParam, lParam);
+ else
+ return FALSE;
+}
+
+
+/*
+ * Register and unregister the custom WndProc
+ */
+
+static void
+winOverrideURLButton (HWND hwnd, int id)
+{
+ WNDPROC origCB;
+ origCB = (WNDPROC)SetWindowLongPtr(GetDlgItem (hwnd, id),
+ GWLP_WNDPROC, (LONG_PTR)winURLWndProc);
+ SetWindowLongPtr(GetDlgItem (hwnd, id), GWLP_USERDATA, (LONG_PTR)origCB);
+}
+
+static void
+winUnoverrideURLButton (HWND hwnd, int id)
+{
+ WNDPROC origCB;
+ origCB = (WNDPROC)SetWindowLongPtr(GetDlgItem (hwnd, id),
+ GWLP_USERDATA, 0);
+ if (origCB)
+ SetWindowLongPtr(GetDlgItem (hwnd, id), GWLP_WNDPROC, (LONG_PTR)origCB);
+}
+
+
+/*
+ * Center a dialog window in the desktop window
+ * and set small and large icons to X icons.
+ */
+
+static void
+winInitDialog (HWND hwndDlg)
+{
+ HWND hwndDesk;
+ RECT rc, rcDlg, rcDesk;
+ HICON hIcon, hIconSmall;
+
+ hwndDesk = GetParent (hwndDlg);
+ if (!hwndDesk || IsIconic (hwndDesk))
+ hwndDesk = GetDesktopWindow ();
+
+ /* Remove minimize and maximize buttons */
+ SetWindowLongPtr(hwndDlg, GWL_STYLE,
+ GetWindowLongPtr(hwndDlg, GWL_STYLE)
+ & ~(WS_MAXIMIZEBOX | WS_MINIMIZEBOX));
+
+ /* Set Window not to show in the task bar */
+ SetWindowLongPtr(hwndDlg, GWL_EXSTYLE,
+ GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) & ~WS_EX_APPWINDOW );
+
+ /* Center dialog window in the screen. Not done for multi-monitor systems, where
+ * it is likely to end up split across the screens. In that case, it appears
+ * near the Tray icon.
+ */
+ if (GetSystemMetrics(SM_CMONITORS)>1) {
+ /* Still need to refresh the frame change. */
+ SetWindowPos (hwndDlg, HWND_TOPMOST, 0,0,0,0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
+ } else {
+ GetWindowRect (hwndDesk, &rcDesk);
+ GetWindowRect (hwndDlg, &rcDlg);
+ CopyRect (&rc, &rcDesk);
+
+ OffsetRect (&rcDlg, -rcDlg.left, -rcDlg.top);
+ OffsetRect (&rc, -rc.left, -rc.top);
+ OffsetRect (&rc, -rcDlg.right, -rcDlg.bottom);
+
+ SetWindowPos (hwndDlg,
+ HWND_TOPMOST,
+ rcDesk.left + (rc.right / 2),
+ rcDesk.top + (rc.bottom / 2),
+ 0, 0,
+ SWP_NOSIZE | SWP_FRAMECHANGED);
+ }
+
+#ifdef XWIN_MULTIWINDOW
+ if (g_hIconX) hIcon=g_hIconX;
+ else
+#endif
+ hIcon = LoadIcon (g_hInstance, MAKEINTRESOURCE(IDI_XWIN));
+
+#ifdef XWIN_MULTIWINDOW
+ if (g_hSmallIconX) hIconSmall=g_hSmallIconX;
+ else
+#endif
+ hIconSmall = LoadImage (g_hInstance,
+ MAKEINTRESOURCE(IDI_XWIN), IMAGE_ICON,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON),
+ LR_SHARED);
+
+ PostMessage (hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
+ PostMessage (hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
+}
+
+
+/*
+ * Display the Exit dialog box
+ */
+
+void
+winDisplayExitDialog (winPrivScreenPtr pScreenPriv)
+{
+ int i;
+ int liveClients = 0;
+
+ /* Count up running clients (clients[0] is serverClient) */
+ for (i = 1; i < currentMaxClients; i++)
+ if (clients[i] != NullClient)
+ liveClients++;
+#if defined(XWIN_MULTIWINDOW)
+ /* Count down server internal clients */
+ if (pScreenPriv->pScreenInfo->fMultiWindow)
+ liveClients -= 2; /* multiwindow window manager & XMsgProc */
+#endif
+#if defined(XWIN_CLIPBOARD)
+ if (g_fClipboardStarted)
+ liveClients--; /* clipboard manager */
+#endif
+
+ /* A user reported that this sometimes drops below zero. just eye-candy. */
+ if (liveClients < 0)
+ liveClients = 0;
+
+ /* Don't show the exit confirmation dialog if SilentExit & no clients,
+ or ForceExit, is enabled */
+ if ((pref.fSilentExit && liveClients <= 0) || pref.fForceExit)
+ {
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+ PostMessage (pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
+ return;
+ }
+
+ pScreenPriv->iConnectedClients = liveClients;
+
+ /* Check if dialog already exists */
+ if (g_hDlgExit != NULL)
+ {
+ /* Dialog box already exists, display it */
+ ShowWindow (g_hDlgExit, SW_SHOWDEFAULT);
+
+ /* User has lost the dialog. Show them where it is. */
+ SetForegroundWindow (g_hDlgExit);
+
+ return;
+ }
+
+ /* Create dialog box */
+ g_hDlgExit = CreateDialogParam (g_hInstance,
+ "EXIT_DIALOG",
+ pScreenPriv->hwndScreen,
+ winExitDlgProc,
+ (int) pScreenPriv);
+
+ /* Show the dialog box */
+ ShowWindow (g_hDlgExit, SW_SHOW);
+
+ /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
+ SetForegroundWindow (g_hDlgExit);
+
+ /* Set focus to the Cancel button */
+ PostMessage (g_hDlgExit, WM_NEXTDLGCTL,
+ (WPARAM)GetDlgItem (g_hDlgExit, IDCANCEL), TRUE);
+}
+
+#define CONNECTED_CLIENTS_FORMAT "There %s currently %d client%s connected."
+
+
+/*
+ * Exit dialog window procedure
+ */
+
+static wBOOL CALLBACK
+winExitDlgProc (HWND hDialog, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ static winPrivScreenPtr s_pScreenPriv = NULL;
+
+ /* Branch on message type */
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ {
+ char *pszConnectedClients;
+
+ /* Store pointers to private structures for future use */
+ s_pScreenPriv = (winPrivScreenPtr) lParam;
+
+ winInitDialog (hDialog);
+
+ /* Format the connected clients string */
+ if (asprintf (&pszConnectedClients, CONNECTED_CLIENTS_FORMAT,
+ (s_pScreenPriv->iConnectedClients == 1) ? "is" : "are",
+ s_pScreenPriv->iConnectedClients,
+ (s_pScreenPriv->iConnectedClients == 1) ? "" : "s") == -1)
+ return TRUE;
+
+
+
+ /* Set the number of connected clients */
+ SetWindowText (GetDlgItem (hDialog, IDC_CLIENTS_CONNECTED),
+ pszConnectedClients);
+ free(pszConnectedClients);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case IDOK:
+ /* Send message to call the GiveUp function */
+ PostMessage (s_pScreenPriv->hwndScreen, WM_GIVEUP, 0, 0);
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+
+ /* Fix to make sure keyboard focus isn't trapped */
+ PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
+ return TRUE;
+
+ case IDCANCEL:
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+
+ /* Fix to make sure keyboard focus isn't trapped */
+ PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
+ return TRUE;
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ case WM_NCMOUSEMOVE:
+ /* Show the cursor if it is hidden */
+ if (g_fSoftwareCursor && !g_fCursor)
+ {
+ g_fCursor = TRUE;
+ ShowCursor (TRUE);
+ }
+ return TRUE;
+
+ case WM_CLOSE:
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+
+ /* Fix to make sure keyboard focus isn't trapped */
+ PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Display the Depth Change dialog box
+ */
+
+void
+winDisplayDepthChangeDialog (winPrivScreenPtr pScreenPriv)
+{
+ /* Check if dialog already exists */
+ if (g_hDlgDepthChange != NULL)
+ {
+ /* Dialog box already exists, display it */
+ ShowWindow (g_hDlgDepthChange, SW_SHOWDEFAULT);
+
+ /* User has lost the dialog. Show them where it is. */
+ SetForegroundWindow (g_hDlgDepthChange);
+
+ return;
+ }
+
+ /*
+ * Display a notification to the user that the visual
+ * will not be displayed until the Windows display depth
+ * is restored to the original value.
+ */
+ g_hDlgDepthChange = CreateDialogParam (g_hInstance,
+ "DEPTH_CHANGE_BOX",
+ pScreenPriv->hwndScreen,
+ winChangeDepthDlgProc,
+ (int) pScreenPriv);
+ /* Show the dialog box */
+ ShowWindow (g_hDlgDepthChange, SW_SHOW);
+
+ ErrorF ("winDisplayDepthChangeDialog - DialogBox returned: %d\n",
+ (int) g_hDlgDepthChange);
+ ErrorF ("winDisplayDepthChangeDialog - GetLastError: %d\n",
+ (int) GetLastError ());
+
+ /* Minimize the display window */
+ ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE);
+}
+
+
+/*
+ * Process messages for the dialog that is displayed for
+ * disruptive screen depth changes.
+ */
+
+static wBOOL CALLBACK
+winChangeDepthDlgProc (HWND hwndDialog, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ static winPrivScreenPtr s_pScreenPriv = NULL;
+ static winScreenInfo *s_pScreenInfo = NULL;
+ static ScreenPtr s_pScreen = NULL;
+
+#if CYGDEBUG
+ winDebug ("winChangeDepthDlgProc\n");
+#endif
+
+ /* Branch on message type */
+ switch (message)
+ {
+ case WM_INITDIALOG:
+#if CYGDEBUG
+ winDebug ("winChangeDepthDlgProc - WM_INITDIALOG\n");
+#endif
+
+ /* Store pointers to private structures for future use */
+ s_pScreenPriv = (winPrivScreenPtr) lParam;
+ s_pScreenInfo = s_pScreenPriv->pScreenInfo;
+ s_pScreen = s_pScreenInfo->pScreen;
+
+#if CYGDEBUG
+ winDebug ("winChangeDepthDlgProc - WM_INITDIALOG - s_pScreenPriv: %08x, "
+ "s_pScreenInfo: %08x, s_pScreen: %08x\n",
+ s_pScreenPriv, s_pScreenInfo, s_pScreen);
+#endif
+
+#if CYGDEBUG
+ winDebug ("winChangeDepthDlgProc - WM_INITDIALOG - orig bpp: %d, "
+ "current bpp: %d\n",
+ s_pScreenInfo->dwBPP,
+ GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL));
+#endif
+
+ winInitDialog( hwndDialog );
+
+ return TRUE;
+
+ case WM_DISPLAYCHANGE:
+#if CYGDEBUG
+ winDebug ("winChangeDepthDlgProc - WM_DISPLAYCHANGE - orig bpp: %d, "
+ "new bpp: %d\n",
+ s_pScreenInfo->dwBPP,
+ GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL));
+#endif
+
+ /* Dismiss the dialog if the display returns to the original depth */
+ if (GetDeviceCaps(s_pScreenPriv->hdcScreen, BITSPIXEL) == s_pScreenInfo->dwBPP)
+ {
+ ErrorF ("winChangeDelthDlgProc - wParam == s_pScreenInfo->dwBPP\n");
+
+ /* Depth has been restored, dismiss dialog */
+ DestroyWindow (g_hDlgDepthChange);
+ g_hDlgDepthChange = NULL;
+
+ /* Flag that we have a valid screen depth */
+ s_pScreenPriv->fBadDepth = FALSE;
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case IDOK:
+ case IDCANCEL:
+ ErrorF ("winChangeDepthDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
+
+ /*
+ * User dismissed the dialog, hide it until the
+ * display mode is restored.
+ */
+ ShowWindow (g_hDlgDepthChange, SW_HIDE);
+ return TRUE;
+ }
+ break;
+
+ case WM_CLOSE:
+ ErrorF ("winChangeDepthDlgProc - WM_CLOSE\n");
+
+ DestroyWindow (g_hDlgAbout);
+ g_hDlgAbout = NULL;
+
+ /* Fix to make sure keyboard focus isn't trapped */
+ PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * Display the About dialog box
+ */
+
+void
+winDisplayAboutDialog (winPrivScreenPtr pScreenPriv)
+{
+ /* Check if dialog already exists */
+ if (g_hDlgAbout != NULL)
+ {
+ /* Dialog box already exists, display it */
+ ShowWindow (g_hDlgAbout, SW_SHOWDEFAULT);
+
+ /* User has lost the dialog. Show them where it is. */
+ SetForegroundWindow (g_hDlgAbout);
+
+ return;
+ }
+
+ /*
+ * Display the about box
+ */
+ g_hDlgAbout = CreateDialogParam (g_hInstance,
+ "ABOUT_BOX",
+ pScreenPriv->hwndScreen,
+ winAboutDlgProc,
+ (int) pScreenPriv);
+
+ /* Show the dialog box */
+ ShowWindow (g_hDlgAbout, SW_SHOW);
+
+ /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
+ SetForegroundWindow (g_hDlgAbout);
+
+ /* Set focus to the OK button */
+ PostMessage (g_hDlgAbout, WM_NEXTDLGCTL,
+ (WPARAM)GetDlgItem (g_hDlgAbout, IDOK), TRUE);
+}
+
+
+/*
+ * Process messages for the about dialog.
+ */
+
+static wBOOL CALLBACK
+winAboutDlgProc (HWND hwndDialog, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ static winPrivScreenPtr s_pScreenPriv = NULL;
+ static winScreenInfo *s_pScreenInfo = NULL;
+ static ScreenPtr s_pScreen = NULL;
+
+#if CYGDEBUG
+ winDebug ("winAboutDlgProc\n");
+#endif
+
+ /* Branch on message type */
+ switch (message)
+ {
+ case WM_INITDIALOG:
+#if CYGDEBUG
+ winDebug ("winAboutDlgProc - WM_INITDIALOG\n");
+#endif
+
+ /* Store pointers to private structures for future use */
+ s_pScreenPriv = (winPrivScreenPtr) lParam;
+ s_pScreenInfo = s_pScreenPriv->pScreenInfo;
+ s_pScreen = s_pScreenInfo->pScreen;
+
+ winInitDialog (hwndDialog);
+
+ /* Override the URL buttons */
+ winOverrideURLButton (hwndDialog, ID_ABOUT_CHANGELOG);
+ winOverrideURLButton (hwndDialog, ID_ABOUT_WEBSITE);
+ winOverrideURLButton (hwndDialog, ID_ABOUT_UG);
+ winOverrideURLButton (hwndDialog, ID_ABOUT_FAQ);
+
+ return TRUE;
+
+ case WM_DRAWITEM:
+ /* Draw the URL buttons as needed */
+ winDrawURLWindow (lParam);
+ return TRUE;
+
+ case WM_MOUSEMOVE:
+ case WM_NCMOUSEMOVE:
+ /* Show the cursor if it is hidden */
+ if (g_fSoftwareCursor && !g_fCursor)
+ {
+ g_fCursor = TRUE;
+ ShowCursor (TRUE);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case IDOK:
+ case IDCANCEL:
+ ErrorF ("winAboutDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
+
+ DestroyWindow (g_hDlgAbout);
+ g_hDlgAbout = NULL;
+
+ /* Fix to make sure keyboard focus isn't trapped */
+ PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
+
+ /* Restore window procedures for URL buttons */
+ winUnoverrideURLButton (hwndDialog, ID_ABOUT_CHANGELOG);
+ winUnoverrideURLButton (hwndDialog, ID_ABOUT_WEBSITE);
+ winUnoverrideURLButton (hwndDialog, ID_ABOUT_UG);
+ winUnoverrideURLButton (hwndDialog, ID_ABOUT_FAQ);
+
+ return TRUE;
+
+ case ID_ABOUT_CHANGELOG:
+ {
+ int iReturn;
+#ifdef __CYGWIN__
+ const char * pszCygPath = "/usr/X11R6/share/doc/"
+ "xorg-x11-xwin/changelog.html";
+ char pszWinPath[MAX_PATH + 1];
+
+ /* Convert the POSIX path to a Win32 path */
+ cygwin_conv_to_win32_path (pszCygPath, pszWinPath);
+#else
+ const char * pszWinPath = "http://x.cygwin.com/"
+ "devel/server/changelog.html";
+#endif
+
+ iReturn = (int)ShellExecute (NULL,
+ "open",
+ pszWinPath,
+ NULL,
+ NULL,
+ SW_MAXIMIZE);
+ if (iReturn < 32)
+ {
+ ErrorF ("winAboutDlgProc - WM_COMMAND - ID_ABOUT_CHANGELOG - "
+ "ShellExecute failed: %d\n",
+ iReturn);
+ }
+ }
+ return TRUE;
+
+ case ID_ABOUT_WEBSITE:
+ {
+ const char * pszPath = __VENDORDWEBSUPPORT__;
+ int iReturn;
+
+ iReturn = (int)ShellExecute (NULL,
+ "open",
+ pszPath,
+ NULL,
+ NULL,
+ SW_MAXIMIZE);
+ if (iReturn < 32)
+ {
+ ErrorF ("winAboutDlgProc - WM_COMMAND - ID_ABOUT_WEBSITE - "
+ "ShellExecute failed: %d\n",
+ iReturn);
+ }
+ }
+ return TRUE;
+
+ case ID_ABOUT_UG:
+ {
+ const char * pszPath = "http://x.cygwin.com/docs/ug/";
+ int iReturn;
+
+ iReturn = (int)ShellExecute (NULL,
+ "open",
+ pszPath,
+ NULL,
+ NULL,
+ SW_MAXIMIZE);
+ if (iReturn < 32)
+ {
+ ErrorF ("winAboutDlgProc - WM_COMMAND - ID_ABOUT_UG - "
+ "ShellExecute failed: %d\n",
+ iReturn);
+ }
+ }
+ return TRUE;
+
+ case ID_ABOUT_FAQ:
+ {
+ const char * pszPath = "http://x.cygwin.com/docs/faq/";
+ int iReturn;
+
+ iReturn = (int)ShellExecute (NULL,
+ "open",
+ pszPath,
+ NULL,
+ NULL,
+ SW_MAXIMIZE);
+ if (iReturn < 32)
+ {
+ ErrorF ("winAboutDlgProc - WM_COMMAND - ID_ABOUT_FAQ - "
+ "ShellExecute failed: %d\n",
+ iReturn);
+ }
+ }
+ return TRUE;
+ }
+ break;
+
+ case WM_CLOSE:
+ ErrorF ("winAboutDlgProc - WM_CLOSE\n");
+
+ DestroyWindow (g_hDlgAbout);
+ g_hDlgAbout = NULL;
+
+ /* Fix to make sure keyboard focus isn't trapped */
+ PostMessage (s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
+
+ /* Restore window procedures for URL buttons */
+ winUnoverrideURLButton (hwndDialog, ID_ABOUT_CHANGELOG);
+ winUnoverrideURLButton (hwndDialog, ID_ABOUT_WEBSITE);
+ winUnoverrideURLButton (hwndDialog, ID_ABOUT_UG);
+ winUnoverrideURLButton (hwndDialog, ID_ABOUT_FAQ);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/xorg-server/hw/xwin/winmonitors.c b/xorg-server/hw/xwin/winmonitors.c
new file mode 100644
index 000000000..63af803d0
--- /dev/null
+++ b/xorg-server/hw/xwin/winmonitors.c
@@ -0,0 +1,92 @@
+/*
+
+Copyright 1993, 1998 The Open Group
+Copyright (C) Colin Harrison 2005-2008
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+
+#include "win.h"
+#include "winmonitors.h"
+
+/*
+ * getMonitorInfo - callback function used to return information from the enumeration of monitors attached
+ */
+
+static
+wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data)
+{
+ struct GetMonitorInfoData* data = (struct GetMonitorInfoData*)_data;
+ // only get data for monitor number specified in <data>
+ data->monitorNum++;
+ if (data->monitorNum == data->requestedMonitor)
+ {
+ data->bMonitorSpecifiedExists = TRUE;
+ data->monitorOffsetX = rect->left;
+ data->monitorOffsetY = rect->top;
+ data->monitorHeight = rect->bottom - rect->top;
+ data->monitorWidth = rect->right - rect->left;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+typedef wBOOL (*ENUMDISPLAYMONITORSPROC)(HDC,LPCRECT,MONITORENUMPROC,LPARAM);
+ENUMDISPLAYMONITORSPROC _EnumDisplayMonitors;
+
+wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data);
+
+Bool QueryMonitor(int index, struct GetMonitorInfoData *data)
+{
+ /* Load EnumDisplayMonitors from DLL */
+ HMODULE user32;
+ FARPROC func;
+ user32 = LoadLibrary("user32.dll");
+ if (user32 == NULL)
+ {
+ winW32Error(2, "Could not open user32.dll");
+ return FALSE;
+ }
+ func = GetProcAddress(user32, "EnumDisplayMonitors");
+ if (func == NULL)
+ {
+ winW32Error(2, "Could not resolve EnumDisplayMonitors: ");
+ return FALSE;
+ }
+ _EnumDisplayMonitors = (ENUMDISPLAYMONITORSPROC)func;
+
+ /* prepare data */
+ if (data == NULL)
+ return FALSE;
+ memset(data, 0, sizeof(*data));
+ data->requestedMonitor = index;
+
+ /* query information */
+ _EnumDisplayMonitors(NULL, NULL, getMonitorInfo, (LPARAM) data);
+
+ /* cleanup */
+ FreeLibrary(user32);
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winmonitors.h b/xorg-server/hw/xwin/winmonitors.h
new file mode 100644
index 000000000..180566b00
--- /dev/null
+++ b/xorg-server/hw/xwin/winmonitors.h
@@ -0,0 +1,14 @@
+
+/* data returned for monitor information */
+struct GetMonitorInfoData {
+ int requestedMonitor;
+ int monitorNum;
+ Bool bUserSpecifiedMonitor;
+ Bool bMonitorSpecifiedExists;
+ int monitorOffsetX;
+ int monitorOffsetY;
+ int monitorHeight;
+ int monitorWidth;
+};
+
+Bool QueryMonitor(int index, struct GetMonitorInfoData *data);
diff --git a/xorg-server/hw/xwin/winnativegdi.c b/xorg-server/hw/xwin/winnativegdi.c
index 1a41bb484..4d7afe898 100644
--- a/xorg-server/hw/xwin/winnativegdi.c
+++ b/xorg-server/hw/xwin/winnativegdi.c
@@ -1,539 +1,534 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Harold L Hunt II
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-
-
-/*
- * Local function prototypes
- */
-
-static Bool
-winAllocateFBNativeGDI (ScreenPtr pScreen);
-
-static void
-winShadowUpdateNativeGDI (ScreenPtr pScreen,
- shadowBufPtr pBuf);
-
-static Bool
-winCloseScreenNativeGDI (int nIndex, ScreenPtr pScreen);
-
-static Bool
-winInitVisualsNativeGDI (ScreenPtr pScreen);
-
-static Bool
-winAdjustVideoModeNativeGDI (ScreenPtr pScreen);
-
-#if 0
-static Bool
-winBltExposedRegionsNativeGDI (ScreenPtr pScreen);
-#endif
-
-static Bool
-winActivateAppNativeGDI (ScreenPtr pScreen);
-
-static Bool
-winRedrawScreenNativeGDI (ScreenPtr pScreen);
-
-static Bool
-winRealizeInstalledPaletteNativeGDI (ScreenPtr pScreen);
-
-static Bool
-winInstallColormapNativeGDI (ColormapPtr pColormap);
-
-static Bool
-winStoreColorsNativeGDI (ColormapPtr pmap,
- int ndef,
- xColorItem *pdefs);
-
-static Bool
-winCreateColormapNativeGDI (ColormapPtr pColormap);
-
-static Bool
-winDestroyColormapNativeGDI (ColormapPtr pColormap);
-
-
-
-static Bool
-winAllocateFBNativeGDI (ScreenPtr pScreen)
-{
- FatalError ("winAllocateFBNativeGDI\n");
-
- return TRUE;
-}
-
-
-/*
- * We wrap whatever CloseScreen procedure was specified by fb;
- * a pointer to said procedure is stored in our privates.
- */
-
-static Bool
-winCloseScreenNativeGDI (int nIndex, ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- ErrorF ("winCloseScreenNativeGDI - Freeing screen resources\n");
-
- /* Flag that the screen is closed */
- pScreenPriv->fClosed = TRUE;
- pScreenPriv->fActive = FALSE;
-
- /*
- * NOTE: mi doesn't use a CloseScreen procedure, so we do not
- * need to call a wrapped procedure here.
- */
-
- /* Delete the window property */
- RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
-
- ErrorF ("winCloseScreenNativeGDI - Destroying window\n");
-
- /* Delete tray icon, if we have one */
- if (!pScreenInfo->fNoTrayIcon)
- winDeleteNotifyIcon (pScreenPriv);
-
- /* Free the exit confirmation dialog box, if it exists */
- if (g_hDlgExit != NULL)
- {
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
- }
-
- /* Kill our window */
- if (pScreenPriv->hwndScreen)
- {
- DestroyWindow (pScreenPriv->hwndScreen);
- pScreenPriv->hwndScreen = NULL;
- }
-
- /* Invalidate our screeninfo's pointer to the screen */
- pScreenInfo->pScreen = NULL;
-
- /* Free the screen privates for this screen */
- free (pScreenPriv);
-
- ErrorF ("winCloseScreenNativeGDI - Returning\n");
-
- return TRUE;
-}
-
-
-static void
-winShadowUpdateNativeGDI (ScreenPtr pScreen,
- shadowBufPtr pBuf)
-{
- FatalError ("winShadowUpdateNativeGDI\n");
- return;
-}
-
-
-static Bool
-winInitVisualsNativeGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /* Set the bitsPerRGB and bit masks */
- switch (pScreenInfo->dwDepth)
- {
- case 24:
- pScreenPriv->dwBitsPerRGB = 8;
- pScreenPriv->dwRedMask = 0x00FF0000;
- pScreenPriv->dwGreenMask = 0x0000FF00;
- pScreenPriv->dwBlueMask = 0x000000FF;
- break;
-
- case 16:
- pScreenPriv->dwBitsPerRGB = 6;
- pScreenPriv->dwRedMask = 0xF800;
- pScreenPriv->dwGreenMask = 0x07E0;
- pScreenPriv->dwBlueMask = 0x001F;
- break;
-
- case 15:
- pScreenPriv->dwBitsPerRGB = 5;
- pScreenPriv->dwRedMask = 0x7C00;
- pScreenPriv->dwGreenMask = 0x03E0;
- pScreenPriv->dwBlueMask = 0x001F;
- break;
-
- case 8:
- pScreenPriv->dwBitsPerRGB = 8;
- pScreenPriv->dwRedMask = 0;
- pScreenPriv->dwGreenMask = 0;
- pScreenPriv->dwBlueMask = 0;
- break;
-
- default:
- ErrorF ("winInitVisualsNativeGDI - Unknown screen depth\n");
- return FALSE;
- break;
- }
-
- /* Tell the user how many bits per RGB we are using */
- ErrorF ("winInitVisualsNativeGDI - Using dwBitsPerRGB: %d\n",
- (int) pScreenPriv->dwBitsPerRGB);
-
- /* Create a single visual according to the Windows screen depth */
- switch (pScreenInfo->dwDepth)
- {
- case 24:
- case 16:
- case 15:
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- TrueColorMask,
- pScreenPriv->dwBitsPerRGB,
- TrueColor,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisuals - miSetVisualTypesAndMasks failed\n");
- return FALSE;
- }
- break;
-
- case 8:
- ErrorF ("winInitVisuals - Calling miSetVisualTypesAndMasks\n");
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- StaticColorMask,
- pScreenPriv->dwBitsPerRGB,
- StaticColor,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisuals - miSetVisualTypesAndMasks failed\n");
- return FALSE;
- }
- break;
-
- default:
- ErrorF ("winInitVisualsNativeGDI - Unknown screen depth\n");
- return FALSE;
- }
-
-#if 1
- ErrorF ("winInitVisualsNativeGDI - Returning\n");
-#endif
-
- return TRUE;
-}
-
-
-/* Adjust the video mode */
-static Bool
-winAdjustVideoModeNativeGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HDC hdc = NULL;
- DWORD dwBPP;
-
- hdc = GetDC (NULL);
-
- /* We're in serious trouble if we can't get a DC */
- if (hdc == NULL)
- {
- ErrorF ("winAdjustVideoModeNativeGDI - GetDC () failed\n");
- return FALSE;
- }
-
- /* Query GDI for current display depth */
- dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
- pScreenInfo->dwDepth = GetDeviceCaps (hdc, PLANES);
-
- switch (pScreenInfo->dwDepth) {
- case 24:
- case 16:
- case 15:
- case 8:
- break;
- default:
- if (dwBPP == 32)
- pScreenInfo->dwDepth = 24;
- else
- pScreenInfo->dwDepth = dwBPP;
- break;
- }
-
- /* GDI cannot change the screen depth */
- if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP)
- {
- /* No -depth parameter passed, let the user know the depth being used */
- ErrorF ("winAdjustVideoModeNativeGDI - Using Windows display "
- "depth of %d bits per pixel, %d depth\n",
- (int) dwBPP, (int) pScreenInfo->dwDepth);
-
- /* Use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
- else if (dwBPP != pScreenInfo->dwBPP)
- {
- /* Warn user if GDI depth is different than -depth parameter */
- ErrorF ("winAdjustVideoModeNativeGDI - Command line bpp: %d, "\
- "using bpp: %d\n",
- (int) pScreenInfo->dwBPP, (int) dwBPP);
-
- /* We'll use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
-
- /* Release our DC */
- ReleaseDC (NULL, hdc);
-
- return TRUE;
-}
-
-
-static Bool
-winActivateAppNativeGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /*
- * Are we active?
- * Are we fullscreen?
- */
- if (pScreenPriv != NULL
- && pScreenPriv->fActive
- && pScreenInfo->fFullScreen)
- {
- /*
- * Activating, attempt to bring our window
- * to the top of the display
- */
- ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE);
- }
-
- /*
- * Are we inactive?
- * Are we fullscreen?
- */
- if (pScreenPriv != NULL
- && !pScreenPriv->fActive
- && pScreenInfo->fFullScreen)
- {
- /*
- * Deactivating, stuff our window onto the
- * task bar.
- */
- ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE);
- }
-
- return TRUE;
-}
-
-
-HBITMAP
-winCreateDIBNativeGDI (int iWidth, int iHeight, int iDepth,
- BYTE **ppbBits, BITMAPINFO **ppbmi)
-{
- BITMAPINFOHEADER *pbmih = NULL;
- HBITMAP hBitmap = NULL;
- BITMAPINFO *pbmi = NULL;
-
- /* Don't create an invalid bitmap */
- if (iWidth == 0
- || iHeight == 0
- || iDepth == 0)
- {
- ErrorF ("\nwinCreateDIBNativeGDI - Invalid specs w %d h %d d %d\n\n",
- iWidth, iHeight, iDepth);
- return NULL;
- }
-
- /* Allocate bitmap info header */
- pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
- + 256 * sizeof (RGBQUAD));
- if (pbmih == NULL)
- {
- ErrorF ("winCreateDIBNativeGDI - malloc () failed\n");
- return FALSE;
- }
- ZeroMemory (pbmih, sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD));
-
- /* Describe bitmap to be created */
- pbmih->biSize = sizeof (BITMAPINFOHEADER);
- pbmih->biWidth = iWidth;
- pbmih->biHeight = -iHeight;
- pbmih->biPlanes = 1;
- pbmih->biBitCount = iDepth;
- pbmih->biCompression = BI_RGB;
- pbmih->biSizeImage = 0;
- pbmih->biXPelsPerMeter = 0;
- pbmih->biYPelsPerMeter = 0;
- pbmih->biClrUsed = 0;
- pbmih->biClrImportant = 0;
-
- /* Setup color table for mono DIBs */
- if (iDepth == 1)
- {
- pbmi = (BITMAPINFO*) pbmih;
- pbmi->bmiColors[1].rgbBlue = 255;
- pbmi->bmiColors[1].rgbGreen = 255;
- pbmi->bmiColors[1].rgbRed = 255;
- }
-
- /* Create a DIB with a bit pointer */
- hBitmap = CreateDIBSection (NULL,
- (BITMAPINFO *) pbmih,
- DIB_RGB_COLORS,
- (void **) ppbBits,
- NULL,
- 0);
- if (hBitmap == NULL)
- {
- ErrorF ("winCreateDIBNativeGDI - CreateDIBSection () failed\n");
- return NULL;
- }
-
- /* Free the bitmap info header memory */
- if (ppbmi != NULL)
- {
- /* Store the address of the BMIH in the ppbmih parameter */
- *ppbmi = (BITMAPINFO *) pbmih;
- }
- else
- {
- free (pbmih);
- pbmih = NULL;
- }
-
- return hBitmap;
-}
-
-
-#if 0
-static Bool
-winBltExposedRegionsNativeGDI (ScreenPtr pScreen)
-{
-
- return TRUE;
-}
-#endif
-
-
-static Bool
-winRedrawScreenNativeGDI (ScreenPtr pScreen)
-{
- FatalError ("winRedrawScreenNativeGDI\n");
- return TRUE;
-}
-
-
-static Bool
-winRealizeInstalledPaletteNativeGDI (ScreenPtr pScreen)
-{
- FatalError ("winRealizeInstalledPaletteNativeGDI\n");
- return TRUE;
-}
-
-
-static Bool
-winInstallColormapNativeGDI (ColormapPtr pColormap)
-{
- FatalError ("winInstallColormapNativeGDI\n");
- return TRUE;
-}
-
-
-static Bool
-winStoreColorsNativeGDI (ColormapPtr pmap,
- int ndef,
- xColorItem *pdefs)
-{
- FatalError ("winStoreColorsNativeGDI\n");
- return TRUE;
-}
-
-
-static Bool
-winCreateColormapNativeGDI (ColormapPtr pColormap)
-{
- FatalError ("winCreateColormapNativeGDI\n");
- return TRUE;
-}
-
-
-static Bool
-winDestroyColormapNativeGDI (ColormapPtr pColormap)
-{
- FatalError ("winDestroyColormapNativeGDI\n");
- return TRUE;
-}
-
-
-/* Set engine specific funtions */
-Bool
-winSetEngineFunctionsNativeGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /* Set our pointers */
- pScreenPriv->pwinAllocateFB = winAllocateFBNativeGDI;
- pScreenPriv->pwinShadowUpdate = winShadowUpdateNativeGDI;
- pScreenPriv->pwinCloseScreen = winCloseScreenNativeGDI;
- pScreenPriv->pwinInitVisuals = winInitVisualsNativeGDI;
- pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeNativeGDI;
- if (pScreenInfo->fFullScreen)
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
- else
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
- pScreenPriv->pwinFinishScreenInit = winFinishScreenInitNativeGDI;
- /*
- * WARNING: Do not set the BltExposedRegions procedure pointer to anything
- * other than NULL until a working painting procedure is in place.
- * Else, winWindowProc will get stuck in an infinite loop because
- * Windows expects the BeginPaint and EndPaint functions to be called
- * before a WM_PAINT message can be removed from the queue. We are
- * using NULL here as a signal for winWindowProc that it should
- * not signal that the WM_PAINT message has been processed.
- */
- pScreenPriv->pwinBltExposedRegions = NULL;
- pScreenPriv->pwinActivateApp = winActivateAppNativeGDI;
- pScreenPriv->pwinRedrawScreen = winRedrawScreenNativeGDI;
- pScreenPriv->pwinRealizeInstalledPalette =
- winRealizeInstalledPaletteNativeGDI;
- pScreenPriv->pwinInstallColormap = winInstallColormapNativeGDI;
- pScreenPriv->pwinStoreColors = winStoreColorsNativeGDI;
- pScreenPriv->pwinCreateColormap = winCreateColormapNativeGDI;
- pScreenPriv->pwinDestroyColormap = winDestroyColormapNativeGDI;
- pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
-
- return TRUE;
-}
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+static Bool
+winAllocateFBNativeGDI (ScreenPtr pScreen);
+
+static void
+winShadowUpdateNativeGDI (ScreenPtr pScreen,
+ shadowBufPtr pBuf);
+
+static Bool
+winCloseScreenNativeGDI (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsNativeGDI (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModeNativeGDI (ScreenPtr pScreen);
+
+#if 0
+static Bool
+winBltExposedRegionsNativeGDI (ScreenPtr pScreen);
+#endif
+
+static Bool
+winActivateAppNativeGDI (ScreenPtr pScreen);
+
+static Bool
+winRedrawScreenNativeGDI (ScreenPtr pScreen);
+
+static Bool
+winRealizeInstalledPaletteNativeGDI (ScreenPtr pScreen);
+
+static Bool
+winInstallColormapNativeGDI (ColormapPtr pColormap);
+
+static Bool
+winStoreColorsNativeGDI (ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs);
+
+static Bool
+winCreateColormapNativeGDI (ColormapPtr pColormap);
+
+static Bool
+winDestroyColormapNativeGDI (ColormapPtr pColormap);
+
+
+
+static Bool
+winAllocateFBNativeGDI (ScreenPtr pScreen)
+{
+ FatalError ("winAllocateFBNativeGDI\n");
+
+ return TRUE;
+}
+
+static void
+winFreeFBNativeGDI (ScreenPtr pScreen)
+{
+ FatalError ("winFreeFBNativeGDI\n");
+}
+
+
+static Bool
+winInitScreenNativeGDI(ScreenPtr pScreen)
+{
+ FatalError ("winInitScreenNativeGDI\n");
+}
+
+/*
+ * We wrap whatever CloseScreen procedure was specified by fb;
+ * a pointer to said procedure is stored in our privates.
+ */
+
+static Bool
+winCloseScreenNativeGDI (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ ErrorF ("winCloseScreenNativeGDI - Freeing screen resources\n");
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /*
+ * NOTE: mi doesn't use a CloseScreen procedure, so we do not
+ * need to call a wrapped procedure here.
+ */
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ ErrorF ("winCloseScreenNativeGDI - Destroying window\n");
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+ /* Invalidate our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free (pScreenPriv);
+
+ ErrorF ("winCloseScreenNativeGDI - Returning\n");
+
+ return TRUE;
+}
+
+
+static void
+winShadowUpdateNativeGDI (ScreenPtr pScreen,
+ shadowBufPtr pBuf)
+{
+ FatalError ("winShadowUpdateNativeGDI\n");
+ return;
+}
+
+
+static Bool
+winInitVisualsNativeGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set the bitsPerRGB and bit masks */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ pScreenPriv->dwBitsPerRGB = 8;
+ pScreenPriv->dwRedMask = 0x00FF0000;
+ pScreenPriv->dwGreenMask = 0x0000FF00;
+ pScreenPriv->dwBlueMask = 0x000000FF;
+ break;
+
+ case 16:
+ pScreenPriv->dwBitsPerRGB = 6;
+ pScreenPriv->dwRedMask = 0xF800;
+ pScreenPriv->dwGreenMask = 0x07E0;
+ pScreenPriv->dwBlueMask = 0x001F;
+ break;
+
+ case 15:
+ pScreenPriv->dwBitsPerRGB = 5;
+ pScreenPriv->dwRedMask = 0x7C00;
+ pScreenPriv->dwGreenMask = 0x03E0;
+ pScreenPriv->dwBlueMask = 0x001F;
+ break;
+
+ case 8:
+ pScreenPriv->dwBitsPerRGB = 8;
+ pScreenPriv->dwRedMask = 0;
+ pScreenPriv->dwGreenMask = 0;
+ pScreenPriv->dwBlueMask = 0;
+ break;
+
+ default:
+ ErrorF ("winInitVisualsNativeGDI - Unknown screen depth\n");
+ return FALSE;
+ break;
+ }
+
+ /* Tell the user how many bits per RGB we are using */
+ ErrorF ("winInitVisualsNativeGDI - Using dwBitsPerRGB: %d\n",
+ (int) pScreenPriv->dwBitsPerRGB);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ TrueColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisuals - miSetVisualTypesAndMasks failed\n");
+ return FALSE;
+ }
+ break;
+
+ case 8:
+ ErrorF ("winInitVisuals - Calling miSetVisualTypesAndMasks\n");
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ StaticColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ StaticColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisuals - miSetVisualTypesAndMasks failed\n");
+ return FALSE;
+ }
+ break;
+
+ default:
+ ErrorF ("winInitVisualsNativeGDI - Unknown screen depth\n");
+ return FALSE;
+ }
+
+#if 1
+ ErrorF ("winInitVisualsNativeGDI - Returning\n");
+#endif
+
+ return TRUE;
+}
+
+
+/* Adjust the video mode */
+static Bool
+winAdjustVideoModeNativeGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc = NULL;
+ DWORD dwBPP;
+
+ hdc = GetDC (NULL);
+
+ /* We're in serious trouble if we can't get a DC */
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModeNativeGDI - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+ pScreenInfo->dwDepth = GetDeviceCaps (hdc, PLANES);
+
+ switch (pScreenInfo->dwDepth) {
+ case 24:
+ case 16:
+ case 15:
+ case 8:
+ break;
+ default:
+ if (dwBPP == 32)
+ pScreenInfo->dwDepth = 24;
+ else
+ pScreenInfo->dwDepth = dwBPP;
+ break;
+ }
+
+ /* GDI cannot change the screen depth, so we'll use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+
+ return TRUE;
+}
+
+
+static Bool
+winActivateAppNativeGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /*
+ * Are we active?
+ * Are we fullscreen?
+ */
+ if (pScreenPriv != NULL
+ && pScreenPriv->fActive
+ && pScreenInfo->fFullScreen)
+ {
+ /*
+ * Activating, attempt to bring our window
+ * to the top of the display
+ */
+ ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE);
+ }
+
+ /*
+ * Are we inactive?
+ * Are we fullscreen?
+ */
+ if (pScreenPriv != NULL
+ && !pScreenPriv->fActive
+ && pScreenInfo->fFullScreen)
+ {
+ /*
+ * Deactivating, stuff our window onto the
+ * task bar.
+ */
+ ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE);
+ }
+
+ return TRUE;
+}
+
+
+HBITMAP
+winCreateDIBNativeGDI (int iWidth, int iHeight, int iDepth,
+ BYTE **ppbBits, BITMAPINFO **ppbmi)
+{
+ BITMAPINFOHEADER *pbmih = NULL;
+ HBITMAP hBitmap = NULL;
+ BITMAPINFO *pbmi = NULL;
+
+ /* Don't create an invalid bitmap */
+ if (iWidth == 0
+ || iHeight == 0
+ || iDepth == 0)
+ {
+ ErrorF ("\nwinCreateDIBNativeGDI - Invalid specs w %d h %d d %d\n\n",
+ iWidth, iHeight, iDepth);
+ return NULL;
+ }
+
+ /* Allocate bitmap info header */
+ pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
+ + 256 * sizeof (RGBQUAD));
+ if (pbmih == NULL)
+ {
+ ErrorF ("winCreateDIBNativeGDI - malloc () failed\n");
+ return FALSE;
+ }
+ ZeroMemory (pbmih, sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD));
+
+ /* Describe bitmap to be created */
+ pbmih->biSize = sizeof (BITMAPINFOHEADER);
+ pbmih->biWidth = iWidth;
+ pbmih->biHeight = -iHeight;
+ pbmih->biPlanes = 1;
+ pbmih->biBitCount = iDepth;
+ pbmih->biCompression = BI_RGB;
+ pbmih->biSizeImage = 0;
+ pbmih->biXPelsPerMeter = 0;
+ pbmih->biYPelsPerMeter = 0;
+ pbmih->biClrUsed = 0;
+ pbmih->biClrImportant = 0;
+
+ /* Setup color table for mono DIBs */
+ if (iDepth == 1)
+ {
+ pbmi = (BITMAPINFO*) pbmih;
+ pbmi->bmiColors[1].rgbBlue = 255;
+ pbmi->bmiColors[1].rgbGreen = 255;
+ pbmi->bmiColors[1].rgbRed = 255;
+ }
+
+ /* Create a DIB with a bit pointer */
+ hBitmap = CreateDIBSection (NULL,
+ (BITMAPINFO *) pbmih,
+ DIB_RGB_COLORS,
+ (void **) ppbBits,
+ NULL,
+ 0);
+ if (hBitmap == NULL)
+ {
+ ErrorF ("winCreateDIBNativeGDI - CreateDIBSection () failed\n");
+ return NULL;
+ }
+
+ /* Free the bitmap info header memory */
+ if (ppbmi != NULL)
+ {
+ /* Store the address of the BMIH in the ppbmih parameter */
+ *ppbmi = (BITMAPINFO *) pbmih;
+ }
+ else
+ {
+ free (pbmih);
+ pbmih = NULL;
+ }
+
+ return hBitmap;
+}
+
+
+#if 0
+static Bool
+winBltExposedRegionsNativeGDI (ScreenPtr pScreen)
+{
+
+ return TRUE;
+}
+#endif
+
+
+static Bool
+winRedrawScreenNativeGDI (ScreenPtr pScreen)
+{
+ FatalError ("winRedrawScreenNativeGDI\n");
+ return TRUE;
+}
+
+
+static Bool
+winRealizeInstalledPaletteNativeGDI (ScreenPtr pScreen)
+{
+ FatalError ("winRealizeInstalledPaletteNativeGDI\n");
+ return TRUE;
+}
+
+
+static Bool
+winInstallColormapNativeGDI (ColormapPtr pColormap)
+{
+ FatalError ("winInstallColormapNativeGDI\n");
+ return TRUE;
+}
+
+
+static Bool
+winStoreColorsNativeGDI (ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs)
+{
+ FatalError ("winStoreColorsNativeGDI\n");
+ return TRUE;
+}
+
+
+static Bool
+winCreateColormapNativeGDI (ColormapPtr pColormap)
+{
+ FatalError ("winCreateColormapNativeGDI\n");
+ return TRUE;
+}
+
+
+static Bool
+winDestroyColormapNativeGDI (ColormapPtr pColormap)
+{
+ FatalError ("winDestroyColormapNativeGDI\n");
+ return TRUE;
+}
+
+
+/* Set engine specific funtions */
+Bool
+winSetEngineFunctionsNativeGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBNativeGDI;
+ pScreenPriv->pwinFreeFB = winFreeFBNativeGDI;
+ pScreenPriv->pwinShadowUpdate = winShadowUpdateNativeGDI;
+ pScreenPriv->pwinInitScreen = winInitScreenNativeGDI;
+ pScreenPriv->pwinCloseScreen = winCloseScreenNativeGDI;
+ pScreenPriv->pwinInitVisuals = winInitVisualsNativeGDI;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeNativeGDI;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitNativeGDI;
+ /*
+ * WARNING: Do not set the BltExposedRegions procedure pointer to anything
+ * other than NULL until a working painting procedure is in place.
+ * Else, winWindowProc will get stuck in an infinite loop because
+ * Windows expects the BeginPaint and EndPaint functions to be called
+ * before a WM_PAINT message can be removed from the queue. We are
+ * using NULL here as a signal for winWindowProc that it should
+ * not signal that the WM_PAINT message has been processed.
+ */
+ pScreenPriv->pwinBltExposedRegions = NULL;
+ pScreenPriv->pwinActivateApp = winActivateAppNativeGDI;
+ pScreenPriv->pwinRedrawScreen = winRedrawScreenNativeGDI;
+ pScreenPriv->pwinRealizeInstalledPalette =
+ winRealizeInstalledPaletteNativeGDI;
+ pScreenPriv->pwinInstallColormap = winInstallColormapNativeGDI;
+ pScreenPriv->pwinStoreColors = winStoreColorsNativeGDI;
+ pScreenPriv->pwinCreateColormap = winCreateColormapNativeGDI;
+ pScreenPriv->pwinDestroyColormap = winDestroyColormapNativeGDI;
+ pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winpfbdd.c b/xorg-server/hw/xwin/winpfbdd.c
index 840a839f0..c0bca71e3 100644
--- a/xorg-server/hw/xwin/winpfbdd.c
+++ b/xorg-server/hw/xwin/winpfbdd.c
@@ -1,676 +1,678 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Dakshinamurthy Karra
- * Suhaib M Siddiqi
- * Peter Busch
- * Harold L Hunt II
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-
-
-/*
- * Local function prototypes
- */
-
-static Bool
-winAllocateFBPrimaryDD (ScreenPtr pScreen);
-
-static Bool
-winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen);
-
-static Bool
-winInitVisualsPrimaryDD (ScreenPtr pScreen);
-
-static Bool
-winAdjustVideoModePrimaryDD (ScreenPtr pScreen);
-
-static Bool
-winActivateAppPrimaryDD (ScreenPtr pScreen);
-
-static Bool
-winHotKeyAltTabPrimaryDD (ScreenPtr pScreen);
-
-
-/*
- * Create a DirectDraw primary surface
- */
-
-static Bool
-winAllocateFBPrimaryDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HRESULT ddrval = DD_OK;
- DDSURFACEDESC ddsd;
- DDSURFACEDESC *pddsdPrimary = NULL;
- DDSURFACEDESC *pddsdOffscreen = NULL;
- RECT rcClient;
-
- ErrorF ("winAllocateFBPrimaryDD\n");
-
- /* Get client area location in screen coords */
- GetClientRect (pScreenPriv->hwndScreen, &rcClient);
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&rcClient, 2);
-
- /* Create a DirectDraw object, store the address at lpdd */
- ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
- if (ddrval != DD_OK)
- FatalError ("winAllocateFBPrimaryDD - Could not start DirectDraw\n");
-
- /* Get a DirectDraw2 interface pointer */
- ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
- &IID_IDirectDraw2,
- (LPVOID*) &pScreenPriv->pdd2);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-
- ErrorF ("winAllocateFBPrimaryDD - Created and initialized DD\n");
-
- /* Are we windowed or fullscreen? */
- if (pScreenInfo->fFullScreen)
- {
- /* Full screen mode */
- ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
- pScreenPriv->hwndScreen,
- DDSCL_FULLSCREEN
- | DDSCL_EXCLUSIVE);
- if (FAILED (ddrval))
- FatalError ("winAllocateFBPrimaryDD - Could not set "
- "cooperative level\n");
-
- /* Change the video mode to the mode requested */
- ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
- pScreenInfo->dwWidth,
- pScreenInfo->dwHeight,
- pScreenInfo->dwBPP,
- pScreenInfo->dwRefreshRate,
- 0);
- if (FAILED (ddrval))
- FatalError ("winAllocateFBPrimaryDD - Could not set "
- "full screen display mode\n");
- }
- else
- {
- /* Windowed mode */
- ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
- pScreenPriv->hwndScreen,
- DDSCL_NORMAL);
- if (FAILED (ddrval))
- FatalError ("winAllocateFBPrimaryDD - Could not set "
- "cooperative level\n");
- }
-
- /* Describe the primary surface */
- ZeroMemory (&ddsd, sizeof (ddsd));
- ddsd.dwSize = sizeof (ddsd);
- ddsd.dwFlags = DDSD_CAPS;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
-
- /* Create the primary surface */
- ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
- &ddsd,
- &pScreenPriv->pddsPrimary,
- NULL);
- if (FAILED (ddrval))
- FatalError ("winAllocateFBPrimaryDD - Could not create primary "
- "surface %08x\n", (unsigned int) ddrval);
-
- ErrorF ("winAllocateFBPrimaryDD - Created primary\n");
-
- /* Allocate a DD surface description for our screen privates */
- pddsdPrimary = pScreenPriv->pddsdPrimary
- = malloc (sizeof (DDSURFACEDESC));
- if (pddsdPrimary == NULL)
- FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
- "description memory\n");
- ZeroMemory (pddsdPrimary, sizeof (*pddsdPrimary));
- pddsdPrimary->dwSize = sizeof (*pddsdPrimary);
-
- /* Describe the offscreen surface to be created */
- /*
- * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
- * as drawing, locking, and unlocking take forever
- * with video memory surfaces. In addition,
- * video memory is a somewhat scarce resource,
- * so you shouldn't be allocating video memory when
- * you have the option of using system memory instead.
- */
- ZeroMemory (&ddsd, sizeof (ddsd));
- ddsd.dwSize = sizeof (ddsd);
- ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
- ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
- ddsd.dwHeight = pScreenInfo->dwHeight;
- ddsd.dwWidth = pScreenInfo->dwWidth;
-
- /* Create the shadow surface */
- ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
- &ddsd,
- &pScreenPriv->pddsOffscreen,
- NULL);
- if (ddrval != DD_OK)
- FatalError ("winAllocateFBPrimaryDD - Could not create shadow "
- "surface\n");
-
- ErrorF ("winAllocateFBPrimaryDD - Created offscreen\n");
-
- /* Allocate a DD surface description for our screen privates */
- pddsdOffscreen = pScreenPriv->pddsdOffscreen
- = malloc (sizeof (DDSURFACEDESC));
- if (pddsdOffscreen == NULL)
- FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
- "description memory\n");
- ZeroMemory (pddsdOffscreen, sizeof (*pddsdOffscreen));
- pddsdOffscreen->dwSize = sizeof (*pddsdOffscreen);
-
- ErrorF ("winAllocateFBPrimaryDD - Locking primary\n");
-
- /* Lock the primary surface */
- ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
- pScreenInfo->fFullScreen ? NULL:&rcClient,
- pddsdPrimary,
- DDLOCK_WAIT,
- NULL);
- if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL)
- FatalError ("winAllocateFBPrimaryDD - Could not lock "
- "primary surface\n");
-
- ErrorF ("winAllocateFBPrimaryDD - Locked primary\n");
-
- /* We don't know how to deal with anything other than RGB */
- if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB))
- FatalError ("winAllocateFBPrimaryDD - Color format other than RGB\n");
-
- /* Grab the pitch from the surface desc */
- pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8)
- / pScreenInfo->dwBPP;
-
- /* Save the pointer to our surface memory */
- pScreenInfo->pfb = pddsdPrimary->lpSurface;
-
- /* Grab the color depth and masks from the surface description */
- pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask;
- pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask;
- pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask;
-
- ErrorF ("winAllocateFBPrimaryDD - Returning\n");
-
- return TRUE;
-}
-
-
-/*
- * Call the wrapped CloseScreen function.
- *
- * Free our resources and private structures.
- */
-
-static Bool
-winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- Bool fReturn;
-
- ErrorF ("winCloseScreenPrimaryDD - Freeing screen resources\n");
-
- /* Flag that the screen is closed */
- pScreenPriv->fClosed = TRUE;
- pScreenPriv->fActive = FALSE;
-
- /* Call the wrapped CloseScreen procedure */
- WIN_UNWRAP(CloseScreen);
- fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
-
- /* Delete the window property */
- RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
-
- /* Free the offscreen surface, if there is one */
- if (pScreenPriv->pddsOffscreen)
- {
- IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, NULL);
- IDirectDrawSurface2_Release (pScreenPriv->pddsOffscreen);
- pScreenPriv->pddsOffscreen = NULL;
- }
-
- /* Release the primary surface, if there is one */
- if (pScreenPriv->pddsPrimary)
- {
- IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, NULL);
- IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
- pScreenPriv->pddsPrimary = NULL;
- }
-
- /* Free the DirectDraw object, if there is one */
- if (pScreenPriv->pdd)
- {
- IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd);
- IDirectDraw2_Release (pScreenPriv->pdd);
- pScreenPriv->pdd = NULL;
- }
-
- /* Delete tray icon, if we have one */
- if (!pScreenInfo->fNoTrayIcon)
- winDeleteNotifyIcon (pScreenPriv);
-
- /* Free the exit confirmation dialog box, if it exists */
- if (g_hDlgExit != NULL)
- {
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
- }
-
- /* Kill our window */
- if (pScreenPriv->hwndScreen)
- {
- DestroyWindow (pScreenPriv->hwndScreen);
- pScreenPriv->hwndScreen = NULL;
- }
-
- /* Kill our screeninfo's pointer to the screen */
- pScreenInfo->pScreen = NULL;
-
- /* Invalidate the ScreenInfo's fb pointer */
- pScreenInfo->pfb = NULL;
-
- /* Free the screen privates for this screen */
- free ((pointer) pScreenPriv);
-
- return fReturn;
-}
-
-
-/*
- * Tell mi what sort of visuals we need.
- *
- * Generally we only need one visual, as our screen can only
- * handle one format at a time, I believe. You may want
- * to verify that last sentence.
- */
-
-static Bool
-winInitVisualsPrimaryDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- DWORD dwRedBits, dwGreenBits, dwBlueBits;
-
- /* Count the number of ones in each color mask */
- dwRedBits = winCountBits (pScreenPriv->dwRedMask);
- dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
- dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
-
- /* Store the maximum number of ones in a color mask as the bitsPerRGB */
- if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
- pScreenPriv->dwBitsPerRGB = dwRedBits;
- else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
- pScreenPriv->dwBitsPerRGB = dwGreenBits;
- else
- pScreenPriv->dwBitsPerRGB = dwBlueBits;
-
- ErrorF ("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n",
- (unsigned int) pScreenPriv->dwRedMask,
- (unsigned int) pScreenPriv->dwGreenMask,
- (unsigned int) pScreenPriv->dwBlueMask,
- (int) pScreenPriv->dwBitsPerRGB);
-
- /* Create a single visual according to the Windows screen depth */
- switch (pScreenInfo->dwDepth)
- {
- case 24:
- case 16:
- case 15:
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- TrueColorMask,
- pScreenPriv->dwBitsPerRGB,
- TrueColor,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisualsPrimaryDD - "
- "miSetVisualTypesAndMasks failed\n");
- return FALSE;
- }
- break;
-
- case 8:
-#if CYGDEBUG
- winDebug ("winInitVisuals - Calling miSetVisualTypesAndMasks\n");
-#endif /* CYGDEBUG */
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- PseudoColorMask,
- pScreenPriv->dwBitsPerRGB,
- PseudoColor,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisualsPrimaryDD - "
- "miSetVisualTypesAndMasks failed\n");
- return FALSE;
- }
-#if CYGDEBUG
- winDebug ("winInitVisualsPrimaryDD - Returned from "
- "miSetVisualTypesAndMasks\n");
-#endif /* CYGDEBUG */
- break;
-
- default:
- ErrorF ("winInitVisualsPrimaryDD - Unknown screen depth\n");
- return FALSE;
- }
-
- ErrorF ("winInitVisualsPrimaryDD - Returning\n");
-
- return TRUE;
-}
-
-
-static Bool
-winAdjustVideoModePrimaryDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HDC hdc = NULL;
- DWORD dwBPP;
-
- /* We're in serious trouble if we can't get a DC */
- hdc = GetDC (NULL);
- if (hdc == NULL)
- {
- ErrorF ("winAdjustVideoModePrimaryDD - GetDC failed\n");
- return FALSE;
- }
-
- /* Query GDI for current display depth */
- dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
-
- /* DirectDraw can only change the depth in fullscreen mode */
- if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP)
- {
- /* No -depth parameter passed, let the user know the depth being used */
- ErrorF ("winAdjustVideoModePrimaryDD - Using Windows display "
- "depth of %d bits per pixel\n", (int) dwBPP);
-
- /* Use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
- else if (pScreenInfo->fFullScreen
- && pScreenInfo->dwBPP != dwBPP)
- {
- /* FullScreen, and GDI depth differs from -depth parameter */
- ErrorF ("winAdjustVideoModePrimaryDD - FullScreen, using command "
- "line depth: %d\n", (int) pScreenInfo->dwBPP);
- }
- else if (dwBPP != pScreenInfo->dwBPP)
- {
- /* Windowed, and GDI depth differs from -depth parameter */
- ErrorF ("winAdjustVideoModePrimaryDD - Windowed, command line "
- "depth: %d, using depth: %d\n",
- (int) pScreenInfo->dwBPP, (int) dwBPP);
-
- /* We'll use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
-
- /* Release our DC */
- ReleaseDC (NULL, hdc);
-
- return TRUE;
-}
-
-
-/*
- * We need to blit our offscreen fb to
- * the screen when we are activated, and we need to point
- * the fb code back to the primary surface memory.
- */
-
-static Bool
-winActivateAppPrimaryDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- RECT rcSrc, rcClient;
- HRESULT ddrval = DD_OK;
-
- /* Check for errors */
- if (pScreenPriv == NULL
- || pScreenPriv->pddsPrimary == NULL
- || pScreenPriv->pddsOffscreen == NULL)
- return FALSE;
-
- /* Check for do-nothing */
- if (!pScreenPriv->fActive)
- return TRUE;
-
- /* We are activating */
- ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsOffscreen);
- if (ddrval == DD_OK)
- {
- IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen,
- NULL);
- /*
- * We don't check for an error from Unlock, because it
- * doesn't matter if the Unlock failed.
- */
- }
-
- /* Restore both surfaces, just cause I like it that way */
- IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
- IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
-
- /* Get client area in screen coords */
- GetClientRect (pScreenPriv->hwndScreen, &rcClient);
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&rcClient, 2);
-
- /* Setup a source rectangle */
- rcSrc.left = 0;
- rcSrc.top = 0;
- rcSrc.right = pScreenInfo->dwWidth;
- rcSrc.bottom = pScreenInfo->dwHeight;
-
- ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
- &rcClient,
- pScreenPriv->pddsOffscreen,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
- if (ddrval != DD_OK)
- FatalError ("winActivateAppPrimaryDD () - Failed blitting offscreen "
- "surface to primary surface %08x\n", (unsigned int) ddrval);
-
- /* Lock the primary surface */
- ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
- &rcClient,
- pScreenPriv->pddsdPrimary,
- DDLOCK_WAIT,
- NULL);
- if (ddrval != DD_OK
- || pScreenPriv->pddsdPrimary->lpSurface == NULL)
- FatalError ("winActivateAppPrimaryDD () - Could not lock "
- "primary surface\n");
-
- /* Notify FB of the new memory pointer */
- winUpdateFBPointer (pScreen,
- pScreenPriv->pddsdPrimary->lpSurface);
-
- /*
- * Register the Alt-Tab combo as a hotkey so we can copy
- * the primary framebuffer before the display mode changes
- */
- RegisterHotKey (pScreenPriv->hwndScreen, 1, MOD_ALT, 9);
-
- return TRUE;
-}
-
-
-/*
- * Handle the Alt+Tab hotkey.
- *
- * We need to save the primary fb to an offscreen fb when
- * we get deactivated, and point the fb code at the offscreen
- * fb for the duration of the deactivation.
- */
-
-static Bool
-winHotKeyAltTabPrimaryDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- RECT rcClient, rcSrc;
- HRESULT ddrval = DD_OK;
-
- ErrorF ("\nwinHotKeyAltTabPrimaryDD\n\n");
-
- /* Alt+Tab was pressed, we will lose focus very soon */
- pScreenPriv->fActive = FALSE;
-
- /* Check for error conditions */
- if (pScreenPriv->pddsPrimary == NULL
- || pScreenPriv->pddsOffscreen == NULL)
- return FALSE;
-
- /* Get client area in screen coords */
- GetClientRect (pScreenPriv->hwndScreen, &rcClient);
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&rcClient, 2);
-
- /* Did we loose the primary surface? */
- ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsPrimary);
- if (ddrval == DD_OK)
- {
- ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary,
- NULL);
- if (FAILED (ddrval))
- FatalError ("winHotKeyAltTabPrimaryDD - Failed unlocking primary "
- "surface\n");
- }
-
- /* Setup a source rectangle */
- rcSrc.left = 0;
- rcSrc.top = 0;
- rcSrc.right = pScreenInfo->dwWidth;
- rcSrc.bottom = pScreenInfo->dwHeight;
-
- /* Blit the primary surface to the offscreen surface */
- ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
- NULL, /* should be rcDest */
- pScreenPriv->pddsPrimary,
- NULL,
- DDBLT_WAIT,
- NULL);
- if (ddrval == DDERR_SURFACELOST)
- {
- IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
- IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
-
- /* Blit the primary surface to the offscreen surface */
- ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
- NULL,
- pScreenPriv->pddsPrimary,
- NULL,
- DDBLT_WAIT,
- NULL);
- if (FAILED (ddrval))
- FatalError ("winHotKeyAltTabPrimaryDD - Failed blitting primary "
- "surface to offscreen surface: %08x\n",
- (unsigned int) ddrval);
- }
- else
- {
- FatalError ("winHotKeyAltTabPrimaryDD - Unknown error from "
- "Blt: %08dx\n", (unsigned int) ddrval);
- }
-
- /* Lock the offscreen surface */
- ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsOffscreen,
- NULL,
- pScreenPriv->pddsdOffscreen,
- DDLOCK_WAIT,
- NULL);
- if (ddrval != DD_OK
- || pScreenPriv->pddsdPrimary->lpSurface == NULL)
- FatalError ("winHotKeyAltTabPrimaryDD - Could not lock "
- "offscreen surface\n");
-
- /* Notify FB of the new memory pointer */
- winUpdateFBPointer (pScreen,
- pScreenPriv->pddsdOffscreen->lpSurface);
-
- /* Unregister our hotkey */
- UnregisterHotKey (pScreenPriv->hwndScreen, 1);
-
- return TRUE;
-}
-
-
-/* Set engine specific functions */
-Bool
-winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /* Set our pointers */
- pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD;
- pScreenPriv->pwinShadowUpdate
- = (winShadowUpdateProcPtr) (void (*)(void))NoopDDA;
- pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD;
- pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD;
- pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD;
- if (pScreenInfo->fFullScreen)
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
- else
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
- pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
- pScreenPriv->pwinBltExposedRegions
- = (winBltExposedRegionsProcPtr) (void (*)(void))NoopDDA;
- pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD;
- pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD;
-#ifdef XWIN_MULTIWINDOW
- pScreenPriv->pwinFinishCreateWindowsWindow =
- (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
-#endif
-
- return TRUE;
-}
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+static Bool
+winAllocateFBPrimaryDD (ScreenPtr pScreen);
+
+static Bool
+winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsPrimaryDD (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModePrimaryDD (ScreenPtr pScreen);
+
+static Bool
+winActivateAppPrimaryDD (ScreenPtr pScreen);
+
+static Bool
+winHotKeyAltTabPrimaryDD (ScreenPtr pScreen);
+
+
+/*
+ * Create a DirectDraw primary surface
+ */
+
+static Bool
+winAllocateFBPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC ddsd;
+ DDSURFACEDESC *pddsdPrimary = NULL;
+ DDSURFACEDESC *pddsdOffscreen = NULL;
+ RECT rcClient;
+
+ ErrorF ("winAllocateFBPrimaryDD\n");
+
+ /* Get client area location in screen coords */
+ GetClientRect (pScreenPriv->hwndScreen, &rcClient);
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&rcClient, 2);
+
+ /* Create a DirectDraw object, store the address at lpdd */
+ ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
+ if (ddrval != DD_OK)
+ FatalError ("winAllocateFBPrimaryDD - Could not start DirectDraw\n");
+
+ /* Get a DirectDraw2 interface pointer */
+ ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
+ &IID_IDirectDraw2,
+ (LPVOID*) &pScreenPriv->pdd2);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+
+ ErrorF ("winAllocateFBPrimaryDD - Created and initialized DD\n");
+
+ /* Are we windowed or fullscreen? */
+ if (pScreenInfo->fFullScreen)
+ {
+ /* Full screen mode */
+ ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
+ pScreenPriv->hwndScreen,
+ DDSCL_FULLSCREEN
+ | DDSCL_EXCLUSIVE);
+ if (FAILED (ddrval))
+ FatalError ("winAllocateFBPrimaryDD - Could not set "
+ "cooperative level\n");
+
+ /* Change the video mode to the mode requested */
+ ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ pScreenInfo->dwRefreshRate,
+ 0);
+ if (FAILED (ddrval))
+ FatalError ("winAllocateFBPrimaryDD - Could not set "
+ "full screen display mode\n");
+ }
+ else
+ {
+ /* Windowed mode */
+ ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
+ pScreenPriv->hwndScreen,
+ DDSCL_NORMAL);
+ if (FAILED (ddrval))
+ FatalError ("winAllocateFBPrimaryDD - Could not set "
+ "cooperative level\n");
+ }
+
+ /* Describe the primary surface */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ /* Create the primary surface */
+ ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
+ &ddsd,
+ &pScreenPriv->pddsPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ FatalError ("winAllocateFBPrimaryDD - Could not create primary "
+ "surface %08x\n", (unsigned int) ddrval);
+
+ ErrorF ("winAllocateFBPrimaryDD - Created primary\n");
+
+ /* Allocate a DD surface description for our screen privates */
+ pddsdPrimary = pScreenPriv->pddsdPrimary
+ = malloc (sizeof (DDSURFACEDESC));
+ if (pddsdPrimary == NULL)
+ FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
+ "description memory\n");
+ ZeroMemory (pddsdPrimary, sizeof (*pddsdPrimary));
+ pddsdPrimary->dwSize = sizeof (*pddsdPrimary);
+
+ /* Describe the offscreen surface to be created */
+ /*
+ * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
+ * as drawing, locking, and unlocking take forever
+ * with video memory surfaces. In addition,
+ * video memory is a somewhat scarce resource,
+ * so you shouldn't be allocating video memory when
+ * you have the option of using system memory instead.
+ */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ ddsd.dwHeight = pScreenInfo->dwHeight;
+ ddsd.dwWidth = pScreenInfo->dwWidth;
+
+ /* Create the shadow surface */
+ ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
+ &ddsd,
+ &pScreenPriv->pddsOffscreen,
+ NULL);
+ if (ddrval != DD_OK)
+ FatalError ("winAllocateFBPrimaryDD - Could not create shadow "
+ "surface\n");
+
+ ErrorF ("winAllocateFBPrimaryDD - Created offscreen\n");
+
+ /* Allocate a DD surface description for our screen privates */
+ pddsdOffscreen = pScreenPriv->pddsdOffscreen
+ = malloc (sizeof (DDSURFACEDESC));
+ if (pddsdOffscreen == NULL)
+ FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
+ "description memory\n");
+ ZeroMemory (pddsdOffscreen, sizeof (*pddsdOffscreen));
+ pddsdOffscreen->dwSize = sizeof (*pddsdOffscreen);
+
+ ErrorF ("winAllocateFBPrimaryDD - Locking primary\n");
+
+ /* Lock the primary surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
+ pScreenInfo->fFullScreen ? NULL:&rcClient,
+ pddsdPrimary,
+ DDLOCK_WAIT,
+ NULL);
+ if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL)
+ FatalError ("winAllocateFBPrimaryDD - Could not lock "
+ "primary surface\n");
+
+ ErrorF ("winAllocateFBPrimaryDD - Locked primary\n");
+
+ /* We don't know how to deal with anything other than RGB */
+ if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB))
+ FatalError ("winAllocateFBPrimaryDD - Color format other than RGB\n");
+
+ /* Grab the pitch from the surface desc */
+ pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8)
+ / pScreenInfo->dwBPP;
+
+ /* Save the pointer to our surface memory */
+ pScreenInfo->pfb = pddsdPrimary->lpSurface;
+
+ /* Grab the color depth and masks from the surface description */
+ pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask;
+ pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask;
+ pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask;
+
+ ErrorF ("winAllocateFBPrimaryDD - Returning\n");
+
+ return TRUE;
+}
+
+static void
+winFreeFBPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Free the offscreen surface, if there is one */
+ if (pScreenPriv->pddsOffscreen)
+ {
+ IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, NULL);
+ IDirectDrawSurface2_Release (pScreenPriv->pddsOffscreen);
+ pScreenPriv->pddsOffscreen = NULL;
+ }
+
+ /* Release the primary surface, if there is one */
+ if (pScreenPriv->pddsPrimary)
+ {
+ IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, NULL);
+ IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
+ pScreenPriv->pddsPrimary = NULL;
+ }
+
+ /* Free the DirectDraw object, if there is one */
+ if (pScreenPriv->pdd)
+ {
+ IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd);
+ IDirectDraw2_Release (pScreenPriv->pdd);
+ pScreenPriv->pdd = NULL;
+ }
+
+ /* Invalidate the ScreenInfo's fb pointer */
+ pScreenInfo->pfb = NULL;
+}
+
+static Bool
+winInitScreenPrimaryDD(ScreenPtr pScreen)
+{
+ return winAllocateFBPrimaryDD(pScreen);
+}
+
+/*
+ * Call the wrapped CloseScreen function.
+ *
+ * Free our resources and private structures.
+ */
+
+static Bool
+winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ Bool fReturn;
+
+ ErrorF ("winCloseScreenPrimaryDD - Freeing screen resources\n");
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /* Call the wrapped CloseScreen procedure */
+ WIN_UNWRAP(CloseScreen);
+ fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ winFreeFBPrimaryDD(pScreen);
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+ /* Kill our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free ((pointer) pScreenPriv);
+
+ return fReturn;
+}
+
+
+/*
+ * Tell mi what sort of visuals we need.
+ *
+ * Generally we only need one visual, as our screen can only
+ * handle one format at a time, I believe. You may want
+ * to verify that last sentence.
+ */
+
+static Bool
+winInitVisualsPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ DWORD dwRedBits, dwGreenBits, dwBlueBits;
+
+ /* Count the number of ones in each color mask */
+ dwRedBits = winCountBits (pScreenPriv->dwRedMask);
+ dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
+ dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
+
+ /* Store the maximum number of ones in a color mask as the bitsPerRGB */
+ if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwRedBits;
+ else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwGreenBits;
+ else
+ pScreenPriv->dwBitsPerRGB = dwBlueBits;
+
+ ErrorF ("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask,
+ (int) pScreenPriv->dwBitsPerRGB);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ TrueColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsPrimaryDD - "
+ "miSetVisualTypesAndMasks failed\n");
+ return FALSE;
+ }
+ break;
+
+ case 8:
+#if CYGDEBUG
+ winDebug ("winInitVisuals - Calling miSetVisualTypesAndMasks\n");
+#endif /* CYGDEBUG */
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ PseudoColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ PseudoColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsPrimaryDD - "
+ "miSetVisualTypesAndMasks failed\n");
+ return FALSE;
+ }
+#if CYGDEBUG
+ winDebug ("winInitVisualsPrimaryDD - Returned from "
+ "miSetVisualTypesAndMasks\n");
+#endif /* CYGDEBUG */
+ break;
+
+ default:
+ ErrorF ("winInitVisualsPrimaryDD - Unknown screen depth\n");
+ return FALSE;
+ }
+
+ ErrorF ("winInitVisualsPrimaryDD - Returning\n");
+
+ return TRUE;
+}
+
+
+static Bool
+winAdjustVideoModePrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc = NULL;
+ DWORD dwBPP;
+
+ /* We're in serious trouble if we can't get a DC */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModePrimaryDD - GetDC failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+
+ /* DirectDraw can only change the depth in fullscreen mode */
+ if (!(pScreenInfo->fFullScreen &&
+ (pScreenInfo->dwBPP != WIN_DEFAULT_BPP)))
+ {
+ /* Otherwise, We'll use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+
+ return TRUE;
+}
+
+
+/*
+ * We need to blit our offscreen fb to
+ * the screen when we are activated, and we need to point
+ * the fb code back to the primary surface memory.
+ */
+
+static Bool
+winActivateAppPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcSrc, rcClient;
+ HRESULT ddrval = DD_OK;
+
+ /* Check for errors */
+ if (pScreenPriv == NULL
+ || pScreenPriv->pddsPrimary == NULL
+ || pScreenPriv->pddsOffscreen == NULL)
+ return FALSE;
+
+ /* Check for do-nothing */
+ if (!pScreenPriv->fActive)
+ return TRUE;
+
+ /* We are activating */
+ ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsOffscreen);
+ if (ddrval == DD_OK)
+ {
+ IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen,
+ NULL);
+ /*
+ * We don't check for an error from Unlock, because it
+ * doesn't matter if the Unlock failed.
+ */
+ }
+
+ /* Restore both surfaces, just cause I like it that way */
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
+
+ /* Get client area in screen coords */
+ GetClientRect (pScreenPriv->hwndScreen, &rcClient);
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&rcClient, 2);
+
+ /* Setup a source rectangle */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcClient,
+ pScreenPriv->pddsOffscreen,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (ddrval != DD_OK)
+ FatalError ("winActivateAppPrimaryDD () - Failed blitting offscreen "
+ "surface to primary surface %08x\n", (unsigned int) ddrval);
+
+ /* Lock the primary surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
+ &rcClient,
+ pScreenPriv->pddsdPrimary,
+ DDLOCK_WAIT,
+ NULL);
+ if (ddrval != DD_OK
+ || pScreenPriv->pddsdPrimary->lpSurface == NULL)
+ FatalError ("winActivateAppPrimaryDD () - Could not lock "
+ "primary surface\n");
+
+ /* Notify FB of the new memory pointer */
+ winUpdateFBPointer (pScreen,
+ pScreenPriv->pddsdPrimary->lpSurface);
+
+ /*
+ * Register the Alt-Tab combo as a hotkey so we can copy
+ * the primary framebuffer before the display mode changes
+ */
+ RegisterHotKey (pScreenPriv->hwndScreen, 1, MOD_ALT, 9);
+
+ return TRUE;
+}
+
+
+/*
+ * Handle the Alt+Tab hotkey.
+ *
+ * We need to save the primary fb to an offscreen fb when
+ * we get deactivated, and point the fb code at the offscreen
+ * fb for the duration of the deactivation.
+ */
+
+static Bool
+winHotKeyAltTabPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcClient, rcSrc;
+ HRESULT ddrval = DD_OK;
+
+ ErrorF ("\nwinHotKeyAltTabPrimaryDD\n\n");
+
+ /* Alt+Tab was pressed, we will lose focus very soon */
+ pScreenPriv->fActive = FALSE;
+
+ /* Check for error conditions */
+ if (pScreenPriv->pddsPrimary == NULL
+ || pScreenPriv->pddsOffscreen == NULL)
+ return FALSE;
+
+ /* Get client area in screen coords */
+ GetClientRect (pScreenPriv->hwndScreen, &rcClient);
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&rcClient, 2);
+
+ /* Did we loose the primary surface? */
+ ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsPrimary);
+ if (ddrval == DD_OK)
+ {
+ ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ FatalError ("winHotKeyAltTabPrimaryDD - Failed unlocking primary "
+ "surface\n");
+ }
+
+ /* Setup a source rectangle */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Blit the primary surface to the offscreen surface */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
+ NULL, /* should be rcDest */
+ pScreenPriv->pddsPrimary,
+ NULL,
+ DDBLT_WAIT,
+ NULL);
+ if (ddrval == DDERR_SURFACELOST)
+ {
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
+
+ /* Blit the primary surface to the offscreen surface */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
+ NULL,
+ pScreenPriv->pddsPrimary,
+ NULL,
+ DDBLT_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ FatalError ("winHotKeyAltTabPrimaryDD - Failed blitting primary "
+ "surface to offscreen surface: %08x\n",
+ (unsigned int) ddrval);
+ }
+ else
+ {
+ FatalError ("winHotKeyAltTabPrimaryDD - Unknown error from "
+ "Blt: %08dx\n", (unsigned int) ddrval);
+ }
+
+ /* Lock the offscreen surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsOffscreen,
+ NULL,
+ pScreenPriv->pddsdOffscreen,
+ DDLOCK_WAIT,
+ NULL);
+ if (ddrval != DD_OK
+ || pScreenPriv->pddsdPrimary->lpSurface == NULL)
+ FatalError ("winHotKeyAltTabPrimaryDD - Could not lock "
+ "offscreen surface\n");
+
+ /* Notify FB of the new memory pointer */
+ winUpdateFBPointer (pScreen,
+ pScreenPriv->pddsdOffscreen->lpSurface);
+
+ /* Unregister our hotkey */
+ UnregisterHotKey (pScreenPriv->hwndScreen, 1);
+
+ return TRUE;
+}
+
+
+/* Set engine specific functions */
+Bool
+winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD;
+ pScreenPriv->pwinFreeFB = winFreeFBPrimaryDD;
+ pScreenPriv->pwinShadowUpdate = (winShadowUpdateProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinInitScreen = winInitScreenPrimaryDD;
+ pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD;
+ pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
+ pScreenPriv->pwinBltExposedRegions = (winBltExposedRegionsProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD;
+ pScreenPriv->pwinRedrawScreen = NULL;
+ pScreenPriv->pwinRealizeInstalledPalette = NULL;
+ pScreenPriv->pwinInstallColormap = NULL;
+ pScreenPriv->pwinStoreColors = NULL;
+ pScreenPriv->pwinCreateColormap = NULL;
+ pScreenPriv->pwinDestroyColormap = NULL;
+ pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD;
+ pScreenPriv->pwinCreatePrimarySurface = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinReleasePrimarySurface = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
+#ifdef XWIN_MULTIWINDOW
+ pScreenPriv->pwinFinishCreateWindowsWindow =
+ (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
+#endif
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winprocarg.c b/xorg-server/hw/xwin/winprocarg.c
index 39f0ee3e5..ddfe1f5b7 100644
--- a/xorg-server/hw/xwin/winprocarg.c
+++ b/xorg-server/hw/xwin/winprocarg.c
@@ -1,1256 +1,1217 @@
-/*
-
-Copyright 1993, 1998 The Open Group
-Copyright (C) Colin Harrison 2005-2008
-
-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_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-
-#include <../xfree86/common/xorgVersion.h>
-#include "win.h"
-#include "winconfig.h"
-#include "winmsg.h"
-
-/*
- * References to external symbols
- */
-
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboard;
-#endif
-/* globals required by callback function for monitor information */
-struct GetMonitorInfoData {
- int requestedMonitor;
- int monitorNum;
- Bool bUserSpecifiedMonitor;
- Bool bMonitorSpecifiedExists;
- int monitorOffsetX;
- int monitorOffsetY;
- int monitorHeight;
- int monitorWidth;
-};
-
-typedef wBOOL (*ENUMDISPLAYMONITORSPROC)(HDC,LPCRECT,MONITORENUMPROC,LPARAM);
-ENUMDISPLAYMONITORSPROC _EnumDisplayMonitors;
-
-wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data);
-
-static Bool QueryMonitor(int index, struct GetMonitorInfoData *data)
-{
- /* Load EnumDisplayMonitors from DLL */
- HMODULE user32;
- FARPROC func;
- user32 = LoadLibrary("user32.dll");
- if (user32 == NULL)
- {
- winW32Error(2, "Could not open user32.dll");
- return FALSE;
- }
- func = GetProcAddress(user32, "EnumDisplayMonitors");
- if (func == NULL)
- {
- winW32Error(2, "Could not resolve EnumDisplayMonitors: ");
- return FALSE;
- }
- _EnumDisplayMonitors = (ENUMDISPLAYMONITORSPROC)func;
-
- /* prepare data */
- if (data == NULL)
- return FALSE;
- memset(data, 0, sizeof(*data));
- data->requestedMonitor = index;
-
- /* query information */
- _EnumDisplayMonitors(NULL, NULL, getMonitorInfo, (LPARAM) data);
-
- /* cleanup */
- FreeLibrary(user32);
- return TRUE;
-}
-
-/*
- * Function prototypes
- */
-
-void
-winLogCommandLine (int argc, char *argv[]);
-
-void
-winLogVersionInfo (void);
-
-#ifdef DDXOSVERRORF
-void OsVendorVErrorF (const char *pszFormat, va_list va_args);
-#endif
-
-/*
- * Process arguments on the command line
- */
-
-static int iLastScreen = -1;
-static winScreenInfo defaultScreenInfo;
-
-static void
-winInitializeScreenDefaults(void)
-{
- DWORD dwWidth, dwHeight;
- static Bool fInitializedScreenDefaults = FALSE;
-
- /* Bail out early if default screen has already been initialized */
- if (fInitializedScreenDefaults)
- return;
-
- /* Zero the memory used for storing the screen info */
- memset(&defaultScreenInfo, 0, sizeof(winScreenInfo));
-
- /* Get default width and height */
- /*
- * NOTE: These defaults will cause the window to cover only
- * the primary monitor in the case that we have multiple monitors.
- */
- dwWidth = GetSystemMetrics (SM_CXSCREEN);
- dwHeight = GetSystemMetrics (SM_CYSCREEN);
-
- winErrorFVerb (2, "winInitializeScreenDefaults - w %d h %d\n",
- (int) dwWidth, (int) dwHeight);
-
- /* Set a default DPI, if no parameter was passed */
- if (monitorResolution == 0)
- monitorResolution = WIN_DEFAULT_DPI;
-
- defaultScreenInfo.dwWidth = dwWidth;
- defaultScreenInfo.dwHeight = dwHeight;
- defaultScreenInfo.dwUserWidth = dwWidth;
- defaultScreenInfo.dwUserHeight = dwHeight;
- defaultScreenInfo.fUserGaveHeightAndWidth = WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH;
- defaultScreenInfo.fUserGavePosition = FALSE;
- defaultScreenInfo.dwBPP = WIN_DEFAULT_BPP;
- defaultScreenInfo.dwClipUpdatesNBoxes = WIN_DEFAULT_CLIP_UPDATES_NBOXES;
-#ifdef XWIN_EMULATEPSEUDO
- defaultScreenInfo.fEmulatePseudo = WIN_DEFAULT_EMULATE_PSEUDO;
-#endif
- defaultScreenInfo.dwRefreshRate = WIN_DEFAULT_REFRESH;
- defaultScreenInfo.pfb = NULL;
- defaultScreenInfo.fFullScreen = FALSE;
- defaultScreenInfo.fDecoration = TRUE;
-#ifdef XWIN_MULTIWINDOWEXTWM
- defaultScreenInfo.fMWExtWM = FALSE;
- defaultScreenInfo.fInternalWM = FALSE;
-#endif
- defaultScreenInfo.fRootless = FALSE;
-#ifdef XWIN_MULTIWINDOW
- defaultScreenInfo.fMultiWindow = FALSE;
-#endif
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- defaultScreenInfo.fMultiMonitorOverride = FALSE;
-#endif
- defaultScreenInfo.fMultipleMonitors = FALSE;
- defaultScreenInfo.fLessPointer = FALSE;
- defaultScreenInfo.fScrollbars = FALSE;
- defaultScreenInfo.fNoTrayIcon = FALSE;
- defaultScreenInfo.iE3BTimeout = WIN_E3B_OFF;
- defaultScreenInfo.dwWidth_mm = (dwWidth / WIN_DEFAULT_DPI) * 25.4;
- defaultScreenInfo.dwHeight_mm = (dwHeight / WIN_DEFAULT_DPI) * 25.4;
- defaultScreenInfo.fUseWinKillKey = WIN_DEFAULT_WIN_KILL;
- defaultScreenInfo.fUseUnixKillKey = WIN_DEFAULT_UNIX_KILL;
- defaultScreenInfo.fIgnoreInput = FALSE;
- defaultScreenInfo.fExplicitScreen = FALSE;
-
- /* Note that the default screen has been initialized */
- fInitializedScreenDefaults = TRUE;
-}
-
-static void
-winInitializeScreen(int i)
-{
- winErrorFVerb (2, "winInitializeScreen - %d\n",i);
-
- /* Initialize default screen values, if needed */
- winInitializeScreenDefaults();
-
- /* Copy the default screen info */
- g_ScreenInfo[i] = defaultScreenInfo;
-
- /* Set the screen number */
- g_ScreenInfo[i].dwScreen = i;
-}
-
-void
-winInitializeScreens(int maxscreens)
-{
- int i;
- winErrorFVerb (2, "winInitializeScreens - %i\n", maxscreens);
-
- if (maxscreens > g_iNumScreens)
- {
- /* Reallocate the memory for DDX-specific screen info */
- g_ScreenInfo = realloc(g_ScreenInfo, maxscreens * sizeof (winScreenInfo));
-
- /* Set default values for any new screens */
- for (i = g_iNumScreens; i < maxscreens ; i++)
- winInitializeScreen(i);
-
- /* Keep a count of the number of screens */
- g_iNumScreens = maxscreens;
- }
-}
-
-/* See Porting Layer Definition - p. 57 */
-/*
- * INPUT
- * argv: pointer to an array of null-terminated strings, one for
- * each token in the X Server command line; the first token
- * is 'XWin.exe', or similar.
- * argc: a count of the number of tokens stored in argv.
- * i: a zero-based index into argv indicating the current token being
- * processed.
- *
- * OUTPUT
- * return: return the number of tokens processed correctly.
- *
- * NOTE
- * When looking for n tokens, check that i + n is less than argc. Or,
- * you may check if i is greater than or equal to argc, in which case
- * you should display the UseMsg () and return 0.
- */
-
-/* Check if enough arguments are given for the option */
-#define CHECK_ARGS(count) if (i + count >= argc) { UseMsg (); return 0; }
-
-/* Compare the current option with the string. */
-#define IS_OPTION(name) (strcmp (argv[i], name) == 0)
-
-int
-ddxProcessArgument (int argc, char *argv[], int i)
-{
- static Bool s_fBeenHere = FALSE;
- winScreenInfo *screenInfoPtr = NULL;
-
- /* Initialize once */
- if (!s_fBeenHere)
- {
-#ifdef DDXOSVERRORF
- /*
- * This initialises our hook into VErrorF () for catching log messages
- * that are generated before OsInit () is called.
- */
- OsVendorVErrorFProc = OsVendorVErrorF;
-#endif
-
- s_fBeenHere = TRUE;
-
- /* Initialize only if option is not -help */
- if (!IS_OPTION("-help") && !IS_OPTION("-h") && !IS_OPTION("--help") &&
- !IS_OPTION("-version") && !IS_OPTION("--version"))
- {
-
- /* Log the version information */
- winLogVersionInfo ();
-
- /* Log the command line */
- winLogCommandLine (argc, argv);
-
- /*
- * Initialize default screen settings. We have to do this before
- * OsVendorInit () gets called, otherwise we will overwrite
- * settings changed by parameters such as -fullscreen, etc.
- */
- winErrorFVerb (2, "ddxProcessArgument - Initializing default "
- "screens\n");
- winInitializeScreenDefaults();
- }
- }
-
-#if CYGDEBUG
- winDebug ("ddxProcessArgument - arg: %s\n", argv[i]);
-#endif
-
- /*
- * Look for the '-help' and similar options
- */
- if (IS_OPTION ("-help") || IS_OPTION("-h") || IS_OPTION("--help"))
- {
- /* Reset logfile. We don't need that helpmessage in the logfile */
- g_pszLogFile = NULL;
- g_fNoHelpMessageBox = TRUE;
- UseMsg();
- exit (0);
- return 1;
- }
-
- if (IS_OPTION ("-version") || IS_OPTION("--version"))
- {
- /* Reset logfile. We don't need that versioninfo in the logfile */
- g_pszLogFile = NULL;
- winLogVersionInfo ();
- exit (0);
- return 1;
- }
-
- /*
- * Look for the '-screen scr_num [width height]' argument
- */
- if (IS_OPTION ("-screen"))
- {
- int iArgsProcessed = 1;
- int nScreenNum;
- int iWidth, iHeight, iX, iY;
- int iMonitor;
-
-#if CYGDEBUG
- winDebug ("ddxProcessArgument - screen - argc: %d i: %d\n",
- argc, i);
-#endif
-
- /* Display the usage message if the argument is malformed */
- if (i + 1 >= argc)
- {
- return 0;
- }
-
- /* Grab screen number */
- nScreenNum = atoi (argv[i + 1]);
-
- /* Validate the specified screen number */
- if (nScreenNum < 0)
- {
- ErrorF ("ddxProcessArgument - screen - Invalid screen number %d\n",
- nScreenNum);
- UseMsg ();
- return 0;
- }
-
- /*
- Initialize default values for any new screens
-
- Note that default values can't change after a -screen option is
- seen, so it's safe to do this for each screen as it is introduced
- */
- winInitializeScreens(nScreenNum+1);
-
- /* look for @m where m is monitor number */
- if (i + 2 < argc
- && 1 == sscanf(argv[i + 2], "@%d", (int *) &iMonitor))
- {
- struct GetMonitorInfoData data;
- if (!QueryMonitor(iMonitor, &data))
- {
- ErrorF ("ddxProcessArgument - screen - "
- "Querying monitors is not supported on NT4 and Win95\n");
- } else if (data.bMonitorSpecifiedExists == TRUE)
- {
- winErrorFVerb(2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor);
- iArgsProcessed = 3;
- g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
- g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
- g_ScreenInfo[nScreenNum].dwWidth = data.monitorWidth;
- g_ScreenInfo[nScreenNum].dwHeight = data.monitorHeight;
- g_ScreenInfo[nScreenNum].dwUserWidth = data.monitorWidth;
- g_ScreenInfo[nScreenNum].dwUserHeight = data.monitorHeight;
- g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
- g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
- }
- else
- {
- /* monitor does not exist, error out */
- ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
- iMonitor);
- UseMsg ();
- exit (0);
- return 0;
- }
- }
-
- /* Look for 'WxD' or 'W D' */
- else if (i + 2 < argc
- && 2 == sscanf (argv[i + 2], "%dx%d",
- (int *) &iWidth,
- (int *) &iHeight))
- {
- winErrorFVerb (2, "ddxProcessArgument - screen - Found ``WxD'' arg\n");
- iArgsProcessed = 3;
- g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE;
- g_ScreenInfo[nScreenNum].dwWidth = iWidth;
- g_ScreenInfo[nScreenNum].dwHeight = iHeight;
- g_ScreenInfo[nScreenNum].dwUserWidth = iWidth;
- g_ScreenInfo[nScreenNum].dwUserHeight = iHeight;
- /* Look for WxD+X+Y */
- if (2 == sscanf (argv[i + 2], "%*dx%*d+%d+%d",
- (int *) &iX,
- (int *) &iY))
- {
- winErrorFVerb (2, "ddxProcessArgument - screen - Found ``X+Y'' arg\n");
- g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
- g_ScreenInfo[nScreenNum].dwInitialX = iX;
- g_ScreenInfo[nScreenNum].dwInitialY = iY;
-
- /* look for WxD+X+Y@m where m is monitor number. take X,Y to be offsets from monitor's root position */
- if (1 == sscanf (argv[i + 2], "%*dx%*d+%*d+%*d@%d",
- (int *) &iMonitor))
- {
- struct GetMonitorInfoData data;
- if (!QueryMonitor(iMonitor, &data))
- {
- ErrorF ("ddxProcessArgument - screen - "
- "Querying monitors is not supported on NT4 and Win95\n");
- } else if (data.bMonitorSpecifiedExists == TRUE)
- {
- g_ScreenInfo[nScreenNum].dwInitialX += data.monitorOffsetX;
- g_ScreenInfo[nScreenNum].dwInitialY += data.monitorOffsetY;
- }
- else
- {
- /* monitor does not exist, error out */
- ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
- iMonitor);
- UseMsg ();
- exit (0);
- return 0;
- }
-
- }
- }
-
- /* look for WxD@m where m is monitor number */
- else if (1 == sscanf(argv[i + 2], "%*dx%*d@%d",
- (int *) &iMonitor))
- {
- struct GetMonitorInfoData data;
- if (!QueryMonitor(iMonitor, &data))
- {
- ErrorF ("ddxProcessArgument - screen - "
- "Querying monitors is not supported on NT4 and Win95\n");
- } else if (data.bMonitorSpecifiedExists == TRUE)
- {
- winErrorFVerb (2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor);
- g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
- g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
- g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
- }
- else
- {
- /* monitor does not exist, error out */
- ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
- iMonitor);
- UseMsg ();
- exit (0);
- return 0;
- }
-
- }
- }
- else if (i + 3 < argc
- && 1 == sscanf (argv[i + 2], "%d",
- (int *) &iWidth)
- && 1 == sscanf (argv[i + 3], "%d",
- (int *) &iHeight))
- {
- winErrorFVerb (2, "ddxProcessArgument - screen - Found ``W D'' arg\n");
- iArgsProcessed = 4;
- g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE;
- g_ScreenInfo[nScreenNum].dwWidth = iWidth;
- g_ScreenInfo[nScreenNum].dwHeight = iHeight;
- g_ScreenInfo[nScreenNum].dwUserWidth = iWidth;
- g_ScreenInfo[nScreenNum].dwUserHeight = iHeight;
- if (i + 5 < argc
- && 1 == sscanf (argv[i + 4], "%d",
- (int *) &iX)
- && 1 == sscanf (argv[i + 5], "%d",
- (int *) &iY))
- {
- winErrorFVerb (2, "ddxProcessArgument - screen - Found ``X Y'' arg\n");
- iArgsProcessed = 6;
- g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
- g_ScreenInfo[nScreenNum].dwInitialX = iX;
- g_ScreenInfo[nScreenNum].dwInitialY = iY;
- }
- }
- else
- {
- winErrorFVerb (2, "ddxProcessArgument - screen - Did not find size arg. "
- "dwWidth: %d dwHeight: %d\n",
- (int) g_ScreenInfo[nScreenNum].dwWidth,
- (int) g_ScreenInfo[nScreenNum].dwHeight);
- iArgsProcessed = 2;
- g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
- }
-
- /* Calculate the screen width and height in millimeters */
- if (g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth)
- {
- g_ScreenInfo[nScreenNum].dwWidth_mm
- = (g_ScreenInfo[nScreenNum].dwWidth
- / monitorResolution) * 25.4;
- g_ScreenInfo[nScreenNum].dwHeight_mm
- = (g_ScreenInfo[nScreenNum].dwHeight
- / monitorResolution) * 25.4;
- }
-
- /* Flag that this screen was explicity specified by the user */
- g_ScreenInfo[nScreenNum].fExplicitScreen = TRUE;
-
- /*
- * Keep track of the last screen number seen, as parameters seen
- * before a screen number apply to all screens, whereas parameters
- * seen after a screen number apply to that screen number only.
- */
- iLastScreen = nScreenNum;
-
- return iArgsProcessed;
- }
-
-
- /*
- * Is this parameter attached to a screen or global?
- *
- * If the parameter is for all screens (appears before
- * any -screen option), store it in the default screen
- * info
- *
- * If the parameter is for a single screen (appears
- * after a -screen option), store it in the screen info
- * for that screen
- *
- */
- if (iLastScreen == -1)
- {
- screenInfoPtr = &defaultScreenInfo;
- }
- else
- {
- screenInfoPtr = &(g_ScreenInfo[iLastScreen]);
- }
-
- /*
- * Look for the '-engine n' argument
- */
- if (IS_OPTION ("-engine"))
- {
- DWORD dwEngine = 0;
- CARD8 c8OnBits = 0;
-
- /* Display the usage message if the argument is malformed */
- if (++i >= argc)
- {
- UseMsg ();
- return 0;
- }
-
- /* Grab the argument */
- dwEngine = atoi (argv[i]);
-
- /* Count the one bits in the engine argument */
- c8OnBits = winCountBits (dwEngine);
-
- /* Argument should only have a single bit on */
- if (c8OnBits != 1)
- {
- UseMsg ();
- return 0;
- }
-
- screenInfoPtr->dwEnginePreferred = dwEngine;
-
- /* Indicate that we have processed the argument */
- return 2;
- }
-
- /*
- * Look for the '-fullscreen' argument
- */
- if (IS_OPTION ("-fullscreen"))
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!screenInfoPtr->fMultiMonitorOverride)
- screenInfoPtr->fMultipleMonitors = FALSE;
-#endif
- screenInfoPtr->fFullScreen = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-lesspointer' argument
- */
- if (IS_OPTION ("-lesspointer"))
- {
- screenInfoPtr->fLessPointer = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-nodecoration' argument
- */
- if (IS_OPTION ("-nodecoration"))
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!screenInfoPtr->fMultiMonitorOverride)
- screenInfoPtr->fMultipleMonitors = FALSE;
-#endif
- screenInfoPtr->fDecoration = FALSE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- /*
- * Look for the '-mwextwm' argument
- */
- if (IS_OPTION ("-mwextwm"))
- {
- if (!screenInfoPtr->fMultiMonitorOverride)
- screenInfoPtr->fMultipleMonitors = TRUE;
- screenInfoPtr->fMWExtWM = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
- /*
- * Look for the '-internalwm' argument
- */
- if (IS_OPTION ("-internalwm"))
- {
- if (!screenInfoPtr->fMultiMonitorOverride)
- screenInfoPtr->fMultipleMonitors = TRUE;
- screenInfoPtr->fMWExtWM = TRUE;
- screenInfoPtr->fInternalWM = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-#endif
-
- /*
- * Look for the '-rootless' argument
- */
- if (IS_OPTION ("-rootless"))
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!screenInfoPtr->fMultiMonitorOverride)
- screenInfoPtr->fMultipleMonitors = FALSE;
-#endif
- screenInfoPtr->fRootless = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
-#ifdef XWIN_MULTIWINDOW
- /*
- * Look for the '-multiwindow' argument
- */
- if (IS_OPTION ("-multiwindow"))
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (!screenInfoPtr->fMultiMonitorOverride)
- screenInfoPtr->fMultipleMonitors = TRUE;
-#endif
- screenInfoPtr->fMultiWindow = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-#endif
-
- /*
- * Look for the '-multiplemonitors' argument
- */
- if (IS_OPTION ("-multiplemonitors")
- || IS_OPTION ("-multimonitors"))
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- screenInfoPtr->fMultiMonitorOverride = TRUE;
-#endif
- screenInfoPtr->fMultipleMonitors = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-nomultiplemonitors' argument
- */
- if (IS_OPTION ("-nomultiplemonitors")
- || IS_OPTION ("-nomultimonitors"))
- {
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- screenInfoPtr->fMultiMonitorOverride = TRUE;
-#endif
- screenInfoPtr->fMultipleMonitors = FALSE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
-
- /*
- * Look for the '-scrollbars' argument
- */
- if (IS_OPTION ("-scrollbars"))
- {
- screenInfoPtr->fScrollbars = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
-
-#ifdef XWIN_CLIPBOARD
- /*
- * Look for the '-clipboard' argument
- */
- if (IS_OPTION ("-clipboard"))
- {
- /* Now the default, we still accept the arg for backwards compatibility */
- g_fClipboard = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-noclipboard' argument
- */
- if (IS_OPTION ("-noclipboard"))
- {
- g_fClipboard = FALSE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-#endif
-
-
- /*
- * Look for the '-ignoreinput' argument
- */
- if (IS_OPTION ("-ignoreinput"))
- {
- screenInfoPtr->fIgnoreInput = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-emulate3buttons' argument
- */
- if (IS_OPTION ("-emulate3buttons"))
- {
- int iArgsProcessed = 1;
- int iE3BTimeout = WIN_DEFAULT_E3B_TIME;
-
- /* Grab the optional timeout value */
- if (i + 1 < argc
- && 1 == sscanf (argv[i + 1], "%d",
- &iE3BTimeout))
- {
- /* Indicate that we have processed the next argument */
- iArgsProcessed++;
- }
- else
- {
- /*
- * sscanf () won't modify iE3BTimeout if it doesn't find
- * the specified format; however, I want to be explicit
- * about setting the default timeout in such cases to
- * prevent some programs (me) from getting confused.
- */
- iE3BTimeout = WIN_DEFAULT_E3B_TIME;
- }
-
- screenInfoPtr->iE3BTimeout = iE3BTimeout;
-
- /* Indicate that we have processed this argument */
- return iArgsProcessed;
- }
-
- /*
- * Look for the '-depth n' argument
- */
- if (IS_OPTION ("-depth"))
- {
- DWORD dwBPP = 0;
-
- /* Display the usage message if the argument is malformed */
- if (++i >= argc)
- {
- UseMsg ();
- return 0;
- }
-
- /* Grab the argument */
- dwBPP = atoi (argv[i]);
-
- screenInfoPtr->dwBPP = dwBPP;
-
- /* Indicate that we have processed the argument */
- return 2;
- }
-
- /*
- * Look for the '-refresh n' argument
- */
- if (IS_OPTION ("-refresh"))
- {
- DWORD dwRefreshRate = 0;
-
- /* Display the usage message if the argument is malformed */
- if (++i >= argc)
- {
- UseMsg ();
- return 0;
- }
-
- /* Grab the argument */
- dwRefreshRate = atoi (argv[i]);
-
- screenInfoPtr->dwRefreshRate = dwRefreshRate;
-
- /* Indicate that we have processed the argument */
- return 2;
- }
-
- /*
- * Look for the '-clipupdates num_boxes' argument
- */
- if (IS_OPTION ("-clipupdates"))
- {
- DWORD dwNumBoxes = 0;
-
- /* Display the usage message if the argument is malformed */
- if (++i >= argc)
- {
- UseMsg ();
- return 0;
- }
-
- /* Grab the argument */
- dwNumBoxes = atoi (argv[i]);
-
- screenInfoPtr->dwClipUpdatesNBoxes = dwNumBoxes;
-
- /* Indicate that we have processed the argument */
- return 2;
- }
-
-#ifdef XWIN_EMULATEPSEUDO
- /*
- * Look for the '-emulatepseudo' argument
- */
- if (IS_OPTION ("-emulatepseudo"))
- {
- screenInfoPtr->fEmulatePseudo = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-#endif
-
- /*
- * Look for the '-nowinkill' argument
- */
- if (IS_OPTION ("-nowinkill"))
- {
- screenInfoPtr->fUseWinKillKey = FALSE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-winkill' argument
- */
- if (IS_OPTION ("-winkill"))
- {
- screenInfoPtr->fUseWinKillKey = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-nounixkill' argument
- */
- if (IS_OPTION ("-nounixkill"))
- {
- screenInfoPtr->fUseUnixKillKey = FALSE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-unixkill' argument
- */
- if (IS_OPTION ("-unixkill"))
- {
- screenInfoPtr->fUseUnixKillKey = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-notrayicon' argument
- */
- if (IS_OPTION ("-notrayicon"))
- {
- screenInfoPtr->fNoTrayIcon = TRUE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-trayicon' argument
- */
- if (IS_OPTION ("-trayicon"))
- {
- screenInfoPtr->fNoTrayIcon = FALSE;
-
- /* Indicate that we have processed this argument */
- return 1;
- }
-
- /*
- * Look for the '-fp' argument
- */
- if (IS_OPTION ("-fp"))
- {
- CHECK_ARGS (1);
- g_cmdline.fontPath = argv[++i];
- return 0; /* Let DIX parse this again */
- }
-
- /*
- * Look for the '-query' argument
- */
- if (IS_OPTION ("-query"))
- {
- CHECK_ARGS (1);
- g_fXdmcpEnabled = TRUE;
- g_pszQueryHost = argv[++i];
- return 0; /* Let DIX parse this again */
- }
-
- /*
- * Look for the '-auth' argument
- */
- if (IS_OPTION ("-auth"))
- {
- g_fAuthEnabled = TRUE;
- return 0; /* Let DIX parse this again */
- }
-
- /*
- * Look for the '-indirect' or '-broadcast' arguments
- */
- if (IS_OPTION ("-indirect")
- || IS_OPTION ("-broadcast"))
- {
- g_fXdmcpEnabled = TRUE;
- return 0; /* Let DIX parse this again */
- }
-
- /*
- * Look for the '-config' argument
- */
- if (IS_OPTION ("-config")
- || IS_OPTION ("-xf86config"))
- {
- CHECK_ARGS (1);
-#ifdef XWIN_XF86CONFIG
- g_cmdline.configFile = argv[++i];
-#else
- winMessageBoxF ("The %s option is not supported in this "
- "release.\n"
- "Ignoring this option and continuing.\n",
- MB_ICONINFORMATION,
- argv[i]);
-#endif
- return 2;
- }
-
- /*
- * Look for the '-configdir' argument
- */
- if (IS_OPTION ("-configdir"))
- {
- CHECK_ARGS (1);
-#ifdef XWIN_XF86CONFIG
- g_cmdline.configDir = argv[++i];
-#else
- winMessageBoxF ("The %s option is not supported in this "
- "release.\n"
- "Ignoring this option and continuing.\n",
- MB_ICONINFORMATION,
- argv[i]);
-#endif
- return 2;
- }
-
- /*
- * Look for the '-keyboard' argument
- */
- if (IS_OPTION ("-keyboard"))
- {
-#ifdef XWIN_XF86CONFIG
- CHECK_ARGS (1);
- g_cmdline.keyboard = argv[++i];
-#else
- winMessageBoxF ("The -keyboard option is not supported in this "
- "release.\n"
- "Ignoring this option and continuing.\n",
- MB_ICONINFORMATION);
-#endif
- return 2;
- }
-
- /*
- * Look for the '-logfile' argument
- */
- if (IS_OPTION ("-logfile"))
- {
- CHECK_ARGS (1);
- g_pszLogFile = argv[++i];
-#ifdef RELOCATE_PROJECTROOT
- g_fLogFileChanged = TRUE;
-#endif
- return 2;
- }
-
- /*
- * Look for the '-logverbose' argument
- */
- if (IS_OPTION ("-logverbose"))
- {
- CHECK_ARGS (1);
- g_iLogVerbose = atoi(argv[++i]);
- return 2;
- }
-
-#ifdef XWIN_CLIPBOARD
- /*
- * Look for the '-nounicodeclipboard' argument
- */
- if (IS_OPTION ("-nounicodeclipboard"))
- {
- g_fUnicodeClipboard = FALSE;
- /* Indicate that we have processed the argument */
- return 1;
- }
-#endif
-
- if (IS_OPTION ("-xkbrules"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbRules = argv[++i];
- return 2;
- }
- if (IS_OPTION ("-xkbmodel"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbModel = argv[++i];
- return 2;
- }
- if (IS_OPTION ("-xkblayout"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbLayout = argv[++i];
- return 2;
- }
- if (IS_OPTION ("-xkbvariant"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbVariant = argv[++i];
- return 2;
- }
- if (IS_OPTION ("-xkboptions"))
- {
- CHECK_ARGS (1);
- g_cmdline.xkbOptions = argv[++i];
- return 2;
- }
-
- if (IS_OPTION ("-keyhook"))
- {
- g_fKeyboardHookLL = TRUE;
- return 1;
- }
-
- if (IS_OPTION ("-nokeyhook"))
- {
- g_fKeyboardHookLL = FALSE;
- return 1;
- }
-
- if (IS_OPTION ("-swcursor"))
- {
- g_fSoftwareCursor = TRUE;
- return 1;
- }
-
- if (IS_OPTION ("-silent-dup-error"))
- {
- g_fSilentDupError = TRUE;
- return 1;
- }
-
- if (IS_OPTION("-wgl"))
- {
- g_fNativeGl = TRUE;
- return 1;
- }
-
- if (IS_OPTION("-nowgl"))
- {
- g_fNativeGl = FALSE;
- return 1;
- }
-
- return 0;
-}
-
-
-/*
- * winLogCommandLine - Write entire command line to the log file
- */
-
-void
-winLogCommandLine (int argc, char *argv[])
-{
- int i;
- int iSize = 0;
- int iCurrLen = 0;
-
-#define CHARS_PER_LINE 60
-
- /* Bail if command line has already been logged */
- if (g_pszCommandLine)
- return;
-
- /* Count how much memory is needed for concatenated command line */
- for (i = 0, iCurrLen = 0; i < argc; ++i)
- if (argv[i])
- {
- /* Adds two characters for lines that overflow */
- if ((strlen (argv[i]) < CHARS_PER_LINE
- && iCurrLen + strlen (argv[i]) > CHARS_PER_LINE)
- || strlen (argv[i]) > CHARS_PER_LINE)
- {
- iCurrLen = 0;
- iSize += 2;
- }
-
- /* Add space for item and trailing space */
- iSize += strlen (argv[i]) + 1;
-
- /* Update current line length */
- iCurrLen += strlen (argv[i]);
- }
-
- /* Allocate memory for concatenated command line */
- g_pszCommandLine = malloc (iSize + 1);
- if (!g_pszCommandLine)
- FatalError ("winLogCommandLine - Could not allocate memory for "
- "command line string. Exiting.\n");
-
- /* Set first character to concatenated command line to null */
- g_pszCommandLine[0] = '\0';
-
- /* Loop through all args */
- for (i = 0, iCurrLen = 0; i < argc; ++i)
- {
- /* Add a character for lines that overflow */
- if ((strlen (argv[i]) < CHARS_PER_LINE
- && iCurrLen + strlen (argv[i]) > CHARS_PER_LINE)
- || strlen (argv[i]) > CHARS_PER_LINE)
- {
- iCurrLen = 0;
-
- /* Add line break if it fits */
- strncat (g_pszCommandLine, "\n ", iSize - strlen (g_pszCommandLine));
- }
-
- strncat (g_pszCommandLine, argv[i], iSize - strlen (g_pszCommandLine));
- strncat (g_pszCommandLine, " ", iSize - strlen (g_pszCommandLine));
-
- /* Save new line length */
- iCurrLen += strlen (argv[i]);
- }
-
- ErrorF ("XWin was started with the following command line:\n\n"
- "%s\n\n", g_pszCommandLine);
-}
-
-
-/*
- * winLogVersionInfo - Log Cygwin/X version information
- */
-
-void
-winLogVersionInfo (void)
-{
- static Bool s_fBeenHere = FALSE;
-
- if (s_fBeenHere)
- return;
- s_fBeenHere = TRUE;
-
- ErrorF ("Welcome to the XWin X Server\n");
- ErrorF ("Vendor: %s\n", XVENDORNAME);
- ErrorF ("Release: %d.%d.%d.%d (%d)\n", XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP, XORG_VERSION_CURRENT);
- ErrorF ("%s\n\n", BUILDERSTRING);
- ErrorF ("Contact: %s\n", BUILDERADDR);
-}
-
-/*
- * getMonitorInfo - callback function used to return information from the enumeration of monitors attached
- */
-
-wBOOL CALLBACK getMonitorInfo(HMONITOR hMonitor, HDC hdc, LPRECT rect, LPARAM _data)
-{
- struct GetMonitorInfoData* data = (struct GetMonitorInfoData*)_data;
- // only get data for monitor number specified in <data>
- data->monitorNum++;
- if (data->monitorNum == data->requestedMonitor)
- {
- data->bMonitorSpecifiedExists = TRUE;
- data->monitorOffsetX = rect->left;
- data->monitorOffsetY = rect->top;
- data->monitorHeight = rect->bottom - rect->top;
- data->monitorWidth = rect->right - rect->left;
- return FALSE;
- }
- return TRUE;
-}
+/*
+
+Copyright 1993, 1998 The Open Group
+Copyright (C) Colin Harrison 2005-2008
+
+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_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <../xfree86/common/xorgVersion.h>
+#include "win.h"
+#include "winconfig.h"
+#include "winmsg.h"
+#include "winmonitors.h"
+
+/*
+ * References to external symbols
+ */
+
+#ifdef XWIN_CLIPBOARD
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboard;
+#endif
+
+/*
+ * Function prototypes
+ */
+
+void
+winLogCommandLine (int argc, char *argv[]);
+
+void
+winLogVersionInfo (void);
+
+#ifdef DDXOSVERRORF
+void OsVendorVErrorF (const char *pszFormat, va_list va_args);
+#endif
+
+/*
+ * Process arguments on the command line
+ */
+
+static int iLastScreen = -1;
+static winScreenInfo defaultScreenInfo;
+
+static void
+winInitializeScreenDefaults(void)
+{
+ DWORD dwWidth, dwHeight;
+ static Bool fInitializedScreenDefaults = FALSE;
+
+ /* Bail out early if default screen has already been initialized */
+ if (fInitializedScreenDefaults)
+ return;
+
+ /* Zero the memory used for storing the screen info */
+ memset(&defaultScreenInfo, 0, sizeof(winScreenInfo));
+
+ /* Get default width and height */
+ /*
+ * NOTE: These defaults will cause the window to cover only
+ * the primary monitor in the case that we have multiple monitors.
+ */
+ dwWidth = GetSystemMetrics (SM_CXSCREEN);
+ dwHeight = GetSystemMetrics (SM_CYSCREEN);
+
+ winErrorFVerb (2, "winInitializeScreenDefaults - w %d h %d\n",
+ (int) dwWidth, (int) dwHeight);
+
+ /* Set a default DPI, if no parameter was passed */
+ if (monitorResolution == 0)
+ monitorResolution = WIN_DEFAULT_DPI;
+
+ defaultScreenInfo.iMonitor = 1;
+ defaultScreenInfo.dwWidth = dwWidth;
+ defaultScreenInfo.dwHeight = dwHeight;
+ defaultScreenInfo.dwUserWidth = dwWidth;
+ defaultScreenInfo.dwUserHeight = dwHeight;
+ defaultScreenInfo.fUserGaveHeightAndWidth = WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH;
+ defaultScreenInfo.fUserGavePosition = FALSE;
+ defaultScreenInfo.dwBPP = WIN_DEFAULT_BPP;
+ defaultScreenInfo.dwClipUpdatesNBoxes = WIN_DEFAULT_CLIP_UPDATES_NBOXES;
+#ifdef XWIN_EMULATEPSEUDO
+ defaultScreenInfo.fEmulatePseudo = WIN_DEFAULT_EMULATE_PSEUDO;
+#endif
+ defaultScreenInfo.dwRefreshRate = WIN_DEFAULT_REFRESH;
+ defaultScreenInfo.pfb = NULL;
+ defaultScreenInfo.fFullScreen = FALSE;
+ defaultScreenInfo.fDecoration = TRUE;
+#ifdef XWIN_MULTIWINDOWEXTWM
+ defaultScreenInfo.fMWExtWM = FALSE;
+ defaultScreenInfo.fInternalWM = FALSE;
+#endif
+ defaultScreenInfo.fRootless = FALSE;
+#ifdef XWIN_MULTIWINDOW
+ defaultScreenInfo.fMultiWindow = FALSE;
+#endif
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ defaultScreenInfo.fMultiMonitorOverride = FALSE;
+#endif
+ defaultScreenInfo.fMultipleMonitors = FALSE;
+ defaultScreenInfo.fLessPointer = FALSE;
+ defaultScreenInfo.iResizeMode = notAllowed;
+ defaultScreenInfo.fNoTrayIcon = FALSE;
+ defaultScreenInfo.iE3BTimeout = WIN_E3B_OFF;
+ defaultScreenInfo.fUseWinKillKey = WIN_DEFAULT_WIN_KILL;
+ defaultScreenInfo.fUseUnixKillKey = WIN_DEFAULT_UNIX_KILL;
+ defaultScreenInfo.fIgnoreInput = FALSE;
+ defaultScreenInfo.fExplicitScreen = FALSE;
+
+ /* Note that the default screen has been initialized */
+ fInitializedScreenDefaults = TRUE;
+}
+
+static void
+winInitializeScreen(int i)
+{
+ winErrorFVerb (2, "winInitializeScreen - %d\n",i);
+
+ /* Initialize default screen values, if needed */
+ winInitializeScreenDefaults();
+
+ /* Copy the default screen info */
+ g_ScreenInfo[i] = defaultScreenInfo;
+
+ /* Set the screen number */
+ g_ScreenInfo[i].dwScreen = i;
+}
+
+void
+winInitializeScreens(int maxscreens)
+{
+ int i;
+ winErrorFVerb (2, "winInitializeScreens - %i\n", maxscreens);
+
+ if (maxscreens > g_iNumScreens)
+ {
+ /* Reallocate the memory for DDX-specific screen info */
+ g_ScreenInfo = realloc(g_ScreenInfo, maxscreens * sizeof (winScreenInfo));
+
+ /* Set default values for any new screens */
+ for (i = g_iNumScreens; i < maxscreens ; i++)
+ winInitializeScreen(i);
+
+ /* Keep a count of the number of screens */
+ g_iNumScreens = maxscreens;
+ }
+}
+
+/* See Porting Layer Definition - p. 57 */
+/*
+ * INPUT
+ * argv: pointer to an array of null-terminated strings, one for
+ * each token in the X Server command line; the first token
+ * is 'XWin.exe', or similar.
+ * argc: a count of the number of tokens stored in argv.
+ * i: a zero-based index into argv indicating the current token being
+ * processed.
+ *
+ * OUTPUT
+ * return: return the number of tokens processed correctly.
+ *
+ * NOTE
+ * When looking for n tokens, check that i + n is less than argc. Or,
+ * you may check if i is greater than or equal to argc, in which case
+ * you should display the UseMsg () and return 0.
+ */
+
+/* Check if enough arguments are given for the option */
+#define CHECK_ARGS(count) if (i + count >= argc) { UseMsg (); return 0; }
+
+/* Compare the current option with the string. */
+#define IS_OPTION(name) (strcmp (argv[i], name) == 0)
+
+int
+ddxProcessArgument (int argc, char *argv[], int i)
+{
+ static Bool s_fBeenHere = FALSE;
+ winScreenInfo *screenInfoPtr = NULL;
+
+ /* Initialize once */
+ if (!s_fBeenHere)
+ {
+#ifdef DDXOSVERRORF
+ /*
+ * This initialises our hook into VErrorF () for catching log messages
+ * that are generated before OsInit () is called.
+ */
+ OsVendorVErrorFProc = OsVendorVErrorF;
+#endif
+
+ s_fBeenHere = TRUE;
+
+ /* Initialize only if option is not -help */
+ if (!IS_OPTION("-help") && !IS_OPTION("-h") && !IS_OPTION("--help") &&
+ !IS_OPTION("-version") && !IS_OPTION("--version"))
+ {
+
+ /* Log the version information */
+ winLogVersionInfo ();
+
+ /* Log the command line */
+ winLogCommandLine (argc, argv);
+
+ /*
+ * Initialize default screen settings. We have to do this before
+ * OsVendorInit () gets called, otherwise we will overwrite
+ * settings changed by parameters such as -fullscreen, etc.
+ */
+ winErrorFVerb (2, "ddxProcessArgument - Initializing default "
+ "screens\n");
+ winInitializeScreenDefaults();
+ }
+ }
+
+#if CYGDEBUG
+ winDebug ("ddxProcessArgument - arg: %s\n", argv[i]);
+#endif
+
+ /*
+ * Look for the '-help' and similar options
+ */
+ if (IS_OPTION ("-help") || IS_OPTION("-h") || IS_OPTION("--help"))
+ {
+ /* Reset logfile. We don't need that helpmessage in the logfile */
+ g_pszLogFile = NULL;
+ g_fNoHelpMessageBox = TRUE;
+ UseMsg();
+ exit (0);
+ return 1;
+ }
+
+ if (IS_OPTION ("-version") || IS_OPTION("--version"))
+ {
+ /* Reset logfile. We don't need that versioninfo in the logfile */
+ g_pszLogFile = NULL;
+ winLogVersionInfo ();
+ exit (0);
+ return 1;
+ }
+
+ /*
+ * Look for the '-screen scr_num [width height]' argument
+ */
+ if (IS_OPTION ("-screen"))
+ {
+ int iArgsProcessed = 1;
+ int nScreenNum;
+ int iWidth, iHeight, iX, iY;
+ int iMonitor;
+
+#if CYGDEBUG
+ winDebug ("ddxProcessArgument - screen - argc: %d i: %d\n",
+ argc, i);
+#endif
+
+ /* Display the usage message if the argument is malformed */
+ if (i + 1 >= argc)
+ {
+ return 0;
+ }
+
+ /* Grab screen number */
+ nScreenNum = atoi (argv[i + 1]);
+
+ /* Validate the specified screen number */
+ if (nScreenNum < 0)
+ {
+ ErrorF ("ddxProcessArgument - screen - Invalid screen number %d\n",
+ nScreenNum);
+ UseMsg ();
+ return 0;
+ }
+
+ /*
+ Initialize default values for any new screens
+
+ Note that default values can't change after a -screen option is
+ seen, so it's safe to do this for each screen as it is introduced
+ */
+ winInitializeScreens(nScreenNum+1);
+
+ /* look for @m where m is monitor number */
+ if (i + 2 < argc
+ && 1 == sscanf(argv[i + 2], "@%d", (int *) &iMonitor))
+ {
+ struct GetMonitorInfoData data;
+ if (!QueryMonitor(iMonitor, &data))
+ {
+ ErrorF ("ddxProcessArgument - screen - "
+ "Querying monitors is not supported on NT4 and Win95\n");
+ } else if (data.bMonitorSpecifiedExists == TRUE)
+ {
+ winErrorFVerb(2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor);
+ iArgsProcessed = 3;
+ g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
+ g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
+ g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
+ g_ScreenInfo[nScreenNum].dwWidth = data.monitorWidth;
+ g_ScreenInfo[nScreenNum].dwHeight = data.monitorHeight;
+ g_ScreenInfo[nScreenNum].dwUserWidth = data.monitorWidth;
+ g_ScreenInfo[nScreenNum].dwUserHeight = data.monitorHeight;
+ g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
+ g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
+ }
+ else
+ {
+ /* monitor does not exist, error out */
+ ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
+ iMonitor);
+ UseMsg ();
+ exit (0);
+ return 0;
+ }
+ }
+
+ /* Look for 'WxD' or 'W D' */
+ else if (i + 2 < argc
+ && 2 == sscanf (argv[i + 2], "%dx%d",
+ (int *) &iWidth,
+ (int *) &iHeight))
+ {
+ winErrorFVerb (2, "ddxProcessArgument - screen - Found ``WxD'' arg\n");
+ iArgsProcessed = 3;
+ g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE;
+ g_ScreenInfo[nScreenNum].dwWidth = iWidth;
+ g_ScreenInfo[nScreenNum].dwHeight = iHeight;
+ g_ScreenInfo[nScreenNum].dwUserWidth = iWidth;
+ g_ScreenInfo[nScreenNum].dwUserHeight = iHeight;
+ /* Look for WxD+X+Y */
+ if (2 == sscanf (argv[i + 2], "%*dx%*d+%d+%d",
+ (int *) &iX,
+ (int *) &iY))
+ {
+ winErrorFVerb (2, "ddxProcessArgument - screen - Found ``X+Y'' arg\n");
+ g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
+ g_ScreenInfo[nScreenNum].dwInitialX = iX;
+ g_ScreenInfo[nScreenNum].dwInitialY = iY;
+
+ /* look for WxD+X+Y@m where m is monitor number. take X,Y to be offsets from monitor's root position */
+ if (1 == sscanf (argv[i + 2], "%*dx%*d+%*d+%*d@%d",
+ (int *) &iMonitor))
+ {
+ struct GetMonitorInfoData data;
+ if (!QueryMonitor(iMonitor, &data))
+ {
+ ErrorF ("ddxProcessArgument - screen - "
+ "Querying monitors is not supported on NT4 and Win95\n");
+ } else if (data.bMonitorSpecifiedExists == TRUE)
+ {
+ g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
+ g_ScreenInfo[nScreenNum].dwInitialX += data.monitorOffsetX;
+ g_ScreenInfo[nScreenNum].dwInitialY += data.monitorOffsetY;
+ }
+ else
+ {
+ /* monitor does not exist, error out */
+ ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
+ iMonitor);
+ UseMsg ();
+ exit (0);
+ return 0;
+ }
+
+ }
+ }
+
+ /* look for WxD@m where m is monitor number */
+ else if (1 == sscanf(argv[i + 2], "%*dx%*d@%d",
+ (int *) &iMonitor))
+ {
+ struct GetMonitorInfoData data;
+ if (!QueryMonitor(iMonitor, &data))
+ {
+ ErrorF ("ddxProcessArgument - screen - "
+ "Querying monitors is not supported on NT4 and Win95\n");
+ } else if (data.bMonitorSpecifiedExists == TRUE)
+ {
+ winErrorFVerb (2, "ddxProcessArgument - screen - Found Valid ``@Monitor'' = %d arg\n", iMonitor);
+ g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
+ g_ScreenInfo[nScreenNum].iMonitor = iMonitor;
+ g_ScreenInfo[nScreenNum].dwInitialX = data.monitorOffsetX;
+ g_ScreenInfo[nScreenNum].dwInitialY = data.monitorOffsetY;
+ }
+ else
+ {
+ /* monitor does not exist, error out */
+ ErrorF ("ddxProcessArgument - screen - Invalid monitor number %d\n",
+ iMonitor);
+ UseMsg ();
+ exit (0);
+ return 0;
+ }
+
+ }
+ }
+ else if (i + 3 < argc
+ && 1 == sscanf (argv[i + 2], "%d",
+ (int *) &iWidth)
+ && 1 == sscanf (argv[i + 3], "%d",
+ (int *) &iHeight))
+ {
+ winErrorFVerb (2, "ddxProcessArgument - screen - Found ``W D'' arg\n");
+ iArgsProcessed = 4;
+ g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = TRUE;
+ g_ScreenInfo[nScreenNum].dwWidth = iWidth;
+ g_ScreenInfo[nScreenNum].dwHeight = iHeight;
+ g_ScreenInfo[nScreenNum].dwUserWidth = iWidth;
+ g_ScreenInfo[nScreenNum].dwUserHeight = iHeight;
+ if (i + 5 < argc
+ && 1 == sscanf (argv[i + 4], "%d",
+ (int *) &iX)
+ && 1 == sscanf (argv[i + 5], "%d",
+ (int *) &iY))
+ {
+ winErrorFVerb (2, "ddxProcessArgument - screen - Found ``X Y'' arg\n");
+ iArgsProcessed = 6;
+ g_ScreenInfo[nScreenNum].fUserGavePosition = TRUE;
+ g_ScreenInfo[nScreenNum].dwInitialX = iX;
+ g_ScreenInfo[nScreenNum].dwInitialY = iY;
+ }
+ }
+ else
+ {
+ winErrorFVerb (2, "ddxProcessArgument - screen - Did not find size arg. "
+ "dwWidth: %d dwHeight: %d\n",
+ (int) g_ScreenInfo[nScreenNum].dwWidth,
+ (int) g_ScreenInfo[nScreenNum].dwHeight);
+ iArgsProcessed = 2;
+ g_ScreenInfo[nScreenNum].fUserGaveHeightAndWidth = FALSE;
+ }
+
+ /* Flag that this screen was explicity specified by the user */
+ g_ScreenInfo[nScreenNum].fExplicitScreen = TRUE;
+
+ /*
+ * Keep track of the last screen number seen, as parameters seen
+ * before a screen number apply to all screens, whereas parameters
+ * seen after a screen number apply to that screen number only.
+ */
+ iLastScreen = nScreenNum;
+
+ return iArgsProcessed;
+ }
+
+
+ /*
+ * Is this parameter attached to a screen or global?
+ *
+ * If the parameter is for all screens (appears before
+ * any -screen option), store it in the default screen
+ * info
+ *
+ * If the parameter is for a single screen (appears
+ * after a -screen option), store it in the screen info
+ * for that screen
+ *
+ */
+ if (iLastScreen == -1)
+ {
+ screenInfoPtr = &defaultScreenInfo;
+ }
+ else
+ {
+ screenInfoPtr = &(g_ScreenInfo[iLastScreen]);
+ }
+
+ /*
+ * Look for the '-engine n' argument
+ */
+ if (IS_OPTION ("-engine"))
+ {
+ DWORD dwEngine = 0;
+ CARD8 c8OnBits = 0;
+
+ /* Display the usage message if the argument is malformed */
+ if (++i >= argc)
+ {
+ UseMsg ();
+ return 0;
+ }
+
+ /* Grab the argument */
+ dwEngine = atoi (argv[i]);
+
+ /* Count the one bits in the engine argument */
+ c8OnBits = winCountBits (dwEngine);
+
+ /* Argument should only have a single bit on */
+ if (c8OnBits != 1)
+ {
+ UseMsg ();
+ return 0;
+ }
+
+ screenInfoPtr->dwEnginePreferred = dwEngine;
+
+ /* Indicate that we have processed the argument */
+ return 2;
+ }
+
+ /*
+ * Look for the '-fullscreen' argument
+ */
+ if (IS_OPTION ("-fullscreen"))
+ {
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ if (!screenInfoPtr->fMultiMonitorOverride)
+ screenInfoPtr->fMultipleMonitors = FALSE;
+#endif
+ screenInfoPtr->fFullScreen = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-lesspointer' argument
+ */
+ if (IS_OPTION ("-lesspointer"))
+ {
+ screenInfoPtr->fLessPointer = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-nodecoration' argument
+ */
+ if (IS_OPTION ("-nodecoration"))
+ {
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ if (!screenInfoPtr->fMultiMonitorOverride)
+ screenInfoPtr->fMultipleMonitors = FALSE;
+#endif
+ screenInfoPtr->fDecoration = FALSE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ /*
+ * Look for the '-mwextwm' argument
+ */
+ if (IS_OPTION ("-mwextwm"))
+ {
+ if (!screenInfoPtr->fMultiMonitorOverride)
+ screenInfoPtr->fMultipleMonitors = TRUE;
+ screenInfoPtr->fMWExtWM = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+ /*
+ * Look for the '-internalwm' argument
+ */
+ if (IS_OPTION ("-internalwm"))
+ {
+ if (!screenInfoPtr->fMultiMonitorOverride)
+ screenInfoPtr->fMultipleMonitors = TRUE;
+ screenInfoPtr->fMWExtWM = TRUE;
+ screenInfoPtr->fInternalWM = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+#endif
+
+ /*
+ * Look for the '-rootless' argument
+ */
+ if (IS_OPTION ("-rootless"))
+ {
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ if (!screenInfoPtr->fMultiMonitorOverride)
+ screenInfoPtr->fMultipleMonitors = FALSE;
+#endif
+ screenInfoPtr->fRootless = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+#ifdef XWIN_MULTIWINDOW
+ /*
+ * Look for the '-multiwindow' argument
+ */
+ if (IS_OPTION ("-multiwindow"))
+ {
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ if (!screenInfoPtr->fMultiMonitorOverride)
+ screenInfoPtr->fMultipleMonitors = TRUE;
+#endif
+ screenInfoPtr->fMultiWindow = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+#endif
+
+ /*
+ * Look for the '-multiplemonitors' argument
+ */
+ if (IS_OPTION ("-multiplemonitors")
+ || IS_OPTION ("-multimonitors"))
+ {
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ screenInfoPtr->fMultiMonitorOverride = TRUE;
+#endif
+ screenInfoPtr->fMultipleMonitors = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-nomultiplemonitors' argument
+ */
+ if (IS_OPTION ("-nomultiplemonitors")
+ || IS_OPTION ("-nomultimonitors"))
+ {
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ screenInfoPtr->fMultiMonitorOverride = TRUE;
+#endif
+ screenInfoPtr->fMultipleMonitors = FALSE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+
+ /*
+ * Look for the '-scrollbars' argument
+ */
+ if (IS_OPTION ("-scrollbars"))
+ {
+
+ screenInfoPtr->iResizeMode = resizeWithScrollbars;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-resize' argument
+ */
+ if (IS_OPTION ("-resize") || IS_OPTION ("-noresize") ||
+ (strncmp(argv[i], "-resize=",strlen("-resize=")) == 0))
+ {
+ winResizeMode mode;
+
+ if (IS_OPTION ("-resize"))
+ mode = resizeWithRandr;
+ else if (IS_OPTION ("-noresize"))
+ mode = notAllowed;
+ else if (strncmp(argv[i], "-resize=",strlen("-resize=")) == 0)
+ {
+ char *option = argv[i] + strlen("-resize=");
+ if (strcmp(option, "randr") == 0)
+ mode = resizeWithRandr;
+ else if (strcmp(option, "scrollbars") == 0)
+ mode = resizeWithScrollbars;
+ else if (strcmp(option, "none") == 0)
+ mode = notAllowed;
+ else
+ {
+ ErrorF ("ddxProcessArgument - resize - Invalid resize mode %s\n", option);
+ return 0;
+ }
+ }
+ else
+ {
+ ErrorF ("ddxProcessArgument - resize - Invalid resize option %s\n", argv[i]);
+ return 0;
+ }
+
+ screenInfoPtr->iResizeMode = mode;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+#ifdef XWIN_CLIPBOARD
+ /*
+ * Look for the '-clipboard' argument
+ */
+ if (IS_OPTION ("-clipboard"))
+ {
+ /* Now the default, we still accept the arg for backwards compatibility */
+ g_fClipboard = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-noclipboard' argument
+ */
+ if (IS_OPTION ("-noclipboard"))
+ {
+ g_fClipboard = FALSE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+#endif
+
+
+ /*
+ * Look for the '-ignoreinput' argument
+ */
+ if (IS_OPTION ("-ignoreinput"))
+ {
+ screenInfoPtr->fIgnoreInput = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-emulate3buttons' argument
+ */
+ if (IS_OPTION ("-emulate3buttons"))
+ {
+ int iArgsProcessed = 1;
+ int iE3BTimeout = WIN_DEFAULT_E3B_TIME;
+
+ /* Grab the optional timeout value */
+ if (i + 1 < argc
+ && 1 == sscanf (argv[i + 1], "%d",
+ &iE3BTimeout))
+ {
+ /* Indicate that we have processed the next argument */
+ iArgsProcessed++;
+ }
+ else
+ {
+ /*
+ * sscanf () won't modify iE3BTimeout if it doesn't find
+ * the specified format; however, I want to be explicit
+ * about setting the default timeout in such cases to
+ * prevent some programs (me) from getting confused.
+ */
+ iE3BTimeout = WIN_DEFAULT_E3B_TIME;
+ }
+
+ screenInfoPtr->iE3BTimeout = iE3BTimeout;
+
+ /* Indicate that we have processed this argument */
+ return iArgsProcessed;
+ }
+
+ /*
+ * Look for the '-depth n' argument
+ */
+ if (IS_OPTION ("-depth"))
+ {
+ DWORD dwBPP = 0;
+
+ /* Display the usage message if the argument is malformed */
+ if (++i >= argc)
+ {
+ UseMsg ();
+ return 0;
+ }
+
+ /* Grab the argument */
+ dwBPP = atoi (argv[i]);
+
+ screenInfoPtr->dwBPP = dwBPP;
+
+ /* Indicate that we have processed the argument */
+ return 2;
+ }
+
+ /*
+ * Look for the '-refresh n' argument
+ */
+ if (IS_OPTION ("-refresh"))
+ {
+ DWORD dwRefreshRate = 0;
+
+ /* Display the usage message if the argument is malformed */
+ if (++i >= argc)
+ {
+ UseMsg ();
+ return 0;
+ }
+
+ /* Grab the argument */
+ dwRefreshRate = atoi (argv[i]);
+
+ screenInfoPtr->dwRefreshRate = dwRefreshRate;
+
+ /* Indicate that we have processed the argument */
+ return 2;
+ }
+
+ /*
+ * Look for the '-clipupdates num_boxes' argument
+ */
+ if (IS_OPTION ("-clipupdates"))
+ {
+ DWORD dwNumBoxes = 0;
+
+ /* Display the usage message if the argument is malformed */
+ if (++i >= argc)
+ {
+ UseMsg ();
+ return 0;
+ }
+
+ /* Grab the argument */
+ dwNumBoxes = atoi (argv[i]);
+
+ screenInfoPtr->dwClipUpdatesNBoxes = dwNumBoxes;
+
+ /* Indicate that we have processed the argument */
+ return 2;
+ }
+
+#ifdef XWIN_EMULATEPSEUDO
+ /*
+ * Look for the '-emulatepseudo' argument
+ */
+ if (IS_OPTION ("-emulatepseudo"))
+ {
+ screenInfoPtr->fEmulatePseudo = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+#endif
+
+ /*
+ * Look for the '-nowinkill' argument
+ */
+ if (IS_OPTION ("-nowinkill"))
+ {
+ screenInfoPtr->fUseWinKillKey = FALSE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-winkill' argument
+ */
+ if (IS_OPTION ("-winkill"))
+ {
+ screenInfoPtr->fUseWinKillKey = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-nounixkill' argument
+ */
+ if (IS_OPTION ("-nounixkill"))
+ {
+ screenInfoPtr->fUseUnixKillKey = FALSE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-unixkill' argument
+ */
+ if (IS_OPTION ("-unixkill"))
+ {
+ screenInfoPtr->fUseUnixKillKey = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-notrayicon' argument
+ */
+ if (IS_OPTION ("-notrayicon"))
+ {
+ screenInfoPtr->fNoTrayIcon = TRUE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-trayicon' argument
+ */
+ if (IS_OPTION ("-trayicon"))
+ {
+ screenInfoPtr->fNoTrayIcon = FALSE;
+
+ /* Indicate that we have processed this argument */
+ return 1;
+ }
+
+ /*
+ * Look for the '-fp' argument
+ */
+ if (IS_OPTION ("-fp"))
+ {
+ CHECK_ARGS (1);
+ g_cmdline.fontPath = argv[++i];
+ return 0; /* Let DIX parse this again */
+ }
+
+ /*
+ * Look for the '-query' argument
+ */
+ if (IS_OPTION ("-query"))
+ {
+ CHECK_ARGS (1);
+ g_fXdmcpEnabled = TRUE;
+ g_pszQueryHost = argv[++i];
+ return 0; /* Let DIX parse this again */
+ }
+
+ /*
+ * Look for the '-auth' argument
+ */
+ if (IS_OPTION ("-auth"))
+ {
+ g_fAuthEnabled = TRUE;
+ return 0; /* Let DIX parse this again */
+ }
+
+ /*
+ * Look for the '-indirect' or '-broadcast' arguments
+ */
+ if (IS_OPTION ("-indirect")
+ || IS_OPTION ("-broadcast"))
+ {
+ g_fXdmcpEnabled = TRUE;
+ return 0; /* Let DIX parse this again */
+ }
+
+ /*
+ * Look for the '-config' argument
+ */
+ if (IS_OPTION ("-config")
+ || IS_OPTION ("-xf86config"))
+ {
+ CHECK_ARGS (1);
+#ifdef XWIN_XF86CONFIG
+ g_cmdline.configFile = argv[++i];
+#else
+ winMessageBoxF ("The %s option is not supported in this "
+ "release.\n"
+ "Ignoring this option and continuing.\n",
+ MB_ICONINFORMATION,
+ argv[i]);
+#endif
+ return 2;
+ }
+
+ /*
+ * Look for the '-configdir' argument
+ */
+ if (IS_OPTION ("-configdir"))
+ {
+ CHECK_ARGS (1);
+#ifdef XWIN_XF86CONFIG
+ g_cmdline.configDir = argv[++i];
+#else
+ winMessageBoxF ("The %s option is not supported in this "
+ "release.\n"
+ "Ignoring this option and continuing.\n",
+ MB_ICONINFORMATION,
+ argv[i]);
+#endif
+ return 2;
+ }
+
+ /*
+ * Look for the '-keyboard' argument
+ */
+ if (IS_OPTION ("-keyboard"))
+ {
+#ifdef XWIN_XF86CONFIG
+ CHECK_ARGS (1);
+ g_cmdline.keyboard = argv[++i];
+#else
+ winMessageBoxF ("The -keyboard option is not supported in this "
+ "release.\n"
+ "Ignoring this option and continuing.\n",
+ MB_ICONINFORMATION);
+#endif
+ return 2;
+ }
+
+ /*
+ * Look for the '-logfile' argument
+ */
+ if (IS_OPTION ("-logfile"))
+ {
+ CHECK_ARGS (1);
+ g_pszLogFile = argv[++i];
+#ifdef RELOCATE_PROJECTROOT
+ g_fLogFileChanged = TRUE;
+#endif
+ return 2;
+ }
+
+ /*
+ * Look for the '-logverbose' argument
+ */
+ if (IS_OPTION ("-logverbose"))
+ {
+ CHECK_ARGS (1);
+ g_iLogVerbose = atoi(argv[++i]);
+ return 2;
+ }
+
+#ifdef XWIN_CLIPBOARD
+ /*
+ * Look for the '-nounicodeclipboard' argument
+ */
+ if (IS_OPTION ("-nounicodeclipboard"))
+ {
+ g_fUnicodeClipboard = FALSE;
+ /* Indicate that we have processed the argument */
+ return 1;
+ }
+#endif
+
+ if (IS_OPTION ("-xkbrules"))
+ {
+ CHECK_ARGS (1);
+ g_cmdline.xkbRules = argv[++i];
+ return 2;
+ }
+ if (IS_OPTION ("-xkbmodel"))
+ {
+ CHECK_ARGS (1);
+ g_cmdline.xkbModel = argv[++i];
+ return 2;
+ }
+ if (IS_OPTION ("-xkblayout"))
+ {
+ CHECK_ARGS (1);
+ g_cmdline.xkbLayout = argv[++i];
+ return 2;
+ }
+ if (IS_OPTION ("-xkbvariant"))
+ {
+ CHECK_ARGS (1);
+ g_cmdline.xkbVariant = argv[++i];
+ return 2;
+ }
+ if (IS_OPTION ("-xkboptions"))
+ {
+ CHECK_ARGS (1);
+ g_cmdline.xkbOptions = argv[++i];
+ return 2;
+ }
+
+ if (IS_OPTION ("-keyhook"))
+ {
+ g_fKeyboardHookLL = TRUE;
+ return 1;
+ }
+
+ if (IS_OPTION ("-nokeyhook"))
+ {
+ g_fKeyboardHookLL = FALSE;
+ return 1;
+ }
+
+ if (IS_OPTION ("-swcursor"))
+ {
+ g_fSoftwareCursor = TRUE;
+ return 1;
+ }
+
+ if (IS_OPTION ("-silent-dup-error"))
+ {
+ g_fSilentDupError = TRUE;
+ return 1;
+ }
+
+ if (IS_OPTION("-wgl"))
+ {
+ g_fNativeGl = TRUE;
+ return 1;
+ }
+
+ if (IS_OPTION("-nowgl"))
+ {
+ g_fNativeGl = FALSE;
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * winLogCommandLine - Write entire command line to the log file
+ */
+
+void
+winLogCommandLine (int argc, char *argv[])
+{
+ int i;
+ int iSize = 0;
+ int iCurrLen = 0;
+
+#define CHARS_PER_LINE 60
+
+ /* Bail if command line has already been logged */
+ if (g_pszCommandLine)
+ return;
+
+ /* Count how much memory is needed for concatenated command line */
+ for (i = 0, iCurrLen = 0; i < argc; ++i)
+ if (argv[i])
+ {
+ /* Adds two characters for lines that overflow */
+ if ((strlen (argv[i]) < CHARS_PER_LINE
+ && iCurrLen + strlen (argv[i]) > CHARS_PER_LINE)
+ || strlen (argv[i]) > CHARS_PER_LINE)
+ {
+ iCurrLen = 0;
+ iSize += 2;
+ }
+
+ /* Add space for item and trailing space */
+ iSize += strlen (argv[i]) + 1;
+
+ /* Update current line length */
+ iCurrLen += strlen (argv[i]);
+ }
+
+ /* Allocate memory for concatenated command line */
+ g_pszCommandLine = malloc (iSize + 1);
+ if (!g_pszCommandLine)
+ FatalError ("winLogCommandLine - Could not allocate memory for "
+ "command line string. Exiting.\n");
+
+ /* Set first character to concatenated command line to null */
+ g_pszCommandLine[0] = '\0';
+
+ /* Loop through all args */
+ for (i = 0, iCurrLen = 0; i < argc; ++i)
+ {
+ /* Add a character for lines that overflow */
+ if ((strlen (argv[i]) < CHARS_PER_LINE
+ && iCurrLen + strlen (argv[i]) > CHARS_PER_LINE)
+ || strlen (argv[i]) > CHARS_PER_LINE)
+ {
+ iCurrLen = 0;
+
+ /* Add line break if it fits */
+ strncat (g_pszCommandLine, "\n ", iSize - strlen (g_pszCommandLine));
+ }
+
+ strncat (g_pszCommandLine, argv[i], iSize - strlen (g_pszCommandLine));
+ strncat (g_pszCommandLine, " ", iSize - strlen (g_pszCommandLine));
+
+ /* Save new line length */
+ iCurrLen += strlen (argv[i]);
+ }
+
+ ErrorF ("XWin was started with the following command line:\n\n"
+ "%s\n\n", g_pszCommandLine);
+}
+
+
+/*
+ * winLogVersionInfo - Log Cygwin/X version information
+ */
+
+void
+winLogVersionInfo (void)
+{
+ static Bool s_fBeenHere = FALSE;
+
+ if (s_fBeenHere)
+ return;
+ s_fBeenHere = TRUE;
+
+ ErrorF ("Welcome to the XWin X Server\n");
+ ErrorF ("Vendor: %s\n", XVENDORNAME);
+ ErrorF ("Release: %d.%d.%d.%d (%d)\n", XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP, XORG_VERSION_CURRENT);
+ ErrorF ("%s\n\n", BUILDERSTRING);
+ ErrorF ("Contact: %s\n", BUILDERADDR);
+}
diff --git a/xorg-server/hw/xwin/winrandr.c b/xorg-server/hw/xwin/winrandr.c
index 7b5b1359c..248404800 100644
--- a/xorg-server/hw/xwin/winrandr.c
+++ b/xorg-server/hw/xwin/winrandr.c
@@ -1,8 +1,9 @@
/*
*Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
+ *Copyright (C) 2009-2010 Jon TURNEY
*
*Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
+ *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
@@ -20,101 +21,280 @@
*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 Harold L Hunt II
+ *Except as contained in this notice, the name of the 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 Harold L Hunt II.
+ *from the author(s)
*
* Authors: Harold L Hunt II
+ * Jon TURNEY
*/
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "win.h"
+#include "mivalidate.h" // for union _Validate used by windowstr.h
+
+#ifndef RANDR_12_INTERFACE
+#error X server must have RandR 1.2 interface
+#endif
/*
- * Local prototypes
+ * Answer queries about the RandR features supported.
*/
static Bool
-winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations);
+winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations)
+{
+ winDebug ("winRandRGetInfo ()\n");
-static Bool
-winRandRSetConfig (ScreenPtr pScreen,
- Rotation rotateKind,
- int rate,
- RRScreenSizePtr pSize);
+ /* Don't support rotations */
+ *pRotations = RR_Rotate_0;
-Bool
-winRandRInit (ScreenPtr pScreen);
+ /*
+ The screen doesn't have to be limited to the actual
+ monitor size (we can have scrollbars :-), so what is
+ the upper limit?
+ */
+ RRScreenSetSizeRange(pScreen, 0, 0, 4096, 4096);
+
+ return TRUE;
+}
/*
- * Answer queries about the RandR features supported.
+ Copied from the xfree86 DDX
+
+ Why can't this be in DIX?
+ Does union _Validate vary depending on DDX??
*/
+static void
+xf86SetRootClip (ScreenPtr pScreen, Bool enable)
+{
+ WindowPtr pWin = pScreen->root;
+ WindowPtr pChild;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ Bool anyMarked = FALSE;
+ WindowPtr pLayerWin;
+ BoxRec box;
-static Bool
-winRandRGetInfo (ScreenPtr pScreen, Rotation *pRotations)
+ if (WasViewable)
+ {
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ (void) (*pScreen->MarkOverlappedWindows)(pChild,
+ pChild,
+ &pLayerWin);
+ }
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ if (pWin->valdata)
+ {
+ if (HasBorder (pWin))
+ {
+ RegionPtr borderVisible;
+
+ borderVisible = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ }
+ pWin->valdata->before.resized = TRUE;
+ }
+ }
+
+ /*
+ * Use REGION_BREAK to avoid optimizations in ValidateTree
+ * that assume the root borderClip can't change well, normally
+ * it doesn't...)
+ */
+ if (enable)
+ {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_INIT (pScreen, &pWin->winSize, &box, 1);
+ REGION_INIT (pScreen, &pWin->borderSize, &box, 1);
+ if (WasViewable)
+ REGION_RESET(pScreen, &pWin->borderClip, &box);
+ pWin->drawable.width = pScreen->width;
+ pWin->drawable.height = pScreen->height;
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+ else
+ {
+ REGION_EMPTY(pScreen, &pWin->borderClip);
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+
+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
+
+ if (WasViewable)
+ {
+ if (pWin->firstChild)
+ {
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild,
+ pWin->firstChild,
+ (WindowPtr *)NULL);
+ }
+ else
+ {
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ }
+
+
+ if (anyMarked)
+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
+ }
+
+ if (WasViewable)
+ {
+ if (anyMarked)
+ (*pScreen->HandleExposures)(pWin);
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+ FlushAllOutput ();
+}
+
+/*
+
+*/
+void
+winDoRandRScreenSetSize (ScreenPtr pScreen,
+ CARD16 width,
+ CARD16 height,
+ CARD32 mmWidth,
+ CARD32 mmHeight)
{
winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- int n;
- Rotation rotateKind;
- RRScreenSizePtr pSize;
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ WindowPtr pRoot = pScreen->root;
- winDebug ("winRandRGetInfo ()\n");
+ // Prevent screen updates while we change things around
+ xf86SetRootClip(pScreen, FALSE);
- /* Don't support rotations, yet */
- *pRotations = RR_Rotate_0;
+ /* Update the screen size as requested */
+ pScreenInfo->dwWidth = width;
+ pScreenInfo->dwHeight = height;
- /* Bail if no depth has a visual associated with it */
- for (n = 0; n < pScreen->numDepths; n++)
- if (pScreen->allowedDepths[n].numVids)
- break;
- if (n == pScreen->numDepths)
- return FALSE;
+ /* Reallocate the framebuffer used by the drawing engine */
+ (*pScreenPriv->pwinFreeFB)(pScreen);
+ if (!(*pScreenPriv->pwinAllocateFB)(pScreen))
+ {
+ ErrorF ("winDoRandRScreenSetSize - Could not reallocate framebuffer\n");
+ }
- /* Only one allowed rotation for now */
- rotateKind = RR_Rotate_0;
+ pScreen->width = width;
+ pScreen->height = height;
+ pScreen->mmWidth = mmWidth;
+ pScreen->mmHeight = mmHeight;
- /*
- * Register supported sizes. This can be called many times, but
- * we only support one size for now.
- */
- pSize = RRRegisterSize (pScreen,
- pScreenInfo->dwWidth,
- pScreenInfo->dwHeight,
- pScreenInfo->dwWidth_mm,
- pScreenInfo->dwHeight_mm);
-
- /* Tell RandR what the current config is */
- RRSetCurrentConfig (pScreen,
- rotateKind,
- 0, /* refresh rate, not needed */
- pSize);
-
- return TRUE;
-}
+ /* Update the screen pixmap to point to the new framebuffer */
+ winUpdateFBPointer(pScreen, pScreenInfo->pfb);
+
+ // pScreen->devPrivate == pScreen->GetScreenPixmap(screen) ?
+ // resize the root window
+ //pScreen->ResizeWindow(pRoot, 0, 0, width, height, NULL);
+ // does this emit a ConfigureNotify??
+ // Restore the ability to update screen, now with new dimensions
+ xf86SetRootClip(pScreen, TRUE);
+
+ // and arrange for it to be repainted
+ miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND);
+
+ /* Indicate that a screen size change took place */
+ RRScreenSizeNotify(pScreen);
+}
/*
- * Respond to resize/rotate request from either X Server or X client app
+ * Respond to resize request
*/
-
-static Bool
-winRandRSetConfig (ScreenPtr pScreen,
- Rotation rotateKind,
- int rate,
- RRScreenSizePtr pSize)
+static
+Bool
+winRandRScreenSetSize (ScreenPtr pScreen,
+ CARD16 width,
+ CARD16 height,
+ CARD16 pixWidth,
+ CARD16 pixHeight,
+ CARD32 mmWidth,
+ CARD32 mmHeight)
{
- winDebug ("winRandRSetConfig ()\n");
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ winDebug ("winRandRScreenSetSize ()\n");
+
+ /*
+ It doesn't currently make sense to allow resize in fullscreen mode
+ (we'd actually have to list the supported resolutions)
+ */
+ if (pScreenInfo->fFullScreen)
+ {
+ ErrorF ("winRandRScreenSetSize - resize not supported in fullscreen mode\n");
+ return FALSE;
+ }
+
+ /*
+ Client resize requests aren't allowed in rootless modes, even if
+ the X screen is monitor or virtual desktop size, we'd need to
+ resize the native display size
+ */
+ if (FALSE
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || pScreenInfo->fMWExtWM
+#endif
+ || pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOW
+ || pScreenInfo->fMultiWindow
+#endif
+ )
+ {
+ ErrorF ("winRandRScreenSetSize - resize not supported in rootless modes\n");
+ return FALSE;
+ }
+
+ winDoRandRScreenSetSize(pScreen, width, height, mmWidth, mmHeight);
+
+ /* Cause the native window for the screen to resize itself */
+ {
+ DWORD dwStyle, dwExStyle;
+ RECT rcClient;
+
+ rcClient.left = 0;
+ rcClient.top = 0;
+ rcClient.right = width;
+ rcClient.bottom = height;
+
+ ErrorF ("winRandRScreenSetSize new client area w: %d h: %d\n", width, height);
+
+ /* Get the Windows window style and extended style */
+ dwExStyle = GetWindowLongPtr(pScreenPriv->hwndScreen, GWL_EXSTYLE);
+ dwStyle = GetWindowLongPtr(pScreenPriv->hwndScreen, GWL_STYLE);
+
+ /*
+ * Calculate the window size needed for the given client area
+ * adjusting for any decorations it will have
+ */
+ AdjustWindowRectEx(&rcClient, dwStyle, FALSE, dwExStyle);
+
+ ErrorF ("winRandRScreenSetSize new window area w: %ld h: %ld\n", rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
+
+ SetWindowPos(pScreenPriv->hwndScreen, NULL,
+ 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top,
+ SWP_NOZORDER | SWP_NOMOVE);
+ }
return TRUE;
}
-
/*
* Initialize the RandR layer.
*/
@@ -122,8 +302,7 @@ winRandRSetConfig (ScreenPtr pScreen,
Bool
winRandRInit (ScreenPtr pScreen)
{
- rrScrPrivPtr pRRScrPriv;
-
+ rrScrPrivPtr pRRScrPriv;
winDebug ("winRandRInit ()\n");
if (!RRScreenInit (pScreen))
@@ -135,7 +314,10 @@ winRandRInit (ScreenPtr pScreen)
/* Set some RandR function pointers */
pRRScrPriv = rrGetScrPriv (pScreen);
pRRScrPriv->rrGetInfo = winRandRGetInfo;
- pRRScrPriv->rrSetConfig = winRandRSetConfig;
+ pRRScrPriv->rrSetConfig = NULL;
+ pRRScrPriv->rrScreenSetSize = winRandRScreenSetSize;
+ pRRScrPriv->rrCrtcSet = NULL;
+ pRRScrPriv->rrCrtcSetGamma = NULL;
return TRUE;
}
diff --git a/xorg-server/hw/xwin/winscrinit.c b/xorg-server/hw/xwin/winscrinit.c
index f067fde6a..691237e6f 100644
--- a/xorg-server/hw/xwin/winscrinit.c
+++ b/xorg-server/hw/xwin/winscrinit.c
@@ -1,767 +1,769 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Dakshinamurthy Karra
- * Suhaib M Siddiqi
- * Peter Busch
- * Harold L Hunt II
- * Kensuke Matsuzaki
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include "winmsg.h"
-
-
-#ifdef XWIN_MULTIWINDOWEXTWM
-static RootlessFrameProcsRec
-winMWExtWMProcs = {
- winMWExtWMCreateFrame,
- winMWExtWMDestroyFrame,
-
- winMWExtWMMoveFrame,
- winMWExtWMResizeFrame,
- winMWExtWMRestackFrame,
- winMWExtWMReshapeFrame,
- winMWExtWMUnmapFrame,
-
- winMWExtWMStartDrawing,
- winMWExtWMStopDrawing,
- winMWExtWMUpdateRegion,
- winMWExtWMDamageRects,
- winMWExtWMRootlessSwitchWindow,
- NULL,//winMWExtWMDoReorderWindow,
- NULL,//winMWExtWMHideWindow,
- NULL,//winMWExtWMUpdateColorMap,
-
- NULL,//winMWExtWMCopyBytes,
- winMWExtWMCopyWindow
-};
-#endif
-
-/*
- * Prototypes
- */
-
-Bool
-winRandRInit (ScreenPtr pScreen);
-
-
-/*
- * Local functions
- */
-
-static Bool
-winSaveScreen (ScreenPtr pScreen, int on);
-
-
-/*
- * Determine what type of screen we are initializing
- * and call the appropriate procedure to intiailize
- * that type of screen.
- */
-
-Bool
-winScreenInit (int index,
- ScreenPtr pScreen,
- int argc, char **argv)
-{
- winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index];
- winPrivScreenPtr pScreenPriv;
- HDC hdc;
-
-#if CYGDEBUG || YES
- winDebug ("winScreenInit - dwWidth: %ld dwHeight: %ld\n",
- pScreenInfo->dwWidth, pScreenInfo->dwHeight);
-#endif
-
- /* Allocate privates for this screen */
- if (!winAllocatePrivates (pScreen))
- {
- ErrorF ("winScreenInit - Couldn't allocate screen privates\n");
- return FALSE;
- }
-
- /* Get a pointer to the privates structure that was allocated */
- pScreenPriv = winGetScreenPriv (pScreen);
-
- /* Save a pointer to this screen in the screen info structure */
- pScreenInfo->pScreen = pScreen;
-
- /* Save a pointer to the screen info in the screen privates structure */
- /* This allows us to get back to the screen info from a screen pointer */
- pScreenPriv->pScreenInfo = pScreenInfo;
-
- /*
- * Determine which engine to use.
- *
- * NOTE: This is done once per screen because each screen possibly has
- * a preferred engine specified on the command line.
- */
- if (!winSetEngine (pScreen))
- {
- ErrorF ("winScreenInit - winSetEngine () failed\n");
- return FALSE;
- }
-
- /* Adjust the video mode for our engine type */
- if (!(*pScreenPriv->pwinAdjustVideoMode) (pScreen))
- {
- ErrorF ("winScreenInit - winAdjustVideoMode () failed\n");
- return FALSE;
- }
-
- /* Check for supported display depth */
- if (!(WIN_SUPPORTED_BPPS & (1 << (pScreenInfo->dwBPP - 1))))
- {
- ErrorF ("winScreenInit - Unsupported display depth: %d\n" \
- "Change your Windows display depth to 15, 16, 24, or 32 bits "
- "per pixel.\n",
- (int) pScreenInfo->dwBPP);
- ErrorF ("winScreenInit - Supported depths: %08x\n",
- WIN_SUPPORTED_BPPS);
-#if WIN_CHECK_DEPTH
- return FALSE;
-#endif
- }
-
- /*
- * Check that all monitors have the same display depth if we are using
- * multiple monitors
- */
- if (pScreenInfo->fMultipleMonitors
- && !GetSystemMetrics (SM_SAMEDISPLAYFORMAT))
- {
- ErrorF ("winScreenInit - Monitors do not all have same pixel format / "
- "display depth.\n"
- "Using primary display only.\n");
- pScreenInfo->fMultipleMonitors = FALSE;
- }
-
- /* Create display window */
- if (!(*pScreenPriv->pwinCreateBoundingWindow) (pScreen))
- {
- ErrorF ("winScreenInit - pwinCreateBoundingWindow () "
- "failed\n");
- return FALSE;
- }
-
- /* Get a device context */
- hdc = GetDC (pScreenPriv->hwndScreen);
-
- /* Store the initial height, width, and depth of the display */
- /* Are we using multiple monitors? */
- if (pScreenInfo->fMultipleMonitors)
- {
- pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
- pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
-
- /*
- * In this case, some of the defaults set in
- * winInitializeScreenDefaults() are not correct ...
- */
- if (!pScreenInfo->fUserGaveHeightAndWidth)
- {
- pScreenInfo->dwWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
- pScreenInfo->dwHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
- pScreenInfo->dwWidth_mm = (pScreenInfo->dwWidth /
- WIN_DEFAULT_DPI) * 25.4;
- pScreenInfo->dwHeight_mm = (pScreenInfo->dwHeight /
- WIN_DEFAULT_DPI) * 25.4;
- }
- }
- else
- {
- pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXSCREEN);
- pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYSCREEN);
- }
-
- /* Save the original bits per pixel */
- pScreenPriv->dwLastWindowsBitsPixel = GetDeviceCaps (hdc, BITSPIXEL);
-
- /* Release the device context */
- ReleaseDC (pScreenPriv->hwndScreen, hdc);
-
- /* Clear the visuals list */
- miClearVisualTypes ();
-
- /* Set the padded screen width */
- pScreenInfo->dwPaddedWidth = PixmapBytePad (pScreenInfo->dwWidth,
- pScreenInfo->dwBPP);
-
- /* Call the engine dependent screen initialization procedure */
- if (!((*pScreenPriv->pwinFinishScreenInit) (index, pScreen, argc, argv)))
- {
- ErrorF ("winScreenInit - winFinishScreenInit () failed\n");
- return FALSE;
- }
-
- if (!g_fSoftwareCursor)
- winInitCursor(pScreen);
- else
- winErrorFVerb(2, "winScreenInit - Using software cursor\n");
-
- /*
- Note the screen origin in a normalized coordinate space where (0,0) is at the top left
- of the native virtual desktop area
- */
- pScreen->x = pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN);
- pScreen->y = pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN);
-
- ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n",
- index, pScreen->x, pScreen->y);
-
-#if CYGDEBUG || YES
- winDebug ("winScreenInit - returning\n");
-#endif
-
- return TRUE;
-}
-
-static Bool
-winCreateScreenResources(ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- Bool result;
-
- result = pScreenPriv->pwinCreateScreenResources(pScreen);
-
- /* Now the screen bitmap has been wrapped in a pixmap,
- add that to the Shadow framebuffer */
- if (!shadowAdd(pScreen, pScreen->devPrivate,
- pScreenPriv->pwinShadowUpdate, NULL, 0, 0))
- {
- ErrorF ("winCreateScreenResources - shadowAdd () failed\n");
- return FALSE;
- }
-
- return result;
-}
-
-/* See Porting Layer Definition - p. 20 */
-Bool
-winFinishScreenInitFB (int index,
- ScreenPtr pScreen,
- int argc, char **argv)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- VisualPtr pVisual = NULL;
- char *pbits = NULL;
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
- int iReturn;
-#endif
-
- /* Create framebuffer */
- if (!(*pScreenPriv->pwinAllocateFB) (pScreen))
- {
- ErrorF ("winFinishScreenInitFB - Could not allocate framebuffer\n");
- return FALSE;
- }
-
- /*
- * Grab the number of bits that are used to represent color in each pixel.
- */
- if (pScreenInfo->dwBPP == 8)
- pScreenInfo->dwDepth = 8;
- else
- pScreenInfo->dwDepth = winCountBits (pScreenPriv->dwRedMask)
- + winCountBits (pScreenPriv->dwGreenMask)
- + winCountBits (pScreenPriv->dwBlueMask);
-
- winErrorFVerb (2, "winFinishScreenInitFB - Masks: %08x %08x %08x\n",
- (unsigned int) pScreenPriv->dwRedMask,
- (unsigned int) pScreenPriv->dwGreenMask,
- (unsigned int) pScreenPriv->dwBlueMask);
-
- /* Init visuals */
- if (!(*pScreenPriv->pwinInitVisuals) (pScreen))
- {
- ErrorF ("winFinishScreenInitFB - winInitVisuals failed\n");
- return FALSE;
- }
-
- /* Setup a local variable to point to the framebuffer */
- pbits = pScreenInfo->pfb;
-
- /* Apparently we need this for the render extension */
- miSetPixmapDepths ();
-
- /* Start fb initialization */
- if (!fbSetupScreen (pScreen,
- pScreenInfo->pfb,
- pScreenInfo->dwWidth, pScreenInfo->dwHeight,
- monitorResolution, monitorResolution,
- pScreenInfo->dwStride,
- pScreenInfo->dwBPP))
- {
- ErrorF ("winFinishScreenInitFB - fbSetupScreen failed\n");
- return FALSE;
- }
-
- /* Override default colormap routines if visual class is dynamic */
- if (pScreenInfo->dwDepth == 8
- && (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
- || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
- && pScreenInfo->fFullScreen)
- || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
- && pScreenInfo->fFullScreen)))
- {
- winSetColormapFunctions (pScreen);
-
- /*
- * NOTE: Setting whitePixel to 255 causes Magic 7.1 to allocate its
- * own colormap, as it cannot allocate 7 planes in the default
- * colormap. Setting whitePixel to 1 allows Magic to get 7
- * planes in the default colormap, so it doesn't create its
- * own colormap. This latter situation is highly desireable,
- * as it keeps the Magic window viewable when switching to
- * other X clients that use the default colormap.
- */
- pScreen->blackPixel = 0;
- pScreen->whitePixel = 1;
- }
-
- /* Place our save screen function */
- pScreen->SaveScreen = winSaveScreen;
-
- /* Finish fb initialization */
- if (!fbFinishScreenInit (pScreen,
- pScreenInfo->pfb,
- pScreenInfo->dwWidth, pScreenInfo->dwHeight,
- monitorResolution, monitorResolution,
- pScreenInfo->dwStride,
- pScreenInfo->dwBPP))
- {
- ErrorF ("winFinishScreenInitFB - fbFinishScreenInit failed\n");
- return FALSE;
- }
-
- /* Save a pointer to the root visual */
- for (pVisual = pScreen->visuals;
- pVisual->vid != pScreen->rootVisual;
- pVisual++);
- pScreenPriv->pRootVisual = pVisual;
-
- /*
- * Setup points to the block and wakeup handlers. Pass a pointer
- * to the current screen as pWakeupdata.
- */
- pScreen->BlockHandler = winBlockHandler;
- pScreen->WakeupHandler = winWakeupHandler;
- pScreen->blockData = pScreen;
- pScreen->wakeupData = pScreen;
-
- /* Render extension initialization, calls miPictureInit */
- if (!fbPictureInit (pScreen, NULL, 0))
- {
- ErrorF ("winFinishScreenInitFB - fbPictureInit () failed\n");
- return FALSE;
- }
-
-#ifdef RANDR
- /* Initialize resize and rotate support */
- if (!winRandRInit (pScreen))
- {
- ErrorF ("winFinishScreenInitFB - winRandRInit () failed\n");
- return FALSE;
- }
-#endif
-
- /* Setup the cursor routines */
-#if CYGDEBUG
- winDebug ("winFinishScreenInitFB - Calling miDCInitialize ()\n");
-#endif
- miDCInitialize (pScreen, &g_winPointerCursorFuncs);
-
- /* KDrive does winCreateDefColormap right after miDCInitialize */
- /* Create a default colormap */
-#if CYGDEBUG
- winDebug ("winFinishScreenInitFB - Calling winCreateDefColormap ()\n");
-#endif
- if (!winCreateDefColormap (pScreen))
- {
- ErrorF ("winFinishScreenInitFB - Could not create colormap\n");
- return FALSE;
- }
-
- /* Initialize the shadow framebuffer layer */
- if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
- || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
- || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)
-#ifdef XWIN_MULTIWINDOWEXTWM
- && !pScreenInfo->fMWExtWM
-#endif
- )
- {
-#if CYGDEBUG
- winDebug ("winFinishScreenInitFB - Calling shadowSetup ()\n");
-#endif
- if (!shadowSetup(pScreen))
- {
- ErrorF ("winFinishScreenInitFB - shadowSetup () failed\n");
- return FALSE;
- }
-
- /* Wrap CreateScreenResources so we can add the screen pixmap
- to the Shadow framebuffer after it's been created */
- pScreenPriv->pwinCreateScreenResources = pScreen->CreateScreenResources;
- pScreen->CreateScreenResources = winCreateScreenResources;
- }
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- /* Handle multi-window external window manager mode */
- if (pScreenInfo->fMWExtWM)
- {
- winDebug ("winScreenInit - MultiWindowExtWM - Calling RootlessInit\n");
-
- RootlessInit(pScreen, &winMWExtWMProcs);
-
- winDebug ("winScreenInit - MultiWindowExtWM - RootlessInit returned\n");
-
- rootless_CopyBytes_threshold = 0;
- /* FIXME: How many? Profiling needed? */
- rootless_CopyWindow_threshold = 1;
-
- winWindowsWMExtensionInit ();
- }
-#endif
-
- /* Handle rootless mode */
- if (pScreenInfo->fRootless)
- {
- /* Define the WRAP macro temporarily for local use */
-#define WRAP(a) \
- if (pScreen->a) { \
- pScreenPriv->a = pScreen->a; \
- } else { \
- ErrorF("null screen fn " #a "\n"); \
- pScreenPriv->a = NULL; \
- }
-
- /* Save a pointer to each lower-level window procedure */
- WRAP(CreateWindow);
- WRAP(DestroyWindow);
- WRAP(RealizeWindow);
- WRAP(UnrealizeWindow);
- WRAP(PositionWindow);
- WRAP(ChangeWindowAttributes);
- WRAP(SetShape);
-
- /* Assign rootless window procedures to be top level procedures */
- pScreen->CreateWindow = winCreateWindowRootless;
- pScreen->DestroyWindow = winDestroyWindowRootless;
- pScreen->PositionWindow = winPositionWindowRootless;
- /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesRootless;*/
- pScreen->RealizeWindow = winMapWindowRootless;
- pScreen->UnrealizeWindow = winUnmapWindowRootless;
- pScreen->SetShape = winSetShapeRootless;
-
- /* Undefine the WRAP macro, as it is not needed elsewhere */
-#undef WRAP
- }
-
-
-#ifdef XWIN_MULTIWINDOW
- /* Handle multi window mode */
- else if (pScreenInfo->fMultiWindow)
- {
- /* Define the WRAP macro temporarily for local use */
-#define WRAP(a) \
- if (pScreen->a) { \
- pScreenPriv->a = pScreen->a; \
- } else { \
- ErrorF("null screen fn " #a "\n"); \
- pScreenPriv->a = NULL; \
- }
-
- /* Save a pointer to each lower-level window procedure */
- WRAP(CreateWindow);
- WRAP(DestroyWindow);
- WRAP(RealizeWindow);
- WRAP(UnrealizeWindow);
- WRAP(PositionWindow);
- WRAP(ChangeWindowAttributes);
- WRAP(ReparentWindow);
- WRAP(RestackWindow);
- WRAP(ResizeWindow);
- WRAP(MoveWindow);
- WRAP(CopyWindow);
- WRAP(SetShape);
-
- /* Assign multi-window window procedures to be top level procedures */
- pScreen->CreateWindow = winCreateWindowMultiWindow;
- pScreen->DestroyWindow = winDestroyWindowMultiWindow;
- pScreen->PositionWindow = winPositionWindowMultiWindow;
- /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesMultiWindow;*/
- pScreen->RealizeWindow = winMapWindowMultiWindow;
- pScreen->UnrealizeWindow = winUnmapWindowMultiWindow;
- pScreen->ReparentWindow = winReparentWindowMultiWindow;
- pScreen->RestackWindow = winRestackWindowMultiWindow;
- pScreen->ResizeWindow = winResizeWindowMultiWindow;
- pScreen->MoveWindow = winMoveWindowMultiWindow;
- pScreen->CopyWindow = winCopyWindowMultiWindow;
- pScreen->SetShape = winSetShapeMultiWindow;
-
- /* Undefine the WRAP macro, as it is not needed elsewhere */
-#undef WRAP
- }
-#endif
-
- /* Wrap either fb's or shadow's CloseScreen with our CloseScreen */
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = pScreenPriv->pwinCloseScreen;
-
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
- /* Create a mutex for modules in separate threads to wait for */
- iReturn = pthread_mutex_init (&pScreenPriv->pmServerStarted, NULL);
- if (iReturn != 0)
- {
- ErrorF ("winFinishScreenInitFB - pthread_mutex_init () failed: %d\n",
- iReturn);
- return FALSE;
- }
-
- /* Own the mutex for modules in separate threads */
- iReturn = pthread_mutex_lock (&pScreenPriv->pmServerStarted);
- if (iReturn != 0)
- {
- ErrorF ("winFinishScreenInitFB - pthread_mutex_lock () failed: %d\n",
- iReturn);
- return FALSE;
- }
-
- /* Set the ServerStarted flag to false */
- pScreenPriv->fServerStarted = FALSE;
-#endif
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- pScreenPriv->fRestacking = FALSE;
-#endif
-
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
- if (FALSE
-#ifdef XWIN_MULTIWINDOW
- || pScreenInfo->fMultiWindow
-#endif
-#ifdef XWIN_MULTIWINDOWEXTWM
- || pScreenInfo->fInternalWM
-#endif
- )
- {
-#if CYGDEBUG || YES
- winDebug ("winFinishScreenInitFB - Calling winInitWM.\n");
-#endif
-
- /* Initialize multi window mode */
- if (!winInitWM (&pScreenPriv->pWMInfo,
- &pScreenPriv->ptWMProc,
- &pScreenPriv->ptXMsgProc,
- &pScreenPriv->pmServerStarted,
- pScreenInfo->dwScreen,
- (HWND)&pScreenPriv->hwndScreen,
-#ifdef XWIN_MULTIWINDOWEXTWM
- pScreenInfo->fInternalWM ||
-#endif
- FALSE))
- {
- ErrorF ("winFinishScreenInitFB - winInitWM () failed.\n");
- return FALSE;
- }
- }
-#endif
-
- /* Tell the server that we are enabled */
- pScreenPriv->fEnabled = TRUE;
-
- /* Tell the server that we have a valid depth */
- pScreenPriv->fBadDepth = FALSE;
-
-#if CYGDEBUG || YES
- winDebug ("winFinishScreenInitFB - returning\n");
-#endif
-
- return TRUE;
-}
-
-#ifdef XWIN_NATIVEGDI
-/* See Porting Layer Definition - p. 20 */
-
-Bool
-winFinishScreenInitNativeGDI (int index,
- ScreenPtr pScreen,
- int argc, char **argv)
-{
- winScreenPriv(pScreen);
- winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index];
- VisualPtr pVisuals = NULL;
- DepthPtr pDepths = NULL;
- VisualID rootVisual = 0;
- int nVisuals = 0, nDepths = 0, nRootDepth = 0;
-
- /* Ignore user input (mouse, keyboard) */
- pScreenInfo->fIgnoreInput = FALSE;
-
- /* Get device contexts for the screen and shadow bitmap */
- pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
- if (pScreenPriv->hdcScreen == NULL)
- FatalError ("winFinishScreenInitNativeGDI - Couldn't get a DC\n");
-
- /* Init visuals */
- if (!(*pScreenPriv->pwinInitVisuals) (pScreen))
- {
- ErrorF ("winFinishScreenInitNativeGDI - pwinInitVisuals failed\n");
- return FALSE;
- }
-
- /* Initialize the mi visuals */
- if (!miInitVisuals (&pVisuals, &pDepths, &nVisuals, &nDepths, &nRootDepth,
- &rootVisual,
- ((unsigned long)1 << (pScreenInfo->dwDepth - 1)), 8,
- TrueColor))
- {
- ErrorF ("winFinishScreenInitNativeGDI - miInitVisuals () failed\n");
- return FALSE;
- }
-
- /* Initialize the CloseScreen procedure pointer */
- pScreen->CloseScreen = NULL;
-
- /* Initialize the mi code */
- if (!miScreenInit (pScreen,
- NULL, /* No framebuffer */
- pScreenInfo->dwWidth, pScreenInfo->dwHeight,
- monitorResolution, monitorResolution,
- pScreenInfo->dwStride,
- nRootDepth, nDepths, pDepths, rootVisual,
- nVisuals, pVisuals))
- {
- ErrorF ("winFinishScreenInitNativeGDI - miScreenInit failed\n");
- return FALSE;
- }
-
- pScreen->defColormap = FakeClientID(0);
-
- /*
- * Register our block and wakeup handlers; these procedures
- * process messages in our Windows message queue; specifically,
- * they process mouse and keyboard input.
- */
- pScreen->BlockHandler = winBlockHandler;
- pScreen->WakeupHandler = winWakeupHandler;
- pScreen->blockData = pScreen;
- pScreen->wakeupData = pScreen;
-
- /* Place our save screen function */
- pScreen->SaveScreen = winSaveScreen;
-
- /* Pixmaps */
- pScreen->CreatePixmap = winCreatePixmapNativeGDI;
- pScreen->DestroyPixmap = winDestroyPixmapNativeGDI;
-
- /* Other Screen Routines */
- pScreen->QueryBestSize = winQueryBestSizeNativeGDI;
- pScreen->SaveScreen = winSaveScreen;
- pScreen->GetImage = miGetImage;
- pScreen->GetSpans = winGetSpansNativeGDI;
-
- /* Window Procedures */
- pScreen->CreateWindow = winCreateWindowNativeGDI;
- pScreen->DestroyWindow = winDestroyWindowNativeGDI;
- pScreen->PositionWindow = winPositionWindowNativeGDI;
- /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesNativeGDI;*/
- pScreen->RealizeWindow = winMapWindowNativeGDI;
- pScreen->UnrealizeWindow = winUnmapWindowNativeGDI;
-
- /* Paint window */
- pScreen->CopyWindow = winCopyWindowNativeGDI;
-
- /* Fonts */
- pScreen->RealizeFont = winRealizeFontNativeGDI;
- pScreen->UnrealizeFont = winUnrealizeFontNativeGDI;
-
- /* GC */
- pScreen->CreateGC = winCreateGCNativeGDI;
-
- /* Colormap Routines */
- pScreen->CreateColormap = miInitializeColormap;
- pScreen->DestroyColormap = (DestroyColormapProcPtr) (void (*)(void)) NoopDDA;
- pScreen->InstallColormap = miInstallColormap;
- pScreen->UninstallColormap = miUninstallColormap;
- pScreen->ListInstalledColormaps = miListInstalledColormaps;
- pScreen->StoreColors = (StoreColorsProcPtr) (void (*)(void)) NoopDDA;
- pScreen->ResolveColor = miResolveColor;
-
- /* Bitmap */
- pScreen->BitmapToRegion = winPixmapToRegionNativeGDI;
-
- ErrorF ("winFinishScreenInitNativeGDI - calling miDCInitialize\n");
-
- /* Set the default white and black pixel positions */
- pScreen->whitePixel = pScreen->blackPixel = (Pixel) 0;
-
- /* Initialize the cursor */
- if (!miDCInitialize (pScreen, &g_winPointerCursorFuncs))
- {
- ErrorF ("winFinishScreenInitNativeGDI - miDCInitialize failed\n");
- return FALSE;
- }
-
- /* Create a default colormap */
- if (!miCreateDefColormap (pScreen))
- {
- ErrorF ("winFinishScreenInitNativeGDI - miCreateDefColormap () "
- "failed\n");
- return FALSE;
- }
-
- ErrorF ("winFinishScreenInitNativeGDI - miCreateDefColormap () "
- "returned\n");
-
- /* mi doesn't use a CloseScreen procedure, so no need to wrap */
- pScreen->CloseScreen = pScreenPriv->pwinCloseScreen;
-
- /* Tell the server that we are enabled */
- pScreenPriv->fEnabled = TRUE;
-
- ErrorF ("winFinishScreenInitNativeGDI - Successful addition of "
- "screen %08x\n",
- (unsigned int) pScreen);
-
- return TRUE;
-}
-#endif
-
-
-/* See Porting Layer Definition - p. 33 */
-static Bool
-winSaveScreen (ScreenPtr pScreen, int on)
-{
- return TRUE;
-}
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ * Kensuke Matsuzaki
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include "winmsg.h"
+
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+static RootlessFrameProcsRec
+winMWExtWMProcs = {
+ winMWExtWMCreateFrame,
+ winMWExtWMDestroyFrame,
+
+ winMWExtWMMoveFrame,
+ winMWExtWMResizeFrame,
+ winMWExtWMRestackFrame,
+ winMWExtWMReshapeFrame,
+ winMWExtWMUnmapFrame,
+
+ winMWExtWMStartDrawing,
+ winMWExtWMStopDrawing,
+ winMWExtWMUpdateRegion,
+ winMWExtWMDamageRects,
+ winMWExtWMRootlessSwitchWindow,
+ NULL,//winMWExtWMDoReorderWindow,
+ NULL,//winMWExtWMHideWindow,
+ NULL,//winMWExtWMUpdateColorMap,
+
+ NULL,//winMWExtWMCopyBytes,
+ winMWExtWMCopyWindow
+};
+#endif
+
+/*
+ * Prototypes
+ */
+
+/*
+ * Local functions
+ */
+
+static Bool
+winSaveScreen (ScreenPtr pScreen, int on);
+
+
+/*
+ * Determine what type of screen we are initializing
+ * and call the appropriate procedure to intiailize
+ * that type of screen.
+ */
+
+Bool
+winScreenInit (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv)
+{
+ winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index];
+ winPrivScreenPtr pScreenPriv;
+ HDC hdc;
+ DWORD dwInitialBPP;
+
+#if CYGDEBUG || YES
+ winDebug ("winScreenInit - dwWidth: %ld dwHeight: %ld\n",
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight);
+#endif
+
+ /* Allocate privates for this screen */
+ if (!winAllocatePrivates (pScreen))
+ {
+ ErrorF ("winScreenInit - Couldn't allocate screen privates\n");
+ return FALSE;
+ }
+
+ /* Get a pointer to the privates structure that was allocated */
+ pScreenPriv = winGetScreenPriv (pScreen);
+
+ /* Save a pointer to this screen in the screen info structure */
+ pScreenInfo->pScreen = pScreen;
+
+ /* Save a pointer to the screen info in the screen privates structure */
+ /* This allows us to get back to the screen info from a screen pointer */
+ pScreenPriv->pScreenInfo = pScreenInfo;
+
+ /*
+ * Determine which engine to use.
+ *
+ * NOTE: This is done once per screen because each screen possibly has
+ * a preferred engine specified on the command line.
+ */
+ if (!winSetEngine (pScreen))
+ {
+ ErrorF ("winScreenInit - winSetEngine () failed\n");
+ return FALSE;
+ }
+
+ /* Horribly misnamed function: Allow engine to adjust BPP for screen */
+ dwInitialBPP = pScreenInfo->dwBPP;
+
+ if (!(*pScreenPriv->pwinAdjustVideoMode) (pScreen))
+ {
+ ErrorF ("winScreenInit - winAdjustVideoMode () failed\n");
+ return FALSE;
+ }
+
+ if (dwInitialBPP == WIN_DEFAULT_BPP)
+ {
+ /* No -depth parameter was passed, let the user know the depth being used */
+ ErrorF ("winScreenInit - Using Windows display depth of %d bits per pixel\n", (int) pScreenInfo->dwBPP);
+ }
+ else if (dwInitialBPP != pScreenInfo->dwBPP)
+ {
+ /* Warn user if engine forced a depth different to -depth parameter */
+ ErrorF ("winScreenInit - Command line depth of %d bpp overidden by engine, using %d bpp\n", (int) dwInitialBPP, (int) pScreenInfo->dwBPP);
+ }
+ else
+ {
+ ErrorF ("winScreenInit - Using command line depth of %d bpp\n", (int) pScreenInfo->dwBPP);
+ }
+
+ /* Check for supported display depth */
+ if (!(WIN_SUPPORTED_BPPS & (1 << (pScreenInfo->dwBPP - 1))))
+ {
+ ErrorF ("winScreenInit - Unsupported display depth: %d\n" \
+ "Change your Windows display depth to 15, 16, 24, or 32 bits "
+ "per pixel.\n",
+ (int) pScreenInfo->dwBPP);
+ ErrorF ("winScreenInit - Supported depths: %08x\n",
+ WIN_SUPPORTED_BPPS);
+#if WIN_CHECK_DEPTH
+ return FALSE;
+#endif
+ }
+
+ /*
+ * Check that all monitors have the same display depth if we are using
+ * multiple monitors
+ */
+ if (pScreenInfo->fMultipleMonitors
+ && !GetSystemMetrics (SM_SAMEDISPLAYFORMAT))
+ {
+ ErrorF ("winScreenInit - Monitors do not all have same pixel format / "
+ "display depth.\n");
+ if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI)
+ {
+ ErrorF ("winScreenInit - Performance may suffer off primary display.\n");
+ }
+ else
+ {
+ ErrorF ("winScreenInit - Using primary display only.\n");
+ pScreenInfo->fMultipleMonitors = FALSE;
+ }
+ }
+
+ /* Create display window */
+ if (!(*pScreenPriv->pwinCreateBoundingWindow) (pScreen))
+ {
+ ErrorF ("winScreenInit - pwinCreateBoundingWindow () "
+ "failed\n");
+ return FALSE;
+ }
+
+ /* Get a device context */
+ hdc = GetDC (pScreenPriv->hwndScreen);
+
+ /* Are we using multiple monitors? */
+ if (pScreenInfo->fMultipleMonitors)
+ {
+ /*
+ * In this case, some of the defaults set in
+ * winInitializeScreenDefaults() are not correct ...
+ */
+ if (!pScreenInfo->fUserGaveHeightAndWidth)
+ {
+ pScreenInfo->dwWidth = GetSystemMetrics (SM_CXVIRTUALSCREEN);
+ pScreenInfo->dwHeight = GetSystemMetrics (SM_CYVIRTUALSCREEN);
+ }
+ }
+
+ /* Release the device context */
+ ReleaseDC (pScreenPriv->hwndScreen, hdc);
+
+ /* Clear the visuals list */
+ miClearVisualTypes ();
+
+ /* Call the engine dependent screen initialization procedure */
+ if (!((*pScreenPriv->pwinFinishScreenInit) (index, pScreen, argc, argv)))
+ {
+ ErrorF ("winScreenInit - winFinishScreenInit () failed\n");
+ return FALSE;
+ }
+
+ if (!g_fSoftwareCursor)
+ winInitCursor(pScreen);
+ else
+ winErrorFVerb(2, "winScreenInit - Using software cursor\n");
+
+ /*
+ Note the screen origin in a normalized coordinate space where (0,0) is at the top left
+ of the native virtual desktop area
+ */
+ pScreen->x = pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN);
+ pScreen->y = pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN);
+
+ ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n",
+ index, pScreen->x, pScreen->y);
+
+#if CYGDEBUG || YES
+ winDebug ("winScreenInit - returning\n");
+#endif
+
+ return TRUE;
+}
+
+static Bool
+winCreateScreenResources(ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ Bool result;
+
+ result = pScreenPriv->pwinCreateScreenResources(pScreen);
+
+ /* Now the screen bitmap has been wrapped in a pixmap,
+ add that to the Shadow framebuffer */
+ if (!shadowAdd(pScreen, pScreen->devPrivate,
+ pScreenPriv->pwinShadowUpdate, NULL, 0, 0))
+ {
+ ErrorF ("winCreateScreenResources - shadowAdd () failed\n");
+ return FALSE;
+ }
+
+ return result;
+}
+
+/* See Porting Layer Definition - p. 20 */
+Bool
+winFinishScreenInitFB (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ VisualPtr pVisual = NULL;
+ char *pbits = NULL;
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ int iReturn;
+#endif
+
+ /* Create framebuffer */
+ if (!(*pScreenPriv->pwinInitScreen) (pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - Could not allocate framebuffer\n");
+ return FALSE;
+ }
+
+ /*
+ * Calculate the number of bits that are used to represent color in each pixel,
+ * the color depth for the screen
+ */
+ if (pScreenInfo->dwBPP == 8)
+ pScreenInfo->dwDepth = 8;
+ else
+ pScreenInfo->dwDepth = winCountBits (pScreenPriv->dwRedMask)
+ + winCountBits (pScreenPriv->dwGreenMask)
+ + winCountBits (pScreenPriv->dwBlueMask);
+
+ winErrorFVerb (2, "winFinishScreenInitFB - Masks: %08x %08x %08x\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask);
+
+ /* Init visuals */
+ if (!(*pScreenPriv->pwinInitVisuals) (pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - winInitVisuals failed\n");
+ return FALSE;
+ }
+
+ /* Setup a local variable to point to the framebuffer */
+ pbits = pScreenInfo->pfb;
+
+ /* Apparently we need this for the render extension */
+ miSetPixmapDepths ();
+
+ /* Start fb initialization */
+ if (!fbSetupScreen (pScreen,
+ pScreenInfo->pfb,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ monitorResolution, monitorResolution,
+ pScreenInfo->dwStride,
+ pScreenInfo->dwBPP))
+ {
+ ErrorF ("winFinishScreenInitFB - fbSetupScreen failed\n");
+ return FALSE;
+ }
+
+ /* Override default colormap routines if visual class is dynamic */
+ if (pScreenInfo->dwDepth == 8
+ && (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
+ || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
+ && pScreenInfo->fFullScreen)
+ || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
+ && pScreenInfo->fFullScreen)))
+ {
+ winSetColormapFunctions (pScreen);
+
+ /*
+ * NOTE: Setting whitePixel to 255 causes Magic 7.1 to allocate its
+ * own colormap, as it cannot allocate 7 planes in the default
+ * colormap. Setting whitePixel to 1 allows Magic to get 7
+ * planes in the default colormap, so it doesn't create its
+ * own colormap. This latter situation is highly desireable,
+ * as it keeps the Magic window viewable when switching to
+ * other X clients that use the default colormap.
+ */
+ pScreen->blackPixel = 0;
+ pScreen->whitePixel = 1;
+ }
+
+ /* Place our save screen function */
+ pScreen->SaveScreen = winSaveScreen;
+
+ /* Finish fb initialization */
+ if (!fbFinishScreenInit (pScreen,
+ pScreenInfo->pfb,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ monitorResolution, monitorResolution,
+ pScreenInfo->dwStride,
+ pScreenInfo->dwBPP))
+ {
+ ErrorF ("winFinishScreenInitFB - fbFinishScreenInit failed\n");
+ return FALSE;
+ }
+
+ /* Save a pointer to the root visual */
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != pScreen->rootVisual;
+ pVisual++);
+ pScreenPriv->pRootVisual = pVisual;
+
+ /*
+ * Setup points to the block and wakeup handlers. Pass a pointer
+ * to the current screen as pWakeupdata.
+ */
+ pScreen->BlockHandler = winBlockHandler;
+ pScreen->WakeupHandler = winWakeupHandler;
+ pScreen->blockData = pScreen;
+ pScreen->wakeupData = pScreen;
+
+ /* Render extension initialization, calls miPictureInit */
+ if (!fbPictureInit (pScreen, NULL, 0))
+ {
+ ErrorF ("winFinishScreenInitFB - fbPictureInit () failed\n");
+ return FALSE;
+ }
+
+#ifdef RANDR
+ /* Initialize resize and rotate support */
+ if (!winRandRInit (pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - winRandRInit () failed\n");
+ return FALSE;
+ }
+#endif
+
+ /* Setup the cursor routines */
+#if CYGDEBUG
+ winDebug ("winFinishScreenInitFB - Calling miDCInitialize ()\n");
+#endif
+ miDCInitialize (pScreen, &g_winPointerCursorFuncs);
+
+ /* KDrive does winCreateDefColormap right after miDCInitialize */
+ /* Create a default colormap */
+#if CYGDEBUG
+ winDebug ("winFinishScreenInitFB - Calling winCreateDefColormap ()\n");
+#endif
+ if (!winCreateDefColormap (pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - Could not create colormap\n");
+ return FALSE;
+ }
+
+ /* Initialize the shadow framebuffer layer */
+ if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
+ || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
+ || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)
+#ifdef XWIN_MULTIWINDOWEXTWM
+ && !pScreenInfo->fMWExtWM
+#endif
+ )
+ {
+#if CYGDEBUG
+ winDebug ("winFinishScreenInitFB - Calling shadowSetup ()\n");
+#endif
+ if (!shadowSetup(pScreen))
+ {
+ ErrorF ("winFinishScreenInitFB - shadowSetup () failed\n");
+ return FALSE;
+ }
+
+ /* Wrap CreateScreenResources so we can add the screen pixmap
+ to the Shadow framebuffer after it's been created */
+ pScreenPriv->pwinCreateScreenResources = pScreen->CreateScreenResources;
+ pScreen->CreateScreenResources = winCreateScreenResources;
+ }
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ /* Handle multi-window external window manager mode */
+ if (pScreenInfo->fMWExtWM)
+ {
+ winDebug ("winScreenInit - MultiWindowExtWM - Calling RootlessInit\n");
+
+ RootlessInit(pScreen, &winMWExtWMProcs);
+
+ winDebug ("winScreenInit - MultiWindowExtWM - RootlessInit returned\n");
+
+ rootless_CopyBytes_threshold = 0;
+ /* FIXME: How many? Profiling needed? */
+ rootless_CopyWindow_threshold = 1;
+
+ winWindowsWMExtensionInit ();
+ }
+#endif
+
+ /* Handle rootless mode */
+ if (pScreenInfo->fRootless)
+ {
+ /* Define the WRAP macro temporarily for local use */
+#define WRAP(a) \
+ if (pScreen->a) { \
+ pScreenPriv->a = pScreen->a; \
+ } else { \
+ ErrorF("null screen fn " #a "\n"); \
+ pScreenPriv->a = NULL; \
+ }
+
+ /* Save a pointer to each lower-level window procedure */
+ WRAP(CreateWindow);
+ WRAP(DestroyWindow);
+ WRAP(RealizeWindow);
+ WRAP(UnrealizeWindow);
+ WRAP(PositionWindow);
+ WRAP(ChangeWindowAttributes);
+ WRAP(SetShape);
+
+ /* Assign rootless window procedures to be top level procedures */
+ pScreen->CreateWindow = winCreateWindowRootless;
+ pScreen->DestroyWindow = winDestroyWindowRootless;
+ pScreen->PositionWindow = winPositionWindowRootless;
+ /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesRootless;*/
+ pScreen->RealizeWindow = winMapWindowRootless;
+ pScreen->UnrealizeWindow = winUnmapWindowRootless;
+ pScreen->SetShape = winSetShapeRootless;
+
+ /* Undefine the WRAP macro, as it is not needed elsewhere */
+#undef WRAP
+ }
+
+
+#ifdef XWIN_MULTIWINDOW
+ /* Handle multi window mode */
+ else if (pScreenInfo->fMultiWindow)
+ {
+ /* Define the WRAP macro temporarily for local use */
+#define WRAP(a) \
+ if (pScreen->a) { \
+ pScreenPriv->a = pScreen->a; \
+ } else { \
+ ErrorF("null screen fn " #a "\n"); \
+ pScreenPriv->a = NULL; \
+ }
+
+ /* Save a pointer to each lower-level window procedure */
+ WRAP(CreateWindow);
+ WRAP(DestroyWindow);
+ WRAP(RealizeWindow);
+ WRAP(UnrealizeWindow);
+ WRAP(PositionWindow);
+ WRAP(ChangeWindowAttributes);
+ WRAP(ReparentWindow);
+ WRAP(RestackWindow);
+ WRAP(ResizeWindow);
+ WRAP(MoveWindow);
+ WRAP(CopyWindow);
+ WRAP(SetShape);
+
+ /* Assign multi-window window procedures to be top level procedures */
+ pScreen->CreateWindow = winCreateWindowMultiWindow;
+ pScreen->DestroyWindow = winDestroyWindowMultiWindow;
+ pScreen->PositionWindow = winPositionWindowMultiWindow;
+ /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesMultiWindow;*/
+ pScreen->RealizeWindow = winMapWindowMultiWindow;
+ pScreen->UnrealizeWindow = winUnmapWindowMultiWindow;
+ pScreen->ReparentWindow = winReparentWindowMultiWindow;
+ pScreen->RestackWindow = winRestackWindowMultiWindow;
+ pScreen->ResizeWindow = winResizeWindowMultiWindow;
+ pScreen->MoveWindow = winMoveWindowMultiWindow;
+ pScreen->CopyWindow = winCopyWindowMultiWindow;
+ pScreen->SetShape = winSetShapeMultiWindow;
+
+ /* Undefine the WRAP macro, as it is not needed elsewhere */
+#undef WRAP
+ }
+#endif
+
+ /* Wrap either fb's or shadow's CloseScreen with our CloseScreen */
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = pScreenPriv->pwinCloseScreen;
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Create a mutex for modules in separate threads to wait for */
+ iReturn = pthread_mutex_init (&pScreenPriv->pmServerStarted, NULL);
+ if (iReturn != 0)
+ {
+ ErrorF ("winFinishScreenInitFB - pthread_mutex_init () failed: %d\n",
+ iReturn);
+ return FALSE;
+ }
+
+ /* Own the mutex for modules in separate threads */
+ iReturn = pthread_mutex_lock (&pScreenPriv->pmServerStarted);
+ if (iReturn != 0)
+ {
+ ErrorF ("winFinishScreenInitFB - pthread_mutex_lock () failed: %d\n",
+ iReturn);
+ return FALSE;
+ }
+
+ /* Set the ServerStarted flag to false */
+ pScreenPriv->fServerStarted = FALSE;
+#endif
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ pScreenPriv->fRestacking = FALSE;
+#endif
+
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+ if (FALSE
+#ifdef XWIN_MULTIWINDOW
+ || pScreenInfo->fMultiWindow
+#endif
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || pScreenInfo->fInternalWM
+#endif
+ )
+ {
+#if CYGDEBUG || YES
+ winDebug ("winFinishScreenInitFB - Calling winInitWM.\n");
+#endif
+
+ /* Initialize multi window mode */
+ if (!winInitWM (&pScreenPriv->pWMInfo,
+ &pScreenPriv->ptWMProc,
+ &pScreenPriv->ptXMsgProc,
+ &pScreenPriv->pmServerStarted,
+ pScreenInfo->dwScreen,
+ (HWND)&pScreenPriv->hwndScreen,
+#ifdef XWIN_MULTIWINDOWEXTWM
+ pScreenInfo->fInternalWM ||
+#endif
+ FALSE))
+ {
+ ErrorF ("winFinishScreenInitFB - winInitWM () failed.\n");
+ return FALSE;
+ }
+ }
+#endif
+
+ /* Tell the server that we are enabled */
+ pScreenPriv->fEnabled = TRUE;
+
+ /* Tell the server that we have a valid depth */
+ pScreenPriv->fBadDepth = FALSE;
+
+#if CYGDEBUG || YES
+ winDebug ("winFinishScreenInitFB - returning\n");
+#endif
+
+ return TRUE;
+}
+
+#ifdef XWIN_NATIVEGDI
+/* See Porting Layer Definition - p. 20 */
+
+Bool
+winFinishScreenInitNativeGDI (int index,
+ ScreenPtr pScreen,
+ int argc, char **argv)
+{
+ winScreenPriv(pScreen);
+ winScreenInfoPtr pScreenInfo = &g_ScreenInfo[index];
+ VisualPtr pVisuals = NULL;
+ DepthPtr pDepths = NULL;
+ VisualID rootVisual = 0;
+ int nVisuals = 0, nDepths = 0, nRootDepth = 0;
+
+ /* Ignore user input (mouse, keyboard) */
+ pScreenInfo->fIgnoreInput = FALSE;
+
+ /* Get device contexts for the screen and shadow bitmap */
+ pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
+ if (pScreenPriv->hdcScreen == NULL)
+ FatalError ("winFinishScreenInitNativeGDI - Couldn't get a DC\n");
+
+ /* Init visuals */
+ if (!(*pScreenPriv->pwinInitVisuals) (pScreen))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - pwinInitVisuals failed\n");
+ return FALSE;
+ }
+
+ /* Initialize the mi visuals */
+ if (!miInitVisuals (&pVisuals, &pDepths, &nVisuals, &nDepths, &nRootDepth,
+ &rootVisual,
+ ((unsigned long)1 << (pScreenInfo->dwDepth - 1)), 8,
+ TrueColor))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - miInitVisuals () failed\n");
+ return FALSE;
+ }
+
+ /* Initialize the CloseScreen procedure pointer */
+ pScreen->CloseScreen = NULL;
+
+ /* Initialize the mi code */
+ if (!miScreenInit (pScreen,
+ NULL, /* No framebuffer */
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ monitorResolution, monitorResolution,
+ pScreenInfo->dwStride,
+ nRootDepth, nDepths, pDepths, rootVisual,
+ nVisuals, pVisuals))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - miScreenInit failed\n");
+ return FALSE;
+ }
+
+ pScreen->defColormap = FakeClientID(0);
+
+ /*
+ * Register our block and wakeup handlers; these procedures
+ * process messages in our Windows message queue; specifically,
+ * they process mouse and keyboard input.
+ */
+ pScreen->BlockHandler = winBlockHandler;
+ pScreen->WakeupHandler = winWakeupHandler;
+ pScreen->blockData = pScreen;
+ pScreen->wakeupData = pScreen;
+
+ /* Place our save screen function */
+ pScreen->SaveScreen = winSaveScreen;
+
+ /* Pixmaps */
+ pScreen->CreatePixmap = winCreatePixmapNativeGDI;
+ pScreen->DestroyPixmap = winDestroyPixmapNativeGDI;
+
+ /* Other Screen Routines */
+ pScreen->QueryBestSize = winQueryBestSizeNativeGDI;
+ pScreen->SaveScreen = winSaveScreen;
+ pScreen->GetImage = miGetImage;
+ pScreen->GetSpans = winGetSpansNativeGDI;
+
+ /* Window Procedures */
+ pScreen->CreateWindow = winCreateWindowNativeGDI;
+ pScreen->DestroyWindow = winDestroyWindowNativeGDI;
+ pScreen->PositionWindow = winPositionWindowNativeGDI;
+ /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesNativeGDI;*/
+ pScreen->RealizeWindow = winMapWindowNativeGDI;
+ pScreen->UnrealizeWindow = winUnmapWindowNativeGDI;
+
+ /* Paint window */
+ pScreen->CopyWindow = winCopyWindowNativeGDI;
+
+ /* Fonts */
+ pScreen->RealizeFont = winRealizeFontNativeGDI;
+ pScreen->UnrealizeFont = winUnrealizeFontNativeGDI;
+
+ /* GC */
+ pScreen->CreateGC = winCreateGCNativeGDI;
+
+ /* Colormap Routines */
+ pScreen->CreateColormap = miInitializeColormap;
+ pScreen->DestroyColormap = (DestroyColormapProcPtr) (void (*)(void)) NoopDDA;
+ pScreen->InstallColormap = miInstallColormap;
+ pScreen->UninstallColormap = miUninstallColormap;
+ pScreen->ListInstalledColormaps = miListInstalledColormaps;
+ pScreen->StoreColors = (StoreColorsProcPtr) (void (*)(void)) NoopDDA;
+ pScreen->ResolveColor = miResolveColor;
+
+ /* Bitmap */
+ pScreen->BitmapToRegion = winPixmapToRegionNativeGDI;
+
+ ErrorF ("winFinishScreenInitNativeGDI - calling miDCInitialize\n");
+
+ /* Set the default white and black pixel positions */
+ pScreen->whitePixel = pScreen->blackPixel = (Pixel) 0;
+
+ /* Initialize the cursor */
+ if (!miDCInitialize (pScreen, &g_winPointerCursorFuncs))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - miDCInitialize failed\n");
+ return FALSE;
+ }
+
+ /* Create a default colormap */
+ if (!miCreateDefColormap (pScreen))
+ {
+ ErrorF ("winFinishScreenInitNativeGDI - miCreateDefColormap () "
+ "failed\n");
+ return FALSE;
+ }
+
+ ErrorF ("winFinishScreenInitNativeGDI - miCreateDefColormap () "
+ "returned\n");
+
+ /* mi doesn't use a CloseScreen procedure, so no need to wrap */
+ pScreen->CloseScreen = pScreenPriv->pwinCloseScreen;
+
+ /* Tell the server that we are enabled */
+ pScreenPriv->fEnabled = TRUE;
+
+ ErrorF ("winFinishScreenInitNativeGDI - Successful addition of "
+ "screen %08x\n",
+ (unsigned int) pScreen);
+
+ return TRUE;
+}
+#endif
+
+
+/* See Porting Layer Definition - p. 33 */
+static Bool
+winSaveScreen (ScreenPtr pScreen, int on)
+{
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winshaddd.c b/xorg-server/hw/xwin/winshaddd.c
index ae49d5a3d..00d7a379f 100644
--- a/xorg-server/hw/xwin/winshaddd.c
+++ b/xorg-server/hw/xwin/winshaddd.c
@@ -1,1400 +1,1366 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Dakshinamurthy Karra
- * Suhaib M Siddiqi
- * Peter Busch
- * Harold L Hunt II
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-
-
-/*
- * FIXME: Headers are broken, DEFINE_GUID doesn't work correctly,
- * so we have to redefine it here.
- */
-#ifdef DEFINE_GUID
-#undef DEFINE_GUID
-#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-#endif /* DEFINE_GUID */
-
-
-/*
- * FIXME: Headers are broken, IID_IDirectDraw2 has to be defined
- * here manually. Should be handled by ddraw.h
- */
-#ifndef IID_IDirectDraw2
-DEFINE_GUID( IID_IDirectDraw2,0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
-#endif /* IID_IDirectDraw2 */
-
-
-/*
- * Local prototypes
- */
-
-static Bool
-winAllocateFBShadowDD (ScreenPtr pScreen);
-
-static void
-winShadowUpdateDD (ScreenPtr pScreen,
- shadowBufPtr pBuf);
-
-static Bool
-winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen);
-
-static Bool
-winInitVisualsShadowDD (ScreenPtr pScreen);
-
-static Bool
-winAdjustVideoModeShadowDD (ScreenPtr pScreen);
-
-static Bool
-winBltExposedRegionsShadowDD (ScreenPtr pScreen);
-
-static Bool
-winActivateAppShadowDD (ScreenPtr pScreen);
-
-static Bool
-winRedrawScreenShadowDD (ScreenPtr pScreen);
-
-static Bool
-winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen);
-
-static Bool
-winInstallColormapShadowDD (ColormapPtr pColormap);
-
-static Bool
-winStoreColorsShadowDD (ColormapPtr pmap,
- int ndef,
- xColorItem *pdefs);
-
-static Bool
-winCreateColormapShadowDD (ColormapPtr pColormap);
-
-static Bool
-winDestroyColormapShadowDD (ColormapPtr pColormap);
-
-static Bool
-winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen);
-
-static Bool
-winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen);
-
-
-/*
- * Create the primary surface and attach the clipper.
- * Used for both the initial surface creation and during
- * WM_DISPLAYCHANGE messages.
- */
-
-static Bool
-winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- HRESULT ddrval = DD_OK;
- DDSURFACEDESC ddsd;
-
- /* Describe the primary surface */
- ZeroMemory (&ddsd, sizeof (ddsd));
- ddsd.dwSize = sizeof (ddsd);
- ddsd.dwFlags = DDSD_CAPS;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
-
- /* Create the primary surface */
- ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
- &ddsd,
- &pScreenPriv->pddsPrimary,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winCreatePrimarySurfaceShadowDD - Could not create primary "
- "surface: %08x\n", (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winCreatePrimarySurfaceShadowDD - Created primary surface\n");
-#endif
-
- /*
- * Attach a clipper to the primary surface that will clip our blits to our
- * display window.
- */
- ddrval = IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary,
- pScreenPriv->pddcPrimary);
- if (FAILED (ddrval))
- {
- ErrorF ("winCreatePrimarySurfaceShadowDD - Primary attach clipper "
- "failed: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winCreatePrimarySurfaceShadowDD - Attached clipper to "
- "primary surface\n");
-#endif
-
- /* Everything was correct */
- return TRUE;
-}
-
-
-/*
- * Detach the clipper and release the primary surface.
- * Called from WM_DISPLAYCHANGE.
- */
-
-static Bool
-winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
-
- ErrorF ("winReleasePrimarySurfaceShadowDD - Hello\n");
-
- /* Release the primary surface and clipper, if they exist */
- if (pScreenPriv->pddsPrimary)
- {
- /*
- * Detach the clipper from the primary surface.
- * NOTE: We do this explicity for clarity. The Clipper is not released.
- */
- IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary,
- NULL);
-
- ErrorF ("winReleasePrimarySurfaceShadowDD - Detached clipper\n");
-
- /* Release the primary surface */
- IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
- pScreenPriv->pddsPrimary = NULL;
- }
-
- ErrorF ("winReleasePrimarySurfaceShadowDD - Released primary surface\n");
-
- return TRUE;
-}
-
-
-/*
- * Create a DirectDraw surface for the shadow framebuffer; also create
- * a primary surface object so we can blit to the display.
- *
- * Install a DirectDraw clipper on our primary surface object
- * that clips our blits to the unobscured client area of our display window.
- */
-
-static Bool
-winAllocateFBShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HRESULT ddrval = DD_OK;
- DDSURFACEDESC ddsd;
- DDSURFACEDESC *pddsdShadow = NULL;
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDD\n");
-#endif
-
- /* Create a clipper */
- ddrval = (*g_fpDirectDrawCreateClipper) (0,
- &pScreenPriv->pddcPrimary,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Could not create clipper: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDD - Created a clipper\n");
-#endif
-
- /* Get a device context for the screen */
- pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
-
- /* Attach the clipper to our display window */
- ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary,
- 0,
- pScreenPriv->hwndScreen);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Clipper not attached to "
- "window: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDD - Attached clipper to window\n");
-#endif
-
- /* Create a DirectDraw object, store the address at lpdd */
- ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Could not start DirectDraw: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDD () - Created and initialized DD\n");
-#endif
-
- /* Get a DirectDraw2 interface pointer */
- ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
- &IID_IDirectDraw2,
- (LPVOID*) &pScreenPriv->pdd2);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
- /* Are we full screen? */
- if (pScreenInfo->fFullScreen)
- {
- DDSURFACEDESC ddsdCurrent;
- DWORD dwRefreshRateCurrent = 0;
- HDC hdc = NULL;
-
- /* Set the cooperative level to full screen */
- ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
- pScreenPriv->hwndScreen,
- DDSCL_EXCLUSIVE
- | DDSCL_FULLSCREEN);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Could not set "
- "cooperative level: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
- /*
- * We only need to get the current refresh rate for comparison
- * if a refresh rate has been passed on the command line.
- */
- if (pScreenInfo->dwRefreshRate != 0)
- {
- ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent));
- ddsdCurrent.dwSize = sizeof (ddsdCurrent);
-
- /* Get information about current display settings */
- ddrval = IDirectDraw2_GetDisplayMode (pScreenPriv->pdd2,
- &ddsdCurrent);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Could not get current "
- "refresh rate: %08x. Continuing.\n",
- (unsigned int) ddrval);
- dwRefreshRateCurrent = 0;
- }
- else
- {
- /* Grab the current refresh rate */
- dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate;
- }
- }
-
- /* Clean up the refresh rate */
- if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate)
- {
- /*
- * Refresh rate is non-specified or equal to current.
- */
- pScreenInfo->dwRefreshRate = 0;
- }
-
- /* Grab a device context for the screen */
- hdc = GetDC (NULL);
- if (hdc == NULL)
- {
- ErrorF ("winAllocateFBShadowDD - GetDC () failed\n");
- return FALSE;
- }
-
- /* Only change the video mode when different than current mode */
- if (!pScreenInfo->fMultipleMonitors
- && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN)
- || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN)
- || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL)
- || pScreenInfo->dwRefreshRate != 0))
- {
- ErrorF ("winAllocateFBShadowDD - Changing video mode\n");
-
- /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
- ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
- pScreenInfo->dwWidth,
- pScreenInfo->dwHeight,
- pScreenInfo->dwBPP,
- pScreenInfo->dwRefreshRate,
- 0);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Could not set "\
- "full screen display mode: %08x\n",
- (unsigned int) ddrval);
- ErrorF ("winAllocateFBShadowDD - Using default driver refresh rate\n");
- ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
- pScreenInfo->dwWidth,
- pScreenInfo->dwHeight,
- pScreenInfo->dwBPP,
- 0,
- 0);
- if (FAILED(ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Could not set default refresh rate "
- "full screen display mode: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
- }
- }
- else
- {
- ErrorF ("winAllocateFBShadowDD - Not changing video mode\n");
- }
-
- /* Release our DC */
- ReleaseDC (NULL, hdc);
- hdc = NULL;
- }
- else
- {
- /* Set the cooperative level for windowed mode */
- ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
- pScreenPriv->hwndScreen,
- DDSCL_NORMAL);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Could not set "\
- "cooperative level: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
- }
-
- /* Create the primary surface */
- if (!winCreatePrimarySurfaceShadowDD (pScreen))
- {
- ErrorF ("winAllocateFBShadowDD - winCreatePrimarySurfaceShadowDD "
- "failed\n");
- return FALSE;
- }
-
- /* Describe the shadow surface to be created */
- /* NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
- * as drawing, locking, and unlocking take forever
- * with video memory surfaces. In addition,
- * video memory is a somewhat scarce resource,
- * so you shouldn't be allocating video memory when
- * you have the option of using system memory instead.
- */
- ZeroMemory (&ddsd, sizeof (ddsd));
- ddsd.dwSize = sizeof (ddsd);
- ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
- ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
- ddsd.dwHeight = pScreenInfo->dwHeight;
- ddsd.dwWidth = pScreenInfo->dwWidth;
-
- /* Create the shadow surface */
- ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
- &ddsd,
- &pScreenPriv->pddsShadow,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDD - Could not create shadow "\
- "surface: %08x\n", (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDD - Created shadow\n");
-#endif
-
- /* Allocate a DD surface description for our screen privates */
- pddsdShadow = pScreenPriv->pddsdShadow = malloc (sizeof (DDSURFACEDESC));
- if (pddsdShadow == NULL)
- {
- ErrorF ("winAllocateFBShadowDD - Could not allocate surface "\
- "description memory\n");
- return FALSE;
- }
- ZeroMemory (pddsdShadow, sizeof (*pddsdShadow));
- pddsdShadow->dwSize = sizeof (*pddsdShadow);
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDD - Locking shadow\n");
-#endif
-
- /* Lock the shadow surface */
- ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
- NULL,
- pddsdShadow,
- DDLOCK_WAIT,
- NULL);
- if (FAILED (ddrval) || pddsdShadow->lpSurface == NULL)
- {
- ErrorF ("winAllocateFBShadowDD - Could not lock shadow "\
- "surface: %08x\n", (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDD - Locked shadow\n");
-#endif
-
- /* We don't know how to deal with anything other than RGB */
- if (!(pddsdShadow->ddpfPixelFormat.dwFlags & DDPF_RGB))
- {
- ErrorF ("winAllocateFBShadowDD - Color format other than RGB\n");
- return FALSE;
- }
-
- /* Grab the pitch from the surface desc */
- pScreenInfo->dwStride = (pddsdShadow->u1.lPitch * 8)
- / pScreenInfo->dwBPP;
-
- /* Save the pointer to our surface memory */
- pScreenInfo->pfb = pddsdShadow->lpSurface;
-
- /* Grab the color depth and masks from the surface description */
- pScreenPriv->dwRedMask = pddsdShadow->ddpfPixelFormat.u2.dwRBitMask;
- pScreenPriv->dwGreenMask = pddsdShadow->ddpfPixelFormat.u3.dwGBitMask;
- pScreenPriv->dwBlueMask = pddsdShadow->ddpfPixelFormat.u4.dwBBitMask;
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDD - Returning\n");
-#endif
-
- return TRUE;
-}
-
-
-/*
- * Transfer the damaged regions of the shadow framebuffer to the display.
- */
-
-static void
-winShadowUpdateDD (ScreenPtr pScreen,
- shadowBufPtr pBuf)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- RegionPtr damage = shadowDamage(pBuf);
- HRESULT ddrval = DD_OK;
- RECT rcDest, rcSrc;
- POINT ptOrigin;
- DWORD dwBox = RegionNumRects (damage);
- BoxPtr pBox = RegionRects (damage);
- HRGN hrgnTemp = NULL, hrgnCombined = NULL;
-
- /*
- * Return immediately if the app is not active
- * and we are fullscreen, or if we have a bad display depth
- */
- if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
- || pScreenPriv->fBadDepth) return;
-
- /* Get the origin of the window in the screen coords */
- ptOrigin.x = pScreenInfo->dwXOffset;
- ptOrigin.y = pScreenInfo->dwYOffset;
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&ptOrigin, 1);
-
- /* Unlock the shadow surface, so we can blit */
- ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winShadowUpdateDD - Unlock failed\n");
- return;
- }
-
- /*
- * Handle small regions with multiple blits,
- * handle large regions by creating a clipping region and
- * doing a single blit constrained to that clipping region.
- */
- if (pScreenInfo->dwClipUpdatesNBoxes == 0
- || dwBox < pScreenInfo->dwClipUpdatesNBoxes)
- {
- /* Loop through all boxes in the damaged region */
- while (dwBox--)
- {
- /* Assign damage box to source rectangle */
- rcSrc.left = pBox->x1;
- rcSrc.top = pBox->y1;
- rcSrc.right = pBox->x2;
- rcSrc.bottom = pBox->y2;
-
- /* Calculate destination rectange */
- rcDest.left = ptOrigin.x + rcSrc.left;
- rcDest.top = ptOrigin.y + rcSrc.top;
- rcDest.right = ptOrigin.x + rcSrc.right;
- rcDest.bottom = ptOrigin.y + rcSrc.bottom;
-
- /* Blit the damaged areas */
- ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
- &rcDest,
- pScreenPriv->pddsShadow,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
-
- /* Get a pointer to the next box */
- ++pBox;
- }
- }
- else
- {
- BoxPtr pBoxExtents = RegionExtents(damage);
-
- /* Compute a GDI region from the damaged region */
- hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
- dwBox--;
- pBox++;
- while (dwBox--)
- {
- hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
- CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
- DeleteObject (hrgnTemp);
- pBox++;
- }
-
- /* Install the GDI region as a clipping region */
- SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
- DeleteObject (hrgnCombined);
- hrgnCombined = NULL;
-
- /* Calculating a bounding box for the source is easy */
- rcSrc.left = pBoxExtents->x1;
- rcSrc.top = pBoxExtents->y1;
- rcSrc.right = pBoxExtents->x2;
- rcSrc.bottom = pBoxExtents->y2;
-
- /* Calculating a bounding box for the destination is trickier */
- rcDest.left = ptOrigin.x + rcSrc.left;
- rcDest.top = ptOrigin.y + rcSrc.top;
- rcDest.right = ptOrigin.x + rcSrc.right;
- rcDest.bottom = ptOrigin.y + rcSrc.bottom;
-
- /* Our Blt should be clipped to the invalidated region */
- ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
- &rcDest,
- pScreenPriv->pddsShadow,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
-
- /* Reset the clip region */
- SelectClipRgn (pScreenPriv->hdcScreen, NULL);
- }
-
- /* Relock the shadow surface */
- ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
- NULL,
- pScreenPriv->pddsdShadow,
- DDLOCK_WAIT,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winShadowUpdateDD - Lock failed\n");
- return;
- }
-
- /* Has our memory pointer changed? */
- if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
- {
- ErrorF ("winShadowUpdateDD - Memory location of the shadow "
- "surface has changed, trying to update the root window "
- "pixmap header to point to the new address. If you get "
- "this message and "PROJECT_NAME" freezes or crashes "
- "after this message then send a problem report and your "
- "%s file to " BUILDERADDR "\n", g_pszLogFile);
-
- /* Location of shadow framebuffer has changed */
- pScreenInfo->pfb = pScreenPriv->pddsdShadow->lpSurface;
-
- /* Update the screen pixmap */
- if (!(*pScreen->ModifyPixmapHeader)(pScreen->devPrivate,
- pScreen->width,
- pScreen->height,
- pScreen->rootDepth,
- BitsPerPixel (pScreen->rootDepth),
- PixmapBytePad (pScreenInfo->dwStride,
- pScreenInfo->dwBPP),
- pScreenInfo->pfb))
- {
- ErrorF ("winShadowUpdateDD - Bits changed, could not "
- "notify fb.\n");
- return;
- }
- }
-}
-
-
-/*
- * Call the wrapped CloseScreen function.
- *
- * Free our resources and private structures.
- */
-
-static Bool
-winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- Bool fReturn;
-
-#if CYGDEBUG
- winDebug ("winCloseScreenShadowDD - Freeing screen resources\n");
-#endif
-
- /* Flag that the screen is closed */
- pScreenPriv->fClosed = TRUE;
- pScreenPriv->fActive = FALSE;
-
- /* Call the wrapped CloseScreen procedure */
- WIN_UNWRAP(CloseScreen);
- fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
-
- /* Free the screen DC */
- ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
-
- /* Delete the window property */
- RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
-
- /* Free the shadow surface, if there is one */
- if (pScreenPriv->pddsShadow)
- {
- IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
- IDirectDrawSurface2_Release (pScreenPriv->pddsShadow);
- pScreenPriv->pddsShadow = NULL;
- }
-
- /* Detach the clipper from the primary surface and release the clipper. */
- if (pScreenPriv->pddcPrimary)
- {
- /* Detach the clipper */
- IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary,
- NULL);
-
- /* Release the clipper object */
- IDirectDrawClipper_Release (pScreenPriv->pddcPrimary);
- pScreenPriv->pddcPrimary = NULL;
- }
-
- /* Release the primary surface, if there is one */
- if (pScreenPriv->pddsPrimary)
- {
- IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
- pScreenPriv->pddsPrimary = NULL;
- }
-
- /* Free the DirectDraw2 object, if there is one */
- if (pScreenPriv->pdd2)
- {
- IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd2);
- IDirectDraw2_Release (pScreenPriv->pdd2);
- pScreenPriv->pdd2 = NULL;
- }
-
- /* Free the DirectDraw object, if there is one */
- if (pScreenPriv->pdd)
- {
- IDirectDraw_Release (pScreenPriv->pdd);
- pScreenPriv->pdd = NULL;
- }
-
- /* Delete tray icon, if we have one */
- if (!pScreenInfo->fNoTrayIcon)
- winDeleteNotifyIcon (pScreenPriv);
-
- /* Free the exit confirmation dialog box, if it exists */
- if (g_hDlgExit != NULL)
- {
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
- }
-
- /* Kill our window */
- if (pScreenPriv->hwndScreen)
- {
- DestroyWindow (pScreenPriv->hwndScreen);
- pScreenPriv->hwndScreen = NULL;
- }
-
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
- /* Destroy the thread startup mutex */
- pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
-#endif
-
- /* Kill our screeninfo's pointer to the screen */
- pScreenInfo->pScreen = NULL;
-
- /* Invalidate the ScreenInfo's fb pointer */
- pScreenInfo->pfb = NULL;
-
- /* Free the screen privates for this screen */
- free ((pointer) pScreenPriv);
-
- return fReturn;
-}
-
-
-/*
- * Tell mi what sort of visuals we need.
- *
- * Generally we only need one visual, as our screen can only
- * handle one format at a time, I believe. You may want
- * to verify that last sentence.
- */
-
-static Bool
-winInitVisualsShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- DWORD dwRedBits, dwGreenBits, dwBlueBits;
-
- /* Count the number of ones in each color mask */
- dwRedBits = winCountBits (pScreenPriv->dwRedMask);
- dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
- dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
-
- /* Store the maximum number of ones in a color mask as the bitsPerRGB */
- if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0)
- pScreenPriv->dwBitsPerRGB = 8;
- else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
- pScreenPriv->dwBitsPerRGB = dwRedBits;
- else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
- pScreenPriv->dwBitsPerRGB = dwGreenBits;
- else
- pScreenPriv->dwBitsPerRGB = dwBlueBits;
-
- ErrorF ("winInitVisualsShadowDD - Masks %08x %08x %08x BPRGB %d d %d "
- "bpp %d\n",
- (unsigned int) pScreenPriv->dwRedMask,
- (unsigned int) pScreenPriv->dwGreenMask,
- (unsigned int) pScreenPriv->dwBlueMask,
- (int) pScreenPriv->dwBitsPerRGB,
- (int) pScreenInfo->dwDepth,
- (int) pScreenInfo->dwBPP);
-
- /* Create a single visual according to the Windows screen depth */
- switch (pScreenInfo->dwDepth)
- {
- case 24:
- case 16:
- case 15:
- /* Create the real visual */
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- TrueColorMask,
- pScreenPriv->dwBitsPerRGB,
- TrueColor,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
- "failed for TrueColor\n");
- return FALSE;
- }
-
-#ifdef XWIN_EMULATEPSEUDO
- if (!pScreenInfo->fEmulatePseudo)
- break;
-
- /* Setup a pseudocolor visual */
- if (!miSetVisualTypesAndMasks (8,
- PseudoColorMask,
- 8,
- -1,
- 0,
- 0,
- 0))
- {
- ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
- "failed for PseudoColor\n");
- return FALSE;
- }
-#endif
- break;
-
- case 8:
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- pScreenInfo->fFullScreen
- ? PseudoColorMask : StaticColorMask,
- pScreenPriv->dwBitsPerRGB,
- pScreenInfo->fFullScreen
- ? PseudoColor : StaticColor,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
- "failed\n");
- return FALSE;
- }
- break;
-
- default:
- ErrorF ("winInitVisualsShadowDD - Unknown screen depth\n");
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winInitVisualsShadowDD - Returning\n");
-#endif
-
- return TRUE;
-}
-
-
-/*
- * Adjust the user proposed video mode
- */
-
-static Bool
-winAdjustVideoModeShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HDC hdc = NULL;
- DWORD dwBPP;
-
- /* We're in serious trouble if we can't get a DC */
- hdc = GetDC (NULL);
- if (hdc == NULL)
- {
- ErrorF ("winAdjustVideoModeShadowDD - GetDC () failed\n");
- return FALSE;
- }
-
- /* Query GDI for current display depth */
- dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
-
- /* DirectDraw can only change the depth in fullscreen mode */
- if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP)
- {
- /* No -depth parameter passed, let the user know the depth being used */
- ErrorF ("winAdjustVideoModeShadowDD - Using Windows display "
- "depth of %d bits per pixel\n", (int) dwBPP);
-
- /* Use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
- else if (pScreenInfo->fFullScreen
- && pScreenInfo->dwBPP != dwBPP)
- {
- /* FullScreen, and GDI depth differs from -depth parameter */
- ErrorF ("winAdjustVideoModeShadowDD - FullScreen, using command line "
- "bpp: %d\n", (int) pScreenInfo->dwBPP);
- }
- else if (dwBPP != pScreenInfo->dwBPP)
- {
- /* Windowed, and GDI depth differs from -depth parameter */
- ErrorF ("winAdjustVideoModeShadowDD - Windowed, command line bpp: "
- "%d, using bpp: %d\n", (int) pScreenInfo->dwBPP, (int) dwBPP);
-
- /* We'll use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
-
- /* See if the shadow bitmap will be larger than the DIB size limit */
- if (pScreenInfo->dwWidth * pScreenInfo->dwHeight * pScreenInfo->dwBPP
- >= WIN_DIB_MAXIMUM_SIZE)
- {
- ErrorF ("winAdjustVideoModeShadowDD - Requested DirectDraw surface "
- "will be larger than %d MB. The surface may fail to be "
- "allocated on Windows 95, 98, or Me, due to a %d MB limit in "
- "DIB size. This limit does not apply to Windows NT/2000, and "
- "this message may be ignored on those platforms.\n",
- WIN_DIB_MAXIMUM_SIZE_MB, WIN_DIB_MAXIMUM_SIZE_MB);
- }
-
- /* Release our DC */
- ReleaseDC (NULL, hdc);
- return TRUE;
-}
-
-
-/*
- * Blt exposed regions to the screen
- */
-
-static Bool
-winBltExposedRegionsShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- RECT rcSrc, rcDest;
- POINT ptOrigin;
- HDC hdcUpdate = NULL;
- PAINTSTRUCT ps;
- HRESULT ddrval = DD_OK;
- Bool fReturn = TRUE;
- Bool fLocked = TRUE;
- int i;
-
- /* BeginPaint gives us an hdc that clips to the invalidated region */
- hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
- if (hdcUpdate == NULL)
- {
- ErrorF ("winBltExposedRegionsShadowDD - BeginPaint () returned "
- "a NULL device context handle. Aborting blit attempt.\n");
- return FALSE;
- }
-
- /* Unlock the shadow surface, so we can blit */
- ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
- if (FAILED (ddrval))
- {
- fReturn = FALSE;
- goto winBltExposedRegionsShadowDD_Exit;
- }
- else
- {
- /* Flag that we have unlocked the shadow surface */
- fLocked = FALSE;
- }
-
- /* Get the origin of the window in the screen coords */
- ptOrigin.x = pScreenInfo->dwXOffset;
- ptOrigin.y = pScreenInfo->dwYOffset;
-
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&ptOrigin, 1);
- rcDest.left = ptOrigin.x;
- rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
- rcDest.top = ptOrigin.y;
- rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
-
- /* Source can be enter shadow surface, as Blt should clip */
- rcSrc.left = 0;
- rcSrc.top = 0;
- rcSrc.right = pScreenInfo->dwWidth;
- rcSrc.bottom = pScreenInfo->dwHeight;
-
- /* Try to regain the primary surface and blit again if we've lost it */
- for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i)
- {
- /* Our Blt should be clipped to the invalidated region */
- ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
- &rcDest,
- pScreenPriv->pddsShadow,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
- if (ddrval == DDERR_SURFACELOST)
- {
- /* Surface was lost */
- ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
- "reported that the primary surface was lost, "
- "trying to restore, retry: %d\n", i + 1);
-
- /* Try to restore the surface, once */
- ddrval = IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
- ErrorF ("winBltExposedRegionsShadowDD - "
- "IDirectDrawSurface2_Restore returned: ");
- if (ddrval == DD_OK)
- ErrorF ("DD_OK\n");
- else if (ddrval == DDERR_WRONGMODE)
- ErrorF ("DDERR_WRONGMODE\n");
- else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
- ErrorF ("DDERR_INCOMPATIBLEPRIMARY\n");
- else if (ddrval == DDERR_UNSUPPORTED)
- ErrorF ("DDERR_UNSUPPORTED\n");
- else if (ddrval == DDERR_INVALIDPARAMS)
- ErrorF ("DDERR_INVALIDPARAMS\n");
- else if (ddrval == DDERR_INVALIDOBJECT)
- ErrorF ("DDERR_INVALIDOBJECT\n");
- else
- ErrorF ("unknown error: %08x\n", (unsigned int) ddrval);
-
- /* Loop around to try the blit one more time */
- continue;
- }
- else if (FAILED (ddrval))
- {
- fReturn = FALSE;
- ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
- "failed, but surface not lost: %08x %d\n",
- (unsigned int) ddrval, (int) ddrval);
- goto winBltExposedRegionsShadowDD_Exit;
- }
- else
- {
- /* Success, stop looping */
- break;
- }
- }
-
- /* Relock the shadow surface */
- ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
- NULL,
- pScreenPriv->pddsdShadow,
- DDLOCK_WAIT,
- NULL);
- if (FAILED (ddrval))
- {
- fReturn = FALSE;
- ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Lock "
- "failed\n");
- goto winBltExposedRegionsShadowDD_Exit;
- }
- else
- {
- /* Indicate that we have relocked the shadow surface */
- fLocked = TRUE;
- }
-
- /* Has our memory pointer changed? */
- if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
- winUpdateFBPointer (pScreen,
- pScreenPriv->pddsdShadow->lpSurface);
-
- winBltExposedRegionsShadowDD_Exit:
- /* EndPaint frees the DC */
- if (hdcUpdate != NULL)
- EndPaint (pScreenPriv->hwndScreen, &ps);
-
- /*
- * Relock the surface if it is not locked. We don't care if locking fails,
- * as it will cause the server to shutdown within a few more operations.
- */
- if (!fLocked)
- {
- IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
- NULL,
- pScreenPriv->pddsdShadow,
- DDLOCK_WAIT,
- NULL);
-
- /* Has our memory pointer changed? */
- if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
- winUpdateFBPointer (pScreen,
- pScreenPriv->pddsdShadow->lpSurface);
-
- fLocked = TRUE;
- }
- return fReturn;
-}
-
-
-/*
- * Do any engine-specific appliation-activation processing
- */
-
-static Bool
-winActivateAppShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
-
- /*
- * Do we have a surface?
- * Are we active?
- * Are we fullscreen?
- */
- if (pScreenPriv != NULL
- && pScreenPriv->pddsPrimary != NULL
- && pScreenPriv->fActive)
- {
- /* Primary surface was lost, restore it */
- IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
- }
-
- return TRUE;
-}
-
-
-/*
- * Reblit the shadow framebuffer to the screen.
- */
-
-static Bool
-winRedrawScreenShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HRESULT ddrval = DD_OK;
- RECT rcSrc, rcDest;
- POINT ptOrigin;
-
- /* Get the origin of the window in the screen coords */
- ptOrigin.x = pScreenInfo->dwXOffset;
- ptOrigin.y = pScreenInfo->dwYOffset;
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&ptOrigin, 1);
- rcDest.left = ptOrigin.x;
- rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
- rcDest.top = ptOrigin.y;
- rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
-
- /* Source can be entire shadow surface, as Blt should clip for us */
- rcSrc.left = 0;
- rcSrc.top = 0;
- rcSrc.right = pScreenInfo->dwWidth;
- rcSrc.bottom = pScreenInfo->dwHeight;
-
- /* Redraw the whole window, to take account for the new colors */
- ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
- &rcDest,
- pScreenPriv->pddsShadow,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winRedrawScreenShadowDD - IDirectDrawSurface_Blt () "
- "failed: %08x\n",
- (unsigned int) ddrval);
- }
-
- return TRUE;
-}
-
-
-/*
- * Realize the currently installed colormap
- */
-
-static Bool
-winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen)
-{
- return TRUE;
-}
-
-
-/*
- * Install the specified colormap
- */
-
-static Bool
-winInstallColormapShadowDD (ColormapPtr pColormap)
-{
- ScreenPtr pScreen = pColormap->pScreen;
- winScreenPriv(pScreen);
- winCmapPriv(pColormap);
- HRESULT ddrval = DD_OK;
-
- /* Install the DirectDraw palette on the primary surface */
- ddrval = IDirectDrawSurface2_SetPalette (pScreenPriv->pddsPrimary,
- pCmapPriv->lpDDPalette);
- if (FAILED (ddrval))
- {
- ErrorF ("winInstallColormapShadowDD - Failed installing the "
- "DirectDraw palette.\n");
- return FALSE;
- }
-
- /* Save a pointer to the newly installed colormap */
- pScreenPriv->pcmapInstalled = pColormap;
-
- return TRUE;
-}
-
-
-/*
- * Store the specified colors in the specified colormap
- */
-
-static Bool
-winStoreColorsShadowDD (ColormapPtr pColormap,
- int ndef,
- xColorItem *pdefs)
-{
- ScreenPtr pScreen = pColormap->pScreen;
- winScreenPriv(pScreen);
- winCmapPriv(pColormap);
- ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
- HRESULT ddrval = DD_OK;
-
- /* Put the X colormap entries into the Windows logical palette */
- ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette,
- 0,
- pdefs[0].pixel,
- ndef,
- pCmapPriv->peColors
- + pdefs[0].pixel);
- if (FAILED (ddrval))
- {
- ErrorF ("winStoreColorsShadowDD - SetEntries () failed\n");
- return FALSE;
- }
-
- /* Don't install the DirectDraw palette if the colormap is not installed */
- if (pColormap != curpmap)
- {
- return TRUE;
- }
-
- if (!winInstallColormapShadowDD (pColormap))
- {
- ErrorF ("winStoreColorsShadowDD - Failed installing colormap\n");
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * Colormap initialization procedure
- */
-
-static Bool
-winCreateColormapShadowDD (ColormapPtr pColormap)
-{
- HRESULT ddrval = DD_OK;
- ScreenPtr pScreen = pColormap->pScreen;
- winScreenPriv(pScreen);
- winCmapPriv(pColormap);
-
- /* Create a DirectDraw palette */
- ddrval = IDirectDraw2_CreatePalette (pScreenPriv->pdd,
- DDPCAPS_8BIT | DDPCAPS_ALLOW256,
- pCmapPriv->peColors,
- &pCmapPriv->lpDDPalette,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winCreateColormapShadowDD - CreatePalette failed\n");
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * Colormap destruction procedure
- */
-
-static Bool
-winDestroyColormapShadowDD (ColormapPtr pColormap)
-{
- winScreenPriv(pColormap->pScreen);
- winCmapPriv(pColormap);
- HRESULT ddrval = DD_OK;
-
- /*
- * Is colormap to be destroyed the default?
- *
- * Non-default colormaps should have had winUninstallColormap
- * called on them before we get here. The default colormap
- * will not have had winUninstallColormap called on it. Thus,
- * we need to handle the default colormap in a special way.
- */
- if (pColormap->flags & IsDefault)
- {
-#if CYGDEBUG
- winDebug ("winDestroyColormapShadowDD - Destroying default "
- "colormap\n");
-#endif
-
- /*
- * FIXME: Walk the list of all screens, popping the default
- * palette out of each screen device context.
- */
-
- /* Pop the palette out of the primary surface */
- ddrval = IDirectDrawSurface2_SetPalette (pScreenPriv->pddsPrimary,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winDestroyColormapShadowDD - Failed freeing the "
- "default colormap DirectDraw palette.\n");
- return FALSE;
- }
-
- /* Clear our private installed colormap pointer */
- pScreenPriv->pcmapInstalled = NULL;
- }
-
- /* Release the palette */
- IDirectDrawPalette_Release (pCmapPriv->lpDDPalette);
-
- /* Invalidate the colormap privates */
- pCmapPriv->lpDDPalette = NULL;
-
- return TRUE;
-}
-
-
-/*
- * Set engine specific functions
- */
-
-Bool
-winSetEngineFunctionsShadowDD (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /* Set our pointers */
- pScreenPriv->pwinAllocateFB = winAllocateFBShadowDD;
- pScreenPriv->pwinShadowUpdate = winShadowUpdateDD;
- pScreenPriv->pwinCloseScreen = winCloseScreenShadowDD;
- pScreenPriv->pwinInitVisuals = winInitVisualsShadowDD;
- pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDD;
- if (pScreenInfo->fFullScreen)
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
- else
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
- pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
- pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDD;
- pScreenPriv->pwinActivateApp = winActivateAppShadowDD;
- pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDD;
- pScreenPriv->pwinRealizeInstalledPalette
- = winRealizeInstalledPaletteShadowDD;
- pScreenPriv->pwinInstallColormap = winInstallColormapShadowDD;
- pScreenPriv->pwinStoreColors = winStoreColorsShadowDD;
- pScreenPriv->pwinCreateColormap = winCreateColormapShadowDD;
- pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDD;
- pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
- pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDD;
- pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDD;
-#ifdef XWIN_MULTIWINDOW
- pScreenPriv->pwinFinishCreateWindowsWindow =
- (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
-#endif
-
- return TRUE;
-}
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+
+
+/*
+ * FIXME: Headers are broken, DEFINE_GUID doesn't work correctly,
+ * so we have to redefine it here.
+ */
+#ifdef DEFINE_GUID
+#undef DEFINE_GUID
+#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+#endif /* DEFINE_GUID */
+
+
+/*
+ * FIXME: Headers are broken, IID_IDirectDraw2 has to be defined
+ * here manually. Should be handled by ddraw.h
+ */
+#ifndef IID_IDirectDraw2
+DEFINE_GUID( IID_IDirectDraw2,0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
+#endif /* IID_IDirectDraw2 */
+
+
+/*
+ * Local prototypes
+ */
+
+static Bool
+winAllocateFBShadowDD (ScreenPtr pScreen);
+
+static void
+winShadowUpdateDD (ScreenPtr pScreen,
+ shadowBufPtr pBuf);
+
+static Bool
+winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsShadowDD (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModeShadowDD (ScreenPtr pScreen);
+
+static Bool
+winBltExposedRegionsShadowDD (ScreenPtr pScreen);
+
+static Bool
+winActivateAppShadowDD (ScreenPtr pScreen);
+
+static Bool
+winRedrawScreenShadowDD (ScreenPtr pScreen);
+
+static Bool
+winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen);
+
+static Bool
+winInstallColormapShadowDD (ColormapPtr pColormap);
+
+static Bool
+winStoreColorsShadowDD (ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs);
+
+static Bool
+winCreateColormapShadowDD (ColormapPtr pColormap);
+
+static Bool
+winDestroyColormapShadowDD (ColormapPtr pColormap);
+
+static Bool
+winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen);
+
+static Bool
+winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen);
+
+
+/*
+ * Create the primary surface and attach the clipper.
+ * Used for both the initial surface creation and during
+ * WM_DISPLAYCHANGE messages.
+ */
+
+static Bool
+winCreatePrimarySurfaceShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC ddsd;
+
+ /* Describe the primary surface */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ /* Create the primary surface */
+ ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
+ &ddsd,
+ &pScreenPriv->pddsPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreatePrimarySurfaceShadowDD - Could not create primary "
+ "surface: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winCreatePrimarySurfaceShadowDD - Created primary surface\n");
+#endif
+
+ /*
+ * Attach a clipper to the primary surface that will clip our blits to our
+ * display window.
+ */
+ ddrval = IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary,
+ pScreenPriv->pddcPrimary);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreatePrimarySurfaceShadowDD - Primary attach clipper "
+ "failed: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winCreatePrimarySurfaceShadowDD - Attached clipper to "
+ "primary surface\n");
+#endif
+
+ /* Everything was correct */
+ return TRUE;
+}
+
+
+/*
+ * Detach the clipper and release the primary surface.
+ * Called from WM_DISPLAYCHANGE.
+ */
+
+static Bool
+winReleasePrimarySurfaceShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ ErrorF ("winReleasePrimarySurfaceShadowDD - Hello\n");
+
+ /* Release the primary surface and clipper, if they exist */
+ if (pScreenPriv->pddsPrimary)
+ {
+ /*
+ * Detach the clipper from the primary surface.
+ * NOTE: We do this explicity for clarity. The Clipper is not released.
+ */
+ IDirectDrawSurface2_SetClipper (pScreenPriv->pddsPrimary,
+ NULL);
+
+ ErrorF ("winReleasePrimarySurfaceShadowDD - Detached clipper\n");
+
+ /* Release the primary surface */
+ IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
+ pScreenPriv->pddsPrimary = NULL;
+ }
+
+ ErrorF ("winReleasePrimarySurfaceShadowDD - Released primary surface\n");
+
+ return TRUE;
+}
+
+
+/*
+ * Create a DirectDraw surface for the shadow framebuffer; also create
+ * a primary surface object so we can blit to the display.
+ *
+ * Install a DirectDraw clipper on our primary surface object
+ * that clips our blits to the unobscured client area of our display window.
+ */
+
+static Bool
+winAllocateFBShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC ddsd;
+ DDSURFACEDESC *pddsdShadow = NULL;
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDD\n");
+#endif
+
+ /* Create a clipper */
+ ddrval = (*g_fpDirectDrawCreateClipper) (0,
+ &pScreenPriv->pddcPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not create clipper: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDD - Created a clipper\n");
+#endif
+
+ /* Attach the clipper to our display window */
+ ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary,
+ 0,
+ pScreenPriv->hwndScreen);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Clipper not attached to "
+ "window: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDD - Attached clipper to window\n");
+#endif
+
+ /* Create a DirectDraw object, store the address at lpdd */
+ ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not start DirectDraw: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDD () - Created and initialized DD\n");
+#endif
+
+ /* Get a DirectDraw2 interface pointer */
+ ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
+ &IID_IDirectDraw2,
+ (LPVOID*) &pScreenPriv->pdd2);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /* Are we full screen? */
+ if (pScreenInfo->fFullScreen)
+ {
+ DDSURFACEDESC ddsdCurrent;
+ DWORD dwRefreshRateCurrent = 0;
+ HDC hdc = NULL;
+
+ /* Set the cooperative level to full screen */
+ ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
+ pScreenPriv->hwndScreen,
+ DDSCL_EXCLUSIVE
+ | DDSCL_FULLSCREEN);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not set "
+ "cooperative level: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /*
+ * We only need to get the current refresh rate for comparison
+ * if a refresh rate has been passed on the command line.
+ */
+ if (pScreenInfo->dwRefreshRate != 0)
+ {
+ ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent));
+ ddsdCurrent.dwSize = sizeof (ddsdCurrent);
+
+ /* Get information about current display settings */
+ ddrval = IDirectDraw2_GetDisplayMode (pScreenPriv->pdd2,
+ &ddsdCurrent);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not get current "
+ "refresh rate: %08x. Continuing.\n",
+ (unsigned int) ddrval);
+ dwRefreshRateCurrent = 0;
+ }
+ else
+ {
+ /* Grab the current refresh rate */
+ dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate;
+ }
+ }
+
+ /* Clean up the refresh rate */
+ if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate)
+ {
+ /*
+ * Refresh rate is non-specified or equal to current.
+ */
+ pScreenInfo->dwRefreshRate = 0;
+ }
+
+ /* Grab a device context for the screen */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDD - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Only change the video mode when different than current mode */
+ if (!pScreenInfo->fMultipleMonitors
+ && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN)
+ || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN)
+ || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL)
+ || pScreenInfo->dwRefreshRate != 0))
+ {
+ ErrorF ("winAllocateFBShadowDD - Changing video mode\n");
+
+ /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
+ ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ pScreenInfo->dwRefreshRate,
+ 0);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not set "\
+ "full screen display mode: %08x\n",
+ (unsigned int) ddrval);
+ ErrorF ("winAllocateFBShadowDD - Using default driver refresh rate\n");
+ ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ 0,
+ 0);
+ if (FAILED(ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not set default refresh rate "
+ "full screen display mode: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ ErrorF ("winAllocateFBShadowDD - Not changing video mode\n");
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+ hdc = NULL;
+ }
+ else
+ {
+ /* Set the cooperative level for windowed mode */
+ ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
+ pScreenPriv->hwndScreen,
+ DDSCL_NORMAL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not set "\
+ "cooperative level: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+ }
+
+ /* Create the primary surface */
+ if (!winCreatePrimarySurfaceShadowDD (pScreen))
+ {
+ ErrorF ("winAllocateFBShadowDD - winCreatePrimarySurfaceShadowDD "
+ "failed\n");
+ return FALSE;
+ }
+
+ /* Describe the shadow surface to be created */
+ /* NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
+ * as drawing, locking, and unlocking take forever
+ * with video memory surfaces. In addition,
+ * video memory is a somewhat scarce resource,
+ * so you shouldn't be allocating video memory when
+ * you have the option of using system memory instead.
+ */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ ddsd.dwHeight = pScreenInfo->dwHeight;
+ ddsd.dwWidth = pScreenInfo->dwWidth;
+
+ /* Create the shadow surface */
+ ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
+ &ddsd,
+ &pScreenPriv->pddsShadow,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not create shadow "\
+ "surface: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDD - Created shadow\n");
+#endif
+
+ /* Allocate a DD surface description for our screen privates */
+ pddsdShadow = pScreenPriv->pddsdShadow = malloc (sizeof (DDSURFACEDESC));
+ if (pddsdShadow == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not allocate surface "\
+ "description memory\n");
+ return FALSE;
+ }
+ ZeroMemory (pddsdShadow, sizeof (*pddsdShadow));
+ pddsdShadow->dwSize = sizeof (*pddsdShadow);
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDD - Locking shadow\n");
+#endif
+
+ /* Lock the shadow surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
+ NULL,
+ pddsdShadow,
+ DDLOCK_WAIT,
+ NULL);
+ if (FAILED (ddrval) || pddsdShadow->lpSurface == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDD - Could not lock shadow "\
+ "surface: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDD - Locked shadow\n");
+#endif
+
+ /* We don't know how to deal with anything other than RGB */
+ if (!(pddsdShadow->ddpfPixelFormat.dwFlags & DDPF_RGB))
+ {
+ ErrorF ("winAllocateFBShadowDD - Color format other than RGB\n");
+ return FALSE;
+ }
+
+ /* Grab the pitch from the surface desc */
+ pScreenInfo->dwStride = (pddsdShadow->u1.lPitch * 8)
+ / pScreenInfo->dwBPP;
+
+ /* Save the pointer to our surface memory */
+ pScreenInfo->pfb = pddsdShadow->lpSurface;
+
+ /* Grab the color depth and masks from the surface description */
+ pScreenPriv->dwRedMask = pddsdShadow->ddpfPixelFormat.u2.dwRBitMask;
+ pScreenPriv->dwGreenMask = pddsdShadow->ddpfPixelFormat.u3.dwGBitMask;
+ pScreenPriv->dwBlueMask = pddsdShadow->ddpfPixelFormat.u4.dwBBitMask;
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDD - Returning\n");
+#endif
+
+ return TRUE;
+}
+
+static void
+winFreeFBShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Free the shadow surface, if there is one */
+ if (pScreenPriv->pddsShadow)
+ {
+ IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
+ IDirectDrawSurface2_Release (pScreenPriv->pddsShadow);
+ pScreenPriv->pddsShadow = NULL;
+ }
+
+ /* Detach the clipper from the primary surface and release the primary surface, if there is one */
+ winReleasePrimarySurfaceShadowDD(pScreen);
+
+ /* Release the clipper object */
+ if (pScreenPriv->pddcPrimary)
+ {
+ IDirectDrawClipper_Release (pScreenPriv->pddcPrimary);
+ pScreenPriv->pddcPrimary = NULL;
+ }
+
+ /* Free the DirectDraw2 object, if there is one */
+ if (pScreenPriv->pdd2)
+ {
+ IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd2);
+ IDirectDraw2_Release (pScreenPriv->pdd2);
+ pScreenPriv->pdd2 = NULL;
+ }
+
+ /* Free the DirectDraw object, if there is one */
+ if (pScreenPriv->pdd)
+ {
+ IDirectDraw_Release (pScreenPriv->pdd);
+ pScreenPriv->pdd = NULL;
+ }
+
+ /* Invalidate the ScreenInfo's fb pointer */
+ pScreenInfo->pfb = NULL;
+}
+
+/*
+ * Transfer the damaged regions of the shadow framebuffer to the display.
+ */
+
+static void
+winShadowUpdateDD (ScreenPtr pScreen,
+ shadowBufPtr pBuf)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RegionPtr damage = shadowDamage(pBuf);
+ HRESULT ddrval = DD_OK;
+ RECT rcDest, rcSrc;
+ POINT ptOrigin;
+ DWORD dwBox = RegionNumRects (damage);
+ BoxPtr pBox = RegionRects (damage);
+ HRGN hrgnTemp = NULL, hrgnCombined = NULL;
+
+ /*
+ * Return immediately if the app is not active
+ * and we are fullscreen, or if we have a bad display depth
+ */
+ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
+ || pScreenPriv->fBadDepth) return;
+
+ /* Return immediately if we didn't get needed surfaces */
+ if (!pScreenPriv->pddsPrimary || !pScreenPriv->pddsShadow)
+ return;
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+
+ /* Unlock the shadow surface, so we can blit */
+ ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winShadowUpdateDD - Unlock failed\n");
+ return;
+ }
+
+ /*
+ * Handle small regions with multiple blits,
+ * handle large regions by creating a clipping region and
+ * doing a single blit constrained to that clipping region.
+ */
+ if (pScreenInfo->dwClipUpdatesNBoxes == 0
+ || dwBox < pScreenInfo->dwClipUpdatesNBoxes)
+ {
+ /* Loop through all boxes in the damaged region */
+ while (dwBox--)
+ {
+ /* Assign damage box to source rectangle */
+ rcSrc.left = pBox->x1;
+ rcSrc.top = pBox->y1;
+ rcSrc.right = pBox->x2;
+ rcSrc.bottom = pBox->y2;
+
+ /* Calculate destination rectange */
+ rcDest.left = ptOrigin.x + rcSrc.left;
+ rcDest.top = ptOrigin.y + rcSrc.top;
+ rcDest.right = ptOrigin.x + rcSrc.right;
+ rcDest.bottom = ptOrigin.y + rcSrc.bottom;
+
+ /* Blit the damaged areas */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcDest,
+ pScreenPriv->pddsShadow,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+
+ /* Get a pointer to the next box */
+ ++pBox;
+ }
+ }
+ else
+ {
+ BoxPtr pBoxExtents = RegionExtents(damage);
+
+ /* Compute a GDI region from the damaged region */
+ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ dwBox--;
+ pBox++;
+ while (dwBox--)
+ {
+ hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
+ DeleteObject (hrgnTemp);
+ pBox++;
+ }
+
+ /* Install the GDI region as a clipping region */
+ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
+ DeleteObject (hrgnCombined);
+ hrgnCombined = NULL;
+
+ /* Calculating a bounding box for the source is easy */
+ rcSrc.left = pBoxExtents->x1;
+ rcSrc.top = pBoxExtents->y1;
+ rcSrc.right = pBoxExtents->x2;
+ rcSrc.bottom = pBoxExtents->y2;
+
+ /* Calculating a bounding box for the destination is trickier */
+ rcDest.left = ptOrigin.x + rcSrc.left;
+ rcDest.top = ptOrigin.y + rcSrc.top;
+ rcDest.right = ptOrigin.x + rcSrc.right;
+ rcDest.bottom = ptOrigin.y + rcSrc.bottom;
+
+ /* Our Blt should be clipped to the invalidated region */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcDest,
+ pScreenPriv->pddsShadow,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+
+ /* Reset the clip region */
+ SelectClipRgn (pScreenPriv->hdcScreen, NULL);
+ }
+
+ /* Relock the shadow surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
+ NULL,
+ pScreenPriv->pddsdShadow,
+ DDLOCK_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winShadowUpdateDD - Lock failed\n");
+ return;
+ }
+
+ /* Has our memory pointer changed? */
+ if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
+ {
+ ErrorF ("winShadowUpdateDD - Memory location of the shadow "
+ "surface has changed, trying to update the root window "
+ "pixmap header to point to the new address. If you get "
+ "this message and "PROJECT_NAME" freezes or crashes "
+ "after this message then send a problem report and your "
+ "%s file to " BUILDERADDR "\n", g_pszLogFile);
+
+ /* Location of shadow framebuffer has changed */
+ winUpdateFBPointer(pScreen, pScreenPriv->pddsdShadow->lpSurface);
+ }
+}
+
+static Bool
+winInitScreenShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /* Get a device context for the screen */
+ pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
+
+ return winAllocateFBShadowDD(pScreen);
+}
+
+/*
+ * Call the wrapped CloseScreen function.
+ *
+ * Free our resources and private structures.
+ */
+
+static Bool
+winCloseScreenShadowDD (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ Bool fReturn;
+
+#if CYGDEBUG
+ winDebug ("winCloseScreenShadowDD - Freeing screen resources\n");
+#endif
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /* Call the wrapped CloseScreen procedure */
+ WIN_UNWRAP(CloseScreen);
+ fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
+
+ winFreeFBShadowDD(pScreen);
+
+ /* Free the screen DC */
+ ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Destroy the thread startup mutex */
+ pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
+#endif
+
+ /* Kill our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free ((pointer) pScreenPriv);
+
+ return fReturn;
+}
+
+
+/*
+ * Tell mi what sort of visuals we need.
+ *
+ * Generally we only need one visual, as our screen can only
+ * handle one format at a time, I believe. You may want
+ * to verify that last sentence.
+ */
+
+static Bool
+winInitVisualsShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ DWORD dwRedBits, dwGreenBits, dwBlueBits;
+
+ /* Count the number of ones in each color mask */
+ dwRedBits = winCountBits (pScreenPriv->dwRedMask);
+ dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
+ dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
+
+ /* Store the maximum number of ones in a color mask as the bitsPerRGB */
+ if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0)
+ pScreenPriv->dwBitsPerRGB = 8;
+ else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwRedBits;
+ else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwGreenBits;
+ else
+ pScreenPriv->dwBitsPerRGB = dwBlueBits;
+
+ ErrorF ("winInitVisualsShadowDD - Masks %08x %08x %08x BPRGB %d d %d "
+ "bpp %d\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask,
+ (int) pScreenPriv->dwBitsPerRGB,
+ (int) pScreenInfo->dwDepth,
+ (int) pScreenInfo->dwBPP);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ /* Create the real visual */
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ TrueColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
+ "failed for TrueColor\n");
+ return FALSE;
+ }
+
+#ifdef XWIN_EMULATEPSEUDO
+ if (!pScreenInfo->fEmulatePseudo)
+ break;
+
+ /* Setup a pseudocolor visual */
+ if (!miSetVisualTypesAndMasks (8,
+ PseudoColorMask,
+ 8,
+ -1,
+ 0,
+ 0,
+ 0))
+ {
+ ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
+ "failed for PseudoColor\n");
+ return FALSE;
+ }
+#endif
+ break;
+
+ case 8:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ pScreenInfo->fFullScreen
+ ? PseudoColorMask : StaticColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ pScreenInfo->fFullScreen
+ ? PseudoColor : StaticColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowDD - miSetVisualTypesAndMasks "
+ "failed\n");
+ return FALSE;
+ }
+ break;
+
+ default:
+ ErrorF ("winInitVisualsShadowDD - Unknown screen depth\n");
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winInitVisualsShadowDD - Returning\n");
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Adjust the user proposed video mode
+ */
+
+static Bool
+winAdjustVideoModeShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc = NULL;
+ DWORD dwBPP;
+
+ /* We're in serious trouble if we can't get a DC */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModeShadowDD - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+
+ /* DirectDraw can only change the depth in fullscreen mode */
+ if (!(pScreenInfo->fFullScreen &&
+ (pScreenInfo->dwBPP != WIN_DEFAULT_BPP)))
+ {
+ /* Otherwise, We'll use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+ return TRUE;
+}
+
+
+/*
+ * Blt exposed regions to the screen
+ */
+
+static Bool
+winBltExposedRegionsShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcSrc, rcDest;
+ POINT ptOrigin;
+ HDC hdcUpdate = NULL;
+ PAINTSTRUCT ps;
+ HRESULT ddrval = DD_OK;
+ Bool fReturn = TRUE;
+ Bool fLocked = TRUE;
+ int i;
+
+ /* BeginPaint gives us an hdc that clips to the invalidated region */
+ hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
+ if (hdcUpdate == NULL)
+ {
+ ErrorF ("winBltExposedRegionsShadowDD - BeginPaint () returned "
+ "a NULL device context handle. Aborting blit attempt.\n");
+ return FALSE;
+ }
+
+ /* Unlock the shadow surface, so we can blit */
+ ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
+ if (FAILED (ddrval))
+ {
+ fReturn = FALSE;
+ goto winBltExposedRegionsShadowDD_Exit;
+ }
+ else
+ {
+ /* Flag that we have unlocked the shadow surface */
+ fLocked = FALSE;
+ }
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+ rcDest.left = ptOrigin.x;
+ rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
+ rcDest.top = ptOrigin.y;
+ rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
+
+ /* Source can be enter shadow surface, as Blt should clip */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Try to regain the primary surface and blit again if we've lost it */
+ for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i)
+ {
+ /* Our Blt should be clipped to the invalidated region */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcDest,
+ pScreenPriv->pddsShadow,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (ddrval == DDERR_SURFACELOST)
+ {
+ /* Surface was lost */
+ ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
+ "reported that the primary surface was lost, "
+ "trying to restore, retry: %d\n", i + 1);
+
+ /* Try to restore the surface, once */
+ ddrval = IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
+ ErrorF ("winBltExposedRegionsShadowDD - "
+ "IDirectDrawSurface2_Restore returned: ");
+ if (ddrval == DD_OK)
+ ErrorF ("DD_OK\n");
+ else if (ddrval == DDERR_WRONGMODE)
+ ErrorF ("DDERR_WRONGMODE\n");
+ else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
+ ErrorF ("DDERR_INCOMPATIBLEPRIMARY\n");
+ else if (ddrval == DDERR_UNSUPPORTED)
+ ErrorF ("DDERR_UNSUPPORTED\n");
+ else if (ddrval == DDERR_INVALIDPARAMS)
+ ErrorF ("DDERR_INVALIDPARAMS\n");
+ else if (ddrval == DDERR_INVALIDOBJECT)
+ ErrorF ("DDERR_INVALIDOBJECT\n");
+ else
+ ErrorF ("unknown error: %08x\n", (unsigned int) ddrval);
+
+ /* Loop around to try the blit one more time */
+ continue;
+ }
+ else if (FAILED (ddrval))
+ {
+ fReturn = FALSE;
+ ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Blt "
+ "failed, but surface not lost: %08x %d\n",
+ (unsigned int) ddrval, (int) ddrval);
+ goto winBltExposedRegionsShadowDD_Exit;
+ }
+ else
+ {
+ /* Success, stop looping */
+ break;
+ }
+ }
+
+ /* Relock the shadow surface */
+ ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
+ NULL,
+ pScreenPriv->pddsdShadow,
+ DDLOCK_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ fReturn = FALSE;
+ ErrorF ("winBltExposedRegionsShadowDD - IDirectDrawSurface2_Lock "
+ "failed\n");
+ goto winBltExposedRegionsShadowDD_Exit;
+ }
+ else
+ {
+ /* Indicate that we have relocked the shadow surface */
+ fLocked = TRUE;
+ }
+
+ /* Has our memory pointer changed? */
+ if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
+ winUpdateFBPointer (pScreen,
+ pScreenPriv->pddsdShadow->lpSurface);
+
+ winBltExposedRegionsShadowDD_Exit:
+ /* EndPaint frees the DC */
+ if (hdcUpdate != NULL)
+ EndPaint (pScreenPriv->hwndScreen, &ps);
+
+ /*
+ * Relock the surface if it is not locked. We don't care if locking fails,
+ * as it will cause the server to shutdown within a few more operations.
+ */
+ if (!fLocked)
+ {
+ IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
+ NULL,
+ pScreenPriv->pddsdShadow,
+ DDLOCK_WAIT,
+ NULL);
+
+ /* Has our memory pointer changed? */
+ if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
+ winUpdateFBPointer (pScreen,
+ pScreenPriv->pddsdShadow->lpSurface);
+
+ fLocked = TRUE;
+ }
+ return fReturn;
+}
+
+
+/*
+ * Do any engine-specific appliation-activation processing
+ */
+
+static Bool
+winActivateAppShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /*
+ * Do we have a surface?
+ * Are we active?
+ * Are we fullscreen?
+ */
+ if (pScreenPriv != NULL
+ && pScreenPriv->pddsPrimary != NULL
+ && pScreenPriv->fActive)
+ {
+ /* Primary surface was lost, restore it */
+ IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Reblit the shadow framebuffer to the screen.
+ */
+
+static Bool
+winRedrawScreenShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ RECT rcSrc, rcDest;
+ POINT ptOrigin;
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+ rcDest.left = ptOrigin.x;
+ rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
+ rcDest.top = ptOrigin.y;
+ rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
+
+ /* Source can be entire shadow surface, as Blt should clip for us */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Redraw the whole window, to take account for the new colors */
+ ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
+ &rcDest,
+ pScreenPriv->pddsShadow,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winRedrawScreenShadowDD - IDirectDrawSurface_Blt () "
+ "failed: %08x\n",
+ (unsigned int) ddrval);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Realize the currently installed colormap
+ */
+
+static Bool
+winRealizeInstalledPaletteShadowDD (ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+
+/*
+ * Install the specified colormap
+ */
+
+static Bool
+winInstallColormapShadowDD (ColormapPtr pColormap)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ HRESULT ddrval = DD_OK;
+
+ /* Install the DirectDraw palette on the primary surface */
+ ddrval = IDirectDrawSurface2_SetPalette (pScreenPriv->pddsPrimary,
+ pCmapPriv->lpDDPalette);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winInstallColormapShadowDD - Failed installing the "
+ "DirectDraw palette.\n");
+ return FALSE;
+ }
+
+ /* Save a pointer to the newly installed colormap */
+ pScreenPriv->pcmapInstalled = pColormap;
+
+ return TRUE;
+}
+
+
+/*
+ * Store the specified colors in the specified colormap
+ */
+
+static Bool
+winStoreColorsShadowDD (ColormapPtr pColormap,
+ int ndef,
+ xColorItem *pdefs)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
+ HRESULT ddrval = DD_OK;
+
+ /* Put the X colormap entries into the Windows logical palette */
+ ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette,
+ 0,
+ pdefs[0].pixel,
+ ndef,
+ pCmapPriv->peColors
+ + pdefs[0].pixel);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winStoreColorsShadowDD - SetEntries () failed\n");
+ return FALSE;
+ }
+
+ /* Don't install the DirectDraw palette if the colormap is not installed */
+ if (pColormap != curpmap)
+ {
+ return TRUE;
+ }
+
+ if (!winInstallColormapShadowDD (pColormap))
+ {
+ ErrorF ("winStoreColorsShadowDD - Failed installing colormap\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap initialization procedure
+ */
+
+static Bool
+winCreateColormapShadowDD (ColormapPtr pColormap)
+{
+ HRESULT ddrval = DD_OK;
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+
+ /* Create a DirectDraw palette */
+ ddrval = IDirectDraw2_CreatePalette (pScreenPriv->pdd,
+ DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+ pCmapPriv->peColors,
+ &pCmapPriv->lpDDPalette,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreateColormapShadowDD - CreatePalette failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap destruction procedure
+ */
+
+static Bool
+winDestroyColormapShadowDD (ColormapPtr pColormap)
+{
+ winScreenPriv(pColormap->pScreen);
+ winCmapPriv(pColormap);
+ HRESULT ddrval = DD_OK;
+
+ /*
+ * Is colormap to be destroyed the default?
+ *
+ * Non-default colormaps should have had winUninstallColormap
+ * called on them before we get here. The default colormap
+ * will not have had winUninstallColormap called on it. Thus,
+ * we need to handle the default colormap in a special way.
+ */
+ if (pColormap->flags & IsDefault)
+ {
+#if CYGDEBUG
+ winDebug ("winDestroyColormapShadowDD - Destroying default "
+ "colormap\n");
+#endif
+
+ /*
+ * FIXME: Walk the list of all screens, popping the default
+ * palette out of each screen device context.
+ */
+
+ /* Pop the palette out of the primary surface */
+ ddrval = IDirectDrawSurface2_SetPalette (pScreenPriv->pddsPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winDestroyColormapShadowDD - Failed freeing the "
+ "default colormap DirectDraw palette.\n");
+ return FALSE;
+ }
+
+ /* Clear our private installed colormap pointer */
+ pScreenPriv->pcmapInstalled = NULL;
+ }
+
+ /* Release the palette */
+ IDirectDrawPalette_Release (pCmapPriv->lpDDPalette);
+
+ /* Invalidate the colormap privates */
+ pCmapPriv->lpDDPalette = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * Set engine specific functions
+ */
+
+Bool
+winSetEngineFunctionsShadowDD (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBShadowDD;
+ pScreenPriv->pwinFreeFB = winFreeFBShadowDD;
+ pScreenPriv->pwinShadowUpdate = winShadowUpdateDD;
+ pScreenPriv->pwinInitScreen = winInitScreenShadowDD;
+ pScreenPriv->pwinCloseScreen = winCloseScreenShadowDD;
+ pScreenPriv->pwinInitVisuals = winInitVisualsShadowDD;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDD;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
+ pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDD;
+ pScreenPriv->pwinActivateApp = winActivateAppShadowDD;
+ pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDD;
+ pScreenPriv->pwinRealizeInstalledPalette
+ = winRealizeInstalledPaletteShadowDD;
+ pScreenPriv->pwinInstallColormap = winInstallColormapShadowDD;
+ pScreenPriv->pwinStoreColors = winStoreColorsShadowDD;
+ pScreenPriv->pwinCreateColormap = winCreateColormapShadowDD;
+ pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDD;
+ pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDD;
+ pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDD;
+#ifdef XWIN_MULTIWINDOW
+ pScreenPriv->pwinFinishCreateWindowsWindow =
+ (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
+#endif
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winshadddnl.c b/xorg-server/hw/xwin/winshadddnl.c
index 0ce5d8d85..0a0b4ae13 100644
--- a/xorg-server/hw/xwin/winshadddnl.c
+++ b/xorg-server/hw/xwin/winshadddnl.c
@@ -1,1412 +1,1396 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Dakshinamurthy Karra
- * Suhaib M Siddiqi
- * Peter Busch
- * Harold L Hunt II
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-
-
-/*
- * FIXME: Headers are broken, DEFINE_GUID doesn't work correctly,
- * so we have to redefine it here.
- */
-#ifdef DEFINE_GUID
-#undef DEFINE_GUID
-#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-#endif /* DEFINE_GUID */
-
-/*
- * FIXME: Headers are broken, IID_IDirectDraw4 has to be defined
- * here manually. Should be handled by ddraw.h
- */
-#ifndef IID_IDirectDraw4
-DEFINE_GUID( IID_IDirectDraw4, 0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 );
-#endif /* IID_IDirectDraw4 */
-
-#define FAIL_MSG_MAX_BLT 10
-
-
-/*
- * Local prototypes
- */
-
-static Bool
-winAllocateFBShadowDDNL (ScreenPtr pScreen);
-
-static void
-winShadowUpdateDDNL (ScreenPtr pScreen,
- shadowBufPtr pBuf);
-
-static Bool
-winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen);
-
-static Bool
-winInitVisualsShadowDDNL (ScreenPtr pScreen);
-
-static Bool
-winAdjustVideoModeShadowDDNL (ScreenPtr pScreen);
-
-static Bool
-winBltExposedRegionsShadowDDNL (ScreenPtr pScreen);
-
-static Bool
-winActivateAppShadowDDNL (ScreenPtr pScreen);
-
-static Bool
-winRedrawScreenShadowDDNL (ScreenPtr pScreen);
-
-static Bool
-winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen);
-
-static Bool
-winInstallColormapShadowDDNL (ColormapPtr pColormap);
-
-static Bool
-winStoreColorsShadowDDNL (ColormapPtr pmap,
- int ndef,
- xColorItem *pdefs);
-
-static Bool
-winCreateColormapShadowDDNL (ColormapPtr pColormap);
-
-static Bool
-winDestroyColormapShadowDDNL (ColormapPtr pColormap);
-
-static Bool
-winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen);
-
-static Bool
-winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen);
-
-
-/*
- * Create the primary surface and attach the clipper.
- * Used for both the initial surface creation and during
- * WM_DISPLAYCHANGE messages.
- */
-
-static Bool
-winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- HRESULT ddrval = DD_OK;
- DDSURFACEDESC2 ddsd;
-
- winDebug ("winCreatePrimarySurfaceShadowDDNL - Creating primary surface\n");
-
- /* Describe the primary surface */
- ZeroMemory (&ddsd, sizeof (ddsd));
- ddsd.dwSize = sizeof (ddsd);
- ddsd.dwFlags = DDSD_CAPS;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
-
- /* Create the primary surface */
- ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
- &ddsd,
- &pScreenPriv->pddsPrimary4,
- NULL);
- pScreenPriv->fRetryCreateSurface = FALSE;
- if (FAILED (ddrval))
- {
- if (ddrval == DDERR_NOEXCLUSIVEMODE)
- {
- /* Recreating the surface failed. Mark screen to retry later */
- pScreenPriv->fRetryCreateSurface = TRUE;
- winDebug ("winCreatePrimarySurfaceShadowDDNL - Could not create "
- "primary surface: DDERR_NOEXCLUSIVEMODE\n");
- }
- else
- {
- ErrorF ("winCreatePrimarySurfaceShadowDDNL - Could not create "
- "primary surface: %08x\n", (unsigned int) ddrval);
- }
- return FALSE;
- }
-
-#if 1
- winDebug ("winCreatePrimarySurfaceShadowDDNL - Created primary surface\n");
-#endif
-
- /* Attach our clipper to our primary surface handle */
- ddrval = IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4,
- pScreenPriv->pddcPrimary);
- if (FAILED (ddrval))
- {
- ErrorF ("winCreatePrimarySurfaceShadowDDNL - Primary attach clipper "
- "failed: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if 1
- winDebug ("winCreatePrimarySurfaceShadowDDNL - Attached clipper to primary "
- "surface\n");
-#endif
-
- /* Everything was correct */
- return TRUE;
-}
-
-
-/*
- * Detach the clipper and release the primary surface.
- * Called from WM_DISPLAYCHANGE.
- */
-
-static Bool
-winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
-
- winDebug ("winReleasePrimarySurfaceShadowDDNL - Hello\n");
-
- /* Release the primary surface and clipper, if they exist */
- if (pScreenPriv->pddsPrimary4)
- {
- /*
- * Detach the clipper from the primary surface.
- * NOTE: We do this explicity for clarity. The Clipper is not released.
- */
- IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4,
- NULL);
-
- winDebug ("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n");
-
- /* Release the primary surface */
- IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4);
- pScreenPriv->pddsPrimary4 = NULL;
- }
-
- winDebug ("winReleasePrimarySurfaceShadowDDNL - Released primary surface\n");
-
- return TRUE;
-}
-
-
-/*
- * Create a DirectDraw surface for the shadow framebuffer; also create
- * a primary surface object so we can blit to the display.
- *
- * Install a DirectDraw clipper on our primary surface object
- * that clips our blits to the unobscured client area of our display window.
- */
-
-Bool
-winAllocateFBShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HRESULT ddrval = DD_OK;
- DDSURFACEDESC2 ddsdShadow;
- char *lpSurface = NULL;
- DDPIXELFORMAT ddpfPrimary;
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDDNL - w %d h %d d %d\n",
- pScreenInfo->dwWidth, pScreenInfo->dwHeight, pScreenInfo->dwDepth);
-#endif
-
- /* Allocate memory for our shadow surface */
- lpSurface = malloc (pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight);
- if (lpSurface == NULL)
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not allocate bits\n");
- return FALSE;
- }
-
- /*
- * Initialize the framebuffer memory so we don't get a
- * strange display at startup
- */
- ZeroMemory (lpSurface, pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight);
-
- /* Create a clipper */
- ddrval = (*g_fpDirectDrawCreateClipper) (0,
- &pScreenPriv->pddcPrimary,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not attach clipper: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDDNL - Created a clipper\n");
-#endif
-
- /* Get a device context for the screen */
- pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
-
- /* Attach the clipper to our display window */
- ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary,
- 0,
- pScreenPriv->hwndScreen);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Clipper not attached "
- "to window: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDDNL - Attached clipper to window\n");
-#endif
-
- /* Create a DirectDraw object, store the address at lpdd */
- ddrval = (*g_fpDirectDrawCreate) (NULL,
- (LPDIRECTDRAW*) &pScreenPriv->pdd,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not start "
- "DirectDraw: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDDNL - Created and initialized DD\n");
-#endif
-
- /* Get a DirectDraw4 interface pointer */
- ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
- &IID_IDirectDraw4,
- (LPVOID*) &pScreenPriv->pdd4);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Failed DD4 query: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
- /* Are we full screen? */
- if (pScreenInfo->fFullScreen)
- {
- DDSURFACEDESC2 ddsdCurrent;
- DWORD dwRefreshRateCurrent = 0;
- HDC hdc = NULL;
-
- /* Set the cooperative level to full screen */
- ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4,
- pScreenPriv->hwndScreen,
- DDSCL_EXCLUSIVE
- | DDSCL_FULLSCREEN);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not set "
- "cooperative level: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
- /*
- * We only need to get the current refresh rate for comparison
- * if a refresh rate has been passed on the command line.
- */
- if (pScreenInfo->dwRefreshRate != 0)
- {
- ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent));
- ddsdCurrent.dwSize = sizeof (ddsdCurrent);
-
- /* Get information about current display settings */
- ddrval = IDirectDraw4_GetDisplayMode (pScreenPriv->pdd4,
- &ddsdCurrent);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not get current "
- "refresh rate: %08x. Continuing.\n",
- (unsigned int) ddrval);
- dwRefreshRateCurrent = 0;
- }
- else
- {
- /* Grab the current refresh rate */
- dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate;
- }
- }
-
- /* Clean up the refresh rate */
- if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate)
- {
- /*
- * Refresh rate is non-specified or equal to current.
- */
- pScreenInfo->dwRefreshRate = 0;
- }
-
- /* Grab a device context for the screen */
- hdc = GetDC (NULL);
- if (hdc == NULL)
- {
- ErrorF ("winAllocateFBShadowDDNL - GetDC () failed\n");
- return FALSE;
- }
-
- /* Only change the video mode when different than current mode */
- if (!pScreenInfo->fMultipleMonitors
- && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN)
- || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN)
- || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL)
- || pScreenInfo->dwRefreshRate != 0))
- {
- winDebug ("winAllocateFBShadowDDNL - Changing video mode\n");
-
- /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
- ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4,
- pScreenInfo->dwWidth,
- pScreenInfo->dwHeight,
- pScreenInfo->dwBPP,
- pScreenInfo->dwRefreshRate,
- 0);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not set "
- "full screen display mode: %08x\n",
- (unsigned int) ddrval);
- ErrorF ("winAllocateFBShadowDDNL - Using default driver refresh rate\n");
- ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4,
- pScreenInfo->dwWidth,
- pScreenInfo->dwHeight,
- pScreenInfo->dwBPP,
- 0,
- 0);
- if (FAILED(ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not set default refresh rate "
- "full screen display mode: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
- }
- }
- else
- {
- winDebug ("winAllocateFBShadowDDNL - Not changing video mode\n");
- }
-
- /* Release our DC */
- ReleaseDC (NULL, hdc);
- hdc = NULL;
- }
- else
- {
- /* Set the cooperative level for windowed mode */
- ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4,
- pScreenPriv->hwndScreen,
- DDSCL_NORMAL);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not set "
- "cooperative level: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
- }
-
- /* Create the primary surface */
- if (!winCreatePrimarySurfaceShadowDDNL (pScreen))
- {
- ErrorF ("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL "
- "failed\n");
- return FALSE;
- }
-
- /* Get primary surface's pixel format */
- ZeroMemory (&ddpfPrimary, sizeof (ddpfPrimary));
- ddpfPrimary.dwSize = sizeof (ddpfPrimary);
- ddrval = IDirectDrawSurface4_GetPixelFormat (pScreenPriv->pddsPrimary4,
- &ddpfPrimary);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not get primary "
- "pixformat: %08x\n",
- (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x "
- "dwRGBBitCount: %d\n",
- ddpfPrimary.u2.dwRBitMask,
- ddpfPrimary.u3.dwGBitMask,
- ddpfPrimary.u4.dwBBitMask,
- ddpfPrimary.u1.dwRGBBitCount);
-#endif
-
- /* Describe the shadow surface to be created */
- /*
- * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
- * as drawing, locking, and unlocking take forever
- * with video memory surfaces. In addition,
- * video memory is a somewhat scarce resource,
- * so you shouldn't be allocating video memory when
- * you have the option of using system memory instead.
- */
- ZeroMemory (&ddsdShadow, sizeof (ddsdShadow));
- ddsdShadow.dwSize = sizeof (ddsdShadow);
- ddsdShadow.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH
- | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT;
- ddsdShadow.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
- ddsdShadow.dwHeight = pScreenInfo->dwHeight;
- ddsdShadow.dwWidth = pScreenInfo->dwWidth;
- ddsdShadow.u1.lPitch = pScreenInfo->dwPaddedWidth;
- ddsdShadow.lpSurface = lpSurface;
- ddsdShadow.u4.ddpfPixelFormat = ddpfPrimary;
-
- winDebug ("winAllocateFBShadowDDNL - lPitch: %d\n",
- (int) pScreenInfo->dwPaddedWidth);
-
- /* Create the shadow surface */
- ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
- &ddsdShadow,
- &pScreenPriv->pddsShadow4,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winAllocateFBShadowDDNL - Could not create shadow "
- "surface: %08x\n", (unsigned int) ddrval);
- return FALSE;
- }
-
-#if CYGDEBUG || YES
- winDebug ("winAllocateFBShadowDDNL - Created shadow pitch: %d\n",
- (int) ddsdShadow.u1.lPitch);
-#endif
-
- /* Grab the pitch from the surface desc */
- pScreenInfo->dwStride = (ddsdShadow.u1.lPitch * 8)
- / pScreenInfo->dwBPP;
-
-#if CYGDEBUG || YES
- winDebug ("winAllocateFBShadowDDNL - Created shadow stride: %d\n",
- (int) pScreenInfo->dwStride);
-#endif
-
- /* Save the pointer to our surface memory */
- pScreenInfo->pfb = lpSurface;
-
- /* Grab the masks from the surface description */
- pScreenPriv->dwRedMask = ddsdShadow.u4.ddpfPixelFormat.u2.dwRBitMask;
- pScreenPriv->dwGreenMask = ddsdShadow.u4.ddpfPixelFormat.u3.dwGBitMask;
- pScreenPriv->dwBlueMask = ddsdShadow.u4.ddpfPixelFormat.u4.dwBBitMask;
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowDDNL - Returning\n");
-#endif
-
- return TRUE;
-}
-
-
-#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
-/*
- * Create a DirectDraw surface for the new multi-window window
- */
-
-static
-Bool
-winFinishCreateWindowsWindowDDNL (WindowPtr pWin)
-{
- winWindowPriv(pWin);
- winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv;
- HRESULT ddrval = DD_OK;
- DDSURFACEDESC2 ddsd;
- int iWidth, iHeight;
- int iX, iY;
-
- winDebug ("winFinishCreateWindowsWindowDDNL!\n\n");
-
- iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
- iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
-
- iWidth = pWin->drawable.width;
- iHeight = pWin->drawable.height;
-
- /* Describe the primary surface */
- ZeroMemory (&ddsd, sizeof (ddsd));
- ddsd.dwSize = sizeof (ddsd);
- ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
- ddsd.dwHeight = iHeight;
- ddsd.dwWidth = iWidth;
-
- /* Create the primary surface */
- ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
- &ddsd,
- &pWinPriv->pddsPrimary4,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winFinishCreateWindowsWindowDDNL - Could not create primary "
- "surface: %08x\n",
- (unsigned int)ddrval);
- return FALSE;
- }
- return TRUE;
-}
-#endif
-
-
-/*
- * Transfer the damaged regions of the shadow framebuffer to the display.
- */
-
-static void
-winShadowUpdateDDNL (ScreenPtr pScreen,
- shadowBufPtr pBuf)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- RegionPtr damage = shadowDamage(pBuf);
- HRESULT ddrval = DD_OK;
- RECT rcDest, rcSrc;
- POINT ptOrigin;
- DWORD dwBox = RegionNumRects (damage);
- BoxPtr pBox = RegionRects (damage);
- HRGN hrgnTemp = NULL, hrgnCombined = NULL;
-
- /*
- * Return immediately if the app is not active
- * and we are fullscreen, or if we have a bad display depth
- */
- if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
- || pScreenPriv->fBadDepth) return;
-
- /* Get the origin of the window in the screen coords */
- ptOrigin.x = pScreenInfo->dwXOffset;
- ptOrigin.y = pScreenInfo->dwYOffset;
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&ptOrigin, 1);
-
- /*
- * Handle small regions with multiple blits,
- * handle large regions by creating a clipping region and
- * doing a single blit constrained to that clipping region.
- */
- if (pScreenInfo->dwClipUpdatesNBoxes == 0
- || dwBox < pScreenInfo->dwClipUpdatesNBoxes)
- {
- /* Loop through all boxes in the damaged region */
- while (dwBox--)
- {
- /* Assign damage box to source rectangle */
- rcSrc.left = pBox->x1;
- rcSrc.top = pBox->y1;
- rcSrc.right = pBox->x2;
- rcSrc.bottom = pBox->y2;
-
- /* Calculate destination rectangle */
- rcDest.left = ptOrigin.x + rcSrc.left;
- rcDest.top = ptOrigin.y + rcSrc.top;
- rcDest.right = ptOrigin.x + rcSrc.right;
- rcDest.bottom = ptOrigin.y + rcSrc.bottom;
-
- /* Blit the damaged areas */
- ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
- &rcDest,
- pScreenPriv->pddsShadow4,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
- if (FAILED (ddrval))
- {
- static int s_iFailCount = 0;
-
- if (s_iFailCount < FAIL_MSG_MAX_BLT)
- {
- ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () "
- "failed: %08x\n",
- (unsigned int) ddrval);
-
- ++s_iFailCount;
-
- if (s_iFailCount == FAIL_MSG_MAX_BLT)
- {
- ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt "
- "failure message maximum (%d) reached. No "
- "more failure messages will be printed.\n",
- FAIL_MSG_MAX_BLT);
- }
- }
- }
-
- /* Get a pointer to the next box */
- ++pBox;
- }
- }
- else
- {
- BoxPtr pBoxExtents = RegionExtents(damage);
-
- /* Compute a GDI region from the damaged region */
- hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
- dwBox--;
- pBox++;
- while (dwBox--)
- {
- hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
- CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
- DeleteObject (hrgnTemp);
- pBox++;
- }
-
- /* Install the GDI region as a clipping region */
- SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
- DeleteObject (hrgnCombined);
- hrgnCombined = NULL;
-
-#if CYGDEBUG
- winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n",
- pBoxExtents->x1, pBoxExtents->y1,
- pBoxExtents->x2, pBoxExtents->y2);
-#endif
-
- /* Calculating a bounding box for the source is easy */
- rcSrc.left = pBoxExtents->x1;
- rcSrc.top = pBoxExtents->y1;
- rcSrc.right = pBoxExtents->x2;
- rcSrc.bottom = pBoxExtents->y2;
-
- /* Calculating a bounding box for the destination is trickier */
- rcDest.left = ptOrigin.x + rcSrc.left;
- rcDest.top = ptOrigin.y + rcSrc.top;
- rcDest.right = ptOrigin.x + rcSrc.right;
- rcDest.bottom = ptOrigin.y + rcSrc.bottom;
-
- /* Our Blt should be clipped to the invalidated region */
- ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
- &rcDest,
- pScreenPriv->pddsShadow4,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
-
- /* Reset the clip region */
- SelectClipRgn (pScreenPriv->hdcScreen, NULL);
- }
-}
-
-
-/*
- * Call the wrapped CloseScreen function.
- *
- * Free our resources and private structures.
- */
-
-static Bool
-winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- Bool fReturn;
-
-#if CYGDEBUG
- winDebug ("winCloseScreenShadowDDNL - Freeing screen resources\n");
-#endif
-
- /* Flag that the screen is closed */
- pScreenPriv->fClosed = TRUE;
- pScreenPriv->fActive = FALSE;
-
- /* Call the wrapped CloseScreen procedure */
- WIN_UNWRAP(CloseScreen);
- fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
-
- /* Free the screen DC */
- ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
-
- /* Delete the window property */
- RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
-
- /* Free the shadow surface, if there is one */
- if (pScreenPriv->pddsShadow4)
- {
- IDirectDrawSurface4_Release (pScreenPriv->pddsShadow4);
- free (pScreenInfo->pfb);
- pScreenInfo->pfb = NULL;
- pScreenPriv->pddsShadow4 = NULL;
- }
-
- /* Detach the clipper from the primary surface and release the clipper. */
- if (pScreenPriv->pddcPrimary)
- {
- /* Detach the clipper */
- IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4,
- NULL);
-
- /* Release the clipper object */
- IDirectDrawClipper_Release (pScreenPriv->pddcPrimary);
- pScreenPriv->pddcPrimary = NULL;
- }
-
- /* Release the primary surface, if there is one */
- if (pScreenPriv->pddsPrimary4)
- {
- IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4);
- pScreenPriv->pddsPrimary4 = NULL;
- }
-
- /* Free the DirectDraw4 object, if there is one */
- if (pScreenPriv->pdd4)
- {
- IDirectDraw4_RestoreDisplayMode (pScreenPriv->pdd4);
- IDirectDraw4_Release (pScreenPriv->pdd4);
- pScreenPriv->pdd4 = NULL;
- }
-
- /* Free the DirectDraw object, if there is one */
- if (pScreenPriv->pdd)
- {
- IDirectDraw_Release (pScreenPriv->pdd);
- pScreenPriv->pdd = NULL;
- }
-
- /* Delete tray icon, if we have one */
- if (!pScreenInfo->fNoTrayIcon)
- winDeleteNotifyIcon (pScreenPriv);
-
- /* Free the exit confirmation dialog box, if it exists */
- if (g_hDlgExit != NULL)
- {
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
- }
-
- /* Kill our window */
- if (pScreenPriv->hwndScreen)
- {
- DestroyWindow (pScreenPriv->hwndScreen);
- pScreenPriv->hwndScreen = NULL;
- }
-
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
- /* Destroy the thread startup mutex */
- pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
-#endif
-
- /* Kill our screeninfo's pointer to the screen */
- pScreenInfo->pScreen = NULL;
-
- /* Invalidate the ScreenInfo's fb pointer */
- pScreenInfo->pfb = NULL;
-
- /* Free the screen privates for this screen */
- free ((pointer) pScreenPriv);
-
- return fReturn;
-}
-
-
-/*
- * Tell mi what sort of visuals we need.
- *
- * Generally we only need one visual, as our screen can only
- * handle one format at a time, I believe. You may want
- * to verify that last sentence.
- */
-
-static Bool
-winInitVisualsShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- DWORD dwRedBits, dwGreenBits, dwBlueBits;
-
- /* Count the number of ones in each color mask */
- dwRedBits = winCountBits (pScreenPriv->dwRedMask);
- dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
- dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
-
- /* Store the maximum number of ones in a color mask as the bitsPerRGB */
- if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0)
- pScreenPriv->dwBitsPerRGB = 8;
- else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
- pScreenPriv->dwBitsPerRGB = dwRedBits;
- else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
- pScreenPriv->dwBitsPerRGB = dwGreenBits;
- else
- pScreenPriv->dwBitsPerRGB = dwBlueBits;
-
- winDebug ("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d "
- "bpp %d\n",
- (unsigned int) pScreenPriv->dwRedMask,
- (unsigned int) pScreenPriv->dwGreenMask,
- (unsigned int) pScreenPriv->dwBlueMask,
- (int) pScreenPriv->dwBitsPerRGB,
- (int) pScreenInfo->dwDepth,
- (int) pScreenInfo->dwBPP);
-
- /* Create a single visual according to the Windows screen depth */
- switch (pScreenInfo->dwDepth)
- {
- case 24:
- case 16:
- case 15:
- /* Setup the real visual */
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- TrueColorMask,
- pScreenPriv->dwBitsPerRGB,
- -1,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
- "failed for TrueColor\n");
- return FALSE;
- }
-
-#ifdef XWIN_EMULATEPSEUDO
- if (!pScreenInfo->fEmulatePseudo)
- break;
-
- /* Setup a pseudocolor visual */
- if (!miSetVisualTypesAndMasks (8,
- PseudoColorMask,
- 8,
- -1,
- 0,
- 0,
- 0))
- {
- ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
- "failed for PseudoColor\n");
- return FALSE;
- }
-#endif
- break;
-
- case 8:
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- pScreenInfo->fFullScreen
- ? PseudoColorMask : StaticColorMask,
- pScreenPriv->dwBitsPerRGB,
- pScreenInfo->fFullScreen
- ? PseudoColor : StaticColor,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
- "failed\n");
- return FALSE;
- }
- break;
-
- default:
- ErrorF ("winInitVisualsShadowDDNL - Unknown screen depth\n");
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winInitVisualsShadowDDNL - Returning\n");
-#endif
-
- return TRUE;
-}
-
-
-/*
- * Adjust the user proposed video mode
- */
-
-static Bool
-winAdjustVideoModeShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HDC hdc = NULL;
- DWORD dwBPP;
-
- /* We're in serious trouble if we can't get a DC */
- hdc = GetDC (NULL);
- if (hdc == NULL)
- {
- ErrorF ("winAdjustVideoModeShadowDDNL - GetDC () failed\n");
- return FALSE;
- }
-
- /* Query GDI for current display depth */
- dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
-
- /* DirectDraw can only change the depth in fullscreen mode */
- if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP)
- {
- /* No -depth parameter passed, let the user know the depth being used */
- winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - Using Windows display "
- "depth of %d bits per pixel\n", (int) dwBPP);
-
- /* Use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
- else if (pScreenInfo->fFullScreen
- && pScreenInfo->dwBPP != dwBPP)
- {
- /* FullScreen, and GDI depth differs from -depth parameter */
- winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - FullScreen, using command "
- "line bpp: %d\n", (int) pScreenInfo->dwBPP);
- }
- else if (dwBPP != pScreenInfo->dwBPP)
- {
- /* Windowed, and GDI depth differs from -depth parameter */
- winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - Windowed, command line "
- "bpp: %d, using bpp: %d\n",
- (int) pScreenInfo->dwBPP, (int) dwBPP);
-
- /* We'll use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
-
- /* See if the shadow bitmap will be larger than the DIB size limit */
- if (pScreenInfo->dwWidth * pScreenInfo->dwHeight * pScreenInfo->dwBPP
- >= WIN_DIB_MAXIMUM_SIZE)
- {
- winErrorFVerb (1, "winAdjustVideoModeShadowDDNL - Requested DirectDraw surface "
- "will be larger than %d MB. The surface may fail to be "
- "allocated on Windows 95, 98, or Me, due to a %d MB limit in "
- "DIB size. This limit does not apply to Windows NT/2000, and "
- "this message may be ignored on those platforms.\n",
- WIN_DIB_MAXIMUM_SIZE_MB, WIN_DIB_MAXIMUM_SIZE_MB);
- }
-
- /* Release our DC */
- ReleaseDC (NULL, hdc);
-
- return TRUE;
-}
-
-
-/*
- * Blt exposed regions to the screen
- */
-
-static Bool
-winBltExposedRegionsShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- RECT rcSrc, rcDest;
- POINT ptOrigin;
- HDC hdcUpdate;
- PAINTSTRUCT ps;
- HRESULT ddrval = DD_OK;
- Bool fReturn = TRUE;
- int i;
-
- /* Quite common case. The primary surface was lost (maybe because of depth
- * change). Try to create a new primary surface. Bail out if this fails */
- if (pScreenPriv->pddsPrimary4 == NULL && pScreenPriv->fRetryCreateSurface &&
- !winCreatePrimarySurfaceShadowDDNL(pScreen))
- {
- Sleep(100);
- return FALSE;
- }
- if (pScreenPriv->pddsPrimary4 == NULL)
- return FALSE;
-
- /* BeginPaint gives us an hdc that clips to the invalidated region */
- hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
- if (hdcUpdate == NULL)
- {
- fReturn = FALSE;
- ErrorF ("winBltExposedRegionsShadowDDNL - BeginPaint () returned "
- "a NULL device context handle. Aborting blit attempt.\n");
- goto winBltExposedRegionsShadowDDNL_Exit;
- }
-
- /* Get the origin of the window in the screen coords */
- ptOrigin.x = pScreenInfo->dwXOffset;
- ptOrigin.y = pScreenInfo->dwYOffset;
-
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&ptOrigin, 1);
- rcDest.left = ptOrigin.x;
- rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
- rcDest.top = ptOrigin.y;
- rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
-
- /* Source can be entire shadow surface, as Blt should clip for us */
- rcSrc.left = 0;
- rcSrc.top = 0;
- rcSrc.right = pScreenInfo->dwWidth;
- rcSrc.bottom = pScreenInfo->dwHeight;
-
- /* Try to regain the primary surface and blit again if we've lost it */
- for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i)
- {
- /* Our Blt should be clipped to the invalidated region */
- ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
- &rcDest,
- pScreenPriv->pddsShadow4,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
- if (ddrval == DDERR_SURFACELOST)
- {
- /* Surface was lost */
- winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
- "IDirectDrawSurface4_Blt reported that the primary "
- "surface was lost, trying to restore, retry: %d\n", i + 1);
-
- /* Try to restore the surface, once */
-
- ddrval = IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4);
- winDebug ("winBltExposedRegionsShadowDDNL - "
- "IDirectDrawSurface4_Restore returned: ");
- if (ddrval == DD_OK)
- winDebug ("DD_OK\n");
- else if (ddrval == DDERR_WRONGMODE)
- winDebug ("DDERR_WRONGMODE\n");
- else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
- winDebug ("DDERR_INCOMPATIBLEPRIMARY\n");
- else if (ddrval == DDERR_UNSUPPORTED)
- winDebug ("DDERR_UNSUPPORTED\n");
- else if (ddrval == DDERR_INVALIDPARAMS)
- winDebug ("DDERR_INVALIDPARAMS\n");
- else if (ddrval == DDERR_INVALIDOBJECT)
- winDebug ("DDERR_INVALIDOBJECT\n");
- else
- winDebug ("unknown error: %08x\n", (unsigned int) ddrval);
-
- /* Loop around to try the blit one more time */
- continue;
- }
- else if (FAILED (ddrval))
- {
- fReturn = FALSE;
- winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
- "IDirectDrawSurface4_Blt failed, but surface not "
- "lost: %08x %d\n",
- (unsigned int) ddrval, (int) ddrval);
- goto winBltExposedRegionsShadowDDNL_Exit;
- }
- else
- {
- /* Success, stop looping */
- break;
- }
- }
-
- winBltExposedRegionsShadowDDNL_Exit:
- /* EndPaint frees the DC */
- if (hdcUpdate != NULL)
- EndPaint (pScreenPriv->hwndScreen, &ps);
- return fReturn;
-}
-
-
-/*
- * Do any engine-specific application-activation processing
- */
-
-static Bool
-winActivateAppShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
-
- /*
- * Do we have a surface?
- * Are we active?
- * Are we full screen?
- */
- if (pScreenPriv != NULL
- && pScreenPriv->pddsPrimary4 != NULL
- && pScreenPriv->fActive)
- {
- /* Primary surface was lost, restore it */
- IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4);
- }
-
- return TRUE;
-}
-
-
-/*
- * Reblit the shadow framebuffer to the screen.
- */
-
-static Bool
-winRedrawScreenShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HRESULT ddrval = DD_OK;
- RECT rcSrc, rcDest;
- POINT ptOrigin;
-
- /* Get the origin of the window in the screen coords */
- ptOrigin.x = pScreenInfo->dwXOffset;
- ptOrigin.y = pScreenInfo->dwYOffset;
- MapWindowPoints (pScreenPriv->hwndScreen,
- HWND_DESKTOP,
- (LPPOINT)&ptOrigin, 1);
- rcDest.left = ptOrigin.x;
- rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
- rcDest.top = ptOrigin.y;
- rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
-
- /* Source can be entire shadow surface, as Blt should clip for us */
- rcSrc.left = 0;
- rcSrc.top = 0;
- rcSrc.right = pScreenInfo->dwWidth;
- rcSrc.bottom = pScreenInfo->dwHeight;
-
- /* Redraw the whole window, to take account for the new colors */
- ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
- &rcDest,
- pScreenPriv->pddsShadow4,
- &rcSrc,
- DDBLT_WAIT,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winRedrawScreenShadowDDNL - IDirectDrawSurface4_Blt () "
- "failed: %08x\n",
- (unsigned int) ddrval);
- }
-
- return TRUE;
-}
-
-
-/*
- * Realize the currently installed colormap
- */
-
-static Bool
-winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen)
-{
- return TRUE;
-}
-
-
-/*
- * Install the specified colormap
- */
-
-static Bool
-winInstallColormapShadowDDNL (ColormapPtr pColormap)
-{
- ScreenPtr pScreen = pColormap->pScreen;
- winScreenPriv(pScreen);
- winCmapPriv(pColormap);
- HRESULT ddrval = DD_OK;
-
- /* Install the DirectDraw palette on the primary surface */
- ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4,
- pCmapPriv->lpDDPalette);
- if (FAILED (ddrval))
- {
- ErrorF ("winInstallColormapShadowDDNL - Failed installing the "
- "DirectDraw palette.\n");
- return FALSE;
- }
-
- /* Save a pointer to the newly installed colormap */
- pScreenPriv->pcmapInstalled = pColormap;
-
- return TRUE;
-}
-
-
-/*
- * Store the specified colors in the specified colormap
- */
-
-static Bool
-winStoreColorsShadowDDNL (ColormapPtr pColormap,
- int ndef,
- xColorItem *pdefs)
-{
- ScreenPtr pScreen = pColormap->pScreen;
- winScreenPriv(pScreen);
- winCmapPriv(pColormap);
- ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
- HRESULT ddrval = DD_OK;
-
- /* Put the X colormap entries into the Windows logical palette */
- ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette,
- 0,
- pdefs[0].pixel,
- ndef,
- pCmapPriv->peColors
- + pdefs[0].pixel);
- if (FAILED (ddrval))
- {
- ErrorF ("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n", (unsigned int) ddrval);
- return FALSE;
- }
-
- /* Don't install the DirectDraw palette if the colormap is not installed */
- if (pColormap != curpmap)
- {
- return TRUE;
- }
-
- if (!winInstallColormapShadowDDNL (pColormap))
- {
- ErrorF ("winStoreColorsShadowDDNL - Failed installing colormap\n");
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * Colormap initialization procedure
- */
-
-static Bool
-winCreateColormapShadowDDNL (ColormapPtr pColormap)
-{
- HRESULT ddrval = DD_OK;
- ScreenPtr pScreen = pColormap->pScreen;
- winScreenPriv(pScreen);
- winCmapPriv(pColormap);
-
- /* Create a DirectDraw palette */
- ddrval = IDirectDraw4_CreatePalette (pScreenPriv->pdd4,
- DDPCAPS_8BIT | DDPCAPS_ALLOW256,
- pCmapPriv->peColors,
- &pCmapPriv->lpDDPalette,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winCreateColormapShadowDDNL - CreatePalette failed\n");
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * Colormap destruction procedure
- */
-
-static Bool
-winDestroyColormapShadowDDNL (ColormapPtr pColormap)
-{
- winScreenPriv(pColormap->pScreen);
- winCmapPriv(pColormap);
- HRESULT ddrval = DD_OK;
-
- /*
- * Is colormap to be destroyed the default?
- *
- * Non-default colormaps should have had winUninstallColormap
- * called on them before we get here. The default colormap
- * will not have had winUninstallColormap called on it. Thus,
- * we need to handle the default colormap in a special way.
- */
- if (pColormap->flags & IsDefault)
- {
-#if CYGDEBUG
- winDebug ("winDestroyColormapShadowDDNL - Destroying default colormap\n");
-#endif
-
- /*
- * FIXME: Walk the list of all screens, popping the default
- * palette out of each screen device context.
- */
-
- /* Pop the palette out of the primary surface */
- ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4,
- NULL);
- if (FAILED (ddrval))
- {
- ErrorF ("winDestroyColormapShadowDDNL - Failed freeing the "
- "default colormap DirectDraw palette.\n");
- return FALSE;
- }
-
- /* Clear our private installed colormap pointer */
- pScreenPriv->pcmapInstalled = NULL;
- }
-
- /* Release the palette */
- IDirectDrawPalette_Release (pCmapPriv->lpDDPalette);
-
- /* Invalidate the colormap privates */
- pCmapPriv->lpDDPalette = NULL;
-
- return TRUE;
-}
-
-
-/*
- * Set pointers to our engine specific functions
- */
-
-Bool
-winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /* Set our pointers */
- pScreenPriv->pwinAllocateFB = winAllocateFBShadowDDNL;
- pScreenPriv->pwinShadowUpdate = winShadowUpdateDDNL;
- pScreenPriv->pwinCloseScreen = winCloseScreenShadowDDNL;
- pScreenPriv->pwinInitVisuals = winInitVisualsShadowDDNL;
- pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDDNL;
- if (pScreenInfo->fFullScreen)
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
- else
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
- pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
- pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL;
- pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL;
- pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL;
- pScreenPriv->pwinRealizeInstalledPalette
- = winRealizeInstalledPaletteShadowDDNL;
- pScreenPriv->pwinInstallColormap = winInstallColormapShadowDDNL;
- pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL;
- pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL;
- pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL;
- pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
- pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL;
- pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL;
-#ifdef XWIN_MULTIWINDOW
- pScreenPriv->pwinFinishCreateWindowsWindow
- = winFinishCreateWindowsWindowDDNL;
-#endif
-
- return TRUE;
-}
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+
+
+/*
+ * FIXME: Headers are broken, DEFINE_GUID doesn't work correctly,
+ * so we have to redefine it here.
+ */
+#ifdef DEFINE_GUID
+#undef DEFINE_GUID
+#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+#endif /* DEFINE_GUID */
+
+/*
+ * FIXME: Headers are broken, IID_IDirectDraw4 has to be defined
+ * here manually. Should be handled by ddraw.h
+ */
+#ifndef IID_IDirectDraw4
+DEFINE_GUID( IID_IDirectDraw4, 0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 );
+#endif /* IID_IDirectDraw4 */
+
+#define FAIL_MSG_MAX_BLT 10
+
+
+/*
+ * Local prototypes
+ */
+
+static Bool
+winAllocateFBShadowDDNL (ScreenPtr pScreen);
+
+static void
+winShadowUpdateDDNL (ScreenPtr pScreen,
+ shadowBufPtr pBuf);
+
+static Bool
+winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModeShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winBltExposedRegionsShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winActivateAppShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winRedrawScreenShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winInstallColormapShadowDDNL (ColormapPtr pColormap);
+
+static Bool
+winStoreColorsShadowDDNL (ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs);
+
+static Bool
+winCreateColormapShadowDDNL (ColormapPtr pColormap);
+
+static Bool
+winDestroyColormapShadowDDNL (ColormapPtr pColormap);
+
+static Bool
+winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen);
+
+static Bool
+winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen);
+
+
+/*
+ * Create the primary surface and attach the clipper.
+ * Used for both the initial surface creation and during
+ * WM_DISPLAYCHANGE messages.
+ */
+
+static Bool
+winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC2 ddsd;
+
+ winDebug ("winCreatePrimarySurfaceShadowDDNL - Creating primary surface\n");
+
+ /* Describe the primary surface */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ /* Create the primary surface */
+ ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
+ &ddsd,
+ &pScreenPriv->pddsPrimary4,
+ NULL);
+ pScreenPriv->fRetryCreateSurface = FALSE;
+ if (FAILED (ddrval))
+ {
+ if (ddrval == DDERR_NOEXCLUSIVEMODE)
+ {
+ /* Recreating the surface failed. Mark screen to retry later */
+ pScreenPriv->fRetryCreateSurface = TRUE;
+ winDebug ("winCreatePrimarySurfaceShadowDDNL - Could not create "
+ "primary surface: DDERR_NOEXCLUSIVEMODE\n");
+ }
+ else
+ {
+ ErrorF ("winCreatePrimarySurfaceShadowDDNL - Could not create "
+ "primary surface: %08x\n", (unsigned int) ddrval);
+ }
+ return FALSE;
+ }
+
+#if 1
+ winDebug ("winCreatePrimarySurfaceShadowDDNL - Created primary surface\n");
+#endif
+
+ /* Attach our clipper to our primary surface handle */
+ ddrval = IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4,
+ pScreenPriv->pddcPrimary);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreatePrimarySurfaceShadowDDNL - Primary attach clipper "
+ "failed: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if 1
+ winDebug ("winCreatePrimarySurfaceShadowDDNL - Attached clipper to primary "
+ "surface\n");
+#endif
+
+ /* Everything was correct */
+ return TRUE;
+}
+
+
+/*
+ * Detach the clipper and release the primary surface.
+ * Called from WM_DISPLAYCHANGE.
+ */
+
+static Bool
+winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ winDebug ("winReleasePrimarySurfaceShadowDDNL - Hello\n");
+
+ /* Release the primary surface and clipper, if they exist */
+ if (pScreenPriv->pddsPrimary4)
+ {
+ /*
+ * Detach the clipper from the primary surface.
+ * NOTE: We do this explicity for clarity. The Clipper is not released.
+ */
+ IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4,
+ NULL);
+
+ winDebug ("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n");
+
+ /* Release the primary surface */
+ IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4);
+ pScreenPriv->pddsPrimary4 = NULL;
+ }
+
+ winDebug ("winReleasePrimarySurfaceShadowDDNL - Released primary surface\n");
+
+ return TRUE;
+}
+
+
+/*
+ * Create a DirectDraw surface for the shadow framebuffer; also create
+ * a primary surface object so we can blit to the display.
+ *
+ * Install a DirectDraw clipper on our primary surface object
+ * that clips our blits to the unobscured client area of our display window.
+ */
+
+Bool
+winAllocateFBShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC2 ddsdShadow;
+ char *lpSurface = NULL;
+ DDPIXELFORMAT ddpfPrimary;
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDDNL - w %d h %d d %d\n",
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight, pScreenInfo->dwDepth);
+#endif
+
+ /* Set the padded screen width */
+ pScreenInfo->dwPaddedWidth = PixmapBytePad (pScreenInfo->dwWidth,
+ pScreenInfo->dwBPP);
+
+ /* Allocate memory for our shadow surface */
+ lpSurface = malloc (pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight);
+ if (lpSurface == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not allocate bits\n");
+ return FALSE;
+ }
+
+ /*
+ * Initialize the framebuffer memory so we don't get a
+ * strange display at startup
+ */
+ ZeroMemory (lpSurface, pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight);
+
+ /* Create a clipper */
+ ddrval = (*g_fpDirectDrawCreateClipper) (0,
+ &pScreenPriv->pddcPrimary,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not attach clipper: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDDNL - Created a clipper\n");
+#endif
+
+ /* Attach the clipper to our display window */
+ ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary,
+ 0,
+ pScreenPriv->hwndScreen);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Clipper not attached "
+ "to window: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDDNL - Attached clipper to window\n");
+#endif
+
+ /* Create a DirectDraw object, store the address at lpdd */
+ ddrval = (*g_fpDirectDrawCreate) (NULL,
+ (LPDIRECTDRAW*) &pScreenPriv->pdd,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not start "
+ "DirectDraw: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDDNL - Created and initialized DD\n");
+#endif
+
+ /* Get a DirectDraw4 interface pointer */
+ ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
+ &IID_IDirectDraw4,
+ (LPVOID*) &pScreenPriv->pdd4);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Failed DD4 query: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /* Are we full screen? */
+ if (pScreenInfo->fFullScreen)
+ {
+ DDSURFACEDESC2 ddsdCurrent;
+ DWORD dwRefreshRateCurrent = 0;
+ HDC hdc = NULL;
+
+ /* Set the cooperative level to full screen */
+ ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4,
+ pScreenPriv->hwndScreen,
+ DDSCL_EXCLUSIVE
+ | DDSCL_FULLSCREEN);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not set "
+ "cooperative level: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /*
+ * We only need to get the current refresh rate for comparison
+ * if a refresh rate has been passed on the command line.
+ */
+ if (pScreenInfo->dwRefreshRate != 0)
+ {
+ ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent));
+ ddsdCurrent.dwSize = sizeof (ddsdCurrent);
+
+ /* Get information about current display settings */
+ ddrval = IDirectDraw4_GetDisplayMode (pScreenPriv->pdd4,
+ &ddsdCurrent);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not get current "
+ "refresh rate: %08x. Continuing.\n",
+ (unsigned int) ddrval);
+ dwRefreshRateCurrent = 0;
+ }
+ else
+ {
+ /* Grab the current refresh rate */
+ dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate;
+ }
+ }
+
+ /* Clean up the refresh rate */
+ if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate)
+ {
+ /*
+ * Refresh rate is non-specified or equal to current.
+ */
+ pScreenInfo->dwRefreshRate = 0;
+ }
+
+ /* Grab a device context for the screen */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAllocateFBShadowDDNL - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Only change the video mode when different than current mode */
+ if (!pScreenInfo->fMultipleMonitors
+ && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN)
+ || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN)
+ || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL)
+ || pScreenInfo->dwRefreshRate != 0))
+ {
+ winDebug ("winAllocateFBShadowDDNL - Changing video mode\n");
+
+ /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
+ ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ pScreenInfo->dwRefreshRate,
+ 0);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not set "
+ "full screen display mode: %08x\n",
+ (unsigned int) ddrval);
+ ErrorF ("winAllocateFBShadowDDNL - Using default driver refresh rate\n");
+ ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4,
+ pScreenInfo->dwWidth,
+ pScreenInfo->dwHeight,
+ pScreenInfo->dwBPP,
+ 0,
+ 0);
+ if (FAILED(ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not set default refresh rate "
+ "full screen display mode: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ winDebug ("winAllocateFBShadowDDNL - Not changing video mode\n");
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+ hdc = NULL;
+ }
+ else
+ {
+ /* Set the cooperative level for windowed mode */
+ ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4,
+ pScreenPriv->hwndScreen,
+ DDSCL_NORMAL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not set "
+ "cooperative level: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+ }
+
+ /* Create the primary surface */
+ if (!winCreatePrimarySurfaceShadowDDNL (pScreen))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL "
+ "failed\n");
+ return FALSE;
+ }
+
+ /* Get primary surface's pixel format */
+ ZeroMemory (&ddpfPrimary, sizeof (ddpfPrimary));
+ ddpfPrimary.dwSize = sizeof (ddpfPrimary);
+ ddrval = IDirectDrawSurface4_GetPixelFormat (pScreenPriv->pddsPrimary4,
+ &ddpfPrimary);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not get primary "
+ "pixformat: %08x\n",
+ (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x "
+ "dwRGBBitCount: %d\n",
+ ddpfPrimary.u2.dwRBitMask,
+ ddpfPrimary.u3.dwGBitMask,
+ ddpfPrimary.u4.dwBBitMask,
+ ddpfPrimary.u1.dwRGBBitCount);
+#endif
+
+ /* Describe the shadow surface to be created */
+ /*
+ * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
+ * as drawing, locking, and unlocking take forever
+ * with video memory surfaces. In addition,
+ * video memory is a somewhat scarce resource,
+ * so you shouldn't be allocating video memory when
+ * you have the option of using system memory instead.
+ */
+ ZeroMemory (&ddsdShadow, sizeof (ddsdShadow));
+ ddsdShadow.dwSize = sizeof (ddsdShadow);
+ ddsdShadow.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH
+ | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT;
+ ddsdShadow.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
+ ddsdShadow.dwHeight = pScreenInfo->dwHeight;
+ ddsdShadow.dwWidth = pScreenInfo->dwWidth;
+ ddsdShadow.u1.lPitch = pScreenInfo->dwPaddedWidth;
+ ddsdShadow.lpSurface = lpSurface;
+ ddsdShadow.u4.ddpfPixelFormat = ddpfPrimary;
+
+ winDebug ("winAllocateFBShadowDDNL - lPitch: %d\n",
+ (int) pScreenInfo->dwPaddedWidth);
+
+ /* Create the shadow surface */
+ ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
+ &ddsdShadow,
+ &pScreenPriv->pddsShadow4,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winAllocateFBShadowDDNL - Could not create shadow "
+ "surface: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+#if CYGDEBUG || YES
+ winDebug ("winAllocateFBShadowDDNL - Created shadow pitch: %d\n",
+ (int) ddsdShadow.u1.lPitch);
+#endif
+
+ /* Grab the pitch from the surface desc */
+ pScreenInfo->dwStride = (ddsdShadow.u1.lPitch * 8)
+ / pScreenInfo->dwBPP;
+
+#if CYGDEBUG || YES
+ winDebug ("winAllocateFBShadowDDNL - Created shadow stride: %d\n",
+ (int) pScreenInfo->dwStride);
+#endif
+
+ /* Save the pointer to our surface memory */
+ pScreenInfo->pfb = lpSurface;
+
+ /* Grab the masks from the surface description */
+ pScreenPriv->dwRedMask = ddsdShadow.u4.ddpfPixelFormat.u2.dwRBitMask;
+ pScreenPriv->dwGreenMask = ddsdShadow.u4.ddpfPixelFormat.u3.dwGBitMask;
+ pScreenPriv->dwBlueMask = ddsdShadow.u4.ddpfPixelFormat.u4.dwBBitMask;
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowDDNL - Returning\n");
+#endif
+
+ return TRUE;
+}
+
+static void
+winFreeFBShadowDDNL(ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Free the shadow surface, if there is one */
+ if (pScreenPriv->pddsShadow4)
+ {
+ IDirectDrawSurface4_Release (pScreenPriv->pddsShadow4);
+ free (pScreenInfo->pfb);
+ pScreenInfo->pfb = NULL;
+ pScreenPriv->pddsShadow4 = NULL;
+ }
+
+ /* Detach the clipper from the primary surface and release the primary surface, if there is one */
+ winReleasePrimarySurfaceShadowDDNL(pScreen);
+
+ /* Release the clipper object */
+ if (pScreenPriv->pddcPrimary)
+ {
+ IDirectDrawClipper_Release (pScreenPriv->pddcPrimary);
+ pScreenPriv->pddcPrimary = NULL;
+ }
+
+ /* Free the DirectDraw4 object, if there is one */
+ if (pScreenPriv->pdd4)
+ {
+ IDirectDraw4_RestoreDisplayMode (pScreenPriv->pdd4);
+ IDirectDraw4_Release (pScreenPriv->pdd4);
+ pScreenPriv->pdd4 = NULL;
+ }
+
+ /* Free the DirectDraw object, if there is one */
+ if (pScreenPriv->pdd)
+ {
+ IDirectDraw_Release (pScreenPriv->pdd);
+ pScreenPriv->pdd = NULL;
+ }
+
+ /* Invalidate the ScreenInfo's fb pointer */
+ pScreenInfo->pfb = NULL;
+}
+
+#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
+/*
+ * Create a DirectDraw surface for the new multi-window window
+ */
+
+static
+Bool
+winFinishCreateWindowsWindowDDNL (WindowPtr pWin)
+{
+ winWindowPriv(pWin);
+ winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv;
+ HRESULT ddrval = DD_OK;
+ DDSURFACEDESC2 ddsd;
+ int iWidth, iHeight;
+ int iX, iY;
+
+ winDebug ("winFinishCreateWindowsWindowDDNL!\n\n");
+
+ iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
+ iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
+
+ iWidth = pWin->drawable.width;
+ iHeight = pWin->drawable.height;
+
+ /* Describe the primary surface */
+ ZeroMemory (&ddsd, sizeof (ddsd));
+ ddsd.dwSize = sizeof (ddsd);
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ ddsd.dwHeight = iHeight;
+ ddsd.dwWidth = iWidth;
+
+ /* Create the primary surface */
+ ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
+ &ddsd,
+ &pWinPriv->pddsPrimary4,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winFinishCreateWindowsWindowDDNL - Could not create primary "
+ "surface: %08x\n",
+ (unsigned int)ddrval);
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif
+
+
+/*
+ * Transfer the damaged regions of the shadow framebuffer to the display.
+ */
+
+static void
+winShadowUpdateDDNL (ScreenPtr pScreen,
+ shadowBufPtr pBuf)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RegionPtr damage = shadowDamage(pBuf);
+ HRESULT ddrval = DD_OK;
+ RECT rcDest, rcSrc;
+ POINT ptOrigin;
+ DWORD dwBox = RegionNumRects (damage);
+ BoxPtr pBox = RegionRects (damage);
+ HRGN hrgnTemp = NULL, hrgnCombined = NULL;
+
+ /*
+ * Return immediately if the app is not active
+ * and we are fullscreen, or if we have a bad display depth
+ */
+ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
+ || pScreenPriv->fBadDepth) return;
+
+ /* Return immediately if we didn't get needed surfaces */
+ if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4)
+ return;
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+
+ /*
+ * Handle small regions with multiple blits,
+ * handle large regions by creating a clipping region and
+ * doing a single blit constrained to that clipping region.
+ */
+ if (pScreenInfo->dwClipUpdatesNBoxes == 0
+ || dwBox < pScreenInfo->dwClipUpdatesNBoxes)
+ {
+ /* Loop through all boxes in the damaged region */
+ while (dwBox--)
+ {
+ /* Assign damage box to source rectangle */
+ rcSrc.left = pBox->x1;
+ rcSrc.top = pBox->y1;
+ rcSrc.right = pBox->x2;
+ rcSrc.bottom = pBox->y2;
+
+ /* Calculate destination rectangle */
+ rcDest.left = ptOrigin.x + rcSrc.left;
+ rcDest.top = ptOrigin.y + rcSrc.top;
+ rcDest.right = ptOrigin.x + rcSrc.right;
+ rcDest.bottom = ptOrigin.y + rcSrc.bottom;
+
+ /* Blit the damaged areas */
+ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
+ &rcDest,
+ pScreenPriv->pddsShadow4,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ static int s_iFailCount = 0;
+
+ if (s_iFailCount < FAIL_MSG_MAX_BLT)
+ {
+ ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () "
+ "failed: %08x\n",
+ (unsigned int) ddrval);
+
+ ++s_iFailCount;
+
+ if (s_iFailCount == FAIL_MSG_MAX_BLT)
+ {
+ ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt "
+ "failure message maximum (%d) reached. No "
+ "more failure messages will be printed.\n",
+ FAIL_MSG_MAX_BLT);
+ }
+ }
+ }
+
+ /* Get a pointer to the next box */
+ ++pBox;
+ }
+ }
+ else
+ {
+ BoxPtr pBoxExtents = RegionExtents(damage);
+
+ /* Compute a GDI region from the damaged region */
+ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ dwBox--;
+ pBox++;
+ while (dwBox--)
+ {
+ hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
+ DeleteObject (hrgnTemp);
+ pBox++;
+ }
+
+ /* Install the GDI region as a clipping region */
+ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
+ DeleteObject (hrgnCombined);
+ hrgnCombined = NULL;
+
+#if CYGDEBUG
+ winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n",
+ pBoxExtents->x1, pBoxExtents->y1,
+ pBoxExtents->x2, pBoxExtents->y2);
+#endif
+
+ /* Calculating a bounding box for the source is easy */
+ rcSrc.left = pBoxExtents->x1;
+ rcSrc.top = pBoxExtents->y1;
+ rcSrc.right = pBoxExtents->x2;
+ rcSrc.bottom = pBoxExtents->y2;
+
+ /* Calculating a bounding box for the destination is trickier */
+ rcDest.left = ptOrigin.x + rcSrc.left;
+ rcDest.top = ptOrigin.y + rcSrc.top;
+ rcDest.right = ptOrigin.x + rcSrc.right;
+ rcDest.bottom = ptOrigin.y + rcSrc.bottom;
+
+ /* Our Blt should be clipped to the invalidated region */
+ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
+ &rcDest,
+ pScreenPriv->pddsShadow4,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+
+ /* Reset the clip region */
+ SelectClipRgn (pScreenPriv->hdcScreen, NULL);
+ }
+}
+
+static Bool
+winInitScreenShadowDDNL(ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /* Get a device context for the screen */
+ pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
+
+ return winAllocateFBShadowDDNL(pScreen);
+}
+
+/*
+ * Call the wrapped CloseScreen function.
+ *
+ * Free our resources and private structures.
+ */
+
+static Bool
+winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ Bool fReturn;
+
+#if CYGDEBUG
+ winDebug ("winCloseScreenShadowDDNL - Freeing screen resources\n");
+#endif
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /* Call the wrapped CloseScreen procedure */
+ WIN_UNWRAP(CloseScreen);
+ fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
+
+ winFreeFBShadowDDNL(pScreen);
+
+ /* Free the screen DC */
+ ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Destroy the thread startup mutex */
+ pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
+#endif
+
+ /* Kill our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free ((pointer) pScreenPriv);
+
+ return fReturn;
+}
+
+
+/*
+ * Tell mi what sort of visuals we need.
+ *
+ * Generally we only need one visual, as our screen can only
+ * handle one format at a time, I believe. You may want
+ * to verify that last sentence.
+ */
+
+static Bool
+winInitVisualsShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ DWORD dwRedBits, dwGreenBits, dwBlueBits;
+
+ /* Count the number of ones in each color mask */
+ dwRedBits = winCountBits (pScreenPriv->dwRedMask);
+ dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
+ dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
+
+ /* Store the maximum number of ones in a color mask as the bitsPerRGB */
+ if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0)
+ pScreenPriv->dwBitsPerRGB = 8;
+ else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwRedBits;
+ else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwGreenBits;
+ else
+ pScreenPriv->dwBitsPerRGB = dwBlueBits;
+
+ winDebug ("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d "
+ "bpp %d\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask,
+ (int) pScreenPriv->dwBitsPerRGB,
+ (int) pScreenInfo->dwDepth,
+ (int) pScreenInfo->dwBPP);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ /* Setup the real visual */
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ -1,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
+ "failed for TrueColor\n");
+ return FALSE;
+ }
+
+#ifdef XWIN_EMULATEPSEUDO
+ if (!pScreenInfo->fEmulatePseudo)
+ break;
+
+ /* Setup a pseudocolor visual */
+ if (!miSetVisualTypesAndMasks (8,
+ PseudoColorMask,
+ 8,
+ -1,
+ 0,
+ 0,
+ 0))
+ {
+ ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
+ "failed for PseudoColor\n");
+ return FALSE;
+ }
+#endif
+ break;
+
+ case 8:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ pScreenInfo->fFullScreen
+ ? PseudoColorMask : StaticColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ pScreenInfo->fFullScreen
+ ? PseudoColor : StaticColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
+ "failed\n");
+ return FALSE;
+ }
+ break;
+
+ default:
+ ErrorF ("winInitVisualsShadowDDNL - Unknown screen depth\n");
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winInitVisualsShadowDDNL - Returning\n");
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Adjust the user proposed video mode
+ */
+
+static Bool
+winAdjustVideoModeShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc = NULL;
+ DWORD dwBPP;
+
+ /* We're in serious trouble if we can't get a DC */
+ hdc = GetDC (NULL);
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModeShadowDDNL - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+
+ /* DirectDraw can only change the depth in fullscreen mode */
+ if (!(pScreenInfo->fFullScreen &&
+ (pScreenInfo->dwBPP != WIN_DEFAULT_BPP)))
+ {
+ /* Otherwise, We'll use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+ }
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+
+ return TRUE;
+}
+
+
+/*
+ * Blt exposed regions to the screen
+ */
+
+static Bool
+winBltExposedRegionsShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RECT rcSrc, rcDest;
+ POINT ptOrigin;
+ HDC hdcUpdate;
+ PAINTSTRUCT ps;
+ HRESULT ddrval = DD_OK;
+ Bool fReturn = TRUE;
+ int i;
+
+ /* Quite common case. The primary surface was lost (maybe because of depth
+ * change). Try to create a new primary surface. Bail out if this fails */
+ if (pScreenPriv->pddsPrimary4 == NULL && pScreenPriv->fRetryCreateSurface &&
+ !winCreatePrimarySurfaceShadowDDNL(pScreen))
+ {
+ Sleep(100);
+ return FALSE;
+ }
+ if (pScreenPriv->pddsPrimary4 == NULL)
+ return FALSE;
+
+ /* BeginPaint gives us an hdc that clips to the invalidated region */
+ hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
+ if (hdcUpdate == NULL)
+ {
+ fReturn = FALSE;
+ ErrorF ("winBltExposedRegionsShadowDDNL - BeginPaint () returned "
+ "a NULL device context handle. Aborting blit attempt.\n");
+ goto winBltExposedRegionsShadowDDNL_Exit;
+ }
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+ rcDest.left = ptOrigin.x;
+ rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
+ rcDest.top = ptOrigin.y;
+ rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
+
+ /* Source can be entire shadow surface, as Blt should clip for us */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Try to regain the primary surface and blit again if we've lost it */
+ for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i)
+ {
+ /* Our Blt should be clipped to the invalidated region */
+ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
+ &rcDest,
+ pScreenPriv->pddsShadow4,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (ddrval == DDERR_SURFACELOST)
+ {
+ /* Surface was lost */
+ winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
+ "IDirectDrawSurface4_Blt reported that the primary "
+ "surface was lost, trying to restore, retry: %d\n", i + 1);
+
+ /* Try to restore the surface, once */
+
+ ddrval = IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4);
+ winDebug ("winBltExposedRegionsShadowDDNL - "
+ "IDirectDrawSurface4_Restore returned: ");
+ if (ddrval == DD_OK)
+ winDebug ("DD_OK\n");
+ else if (ddrval == DDERR_WRONGMODE)
+ winDebug ("DDERR_WRONGMODE\n");
+ else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
+ winDebug ("DDERR_INCOMPATIBLEPRIMARY\n");
+ else if (ddrval == DDERR_UNSUPPORTED)
+ winDebug ("DDERR_UNSUPPORTED\n");
+ else if (ddrval == DDERR_INVALIDPARAMS)
+ winDebug ("DDERR_INVALIDPARAMS\n");
+ else if (ddrval == DDERR_INVALIDOBJECT)
+ winDebug ("DDERR_INVALIDOBJECT\n");
+ else
+ winDebug ("unknown error: %08x\n", (unsigned int) ddrval);
+
+ /* Loop around to try the blit one more time */
+ continue;
+ }
+ else if (FAILED (ddrval))
+ {
+ fReturn = FALSE;
+ winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
+ "IDirectDrawSurface4_Blt failed, but surface not "
+ "lost: %08x %d\n",
+ (unsigned int) ddrval, (int) ddrval);
+ goto winBltExposedRegionsShadowDDNL_Exit;
+ }
+ else
+ {
+ /* Success, stop looping */
+ break;
+ }
+ }
+
+ winBltExposedRegionsShadowDDNL_Exit:
+ /* EndPaint frees the DC */
+ if (hdcUpdate != NULL)
+ EndPaint (pScreenPriv->hwndScreen, &ps);
+ return fReturn;
+}
+
+
+/*
+ * Do any engine-specific application-activation processing
+ */
+
+static Bool
+winActivateAppShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /*
+ * Do we have a surface?
+ * Are we active?
+ * Are we full screen?
+ */
+ if (pScreenPriv != NULL
+ && pScreenPriv->pddsPrimary4 != NULL
+ && pScreenPriv->fActive)
+ {
+ /* Primary surface was lost, restore it */
+ IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Reblit the shadow framebuffer to the screen.
+ */
+
+static Bool
+winRedrawScreenShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HRESULT ddrval = DD_OK;
+ RECT rcSrc, rcDest;
+ POINT ptOrigin;
+
+ /* Get the origin of the window in the screen coords */
+ ptOrigin.x = pScreenInfo->dwXOffset;
+ ptOrigin.y = pScreenInfo->dwYOffset;
+ MapWindowPoints (pScreenPriv->hwndScreen,
+ HWND_DESKTOP,
+ (LPPOINT)&ptOrigin, 1);
+ rcDest.left = ptOrigin.x;
+ rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
+ rcDest.top = ptOrigin.y;
+ rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
+
+ /* Source can be entire shadow surface, as Blt should clip for us */
+ rcSrc.left = 0;
+ rcSrc.top = 0;
+ rcSrc.right = pScreenInfo->dwWidth;
+ rcSrc.bottom = pScreenInfo->dwHeight;
+
+ /* Redraw the whole window, to take account for the new colors */
+ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
+ &rcDest,
+ pScreenPriv->pddsShadow4,
+ &rcSrc,
+ DDBLT_WAIT,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winRedrawScreenShadowDDNL - IDirectDrawSurface4_Blt () "
+ "failed: %08x\n",
+ (unsigned int) ddrval);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Realize the currently installed colormap
+ */
+
+static Bool
+winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen)
+{
+ return TRUE;
+}
+
+
+/*
+ * Install the specified colormap
+ */
+
+static Bool
+winInstallColormapShadowDDNL (ColormapPtr pColormap)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ HRESULT ddrval = DD_OK;
+
+ /* Install the DirectDraw palette on the primary surface */
+ ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4,
+ pCmapPriv->lpDDPalette);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winInstallColormapShadowDDNL - Failed installing the "
+ "DirectDraw palette.\n");
+ return FALSE;
+ }
+
+ /* Save a pointer to the newly installed colormap */
+ pScreenPriv->pcmapInstalled = pColormap;
+
+ return TRUE;
+}
+
+
+/*
+ * Store the specified colors in the specified colormap
+ */
+
+static Bool
+winStoreColorsShadowDDNL (ColormapPtr pColormap,
+ int ndef,
+ xColorItem *pdefs)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
+ HRESULT ddrval = DD_OK;
+
+ /* Put the X colormap entries into the Windows logical palette */
+ ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette,
+ 0,
+ pdefs[0].pixel,
+ ndef,
+ pCmapPriv->peColors
+ + pdefs[0].pixel);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n", (unsigned int) ddrval);
+ return FALSE;
+ }
+
+ /* Don't install the DirectDraw palette if the colormap is not installed */
+ if (pColormap != curpmap)
+ {
+ return TRUE;
+ }
+
+ if (!winInstallColormapShadowDDNL (pColormap))
+ {
+ ErrorF ("winStoreColorsShadowDDNL - Failed installing colormap\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap initialization procedure
+ */
+
+static Bool
+winCreateColormapShadowDDNL (ColormapPtr pColormap)
+{
+ HRESULT ddrval = DD_OK;
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+
+ /* Create a DirectDraw palette */
+ ddrval = IDirectDraw4_CreatePalette (pScreenPriv->pdd4,
+ DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+ pCmapPriv->peColors,
+ &pCmapPriv->lpDDPalette,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winCreateColormapShadowDDNL - CreatePalette failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap destruction procedure
+ */
+
+static Bool
+winDestroyColormapShadowDDNL (ColormapPtr pColormap)
+{
+ winScreenPriv(pColormap->pScreen);
+ winCmapPriv(pColormap);
+ HRESULT ddrval = DD_OK;
+
+ /*
+ * Is colormap to be destroyed the default?
+ *
+ * Non-default colormaps should have had winUninstallColormap
+ * called on them before we get here. The default colormap
+ * will not have had winUninstallColormap called on it. Thus,
+ * we need to handle the default colormap in a special way.
+ */
+ if (pColormap->flags & IsDefault)
+ {
+#if CYGDEBUG
+ winDebug ("winDestroyColormapShadowDDNL - Destroying default colormap\n");
+#endif
+
+ /*
+ * FIXME: Walk the list of all screens, popping the default
+ * palette out of each screen device context.
+ */
+
+ /* Pop the palette out of the primary surface */
+ ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4,
+ NULL);
+ if (FAILED (ddrval))
+ {
+ ErrorF ("winDestroyColormapShadowDDNL - Failed freeing the "
+ "default colormap DirectDraw palette.\n");
+ return FALSE;
+ }
+
+ /* Clear our private installed colormap pointer */
+ pScreenPriv->pcmapInstalled = NULL;
+ }
+
+ /* Release the palette */
+ IDirectDrawPalette_Release (pCmapPriv->lpDDPalette);
+
+ /* Invalidate the colormap privates */
+ pCmapPriv->lpDDPalette = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * Set pointers to our engine specific functions
+ */
+
+Bool
+winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBShadowDDNL;
+ pScreenPriv->pwinFreeFB = winFreeFBShadowDDNL;
+ pScreenPriv->pwinShadowUpdate = winShadowUpdateDDNL;
+ pScreenPriv->pwinInitScreen = winInitScreenShadowDDNL;
+ pScreenPriv->pwinCloseScreen = winCloseScreenShadowDDNL;
+ pScreenPriv->pwinInitVisuals = winInitVisualsShadowDDNL;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDDNL;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
+ pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL;
+ pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL;
+ pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL;
+ pScreenPriv->pwinRealizeInstalledPalette
+ = winRealizeInstalledPaletteShadowDDNL;
+ pScreenPriv->pwinInstallColormap = winInstallColormapShadowDDNL;
+ pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL;
+ pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL;
+ pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL;
+ pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL;
+ pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL;
+#ifdef XWIN_MULTIWINDOW
+ pScreenPriv->pwinFinishCreateWindowsWindow
+ = winFinishCreateWindowsWindowDDNL;
+#endif
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winshadgdi.c b/xorg-server/hw/xwin/winshadgdi.c
index 4f36547f9..499037656 100644
--- a/xorg-server/hw/xwin/winshadgdi.c
+++ b/xorg-server/hw/xwin/winshadgdi.c
@@ -1,1267 +1,1259 @@
-/*
- *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II 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 Harold L Hunt II
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from Harold L Hunt II.
- *
- * Authors: Harold L Hunt II
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-
-
-/*
- * Local function prototypes
- */
-
-#ifdef XWIN_MULTIWINDOW
-static wBOOL CALLBACK
-winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam);
-
-static wBOOL CALLBACK
-winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam);
-#endif
-
-static Bool
-winAllocateFBShadowGDI (ScreenPtr pScreen);
-
-static void
-winShadowUpdateGDI (ScreenPtr pScreen,
- shadowBufPtr pBuf);
-
-static Bool
-winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen);
-
-static Bool
-winInitVisualsShadowGDI (ScreenPtr pScreen);
-
-static Bool
-winAdjustVideoModeShadowGDI (ScreenPtr pScreen);
-
-static Bool
-winBltExposedRegionsShadowGDI (ScreenPtr pScreen);
-
-static Bool
-winActivateAppShadowGDI (ScreenPtr pScreen);
-
-static Bool
-winRedrawScreenShadowGDI (ScreenPtr pScreen);
-
-static Bool
-winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen);
-
-static Bool
-winInstallColormapShadowGDI (ColormapPtr pColormap);
-
-static Bool
-winStoreColorsShadowGDI (ColormapPtr pmap,
- int ndef,
- xColorItem *pdefs);
-
-static Bool
-winCreateColormapShadowGDI (ColormapPtr pColormap);
-
-static Bool
-winDestroyColormapShadowGDI (ColormapPtr pColormap);
-
-
-/*
- * Internal function to get the DIB format that is compatible with the screen
- */
-
-static
-Bool
-winQueryScreenDIBFormat (ScreenPtr pScreen, BITMAPINFOHEADER *pbmih)
-{
- winScreenPriv(pScreen);
- HBITMAP hbmp;
-#if CYGDEBUG
- LPDWORD pdw = NULL;
-#endif
-
- /* Create a memory bitmap compatible with the screen */
- hbmp = CreateCompatibleBitmap (pScreenPriv->hdcScreen, 1, 1);
- if (hbmp == NULL)
- {
- ErrorF ("winQueryScreenDIBFormat - CreateCompatibleBitmap failed\n");
- return FALSE;
- }
-
- /* Initialize our bitmap info header */
- ZeroMemory (pbmih, sizeof (BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD));
- pbmih->biSize = sizeof (BITMAPINFOHEADER);
-
- /* Get the biBitCount */
- if (!GetDIBits (pScreenPriv->hdcScreen,
- hbmp,
- 0, 1,
- NULL,
- (BITMAPINFO*) pbmih,
- DIB_RGB_COLORS))
- {
- ErrorF ("winQueryScreenDIBFormat - First call to GetDIBits failed\n");
- DeleteObject (hbmp);
- return FALSE;
- }
-
-#if CYGDEBUG
- /* Get a pointer to bitfields */
- pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
-
- winDebug ("winQueryScreenDIBFormat - First call masks: %08x %08x %08x\n",
- pdw[0], pdw[1], pdw[2]);
-#endif
-
- /* Get optimal color table, or the optimal bitfields */
- if (!GetDIBits (pScreenPriv->hdcScreen,
- hbmp,
- 0, 1,
- NULL,
- (BITMAPINFO*)pbmih,
- DIB_RGB_COLORS))
- {
- ErrorF ("winQueryScreenDIBFormat - Second call to GetDIBits "
- "failed\n");
- DeleteObject (hbmp);
- return FALSE;
- }
-
- /* Free memory */
- DeleteObject (hbmp);
-
- return TRUE;
-}
-
-
-/*
- * Internal function to determine the GDI bits per rgb and bit masks
- */
-
-static
-Bool
-winQueryRGBBitsAndMasks (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- BITMAPINFOHEADER *pbmih = NULL;
- Bool fReturn = TRUE;
- LPDWORD pdw = NULL;
- DWORD dwRedBits, dwGreenBits, dwBlueBits;
-
- /* Color masks for 8 bpp are standardized */
- if (GetDeviceCaps (pScreenPriv->hdcScreen, RASTERCAPS) & RC_PALETTE)
- {
- /*
- * RGB BPP for 8 bit palletes is always 8
- * and the color masks are always 0.
- */
- pScreenPriv->dwBitsPerRGB = 8;
- pScreenPriv->dwRedMask = 0x0L;
- pScreenPriv->dwGreenMask = 0x0L;
- pScreenPriv->dwBlueMask = 0x0L;
- return TRUE;
- }
-
- /* Color masks for 24 bpp are standardized */
- if (GetDeviceCaps (pScreenPriv->hdcScreen, PLANES)
- * GetDeviceCaps (pScreenPriv->hdcScreen, BITSPIXEL) == 24)
- {
- ErrorF ("winQueryRGBBitsAndMasks - GetDeviceCaps (BITSPIXEL) "
- "returned 24 for the screen. Using default 24bpp masks.\n");
-
- /* 8 bits per primary color */
- pScreenPriv->dwBitsPerRGB = 8;
-
- /* Set screen privates masks */
- pScreenPriv->dwRedMask = WIN_24BPP_MASK_RED;
- pScreenPriv->dwGreenMask = WIN_24BPP_MASK_GREEN;
- pScreenPriv->dwBlueMask = WIN_24BPP_MASK_BLUE;
-
- return TRUE;
- }
-
- /* Allocate a bitmap header and color table */
- pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
- + 256 * sizeof (RGBQUAD));
- if (pbmih == NULL)
- {
- ErrorF ("winQueryRGBBitsAndMasks - malloc failed\n");
- return FALSE;
- }
-
- /* Get screen description */
- if (winQueryScreenDIBFormat (pScreen, pbmih))
- {
- /* Get a pointer to bitfields */
- pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
-
-#if CYGDEBUG
- winDebug ("%s - Masks: %08x %08x %08x\n", __FUNCTION__,
- pdw[0], pdw[1], pdw[2]);
- winDebug ("%s - Bitmap: %dx%d %d bpp %d planes\n", __FUNCTION__,
- pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount, pbmih->biPlanes);
- winDebug ("%s - Compression: %d %s\n", __FUNCTION__,
- pbmih->biCompression,
- (pbmih->biCompression == BI_RGB?"(BI_RGB)":
- (pbmih->biCompression == BI_RLE8?"(BI_RLE8)":
- (pbmih->biCompression == BI_RLE4?"(BI_RLE4)":
- (pbmih->biCompression == BI_BITFIELDS?"(BI_BITFIELDS)":""
- )))));
-#endif
-
- /* Handle BI_RGB case, which is returned by Wine */
- if (pbmih->biCompression == BI_RGB)
- {
- dwRedBits = 5;
- dwGreenBits = 5;
- dwBlueBits = 5;
-
- pScreenPriv->dwBitsPerRGB = 5;
-
- /* Set screen privates masks */
- pScreenPriv->dwRedMask = 0x7c00;
- pScreenPriv->dwGreenMask = 0x03e0;
- pScreenPriv->dwBlueMask = 0x001f;
- }
- else
- {
- /* Count the number of bits in each mask */
- dwRedBits = winCountBits (pdw[0]);
- dwGreenBits = winCountBits (pdw[1]);
- dwBlueBits = winCountBits (pdw[2]);
-
- /* Find maximum bits per red, green, blue */
- if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
- pScreenPriv->dwBitsPerRGB = dwRedBits;
- else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
- pScreenPriv->dwBitsPerRGB = dwGreenBits;
- else
- pScreenPriv->dwBitsPerRGB = dwBlueBits;
-
- /* Set screen privates masks */
- pScreenPriv->dwRedMask = pdw[0];
- pScreenPriv->dwGreenMask = pdw[1];
- pScreenPriv->dwBlueMask = pdw[2];
- }
- }
- else
- {
- ErrorF ("winQueryRGBBitsAndMasks - winQueryScreenDIBFormat failed\n");
- free (pbmih);
- fReturn = FALSE;
- }
-
- /* Free memory */
- free (pbmih);
-
- return fReturn;
-}
-
-
-#ifdef XWIN_MULTIWINDOW
-/*
- * Redraw all ---?
- */
-
-static wBOOL CALLBACK
-winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam)
-{
- if (hwnd == (HWND)lParam)
- return TRUE;
- InvalidateRect (hwnd, NULL, FALSE);
- UpdateWindow (hwnd);
- return TRUE;
-}
-
-static wBOOL CALLBACK
-winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam)
-{
- BoxPtr pDamage = (BoxPtr)lParam;
- RECT rcClient, rcDamage, rcRedraw;
- POINT topLeft, bottomRight;
-
- if (IsIconic (hwnd))
- return TRUE; /* Don't care minimized windows */
-
- /* Convert the damaged area from Screen coords to Client coords */
- topLeft.x = pDamage->x1; topLeft.y = pDamage->y1;
- bottomRight.x = pDamage->x2; bottomRight.y = pDamage->y2;
- topLeft.x += GetSystemMetrics (SM_XVIRTUALSCREEN);
- bottomRight.x += GetSystemMetrics (SM_XVIRTUALSCREEN);
- topLeft.y += GetSystemMetrics (SM_YVIRTUALSCREEN);
- bottomRight.y += GetSystemMetrics (SM_YVIRTUALSCREEN);
- ScreenToClient (hwnd, &topLeft);
- ScreenToClient (hwnd, &bottomRight);
- SetRect (&rcDamage, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
-
- GetClientRect (hwnd, &rcClient);
-
- if (IntersectRect (&rcRedraw, &rcClient, &rcDamage))
- {
- InvalidateRect (hwnd, &rcRedraw, FALSE);
- UpdateWindow (hwnd);
- }
- return TRUE;
-}
-#endif
-
-
-/*
- * Allocate a DIB for the shadow framebuffer GDI server
- */
-
-static Bool
-winAllocateFBShadowGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- BITMAPINFOHEADER *pbmih = NULL;
- DIBSECTION dibsection;
- Bool fReturn = TRUE;
-
- /* Get device contexts for the screen and shadow bitmap */
- pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
- pScreenPriv->hdcShadow = CreateCompatibleDC (pScreenPriv->hdcScreen);
-
- /* Allocate bitmap info header */
- pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
- + 256 * sizeof (RGBQUAD));
- if (pbmih == NULL)
- {
- ErrorF ("winAllocateFBShadowGDI - malloc () failed\n");
- return FALSE;
- }
-
- /* Query the screen format */
- fReturn = winQueryScreenDIBFormat (pScreen, pbmih);
-
- /* Describe shadow bitmap to be created */
- pbmih->biWidth = pScreenInfo->dwWidth;
- pbmih->biHeight = -pScreenInfo->dwHeight;
-
- ErrorF ("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d "
- "depth: %d\n",
- (int) pbmih->biWidth, (int) -pbmih->biHeight, pbmih->biBitCount);
-
- /* Create a DI shadow bitmap with a bit pointer */
- pScreenPriv->hbmpShadow = CreateDIBSection (pScreenPriv->hdcScreen,
- (BITMAPINFO *) pbmih,
- DIB_RGB_COLORS,
- (VOID**) &pScreenInfo->pfb,
- NULL,
- 0);
- if (pScreenPriv->hbmpShadow == NULL || pScreenInfo->pfb == NULL)
- {
- winW32Error (2, "winAllocateFBShadowGDI - CreateDIBSection failed:");
- return FALSE;
- }
- else
- {
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowGDI - Shadow buffer allocated\n");
-#endif
- }
-
- /* Get information about the bitmap that was allocated */
- GetObject (pScreenPriv->hbmpShadow,
- sizeof (dibsection),
- &dibsection);
-
-#if CYGDEBUG || YES
- /* Print information about bitmap allocated */
- winDebug ("winAllocateFBShadowGDI - Dibsection width: %d height: %d "
- "depth: %d size image: %d\n",
- (int) dibsection.dsBmih.biWidth, (int) dibsection.dsBmih.biHeight,
- dibsection.dsBmih.biBitCount,
- (int) dibsection.dsBmih.biSizeImage);
-#endif
-
- /* Select the shadow bitmap into the shadow DC */
- SelectObject (pScreenPriv->hdcShadow,
- pScreenPriv->hbmpShadow);
-
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowGDI - Attempting a shadow blit\n");
-#endif
-
- /* Do a test blit from the shadow to the screen, I think */
- fReturn = BitBlt (pScreenPriv->hdcScreen,
- 0, 0,
- pScreenInfo->dwWidth, pScreenInfo->dwHeight,
- pScreenPriv->hdcShadow,
- 0, 0,
- SRCCOPY);
- if (fReturn)
- {
-#if CYGDEBUG
- winDebug ("winAllocateFBShadowGDI - Shadow blit success\n");
-#endif
- }
- else
- {
- winW32Error (2, "winAllocateFBShadowGDI - Shadow blit failure\n");
-#if 0
- return FALSE;
-#else
- /* ago: ignore this error. The blit fails with wine, but does not
- * cause any problems later. */
-
- fReturn = TRUE;
-#endif
- }
-
- /* Look for height weirdness */
- if (dibsection.dsBmih.biHeight < 0)
- {
- dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
- }
-
- /* Set screeninfo stride */
- pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage
- / dibsection.dsBmih.biHeight)
- * 8) / pScreenInfo->dwBPP;
-
-#if CYGDEBUG || YES
- winDebug ("winAllocateFBShadowGDI - Created shadow stride: %d\n",
- (int) pScreenInfo->dwStride);
-#endif
-
- /* See if the shadow bitmap will be larger than the DIB size limit */
- if (pScreenInfo->dwWidth * pScreenInfo->dwHeight * pScreenInfo->dwBPP
- >= WIN_DIB_MAXIMUM_SIZE)
- {
- ErrorF ("winAllocateFBShadowGDI - Requested DIB (bitmap) "
- "will be larger than %d MB. The surface may fail to be "
- "allocated on Windows 95, 98, or Me, due to a %d MB limit in "
- "DIB size. This limit does not apply to Windows NT/2000, and "
- "this message may be ignored on those platforms.\n",
- WIN_DIB_MAXIMUM_SIZE_MB, WIN_DIB_MAXIMUM_SIZE_MB);
- }
-
- /* Determine our color masks */
- if (!winQueryRGBBitsAndMasks (pScreen))
- {
- ErrorF ("winAllocateFBShadowGDI - winQueryRGBBitsAndMasks failed\n");
- return FALSE;
- }
-
-#ifdef XWIN_MULTIWINDOW
- /* Redraw all windows */
- if (pScreenInfo->fMultiWindow)
- EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
-#endif
-
- return fReturn;
-}
-
-
-/*
- * Blit the damaged regions of the shadow fb to the screen
- */
-
-static void
-winShadowUpdateGDI (ScreenPtr pScreen,
- shadowBufPtr pBuf)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- RegionPtr damage = shadowDamage(pBuf);
- DWORD dwBox = RegionNumRects (damage);
- BoxPtr pBox = RegionRects (damage);
- int x, y, w, h;
- HRGN hrgnTemp = NULL, hrgnCombined = NULL;
-#ifdef XWIN_UPDATESTATS
- static DWORD s_dwNonUnitRegions = 0;
- static DWORD s_dwTotalUpdates = 0;
- static DWORD s_dwTotalBoxes = 0;
-#endif
- BoxPtr pBoxExtents = RegionExtents(damage);
-
- /*
- * Return immediately if the app is not active
- * and we are fullscreen, or if we have a bad display depth
- */
- if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
- || pScreenPriv->fBadDepth) return;
-
-#ifdef XWIN_UPDATESTATS
- ++s_dwTotalUpdates;
- s_dwTotalBoxes += dwBox;
-
- if (dwBox != 1)
- {
- ++s_dwNonUnitRegions;
- ErrorF ("winShadowUpdatGDI - dwBox: %d\n", dwBox);
- }
-
- if ((s_dwTotalUpdates % 100) == 0)
- ErrorF ("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d "
- "nu: %d tu: %d\n",
- (s_dwNonUnitRegions * 100) / s_dwTotalUpdates,
- s_dwTotalBoxes / s_dwTotalUpdates,
- s_dwNonUnitRegions, s_dwTotalUpdates);
-#endif /* XWIN_UPDATESTATS */
-
- /*
- * Handle small regions with multiple blits,
- * handle large regions by creating a clipping region and
- * doing a single blit constrained to that clipping region.
- */
- if (!pScreenInfo->fMultiWindow &&
- (pScreenInfo->dwClipUpdatesNBoxes == 0 ||
- dwBox < pScreenInfo->dwClipUpdatesNBoxes))
- {
- /* Loop through all boxes in the damaged region */
- while (dwBox--)
- {
- /*
- * Calculate x offset, y offset, width, and height for
- * current damage box
- */
- x = pBox->x1;
- y = pBox->y1;
- w = pBox->x2 - pBox->x1;
- h = pBox->y2 - pBox->y1;
-
- BitBlt (pScreenPriv->hdcScreen,
- x, y,
- w, h,
- pScreenPriv->hdcShadow,
- x, y,
- SRCCOPY);
-
- /* Get a pointer to the next box */
- ++pBox;
- }
- }
- else if (!pScreenInfo->fMultiWindow)
- {
- /* Compute a GDI region from the damaged region */
- hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
- dwBox--;
- pBox++;
- while (dwBox--)
- {
- hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
- CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
- DeleteObject (hrgnTemp);
- pBox++;
- }
-
- /* Install the GDI region as a clipping region */
- SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
- DeleteObject (hrgnCombined);
- hrgnCombined = NULL;
-
- /*
- * Blit the shadow buffer to the screen,
- * constrained to the clipping region.
- */
- BitBlt (pScreenPriv->hdcScreen,
- pBoxExtents->x1, pBoxExtents->y1,
- pBoxExtents->x2 - pBoxExtents->x1,
- pBoxExtents->y2 - pBoxExtents->y1,
- pScreenPriv->hdcShadow,
- pBoxExtents->x1, pBoxExtents->y1,
- SRCCOPY);
-
- /* Reset the clip region */
- SelectClipRgn (pScreenPriv->hdcScreen, NULL);
- }
-
-#ifdef XWIN_MULTIWINDOW
- /* Redraw all multiwindow windows */
- if (pScreenInfo->fMultiWindow)
- EnumThreadWindows (g_dwCurrentThreadID,
- winRedrawDamagedWindowShadowGDI,
- (LPARAM)pBoxExtents);
-#endif
-}
-
-
-/* See Porting Layer Definition - p. 33 */
-/*
- * We wrap whatever CloseScreen procedure was specified by fb;
- * a pointer to said procedure is stored in our privates.
- */
-
-static Bool
-winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- Bool fReturn;
-
-#if CYGDEBUG
- winDebug ("winCloseScreenShadowGDI - Freeing screen resources\n");
-#endif
-
- /* Flag that the screen is closed */
- pScreenPriv->fClosed = TRUE;
- pScreenPriv->fActive = FALSE;
-
- /* Call the wrapped CloseScreen procedure */
- WIN_UNWRAP(CloseScreen);
- fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
-
- /* Delete the window property */
- RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
-
- /* Free the shadow DC; which allows the bitmap to be freed */
- DeleteDC (pScreenPriv->hdcShadow);
-
- /* Free the shadow bitmap */
- DeleteObject (pScreenPriv->hbmpShadow);
-
- /* Free the screen DC */
- ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
-
- /* Delete tray icon, if we have one */
- if (!pScreenInfo->fNoTrayIcon)
- winDeleteNotifyIcon (pScreenPriv);
-
- /* Free the exit confirmation dialog box, if it exists */
- if (g_hDlgExit != NULL)
- {
- DestroyWindow (g_hDlgExit);
- g_hDlgExit = NULL;
- }
-
- /* Kill our window */
- if (pScreenPriv->hwndScreen)
- {
- DestroyWindow (pScreenPriv->hwndScreen);
- pScreenPriv->hwndScreen = NULL;
- }
-
-#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
- /* Destroy the thread startup mutex */
- pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
-#endif
-
- /* Invalidate our screeninfo's pointer to the screen */
- pScreenInfo->pScreen = NULL;
-
- /* Invalidate the ScreenInfo's fb pointer */
- pScreenInfo->pfb = NULL;
-
- /* Free the screen privates for this screen */
- free ((pointer) pScreenPriv);
-
- return fReturn;
-}
-
-
-/*
- * Tell mi what sort of visuals we need.
- *
- * Generally we only need one visual, as our screen can only
- * handle one format at a time, I believe. You may want
- * to verify that last sentence.
- */
-
-static Bool
-winInitVisualsShadowGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /* Display debugging information */
- ErrorF ("winInitVisualsShadowGDI - Masks %08x %08x %08x BPRGB %d d %d "
- "bpp %d\n",
- (unsigned int) pScreenPriv->dwRedMask,
- (unsigned int) pScreenPriv->dwGreenMask,
- (unsigned int) pScreenPriv->dwBlueMask,
- (int) pScreenPriv->dwBitsPerRGB,
- (int) pScreenInfo->dwDepth,
- (int) pScreenInfo->dwBPP);
-
- /* Create a single visual according to the Windows screen depth */
- switch (pScreenInfo->dwDepth)
- {
- case 24:
- case 16:
- case 15:
- /* Setup the real visual */
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- TrueColorMask,
- pScreenPriv->dwBitsPerRGB,
- -1,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
- "failed\n");
- return FALSE;
- }
-
-#ifdef XWIN_EMULATEPSEUDO
- if (!pScreenInfo->fEmulatePseudo)
- break;
-
- /* Setup a pseudocolor visual */
- if (!miSetVisualTypesAndMasks (8,
- PseudoColorMask,
- 8,
- -1,
- 0,
- 0,
- 0))
- {
- ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
- "failed for PseudoColor\n");
- return FALSE;
- }
-#endif
- break;
-
- case 8:
- if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
- PseudoColorMask,
- pScreenPriv->dwBitsPerRGB,
- PseudoColor,
- pScreenPriv->dwRedMask,
- pScreenPriv->dwGreenMask,
- pScreenPriv->dwBlueMask))
- {
- ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
- "failed\n");
- return FALSE;
- }
- break;
-
- default:
- ErrorF ("winInitVisualsShadowGDI - Unknown screen depth\n");
- return FALSE;
- }
-
-#if CYGDEBUG
- winDebug ("winInitVisualsShadowGDI - Returning\n");
-#endif
-
- return TRUE;
-}
-
-
-/*
- * Adjust the proposed video mode
- */
-
-static Bool
-winAdjustVideoModeShadowGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- HDC hdc;
- DWORD dwBPP;
-
- hdc = GetDC (NULL);
-
- /* We're in serious trouble if we can't get a DC */
- if (hdc == NULL)
- {
- ErrorF ("winAdjustVideoModeShadowGDI - GetDC () failed\n");
- return FALSE;
- }
-
- /* Query GDI for current display depth */
- dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
-
- /* GDI cannot change the screen depth */
- if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP)
- {
- /* No -depth parameter passed, let the user know the depth being used */
- ErrorF ("winAdjustVideoModeShadowGDI - Using Windows display "
- "depth of %d bits per pixel\n", (int) dwBPP);
-
- /* Use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
- else if (dwBPP != pScreenInfo->dwBPP)
- {
- /* Warn user if GDI depth is different than -depth parameter */
- ErrorF ("winAdjustVideoModeShadowGDI - Command line bpp: %d, "\
- "using bpp: %d\n", (int) pScreenInfo->dwBPP, (int) dwBPP);
-
- /* We'll use GDI's depth */
- pScreenInfo->dwBPP = dwBPP;
- }
-
- /* Release our DC */
- ReleaseDC (NULL, hdc);
- hdc = NULL;
-
- return TRUE;
-}
-
-
-/*
- * Blt exposed regions to the screen
- */
-
-static Bool
-winBltExposedRegionsShadowGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- winPrivCmapPtr pCmapPriv = NULL;
- HDC hdcUpdate;
- PAINTSTRUCT ps;
-
- /* BeginPaint gives us an hdc that clips to the invalidated region */
- hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
-
- /* Realize the palette, if we have one */
- if (pScreenPriv->pcmapInstalled != NULL)
- {
- pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled);
-
- SelectPalette (hdcUpdate, pCmapPriv->hPalette, FALSE);
- RealizePalette (hdcUpdate);
- }
-
- /* Our BitBlt will be clipped to the invalidated region */
- BitBlt (hdcUpdate,
- 0, 0,
- pScreenInfo->dwWidth, pScreenInfo->dwHeight,
- pScreenPriv->hdcShadow,
- 0, 0,
- SRCCOPY);
-
- /* EndPaint frees the DC */
- EndPaint (pScreenPriv->hwndScreen, &ps);
-
-#ifdef XWIN_MULTIWINDOW
- /* Redraw all windows */
- if (pScreenInfo->fMultiWindow)
- EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI,
- (LPARAM)pScreenPriv->hwndScreen);
-#endif
-
- return TRUE;
-}
-
-
-/*
- * Do any engine-specific appliation-activation processing
- */
-
-static Bool
-winActivateAppShadowGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /*
- * 2004/04/12 - Harold - We perform the restoring or minimizing
- * manually for ShadowGDI in fullscreen modes so that this engine
- * will perform just like ShadowDD and ShadowDDNL in fullscreen mode;
- * if we do not do this then our fullscreen window will appear in the
- * z-order when it is deactivated and it can be uncovered by resizing
- * or minimizing another window that is on top of it, which is not how
- * the DirectDraw engines work. Therefore we keep this code here to
- * make sure that all engines work the same in fullscreen mode.
- */
-
- /*
- * Are we active?
- * Are we fullscreen?
- */
- if (pScreenPriv->fActive
- && pScreenInfo->fFullScreen)
- {
- /*
- * Activating, attempt to bring our window
- * to the top of the display
- */
- ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE);
- }
- else if (!pScreenPriv->fActive
- && pScreenInfo->fFullScreen)
- {
- /*
- * Deactivating, stuff our window onto the
- * task bar.
- */
- ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE);
- }
-
- return TRUE;
-}
-
-
-/*
- * Reblit the shadow framebuffer to the screen.
- */
-
-static Bool
-winRedrawScreenShadowGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /* Redraw the whole window, to take account for the new colors */
- BitBlt (pScreenPriv->hdcScreen,
- 0, 0,
- pScreenInfo->dwWidth, pScreenInfo->dwHeight,
- pScreenPriv->hdcShadow,
- 0, 0,
- SRCCOPY);
-
-#ifdef XWIN_MULTIWINDOW
- /* Redraw all windows */
- if (pScreenInfo->fMultiWindow)
- EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
-#endif
-
- return TRUE;
-}
-
-
-
-/*
- * Realize the currently installed colormap
- */
-
-static Bool
-winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winPrivCmapPtr pCmapPriv = NULL;
-
-#if CYGDEBUG
- winDebug ("winRealizeInstalledPaletteShadowGDI\n");
-#endif
-
- /* Don't do anything if there is not a colormap */
- if (pScreenPriv->pcmapInstalled == NULL)
- {
-#if CYGDEBUG
- winDebug ("winRealizeInstalledPaletteShadowGDI - No colormap "
- "installed\n");
-#endif
- return TRUE;
- }
-
- pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled);
-
- /* Realize our palette for the screen */
- if (RealizePalette (pScreenPriv->hdcScreen) == GDI_ERROR)
- {
- ErrorF ("winRealizeInstalledPaletteShadowGDI - RealizePalette () "
- "failed\n");
- return FALSE;
- }
-
- /* Set the DIB color table */
- if (SetDIBColorTable (pScreenPriv->hdcShadow,
- 0,
- WIN_NUM_PALETTE_ENTRIES,
- pCmapPriv->rgbColors) == 0)
- {
- ErrorF ("winRealizeInstalledPaletteShadowGDI - SetDIBColorTable () "
- "failed\n");
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * Install the specified colormap
- */
-
-static Bool
-winInstallColormapShadowGDI (ColormapPtr pColormap)
-{
- ScreenPtr pScreen = pColormap->pScreen;
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
- winCmapPriv(pColormap);
-
- /*
- * Tell Windows to install the new colormap
- */
- if (SelectPalette (pScreenPriv->hdcScreen,
- pCmapPriv->hPalette,
- FALSE) == NULL)
- {
- ErrorF ("winInstallColormapShadowGDI - SelectPalette () failed\n");
- return FALSE;
- }
-
- /* Realize the palette */
- if (GDI_ERROR == RealizePalette (pScreenPriv->hdcScreen))
- {
- ErrorF ("winInstallColormapShadowGDI - RealizePalette () failed\n");
- return FALSE;
- }
-
- /* Set the DIB color table */
- if (SetDIBColorTable (pScreenPriv->hdcShadow,
- 0,
- WIN_NUM_PALETTE_ENTRIES,
- pCmapPriv->rgbColors) == 0)
- {
- ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
- return FALSE;
- }
-
- /* Redraw the whole window, to take account for the new colors */
- BitBlt (pScreenPriv->hdcScreen,
- 0, 0,
- pScreenInfo->dwWidth, pScreenInfo->dwHeight,
- pScreenPriv->hdcShadow,
- 0, 0,
- SRCCOPY);
-
- /* Save a pointer to the newly installed colormap */
- pScreenPriv->pcmapInstalled = pColormap;
-
-#ifdef XWIN_MULTIWINDOW
- /* Redraw all windows */
- if (pScreenInfo->fMultiWindow)
- EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
-#endif
-
- return TRUE;
-}
-
-
-/*
- * Store the specified colors in the specified colormap
- */
-
-static Bool
-winStoreColorsShadowGDI (ColormapPtr pColormap,
- int ndef,
- xColorItem *pdefs)
-{
- ScreenPtr pScreen = pColormap->pScreen;
- winScreenPriv(pScreen);
- winCmapPriv(pColormap);
- ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
-
- /* Put the X colormap entries into the Windows logical palette */
- if (SetPaletteEntries (pCmapPriv->hPalette,
- pdefs[0].pixel,
- ndef,
- pCmapPriv->peColors + pdefs[0].pixel) == 0)
- {
- ErrorF ("winStoreColorsShadowGDI - SetPaletteEntries () failed\n");
- return FALSE;
- }
-
- /* Don't install the Windows palette if the colormap is not installed */
- if (pColormap != curpmap)
- {
- return TRUE;
- }
-
- /* Try to install the newly modified colormap */
- if (!winInstallColormapShadowGDI (pColormap))
- {
- ErrorF ("winInstallColormapShadowGDI - winInstallColormapShadowGDI "
- "failed\n");
- return FALSE;
- }
-
-#if 0
- /* Tell Windows that the palette has changed */
- RealizePalette (pScreenPriv->hdcScreen);
-
- /* Set the DIB color table */
- if (SetDIBColorTable (pScreenPriv->hdcShadow,
- pdefs[0].pixel,
- ndef,
- pCmapPriv->rgbColors + pdefs[0].pixel) == 0)
- {
- ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
- return FALSE;
- }
-
- /* Save a pointer to the newly installed colormap */
- pScreenPriv->pcmapInstalled = pColormap;
-#endif
-
- return TRUE;
-}
-
-
-/*
- * Colormap initialization procedure
- */
-
-static Bool
-winCreateColormapShadowGDI (ColormapPtr pColormap)
-{
- LPLOGPALETTE lpPaletteNew = NULL;
- DWORD dwEntriesMax;
- VisualPtr pVisual;
- HPALETTE hpalNew = NULL;
- winCmapPriv(pColormap);
-
- /* Get a pointer to the visual that the colormap belongs to */
- pVisual = pColormap->pVisual;
-
- /* Get the maximum number of palette entries for this visual */
- dwEntriesMax = pVisual->ColormapEntries;
-
- /* Allocate a Windows logical color palette with max entries */
- lpPaletteNew = malloc (sizeof (LOGPALETTE)
- + (dwEntriesMax - 1) * sizeof (PALETTEENTRY));
- if (lpPaletteNew == NULL)
- {
- ErrorF ("winCreateColormapShadowGDI - Couldn't allocate palette "
- "with %d entries\n",
- (int) dwEntriesMax);
- return FALSE;
- }
-
- /* Zero out the colormap */
- ZeroMemory (lpPaletteNew, sizeof (LOGPALETTE)
- + (dwEntriesMax - 1) * sizeof (PALETTEENTRY));
-
- /* Set the logical palette structure */
- lpPaletteNew->palVersion = 0x0300;
- lpPaletteNew->palNumEntries = dwEntriesMax;
-
- /* Tell Windows to create the palette */
- hpalNew = CreatePalette (lpPaletteNew);
- if (hpalNew == NULL)
- {
- ErrorF ("winCreateColormapShadowGDI - CreatePalette () failed\n");
- free (lpPaletteNew);
- return FALSE;
- }
-
- /* Save the Windows logical palette handle in the X colormaps' privates */
- pCmapPriv->hPalette = hpalNew;
-
- /* Free the palette initialization memory */
- free (lpPaletteNew);
-
- return TRUE;
-}
-
-
-/*
- * Colormap destruction procedure
- */
-
-static Bool
-winDestroyColormapShadowGDI (ColormapPtr pColormap)
-{
- winScreenPriv(pColormap->pScreen);
- winCmapPriv(pColormap);
-
- /*
- * Is colormap to be destroyed the default?
- *
- * Non-default colormaps should have had winUninstallColormap
- * called on them before we get here. The default colormap
- * will not have had winUninstallColormap called on it. Thus,
- * we need to handle the default colormap in a special way.
- */
- if (pColormap->flags & IsDefault)
- {
-#if CYGDEBUG
- winDebug ("winDestroyColormapShadowGDI - Destroying default "
- "colormap\n");
-#endif
-
- /*
- * FIXME: Walk the list of all screens, popping the default
- * palette out of each screen device context.
- */
-
- /* Pop the palette out of the device context */
- SelectPalette (pScreenPriv->hdcScreen,
- GetStockObject (DEFAULT_PALETTE),
- FALSE);
-
- /* Clear our private installed colormap pointer */
- pScreenPriv->pcmapInstalled = NULL;
- }
-
- /* Try to delete the logical palette */
- if (DeleteObject (pCmapPriv->hPalette) == 0)
- {
- ErrorF ("winDestroyColormap - DeleteObject () failed\n");
- return FALSE;
- }
-
- /* Invalidate the colormap privates */
- pCmapPriv->hPalette = NULL;
-
- return TRUE;
-}
-
-
-/*
- * Set engine specific funtions
- */
-
-Bool
-winSetEngineFunctionsShadowGDI (ScreenPtr pScreen)
-{
- winScreenPriv(pScreen);
- winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
-
- /* Set our pointers */
- pScreenPriv->pwinAllocateFB = winAllocateFBShadowGDI;
- pScreenPriv->pwinShadowUpdate = winShadowUpdateGDI;
- pScreenPriv->pwinCloseScreen = winCloseScreenShadowGDI;
- pScreenPriv->pwinInitVisuals = winInitVisualsShadowGDI;
- pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowGDI;
- if (pScreenInfo->fFullScreen)
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
- else
- pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
- pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
- pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI;
- pScreenPriv->pwinActivateApp = winActivateAppShadowGDI;
- pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI;
- pScreenPriv->pwinRealizeInstalledPalette =
- winRealizeInstalledPaletteShadowGDI;
- pScreenPriv->pwinInstallColormap = winInstallColormapShadowGDI;
- pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI;
- pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI;
- pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI;
- pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
- pScreenPriv->pwinCreatePrimarySurface
- = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
- pScreenPriv->pwinReleasePrimarySurface
- = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
-#ifdef XWIN_MULTIWINDOW
- pScreenPriv->pwinFinishCreateWindowsWindow =
- (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
-#endif
-
- return TRUE;
-}
+/*
+ *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II 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 Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+#ifdef XWIN_MULTIWINDOW
+static wBOOL CALLBACK
+winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam);
+
+static wBOOL CALLBACK
+winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam);
+#endif
+
+static Bool
+winAllocateFBShadowGDI (ScreenPtr pScreen);
+
+static void
+winShadowUpdateGDI (ScreenPtr pScreen,
+ shadowBufPtr pBuf);
+
+static Bool
+winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen);
+
+static Bool
+winInitVisualsShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winAdjustVideoModeShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winBltExposedRegionsShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winActivateAppShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winRedrawScreenShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen);
+
+static Bool
+winInstallColormapShadowGDI (ColormapPtr pColormap);
+
+static Bool
+winStoreColorsShadowGDI (ColormapPtr pmap,
+ int ndef,
+ xColorItem *pdefs);
+
+static Bool
+winCreateColormapShadowGDI (ColormapPtr pColormap);
+
+static Bool
+winDestroyColormapShadowGDI (ColormapPtr pColormap);
+
+
+/*
+ * Internal function to get the DIB format that is compatible with the screen
+ */
+
+static
+Bool
+winQueryScreenDIBFormat (ScreenPtr pScreen, BITMAPINFOHEADER *pbmih)
+{
+ winScreenPriv(pScreen);
+ HBITMAP hbmp;
+#if CYGDEBUG
+ LPDWORD pdw = NULL;
+#endif
+
+ /* Create a memory bitmap compatible with the screen */
+ hbmp = CreateCompatibleBitmap (pScreenPriv->hdcScreen, 1, 1);
+ if (hbmp == NULL)
+ {
+ ErrorF ("winQueryScreenDIBFormat - CreateCompatibleBitmap failed\n");
+ return FALSE;
+ }
+
+ /* Initialize our bitmap info header */
+ ZeroMemory (pbmih, sizeof (BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD));
+ pbmih->biSize = sizeof (BITMAPINFOHEADER);
+
+ /* Get the biBitCount */
+ if (!GetDIBits (pScreenPriv->hdcScreen,
+ hbmp,
+ 0, 1,
+ NULL,
+ (BITMAPINFO*) pbmih,
+ DIB_RGB_COLORS))
+ {
+ ErrorF ("winQueryScreenDIBFormat - First call to GetDIBits failed\n");
+ DeleteObject (hbmp);
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ /* Get a pointer to bitfields */
+ pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
+
+ winDebug ("winQueryScreenDIBFormat - First call masks: %08x %08x %08x\n",
+ pdw[0], pdw[1], pdw[2]);
+#endif
+
+ /* Get optimal color table, or the optimal bitfields */
+ if (!GetDIBits (pScreenPriv->hdcScreen,
+ hbmp,
+ 0, 1,
+ NULL,
+ (BITMAPINFO*)pbmih,
+ DIB_RGB_COLORS))
+ {
+ ErrorF ("winQueryScreenDIBFormat - Second call to GetDIBits "
+ "failed\n");
+ DeleteObject (hbmp);
+ return FALSE;
+ }
+
+ /* Free memory */
+ DeleteObject (hbmp);
+
+ return TRUE;
+}
+
+
+/*
+ * Internal function to determine the GDI bits per rgb and bit masks
+ */
+
+static
+Bool
+winQueryRGBBitsAndMasks (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ BITMAPINFOHEADER *pbmih = NULL;
+ Bool fReturn = TRUE;
+ LPDWORD pdw = NULL;
+ DWORD dwRedBits, dwGreenBits, dwBlueBits;
+
+ /* Color masks for 8 bpp are standardized */
+ if (GetDeviceCaps (pScreenPriv->hdcScreen, RASTERCAPS) & RC_PALETTE)
+ {
+ /*
+ * RGB BPP for 8 bit palletes is always 8
+ * and the color masks are always 0.
+ */
+ pScreenPriv->dwBitsPerRGB = 8;
+ pScreenPriv->dwRedMask = 0x0L;
+ pScreenPriv->dwGreenMask = 0x0L;
+ pScreenPriv->dwBlueMask = 0x0L;
+ return TRUE;
+ }
+
+ /* Color masks for 24 bpp are standardized */
+ if (GetDeviceCaps (pScreenPriv->hdcScreen, PLANES)
+ * GetDeviceCaps (pScreenPriv->hdcScreen, BITSPIXEL) == 24)
+ {
+ ErrorF ("winQueryRGBBitsAndMasks - GetDeviceCaps (BITSPIXEL) "
+ "returned 24 for the screen. Using default 24bpp masks.\n");
+
+ /* 8 bits per primary color */
+ pScreenPriv->dwBitsPerRGB = 8;
+
+ /* Set screen privates masks */
+ pScreenPriv->dwRedMask = WIN_24BPP_MASK_RED;
+ pScreenPriv->dwGreenMask = WIN_24BPP_MASK_GREEN;
+ pScreenPriv->dwBlueMask = WIN_24BPP_MASK_BLUE;
+
+ return TRUE;
+ }
+
+ /* Allocate a bitmap header and color table */
+ pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
+ + 256 * sizeof (RGBQUAD));
+ if (pbmih == NULL)
+ {
+ ErrorF ("winQueryRGBBitsAndMasks - malloc failed\n");
+ return FALSE;
+ }
+
+ /* Get screen description */
+ if (winQueryScreenDIBFormat (pScreen, pbmih))
+ {
+ /* Get a pointer to bitfields */
+ pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
+
+#if CYGDEBUG
+ winDebug ("%s - Masks: %08x %08x %08x\n", __FUNCTION__,
+ pdw[0], pdw[1], pdw[2]);
+ winDebug ("%s - Bitmap: %dx%d %d bpp %d planes\n", __FUNCTION__,
+ pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount, pbmih->biPlanes);
+ winDebug ("%s - Compression: %d %s\n", __FUNCTION__,
+ pbmih->biCompression,
+ (pbmih->biCompression == BI_RGB?"(BI_RGB)":
+ (pbmih->biCompression == BI_RLE8?"(BI_RLE8)":
+ (pbmih->biCompression == BI_RLE4?"(BI_RLE4)":
+ (pbmih->biCompression == BI_BITFIELDS?"(BI_BITFIELDS)":""
+ )))));
+#endif
+
+ /* Handle BI_RGB case, which is returned by Wine */
+ if (pbmih->biCompression == BI_RGB)
+ {
+ dwRedBits = 5;
+ dwGreenBits = 5;
+ dwBlueBits = 5;
+
+ pScreenPriv->dwBitsPerRGB = 5;
+
+ /* Set screen privates masks */
+ pScreenPriv->dwRedMask = 0x7c00;
+ pScreenPriv->dwGreenMask = 0x03e0;
+ pScreenPriv->dwBlueMask = 0x001f;
+ }
+ else
+ {
+ /* Count the number of bits in each mask */
+ dwRedBits = winCountBits (pdw[0]);
+ dwGreenBits = winCountBits (pdw[1]);
+ dwBlueBits = winCountBits (pdw[2]);
+
+ /* Find maximum bits per red, green, blue */
+ if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwRedBits;
+ else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
+ pScreenPriv->dwBitsPerRGB = dwGreenBits;
+ else
+ pScreenPriv->dwBitsPerRGB = dwBlueBits;
+
+ /* Set screen privates masks */
+ pScreenPriv->dwRedMask = pdw[0];
+ pScreenPriv->dwGreenMask = pdw[1];
+ pScreenPriv->dwBlueMask = pdw[2];
+ }
+ }
+ else
+ {
+ ErrorF ("winQueryRGBBitsAndMasks - winQueryScreenDIBFormat failed\n");
+ free (pbmih);
+ fReturn = FALSE;
+ }
+
+ /* Free memory */
+ free (pbmih);
+
+ return fReturn;
+}
+
+
+#ifdef XWIN_MULTIWINDOW
+/*
+ * Redraw all ---?
+ */
+
+static wBOOL CALLBACK
+winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam)
+{
+ if (hwnd == (HWND)lParam)
+ return TRUE;
+ InvalidateRect (hwnd, NULL, FALSE);
+ UpdateWindow (hwnd);
+ return TRUE;
+}
+
+static wBOOL CALLBACK
+winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam)
+{
+ BoxPtr pDamage = (BoxPtr)lParam;
+ RECT rcClient, rcDamage, rcRedraw;
+ POINT topLeft, bottomRight;
+
+ if (IsIconic (hwnd))
+ return TRUE; /* Don't care minimized windows */
+
+ /* Convert the damaged area from Screen coords to Client coords */
+ topLeft.x = pDamage->x1; topLeft.y = pDamage->y1;
+ bottomRight.x = pDamage->x2; bottomRight.y = pDamage->y2;
+ topLeft.x += GetSystemMetrics (SM_XVIRTUALSCREEN);
+ bottomRight.x += GetSystemMetrics (SM_XVIRTUALSCREEN);
+ topLeft.y += GetSystemMetrics (SM_YVIRTUALSCREEN);
+ bottomRight.y += GetSystemMetrics (SM_YVIRTUALSCREEN);
+ ScreenToClient (hwnd, &topLeft);
+ ScreenToClient (hwnd, &bottomRight);
+ SetRect (&rcDamage, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
+
+ GetClientRect (hwnd, &rcClient);
+
+ if (IntersectRect (&rcRedraw, &rcClient, &rcDamage))
+ {
+ InvalidateRect (hwnd, &rcRedraw, FALSE);
+ UpdateWindow (hwnd);
+ }
+ return TRUE;
+}
+#endif
+
+
+/*
+ * Allocate a DIB for the shadow framebuffer GDI server
+ */
+
+static Bool
+winAllocateFBShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ DIBSECTION dibsection;
+ Bool fReturn = TRUE;
+
+ /* Describe shadow bitmap to be created */
+ pScreenPriv->pbmih->biWidth = pScreenInfo->dwWidth;
+ pScreenPriv->pbmih->biHeight = -pScreenInfo->dwHeight;
+
+ ErrorF ("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d "
+ "depth: %d\n",
+ (int) pScreenPriv->pbmih->biWidth, (int) -pScreenPriv->pbmih->biHeight, pScreenPriv->pbmih->biBitCount);
+
+ /* Create a DI shadow bitmap with a bit pointer */
+ pScreenPriv->hbmpShadow = CreateDIBSection (pScreenPriv->hdcScreen,
+ (BITMAPINFO *) pScreenPriv->pbmih,
+ DIB_RGB_COLORS,
+ (VOID**) &pScreenInfo->pfb,
+ NULL,
+ 0);
+ if (pScreenPriv->hbmpShadow == NULL || pScreenInfo->pfb == NULL)
+ {
+ winW32Error (2, "winAllocateFBShadowGDI - CreateDIBSection failed:");
+ return FALSE;
+ }
+ else
+ {
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowGDI - Shadow buffer allocated\n");
+#endif
+ }
+
+ /* Get information about the bitmap that was allocated */
+ GetObject (pScreenPriv->hbmpShadow,
+ sizeof (dibsection),
+ &dibsection);
+
+#if CYGDEBUG || YES
+ /* Print information about bitmap allocated */
+ winDebug ("winAllocateFBShadowGDI - Dibsection width: %d height: %d "
+ "depth: %d size image: %d\n",
+ (int) dibsection.dsBmih.biWidth, (int) dibsection.dsBmih.biHeight,
+ dibsection.dsBmih.biBitCount,
+ (int) dibsection.dsBmih.biSizeImage);
+#endif
+
+ /* Select the shadow bitmap into the shadow DC */
+ SelectObject (pScreenPriv->hdcShadow,
+ pScreenPriv->hbmpShadow);
+
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowGDI - Attempting a shadow blit\n");
+#endif
+
+ /* Do a test blit from the shadow to the screen, I think */
+ fReturn = BitBlt (pScreenPriv->hdcScreen,
+ 0, 0,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ pScreenPriv->hdcShadow,
+ 0, 0,
+ SRCCOPY);
+ if (fReturn)
+ {
+#if CYGDEBUG
+ winDebug ("winAllocateFBShadowGDI - Shadow blit success\n");
+#endif
+ }
+ else
+ {
+ winW32Error (2, "winAllocateFBShadowGDI - Shadow blit failure\n");
+#if 0
+ return FALSE;
+#else
+ /* ago: ignore this error. The blit fails with wine, but does not
+ * cause any problems later. */
+
+ fReturn = TRUE;
+#endif
+ }
+
+ /* Look for height weirdness */
+ if (dibsection.dsBmih.biHeight < 0)
+ {
+ dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
+ }
+
+ /* Set screeninfo stride */
+ pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage
+ / dibsection.dsBmih.biHeight)
+ * 8) / pScreenInfo->dwBPP;
+
+#if CYGDEBUG || YES
+ winDebug ("winAllocateFBShadowGDI - Created shadow stride: %d\n",
+ (int) pScreenInfo->dwStride);
+#endif
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
+#endif
+
+ return fReturn;
+}
+
+static void
+winFreeFBShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Free the shadow bitmap */
+ DeleteObject (pScreenPriv->hbmpShadow);
+
+ /* Invalidate the ScreenInfo's fb pointer */
+ pScreenInfo->pfb = NULL;
+}
+
+/*
+ * Blit the damaged regions of the shadow fb to the screen
+ */
+
+static void
+winShadowUpdateGDI (ScreenPtr pScreen,
+ shadowBufPtr pBuf)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ RegionPtr damage = shadowDamage(pBuf);
+ DWORD dwBox = RegionNumRects (damage);
+ BoxPtr pBox = RegionRects (damage);
+ int x, y, w, h;
+ HRGN hrgnTemp = NULL, hrgnCombined = NULL;
+#ifdef XWIN_UPDATESTATS
+ static DWORD s_dwNonUnitRegions = 0;
+ static DWORD s_dwTotalUpdates = 0;
+ static DWORD s_dwTotalBoxes = 0;
+#endif
+ BoxPtr pBoxExtents = RegionExtents(damage);
+
+ /*
+ * Return immediately if the app is not active
+ * and we are fullscreen, or if we have a bad display depth
+ */
+ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
+ || pScreenPriv->fBadDepth) return;
+
+#ifdef XWIN_UPDATESTATS
+ ++s_dwTotalUpdates;
+ s_dwTotalBoxes += dwBox;
+
+ if (dwBox != 1)
+ {
+ ++s_dwNonUnitRegions;
+ ErrorF ("winShadowUpdatGDI - dwBox: %d\n", dwBox);
+ }
+
+ if ((s_dwTotalUpdates % 100) == 0)
+ ErrorF ("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d "
+ "nu: %d tu: %d\n",
+ (s_dwNonUnitRegions * 100) / s_dwTotalUpdates,
+ s_dwTotalBoxes / s_dwTotalUpdates,
+ s_dwNonUnitRegions, s_dwTotalUpdates);
+#endif /* XWIN_UPDATESTATS */
+
+ /*
+ * Handle small regions with multiple blits,
+ * handle large regions by creating a clipping region and
+ * doing a single blit constrained to that clipping region.
+ */
+ if (!pScreenInfo->fMultiWindow &&
+ (pScreenInfo->dwClipUpdatesNBoxes == 0 ||
+ dwBox < pScreenInfo->dwClipUpdatesNBoxes))
+ {
+ /* Loop through all boxes in the damaged region */
+ while (dwBox--)
+ {
+ /*
+ * Calculate x offset, y offset, width, and height for
+ * current damage box
+ */
+ x = pBox->x1;
+ y = pBox->y1;
+ w = pBox->x2 - pBox->x1;
+ h = pBox->y2 - pBox->y1;
+
+ BitBlt (pScreenPriv->hdcScreen,
+ x, y,
+ w, h,
+ pScreenPriv->hdcShadow,
+ x, y,
+ SRCCOPY);
+
+ /* Get a pointer to the next box */
+ ++pBox;
+ }
+ }
+ else if (!pScreenInfo->fMultiWindow)
+ {
+ /* Compute a GDI region from the damaged region */
+ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ dwBox--;
+ pBox++;
+ while (dwBox--)
+ {
+ hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
+ DeleteObject (hrgnTemp);
+ pBox++;
+ }
+
+ /* Install the GDI region as a clipping region */
+ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
+ DeleteObject (hrgnCombined);
+ hrgnCombined = NULL;
+
+ /*
+ * Blit the shadow buffer to the screen,
+ * constrained to the clipping region.
+ */
+ BitBlt (pScreenPriv->hdcScreen,
+ pBoxExtents->x1, pBoxExtents->y1,
+ pBoxExtents->x2 - pBoxExtents->x1,
+ pBoxExtents->y2 - pBoxExtents->y1,
+ pScreenPriv->hdcShadow,
+ pBoxExtents->x1, pBoxExtents->y1,
+ SRCCOPY);
+
+ /* Reset the clip region */
+ SelectClipRgn (pScreenPriv->hdcScreen, NULL);
+ }
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all multiwindow windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows (g_dwCurrentThreadID,
+ winRedrawDamagedWindowShadowGDI,
+ (LPARAM)pBoxExtents);
+#endif
+}
+
+
+static Bool
+winInitScreenShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+
+ /* Get device contexts for the screen and shadow bitmap */
+ pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
+ pScreenPriv->hdcShadow = CreateCompatibleDC (pScreenPriv->hdcScreen);
+
+ /* Allocate bitmap info header */
+ pScreenPriv->pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
+ + 256 * sizeof (RGBQUAD));
+ if (pScreenPriv->pbmih == NULL)
+ {
+ ErrorF ("winInitScreenShadowGDI - malloc () failed\n");
+ return FALSE;
+ }
+
+ /* Query the screen format */
+ if (!winQueryScreenDIBFormat (pScreen, pScreenPriv->pbmih))
+ {
+ ErrorF ("winInitScreenShadowGDI - winQueryScreenDIBFormat failed\n");
+ return FALSE;
+ }
+
+ /* Determine our color masks */
+ if (!winQueryRGBBitsAndMasks (pScreen))
+ {
+ ErrorF ("winInitScreenShadowGDI - winQueryRGBBitsAndMasks failed\n");
+ return FALSE;
+ }
+
+ return winAllocateFBShadowGDI(pScreen);
+}
+
+/* See Porting Layer Definition - p. 33 */
+/*
+ * We wrap whatever CloseScreen procedure was specified by fb;
+ * a pointer to said procedure is stored in our privates.
+ */
+
+static Bool
+winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ Bool fReturn;
+
+#if CYGDEBUG
+ winDebug ("winCloseScreenShadowGDI - Freeing screen resources\n");
+#endif
+
+ /* Flag that the screen is closed */
+ pScreenPriv->fClosed = TRUE;
+ pScreenPriv->fActive = FALSE;
+
+ /* Call the wrapped CloseScreen procedure */
+ WIN_UNWRAP(CloseScreen);
+ fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
+
+ /* Delete the window property */
+ RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
+
+ /* Free the shadow DC; which allows the bitmap to be freed */
+ DeleteDC (pScreenPriv->hdcShadow);
+
+ winFreeFBShadowGDI(pScreen);
+
+ /* Free the screen DC */
+ ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
+
+ /* Delete tray icon, if we have one */
+ if (!pScreenInfo->fNoTrayIcon)
+ winDeleteNotifyIcon (pScreenPriv);
+
+ /* Free the exit confirmation dialog box, if it exists */
+ if (g_hDlgExit != NULL)
+ {
+ DestroyWindow (g_hDlgExit);
+ g_hDlgExit = NULL;
+ }
+
+ /* Kill our window */
+ if (pScreenPriv->hwndScreen)
+ {
+ DestroyWindow (pScreenPriv->hwndScreen);
+ pScreenPriv->hwndScreen = NULL;
+ }
+
+#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
+ /* Destroy the thread startup mutex */
+ pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
+#endif
+
+ /* Invalidate our screeninfo's pointer to the screen */
+ pScreenInfo->pScreen = NULL;
+
+ /* Free the screen privates for this screen */
+ free ((pointer) pScreenPriv);
+
+ return fReturn;
+}
+
+
+/*
+ * Tell mi what sort of visuals we need.
+ *
+ * Generally we only need one visual, as our screen can only
+ * handle one format at a time, I believe. You may want
+ * to verify that last sentence.
+ */
+
+static Bool
+winInitVisualsShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Display debugging information */
+ ErrorF ("winInitVisualsShadowGDI - Masks %08x %08x %08x BPRGB %d d %d "
+ "bpp %d\n",
+ (unsigned int) pScreenPriv->dwRedMask,
+ (unsigned int) pScreenPriv->dwGreenMask,
+ (unsigned int) pScreenPriv->dwBlueMask,
+ (int) pScreenPriv->dwBitsPerRGB,
+ (int) pScreenInfo->dwDepth,
+ (int) pScreenInfo->dwBPP);
+
+ /* Create a single visual according to the Windows screen depth */
+ switch (pScreenInfo->dwDepth)
+ {
+ case 24:
+ case 16:
+ case 15:
+ /* Setup the real visual */
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ TrueColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ -1,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
+ "failed\n");
+ return FALSE;
+ }
+
+#ifdef XWIN_EMULATEPSEUDO
+ if (!pScreenInfo->fEmulatePseudo)
+ break;
+
+ /* Setup a pseudocolor visual */
+ if (!miSetVisualTypesAndMasks (8,
+ PseudoColorMask,
+ 8,
+ -1,
+ 0,
+ 0,
+ 0))
+ {
+ ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
+ "failed for PseudoColor\n");
+ return FALSE;
+ }
+#endif
+ break;
+
+ case 8:
+ if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
+ PseudoColorMask,
+ pScreenPriv->dwBitsPerRGB,
+ PseudoColor,
+ pScreenPriv->dwRedMask,
+ pScreenPriv->dwGreenMask,
+ pScreenPriv->dwBlueMask))
+ {
+ ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
+ "failed\n");
+ return FALSE;
+ }
+ break;
+
+ default:
+ ErrorF ("winInitVisualsShadowGDI - Unknown screen depth\n");
+ return FALSE;
+ }
+
+#if CYGDEBUG
+ winDebug ("winInitVisualsShadowGDI - Returning\n");
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Adjust the proposed video mode
+ */
+
+static Bool
+winAdjustVideoModeShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ HDC hdc;
+ DWORD dwBPP;
+
+ hdc = GetDC (NULL);
+
+ /* We're in serious trouble if we can't get a DC */
+ if (hdc == NULL)
+ {
+ ErrorF ("winAdjustVideoModeShadowGDI - GetDC () failed\n");
+ return FALSE;
+ }
+
+ /* Query GDI for current display depth */
+ dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
+
+ /* GDI cannot change the screen depth, so always use GDI's depth */
+ pScreenInfo->dwBPP = dwBPP;
+
+ /* Release our DC */
+ ReleaseDC (NULL, hdc);
+ hdc = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * Blt exposed regions to the screen
+ */
+
+static Bool
+winBltExposedRegionsShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ winPrivCmapPtr pCmapPriv = NULL;
+ HDC hdcUpdate;
+ PAINTSTRUCT ps;
+
+ /* BeginPaint gives us an hdc that clips to the invalidated region */
+ hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
+
+ /* Realize the palette, if we have one */
+ if (pScreenPriv->pcmapInstalled != NULL)
+ {
+ pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled);
+
+ SelectPalette (hdcUpdate, pCmapPriv->hPalette, FALSE);
+ RealizePalette (hdcUpdate);
+ }
+
+ /* Our BitBlt will be clipped to the invalidated region */
+ BitBlt (hdcUpdate,
+ 0, 0,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ pScreenPriv->hdcShadow,
+ 0, 0,
+ SRCCOPY);
+
+ /* EndPaint frees the DC */
+ EndPaint (pScreenPriv->hwndScreen, &ps);
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI,
+ (LPARAM)pScreenPriv->hwndScreen);
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Do any engine-specific appliation-activation processing
+ */
+
+static Bool
+winActivateAppShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /*
+ * 2004/04/12 - Harold - We perform the restoring or minimizing
+ * manually for ShadowGDI in fullscreen modes so that this engine
+ * will perform just like ShadowDD and ShadowDDNL in fullscreen mode;
+ * if we do not do this then our fullscreen window will appear in the
+ * z-order when it is deactivated and it can be uncovered by resizing
+ * or minimizing another window that is on top of it, which is not how
+ * the DirectDraw engines work. Therefore we keep this code here to
+ * make sure that all engines work the same in fullscreen mode.
+ */
+
+ /*
+ * Are we active?
+ * Are we fullscreen?
+ */
+ if (pScreenPriv->fActive
+ && pScreenInfo->fFullScreen)
+ {
+ /*
+ * Activating, attempt to bring our window
+ * to the top of the display
+ */
+ ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE);
+ }
+ else if (!pScreenPriv->fActive
+ && pScreenInfo->fFullScreen)
+ {
+ /*
+ * Deactivating, stuff our window onto the
+ * task bar.
+ */
+ ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Reblit the shadow framebuffer to the screen.
+ */
+
+static Bool
+winRedrawScreenShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Redraw the whole window, to take account for the new colors */
+ BitBlt (pScreenPriv->hdcScreen,
+ 0, 0,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ pScreenPriv->hdcShadow,
+ 0, 0,
+ SRCCOPY);
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
+#endif
+
+ return TRUE;
+}
+
+
+
+/*
+ * Realize the currently installed colormap
+ */
+
+static Bool
+winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winPrivCmapPtr pCmapPriv = NULL;
+
+#if CYGDEBUG
+ winDebug ("winRealizeInstalledPaletteShadowGDI\n");
+#endif
+
+ /* Don't do anything if there is not a colormap */
+ if (pScreenPriv->pcmapInstalled == NULL)
+ {
+#if CYGDEBUG
+ winDebug ("winRealizeInstalledPaletteShadowGDI - No colormap "
+ "installed\n");
+#endif
+ return TRUE;
+ }
+
+ pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled);
+
+ /* Realize our palette for the screen */
+ if (RealizePalette (pScreenPriv->hdcScreen) == GDI_ERROR)
+ {
+ ErrorF ("winRealizeInstalledPaletteShadowGDI - RealizePalette () "
+ "failed\n");
+ return FALSE;
+ }
+
+ /* Set the DIB color table */
+ if (SetDIBColorTable (pScreenPriv->hdcShadow,
+ 0,
+ WIN_NUM_PALETTE_ENTRIES,
+ pCmapPriv->rgbColors) == 0)
+ {
+ ErrorF ("winRealizeInstalledPaletteShadowGDI - SetDIBColorTable () "
+ "failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Install the specified colormap
+ */
+
+static Bool
+winInstallColormapShadowGDI (ColormapPtr pColormap)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+ winCmapPriv(pColormap);
+
+ /*
+ * Tell Windows to install the new colormap
+ */
+ if (SelectPalette (pScreenPriv->hdcScreen,
+ pCmapPriv->hPalette,
+ FALSE) == NULL)
+ {
+ ErrorF ("winInstallColormapShadowGDI - SelectPalette () failed\n");
+ return FALSE;
+ }
+
+ /* Realize the palette */
+ if (GDI_ERROR == RealizePalette (pScreenPriv->hdcScreen))
+ {
+ ErrorF ("winInstallColormapShadowGDI - RealizePalette () failed\n");
+ return FALSE;
+ }
+
+ /* Set the DIB color table */
+ if (SetDIBColorTable (pScreenPriv->hdcShadow,
+ 0,
+ WIN_NUM_PALETTE_ENTRIES,
+ pCmapPriv->rgbColors) == 0)
+ {
+ ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
+ return FALSE;
+ }
+
+ /* Redraw the whole window, to take account for the new colors */
+ BitBlt (pScreenPriv->hdcScreen,
+ 0, 0,
+ pScreenInfo->dwWidth, pScreenInfo->dwHeight,
+ pScreenPriv->hdcShadow,
+ 0, 0,
+ SRCCOPY);
+
+ /* Save a pointer to the newly installed colormap */
+ pScreenPriv->pcmapInstalled = pColormap;
+
+#ifdef XWIN_MULTIWINDOW
+ /* Redraw all windows */
+ if (pScreenInfo->fMultiWindow)
+ EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Store the specified colors in the specified colormap
+ */
+
+static Bool
+winStoreColorsShadowGDI (ColormapPtr pColormap,
+ int ndef,
+ xColorItem *pdefs)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ winScreenPriv(pScreen);
+ winCmapPriv(pColormap);
+ ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
+
+ /* Put the X colormap entries into the Windows logical palette */
+ if (SetPaletteEntries (pCmapPriv->hPalette,
+ pdefs[0].pixel,
+ ndef,
+ pCmapPriv->peColors + pdefs[0].pixel) == 0)
+ {
+ ErrorF ("winStoreColorsShadowGDI - SetPaletteEntries () failed\n");
+ return FALSE;
+ }
+
+ /* Don't install the Windows palette if the colormap is not installed */
+ if (pColormap != curpmap)
+ {
+ return TRUE;
+ }
+
+ /* Try to install the newly modified colormap */
+ if (!winInstallColormapShadowGDI (pColormap))
+ {
+ ErrorF ("winInstallColormapShadowGDI - winInstallColormapShadowGDI "
+ "failed\n");
+ return FALSE;
+ }
+
+#if 0
+ /* Tell Windows that the palette has changed */
+ RealizePalette (pScreenPriv->hdcScreen);
+
+ /* Set the DIB color table */
+ if (SetDIBColorTable (pScreenPriv->hdcShadow,
+ pdefs[0].pixel,
+ ndef,
+ pCmapPriv->rgbColors + pdefs[0].pixel) == 0)
+ {
+ ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
+ return FALSE;
+ }
+
+ /* Save a pointer to the newly installed colormap */
+ pScreenPriv->pcmapInstalled = pColormap;
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap initialization procedure
+ */
+
+static Bool
+winCreateColormapShadowGDI (ColormapPtr pColormap)
+{
+ LPLOGPALETTE lpPaletteNew = NULL;
+ DWORD dwEntriesMax;
+ VisualPtr pVisual;
+ HPALETTE hpalNew = NULL;
+ winCmapPriv(pColormap);
+
+ /* Get a pointer to the visual that the colormap belongs to */
+ pVisual = pColormap->pVisual;
+
+ /* Get the maximum number of palette entries for this visual */
+ dwEntriesMax = pVisual->ColormapEntries;
+
+ /* Allocate a Windows logical color palette with max entries */
+ lpPaletteNew = malloc (sizeof (LOGPALETTE)
+ + (dwEntriesMax - 1) * sizeof (PALETTEENTRY));
+ if (lpPaletteNew == NULL)
+ {
+ ErrorF ("winCreateColormapShadowGDI - Couldn't allocate palette "
+ "with %d entries\n",
+ (int) dwEntriesMax);
+ return FALSE;
+ }
+
+ /* Zero out the colormap */
+ ZeroMemory (lpPaletteNew, sizeof (LOGPALETTE)
+ + (dwEntriesMax - 1) * sizeof (PALETTEENTRY));
+
+ /* Set the logical palette structure */
+ lpPaletteNew->palVersion = 0x0300;
+ lpPaletteNew->palNumEntries = dwEntriesMax;
+
+ /* Tell Windows to create the palette */
+ hpalNew = CreatePalette (lpPaletteNew);
+ if (hpalNew == NULL)
+ {
+ ErrorF ("winCreateColormapShadowGDI - CreatePalette () failed\n");
+ free (lpPaletteNew);
+ return FALSE;
+ }
+
+ /* Save the Windows logical palette handle in the X colormaps' privates */
+ pCmapPriv->hPalette = hpalNew;
+
+ /* Free the palette initialization memory */
+ free (lpPaletteNew);
+
+ return TRUE;
+}
+
+
+/*
+ * Colormap destruction procedure
+ */
+
+static Bool
+winDestroyColormapShadowGDI (ColormapPtr pColormap)
+{
+ winScreenPriv(pColormap->pScreen);
+ winCmapPriv(pColormap);
+
+ /*
+ * Is colormap to be destroyed the default?
+ *
+ * Non-default colormaps should have had winUninstallColormap
+ * called on them before we get here. The default colormap
+ * will not have had winUninstallColormap called on it. Thus,
+ * we need to handle the default colormap in a special way.
+ */
+ if (pColormap->flags & IsDefault)
+ {
+#if CYGDEBUG
+ winDebug ("winDestroyColormapShadowGDI - Destroying default "
+ "colormap\n");
+#endif
+
+ /*
+ * FIXME: Walk the list of all screens, popping the default
+ * palette out of each screen device context.
+ */
+
+ /* Pop the palette out of the device context */
+ SelectPalette (pScreenPriv->hdcScreen,
+ GetStockObject (DEFAULT_PALETTE),
+ FALSE);
+
+ /* Clear our private installed colormap pointer */
+ pScreenPriv->pcmapInstalled = NULL;
+ }
+
+ /* Try to delete the logical palette */
+ if (DeleteObject (pCmapPriv->hPalette) == 0)
+ {
+ ErrorF ("winDestroyColormap - DeleteObject () failed\n");
+ return FALSE;
+ }
+
+ /* Invalidate the colormap privates */
+ pCmapPriv->hPalette = NULL;
+
+ return TRUE;
+}
+
+
+/*
+ * Set engine specific funtions
+ */
+
+Bool
+winSetEngineFunctionsShadowGDI (ScreenPtr pScreen)
+{
+ winScreenPriv(pScreen);
+ winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
+
+ /* Set our pointers */
+ pScreenPriv->pwinAllocateFB = winAllocateFBShadowGDI;
+ pScreenPriv->pwinFreeFB = winFreeFBShadowGDI;
+ pScreenPriv->pwinShadowUpdate = winShadowUpdateGDI;
+ pScreenPriv->pwinInitScreen = winInitScreenShadowGDI;
+ pScreenPriv->pwinCloseScreen = winCloseScreenShadowGDI;
+ pScreenPriv->pwinInitVisuals = winInitVisualsShadowGDI;
+ pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowGDI;
+ if (pScreenInfo->fFullScreen)
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
+ else
+ pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
+ pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
+ pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI;
+ pScreenPriv->pwinActivateApp = winActivateAppShadowGDI;
+ pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI;
+ pScreenPriv->pwinRealizeInstalledPalette =
+ winRealizeInstalledPaletteShadowGDI;
+ pScreenPriv->pwinInstallColormap = winInstallColormapShadowGDI;
+ pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI;
+ pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI;
+ pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI;
+ pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinCreatePrimarySurface
+ = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
+ pScreenPriv->pwinReleasePrimarySurface
+ = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
+#ifdef XWIN_MULTIWINDOW
+ pScreenPriv->pwinFinishCreateWindowsWindow =
+ (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
+#endif
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winvalargs.c b/xorg-server/hw/xwin/winvalargs.c
index f97bce610..04db777b0 100644
--- a/xorg-server/hw/xwin/winvalargs.c
+++ b/xorg-server/hw/xwin/winvalargs.c
@@ -1,180 +1,180 @@
-/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II 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 Harold L Hunt II
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from Harold L Hunt II.
- *
- * Authors: Harold L Hunt II
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include "winmsg.h"
-
-
-
-
-/*
- * Verify all screens have been explicitly specified
- */
-static BOOL
-isEveryScreenExplicit(void)
-{
- int i;
-
- for (i = 0; i < g_iNumScreens; i++)
- if (!g_ScreenInfo[i].fExplicitScreen)
- return FALSE;
-
- return TRUE;
-}
-
-/*
- * winValidateArgs - Look for invalid argument combinations
- */
-
-Bool
-winValidateArgs (void)
-{
- int i;
- int iMaxConsecutiveScreen = 0;
- BOOL fHasNormalScreen0 = FALSE;
- BOOL fImplicitScreenFound = FALSE;
-
- /*
- * Check for a malformed set of -screen parameters.
- * Examples of malformed parameters:
- * XWin -screen 1
- * XWin -screen 0 -screen 2
- * XWin -screen 1 -screen 2
- */
- if (!isEveryScreenExplicit())
- {
- ErrorF ("winValidateArgs - Malformed set of screen parameter(s). "
- "Screens must be specified consecutively starting with "
- "screen 0. That is, you cannot have only a screen 1, nor "
- "could you have screen 0 and screen 2. You instead must "
- "have screen 0, or screen 0 and screen 1, respectively. "
- "You can specify as many screens as you want.\n");
- return FALSE;
- }
-
- /* Loop through all screens */
- for (i = 0; i < g_iNumScreens; ++i)
- {
- /*
- * Check for any combination of
- * -multiwindow, -mwextwm, and -rootless.
- */
- {
- int iCount = 0;
-
- /* Count conflicting options */
-#ifdef XWIN_MULTIWINDOW
- if (g_ScreenInfo[i].fMultiWindow)
- ++iCount;
-#endif
-#ifdef XWIN_MULTIWINDOWEXTWM
- if (g_ScreenInfo[i].fMWExtWM)
- ++iCount;
-#endif
- if (g_ScreenInfo[i].fRootless)
- ++iCount;
-
- /* Check if the first screen is without rootless and multiwindow */
- if (iCount == 0 && i == 0)
- fHasNormalScreen0 = TRUE;
-
- /* Fail if two or more conflicting options */
- if (iCount > 1)
- {
- ErrorF ("winValidateArgs - Only one of -multiwindow, -mwextwm, "
- "and -rootless can be specific at a time.\n");
- return FALSE;
- }
- }
-
- /* Check for -multiwindow or -mwextwm and Xdmcp */
- /* allow xdmcp if screen 0 is normal. */
- if (g_fXdmcpEnabled && !fHasNormalScreen0
- && (FALSE
-#ifdef XWIN_MULTIWINDOW
- || g_ScreenInfo[i].fMultiWindow
-#endif
-#ifdef XWIN_MULTIWINDOWEXTWM
- || g_ScreenInfo[i].fMWExtWM
-#endif
- )
- )
- {
- ErrorF ("winValidateArgs - Xdmcp (-query, -broadcast, or -indirect) "
- "is invalid with -multiwindow or -mwextwm.\n");
- return FALSE;
- }
-
- /* Check for -multiwindow, -mwextwm, or -rootless and fullscreen */
- if (g_ScreenInfo[i].fFullScreen
- && (FALSE
-#ifdef XWIN_MULTIWINDOW
- || g_ScreenInfo[i].fMultiWindow
-#endif
-#ifdef XWIN_MULTIWINDOWEXTWM
- || g_ScreenInfo[i].fMWExtWM
-#endif
- || g_ScreenInfo[i].fRootless)
- )
- {
- ErrorF ("winValidateArgs - -fullscreen is invalid with "
- "-multiwindow, -mwextwm, or -rootless.\n");
- return FALSE;
- }
-
- /* Check for !fullscreen and any fullscreen-only parameters */
- if (!g_ScreenInfo[i].fFullScreen
- && (g_ScreenInfo[i].dwRefreshRate != WIN_DEFAULT_BPP
- || g_ScreenInfo[i].dwBPP != WIN_DEFAULT_REFRESH))
- {
- ErrorF ("winValidateArgs - -refresh and -depth are only valid "
- "with -fullscreen.\n");
- return FALSE;
- }
-
- /* Check for fullscreen and any non-fullscreen parameters */
- if (g_ScreenInfo[i].fFullScreen
- && (g_ScreenInfo[i].fScrollbars
- || !g_ScreenInfo[i].fDecoration
- || g_ScreenInfo[i].fLessPointer))
- {
- ErrorF ("winValidateArgs - -fullscreen is invalid with "
- "-scrollbars, -nodecoration, or -lesspointer.\n");
- return FALSE;
- }
- }
-
- winDebug ("winValidateArgs - Returning.\n");
-
- return TRUE;
-}
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II 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 Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include "winmsg.h"
+
+
+
+
+/*
+ * Verify all screens have been explicitly specified
+ */
+static BOOL
+isEveryScreenExplicit(void)
+{
+ int i;
+
+ for (i = 0; i < g_iNumScreens; i++)
+ if (!g_ScreenInfo[i].fExplicitScreen)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * winValidateArgs - Look for invalid argument combinations
+ */
+
+Bool
+winValidateArgs (void)
+{
+ int i;
+ int iMaxConsecutiveScreen = 0;
+ BOOL fHasNormalScreen0 = FALSE;
+ BOOL fImplicitScreenFound = FALSE;
+
+ /*
+ * Check for a malformed set of -screen parameters.
+ * Examples of malformed parameters:
+ * XWin -screen 1
+ * XWin -screen 0 -screen 2
+ * XWin -screen 1 -screen 2
+ */
+ if (!isEveryScreenExplicit())
+ {
+ ErrorF ("winValidateArgs - Malformed set of screen parameter(s). "
+ "Screens must be specified consecutively starting with "
+ "screen 0. That is, you cannot have only a screen 1, nor "
+ "could you have screen 0 and screen 2. You instead must "
+ "have screen 0, or screen 0 and screen 1, respectively. "
+ "You can specify as many screens as you want.\n");
+ return FALSE;
+ }
+
+ /* Loop through all screens */
+ for (i = 0; i < g_iNumScreens; ++i)
+ {
+ /*
+ * Check for any combination of
+ * -multiwindow, -mwextwm, and -rootless.
+ */
+ {
+ int iCount = 0;
+
+ /* Count conflicting options */
+#ifdef XWIN_MULTIWINDOW
+ if (g_ScreenInfo[i].fMultiWindow)
+ ++iCount;
+#endif
+#ifdef XWIN_MULTIWINDOWEXTWM
+ if (g_ScreenInfo[i].fMWExtWM)
+ ++iCount;
+#endif
+ if (g_ScreenInfo[i].fRootless)
+ ++iCount;
+
+ /* Check if the first screen is without rootless and multiwindow */
+ if (iCount == 0 && i == 0)
+ fHasNormalScreen0 = TRUE;
+
+ /* Fail if two or more conflicting options */
+ if (iCount > 1)
+ {
+ ErrorF ("winValidateArgs - Only one of -multiwindow, -mwextwm, "
+ "and -rootless can be specific at a time.\n");
+ return FALSE;
+ }
+ }
+
+ /* Check for -multiwindow or -mwextwm and Xdmcp */
+ /* allow xdmcp if screen 0 is normal. */
+ if (g_fXdmcpEnabled && !fHasNormalScreen0
+ && (FALSE
+#ifdef XWIN_MULTIWINDOW
+ || g_ScreenInfo[i].fMultiWindow
+#endif
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || g_ScreenInfo[i].fMWExtWM
+#endif
+ )
+ )
+ {
+ ErrorF ("winValidateArgs - Xdmcp (-query, -broadcast, or -indirect) "
+ "is invalid with -multiwindow or -mwextwm.\n");
+ return FALSE;
+ }
+
+ /* Check for -multiwindow, -mwextwm, or -rootless and fullscreen */
+ if (g_ScreenInfo[i].fFullScreen
+ && (FALSE
+#ifdef XWIN_MULTIWINDOW
+ || g_ScreenInfo[i].fMultiWindow
+#endif
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || g_ScreenInfo[i].fMWExtWM
+#endif
+ || g_ScreenInfo[i].fRootless)
+ )
+ {
+ ErrorF ("winValidateArgs - -fullscreen is invalid with "
+ "-multiwindow, -mwextwm, or -rootless.\n");
+ return FALSE;
+ }
+
+ /* Check for !fullscreen and any fullscreen-only parameters */
+ if (!g_ScreenInfo[i].fFullScreen
+ && (g_ScreenInfo[i].dwRefreshRate != WIN_DEFAULT_REFRESH
+ || g_ScreenInfo[i].dwBPP != WIN_DEFAULT_BPP))
+ {
+ ErrorF ("winValidateArgs - -refresh and -depth are only valid "
+ "with -fullscreen.\n");
+ return FALSE;
+ }
+
+ /* Check for fullscreen and any non-fullscreen parameters */
+ if (g_ScreenInfo[i].fFullScreen
+ && ((g_ScreenInfo[i].iResizeMode != notAllowed)
+ || !g_ScreenInfo[i].fDecoration
+ || g_ScreenInfo[i].fLessPointer))
+ {
+ ErrorF ("winValidateArgs - -fullscreen is invalid with "
+ "-scrollbars, -resize, -nodecoration, or -lesspointer.\n");
+ return FALSE;
+ }
+ }
+
+ winDebug ("winValidateArgs - Returning.\n");
+
+ return TRUE;
+}
diff --git a/xorg-server/hw/xwin/winwindow.c b/xorg-server/hw/xwin/winwindow.c
index f6371a65c..7975d71a9 100644
--- a/xorg-server/hw/xwin/winwindow.c
+++ b/xorg-server/hw/xwin/winwindow.c
@@ -1,636 +1,637 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Harold L Hunt II
- * Kensuke Matsuzaki
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-
-
-/*
- * Prototypes for local functions
- */
-
-static int
-winAddRgn (WindowPtr pWindow, pointer data);
-
-static
-void
-winUpdateRgnRootless (WindowPtr pWindow);
-
-static
-void
-winReshapeRootless (WindowPtr pWin);
-
-
-#ifdef XWIN_NATIVEGDI
-/* See Porting Layer Definition - p. 37 */
-/* See mfb/mfbwindow.c - mfbCreateWindow() */
-
-Bool
-winCreateWindowNativeGDI (WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winCreateWindowNativeGDI (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(CreateWindow);
- fResult = (*pScreen->CreateWindow) (pWin);
- WIN_WRAP(CreateWindow, winCreateWindowNativeGDI);
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37 */
-/* See mfb/mfbwindow.c - mfbDestroyWindow() */
-
-Bool
-winDestroyWindowNativeGDI (WindowPtr pWin)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winDestroyWindowNativeGDI (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(DestroyWindow);
- fResult = (*pScreen->DestroyWindow)(pWin);
- WIN_WRAP(DestroyWindow, winDestroyWindowNativeGDI);
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37 */
-/* See mfb/mfbwindow.c - mfbPositionWindow() */
-
-Bool
-winPositionWindowNativeGDI (WindowPtr pWin, int x, int y)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winPositionWindowNativeGDI (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(PositionWindow);
- fResult = (*pScreen->PositionWindow)(pWin, x, y);
- WIN_WRAP(PositionWindow, winPositionWindowNativeGDI);
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 39 */
-/* See mfb/mfbwindow.c - mfbCopyWindow() */
-
-void
-winCopyWindowNativeGDI (WindowPtr pWin,
- DDXPointRec ptOldOrg,
- RegionPtr prgnSrc)
-{
- DDXPointPtr pptSrc;
- DDXPointPtr ppt;
- RegionPtr prgnDst;
- BoxPtr pBox;
- int dx, dy;
- int i, nbox;
- WindowPtr pwinRoot;
- BoxPtr pBoxDst;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if 0
- ErrorF ("winCopyWindow\n");
-#endif
-
- /* Get a pointer to the root window */
- pwinRoot = pWin->drawable.pScreen->root;
-
- /* Create a region for the destination */
- prgnDst = RegionCreate(NULL, 1);
-
- /* Calculate the shift from the source to the destination */
- dx = ptOldOrg.x - pWin->drawable.x;
- dy = ptOldOrg.y - pWin->drawable.y;
-
- /* Translate the region from the destination to the source? */
- RegionTranslate(prgnSrc, -dx, -dy);
- RegionIntersect(prgnDst, &pWin->borderClip,
- prgnSrc);
-
- /* Get a pointer to the first box in the region to be copied */
- pBox = RegionRects(prgnDst);
-
- /* Get the number of boxes in the region */
- nbox = RegionNumRects(prgnDst);
-
- /* Allocate source points for each box */
- if(!(pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec))))
- return;
-
- /* Set an iterator pointer */
- ppt = pptSrc;
-
- /* Calculate the source point of each box? */
- for (i = nbox; --i >= 0; ppt++, pBox++)
- {
- ppt->x = pBox->x1 + dx;
- ppt->y = pBox->y1 + dy;
- }
-
- /* Setup loop pointers again */
- pBoxDst = RegionRects(prgnDst);
- ppt = pptSrc;
-
-#if 0
- ErrorF ("winCopyWindow - x1\tx2\ty1\ty2\tx\ty\n");
-#endif
-
- /* BitBlt each source to the destination point */
- for (i = nbox; --i >= 0; pBoxDst++, ppt++)
- {
-#if 0
- ErrorF ("winCopyWindow - %d\t%d\t%d\t%d\t%d\t%d\n",
- pBoxDst->x1, pBoxDst->x2, pBoxDst->y1, pBoxDst->y2,
- ppt->x, ppt->y);
-#endif
-
- BitBlt (pScreenPriv->hdcScreen,
- pBoxDst->x1, pBoxDst->y1,
- pBoxDst->x2 - pBoxDst->x1, pBoxDst->y2 - pBoxDst->y1,
- pScreenPriv->hdcScreen,
- ppt->x, ppt->y,
- SRCCOPY);
- }
-
- /* Cleanup the regions, etc. */
- free(pptSrc);
- RegionDestroy(prgnDst);
-}
-
-
-/* See Porting Layer Definition - p. 37 */
-/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */
-
-Bool
-winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winChangeWindowAttributesNativeGDI (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(ChangeWindowAttributes);
- fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
- WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesNativeGDI);
-
- /*
- * NOTE: We do not currently need to do anything here.
- */
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37
- * Also referred to as UnrealizeWindow
- */
-
-Bool
-winUnmapWindowNativeGDI (WindowPtr pWin)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winUnmapWindowNativeGDI (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(UnrealizeWindow);
- fResult = (*pScreen->UnrealizeWindow)(pWin);
- WIN_WRAP(UnrealizeWindow, winUnmapWindowNativeGDI);
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37
- * Also referred to as RealizeWindow
- */
-
-Bool
-winMapWindowNativeGDI (WindowPtr pWin)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winMapWindowNativeGDI (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(RealizeWindow);
- fResult = (*pScreen->RealizeWindow)(pWin);
- WIN_WRAP(RealizeWindow, winMapWindowMultiWindow);
-
- return fResult;
-
-}
-#endif
-
-
-/* See Porting Layer Definition - p. 37 */
-/* See mfb/mfbwindow.c - mfbCreateWindow() */
-
-Bool
-winCreateWindowRootless (WindowPtr pWin)
-{
- Bool fResult = FALSE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winCreateWindowRootless (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(CreateWindow);
- fResult = (*pScreen->CreateWindow) (pWin);
- WIN_WRAP(CreateWindow, winCreateWindowRootless);
-
- pWinPriv->hRgn = NULL;
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37 */
-/* See mfb/mfbwindow.c - mfbDestroyWindow() */
-
-Bool
-winDestroyWindowRootless (WindowPtr pWin)
-{
- Bool fResult = FALSE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winDestroyWindowRootless (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(DestroyWindow);
- fResult = (*pScreen->DestroyWindow)(pWin);
- WIN_WRAP(DestroyWindow, winDestroyWindowRootless);
-
- if (pWinPriv->hRgn != NULL)
- {
- DeleteObject(pWinPriv->hRgn);
- pWinPriv->hRgn = NULL;
- }
-
- winUpdateRgnRootless (pWin);
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37 */
-/* See mfb/mfbwindow.c - mfbPositionWindow() */
-
-Bool
-winPositionWindowRootless (WindowPtr pWin, int x, int y)
-{
- Bool fResult = FALSE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-
-#if CYGDEBUG
- winTrace ("winPositionWindowRootless (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(PositionWindow);
- fResult = (*pScreen->PositionWindow)(pWin, x, y);
- WIN_WRAP(PositionWindow, winPositionWindowRootless);
-
- winUpdateRgnRootless (pWin);
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37 */
-/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */
-
-Bool
-winChangeWindowAttributesRootless (WindowPtr pWin, unsigned long mask)
-{
- Bool fResult = FALSE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winChangeWindowAttributesRootless (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(ChangeWindowAttributes);
- fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
- WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesRootless);
-
- winUpdateRgnRootless (pWin);
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37
- * Also referred to as UnrealizeWindow
- */
-
-Bool
-winUnmapWindowRootless (WindowPtr pWin)
-{
- Bool fResult = FALSE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winUnmapWindowRootless (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(UnrealizeWindow);
- fResult = (*pScreen->UnrealizeWindow)(pWin);
- WIN_WRAP(UnrealizeWindow, winUnmapWindowRootless);
-
- if (pWinPriv->hRgn != NULL)
- {
- DeleteObject(pWinPriv->hRgn);
- pWinPriv->hRgn = NULL;
- }
-
- winUpdateRgnRootless (pWin);
-
- return fResult;
-}
-
-
-/* See Porting Layer Definition - p. 37
- * Also referred to as RealizeWindow
- */
-
-Bool
-winMapWindowRootless (WindowPtr pWin)
-{
- Bool fResult = FALSE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winMapWindowRootless (%p)\n", pWin);
-#endif
-
- WIN_UNWRAP(RealizeWindow);
- fResult = (*pScreen->RealizeWindow)(pWin);
- WIN_WRAP(RealizeWindow, winMapWindowRootless);
-
- winReshapeRootless (pWin);
-
- winUpdateRgnRootless (pWin);
-
- return fResult;
-}
-
-
-void
-winSetShapeRootless (WindowPtr pWin, int kind)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGDEBUG
- winTrace ("winSetShapeRootless (%p, %i)\n", pWin, kind);
-#endif
-
- WIN_UNWRAP(SetShape);
- (*pScreen->SetShape)(pWin, kind);
- WIN_WRAP(SetShape, winSetShapeRootless);
-
- winReshapeRootless (pWin);
- winUpdateRgnRootless (pWin);
-
- return;
-}
-
-
-/*
- * Local function for adding a region to the Windows window region
- */
-
-static
-int
-winAddRgn (WindowPtr pWin, pointer data)
-{
- int iX, iY, iWidth, iHeight, iBorder;
- HRGN hRgn = *(HRGN*)data;
- HRGN hRgnWin;
- winWindowPriv(pWin);
-
- /* If pWin is not Root */
- if (pWin->parent != NULL)
- {
-#if CYGDEBUG
- winDebug ("winAddRgn ()\n");
-#endif
- if (pWin->mapped)
- {
- iBorder = wBorderWidth (pWin);
-
- iX = pWin->drawable.x - iBorder;
- iY = pWin->drawable.y - iBorder;
-
- iWidth = pWin->drawable.width + iBorder * 2;
- iHeight = pWin->drawable.height + iBorder * 2;
-
- hRgnWin = CreateRectRgn (0, 0, iWidth, iHeight);
-
- if (hRgnWin == NULL)
- {
- ErrorF ("winAddRgn - CreateRectRgn () failed\n");
- ErrorF (" Rect %d %d %d %d\n",
- iX, iY, iX + iWidth, iY + iHeight);
- }
-
- if (pWinPriv->hRgn)
- {
- if (CombineRgn (hRgnWin, hRgnWin, pWinPriv->hRgn, RGN_AND)
- == ERROR)
- {
- ErrorF ("winAddRgn - CombineRgn () failed\n");
- }
- }
-
- OffsetRgn (hRgnWin, iX, iY);
-
- if (CombineRgn (hRgn, hRgn, hRgnWin, RGN_OR) == ERROR)
- {
- ErrorF ("winAddRgn - CombineRgn () failed\n");
- }
-
- DeleteObject (hRgnWin);
- }
- return WT_DONTWALKCHILDREN;
- }
- else
- {
- return WT_WALKCHILDREN;
- }
-}
-
-
-/*
- * Local function to update the Windows window's region
- */
-
-static
-void
-winUpdateRgnRootless (WindowPtr pWin)
-{
- HRGN hRgn = CreateRectRgn (0, 0, 0, 0);
-
- if (hRgn != NULL)
- {
- WalkTree (pWin->drawable.pScreen, winAddRgn, &hRgn);
- SetWindowRgn (winGetScreenPriv(pWin->drawable.pScreen)->hwndScreen,
- hRgn, TRUE);
- }
- else
- {
- ErrorF ("winUpdateRgnRootless - CreateRectRgn failed.\n");
- }
-}
-
-
-static
-void
-winReshapeRootless (WindowPtr pWin)
-{
- int nRects;
- RegionRec rrNewShape;
- BoxPtr pShape, pRects, pEnd;
- HRGN hRgn, hRgnRect;
- winWindowPriv(pWin);
-
-#if CYGDEBUG
- winDebug ("winReshapeRootless ()\n");
-#endif
-
- /* Bail if the window is the root window */
- if (pWin->parent == NULL)
- return;
-
- /* Bail if the window is not top level */
- if (pWin->parent->parent != NULL)
- return;
-
- /* Free any existing window region stored in the window privates */
- if (pWinPriv->hRgn != NULL)
- {
- DeleteObject (pWinPriv->hRgn);
- pWinPriv->hRgn = NULL;
- }
-
- /* Bail if the window has no bounding region defined */
- if (!wBoundingShape (pWin))
- return;
-
- RegionNull(&rrNewShape);
- RegionCopy(&rrNewShape, wBoundingShape(pWin));
- RegionTranslate(&rrNewShape, pWin->borderWidth,
- pWin->borderWidth);
-
- nRects = RegionNumRects(&rrNewShape);
- pShape = RegionRects(&rrNewShape);
-
- if (nRects > 0)
- {
- /* Create initial empty Windows region */
- hRgn = CreateRectRgn (0, 0, 0, 0);
-
- /* Loop through all rectangles in the X region */
- for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++)
- {
- /* Create a Windows region for the X rectangle */
- hRgnRect = CreateRectRgn (pRects->x1, pRects->y1,
- pRects->x2, pRects->y2);
- if (hRgnRect == NULL)
- {
- ErrorF("winReshapeRootless - CreateRectRgn() failed\n");
- }
-
- /* Merge the Windows region with the accumulated region */
- if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR)
- {
- ErrorF("winReshapeRootless - CombineRgn() failed\n");
- }
-
- /* Delete the temporary Windows region */
- DeleteObject (hRgnRect);
- }
-
- /* Save a handle to the composite region in the window privates */
- pWinPriv->hRgn = hRgn;
- }
-
- RegionUninit(&rrNewShape);
-
- return;
-}
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ * Kensuke Matsuzaki
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+
+
+/*
+ * Prototypes for local functions
+ */
+
+static int
+winAddRgn (WindowPtr pWindow, pointer data);
+
+static
+void
+winUpdateRgnRootless (WindowPtr pWindow);
+
+static
+void
+winReshapeRootless (WindowPtr pWin);
+
+
+#ifdef XWIN_NATIVEGDI
+/* See Porting Layer Definition - p. 37 */
+/* See mfb/mfbwindow.c - mfbCreateWindow() */
+
+Bool
+winCreateWindowNativeGDI (WindowPtr pWin)
+{
+ Bool fResult = TRUE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winCreateWindowNativeGDI (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(CreateWindow);
+ fResult = (*pScreen->CreateWindow) (pWin);
+ WIN_WRAP(CreateWindow, winCreateWindowNativeGDI);
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37 */
+/* See mfb/mfbwindow.c - mfbDestroyWindow() */
+
+Bool
+winDestroyWindowNativeGDI (WindowPtr pWin)
+{
+ Bool fResult = TRUE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winDestroyWindowNativeGDI (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(DestroyWindow);
+ fResult = (*pScreen->DestroyWindow)(pWin);
+ WIN_WRAP(DestroyWindow, winDestroyWindowNativeGDI);
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37 */
+/* See mfb/mfbwindow.c - mfbPositionWindow() */
+
+Bool
+winPositionWindowNativeGDI (WindowPtr pWin, int x, int y)
+{
+ Bool fResult = TRUE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winPositionWindowNativeGDI (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(PositionWindow);
+ fResult = (*pScreen->PositionWindow)(pWin, x, y);
+ WIN_WRAP(PositionWindow, winPositionWindowNativeGDI);
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 39 */
+/* See mfb/mfbwindow.c - mfbCopyWindow() */
+
+void
+winCopyWindowNativeGDI (WindowPtr pWin,
+ DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ DDXPointPtr pptSrc;
+ DDXPointPtr ppt;
+ RegionPtr prgnDst;
+ BoxPtr pBox;
+ int dx, dy;
+ int i, nbox;
+ WindowPtr pwinRoot;
+ BoxPtr pBoxDst;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winScreenPriv(pScreen);
+
+#if 0
+ ErrorF ("winCopyWindow\n");
+#endif
+
+ /* Get a pointer to the root window */
+ pwinRoot = pWin->drawable.pScreen->root;
+
+ /* Create a region for the destination */
+ prgnDst = RegionCreate(NULL, 1);
+
+ /* Calculate the shift from the source to the destination */
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+
+ /* Translate the region from the destination to the source? */
+ RegionTranslate(prgnSrc, -dx, -dy);
+ RegionIntersect(prgnDst, &pWin->borderClip,
+ prgnSrc);
+
+ /* Get a pointer to the first box in the region to be copied */
+ pBox = RegionRects(prgnDst);
+
+ /* Get the number of boxes in the region */
+ nbox = RegionNumRects(prgnDst);
+
+ /* Allocate source points for each box */
+ if(!(pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec))))
+ return;
+
+ /* Set an iterator pointer */
+ ppt = pptSrc;
+
+ /* Calculate the source point of each box? */
+ for (i = nbox; --i >= 0; ppt++, pBox++)
+ {
+ ppt->x = pBox->x1 + dx;
+ ppt->y = pBox->y1 + dy;
+ }
+
+ /* Setup loop pointers again */
+ pBoxDst = RegionRects(prgnDst);
+ ppt = pptSrc;
+
+#if 0
+ ErrorF ("winCopyWindow - x1\tx2\ty1\ty2\tx\ty\n");
+#endif
+
+ /* BitBlt each source to the destination point */
+ for (i = nbox; --i >= 0; pBoxDst++, ppt++)
+ {
+#if 0
+ ErrorF ("winCopyWindow - %d\t%d\t%d\t%d\t%d\t%d\n",
+ pBoxDst->x1, pBoxDst->x2, pBoxDst->y1, pBoxDst->y2,
+ ppt->x, ppt->y);
+#endif
+
+ BitBlt (pScreenPriv->hdcScreen,
+ pBoxDst->x1, pBoxDst->y1,
+ pBoxDst->x2 - pBoxDst->x1, pBoxDst->y2 - pBoxDst->y1,
+ pScreenPriv->hdcScreen,
+ ppt->x, ppt->y,
+ SRCCOPY);
+ }
+
+ /* Cleanup the regions, etc. */
+ free(pptSrc);
+ RegionDestroy(prgnDst);
+}
+
+
+/* See Porting Layer Definition - p. 37 */
+/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */
+
+Bool
+winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask)
+{
+ Bool fResult = TRUE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winChangeWindowAttributesNativeGDI (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(ChangeWindowAttributes);
+ fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
+ WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesNativeGDI);
+
+ /*
+ * NOTE: We do not currently need to do anything here.
+ */
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37
+ * Also referred to as UnrealizeWindow
+ */
+
+Bool
+winUnmapWindowNativeGDI (WindowPtr pWin)
+{
+ Bool fResult = TRUE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winUnmapWindowNativeGDI (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(UnrealizeWindow);
+ fResult = (*pScreen->UnrealizeWindow)(pWin);
+ WIN_WRAP(UnrealizeWindow, winUnmapWindowNativeGDI);
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37
+ * Also referred to as RealizeWindow
+ */
+
+Bool
+winMapWindowNativeGDI (WindowPtr pWin)
+{
+ Bool fResult = TRUE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winMapWindowNativeGDI (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(RealizeWindow);
+ fResult = (*pScreen->RealizeWindow)(pWin);
+ WIN_WRAP(RealizeWindow, winMapWindowMultiWindow);
+
+ return fResult;
+
+}
+#endif
+
+
+/* See Porting Layer Definition - p. 37 */
+/* See mfb/mfbwindow.c - mfbCreateWindow() */
+
+Bool
+winCreateWindowRootless (WindowPtr pWin)
+{
+ Bool fResult = FALSE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winCreateWindowRootless (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(CreateWindow);
+ fResult = (*pScreen->CreateWindow) (pWin);
+ WIN_WRAP(CreateWindow, winCreateWindowRootless);
+
+ pWinPriv->hRgn = NULL;
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37 */
+/* See mfb/mfbwindow.c - mfbDestroyWindow() */
+
+Bool
+winDestroyWindowRootless (WindowPtr pWin)
+{
+ Bool fResult = FALSE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winDestroyWindowRootless (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(DestroyWindow);
+ fResult = (*pScreen->DestroyWindow)(pWin);
+ WIN_WRAP(DestroyWindow, winDestroyWindowRootless);
+
+ if (pWinPriv->hRgn != NULL)
+ {
+ DeleteObject(pWinPriv->hRgn);
+ pWinPriv->hRgn = NULL;
+ }
+
+ winUpdateRgnRootless (pWin);
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37 */
+/* See mfb/mfbwindow.c - mfbPositionWindow() */
+
+Bool
+winPositionWindowRootless (WindowPtr pWin, int x, int y)
+{
+ Bool fResult = FALSE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winScreenPriv(pScreen);
+
+
+#if CYGDEBUG
+ winTrace ("winPositionWindowRootless (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(PositionWindow);
+ fResult = (*pScreen->PositionWindow)(pWin, x, y);
+ WIN_WRAP(PositionWindow, winPositionWindowRootless);
+
+ winUpdateRgnRootless (pWin);
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37 */
+/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */
+
+Bool
+winChangeWindowAttributesRootless (WindowPtr pWin, unsigned long mask)
+{
+ Bool fResult = FALSE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winChangeWindowAttributesRootless (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(ChangeWindowAttributes);
+ fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
+ WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesRootless);
+
+ winUpdateRgnRootless (pWin);
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37
+ * Also referred to as UnrealizeWindow
+ */
+
+Bool
+winUnmapWindowRootless (WindowPtr pWin)
+{
+ Bool fResult = FALSE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winWindowPriv(pWin);
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winUnmapWindowRootless (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(UnrealizeWindow);
+ fResult = (*pScreen->UnrealizeWindow)(pWin);
+ WIN_WRAP(UnrealizeWindow, winUnmapWindowRootless);
+
+ if (pWinPriv->hRgn != NULL)
+ {
+ DeleteObject(pWinPriv->hRgn);
+ pWinPriv->hRgn = NULL;
+ }
+
+ winUpdateRgnRootless (pWin);
+
+ return fResult;
+}
+
+
+/* See Porting Layer Definition - p. 37
+ * Also referred to as RealizeWindow
+ */
+
+Bool
+winMapWindowRootless (WindowPtr pWin)
+{
+ Bool fResult = FALSE;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winMapWindowRootless (%p)\n", pWin);
+#endif
+
+ WIN_UNWRAP(RealizeWindow);
+ fResult = (*pScreen->RealizeWindow)(pWin);
+ WIN_WRAP(RealizeWindow, winMapWindowRootless);
+
+ winReshapeRootless (pWin);
+
+ winUpdateRgnRootless (pWin);
+
+ return fResult;
+}
+
+
+void
+winSetShapeRootless (WindowPtr pWin, int kind)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ winScreenPriv(pScreen);
+
+#if CYGDEBUG
+ winTrace ("winSetShapeRootless (%p, %i)\n", pWin, kind);
+#endif
+
+ WIN_UNWRAP(SetShape);
+ (*pScreen->SetShape)(pWin, kind);
+ WIN_WRAP(SetShape, winSetShapeRootless);
+
+ winReshapeRootless (pWin);
+ winUpdateRgnRootless (pWin);
+
+ return;
+}
+
+
+/*
+ * Local function for adding a region to the Windows window region
+ */
+
+static
+int
+winAddRgn (WindowPtr pWin, pointer data)
+{
+ int iX, iY, iWidth, iHeight, iBorder;
+ HRGN hRgn = *(HRGN*)data;
+ HRGN hRgnWin;
+ winWindowPriv(pWin);
+
+ /* If pWin is not Root */
+ if (pWin->parent != NULL)
+ {
+#if CYGDEBUG
+ winDebug ("winAddRgn ()\n");
+#endif
+ if (pWin->mapped)
+ {
+ iBorder = wBorderWidth (pWin);
+
+ iX = pWin->drawable.x - iBorder;
+ iY = pWin->drawable.y - iBorder;
+
+ iWidth = pWin->drawable.width + iBorder * 2;
+ iHeight = pWin->drawable.height + iBorder * 2;
+
+ hRgnWin = CreateRectRgn (0, 0, iWidth, iHeight);
+
+ if (hRgnWin == NULL)
+ {
+ ErrorF ("winAddRgn - CreateRectRgn () failed\n");
+ ErrorF (" Rect %d %d %d %d\n",
+ iX, iY, iX + iWidth, iY + iHeight);
+ }
+
+ if (pWinPriv->hRgn)
+ {
+ if (CombineRgn (hRgnWin, hRgnWin, pWinPriv->hRgn, RGN_AND)
+ == ERROR)
+ {
+ ErrorF ("winAddRgn - CombineRgn () failed\n");
+ }
+ }
+
+ OffsetRgn (hRgnWin, iX, iY);
+
+ if (CombineRgn (hRgn, hRgn, hRgnWin, RGN_OR) == ERROR)
+ {
+ ErrorF ("winAddRgn - CombineRgn () failed\n");
+ }
+
+ DeleteObject (hRgnWin);
+ }
+ return WT_DONTWALKCHILDREN;
+ }
+ else
+ {
+ return WT_WALKCHILDREN;
+ }
+}
+
+
+/*
+ * Local function to update the Windows window's region
+ */
+
+static
+void
+winUpdateRgnRootless (WindowPtr pWin)
+{
+ HRGN hRgn = CreateRectRgn (0, 0, 0, 0);
+
+ if (hRgn != NULL)
+ {
+ WalkTree (pWin->drawable.pScreen, winAddRgn, &hRgn);
+ SetWindowRgn (winGetScreenPriv(pWin->drawable.pScreen)->hwndScreen,
+ hRgn, TRUE);
+ }
+ else
+ {
+ ErrorF ("winUpdateRgnRootless - CreateRectRgn failed.\n");
+ }
+}
+
+
+static
+void
+winReshapeRootless (WindowPtr pWin)
+{
+ int nRects;
+ RegionRec rrNewShape;
+ BoxPtr pShape, pRects, pEnd;
+ HRGN hRgn, hRgnRect;
+ winWindowPriv(pWin);
+
+#if CYGDEBUG
+ winDebug ("winReshapeRootless ()\n");
+#endif
+
+ /* Bail if the window is the root window */
+ if (pWin->parent == NULL)
+ return;
+
+ /* Bail if the window is not top level */
+ if (pWin->parent->parent != NULL)
+ return;
+
+ /* Free any existing window region stored in the window privates */
+ if (pWinPriv->hRgn != NULL)
+ {
+ DeleteObject (pWinPriv->hRgn);
+ pWinPriv->hRgn = NULL;
+ }
+
+ /* Bail if the window has no bounding region defined */
+ if (!wBoundingShape (pWin))
+ return;
+
+ RegionNull(&rrNewShape);
+ RegionCopy(&rrNewShape, wBoundingShape(pWin));
+ RegionTranslate(&rrNewShape, pWin->borderWidth,
+ pWin->borderWidth);
+
+ nRects = RegionNumRects(&rrNewShape);
+ pShape = RegionRects(&rrNewShape);
+
+ if (nRects > 0)
+ {
+ /* Create initial empty Windows region */
+ hRgn = CreateRectRgn (0, 0, 0, 0);
+
+ /* Loop through all rectangles in the X region */
+ for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++)
+ {
+ /* Create a Windows region for the X rectangle */
+ hRgnRect = CreateRectRgn (pRects->x1, pRects->y1,
+ pRects->x2, pRects->y2);
+ if (hRgnRect == NULL)
+ {
+ ErrorF("winReshapeRootless - CreateRectRgn() failed\n");
+ }
+
+ /* Merge the Windows region with the accumulated region */
+ if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR)
+ {
+ ErrorF("winReshapeRootless - CombineRgn() failed\n");
+ }
+
+ /* Delete the temporary Windows region */
+ DeleteObject (hRgnRect);
+ }
+
+ /* Save a handle to the composite region in the window privates */
+ pWinPriv->hRgn = hRgn;
+ }
+
+ RegionUninit(&rrNewShape);
+
+ return;
+}
diff --git a/xorg-server/hw/xwin/winwndproc.c b/xorg-server/hw/xwin/winwndproc.c
index 6d03de174..bccd6f9f2 100644
--- a/xorg-server/hw/xwin/winwndproc.c
+++ b/xorg-server/hw/xwin/winwndproc.c
@@ -1,1263 +1,1312 @@
-/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Dakshinamurthy Karra
- * Suhaib M Siddiqi
- * Peter Busch
- * Harold L Hunt II
- * MATSUZAKI Kensuke
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include <commctrl.h>
-#include "winprefs.h"
-#include "winconfig.h"
-#include "winmsg.h"
-#include "inputstr.h"
-
-/*
- * Global variables
- */
-
-Bool g_fCursor = TRUE;
-Bool g_fButton[3] = { FALSE, FALSE, FALSE };
-
-
-/*
- * Called by winWakeupHandler
- * Processes current Windows message
- */
-
-LRESULT CALLBACK
-winWindowProc (HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam)
-{
- static winPrivScreenPtr s_pScreenPriv = NULL;
- static winScreenInfo *s_pScreenInfo = NULL;
- static ScreenPtr s_pScreen = NULL;
- static HWND s_hwndLastPrivates = NULL;
- static HINSTANCE s_hInstance;
- static Bool s_fTracking = FALSE;
- static unsigned long s_ulServerGeneration = 0;
- static UINT s_uTaskbarRestart = 0;
- int iScanCode;
- int i;
-
-#if CYGDEBUG
- winDebugWin32Message("winWindowProc", hwnd, message, wParam, lParam);
-#endif
-
- /* Watch for server regeneration */
- if (g_ulServerGeneration != s_ulServerGeneration)
- {
- /* Store new server generation */
- s_ulServerGeneration = g_ulServerGeneration;
- }
-
- /* Only retrieve new privates pointers if window handle is null or changed */
- if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates)
- && (s_pScreenPriv = GetProp (hwnd, WIN_SCR_PROP)) != NULL)
- {
-#if CYGDEBUG
- winDebug ("winWindowProc - Setting privates handle\n");
-#endif
- s_pScreenInfo = s_pScreenPriv->pScreenInfo;
- s_pScreen = s_pScreenInfo->pScreen;
- s_hwndLastPrivates = hwnd;
- }
- else if (s_pScreenPriv == NULL)
- {
- /* For safety, handle case that should never happen */
- s_pScreenInfo = NULL;
- s_pScreen = NULL;
- s_hwndLastPrivates = NULL;
- }
-
- /* Branch on message type */
- switch (message)
- {
- case WM_TRAYICON:
- return winHandleIconMessage (hwnd, message, wParam, lParam,
- s_pScreenPriv);
-
- case WM_CREATE:
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_CREATE\n");
-#endif
-
- /*
- * Add a property to our display window that references
- * this screens' privates.
- *
- * This allows the window procedure to refer to the
- * appropriate window DC and shadow DC for the window that
- * it is processing. We use this to repaint exposed
- * areas of our display window.
- */
- s_pScreenPriv = ((LPCREATESTRUCT) lParam)->lpCreateParams;
- s_hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
- s_pScreenInfo = s_pScreenPriv->pScreenInfo;
- s_pScreen = s_pScreenInfo->pScreen;
- s_hwndLastPrivates = hwnd;
- s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
- SetProp (hwnd, WIN_SCR_PROP, s_pScreenPriv);
-
- /* Setup tray icon */
- if (!s_pScreenInfo->fNoTrayIcon)
- {
- /*
- * NOTE: The WM_CREATE message is processed before CreateWindowEx
- * returns, so s_pScreenPriv->hwndScreen is invalid at this point.
- * We go ahead and copy our hwnd parameter over top of the screen
- * privates hwndScreen so that we have a valid value for
- * that member. Otherwise, the tray icon will disappear
- * the first time you move the mouse over top of it.
- */
-
- s_pScreenPriv->hwndScreen = hwnd;
-
- winInitNotifyIcon (s_pScreenPriv);
- }
- return 0;
-
- case WM_DISPLAYCHANGE:
- /* We cannot handle a display mode change during initialization */
- if (s_pScreenInfo == NULL)
- FatalError ("winWindowProc - WM_DISPLAYCHANGE - The display "
- "mode changed while we were intializing. This is "
- "very bad and unexpected. Exiting.\n");
-
- /*
- * We do not care about display changes with
- * fullscreen DirectDraw engines, because those engines set
- * their own mode when they become active.
- */
- if (s_pScreenInfo->fFullScreen
- && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
- || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
-#ifdef XWIN_PRIMARYFB
- || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD
-#endif
- ))
- {
- /*
- * Store the new display dimensions and depth.
- * We do this here for future compatibility in case we
- * ever allow switching from fullscreen to windowed mode.
- */
- s_pScreenPriv->dwLastWindowsWidth = GetSystemMetrics (SM_CXSCREEN);
- s_pScreenPriv->dwLastWindowsHeight = GetSystemMetrics (SM_CYSCREEN);
- s_pScreenPriv->dwLastWindowsBitsPixel
- = GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL);
- break;
- }
-
- ErrorF ("winWindowProc - WM_DISPLAYCHANGE - orig bpp: %d, last bpp: %d, "
- "new bpp: %d\n",
- (int) s_pScreenInfo->dwBPP,
- (int) s_pScreenPriv->dwLastWindowsBitsPixel,
- wParam);
-
- ErrorF ("winWindowProc - WM_DISPLAYCHANGE - new width: %d "
- "new height: %d\n",
- LOWORD (lParam), HIWORD (lParam));
-
- /*
- * TrueColor --> TrueColor depth changes are disruptive for:
- * Windowed:
- * Shadow DirectDraw
- * Shadow DirectDraw Non-Locking
- * Primary DirectDraw
- *
- * TrueColor --> TrueColor depth changes are non-optimal for:
- * Windowed:
- * Shadow GDI
- *
- * FullScreen:
- * Shadow GDI
- *
- * TrueColor --> PseudoColor or vice versa are disruptive for:
- * Windowed:
- * Shadow DirectDraw
- * Shadow DirectDraw Non-Locking
- * Primary DirectDraw
- * Shadow GDI
- */
-
- /*
- * Check for a disruptive change in depth.
- * We can only display a message for a disruptive depth change,
- * we cannot do anything to correct the situation.
- */
- if ((s_pScreenInfo->dwBPP != wParam)
- && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
- || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
-#ifdef XWIN_PRIMARYFB
- || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD
-#endif
- ))
- {
- /* Cannot display the visual until the depth is restored */
- ErrorF ("winWindowProc - Disruptive change in depth\n");
-
- /* Display Exit dialog */
- winDisplayDepthChangeDialog (s_pScreenPriv);
-
- /* Flag that we have an invalid screen depth */
- s_pScreenPriv->fBadDepth = TRUE;
-
- /* Minimize the display window */
- ShowWindow (hwnd, SW_MINIMIZE);
- }
- else
- {
- /* Flag that we have a valid screen depth */
- s_pScreenPriv->fBadDepth = FALSE;
- }
-
- /*
- * Check for a change in display dimensions.
- * We can simply recreate the same-sized primary surface when
- * the display dimensions change.
- */
- if (s_pScreenPriv->dwLastWindowsWidth != LOWORD (lParam)
- || s_pScreenPriv->dwLastWindowsHeight != HIWORD (lParam))
- {
- /*
- * NOTE: The non-DirectDraw engines set the ReleasePrimarySurface
- * and CreatePrimarySurface function pointers to point
- * to the no operation function, NoopDDA. This allows us
- * to blindly call these functions, even if they are not
- * relevant to the current engine (e.g., Shadow GDI).
- */
-
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_DISPLAYCHANGE - Dimensions changed\n");
-#endif
-
- /* Release the old primary surface */
- (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen);
-
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_DISPLAYCHANGE - Released "
- "primary surface\n");
-#endif
-
- /* Create the new primary surface */
- (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen);
-
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_DISPLAYCHANGE - Recreated "
- "primary surface\n");
-#endif
-
-#if 0
- /* Multi-Window mode uses RandR for resizes */
- if (s_pScreenInfo->fMultiWindow)
- {
- RRSetScreenConfig ();
- }
-#endif
- }
- else
- {
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_DISPLAYCHANGE - Dimensions did not "
- "change\n");
-#endif
- }
-
- /* Store the new display dimensions and depth */
- if (s_pScreenInfo->fMultipleMonitors)
- {
- s_pScreenPriv->dwLastWindowsWidth
- = GetSystemMetrics (SM_CXVIRTUALSCREEN);
- s_pScreenPriv->dwLastWindowsHeight
- = GetSystemMetrics (SM_CYVIRTUALSCREEN);
- }
- else
- {
- s_pScreenPriv->dwLastWindowsWidth
- = GetSystemMetrics (SM_CXSCREEN);
- s_pScreenPriv->dwLastWindowsHeight
- = GetSystemMetrics (SM_CYSCREEN);
- }
- s_pScreenPriv->dwLastWindowsBitsPixel
- = GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL);
- break;
-
- case WM_SIZE:
- {
- SCROLLINFO si;
- RECT rcWindow;
- int iWidth, iHeight;
-
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_SIZE\n");
-#endif
-
- /* Break if we do not use scrollbars */
- if (!s_pScreenInfo->fScrollbars
- || !s_pScreenInfo->fDecoration
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- || s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOW
- || s_pScreenInfo->fMultiWindow
-#endif
- || s_pScreenInfo->fFullScreen)
- break;
-
- /* No need to resize if we get minimized */
- if (wParam == SIZE_MINIMIZED)
- return 0;
-
- /*
- * Get the size of the whole window, including client area,
- * scrollbars, and non-client area decorations (caption, borders).
- * We do this because we need to check if the client area
- * without scrollbars is large enough to display the whole visual.
- * The new client area size passed by lParam already subtracts
- * the size of the scrollbars if they are currently displayed.
- * So checking is LOWORD(lParam) == visual_width and
- * HIWORD(lParam) == visual_height will never tell us to hide
- * the scrollbars because the client area would always be too small.
- * GetClientRect returns the same sizes given by lParam, so we
- * cannot use GetClientRect either.
- */
- GetWindowRect (hwnd, &rcWindow);
- iWidth = rcWindow.right - rcWindow.left;
- iHeight = rcWindow.bottom - rcWindow.top;
-
- ErrorF ("winWindowProc - WM_SIZE - window w: %d h: %d, "
- "new client area w: %d h: %d\n",
- iWidth, iHeight, LOWORD (lParam), HIWORD (lParam));
-
- /* Subtract the frame size from the window size. */
- iWidth -= 2 * GetSystemMetrics (SM_CXSIZEFRAME);
- iHeight -= (2 * GetSystemMetrics (SM_CYSIZEFRAME)
- + GetSystemMetrics (SM_CYCAPTION));
-
- /*
- * Update scrollbar page sizes.
- * NOTE: If page size == range, then the scrollbar is
- * automatically hidden.
- */
-
- /* Is the naked client area large enough to show the whole visual? */
- if (iWidth < s_pScreenInfo->dwWidth
- || iHeight < s_pScreenInfo->dwHeight)
- {
- /* Client area too small to display visual, use scrollbars */
- iWidth -= GetSystemMetrics (SM_CXVSCROLL);
- iHeight -= GetSystemMetrics (SM_CYHSCROLL);
- }
-
- /* Set the horizontal scrollbar page size */
- si.cbSize = sizeof (si);
- si.fMask = SIF_PAGE | SIF_RANGE;
- si.nMin = 0;
- si.nMax = s_pScreenInfo->dwWidth - 1;
- si.nPage = iWidth;
- SetScrollInfo (hwnd, SB_HORZ, &si, TRUE);
-
- /* Set the vertical scrollbar page size */
- si.cbSize = sizeof (si);
- si.fMask = SIF_PAGE | SIF_RANGE;
- si.nMin = 0;
- si.nMax = s_pScreenInfo->dwHeight - 1;
- si.nPage = iHeight;
- SetScrollInfo (hwnd, SB_VERT, &si, TRUE);
-
- /*
- * NOTE: Scrollbars may have moved if they were at the
- * far right/bottom, so we query their current position.
- */
-
- /* Get the horizontal scrollbar position and set the offset */
- si.cbSize = sizeof (si);
- si.fMask = SIF_POS;
- GetScrollInfo (hwnd, SB_HORZ, &si);
- s_pScreenInfo->dwXOffset = -si.nPos;
-
- /* Get the vertical scrollbar position and set the offset */
- si.cbSize = sizeof (si);
- si.fMask = SIF_POS;
- GetScrollInfo (hwnd, SB_VERT, &si);
- s_pScreenInfo->dwYOffset = -si.nPos;
- }
- return 0;
-
- case WM_VSCROLL:
- {
- SCROLLINFO si;
- int iVertPos;
-
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_VSCROLL\n");
-#endif
-
- /* Get vertical scroll bar info */
- si.cbSize = sizeof (si);
- si.fMask = SIF_ALL;
- GetScrollInfo (hwnd, SB_VERT, &si);
-
- /* Save the vertical position for comparison later */
- iVertPos = si.nPos;
-
- /*
- * Don't forget:
- * moving the scrollbar to the DOWN, scroll the content UP
- */
- switch (LOWORD(wParam))
- {
- case SB_TOP:
- si.nPos = si.nMin;
- break;
-
- case SB_BOTTOM:
- si.nPos = si.nMax - si.nPage + 1;
- break;
-
- case SB_LINEUP:
- si.nPos -= 1;
- break;
-
- case SB_LINEDOWN:
- si.nPos += 1;
- break;
-
- case SB_PAGEUP:
- si.nPos -= si.nPage;
- break;
-
- case SB_PAGEDOWN:
- si.nPos += si.nPage;
- break;
-
- case SB_THUMBTRACK:
- si.nPos = si.nTrackPos;
- break;
-
- default:
- break;
- }
-
- /*
- * We retrieve the position after setting it,
- * because Windows may adjust it.
- */
- si.fMask = SIF_POS;
- SetScrollInfo (hwnd, SB_VERT, &si, TRUE);
- GetScrollInfo (hwnd, SB_VERT, &si);
-
- /* Scroll the window if the position has changed */
- if (si.nPos != iVertPos)
- {
- /* Save the new offset for bit block transfers, etc. */
- s_pScreenInfo->dwYOffset = -si.nPos;
-
- /* Change displayed region in the window */
- ScrollWindowEx (hwnd,
- 0,
- iVertPos - si.nPos,
- NULL,
- NULL,
- NULL,
- NULL,
- SW_INVALIDATE);
-
- /* Redraw the window contents */
- UpdateWindow (hwnd);
- }
- }
- return 0;
-
- case WM_HSCROLL:
- {
- SCROLLINFO si;
- int iHorzPos;
-
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_HSCROLL\n");
-#endif
-
- /* Get horizontal scroll bar info */
- si.cbSize = sizeof (si);
- si.fMask = SIF_ALL;
- GetScrollInfo (hwnd, SB_HORZ, &si);
-
- /* Save the horizontal position for comparison later */
- iHorzPos = si.nPos;
-
- /*
- * Don't forget:
- * moving the scrollbar to the RIGHT, scroll the content LEFT
- */
- switch (LOWORD(wParam))
- {
- case SB_LEFT:
- si.nPos = si.nMin;
- break;
-
- case SB_RIGHT:
- si.nPos = si.nMax - si.nPage + 1;
- break;
-
- case SB_LINELEFT:
- si.nPos -= 1;
- break;
-
- case SB_LINERIGHT:
- si.nPos += 1;
- break;
-
- case SB_PAGELEFT:
- si.nPos -= si.nPage;
- break;
-
- case SB_PAGERIGHT:
- si.nPos += si.nPage;
- break;
-
- case SB_THUMBTRACK:
- si.nPos = si.nTrackPos;
- break;
-
- default:
- break;
- }
-
- /*
- * We retrieve the position after setting it,
- * because Windows may adjust it.
- */
- si.fMask = SIF_POS;
- SetScrollInfo (hwnd, SB_HORZ, &si, TRUE);
- GetScrollInfo (hwnd, SB_HORZ, &si);
-
- /* Scroll the window if the position has changed */
- if (si.nPos != iHorzPos)
- {
- /* Save the new offset for bit block transfers, etc. */
- s_pScreenInfo->dwXOffset = -si.nPos;
-
- /* Change displayed region in the window */
- ScrollWindowEx (hwnd,
- iHorzPos - si.nPos,
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- SW_INVALIDATE);
-
- /* Redraw the window contents */
- UpdateWindow (hwnd);
- }
- }
- return 0;
-
- case WM_GETMINMAXINFO:
- {
- MINMAXINFO *pMinMaxInfo = (MINMAXINFO *) lParam;
- int iCaptionHeight;
- int iBorderHeight, iBorderWidth;
-
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %08x\n",
- s_pScreenInfo);
-#endif
-
- /* Can't do anything without screen info */
- if (s_pScreenInfo == NULL
- || !s_pScreenInfo->fScrollbars
- || s_pScreenInfo->fFullScreen
- || !s_pScreenInfo->fDecoration
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- || s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOW
- || s_pScreenInfo->fMultiWindow
-#endif
- )
- break;
-
- /*
- * Here we can override the maximum tracking size, which
- * is the largest size that can be assigned to our window
- * via the sizing border.
- */
-
- /*
- * FIXME: Do we only need to do this once, since our visual size
- * does not change? Does Windows store this value statically
- * once we have set it once?
- */
-
- /* Get the border and caption sizes */
- iCaptionHeight = GetSystemMetrics (SM_CYCAPTION);
- iBorderWidth = 2 * GetSystemMetrics (SM_CXSIZEFRAME);
- iBorderHeight = 2 * GetSystemMetrics (SM_CYSIZEFRAME);
-
- /* Allow the full visual to be displayed */
- pMinMaxInfo->ptMaxTrackSize.x
- = s_pScreenInfo->dwWidth + iBorderWidth;
- pMinMaxInfo->ptMaxTrackSize.y
- = s_pScreenInfo->dwHeight + iBorderHeight + iCaptionHeight;
- }
- return 0;
-
- case WM_ERASEBKGND:
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_ERASEBKGND\n");
-#endif
- /*
- * Pretend that we did erase the background but we don't care,
- * the application uses the full window estate. This avoids some
- * flickering when resizing.
- */
- return TRUE;
-
- case WM_PAINT:
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_PAINT\n");
-#endif
- /* Only paint if we have privates and the server is enabled */
- if (s_pScreenPriv == NULL
- || !s_pScreenPriv->fEnabled
- || (s_pScreenInfo->fFullScreen && !s_pScreenPriv->fActive)
- || s_pScreenPriv->fBadDepth)
- {
- /* We don't want to paint */
- break;
- }
-
- /* Break out here if we don't have a valid paint routine */
- if (s_pScreenPriv->pwinBltExposedRegions == NULL)
- break;
-
- /* Call the engine dependent repainter */
- (*s_pScreenPriv->pwinBltExposedRegions) (s_pScreen);
- return 0;
-
- case WM_PALETTECHANGED:
- {
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_PALETTECHANGED\n");
-#endif
- /*
- * Don't process if we don't have privates or a colormap,
- * or if we have an invalid depth.
- */
- if (s_pScreenPriv == NULL
- || s_pScreenPriv->pcmapInstalled == NULL
- || s_pScreenPriv->fBadDepth)
- break;
-
- /* Return if we caused the palette to change */
- if ((HWND) wParam == hwnd)
- {
- /* Redraw the screen */
- (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
- return 0;
- }
-
- /* Reinstall the windows palette */
- (*s_pScreenPriv->pwinRealizeInstalledPalette) (s_pScreen);
-
- /* Redraw the screen */
- (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
- return 0;
- }
-
- case WM_MOUSEMOVE:
- /* We can't do anything without privates */
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
-
- /* We can't do anything without g_pwinPointer */
- if (g_pwinPointer == NULL)
- break;
-
- /* Has the mouse pointer crossed screens? */
- if (s_pScreen != miPointerGetScreen(g_pwinPointer))
- miPointerSetScreen (g_pwinPointer, s_pScreenInfo->dwScreen,
- GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset,
- GET_Y_LPARAM(lParam)-s_pScreenInfo->dwYOffset);
-
- /* Are we tracking yet? */
- if (!s_fTracking)
- {
- TRACKMOUSEEVENT tme;
-
- /* Setup data structure */
- ZeroMemory (&tme, sizeof (tme));
- tme.cbSize = sizeof (tme);
- tme.dwFlags = TME_LEAVE;
- tme.hwndTrack = hwnd;
-
- /* Call the tracking function */
- if (!(*g_fpTrackMouseEvent) (&tme))
- ErrorF ("winWindowProc - _TrackMouseEvent failed\n");
-
- /* Flag that we are tracking now */
- s_fTracking = TRUE;
- }
-
- /* Hide or show the Windows mouse cursor */
- if (g_fSoftwareCursor && g_fCursor && (s_pScreenPriv->fActive || s_pScreenInfo->fLessPointer))
- {
- /* Hide Windows cursor */
- g_fCursor = FALSE;
- ShowCursor (FALSE);
- }
- else if (g_fSoftwareCursor && !g_fCursor && !s_pScreenPriv->fActive
- && !s_pScreenInfo->fLessPointer)
- {
- /* Show Windows cursor */
- g_fCursor = TRUE;
- ShowCursor (TRUE);
- }
-
- /* Deliver absolute cursor position to X Server */
- winEnqueueMotion(GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset,
- GET_Y_LPARAM(lParam)-s_pScreenInfo->dwYOffset);
- return 0;
-
- case WM_NCMOUSEMOVE:
- /*
- * We break instead of returning 0 since we need to call
- * DefWindowProc to get the mouse cursor changes
- * and min/max/close button highlighting in Windows XP.
- * The Platform SDK says that you should return 0 if you
- * process this message, but it fails to mention that you
- * will give up any default functionality if you do return 0.
- */
-
- /* We can't do anything without privates */
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
-
- /* Non-client mouse movement, show Windows cursor */
- if (g_fSoftwareCursor && !g_fCursor)
- {
- g_fCursor = TRUE;
- ShowCursor (TRUE);
- }
- break;
-
- case WM_MOUSELEAVE:
- /* Mouse has left our client area */
-
- /* Flag that we are no longer tracking */
- s_fTracking = FALSE;
-
- /* Show the mouse cursor, if necessary */
- if (g_fSoftwareCursor && !g_fCursor)
- {
- g_fCursor = TRUE;
- ShowCursor (TRUE);
- }
- return 0;
-
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
- if (s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- )
- SetCapture (hwnd);
- return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam);
-
- case WM_LBUTTONUP:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
- if (s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- )
- ReleaseCapture ();
- return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam);
-
- case WM_MBUTTONDBLCLK:
- case WM_MBUTTONDOWN:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
- if (s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- )
- SetCapture (hwnd);
- return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam);
-
- case WM_MBUTTONUP:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
- if (s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- )
- ReleaseCapture ();
- return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam);
-
- case WM_RBUTTONDBLCLK:
- case WM_RBUTTONDOWN:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
- if (s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- )
- SetCapture (hwnd);
- return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam);
-
- case WM_RBUTTONUP:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
- if (s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- )
- ReleaseCapture ();
- return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam);
-
- case WM_XBUTTONDBLCLK:
- case WM_XBUTTONDOWN:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
- if (s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- )
- SetCapture (hwnd);
- return winMouseButtonsHandle (s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
- case WM_XBUTTONUP:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
- if (s_pScreenInfo->fRootless
-#ifdef XWIN_MULTIWINDOWEXTWM
- || s_pScreenInfo->fMWExtWM
-#endif
- )
- ReleaseCapture ();
- return winMouseButtonsHandle (s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
-
- case WM_TIMER:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
-
- /* Branch on the timer id */
- switch (wParam)
- {
- case WIN_E3B_TIMER_ID:
- /* Send delayed button press */
- winMouseButtonsSendEvent (ButtonPress,
- s_pScreenPriv->iE3BCachedPress);
-
- /* Kill this timer */
- KillTimer (s_pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID);
-
- /* Clear screen privates flags */
- s_pScreenPriv->iE3BCachedPress = 0;
- break;
-
- case WIN_POLLING_MOUSE_TIMER_ID:
- {
- POINT point;
- WPARAM wL, wM, wR, wShift, wCtrl;
- LPARAM lPos;
-
- /* Get the current position of the mouse cursor */
- GetCursorPos (&point);
-
- /* Map from screen (-X, -Y) to root (0, 0) */
- point.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
- point.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
-
- /* Deliver absolute cursor position to X Server */
- winEnqueueMotion(point.x , point.y);
-
- /* Check if a button was released but we didn't see it */
- GetCursorPos (&point);
- wL = (GetKeyState (VK_LBUTTON) & 0x8000)?MK_LBUTTON:0;
- wM = (GetKeyState (VK_MBUTTON) & 0x8000)?MK_MBUTTON:0;
- wR = (GetKeyState (VK_RBUTTON) & 0x8000)?MK_RBUTTON:0;
- wShift = (GetKeyState (VK_SHIFT) & 0x8000)?MK_SHIFT:0;
- wCtrl = (GetKeyState (VK_CONTROL) & 0x8000)?MK_CONTROL:0;
- lPos = MAKELPARAM(point.x, point.y);
- if (g_fButton[0] & !wL)
- PostMessage (hwnd, WM_LBUTTONUP, wCtrl|wM|wR|wShift, lPos);
- if (g_fButton[1] & !wM)
- PostMessage (hwnd, WM_MBUTTONUP, wCtrl|wL|wR|wShift, lPos);
- if (g_fButton[2] & !wR)
- PostMessage (hwnd, WM_RBUTTONUP, wCtrl|wL|wM|wShift, lPos);
- }
- }
- return 0;
-
- case WM_CTLCOLORSCROLLBAR:
- FatalError ("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not "
- "supposed to get this message. Exiting.\n");
- return 0;
-
- case WM_MOUSEWHEEL:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_MOUSEWHEEL\n");
-#endif
- winMouseWheel (s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam));
- break;
-
- case WM_SETFOCUS:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
-
- /* Restore the state of all mode keys */
- winRestoreModeKeyStates ();
-
- /* Add the keyboard hook if possible */
- if (g_fKeyboardHookLL)
- g_fKeyboardHookLL = winInstallKeyboardHookLL ();
- return 0;
-
- case WM_KILLFOCUS:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
-
- /* Release any pressed keys */
- winKeybdReleaseKeys ();
-
- /* Remove our keyboard hook if it is installed */
- winRemoveKeyboardHookLL ();
- return 0;
-
- case WM_SYSKEYDOWN:
- case WM_KEYDOWN:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
-
- /*
- * FIXME: Catching Alt-F4 like this is really terrible. This should
- * be generalized to handle other Windows keyboard signals. Actually,
- * the list keys to catch and the actions to perform when caught should
- * be configurable; that way user's can customize the keys that they
- * need to have passed through to their window manager or apps, or they
- * can remap certain actions to new key codes that do not conflict
- * with the X apps that they are using. Yeah, that'll take awhile.
- */
- if ((s_pScreenInfo->fUseWinKillKey && wParam == VK_F4
- && (GetKeyState (VK_MENU) & 0x8000))
- || (s_pScreenInfo->fUseUnixKillKey && wParam == VK_BACK
- && (GetKeyState (VK_MENU) & 0x8000)
- && (GetKeyState (VK_CONTROL) & 0x8000)))
- {
- /*
- * Better leave this message here, just in case some unsuspecting
- * user enters Alt + F4 and is surprised when the application
- * quits.
- */
- ErrorF ("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n");
-
- /* Display Exit dialog */
- winDisplayExitDialog (s_pScreenPriv);
- return 0;
- }
-
- /*
- * Don't do anything for the Windows keys, as focus will soon
- * be returned to Windows. We may be able to trap the Windows keys,
- * but we should determine if that is desirable before doing so.
- */
- if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
- break;
-
- /*
- * Discard presses generated from Windows auto-repeat
- */
- if (lParam & (1<<30))
- {
- switch (wParam)
- {
- /* ago: Pressing LControl while RControl is pressed is
- * Indicated as repeat. Fix this!
- */
- case VK_CONTROL:
- case VK_SHIFT:
- if (winCheckKeyPressed(wParam, lParam))
- return 0;
- break;
- default:
- return 0;
- }
- }
-
- /* Discard fake Ctrl_L presses that precede AltGR on non-US keyboards */
- if (winIsFakeCtrl_L (message, wParam, lParam))
- return 0;
-
- /* Translate Windows key code to X scan code */
- winTranslateKey (wParam, lParam, &iScanCode);
-
- /* Ignore repeats for CapsLock */
- if (wParam == VK_CAPITAL)
- lParam = 1;
-
- /* Send the key event(s) */
- for (i = 0; i < LOWORD(lParam); ++i)
- winSendKeyEvent (iScanCode, TRUE);
- return 0;
-
- case WM_SYSKEYUP:
- case WM_KEYUP:
- if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
- break;
-
- /*
- * Don't do anything for the Windows keys, as focus will soon
- * be returned to Windows. We may be able to trap the Windows keys,
- * but we should determine if that is desirable before doing so.
- */
- if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
- break;
-
- /* Ignore the fake Ctrl_L that follows an AltGr release */
- if (winIsFakeCtrl_L (message, wParam, lParam))
- return 0;
-
- /* Enqueue a keyup event */
- winTranslateKey (wParam, lParam, &iScanCode);
- winSendKeyEvent (iScanCode, FALSE);
-
- /* Release all pressed shift keys */
- if (wParam == VK_SHIFT)
- winFixShiftKeys (iScanCode);
- return 0;
-
- case WM_HOTKEY:
- if (s_pScreenPriv == NULL)
- break;
-
- /* Call the engine-specific hot key handler */
- (*s_pScreenPriv->pwinHotKeyAltTab) (s_pScreen);
- return 0;
-
- case WM_ACTIVATE:
- if (s_pScreenPriv == NULL
- || s_pScreenInfo->fIgnoreInput)
- break;
-
- /* TODO: Override display of window when we have a bad depth */
- if (LOWORD(wParam) != WA_INACTIVE && s_pScreenPriv->fBadDepth)
- {
- ErrorF ("winWindowProc - WM_ACTIVATE - Bad depth, trying "
- "to override window activation\n");
-
- /* Minimize the window */
- ShowWindow (hwnd, SW_MINIMIZE);
-
- /* Display dialog box */
- if (g_hDlgDepthChange != NULL)
- {
- /* Make the existing dialog box active */
- SetActiveWindow (g_hDlgDepthChange);
- }
- else
- {
- /* TODO: Recreate the dialog box and bring to the top */
- ShowWindow (g_hDlgDepthChange, SW_SHOWDEFAULT);
- }
-
- /* Don't do any other processing of this message */
- return 0;
- }
-
-#if CYGDEBUG
- winDebug ("winWindowProc - WM_ACTIVATE\n");
-#endif
-
- /*
- * Focus is being changed to another window.
- * The other window may or may not belong to
- * our process.
- */
-
- /* Clear any lingering wheel delta */
- s_pScreenPriv->iDeltaZ = 0;
-
- /* Reshow the Windows mouse cursor if we are being deactivated */
- if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE
- && !g_fCursor)
- {
- /* Show Windows cursor */
- g_fCursor = TRUE;
- ShowCursor (TRUE);
- }
- return 0;
-
- case WM_ACTIVATEAPP:
- if (s_pScreenPriv == NULL
- || s_pScreenInfo->fIgnoreInput)
- break;
-
-#if CYGDEBUG || TRUE
- winDebug ("winWindowProc - WM_ACTIVATEAPP\n");
-#endif
-
- /* Activate or deactivate */
- s_pScreenPriv->fActive = wParam;
-
- /* Reshow the Windows mouse cursor if we are being deactivated */
- if (g_fSoftwareCursor && !s_pScreenPriv->fActive
- && !g_fCursor)
- {
- /* Show Windows cursor */
- g_fCursor = TRUE;
- ShowCursor (TRUE);
- }
-
-#ifdef XWIN_CLIPBOARD
- /* Make sure the clipboard chain is ok. */
- winFixClipboardChain ();
-#endif
-
- /* Call engine specific screen activation/deactivation function */
- (*s_pScreenPriv->pwinActivateApp) (s_pScreen);
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- if (s_pScreenPriv->fActive)
- {
- /* Restack all window unless using built-in wm. */
- if (s_pScreenInfo->fInternalWM && s_pScreenInfo->fAnotherWMRunning)
- winMWExtWMRestackWindows (s_pScreen);
- }
-#endif
-
- return 0;
-
- case WM_COMMAND:
- switch (LOWORD (wParam))
- {
- case ID_APP_EXIT:
- /* Display Exit dialog */
- winDisplayExitDialog (s_pScreenPriv);
- return 0;
-
-#ifdef XWIN_MULTIWINDOW
- case ID_APP_HIDE_ROOT:
- if (s_pScreenPriv->fRootWindowShown)
- ShowWindow (s_pScreenPriv->hwndScreen, SW_HIDE);
- else
- ShowWindow (s_pScreenPriv->hwndScreen, SW_SHOW);
- s_pScreenPriv->fRootWindowShown = !s_pScreenPriv->fRootWindowShown;
- return 0;
-#endif
-
- case ID_APP_ABOUT:
- /* Display the About box */
- winDisplayAboutDialog (s_pScreenPriv);
- return 0;
-
- default:
- /* It's probably one of the custom menus... */
- if (HandleCustomWM_COMMAND (0, LOWORD (wParam)))
- return 0;
- }
- break;
-
- case WM_ENDSESSION:
- case WM_GIVEUP:
- /* Tell X that we are giving up */
-#ifdef XWIN_MULTIWINDOW
- if (s_pScreenInfo->fMultiWindow)
- winDeinitMultiWindowWM ();
-#endif
- GiveUp (0);
- return 0;
-
- case WM_CLOSE:
- /* Display Exit dialog */
- winDisplayExitDialog (s_pScreenPriv);
- return 0;
-
- case WM_SETCURSOR:
- if (LOWORD(lParam) == HTCLIENT)
- {
- if (!g_fSoftwareCursor) SetCursor (s_pScreenPriv->cursor.handle);
- return TRUE;
- }
- break;
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- case WM_MANAGE:
- ErrorF ("winWindowProc - WM_MANAGE\n");
- s_pScreenInfo->fAnotherWMRunning = FALSE;
-
- if (s_pScreenInfo->fInternalWM)
- {
- EnumThreadWindows (g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0);
- //RootlessRepositionWindows (s_pScreen);
- }
- break;
-
- case WM_UNMANAGE:
- ErrorF ("winWindowProc - WM_UNMANAGE\n");
- s_pScreenInfo->fAnotherWMRunning = TRUE;
-
- if (s_pScreenInfo->fInternalWM)
- {
- EnumThreadWindows (g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0);
- winMWExtWMRestackWindows (s_pScreen);
- }
- break;
-#endif
-
- default:
- if(message == s_uTaskbarRestart)
- {
- winInitNotifyIcon (s_pScreenPriv);
- }
- break;
- }
-
- return DefWindowProc (hwnd, message, wParam, lParam);
-}
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Dakshinamurthy Karra
+ * Suhaib M Siddiqi
+ * Peter Busch
+ * Harold L Hunt II
+ * MATSUZAKI Kensuke
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include <commctrl.h>
+#include "winprefs.h"
+#include "winconfig.h"
+#include "winmsg.h"
+#include "winmonitors.h"
+#include "inputstr.h"
+
+/*
+ * Global variables
+ */
+
+Bool g_fCursor = TRUE;
+Bool g_fButton[3] = { FALSE, FALSE, FALSE };
+
+
+/*
+ * Called by winWakeupHandler
+ * Processes current Windows message
+ */
+
+LRESULT CALLBACK
+winWindowProc (HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ static winPrivScreenPtr s_pScreenPriv = NULL;
+ static winScreenInfo *s_pScreenInfo = NULL;
+ static ScreenPtr s_pScreen = NULL;
+ static HWND s_hwndLastPrivates = NULL;
+ static HINSTANCE s_hInstance;
+ static Bool s_fTracking = FALSE;
+ static unsigned long s_ulServerGeneration = 0;
+ static UINT s_uTaskbarRestart = 0;
+ int iScanCode;
+ int i;
+
+#if CYGDEBUG
+ winDebugWin32Message("winWindowProc", hwnd, message, wParam, lParam);
+#endif
+
+ /* Watch for server regeneration */
+ if (g_ulServerGeneration != s_ulServerGeneration)
+ {
+ /* Store new server generation */
+ s_ulServerGeneration = g_ulServerGeneration;
+ }
+
+ /* Only retrieve new privates pointers if window handle is null or changed */
+ if ((s_pScreenPriv == NULL || hwnd != s_hwndLastPrivates)
+ && (s_pScreenPriv = GetProp (hwnd, WIN_SCR_PROP)) != NULL)
+ {
+#if CYGDEBUG
+ winDebug ("winWindowProc - Setting privates handle\n");
+#endif
+ s_pScreenInfo = s_pScreenPriv->pScreenInfo;
+ s_pScreen = s_pScreenInfo->pScreen;
+ s_hwndLastPrivates = hwnd;
+ }
+ else if (s_pScreenPriv == NULL)
+ {
+ /* For safety, handle case that should never happen */
+ s_pScreenInfo = NULL;
+ s_pScreen = NULL;
+ s_hwndLastPrivates = NULL;
+ }
+
+ /* Branch on message type */
+ switch (message)
+ {
+ case WM_TRAYICON:
+ return winHandleIconMessage (hwnd, message, wParam, lParam,
+ s_pScreenPriv);
+
+ case WM_CREATE:
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_CREATE\n");
+#endif
+
+ /*
+ * Add a property to our display window that references
+ * this screens' privates.
+ *
+ * This allows the window procedure to refer to the
+ * appropriate window DC and shadow DC for the window that
+ * it is processing. We use this to repaint exposed
+ * areas of our display window.
+ */
+ s_pScreenPriv = ((LPCREATESTRUCT) lParam)->lpCreateParams;
+ s_hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
+ s_pScreenInfo = s_pScreenPriv->pScreenInfo;
+ s_pScreen = s_pScreenInfo->pScreen;
+ s_hwndLastPrivates = hwnd;
+ s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
+ SetProp (hwnd, WIN_SCR_PROP, s_pScreenPriv);
+
+ /* Setup tray icon */
+ if (!s_pScreenInfo->fNoTrayIcon)
+ {
+ /*
+ * NOTE: The WM_CREATE message is processed before CreateWindowEx
+ * returns, so s_pScreenPriv->hwndScreen is invalid at this point.
+ * We go ahead and copy our hwnd parameter over top of the screen
+ * privates hwndScreen so that we have a valid value for
+ * that member. Otherwise, the tray icon will disappear
+ * the first time you move the mouse over top of it.
+ */
+
+ s_pScreenPriv->hwndScreen = hwnd;
+
+ winInitNotifyIcon (s_pScreenPriv);
+ }
+ return 0;
+
+ case WM_DISPLAYCHANGE:
+ /*
+ WM_DISPLAYCHANGE seems to be sent when the monitor layout or
+ any monitor's resolution or depth changes, but it's lParam and
+ wParam always indicate the resolution and bpp for the primary
+ monitor (so ignore that as we could be on any monitor...)
+ */
+
+ /* We cannot handle a display mode change during initialization */
+ if (s_pScreenInfo == NULL)
+ FatalError ("winWindowProc - WM_DISPLAYCHANGE - The display "
+ "mode changed while we were intializing. This is "
+ "very bad and unexpected. Exiting.\n");
+
+ /*
+ * We do not care about display changes with
+ * fullscreen DirectDraw engines, because those engines set
+ * their own mode when they become active.
+ */
+ if (s_pScreenInfo->fFullScreen
+ && (s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
+ || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
+#ifdef XWIN_PRIMARYFB
+ || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD
+#endif
+ ))
+ {
+ break;
+ }
+
+ ErrorF ("winWindowProc - WM_DISPLAYCHANGE - new width: %d "
+ "new height: %d new bpp: %d\n",
+ LOWORD (lParam), HIWORD (lParam), wParam);
+
+ /*
+ * Check for a disruptive change in depth.
+ * We can only display a message for a disruptive depth change,
+ * we cannot do anything to correct the situation.
+ */
+ /*
+ XXX: maybe we need to check if GetSystemMetrics(SM_SAMEDISPLAYFORMAT)
+ has changed as well...
+ */
+ if (s_pScreenInfo->dwBPP != GetDeviceCaps (s_pScreenPriv->hdcScreen, BITSPIXEL))
+ {
+ if ((s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DD
+ || s_pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
+#ifdef XWIN_PRIMARYFB
+ || s_pScreenInfo->dwEngine == WIN_SERVER_PRIMARY_DD
+#endif
+ ))
+ {
+ /* Cannot display the visual until the depth is restored */
+ ErrorF ("winWindowProc - Disruptive change in depth\n");
+
+ /* Display depth change dialog */
+ winDisplayDepthChangeDialog (s_pScreenPriv);
+
+ /* Flag that we have an invalid screen depth */
+ s_pScreenPriv->fBadDepth = TRUE;
+
+ /* Minimize the display window */
+ ShowWindow (hwnd, SW_MINIMIZE);
+ }
+ else
+ {
+ /* For GDI, performance may suffer until original depth is restored */
+ ErrorF ("winWindowProc - Performance may be non-optimal after change in depth\n");
+ }
+ }
+ else
+ {
+ /* Flag that we have a valid screen depth */
+ s_pScreenPriv->fBadDepth = FALSE;
+ }
+
+ /*
+ If we could cheaply check if this WM_DISPLAYCHANGE change
+ affects the monitor(s) which this X screen is displayed on
+ then we should do so here. For the moment, assume it does.
+ (this is probably usually the case so that might be an
+ overoptimization)
+ */
+ {
+ /*
+ In rootless modes which are monitor or virtual desktop size
+ use RandR to resize the X screen
+ */
+ if ((!s_pScreenInfo->fUserGaveHeightAndWidth) &&
+ (s_pScreenInfo->iResizeMode == resizeWithRandr) &&
+ (FALSE
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ || s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOW
+ || s_pScreenInfo->fMultiWindow
+#endif
+ ))
+ {
+ DWORD dwWidth, dwHeight;
+
+ if (s_pScreenInfo->fMultipleMonitors)
+ {
+ /* resize to new virtual desktop size */
+ dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+ }
+ else
+ {
+ /* resize to new size of specified monitor */
+ struct GetMonitorInfoData data;
+ if (QueryMonitor(s_pScreenInfo->iMonitor, &data))
+ {
+ if (data.bMonitorSpecifiedExists == TRUE)
+ {
+ dwWidth = data.monitorWidth;
+ dwHeight = data.monitorHeight;
+ /*
+ XXX: monitor may have changed position,
+ so we might need to update xinerama data
+ */
+ }
+ else
+ {
+ ErrorF ("Monitor number %d no longer exists!\n", s_pScreenInfo->iMonitor);
+ }
+ }
+ }
+
+ /*
+ XXX: probably a small bug here: we don't compute the work area
+ and allow for task bar
+
+ XXX: generally, we don't allow for the task bar being moved after
+ the server is started
+ */
+
+ /* Set screen size to match new size, if it is different to current */
+ if ((s_pScreenInfo->dwWidth != dwWidth) ||
+ (s_pScreenInfo->dwHeight != dwHeight))
+ {
+ winDoRandRScreenSetSize(s_pScreen,
+ dwWidth,
+ dwHeight,
+ (dwWidth * 25.4) / monitorResolution,
+ (dwHeight * 25.4) / monitorResolution);
+ }
+ }
+ else
+ {
+ /*
+ * We can simply recreate the same-sized primary surface when
+ * the display dimensions change.
+ */
+
+ /*
+ * NOTE: The non-DirectDraw engines set the ReleasePrimarySurface
+ * and CreatePrimarySurface function pointers to point
+ * to the no operation function, NoopDDA. This allows us
+ * to blindly call these functions, even if they are not
+ * relevant to the current engine (e.g., Shadow GDI).
+ */
+
+ winDebug ("winWindowProc - WM_DISPLAYCHANGE - Releasing and recreating primary surface\n");
+
+ /* Release the old primary surface */
+ (*s_pScreenPriv->pwinReleasePrimarySurface) (s_pScreen);
+
+ /* Create the new primary surface */
+ (*s_pScreenPriv->pwinCreatePrimarySurface) (s_pScreen);
+ }
+ }
+
+ break;
+
+ case WM_SIZE:
+ {
+ SCROLLINFO si;
+ RECT rcWindow;
+ int iWidth, iHeight;
+
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_SIZE\n");
+#endif
+
+ /* Break if we do not allow resizing */
+ if ((s_pScreenInfo->iResizeMode == notAllowed)
+ || !s_pScreenInfo->fDecoration
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ || s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOW
+ || s_pScreenInfo->fMultiWindow
+#endif
+ || s_pScreenInfo->fFullScreen)
+ break;
+
+ /* No need to resize if we get minimized */
+ if (wParam == SIZE_MINIMIZED)
+ return 0;
+
+ ErrorF ("winWindowProc - WM_SIZE - new client area w: %d h: %d\n",
+ LOWORD (lParam), HIWORD (lParam));
+
+ if (s_pScreenInfo->iResizeMode == resizeWithRandr)
+ {
+ /* Actual resizing is done on WM_EXITSIZEMOVE */
+ return 0;
+ }
+
+ /* Otherwise iResizeMode == resizeWithScrollbars */
+
+ /*
+ * Get the size of the whole window, including client area,
+ * scrollbars, and non-client area decorations (caption, borders).
+ * We do this because we need to check if the client area
+ * without scrollbars is large enough to display the whole visual.
+ * The new client area size passed by lParam already subtracts
+ * the size of the scrollbars if they are currently displayed.
+ * So checking is LOWORD(lParam) == visual_width and
+ * HIWORD(lParam) == visual_height will never tell us to hide
+ * the scrollbars because the client area would always be too small.
+ * GetClientRect returns the same sizes given by lParam, so we
+ * cannot use GetClientRect either.
+ */
+ GetWindowRect (hwnd, &rcWindow);
+ iWidth = rcWindow.right - rcWindow.left;
+ iHeight = rcWindow.bottom - rcWindow.top;
+
+ /* Subtract the frame size from the window size. */
+ iWidth -= 2 * GetSystemMetrics (SM_CXSIZEFRAME);
+ iHeight -= (2 * GetSystemMetrics (SM_CYSIZEFRAME)
+ + GetSystemMetrics (SM_CYCAPTION));
+
+ /*
+ * Update scrollbar page sizes.
+ * NOTE: If page size == range, then the scrollbar is
+ * automatically hidden.
+ */
+
+ /* Is the naked client area large enough to show the whole visual? */
+ if (iWidth < s_pScreenInfo->dwWidth
+ || iHeight < s_pScreenInfo->dwHeight)
+ {
+ /* Client area too small to display visual, use scrollbars */
+ iWidth -= GetSystemMetrics (SM_CXVSCROLL);
+ iHeight -= GetSystemMetrics (SM_CYHSCROLL);
+ }
+
+ /* Set the horizontal scrollbar page size */
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_PAGE | SIF_RANGE;
+ si.nMin = 0;
+ si.nMax = s_pScreenInfo->dwWidth - 1;
+ si.nPage = iWidth;
+ SetScrollInfo (hwnd, SB_HORZ, &si, TRUE);
+
+ /* Set the vertical scrollbar page size */
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_PAGE | SIF_RANGE;
+ si.nMin = 0;
+ si.nMax = s_pScreenInfo->dwHeight - 1;
+ si.nPage = iHeight;
+ SetScrollInfo (hwnd, SB_VERT, &si, TRUE);
+
+ /*
+ * NOTE: Scrollbars may have moved if they were at the
+ * far right/bottom, so we query their current position.
+ */
+
+ /* Get the horizontal scrollbar position and set the offset */
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
+ GetScrollInfo (hwnd, SB_HORZ, &si);
+ s_pScreenInfo->dwXOffset = -si.nPos;
+
+ /* Get the vertical scrollbar position and set the offset */
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
+ GetScrollInfo (hwnd, SB_VERT, &si);
+ s_pScreenInfo->dwYOffset = -si.nPos;
+ }
+ return 0;
+
+ case WM_ENTERSIZEMOVE:
+ ErrorF("winWindowProc - WM_ENTERSIZEMOVE\n");
+ break;
+
+ case WM_EXITSIZEMOVE:
+ ErrorF("winWindowProc - WM_EXITSIZEMOVE\n");
+
+ if (s_pScreenInfo->iResizeMode == resizeWithRandr)
+ {
+ /* Set screen size to match new client area, if it is different to current */
+ RECT rcClient;
+ DWORD dwWidth, dwHeight;
+
+ GetClientRect (hwnd, &rcClient);
+ dwWidth = rcClient.right - rcClient.left;
+ dwHeight = rcClient.bottom - rcClient.top;
+
+ if ((s_pScreenInfo->dwWidth != dwWidth) ||
+ (s_pScreenInfo->dwHeight != dwHeight))
+ {
+ /* mm = dots * (25.4 mm / inch) / (dots / inch) */
+ winDoRandRScreenSetSize(s_pScreen,
+ dwWidth,
+ dwHeight,
+ (dwWidth * 25.4) / monitorResolution,
+ (dwHeight * 25.4) / monitorResolution);
+ }
+ }
+
+ break;
+
+ case WM_VSCROLL:
+ {
+ SCROLLINFO si;
+ int iVertPos;
+
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_VSCROLL\n");
+#endif
+
+ /* Get vertical scroll bar info */
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_ALL;
+ GetScrollInfo (hwnd, SB_VERT, &si);
+
+ /* Save the vertical position for comparison later */
+ iVertPos = si.nPos;
+
+ /*
+ * Don't forget:
+ * moving the scrollbar to the DOWN, scroll the content UP
+ */
+ switch (LOWORD(wParam))
+ {
+ case SB_TOP:
+ si.nPos = si.nMin;
+ break;
+
+ case SB_BOTTOM:
+ si.nPos = si.nMax - si.nPage + 1;
+ break;
+
+ case SB_LINEUP:
+ si.nPos -= 1;
+ break;
+
+ case SB_LINEDOWN:
+ si.nPos += 1;
+ break;
+
+ case SB_PAGEUP:
+ si.nPos -= si.nPage;
+ break;
+
+ case SB_PAGEDOWN:
+ si.nPos += si.nPage;
+ break;
+
+ case SB_THUMBTRACK:
+ si.nPos = si.nTrackPos;
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * We retrieve the position after setting it,
+ * because Windows may adjust it.
+ */
+ si.fMask = SIF_POS;
+ SetScrollInfo (hwnd, SB_VERT, &si, TRUE);
+ GetScrollInfo (hwnd, SB_VERT, &si);
+
+ /* Scroll the window if the position has changed */
+ if (si.nPos != iVertPos)
+ {
+ /* Save the new offset for bit block transfers, etc. */
+ s_pScreenInfo->dwYOffset = -si.nPos;
+
+ /* Change displayed region in the window */
+ ScrollWindowEx (hwnd,
+ 0,
+ iVertPos - si.nPos,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ SW_INVALIDATE);
+
+ /* Redraw the window contents */
+ UpdateWindow (hwnd);
+ }
+ }
+ return 0;
+
+ case WM_HSCROLL:
+ {
+ SCROLLINFO si;
+ int iHorzPos;
+
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_HSCROLL\n");
+#endif
+
+ /* Get horizontal scroll bar info */
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_ALL;
+ GetScrollInfo (hwnd, SB_HORZ, &si);
+
+ /* Save the horizontal position for comparison later */
+ iHorzPos = si.nPos;
+
+ /*
+ * Don't forget:
+ * moving the scrollbar to the RIGHT, scroll the content LEFT
+ */
+ switch (LOWORD(wParam))
+ {
+ case SB_LEFT:
+ si.nPos = si.nMin;
+ break;
+
+ case SB_RIGHT:
+ si.nPos = si.nMax - si.nPage + 1;
+ break;
+
+ case SB_LINELEFT:
+ si.nPos -= 1;
+ break;
+
+ case SB_LINERIGHT:
+ si.nPos += 1;
+ break;
+
+ case SB_PAGELEFT:
+ si.nPos -= si.nPage;
+ break;
+
+ case SB_PAGERIGHT:
+ si.nPos += si.nPage;
+ break;
+
+ case SB_THUMBTRACK:
+ si.nPos = si.nTrackPos;
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * We retrieve the position after setting it,
+ * because Windows may adjust it.
+ */
+ si.fMask = SIF_POS;
+ SetScrollInfo (hwnd, SB_HORZ, &si, TRUE);
+ GetScrollInfo (hwnd, SB_HORZ, &si);
+
+ /* Scroll the window if the position has changed */
+ if (si.nPos != iHorzPos)
+ {
+ /* Save the new offset for bit block transfers, etc. */
+ s_pScreenInfo->dwXOffset = -si.nPos;
+
+ /* Change displayed region in the window */
+ ScrollWindowEx (hwnd,
+ iHorzPos - si.nPos,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ SW_INVALIDATE);
+
+ /* Redraw the window contents */
+ UpdateWindow (hwnd);
+ }
+ }
+ return 0;
+
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO *pMinMaxInfo = (MINMAXINFO *) lParam;
+ int iCaptionHeight;
+ int iBorderHeight, iBorderWidth;
+
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_GETMINMAXINFO - pScreenInfo: %08x\n",
+ s_pScreenInfo);
+#endif
+
+ /* Can't do anything without screen info */
+ if (s_pScreenInfo == NULL
+ || (s_pScreenInfo->iResizeMode != resizeWithScrollbars)
+ || s_pScreenInfo->fFullScreen
+ || !s_pScreenInfo->fDecoration
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ || s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOW
+ || s_pScreenInfo->fMultiWindow
+#endif
+ )
+ break;
+
+ /*
+ * Here we can override the maximum tracking size, which
+ * is the largest size that can be assigned to our window
+ * via the sizing border.
+ */
+
+ /*
+ * FIXME: Do we only need to do this once, since our visual size
+ * does not change? Does Windows store this value statically
+ * once we have set it once?
+ */
+
+ /* Get the border and caption sizes */
+ iCaptionHeight = GetSystemMetrics (SM_CYCAPTION);
+ iBorderWidth = 2 * GetSystemMetrics (SM_CXSIZEFRAME);
+ iBorderHeight = 2 * GetSystemMetrics (SM_CYSIZEFRAME);
+
+ /* Allow the full visual to be displayed */
+ pMinMaxInfo->ptMaxTrackSize.x
+ = s_pScreenInfo->dwWidth + iBorderWidth;
+ pMinMaxInfo->ptMaxTrackSize.y
+ = s_pScreenInfo->dwHeight + iBorderHeight + iCaptionHeight;
+ }
+ return 0;
+
+ case WM_ERASEBKGND:
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_ERASEBKGND\n");
+#endif
+ /*
+ * Pretend that we did erase the background but we don't care,
+ * the application uses the full window estate. This avoids some
+ * flickering when resizing.
+ */
+ return TRUE;
+
+ case WM_PAINT:
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_PAINT\n");
+#endif
+ /* Only paint if we have privates and the server is enabled */
+ if (s_pScreenPriv == NULL
+ || !s_pScreenPriv->fEnabled
+ || (s_pScreenInfo->fFullScreen && !s_pScreenPriv->fActive)
+ || s_pScreenPriv->fBadDepth)
+ {
+ /* We don't want to paint */
+ break;
+ }
+
+ /* Break out here if we don't have a valid paint routine */
+ if (s_pScreenPriv->pwinBltExposedRegions == NULL)
+ break;
+
+ /* Call the engine dependent repainter */
+ (*s_pScreenPriv->pwinBltExposedRegions) (s_pScreen);
+ return 0;
+
+ case WM_PALETTECHANGED:
+ {
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_PALETTECHANGED\n");
+#endif
+ /*
+ * Don't process if we don't have privates or a colormap,
+ * or if we have an invalid depth.
+ */
+ if (s_pScreenPriv == NULL
+ || s_pScreenPriv->pcmapInstalled == NULL
+ || s_pScreenPriv->fBadDepth)
+ break;
+
+ /* Return if we caused the palette to change */
+ if ((HWND) wParam == hwnd)
+ {
+ /* Redraw the screen */
+ (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
+ return 0;
+ }
+
+ /* Reinstall the windows palette */
+ (*s_pScreenPriv->pwinRealizeInstalledPalette) (s_pScreen);
+
+ /* Redraw the screen */
+ (*s_pScreenPriv->pwinRedrawScreen) (s_pScreen);
+ return 0;
+ }
+
+ case WM_MOUSEMOVE:
+ /* We can't do anything without privates */
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+
+ /* We can't do anything without g_pwinPointer */
+ if (g_pwinPointer == NULL)
+ break;
+
+ /* Has the mouse pointer crossed screens? */
+ if (s_pScreen != miPointerGetScreen(g_pwinPointer))
+ miPointerSetScreen (g_pwinPointer, s_pScreenInfo->dwScreen,
+ GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset,
+ GET_Y_LPARAM(lParam)-s_pScreenInfo->dwYOffset);
+
+ /* Are we tracking yet? */
+ if (!s_fTracking)
+ {
+ TRACKMOUSEEVENT tme;
+
+ /* Setup data structure */
+ ZeroMemory (&tme, sizeof (tme));
+ tme.cbSize = sizeof (tme);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hwnd;
+
+ /* Call the tracking function */
+ if (!(*g_fpTrackMouseEvent) (&tme))
+ ErrorF ("winWindowProc - _TrackMouseEvent failed\n");
+
+ /* Flag that we are tracking now */
+ s_fTracking = TRUE;
+ }
+
+ /* Hide or show the Windows mouse cursor */
+ if (g_fSoftwareCursor && g_fCursor && (s_pScreenPriv->fActive || s_pScreenInfo->fLessPointer))
+ {
+ /* Hide Windows cursor */
+ g_fCursor = FALSE;
+ ShowCursor (FALSE);
+ }
+ else if (g_fSoftwareCursor && !g_fCursor && !s_pScreenPriv->fActive
+ && !s_pScreenInfo->fLessPointer)
+ {
+ /* Show Windows cursor */
+ g_fCursor = TRUE;
+ ShowCursor (TRUE);
+ }
+
+ /* Deliver absolute cursor position to X Server */
+ winEnqueueMotion(GET_X_LPARAM(lParam)-s_pScreenInfo->dwXOffset,
+ GET_Y_LPARAM(lParam)-s_pScreenInfo->dwYOffset);
+ return 0;
+
+ case WM_NCMOUSEMOVE:
+ /*
+ * We break instead of returning 0 since we need to call
+ * DefWindowProc to get the mouse cursor changes
+ * and min/max/close button highlighting in Windows XP.
+ * The Platform SDK says that you should return 0 if you
+ * process this message, but it fails to mention that you
+ * will give up any default functionality if you do return 0.
+ */
+
+ /* We can't do anything without privates */
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+
+ /* Non-client mouse movement, show Windows cursor */
+ if (g_fSoftwareCursor && !g_fCursor)
+ {
+ g_fCursor = TRUE;
+ ShowCursor (TRUE);
+ }
+ break;
+
+ case WM_MOUSELEAVE:
+ /* Mouse has left our client area */
+
+ /* Flag that we are no longer tracking */
+ s_fTracking = FALSE;
+
+ /* Show the mouse cursor, if necessary */
+ if (g_fSoftwareCursor && !g_fCursor)
+ {
+ g_fCursor = TRUE;
+ ShowCursor (TRUE);
+ }
+ return 0;
+
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONDOWN:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+ if (s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ )
+ SetCapture (hwnd);
+ return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam);
+
+ case WM_LBUTTONUP:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+ if (s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ )
+ ReleaseCapture ();
+ return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam);
+
+ case WM_MBUTTONDBLCLK:
+ case WM_MBUTTONDOWN:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+ if (s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ )
+ SetCapture (hwnd);
+ return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam);
+
+ case WM_MBUTTONUP:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+ if (s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ )
+ ReleaseCapture ();
+ return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam);
+
+ case WM_RBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+ if (s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ )
+ SetCapture (hwnd);
+ return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam);
+
+ case WM_RBUTTONUP:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+ if (s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ )
+ ReleaseCapture ();
+ return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam);
+
+ case WM_XBUTTONDBLCLK:
+ case WM_XBUTTONDOWN:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+ if (s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ )
+ SetCapture (hwnd);
+ return winMouseButtonsHandle (s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
+ case WM_XBUTTONUP:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+ if (s_pScreenInfo->fRootless
+#ifdef XWIN_MULTIWINDOWEXTWM
+ || s_pScreenInfo->fMWExtWM
+#endif
+ )
+ ReleaseCapture ();
+ return winMouseButtonsHandle (s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
+
+ case WM_TIMER:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+
+ /* Branch on the timer id */
+ switch (wParam)
+ {
+ case WIN_E3B_TIMER_ID:
+ /* Send delayed button press */
+ winMouseButtonsSendEvent (ButtonPress,
+ s_pScreenPriv->iE3BCachedPress);
+
+ /* Kill this timer */
+ KillTimer (s_pScreenPriv->hwndScreen, WIN_E3B_TIMER_ID);
+
+ /* Clear screen privates flags */
+ s_pScreenPriv->iE3BCachedPress = 0;
+ break;
+
+ case WIN_POLLING_MOUSE_TIMER_ID:
+ {
+ POINT point;
+ WPARAM wL, wM, wR, wShift, wCtrl;
+ LPARAM lPos;
+
+ /* Get the current position of the mouse cursor */
+ GetCursorPos (&point);
+
+ /* Map from screen (-X, -Y) to root (0, 0) */
+ point.x -= GetSystemMetrics (SM_XVIRTUALSCREEN);
+ point.y -= GetSystemMetrics (SM_YVIRTUALSCREEN);
+
+ /* Deliver absolute cursor position to X Server */
+ winEnqueueMotion(point.x , point.y);
+
+ /* Check if a button was released but we didn't see it */
+ GetCursorPos (&point);
+ wL = (GetKeyState (VK_LBUTTON) & 0x8000)?MK_LBUTTON:0;
+ wM = (GetKeyState (VK_MBUTTON) & 0x8000)?MK_MBUTTON:0;
+ wR = (GetKeyState (VK_RBUTTON) & 0x8000)?MK_RBUTTON:0;
+ wShift = (GetKeyState (VK_SHIFT) & 0x8000)?MK_SHIFT:0;
+ wCtrl = (GetKeyState (VK_CONTROL) & 0x8000)?MK_CONTROL:0;
+ lPos = MAKELPARAM(point.x, point.y);
+ if (g_fButton[0] & !wL)
+ PostMessage (hwnd, WM_LBUTTONUP, wCtrl|wM|wR|wShift, lPos);
+ if (g_fButton[1] & !wM)
+ PostMessage (hwnd, WM_MBUTTONUP, wCtrl|wL|wR|wShift, lPos);
+ if (g_fButton[2] & !wR)
+ PostMessage (hwnd, WM_RBUTTONUP, wCtrl|wL|wM|wShift, lPos);
+ }
+ }
+ return 0;
+
+ case WM_CTLCOLORSCROLLBAR:
+ FatalError ("winWindowProc - WM_CTLCOLORSCROLLBAR - We are not "
+ "supposed to get this message. Exiting.\n");
+ return 0;
+
+ case WM_MOUSEWHEEL:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_MOUSEWHEEL\n");
+#endif
+ winMouseWheel (s_pScreen, GET_WHEEL_DELTA_WPARAM(wParam));
+ break;
+
+ case WM_SETFOCUS:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+
+ /* Restore the state of all mode keys */
+ winRestoreModeKeyStates ();
+
+ /* Add the keyboard hook if possible */
+ if (g_fKeyboardHookLL)
+ g_fKeyboardHookLL = winInstallKeyboardHookLL ();
+ return 0;
+
+ case WM_KILLFOCUS:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+
+ /* Release any pressed keys */
+ winKeybdReleaseKeys ();
+
+ /* Remove our keyboard hook if it is installed */
+ winRemoveKeyboardHookLL ();
+ return 0;
+
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+
+ /*
+ * FIXME: Catching Alt-F4 like this is really terrible. This should
+ * be generalized to handle other Windows keyboard signals. Actually,
+ * the list keys to catch and the actions to perform when caught should
+ * be configurable; that way user's can customize the keys that they
+ * need to have passed through to their window manager or apps, or they
+ * can remap certain actions to new key codes that do not conflict
+ * with the X apps that they are using. Yeah, that'll take awhile.
+ */
+ if ((s_pScreenInfo->fUseWinKillKey && wParam == VK_F4
+ && (GetKeyState (VK_MENU) & 0x8000))
+ || (s_pScreenInfo->fUseUnixKillKey && wParam == VK_BACK
+ && (GetKeyState (VK_MENU) & 0x8000)
+ && (GetKeyState (VK_CONTROL) & 0x8000)))
+ {
+ /*
+ * Better leave this message here, just in case some unsuspecting
+ * user enters Alt + F4 and is surprised when the application
+ * quits.
+ */
+ ErrorF ("winWindowProc - WM_*KEYDOWN - Closekey hit, quitting\n");
+
+ /* Display Exit dialog */
+ winDisplayExitDialog (s_pScreenPriv);
+ return 0;
+ }
+
+ /*
+ * Don't do anything for the Windows keys, as focus will soon
+ * be returned to Windows. We may be able to trap the Windows keys,
+ * but we should determine if that is desirable before doing so.
+ */
+ if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
+ break;
+
+ /*
+ * Discard presses generated from Windows auto-repeat
+ */
+ if (lParam & (1<<30))
+ {
+ switch (wParam)
+ {
+ /* ago: Pressing LControl while RControl is pressed is
+ * Indicated as repeat. Fix this!
+ */
+ case VK_CONTROL:
+ case VK_SHIFT:
+ if (winCheckKeyPressed(wParam, lParam))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ /* Discard fake Ctrl_L presses that precede AltGR on non-US keyboards */
+ if (winIsFakeCtrl_L (message, wParam, lParam))
+ return 0;
+
+ /* Translate Windows key code to X scan code */
+ winTranslateKey (wParam, lParam, &iScanCode);
+
+ /* Ignore repeats for CapsLock */
+ if (wParam == VK_CAPITAL)
+ lParam = 1;
+
+ /* Send the key event(s) */
+ for (i = 0; i < LOWORD(lParam); ++i)
+ winSendKeyEvent (iScanCode, TRUE);
+ return 0;
+
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
+ break;
+
+ /*
+ * Don't do anything for the Windows keys, as focus will soon
+ * be returned to Windows. We may be able to trap the Windows keys,
+ * but we should determine if that is desirable before doing so.
+ */
+ if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
+ break;
+
+ /* Ignore the fake Ctrl_L that follows an AltGr release */
+ if (winIsFakeCtrl_L (message, wParam, lParam))
+ return 0;
+
+ /* Enqueue a keyup event */
+ winTranslateKey (wParam, lParam, &iScanCode);
+ winSendKeyEvent (iScanCode, FALSE);
+
+ /* Release all pressed shift keys */
+ if (wParam == VK_SHIFT)
+ winFixShiftKeys (iScanCode);
+ return 0;
+
+ case WM_HOTKEY:
+ if (s_pScreenPriv == NULL)
+ break;
+
+ /* Call the engine-specific hot key handler */
+ (*s_pScreenPriv->pwinHotKeyAltTab) (s_pScreen);
+ return 0;
+
+ case WM_ACTIVATE:
+ if (s_pScreenPriv == NULL
+ || s_pScreenInfo->fIgnoreInput)
+ break;
+
+ /* TODO: Override display of window when we have a bad depth */
+ if (LOWORD(wParam) != WA_INACTIVE && s_pScreenPriv->fBadDepth)
+ {
+ ErrorF ("winWindowProc - WM_ACTIVATE - Bad depth, trying "
+ "to override window activation\n");
+
+ /* Minimize the window */
+ ShowWindow (hwnd, SW_MINIMIZE);
+
+ /* Display dialog box */
+ if (g_hDlgDepthChange != NULL)
+ {
+ /* Make the existing dialog box active */
+ SetActiveWindow (g_hDlgDepthChange);
+ }
+ else
+ {
+ /* TODO: Recreate the dialog box and bring to the top */
+ ShowWindow (g_hDlgDepthChange, SW_SHOWDEFAULT);
+ }
+
+ /* Don't do any other processing of this message */
+ return 0;
+ }
+
+#if CYGDEBUG
+ winDebug ("winWindowProc - WM_ACTIVATE\n");
+#endif
+
+ /*
+ * Focus is being changed to another window.
+ * The other window may or may not belong to
+ * our process.
+ */
+
+ /* Clear any lingering wheel delta */
+ s_pScreenPriv->iDeltaZ = 0;
+
+ /* Reshow the Windows mouse cursor if we are being deactivated */
+ if (g_fSoftwareCursor && LOWORD(wParam) == WA_INACTIVE
+ && !g_fCursor)
+ {
+ /* Show Windows cursor */
+ g_fCursor = TRUE;
+ ShowCursor (TRUE);
+ }
+ return 0;
+
+ case WM_ACTIVATEAPP:
+ if (s_pScreenPriv == NULL
+ || s_pScreenInfo->fIgnoreInput)
+ break;
+
+#if CYGDEBUG || TRUE
+ winDebug ("winWindowProc - WM_ACTIVATEAPP\n");
+#endif
+
+ /* Activate or deactivate */
+ s_pScreenPriv->fActive = wParam;
+
+ /* Reshow the Windows mouse cursor if we are being deactivated */
+ if (g_fSoftwareCursor && !s_pScreenPriv->fActive
+ && !g_fCursor)
+ {
+ /* Show Windows cursor */
+ g_fCursor = TRUE;
+ ShowCursor (TRUE);
+ }
+
+#ifdef XWIN_CLIPBOARD
+ /* Make sure the clipboard chain is ok. */
+ winFixClipboardChain ();
+#endif
+
+ /* Call engine specific screen activation/deactivation function */
+ (*s_pScreenPriv->pwinActivateApp) (s_pScreen);
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ if (s_pScreenPriv->fActive)
+ {
+ /* Restack all window unless using built-in wm. */
+ if (s_pScreenInfo->fInternalWM && s_pScreenInfo->fAnotherWMRunning)
+ winMWExtWMRestackWindows (s_pScreen);
+ }
+#endif
+
+ return 0;
+
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case ID_APP_EXIT:
+ /* Display Exit dialog */
+ winDisplayExitDialog (s_pScreenPriv);
+ return 0;
+
+#ifdef XWIN_MULTIWINDOW
+ case ID_APP_HIDE_ROOT:
+ if (s_pScreenPriv->fRootWindowShown)
+ ShowWindow (s_pScreenPriv->hwndScreen, SW_HIDE);
+ else
+ ShowWindow (s_pScreenPriv->hwndScreen, SW_SHOW);
+ s_pScreenPriv->fRootWindowShown = !s_pScreenPriv->fRootWindowShown;
+ return 0;
+#endif
+
+ case ID_APP_ABOUT:
+ /* Display the About box */
+ winDisplayAboutDialog (s_pScreenPriv);
+ return 0;
+
+ default:
+ /* It's probably one of the custom menus... */
+ if (HandleCustomWM_COMMAND (0, LOWORD (wParam)))
+ return 0;
+ }
+ break;
+
+ case WM_ENDSESSION:
+ case WM_GIVEUP:
+ /* Tell X that we are giving up */
+#ifdef XWIN_MULTIWINDOW
+ if (s_pScreenInfo->fMultiWindow)
+ winDeinitMultiWindowWM ();
+#endif
+ GiveUp (0);
+ return 0;
+
+ case WM_CLOSE:
+ /* Display Exit dialog */
+ winDisplayExitDialog (s_pScreenPriv);
+ return 0;
+
+ case WM_SETCURSOR:
+ if (LOWORD(lParam) == HTCLIENT)
+ {
+ if (!g_fSoftwareCursor) SetCursor (s_pScreenPriv->cursor.handle);
+ return TRUE;
+ }
+ break;
+
+#ifdef XWIN_MULTIWINDOWEXTWM
+ case WM_MANAGE:
+ ErrorF ("winWindowProc - WM_MANAGE\n");
+ s_pScreenInfo->fAnotherWMRunning = FALSE;
+
+ if (s_pScreenInfo->fInternalWM)
+ {
+ EnumThreadWindows (g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0);
+ //RootlessRepositionWindows (s_pScreen);
+ }
+ break;
+
+ case WM_UNMANAGE:
+ ErrorF ("winWindowProc - WM_UNMANAGE\n");
+ s_pScreenInfo->fAnotherWMRunning = TRUE;
+
+ if (s_pScreenInfo->fInternalWM)
+ {
+ EnumThreadWindows (g_dwCurrentThreadID, winMWExtWMDecorateWindow, 0);
+ winMWExtWMRestackWindows (s_pScreen);
+ }
+ break;
+#endif
+
+ default:
+ if(message == s_uTaskbarRestart)
+ {
+ winInitNotifyIcon (s_pScreenPriv);
+ }
+ break;
+ }
+
+ return DefWindowProc (hwnd, message, wParam, lParam);
+}
diff --git a/xorg-server/include/dix.h b/xorg-server/include/dix.h
index ac19a9536..12e4b5977 100644
--- a/xorg-server/include/dix.h
+++ b/xorg-server/include/dix.h
@@ -1,602 +1,609 @@
-/***********************************************************
-
-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 DIX_H
-#define DIX_H
-
-#include "callback.h"
-#include "gc.h"
-#include "window.h"
-#include "input.h"
-#include "cursor.h"
-#include "geext.h"
-#include "events.h"
-#include <X11/extensions/XI.h>
-
-#define EARLIER -1
-#define SAMETIME 0
-#define LATER 1
-
-#define NullClient ((ClientPtr) 0)
-#define REQUEST(type) \
- type *stuff = (type *)client->requestBuffer
-
-
-#define REQUEST_SIZE_MATCH(req)\
- if ((sizeof(req) >> 2) != client->req_len)\
- return(BadLength)
-
-#define REQUEST_AT_LEAST_SIZE(req) \
- if ((sizeof(req) >> 2) > client->req_len )\
- return(BadLength)
-
-#define REQUEST_FIXED_SIZE(req, n)\
- if (((sizeof(req) >> 2) > client->req_len) || \
- (((sizeof(req) + (n) + 3) >> 2) != client->req_len)) \
- return(BadLength)
-
-#define LEGAL_NEW_RESOURCE(id,client)\
- if (!LegalNewID(id,client)) \
- {\
- client->errorValue = id;\
- return BadIDChoice;\
- }
-
-#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, mode)\
- {\
- int rc = dixLookupDrawable(&(pDraw), drawID, client, M_ANY, mode);\
- if (rc != Success)\
- return rc;\
- rc = dixLookupGC(&(pGC), stuff->gc, client, DixUseAccess);\
- if (rc != Success)\
- return rc;\
- if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen))\
- return BadMatch;\
- }\
- if (pGC->serialNumber != pDraw->serialNumber)\
- ValidateGC(pDraw, pGC);
-
-
-#define WriteReplyToClient(pClient, size, pReply) { \
- if ((pClient)->swapped) \
- (*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \
- (pClient, (int)(size), pReply); \
- else (void) WriteToClient(pClient, (int)(size), (char *)(pReply)); }
-
-#define WriteSwappedDataToClient(pClient, size, pbuf) \
- if ((pClient)->swapped) \
- (*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \
- else (void) WriteToClient (pClient, (int)(size), (char *)(pbuf));
-
-typedef struct _TimeStamp *TimeStampPtr;
-
-#ifndef _XTYPEDEF_CLIENTPTR
-typedef struct _Client *ClientPtr; /* also in misc.h */
-#define _XTYPEDEF_CLIENTPTR
-#endif
-
-typedef struct _WorkQueue *WorkQueuePtr;
-
-extern _X_EXPORT ClientPtr clients[MAXCLIENTS];
-extern _X_EXPORT ClientPtr serverClient;
-extern _X_EXPORT int currentMaxClients;
-extern _X_EXPORT char dispatchExceptionAtReset;
-
-typedef int HWEventQueueType;
-typedef HWEventQueueType* HWEventQueuePtr;
-
-extern _X_EXPORT HWEventQueuePtr checkForInput[2];
-
-typedef struct _TimeStamp {
- CARD32 months; /* really ~49.7 days */
- CARD32 milliseconds;
-} TimeStamp;
-
-/* dispatch.c */
-
-extern _X_EXPORT void SetInputCheck(
- HWEventQueuePtr /*c0*/,
- HWEventQueuePtr /*c1*/);
-
-extern _X_EXPORT void CloseDownClient(
- ClientPtr /*client*/);
-
-extern _X_EXPORT void UpdateCurrentTime(void);
-
-extern _X_EXPORT void UpdateCurrentTimeIf(void);
-
-extern _X_EXPORT int dixDestroyPixmap(
- pointer /*value*/,
- XID /*pid*/);
-
-extern _X_EXPORT void InitClient(
- ClientPtr /*client*/,
- int /*i*/,
- pointer /*ospriv*/);
-
-extern _X_EXPORT ClientPtr NextAvailableClient(
- pointer /*ospriv*/);
-
-extern _X_EXPORT void SendErrorToClient(
- ClientPtr /*client*/,
- unsigned int /*majorCode*/,
- unsigned int /*minorCode*/,
- XID /*resId*/,
- int /*errorCode*/);
-
-extern _X_EXPORT void MarkClientException(
- ClientPtr /*client*/);
-
-extern _X_HIDDEN Bool CreateConnectionBlock(void);
-/* dixutils.c */
-
-extern _X_EXPORT int CompareISOLatin1Lowered(
- unsigned char * /*a*/,
- int alen,
- unsigned char * /*b*/,
- int blen);
-
-extern _X_EXPORT int dixLookupWindow(
- WindowPtr *result,
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-extern _X_EXPORT int dixLookupDrawable(
- DrawablePtr *result,
- XID id,
- ClientPtr client,
- Mask type_mask,
- Mask access_mode);
-
-extern _X_EXPORT int dixLookupGC(
- GCPtr *result,
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-extern _X_EXPORT int dixLookupFontable(
- FontPtr *result,
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-extern _X_EXPORT int dixLookupClient(
- ClientPtr *result,
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-extern _X_EXPORT void NoopDDA(void);
-
-extern _X_EXPORT int AlterSaveSetForClient(
- ClientPtr /*client*/,
- WindowPtr /*pWin*/,
- unsigned /*mode*/,
- Bool /*toRoot*/,
- Bool /*map*/);
-
-extern _X_EXPORT void DeleteWindowFromAnySaveSet(
- WindowPtr /*pWin*/);
-
-extern _X_EXPORT void BlockHandler(
- pointer /*pTimeout*/,
- pointer /*pReadmask*/);
-
-extern _X_EXPORT void WakeupHandler(
- int /*result*/,
- pointer /*pReadmask*/);
-
-void
-EnableLimitedSchedulingLatency(void);
-
-void
-DisableLimitedSchedulingLatency(void);
-
-typedef void (* WakeupHandlerProcPtr)(
- pointer /* blockData */,
- int /* result */,
- pointer /* pReadmask */);
-
-extern _X_EXPORT Bool RegisterBlockAndWakeupHandlers(
- BlockHandlerProcPtr /*blockHandler*/,
- WakeupHandlerProcPtr /*wakeupHandler*/,
- pointer /*blockData*/);
-
-extern _X_EXPORT void RemoveBlockAndWakeupHandlers(
- BlockHandlerProcPtr /*blockHandler*/,
- WakeupHandlerProcPtr /*wakeupHandler*/,
- pointer /*blockData*/);
-
-extern _X_EXPORT void InitBlockAndWakeupHandlers(void);
-
-extern _X_EXPORT void ProcessWorkQueue(void);
-
-extern _X_EXPORT void ProcessWorkQueueZombies(void);
-
-extern _X_EXPORT Bool QueueWorkProc(
- Bool (* /*function*/)(
- ClientPtr /*clientUnused*/,
- pointer /*closure*/),
- ClientPtr /*client*/,
- pointer /*closure*/
-);
-
-typedef Bool (* ClientSleepProcPtr)(
- ClientPtr /*client*/,
- pointer /*closure*/);
-
-extern _X_EXPORT Bool ClientSleep(
- ClientPtr /*client*/,
- ClientSleepProcPtr /* function */,
- pointer /*closure*/);
-
-#ifndef ___CLIENTSIGNAL_DEFINED___
-#define ___CLIENTSIGNAL_DEFINED___
-extern _X_EXPORT Bool ClientSignal(
- ClientPtr /*client*/);
-#endif /* ___CLIENTSIGNAL_DEFINED___ */
-
-extern _X_EXPORT void ClientWakeup(
- ClientPtr /*client*/);
-
-extern _X_EXPORT Bool ClientIsAsleep(
- ClientPtr /*client*/);
-
-/* atom.c */
-
-extern _X_EXPORT Atom MakeAtom(
- const char * /*string*/,
- unsigned /*len*/,
- Bool /*makeit*/);
-
-extern _X_EXPORT Bool ValidAtom(
- Atom /*atom*/);
-
-extern _X_EXPORT const char *NameForAtom(
- Atom /*atom*/);
-
-extern _X_EXPORT void AtomError(void) _X_NORETURN;
-
-extern _X_EXPORT void FreeAllAtoms(void);
-
-extern _X_EXPORT void InitAtoms(void);
-
-/* main.c */
-
-extern _X_EXPORT void SetVendorRelease(int release);
-
-extern _X_EXPORT void SetVendorString(char *string);
-
-/* events.c */
-
-extern void SetMaskForEvent(
- int /* deviceid */,
- Mask /* mask */,
- int /* event */);
-
-extern _X_EXPORT void ConfineToShape(
- DeviceIntPtr /* pDev */,
- RegionPtr /* shape */,
- int* /* px */,
- int* /* py */);
-
-extern _X_EXPORT Bool IsParent(
- WindowPtr /* maybeparent */,
- WindowPtr /* child */);
-
-extern _X_EXPORT WindowPtr GetCurrentRootWindow(DeviceIntPtr pDev);
-
-extern _X_EXPORT WindowPtr GetSpriteWindow(DeviceIntPtr pDev);
-
-
-extern _X_EXPORT void NoticeEventTime(InternalEvent *ev);
-
-extern void EnqueueEvent(
- InternalEvent * /* ev */,
- DeviceIntPtr /* device */);
-
-extern void ActivatePointerGrab(
- DeviceIntPtr /* mouse */,
- GrabPtr /* grab */,
- TimeStamp /* time */,
- Bool /* autoGrab */);
-
-extern void DeactivatePointerGrab(
- DeviceIntPtr /* mouse */);
-
-extern void ActivateKeyboardGrab(
- DeviceIntPtr /* keybd */,
- GrabPtr /* grab */,
- TimeStamp /* time */,
- Bool /* passive */);
-
-extern void DeactivateKeyboardGrab(
- DeviceIntPtr /* keybd */);
-
-extern BOOL ActivateFocusInGrab(
- DeviceIntPtr /* dev */,
- WindowPtr /* old */,
- WindowPtr /* win */);
-
-extern void AllowSome(
- ClientPtr /* client */,
- TimeStamp /* time */,
- DeviceIntPtr /* thisDev */,
- int /* newState */);
-
-extern void ReleaseActiveGrabs(
- ClientPtr client);
-
-extern _X_EXPORT int DeliverEventsToWindow(
- DeviceIntPtr /* pWin */,
- WindowPtr /* pWin */,
- xEventPtr /* pEvents */,
- int /* count */,
- Mask /* filter */,
- GrabPtr /* grab */);
-
-extern int DeliverDeviceEvents(
- WindowPtr /* pWin */,
- InternalEvent* /* event */,
- GrabPtr /* grab */,
- WindowPtr /* stopAt */,
- DeviceIntPtr /* dev */);
-
-extern void InitializeSprite(
- DeviceIntPtr /* pDev */,
- WindowPtr /* pWin */);
-
-extern void UpdateSpriteForScreen(
- DeviceIntPtr /* pDev */,
- ScreenPtr /* pScreen */);
-
-extern _X_EXPORT void WindowHasNewCursor(
- WindowPtr /* pWin */);
-
-extern Bool CheckDeviceGrabs(
- DeviceIntPtr /* device */,
- DeviceEvent* /* event */,
- WindowPtr /* ancestor */);
-
-extern void DeliverFocusedEvent(
- DeviceIntPtr /* keybd */,
- InternalEvent* /* event */,
- WindowPtr /* window */);
-
-extern void DeliverGrabbedEvent(
- InternalEvent* /* event */,
- DeviceIntPtr /* thisDev */,
- Bool /* deactivateGrab */);
-
-extern void FixKeyState(
- DeviceEvent* /* event */,
- DeviceIntPtr /* keybd */);
-
-extern void RecalculateDeliverableEvents(
- WindowPtr /* pWin */);
-
-extern _X_EXPORT int OtherClientGone(
- pointer /* value */,
- XID /* id */);
-
-extern void DoFocusEvents(
- DeviceIntPtr /* dev */,
- WindowPtr /* fromWin */,
- WindowPtr /* toWin */,
- int /* mode */);
-
-extern int SetInputFocus(
- ClientPtr /* client */,
- DeviceIntPtr /* dev */,
- Window /* focusID */,
- CARD8 /* revertTo */,
- Time /* ctime */,
- Bool /* followOK */);
-
-extern int GrabDevice(
- ClientPtr /* client */,
- DeviceIntPtr /* dev */,
- unsigned /* this_mode */,
- unsigned /* other_mode */,
- Window /* grabWindow */,
- unsigned /* ownerEvents */,
- Time /* ctime */,
- GrabMask* /* mask */,
- int /* grabtype */,
- Cursor /* curs */,
- Window /* confineToWin */,
- CARD8 * /* status */);
-
-extern void InitEvents(void);
-
-extern void CloseDownEvents(void);
-
-extern void DeleteWindowFromAnyEvents(
- WindowPtr /* pWin */,
- Bool /* freeResources */);
-
-
-extern Mask EventMaskForClient(
- WindowPtr /* pWin */,
- ClientPtr /* client */);
-
-
-
-extern _X_EXPORT int DeliverEvents(
- WindowPtr /*pWin*/,
- xEventPtr /*xE*/,
- int /*count*/,
- WindowPtr /*otherParent*/);
-
-extern Bool CheckMotion(
- DeviceEvent* /* ev */,
- DeviceIntPtr /* pDev */);
-
-extern _X_EXPORT void WriteEventsToClient(
- ClientPtr /*pClient*/,
- int /*count*/,
- xEventPtr /*events*/);
-
-extern _X_EXPORT int TryClientEvents(
- ClientPtr /*client*/,
- DeviceIntPtr /* device */,
- xEventPtr /*pEvents*/,
- int /*count*/,
- Mask /*mask*/,
- Mask /*filter*/,
- GrabPtr /*grab*/);
-
-extern _X_EXPORT void WindowsRestructured(void);
-
-extern int SetClientPointer(
- ClientPtr /* client */,
- DeviceIntPtr /* device */);
-
-extern _X_EXPORT DeviceIntPtr PickPointer(
- ClientPtr /* client */);
-
-extern _X_EXPORT DeviceIntPtr PickKeyboard(
- ClientPtr /* client */);
-
-extern Bool IsInterferingGrab(
- ClientPtr /* client */,
- DeviceIntPtr /* dev */,
- xEvent* /* events */);
-
-#ifdef PANORAMIX
-extern _X_EXPORT void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
-#endif
-
-#ifdef RANDR
-extern _X_EXPORT void
-ScreenRestructured (ScreenPtr pScreen);
-#endif
-
-extern _X_EXPORT int ffs(int i);
-
-
-/*
- * ServerGrabCallback stuff
- */
-
-extern _X_EXPORT CallbackListPtr ServerGrabCallback;
-
-typedef enum {SERVER_GRABBED, SERVER_UNGRABBED,
- CLIENT_PERVIOUS, CLIENT_IMPERVIOUS } ServerGrabState;
-
-typedef struct {
- ClientPtr client;
- ServerGrabState grabstate;
-} ServerGrabInfoRec;
-
-/*
- * EventCallback stuff
- */
-
-extern _X_EXPORT CallbackListPtr EventCallback;
-
-typedef struct {
- ClientPtr client;
- xEventPtr events;
- int count;
-} EventInfoRec;
-
-/*
- * DeviceEventCallback stuff
- */
-
-extern _X_EXPORT CallbackListPtr DeviceEventCallback;
-
-typedef struct {
- InternalEvent *event;
- DeviceIntPtr device;
-} DeviceEventInfoRec;
-
-extern int XItoCoreType(int xi_type);
-extern Bool DevHasCursor(DeviceIntPtr pDev);
-extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
-extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
-extern Bool IsPointerEvent(InternalEvent *event);
-extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
-
-extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
-extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what);
-extern _X_HIDDEN int CoreKeyboardProc(DeviceIntPtr dev, int what);
-
-
-/*
- * These are deprecated compatibility functions and will be removed soon!
- * Please use the noted replacements instead.
- */
-/* replaced by dixLookupWindow */
-extern _X_EXPORT WindowPtr SecurityLookupWindow(
- XID id,
- ClientPtr client,
- Mask access_mode);
-/* replaced by dixLookupWindow */
-extern _X_EXPORT WindowPtr LookupWindow(
- XID id,
- ClientPtr client);
-
-/* replaced by dixLookupDrawable */
-extern _X_EXPORT pointer SecurityLookupDrawable(
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-/* replaced by dixLookupDrawable */
-extern _X_EXPORT pointer LookupDrawable(
- XID id,
- ClientPtr client);
-
-/* replaced by dixLookupClient */
-extern _X_EXPORT ClientPtr LookupClient(
- XID id,
- ClientPtr client);
-
-#endif /* DIX_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 DIX_H
+#define DIX_H
+
+#include "callback.h"
+#include "gc.h"
+#include "window.h"
+#include "input.h"
+#include "cursor.h"
+#include "geext.h"
+#include "events.h"
+#include <X11/extensions/XI.h>
+
+#define EARLIER -1
+#define SAMETIME 0
+#define LATER 1
+
+#define NullClient ((ClientPtr) 0)
+#define REQUEST(type) \
+ type *stuff = (type *)client->requestBuffer
+
+
+#define REQUEST_SIZE_MATCH(req)\
+ if ((sizeof(req) >> 2) != client->req_len)\
+ return(BadLength)
+
+#define REQUEST_AT_LEAST_SIZE(req) \
+ if ((sizeof(req) >> 2) > client->req_len )\
+ return(BadLength)
+
+#define REQUEST_FIXED_SIZE(req, n)\
+ if (((sizeof(req) >> 2) > client->req_len) || \
+ (((sizeof(req) + (n) + 3) >> 2) != client->req_len)) \
+ return(BadLength)
+
+#define LEGAL_NEW_RESOURCE(id,client)\
+ if (!LegalNewID(id,client)) \
+ {\
+ client->errorValue = id;\
+ return BadIDChoice;\
+ }
+
+#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, mode)\
+ {\
+ int rc = dixLookupDrawable(&(pDraw), drawID, client, M_ANY, mode);\
+ if (rc != Success)\
+ return rc;\
+ rc = dixLookupGC(&(pGC), stuff->gc, client, DixUseAccess);\
+ if (rc != Success)\
+ return rc;\
+ if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen))\
+ return BadMatch;\
+ }\
+ if (pGC->serialNumber != pDraw->serialNumber)\
+ ValidateGC(pDraw, pGC);
+
+
+#define WriteReplyToClient(pClient, size, pReply) { \
+ if ((pClient)->swapped) \
+ (*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \
+ (pClient, (int)(size), pReply); \
+ else (void) WriteToClient(pClient, (int)(size), (char *)(pReply)); }
+
+#define WriteSwappedDataToClient(pClient, size, pbuf) \
+ if ((pClient)->swapped) \
+ (*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \
+ else (void) WriteToClient (pClient, (int)(size), (char *)(pbuf));
+
+typedef struct _TimeStamp *TimeStampPtr;
+
+#ifndef _XTYPEDEF_CLIENTPTR
+typedef struct _Client *ClientPtr; /* also in misc.h */
+#define _XTYPEDEF_CLIENTPTR
+#endif
+
+typedef struct _WorkQueue *WorkQueuePtr;
+
+extern _X_EXPORT ClientPtr clients[MAXCLIENTS];
+extern _X_EXPORT ClientPtr serverClient;
+extern _X_EXPORT int currentMaxClients;
+extern _X_EXPORT char dispatchExceptionAtReset;
+
+typedef int HWEventQueueType;
+typedef HWEventQueueType* HWEventQueuePtr;
+
+extern _X_EXPORT HWEventQueuePtr checkForInput[2];
+
+typedef struct _TimeStamp {
+ CARD32 months; /* really ~49.7 days */
+ CARD32 milliseconds;
+} TimeStamp;
+
+/* dispatch.c */
+
+extern _X_EXPORT void SetInputCheck(
+ HWEventQueuePtr /*c0*/,
+ HWEventQueuePtr /*c1*/);
+
+extern _X_EXPORT void CloseDownClient(
+ ClientPtr /*client*/);
+
+extern _X_EXPORT void UpdateCurrentTime(void);
+
+extern _X_EXPORT void UpdateCurrentTimeIf(void);
+
+extern _X_EXPORT int dixDestroyPixmap(
+ pointer /*value*/,
+ XID /*pid*/);
+
+extern _X_EXPORT void InitClient(
+ ClientPtr /*client*/,
+ int /*i*/,
+ pointer /*ospriv*/);
+
+extern _X_EXPORT ClientPtr NextAvailableClient(
+ pointer /*ospriv*/);
+
+extern _X_EXPORT void SendErrorToClient(
+ ClientPtr /*client*/,
+ unsigned int /*majorCode*/,
+ unsigned int /*minorCode*/,
+ XID /*resId*/,
+ int /*errorCode*/);
+
+extern _X_EXPORT void MarkClientException(
+ ClientPtr /*client*/);
+
+extern _X_HIDDEN Bool CreateConnectionBlock(void);
+/* dixutils.c */
+
+extern _X_EXPORT int CompareISOLatin1Lowered(
+ unsigned char * /*a*/,
+ int alen,
+ unsigned char * /*b*/,
+ int blen);
+
+extern _X_EXPORT int dixLookupWindow(
+ WindowPtr *result,
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+extern _X_EXPORT int dixLookupDrawable(
+ DrawablePtr *result,
+ XID id,
+ ClientPtr client,
+ Mask type_mask,
+ Mask access_mode);
+
+extern _X_EXPORT int dixLookupGC(
+ GCPtr *result,
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+extern _X_EXPORT int dixLookupFontable(
+ FontPtr *result,
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+extern _X_EXPORT int dixLookupClient(
+ ClientPtr *result,
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+extern _X_EXPORT void NoopDDA(void);
+
+extern _X_EXPORT int AlterSaveSetForClient(
+ ClientPtr /*client*/,
+ WindowPtr /*pWin*/,
+ unsigned /*mode*/,
+ Bool /*toRoot*/,
+ Bool /*map*/);
+
+extern _X_EXPORT void DeleteWindowFromAnySaveSet(
+ WindowPtr /*pWin*/);
+
+extern _X_EXPORT void BlockHandler(
+ pointer /*pTimeout*/,
+ pointer /*pReadmask*/);
+
+extern _X_EXPORT void WakeupHandler(
+ int /*result*/,
+ pointer /*pReadmask*/);
+
+void
+EnableLimitedSchedulingLatency(void);
+
+void
+DisableLimitedSchedulingLatency(void);
+
+typedef void (* WakeupHandlerProcPtr)(
+ pointer /* blockData */,
+ int /* result */,
+ pointer /* pReadmask */);
+
+extern _X_EXPORT Bool RegisterBlockAndWakeupHandlers(
+ BlockHandlerProcPtr /*blockHandler*/,
+ WakeupHandlerProcPtr /*wakeupHandler*/,
+ pointer /*blockData*/);
+
+extern _X_EXPORT void RemoveBlockAndWakeupHandlers(
+ BlockHandlerProcPtr /*blockHandler*/,
+ WakeupHandlerProcPtr /*wakeupHandler*/,
+ pointer /*blockData*/);
+
+extern _X_EXPORT void InitBlockAndWakeupHandlers(void);
+
+extern _X_EXPORT void ProcessWorkQueue(void);
+
+extern _X_EXPORT void ProcessWorkQueueZombies(void);
+
+extern _X_EXPORT Bool QueueWorkProc(
+ Bool (* /*function*/)(
+ ClientPtr /*clientUnused*/,
+ pointer /*closure*/),
+ ClientPtr /*client*/,
+ pointer /*closure*/
+);
+
+typedef Bool (* ClientSleepProcPtr)(
+ ClientPtr /*client*/,
+ pointer /*closure*/);
+
+extern _X_EXPORT Bool ClientSleep(
+ ClientPtr /*client*/,
+ ClientSleepProcPtr /* function */,
+ pointer /*closure*/);
+
+#ifndef ___CLIENTSIGNAL_DEFINED___
+#define ___CLIENTSIGNAL_DEFINED___
+extern _X_EXPORT Bool ClientSignal(
+ ClientPtr /*client*/);
+#endif /* ___CLIENTSIGNAL_DEFINED___ */
+
+extern _X_EXPORT void ClientWakeup(
+ ClientPtr /*client*/);
+
+extern _X_EXPORT Bool ClientIsAsleep(
+ ClientPtr /*client*/);
+
+/* atom.c */
+
+extern _X_EXPORT Atom MakeAtom(
+ const char * /*string*/,
+ unsigned /*len*/,
+ Bool /*makeit*/);
+
+extern _X_EXPORT Bool ValidAtom(
+ Atom /*atom*/);
+
+extern _X_EXPORT const char *NameForAtom(
+ Atom /*atom*/);
+
+extern _X_EXPORT void AtomError(void) _X_NORETURN;
+
+extern _X_EXPORT void FreeAllAtoms(void);
+
+extern _X_EXPORT void InitAtoms(void);
+
+/* main.c */
+
+extern _X_EXPORT void SetVendorRelease(int release);
+
+extern _X_EXPORT void SetVendorString(char *string);
+
+/* events.c */
+
+extern void SetMaskForEvent(
+ int /* deviceid */,
+ Mask /* mask */,
+ int /* event */);
+
+extern _X_EXPORT void ConfineToShape(
+ DeviceIntPtr /* pDev */,
+ RegionPtr /* shape */,
+ int* /* px */,
+ int* /* py */);
+
+extern _X_EXPORT Bool IsParent(
+ WindowPtr /* maybeparent */,
+ WindowPtr /* child */);
+
+extern _X_EXPORT WindowPtr GetCurrentRootWindow(DeviceIntPtr pDev);
+
+extern _X_EXPORT WindowPtr GetSpriteWindow(DeviceIntPtr pDev);
+
+
+extern _X_EXPORT void NoticeEventTime(InternalEvent *ev);
+
+extern void EnqueueEvent(
+ InternalEvent * /* ev */,
+ DeviceIntPtr /* device */);
+
+extern void ActivatePointerGrab(
+ DeviceIntPtr /* mouse */,
+ GrabPtr /* grab */,
+ TimeStamp /* time */,
+ Bool /* autoGrab */);
+
+extern void DeactivatePointerGrab(
+ DeviceIntPtr /* mouse */);
+
+extern void ActivateKeyboardGrab(
+ DeviceIntPtr /* keybd */,
+ GrabPtr /* grab */,
+ TimeStamp /* time */,
+ Bool /* passive */);
+
+extern void DeactivateKeyboardGrab(
+ DeviceIntPtr /* keybd */);
+
+extern BOOL ActivateFocusInGrab(
+ DeviceIntPtr /* dev */,
+ WindowPtr /* old */,
+ WindowPtr /* win */);
+
+extern void AllowSome(
+ ClientPtr /* client */,
+ TimeStamp /* time */,
+ DeviceIntPtr /* thisDev */,
+ int /* newState */);
+
+extern void ReleaseActiveGrabs(
+ ClientPtr client);
+
+extern GrabPtr CheckPassiveGrabsOnWindow(
+ WindowPtr /* pWin */,
+ DeviceIntPtr /* device */,
+ DeviceEvent * /* event */,
+ BOOL /* checkCore */,
+ BOOL /* activate */);
+
+extern _X_EXPORT int DeliverEventsToWindow(
+ DeviceIntPtr /* pWin */,
+ WindowPtr /* pWin */,
+ xEventPtr /* pEvents */,
+ int /* count */,
+ Mask /* filter */,
+ GrabPtr /* grab */);
+
+extern int DeliverDeviceEvents(
+ WindowPtr /* pWin */,
+ InternalEvent* /* event */,
+ GrabPtr /* grab */,
+ WindowPtr /* stopAt */,
+ DeviceIntPtr /* dev */);
+
+extern void InitializeSprite(
+ DeviceIntPtr /* pDev */,
+ WindowPtr /* pWin */);
+
+extern void UpdateSpriteForScreen(
+ DeviceIntPtr /* pDev */,
+ ScreenPtr /* pScreen */);
+
+extern _X_EXPORT void WindowHasNewCursor(
+ WindowPtr /* pWin */);
+
+extern Bool CheckDeviceGrabs(
+ DeviceIntPtr /* device */,
+ DeviceEvent* /* event */,
+ WindowPtr /* ancestor */);
+
+extern void DeliverFocusedEvent(
+ DeviceIntPtr /* keybd */,
+ InternalEvent* /* event */,
+ WindowPtr /* window */);
+
+extern void DeliverGrabbedEvent(
+ InternalEvent* /* event */,
+ DeviceIntPtr /* thisDev */,
+ Bool /* deactivateGrab */);
+
+extern void FixKeyState(
+ DeviceEvent* /* event */,
+ DeviceIntPtr /* keybd */);
+
+extern void RecalculateDeliverableEvents(
+ WindowPtr /* pWin */);
+
+extern _X_EXPORT int OtherClientGone(
+ pointer /* value */,
+ XID /* id */);
+
+extern void DoFocusEvents(
+ DeviceIntPtr /* dev */,
+ WindowPtr /* fromWin */,
+ WindowPtr /* toWin */,
+ int /* mode */);
+
+extern int SetInputFocus(
+ ClientPtr /* client */,
+ DeviceIntPtr /* dev */,
+ Window /* focusID */,
+ CARD8 /* revertTo */,
+ Time /* ctime */,
+ Bool /* followOK */);
+
+extern int GrabDevice(
+ ClientPtr /* client */,
+ DeviceIntPtr /* dev */,
+ unsigned /* this_mode */,
+ unsigned /* other_mode */,
+ Window /* grabWindow */,
+ unsigned /* ownerEvents */,
+ Time /* ctime */,
+ GrabMask* /* mask */,
+ int /* grabtype */,
+ Cursor /* curs */,
+ Window /* confineToWin */,
+ CARD8 * /* status */);
+
+extern void InitEvents(void);
+
+extern void CloseDownEvents(void);
+
+extern void DeleteWindowFromAnyEvents(
+ WindowPtr /* pWin */,
+ Bool /* freeResources */);
+
+
+extern Mask EventMaskForClient(
+ WindowPtr /* pWin */,
+ ClientPtr /* client */);
+
+
+
+extern _X_EXPORT int DeliverEvents(
+ WindowPtr /*pWin*/,
+ xEventPtr /*xE*/,
+ int /*count*/,
+ WindowPtr /*otherParent*/);
+
+extern Bool CheckMotion(
+ DeviceEvent* /* ev */,
+ DeviceIntPtr /* pDev */);
+
+extern _X_EXPORT void WriteEventsToClient(
+ ClientPtr /*pClient*/,
+ int /*count*/,
+ xEventPtr /*events*/);
+
+extern _X_EXPORT int TryClientEvents(
+ ClientPtr /*client*/,
+ DeviceIntPtr /* device */,
+ xEventPtr /*pEvents*/,
+ int /*count*/,
+ Mask /*mask*/,
+ Mask /*filter*/,
+ GrabPtr /*grab*/);
+
+extern _X_EXPORT void WindowsRestructured(void);
+
+extern int SetClientPointer(
+ ClientPtr /* client */,
+ DeviceIntPtr /* device */);
+
+extern _X_EXPORT DeviceIntPtr PickPointer(
+ ClientPtr /* client */);
+
+extern _X_EXPORT DeviceIntPtr PickKeyboard(
+ ClientPtr /* client */);
+
+extern Bool IsInterferingGrab(
+ ClientPtr /* client */,
+ DeviceIntPtr /* dev */,
+ xEvent* /* events */);
+
+#ifdef PANORAMIX
+extern _X_EXPORT void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
+#endif
+
+#ifdef RANDR
+extern _X_EXPORT void
+ScreenRestructured (ScreenPtr pScreen);
+#endif
+
+extern _X_EXPORT int ffs(int i);
+
+
+/*
+ * ServerGrabCallback stuff
+ */
+
+extern _X_EXPORT CallbackListPtr ServerGrabCallback;
+
+typedef enum {SERVER_GRABBED, SERVER_UNGRABBED,
+ CLIENT_PERVIOUS, CLIENT_IMPERVIOUS } ServerGrabState;
+
+typedef struct {
+ ClientPtr client;
+ ServerGrabState grabstate;
+} ServerGrabInfoRec;
+
+/*
+ * EventCallback stuff
+ */
+
+extern _X_EXPORT CallbackListPtr EventCallback;
+
+typedef struct {
+ ClientPtr client;
+ xEventPtr events;
+ int count;
+} EventInfoRec;
+
+/*
+ * DeviceEventCallback stuff
+ */
+
+extern _X_EXPORT CallbackListPtr DeviceEventCallback;
+
+typedef struct {
+ InternalEvent *event;
+ DeviceIntPtr device;
+} DeviceEventInfoRec;
+
+extern int XItoCoreType(int xi_type);
+extern Bool DevHasCursor(DeviceIntPtr pDev);
+extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
+extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
+extern Bool IsPointerEvent(InternalEvent *event);
+extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
+
+extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
+extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what);
+extern _X_HIDDEN int CoreKeyboardProc(DeviceIntPtr dev, int what);
+
+
+/*
+ * These are deprecated compatibility functions and will be removed soon!
+ * Please use the noted replacements instead.
+ */
+/* replaced by dixLookupWindow */
+extern _X_EXPORT WindowPtr SecurityLookupWindow(
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+/* replaced by dixLookupWindow */
+extern _X_EXPORT WindowPtr LookupWindow(
+ XID id,
+ ClientPtr client);
+
+/* replaced by dixLookupDrawable */
+extern _X_EXPORT pointer SecurityLookupDrawable(
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+/* replaced by dixLookupDrawable */
+extern _X_EXPORT pointer LookupDrawable(
+ XID id,
+ ClientPtr client);
+
+/* replaced by dixLookupClient */
+extern _X_EXPORT ClientPtr LookupClient(
+ XID id,
+ ClientPtr client);
+
+#endif /* DIX_H */
diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h
index 31aad9aa4..f96a0a988 100644
--- a/xorg-server/include/input.h
+++ b/xorg-server/include/input.h
@@ -1,585 +1,589 @@
-/************************************************************
-
-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 <X11/Xmd.h>
-#include <X11/Xproto.h>
-#include <stdint.h>
-#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 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*/);
-
-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 GetEventFilter(DeviceIntPtr dev, xEvent *event);
-extern Mask GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev);
-void FixUpEventFromWindow(DeviceIntPtr pDev,
- xEvent *xE,
- WindowPtr pWin,
- Window child,
- Bool calcChild);
-extern int EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event,
- WindowPtr win);
-/**
- * Return masks for EventIsDeliverable.
- * @defgroup EventIsDeliverable return flags
- * @{
- */
-#define XI_MASK (1 << 0) /**< XI mask set on window */
-#define CORE_MASK (1 << 1) /**< Core mask set on window */
-#define DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set on window */
-#define 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_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 <X11/Xmd.h>
+#include <X11/Xproto.h>
+#include <stdint.h>
+#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*/);
+
+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);
+/**
+ * Return masks for EventIsDeliverable.
+ * @defgroup EventIsDeliverable return flags
+ * @{
+ */
+#define XI_MASK (1 << 0) /**< XI mask set on window */
+#define CORE_MASK (1 << 1) /**< Core mask set on window */
+#define DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set on window */
+#define 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/inputstr.h b/xorg-server/include/inputstr.h
index 325d5934f..b74ee0454 100644
--- a/xorg-server/include/inputstr.h
+++ b/xorg-server/include/inputstr.h
@@ -1,615 +1,615 @@
-/************************************************************
-
-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 INPUTSTRUCT_H
-#define INPUTSTRUCT_H
-
-#include <pixman.h>
-#include "input.h"
-#include "window.h"
-#include "dixstruct.h"
-#include "cursorstr.h"
-#include "geext.h"
-#include "privates.h"
-
-#define BitIsOn(ptr, bit) (!!(((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))))
-#define SetBit(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7)))
-#define ClearBit(ptr, bit) (((BYTE *)(ptr))[(bit)>>3] &= ~(1 << ((bit) & 7)))
-extern _X_EXPORT int CountBits(const uint8_t *mask, int len);
-
-#define SameClient(obj,client) \
- (CLIENT_BITS((obj)->resource) == (client)->clientAsMask)
-
-#define EMASKSIZE MAXDEVICES + 2
-
-/* This is the last XI2 event supported by the server. If you add
- * events to the protocol, the server will not support these events until
- * this number here is bumped.
- */
-#define XI2LASTEVENT 17 /* XI_RawMotion */
-#define XI2MASKSIZE ((XI2LASTEVENT + 7)/8) /* no of bits for masks */
-
-/**
- * This struct stores the core event mask for each client except the client
- * that created the window.
- *
- * Each window that has events selected from other clients has at least one of
- * these masks. If multiple clients selected for events on the same window,
- * these masks are in a linked list.
- *
- * The event mask for the client that created the window is stored in
- * win->eventMask instead.
- *
- * The resource id is simply a fake client ID to associate this mask with a
- * client.
- *
- * Kludge: OtherClients and InputClients must be compatible, see code.
- */
-typedef struct _OtherClients {
- OtherClientsPtr next; /**< Pointer to the next mask */
- XID resource; /**< id for putting into resource manager */
- Mask mask; /**< Core event mask */
-} OtherClients;
-
-/**
- * This struct stores the XI event mask for each client.
- *
- * Each window that has events selected has at least one of these masks. If
- * multiple client selected for events on the same window, these masks are in
- * a linked list.
- */
-typedef struct _InputClients {
- InputClientsPtr next; /**< Pointer to the next mask */
- XID resource; /**< id for putting into resource manager */
- Mask mask[EMASKSIZE]; /**< Actual XI event mask, deviceid is index */
- /** XI2 event masks. One per device, each bit is a mask of (1 << type) */
- unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE];
-} InputClients;
-
-/**
- * Combined XI event masks from all devices.
- *
- * This is the XI equivalent of the deliverableEvents, eventMask and
- * dontPropagate mask of the WindowRec (or WindowOptRec).
- *
- * A window that has an XI client selecting for events has exactly one
- * OtherInputMasks struct and exactly one InputClients struct hanging off
- * inputClients. Each further client appends to the inputClients list.
- * Each Mask field is per-device, with the device id as the index.
- * Exception: for non-device events (Presence events), the MAXDEVICES
- * deviceid is used.
- */
-typedef struct _OtherInputMasks {
- /**
- * Bitwise OR of all masks by all clients and the window's parent's masks.
- */
- Mask deliverableEvents[EMASKSIZE];
- /**
- * Bitwise OR of all masks by all clients on this window.
- */
- Mask inputEvents[EMASKSIZE];
- /** The do-not-propagate masks for each device. */
- Mask dontPropagateMask[EMASKSIZE];
- /** The clients that selected for events */
- InputClientsPtr inputClients;
- /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
- unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE];
-} OtherInputMasks;
-
-/*
- * The following structure gets used for both active and passive grabs. For
- * active grabs some of the fields (e.g. modifiers) are not used. However,
- * that is not much waste since there aren't many active grabs (one per
- * keyboard/pointer device) going at once in the server.
- */
-
-#define MasksPerDetailMask 8 /* 256 keycodes and 256 possible
- modifier combinations, but only
- 3 buttons. */
-
-typedef struct _DetailRec { /* Grab details may be bit masks */
- unsigned int exact;
- Mask *pMask;
-} DetailRec;
-
-typedef enum {
- GRABTYPE_CORE,
- GRABTYPE_XI,
- GRABTYPE_XI2
-} GrabType;
-
-union _GrabMask {
- Mask core;
- Mask xi;
- char xi2mask[EMASKSIZE][XI2MASKSIZE];
-};
-
-/**
- * Central struct for device grabs.
- * The same struct is used for both core grabs and device grabs, with
- * different fields being set.
- * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask
- * is a combination of standard event masks (i.e. PointerMotionMask |
- * ButtonPressMask).
- * If the grab is a device grab (GrabDevice), then the eventMask is a
- * combination of event masks for a given XI event type (see SetEventInfo).
- *
- * If the grab is a result of a ButtonPress, then eventMask is the core mask
- * and deviceMask is set to the XI event mask for the grab.
- */
-typedef struct _GrabRec {
- GrabPtr next; /* for chain of passive grabs */
- XID resource;
- DeviceIntPtr device;
- WindowPtr window;
- unsigned ownerEvents:1;
- unsigned keyboardMode:1;
- unsigned pointerMode:1;
- GrabType grabtype;
- CARD8 type; /* event type */
- DetailRec modifiersDetail;
- DeviceIntPtr modifierDevice;
- DetailRec detail; /* key or button */
- WindowPtr confineTo; /* always NULL for keyboards */
- CursorPtr cursor; /* always NULL for keyboards */
- Mask eventMask;
- Mask deviceMask;
- /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
- unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE];
-} GrabRec;
-
-typedef struct _KeyClassRec {
- int sourceid;
- CARD8 down[DOWN_LENGTH];
- CARD8 postdown[DOWN_LENGTH];
- int modifierKeyCount[8];
- struct _XkbSrvInfo *xkbInfo;
-} KeyClassRec, *KeyClassPtr;
-
-typedef struct _AxisInfo {
- int resolution;
- int min_resolution;
- int max_resolution;
- int min_value;
- int max_value;
- Atom label;
- CARD8 mode;
-} AxisInfo, *AxisInfoPtr;
-
-typedef struct _ValuatorAccelerationRec {
- int number;
- PointerAccelSchemeProc AccelSchemeProc;
- void *accelData; /* at disposal of AccelScheme */
- DeviceCallbackProc AccelCleanupProc;
-} ValuatorAccelerationRec, *ValuatorAccelerationPtr;
-
-typedef struct _ValuatorClassRec {
- int sourceid;
- int numMotionEvents;
- int first_motion;
- int last_motion;
- void *motion; /* motion history buffer. Different layout
- for MDs and SDs!*/
- WindowPtr motionHintWindow;
-
- AxisInfoPtr axes;
- unsigned short numAxes;
- double *axisVal; /* always absolute, but device-coord system */
- ValuatorAccelerationRec accelScheme;
-} ValuatorClassRec, *ValuatorClassPtr;
-
-typedef struct _ButtonClassRec {
- int sourceid;
- CARD8 numButtons;
- CARD8 buttonsDown; /* number of buttons currently down
- This counts logical buttons, not
- physical ones, i.e if some buttons
- are mapped to 0, they're not counted
- here */
- unsigned short state;
- Mask motionMask;
- CARD8 down[DOWN_LENGTH];
- CARD8 postdown[DOWN_LENGTH];
- CARD8 map[MAP_LENGTH];
- union _XkbAction *xkb_acts;
- Atom labels[MAX_BUTTONS];
-} ButtonClassRec, *ButtonClassPtr;
-
-typedef struct _FocusClassRec {
- int sourceid;
- WindowPtr win; /* May be set to a int constant (e.g. PointerRootWin)! */
- int revert;
- TimeStamp time;
- WindowPtr *trace;
- int traceSize;
- int traceGood;
-} FocusClassRec, *FocusClassPtr;
-
-typedef struct _ProximityClassRec {
- int sourceid;
- char in_proximity;
-} ProximityClassRec, *ProximityClassPtr;
-
-typedef struct _AbsoluteClassRec {
- int sourceid;
- /* Calibration. */
- int min_x;
- int max_x;
- int min_y;
- int max_y;
- int flip_x;
- int flip_y;
- int rotation;
- int button_threshold;
-
- /* Area. */
- int offset_x;
- int offset_y;
- int width;
- int height;
- int screen;
- XID following;
-} AbsoluteClassRec, *AbsoluteClassPtr;
-
-typedef struct _KbdFeedbackClassRec *KbdFeedbackPtr;
-typedef struct _PtrFeedbackClassRec *PtrFeedbackPtr;
-typedef struct _IntegerFeedbackClassRec *IntegerFeedbackPtr;
-typedef struct _StringFeedbackClassRec *StringFeedbackPtr;
-typedef struct _BellFeedbackClassRec *BellFeedbackPtr;
-typedef struct _LedFeedbackClassRec *LedFeedbackPtr;
-
-typedef struct _KbdFeedbackClassRec {
- BellProcPtr BellProc;
- KbdCtrlProcPtr CtrlProc;
- KeybdCtrl ctrl;
- KbdFeedbackPtr next;
- struct _XkbSrvLedInfo *xkb_sli;
-} KbdFeedbackClassRec;
-
-typedef struct _PtrFeedbackClassRec {
- PtrCtrlProcPtr CtrlProc;
- PtrCtrl ctrl;
- PtrFeedbackPtr next;
-} PtrFeedbackClassRec;
-
-typedef struct _IntegerFeedbackClassRec {
- IntegerCtrlProcPtr CtrlProc;
- IntegerCtrl ctrl;
- IntegerFeedbackPtr next;
-} IntegerFeedbackClassRec;
-
-typedef struct _StringFeedbackClassRec {
- StringCtrlProcPtr CtrlProc;
- StringCtrl ctrl;
- StringFeedbackPtr next;
-} StringFeedbackClassRec;
-
-typedef struct _BellFeedbackClassRec {
- BellProcPtr BellProc;
- BellCtrlProcPtr CtrlProc;
- BellCtrl ctrl;
- BellFeedbackPtr next;
-} BellFeedbackClassRec;
-
-typedef struct _LedFeedbackClassRec {
- LedCtrlProcPtr CtrlProc;
- LedCtrl ctrl;
- LedFeedbackPtr next;
- struct _XkbSrvLedInfo *xkb_sli;
-} LedFeedbackClassRec;
-
-
-typedef struct _ClassesRec {
- KeyClassPtr key;
- ValuatorClassPtr valuator;
- ButtonClassPtr button;
- FocusClassPtr focus;
- ProximityClassPtr proximity;
- AbsoluteClassPtr absolute;
- KbdFeedbackPtr kbdfeed;
- PtrFeedbackPtr ptrfeed;
- IntegerFeedbackPtr intfeed;
- StringFeedbackPtr stringfeed;
- BellFeedbackPtr bell;
- LedFeedbackPtr leds;
-} ClassesRec;
-
-
-/**
- * Sprite information for a device.
- */
-typedef struct {
- CursorPtr current;
- BoxRec hotLimits; /* logical constraints of hot spot */
- Bool confined; /* confined to screen */
- RegionPtr hotShape; /* additional logical shape constraint */
- BoxRec physLimits; /* physical constraints of hot spot */
- WindowPtr win; /* window of logical position */
- HotSpot hot; /* logical pointer position */
- HotSpot hotPhys; /* physical pointer position */
-#ifdef PANORAMIX
- ScreenPtr screen; /* all others are in Screen 0 coordinates */
- RegionRec Reg1; /* Region 1 for confining motion */
- RegionRec Reg2; /* Region 2 for confining virtual motion */
- WindowPtr windows[MAXSCREENS];
- WindowPtr confineWin; /* confine window */
-#endif
- /* The window trace information is used at dix/events.c to avoid having
- * to compute all the windows between the root and the current pointer
- * window each time a button or key goes down. The grabs on each of those
- * windows must be checked.
- * spriteTraces should only be used at dix/events.c! */
- WindowPtr *spriteTrace;
- int spriteTraceSize;
- int spriteTraceGood;
-
- /* Due to delays between event generation and event processing, it is
- * possible that the pointer has crossed screen boundaries between the
- * time in which it begins generating events and the time when
- * those events are processed.
- *
- * pEnqueueScreen: screen the pointer was on when the event was generated
- * pDequeueScreen: screen the pointer was on when the event is processed
- */
- ScreenPtr pEnqueueScreen;
- ScreenPtr pDequeueScreen;
-
-} SpriteRec, *SpritePtr;
-
-/* Device properties */
-typedef struct _XIPropertyValue
-{
- 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 */
-} XIPropertyValueRec;
-
-typedef struct _XIProperty
-{
- struct _XIProperty *next;
- Atom propertyName;
- BOOL deletable; /* clients can delete this prop? */
- XIPropertyValueRec value;
-} XIPropertyRec;
-
-typedef XIPropertyRec *XIPropertyPtr;
-typedef XIPropertyValueRec *XIPropertyValuePtr;
-
-
-typedef struct _XIPropertyHandler
-{
- struct _XIPropertyHandler* next;
- long id;
- int (*SetProperty) (DeviceIntPtr dev,
- Atom property,
- XIPropertyValuePtr prop,
- BOOL checkonly);
- int (*GetProperty) (DeviceIntPtr dev,
- Atom property);
- int (*DeleteProperty) (DeviceIntPtr dev,
- Atom property);
-} XIPropertyHandler, *XIPropertyHandlerPtr;
-
-/* states for devices */
-
-#define NOT_GRABBED 0
-#define THAWED 1
-#define THAWED_BOTH 2 /* not a real state */
-#define FREEZE_NEXT_EVENT 3
-#define FREEZE_BOTH_NEXT_EVENT 4
-#define FROZEN 5 /* any state >= has device frozen */
-#define FROZEN_NO_EVENT 5
-#define FROZEN_WITH_EVENT 6
-#define THAW_OTHERS 7
-
-
-typedef struct _GrabInfoRec {
- TimeStamp grabTime;
- Bool fromPassiveGrab; /* true if from passive grab */
- Bool implicitGrab; /* implicit from ButtonPress */
- GrabRec activeGrab;
- GrabPtr grab;
- CARD8 activatingKey;
- void (*ActivateGrab) (
- DeviceIntPtr /*device*/,
- GrabPtr /*grab*/,
- TimeStamp /*time*/,
- Bool /*autoGrab*/);
- void (*DeactivateGrab)(
- DeviceIntPtr /*device*/);
- struct {
- Bool frozen;
- int state;
- GrabPtr other; /* if other grab has this frozen */
- DeviceEvent *event; /* saved to be replayed */
- } sync;
-} GrabInfoRec, *GrabInfoPtr;
-
-typedef struct _SpriteInfoRec {
- /* sprite must always point to a valid sprite. For devices sharing the
- * sprite, let sprite point to a paired spriteOwner's sprite. */
- SpritePtr sprite; /* sprite information */
- Bool spriteOwner; /* True if device owns the sprite */
- DeviceIntPtr paired; /* The paired device. Keyboard if
- spriteOwner is TRUE, otherwise the
- pointer that owns the sprite. */
-
- /* keep states for animated cursor */
- struct {
- CursorPtr pCursor;
- ScreenPtr pScreen;
- int elt;
- CARD32 time;
- } anim;
-} SpriteInfoRec, *SpriteInfoPtr;
-
-/* device types */
-#define MASTER_POINTER 1
-#define MASTER_KEYBOARD 2
-#define SLAVE 3
-
-typedef struct _DeviceIntRec {
- DeviceRec public;
- DeviceIntPtr next;
- Bool startup; /* true if needs to be turned on at
- server intialization time */
- DeviceProc deviceProc; /* proc(DevicePtr, DEVICE_xx). It is
- used to initialize, turn on, or
- turn off the device */
- Bool inited; /* TRUE if INIT returns Success */
- Bool enabled; /* TRUE if ON returns Success */
- Bool coreEvents; /* TRUE if device also sends core */
- GrabInfoRec deviceGrab; /* grab on the device */
- int type; /* MASTER_POINTER, MASTER_KEYBOARD, SLAVE */
- Atom xinput_type;
- char *name;
- int id;
- KeyClassPtr key;
- ValuatorClassPtr valuator;
- ButtonClassPtr button;
- FocusClassPtr focus;
- ProximityClassPtr proximity;
- AbsoluteClassPtr absolute;
- KbdFeedbackPtr kbdfeed;
- PtrFeedbackPtr ptrfeed;
- IntegerFeedbackPtr intfeed;
- StringFeedbackPtr stringfeed;
- BellFeedbackPtr bell;
- LedFeedbackPtr leds;
- struct _XkbInterest *xkb_interest;
- char *config_info; /* used by the hotplug layer */
- ClassesPtr unused_classes; /* for master devices */
- int saved_master_id; /* for slaves while grabbed */
- PrivateRec *devPrivates;
- DeviceUnwrapProc unwrapProc;
- SpriteInfoPtr spriteInfo;
- union {
- DeviceIntPtr master; /* master device */
- DeviceIntPtr lastSlave; /* last slave device used */
- } u;
-
- /* last valuator values recorded, not posted to client;
- * for slave devices, valuators is in device coordinates
- * for master devices, valuators is in screen coordinates
- * see dix/getevents.c
- * remainder supports acceleration
- */
- struct {
- int valuators[MAX_VALUATORS];
- float remainder[MAX_VALUATORS];
- int numValuators;
- DeviceIntPtr slave;
- } last;
-
- /* Input device property handling. */
- struct {
- XIPropertyPtr properties;
- XIPropertyHandlerPtr handlers; /* NULL-terminated */
- } properties;
-
- /* coordinate transformation matrix for absolute input devices */
- struct pixman_f_transform transform;
-
- /* XTest related master device id */
- int xtest_master_id;
-} DeviceIntRec;
-
-typedef struct {
- int numDevices; /* total number of devices */
- DeviceIntPtr devices; /* all devices turned on */
- DeviceIntPtr off_devices; /* all devices turned off */
- DeviceIntPtr keyboard; /* the main one for the server */
- DeviceIntPtr pointer;
- DeviceIntPtr all_devices;
- DeviceIntPtr all_master_devices;
-} InputInfo;
-
-extern _X_EXPORT InputInfo inputInfo;
-
-/* for keeping the events for devices grabbed synchronously */
-typedef struct _QdEvent *QdEventPtr;
-typedef struct _QdEvent {
- QdEventPtr next;
- DeviceIntPtr device;
- ScreenPtr pScreen; /* what screen the pointer was on */
- unsigned long months; /* milliseconds is in the event */
- InternalEvent *event;
-} QdEventRec;
-
-/**
- * syncEvents is the global structure for queued events.
- *
- * Devices can be frozen through GrabModeSync pointer grabs. If this is the
- * case, events from these devices are added to "pending" instead of being
- * processed normally. When the device is unfrozen, events in "pending" are
- * replayed and processed as if they would come from the device directly.
- */
-typedef struct _EventSyncInfo {
- QdEventPtr pending, /**< list of queued events */
- *pendtail; /**< last event in list */
- /** The device to replay events for. Only set in AllowEvents(), in which
- * case it is set to the device specified in the request. */
- DeviceIntPtr replayDev; /* kludgy rock to put flag for */
-
- /**
- * The window the events are supposed to be replayed on.
- * This window may be set to the grab's window (but only when
- * Replay{Pointer|Keyboard} is given in the XAllowEvents()
- * request. */
- WindowPtr replayWin; /* ComputeFreezes */
- /**
- * Flag to indicate whether we're in the process of
- * replaying events. Only set in ComputeFreezes(). */
- Bool playingEvents;
- TimeStamp time;
-} EventSyncInfoRec, *EventSyncInfoPtr;
-
-extern EventSyncInfoRec syncEvents;
-
-#endif /* INPUTSTRUCT_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 INPUTSTRUCT_H
+#define INPUTSTRUCT_H
+
+#include <pixman.h>
+#include "input.h"
+#include "window.h"
+#include "dixstruct.h"
+#include "cursorstr.h"
+#include "geext.h"
+#include "privates.h"
+
+#define BitIsOn(ptr, bit) (!!(((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))))
+#define SetBit(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7)))
+#define ClearBit(ptr, bit) (((BYTE *)(ptr))[(bit)>>3] &= ~(1 << ((bit) & 7)))
+extern _X_EXPORT int CountBits(const uint8_t *mask, int len);
+
+#define SameClient(obj,client) \
+ (CLIENT_BITS((obj)->resource) == (client)->clientAsMask)
+
+#define EMASKSIZE MAXDEVICES + 2
+
+/* This is the last XI2 event supported by the server. If you add
+ * events to the protocol, the server will not support these events until
+ * this number here is bumped.
+ */
+#define XI2LASTEVENT 17 /* XI_RawMotion */
+#define XI2MASKSIZE ((XI2LASTEVENT + 7)/8) /* no of bits for masks */
+
+/**
+ * This struct stores the core event mask for each client except the client
+ * that created the window.
+ *
+ * Each window that has events selected from other clients has at least one of
+ * these masks. If multiple clients selected for events on the same window,
+ * these masks are in a linked list.
+ *
+ * The event mask for the client that created the window is stored in
+ * win->eventMask instead.
+ *
+ * The resource id is simply a fake client ID to associate this mask with a
+ * client.
+ *
+ * Kludge: OtherClients and InputClients must be compatible, see code.
+ */
+typedef struct _OtherClients {
+ OtherClientsPtr next; /**< Pointer to the next mask */
+ XID resource; /**< id for putting into resource manager */
+ Mask mask; /**< Core event mask */
+} OtherClients;
+
+/**
+ * This struct stores the XI event mask for each client.
+ *
+ * Each window that has events selected has at least one of these masks. If
+ * multiple client selected for events on the same window, these masks are in
+ * a linked list.
+ */
+typedef struct _InputClients {
+ InputClientsPtr next; /**< Pointer to the next mask */
+ XID resource; /**< id for putting into resource manager */
+ Mask mask[EMASKSIZE]; /**< Actual XI event mask, deviceid is index */
+ /** XI2 event masks. One per device, each bit is a mask of (1 << type) */
+ unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE];
+} InputClients;
+
+/**
+ * Combined XI event masks from all devices.
+ *
+ * This is the XI equivalent of the deliverableEvents, eventMask and
+ * dontPropagate mask of the WindowRec (or WindowOptRec).
+ *
+ * A window that has an XI client selecting for events has exactly one
+ * OtherInputMasks struct and exactly one InputClients struct hanging off
+ * inputClients. Each further client appends to the inputClients list.
+ * Each Mask field is per-device, with the device id as the index.
+ * Exception: for non-device events (Presence events), the MAXDEVICES
+ * deviceid is used.
+ */
+typedef struct _OtherInputMasks {
+ /**
+ * Bitwise OR of all masks by all clients and the window's parent's masks.
+ */
+ Mask deliverableEvents[EMASKSIZE];
+ /**
+ * Bitwise OR of all masks by all clients on this window.
+ */
+ Mask inputEvents[EMASKSIZE];
+ /** The do-not-propagate masks for each device. */
+ Mask dontPropagateMask[EMASKSIZE];
+ /** The clients that selected for events */
+ InputClientsPtr inputClients;
+ /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
+ unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE];
+} OtherInputMasks;
+
+/*
+ * The following structure gets used for both active and passive grabs. For
+ * active grabs some of the fields (e.g. modifiers) are not used. However,
+ * that is not much waste since there aren't many active grabs (one per
+ * keyboard/pointer device) going at once in the server.
+ */
+
+#define MasksPerDetailMask 8 /* 256 keycodes and 256 possible
+ modifier combinations, but only
+ 3 buttons. */
+
+typedef struct _DetailRec { /* Grab details may be bit masks */
+ unsigned int exact;
+ Mask *pMask;
+} DetailRec;
+
+typedef enum {
+ GRABTYPE_CORE,
+ GRABTYPE_XI,
+ GRABTYPE_XI2
+} GrabType;
+
+union _GrabMask {
+ Mask core;
+ Mask xi;
+ char xi2mask[EMASKSIZE][XI2MASKSIZE];
+};
+
+/**
+ * Central struct for device grabs.
+ * The same struct is used for both core grabs and device grabs, with
+ * different fields being set.
+ * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask
+ * is a combination of standard event masks (i.e. PointerMotionMask |
+ * ButtonPressMask).
+ * If the grab is a device grab (GrabDevice), then the eventMask is a
+ * combination of event masks for a given XI event type (see SetEventInfo).
+ *
+ * If the grab is a result of a ButtonPress, then eventMask is the core mask
+ * and deviceMask is set to the XI event mask for the grab.
+ */
+typedef struct _GrabRec {
+ GrabPtr next; /* for chain of passive grabs */
+ XID resource;
+ DeviceIntPtr device;
+ WindowPtr window;
+ unsigned ownerEvents:1;
+ unsigned keyboardMode:1;
+ unsigned pointerMode:1;
+ GrabType grabtype;
+ CARD8 type; /* event type */
+ DetailRec modifiersDetail;
+ DeviceIntPtr modifierDevice;
+ DetailRec detail; /* key or button */
+ WindowPtr confineTo; /* always NULL for keyboards */
+ CursorPtr cursor; /* always NULL for keyboards */
+ Mask eventMask;
+ Mask deviceMask;
+ /* XI2 event masks. One per device, each bit is a mask of (1 << type) */
+ unsigned char xi2mask[EMASKSIZE][XI2MASKSIZE];
+} GrabRec;
+
+/**
+ * Sprite information for a device.
+ */
+typedef struct _SpriteRec {
+ CursorPtr current;
+ BoxRec hotLimits; /* logical constraints of hot spot */
+ Bool confined; /* confined to screen */
+ RegionPtr hotShape; /* additional logical shape constraint */
+ BoxRec physLimits; /* physical constraints of hot spot */
+ WindowPtr win; /* window of logical position */
+ HotSpot hot; /* logical pointer position */
+ HotSpot hotPhys; /* physical pointer position */
+#ifdef PANORAMIX
+ ScreenPtr screen; /* all others are in Screen 0 coordinates */
+ RegionRec Reg1; /* Region 1 for confining motion */
+ RegionRec Reg2; /* Region 2 for confining virtual motion */
+ WindowPtr windows[MAXSCREENS];
+ WindowPtr confineWin; /* confine window */
+#endif
+ /* The window trace information is used at dix/events.c to avoid having
+ * to compute all the windows between the root and the current pointer
+ * window each time a button or key goes down. The grabs on each of those
+ * windows must be checked.
+ * spriteTraces should only be used at dix/events.c! */
+ WindowPtr *spriteTrace;
+ int spriteTraceSize;
+ int spriteTraceGood;
+
+ /* Due to delays between event generation and event processing, it is
+ * possible that the pointer has crossed screen boundaries between the
+ * time in which it begins generating events and the time when
+ * those events are processed.
+ *
+ * pEnqueueScreen: screen the pointer was on when the event was generated
+ * pDequeueScreen: screen the pointer was on when the event is processed
+ */
+ ScreenPtr pEnqueueScreen;
+ ScreenPtr pDequeueScreen;
+
+} SpriteRec;
+
+typedef struct _KeyClassRec {
+ int sourceid;
+ CARD8 down[DOWN_LENGTH];
+ CARD8 postdown[DOWN_LENGTH];
+ int modifierKeyCount[8];
+ struct _XkbSrvInfo *xkbInfo;
+} KeyClassRec, *KeyClassPtr;
+
+typedef struct _AxisInfo {
+ int resolution;
+ int min_resolution;
+ int max_resolution;
+ int min_value;
+ int max_value;
+ Atom label;
+ CARD8 mode;
+} AxisInfo, *AxisInfoPtr;
+
+typedef struct _ValuatorAccelerationRec {
+ int number;
+ PointerAccelSchemeProc AccelSchemeProc;
+ void *accelData; /* at disposal of AccelScheme */
+ DeviceCallbackProc AccelCleanupProc;
+} ValuatorAccelerationRec, *ValuatorAccelerationPtr;
+
+typedef struct _ValuatorClassRec {
+ int sourceid;
+ int numMotionEvents;
+ int first_motion;
+ int last_motion;
+ void *motion; /* motion history buffer. Different layout
+ for MDs and SDs!*/
+ WindowPtr motionHintWindow;
+
+ AxisInfoPtr axes;
+ unsigned short numAxes;
+ double *axisVal; /* always absolute, but device-coord system */
+ ValuatorAccelerationRec accelScheme;
+} ValuatorClassRec, *ValuatorClassPtr;
+
+typedef struct _ButtonClassRec {
+ int sourceid;
+ CARD8 numButtons;
+ CARD8 buttonsDown; /* number of buttons currently down
+ This counts logical buttons, not
+ physical ones, i.e if some buttons
+ are mapped to 0, they're not counted
+ here */
+ unsigned short state;
+ Mask motionMask;
+ CARD8 down[DOWN_LENGTH];
+ CARD8 postdown[DOWN_LENGTH];
+ CARD8 map[MAP_LENGTH];
+ union _XkbAction *xkb_acts;
+ Atom labels[MAX_BUTTONS];
+} ButtonClassRec, *ButtonClassPtr;
+
+typedef struct _FocusClassRec {
+ int sourceid;
+ WindowPtr win; /* May be set to a int constant (e.g. PointerRootWin)! */
+ int revert;
+ TimeStamp time;
+ WindowPtr *trace;
+ int traceSize;
+ int traceGood;
+} FocusClassRec, *FocusClassPtr;
+
+typedef struct _ProximityClassRec {
+ int sourceid;
+ char in_proximity;
+} ProximityClassRec, *ProximityClassPtr;
+
+typedef struct _AbsoluteClassRec {
+ int sourceid;
+ /* Calibration. */
+ int min_x;
+ int max_x;
+ int min_y;
+ int max_y;
+ int flip_x;
+ int flip_y;
+ int rotation;
+ int button_threshold;
+
+ /* Area. */
+ int offset_x;
+ int offset_y;
+ int width;
+ int height;
+ int screen;
+ XID following;
+} AbsoluteClassRec, *AbsoluteClassPtr;
+
+typedef struct _KbdFeedbackClassRec *KbdFeedbackPtr;
+typedef struct _PtrFeedbackClassRec *PtrFeedbackPtr;
+typedef struct _IntegerFeedbackClassRec *IntegerFeedbackPtr;
+typedef struct _StringFeedbackClassRec *StringFeedbackPtr;
+typedef struct _BellFeedbackClassRec *BellFeedbackPtr;
+typedef struct _LedFeedbackClassRec *LedFeedbackPtr;
+
+typedef struct _KbdFeedbackClassRec {
+ BellProcPtr BellProc;
+ KbdCtrlProcPtr CtrlProc;
+ KeybdCtrl ctrl;
+ KbdFeedbackPtr next;
+ struct _XkbSrvLedInfo *xkb_sli;
+} KbdFeedbackClassRec;
+
+typedef struct _PtrFeedbackClassRec {
+ PtrCtrlProcPtr CtrlProc;
+ PtrCtrl ctrl;
+ PtrFeedbackPtr next;
+} PtrFeedbackClassRec;
+
+typedef struct _IntegerFeedbackClassRec {
+ IntegerCtrlProcPtr CtrlProc;
+ IntegerCtrl ctrl;
+ IntegerFeedbackPtr next;
+} IntegerFeedbackClassRec;
+
+typedef struct _StringFeedbackClassRec {
+ StringCtrlProcPtr CtrlProc;
+ StringCtrl ctrl;
+ StringFeedbackPtr next;
+} StringFeedbackClassRec;
+
+typedef struct _BellFeedbackClassRec {
+ BellProcPtr BellProc;
+ BellCtrlProcPtr CtrlProc;
+ BellCtrl ctrl;
+ BellFeedbackPtr next;
+} BellFeedbackClassRec;
+
+typedef struct _LedFeedbackClassRec {
+ LedCtrlProcPtr CtrlProc;
+ LedCtrl ctrl;
+ LedFeedbackPtr next;
+ struct _XkbSrvLedInfo *xkb_sli;
+} LedFeedbackClassRec;
+
+
+typedef struct _ClassesRec {
+ KeyClassPtr key;
+ ValuatorClassPtr valuator;
+ ButtonClassPtr button;
+ FocusClassPtr focus;
+ ProximityClassPtr proximity;
+ AbsoluteClassPtr absolute;
+ KbdFeedbackPtr kbdfeed;
+ PtrFeedbackPtr ptrfeed;
+ IntegerFeedbackPtr intfeed;
+ StringFeedbackPtr stringfeed;
+ BellFeedbackPtr bell;
+ LedFeedbackPtr leds;
+} ClassesRec;
+
+
+/* Device properties */
+typedef struct _XIPropertyValue
+{
+ 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 */
+} XIPropertyValueRec;
+
+typedef struct _XIProperty
+{
+ struct _XIProperty *next;
+ Atom propertyName;
+ BOOL deletable; /* clients can delete this prop? */
+ XIPropertyValueRec value;
+} XIPropertyRec;
+
+typedef XIPropertyRec *XIPropertyPtr;
+typedef XIPropertyValueRec *XIPropertyValuePtr;
+
+
+typedef struct _XIPropertyHandler
+{
+ struct _XIPropertyHandler* next;
+ long id;
+ int (*SetProperty) (DeviceIntPtr dev,
+ Atom property,
+ XIPropertyValuePtr prop,
+ BOOL checkonly);
+ int (*GetProperty) (DeviceIntPtr dev,
+ Atom property);
+ int (*DeleteProperty) (DeviceIntPtr dev,
+ Atom property);
+} XIPropertyHandler, *XIPropertyHandlerPtr;
+
+/* states for devices */
+
+#define NOT_GRABBED 0
+#define THAWED 1
+#define THAWED_BOTH 2 /* not a real state */
+#define FREEZE_NEXT_EVENT 3
+#define FREEZE_BOTH_NEXT_EVENT 4
+#define FROZEN 5 /* any state >= has device frozen */
+#define FROZEN_NO_EVENT 5
+#define FROZEN_WITH_EVENT 6
+#define THAW_OTHERS 7
+
+
+typedef struct _GrabInfoRec {
+ TimeStamp grabTime;
+ Bool fromPassiveGrab; /* true if from passive grab */
+ Bool implicitGrab; /* implicit from ButtonPress */
+ GrabRec activeGrab;
+ GrabPtr grab;
+ CARD8 activatingKey;
+ void (*ActivateGrab) (
+ DeviceIntPtr /*device*/,
+ GrabPtr /*grab*/,
+ TimeStamp /*time*/,
+ Bool /*autoGrab*/);
+ void (*DeactivateGrab)(
+ DeviceIntPtr /*device*/);
+ struct {
+ Bool frozen;
+ int state;
+ GrabPtr other; /* if other grab has this frozen */
+ DeviceEvent *event; /* saved to be replayed */
+ } sync;
+} GrabInfoRec, *GrabInfoPtr;
+
+typedef struct _SpriteInfoRec {
+ /* sprite must always point to a valid sprite. For devices sharing the
+ * sprite, let sprite point to a paired spriteOwner's sprite. */
+ SpritePtr sprite; /* sprite information */
+ Bool spriteOwner; /* True if device owns the sprite */
+ DeviceIntPtr paired; /* The paired device. Keyboard if
+ spriteOwner is TRUE, otherwise the
+ pointer that owns the sprite. */
+
+ /* keep states for animated cursor */
+ struct {
+ CursorPtr pCursor;
+ ScreenPtr pScreen;
+ int elt;
+ CARD32 time;
+ } anim;
+} SpriteInfoRec, *SpriteInfoPtr;
+
+/* device types */
+#define MASTER_POINTER 1
+#define MASTER_KEYBOARD 2
+#define SLAVE 3
+
+typedef struct _DeviceIntRec {
+ DeviceRec public;
+ DeviceIntPtr next;
+ Bool startup; /* true if needs to be turned on at
+ server intialization time */
+ DeviceProc deviceProc; /* proc(DevicePtr, DEVICE_xx). It is
+ used to initialize, turn on, or
+ turn off the device */
+ Bool inited; /* TRUE if INIT returns Success */
+ Bool enabled; /* TRUE if ON returns Success */
+ Bool coreEvents; /* TRUE if device also sends core */
+ GrabInfoRec deviceGrab; /* grab on the device */
+ int type; /* MASTER_POINTER, MASTER_KEYBOARD, SLAVE */
+ Atom xinput_type;
+ char *name;
+ int id;
+ KeyClassPtr key;
+ ValuatorClassPtr valuator;
+ ButtonClassPtr button;
+ FocusClassPtr focus;
+ ProximityClassPtr proximity;
+ AbsoluteClassPtr absolute;
+ KbdFeedbackPtr kbdfeed;
+ PtrFeedbackPtr ptrfeed;
+ IntegerFeedbackPtr intfeed;
+ StringFeedbackPtr stringfeed;
+ BellFeedbackPtr bell;
+ LedFeedbackPtr leds;
+ struct _XkbInterest *xkb_interest;
+ char *config_info; /* used by the hotplug layer */
+ ClassesPtr unused_classes; /* for master devices */
+ int saved_master_id; /* for slaves while grabbed */
+ PrivateRec *devPrivates;
+ DeviceUnwrapProc unwrapProc;
+ SpriteInfoPtr spriteInfo;
+ union {
+ DeviceIntPtr master; /* master device */
+ DeviceIntPtr lastSlave; /* last slave device used */
+ } u;
+
+ /* last valuator values recorded, not posted to client;
+ * for slave devices, valuators is in device coordinates
+ * for master devices, valuators is in screen coordinates
+ * see dix/getevents.c
+ * remainder supports acceleration
+ */
+ struct {
+ int valuators[MAX_VALUATORS];
+ float remainder[MAX_VALUATORS];
+ int numValuators;
+ DeviceIntPtr slave;
+ } last;
+
+ /* Input device property handling. */
+ struct {
+ XIPropertyPtr properties;
+ XIPropertyHandlerPtr handlers; /* NULL-terminated */
+ } properties;
+
+ /* coordinate transformation matrix for absolute input devices */
+ struct pixman_f_transform transform;
+
+ /* XTest related master device id */
+ int xtest_master_id;
+} DeviceIntRec;
+
+typedef struct {
+ int numDevices; /* total number of devices */
+ DeviceIntPtr devices; /* all devices turned on */
+ DeviceIntPtr off_devices; /* all devices turned off */
+ DeviceIntPtr keyboard; /* the main one for the server */
+ DeviceIntPtr pointer;
+ DeviceIntPtr all_devices;
+ DeviceIntPtr all_master_devices;
+} InputInfo;
+
+extern _X_EXPORT InputInfo inputInfo;
+
+/* for keeping the events for devices grabbed synchronously */
+typedef struct _QdEvent *QdEventPtr;
+typedef struct _QdEvent {
+ QdEventPtr next;
+ DeviceIntPtr device;
+ ScreenPtr pScreen; /* what screen the pointer was on */
+ unsigned long months; /* milliseconds is in the event */
+ InternalEvent *event;
+} QdEventRec;
+
+/**
+ * syncEvents is the global structure for queued events.
+ *
+ * Devices can be frozen through GrabModeSync pointer grabs. If this is the
+ * case, events from these devices are added to "pending" instead of being
+ * processed normally. When the device is unfrozen, events in "pending" are
+ * replayed and processed as if they would come from the device directly.
+ */
+typedef struct _EventSyncInfo {
+ QdEventPtr pending, /**< list of queued events */
+ *pendtail; /**< last event in list */
+ /** The device to replay events for. Only set in AllowEvents(), in which
+ * case it is set to the device specified in the request. */
+ DeviceIntPtr replayDev; /* kludgy rock to put flag for */
+
+ /**
+ * The window the events are supposed to be replayed on.
+ * This window may be set to the grab's window (but only when
+ * Replay{Pointer|Keyboard} is given in the XAllowEvents()
+ * request. */
+ WindowPtr replayWin; /* ComputeFreezes */
+ /**
+ * Flag to indicate whether we're in the process of
+ * replaying events. Only set in ComputeFreezes(). */
+ Bool playingEvents;
+ TimeStamp time;
+} EventSyncInfoRec, *EventSyncInfoPtr;
+
+extern EventSyncInfoRec syncEvents;
+
+#endif /* INPUTSTRUCT_H */
diff --git a/xorg-server/mi/miinitext.c b/xorg-server/mi/miinitext.c
index a7441c9a8..4499f377c 100644
--- a/xorg-server/mi/miinitext.c
+++ b/xorg-server/mi/miinitext.c
@@ -389,9 +389,7 @@ InitExtensions(int argc, char *argv[])
if (!noGEExtension) GEExtensionInit();
#ifdef PANORAMIX
-# if !defined(NO_PANORAMIX)
if (!noPanoramiXExtension) PanoramiXExtensionInit();
-# endif
#endif
#ifdef INXQUARTZ
if(!noPseudoramiXExtension) PseudoramiXExtensionInit();
diff --git a/xorg-server/os/WaitFor.c b/xorg-server/os/WaitFor.c
index ac4b58e48..867cb04b8 100644
--- a/xorg-server/os/WaitFor.c
+++ b/xorg-server/os/WaitFor.c
@@ -1,681 +1,687 @@
-/***********************************************************
-
-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.
-
-******************************************************************/
-
-
-/*****************************************************************
- * OS Dependent input routines:
- *
- * WaitForSomething
- * TimerForce, TimerSet, TimerCheck, TimerFree
- *
- *****************************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-#include <X11/Xos.h> /* for strings, fcntl, time */
-#include <errno.h>
-#include <stdio.h>
-#include <X11/X.h>
-#include "misc.h"
-
-#include "osdep.h"
-#include <X11/Xpoll.h>
-#include "dixstruct.h"
-#include "opaque.h"
-#ifdef DPMSExtension
-#include "dpmsproc.h"
-#endif
-
-#ifdef WIN32
-/* Error codes from windows sockets differ from fileio error codes */
-#undef EINTR
-#define EINTR WSAEINTR
-#undef EINVAL
-#define EINVAL WSAEINVAL
-#undef EBADF
-#define EBADF WSAENOTSOCK
-/* Windows select does not set errno. Use GetErrno as wrapper for
- WSAGetLastError */
-#define GetErrno WSAGetLastError
-#else
-/* This is just a fallback to errno to hide the differences between unix and
- Windows in the code */
-#define GetErrno() errno
-#endif
-
-/* like ffs, but uses fd_mask instead of int as argument, so it works
- when fd_mask is longer than an int, such as common 64-bit platforms */
-/* modifications by raphael */
-int
-mffs(fd_mask mask)
-{
- int i;
-
- if (!mask) return 0;
- i = 1;
- while (!(mask & 1))
- {
- i++;
- mask >>= 1;
- }
- return i;
-}
-
-#ifdef DPMSExtension
-#include <X11/extensions/dpmsconst.h>
-#endif
-
-struct _OsTimerRec {
- OsTimerPtr next;
- CARD32 expires;
- CARD32 delta;
- OsTimerCallback callback;
- pointer arg;
-};
-
-static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
-static void CheckAllTimers(void);
-static OsTimerPtr timers = NULL;
-
-/*****************
- * WaitForSomething:
- * Make the server suspend until there is
- * 1. data from clients or
- * 2. input events available or
- * 3. ddx notices something of interest (graphics
- * queue ready, etc.) or
- * 4. clients that have buffered replies/events are ready
- *
- * If the time between INPUT events is
- * greater than ScreenSaverTime, the display is turned off (or
- * saved, depending on the hardware). So, WaitForSomething()
- * has to handle this also (that's why the select() has a timeout.
- * For more info on ClientsWithInput, see ReadRequestFromClient().
- * pClientsReady is an array to store ready client->index values into.
- *****************/
-
-int
-WaitForSomething(int *pClientsReady)
-{
- int i;
- struct timeval waittime, *wt;
- INT32 timeout = 0;
- fd_set clientsReadable;
- fd_set clientsWritable;
- int curclient;
- int selecterr;
- int nready;
- fd_set devicesReadable;
- CARD32 now = 0;
- Bool someReady = FALSE;
-
- FD_ZERO(&clientsReadable);
-
- /* We need a while loop here to handle
- crashed connections and the screen saver timeout */
- while (1)
- {
- /* deal with any blocked jobs */
- if (workQueue)
- ProcessWorkQueue();
- if (XFD_ANYSET (&ClientsWithInput))
- {
- if (!SmartScheduleDisable)
- {
- someReady = TRUE;
- waittime.tv_sec = 0;
- waittime.tv_usec = 0;
- wt = &waittime;
- }
- else
- {
- XFD_COPYSET (&ClientsWithInput, &clientsReadable);
- break;
- }
- }
- if (someReady)
- {
- XFD_COPYSET(&AllSockets, &LastSelectMask);
- XFD_UNSET(&LastSelectMask, &ClientsWithInput);
- }
- else
- {
- wt = NULL;
- if (timers)
- {
- now = GetTimeInMillis();
- timeout = timers->expires - now;
- if (timeout > 0 && timeout > timers->delta + 250) {
- /* time has rewound. reset the timers. */
- CheckAllTimers();
- }
-
- if (timers) {
- timeout = timers->expires - now;
- if (timeout < 0)
- timeout = 0;
- waittime.tv_sec = timeout / MILLI_PER_SECOND;
- waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
- (1000000 / MILLI_PER_SECOND);
- wt = &waittime;
- }
- }
- XFD_COPYSET(&AllSockets, &LastSelectMask);
- }
- SmartScheduleStopTimer ();
-
- BlockHandler((pointer)&wt, (pointer)&LastSelectMask);
- if (NewOutputPending)
- FlushAllOutput();
- /* keep this check close to select() call to minimize race */
- if (dispatchException)
- i = -1;
- else if (AnyClientsWriteBlocked)
- {
- XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
- i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
- }
- else
- {
- i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
- }
- selecterr = GetErrno();
- WakeupHandler(i, (pointer)&LastSelectMask);
- SmartScheduleStartTimer ();
- if (i <= 0) /* An error or timeout occurred */
- {
- if (dispatchException)
- return 0;
- if (i < 0)
- {
- if (selecterr == EBADF) /* Some client disconnected */
- {
- CheckConnections ();
- if (! XFD_ANYSET (&AllClients))
- return 0;
- }
- else if (selecterr == EINVAL)
- {
- FatalError("WaitForSomething(): select: %s\n",
- strerror(selecterr));
- }
- else if (selecterr != EINTR && selecterr != EAGAIN)
- {
- ErrorF("WaitForSomething(): select: %s\n",
- strerror(selecterr));
- }
- }
- else if (someReady)
- {
- /*
- * If no-one else is home, bail quickly
- */
- XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
- XFD_COPYSET(&ClientsWithInput, &clientsReadable);
- break;
- }
- if (*checkForInput[0] != *checkForInput[1])
- return 0;
-
- if (timers)
- {
- int expired = 0;
- now = GetTimeInMillis();
- if ((int) (timers->expires - now) <= 0)
- expired = 1;
-
- while (timers && (int) (timers->expires - now) <= 0)
- DoTimer(timers, now, &timers);
-
- if (expired)
- return 0;
- }
- }
- else
- {
- fd_set tmp_set;
-
- if (*checkForInput[0] == *checkForInput[1]) {
- if (timers)
- {
- int expired = 0;
- now = GetTimeInMillis();
- if ((int) (timers->expires - now) <= 0)
- expired = 1;
-
- while (timers && (int) (timers->expires - now) <= 0)
- DoTimer(timers, now, &timers);
-
- if (expired)
- return 0;
- }
- }
- if (someReady)
- XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
- if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable))
- {
- NewOutputPending = TRUE;
- XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
- XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
- if (! XFD_ANYSET(&ClientsWriteBlocked))
- AnyClientsWriteBlocked = FALSE;
- }
-
- XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices);
- XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
- XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections);
- if (XFD_ANYSET(&tmp_set))
- QueueWorkProc(EstablishNewConnections, NULL,
- (pointer)&LastSelectMask);
-
- if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable))
- break;
- /* check here for DDXes that queue events during Block/Wakeup */
- if (*checkForInput[0] != *checkForInput[1])
- return 0;
- }
- }
-
- nready = 0;
- if (XFD_ANYSET (&clientsReadable))
- {
-#ifndef WIN32
- for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
- {
- int highest_priority = 0;
-
- while (clientsReadable.fds_bits[i])
- {
- int client_priority, client_index;
-
- curclient = mffs (clientsReadable.fds_bits[i]) - 1;
- client_index = /* raphael: modified */
- ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))];
-#else
- int highest_priority = 0;
- fd_set savedClientsReadable;
- XFD_COPYSET(&clientsReadable, &savedClientsReadable);
- for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++)
- {
- int client_priority, client_index;
-
- curclient = XFD_FD(&savedClientsReadable, i);
- client_index = GetConnectionTranslation(curclient);
-#endif
- /* We implement "strict" priorities.
- * Only the highest priority client is returned to
- * dix. If multiple clients at the same priority are
- * ready, they are all returned. This means that an
- * aggressive client could take over the server.
- * This was not considered a big problem because
- * aggressive clients can hose the server in so many
- * other ways :)
- */
- client_priority = clients[client_index]->priority;
- if (nready == 0 || client_priority > highest_priority)
- {
- /* Either we found the first client, or we found
- * a client whose priority is greater than all others
- * that have been found so far. Either way, we want
- * to initialize the list of clients to contain just
- * this client.
- */
- pClientsReady[0] = client_index;
- highest_priority = client_priority;
- nready = 1;
- }
- /* the following if makes sure that multiple same-priority
- * clients get batched together
- */
- else if (client_priority == highest_priority)
- {
- pClientsReady[nready++] = client_index;
- }
-#ifndef WIN32
- clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient);
- }
-#else
- FD_CLR(curclient, &clientsReadable);
-#endif
- }
- }
- return nready;
-}
-
-/* If time has rewound, re-run every affected timer.
- * Timers might drop out of the list, so we have to restart every time. */
-static void
-CheckAllTimers(void)
-{
- OsTimerPtr timer;
- CARD32 now;
-
-start:
- now = GetTimeInMillis();
-
- for (timer = timers; timer; timer = timer->next) {
- if (timer->expires - now > timer->delta + 250) {
- TimerForce(timer);
- goto start;
- }
- }
-}
-
-static void
-DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
-{
- CARD32 newTime;
-
- *prev = timer->next;
- timer->next = NULL;
- newTime = (*timer->callback)(timer, now, timer->arg);
- if (newTime)
- TimerSet(timer, 0, newTime, timer->callback, timer->arg);
-}
-
-OsTimerPtr
-TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
- OsTimerCallback func, pointer arg)
-{
- register OsTimerPtr *prev;
- CARD32 now = GetTimeInMillis();
-
- if (!timer)
- {
- timer = malloc(sizeof(struct _OsTimerRec));
- if (!timer)
- return NULL;
- }
- else
- {
- for (prev = &timers; *prev; prev = &(*prev)->next)
- {
- if (*prev == timer)
- {
- *prev = timer->next;
- if (flags & TimerForceOld)
- (void)(*timer->callback)(timer, now, timer->arg);
- break;
- }
- }
- }
- if (!millis)
- return timer;
- if (flags & TimerAbsolute) {
- timer->delta = millis - now;
- }
- else {
- timer->delta = millis;
- millis += now;
- }
- timer->expires = millis;
- timer->callback = func;
- timer->arg = arg;
- if ((int) (millis - now) <= 0)
- {
- timer->next = NULL;
- millis = (*timer->callback)(timer, now, timer->arg);
- if (!millis)
- return timer;
- }
- for (prev = &timers;
- *prev && (int) ((*prev)->expires - millis) <= 0;
- prev = &(*prev)->next)
- ;
- timer->next = *prev;
- *prev = timer;
- return timer;
-}
-
-Bool
-TimerForce(OsTimerPtr timer)
-{
- OsTimerPtr *prev;
-
- for (prev = &timers; *prev; prev = &(*prev)->next)
- {
- if (*prev == timer)
- {
- DoTimer(timer, GetTimeInMillis(), prev);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-
-void
-TimerCancel(OsTimerPtr timer)
-{
- OsTimerPtr *prev;
-
- if (!timer)
- return;
- for (prev = &timers; *prev; prev = &(*prev)->next)
- {
- if (*prev == timer)
- {
- *prev = timer->next;
- break;
- }
- }
-}
-
-void
-TimerFree(OsTimerPtr timer)
-{
- if (!timer)
- return;
- TimerCancel(timer);
- free(timer);
-}
-
-void
-TimerCheck(void)
-{
- CARD32 now = GetTimeInMillis();
-
- while (timers && (int) (timers->expires - now) <= 0)
- DoTimer(timers, now, &timers);
-}
-
-void
-TimerInit(void)
-{
- OsTimerPtr timer;
-
- while ((timer = timers))
- {
- timers = timer->next;
- free(timer);
- }
-}
-
-#ifdef DPMSExtension
-
-#define DPMS_CHECK_MODE(mode,time)\
- if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
- DPMSSet(serverClient, mode);
-
-#define DPMS_CHECK_TIMEOUT(time)\
- if (time > 0 && (time - timeout) > 0)\
- return time - timeout;
-
-static CARD32
-NextDPMSTimeout(INT32 timeout)
-{
- /*
- * Return the amount of time remaining until we should set
- * the next power level. Fallthroughs are intentional.
- */
- switch (DPMSPowerLevel)
- {
- case DPMSModeOn:
- DPMS_CHECK_TIMEOUT(DPMSStandbyTime)
-
- case DPMSModeStandby:
- DPMS_CHECK_TIMEOUT(DPMSSuspendTime)
-
- case DPMSModeSuspend:
- DPMS_CHECK_TIMEOUT(DPMSOffTime)
-
- default: /* DPMSModeOff */
- return 0;
- }
-}
-#endif /* DPMSExtension */
-
-static CARD32
-ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg)
-{
- INT32 timeout = now - lastDeviceEventTime.milliseconds;
- CARD32 nextTimeout = 0;
-
-#ifdef DPMSExtension
- /*
- * Check each mode lowest to highest, since a lower mode can
- * have the same timeout as a higher one.
- */
- if (DPMSEnabled)
- {
- DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime)
- DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime)
- DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime)
-
- nextTimeout = NextDPMSTimeout(timeout);
- }
-
- /*
- * Only do the screensaver checks if we're not in a DPMS
- * power saving mode
- */
- if (DPMSPowerLevel != DPMSModeOn)
- return nextTimeout;
-#endif /* DPMSExtension */
-
- if (!ScreenSaverTime)
- return nextTimeout;
-
- if (timeout < ScreenSaverTime)
- {
- return nextTimeout > 0 ?
- min(ScreenSaverTime - timeout, nextTimeout) :
- ScreenSaverTime - timeout;
- }
-
- ResetOsBuffers(); /* not ideal, but better than nothing */
- dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive);
-
- if (ScreenSaverInterval > 0)
- {
- nextTimeout = nextTimeout > 0 ?
- min(ScreenSaverInterval, nextTimeout) :
- ScreenSaverInterval;
- }
-
- return nextTimeout;
-}
-
-static OsTimerPtr ScreenSaverTimer = NULL;
-
-void
-FreeScreenSaverTimer(void)
-{
- if (ScreenSaverTimer) {
- TimerFree(ScreenSaverTimer);
- ScreenSaverTimer = NULL;
- }
-}
-
-void
-SetScreenSaverTimer(void)
-{
- CARD32 timeout = 0;
-
-#ifdef DPMSExtension
- if (DPMSEnabled)
- {
- /*
- * A higher DPMS level has a timeout that's either less
- * than or equal to that of a lower DPMS level.
- */
- if (DPMSStandbyTime > 0)
- timeout = DPMSStandbyTime;
-
- else if (DPMSSuspendTime > 0)
- timeout = DPMSSuspendTime;
-
- else if (DPMSOffTime > 0)
- timeout = DPMSOffTime;
- }
-#endif
-
- if (ScreenSaverTime > 0)
- {
- timeout = timeout > 0 ?
- min(ScreenSaverTime, timeout) :
- ScreenSaverTime;
- }
-
-#ifdef SCREENSAVER
- if (timeout && !screenSaverSuspended) {
-#else
- if (timeout) {
-#endif
- ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout,
- ScreenSaverTimeoutExpire, NULL);
- }
- else if (ScreenSaverTimer) {
- FreeScreenSaverTimer();
- }
-}
-
+/***********************************************************
+
+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.
+
+******************************************************************/
+
+
+/*****************************************************************
+ * OS Dependent input routines:
+ *
+ * WaitForSomething
+ * TimerForce, TimerSet, TimerCheck, TimerFree
+ *
+ *****************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+#include <X11/Xos.h> /* for strings, fcntl, time */
+#include <errno.h>
+#include <stdio.h>
+#include <X11/X.h>
+#include "misc.h"
+
+#include "osdep.h"
+#include <X11/Xpoll.h>
+#include "dixstruct.h"
+#include "opaque.h"
+#ifdef DPMSExtension
+#include "dpmsproc.h"
+#endif
+
+#ifdef WIN32
+/* Error codes from windows sockets differ from fileio error codes */
+#undef EINTR
+#define EINTR WSAEINTR
+#undef EINVAL
+#define EINVAL WSAEINVAL
+#undef EBADF
+#define EBADF WSAENOTSOCK
+/* Windows select does not set errno. Use GetErrno as wrapper for
+ WSAGetLastError */
+#define GetErrno WSAGetLastError
+#else
+/* This is just a fallback to errno to hide the differences between unix and
+ Windows in the code */
+#define GetErrno() errno
+#endif
+
+/* like ffs, but uses fd_mask instead of int as argument, so it works
+ when fd_mask is longer than an int, such as common 64-bit platforms */
+/* modifications by raphael */
+int
+mffs(fd_mask mask)
+{
+ int i;
+
+ if (!mask) return 0;
+ i = 1;
+ while (!(mask & 1))
+ {
+ i++;
+ mask >>= 1;
+ }
+ return i;
+}
+
+#ifdef DPMSExtension
+#include <X11/extensions/dpmsconst.h>
+#endif
+
+struct _OsTimerRec {
+ OsTimerPtr next;
+ CARD32 expires;
+ CARD32 delta;
+ OsTimerCallback callback;
+ pointer arg;
+};
+
+static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
+static void CheckAllTimers(void);
+static OsTimerPtr timers = NULL;
+
+/*****************
+ * WaitForSomething:
+ * Make the server suspend until there is
+ * 1. data from clients or
+ * 2. input events available or
+ * 3. ddx notices something of interest (graphics
+ * queue ready, etc.) or
+ * 4. clients that have buffered replies/events are ready
+ *
+ * If the time between INPUT events is
+ * greater than ScreenSaverTime, the display is turned off (or
+ * saved, depending on the hardware). So, WaitForSomething()
+ * has to handle this also (that's why the select() has a timeout.
+ * For more info on ClientsWithInput, see ReadRequestFromClient().
+ * pClientsReady is an array to store ready client->index values into.
+ *****************/
+
+int
+WaitForSomething(int *pClientsReady)
+{
+ int i;
+ struct timeval waittime, *wt;
+ INT32 timeout = 0;
+ fd_set clientsReadable;
+ fd_set clientsWritable;
+ int curclient;
+ int selecterr;
+ static int nready;
+ fd_set devicesReadable;
+ CARD32 now = 0;
+ Bool someReady = FALSE;
+
+ FD_ZERO(&clientsReadable);
+
+ if (nready)
+ SmartScheduleStopTimer();
+ nready = 0;
+
+ /* We need a while loop here to handle
+ crashed connections and the screen saver timeout */
+ while (1)
+ {
+ /* deal with any blocked jobs */
+ if (workQueue)
+ ProcessWorkQueue();
+ if (XFD_ANYSET (&ClientsWithInput))
+ {
+ if (!SmartScheduleDisable)
+ {
+ someReady = TRUE;
+ waittime.tv_sec = 0;
+ waittime.tv_usec = 0;
+ wt = &waittime;
+ }
+ else
+ {
+ XFD_COPYSET (&ClientsWithInput, &clientsReadable);
+ break;
+ }
+ }
+ if (someReady)
+ {
+ XFD_COPYSET(&AllSockets, &LastSelectMask);
+ XFD_UNSET(&LastSelectMask, &ClientsWithInput);
+ }
+ else
+ {
+ wt = NULL;
+ if (timers)
+ {
+ now = GetTimeInMillis();
+ timeout = timers->expires - now;
+ if (timeout > 0 && timeout > timers->delta + 250) {
+ /* time has rewound. reset the timers. */
+ CheckAllTimers();
+ }
+
+ if (timers) {
+ timeout = timers->expires - now;
+ if (timeout < 0)
+ timeout = 0;
+ waittime.tv_sec = timeout / MILLI_PER_SECOND;
+ waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
+ (1000000 / MILLI_PER_SECOND);
+ wt = &waittime;
+ }
+ }
+ XFD_COPYSET(&AllSockets, &LastSelectMask);
+ }
+
+ BlockHandler((pointer)&wt, (pointer)&LastSelectMask);
+ if (NewOutputPending)
+ FlushAllOutput();
+ /* keep this check close to select() call to minimize race */
+ if (dispatchException)
+ i = -1;
+ else if (AnyClientsWriteBlocked)
+ {
+ XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
+ i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
+ }
+ else
+ {
+ i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
+ }
+ selecterr = GetErrno();
+ WakeupHandler(i, (pointer)&LastSelectMask);
+ if (i <= 0) /* An error or timeout occurred */
+ {
+ if (dispatchException)
+ return 0;
+ if (i < 0)
+ {
+ if (selecterr == EBADF) /* Some client disconnected */
+ {
+ CheckConnections ();
+ if (! XFD_ANYSET (&AllClients))
+ return 0;
+ }
+ else if (selecterr == EINVAL)
+ {
+ FatalError("WaitForSomething(): select: %s\n",
+ strerror(selecterr));
+ }
+ else if (selecterr != EINTR && selecterr != EAGAIN)
+ {
+ ErrorF("WaitForSomething(): select: %s\n",
+ strerror(selecterr));
+ }
+ }
+ else if (someReady)
+ {
+ /*
+ * If no-one else is home, bail quickly
+ */
+ XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
+ XFD_COPYSET(&ClientsWithInput, &clientsReadable);
+ break;
+ }
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
+
+ if (timers)
+ {
+ int expired = 0;
+ now = GetTimeInMillis();
+ if ((int) (timers->expires - now) <= 0)
+ expired = 1;
+
+ while (timers && (int) (timers->expires - now) <= 0)
+ DoTimer(timers, now, &timers);
+
+ if (expired)
+ return 0;
+ }
+ }
+ else
+ {
+ fd_set tmp_set;
+
+ if (*checkForInput[0] == *checkForInput[1]) {
+ if (timers)
+ {
+ int expired = 0;
+ now = GetTimeInMillis();
+ if ((int) (timers->expires - now) <= 0)
+ expired = 1;
+
+ while (timers && (int) (timers->expires - now) <= 0)
+ DoTimer(timers, now, &timers);
+
+ if (expired)
+ return 0;
+ }
+ }
+ if (someReady)
+ XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
+ if (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable))
+ {
+ NewOutputPending = TRUE;
+ XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
+ XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
+ if (! XFD_ANYSET(&ClientsWriteBlocked))
+ AnyClientsWriteBlocked = FALSE;
+ }
+
+ XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices);
+ XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
+ XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections);
+ if (XFD_ANYSET(&tmp_set))
+ QueueWorkProc(EstablishNewConnections, NULL,
+ (pointer)&LastSelectMask);
+
+ if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable))
+ break;
+ /* check here for DDXes that queue events during Block/Wakeup */
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
+ }
+ }
+
+ nready = 0;
+ if (XFD_ANYSET (&clientsReadable))
+ {
+#ifndef WIN32
+ for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
+ {
+ int highest_priority = 0;
+
+ while (clientsReadable.fds_bits[i])
+ {
+ int client_priority, client_index;
+
+ curclient = mffs (clientsReadable.fds_bits[i]) - 1;
+ client_index = /* raphael: modified */
+ ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))];
+#else
+ int highest_priority = 0;
+ fd_set savedClientsReadable;
+ XFD_COPYSET(&clientsReadable, &savedClientsReadable);
+ for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++)
+ {
+ int client_priority, client_index;
+
+ curclient = XFD_FD(&savedClientsReadable, i);
+ client_index = GetConnectionTranslation(curclient);
+#endif
+ /* We implement "strict" priorities.
+ * Only the highest priority client is returned to
+ * dix. If multiple clients at the same priority are
+ * ready, they are all returned. This means that an
+ * aggressive client could take over the server.
+ * This was not considered a big problem because
+ * aggressive clients can hose the server in so many
+ * other ways :)
+ */
+ client_priority = clients[client_index]->priority;
+ if (nready == 0 || client_priority > highest_priority)
+ {
+ /* Either we found the first client, or we found
+ * a client whose priority is greater than all others
+ * that have been found so far. Either way, we want
+ * to initialize the list of clients to contain just
+ * this client.
+ */
+ pClientsReady[0] = client_index;
+ highest_priority = client_priority;
+ nready = 1;
+ }
+ /* the following if makes sure that multiple same-priority
+ * clients get batched together
+ */
+ else if (client_priority == highest_priority)
+ {
+ pClientsReady[nready++] = client_index;
+ }
+#ifndef WIN32
+ clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient);
+ }
+#else
+ FD_CLR(curclient, &clientsReadable);
+#endif
+ }
+ }
+
+ if (nready)
+ SmartScheduleStartTimer();
+
+ return nready;
+}
+
+/* If time has rewound, re-run every affected timer.
+ * Timers might drop out of the list, so we have to restart every time. */
+static void
+CheckAllTimers(void)
+{
+ OsTimerPtr timer;
+ CARD32 now;
+
+start:
+ now = GetTimeInMillis();
+
+ for (timer = timers; timer; timer = timer->next) {
+ if (timer->expires - now > timer->delta + 250) {
+ TimerForce(timer);
+ goto start;
+ }
+ }
+}
+
+static void
+DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
+{
+ CARD32 newTime;
+
+ *prev = timer->next;
+ timer->next = NULL;
+ newTime = (*timer->callback)(timer, now, timer->arg);
+ if (newTime)
+ TimerSet(timer, 0, newTime, timer->callback, timer->arg);
+}
+
+OsTimerPtr
+TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
+ OsTimerCallback func, pointer arg)
+{
+ register OsTimerPtr *prev;
+ CARD32 now = GetTimeInMillis();
+
+ if (!timer)
+ {
+ timer = malloc(sizeof(struct _OsTimerRec));
+ if (!timer)
+ return NULL;
+ }
+ else
+ {
+ for (prev = &timers; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == timer)
+ {
+ *prev = timer->next;
+ if (flags & TimerForceOld)
+ (void)(*timer->callback)(timer, now, timer->arg);
+ break;
+ }
+ }
+ }
+ if (!millis)
+ return timer;
+ if (flags & TimerAbsolute) {
+ timer->delta = millis - now;
+ }
+ else {
+ timer->delta = millis;
+ millis += now;
+ }
+ timer->expires = millis;
+ timer->callback = func;
+ timer->arg = arg;
+ if ((int) (millis - now) <= 0)
+ {
+ timer->next = NULL;
+ millis = (*timer->callback)(timer, now, timer->arg);
+ if (!millis)
+ return timer;
+ }
+ for (prev = &timers;
+ *prev && (int) ((*prev)->expires - millis) <= 0;
+ prev = &(*prev)->next)
+ ;
+ timer->next = *prev;
+ *prev = timer;
+ return timer;
+}
+
+Bool
+TimerForce(OsTimerPtr timer)
+{
+ OsTimerPtr *prev;
+
+ for (prev = &timers; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == timer)
+ {
+ DoTimer(timer, GetTimeInMillis(), prev);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+void
+TimerCancel(OsTimerPtr timer)
+{
+ OsTimerPtr *prev;
+
+ if (!timer)
+ return;
+ for (prev = &timers; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == timer)
+ {
+ *prev = timer->next;
+ break;
+ }
+ }
+}
+
+void
+TimerFree(OsTimerPtr timer)
+{
+ if (!timer)
+ return;
+ TimerCancel(timer);
+ free(timer);
+}
+
+void
+TimerCheck(void)
+{
+ CARD32 now = GetTimeInMillis();
+
+ while (timers && (int) (timers->expires - now) <= 0)
+ DoTimer(timers, now, &timers);
+}
+
+void
+TimerInit(void)
+{
+ OsTimerPtr timer;
+
+ while ((timer = timers))
+ {
+ timers = timer->next;
+ free(timer);
+ }
+}
+
+#ifdef DPMSExtension
+
+#define DPMS_CHECK_MODE(mode,time)\
+ if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
+ DPMSSet(serverClient, mode);
+
+#define DPMS_CHECK_TIMEOUT(time)\
+ if (time > 0 && (time - timeout) > 0)\
+ return time - timeout;
+
+static CARD32
+NextDPMSTimeout(INT32 timeout)
+{
+ /*
+ * Return the amount of time remaining until we should set
+ * the next power level. Fallthroughs are intentional.
+ */
+ switch (DPMSPowerLevel)
+ {
+ case DPMSModeOn:
+ DPMS_CHECK_TIMEOUT(DPMSStandbyTime)
+
+ case DPMSModeStandby:
+ DPMS_CHECK_TIMEOUT(DPMSSuspendTime)
+
+ case DPMSModeSuspend:
+ DPMS_CHECK_TIMEOUT(DPMSOffTime)
+
+ default: /* DPMSModeOff */
+ return 0;
+ }
+}
+#endif /* DPMSExtension */
+
+static CARD32
+ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+ INT32 timeout = now - lastDeviceEventTime.milliseconds;
+ CARD32 nextTimeout = 0;
+
+#ifdef DPMSExtension
+ /*
+ * Check each mode lowest to highest, since a lower mode can
+ * have the same timeout as a higher one.
+ */
+ if (DPMSEnabled)
+ {
+ DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime)
+ DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime)
+ DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime)
+
+ nextTimeout = NextDPMSTimeout(timeout);
+ }
+
+ /*
+ * Only do the screensaver checks if we're not in a DPMS
+ * power saving mode
+ */
+ if (DPMSPowerLevel != DPMSModeOn)
+ return nextTimeout;
+#endif /* DPMSExtension */
+
+ if (!ScreenSaverTime)
+ return nextTimeout;
+
+ if (timeout < ScreenSaverTime)
+ {
+ return nextTimeout > 0 ?
+ min(ScreenSaverTime - timeout, nextTimeout) :
+ ScreenSaverTime - timeout;
+ }
+
+ ResetOsBuffers(); /* not ideal, but better than nothing */
+ dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive);
+
+ if (ScreenSaverInterval > 0)
+ {
+ nextTimeout = nextTimeout > 0 ?
+ min(ScreenSaverInterval, nextTimeout) :
+ ScreenSaverInterval;
+ }
+
+ return nextTimeout;
+}
+
+static OsTimerPtr ScreenSaverTimer = NULL;
+
+void
+FreeScreenSaverTimer(void)
+{
+ if (ScreenSaverTimer) {
+ TimerFree(ScreenSaverTimer);
+ ScreenSaverTimer = NULL;
+ }
+}
+
+void
+SetScreenSaverTimer(void)
+{
+ CARD32 timeout = 0;
+
+#ifdef DPMSExtension
+ if (DPMSEnabled)
+ {
+ /*
+ * A higher DPMS level has a timeout that's either less
+ * than or equal to that of a lower DPMS level.
+ */
+ if (DPMSStandbyTime > 0)
+ timeout = DPMSStandbyTime;
+
+ else if (DPMSSuspendTime > 0)
+ timeout = DPMSSuspendTime;
+
+ else if (DPMSOffTime > 0)
+ timeout = DPMSOffTime;
+ }
+#endif
+
+ if (ScreenSaverTime > 0)
+ {
+ timeout = timeout > 0 ?
+ min(ScreenSaverTime, timeout) :
+ ScreenSaverTime;
+ }
+
+#ifdef SCREENSAVER
+ if (timeout && !screenSaverSuspended) {
+#else
+ if (timeout) {
+#endif
+ ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout,
+ ScreenSaverTimeoutExpire, NULL);
+ }
+ else if (ScreenSaverTimer) {
+ FreeScreenSaverTimer();
+ }
+}
+
diff --git a/xorg-server/test/input.c b/xorg-server/test/input.c
index 877e9776b..879e14f2f 100644
--- a/xorg-server/test/input.c
+++ b/xorg-server/test/input.c
@@ -1,1089 +1,1083 @@
-/**
- * Copyright © 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdint.h>
-#include <X11/X.h>
-#include "misc.h"
-#include "resource.h"
-#include <X11/Xproto.h>
-#include <X11/extensions/XI2proto.h>
-#include <X11/Xatom.h>
-#include "windowstr.h"
-#include "inputstr.h"
-#include "eventconvert.h"
-#include "exevents.h"
-#include "dixgrabs.h"
-#include "eventstr.h"
-#include "inpututils.h"
-#include <glib.h>
-
-/**
- * Init a device with axes.
- * Verify values set on the device.
- *
- * Result: All axes set to default values (usually 0).
- */
-static void dix_init_valuators(void)
-{
- DeviceIntRec dev;
- ValuatorClassPtr val;
- const int num_axes = 2;
- int i;
- Atom atoms[MAX_VALUATORS] = { 0 };
-
-
- memset(&dev, 0, sizeof(DeviceIntRec));
- dev.type = MASTER_POINTER; /* claim it's a master to stop ptracccel */
-
- g_assert(InitValuatorClassDeviceStruct(NULL, 0, atoms, 0, 0) == FALSE);
- g_assert(InitValuatorClassDeviceStruct(&dev, num_axes, atoms, 0, Absolute));
-
- val = dev.valuator;
- g_assert(val);
- g_assert(val->numAxes == num_axes);
- g_assert(val->numMotionEvents == 0);
- g_assert(val->axisVal);
-
- for (i = 0; i < num_axes; i++)
- {
- g_assert(val->axisVal[i] == 0);
- g_assert(val->axes->min_value == NO_AXIS_LIMITS);
- g_assert(val->axes->max_value == NO_AXIS_LIMITS);
- g_assert(val->axes->mode == Absolute);
- }
-
- g_assert(dev.last.numValuators == num_axes);
-}
-
-/* just check the known success cases, and that error cases set the client's
- * error value correctly. */
-static void dix_check_grab_values(void)
-{
- ClientRec client;
- GrabParameters param;
- int rc;
-
- memset(&client, 0, sizeof(client));
-
- param.grabtype = GRABTYPE_CORE;
- param.this_device_mode = GrabModeSync;
- param.other_devices_mode = GrabModeSync;
- param.modifiers = AnyModifier;
- param.ownerEvents = FALSE;
-
- rc = CheckGrabValues(&client, &param);
- g_assert(rc == Success);
-
- param.this_device_mode = GrabModeAsync;
- rc = CheckGrabValues(&client, &param);
- g_assert(rc == Success);
-
- param.this_device_mode = GrabModeAsync + 1;
- rc = CheckGrabValues(&client, &param);
- g_assert(rc == BadValue);
- g_assert(client.errorValue == param.this_device_mode);
- g_assert(client.errorValue == GrabModeAsync + 1);
-
- param.this_device_mode = GrabModeSync;
- param.other_devices_mode = GrabModeAsync;
- rc = CheckGrabValues(&client, &param);
- g_assert(rc == Success);
-
- param.other_devices_mode = GrabModeAsync + 1;
- rc = CheckGrabValues(&client, &param);
- g_assert(rc == BadValue);
- g_assert(client.errorValue == param.other_devices_mode);
- g_assert(client.errorValue == GrabModeAsync + 1);
-
- param.other_devices_mode = GrabModeSync;
-
- param.modifiers = 1 << 13;
- rc = CheckGrabValues(&client, &param);
- g_assert(rc == BadValue);
- g_assert(client.errorValue == param.modifiers);
- g_assert(client.errorValue == (1 << 13));
-
-
- param.modifiers = AnyModifier;
- param.ownerEvents = TRUE;
- rc = CheckGrabValues(&client, &param);
- g_assert(rc == Success);
-
- param.ownerEvents = 3;
- rc = CheckGrabValues(&client, &param);
- g_assert(rc == BadValue);
- g_assert(client.errorValue == param.ownerEvents);
- g_assert(client.errorValue == 3);
-}
-
-
-/**
- * Convert various internal events to the matching core event and verify the
- * parameters.
- */
-static void dix_event_to_core(int type)
-{
- DeviceEvent ev;
- xEvent core;
- int time;
- int x, y;
- int rc;
- int state;
- int detail;
- const int ROOT_WINDOW_ID = 0x100;
-
- /* EventToCore memsets the event to 0 */
-#define test_event() \
- g_assert(rc == Success); \
- g_assert(core.u.u.type == type); \
- g_assert(core.u.u.detail == detail); \
- g_assert(core.u.keyButtonPointer.time == time); \
- g_assert(core.u.keyButtonPointer.rootX == x); \
- g_assert(core.u.keyButtonPointer.rootY == y); \
- g_assert(core.u.keyButtonPointer.state == state); \
- g_assert(core.u.keyButtonPointer.eventX == 0); \
- g_assert(core.u.keyButtonPointer.eventY == 0); \
- g_assert(core.u.keyButtonPointer.root == ROOT_WINDOW_ID); \
- g_assert(core.u.keyButtonPointer.event == 0); \
- g_assert(core.u.keyButtonPointer.child == 0); \
- g_assert(core.u.keyButtonPointer.sameScreen == FALSE);
-
- x = 0;
- y = 0;
- time = 12345;
- state = 0;
- detail = 0;
-
- ev.header = 0xFF;
- ev.length = sizeof(DeviceEvent);
- ev.time = time;
- ev.root_y = x;
- ev.root_x = y;
- SetBit(ev.valuators.mask, 0);
- SetBit(ev.valuators.mask, 1);
- ev.root = ROOT_WINDOW_ID;
- ev.corestate = state;
- ev.detail.key = detail;
-
- ev.type = type;
- ev.detail.key = 0;
- rc = EventToCore((InternalEvent*)&ev, &core);
- test_event();
-
- x = 1;
- y = 2;
- ev.root_x = x;
- ev.root_y = y;
- rc = EventToCore((InternalEvent*)&ev, &core);
- test_event();
-
- x = 0x7FFF;
- y = 0x7FFF;
- ev.root_x = x;
- ev.root_y = y;
- rc = EventToCore((InternalEvent*)&ev, &core);
- test_event();
-
- x = 0x8000; /* too high */
- y = 0x8000; /* too high */
- ev.root_x = x;
- ev.root_y = y;
- rc = EventToCore((InternalEvent*)&ev, &core);
- g_assert(core.u.keyButtonPointer.rootX != x);
- g_assert(core.u.keyButtonPointer.rootY != y);
-
- x = 0x7FFF;
- y = 0x7FFF;
- ev.root_x = x;
- ev.root_y = y;
- time = 0;
- ev.time = time;
- rc = EventToCore((InternalEvent*)&ev, &core);
- test_event();
-
- detail = 1;
- ev.detail.key = detail;
- rc = EventToCore((InternalEvent*)&ev, &core);
- test_event();
-
- detail = 0xFF; /* highest value */
- ev.detail.key = detail;
- rc = EventToCore((InternalEvent*)&ev, &core);
- test_event();
-
- detail = 0xFFF; /* too big */
- ev.detail.key = detail;
- rc = EventToCore((InternalEvent*)&ev, &core);
- g_assert(rc == BadMatch);
-
- detail = 0xFF; /* too big */
- ev.detail.key = detail;
- state = 0xFFFF; /* highest value */
- ev.corestate = state;
- rc = EventToCore((InternalEvent*)&ev, &core);
- test_event();
-
- state = 0x10000; /* too big */
- ev.corestate = state;
- rc = EventToCore((InternalEvent*)&ev, &core);
- g_assert(core.u.keyButtonPointer.state != state);
- g_assert(core.u.keyButtonPointer.state == (state & 0xFFFF));
-
-#undef test_event
-}
-
-static void dix_event_to_core_conversion(void)
-{
- DeviceEvent ev;
- xEvent core;
- int rc;
-
- ev.header = 0xFF;
- ev.length = sizeof(DeviceEvent);
-
- ev.type = 0;
- rc = EventToCore((InternalEvent*)&ev, &core);
- g_assert(rc == BadImplementation);
-
- ev.type = 1;
- rc = EventToCore((InternalEvent*)&ev, &core);
- g_assert(rc == BadImplementation);
-
- ev.type = ET_ProximityOut + 1;
- rc = EventToCore((InternalEvent*)&ev, &core);
- g_assert(rc == BadImplementation);
-
- ev.type = ET_ProximityIn;
- rc = EventToCore((InternalEvent*)&ev, &core);
- g_assert(rc == BadMatch);
-
- ev.type = ET_ProximityOut;
- rc = EventToCore((InternalEvent*)&ev, &core);
- g_assert(rc == BadMatch);
-
- dix_event_to_core(ET_KeyPress);
- dix_event_to_core(ET_KeyRelease);
- dix_event_to_core(ET_ButtonPress);
- dix_event_to_core(ET_ButtonRelease);
- dix_event_to_core(ET_Motion);
-}
-
-static void xi2_struct_sizes(void)
-{
-#define compare(req) \
- g_assert(sizeof(req) == sz_##req);
-
- compare(xXIQueryVersionReq);
- compare(xXIWarpPointerReq);
- compare(xXIChangeCursorReq);
- compare(xXIChangeHierarchyReq);
- compare(xXISetClientPointerReq);
- compare(xXIGetClientPointerReq);
- compare(xXISelectEventsReq);
- compare(xXIQueryVersionReq);
- compare(xXIQueryDeviceReq);
- compare(xXISetFocusReq);
- compare(xXIGetFocusReq);
- compare(xXIGrabDeviceReq);
- compare(xXIUngrabDeviceReq);
- compare(xXIAllowEventsReq);
- compare(xXIPassiveGrabDeviceReq);
- compare(xXIPassiveUngrabDeviceReq);
- compare(xXIListPropertiesReq);
- compare(xXIChangePropertyReq);
- compare(xXIDeletePropertyReq);
- compare(xXIGetPropertyReq);
- compare(xXIGetSelectedEventsReq);
-#undef compare
-}
-
-
-static void dix_grab_matching(void)
-{
- DeviceIntRec xi_all_devices, xi_all_master_devices, dev1, dev2;
- GrabRec a, b;
- BOOL rc;
-
- memset(&a, 0, sizeof(a));
- memset(&b, 0, sizeof(b));
-
- /* different grabtypes must fail */
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_XI2;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI2;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_CORE;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- /* XI2 grabs for different devices must fail, regardless of ignoreDevice
- * XI2 grabs for master devices must fail against a slave */
- memset(&xi_all_devices, 0, sizeof(DeviceIntRec));
- memset(&xi_all_master_devices, 0, sizeof(DeviceIntRec));
- memset(&dev1, 0, sizeof(DeviceIntRec));
- memset(&dev2, 0, sizeof(DeviceIntRec));
-
- xi_all_devices.id = XIAllDevices;
- xi_all_master_devices.id = XIAllMasterDevices;
- dev1.id = 10;
- dev1.type = SLAVE;
- dev2.id = 11;
- dev2.type = SLAVE;
-
- inputInfo.all_devices = &xi_all_devices;
- inputInfo.all_master_devices = &xi_all_master_devices;
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.device = &dev1;
- b.device = &dev2;
-
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
-
- a.device = &dev2;
- b.device = &dev1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
-
- a.device = inputInfo.all_master_devices;
- b.device = &dev1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
-
- a.device = &dev1;
- b.device = inputInfo.all_master_devices;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
-
- /* ignoreDevice FALSE must fail for different devices for CORE and XI */
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- a.device = &dev1;
- b.device = &dev2;
- a.modifierDevice = &dev1;
- b.modifierDevice = &dev1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- a.device = &dev1;
- b.device = &dev2;
- a.modifierDevice = &dev1;
- b.modifierDevice = &dev1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
-
- /* ignoreDevice FALSE must fail for different modifier devices for CORE
- * and XI */
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- a.device = &dev1;
- b.device = &dev1;
- a.modifierDevice = &dev1;
- b.modifierDevice = &dev2;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- a.device = &dev1;
- b.device = &dev1;
- a.modifierDevice = &dev1;
- b.modifierDevice = &dev2;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
-
- /* different event type must fail */
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.device = &dev1;
- b.device = &dev1;
- a.modifierDevice = &dev1;
- b.modifierDevice = &dev1;
- a.type = XI_KeyPress;
- b.type = XI_KeyRelease;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- a.device = &dev1;
- b.device = &dev1;
- a.modifierDevice = &dev1;
- b.modifierDevice = &dev1;
- a.type = XI_KeyPress;
- b.type = XI_KeyRelease;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- a.device = &dev1;
- b.device = &dev1;
- a.modifierDevice = &dev1;
- b.modifierDevice = &dev1;
- a.type = XI_KeyPress;
- b.type = XI_KeyRelease;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&a, &b, TRUE);
- g_assert(rc == FALSE);
-
- /* different modifiers must fail */
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.device = &dev1;
- b.device = &dev1;
- a.modifierDevice = &dev1;
- b.modifierDevice = &dev1;
- a.type = XI_KeyPress;
- b.type = XI_KeyPress;
- a.modifiersDetail.exact = 1;
- b.modifiersDetail.exact = 2;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- /* AnyModifier must fail for XI2 */
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.modifiersDetail.exact = AnyModifier;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- /* XIAnyModifier must fail for CORE and XI */
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- a.modifiersDetail.exact = XIAnyModifier;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- a.modifiersDetail.exact = XIAnyModifier;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- /* different detail must fail */
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.detail.exact = 1;
- b.detail.exact = 2;
- a.modifiersDetail.exact = 1;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- /* detail of AnyModifier must fail */
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.detail.exact = AnyModifier;
- b.detail.exact = 1;
- a.modifiersDetail.exact = 1;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- /* detail of XIAnyModifier must fail */
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.detail.exact = XIAnyModifier;
- b.detail.exact = 1;
- a.modifiersDetail.exact = 1;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == FALSE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == FALSE);
-
- /* XIAnyModifier or AnyModifer must succeed */
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.detail.exact = 1;
- b.detail.exact = 1;
- a.modifiersDetail.exact = XIAnyModifier;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- a.detail.exact = 1;
- b.detail.exact = 1;
- a.modifiersDetail.exact = AnyModifier;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- a.detail.exact = 1;
- b.detail.exact = 1;
- a.modifiersDetail.exact = AnyModifier;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
-
- /* AnyKey or XIAnyKeycode must succeed */
- a.grabtype = GRABTYPE_XI2;
- b.grabtype = GRABTYPE_XI2;
- a.detail.exact = XIAnyKeycode;
- b.detail.exact = 1;
- a.modifiersDetail.exact = 1;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
-
- a.grabtype = GRABTYPE_CORE;
- b.grabtype = GRABTYPE_CORE;
- a.detail.exact = AnyKey;
- b.detail.exact = 1;
- a.modifiersDetail.exact = 1;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
-
- a.grabtype = GRABTYPE_XI;
- b.grabtype = GRABTYPE_XI;
- a.detail.exact = AnyKey;
- b.detail.exact = 1;
- a.modifiersDetail.exact = 1;
- b.modifiersDetail.exact = 1;
- rc = GrabMatchesSecond(&a, &b, FALSE);
- g_assert(rc == TRUE);
- rc = GrabMatchesSecond(&b, &a, FALSE);
- g_assert(rc == TRUE);
-}
-
-static void test_bits_to_byte(int i)
-{
- int expected_bytes;
- expected_bytes = (i + 7)/8;
-
- g_assert(bits_to_bytes(i) >= i/8);
- g_assert((bits_to_bytes(i) * 8) - i <= 7);
- g_assert(expected_bytes == bits_to_bytes(i));
-}
-
-static void test_bytes_to_int32(int i)
-{
- int expected_4byte;
- expected_4byte = (i + 3)/4;
-
- g_assert(bytes_to_int32(i) <= i);
- g_assert((bytes_to_int32(i) * 4) - i <= 3);
- g_assert(expected_4byte == bytes_to_int32(i));
-}
-
-static void test_pad_to_int32(int i)
-{
- int expected_bytes;
- expected_bytes = ((i + 3)/4) * 4;
-
- g_assert(pad_to_int32(i) >= i);
- g_assert(pad_to_int32(i) - i <= 3);
- g_assert(expected_bytes == pad_to_int32(i));
-}
-static void include_byte_padding_macros(void)
-{
- g_test_message("Testing bits_to_bytes()");
-
- /* the macros don't provide overflow protection */
- test_bits_to_byte(0);
- test_bits_to_byte(1);
- test_bits_to_byte(2);
- test_bits_to_byte(7);
- test_bits_to_byte(8);
- test_bits_to_byte(0xFF);
- test_bits_to_byte(0x100);
- test_bits_to_byte(INT_MAX - 9);
- test_bits_to_byte(INT_MAX - 8);
-
- g_test_message("Testing bytes_to_int32()");
-
- test_bytes_to_int32(0);
- test_bytes_to_int32(1);
- test_bytes_to_int32(2);
- test_bytes_to_int32(7);
- test_bytes_to_int32(8);
- test_bytes_to_int32(0xFF);
- test_bytes_to_int32(0x100);
- test_bytes_to_int32(0xFFFF);
- test_bytes_to_int32(0x10000);
- test_bytes_to_int32(0xFFFFFF);
- test_bytes_to_int32(0x1000000);
- test_bytes_to_int32(INT_MAX - 4);
- test_bytes_to_int32(INT_MAX - 3);
-
- g_test_message("Testing pad_to_int32");
-
- test_pad_to_int32(0);
- test_pad_to_int32(0);
- test_pad_to_int32(1);
- test_pad_to_int32(2);
- test_pad_to_int32(7);
- test_pad_to_int32(8);
- test_pad_to_int32(0xFF);
- test_pad_to_int32(0x100);
- test_pad_to_int32(0xFFFF);
- test_pad_to_int32(0x10000);
- test_pad_to_int32(0xFFFFFF);
- test_pad_to_int32(0x1000000);
- test_pad_to_int32(INT_MAX - 4);
- test_pad_to_int32(INT_MAX - 3);
-}
-
-static void xi_unregister_handlers(void)
-{
- DeviceIntRec dev;
- int handler;
-
- memset(&dev, 0, sizeof(dev));
-
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 1);
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 2);
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 3);
-
- g_test_message("Unlinking from front.");
-
- XIUnregisterPropertyHandler(&dev, 4); /* NOOP */
- g_assert(dev.properties.handlers->id == 3);
- XIUnregisterPropertyHandler(&dev, 3);
- g_assert(dev.properties.handlers->id == 2);
- XIUnregisterPropertyHandler(&dev, 2);
- g_assert(dev.properties.handlers->id == 1);
- XIUnregisterPropertyHandler(&dev, 1);
- g_assert(dev.properties.handlers == NULL);
-
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 4);
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 5);
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 6);
- XIUnregisterPropertyHandler(&dev, 3); /* NOOP */
- g_assert(dev.properties.handlers->next->next->next == NULL);
- XIUnregisterPropertyHandler(&dev, 4);
- g_assert(dev.properties.handlers->next->next == NULL);
- XIUnregisterPropertyHandler(&dev, 5);
- g_assert(dev.properties.handlers->next == NULL);
- XIUnregisterPropertyHandler(&dev, 6);
- g_assert(dev.properties.handlers == NULL);
-
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 7);
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 8);
- handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
- g_assert(handler == 9);
-
- XIDeleteAllDeviceProperties(&dev);
- g_assert(dev.properties.handlers == NULL);
- XIUnregisterPropertyHandler(&dev, 7); /* NOOP */
-
-}
-
-static void cmp_attr_fields(InputAttributes *attr1,
- InputAttributes *attr2)
-{
- char **tags1, **tags2;
-
- g_assert(attr1 && attr2);
- g_assert(attr1 != attr2);
- g_assert(attr1->flags == attr2->flags);
-
- if (attr1->product != NULL)
- {
- g_assert(attr1->product != attr2->product);
- g_assert(strcmp(attr1->product, attr2->product) == 0);
- } else
- g_assert(attr2->product == NULL);
-
- if (attr1->vendor != NULL)
- {
- g_assert(attr1->vendor != attr2->vendor);
- g_assert(strcmp(attr1->vendor, attr2->vendor) == 0);
- } else
- g_assert(attr2->vendor == NULL);
-
- if (attr1->device != NULL)
- {
- g_assert(attr1->device != attr2->device);
- g_assert(strcmp(attr1->device, attr2->device) == 0);
- } else
- g_assert(attr2->device == NULL);
-
- if (attr1->pnp_id != NULL)
- {
- g_assert(attr1->pnp_id != attr2->pnp_id);
- g_assert(strcmp(attr1->pnp_id, attr2->pnp_id) == 0);
- } else
- g_assert(attr2->pnp_id == NULL);
-
- if (attr1->usb_id != NULL)
- {
- g_assert(attr1->usb_id != attr2->usb_id);
- g_assert(strcmp(attr1->usb_id, attr2->usb_id) == 0);
- } else
- g_assert(attr2->usb_id == NULL);
-
- tags1 = attr1->tags;
- tags2 = attr2->tags;
-
- /* if we don't have any tags, skip the tag checking bits */
- if (!tags1)
- {
- g_assert(!tags2);
- return;
- }
-
- /* Don't lug around empty arrays */
- g_assert(*tags1);
- g_assert(*tags2);
-
- /* check for identical content, but duplicated */
- while (*tags1)
- {
- g_assert(*tags1 != *tags2);
- g_assert(strcmp(*tags1, *tags2) == 0);
- tags1++;
- tags2++;
- }
-
- /* ensure tags1 and tags2 have the same no of elements */
- g_assert(!*tags2);
-
- /* check for not sharing memory */
- tags1 = attr1->tags;
- while (*tags1)
- {
- tags2 = attr2->tags;
- while (*tags2)
- g_assert(*tags1 != *tags2++);
-
- tags1++;
- }
-}
-
-static void dix_input_attributes(void)
-{
- InputAttributes orig = {0};
- InputAttributes *new;
- char *tags[4] = {"tag1", "tag2", "tag2", NULL};
-
- new = DuplicateInputAttributes(NULL);
- g_assert(!new);
-
- new = DuplicateInputAttributes(&orig);
- g_assert(memcmp(&orig, new, sizeof(InputAttributes)) == 0);
-
- orig.product = "product name";
- new = DuplicateInputAttributes(&orig);
- cmp_attr_fields(&orig, new);
- FreeInputAttributes(new);
-
- orig.vendor = "vendor name";
- new = DuplicateInputAttributes(&orig);
- cmp_attr_fields(&orig, new);
- FreeInputAttributes(new);
-
- orig.device = "device path";
- new = DuplicateInputAttributes(&orig);
- cmp_attr_fields(&orig, new);
- FreeInputAttributes(new);
-
- orig.pnp_id = "PnPID";
- new = DuplicateInputAttributes(&orig);
- cmp_attr_fields(&orig, new);
- FreeInputAttributes(new);
-
- orig.usb_id = "USBID";
- new = DuplicateInputAttributes(&orig);
- cmp_attr_fields(&orig, new);
- FreeInputAttributes(new);
-
- orig.flags = 0xF0;
- new = DuplicateInputAttributes(&orig);
- cmp_attr_fields(&orig, new);
- FreeInputAttributes(new);
-
- orig.tags = tags;
- new = DuplicateInputAttributes(&orig);
- cmp_attr_fields(&orig, new);
- FreeInputAttributes(new);
-}
-
-static void dix_input_valuator_masks(void)
-{
- ValuatorMask *mask = NULL, *copy;
- int nvaluators = MAX_VALUATORS;
- int valuators[nvaluators];
- int i;
- int first_val, num_vals;
-
- for (i = 0; i < nvaluators; i++)
- valuators[i] = i;
-
- mask = valuator_mask_new(nvaluators);
- g_assert(mask != NULL);
- g_assert(valuator_mask_size(mask) == 0);
- g_assert(valuator_mask_num_valuators(mask) == 0);
-
- for (i = 0; i < nvaluators; i++)
- {
- g_assert(!valuator_mask_isset(mask, i));
- valuator_mask_set(mask, i, valuators[i]);
- g_assert(valuator_mask_isset(mask, i));
- g_assert(valuator_mask_get(mask, i) == valuators[i]);
- g_assert(valuator_mask_size(mask) == i + 1);
- g_assert(valuator_mask_num_valuators(mask) == i + 1);
- }
-
- for (i = 0; i < nvaluators; i++)
- {
- g_assert(valuator_mask_isset(mask, i));
- valuator_mask_unset(mask, i);
- /* we're removing valuators from the front, so size should stay the
- * same until the last bit is removed */
- if (i < nvaluators - 1)
- g_assert(valuator_mask_size(mask) == nvaluators);
- g_assert(!valuator_mask_isset(mask, i));
- }
-
- g_assert(valuator_mask_size(mask) == 0);
- valuator_mask_zero(mask);
- g_assert(valuator_mask_size(mask) == 0);
- g_assert(valuator_mask_num_valuators(mask) == 0);
- for (i = 0; i < nvaluators; i++)
- g_assert(!valuator_mask_isset(mask, i));
-
- first_val = 5;
- num_vals = 6;
-
- valuator_mask_set_range(mask, first_val, num_vals, valuators);
- g_assert(valuator_mask_size(mask) == first_val + num_vals);
- g_assert(valuator_mask_num_valuators(mask) == num_vals);
- for (i = 0; i < nvaluators; i++)
- {
- if (i < first_val || i >= first_val + num_vals)
- g_assert(!valuator_mask_isset(mask, i));
- else
- {
- g_assert(valuator_mask_isset(mask, i));
- g_assert(valuator_mask_get(mask, i) == valuators[i - first_val]);
- }
- }
-
- copy = valuator_mask_new(nvaluators);
- valuator_mask_copy(copy, mask);
- g_assert(mask != copy);
- g_assert(valuator_mask_size(mask) == valuator_mask_size(copy));
- g_assert(valuator_mask_num_valuators(mask) == valuator_mask_num_valuators(copy));
-
- for (i = 0; i < nvaluators; i++)
- {
- g_assert(valuator_mask_isset(mask, i) == valuator_mask_isset(copy, i));
- g_assert(valuator_mask_get(mask, i) == valuator_mask_get(copy, i));
- }
-
- free(mask);
-}
-
-static void dix_valuator_mode(void)
-{
- DeviceIntRec dev;
- const int num_axes = MAX_VALUATORS;
- int i;
- Atom atoms[MAX_VALUATORS] = { 0 };
-
- memset(&dev, 0, sizeof(DeviceIntRec));
- dev.type = MASTER_POINTER; /* claim it's a master to stop ptracccel */
-
- g_assert(InitValuatorClassDeviceStruct(NULL, 0, atoms, 0, 0) == FALSE);
- g_assert(InitValuatorClassDeviceStruct(&dev, num_axes, atoms, 0, Absolute));
-
- for (i = 0; i < num_axes; i++)
- {
- g_assert(valuator_get_mode(&dev, i) == Absolute);
- valuator_set_mode(&dev, i, Relative);
- g_assert(dev.valuator->axes[i].mode == Relative);
- g_assert(valuator_get_mode(&dev, i) == Relative);
- }
-
- valuator_set_mode(&dev, VALUATOR_MODE_ALL_AXES, Absolute);
- for (i = 0; i < num_axes; i++)
- g_assert(valuator_get_mode(&dev, i) == Absolute);
-
- valuator_set_mode(&dev, VALUATOR_MODE_ALL_AXES, Relative);
- for (i = 0; i < num_axes; i++)
- g_assert(valuator_get_mode(&dev, i) == Relative);
-}
-
-static void include_bit_test_macros(void)
-{
- uint8_t mask[9] = { 0 };
- int i;
-
- for (i = 0; i < sizeof(mask)/sizeof(mask[0]); i++)
- {
- g_assert(BitIsOn(mask, i) == 0);
- SetBit(mask, i);
- g_assert(BitIsOn(mask, i) == 1);
- g_assert(!!(mask[i/8] & (1 << (i % 8))));
- g_assert(CountBits(mask, sizeof(mask)) == 1);
- ClearBit(mask, i);
- g_assert(BitIsOn(mask, i) == 0);
- }
-}
-
-int main(int argc, char** argv)
-{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
- g_test_add_func("/dix/input/valuator-masks", dix_input_valuator_masks);
- g_test_add_func("/dix/input/attributes", dix_input_attributes);
- g_test_add_func("/dix/input/init-valuators", dix_init_valuators);
- g_test_add_func("/dix/input/event-core-conversion", dix_event_to_core_conversion);
- g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values);
- g_test_add_func("/dix/input/xi2-struct-sizes", xi2_struct_sizes);
- g_test_add_func("/dix/input/grab_matching", dix_grab_matching);
- g_test_add_func("/dix/input/valuator_mode", dix_valuator_mode);
- g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
- g_test_add_func("/include/bit_test_macros", include_bit_test_macros);
- g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
-
-
- return g_test_run();
-}
+/**
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdint.h>
+#include <X11/X.h>
+#include "misc.h"
+#include "resource.h"
+#include <X11/Xproto.h>
+#include <X11/extensions/XI2proto.h>
+#include <X11/Xatom.h>
+#include "windowstr.h"
+#include "inputstr.h"
+#include "eventconvert.h"
+#include "exevents.h"
+#include "dixgrabs.h"
+#include "eventstr.h"
+#include "inpututils.h"
+#include <glib.h>
+
+/**
+ * Init a device with axes.
+ * Verify values set on the device.
+ *
+ * Result: All axes set to default values (usually 0).
+ */
+static void dix_init_valuators(void)
+{
+ DeviceIntRec dev;
+ ValuatorClassPtr val;
+ const int num_axes = 2;
+ int i;
+ Atom atoms[MAX_VALUATORS] = { 0 };
+
+
+ memset(&dev, 0, sizeof(DeviceIntRec));
+ dev.type = MASTER_POINTER; /* claim it's a master to stop ptracccel */
+
+ g_assert(InitValuatorClassDeviceStruct(NULL, 0, atoms, 0, 0) == FALSE);
+ g_assert(InitValuatorClassDeviceStruct(&dev, num_axes, atoms, 0, Absolute));
+
+ val = dev.valuator;
+ g_assert(val);
+ g_assert(val->numAxes == num_axes);
+ g_assert(val->numMotionEvents == 0);
+ g_assert(val->axisVal);
+
+ for (i = 0; i < num_axes; i++)
+ {
+ g_assert(val->axisVal[i] == 0);
+ g_assert(val->axes->min_value == NO_AXIS_LIMITS);
+ g_assert(val->axes->max_value == NO_AXIS_LIMITS);
+ g_assert(val->axes->mode == Absolute);
+ }
+
+ g_assert(dev.last.numValuators == num_axes);
+}
+
+/* just check the known success cases, and that error cases set the client's
+ * error value correctly. */
+static void dix_check_grab_values(void)
+{
+ ClientRec client;
+ GrabParameters param;
+ int rc;
+
+ memset(&client, 0, sizeof(client));
+
+ param.grabtype = GRABTYPE_CORE;
+ param.this_device_mode = GrabModeSync;
+ param.other_devices_mode = GrabModeSync;
+ param.modifiers = AnyModifier;
+ param.ownerEvents = FALSE;
+
+ rc = CheckGrabValues(&client, &param);
+ g_assert(rc == Success);
+
+ param.this_device_mode = GrabModeAsync;
+ rc = CheckGrabValues(&client, &param);
+ g_assert(rc == Success);
+
+ param.this_device_mode = GrabModeAsync + 1;
+ rc = CheckGrabValues(&client, &param);
+ g_assert(rc == BadValue);
+ g_assert(client.errorValue == param.this_device_mode);
+ g_assert(client.errorValue == GrabModeAsync + 1);
+
+ param.this_device_mode = GrabModeSync;
+ param.other_devices_mode = GrabModeAsync;
+ rc = CheckGrabValues(&client, &param);
+ g_assert(rc == Success);
+
+ param.other_devices_mode = GrabModeAsync + 1;
+ rc = CheckGrabValues(&client, &param);
+ g_assert(rc == BadValue);
+ g_assert(client.errorValue == param.other_devices_mode);
+ g_assert(client.errorValue == GrabModeAsync + 1);
+
+ param.other_devices_mode = GrabModeSync;
+
+ param.modifiers = 1 << 13;
+ rc = CheckGrabValues(&client, &param);
+ g_assert(rc == BadValue);
+ g_assert(client.errorValue == param.modifiers);
+ g_assert(client.errorValue == (1 << 13));
+
+
+ param.modifiers = AnyModifier;
+ param.ownerEvents = TRUE;
+ rc = CheckGrabValues(&client, &param);
+ g_assert(rc == Success);
+
+ param.ownerEvents = 3;
+ rc = CheckGrabValues(&client, &param);
+ g_assert(rc == BadValue);
+ g_assert(client.errorValue == param.ownerEvents);
+ g_assert(client.errorValue == 3);
+}
+
+
+/**
+ * Convert various internal events to the matching core event and verify the
+ * parameters.
+ */
+static void dix_event_to_core(int type)
+{
+ DeviceEvent ev;
+ xEvent core;
+ int time;
+ int x, y;
+ int rc;
+ int state;
+ int detail;
+ const int ROOT_WINDOW_ID = 0x100;
+
+ /* EventToCore memsets the event to 0 */
+#define test_event() \
+ g_assert(rc == Success); \
+ g_assert(core.u.u.type == type); \
+ g_assert(core.u.u.detail == detail); \
+ g_assert(core.u.keyButtonPointer.time == time); \
+ g_assert(core.u.keyButtonPointer.rootX == x); \
+ g_assert(core.u.keyButtonPointer.rootY == y); \
+ g_assert(core.u.keyButtonPointer.state == state); \
+ g_assert(core.u.keyButtonPointer.eventX == 0); \
+ g_assert(core.u.keyButtonPointer.eventY == 0); \
+ g_assert(core.u.keyButtonPointer.root == ROOT_WINDOW_ID); \
+ g_assert(core.u.keyButtonPointer.event == 0); \
+ g_assert(core.u.keyButtonPointer.child == 0); \
+ g_assert(core.u.keyButtonPointer.sameScreen == FALSE);
+
+ x = 0;
+ y = 0;
+ time = 12345;
+ state = 0;
+ detail = 0;
+
+ ev.header = 0xFF;
+ ev.length = sizeof(DeviceEvent);
+ ev.time = time;
+ ev.root_y = x;
+ ev.root_x = y;
+ SetBit(ev.valuators.mask, 0);
+ SetBit(ev.valuators.mask, 1);
+ ev.root = ROOT_WINDOW_ID;
+ ev.corestate = state;
+ ev.detail.key = detail;
+
+ ev.type = type;
+ ev.detail.key = 0;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ test_event();
+
+ x = 1;
+ y = 2;
+ ev.root_x = x;
+ ev.root_y = y;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ test_event();
+
+ x = 0x7FFF;
+ y = 0x7FFF;
+ ev.root_x = x;
+ ev.root_y = y;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ test_event();
+
+ x = 0x8000; /* too high */
+ y = 0x8000; /* too high */
+ ev.root_x = x;
+ ev.root_y = y;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ g_assert(core.u.keyButtonPointer.rootX != x);
+ g_assert(core.u.keyButtonPointer.rootY != y);
+
+ x = 0x7FFF;
+ y = 0x7FFF;
+ ev.root_x = x;
+ ev.root_y = y;
+ time = 0;
+ ev.time = time;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ test_event();
+
+ detail = 1;
+ ev.detail.key = detail;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ test_event();
+
+ detail = 0xFF; /* highest value */
+ ev.detail.key = detail;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ test_event();
+
+ detail = 0xFFF; /* too big */
+ ev.detail.key = detail;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ g_assert(rc == BadMatch);
+
+ detail = 0xFF; /* too big */
+ ev.detail.key = detail;
+ state = 0xFFFF; /* highest value */
+ ev.corestate = state;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ test_event();
+
+ state = 0x10000; /* too big */
+ ev.corestate = state;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ g_assert(core.u.keyButtonPointer.state != state);
+ g_assert(core.u.keyButtonPointer.state == (state & 0xFFFF));
+
+#undef test_event
+}
+
+static void dix_event_to_core_fail(int evtype, int expected_rc)
+{
+ DeviceEvent ev;
+ xEvent core;
+ int rc;
+
+ ev.header = 0xFF;
+ ev.length = sizeof(DeviceEvent);
+
+ ev.type = evtype;
+ rc = EventToCore((InternalEvent*)&ev, &core);
+ g_assert(rc == expected_rc);
+}
+
+static void dix_event_to_core_conversion(void)
+{
+ dix_event_to_core_fail(0, BadImplementation);
+ dix_event_to_core_fail(1, BadImplementation);
+ dix_event_to_core_fail(ET_ProximityOut + 1, BadImplementation);
+ dix_event_to_core_fail(ET_ProximityIn, BadMatch);
+ dix_event_to_core_fail(ET_ProximityOut, BadMatch);
+
+ dix_event_to_core(ET_KeyPress);
+ dix_event_to_core(ET_KeyRelease);
+ dix_event_to_core(ET_ButtonPress);
+ dix_event_to_core(ET_ButtonRelease);
+ dix_event_to_core(ET_Motion);
+}
+
+static void xi2_struct_sizes(void)
+{
+#define compare(req) \
+ g_assert(sizeof(req) == sz_##req);
+
+ compare(xXIQueryVersionReq);
+ compare(xXIWarpPointerReq);
+ compare(xXIChangeCursorReq);
+ compare(xXIChangeHierarchyReq);
+ compare(xXISetClientPointerReq);
+ compare(xXIGetClientPointerReq);
+ compare(xXISelectEventsReq);
+ compare(xXIQueryVersionReq);
+ compare(xXIQueryDeviceReq);
+ compare(xXISetFocusReq);
+ compare(xXIGetFocusReq);
+ compare(xXIGrabDeviceReq);
+ compare(xXIUngrabDeviceReq);
+ compare(xXIAllowEventsReq);
+ compare(xXIPassiveGrabDeviceReq);
+ compare(xXIPassiveUngrabDeviceReq);
+ compare(xXIListPropertiesReq);
+ compare(xXIChangePropertyReq);
+ compare(xXIDeletePropertyReq);
+ compare(xXIGetPropertyReq);
+ compare(xXIGetSelectedEventsReq);
+#undef compare
+}
+
+
+static void dix_grab_matching(void)
+{
+ DeviceIntRec xi_all_devices, xi_all_master_devices, dev1, dev2;
+ GrabRec a, b;
+ BOOL rc;
+
+ memset(&a, 0, sizeof(a));
+ memset(&b, 0, sizeof(b));
+
+ /* different grabtypes must fail */
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_XI2;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI2;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_CORE;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ /* XI2 grabs for different devices must fail, regardless of ignoreDevice
+ * XI2 grabs for master devices must fail against a slave */
+ memset(&xi_all_devices, 0, sizeof(DeviceIntRec));
+ memset(&xi_all_master_devices, 0, sizeof(DeviceIntRec));
+ memset(&dev1, 0, sizeof(DeviceIntRec));
+ memset(&dev2, 0, sizeof(DeviceIntRec));
+
+ xi_all_devices.id = XIAllDevices;
+ xi_all_master_devices.id = XIAllMasterDevices;
+ dev1.id = 10;
+ dev1.type = SLAVE;
+ dev2.id = 11;
+ dev2.type = SLAVE;
+
+ inputInfo.all_devices = &xi_all_devices;
+ inputInfo.all_master_devices = &xi_all_master_devices;
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.device = &dev1;
+ b.device = &dev2;
+
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+
+ a.device = &dev2;
+ b.device = &dev1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&a, &b, TRUE);
+ g_assert(rc == FALSE);
+
+ a.device = inputInfo.all_master_devices;
+ b.device = &dev1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&a, &b, TRUE);
+ g_assert(rc == FALSE);
+
+ a.device = &dev1;
+ b.device = inputInfo.all_master_devices;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&a, &b, TRUE);
+ g_assert(rc == FALSE);
+
+ /* ignoreDevice FALSE must fail for different devices for CORE and XI */
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ a.device = &dev1;
+ b.device = &dev2;
+ a.modifierDevice = &dev1;
+ b.modifierDevice = &dev1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ a.device = &dev1;
+ b.device = &dev2;
+ a.modifierDevice = &dev1;
+ b.modifierDevice = &dev1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+
+ /* ignoreDevice FALSE must fail for different modifier devices for CORE
+ * and XI */
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ a.device = &dev1;
+ b.device = &dev1;
+ a.modifierDevice = &dev1;
+ b.modifierDevice = &dev2;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ a.device = &dev1;
+ b.device = &dev1;
+ a.modifierDevice = &dev1;
+ b.modifierDevice = &dev2;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+
+ /* different event type must fail */
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.device = &dev1;
+ b.device = &dev1;
+ a.modifierDevice = &dev1;
+ b.modifierDevice = &dev1;
+ a.type = XI_KeyPress;
+ b.type = XI_KeyRelease;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&a, &b, TRUE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ a.device = &dev1;
+ b.device = &dev1;
+ a.modifierDevice = &dev1;
+ b.modifierDevice = &dev1;
+ a.type = XI_KeyPress;
+ b.type = XI_KeyRelease;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&a, &b, TRUE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ a.device = &dev1;
+ b.device = &dev1;
+ a.modifierDevice = &dev1;
+ b.modifierDevice = &dev1;
+ a.type = XI_KeyPress;
+ b.type = XI_KeyRelease;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&a, &b, TRUE);
+ g_assert(rc == FALSE);
+
+ /* different modifiers must fail */
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.device = &dev1;
+ b.device = &dev1;
+ a.modifierDevice = &dev1;
+ b.modifierDevice = &dev1;
+ a.type = XI_KeyPress;
+ b.type = XI_KeyPress;
+ a.modifiersDetail.exact = 1;
+ b.modifiersDetail.exact = 2;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ /* AnyModifier must fail for XI2 */
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.modifiersDetail.exact = AnyModifier;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ /* XIAnyModifier must fail for CORE and XI */
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ a.modifiersDetail.exact = XIAnyModifier;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ a.modifiersDetail.exact = XIAnyModifier;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ /* different detail must fail */
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.detail.exact = 1;
+ b.detail.exact = 2;
+ a.modifiersDetail.exact = 1;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ /* detail of AnyModifier must fail */
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.detail.exact = AnyModifier;
+ b.detail.exact = 1;
+ a.modifiersDetail.exact = 1;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ /* detail of XIAnyModifier must fail */
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.detail.exact = XIAnyModifier;
+ b.detail.exact = 1;
+ a.modifiersDetail.exact = 1;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == FALSE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == FALSE);
+
+ /* XIAnyModifier or AnyModifer must succeed */
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.detail.exact = 1;
+ b.detail.exact = 1;
+ a.modifiersDetail.exact = XIAnyModifier;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == TRUE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == TRUE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ a.detail.exact = 1;
+ b.detail.exact = 1;
+ a.modifiersDetail.exact = AnyModifier;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == TRUE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == TRUE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ a.detail.exact = 1;
+ b.detail.exact = 1;
+ a.modifiersDetail.exact = AnyModifier;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == TRUE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == TRUE);
+
+ /* AnyKey or XIAnyKeycode must succeed */
+ a.grabtype = GRABTYPE_XI2;
+ b.grabtype = GRABTYPE_XI2;
+ a.detail.exact = XIAnyKeycode;
+ b.detail.exact = 1;
+ a.modifiersDetail.exact = 1;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == TRUE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == TRUE);
+
+ a.grabtype = GRABTYPE_CORE;
+ b.grabtype = GRABTYPE_CORE;
+ a.detail.exact = AnyKey;
+ b.detail.exact = 1;
+ a.modifiersDetail.exact = 1;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == TRUE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == TRUE);
+
+ a.grabtype = GRABTYPE_XI;
+ b.grabtype = GRABTYPE_XI;
+ a.detail.exact = AnyKey;
+ b.detail.exact = 1;
+ a.modifiersDetail.exact = 1;
+ b.modifiersDetail.exact = 1;
+ rc = GrabMatchesSecond(&a, &b, FALSE);
+ g_assert(rc == TRUE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == TRUE);
+}
+
+static void test_bits_to_byte(int i)
+{
+ int expected_bytes;
+ expected_bytes = (i + 7)/8;
+
+ g_assert(bits_to_bytes(i) >= i/8);
+ g_assert((bits_to_bytes(i) * 8) - i <= 7);
+ g_assert(expected_bytes == bits_to_bytes(i));
+}
+
+static void test_bytes_to_int32(int i)
+{
+ int expected_4byte;
+ expected_4byte = (i + 3)/4;
+
+ g_assert(bytes_to_int32(i) <= i);
+ g_assert((bytes_to_int32(i) * 4) - i <= 3);
+ g_assert(expected_4byte == bytes_to_int32(i));
+}
+
+static void test_pad_to_int32(int i)
+{
+ int expected_bytes;
+ expected_bytes = ((i + 3)/4) * 4;
+
+ g_assert(pad_to_int32(i) >= i);
+ g_assert(pad_to_int32(i) - i <= 3);
+ g_assert(expected_bytes == pad_to_int32(i));
+}
+static void include_byte_padding_macros(void)
+{
+ g_test_message("Testing bits_to_bytes()");
+
+ /* the macros don't provide overflow protection */
+ test_bits_to_byte(0);
+ test_bits_to_byte(1);
+ test_bits_to_byte(2);
+ test_bits_to_byte(7);
+ test_bits_to_byte(8);
+ test_bits_to_byte(0xFF);
+ test_bits_to_byte(0x100);
+ test_bits_to_byte(INT_MAX - 9);
+ test_bits_to_byte(INT_MAX - 8);
+
+ g_test_message("Testing bytes_to_int32()");
+
+ test_bytes_to_int32(0);
+ test_bytes_to_int32(1);
+ test_bytes_to_int32(2);
+ test_bytes_to_int32(7);
+ test_bytes_to_int32(8);
+ test_bytes_to_int32(0xFF);
+ test_bytes_to_int32(0x100);
+ test_bytes_to_int32(0xFFFF);
+ test_bytes_to_int32(0x10000);
+ test_bytes_to_int32(0xFFFFFF);
+ test_bytes_to_int32(0x1000000);
+ test_bytes_to_int32(INT_MAX - 4);
+ test_bytes_to_int32(INT_MAX - 3);
+
+ g_test_message("Testing pad_to_int32");
+
+ test_pad_to_int32(0);
+ test_pad_to_int32(0);
+ test_pad_to_int32(1);
+ test_pad_to_int32(2);
+ test_pad_to_int32(7);
+ test_pad_to_int32(8);
+ test_pad_to_int32(0xFF);
+ test_pad_to_int32(0x100);
+ test_pad_to_int32(0xFFFF);
+ test_pad_to_int32(0x10000);
+ test_pad_to_int32(0xFFFFFF);
+ test_pad_to_int32(0x1000000);
+ test_pad_to_int32(INT_MAX - 4);
+ test_pad_to_int32(INT_MAX - 3);
+}
+
+static void xi_unregister_handlers(void)
+{
+ DeviceIntRec dev;
+ int handler;
+
+ memset(&dev, 0, sizeof(dev));
+
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 1);
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 2);
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 3);
+
+ g_test_message("Unlinking from front.");
+
+ XIUnregisterPropertyHandler(&dev, 4); /* NOOP */
+ g_assert(dev.properties.handlers->id == 3);
+ XIUnregisterPropertyHandler(&dev, 3);
+ g_assert(dev.properties.handlers->id == 2);
+ XIUnregisterPropertyHandler(&dev, 2);
+ g_assert(dev.properties.handlers->id == 1);
+ XIUnregisterPropertyHandler(&dev, 1);
+ g_assert(dev.properties.handlers == NULL);
+
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 4);
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 5);
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 6);
+ XIUnregisterPropertyHandler(&dev, 3); /* NOOP */
+ g_assert(dev.properties.handlers->next->next->next == NULL);
+ XIUnregisterPropertyHandler(&dev, 4);
+ g_assert(dev.properties.handlers->next->next == NULL);
+ XIUnregisterPropertyHandler(&dev, 5);
+ g_assert(dev.properties.handlers->next == NULL);
+ XIUnregisterPropertyHandler(&dev, 6);
+ g_assert(dev.properties.handlers == NULL);
+
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 7);
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 8);
+ handler = XIRegisterPropertyHandler(&dev, NULL, NULL, NULL);
+ g_assert(handler == 9);
+
+ XIDeleteAllDeviceProperties(&dev);
+ g_assert(dev.properties.handlers == NULL);
+ XIUnregisterPropertyHandler(&dev, 7); /* NOOP */
+
+}
+
+static void cmp_attr_fields(InputAttributes *attr1,
+ InputAttributes *attr2)
+{
+ char **tags1, **tags2;
+
+ g_assert(attr1 && attr2);
+ g_assert(attr1 != attr2);
+ g_assert(attr1->flags == attr2->flags);
+
+ if (attr1->product != NULL)
+ {
+ g_assert(attr1->product != attr2->product);
+ g_assert(strcmp(attr1->product, attr2->product) == 0);
+ } else
+ g_assert(attr2->product == NULL);
+
+ if (attr1->vendor != NULL)
+ {
+ g_assert(attr1->vendor != attr2->vendor);
+ g_assert(strcmp(attr1->vendor, attr2->vendor) == 0);
+ } else
+ g_assert(attr2->vendor == NULL);
+
+ if (attr1->device != NULL)
+ {
+ g_assert(attr1->device != attr2->device);
+ g_assert(strcmp(attr1->device, attr2->device) == 0);
+ } else
+ g_assert(attr2->device == NULL);
+
+ if (attr1->pnp_id != NULL)
+ {
+ g_assert(attr1->pnp_id != attr2->pnp_id);
+ g_assert(strcmp(attr1->pnp_id, attr2->pnp_id) == 0);
+ } else
+ g_assert(attr2->pnp_id == NULL);
+
+ if (attr1->usb_id != NULL)
+ {
+ g_assert(attr1->usb_id != attr2->usb_id);
+ g_assert(strcmp(attr1->usb_id, attr2->usb_id) == 0);
+ } else
+ g_assert(attr2->usb_id == NULL);
+
+ tags1 = attr1->tags;
+ tags2 = attr2->tags;
+
+ /* if we don't have any tags, skip the tag checking bits */
+ if (!tags1)
+ {
+ g_assert(!tags2);
+ return;
+ }
+
+ /* Don't lug around empty arrays */
+ g_assert(*tags1);
+ g_assert(*tags2);
+
+ /* check for identical content, but duplicated */
+ while (*tags1)
+ {
+ g_assert(*tags1 != *tags2);
+ g_assert(strcmp(*tags1, *tags2) == 0);
+ tags1++;
+ tags2++;
+ }
+
+ /* ensure tags1 and tags2 have the same no of elements */
+ g_assert(!*tags2);
+
+ /* check for not sharing memory */
+ tags1 = attr1->tags;
+ while (*tags1)
+ {
+ tags2 = attr2->tags;
+ while (*tags2)
+ g_assert(*tags1 != *tags2++);
+
+ tags1++;
+ }
+}
+
+static void dix_input_attributes(void)
+{
+ InputAttributes orig = {0};
+ InputAttributes *new;
+ char *tags[4] = {"tag1", "tag2", "tag2", NULL};
+
+ new = DuplicateInputAttributes(NULL);
+ g_assert(!new);
+
+ new = DuplicateInputAttributes(&orig);
+ g_assert(memcmp(&orig, new, sizeof(InputAttributes)) == 0);
+
+ orig.product = "product name";
+ new = DuplicateInputAttributes(&orig);
+ cmp_attr_fields(&orig, new);
+ FreeInputAttributes(new);
+
+ orig.vendor = "vendor name";
+ new = DuplicateInputAttributes(&orig);
+ cmp_attr_fields(&orig, new);
+ FreeInputAttributes(new);
+
+ orig.device = "device path";
+ new = DuplicateInputAttributes(&orig);
+ cmp_attr_fields(&orig, new);
+ FreeInputAttributes(new);
+
+ orig.pnp_id = "PnPID";
+ new = DuplicateInputAttributes(&orig);
+ cmp_attr_fields(&orig, new);
+ FreeInputAttributes(new);
+
+ orig.usb_id = "USBID";
+ new = DuplicateInputAttributes(&orig);
+ cmp_attr_fields(&orig, new);
+ FreeInputAttributes(new);
+
+ orig.flags = 0xF0;
+ new = DuplicateInputAttributes(&orig);
+ cmp_attr_fields(&orig, new);
+ FreeInputAttributes(new);
+
+ orig.tags = tags;
+ new = DuplicateInputAttributes(&orig);
+ cmp_attr_fields(&orig, new);
+ FreeInputAttributes(new);
+}
+
+static void dix_input_valuator_masks(void)
+{
+ ValuatorMask *mask = NULL, *copy;
+ int nvaluators = MAX_VALUATORS;
+ int valuators[nvaluators];
+ int i;
+ int first_val, num_vals;
+
+ for (i = 0; i < nvaluators; i++)
+ valuators[i] = i;
+
+ mask = valuator_mask_new(nvaluators);
+ g_assert(mask != NULL);
+ g_assert(valuator_mask_size(mask) == 0);
+ g_assert(valuator_mask_num_valuators(mask) == 0);
+
+ for (i = 0; i < nvaluators; i++)
+ {
+ g_assert(!valuator_mask_isset(mask, i));
+ valuator_mask_set(mask, i, valuators[i]);
+ g_assert(valuator_mask_isset(mask, i));
+ g_assert(valuator_mask_get(mask, i) == valuators[i]);
+ g_assert(valuator_mask_size(mask) == i + 1);
+ g_assert(valuator_mask_num_valuators(mask) == i + 1);
+ }
+
+ for (i = 0; i < nvaluators; i++)
+ {
+ g_assert(valuator_mask_isset(mask, i));
+ valuator_mask_unset(mask, i);
+ /* we're removing valuators from the front, so size should stay the
+ * same until the last bit is removed */
+ if (i < nvaluators - 1)
+ g_assert(valuator_mask_size(mask) == nvaluators);
+ g_assert(!valuator_mask_isset(mask, i));
+ }
+
+ g_assert(valuator_mask_size(mask) == 0);
+ valuator_mask_zero(mask);
+ g_assert(valuator_mask_size(mask) == 0);
+ g_assert(valuator_mask_num_valuators(mask) == 0);
+ for (i = 0; i < nvaluators; i++)
+ g_assert(!valuator_mask_isset(mask, i));
+
+ first_val = 5;
+ num_vals = 6;
+
+ valuator_mask_set_range(mask, first_val, num_vals, valuators);
+ g_assert(valuator_mask_size(mask) == first_val + num_vals);
+ g_assert(valuator_mask_num_valuators(mask) == num_vals);
+ for (i = 0; i < nvaluators; i++)
+ {
+ if (i < first_val || i >= first_val + num_vals)
+ g_assert(!valuator_mask_isset(mask, i));
+ else
+ {
+ g_assert(valuator_mask_isset(mask, i));
+ g_assert(valuator_mask_get(mask, i) == valuators[i - first_val]);
+ }
+ }
+
+ copy = valuator_mask_new(nvaluators);
+ valuator_mask_copy(copy, mask);
+ g_assert(mask != copy);
+ g_assert(valuator_mask_size(mask) == valuator_mask_size(copy));
+ g_assert(valuator_mask_num_valuators(mask) == valuator_mask_num_valuators(copy));
+
+ for (i = 0; i < nvaluators; i++)
+ {
+ g_assert(valuator_mask_isset(mask, i) == valuator_mask_isset(copy, i));
+ g_assert(valuator_mask_get(mask, i) == valuator_mask_get(copy, i));
+ }
+
+ valuator_mask_free(&mask);
+ g_assert(mask == NULL);
+}
+
+static void dix_valuator_mode(void)
+{
+ DeviceIntRec dev;
+ const int num_axes = MAX_VALUATORS;
+ int i;
+ Atom atoms[MAX_VALUATORS] = { 0 };
+
+ memset(&dev, 0, sizeof(DeviceIntRec));
+ dev.type = MASTER_POINTER; /* claim it's a master to stop ptracccel */
+
+ g_assert(InitValuatorClassDeviceStruct(NULL, 0, atoms, 0, 0) == FALSE);
+ g_assert(InitValuatorClassDeviceStruct(&dev, num_axes, atoms, 0, Absolute));
+
+ for (i = 0; i < num_axes; i++)
+ {
+ g_assert(valuator_get_mode(&dev, i) == Absolute);
+ valuator_set_mode(&dev, i, Relative);
+ g_assert(dev.valuator->axes[i].mode == Relative);
+ g_assert(valuator_get_mode(&dev, i) == Relative);
+ }
+
+ valuator_set_mode(&dev, VALUATOR_MODE_ALL_AXES, Absolute);
+ for (i = 0; i < num_axes; i++)
+ g_assert(valuator_get_mode(&dev, i) == Absolute);
+
+ valuator_set_mode(&dev, VALUATOR_MODE_ALL_AXES, Relative);
+ for (i = 0; i < num_axes; i++)
+ g_assert(valuator_get_mode(&dev, i) == Relative);
+}
+
+static void include_bit_test_macros(void)
+{
+ uint8_t mask[9] = { 0 };
+ int i;
+
+ for (i = 0; i < sizeof(mask)/sizeof(mask[0]); i++)
+ {
+ g_assert(BitIsOn(mask, i) == 0);
+ SetBit(mask, i);
+ g_assert(BitIsOn(mask, i) == 1);
+ g_assert(!!(mask[i/8] & (1 << (i % 8))));
+ g_assert(CountBits(mask, sizeof(mask)) == 1);
+ ClearBit(mask, i);
+ g_assert(BitIsOn(mask, i) == 0);
+ }
+}
+
+int main(int argc, char** argv)
+{
+ g_test_init(&argc, &argv,NULL);
+ g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
+
+ g_test_add_func("/dix/input/valuator-masks", dix_input_valuator_masks);
+ g_test_add_func("/dix/input/attributes", dix_input_attributes);
+ g_test_add_func("/dix/input/init-valuators", dix_init_valuators);
+ g_test_add_func("/dix/input/event-core-conversion", dix_event_to_core_conversion);
+ g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values);
+ g_test_add_func("/dix/input/xi2-struct-sizes", xi2_struct_sizes);
+ g_test_add_func("/dix/input/grab_matching", dix_grab_matching);
+ g_test_add_func("/dix/input/valuator_mode", dix_valuator_mode);
+ g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
+ g_test_add_func("/include/bit_test_macros", include_bit_test_macros);
+ g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
+
+
+ return g_test_run();
+}
diff --git a/xorg-server/test/xi2/protocol-eventconvert.c b/xorg-server/test/xi2/protocol-eventconvert.c
index 8184886c0..0478c33fe 100644
--- a/xorg-server/test/xi2/protocol-eventconvert.c
+++ b/xorg-server/test/xi2/protocol-eventconvert.c
@@ -1,907 +1,917 @@
-/**
- * Copyright © 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdint.h>
-#include <glib.h>
-
-#include "inputstr.h"
-#include "eventstr.h"
-#include "eventconvert.h"
-#include "exevents.h"
-#include <X11/extensions/XI2proto.h>
-
-
-static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
- BOOL swap)
-{
- int i;
- unsigned char *ptr;
- FP3232 *value, *raw_value;
- int nvals = 0;
- int bits_set;
- int len;
-
- if (swap)
- {
- char n;
-
- swaps(&out->sequenceNumber, n);
- swapl(&out->length, n);
- swaps(&out->evtype, n);
- swaps(&out->deviceid, n);
- swapl(&out->time, n);
- swapl(&out->detail, n);
- swaps(&out->valuators_len, n);
- }
-
-
- g_assert(out->type == GenericEvent);
- g_assert(out->extension == 0); /* IReqCode defaults to 0 */
- g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
- g_assert(out->time == in->time);
- g_assert(out->detail == in->detail.button);
- g_assert(out->deviceid == in->deviceid);
- g_assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(sizeof(in->valuators.mask))));
- g_assert(out->flags == 0); /* FIXME: we don't set the flags yet */
-
- ptr = (unsigned char*)&out[1];
- bits_set = 0;
-
- for (i = 0; out->valuators_len && i < sizeof(in->valuators.mask) * 8; i++)
- {
- g_assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
- if (XIMaskIsSet(in->valuators.mask, i))
- bits_set++;
- }
-
- /* length is len of valuator mask (in 4-byte units) + the number of bits
- * set. Each bit set represents 2 8-byte values, hence the
- * 'bits_set * 4' */
- len = out->valuators_len + bits_set * 4;
- g_assert(out->length == len);
-
- nvals = 0;
-
- for (i = 0; out->valuators_len && i < MAX_VALUATORS; i++)
- {
- g_assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
- if (XIMaskIsSet(in->valuators.mask, i))
- {
- FP3232 vi, vo;
- value = (FP3232*)(((unsigned char*)&out[1]) + out->valuators_len * 4);
- value += nvals;
-
- vi.integral = in->valuators.data[i];
- vi.frac = in->valuators.data_frac[i];
-
- vo.integral = value->integral;
- vo.frac = value->frac;
- if (swap)
- {
- char n;
- swapl(&vo.integral, n);
- swapl(&vo.frac, n);
- }
-
- g_assert(vi.integral == vo.integral);
- g_assert(vi.frac == vo.frac);
-
- raw_value = value + bits_set;
-
- vi.integral = in->valuators.data_raw[i];
- vi.frac = in->valuators.data_raw_frac[i];
-
- vo.integral = raw_value->integral;
- vo.frac = raw_value->frac;
- if (swap)
- {
- char n;
- swapl(&vo.integral, n);
- swapl(&vo.frac, n);
- }
-
- g_assert(vi.integral == vo.integral);
- g_assert(vi.frac == vo.frac);
-
- nvals++;
- }
- }
-}
-
-static void test_XIRawEvent(RawDeviceEvent *in)
-{
- xXIRawEvent *out, *swapped;
- int rc;
-
- rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
- g_assert(rc == Success);
-
- test_values_XIRawEvent(in, out, FALSE);
-
- swapped = calloc(1, sizeof(xEvent) + out->length * 4);
- XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)swapped);
- test_values_XIRawEvent(in, swapped, TRUE);
-
- free(out);
- free(swapped);
-}
-
-static void test_convert_XIFocusEvent(void)
-{
- xEvent *out;
- DeviceEvent in;
- int rc;
-
- in.header = ET_Internal;
- in.type = ET_Enter;
- rc = EventToXI2((InternalEvent*)&in, &out);
- g_assert(rc == Success);
- g_assert(out == NULL);
-
- in.header = ET_Internal;
- in.type = ET_FocusIn;
- rc = EventToXI2((InternalEvent*)&in, &out);
- g_assert(rc == Success);
- g_assert(out == NULL);
-
- in.header = ET_Internal;
- in.type = ET_FocusOut;
- rc = EventToXI2((InternalEvent*)&in, &out);
- g_assert(rc == BadImplementation);
-
- in.header = ET_Internal;
- in.type = ET_Leave;
- rc = EventToXI2((InternalEvent*)&in, &out);
- g_assert(rc == BadImplementation);
-}
-
-
-static void test_convert_XIRawEvent(void)
-{
- RawDeviceEvent in;
- int i;
-
- memset(&in, 0, sizeof(in));
-
- g_test_message("Testing all event types");
- in.header = ET_Internal;
- in.type = ET_RawMotion;
- test_XIRawEvent(&in);
-
- in.header = ET_Internal;
- in.type = ET_RawKeyPress;
- test_XIRawEvent(&in);
-
- in.header = ET_Internal;
- in.type = ET_RawKeyRelease;
- test_XIRawEvent(&in);
-
- in.header = ET_Internal;
- in.type = ET_RawButtonPress;
- test_XIRawEvent(&in);
-
- in.header = ET_Internal;
- in.type = ET_RawButtonRelease;
- test_XIRawEvent(&in);
-
- g_test_message("Testing details and other fields");
- in.detail.button = 1L;
- test_XIRawEvent(&in);
- in.detail.button = 1L << 8;
- test_XIRawEvent(&in);
- in.detail.button = 1L << 16;
- test_XIRawEvent(&in);
- in.detail.button = 1L << 24;
- test_XIRawEvent(&in);
- in.detail.button = ~0L;
- test_XIRawEvent(&in);
-
- in.detail.button = 0;
-
- in.time = 1L;
- test_XIRawEvent(&in);
- in.time = 1L << 8;
- test_XIRawEvent(&in);
- in.time = 1L << 16;
- test_XIRawEvent(&in);
- in.time = 1L << 24;
- test_XIRawEvent(&in);
- in.time = ~0L;
- test_XIRawEvent(&in);
-
- in.deviceid = 1;
- test_XIRawEvent(&in);
- in.deviceid = 1 << 8;
- test_XIRawEvent(&in);
- in.deviceid = ~0 & 0xFF;
- test_XIRawEvent(&in);
-
- g_test_message("Testing valuator masks");
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
- {
- XISetMask(in.valuators.mask, i);
- test_XIRawEvent(&in);
- XIClearMask(in.valuators.mask, i);
- }
-
- for (i = 0; i < MAX_VALUATORS; i++)
- {
- XISetMask(in.valuators.mask, i);
-
- in.valuators.data[i] = i;
- in.valuators.data_raw[i] = i + 10;
- in.valuators.data_frac[i] = i + 20;
- in.valuators.data_raw_frac[i] = i + 30;
- test_XIRawEvent(&in);
- XIClearMask(in.valuators.mask, i);
- }
-
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
- {
- XISetMask(in.valuators.mask, i);
- test_XIRawEvent(&in);
- }
-}
-
-static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
- BOOL swap)
-{
- int buttons, valuators;
- int i;
- unsigned char *ptr;
- FP3232 *values;
-
- if (swap) {
- char n;
-
- swaps(&out->sequenceNumber, n);
- swapl(&out->length, n);
- swaps(&out->evtype, n);
- swaps(&out->deviceid, n);
- swaps(&out->sourceid, n);
- swapl(&out->time, n);
- swapl(&out->detail, n);
- swapl(&out->root, n);
- swapl(&out->event, n);
- swapl(&out->child, n);
- swapl(&out->root_x, n);
- swapl(&out->root_y, n);
- swapl(&out->event_x, n);
- swapl(&out->event_y, n);
- swaps(&out->buttons_len, n);
- swaps(&out->valuators_len, n);
- swapl(&out->mods.base_mods, n);
- swapl(&out->mods.latched_mods, n);
- swapl(&out->mods.locked_mods, n);
- swapl(&out->mods.effective_mods, n);
- }
-
- g_assert(out->extension == 0); /* IReqCode defaults to 0 */
- g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
- g_assert(out->time == in->time);
- g_assert(out->detail == in->detail.button);
- g_assert(out->length >= 12);
-
- g_assert(out->deviceid == in->deviceid);
- g_assert(out->sourceid == in->sourceid);
-
- g_assert(out->flags == 0); /* FIXME: we don't set the flags yet */
-
- g_assert(out->root == in->root);
- g_assert(out->event == None); /* set in FixUpEventFromWindow */
- g_assert(out->child == None); /* set in FixUpEventFromWindow */
-
- g_assert(out->mods.base_mods == in->mods.base);
- g_assert(out->mods.latched_mods == in->mods.latched);
- g_assert(out->mods.locked_mods == in->mods.locked);
- g_assert(out->mods.effective_mods == in->mods.effective);
-
- g_assert(out->group.base_group == in->group.base);
- g_assert(out->group.latched_group == in->group.latched);
- g_assert(out->group.locked_group == in->group.locked);
- g_assert(out->group.effective_group == in->group.effective);
-
- g_assert(out->event_x == 0); /* set in FixUpEventFromWindow */
- g_assert(out->event_y == 0); /* set in FixUpEventFromWindow */
-
- g_assert(out->root_x == FP1616(in->root_x, in->root_x_frac));
- g_assert(out->root_y == FP1616(in->root_y, in->root_y_frac));
-
- buttons = 0;
- for (i = 0; i < bits_to_bytes(sizeof(in->buttons)); i++)
- {
- if (XIMaskIsSet(in->buttons, i))
- {
- g_assert(out->buttons_len >= bytes_to_int32(bits_to_bytes(i)));
- buttons++;
- }
- }
-
- ptr = (unsigned char*)&out[1];
- for (i = 0; i < sizeof(in->buttons) * 8; i++)
- g_assert(XIMaskIsSet(in->buttons, i) == XIMaskIsSet(ptr, i));
-
-
- valuators = 0;
- for (i = 0; i < sizeof(in->valuators.mask) * 8; i++)
- if (XIMaskIsSet(in->valuators.mask, i))
- valuators++;
-
- g_assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(valuators)));
-
- ptr += out->buttons_len * 4;
- values = (FP3232*)(ptr + out->valuators_len * 4);
- for (i = 0; i < sizeof(in->valuators.mask) * 8 ||
- i < (out->valuators_len * 4) * 8; i++)
- {
- if (i > sizeof(in->valuators.mask) * 8)
- g_assert(!XIMaskIsSet(ptr, i));
- else if (i > out->valuators_len * 4 * 8)
- g_assert(!XIMaskIsSet(in->valuators.mask, i));
- else {
- g_assert(XIMaskIsSet(in->valuators.mask, i) ==
- XIMaskIsSet(ptr, i));
-
- if (XIMaskIsSet(ptr, i))
- {
- FP3232 vi, vo;
-
- vi.integral = in->valuators.data[i];
- vi.frac = in->valuators.data_frac[i];
-
- vo = *values;
-
- if (swap)
- {
- char n;
- swapl(&vo.integral, n);
- swapl(&vo.frac, n);
- }
-
-
- g_assert(vi.integral == vo.integral);
- g_assert(vi.frac == vo.frac);
- values++;
- }
- }
- }
-}
-
-static void test_XIDeviceEvent(DeviceEvent *in)
-{
- xXIDeviceEvent *out, *swapped;
- int rc;
-
- rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
- g_assert(rc == Success);
-
- test_values_XIDeviceEvent(in, out, FALSE);
-
- swapped = calloc(1, sizeof(xEvent) + out->length * 4);
- XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)swapped);
- test_values_XIDeviceEvent(in, swapped, TRUE);
-
- free(out);
- free(swapped);
-}
-
-static void test_convert_XIDeviceEvent(void)
-{
- DeviceEvent in;
- int i;
-
- memset(&in, 0, sizeof(in));
-
- g_test_message("Testing simple field values");
- in.header = ET_Internal;
- in.type = ET_Motion;
- in.length = sizeof(DeviceEvent);
- in.time = 0;
- in.deviceid = 1;
- in.sourceid = 2;
- in.root = 3;
- in.root_x = 4;
- in.root_x_frac = 5;
- in.root_y = 6;
- in.root_y_frac = 7;
- in.detail.button = 8;
- in.mods.base = 9;
- in.mods.latched = 10;
- in.mods.locked = 11;
- in.mods.effective = 11;
- in.group.base = 12;
- in.group.latched = 13;
- in.group.locked = 14;
- in.group.effective = 15;
-
- test_XIDeviceEvent(&in);
-
- g_test_message("Testing field ranges");
- /* 32 bit */
- in.detail.button = 1L;
- test_XIDeviceEvent(&in);
- in.detail.button = 1L << 8;
- test_XIDeviceEvent(&in);
- in.detail.button = 1L << 16;
- test_XIDeviceEvent(&in);
- in.detail.button = 1L << 24;
- test_XIDeviceEvent(&in);
- in.detail.button = ~0L;
- test_XIDeviceEvent(&in);
-
- /* 32 bit */
- in.time = 1L;
- test_XIDeviceEvent(&in);
- in.time = 1L << 8;
- test_XIDeviceEvent(&in);
- in.time = 1L << 16;
- test_XIDeviceEvent(&in);
- in.time = 1L << 24;
- test_XIDeviceEvent(&in);
- in.time = ~0L;
- test_XIDeviceEvent(&in);
-
- /* 16 bit */
- in.deviceid = 1;
- test_XIDeviceEvent(&in);
- in.deviceid = 1 << 8;
- test_XIDeviceEvent(&in);
- in.deviceid = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- /* 16 bit */
- in.sourceid = 1;
- test_XIDeviceEvent(&in);
- in.deviceid = 1 << 8;
- test_XIDeviceEvent(&in);
- in.deviceid = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- /* 32 bit */
- in.root = 1L;
- test_XIDeviceEvent(&in);
- in.root = 1L << 8;
- test_XIDeviceEvent(&in);
- in.root = 1L << 16;
- test_XIDeviceEvent(&in);
- in.root = 1L << 24;
- test_XIDeviceEvent(&in);
- in.root = ~0L;
- test_XIDeviceEvent(&in);
-
- /* 16 bit */
- in.root_x = 1;
- test_XIDeviceEvent(&in);
- in.root_x = 1 << 8;
- test_XIDeviceEvent(&in);
- in.root_x = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- in.root_x_frac = 1;
- test_XIDeviceEvent(&in);
- in.root_x_frac = 1 << 8;
- test_XIDeviceEvent(&in);
- in.root_x_frac = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- in.root_y = 1;
- test_XIDeviceEvent(&in);
- in.root_y = 1 << 8;
- test_XIDeviceEvent(&in);
- in.root_y = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- in.root_y_frac = 1;
- test_XIDeviceEvent(&in);
- in.root_y_frac = 1 << 8;
- test_XIDeviceEvent(&in);
- in.root_y_frac = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- /* 32 bit */
- in.mods.base = 1L;
- test_XIDeviceEvent(&in);
- in.mods.base = 1L << 8;
- test_XIDeviceEvent(&in);
- in.mods.base = 1L << 16;
- test_XIDeviceEvent(&in);
- in.mods.base = 1L << 24;
- test_XIDeviceEvent(&in);
- in.mods.base = ~0L;
- test_XIDeviceEvent(&in);
-
- in.mods.latched = 1L;
- test_XIDeviceEvent(&in);
- in.mods.latched = 1L << 8;
- test_XIDeviceEvent(&in);
- in.mods.latched = 1L << 16;
- test_XIDeviceEvent(&in);
- in.mods.latched = 1L << 24;
- test_XIDeviceEvent(&in);
- in.mods.latched = ~0L;
- test_XIDeviceEvent(&in);
-
- in.mods.locked = 1L;
- test_XIDeviceEvent(&in);
- in.mods.locked = 1L << 8;
- test_XIDeviceEvent(&in);
- in.mods.locked = 1L << 16;
- test_XIDeviceEvent(&in);
- in.mods.locked = 1L << 24;
- test_XIDeviceEvent(&in);
- in.mods.locked = ~0L;
- test_XIDeviceEvent(&in);
-
- in.mods.effective = 1L;
- test_XIDeviceEvent(&in);
- in.mods.effective = 1L << 8;
- test_XIDeviceEvent(&in);
- in.mods.effective = 1L << 16;
- test_XIDeviceEvent(&in);
- in.mods.effective = 1L << 24;
- test_XIDeviceEvent(&in);
- in.mods.effective = ~0L;
- test_XIDeviceEvent(&in);
-
- /* 8 bit */
- in.group.base = 1;
- test_XIDeviceEvent(&in);
- in.group.base = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- in.group.latched = 1;
- test_XIDeviceEvent(&in);
- in.group.latched = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- in.group.locked = 1;
- test_XIDeviceEvent(&in);
- in.group.locked = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- in.mods.effective = 1;
- test_XIDeviceEvent(&in);
- in.mods.effective = ~0 & 0xFF;
- test_XIDeviceEvent(&in);
-
- g_test_message("Testing button masks");
- for (i = 0; i < sizeof(in.buttons) * 8; i++)
- {
- XISetMask(in.buttons, i);
- test_XIDeviceEvent(&in);
- XIClearMask(in.buttons, i);
- }
-
- for (i = 0; i < sizeof(in.buttons) * 8; i++)
- {
- XISetMask(in.buttons, i);
- test_XIDeviceEvent(&in);
- }
-
- g_test_message("Testing valuator masks");
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
- {
- XISetMask(in.valuators.mask, i);
- test_XIDeviceEvent(&in);
- XIClearMask(in.valuators.mask, i);
- }
-
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
- {
- XISetMask(in.valuators.mask, i);
-
- in.valuators.data[i] = i;
- in.valuators.data_frac[i] = i + 20;
- test_XIDeviceEvent(&in);
- XIClearMask(in.valuators.mask, i);
- }
-
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
- {
- XISetMask(in.valuators.mask, i);
- test_XIDeviceEvent(&in);
- }
-}
-
-static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
- xXIDeviceChangedEvent *out,
- BOOL swap)
-{
- int i, j;
- unsigned char *ptr;
-
- if (swap)
- {
- char n;
-
- swaps(&out->sequenceNumber, n);
- swapl(&out->length, n);
- swaps(&out->evtype, n);
- swaps(&out->deviceid, n);
- swaps(&out->sourceid, n);
- swapl(&out->time, n);
- swaps(&out->num_classes, n);
- }
-
- g_assert(out->type == GenericEvent);
- g_assert(out->extension == 0); /* IReqCode defaults to 0 */
- g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
- g_assert(out->time == in->time);
- g_assert(out->deviceid == in->deviceid);
- g_assert(out->sourceid == in->sourceid);
-
- ptr = (unsigned char*)&out[1];
- for (i = 0; i < out->num_classes; i++)
- {
- xXIAnyInfo* any = (xXIAnyInfo*)ptr;
-
- if (swap)
- {
- char n;
- swaps(&any->length, n);
- swaps(&any->type, n);
- swaps(&any->sourceid, n);
- }
-
- switch(any->type)
- {
- case XIButtonClass:
- {
- xXIButtonInfo *b = (xXIButtonInfo*)any;
- Atom *names;
-
- if (swap)
- {
- char n;
- swaps(&b->num_buttons, n);
- }
-
- g_assert(b->length ==
- bytes_to_int32(sizeof(xXIButtonInfo)) +
- bytes_to_int32(bits_to_bytes(b->num_buttons)) +
- b->num_buttons);
- g_assert(b->num_buttons == in->buttons.num_buttons);
-
- names = (Atom*)((char*)&b[1] +
- pad_to_int32(bits_to_bytes(b->num_buttons)));
- for (j = 0; j < b->num_buttons; j++)
- {
- if (swap)
- {
- char n;
- swapl(&names[j], n);
- }
- g_assert(names[j] == in->buttons.names[j]);
- }
- }
- break;
- case XIKeyClass:
- {
- xXIKeyInfo *k = (xXIKeyInfo*)any;
- uint32_t *kc;
-
- if (swap)
- {
- char n;
- swaps(&k->num_keycodes, n);
- }
-
- g_assert(k->length ==
- bytes_to_int32(sizeof(xXIKeyInfo)) +
- k->num_keycodes);
- g_assert(k->num_keycodes == in->keys.max_keycode -
- in->keys.min_keycode + 1);
-
- kc = (uint32_t*)&k[1];
- for (j = 0; j < k->num_keycodes; j++)
- {
- if (swap)
- {
- char n;
- swapl(&kc[j], n);
- }
- g_assert(kc[j] >= in->keys.min_keycode);
- g_assert(kc[j] <= in->keys.max_keycode);
- }
- }
- break;
- case XIValuatorClass:
- {
- xXIValuatorInfo *v = (xXIValuatorInfo*)any;
- g_assert(v->length ==
- bytes_to_int32(sizeof(xXIValuatorInfo)));
-
- }
- break;
- default:
- g_error("Invalid class type.\n");
- break;
- }
-
- ptr += any->length * 4;
- }
-
-}
-
-static void test_XIDeviceChangedEvent(DeviceChangedEvent *in)
-{
- xXIDeviceChangedEvent *out, *swapped;
- int rc;
-
- rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
- g_assert(rc == Success);
-
- test_values_XIDeviceChangedEvent(in, out, FALSE);
-
- swapped = calloc(1, sizeof(xEvent) + out->length * 4);
- XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)swapped);
- test_values_XIDeviceChangedEvent(in, swapped, TRUE);
-
- free(out);
- free(swapped);
-}
-
-static void test_convert_XIDeviceChangedEvent(void)
-{
- DeviceChangedEvent in;
- int i;
-
- g_test_message("Testing simple field values");
- memset(&in, 0, sizeof(in));
- in.header = ET_Internal;
- in.type = ET_DeviceChanged;
- in.length = sizeof(DeviceChangedEvent);
- in.time = 0;
- in.deviceid = 1;
- in.sourceid = 2;
- in.masterid = 3;
- in.num_valuators = 4;
- in.flags = DEVCHANGE_SLAVE_SWITCH | DEVCHANGE_POINTER_EVENT | DEVCHANGE_KEYBOARD_EVENT;
-
- for (i = 0; i < MAX_BUTTONS; i++)
- in.buttons.names[i] = i + 10;
-
- in.keys.min_keycode = 8;
- in.keys.max_keycode = 255;
-
- test_XIDeviceChangedEvent(&in);
-
- in.time = 1L;
- test_XIDeviceChangedEvent(&in);
- in.time = 1L << 8;
- test_XIDeviceChangedEvent(&in);
- in.time = 1L << 16;
- test_XIDeviceChangedEvent(&in);
- in.time = 1L << 24;
- test_XIDeviceChangedEvent(&in);
- in.time = ~0L;
- test_XIDeviceChangedEvent(&in);
-
- in.deviceid = 1L;
- test_XIDeviceChangedEvent(&in);
- in.deviceid = 1L << 8;
- test_XIDeviceChangedEvent(&in);
- in.deviceid = ~0 & 0xFFFF;
- test_XIDeviceChangedEvent(&in);
-
- in.sourceid = 1L;
- test_XIDeviceChangedEvent(&in);
- in.sourceid = 1L << 8;
- test_XIDeviceChangedEvent(&in);
- in.sourceid = ~0 & 0xFFFF;
- test_XIDeviceChangedEvent(&in);
-
- in.masterid = 1L;
- test_XIDeviceChangedEvent(&in);
- in.masterid = 1L << 8;
- test_XIDeviceChangedEvent(&in);
- in.masterid = ~0 & 0xFFFF;
- test_XIDeviceChangedEvent(&in);
-
- in.buttons.num_buttons = 0;
- test_XIDeviceChangedEvent(&in);
-
- in.buttons.num_buttons = 1;
- test_XIDeviceChangedEvent(&in);
-
- in.buttons.num_buttons = MAX_BUTTONS;
- test_XIDeviceChangedEvent(&in);
-
- in.keys.min_keycode = 0;
- in.keys.max_keycode = 0;
- test_XIDeviceChangedEvent(&in);
-
- in.keys.max_keycode = 1 << 8;
- test_XIDeviceChangedEvent(&in);
-
- in.keys.max_keycode = 0xFFFC; /* highest range, above that the length
- field gives up */
- test_XIDeviceChangedEvent(&in);
-
- in.keys.min_keycode = 1 << 8;
- in.keys.max_keycode = 1 << 8;
- test_XIDeviceChangedEvent(&in);
-
- in.keys.min_keycode = 1 << 8;
- in.keys.max_keycode = 0;
- test_XIDeviceChangedEvent(&in);
-
- in.num_valuators = 0;
- test_XIDeviceChangedEvent(&in);
-
- in.num_valuators = 1;
- test_XIDeviceChangedEvent(&in);
-
- in.num_valuators = MAX_VALUATORS;
- test_XIDeviceChangedEvent(&in);
-
- for (i = 0; i < MAX_VALUATORS; i++)
- {
- in.valuators[i].min = 0;
- in.valuators[i].max = 0;
- test_XIDeviceChangedEvent(&in);
-
- in.valuators[i].max = 1 << 8;
- test_XIDeviceChangedEvent(&in);
- in.valuators[i].max = 1 << 16;
- test_XIDeviceChangedEvent(&in);
- in.valuators[i].max = 1 << 24;
- test_XIDeviceChangedEvent(&in);
- in.valuators[i].max = abs(~0);
- test_XIDeviceChangedEvent(&in);
-
- in.valuators[i].resolution = 1 << 8;
- test_XIDeviceChangedEvent(&in);
- in.valuators[i].resolution = 1 << 16;
- test_XIDeviceChangedEvent(&in);
- in.valuators[i].resolution = 1 << 24;
- test_XIDeviceChangedEvent(&in);
- in.valuators[i].resolution = abs(~0);
- test_XIDeviceChangedEvent(&in);
-
- in.valuators[i].name = i;
- test_XIDeviceChangedEvent(&in);
-
- in.valuators[i].mode = Relative;
- test_XIDeviceChangedEvent(&in);
-
- in.valuators[i].mode = Absolute;
- test_XIDeviceChangedEvent(&in);
- }
-}
-
-int main(int argc, char** argv)
-{
- g_test_init(&argc, &argv,NULL);
- g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
-
- g_test_add_func("/xi2/eventconvert/XIRawEvent", test_convert_XIRawEvent);
- g_test_add_func("/xi2/eventconvert/XIFocusEvent", test_convert_XIFocusEvent);
- g_test_add_func("/xi2/eventconvert/XIDeviceEvent", test_convert_XIDeviceEvent);
- g_test_add_func("/xi2/eventconvert/XIDeviceChangedEvent", test_convert_XIDeviceChangedEvent);
-
- return g_test_run();
-}
+/**
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdint.h>
+#include <glib.h>
+
+#include "inputstr.h"
+#include "eventstr.h"
+#include "eventconvert.h"
+#include "exevents.h"
+#include <X11/extensions/XI2proto.h>
+
+
+static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
+ BOOL swap)
+{
+ int i;
+ unsigned char *ptr;
+ FP3232 *value, *raw_value;
+ int nvals = 0;
+ int bits_set;
+ int len;
+
+ if (swap)
+ {
+ char n;
+
+ swaps(&out->sequenceNumber, n);
+ swapl(&out->length, n);
+ swaps(&out->evtype, n);
+ swaps(&out->deviceid, n);
+ swapl(&out->time, n);
+ swapl(&out->detail, n);
+ swaps(&out->valuators_len, n);
+ }
+
+
+ g_assert(out->type == GenericEvent);
+ g_assert(out->extension == 0); /* IReqCode defaults to 0 */
+ g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
+ g_assert(out->time == in->time);
+ g_assert(out->detail == in->detail.button);
+ g_assert(out->deviceid == in->deviceid);
+ g_assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(sizeof(in->valuators.mask))));
+ g_assert(out->flags == 0); /* FIXME: we don't set the flags yet */
+
+ ptr = (unsigned char*)&out[1];
+ bits_set = 0;
+
+ for (i = 0; out->valuators_len && i < sizeof(in->valuators.mask) * 8; i++)
+ {
+ g_assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
+ if (XIMaskIsSet(in->valuators.mask, i))
+ bits_set++;
+ }
+
+ /* length is len of valuator mask (in 4-byte units) + the number of bits
+ * set. Each bit set represents 2 8-byte values, hence the
+ * 'bits_set * 4' */
+ len = out->valuators_len + bits_set * 4;
+ g_assert(out->length == len);
+
+ nvals = 0;
+
+ for (i = 0; out->valuators_len && i < MAX_VALUATORS; i++)
+ {
+ g_assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
+ if (XIMaskIsSet(in->valuators.mask, i))
+ {
+ FP3232 vi, vo;
+ value = (FP3232*)(((unsigned char*)&out[1]) + out->valuators_len * 4);
+ value += nvals;
+
+ vi.integral = in->valuators.data[i];
+ vi.frac = in->valuators.data_frac[i];
+
+ vo.integral = value->integral;
+ vo.frac = value->frac;
+ if (swap)
+ {
+ char n;
+ swapl(&vo.integral, n);
+ swapl(&vo.frac, n);
+ }
+
+ g_assert(vi.integral == vo.integral);
+ g_assert(vi.frac == vo.frac);
+
+ raw_value = value + bits_set;
+
+ vi.integral = in->valuators.data_raw[i];
+ vi.frac = in->valuators.data_raw_frac[i];
+
+ vo.integral = raw_value->integral;
+ vo.frac = raw_value->frac;
+ if (swap)
+ {
+ char n;
+ swapl(&vo.integral, n);
+ swapl(&vo.frac, n);
+ }
+
+ g_assert(vi.integral == vo.integral);
+ g_assert(vi.frac == vo.frac);
+
+ nvals++;
+ }
+ }
+}
+
+static void test_XIRawEvent(RawDeviceEvent *in)
+{
+ xXIRawEvent *out, *swapped;
+ int rc;
+
+ rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
+ g_assert(rc == Success);
+
+ test_values_XIRawEvent(in, out, FALSE);
+
+ swapped = calloc(1, sizeof(xEvent) + out->length * 4);
+ XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)swapped);
+ test_values_XIRawEvent(in, swapped, TRUE);
+
+ free(out);
+ free(swapped);
+}
+
+static void test_convert_XIFocusEvent(void)
+{
+ xEvent *out;
+ DeviceEvent in;
+ int rc;
+
+ in.header = ET_Internal;
+ in.type = ET_Enter;
+ rc = EventToXI2((InternalEvent*)&in, &out);
+ g_assert(rc == Success);
+ g_assert(out == NULL);
+
+ in.header = ET_Internal;
+ in.type = ET_FocusIn;
+ rc = EventToXI2((InternalEvent*)&in, &out);
+ g_assert(rc == Success);
+ g_assert(out == NULL);
+
+ in.header = ET_Internal;
+ in.type = ET_FocusOut;
+ rc = EventToXI2((InternalEvent*)&in, &out);
+ g_assert(rc == BadImplementation);
+
+ in.header = ET_Internal;
+ in.type = ET_Leave;
+ rc = EventToXI2((InternalEvent*)&in, &out);
+ g_assert(rc == BadImplementation);
+}
+
+
+static void test_convert_XIRawEvent(void)
+{
+ RawDeviceEvent in;
+ int i;
+
+ memset(&in, 0, sizeof(in));
+
+ g_test_message("Testing all event types");
+ in.header = ET_Internal;
+ in.type = ET_RawMotion;
+ test_XIRawEvent(&in);
+
+ in.header = ET_Internal;
+ in.type = ET_RawKeyPress;
+ test_XIRawEvent(&in);
+
+ in.header = ET_Internal;
+ in.type = ET_RawKeyRelease;
+ test_XIRawEvent(&in);
+
+ in.header = ET_Internal;
+ in.type = ET_RawButtonPress;
+ test_XIRawEvent(&in);
+
+ in.header = ET_Internal;
+ in.type = ET_RawButtonRelease;
+ test_XIRawEvent(&in);
+
+ g_test_message("Testing details and other fields");
+ in.detail.button = 1L;
+ test_XIRawEvent(&in);
+ in.detail.button = 1L << 8;
+ test_XIRawEvent(&in);
+ in.detail.button = 1L << 16;
+ test_XIRawEvent(&in);
+ in.detail.button = 1L << 24;
+ test_XIRawEvent(&in);
+ in.detail.button = ~0L;
+ test_XIRawEvent(&in);
+
+ in.detail.button = 0;
+
+ in.time = 1L;
+ test_XIRawEvent(&in);
+ in.time = 1L << 8;
+ test_XIRawEvent(&in);
+ in.time = 1L << 16;
+ test_XIRawEvent(&in);
+ in.time = 1L << 24;
+ test_XIRawEvent(&in);
+ in.time = ~0L;
+ test_XIRawEvent(&in);
+
+ in.deviceid = 1;
+ test_XIRawEvent(&in);
+ in.deviceid = 1 << 8;
+ test_XIRawEvent(&in);
+ in.deviceid = ~0 & 0xFF;
+ test_XIRawEvent(&in);
+
+ g_test_message("Testing valuator masks");
+ for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ {
+ XISetMask(in.valuators.mask, i);
+ test_XIRawEvent(&in);
+ XIClearMask(in.valuators.mask, i);
+ }
+
+ for (i = 0; i < MAX_VALUATORS; i++)
+ {
+ XISetMask(in.valuators.mask, i);
+
+ in.valuators.data[i] = i;
+ in.valuators.data_raw[i] = i + 10;
+ in.valuators.data_frac[i] = i + 20;
+ in.valuators.data_raw_frac[i] = i + 30;
+ test_XIRawEvent(&in);
+ XIClearMask(in.valuators.mask, i);
+ }
+
+ for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ {
+ XISetMask(in.valuators.mask, i);
+ test_XIRawEvent(&in);
+ }
+}
+
+static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
+ BOOL swap)
+{
+ int buttons, valuators;
+ int i;
+ unsigned char *ptr;
+ uint32_t flagmask = 0;
+ FP3232 *values;
+
+ if (swap) {
+ char n;
+
+ swaps(&out->sequenceNumber, n);
+ swapl(&out->length, n);
+ swaps(&out->evtype, n);
+ swaps(&out->deviceid, n);
+ swaps(&out->sourceid, n);
+ swapl(&out->time, n);
+ swapl(&out->detail, n);
+ swapl(&out->root, n);
+ swapl(&out->event, n);
+ swapl(&out->child, n);
+ swapl(&out->root_x, n);
+ swapl(&out->root_y, n);
+ swapl(&out->event_x, n);
+ swapl(&out->event_y, n);
+ swaps(&out->buttons_len, n);
+ swaps(&out->valuators_len, n);
+ swapl(&out->mods.base_mods, n);
+ swapl(&out->mods.latched_mods, n);
+ swapl(&out->mods.locked_mods, n);
+ swapl(&out->mods.effective_mods, n);
+ swapl(&out->flags, n);
+ }
+
+ g_assert(out->extension == 0); /* IReqCode defaults to 0 */
+ g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
+ g_assert(out->time == in->time);
+ g_assert(out->detail == in->detail.button);
+ g_assert(out->length >= 12);
+
+ g_assert(out->deviceid == in->deviceid);
+ g_assert(out->sourceid == in->sourceid);
+
+ switch (in->type) {
+ case ET_KeyPress:
+ flagmask = XIKeyRepeat;
+ break;
+ default:
+ flagmask = 0;
+ break;
+ }
+ g_assert((out->flags & ~flagmask) == 0);
+
+ g_assert(out->root == in->root);
+ g_assert(out->event == None); /* set in FixUpEventFromWindow */
+ g_assert(out->child == None); /* set in FixUpEventFromWindow */
+
+ g_assert(out->mods.base_mods == in->mods.base);
+ g_assert(out->mods.latched_mods == in->mods.latched);
+ g_assert(out->mods.locked_mods == in->mods.locked);
+ g_assert(out->mods.effective_mods == in->mods.effective);
+
+ g_assert(out->group.base_group == in->group.base);
+ g_assert(out->group.latched_group == in->group.latched);
+ g_assert(out->group.locked_group == in->group.locked);
+ g_assert(out->group.effective_group == in->group.effective);
+
+ g_assert(out->event_x == 0); /* set in FixUpEventFromWindow */
+ g_assert(out->event_y == 0); /* set in FixUpEventFromWindow */
+
+ g_assert(out->root_x == FP1616(in->root_x, in->root_x_frac));
+ g_assert(out->root_y == FP1616(in->root_y, in->root_y_frac));
+
+ buttons = 0;
+ for (i = 0; i < bits_to_bytes(sizeof(in->buttons)); i++)
+ {
+ if (XIMaskIsSet(in->buttons, i))
+ {
+ g_assert(out->buttons_len >= bytes_to_int32(bits_to_bytes(i)));
+ buttons++;
+ }
+ }
+
+ ptr = (unsigned char*)&out[1];
+ for (i = 0; i < sizeof(in->buttons) * 8; i++)
+ g_assert(XIMaskIsSet(in->buttons, i) == XIMaskIsSet(ptr, i));
+
+
+ valuators = 0;
+ for (i = 0; i < sizeof(in->valuators.mask) * 8; i++)
+ if (XIMaskIsSet(in->valuators.mask, i))
+ valuators++;
+
+ g_assert(out->valuators_len >= bytes_to_int32(bits_to_bytes(valuators)));
+
+ ptr += out->buttons_len * 4;
+ values = (FP3232*)(ptr + out->valuators_len * 4);
+ for (i = 0; i < sizeof(in->valuators.mask) * 8 ||
+ i < (out->valuators_len * 4) * 8; i++)
+ {
+ if (i > sizeof(in->valuators.mask) * 8)
+ g_assert(!XIMaskIsSet(ptr, i));
+ else if (i > out->valuators_len * 4 * 8)
+ g_assert(!XIMaskIsSet(in->valuators.mask, i));
+ else {
+ g_assert(XIMaskIsSet(in->valuators.mask, i) ==
+ XIMaskIsSet(ptr, i));
+
+ if (XIMaskIsSet(ptr, i))
+ {
+ FP3232 vi, vo;
+
+ vi.integral = in->valuators.data[i];
+ vi.frac = in->valuators.data_frac[i];
+
+ vo = *values;
+
+ if (swap)
+ {
+ char n;
+ swapl(&vo.integral, n);
+ swapl(&vo.frac, n);
+ }
+
+
+ g_assert(vi.integral == vo.integral);
+ g_assert(vi.frac == vo.frac);
+ values++;
+ }
+ }
+ }
+}
+
+static void test_XIDeviceEvent(DeviceEvent *in)
+{
+ xXIDeviceEvent *out, *swapped;
+ int rc;
+
+ rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
+ g_assert(rc == Success);
+
+ test_values_XIDeviceEvent(in, out, FALSE);
+
+ swapped = calloc(1, sizeof(xEvent) + out->length * 4);
+ XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)swapped);
+ test_values_XIDeviceEvent(in, swapped, TRUE);
+
+ free(out);
+ free(swapped);
+}
+
+static void test_convert_XIDeviceEvent(void)
+{
+ DeviceEvent in;
+ int i;
+
+ memset(&in, 0, sizeof(in));
+
+ g_test_message("Testing simple field values");
+ in.header = ET_Internal;
+ in.type = ET_Motion;
+ in.length = sizeof(DeviceEvent);
+ in.time = 0;
+ in.deviceid = 1;
+ in.sourceid = 2;
+ in.root = 3;
+ in.root_x = 4;
+ in.root_x_frac = 5;
+ in.root_y = 6;
+ in.root_y_frac = 7;
+ in.detail.button = 8;
+ in.mods.base = 9;
+ in.mods.latched = 10;
+ in.mods.locked = 11;
+ in.mods.effective = 11;
+ in.group.base = 12;
+ in.group.latched = 13;
+ in.group.locked = 14;
+ in.group.effective = 15;
+
+ test_XIDeviceEvent(&in);
+
+ g_test_message("Testing field ranges");
+ /* 32 bit */
+ in.detail.button = 1L;
+ test_XIDeviceEvent(&in);
+ in.detail.button = 1L << 8;
+ test_XIDeviceEvent(&in);
+ in.detail.button = 1L << 16;
+ test_XIDeviceEvent(&in);
+ in.detail.button = 1L << 24;
+ test_XIDeviceEvent(&in);
+ in.detail.button = ~0L;
+ test_XIDeviceEvent(&in);
+
+ /* 32 bit */
+ in.time = 1L;
+ test_XIDeviceEvent(&in);
+ in.time = 1L << 8;
+ test_XIDeviceEvent(&in);
+ in.time = 1L << 16;
+ test_XIDeviceEvent(&in);
+ in.time = 1L << 24;
+ test_XIDeviceEvent(&in);
+ in.time = ~0L;
+ test_XIDeviceEvent(&in);
+
+ /* 16 bit */
+ in.deviceid = 1;
+ test_XIDeviceEvent(&in);
+ in.deviceid = 1 << 8;
+ test_XIDeviceEvent(&in);
+ in.deviceid = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ /* 16 bit */
+ in.sourceid = 1;
+ test_XIDeviceEvent(&in);
+ in.deviceid = 1 << 8;
+ test_XIDeviceEvent(&in);
+ in.deviceid = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ /* 32 bit */
+ in.root = 1L;
+ test_XIDeviceEvent(&in);
+ in.root = 1L << 8;
+ test_XIDeviceEvent(&in);
+ in.root = 1L << 16;
+ test_XIDeviceEvent(&in);
+ in.root = 1L << 24;
+ test_XIDeviceEvent(&in);
+ in.root = ~0L;
+ test_XIDeviceEvent(&in);
+
+ /* 16 bit */
+ in.root_x = 1;
+ test_XIDeviceEvent(&in);
+ in.root_x = 1 << 8;
+ test_XIDeviceEvent(&in);
+ in.root_x = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ in.root_x_frac = 1;
+ test_XIDeviceEvent(&in);
+ in.root_x_frac = 1 << 8;
+ test_XIDeviceEvent(&in);
+ in.root_x_frac = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ in.root_y = 1;
+ test_XIDeviceEvent(&in);
+ in.root_y = 1 << 8;
+ test_XIDeviceEvent(&in);
+ in.root_y = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ in.root_y_frac = 1;
+ test_XIDeviceEvent(&in);
+ in.root_y_frac = 1 << 8;
+ test_XIDeviceEvent(&in);
+ in.root_y_frac = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ /* 32 bit */
+ in.mods.base = 1L;
+ test_XIDeviceEvent(&in);
+ in.mods.base = 1L << 8;
+ test_XIDeviceEvent(&in);
+ in.mods.base = 1L << 16;
+ test_XIDeviceEvent(&in);
+ in.mods.base = 1L << 24;
+ test_XIDeviceEvent(&in);
+ in.mods.base = ~0L;
+ test_XIDeviceEvent(&in);
+
+ in.mods.latched = 1L;
+ test_XIDeviceEvent(&in);
+ in.mods.latched = 1L << 8;
+ test_XIDeviceEvent(&in);
+ in.mods.latched = 1L << 16;
+ test_XIDeviceEvent(&in);
+ in.mods.latched = 1L << 24;
+ test_XIDeviceEvent(&in);
+ in.mods.latched = ~0L;
+ test_XIDeviceEvent(&in);
+
+ in.mods.locked = 1L;
+ test_XIDeviceEvent(&in);
+ in.mods.locked = 1L << 8;
+ test_XIDeviceEvent(&in);
+ in.mods.locked = 1L << 16;
+ test_XIDeviceEvent(&in);
+ in.mods.locked = 1L << 24;
+ test_XIDeviceEvent(&in);
+ in.mods.locked = ~0L;
+ test_XIDeviceEvent(&in);
+
+ in.mods.effective = 1L;
+ test_XIDeviceEvent(&in);
+ in.mods.effective = 1L << 8;
+ test_XIDeviceEvent(&in);
+ in.mods.effective = 1L << 16;
+ test_XIDeviceEvent(&in);
+ in.mods.effective = 1L << 24;
+ test_XIDeviceEvent(&in);
+ in.mods.effective = ~0L;
+ test_XIDeviceEvent(&in);
+
+ /* 8 bit */
+ in.group.base = 1;
+ test_XIDeviceEvent(&in);
+ in.group.base = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ in.group.latched = 1;
+ test_XIDeviceEvent(&in);
+ in.group.latched = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ in.group.locked = 1;
+ test_XIDeviceEvent(&in);
+ in.group.locked = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ in.mods.effective = 1;
+ test_XIDeviceEvent(&in);
+ in.mods.effective = ~0 & 0xFF;
+ test_XIDeviceEvent(&in);
+
+ g_test_message("Testing button masks");
+ for (i = 0; i < sizeof(in.buttons) * 8; i++)
+ {
+ XISetMask(in.buttons, i);
+ test_XIDeviceEvent(&in);
+ XIClearMask(in.buttons, i);
+ }
+
+ for (i = 0; i < sizeof(in.buttons) * 8; i++)
+ {
+ XISetMask(in.buttons, i);
+ test_XIDeviceEvent(&in);
+ }
+
+ g_test_message("Testing valuator masks");
+ for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ {
+ XISetMask(in.valuators.mask, i);
+ test_XIDeviceEvent(&in);
+ XIClearMask(in.valuators.mask, i);
+ }
+
+ for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ {
+ XISetMask(in.valuators.mask, i);
+
+ in.valuators.data[i] = i;
+ in.valuators.data_frac[i] = i + 20;
+ test_XIDeviceEvent(&in);
+ XIClearMask(in.valuators.mask, i);
+ }
+
+ for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ {
+ XISetMask(in.valuators.mask, i);
+ test_XIDeviceEvent(&in);
+ }
+}
+
+static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
+ xXIDeviceChangedEvent *out,
+ BOOL swap)
+{
+ int i, j;
+ unsigned char *ptr;
+
+ if (swap)
+ {
+ char n;
+
+ swaps(&out->sequenceNumber, n);
+ swapl(&out->length, n);
+ swaps(&out->evtype, n);
+ swaps(&out->deviceid, n);
+ swaps(&out->sourceid, n);
+ swapl(&out->time, n);
+ swaps(&out->num_classes, n);
+ }
+
+ g_assert(out->type == GenericEvent);
+ g_assert(out->extension == 0); /* IReqCode defaults to 0 */
+ g_assert(out->evtype == GetXI2Type((InternalEvent*)in));
+ g_assert(out->time == in->time);
+ g_assert(out->deviceid == in->deviceid);
+ g_assert(out->sourceid == in->sourceid);
+
+ ptr = (unsigned char*)&out[1];
+ for (i = 0; i < out->num_classes; i++)
+ {
+ xXIAnyInfo* any = (xXIAnyInfo*)ptr;
+
+ if (swap)
+ {
+ char n;
+ swaps(&any->length, n);
+ swaps(&any->type, n);
+ swaps(&any->sourceid, n);
+ }
+
+ switch(any->type)
+ {
+ case XIButtonClass:
+ {
+ xXIButtonInfo *b = (xXIButtonInfo*)any;
+ Atom *names;
+
+ if (swap)
+ {
+ char n;
+ swaps(&b->num_buttons, n);
+ }
+
+ g_assert(b->length ==
+ bytes_to_int32(sizeof(xXIButtonInfo)) +
+ bytes_to_int32(bits_to_bytes(b->num_buttons)) +
+ b->num_buttons);
+ g_assert(b->num_buttons == in->buttons.num_buttons);
+
+ names = (Atom*)((char*)&b[1] +
+ pad_to_int32(bits_to_bytes(b->num_buttons)));
+ for (j = 0; j < b->num_buttons; j++)
+ {
+ if (swap)
+ {
+ char n;
+ swapl(&names[j], n);
+ }
+ g_assert(names[j] == in->buttons.names[j]);
+ }
+ }
+ break;
+ case XIKeyClass:
+ {
+ xXIKeyInfo *k = (xXIKeyInfo*)any;
+ uint32_t *kc;
+
+ if (swap)
+ {
+ char n;
+ swaps(&k->num_keycodes, n);
+ }
+
+ g_assert(k->length ==
+ bytes_to_int32(sizeof(xXIKeyInfo)) +
+ k->num_keycodes);
+ g_assert(k->num_keycodes == in->keys.max_keycode -
+ in->keys.min_keycode + 1);
+
+ kc = (uint32_t*)&k[1];
+ for (j = 0; j < k->num_keycodes; j++)
+ {
+ if (swap)
+ {
+ char n;
+ swapl(&kc[j], n);
+ }
+ g_assert(kc[j] >= in->keys.min_keycode);
+ g_assert(kc[j] <= in->keys.max_keycode);
+ }
+ }
+ break;
+ case XIValuatorClass:
+ {
+ xXIValuatorInfo *v = (xXIValuatorInfo*)any;
+ g_assert(v->length ==
+ bytes_to_int32(sizeof(xXIValuatorInfo)));
+
+ }
+ break;
+ default:
+ g_error("Invalid class type.\n");
+ break;
+ }
+
+ ptr += any->length * 4;
+ }
+
+}
+
+static void test_XIDeviceChangedEvent(DeviceChangedEvent *in)
+{
+ xXIDeviceChangedEvent *out, *swapped;
+ int rc;
+
+ rc = EventToXI2((InternalEvent*)in, (xEvent**)&out);
+ g_assert(rc == Success);
+
+ test_values_XIDeviceChangedEvent(in, out, FALSE);
+
+ swapped = calloc(1, sizeof(xEvent) + out->length * 4);
+ XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)swapped);
+ test_values_XIDeviceChangedEvent(in, swapped, TRUE);
+
+ free(out);
+ free(swapped);
+}
+
+static void test_convert_XIDeviceChangedEvent(void)
+{
+ DeviceChangedEvent in;
+ int i;
+
+ g_test_message("Testing simple field values");
+ memset(&in, 0, sizeof(in));
+ in.header = ET_Internal;
+ in.type = ET_DeviceChanged;
+ in.length = sizeof(DeviceChangedEvent);
+ in.time = 0;
+ in.deviceid = 1;
+ in.sourceid = 2;
+ in.masterid = 3;
+ in.num_valuators = 4;
+ in.flags = DEVCHANGE_SLAVE_SWITCH | DEVCHANGE_POINTER_EVENT | DEVCHANGE_KEYBOARD_EVENT;
+
+ for (i = 0; i < MAX_BUTTONS; i++)
+ in.buttons.names[i] = i + 10;
+
+ in.keys.min_keycode = 8;
+ in.keys.max_keycode = 255;
+
+ test_XIDeviceChangedEvent(&in);
+
+ in.time = 1L;
+ test_XIDeviceChangedEvent(&in);
+ in.time = 1L << 8;
+ test_XIDeviceChangedEvent(&in);
+ in.time = 1L << 16;
+ test_XIDeviceChangedEvent(&in);
+ in.time = 1L << 24;
+ test_XIDeviceChangedEvent(&in);
+ in.time = ~0L;
+ test_XIDeviceChangedEvent(&in);
+
+ in.deviceid = 1L;
+ test_XIDeviceChangedEvent(&in);
+ in.deviceid = 1L << 8;
+ test_XIDeviceChangedEvent(&in);
+ in.deviceid = ~0 & 0xFFFF;
+ test_XIDeviceChangedEvent(&in);
+
+ in.sourceid = 1L;
+ test_XIDeviceChangedEvent(&in);
+ in.sourceid = 1L << 8;
+ test_XIDeviceChangedEvent(&in);
+ in.sourceid = ~0 & 0xFFFF;
+ test_XIDeviceChangedEvent(&in);
+
+ in.masterid = 1L;
+ test_XIDeviceChangedEvent(&in);
+ in.masterid = 1L << 8;
+ test_XIDeviceChangedEvent(&in);
+ in.masterid = ~0 & 0xFFFF;
+ test_XIDeviceChangedEvent(&in);
+
+ in.buttons.num_buttons = 0;
+ test_XIDeviceChangedEvent(&in);
+
+ in.buttons.num_buttons = 1;
+ test_XIDeviceChangedEvent(&in);
+
+ in.buttons.num_buttons = MAX_BUTTONS;
+ test_XIDeviceChangedEvent(&in);
+
+ in.keys.min_keycode = 0;
+ in.keys.max_keycode = 0;
+ test_XIDeviceChangedEvent(&in);
+
+ in.keys.max_keycode = 1 << 8;
+ test_XIDeviceChangedEvent(&in);
+
+ in.keys.max_keycode = 0xFFFC; /* highest range, above that the length
+ field gives up */
+ test_XIDeviceChangedEvent(&in);
+
+ in.keys.min_keycode = 1 << 8;
+ in.keys.max_keycode = 1 << 8;
+ test_XIDeviceChangedEvent(&in);
+
+ in.keys.min_keycode = 1 << 8;
+ in.keys.max_keycode = 0;
+ test_XIDeviceChangedEvent(&in);
+
+ in.num_valuators = 0;
+ test_XIDeviceChangedEvent(&in);
+
+ in.num_valuators = 1;
+ test_XIDeviceChangedEvent(&in);
+
+ in.num_valuators = MAX_VALUATORS;
+ test_XIDeviceChangedEvent(&in);
+
+ for (i = 0; i < MAX_VALUATORS; i++)
+ {
+ in.valuators[i].min = 0;
+ in.valuators[i].max = 0;
+ test_XIDeviceChangedEvent(&in);
+
+ in.valuators[i].max = 1 << 8;
+ test_XIDeviceChangedEvent(&in);
+ in.valuators[i].max = 1 << 16;
+ test_XIDeviceChangedEvent(&in);
+ in.valuators[i].max = 1 << 24;
+ test_XIDeviceChangedEvent(&in);
+ in.valuators[i].max = abs(~0);
+ test_XIDeviceChangedEvent(&in);
+
+ in.valuators[i].resolution = 1 << 8;
+ test_XIDeviceChangedEvent(&in);
+ in.valuators[i].resolution = 1 << 16;
+ test_XIDeviceChangedEvent(&in);
+ in.valuators[i].resolution = 1 << 24;
+ test_XIDeviceChangedEvent(&in);
+ in.valuators[i].resolution = abs(~0);
+ test_XIDeviceChangedEvent(&in);
+
+ in.valuators[i].name = i;
+ test_XIDeviceChangedEvent(&in);
+
+ in.valuators[i].mode = Relative;
+ test_XIDeviceChangedEvent(&in);
+
+ in.valuators[i].mode = Absolute;
+ test_XIDeviceChangedEvent(&in);
+ }
+}
+
+int main(int argc, char** argv)
+{
+ g_test_init(&argc, &argv,NULL);
+ g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
+
+ g_test_add_func("/xi2/eventconvert/XIRawEvent", test_convert_XIRawEvent);
+ g_test_add_func("/xi2/eventconvert/XIFocusEvent", test_convert_XIFocusEvent);
+ g_test_add_func("/xi2/eventconvert/XIDeviceEvent", test_convert_XIDeviceEvent);
+ g_test_add_func("/xi2/eventconvert/XIDeviceChangedEvent", test_convert_XIDeviceChangedEvent);
+
+ return g_test_run();
+}
diff --git a/xorg-server/test/xi2/protocol-xiselectevents.c b/xorg-server/test/xi2/protocol-xiselectevents.c
index fe1c26df8..f951a14fe 100644
--- a/xorg-server/test/xi2/protocol-xiselectevents.c
+++ b/xorg-server/test/xi2/protocol-xiselectevents.c
@@ -131,7 +131,7 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
{
int i, j;
xXIEventMask *mask;
- int nmasks = (XI_LASTEVENT + 7)/8;
+ int nmasks = (XI2LASTEVENT + 7)/8;
unsigned char *bits;
mask = (xXIEventMask*)&req[1];
@@ -150,14 +150,14 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
request_XISelectEvent(req, Success);
/* Test 1:
- * mask may be larger than needed for XI_LASTEVENT.
+ * mask may be larger than needed for XI2LASTEVENT.
* Test setting each valid mask bit, while leaving unneeded bits 0.
* -> Success
*/
bits = (unsigned char*)&mask[1];
mask->mask_len = (nmasks + 3)/4 * 10;
memset(bits, 0, mask->mask_len * 4);
- for (j = 0; j <= XI_LASTEVENT; j++)
+ for (j = 0; j <= XI2LASTEVENT; j++)
{
SetBit(bits, j);
request_XISelectEvent(req, Success);
@@ -165,7 +165,7 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
}
/* Test 2:
- * mask may be larger than needed for XI_LASTEVENT.
+ * mask may be larger than needed for XI2LASTEVENT.
* Test setting all valid mask bits, while leaving unneeded bits 0.
* -> Success
*/
@@ -173,21 +173,21 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
mask->mask_len = (nmasks + 3)/4 * 10;
memset(bits, 0, mask->mask_len * 4);
- for (j = 0; j <= XI_LASTEVENT; j++)
+ for (j = 0; j <= XI2LASTEVENT; j++)
{
SetBit(bits, j);
request_XISelectEvent(req, Success);
}
/* Test 3:
- * mask is larger than needed for XI_LASTEVENT. If any unneeded bit
+ * mask is larger than needed for XI2LASTEVENT. If any unneeded bit
* is set -> BadValue
*/
bits = (unsigned char*)&mask[1];
mask->mask_len = (nmasks + 3)/4 * 10;
memset(bits, 0, mask->mask_len * 4);
- for (j = XI_LASTEVENT + 1; j < mask->mask_len * 4; j++)
+ for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++)
{
SetBit(bits, j);
request_XISelectEvent(req, BadValue);
@@ -200,7 +200,7 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
bits = (unsigned char*)&mask[1];
mask->mask_len = (nmasks + 3)/4;
memset(bits, 0, mask->mask_len * 4);
- for (j = 0; j <= XI_LASTEVENT; j++)
+ for (j = 0; j <= XI2LASTEVENT; j++)
{
SetBit(bits, j);
request_XISelectEvent(req, Success);
@@ -228,7 +228,7 @@ static void request_XISelectEvents_masks(xXISelectEventsReq *req)
bits = (unsigned char*)&mask[1];
mask->mask_len = (nmasks + 3)/4;
memset(bits, 0, mask->mask_len * 4);
- for (j = 0; j <= XI_LASTEVENT; j++)
+ for (j = 0; j <= XI2LASTEVENT; j++)
SetBit(bits, j);
ClearBit(bits, XI_HierarchyChanged);
for (j = 1; j < 6; j++)
diff --git a/xorg-server/xkb/XKBMisc.c b/xorg-server/xkb/XKBMisc.c
index f983466ea..96688be18 100644
--- a/xorg-server/xkb/XKBMisc.c
+++ b/xorg-server/xkb/XKBMisc.c
@@ -1,839 +1,840 @@
-/************************************************************
-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 <dix-config.h>
-#elif defined(HAVE_CONFIG_H)
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "inputstr.h"
-#include <X11/keysym.h>
-#define XKBSRV_NEED_FILE_FUNCS
-#include <xkbsrv.h>
-
-/***====================================================================***/
-
-#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol)
-#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l))
-
-int
-XkbKeyTypesForCoreSymbols( XkbDescPtr xkb,
- int map_width,
- KeySym * core_syms,
- unsigned int protected,
- int * types_inout,
- KeySym * xkb_syms_rtrn)
-{
-register int i;
-unsigned int empty;
-int nSyms[XkbNumKbdGroups];
-int nGroups,tmp,groupsWidth;
-BOOL replicated = FALSE;
-
- /* Section 12.2 of the protocol describes this process in more detail */
- /* Step 1: find the # of symbols in the core mapping per group */
- groupsWidth= 2;
- for (i=0;i<XkbNumKbdGroups;i++) {
- if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) {
- nSyms[i]= xkb->map->types[types_inout[i]].num_levels;
- if (nSyms[i]>groupsWidth)
- groupsWidth= nSyms[i];
- }
- else {
- types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */
- nSyms[i]= 2;
- }
- }
- if (nSyms[XkbGroup1Index]<2)
- nSyms[XkbGroup1Index]= 2;
- if (nSyms[XkbGroup2Index]<2)
- nSyms[XkbGroup2Index]= 2;
- /* Step 2: Copy the symbols from the core ordering to XKB ordering */
- /* symbols in the core are in the order: */
- /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0);
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1);
- for (i=2;i<nSyms[XkbGroup1Index];i++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i);
- }
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2);
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3);
- tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */
- for (i=2;i<nSyms[XkbGroup2Index];i++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i);
- }
-
- /* Special case: if only the first group is explicit, and the symbols
- * replicate across all groups, then we have a Section 12.4 replication */
- if ((protected & ~XkbExplicitKeyType1Mask) == 0)
- {
- int j, width = nSyms[XkbGroup1Index];
-
- replicated = TRUE;
-
- /* Check ABAB in ABABCDECDEABCDE */
- if ((width > 0 && CORE_SYM(0) != CORE_SYM(2)) ||
- (width > 1 && CORE_SYM(1) != CORE_SYM(3)))
- replicated = FALSE;
-
- /* Check CDECDE in ABABCDECDEABCDE */
- for (i = 2; i < width && replicated; i++)
- {
- if (CORE_SYM(2 + i) != CORE_SYM(i + width))
- replicated = FALSE;
- }
-
- /* Check ABCDE in ABABCDECDEABCDE */
- for (j = 2; replicated &&
- j < XkbNumKbdGroups &&
- map_width >= width * (j + 1); j++)
- {
- for (i = 0; i < width && replicated; i++)
- {
- if (CORE_SYM(((i < 2) ? i : 2 + i)) != CORE_SYM(i + width * j))
- replicated = FALSE;
- }
- }
- }
-
- if (replicated)
- {
- nSyms[XkbGroup2Index]= 0;
- nSyms[XkbGroup3Index]= 0;
- nSyms[XkbGroup4Index]= 0;
- nGroups= 1;
- } else
- {
- tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index];
- if ((tmp>=map_width)&&
- ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) {
- nSyms[XkbGroup3Index]= 0;
- nSyms[XkbGroup4Index]= 0;
- nGroups= 2;
- } else
- {
- nGroups= 3;
- for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp);
- }
- if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) {
- nGroups= 4;
- for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) {
- xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp);
- }
- }
- else {
- nSyms[XkbGroup4Index]= 0;
- }
- }
- }
- /* steps 3&4: alphanumeric expansion, assign canonical types */
- empty= 0;
- for (i=0;i<nGroups;i++) {
- KeySym *syms;
- syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
- if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) {
- KeySym upper,lower;
- XkbConvertCase(syms[0],&lower,&upper);
- if (upper!=lower) {
- xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower;
- xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper;
- if ((protected&(1<<i))==0)
- types_inout[i]= XkbAlphabeticIndex;
- }
- else if ((protected&(1<<i))==0) {
- types_inout[i]= XkbOneLevelIndex;
- /* nSyms[i]= 1;*/
- }
- }
- if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) {
- if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1]))
- types_inout[i]= XkbKeypadIndex;
- else {
- KeySym upper,lower;
- XkbConvertCase(syms[0],&lower,&upper);
- if ((syms[0]==lower)&&(syms[1]==upper))
- types_inout[i]= XkbAlphabeticIndex;
- }
- }
- if (syms[0]==NoSymbol) {
- register int n;
- Bool found;
- for (n=1,found=FALSE;(!found)&&(n<nSyms[i]);n++) {
- found= (syms[n]!=NoSymbol);
- }
- if (!found)
- empty|= (1<<i);
- }
- }
- /* step 5: squoosh out empty groups */
- if (empty) {
- for (i=nGroups-1;i>=0;i--) {
- if (((empty&(1<<i))==0)||(protected&(1<<i)))
- break;
- nGroups--;
- }
- }
- if (nGroups<1)
- return 0;
-
- /* step 6: replicate group 1 into group two, if necessary */
- if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) {
- if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) {
- nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index];
- types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index];
- memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn,
- 2*sizeof(KeySym));
- }
- else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) {
- memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]],
- (char *)xkb_syms_rtrn,
- nSyms[XkbGroup1Index]*sizeof(KeySym));
- }
- }
-
- /* step 7: check for all groups identical or all width 1
- *
- * Special feature: if group 1 has an explicit type and all other groups
- * have canonical types with same symbols, we assume it's info lost from
- * the core replication.
- */
- if (nGroups>1) {
- Bool sameType,allOneLevel, canonical = TRUE;
- allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1);
- for (i=1,sameType=TRUE;(allOneLevel||sameType)&&(i<nGroups);i++) {
- sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index]));
- if (allOneLevel)
- allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1);
- if (types_inout[i] > XkbLastRequiredType)
- canonical = FALSE;
- }
- if (((sameType) || canonical)&&
- (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){
- register int s;
- Bool identical;
- for (i=1,identical=TRUE;identical&&(i<nGroups);i++) {
- KeySym *syms;
- if (nSyms[i] != nSyms[XkbGroup1Index])
- identical = FALSE;
- syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
- for (s=0;identical&&(s<nSyms[i]);s++) {
- if (syms[s]!=xkb_syms_rtrn[s])
- identical= FALSE;
- }
- }
- if (identical)
- nGroups= 1;
- }
- if (allOneLevel && (nGroups>1)) {
- KeySym *syms;
- syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]];
- nSyms[XkbGroup1Index]= 1;
- for (i=1;i<nGroups;i++) {
- xkb_syms_rtrn[i]= syms[0];
- syms+= nSyms[i];
- nSyms[i]= 1;
- }
- }
- }
- return nGroups;
-}
-
-static XkbSymInterpretPtr
-_XkbFindMatchingInterp( XkbDescPtr xkb,
- KeySym sym,
- unsigned int real_mods,
- unsigned int level)
-{
-register unsigned i;
-XkbSymInterpretPtr interp,rtrn;
-CARD8 mods;
-
- rtrn= NULL;
- interp= xkb->compat->sym_interpret;
- for (i=0;i<xkb->compat->num_si;i++,interp++) {
- if ((interp->sym==NoSymbol)||(sym==interp->sym)) {
- int match;
- if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0))
- mods= real_mods;
- else mods= 0;
- switch (interp->match&XkbSI_OpMask) {
- case XkbSI_NoneOf:
- match= ((interp->mods&mods)==0);
- break;
- case XkbSI_AnyOfOrNone:
- match= ((mods==0)||((interp->mods&mods)!=0));
- break;
- case XkbSI_AnyOf:
- match= ((interp->mods&mods)!=0);
- break;
- case XkbSI_AllOf:
- match= ((interp->mods&mods)==interp->mods);
- break;
- case XkbSI_Exactly:
- match= (interp->mods==mods);
- break;
- default:
- match= 0;
- break;
- }
- if (match) {
- if (interp->sym!=NoSymbol) {
- return interp;
- }
- else if (rtrn==NULL) {
- rtrn= interp;
- }
- }
- }
- }
- return rtrn;
-}
-
-static void
-_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey)
-{
-KeyCode last;
-
- last= (*pFirst)+(*pNum);
- if (newKey<*pFirst) {
- *pFirst= newKey;
- *pNum= (last-newKey)+1;
- }
- else if (newKey>last) {
- *pNum= (last-*pFirst)+1;
- }
- return;
-}
-
-static void
-_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods)
-{
-unsigned tmp;
-
- switch (act->type) {
- case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
- if (act->mods.flags&XkbSA_UseModMapMods)
- act->mods.real_mods= act->mods.mask= mods;
- if ((tmp= XkbModActionVMods(&act->mods))!=0) {
- XkbVirtualModsToReal(xkb,tmp,&tmp);
- act->mods.mask|= tmp;
- }
- break;
- case XkbSA_ISOLock:
- if (act->iso.flags&XkbSA_UseModMapMods)
- act->iso.real_mods= act->iso.mask= mods;
- if ((tmp= XkbModActionVMods(&act->iso))!=0) {
- XkbVirtualModsToReal(xkb,tmp,&tmp);
- act->iso.mask|= tmp;
- }
- break;
- }
- return;
-}
-
-#define IBUF_SIZE 8
-
-Bool
-XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes)
-{
-KeySym * syms;
-unsigned char explicit,mods;
-XkbSymInterpretPtr *interps,ibuf[IBUF_SIZE];
-int n,nSyms,found;
-unsigned changed,tmp;
-
- if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)||
- (!xkb->compat)||(!xkb->compat->sym_interpret)||
- (key<xkb->min_key_code)||(key>xkb->max_key_code)) {
- return FALSE;
- }
- if (((!xkb->server)||(!xkb->server->key_acts))&&
- (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) {
- return FALSE;
- }
- changed= 0; /* keeps track of what has changed in _this_ call */
- explicit= xkb->server->explicit[key];
- if (explicit&XkbExplicitInterpretMask) /* nothing to do */
- return TRUE;
- mods= (xkb->map->modmap?xkb->map->modmap[key]:0);
- nSyms= XkbKeyNumSyms(xkb,key);
- syms= XkbKeySymsPtr(xkb,key);
- if (nSyms>IBUF_SIZE) {
- interps= calloc(nSyms, sizeof(XkbSymInterpretPtr));
- if (interps==NULL) {
- interps= ibuf;
- nSyms= IBUF_SIZE;
- }
- }
- else {
- interps= ibuf;
- }
- found= 0;
- for (n=0;n<nSyms;n++) {
- unsigned level= (n%XkbKeyGroupsWidth(xkb,key));
- interps[n]= NULL;
- if (syms[n]!=NoSymbol) {
- interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level);
- if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction)
- found++;
- else interps[n]= NULL;
- }
- }
- /* 1/28/96 (ef) -- XXX! WORKING HERE */
- if (!found) {
- if (xkb->server->key_acts[key]!=0) {
- xkb->server->key_acts[key]= 0;
- changed|= XkbKeyActionsMask;
- }
- }
- else {
- XkbAction *pActs;
- unsigned int new_vmodmask;
- changed|= XkbKeyActionsMask;
- pActs= XkbResizeKeyActions(xkb,key,nSyms);
- if (!pActs) {
- if (nSyms > IBUF_SIZE)
- free(interps);
- return FALSE;
- }
- new_vmodmask= 0;
- for (n=0;n<nSyms;n++) {
- if (interps[n]) {
- unsigned effMods;
-
- pActs[n]= *((XkbAction *)&interps[n]->act);
- if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) {
- effMods= mods;
- if (interps[n]->virtual_mod!=XkbNoModifier)
- new_vmodmask|= (1<<interps[n]->virtual_mod);
- }
- else effMods= 0;
- _XkbSetActionKeyMods(xkb,&pActs[n],effMods);
- }
- else pActs[n].type= XkbSA_NoAction;
- }
- if (((explicit&XkbExplicitVModMapMask)==0)&&
- (xkb->server->vmodmap[key]!=new_vmodmask)) {
- changed|= XkbVirtualModMapMask;
- xkb->server->vmodmap[key]= new_vmodmask;
- }
- if (interps[0]) {
- if ((interps[0]->flags&XkbSI_LockingKey)&&
- ((explicit&XkbExplicitBehaviorMask)==0)) {
- xkb->server->behaviors[key].type= XkbKB_Lock;
- changed|= XkbKeyBehaviorsMask;
- }
- if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
- CARD8 old;
- old= xkb->ctrls->per_key_repeat[key/8];
- if (interps[0]->flags&XkbSI_AutoRepeat)
- xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8));
- else xkb->ctrls->per_key_repeat[key/8]&= ~(1<<(key%8));
- if (changes && (old!=xkb->ctrls->per_key_repeat[key/8]))
- changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
- }
- }
- }
- if ((!found)||(interps[0]==NULL)) {
- if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
- CARD8 old;
- old= xkb->ctrls->per_key_repeat[key/8];
- xkb->ctrls->per_key_repeat[key/8]|= (1<<(key%8));
- if (changes && (old!=xkb->ctrls->per_key_repeat[key/8]))
- changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
- }
- if (((explicit&XkbExplicitBehaviorMask)==0)&&
- (xkb->server->behaviors[key].type==XkbKB_Lock)) {
- xkb->server->behaviors[key].type= XkbKB_Default;
- changed|= XkbKeyBehaviorsMask;
- }
- }
- if (changes) {
- XkbMapChangesPtr mc;
- mc= &changes->map;
- tmp= (changed&mc->changed);
- if (tmp&XkbKeyActionsMask)
- _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key);
- else if (changed&XkbKeyActionsMask) {
- mc->changed|= XkbKeyActionsMask;
- mc->first_key_act= key;
- mc->num_key_acts= 1;
- }
- if (tmp&XkbKeyBehaviorsMask) {
- _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors,
- key);
- }
- else if (changed&XkbKeyBehaviorsMask) {
- mc->changed|= XkbKeyBehaviorsMask;
- mc->first_key_behavior= key;
- mc->num_key_behaviors= 1;
- }
- if (tmp&XkbVirtualModMapMask)
- _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key);
- else if (changed&XkbVirtualModMapMask) {
- mc->changed|= XkbVirtualModMapMask;
- mc->first_vmodmap_key= key;
- mc->num_vmodmap_keys= 1;
- }
- mc->changed|= changed;
- }
- if (interps!=ibuf)
- free(interps);
- return TRUE;
-}
-
-Status
-XkbChangeTypesOfKey( XkbDescPtr xkb,
- int key,
- int nGroups,
- unsigned groups,
- int * newTypesIn,
- XkbMapChangesPtr changes)
-{
-XkbKeyTypePtr pOldType,pNewType;
-register int i;
-int width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups];
-
- if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) ||
- (!xkb->map->types)||(!newTypesIn)||((groups&XkbAllGroupsMask)==0)||
- (nGroups>XkbNumKbdGroups)) {
- return BadMatch;
- }
- if (nGroups==0) {
- for (i=0;i<XkbNumKbdGroups;i++) {
- xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex;
- }
- i= xkb->map->key_sym_map[key].group_info;
- i= XkbSetNumGroups(i,0);
- xkb->map->key_sym_map[key].group_info= i;
- XkbResizeKeySyms(xkb,key,0);
- return Success;
- }
-
- nOldGroups= XkbKeyNumGroups(xkb,key);
- oldWidth= XkbKeyGroupsWidth(xkb,key);
- for (width=i=0;i<nGroups;i++) {
- if (groups&(1<<i))
- newTypes[i]= newTypesIn[i];
- else if (i<nOldGroups)
- newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i);
- else if (nOldGroups>0)
- newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
- else newTypes[i]= XkbTwoLevelIndex;
- if (newTypes[i]>xkb->map->num_types)
- return BadMatch;
- pNewType= &xkb->map->types[newTypes[i]];
- if (pNewType->num_levels>width)
- width= pNewType->num_levels;
- }
- if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups))
- xkb->ctrls->num_groups= nGroups;
- if ((width!=oldWidth)||(nGroups!=nOldGroups)) {
- KeySym oldSyms[XkbMaxSymsPerKey],*pSyms;
- int nCopy;
-
- if (nOldGroups==0) {
- pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
- if (pSyms!=NULL) {
- i= xkb->map->key_sym_map[key].group_info;
- i= XkbSetNumGroups(i,nGroups);
- xkb->map->key_sym_map[key].group_info= i;
- xkb->map->key_sym_map[key].width= width;
- for (i=0;i<nGroups;i++) {
- xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
- }
- return Success;
- }
- return BadAlloc;
- }
- pSyms= XkbKeySymsPtr(xkb,key);
- memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
- pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
- if (pSyms==NULL)
- return BadAlloc;
- memset(pSyms, 0, width*nGroups*sizeof(KeySym));
- for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
- pOldType= XkbKeyKeyType(xkb,key,i);
- pNewType= &xkb->map->types[newTypes[i]];
- if (pNewType->num_levels>pOldType->num_levels)
- nCopy= pOldType->num_levels;
- else nCopy= pNewType->num_levels;
- memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym));
- }
- if (XkbKeyHasActions(xkb,key)) {
- XkbAction oldActs[XkbMaxSymsPerKey],*pActs;
- pActs= XkbKeyActionsPtr(xkb,key);
- memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction));
- pActs= XkbResizeKeyActions(xkb,key,width*nGroups);
- if (pActs==NULL)
- return BadAlloc;
- memset(pActs, 0, width*nGroups*sizeof(XkbAction));
- for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
- pOldType= XkbKeyKeyType(xkb,key,i);
- pNewType= &xkb->map->types[newTypes[i]];
- if (pNewType->num_levels>pOldType->num_levels)
- nCopy= pOldType->num_levels;
- else nCopy= pNewType->num_levels;
- memcpy(&pActs[i*width],&oldActs[i*oldWidth],
- nCopy*sizeof(XkbAction));
- }
- }
- i= xkb->map->key_sym_map[key].group_info;
- i= XkbSetNumGroups(i,nGroups);
- xkb->map->key_sym_map[key].group_info= i;
- xkb->map->key_sym_map[key].width= width;
- }
- width= 0;
- for (i=0;i<nGroups;i++) {
- xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
- if (xkb->map->types[newTypes[i]].num_levels>width)
- width= xkb->map->types[newTypes[i]].num_levels;
- }
- xkb->map->key_sym_map[key].width= width;
- if (changes!=NULL) {
- if (changes->changed&XkbKeySymsMask) {
- _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms,
- key);
- }
- else {
- changes->changed|= XkbKeySymsMask;
- changes->first_key_sym= key;
- changes->num_key_syms= 1;
- }
- }
- return Success;
-}
-
-/***====================================================================***/
-
-Bool
-XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn)
-{
-register int i,bit;
-register unsigned mask;
-
- if (xkb==NULL)
- return FALSE;
- if (virtual_mask==0) {
- *mask_rtrn= 0;
- return TRUE;
- }
- if (xkb->server==NULL)
- return FALSE;
- for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (virtual_mask&bit)
- mask|= xkb->server->vmods[i];
- }
- *mask_rtrn= mask;
- return TRUE;
-}
-
-/***====================================================================***/
-
-static Bool
-XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed)
-{
-unsigned int tmp;
-
- switch (act->type) {
- case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
- if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) {
- XkbVirtualModsToReal(xkb,tmp,&tmp);
- act->mods.mask= act->mods.real_mods;
- act->mods.mask|= tmp;
- return TRUE;
- }
- break;
- case XkbSA_ISOLock:
- if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) {
- XkbVirtualModsToReal(xkb,tmp,&tmp);
- act->iso.mask= act->iso.real_mods;
- act->iso.mask|= tmp;
- return TRUE;
- }
- break;
- }
- return FALSE;
-}
-
-static void
-XkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb,
- XkbKeyTypePtr type,
- unsigned int changed,
- XkbChangesPtr changes)
-{
-register unsigned int i;
-unsigned int mask;
-
- XkbVirtualModsToReal(xkb,type->mods.vmods,&mask);
- type->mods.mask= type->mods.real_mods|mask;
- if ((type->map_count>0)&&(type->mods.vmods!=0)) {
- XkbKTMapEntryPtr entry;
- for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
- if (entry->mods.vmods!=0) {
- XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask);
- entry->mods.mask=entry->mods.real_mods|mask;
- /* entry is active if vmods are bound*/
- entry->active= (mask!=0);
- }
- else entry->active= 1;
- }
- }
- if (changes) {
- int type_ndx;
- type_ndx= type-xkb->map->types;
- if ((type_ndx<0)||(type_ndx>xkb->map->num_types))
- return;
- if (changes->map.changed&XkbKeyTypesMask) {
- int last;
- last= changes->map.first_type+changes->map.num_types-1;
- if (type_ndx<changes->map.first_type) {
- changes->map.first_type= type_ndx;
- changes->map.num_types= (last-type_ndx)+1;
- }
- else if (type_ndx>last) {
- changes->map.num_types= (type_ndx-changes->map.first_type)+1;
- }
- }
- else {
- changes->map.changed|= XkbKeyTypesMask;
- changes->map.first_type= type_ndx;
- changes->map.num_types= 1;
- }
- }
- return;
-}
-
-Bool
-XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes)
-{
-register int i;
-unsigned int checkState = 0;
-
- if ((!xkb) || (!xkb->map) || (changed==0))
- return FALSE;
- for (i=0;i<xkb->map->num_types;i++) {
- if (xkb->map->types[i].mods.vmods & changed)
- XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes);
- }
- if (changed&xkb->ctrls->internal.vmods) {
- unsigned int newMask;
- XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask);
- newMask|= xkb->ctrls->internal.real_mods;
- if (xkb->ctrls->internal.mask!=newMask) {
- xkb->ctrls->internal.mask= newMask;
- if (changes) {
- changes->ctrls.changed_ctrls|= XkbInternalModsMask;
- checkState= TRUE;
- }
- }
- }
- if (changed&xkb->ctrls->ignore_lock.vmods) {
- unsigned int newMask;
- XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask);
- newMask|= xkb->ctrls->ignore_lock.real_mods;
- if (xkb->ctrls->ignore_lock.mask!=newMask) {
- xkb->ctrls->ignore_lock.mask= newMask;
- if (changes) {
- changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask;
- checkState= TRUE;
- }
- }
- }
- if (xkb->indicators!=NULL) {
- XkbIndicatorMapPtr map;
- map= &xkb->indicators->maps[0];
- for (i=0;i<XkbNumIndicators;i++,map++) {
- if (map->mods.vmods&changed) {
- unsigned int newMask;
- XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask);
- newMask|= map->mods.real_mods;
- if (newMask!=map->mods.mask) {
- map->mods.mask= newMask;
- if (changes) {
- changes->indicators.map_changes|= (1<<i);
- checkState= TRUE;
- }
- }
- }
- }
- }
- if (xkb->compat!=NULL) {
- XkbCompatMapPtr compat;
- compat= xkb->compat;
- for (i=0;i<XkbNumKbdGroups;i++) {
- unsigned int newMask;
- XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask);
- newMask|= compat->groups[i].real_mods;
- if (compat->groups[i].mask!=newMask) {
- compat->groups[i].mask= newMask;
- if (changes) {
- changes->compat.changed_groups|= (1<<i);
- checkState= TRUE;
- }
- }
- }
- }
- if (xkb->map && xkb->server) {
- int highChange = 0, lowChange = -1;
- for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
- if (XkbKeyHasActions(xkb,i)) {
- register XkbAction *pAct;
- register int n;
-
- pAct= XkbKeyActionsPtr(xkb,i);
- for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) {
- if ((pAct->type!=XkbSA_NoAction)&&
- XkbUpdateActionVirtualMods(xkb,pAct,changed)) {
- if (lowChange<0)
- lowChange= i;
- highChange= i;
- }
- }
- }
- }
- if (changes && (lowChange>0)) { /* something changed */
- if (changes->map.changed&XkbKeyActionsMask) {
- int last;
- if (changes->map.first_key_act<lowChange)
- lowChange= changes->map.first_key_act;
- last= changes->map.first_key_act+changes->map.num_key_acts-1;
- if (last>highChange)
- highChange= last;
- }
- changes->map.changed|= XkbKeyActionsMask;
- changes->map.first_key_act= lowChange;
- changes->map.num_key_acts= (highChange-lowChange)+1;
- }
- }
- return checkState;
-}
+/************************************************************
+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 <dix-config.h>
+#elif defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "inputstr.h"
+#include <X11/keysym.h>
+#define XKBSRV_NEED_FILE_FUNCS
+#include <xkbsrv.h>
+
+/***====================================================================***/
+
+#define CORE_SYM(i) (i<map_width?core_syms[i]:NoSymbol)
+#define XKB_OFFSET(g,l) (((g)*groupsWidth)+(l))
+
+int
+XkbKeyTypesForCoreSymbols( XkbDescPtr xkb,
+ int map_width,
+ KeySym * core_syms,
+ unsigned int protected,
+ int * types_inout,
+ KeySym * xkb_syms_rtrn)
+{
+register int i;
+unsigned int empty;
+int nSyms[XkbNumKbdGroups];
+int nGroups,tmp,groupsWidth;
+BOOL replicated = FALSE;
+
+ /* Section 12.2 of the protocol describes this process in more detail */
+ /* Step 1: find the # of symbols in the core mapping per group */
+ groupsWidth= 2;
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ if ((protected&(1<<i))&&(types_inout[i]<xkb->map->num_types)) {
+ nSyms[i]= xkb->map->types[types_inout[i]].num_levels;
+ if (nSyms[i]>groupsWidth)
+ groupsWidth= nSyms[i];
+ }
+ else {
+ types_inout[i]= XkbTwoLevelIndex; /* don't really know, yet */
+ nSyms[i]= 2;
+ }
+ }
+ if (nSyms[XkbGroup1Index]<2)
+ nSyms[XkbGroup1Index]= 2;
+ if (nSyms[XkbGroup2Index]<2)
+ nSyms[XkbGroup2Index]= 2;
+ /* Step 2: Copy the symbols from the core ordering to XKB ordering */
+ /* symbols in the core are in the order: */
+ /* G1L1 G1L2 G2L1 G2L2 [G1L[3-n]] [G2L[3-n]] [G3L*] [G3L*] */
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,0)]= CORE_SYM(0);
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,1)]= CORE_SYM(1);
+ for (i=2;i<nSyms[XkbGroup1Index];i++) {
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup1Index,i)]= CORE_SYM(2+i);
+ }
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,0)]= CORE_SYM(2);
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,1)]= CORE_SYM(3);
+ tmp= 2+(nSyms[XkbGroup1Index]-2); /* offset to extra group2 syms */
+ for (i=2;i<nSyms[XkbGroup2Index];i++) {
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup2Index,i)]= CORE_SYM(tmp+i);
+ }
+
+ /* Special case: if only the first group is explicit, and the symbols
+ * replicate across all groups, then we have a Section 12.4 replication */
+ if ((protected & ~XkbExplicitKeyType1Mask) == 0)
+ {
+ int j, width = nSyms[XkbGroup1Index];
+
+ replicated = TRUE;
+
+ /* Check ABAB in ABABCDECDEABCDE */
+ if ((width > 0 && CORE_SYM(0) != CORE_SYM(2)) ||
+ (width > 1 && CORE_SYM(1) != CORE_SYM(3)))
+ replicated = FALSE;
+
+ /* Check CDECDE in ABABCDECDEABCDE */
+ for (i = 2; i < width && replicated; i++)
+ {
+ if (CORE_SYM(2 + i) != CORE_SYM(i + width))
+ replicated = FALSE;
+ }
+
+ /* Check ABCDE in ABABCDECDEABCDE */
+ for (j = 2; replicated &&
+ j < XkbNumKbdGroups &&
+ map_width >= width * (j + 1); j++)
+ {
+ for (i = 0; i < width && replicated; i++)
+ {
+ if (CORE_SYM(((i < 2) ? i : 2 + i)) != CORE_SYM(i + width * j))
+ replicated = FALSE;
+ }
+ }
+ }
+
+ if (replicated)
+ {
+ nSyms[XkbGroup2Index]= 0;
+ nSyms[XkbGroup3Index]= 0;
+ nSyms[XkbGroup4Index]= 0;
+ nGroups= 1;
+ } else
+ {
+ tmp= nSyms[XkbGroup1Index]+nSyms[XkbGroup2Index];
+ if ((tmp>=map_width)&&
+ ((protected&(XkbExplicitKeyType3Mask|XkbExplicitKeyType4Mask))==0)) {
+ nSyms[XkbGroup3Index]= 0;
+ nSyms[XkbGroup4Index]= 0;
+ nGroups= 2;
+ } else
+ {
+ nGroups= 3;
+ for (i=0;i<nSyms[XkbGroup3Index];i++,tmp++) {
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup3Index,i)]= CORE_SYM(tmp);
+ }
+ if ((tmp<map_width)||(protected&XkbExplicitKeyType4Mask)) {
+ nGroups= 4;
+ for (i=0;i<nSyms[XkbGroup4Index];i++,tmp++) {
+ xkb_syms_rtrn[XKB_OFFSET(XkbGroup4Index,i)]= CORE_SYM(tmp);
+ }
+ }
+ else {
+ nSyms[XkbGroup4Index]= 0;
+ }
+ }
+ }
+ /* steps 3&4: alphanumeric expansion, assign canonical types */
+ empty= 0;
+ for (i=0;i<nGroups;i++) {
+ KeySym *syms;
+ syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
+ if ((nSyms[i]>1)&&(syms[1]==NoSymbol)&&(syms[0]!=NoSymbol)) {
+ KeySym upper,lower;
+ XkbConvertCase(syms[0],&lower,&upper);
+ if (upper!=lower) {
+ xkb_syms_rtrn[XKB_OFFSET(i,0)]= lower;
+ xkb_syms_rtrn[XKB_OFFSET(i,1)]= upper;
+ if ((protected&(1<<i))==0)
+ types_inout[i]= XkbAlphabeticIndex;
+ }
+ else if ((protected&(1<<i))==0) {
+ types_inout[i]= XkbOneLevelIndex;
+ /* nSyms[i]= 1;*/
+ }
+ }
+ if (((protected&(1<<i))==0)&&(types_inout[i]==XkbTwoLevelIndex)) {
+ if (XkbKSIsKeypad(syms[0])||XkbKSIsKeypad(syms[1]))
+ types_inout[i]= XkbKeypadIndex;
+ else {
+ KeySym upper,lower;
+ XkbConvertCase(syms[0],&lower,&upper);
+ if ((syms[0]==lower)&&(syms[1]==upper))
+ types_inout[i]= XkbAlphabeticIndex;
+ }
+ }
+ if (syms[0]==NoSymbol) {
+ register int n;
+ Bool found;
+ for (n=1,found=FALSE;(!found)&&(n<nSyms[i]);n++) {
+ found= (syms[n]!=NoSymbol);
+ }
+ if (!found)
+ empty|= (1<<i);
+ }
+ }
+ /* step 5: squoosh out empty groups */
+ if (empty) {
+ for (i=nGroups-1;i>=0;i--) {
+ if (((empty&(1<<i))==0)||(protected&(1<<i)))
+ break;
+ nGroups--;
+ }
+ }
+ if (nGroups<1)
+ return 0;
+
+ /* step 6: replicate group 1 into group two, if necessary */
+ if ((nGroups>1)&&((empty&(XkbGroup1Mask|XkbGroup2Mask))==XkbGroup2Mask)) {
+ if ((protected&(XkbExplicitKeyType1Mask|XkbExplicitKeyType2Mask))==0) {
+ nSyms[XkbGroup2Index]= nSyms[XkbGroup1Index];
+ types_inout[XkbGroup2Index]= types_inout[XkbGroup1Index];
+ memcpy((char *)&xkb_syms_rtrn[2],(char *)xkb_syms_rtrn,
+ 2*sizeof(KeySym));
+ }
+ else if (types_inout[XkbGroup1Index]==types_inout[XkbGroup2Index]) {
+ memcpy((char *)&xkb_syms_rtrn[nSyms[XkbGroup1Index]],
+ (char *)xkb_syms_rtrn,
+ nSyms[XkbGroup1Index]*sizeof(KeySym));
+ }
+ }
+
+ /* step 7: check for all groups identical or all width 1
+ *
+ * Special feature: if group 1 has an explicit type and all other groups
+ * have canonical types with same symbols, we assume it's info lost from
+ * the core replication.
+ */
+ if (nGroups>1) {
+ Bool sameType,allOneLevel, canonical = TRUE;
+ allOneLevel= (xkb->map->types[types_inout[0]].num_levels==1);
+ for (i=1,sameType=TRUE;(allOneLevel||sameType)&&(i<nGroups);i++) {
+ sameType=(sameType&&(types_inout[i]==types_inout[XkbGroup1Index]));
+ if (allOneLevel)
+ allOneLevel= (xkb->map->types[types_inout[i]].num_levels==1);
+ if (types_inout[i] > XkbLastRequiredType)
+ canonical = FALSE;
+ }
+ if (((sameType) || canonical)&&
+ (!(protected&(XkbExplicitKeyTypesMask&~XkbExplicitKeyType1Mask)))){
+ register int s;
+ Bool identical;
+ for (i=1,identical=TRUE;identical&&(i<nGroups);i++) {
+ KeySym *syms;
+ if (nSyms[i] != nSyms[XkbGroup1Index])
+ identical = FALSE;
+ syms= &xkb_syms_rtrn[XKB_OFFSET(i,0)];
+ for (s=0;identical&&(s<nSyms[i]);s++) {
+ if (syms[s]!=xkb_syms_rtrn[s])
+ identical= FALSE;
+ }
+ }
+ if (identical)
+ nGroups= 1;
+ }
+ if (allOneLevel && (nGroups>1)) {
+ KeySym *syms;
+ syms= &xkb_syms_rtrn[nSyms[XkbGroup1Index]];
+ nSyms[XkbGroup1Index]= 1;
+ for (i=1;i<nGroups;i++) {
+ xkb_syms_rtrn[i]= syms[0];
+ syms+= nSyms[i];
+ nSyms[i]= 1;
+ }
+ }
+ }
+ return nGroups;
+}
+
+static XkbSymInterpretPtr
+_XkbFindMatchingInterp( XkbDescPtr xkb,
+ KeySym sym,
+ unsigned int real_mods,
+ unsigned int level)
+{
+register unsigned i;
+XkbSymInterpretPtr interp,rtrn;
+CARD8 mods;
+
+ rtrn= NULL;
+ interp= xkb->compat->sym_interpret;
+ for (i=0;i<xkb->compat->num_si;i++,interp++) {
+ if ((interp->sym==NoSymbol)||(sym==interp->sym)) {
+ int match;
+ if ((level==0)||((interp->match&XkbSI_LevelOneOnly)==0))
+ mods= real_mods;
+ else mods= 0;
+ switch (interp->match&XkbSI_OpMask) {
+ case XkbSI_NoneOf:
+ match= ((interp->mods&mods)==0);
+ break;
+ case XkbSI_AnyOfOrNone:
+ match= ((mods==0)||((interp->mods&mods)!=0));
+ break;
+ case XkbSI_AnyOf:
+ match= ((interp->mods&mods)!=0);
+ break;
+ case XkbSI_AllOf:
+ match= ((interp->mods&mods)==interp->mods);
+ break;
+ case XkbSI_Exactly:
+ match= (interp->mods==mods);
+ break;
+ default:
+ match= 0;
+ break;
+ }
+ if (match) {
+ if (interp->sym!=NoSymbol) {
+ return interp;
+ }
+ else if (rtrn==NULL) {
+ rtrn= interp;
+ }
+ }
+ }
+ }
+ return rtrn;
+}
+
+static void
+_XkbAddKeyChange(KeyCode *pFirst,unsigned char *pNum,KeyCode newKey)
+{
+KeyCode last;
+
+ last= (*pFirst)+(*pNum);
+ if (newKey<*pFirst) {
+ *pFirst= newKey;
+ *pNum= (last-newKey)+1;
+ }
+ else if (newKey>last) {
+ *pNum= (last-*pFirst)+1;
+ }
+ return;
+}
+
+static void
+_XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods)
+{
+unsigned tmp;
+
+ switch (act->type) {
+ case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
+ if (act->mods.flags&XkbSA_UseModMapMods)
+ act->mods.real_mods= act->mods.mask= mods;
+ if ((tmp= XkbModActionVMods(&act->mods))!=0) {
+ XkbVirtualModsToReal(xkb,tmp,&tmp);
+ act->mods.mask|= tmp;
+ }
+ break;
+ case XkbSA_ISOLock:
+ if (act->iso.flags&XkbSA_UseModMapMods)
+ act->iso.real_mods= act->iso.mask= mods;
+ if ((tmp= XkbModActionVMods(&act->iso))!=0) {
+ XkbVirtualModsToReal(xkb,tmp,&tmp);
+ act->iso.mask|= tmp;
+ }
+ break;
+ }
+ return;
+}
+
+#define IBUF_SIZE 8
+
+Bool
+XkbApplyCompatMapToKey(XkbDescPtr xkb,KeyCode key,XkbChangesPtr changes)
+{
+KeySym * syms;
+unsigned char explicit,mods;
+XkbSymInterpretPtr *interps,ibuf[IBUF_SIZE];
+int n,nSyms,found;
+unsigned changed,tmp;
+
+ if ((!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)||
+ (!xkb->compat)||(!xkb->compat->sym_interpret)||
+ (key<xkb->min_key_code)||(key>xkb->max_key_code)) {
+ return FALSE;
+ }
+ if (((!xkb->server)||(!xkb->server->key_acts))&&
+ (XkbAllocServerMap(xkb,XkbAllServerInfoMask,0)!=Success)) {
+ return FALSE;
+ }
+ changed= 0; /* keeps track of what has changed in _this_ call */
+ explicit= xkb->server->explicit[key];
+ if (explicit&XkbExplicitInterpretMask) /* nothing to do */
+ return TRUE;
+ mods= (xkb->map->modmap?xkb->map->modmap[key]:0);
+ nSyms= XkbKeyNumSyms(xkb,key);
+ syms= XkbKeySymsPtr(xkb,key);
+ if (nSyms>IBUF_SIZE) {
+ interps= calloc(nSyms, sizeof(XkbSymInterpretPtr));
+ if (interps==NULL) {
+ interps= ibuf;
+ nSyms= IBUF_SIZE;
+ }
+ }
+ else {
+ interps= ibuf;
+ }
+ found= 0;
+ for (n=0;n<nSyms;n++) {
+ unsigned level= (n%XkbKeyGroupsWidth(xkb,key));
+ interps[n]= NULL;
+ if (syms[n]!=NoSymbol) {
+ interps[n]= _XkbFindMatchingInterp(xkb,syms[n],mods,level);
+ if (interps[n]&&interps[n]->act.type!=XkbSA_NoAction)
+ found++;
+ else interps[n]= NULL;
+ }
+ }
+ /* 1/28/96 (ef) -- XXX! WORKING HERE */
+ if (!found) {
+ if (xkb->server->key_acts[key]!=0) {
+ xkb->server->key_acts[key]= 0;
+ changed|= XkbKeyActionsMask;
+ }
+ }
+ else {
+ XkbAction *pActs;
+ unsigned int new_vmodmask;
+ changed|= XkbKeyActionsMask;
+ pActs= XkbResizeKeyActions(xkb,key,nSyms);
+ if (!pActs) {
+ if (nSyms > IBUF_SIZE)
+ free(interps);
+ return FALSE;
+ }
+ new_vmodmask= 0;
+ for (n=0;n<nSyms;n++) {
+ if (interps[n]) {
+ unsigned effMods;
+
+ pActs[n]= *((XkbAction *)&interps[n]->act);
+ if ((n==0)||((interps[n]->match&XkbSI_LevelOneOnly)==0)) {
+ effMods= mods;
+ if (interps[n]->virtual_mod!=XkbNoModifier)
+ new_vmodmask|= (1<<interps[n]->virtual_mod);
+ }
+ else effMods= 0;
+ _XkbSetActionKeyMods(xkb,&pActs[n],effMods);
+ }
+ else pActs[n].type= XkbSA_NoAction;
+ }
+ if (((explicit&XkbExplicitVModMapMask)==0)&&
+ (xkb->server->vmodmap[key]!=new_vmodmask)) {
+ changed|= XkbVirtualModMapMask;
+ xkb->server->vmodmap[key]= new_vmodmask;
+ }
+ if (interps[0]) {
+ if ((interps[0]->flags&XkbSI_LockingKey)&&
+ ((explicit&XkbExplicitBehaviorMask)==0)) {
+ xkb->server->behaviors[key].type= XkbKB_Lock;
+ changed|= XkbKeyBehaviorsMask;
+ }
+ if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
+ CARD8 old;
+ old= BitIsOn(xkb->ctrls->per_key_repeat, key);
+ if (interps[0]->flags&XkbSI_AutoRepeat)
+ SetBit(xkb->ctrls->per_key_repeat, key);
+ else
+ ClearBit(xkb->ctrls->per_key_repeat, key);
+ if (changes && old != BitIsOn(xkb->ctrls->per_key_repeat, key))
+ changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
+ }
+ }
+ }
+ if ((!found)||(interps[0]==NULL)) {
+ if (((explicit&XkbExplicitAutoRepeatMask)==0)&&(xkb->ctrls)) {
+ CARD8 old;
+ old = BitIsOn(xkb->ctrls->per_key_repeat, key);
+ SetBit(xkb->ctrls->per_key_repeat, key);
+ if (changes && (old != BitIsOn(xkb->ctrls->per_key_repeat, key)))
+ changes->ctrls.changed_ctrls|= XkbPerKeyRepeatMask;
+ }
+ if (((explicit&XkbExplicitBehaviorMask)==0)&&
+ (xkb->server->behaviors[key].type==XkbKB_Lock)) {
+ xkb->server->behaviors[key].type= XkbKB_Default;
+ changed|= XkbKeyBehaviorsMask;
+ }
+ }
+ if (changes) {
+ XkbMapChangesPtr mc;
+ mc= &changes->map;
+ tmp= (changed&mc->changed);
+ if (tmp&XkbKeyActionsMask)
+ _XkbAddKeyChange(&mc->first_key_act,&mc->num_key_acts,key);
+ else if (changed&XkbKeyActionsMask) {
+ mc->changed|= XkbKeyActionsMask;
+ mc->first_key_act= key;
+ mc->num_key_acts= 1;
+ }
+ if (tmp&XkbKeyBehaviorsMask) {
+ _XkbAddKeyChange(&mc->first_key_behavior,&mc->num_key_behaviors,
+ key);
+ }
+ else if (changed&XkbKeyBehaviorsMask) {
+ mc->changed|= XkbKeyBehaviorsMask;
+ mc->first_key_behavior= key;
+ mc->num_key_behaviors= 1;
+ }
+ if (tmp&XkbVirtualModMapMask)
+ _XkbAddKeyChange(&mc->first_vmodmap_key,&mc->num_vmodmap_keys,key);
+ else if (changed&XkbVirtualModMapMask) {
+ mc->changed|= XkbVirtualModMapMask;
+ mc->first_vmodmap_key= key;
+ mc->num_vmodmap_keys= 1;
+ }
+ mc->changed|= changed;
+ }
+ if (interps!=ibuf)
+ free(interps);
+ return TRUE;
+}
+
+Status
+XkbChangeTypesOfKey( XkbDescPtr xkb,
+ int key,
+ int nGroups,
+ unsigned groups,
+ int * newTypesIn,
+ XkbMapChangesPtr changes)
+{
+XkbKeyTypePtr pOldType,pNewType;
+register int i;
+int width,nOldGroups,oldWidth,newTypes[XkbNumKbdGroups];
+
+ if ((!xkb) || (!XkbKeycodeInRange(xkb,key)) || (!xkb->map) ||
+ (!xkb->map->types)||(!newTypesIn)||((groups&XkbAllGroupsMask)==0)||
+ (nGroups>XkbNumKbdGroups)) {
+ return BadMatch;
+ }
+ if (nGroups==0) {
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ xkb->map->key_sym_map[key].kt_index[i]= XkbOneLevelIndex;
+ }
+ i= xkb->map->key_sym_map[key].group_info;
+ i= XkbSetNumGroups(i,0);
+ xkb->map->key_sym_map[key].group_info= i;
+ XkbResizeKeySyms(xkb,key,0);
+ return Success;
+ }
+
+ nOldGroups= XkbKeyNumGroups(xkb,key);
+ oldWidth= XkbKeyGroupsWidth(xkb,key);
+ for (width=i=0;i<nGroups;i++) {
+ if (groups&(1<<i))
+ newTypes[i]= newTypesIn[i];
+ else if (i<nOldGroups)
+ newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,i);
+ else if (nOldGroups>0)
+ newTypes[i]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
+ else newTypes[i]= XkbTwoLevelIndex;
+ if (newTypes[i]>xkb->map->num_types)
+ return BadMatch;
+ pNewType= &xkb->map->types[newTypes[i]];
+ if (pNewType->num_levels>width)
+ width= pNewType->num_levels;
+ }
+ if ((xkb->ctrls)&&(nGroups>xkb->ctrls->num_groups))
+ xkb->ctrls->num_groups= nGroups;
+ if ((width!=oldWidth)||(nGroups!=nOldGroups)) {
+ KeySym oldSyms[XkbMaxSymsPerKey],*pSyms;
+ int nCopy;
+
+ if (nOldGroups==0) {
+ pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
+ if (pSyms!=NULL) {
+ i= xkb->map->key_sym_map[key].group_info;
+ i= XkbSetNumGroups(i,nGroups);
+ xkb->map->key_sym_map[key].group_info= i;
+ xkb->map->key_sym_map[key].width= width;
+ for (i=0;i<nGroups;i++) {
+ xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
+ }
+ return Success;
+ }
+ return BadAlloc;
+ }
+ pSyms= XkbKeySymsPtr(xkb,key);
+ memcpy(oldSyms,pSyms,XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
+ pSyms= XkbResizeKeySyms(xkb,key,width*nGroups);
+ if (pSyms==NULL)
+ return BadAlloc;
+ memset(pSyms, 0, width*nGroups*sizeof(KeySym));
+ for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
+ pOldType= XkbKeyKeyType(xkb,key,i);
+ pNewType= &xkb->map->types[newTypes[i]];
+ if (pNewType->num_levels>pOldType->num_levels)
+ nCopy= pOldType->num_levels;
+ else nCopy= pNewType->num_levels;
+ memcpy(&pSyms[i*width],&oldSyms[i*oldWidth],nCopy*sizeof(KeySym));
+ }
+ if (XkbKeyHasActions(xkb,key)) {
+ XkbAction oldActs[XkbMaxSymsPerKey],*pActs;
+ pActs= XkbKeyActionsPtr(xkb,key);
+ memcpy(oldActs,pActs,XkbKeyNumSyms(xkb,key)*sizeof(XkbAction));
+ pActs= XkbResizeKeyActions(xkb,key,width*nGroups);
+ if (pActs==NULL)
+ return BadAlloc;
+ memset(pActs, 0, width*nGroups*sizeof(XkbAction));
+ for (i=0;(i<nGroups)&&(i<nOldGroups);i++) {
+ pOldType= XkbKeyKeyType(xkb,key,i);
+ pNewType= &xkb->map->types[newTypes[i]];
+ if (pNewType->num_levels>pOldType->num_levels)
+ nCopy= pOldType->num_levels;
+ else nCopy= pNewType->num_levels;
+ memcpy(&pActs[i*width],&oldActs[i*oldWidth],
+ nCopy*sizeof(XkbAction));
+ }
+ }
+ i= xkb->map->key_sym_map[key].group_info;
+ i= XkbSetNumGroups(i,nGroups);
+ xkb->map->key_sym_map[key].group_info= i;
+ xkb->map->key_sym_map[key].width= width;
+ }
+ width= 0;
+ for (i=0;i<nGroups;i++) {
+ xkb->map->key_sym_map[key].kt_index[i]= newTypes[i];
+ if (xkb->map->types[newTypes[i]].num_levels>width)
+ width= xkb->map->types[newTypes[i]].num_levels;
+ }
+ xkb->map->key_sym_map[key].width= width;
+ if (changes!=NULL) {
+ if (changes->changed&XkbKeySymsMask) {
+ _XkbAddKeyChange(&changes->first_key_sym,&changes->num_key_syms,
+ key);
+ }
+ else {
+ changes->changed|= XkbKeySymsMask;
+ changes->first_key_sym= key;
+ changes->num_key_syms= 1;
+ }
+ }
+ return Success;
+}
+
+/***====================================================================***/
+
+Bool
+XkbVirtualModsToReal(XkbDescPtr xkb,unsigned virtual_mask,unsigned *mask_rtrn)
+{
+register int i,bit;
+register unsigned mask;
+
+ if (xkb==NULL)
+ return FALSE;
+ if (virtual_mask==0) {
+ *mask_rtrn= 0;
+ return TRUE;
+ }
+ if (xkb->server==NULL)
+ return FALSE;
+ for (i=mask=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+ if (virtual_mask&bit)
+ mask|= xkb->server->vmods[i];
+ }
+ *mask_rtrn= mask;
+ return TRUE;
+}
+
+/***====================================================================***/
+
+static Bool
+XkbUpdateActionVirtualMods(XkbDescPtr xkb,XkbAction *act,unsigned changed)
+{
+unsigned int tmp;
+
+ switch (act->type) {
+ case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
+ if (((tmp= XkbModActionVMods(&act->mods))&changed)!=0) {
+ XkbVirtualModsToReal(xkb,tmp,&tmp);
+ act->mods.mask= act->mods.real_mods;
+ act->mods.mask|= tmp;
+ return TRUE;
+ }
+ break;
+ case XkbSA_ISOLock:
+ if ((((tmp= XkbModActionVMods(&act->iso))!=0)&changed)!=0) {
+ XkbVirtualModsToReal(xkb,tmp,&tmp);
+ act->iso.mask= act->iso.real_mods;
+ act->iso.mask|= tmp;
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static void
+XkbUpdateKeyTypeVirtualMods( XkbDescPtr xkb,
+ XkbKeyTypePtr type,
+ unsigned int changed,
+ XkbChangesPtr changes)
+{
+register unsigned int i;
+unsigned int mask;
+
+ XkbVirtualModsToReal(xkb,type->mods.vmods,&mask);
+ type->mods.mask= type->mods.real_mods|mask;
+ if ((type->map_count>0)&&(type->mods.vmods!=0)) {
+ XkbKTMapEntryPtr entry;
+ for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
+ if (entry->mods.vmods!=0) {
+ XkbVirtualModsToReal(xkb,entry->mods.vmods,&mask);
+ entry->mods.mask=entry->mods.real_mods|mask;
+ /* entry is active if vmods are bound*/
+ entry->active= (mask!=0);
+ }
+ else entry->active= 1;
+ }
+ }
+ if (changes) {
+ int type_ndx;
+ type_ndx= type-xkb->map->types;
+ if ((type_ndx<0)||(type_ndx>xkb->map->num_types))
+ return;
+ if (changes->map.changed&XkbKeyTypesMask) {
+ int last;
+ last= changes->map.first_type+changes->map.num_types-1;
+ if (type_ndx<changes->map.first_type) {
+ changes->map.first_type= type_ndx;
+ changes->map.num_types= (last-type_ndx)+1;
+ }
+ else if (type_ndx>last) {
+ changes->map.num_types= (type_ndx-changes->map.first_type)+1;
+ }
+ }
+ else {
+ changes->map.changed|= XkbKeyTypesMask;
+ changes->map.first_type= type_ndx;
+ changes->map.num_types= 1;
+ }
+ }
+ return;
+}
+
+Bool
+XkbApplyVirtualModChanges(XkbDescPtr xkb,unsigned changed,XkbChangesPtr changes)
+{
+register int i;
+unsigned int checkState = 0;
+
+ if ((!xkb) || (!xkb->map) || (changed==0))
+ return FALSE;
+ for (i=0;i<xkb->map->num_types;i++) {
+ if (xkb->map->types[i].mods.vmods & changed)
+ XkbUpdateKeyTypeVirtualMods(xkb,&xkb->map->types[i],changed,changes);
+ }
+ if (changed&xkb->ctrls->internal.vmods) {
+ unsigned int newMask;
+ XkbVirtualModsToReal(xkb,xkb->ctrls->internal.vmods,&newMask);
+ newMask|= xkb->ctrls->internal.real_mods;
+ if (xkb->ctrls->internal.mask!=newMask) {
+ xkb->ctrls->internal.mask= newMask;
+ if (changes) {
+ changes->ctrls.changed_ctrls|= XkbInternalModsMask;
+ checkState= TRUE;
+ }
+ }
+ }
+ if (changed&xkb->ctrls->ignore_lock.vmods) {
+ unsigned int newMask;
+ XkbVirtualModsToReal(xkb,xkb->ctrls->ignore_lock.vmods,&newMask);
+ newMask|= xkb->ctrls->ignore_lock.real_mods;
+ if (xkb->ctrls->ignore_lock.mask!=newMask) {
+ xkb->ctrls->ignore_lock.mask= newMask;
+ if (changes) {
+ changes->ctrls.changed_ctrls|= XkbIgnoreLockModsMask;
+ checkState= TRUE;
+ }
+ }
+ }
+ if (xkb->indicators!=NULL) {
+ XkbIndicatorMapPtr map;
+ map= &xkb->indicators->maps[0];
+ for (i=0;i<XkbNumIndicators;i++,map++) {
+ if (map->mods.vmods&changed) {
+ unsigned int newMask;
+ XkbVirtualModsToReal(xkb,map->mods.vmods,&newMask);
+ newMask|= map->mods.real_mods;
+ if (newMask!=map->mods.mask) {
+ map->mods.mask= newMask;
+ if (changes) {
+ changes->indicators.map_changes|= (1<<i);
+ checkState= TRUE;
+ }
+ }
+ }
+ }
+ }
+ if (xkb->compat!=NULL) {
+ XkbCompatMapPtr compat;
+ compat= xkb->compat;
+ for (i=0;i<XkbNumKbdGroups;i++) {
+ unsigned int newMask;
+ XkbVirtualModsToReal(xkb,compat->groups[i].vmods,&newMask);
+ newMask|= compat->groups[i].real_mods;
+ if (compat->groups[i].mask!=newMask) {
+ compat->groups[i].mask= newMask;
+ if (changes) {
+ changes->compat.changed_groups|= (1<<i);
+ checkState= TRUE;
+ }
+ }
+ }
+ }
+ if (xkb->map && xkb->server) {
+ int highChange = 0, lowChange = -1;
+ for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
+ if (XkbKeyHasActions(xkb,i)) {
+ register XkbAction *pAct;
+ register int n;
+
+ pAct= XkbKeyActionsPtr(xkb,i);
+ for (n=XkbKeyNumActions(xkb,i);n>0;n--,pAct++) {
+ if ((pAct->type!=XkbSA_NoAction)&&
+ XkbUpdateActionVirtualMods(xkb,pAct,changed)) {
+ if (lowChange<0)
+ lowChange= i;
+ highChange= i;
+ }
+ }
+ }
+ }
+ if (changes && (lowChange>0)) { /* something changed */
+ if (changes->map.changed&XkbKeyActionsMask) {
+ int last;
+ if (changes->map.first_key_act<lowChange)
+ lowChange= changes->map.first_key_act;
+ last= changes->map.first_key_act+changes->map.num_key_acts-1;
+ if (last>highChange)
+ highChange= last;
+ }
+ changes->map.changed|= XkbKeyActionsMask;
+ changes->map.first_key_act= lowChange;
+ changes->map.num_key_acts= (highChange-lowChange)+1;
+ }
+ }
+ return checkState;
+}
diff --git a/xorg-server/xkb/xkbUtils.c b/xorg-server/xkb/xkbUtils.c
index 9db94773f..3a56bea4c 100644
--- a/xorg-server/xkb/xkbUtils.c
+++ b/xorg-server/xkb/xkbUtils.c
@@ -1,2122 +1,2125 @@
-/************************************************************
-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.
-
-********************************************************/
-/*
-
-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.
-
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "os.h"
-#include <stdio.h>
-#include <ctype.h>
-#include <math.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#define XK_CYRILLIC
-#include <X11/keysym.h>
-#include "misc.h"
-#include "inputstr.h"
-#include "eventstr.h"
-
-#define XKBSRV_NEED_FILE_FUNCS
-#include <xkbsrv.h>
-#include "xkbgeom.h"
-#include "xkb.h"
-
-/***====================================================================***/
-
-int
-_XkbLookupAnyDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
- Mask access_mode, int *xkb_err)
-{
- int rc = XkbKeyboardErrorCode;
-
- if (id == XkbUseCoreKbd)
- id = PickKeyboard(client)->id;
- else if (id == XkbUseCorePtr)
- id = PickPointer(client)->id;
-
- rc = dixLookupDevice(pDev, id, client, access_mode);
- if (rc != Success)
- *xkb_err = XkbErr_BadDevice;
-
- return rc;
-}
-
-int
-_XkbLookupKeyboard(DeviceIntPtr *pDev, int id, ClientPtr client,
- Mask access_mode, int *xkb_err)
-{
- DeviceIntPtr dev;
- int rc;
-
- if (id == XkbDfltXIId)
- id = XkbUseCoreKbd;
-
- rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
- if (rc != Success)
- return rc;
-
- dev = *pDev;
- if (!dev->key || !dev->key->xkbInfo) {
- *pDev = NULL;
- *xkb_err= XkbErr_BadClass;
- return XkbKeyboardErrorCode;
- }
- return Success;
-}
-
-int
-_XkbLookupBellDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
- Mask access_mode, int *xkb_err)
-{
- DeviceIntPtr dev;
- int rc;
-
- rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
- if (rc != Success)
- return rc;
-
- dev = *pDev;
- if (!dev->kbdfeed && !dev->bell) {
- *pDev = NULL;
- *xkb_err= XkbErr_BadClass;
- return XkbKeyboardErrorCode;
- }
- return Success;
-}
-
-int
-_XkbLookupLedDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
- Mask access_mode, int *xkb_err)
-{
- DeviceIntPtr dev;
- int rc;
-
- if (id == XkbDfltXIId)
- id = XkbUseCorePtr;
-
- rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
- if (rc != Success)
- return rc;
-
- dev = *pDev;
- if (!dev->kbdfeed && !dev->leds) {
- *pDev = NULL;
- *xkb_err= XkbErr_BadClass;
- return XkbKeyboardErrorCode;
- }
- return Success;
-}
-
-int
-_XkbLookupButtonDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
- Mask access_mode, int *xkb_err)
-{
- DeviceIntPtr dev;
- int rc;
-
- rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
- if (rc != Success)
- return rc;
-
- dev = *pDev;
- if (!dev->button) {
- *pDev = NULL;
- *xkb_err= XkbErr_BadClass;
- return XkbKeyboardErrorCode;
- }
- return Success;
-}
-
-void
-XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods)
-{
-register unsigned tmp;
-
- switch (act->type) {
- case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
- if (act->mods.flags&XkbSA_UseModMapMods)
- act->mods.real_mods= act->mods.mask= mods;
- if ((tmp= XkbModActionVMods(&act->mods))!=0)
- act->mods.mask|= XkbMaskForVMask(xkb,tmp);
- break;
- case XkbSA_ISOLock:
- if (act->iso.flags&XkbSA_UseModMapMods)
- act->iso.real_mods= act->iso.mask= mods;
- if ((tmp= XkbModActionVMods(&act->iso))!=0)
- act->iso.mask|= XkbMaskForVMask(xkb,tmp);
- break;
- }
- return;
-}
-
-unsigned
-XkbMaskForVMask(XkbDescPtr xkb,unsigned vmask)
-{
-register int i,bit;
-register unsigned mask;
-
- for (mask=i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (vmask&bit)
- mask|= xkb->server->vmods[i];
- }
- return mask;
-}
-
-/***====================================================================***/
-
-void
-XkbUpdateKeyTypesFromCore( DeviceIntPtr pXDev,
- KeySymsPtr pCore,
- KeyCode first,
- CARD8 num,
- XkbChangesPtr changes)
-{
-XkbDescPtr xkb;
-unsigned key,nG,explicit;
-int types[XkbNumKbdGroups];
-KeySym tsyms[XkbMaxSymsPerKey],*syms;
-XkbMapChangesPtr mc;
-
- xkb= pXDev->key->xkbInfo->desc;
- if (first+num-1>xkb->max_key_code) {
- /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */
- num= xkb->max_key_code-first+1;
- }
-
- mc= (changes?(&changes->map):NULL);
-
- syms= &pCore->map[(first - pCore->minKeyCode) * pCore->mapWidth];
- for (key=first; key<(first+num); key++,syms+= pCore->mapWidth) {
- explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask;
- types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
- types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index);
- types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index);
- types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index);
- nG= XkbKeyTypesForCoreSymbols(xkb,pCore->mapWidth,syms,explicit,types,
- tsyms);
- XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc);
- memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms,
- XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
- }
- if (changes->map.changed&XkbKeySymsMask) {
- CARD8 oldLast,newLast;
- oldLast = changes->map.first_key_sym+changes->map.num_key_syms-1;
- newLast = first+num-1;
-
- if (first<changes->map.first_key_sym)
- changes->map.first_key_sym = first;
- if (oldLast>newLast)
- newLast= oldLast;
- changes->map.num_key_syms = newLast-changes->map.first_key_sym+1;
- }
- else {
- changes->map.changed|= XkbKeySymsMask;
- changes->map.first_key_sym = first;
- changes->map.num_key_syms = num;
- }
- return;
-}
-
-void
-XkbUpdateDescActions( XkbDescPtr xkb,
- KeyCode first,
- CARD8 num,
- XkbChangesPtr changes)
-{
-register unsigned key;
-
- for (key=first;key<(first+num);key++) {
- XkbApplyCompatMapToKey(xkb,key,changes);
- }
-
- if (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask)) {
- unsigned char newVMods[XkbNumVirtualMods];
- register unsigned bit,i;
- unsigned present;
-
- memset(newVMods, 0, XkbNumVirtualMods);
- present= 0;
- for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
- if (xkb->server->vmodmap[key]==0)
- continue;
- for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if (bit&xkb->server->vmodmap[key]) {
- present|= bit;
- newVMods[i]|= xkb->map->modmap[key];
- }
- }
- }
- for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
- if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) {
- changes->map.changed|= XkbVirtualModsMask;
- changes->map.vmods|= bit;
- xkb->server->vmods[i]= newVMods[i];
- }
- }
- }
- if (changes->map.changed&XkbVirtualModsMask)
- XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes);
-
- if (changes->map.changed&XkbKeyActionsMask) {
- CARD8 oldLast,newLast;
- oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
- newLast = first+num-1;
-
- if (first<changes->map.first_key_act)
- changes->map.first_key_act = first;
- if (newLast>oldLast)
- newLast= oldLast;
- changes->map.num_key_acts= newLast-changes->map.first_key_act+1;
- }
- else {
- changes->map.changed|= XkbKeyActionsMask;
- changes->map.first_key_act = first;
- changes->map.num_key_acts = num;
- }
- return;
-}
-
-void
-XkbUpdateActions( DeviceIntPtr pXDev,
- KeyCode first,
- CARD8 num,
- XkbChangesPtr changes,
- unsigned * needChecksRtrn,
- XkbEventCausePtr cause)
-{
-XkbSrvInfoPtr xkbi;
-XkbDescPtr xkb;
-CARD8 * repeat;
-
- if (needChecksRtrn)
- *needChecksRtrn= 0;
- xkbi= pXDev->key->xkbInfo;
- xkb= xkbi->desc;
- repeat= xkb->ctrls->per_key_repeat;
-
- if (pXDev->kbdfeed)
- memcpy(repeat,pXDev->kbdfeed->ctrl.autoRepeats,XkbPerKeyBitArraySize);
-
- XkbUpdateDescActions(xkb,first,num,changes);
-
- if ((pXDev->kbdfeed)&&
- (changes->ctrls.enabled_ctrls_changes&XkbPerKeyRepeatMask)) {
- memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, XkbPerKeyBitArraySize);
- (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl);
- }
- return;
-}
-
-KeySymsPtr
-XkbGetCoreMap(DeviceIntPtr keybd)
-{
-register int key,tmp;
-int maxSymsPerKey, maxGroup1Width;
-XkbDescPtr xkb;
-KeySymsPtr syms;
-int maxNumberOfGroups;
-
- if (!keybd || !keybd->key || !keybd->key->xkbInfo)
- return NULL;
-
- xkb= keybd->key->xkbInfo->desc;
- maxSymsPerKey= maxGroup1Width= 0;
- maxNumberOfGroups = 0;
-
- /* determine sizes */
- for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
- if (XkbKeycodeInRange(xkb,key)) {
- int nGroups;
- int w;
- nGroups= XkbKeyNumGroups(xkb,key);
- tmp= 0;
- if (nGroups>0) {
- if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup1Index))<=2)
- tmp+= 2;
- else tmp+= w + 2;
- /* remember highest G1 width */
- if (w > maxGroup1Width)
- maxGroup1Width = w;
- }
- if (nGroups>1) {
- if (tmp <= 2) {
- if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))<2)
- tmp+= 2;
- else tmp+= w;
- } else {
- if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))>2)
- tmp+= w - 2;
- }
- }
- if (nGroups>2)
- tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup3Index);
- if (nGroups>3)
- tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup4Index);
- if (tmp>maxSymsPerKey)
- maxSymsPerKey= tmp;
- if (nGroups > maxNumberOfGroups)
- maxNumberOfGroups = nGroups;
- }
- }
-
- if (maxSymsPerKey <= 0)
- return NULL;
-
- syms = calloc(1, sizeof(*syms));
- if (!syms)
- return NULL;
-
- /* See Section 12.4 of the XKB Protocol spec. Because of the
- * single-group distribution for multi-group keyboards, we have to
- * have enough symbols for the largest group 1 to replicate across the
- * number of groups on the keyboard. e.g. a single-group key with 4
- * symbols on a keyboard that has 3 groups -> 12 syms per key */
- if (maxSymsPerKey < maxNumberOfGroups * maxGroup1Width)
- maxSymsPerKey = maxNumberOfGroups * maxGroup1Width;
-
- syms->mapWidth = maxSymsPerKey;
- syms->minKeyCode = xkb->min_key_code;
- syms->maxKeyCode = xkb->max_key_code;
-
- tmp = syms->mapWidth * (xkb->max_key_code - xkb->min_key_code + 1);
- syms->map = calloc(tmp, sizeof(*syms->map));
- if (!syms->map) {
- free(syms);
- return NULL;
- }
-
- for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
- KeySym *pCore,*pXKB;
- unsigned nGroups,groupWidth,n,nOut;
-
- nGroups= XkbKeyNumGroups(xkb,key);
- n= (key-xkb->min_key_code)*syms->mapWidth;
- pCore= &syms->map[n];
- pXKB= XkbKeySymsPtr(xkb,key);
- nOut= 2;
- if (nGroups>0) {
- groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup1Index);
- if (groupWidth>0) pCore[0]= pXKB[0];
- if (groupWidth>1) pCore[1]= pXKB[1];
- for (n=2;n<groupWidth;n++)
- pCore[2+n]= pXKB[n];
- if (groupWidth>2)
- nOut= groupWidth;
- }
-
- /* See XKB Protocol Sec, Section 12.4.
- A 1-group key with ABCDE on a 2 group keyboard must be
- duplicated across all groups as ABABCDECDE.
- */
- if (nGroups == 1)
- {
- int idx, j;
-
- groupWidth = XkbKeyGroupWidth(xkb, key, XkbGroup1Index);
-
- /* AB..CDE... -> ABABCDE... */
- if (groupWidth > 0 && syms->mapWidth >= 3)
- pCore[2] = pCore[0];
- if (groupWidth > 1 && syms->mapWidth >= 4)
- pCore[3] = pCore[1];
-
- /* ABABCDE... -> ABABCDECDE */
- idx = 2 + groupWidth;
- while (groupWidth > 2 && idx < syms->mapWidth &&
- idx < groupWidth * 2)
- {
- pCore[idx] = pCore[idx - groupWidth + 2];
- idx++;
- }
- idx = 2 * groupWidth;
- if (idx < 4)
- idx = 4;
- /* 3 or more groups: ABABCDECDEABCDEABCDE */
- for (j = 3; j <= maxNumberOfGroups; j++)
- for (n = 0; n < groupWidth && idx < maxSymsPerKey; n++)
- pCore[idx++] = pXKB[n];
- }
-
- pXKB+= XkbKeyGroupsWidth(xkb,key);
- nOut+= 2;
- if (nGroups>1) {
- groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup2Index);
- if (groupWidth>0) pCore[2]= pXKB[0];
- if (groupWidth>1) pCore[3]= pXKB[1];
- for (n=2;n<groupWidth;n++) {
- pCore[nOut+(n-2)]= pXKB[n];
- }
- if (groupWidth>2)
- nOut+= (groupWidth-2);
- }
- pXKB+= XkbKeyGroupsWidth(xkb,key);
- for (n=XkbGroup3Index;n<nGroups;n++) {
- register int s;
- groupWidth= XkbKeyGroupWidth(xkb,key,n);
- for (s=0;s<groupWidth;s++) {
- pCore[nOut++]= pXKB[s];
- }
- pXKB+= XkbKeyGroupsWidth(xkb,key);
- }
- }
-
- return syms;
-}
-
-void
-XkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff)
-{
- if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
- xkbControlsNotify cn;
- XkbControlsPtr ctrls = pXDev->key->xkbInfo->desc->ctrls;
- XkbControlsRec old;
- old = *ctrls;
-
- if (key== -1) { /* global autorepeat setting changed */
- if (onoff) ctrls->enabled_ctrls |= XkbRepeatKeysMask;
- else ctrls->enabled_ctrls &= ~XkbRepeatKeysMask;
- }
- else if (pXDev->kbdfeed) {
- ctrls->per_key_repeat[key/8] =
- pXDev->kbdfeed->ctrl.autoRepeats[key/8];
- }
-
- if (XkbComputeControlsNotify(pXDev,&old,ctrls,&cn,TRUE))
- XkbSendControlsNotify(pXDev,&cn);
- }
- return;
-}
-
-/* Applies a change to a single device, does not traverse the device tree. */
-void
-XkbApplyMappingChange(DeviceIntPtr kbd, KeySymsPtr map, KeyCode first_key,
- CARD8 num_keys, CARD8 *modmap, ClientPtr client)
-{
- XkbDescPtr xkb = kbd->key->xkbInfo->desc;
- XkbEventCauseRec cause;
- XkbChangesRec changes;
- unsigned int check;
-
- memset(&changes, 0, sizeof(changes));
- memset(&cause, 0, sizeof(cause));
-
- if (map && first_key && num_keys) {
- check = 0;
- XkbSetCauseCoreReq(&cause, X_ChangeKeyboardMapping, client);
-
- XkbUpdateKeyTypesFromCore(kbd, map, first_key, num_keys, &changes);
- XkbUpdateActions(kbd, first_key, num_keys, &changes, &check, &cause);
-
- if (check)
- XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause);
- }
-
- if (modmap) {
- /* A keymap change can imply a modmap change, se we prefer the
- * former. */
- if (!cause.mjr)
- XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client);
-
- check = 0;
- num_keys = xkb->max_key_code - xkb->min_key_code + 1;
- changes.map.changed |= XkbModifierMapMask;
- changes.map.first_modmap_key = xkb->min_key_code;
- changes.map.num_modmap_keys = num_keys;
- memcpy(kbd->key->xkbInfo->desc->map->modmap, modmap, MAP_LENGTH);
- XkbUpdateActions(kbd, xkb->min_key_code, num_keys, &changes, &check,
- &cause);
-
- if (check)
- XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause);
- }
-
- XkbSendNotification(kbd, &changes, &cause);
-}
-
-void
-XkbDisableComputedAutoRepeats(DeviceIntPtr dev,unsigned key)
-{
-XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
-xkbMapNotify mn;
-
- xkbi->desc->server->explicit[key]|= XkbExplicitAutoRepeatMask;
- memset(&mn, 0, sizeof(mn));
- mn.changed= XkbExplicitComponentsMask;
- mn.firstKeyExplicit= key;
- mn.nKeyExplicit= 1;
- XkbSendMapNotify(dev,&mn);
- return;
-}
-
-unsigned
-XkbStateChangedFlags(XkbStatePtr old,XkbStatePtr new)
-{
-int changed;
-
- changed=(old->group!=new->group?XkbGroupStateMask:0);
- changed|=(old->base_group!=new->base_group?XkbGroupBaseMask:0);
- changed|=(old->latched_group!=new->latched_group?XkbGroupLatchMask:0);
- changed|=(old->locked_group!=new->locked_group?XkbGroupLockMask:0);
- changed|=(old->mods!=new->mods?XkbModifierStateMask:0);
- changed|=(old->base_mods!=new->base_mods?XkbModifierBaseMask:0);
- changed|=(old->latched_mods!=new->latched_mods?XkbModifierLatchMask:0);
- changed|=(old->locked_mods!=new->locked_mods?XkbModifierLockMask:0);
- changed|=(old->compat_state!=new->compat_state?XkbCompatStateMask:0);
- changed|=(old->grab_mods!=new->grab_mods?XkbGrabModsMask:0);
- if (old->compat_grab_mods!=new->compat_grab_mods)
- changed|= XkbCompatGrabModsMask;
- changed|=(old->lookup_mods!=new->lookup_mods?XkbLookupModsMask:0);
- if (old->compat_lookup_mods!=new->compat_lookup_mods)
- changed|= XkbCompatLookupModsMask;
- changed|=(old->ptr_buttons!=new->ptr_buttons?XkbPointerButtonMask:0);
- return changed;
-}
-
-static void
-XkbComputeCompatState(XkbSrvInfoPtr xkbi)
-{
-CARD16 grp_mask;
-XkbStatePtr state= &xkbi->state;
-XkbCompatMapPtr map;
-
- if (!state || !xkbi->desc || !xkbi->desc->ctrls || !xkbi->desc->compat)
- return;
-
- map= xkbi->desc->compat;
- grp_mask= map->groups[state->group].mask;
- state->compat_state = state->mods|grp_mask;
- state->compat_lookup_mods= state->lookup_mods|grp_mask;
-
- if (xkbi->desc->ctrls->enabled_ctrls&XkbIgnoreGroupLockMask)
- grp_mask= map->groups[state->base_group].mask;
- state->compat_grab_mods= state->grab_mods|grp_mask;
- return;
-}
-
-unsigned
-XkbAdjustGroup(int group,XkbControlsPtr ctrls)
-{
-unsigned act;
-
- act= XkbOutOfRangeGroupAction(ctrls->groups_wrap);
- if (group<0) {
- while ( group < 0 ) {
- if (act==XkbClampIntoRange) {
- group= XkbGroup1Index;
- }
- else if (act==XkbRedirectIntoRange) {
- int newGroup;
- newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap);
- if (newGroup>=ctrls->num_groups)
- group= XkbGroup1Index;
- else group= newGroup;
- }
- else {
- group+= ctrls->num_groups;
- }
- }
- }
- else if (group>=ctrls->num_groups) {
- if (act==XkbClampIntoRange) {
- group= ctrls->num_groups-1;
- }
- else if (act==XkbRedirectIntoRange) {
- int newGroup;
- newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap);
- if (newGroup>=ctrls->num_groups)
- group= XkbGroup1Index;
- else group= newGroup;
- }
- else {
- group%= ctrls->num_groups;
- }
- }
- return group;
-}
-
-void
-XkbComputeDerivedState(XkbSrvInfoPtr xkbi)
-{
-XkbStatePtr state= &xkbi->state;
-XkbControlsPtr ctrls= xkbi->desc->ctrls;
-unsigned char grp;
-
- if (!state || !ctrls)
- return;
-
- state->mods= (state->base_mods|state->latched_mods|state->locked_mods);
- state->lookup_mods= state->mods&(~ctrls->internal.mask);
- state->grab_mods= state->lookup_mods&(~ctrls->ignore_lock.mask);
- state->grab_mods|=
- ((state->base_mods|state->latched_mods)&ctrls->ignore_lock.mask);
-
-
- grp= state->locked_group;
- if (grp>=ctrls->num_groups)
- state->locked_group= XkbAdjustGroup(XkbCharToInt(grp),ctrls);
-
- grp= state->locked_group+state->base_group+state->latched_group;
- if (grp>=ctrls->num_groups)
- state->group= XkbAdjustGroup(XkbCharToInt(grp),ctrls);
- else state->group= grp;
- XkbComputeCompatState(xkbi);
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbCheckSecondaryEffects( XkbSrvInfoPtr xkbi,
- unsigned which,
- XkbChangesPtr changes,
- XkbEventCausePtr cause)
-{
- if (which&XkbStateNotifyMask) {
- XkbStateRec old;
- old= xkbi->state;
- changes->state_changes|= XkbStateChangedFlags(&old,&xkbi->state);
- XkbComputeDerivedState(xkbi);
- }
- if (which&XkbIndicatorStateNotifyMask)
- XkbUpdateIndicators(xkbi->device,XkbAllIndicatorsMask,TRUE,changes,
- cause);
- return;
-}
-
-/***====================================================================***/
-
-Bool
-XkbEnableDisableControls( XkbSrvInfoPtr xkbi,
- unsigned long change,
- unsigned long newValues,
- XkbChangesPtr changes,
- XkbEventCausePtr cause)
-{
-XkbControlsPtr ctrls;
-unsigned old;
-XkbSrvLedInfoPtr sli;
-
- ctrls= xkbi->desc->ctrls;
- old= ctrls->enabled_ctrls;
- ctrls->enabled_ctrls&= ~change;
- ctrls->enabled_ctrls|= (change&newValues);
- if (old==ctrls->enabled_ctrls)
- return FALSE;
- if (cause!=NULL) {
- xkbControlsNotify cn;
- cn.numGroups= ctrls->num_groups;
- cn.changedControls= XkbControlsEnabledMask;
- cn.enabledControls= ctrls->enabled_ctrls;
- cn.enabledControlChanges= (ctrls->enabled_ctrls^old);
- cn.keycode= cause->kc;
- cn.eventType= cause->event;
- cn.requestMajor= cause->mjr;
- cn.requestMinor= cause->mnr;
- XkbSendControlsNotify(xkbi->device,&cn);
- }
- else {
- /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes*/
- /* is non-zero, the controls in question changed already in "this" */
- /* request and this change merely undoes the previous one. By the */
- /* same token, we have to figure out whether or not ControlsEnabled */
- /* should be set or not in the changes structure */
- changes->ctrls.enabled_ctrls_changes^= (ctrls->enabled_ctrls^old);
- if (changes->ctrls.enabled_ctrls_changes)
- changes->ctrls.changed_ctrls|= XkbControlsEnabledMask;
- else changes->ctrls.changed_ctrls&= ~XkbControlsEnabledMask;
- }
- sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(xkbi->device,sli->usesControls,TRUE,changes,cause);
- return TRUE;
-}
-
-/***====================================================================***/
-
-#define MAX_TOC 16
-
-XkbGeometryPtr
-XkbLookupNamedGeometry(DeviceIntPtr dev,Atom name,Bool *shouldFree)
-{
-XkbSrvInfoPtr xkbi= dev->key->xkbInfo;
-XkbDescPtr xkb= xkbi->desc;
-
- *shouldFree= 0;
- if (name==None) {
- if (xkb->geom!=NULL)
- return xkb->geom;
- name= xkb->names->geometry;
- }
- if ((xkb->geom!=NULL)&&(xkb->geom->name==name))
- return xkb->geom;
- *shouldFree= 1;
- return NULL;
-}
-
-void
-XkbConvertCase(register KeySym sym, KeySym *lower, KeySym *upper)
-{
- *lower = sym;
- *upper = sym;
- switch(sym >> 8) {
- case 0: /* Latin 1 */
- if ((sym >= XK_A) && (sym <= XK_Z))
- *lower += (XK_a - XK_A);
- else if ((sym >= XK_a) && (sym <= XK_z))
- *upper -= (XK_a - XK_A);
- else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
- *lower += (XK_agrave - XK_Agrave);
- else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
- *upper -= (XK_agrave - XK_Agrave);
- else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
- *lower += (XK_oslash - XK_Ooblique);
- else if ((sym >= XK_oslash) && (sym <= XK_thorn))
- *upper -= (XK_oslash - XK_Ooblique);
- break;
- case 1: /* Latin 2 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym == XK_Aogonek)
- *lower = XK_aogonek;
- else if (sym >= XK_Lstroke && sym <= XK_Sacute)
- *lower += (XK_lstroke - XK_Lstroke);
- else if (sym >= XK_Scaron && sym <= XK_Zacute)
- *lower += (XK_scaron - XK_Scaron);
- else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
- *lower += (XK_zcaron - XK_Zcaron);
- else if (sym == XK_aogonek)
- *upper = XK_Aogonek;
- else if (sym >= XK_lstroke && sym <= XK_sacute)
- *upper -= (XK_lstroke - XK_Lstroke);
- else if (sym >= XK_scaron && sym <= XK_zacute)
- *upper -= (XK_scaron - XK_Scaron);
- else if (sym >= XK_zcaron && sym <= XK_zabovedot)
- *upper -= (XK_zcaron - XK_Zcaron);
- else if (sym >= XK_Racute && sym <= XK_Tcedilla)
- *lower += (XK_racute - XK_Racute);
- else if (sym >= XK_racute && sym <= XK_tcedilla)
- *upper -= (XK_racute - XK_Racute);
- break;
- case 2: /* Latin 3 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
- *lower += (XK_hstroke - XK_Hstroke);
- else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
- *lower += (XK_gbreve - XK_Gbreve);
- else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
- *upper -= (XK_hstroke - XK_Hstroke);
- else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
- *upper -= (XK_gbreve - XK_Gbreve);
- else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
- *lower += (XK_cabovedot - XK_Cabovedot);
- else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
- *upper -= (XK_cabovedot - XK_Cabovedot);
- break;
- case 3: /* Latin 4 */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym >= XK_Rcedilla && sym <= XK_Tslash)
- *lower += (XK_rcedilla - XK_Rcedilla);
- else if (sym >= XK_rcedilla && sym <= XK_tslash)
- *upper -= (XK_rcedilla - XK_Rcedilla);
- else if (sym == XK_ENG)
- *lower = XK_eng;
- else if (sym == XK_eng)
- *upper = XK_ENG;
- else if (sym >= XK_Amacron && sym <= XK_Umacron)
- *lower += (XK_amacron - XK_Amacron);
- else if (sym >= XK_amacron && sym <= XK_umacron)
- *upper -= (XK_amacron - XK_Amacron);
- break;
- case 6: /* Cyrillic */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
- *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
- else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
- *upper += (XK_Serbian_DJE - XK_Serbian_dje);
- else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
- *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
- else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
- *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
- break;
- case 7: /* Greek */
- /* Assume the KeySym is a legal value (ignore discontinuities) */
- if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
- *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
- else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
- sym != XK_Greek_iotaaccentdieresis &&
- sym != XK_Greek_upsilonaccentdieresis)
- *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
- else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
- *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
- else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
- sym != XK_Greek_finalsmallsigma)
- *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
- break;
- }
-}
-
-static Bool
-_XkbCopyClientMap(XkbDescPtr src, XkbDescPtr dst)
-{
- void *tmp = NULL;
- int i;
- XkbKeyTypePtr stype = NULL, dtype = NULL;
-
- /* client map */
- if (src->map) {
- if (!dst->map) {
- tmp = calloc(1, sizeof(XkbClientMapRec));
- if (!tmp)
- return FALSE;
- dst->map = tmp;
- }
-
- if (src->map->syms) {
- if (src->map->size_syms != dst->map->size_syms) {
- tmp = realloc(dst->map->syms,
- src->map->size_syms * sizeof(KeySym));
- if (!tmp)
- return FALSE;
- dst->map->syms = tmp;
-
- }
- memcpy(dst->map->syms, src->map->syms,
- src->map->size_syms * sizeof(KeySym));
- }
- else {
- free(dst->map->syms);
- dst->map->syms = NULL;
- }
- dst->map->num_syms = src->map->num_syms;
- dst->map->size_syms = src->map->size_syms;
-
- if (src->map->key_sym_map) {
- if (src->max_key_code != dst->max_key_code) {
- tmp = realloc(dst->map->key_sym_map,
- (src->max_key_code + 1) * sizeof(XkbSymMapRec));
- if (!tmp)
- return FALSE;
- dst->map->key_sym_map = tmp;
- }
- memcpy(dst->map->key_sym_map, src->map->key_sym_map,
- (src->max_key_code + 1) * sizeof(XkbSymMapRec));
- }
- else {
- free(dst->map->key_sym_map);
- dst->map->key_sym_map = NULL;
- }
-
- if (src->map->types && src->map->num_types) {
- if (src->map->num_types > dst->map->size_types ||
- !dst->map->types || !dst->map->size_types) {
- if (dst->map->types && dst->map->size_types) {
- tmp = realloc(dst->map->types,
- src->map->num_types * sizeof(XkbKeyTypeRec));
- if (!tmp)
- return FALSE;
- dst->map->types = tmp;
- memset(dst->map->types + dst->map->num_types, 0,
- (src->map->num_types - dst->map->num_types) *
- sizeof(XkbKeyTypeRec));
- }
- else {
- tmp = calloc(src->map->num_types, sizeof(XkbKeyTypeRec));
- if (!tmp)
- return FALSE;
- dst->map->types = tmp;
- }
- }
- else if (src->map->num_types < dst->map->num_types &&
- dst->map->types) {
- for (i = src->map->num_types, dtype = (dst->map->types + i);
- i < dst->map->num_types; i++, dtype++) {
- free(dtype->level_names);
- dtype->level_names = NULL;
- dtype->num_levels = 0;
- if (dtype->map_count) {
- free(dtype->map);
- free(dtype->preserve);
- }
- }
- }
-
- stype = src->map->types;
- dtype = dst->map->types;
- for (i = 0; i < src->map->num_types; i++, dtype++, stype++) {
- if (stype->num_levels && stype->level_names) {
- if (stype->num_levels != dtype->num_levels &&
- dtype->num_levels && dtype->level_names &&
- i < dst->map->num_types) {
- tmp = realloc(dtype->level_names,
- stype->num_levels * sizeof(Atom));
- if (!tmp)
- continue;
- dtype->level_names = tmp;
- }
- else if (!dtype->num_levels || !dtype->level_names ||
- i >= dst->map->num_types) {
- tmp = malloc(stype->num_levels * sizeof(Atom));
- if (!tmp)
- continue;
- dtype->level_names = tmp;
- }
- dtype->num_levels = stype->num_levels;
- memcpy(dtype->level_names, stype->level_names,
- stype->num_levels * sizeof(Atom));
- }
- else {
- if (dtype->num_levels && dtype->level_names &&
- i < dst->map->num_types)
- free(dtype->level_names);
- dtype->num_levels = 0;
- dtype->level_names = NULL;
- }
-
- dtype->name = stype->name;
- memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec));
-
- if (stype->map_count) {
- if (stype->map) {
- if (stype->map_count != dtype->map_count &&
- dtype->map_count && dtype->map &&
- i < dst->map->num_types) {
- tmp = realloc(dtype->map,
- stype->map_count *
- sizeof(XkbKTMapEntryRec));
- if (!tmp)
- return FALSE;
- dtype->map = tmp;
- }
- else if (!dtype->map_count || !dtype->map ||
- i >= dst->map->num_types) {
- tmp = malloc(stype->map_count *
- sizeof(XkbKTMapEntryRec));
- if (!tmp)
- return FALSE;
- dtype->map = tmp;
- }
-
- memcpy(dtype->map, stype->map,
- stype->map_count * sizeof(XkbKTMapEntryRec));
- }
- else {
- if (dtype->map && i < dst->map->num_types)
- free(dtype->map);
- dtype->map = NULL;
- }
-
- if (stype->preserve) {
- if (stype->map_count != dtype->map_count &&
- dtype->map_count && dtype->preserve &&
- i < dst->map->num_types) {
- tmp = realloc(dtype->preserve,
- stype->map_count *
- sizeof(XkbModsRec));
- if (!tmp)
- return FALSE;
- dtype->preserve = tmp;
- }
- else if (!dtype->preserve || !dtype->map_count ||
- i >= dst->map->num_types) {
- tmp = malloc(stype->map_count *
- sizeof(XkbModsRec));
- if (!tmp)
- return FALSE;
- dtype->preserve = tmp;
- }
-
- memcpy(dtype->preserve, stype->preserve,
- stype->map_count * sizeof(XkbModsRec));
- }
- else {
- if (dtype->preserve && i < dst->map->num_types)
- free(dtype->preserve);
- dtype->preserve = NULL;
- }
-
- dtype->map_count = stype->map_count;
- }
- else {
- if (dtype->map_count && i < dst->map->num_types) {
- free(dtype->map);
- free(dtype->preserve);
- }
- dtype->map_count = 0;
- dtype->map = NULL;
- dtype->preserve = NULL;
- }
- }
-
- dst->map->size_types = src->map->num_types;
- dst->map->num_types = src->map->num_types;
- }
- else {
- if (dst->map->types) {
- for (i = 0, dtype = dst->map->types; i < dst->map->num_types;
- i++, dtype++) {
- free(dtype->level_names);
- if (dtype->map && dtype->map_count)
- free(dtype->map);
- if (dtype->preserve && dtype->map_count)
- free(dtype->preserve);
- }
- }
- free(dst->map->types);
- dst->map->types = NULL;
- dst->map->num_types = 0;
- dst->map->size_types = 0;
- }
-
- if (src->map->modmap) {
- if (src->max_key_code != dst->max_key_code) {
- tmp = realloc(dst->map->modmap, src->max_key_code + 1);
- if (!tmp)
- return FALSE;
- dst->map->modmap = tmp;
- }
- memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1);
- }
- else {
- free(dst->map->modmap);
- dst->map->modmap = NULL;
- }
- }
- else {
- if (dst->map)
- XkbFreeClientMap(dst, XkbAllClientInfoMask, TRUE);
- }
-
- return TRUE;
-}
-
-static Bool
-_XkbCopyServerMap(XkbDescPtr src, XkbDescPtr dst)
-{
- void *tmp = NULL;
-
- /* server map */
- if (src->server) {
- if (!dst->server) {
- tmp = calloc(1, sizeof(XkbServerMapRec));
- if (!tmp)
- return FALSE;
- dst->server = tmp;
- }
-
- if (src->server->explicit) {
- if (src->max_key_code != dst->max_key_code) {
- tmp = realloc(dst->server->explicit, src->max_key_code + 1);
- if (!tmp)
- return FALSE;
- dst->server->explicit = tmp;
- }
- memcpy(dst->server->explicit, src->server->explicit,
- src->max_key_code + 1);
- }
- else {
- free(dst->server->explicit);
- dst->server->explicit = NULL;
- }
-
- if (src->server->acts) {
- if (src->server->size_acts != dst->server->size_acts) {
- tmp = realloc(dst->server->acts,
- src->server->size_acts * sizeof(XkbAction));
- if (!tmp)
- return FALSE;
- dst->server->acts = tmp;
- }
- memcpy(dst->server->acts, src->server->acts,
- src->server->size_acts * sizeof(XkbAction));
- }
- else {
- free(dst->server->acts);
- dst->server->acts = NULL;
- }
- dst->server->size_acts = src->server->size_acts;
- dst->server->num_acts = src->server->num_acts;
-
- if (src->server->key_acts) {
- if (src->max_key_code != dst->max_key_code) {
- tmp = realloc(dst->server->key_acts,
- (src->max_key_code + 1) * sizeof(unsigned short));
- if (!tmp)
- return FALSE;
- dst->server->key_acts = tmp;
- }
- memcpy(dst->server->key_acts, src->server->key_acts,
- (src->max_key_code + 1) * sizeof(unsigned short));
- }
- else {
- free(dst->server->key_acts);
- dst->server->key_acts = NULL;
- }
-
- if (src->server->behaviors) {
- if (src->max_key_code != dst->max_key_code) {
- tmp = realloc(dst->server->behaviors,
- (src->max_key_code + 1) * sizeof(XkbBehavior));
- if (!tmp)
- return FALSE;
- dst->server->behaviors = tmp;
- }
- memcpy(dst->server->behaviors, src->server->behaviors,
- (src->max_key_code + 1) * sizeof(XkbBehavior));
- }
- else {
- free(dst->server->behaviors);
- dst->server->behaviors = NULL;
- }
-
- memcpy(dst->server->vmods, src->server->vmods, XkbNumVirtualMods);
-
- if (src->server->vmodmap) {
- if (src->max_key_code != dst->max_key_code) {
- tmp = realloc(dst->server->vmodmap,
- (src->max_key_code + 1) * sizeof(unsigned short));
- if (!tmp)
- return FALSE;
- dst->server->vmodmap = tmp;
- }
- memcpy(dst->server->vmodmap, src->server->vmodmap,
- (src->max_key_code + 1) * sizeof(unsigned short));
- }
- else {
- free(dst->server->vmodmap);
- dst->server->vmodmap = NULL;
- }
- }
- else {
- if (dst->server)
- XkbFreeServerMap(dst, XkbAllServerInfoMask, TRUE);
- }
-
- return TRUE;
-}
-
-static Bool
-_XkbCopyNames(XkbDescPtr src, XkbDescPtr dst)
-{
- void *tmp = NULL;
-
- /* names */
- if (src->names) {
- if (!dst->names) {
- dst->names = calloc(1, sizeof(XkbNamesRec));
- if (!dst->names)
- return FALSE;
- }
-
- if (src->names->keys) {
- if (src->max_key_code != dst->max_key_code) {
- tmp = realloc(dst->names->keys,
- (src->max_key_code + 1) * sizeof(XkbKeyNameRec));
- if (!tmp)
- return FALSE;
- dst->names->keys = tmp;
- }
- memcpy(dst->names->keys, src->names->keys,
- (src->max_key_code + 1) * sizeof(XkbKeyNameRec));
- }
- else {
- free(dst->names->keys);
- dst->names->keys = NULL;
- }
-
- if (src->names->num_key_aliases) {
- if (src->names->num_key_aliases != dst->names->num_key_aliases) {
- tmp = realloc(dst->names->key_aliases,
- src->names->num_key_aliases *
- sizeof(XkbKeyAliasRec));
- if (!tmp)
- return FALSE;
- dst->names->key_aliases = tmp;
- }
- memcpy(dst->names->key_aliases, src->names->key_aliases,
- src->names->num_key_aliases * sizeof(XkbKeyAliasRec));
- }
- else {
- free(dst->names->key_aliases);
- dst->names->key_aliases = NULL;
- }
- dst->names->num_key_aliases = src->names->num_key_aliases;
-
- if (src->names->num_rg) {
- if (src->names->num_rg != dst->names->num_rg) {
- tmp = realloc(dst->names->radio_groups,
- src->names->num_rg * sizeof(Atom));
- if (!tmp)
- return FALSE;
- dst->names->radio_groups = tmp;
- }
- memcpy(dst->names->radio_groups, src->names->radio_groups,
- src->names->num_rg * sizeof(Atom));
- }
- else {
- free(dst->names->radio_groups);
- }
- dst->names->num_rg = src->names->num_rg;
-
- dst->names->keycodes = src->names->keycodes;
- dst->names->geometry = src->names->geometry;
- dst->names->symbols = src->names->symbols;
- dst->names->types = src->names->types;
- dst->names->compat = src->names->compat;
- dst->names->phys_symbols = src->names->phys_symbols;
-
- memcpy(dst->names->vmods, src->names->vmods,
- XkbNumVirtualMods * sizeof(Atom));
- memcpy(dst->names->indicators, src->names->indicators,
- XkbNumIndicators * sizeof(Atom));
- memcpy(dst->names->groups, src->names->groups,
- XkbNumKbdGroups * sizeof(Atom));
- }
- else {
- if (dst->names)
- XkbFreeNames(dst, XkbAllNamesMask, TRUE);
- }
-
- return TRUE;
-}
-
-static Bool
-_XkbCopyCompat(XkbDescPtr src, XkbDescPtr dst)
-{
- void *tmp = NULL;
-
- /* compat */
- if (src->compat) {
- if (!dst->compat) {
- dst->compat = calloc(1, sizeof(XkbCompatMapRec));
- if (!dst->compat)
- return FALSE;
- }
-
- if (src->compat->sym_interpret && src->compat->num_si) {
- if (src->compat->num_si != dst->compat->size_si) {
- tmp = realloc(dst->compat->sym_interpret,
- src->compat->num_si * sizeof(XkbSymInterpretRec));
- if (!tmp)
- return FALSE;
- dst->compat->sym_interpret = tmp;
- }
- memcpy(dst->compat->sym_interpret, src->compat->sym_interpret,
- src->compat->num_si * sizeof(XkbSymInterpretRec));
-
- dst->compat->num_si = src->compat->num_si;
- dst->compat->size_si = src->compat->num_si;
- }
- else {
- if (dst->compat->sym_interpret && dst->compat->size_si)
- free(dst->compat->sym_interpret);
-
- dst->compat->sym_interpret = NULL;
- dst->compat->num_si = 0;
- dst->compat->size_si = 0;
- }
-
- memcpy(dst->compat->groups, src->compat->groups,
- XkbNumKbdGroups * sizeof(XkbModsRec));
- }
- else {
- if (dst->compat)
- XkbFreeCompatMap(dst, XkbAllCompatMask, TRUE);
- }
-
- return TRUE;
-}
-
-static Bool
-_XkbCopyGeom(XkbDescPtr src, XkbDescPtr dst)
-{
- void *tmp = NULL;
- int i = 0, j = 0, k = 0;
- XkbColorPtr scolor = NULL, dcolor = NULL;
- XkbDoodadPtr sdoodad = NULL, ddoodad = NULL;
- XkbOutlinePtr soutline = NULL, doutline = NULL;
- XkbPropertyPtr sprop = NULL, dprop = NULL;
- XkbRowPtr srow = NULL, drow = NULL;
- XkbSectionPtr ssection = NULL, dsection = NULL;
- XkbShapePtr sshape = NULL, dshape = NULL;
-
- /* geometry */
- if (src->geom) {
- if (!dst->geom) {
- dst->geom = calloc(sizeof(XkbGeometryRec), 1);
- if (!dst->geom)
- return FALSE;
- }
-
- /* properties */
- if (src->geom->num_properties) {
- if (src->geom->num_properties != dst->geom->sz_properties) {
- /* If we've got more properties in the destination than
- * the source, run through and free all the excess ones
- * first. */
- if (src->geom->num_properties < dst->geom->sz_properties) {
- for (i = src->geom->num_properties,
- dprop = dst->geom->properties + i;
- i < dst->geom->num_properties;
- i++, dprop++) {
- free(dprop->name);
- free(dprop->value);
- }
- }
-
- if (dst->geom->sz_properties)
- tmp = realloc(dst->geom->properties,
- src->geom->num_properties *
- sizeof(XkbPropertyRec));
- else
- tmp = malloc(src->geom->num_properties *
- sizeof(XkbPropertyRec));
- if (!tmp)
- return FALSE;
- dst->geom->properties = tmp;
- }
-
- /* We don't set num_properties as we need it to try and avoid
- * too much reallocing. */
- dst->geom->sz_properties = src->geom->num_properties;
-
- if (dst->geom->sz_properties > dst->geom->num_properties) {
- memset(dst->geom->properties + dst->geom->num_properties, 0,
- (dst->geom->sz_properties - dst->geom->num_properties) *
- sizeof(XkbPropertyRec));
- }
-
- for (i = 0,
- sprop = src->geom->properties,
- dprop = dst->geom->properties;
- i < src->geom->num_properties;
- i++, sprop++, dprop++) {
- if (i < dst->geom->num_properties) {
- if (strlen(sprop->name) != strlen(dprop->name)) {
- tmp = realloc(dprop->name, strlen(sprop->name) + 1);
- if (!tmp)
- return FALSE;
- dprop->name = tmp;
- }
- if (strlen(sprop->value) != strlen(dprop->value)) {
- tmp = realloc(dprop->value, strlen(sprop->value) + 1);
- if (!tmp)
- return FALSE;
- dprop->value = tmp;
- }
- strcpy(dprop->name, sprop->name);
- strcpy(dprop->value, sprop->value);
- }
- else {
- dprop->name = xstrdup(sprop->name);
- dprop->value = xstrdup(sprop->value);
- }
- }
-
- /* ... which is already src->geom->num_properties. */
- dst->geom->num_properties = dst->geom->sz_properties;
- }
- else {
- if (dst->geom->sz_properties) {
- for (i = 0, dprop = dst->geom->properties;
- i < dst->geom->num_properties;
- i++, dprop++) {
- free(dprop->name);
- free(dprop->value);
- }
- free(dst->geom->properties);
- dst->geom->properties = NULL;
- }
-
- dst->geom->num_properties = 0;
- dst->geom->sz_properties = 0;
- }
-
- /* colors */
- if (src->geom->num_colors) {
- if (src->geom->num_colors != dst->geom->sz_colors) {
- if (src->geom->num_colors < dst->geom->sz_colors) {
- for (i = src->geom->num_colors,
- dcolor = dst->geom->colors + i;
- i < dst->geom->num_colors;
- i++, dcolor++) {
- free(dcolor->spec);
- }
- }
-
- if (dst->geom->sz_colors)
- tmp = realloc(dst->geom->colors,
- src->geom->num_colors *
- sizeof(XkbColorRec));
- else
- tmp = malloc(src->geom->num_colors *
- sizeof(XkbColorRec));
- if (!tmp)
- return FALSE;
- dst->geom->colors = tmp;
- }
-
- dst->geom->sz_colors = src->geom->num_colors;
-
- if (dst->geom->sz_colors > dst->geom->num_colors) {
- memset(dst->geom->colors + dst->geom->num_colors, 0,
- (dst->geom->sz_colors - dst->geom->num_colors) *
- sizeof(XkbColorRec));
- }
-
- for (i = 0,
- scolor = src->geom->colors,
- dcolor = dst->geom->colors;
- i < src->geom->num_colors;
- i++, scolor++, dcolor++) {
- if (i < dst->geom->num_colors) {
- if (strlen(scolor->spec) != strlen(dcolor->spec)) {
- tmp = realloc(dcolor->spec, strlen(scolor->spec) + 1);
- if (!tmp)
- return FALSE;
- dcolor->spec = tmp;
- }
- strcpy(dcolor->spec, scolor->spec);
- }
- else {
- dcolor->spec = xstrdup(scolor->spec);
- }
- dcolor->pixel = scolor->pixel;
- }
-
- dst->geom->num_colors = dst->geom->sz_colors;
- }
- else {
- if (dst->geom->sz_colors) {
- for (i = 0, dcolor = dst->geom->colors;
- i < dst->geom->num_colors;
- i++, dcolor++) {
- free(dcolor->spec);
- }
- free(dst->geom->colors);
- dst->geom->colors = NULL;
- }
-
- dst->geom->num_colors = 0;
- dst->geom->sz_colors = 0;
- }
-
- /* shapes */
- /* shapes break down into outlines, which break down into points. */
- if (dst->geom->num_shapes) {
- for (i = 0, dshape = dst->geom->shapes;
- i < dst->geom->num_shapes;
- i++, dshape++) {
- for (j = 0, doutline = dshape->outlines;
- j < dshape->num_outlines;
- j++, doutline++) {
- if (doutline->sz_points)
- free(doutline->points);
- }
-
- if (dshape->sz_outlines) {
- free(dshape->outlines);
- dshape->outlines = NULL;
- }
-
- dshape->num_outlines = 0;
- dshape->sz_outlines = 0;
- }
- }
-
- if (src->geom->num_shapes) {
- tmp = calloc(src->geom->num_shapes, sizeof(XkbShapeRec));
- if (!tmp)
- return FALSE;
- dst->geom->shapes = tmp;
-
- for (i = 0, sshape = src->geom->shapes, dshape = dst->geom->shapes;
- i < src->geom->num_shapes;
- i++, sshape++, dshape++) {
- if (sshape->num_outlines) {
- tmp = calloc(sshape->num_outlines, sizeof(XkbOutlineRec));
- if (!tmp)
- return FALSE;
- dshape->outlines = tmp;
-
- for (j = 0,
- soutline = sshape->outlines,
- doutline = dshape->outlines;
- j < sshape->num_outlines;
- j++, soutline++, doutline++) {
- if (soutline->num_points) {
- tmp = malloc(soutline->num_points *
- sizeof(XkbPointRec));
- if (!tmp)
- return FALSE;
- doutline->points = tmp;
-
- memcpy(doutline->points, soutline->points,
- soutline->num_points * sizeof(XkbPointRec));
-
- doutline->corner_radius = soutline->corner_radius;
- }
-
- doutline->num_points = soutline->num_points;
- doutline->sz_points = soutline->num_points;
- }
- }
-
- dshape->num_outlines = sshape->num_outlines;
- dshape->sz_outlines = sshape->num_outlines;
- dshape->name = sshape->name;
- dshape->bounds = sshape->bounds;
-
- dshape->approx = NULL;
- if (sshape->approx && sshape->num_outlines > 0) {
-
- const ptrdiff_t approx_idx =
- sshape->approx - sshape->outlines;
-
- if (approx_idx < dshape->num_outlines) {
- dshape->approx = dshape->outlines + approx_idx;
- } else {
- LogMessage(X_WARNING, "XKB: approx outline "
- "index is out of range\n");
- }
- }
-
- dshape->primary = NULL;
- if (sshape->primary && sshape->num_outlines > 0) {
-
- const ptrdiff_t primary_idx =
- sshape->primary - sshape->outlines;
-
- if (primary_idx < dshape->num_outlines) {
- dshape->primary = dshape->outlines + primary_idx;
- } else {
- LogMessage(X_WARNING, "XKB: primary outline "
- "index is out of range\n");
- }
- }
- }
-
- dst->geom->num_shapes = src->geom->num_shapes;
- dst->geom->sz_shapes = src->geom->num_shapes;
- }
- else {
- if (dst->geom->sz_shapes) {
- free(dst->geom->shapes);
- }
- dst->geom->shapes = NULL;
- dst->geom->num_shapes = 0;
- dst->geom->sz_shapes = 0;
- }
-
- /* sections */
- /* sections break down into doodads, and also into rows, which break
- * down into keys. */
- if (dst->geom->num_sections) {
- for (i = 0, dsection = dst->geom->sections;
- i < dst->geom->num_sections;
- i++, dsection++) {
- for (j = 0, drow = dsection->rows;
- j < dsection->num_rows;
- j++, drow++) {
- if (drow->num_keys)
- free(drow->keys);
- }
-
- if (dsection->num_rows)
- free(dsection->rows);
-
- /* cut and waste from geom/doodad below. */
- for (j = 0, ddoodad = dsection->doodads;
- j < dsection->num_doodads;
- j++, ddoodad++) {
- if (ddoodad->any.type == XkbTextDoodad) {
- free(ddoodad->text.text);
- ddoodad->text.text = NULL;
- free(ddoodad->text.font);
- ddoodad->text.font = NULL;
- }
- else if (ddoodad->any.type == XkbLogoDoodad) {
- free(ddoodad->logo.logo_name);
- ddoodad->logo.logo_name = NULL;
- }
- }
-
- free(dsection->doodads);
- }
-
- dst->geom->num_sections = 0;
- dst->geom->sections = NULL;
- }
-
- if (src->geom->num_sections) {
- if (dst->geom->sz_sections)
- tmp = realloc(dst->geom->sections,
- src->geom->num_sections *
- sizeof(XkbSectionRec));
- else
- tmp = malloc(src->geom->num_sections * sizeof(XkbSectionRec));
- if (!tmp)
- return FALSE;
- memset(tmp, 0, src->geom->num_sections * sizeof(XkbSectionRec));
- dst->geom->sections = tmp;
- dst->geom->num_sections = src->geom->num_sections;
- dst->geom->sz_sections = src->geom->num_sections;
-
- for (i = 0,
- ssection = src->geom->sections,
- dsection = dst->geom->sections;
- i < src->geom->num_sections;
- i++, ssection++, dsection++) {
- *dsection = *ssection;
- if (ssection->num_rows) {
- tmp = calloc(ssection->num_rows, sizeof(XkbRowRec));
- if (!tmp)
- return FALSE;
- dsection->rows = tmp;
- }
- dsection->num_rows = ssection->num_rows;
- dsection->sz_rows = ssection->num_rows;
-
- for (j = 0, srow = ssection->rows, drow = dsection->rows;
- j < ssection->num_rows;
- j++, srow++, drow++) {
- if (srow->num_keys) {
- tmp = malloc(srow->num_keys * sizeof(XkbKeyRec));
- if (!tmp)
- return FALSE;
- drow->keys = tmp;
- memcpy(drow->keys, srow->keys,
- srow->num_keys * sizeof(XkbKeyRec));
- }
- drow->num_keys = srow->num_keys;
- drow->sz_keys = srow->num_keys;
- drow->top = srow->top;
- drow->left = srow->left;
- drow->vertical = srow->vertical;
- drow->bounds = srow->bounds;
- }
-
- if (ssection->num_doodads) {
- tmp = calloc(ssection->num_doodads, sizeof(XkbDoodadRec));
- if (!tmp)
- return FALSE;
- dsection->doodads = tmp;
- }
- else {
- dsection->doodads = NULL;
- }
-
- dsection->sz_doodads = ssection->num_doodads;
- for (k = 0,
- sdoodad = ssection->doodads,
- ddoodad = dsection->doodads;
- k < ssection->num_doodads;
- k++, sdoodad++, ddoodad++) {
- memcpy(ddoodad , sdoodad, sizeof(XkbDoodadRec));
- if (sdoodad->any.type == XkbTextDoodad) {
- if (sdoodad->text.text)
- ddoodad->text.text =
- strdup(sdoodad->text.text);
- if (sdoodad->text.font)
- ddoodad->text.font =
- strdup(sdoodad->text.font);
- }
- else if (sdoodad->any.type == XkbLogoDoodad) {
- if (sdoodad->logo.logo_name)
- ddoodad->logo.logo_name =
- strdup(sdoodad->logo.logo_name);
- }
- }
- dsection->overlays = NULL;
- dsection->sz_overlays = 0;
- dsection->num_overlays = 0;
- }
- }
- else {
- if (dst->geom->sz_sections) {
- free(dst->geom->sections);
- }
-
- dst->geom->sections = NULL;
- dst->geom->num_sections = 0;
- dst->geom->sz_sections = 0;
- }
-
- /* doodads */
- if (dst->geom->num_doodads) {
- for (i = src->geom->num_doodads,
- ddoodad = dst->geom->doodads +
- src->geom->num_doodads;
- i < dst->geom->num_doodads;
- i++, ddoodad++) {
- if (ddoodad->any.type == XkbTextDoodad) {
- free(ddoodad->text.text);
- ddoodad->text.text = NULL;
- free(ddoodad->text.font);
- ddoodad->text.font = NULL;
- }
- else if (ddoodad->any.type == XkbLogoDoodad) {
- free(ddoodad->logo.logo_name);
- ddoodad->logo.logo_name = NULL;
- }
- }
- dst->geom->num_doodads = 0;
- dst->geom->doodads = NULL;
- }
-
- if (src->geom->num_doodads) {
- if (dst->geom->sz_doodads)
- tmp = realloc(dst->geom->doodads,
- src->geom->num_doodads *
- sizeof(XkbDoodadRec));
- else
- tmp = malloc(src->geom->num_doodads *
- sizeof(XkbDoodadRec));
- if (!tmp)
- return FALSE;
- memset(tmp, 0, src->geom->num_doodads * sizeof(XkbDoodadRec));
- dst->geom->doodads = tmp;
-
- dst->geom->sz_doodads = src->geom->num_doodads;
-
- for (i = 0,
- sdoodad = src->geom->doodads,
- ddoodad = dst->geom->doodads;
- i < src->geom->num_doodads;
- i++, sdoodad++, ddoodad++) {
- memcpy(ddoodad , sdoodad, sizeof(XkbDoodadRec));
- if (sdoodad->any.type == XkbTextDoodad) {
- if (sdoodad->text.text)
- ddoodad->text.text = strdup(sdoodad->text.text);
- if (sdoodad->text.font)
- ddoodad->text.font = strdup(sdoodad->text.font);
- }
- else if (sdoodad->any.type == XkbLogoDoodad) {
- if (sdoodad->logo.logo_name)
- ddoodad->logo.logo_name =
- strdup(sdoodad->logo.logo_name);
- }
- }
-
- dst->geom->num_doodads = dst->geom->sz_doodads;
- }
- else {
- if (dst->geom->sz_doodads) {
- free(dst->geom->doodads);
- }
-
- dst->geom->doodads = NULL;
- dst->geom->num_doodads = 0;
- dst->geom->sz_doodads = 0;
- }
-
- /* key aliases */
- if (src->geom->num_key_aliases) {
- if (src->geom->num_key_aliases != dst->geom->sz_key_aliases) {
- if (dst->geom->sz_key_aliases)
- tmp = realloc(dst->geom->key_aliases,
- src->geom->num_key_aliases *
- 2 * XkbKeyNameLength);
- else
- tmp = malloc(src->geom->num_key_aliases *
- 2 * XkbKeyNameLength);
- if (!tmp)
- return FALSE;
- dst->geom->key_aliases = tmp;
-
- dst->geom->sz_key_aliases = src->geom->num_key_aliases;
- }
-
- memcpy(dst->geom->key_aliases, src->geom->key_aliases,
- src->geom->num_key_aliases * 2 * XkbKeyNameLength);
-
- dst->geom->num_key_aliases = dst->geom->sz_key_aliases;
- }
- else {
- free(dst->geom->key_aliases);
- dst->geom->key_aliases = NULL;
- dst->geom->num_key_aliases = 0;
- dst->geom->sz_key_aliases = 0;
- }
-
- /* font */
- if (src->geom->label_font) {
- if (!dst->geom->label_font) {
- tmp = malloc(strlen(src->geom->label_font) + 1);
- if (!tmp)
- return FALSE;
- dst->geom->label_font = tmp;
- }
- else if (strlen(src->geom->label_font) !=
- strlen(dst->geom->label_font)) {
- tmp = realloc(dst->geom->label_font,
- strlen(src->geom->label_font) + 1);
- if (!tmp)
- return FALSE;
- dst->geom->label_font = tmp;
- }
-
- strcpy(dst->geom->label_font, src->geom->label_font);
- i = XkbGeomColorIndex(src->geom, src->geom->label_color);
- dst->geom->label_color = &(dst->geom->colors[i]);
- i = XkbGeomColorIndex(src->geom, src->geom->base_color);
- dst->geom->base_color = &(dst->geom->colors[i]);
- }
- else {
- free(dst->geom->label_font);
- dst->geom->label_font = NULL;
- dst->geom->label_color = NULL;
- dst->geom->base_color = NULL;
- }
-
- dst->geom->name = src->geom->name;
- dst->geom->width_mm = src->geom->width_mm;
- dst->geom->height_mm = src->geom->height_mm;
- }
- else
- {
- if (dst->geom) {
- /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */
- XkbFreeGeometry(dst->geom, XkbGeomAllMask, TRUE);
- dst->geom = NULL;
- }
- }
-
- return TRUE;
-}
-
-static Bool
-_XkbCopyIndicators(XkbDescPtr src, XkbDescPtr dst)
-{
- /* indicators */
- if (src->indicators) {
- if (!dst->indicators) {
- dst->indicators = malloc(sizeof(XkbIndicatorRec));
- if (!dst->indicators)
- return FALSE;
- }
- memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec));
- }
- else {
- free(dst->indicators);
- dst->indicators = NULL;
- }
- return TRUE;
-}
-
-static Bool
-_XkbCopyControls(XkbDescPtr src, XkbDescPtr dst)
-{
- /* controls */
- if (src->ctrls) {
- if (!dst->ctrls) {
- dst->ctrls = malloc(sizeof(XkbControlsRec));
- if (!dst->ctrls)
- return FALSE;
- }
- memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec));
- }
- else {
- free(dst->ctrls);
- dst->ctrls = NULL;
- }
- return TRUE;
-}
-
-/**
- * Copy an XKB map from src to dst, reallocating when necessary: if some
- * map components are present in one, but not in the other, the destination
- * components will be allocated or freed as necessary.
- *
- * Basic map consistency is assumed on both sides, so maps with random
- * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19)
- * _will_ cause failures. You've been warned.
- *
- * Returns TRUE on success, or FALSE on failure. If this function fails,
- * dst may be in an inconsistent state: all its pointers are guaranteed
- * to remain valid, but part of the map may be from src and part from dst.
- *
- */
-
-Bool
-XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src)
-{
-
- if (!src || !dst) {
- DebugF("XkbCopyKeymap: src (%p) or dst (%p) is NULL\n", src, dst);
- return FALSE;
- }
-
- if (src == dst)
- return TRUE;
-
- if (!_XkbCopyClientMap(src, dst)) {
- DebugF("XkbCopyKeymap: failed to copy client map\n");
- return FALSE;
- }
- if (!_XkbCopyServerMap(src, dst)) {
- DebugF("XkbCopyKeymap: failed to copy server map\n");
- return FALSE;
- }
- if (!_XkbCopyIndicators(src, dst)) {
- DebugF("XkbCopyKeymap: failed to copy indicators\n");
- return FALSE;
- }
- if (!_XkbCopyControls(src, dst)) {
- DebugF("XkbCopyKeymap: failed to copy controls\n");
- return FALSE;
- }
- if (!_XkbCopyNames(src, dst)) {
- DebugF("XkbCopyKeymap: failed to copy names\n");
- return FALSE;
- }
- if (!_XkbCopyCompat(src, dst)) {
- DebugF("XkbCopyKeymap: failed to copy compat map\n");
- return FALSE;
- }
- if (!_XkbCopyGeom(src, dst)) {
- DebugF("XkbCopyKeymap: failed to copy geometry\n");
- return FALSE;
- }
-
- dst->min_key_code = src->min_key_code;
- dst->max_key_code = src->max_key_code;
-
- return TRUE;
-}
-
-Bool
-XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src)
-{
- xkbNewKeyboardNotify nkn;
- Bool ret;
-
- if (!dst->key || !src->key)
- return FALSE;
-
- memset(&nkn, 0, sizeof(xkbNewKeyboardNotify));
- nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code;
- nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code;
- nkn.deviceID = dst->id;
- nkn.oldDeviceID = dst->id; /* maybe src->id? */
- nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code;
- nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code;
- nkn.requestMajor = XkbReqCode;
- nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */
- nkn.changed = XkbNKN_KeycodesMask;
- if (src->key->xkbInfo->desc->geom)
- nkn.changed |= XkbNKN_GeometryMask;
-
- ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc);
- if (ret)
- XkbSendNewKeyboardNotify(dst, &nkn);
-
- return ret;
-}
-
-int
-XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode)
-{
- XkbDescPtr xkb = xkbi->desc;
- int effectiveGroup = xkbState->group;
-
- if (!XkbKeycodeInRange(xkb, keycode))
- return -1;
-
- if (effectiveGroup == XkbGroup1Index)
- return effectiveGroup;
-
- if (XkbKeyNumGroups(xkb,keycode) > 1U) {
- if (effectiveGroup >= XkbKeyNumGroups(xkb,keycode)) {
- unsigned int gi = XkbKeyGroupInfo(xkb,keycode);
- switch (XkbOutOfRangeGroupAction(gi)) {
- default:
- case XkbWrapIntoRange:
- effectiveGroup %= XkbKeyNumGroups(xkb, keycode);
- break;
- case XkbClampIntoRange:
- effectiveGroup = XkbKeyNumGroups(xkb, keycode) - 1;
- break;
- case XkbRedirectIntoRange:
- effectiveGroup = XkbOutOfRangeGroupInfo(gi);
- if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode))
- effectiveGroup = 0;
- break;
- }
- }
- }
- else effectiveGroup = XkbGroup1Index;
-
- return effectiveGroup;
-}
-
-/* Merge the lockedPtrButtons from all attached SDs for the given master
- * device into the MD's state.
- */
-void
-XkbMergeLockedPtrBtns(DeviceIntPtr master)
-{
- DeviceIntPtr d = inputInfo.devices;
- XkbSrvInfoPtr xkbi = NULL;
-
- if (!IsMaster(master))
- return;
-
- if (!master->key)
- return;
-
- xkbi = master->key->xkbInfo;
- xkbi->lockedPtrButtons = 0;
-
- for (; d; d = d->next) {
- if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key)
- continue;
-
- xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons;
- }
-}
+/************************************************************
+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.
+
+********************************************************/
+/*
+
+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.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "os.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#define XK_CYRILLIC
+#include <X11/keysym.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "eventstr.h"
+
+#define XKBSRV_NEED_FILE_FUNCS
+#include <xkbsrv.h>
+#include "xkbgeom.h"
+#include "xkb.h"
+
+/***====================================================================***/
+
+int
+_XkbLookupAnyDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
+ Mask access_mode, int *xkb_err)
+{
+ int rc = XkbKeyboardErrorCode;
+
+ if (id == XkbUseCoreKbd)
+ id = PickKeyboard(client)->id;
+ else if (id == XkbUseCorePtr)
+ id = PickPointer(client)->id;
+
+ rc = dixLookupDevice(pDev, id, client, access_mode);
+ if (rc != Success)
+ *xkb_err = XkbErr_BadDevice;
+
+ return rc;
+}
+
+int
+_XkbLookupKeyboard(DeviceIntPtr *pDev, int id, ClientPtr client,
+ Mask access_mode, int *xkb_err)
+{
+ DeviceIntPtr dev;
+ int rc;
+
+ if (id == XkbDfltXIId)
+ id = XkbUseCoreKbd;
+
+ rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
+ if (rc != Success)
+ return rc;
+
+ dev = *pDev;
+ if (!dev->key || !dev->key->xkbInfo) {
+ *pDev = NULL;
+ *xkb_err= XkbErr_BadClass;
+ return XkbKeyboardErrorCode;
+ }
+ return Success;
+}
+
+int
+_XkbLookupBellDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
+ Mask access_mode, int *xkb_err)
+{
+ DeviceIntPtr dev;
+ int rc;
+
+ rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
+ if (rc != Success)
+ return rc;
+
+ dev = *pDev;
+ if (!dev->kbdfeed && !dev->bell) {
+ *pDev = NULL;
+ *xkb_err= XkbErr_BadClass;
+ return XkbKeyboardErrorCode;
+ }
+ return Success;
+}
+
+int
+_XkbLookupLedDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
+ Mask access_mode, int *xkb_err)
+{
+ DeviceIntPtr dev;
+ int rc;
+
+ if (id == XkbDfltXIId)
+ id = XkbUseCorePtr;
+
+ rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
+ if (rc != Success)
+ return rc;
+
+ dev = *pDev;
+ if (!dev->kbdfeed && !dev->leds) {
+ *pDev = NULL;
+ *xkb_err= XkbErr_BadClass;
+ return XkbKeyboardErrorCode;
+ }
+ return Success;
+}
+
+int
+_XkbLookupButtonDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
+ Mask access_mode, int *xkb_err)
+{
+ DeviceIntPtr dev;
+ int rc;
+
+ rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
+ if (rc != Success)
+ return rc;
+
+ dev = *pDev;
+ if (!dev->button) {
+ *pDev = NULL;
+ *xkb_err= XkbErr_BadClass;
+ return XkbKeyboardErrorCode;
+ }
+ return Success;
+}
+
+void
+XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction *act,unsigned mods)
+{
+register unsigned tmp;
+
+ switch (act->type) {
+ case XkbSA_SetMods: case XkbSA_LatchMods: case XkbSA_LockMods:
+ if (act->mods.flags&XkbSA_UseModMapMods)
+ act->mods.real_mods= act->mods.mask= mods;
+ if ((tmp= XkbModActionVMods(&act->mods))!=0)
+ act->mods.mask|= XkbMaskForVMask(xkb,tmp);
+ break;
+ case XkbSA_ISOLock:
+ if (act->iso.flags&XkbSA_UseModMapMods)
+ act->iso.real_mods= act->iso.mask= mods;
+ if ((tmp= XkbModActionVMods(&act->iso))!=0)
+ act->iso.mask|= XkbMaskForVMask(xkb,tmp);
+ break;
+ }
+ return;
+}
+
+unsigned
+XkbMaskForVMask(XkbDescPtr xkb,unsigned vmask)
+{
+register int i,bit;
+register unsigned mask;
+
+ for (mask=i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+ if (vmask&bit)
+ mask|= xkb->server->vmods[i];
+ }
+ return mask;
+}
+
+/***====================================================================***/
+
+void
+XkbUpdateKeyTypesFromCore( DeviceIntPtr pXDev,
+ KeySymsPtr pCore,
+ KeyCode first,
+ CARD8 num,
+ XkbChangesPtr changes)
+{
+XkbDescPtr xkb;
+unsigned key,nG,explicit;
+int types[XkbNumKbdGroups];
+KeySym tsyms[XkbMaxSymsPerKey],*syms;
+XkbMapChangesPtr mc;
+
+ xkb= pXDev->key->xkbInfo->desc;
+ if (first+num-1>xkb->max_key_code) {
+ /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */
+ num= xkb->max_key_code-first+1;
+ }
+
+ mc= (changes?(&changes->map):NULL);
+
+ syms= &pCore->map[(first - pCore->minKeyCode) * pCore->mapWidth];
+ for (key=first; key<(first+num); key++,syms+= pCore->mapWidth) {
+ explicit= xkb->server->explicit[key]&XkbExplicitKeyTypesMask;
+ types[XkbGroup1Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup1Index);
+ types[XkbGroup2Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup2Index);
+ types[XkbGroup3Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup3Index);
+ types[XkbGroup4Index]= XkbKeyKeyTypeIndex(xkb,key,XkbGroup4Index);
+ nG= XkbKeyTypesForCoreSymbols(xkb,pCore->mapWidth,syms,explicit,types,
+ tsyms);
+ XkbChangeTypesOfKey(xkb,key,nG,XkbAllGroupsMask,types,mc);
+ memcpy((char *)XkbKeySymsPtr(xkb,key),(char *)tsyms,
+ XkbKeyNumSyms(xkb,key)*sizeof(KeySym));
+ }
+ if (changes->map.changed&XkbKeySymsMask) {
+ CARD8 oldLast,newLast;
+ oldLast = changes->map.first_key_sym+changes->map.num_key_syms-1;
+ newLast = first+num-1;
+
+ if (first<changes->map.first_key_sym)
+ changes->map.first_key_sym = first;
+ if (oldLast>newLast)
+ newLast= oldLast;
+ changes->map.num_key_syms = newLast-changes->map.first_key_sym+1;
+ }
+ else {
+ changes->map.changed|= XkbKeySymsMask;
+ changes->map.first_key_sym = first;
+ changes->map.num_key_syms = num;
+ }
+ return;
+}
+
+void
+XkbUpdateDescActions( XkbDescPtr xkb,
+ KeyCode first,
+ CARD8 num,
+ XkbChangesPtr changes)
+{
+register unsigned key;
+
+ for (key=first;key<(first+num);key++) {
+ XkbApplyCompatMapToKey(xkb,key,changes);
+ }
+
+ if (changes->map.changed&(XkbVirtualModMapMask|XkbModifierMapMask)) {
+ unsigned char newVMods[XkbNumVirtualMods];
+ register unsigned bit,i;
+ unsigned present;
+
+ memset(newVMods, 0, XkbNumVirtualMods);
+ present= 0;
+ for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
+ if (xkb->server->vmodmap[key]==0)
+ continue;
+ for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+ if (bit&xkb->server->vmodmap[key]) {
+ present|= bit;
+ newVMods[i]|= xkb->map->modmap[key];
+ }
+ }
+ }
+ for (i=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
+ if ((bit&present)&&(newVMods[i]!=xkb->server->vmods[i])) {
+ changes->map.changed|= XkbVirtualModsMask;
+ changes->map.vmods|= bit;
+ xkb->server->vmods[i]= newVMods[i];
+ }
+ }
+ }
+ if (changes->map.changed&XkbVirtualModsMask)
+ XkbApplyVirtualModChanges(xkb,changes->map.vmods,changes);
+
+ if (changes->map.changed&XkbKeyActionsMask) {
+ CARD8 oldLast,newLast;
+ oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
+ newLast = first+num-1;
+
+ if (first<changes->map.first_key_act)
+ changes->map.first_key_act = first;
+ if (newLast>oldLast)
+ newLast= oldLast;
+ changes->map.num_key_acts= newLast-changes->map.first_key_act+1;
+ }
+ else {
+ changes->map.changed|= XkbKeyActionsMask;
+ changes->map.first_key_act = first;
+ changes->map.num_key_acts = num;
+ }
+ return;
+}
+
+void
+XkbUpdateActions( DeviceIntPtr pXDev,
+ KeyCode first,
+ CARD8 num,
+ XkbChangesPtr changes,
+ unsigned * needChecksRtrn,
+ XkbEventCausePtr cause)
+{
+XkbSrvInfoPtr xkbi;
+XkbDescPtr xkb;
+CARD8 * repeat;
+
+ if (needChecksRtrn)
+ *needChecksRtrn= 0;
+ xkbi= pXDev->key->xkbInfo;
+ xkb= xkbi->desc;
+ repeat= xkb->ctrls->per_key_repeat;
+
+ /* before letting XKB do any changes, copy the current core values */
+ if (pXDev->kbdfeed)
+ memcpy(repeat,pXDev->kbdfeed->ctrl.autoRepeats,XkbPerKeyBitArraySize);
+
+ XkbUpdateDescActions(xkb,first,num,changes);
+
+ if ((pXDev->kbdfeed)&&
+ (changes->ctrls.changed_ctrls&XkbPerKeyRepeatMask)) {
+ /* now copy the modified changes back to core */
+ memcpy(pXDev->kbdfeed->ctrl.autoRepeats,repeat, XkbPerKeyBitArraySize);
+ if (pXDev->kbdfeed->CtrlProc)
+ (*pXDev->kbdfeed->CtrlProc)(pXDev, &pXDev->kbdfeed->ctrl);
+ }
+ return;
+}
+
+KeySymsPtr
+XkbGetCoreMap(DeviceIntPtr keybd)
+{
+register int key,tmp;
+int maxSymsPerKey, maxGroup1Width;
+XkbDescPtr xkb;
+KeySymsPtr syms;
+int maxNumberOfGroups;
+
+ if (!keybd || !keybd->key || !keybd->key->xkbInfo)
+ return NULL;
+
+ xkb= keybd->key->xkbInfo->desc;
+ maxSymsPerKey= maxGroup1Width= 0;
+ maxNumberOfGroups = 0;
+
+ /* determine sizes */
+ for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
+ if (XkbKeycodeInRange(xkb,key)) {
+ int nGroups;
+ int w;
+ nGroups= XkbKeyNumGroups(xkb,key);
+ tmp= 0;
+ if (nGroups>0) {
+ if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup1Index))<=2)
+ tmp+= 2;
+ else tmp+= w + 2;
+ /* remember highest G1 width */
+ if (w > maxGroup1Width)
+ maxGroup1Width = w;
+ }
+ if (nGroups>1) {
+ if (tmp <= 2) {
+ if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))<2)
+ tmp+= 2;
+ else tmp+= w;
+ } else {
+ if ((w=XkbKeyGroupWidth(xkb,key,XkbGroup2Index))>2)
+ tmp+= w - 2;
+ }
+ }
+ if (nGroups>2)
+ tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup3Index);
+ if (nGroups>3)
+ tmp+= XkbKeyGroupWidth(xkb,key,XkbGroup4Index);
+ if (tmp>maxSymsPerKey)
+ maxSymsPerKey= tmp;
+ if (nGroups > maxNumberOfGroups)
+ maxNumberOfGroups = nGroups;
+ }
+ }
+
+ if (maxSymsPerKey <= 0)
+ return NULL;
+
+ syms = calloc(1, sizeof(*syms));
+ if (!syms)
+ return NULL;
+
+ /* See Section 12.4 of the XKB Protocol spec. Because of the
+ * single-group distribution for multi-group keyboards, we have to
+ * have enough symbols for the largest group 1 to replicate across the
+ * number of groups on the keyboard. e.g. a single-group key with 4
+ * symbols on a keyboard that has 3 groups -> 12 syms per key */
+ if (maxSymsPerKey < maxNumberOfGroups * maxGroup1Width)
+ maxSymsPerKey = maxNumberOfGroups * maxGroup1Width;
+
+ syms->mapWidth = maxSymsPerKey;
+ syms->minKeyCode = xkb->min_key_code;
+ syms->maxKeyCode = xkb->max_key_code;
+
+ tmp = syms->mapWidth * (xkb->max_key_code - xkb->min_key_code + 1);
+ syms->map = calloc(tmp, sizeof(*syms->map));
+ if (!syms->map) {
+ free(syms);
+ return NULL;
+ }
+
+ for (key=xkb->min_key_code;key<=xkb->max_key_code;key++) {
+ KeySym *pCore,*pXKB;
+ unsigned nGroups,groupWidth,n,nOut;
+
+ nGroups= XkbKeyNumGroups(xkb,key);
+ n= (key-xkb->min_key_code)*syms->mapWidth;
+ pCore= &syms->map[n];
+ pXKB= XkbKeySymsPtr(xkb,key);
+ nOut= 2;
+ if (nGroups>0) {
+ groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup1Index);
+ if (groupWidth>0) pCore[0]= pXKB[0];
+ if (groupWidth>1) pCore[1]= pXKB[1];
+ for (n=2;n<groupWidth;n++)
+ pCore[2+n]= pXKB[n];
+ if (groupWidth>2)
+ nOut= groupWidth;
+ }
+
+ /* See XKB Protocol Sec, Section 12.4.
+ A 1-group key with ABCDE on a 2 group keyboard must be
+ duplicated across all groups as ABABCDECDE.
+ */
+ if (nGroups == 1)
+ {
+ int idx, j;
+
+ groupWidth = XkbKeyGroupWidth(xkb, key, XkbGroup1Index);
+
+ /* AB..CDE... -> ABABCDE... */
+ if (groupWidth > 0 && syms->mapWidth >= 3)
+ pCore[2] = pCore[0];
+ if (groupWidth > 1 && syms->mapWidth >= 4)
+ pCore[3] = pCore[1];
+
+ /* ABABCDE... -> ABABCDECDE */
+ idx = 2 + groupWidth;
+ while (groupWidth > 2 && idx < syms->mapWidth &&
+ idx < groupWidth * 2)
+ {
+ pCore[idx] = pCore[idx - groupWidth + 2];
+ idx++;
+ }
+ idx = 2 * groupWidth;
+ if (idx < 4)
+ idx = 4;
+ /* 3 or more groups: ABABCDECDEABCDEABCDE */
+ for (j = 3; j <= maxNumberOfGroups; j++)
+ for (n = 0; n < groupWidth && idx < maxSymsPerKey; n++)
+ pCore[idx++] = pXKB[n];
+ }
+
+ pXKB+= XkbKeyGroupsWidth(xkb,key);
+ nOut+= 2;
+ if (nGroups>1) {
+ groupWidth= XkbKeyGroupWidth(xkb,key,XkbGroup2Index);
+ if (groupWidth>0) pCore[2]= pXKB[0];
+ if (groupWidth>1) pCore[3]= pXKB[1];
+ for (n=2;n<groupWidth;n++) {
+ pCore[nOut+(n-2)]= pXKB[n];
+ }
+ if (groupWidth>2)
+ nOut+= (groupWidth-2);
+ }
+ pXKB+= XkbKeyGroupsWidth(xkb,key);
+ for (n=XkbGroup3Index;n<nGroups;n++) {
+ register int s;
+ groupWidth= XkbKeyGroupWidth(xkb,key,n);
+ for (s=0;s<groupWidth;s++) {
+ pCore[nOut++]= pXKB[s];
+ }
+ pXKB+= XkbKeyGroupsWidth(xkb,key);
+ }
+ }
+
+ return syms;
+}
+
+void
+XkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff)
+{
+ if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
+ xkbControlsNotify cn;
+ XkbControlsPtr ctrls = pXDev->key->xkbInfo->desc->ctrls;
+ XkbControlsRec old;
+ old = *ctrls;
+
+ if (key== -1) { /* global autorepeat setting changed */
+ if (onoff) ctrls->enabled_ctrls |= XkbRepeatKeysMask;
+ else ctrls->enabled_ctrls &= ~XkbRepeatKeysMask;
+ }
+ else if (pXDev->kbdfeed) {
+ ctrls->per_key_repeat[key/8] =
+ pXDev->kbdfeed->ctrl.autoRepeats[key/8];
+ }
+
+ if (XkbComputeControlsNotify(pXDev,&old,ctrls,&cn,TRUE))
+ XkbSendControlsNotify(pXDev,&cn);
+ }
+ return;
+}
+
+/* Applies a change to a single device, does not traverse the device tree. */
+void
+XkbApplyMappingChange(DeviceIntPtr kbd, KeySymsPtr map, KeyCode first_key,
+ CARD8 num_keys, CARD8 *modmap, ClientPtr client)
+{
+ XkbDescPtr xkb = kbd->key->xkbInfo->desc;
+ XkbEventCauseRec cause;
+ XkbChangesRec changes;
+ unsigned int check;
+
+ memset(&changes, 0, sizeof(changes));
+ memset(&cause, 0, sizeof(cause));
+
+ if (map && first_key && num_keys) {
+ check = 0;
+ XkbSetCauseCoreReq(&cause, X_ChangeKeyboardMapping, client);
+
+ XkbUpdateKeyTypesFromCore(kbd, map, first_key, num_keys, &changes);
+ XkbUpdateActions(kbd, first_key, num_keys, &changes, &check, &cause);
+
+ if (check)
+ XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause);
+ }
+
+ if (modmap) {
+ /* A keymap change can imply a modmap change, se we prefer the
+ * former. */
+ if (!cause.mjr)
+ XkbSetCauseCoreReq(&cause,X_SetModifierMapping,client);
+
+ check = 0;
+ num_keys = xkb->max_key_code - xkb->min_key_code + 1;
+ changes.map.changed |= XkbModifierMapMask;
+ changes.map.first_modmap_key = xkb->min_key_code;
+ changes.map.num_modmap_keys = num_keys;
+ memcpy(kbd->key->xkbInfo->desc->map->modmap, modmap, MAP_LENGTH);
+ XkbUpdateActions(kbd, xkb->min_key_code, num_keys, &changes, &check,
+ &cause);
+
+ if (check)
+ XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause);
+ }
+
+ XkbSendNotification(kbd, &changes, &cause);
+}
+
+void
+XkbDisableComputedAutoRepeats(DeviceIntPtr dev,unsigned key)
+{
+XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
+xkbMapNotify mn;
+
+ xkbi->desc->server->explicit[key]|= XkbExplicitAutoRepeatMask;
+ memset(&mn, 0, sizeof(mn));
+ mn.changed= XkbExplicitComponentsMask;
+ mn.firstKeyExplicit= key;
+ mn.nKeyExplicit= 1;
+ XkbSendMapNotify(dev,&mn);
+ return;
+}
+
+unsigned
+XkbStateChangedFlags(XkbStatePtr old,XkbStatePtr new)
+{
+int changed;
+
+ changed=(old->group!=new->group?XkbGroupStateMask:0);
+ changed|=(old->base_group!=new->base_group?XkbGroupBaseMask:0);
+ changed|=(old->latched_group!=new->latched_group?XkbGroupLatchMask:0);
+ changed|=(old->locked_group!=new->locked_group?XkbGroupLockMask:0);
+ changed|=(old->mods!=new->mods?XkbModifierStateMask:0);
+ changed|=(old->base_mods!=new->base_mods?XkbModifierBaseMask:0);
+ changed|=(old->latched_mods!=new->latched_mods?XkbModifierLatchMask:0);
+ changed|=(old->locked_mods!=new->locked_mods?XkbModifierLockMask:0);
+ changed|=(old->compat_state!=new->compat_state?XkbCompatStateMask:0);
+ changed|=(old->grab_mods!=new->grab_mods?XkbGrabModsMask:0);
+ if (old->compat_grab_mods!=new->compat_grab_mods)
+ changed|= XkbCompatGrabModsMask;
+ changed|=(old->lookup_mods!=new->lookup_mods?XkbLookupModsMask:0);
+ if (old->compat_lookup_mods!=new->compat_lookup_mods)
+ changed|= XkbCompatLookupModsMask;
+ changed|=(old->ptr_buttons!=new->ptr_buttons?XkbPointerButtonMask:0);
+ return changed;
+}
+
+static void
+XkbComputeCompatState(XkbSrvInfoPtr xkbi)
+{
+CARD16 grp_mask;
+XkbStatePtr state= &xkbi->state;
+XkbCompatMapPtr map;
+
+ if (!state || !xkbi->desc || !xkbi->desc->ctrls || !xkbi->desc->compat)
+ return;
+
+ map= xkbi->desc->compat;
+ grp_mask= map->groups[state->group].mask;
+ state->compat_state = state->mods|grp_mask;
+ state->compat_lookup_mods= state->lookup_mods|grp_mask;
+
+ if (xkbi->desc->ctrls->enabled_ctrls&XkbIgnoreGroupLockMask)
+ grp_mask= map->groups[state->base_group].mask;
+ state->compat_grab_mods= state->grab_mods|grp_mask;
+ return;
+}
+
+unsigned
+XkbAdjustGroup(int group,XkbControlsPtr ctrls)
+{
+unsigned act;
+
+ act= XkbOutOfRangeGroupAction(ctrls->groups_wrap);
+ if (group<0) {
+ while ( group < 0 ) {
+ if (act==XkbClampIntoRange) {
+ group= XkbGroup1Index;
+ }
+ else if (act==XkbRedirectIntoRange) {
+ int newGroup;
+ newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap);
+ if (newGroup>=ctrls->num_groups)
+ group= XkbGroup1Index;
+ else group= newGroup;
+ }
+ else {
+ group+= ctrls->num_groups;
+ }
+ }
+ }
+ else if (group>=ctrls->num_groups) {
+ if (act==XkbClampIntoRange) {
+ group= ctrls->num_groups-1;
+ }
+ else if (act==XkbRedirectIntoRange) {
+ int newGroup;
+ newGroup= XkbOutOfRangeGroupNumber(ctrls->groups_wrap);
+ if (newGroup>=ctrls->num_groups)
+ group= XkbGroup1Index;
+ else group= newGroup;
+ }
+ else {
+ group%= ctrls->num_groups;
+ }
+ }
+ return group;
+}
+
+void
+XkbComputeDerivedState(XkbSrvInfoPtr xkbi)
+{
+XkbStatePtr state= &xkbi->state;
+XkbControlsPtr ctrls= xkbi->desc->ctrls;
+unsigned char grp;
+
+ if (!state || !ctrls)
+ return;
+
+ state->mods= (state->base_mods|state->latched_mods|state->locked_mods);
+ state->lookup_mods= state->mods&(~ctrls->internal.mask);
+ state->grab_mods= state->lookup_mods&(~ctrls->ignore_lock.mask);
+ state->grab_mods|=
+ ((state->base_mods|state->latched_mods)&ctrls->ignore_lock.mask);
+
+
+ grp= state->locked_group;
+ if (grp>=ctrls->num_groups)
+ state->locked_group= XkbAdjustGroup(XkbCharToInt(grp),ctrls);
+
+ grp= state->locked_group+state->base_group+state->latched_group;
+ if (grp>=ctrls->num_groups)
+ state->group= XkbAdjustGroup(XkbCharToInt(grp),ctrls);
+ else state->group= grp;
+ XkbComputeCompatState(xkbi);
+ return;
+}
+
+/***====================================================================***/
+
+void
+XkbCheckSecondaryEffects( XkbSrvInfoPtr xkbi,
+ unsigned which,
+ XkbChangesPtr changes,
+ XkbEventCausePtr cause)
+{
+ if (which&XkbStateNotifyMask) {
+ XkbStateRec old;
+ old= xkbi->state;
+ changes->state_changes|= XkbStateChangedFlags(&old,&xkbi->state);
+ XkbComputeDerivedState(xkbi);
+ }
+ if (which&XkbIndicatorStateNotifyMask)
+ XkbUpdateIndicators(xkbi->device,XkbAllIndicatorsMask,TRUE,changes,
+ cause);
+ return;
+}
+
+/***====================================================================***/
+
+Bool
+XkbEnableDisableControls( XkbSrvInfoPtr xkbi,
+ unsigned long change,
+ unsigned long newValues,
+ XkbChangesPtr changes,
+ XkbEventCausePtr cause)
+{
+XkbControlsPtr ctrls;
+unsigned old;
+XkbSrvLedInfoPtr sli;
+
+ ctrls= xkbi->desc->ctrls;
+ old= ctrls->enabled_ctrls;
+ ctrls->enabled_ctrls&= ~change;
+ ctrls->enabled_ctrls|= (change&newValues);
+ if (old==ctrls->enabled_ctrls)
+ return FALSE;
+ if (cause!=NULL) {
+ xkbControlsNotify cn;
+ cn.numGroups= ctrls->num_groups;
+ cn.changedControls= XkbControlsEnabledMask;
+ cn.enabledControls= ctrls->enabled_ctrls;
+ cn.enabledControlChanges= (ctrls->enabled_ctrls^old);
+ cn.keycode= cause->kc;
+ cn.eventType= cause->event;
+ cn.requestMajor= cause->mjr;
+ cn.requestMinor= cause->mnr;
+ XkbSendControlsNotify(xkbi->device,&cn);
+ }
+ else {
+ /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes*/
+ /* is non-zero, the controls in question changed already in "this" */
+ /* request and this change merely undoes the previous one. By the */
+ /* same token, we have to figure out whether or not ControlsEnabled */
+ /* should be set or not in the changes structure */
+ changes->ctrls.enabled_ctrls_changes^= (ctrls->enabled_ctrls^old);
+ if (changes->ctrls.enabled_ctrls_changes)
+ changes->ctrls.changed_ctrls|= XkbControlsEnabledMask;
+ else changes->ctrls.changed_ctrls&= ~XkbControlsEnabledMask;
+ }
+ sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
+ XkbUpdateIndicators(xkbi->device,sli->usesControls,TRUE,changes,cause);
+ return TRUE;
+}
+
+/***====================================================================***/
+
+#define MAX_TOC 16
+
+XkbGeometryPtr
+XkbLookupNamedGeometry(DeviceIntPtr dev,Atom name,Bool *shouldFree)
+{
+XkbSrvInfoPtr xkbi= dev->key->xkbInfo;
+XkbDescPtr xkb= xkbi->desc;
+
+ *shouldFree= 0;
+ if (name==None) {
+ if (xkb->geom!=NULL)
+ return xkb->geom;
+ name= xkb->names->geometry;
+ }
+ if ((xkb->geom!=NULL)&&(xkb->geom->name==name))
+ return xkb->geom;
+ *shouldFree= 1;
+ return NULL;
+}
+
+void
+XkbConvertCase(register KeySym sym, KeySym *lower, KeySym *upper)
+{
+ *lower = sym;
+ *upper = sym;
+ switch(sym >> 8) {
+ case 0: /* Latin 1 */
+ if ((sym >= XK_A) && (sym <= XK_Z))
+ *lower += (XK_a - XK_A);
+ else if ((sym >= XK_a) && (sym <= XK_z))
+ *upper -= (XK_a - XK_A);
+ else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
+ *lower += (XK_agrave - XK_Agrave);
+ else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
+ *upper -= (XK_agrave - XK_Agrave);
+ else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
+ *lower += (XK_oslash - XK_Ooblique);
+ else if ((sym >= XK_oslash) && (sym <= XK_thorn))
+ *upper -= (XK_oslash - XK_Ooblique);
+ break;
+ case 1: /* Latin 2 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym == XK_Aogonek)
+ *lower = XK_aogonek;
+ else if (sym >= XK_Lstroke && sym <= XK_Sacute)
+ *lower += (XK_lstroke - XK_Lstroke);
+ else if (sym >= XK_Scaron && sym <= XK_Zacute)
+ *lower += (XK_scaron - XK_Scaron);
+ else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
+ *lower += (XK_zcaron - XK_Zcaron);
+ else if (sym == XK_aogonek)
+ *upper = XK_Aogonek;
+ else if (sym >= XK_lstroke && sym <= XK_sacute)
+ *upper -= (XK_lstroke - XK_Lstroke);
+ else if (sym >= XK_scaron && sym <= XK_zacute)
+ *upper -= (XK_scaron - XK_Scaron);
+ else if (sym >= XK_zcaron && sym <= XK_zabovedot)
+ *upper -= (XK_zcaron - XK_Zcaron);
+ else if (sym >= XK_Racute && sym <= XK_Tcedilla)
+ *lower += (XK_racute - XK_Racute);
+ else if (sym >= XK_racute && sym <= XK_tcedilla)
+ *upper -= (XK_racute - XK_Racute);
+ break;
+ case 2: /* Latin 3 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
+ *lower += (XK_hstroke - XK_Hstroke);
+ else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
+ *lower += (XK_gbreve - XK_Gbreve);
+ else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
+ *upper -= (XK_hstroke - XK_Hstroke);
+ else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
+ *upper -= (XK_gbreve - XK_Gbreve);
+ else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
+ *lower += (XK_cabovedot - XK_Cabovedot);
+ else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
+ *upper -= (XK_cabovedot - XK_Cabovedot);
+ break;
+ case 3: /* Latin 4 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Rcedilla && sym <= XK_Tslash)
+ *lower += (XK_rcedilla - XK_Rcedilla);
+ else if (sym >= XK_rcedilla && sym <= XK_tslash)
+ *upper -= (XK_rcedilla - XK_Rcedilla);
+ else if (sym == XK_ENG)
+ *lower = XK_eng;
+ else if (sym == XK_eng)
+ *upper = XK_ENG;
+ else if (sym >= XK_Amacron && sym <= XK_Umacron)
+ *lower += (XK_amacron - XK_Amacron);
+ else if (sym >= XK_amacron && sym <= XK_umacron)
+ *upper -= (XK_amacron - XK_Amacron);
+ break;
+ case 6: /* Cyrillic */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
+ *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
+ else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
+ *upper += (XK_Serbian_DJE - XK_Serbian_dje);
+ else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
+ *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
+ else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
+ *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
+ break;
+ case 7: /* Greek */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
+ *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+ else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
+ sym != XK_Greek_iotaaccentdieresis &&
+ sym != XK_Greek_upsilonaccentdieresis)
+ *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+ else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
+ *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
+ else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
+ sym != XK_Greek_finalsmallsigma)
+ *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
+ break;
+ }
+}
+
+static Bool
+_XkbCopyClientMap(XkbDescPtr src, XkbDescPtr dst)
+{
+ void *tmp = NULL;
+ int i;
+ XkbKeyTypePtr stype = NULL, dtype = NULL;
+
+ /* client map */
+ if (src->map) {
+ if (!dst->map) {
+ tmp = calloc(1, sizeof(XkbClientMapRec));
+ if (!tmp)
+ return FALSE;
+ dst->map = tmp;
+ }
+
+ if (src->map->syms) {
+ if (src->map->size_syms != dst->map->size_syms) {
+ tmp = realloc(dst->map->syms,
+ src->map->size_syms * sizeof(KeySym));
+ if (!tmp)
+ return FALSE;
+ dst->map->syms = tmp;
+
+ }
+ memcpy(dst->map->syms, src->map->syms,
+ src->map->size_syms * sizeof(KeySym));
+ }
+ else {
+ free(dst->map->syms);
+ dst->map->syms = NULL;
+ }
+ dst->map->num_syms = src->map->num_syms;
+ dst->map->size_syms = src->map->size_syms;
+
+ if (src->map->key_sym_map) {
+ if (src->max_key_code != dst->max_key_code) {
+ tmp = realloc(dst->map->key_sym_map,
+ (src->max_key_code + 1) * sizeof(XkbSymMapRec));
+ if (!tmp)
+ return FALSE;
+ dst->map->key_sym_map = tmp;
+ }
+ memcpy(dst->map->key_sym_map, src->map->key_sym_map,
+ (src->max_key_code + 1) * sizeof(XkbSymMapRec));
+ }
+ else {
+ free(dst->map->key_sym_map);
+ dst->map->key_sym_map = NULL;
+ }
+
+ if (src->map->types && src->map->num_types) {
+ if (src->map->num_types > dst->map->size_types ||
+ !dst->map->types || !dst->map->size_types) {
+ if (dst->map->types && dst->map->size_types) {
+ tmp = realloc(dst->map->types,
+ src->map->num_types * sizeof(XkbKeyTypeRec));
+ if (!tmp)
+ return FALSE;
+ dst->map->types = tmp;
+ memset(dst->map->types + dst->map->num_types, 0,
+ (src->map->num_types - dst->map->num_types) *
+ sizeof(XkbKeyTypeRec));
+ }
+ else {
+ tmp = calloc(src->map->num_types, sizeof(XkbKeyTypeRec));
+ if (!tmp)
+ return FALSE;
+ dst->map->types = tmp;
+ }
+ }
+ else if (src->map->num_types < dst->map->num_types &&
+ dst->map->types) {
+ for (i = src->map->num_types, dtype = (dst->map->types + i);
+ i < dst->map->num_types; i++, dtype++) {
+ free(dtype->level_names);
+ dtype->level_names = NULL;
+ dtype->num_levels = 0;
+ if (dtype->map_count) {
+ free(dtype->map);
+ free(dtype->preserve);
+ }
+ }
+ }
+
+ stype = src->map->types;
+ dtype = dst->map->types;
+ for (i = 0; i < src->map->num_types; i++, dtype++, stype++) {
+ if (stype->num_levels && stype->level_names) {
+ if (stype->num_levels != dtype->num_levels &&
+ dtype->num_levels && dtype->level_names &&
+ i < dst->map->num_types) {
+ tmp = realloc(dtype->level_names,
+ stype->num_levels * sizeof(Atom));
+ if (!tmp)
+ continue;
+ dtype->level_names = tmp;
+ }
+ else if (!dtype->num_levels || !dtype->level_names ||
+ i >= dst->map->num_types) {
+ tmp = malloc(stype->num_levels * sizeof(Atom));
+ if (!tmp)
+ continue;
+ dtype->level_names = tmp;
+ }
+ dtype->num_levels = stype->num_levels;
+ memcpy(dtype->level_names, stype->level_names,
+ stype->num_levels * sizeof(Atom));
+ }
+ else {
+ if (dtype->num_levels && dtype->level_names &&
+ i < dst->map->num_types)
+ free(dtype->level_names);
+ dtype->num_levels = 0;
+ dtype->level_names = NULL;
+ }
+
+ dtype->name = stype->name;
+ memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec));
+
+ if (stype->map_count) {
+ if (stype->map) {
+ if (stype->map_count != dtype->map_count &&
+ dtype->map_count && dtype->map &&
+ i < dst->map->num_types) {
+ tmp = realloc(dtype->map,
+ stype->map_count *
+ sizeof(XkbKTMapEntryRec));
+ if (!tmp)
+ return FALSE;
+ dtype->map = tmp;
+ }
+ else if (!dtype->map_count || !dtype->map ||
+ i >= dst->map->num_types) {
+ tmp = malloc(stype->map_count *
+ sizeof(XkbKTMapEntryRec));
+ if (!tmp)
+ return FALSE;
+ dtype->map = tmp;
+ }
+
+ memcpy(dtype->map, stype->map,
+ stype->map_count * sizeof(XkbKTMapEntryRec));
+ }
+ else {
+ if (dtype->map && i < dst->map->num_types)
+ free(dtype->map);
+ dtype->map = NULL;
+ }
+
+ if (stype->preserve) {
+ if (stype->map_count != dtype->map_count &&
+ dtype->map_count && dtype->preserve &&
+ i < dst->map->num_types) {
+ tmp = realloc(dtype->preserve,
+ stype->map_count *
+ sizeof(XkbModsRec));
+ if (!tmp)
+ return FALSE;
+ dtype->preserve = tmp;
+ }
+ else if (!dtype->preserve || !dtype->map_count ||
+ i >= dst->map->num_types) {
+ tmp = malloc(stype->map_count *
+ sizeof(XkbModsRec));
+ if (!tmp)
+ return FALSE;
+ dtype->preserve = tmp;
+ }
+
+ memcpy(dtype->preserve, stype->preserve,
+ stype->map_count * sizeof(XkbModsRec));
+ }
+ else {
+ if (dtype->preserve && i < dst->map->num_types)
+ free(dtype->preserve);
+ dtype->preserve = NULL;
+ }
+
+ dtype->map_count = stype->map_count;
+ }
+ else {
+ if (dtype->map_count && i < dst->map->num_types) {
+ free(dtype->map);
+ free(dtype->preserve);
+ }
+ dtype->map_count = 0;
+ dtype->map = NULL;
+ dtype->preserve = NULL;
+ }
+ }
+
+ dst->map->size_types = src->map->num_types;
+ dst->map->num_types = src->map->num_types;
+ }
+ else {
+ if (dst->map->types) {
+ for (i = 0, dtype = dst->map->types; i < dst->map->num_types;
+ i++, dtype++) {
+ free(dtype->level_names);
+ if (dtype->map && dtype->map_count)
+ free(dtype->map);
+ if (dtype->preserve && dtype->map_count)
+ free(dtype->preserve);
+ }
+ }
+ free(dst->map->types);
+ dst->map->types = NULL;
+ dst->map->num_types = 0;
+ dst->map->size_types = 0;
+ }
+
+ if (src->map->modmap) {
+ if (src->max_key_code != dst->max_key_code) {
+ tmp = realloc(dst->map->modmap, src->max_key_code + 1);
+ if (!tmp)
+ return FALSE;
+ dst->map->modmap = tmp;
+ }
+ memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1);
+ }
+ else {
+ free(dst->map->modmap);
+ dst->map->modmap = NULL;
+ }
+ }
+ else {
+ if (dst->map)
+ XkbFreeClientMap(dst, XkbAllClientInfoMask, TRUE);
+ }
+
+ return TRUE;
+}
+
+static Bool
+_XkbCopyServerMap(XkbDescPtr src, XkbDescPtr dst)
+{
+ void *tmp = NULL;
+
+ /* server map */
+ if (src->server) {
+ if (!dst->server) {
+ tmp = calloc(1, sizeof(XkbServerMapRec));
+ if (!tmp)
+ return FALSE;
+ dst->server = tmp;
+ }
+
+ if (src->server->explicit) {
+ if (src->max_key_code != dst->max_key_code) {
+ tmp = realloc(dst->server->explicit, src->max_key_code + 1);
+ if (!tmp)
+ return FALSE;
+ dst->server->explicit = tmp;
+ }
+ memcpy(dst->server->explicit, src->server->explicit,
+ src->max_key_code + 1);
+ }
+ else {
+ free(dst->server->explicit);
+ dst->server->explicit = NULL;
+ }
+
+ if (src->server->acts) {
+ if (src->server->size_acts != dst->server->size_acts) {
+ tmp = realloc(dst->server->acts,
+ src->server->size_acts * sizeof(XkbAction));
+ if (!tmp)
+ return FALSE;
+ dst->server->acts = tmp;
+ }
+ memcpy(dst->server->acts, src->server->acts,
+ src->server->size_acts * sizeof(XkbAction));
+ }
+ else {
+ free(dst->server->acts);
+ dst->server->acts = NULL;
+ }
+ dst->server->size_acts = src->server->size_acts;
+ dst->server->num_acts = src->server->num_acts;
+
+ if (src->server->key_acts) {
+ if (src->max_key_code != dst->max_key_code) {
+ tmp = realloc(dst->server->key_acts,
+ (src->max_key_code + 1) * sizeof(unsigned short));
+ if (!tmp)
+ return FALSE;
+ dst->server->key_acts = tmp;
+ }
+ memcpy(dst->server->key_acts, src->server->key_acts,
+ (src->max_key_code + 1) * sizeof(unsigned short));
+ }
+ else {
+ free(dst->server->key_acts);
+ dst->server->key_acts = NULL;
+ }
+
+ if (src->server->behaviors) {
+ if (src->max_key_code != dst->max_key_code) {
+ tmp = realloc(dst->server->behaviors,
+ (src->max_key_code + 1) * sizeof(XkbBehavior));
+ if (!tmp)
+ return FALSE;
+ dst->server->behaviors = tmp;
+ }
+ memcpy(dst->server->behaviors, src->server->behaviors,
+ (src->max_key_code + 1) * sizeof(XkbBehavior));
+ }
+ else {
+ free(dst->server->behaviors);
+ dst->server->behaviors = NULL;
+ }
+
+ memcpy(dst->server->vmods, src->server->vmods, XkbNumVirtualMods);
+
+ if (src->server->vmodmap) {
+ if (src->max_key_code != dst->max_key_code) {
+ tmp = realloc(dst->server->vmodmap,
+ (src->max_key_code + 1) * sizeof(unsigned short));
+ if (!tmp)
+ return FALSE;
+ dst->server->vmodmap = tmp;
+ }
+ memcpy(dst->server->vmodmap, src->server->vmodmap,
+ (src->max_key_code + 1) * sizeof(unsigned short));
+ }
+ else {
+ free(dst->server->vmodmap);
+ dst->server->vmodmap = NULL;
+ }
+ }
+ else {
+ if (dst->server)
+ XkbFreeServerMap(dst, XkbAllServerInfoMask, TRUE);
+ }
+
+ return TRUE;
+}
+
+static Bool
+_XkbCopyNames(XkbDescPtr src, XkbDescPtr dst)
+{
+ void *tmp = NULL;
+
+ /* names */
+ if (src->names) {
+ if (!dst->names) {
+ dst->names = calloc(1, sizeof(XkbNamesRec));
+ if (!dst->names)
+ return FALSE;
+ }
+
+ if (src->names->keys) {
+ if (src->max_key_code != dst->max_key_code) {
+ tmp = realloc(dst->names->keys,
+ (src->max_key_code + 1) * sizeof(XkbKeyNameRec));
+ if (!tmp)
+ return FALSE;
+ dst->names->keys = tmp;
+ }
+ memcpy(dst->names->keys, src->names->keys,
+ (src->max_key_code + 1) * sizeof(XkbKeyNameRec));
+ }
+ else {
+ free(dst->names->keys);
+ dst->names->keys = NULL;
+ }
+
+ if (src->names->num_key_aliases) {
+ if (src->names->num_key_aliases != dst->names->num_key_aliases) {
+ tmp = realloc(dst->names->key_aliases,
+ src->names->num_key_aliases *
+ sizeof(XkbKeyAliasRec));
+ if (!tmp)
+ return FALSE;
+ dst->names->key_aliases = tmp;
+ }
+ memcpy(dst->names->key_aliases, src->names->key_aliases,
+ src->names->num_key_aliases * sizeof(XkbKeyAliasRec));
+ }
+ else {
+ free(dst->names->key_aliases);
+ dst->names->key_aliases = NULL;
+ }
+ dst->names->num_key_aliases = src->names->num_key_aliases;
+
+ if (src->names->num_rg) {
+ if (src->names->num_rg != dst->names->num_rg) {
+ tmp = realloc(dst->names->radio_groups,
+ src->names->num_rg * sizeof(Atom));
+ if (!tmp)
+ return FALSE;
+ dst->names->radio_groups = tmp;
+ }
+ memcpy(dst->names->radio_groups, src->names->radio_groups,
+ src->names->num_rg * sizeof(Atom));
+ }
+ else {
+ free(dst->names->radio_groups);
+ }
+ dst->names->num_rg = src->names->num_rg;
+
+ dst->names->keycodes = src->names->keycodes;
+ dst->names->geometry = src->names->geometry;
+ dst->names->symbols = src->names->symbols;
+ dst->names->types = src->names->types;
+ dst->names->compat = src->names->compat;
+ dst->names->phys_symbols = src->names->phys_symbols;
+
+ memcpy(dst->names->vmods, src->names->vmods,
+ XkbNumVirtualMods * sizeof(Atom));
+ memcpy(dst->names->indicators, src->names->indicators,
+ XkbNumIndicators * sizeof(Atom));
+ memcpy(dst->names->groups, src->names->groups,
+ XkbNumKbdGroups * sizeof(Atom));
+ }
+ else {
+ if (dst->names)
+ XkbFreeNames(dst, XkbAllNamesMask, TRUE);
+ }
+
+ return TRUE;
+}
+
+static Bool
+_XkbCopyCompat(XkbDescPtr src, XkbDescPtr dst)
+{
+ void *tmp = NULL;
+
+ /* compat */
+ if (src->compat) {
+ if (!dst->compat) {
+ dst->compat = calloc(1, sizeof(XkbCompatMapRec));
+ if (!dst->compat)
+ return FALSE;
+ }
+
+ if (src->compat->sym_interpret && src->compat->num_si) {
+ if (src->compat->num_si != dst->compat->size_si) {
+ tmp = realloc(dst->compat->sym_interpret,
+ src->compat->num_si * sizeof(XkbSymInterpretRec));
+ if (!tmp)
+ return FALSE;
+ dst->compat->sym_interpret = tmp;
+ }
+ memcpy(dst->compat->sym_interpret, src->compat->sym_interpret,
+ src->compat->num_si * sizeof(XkbSymInterpretRec));
+
+ dst->compat->num_si = src->compat->num_si;
+ dst->compat->size_si = src->compat->num_si;
+ }
+ else {
+ if (dst->compat->sym_interpret && dst->compat->size_si)
+ free(dst->compat->sym_interpret);
+
+ dst->compat->sym_interpret = NULL;
+ dst->compat->num_si = 0;
+ dst->compat->size_si = 0;
+ }
+
+ memcpy(dst->compat->groups, src->compat->groups,
+ XkbNumKbdGroups * sizeof(XkbModsRec));
+ }
+ else {
+ if (dst->compat)
+ XkbFreeCompatMap(dst, XkbAllCompatMask, TRUE);
+ }
+
+ return TRUE;
+}
+
+static Bool
+_XkbCopyGeom(XkbDescPtr src, XkbDescPtr dst)
+{
+ void *tmp = NULL;
+ int i = 0, j = 0, k = 0;
+ XkbColorPtr scolor = NULL, dcolor = NULL;
+ XkbDoodadPtr sdoodad = NULL, ddoodad = NULL;
+ XkbOutlinePtr soutline = NULL, doutline = NULL;
+ XkbPropertyPtr sprop = NULL, dprop = NULL;
+ XkbRowPtr srow = NULL, drow = NULL;
+ XkbSectionPtr ssection = NULL, dsection = NULL;
+ XkbShapePtr sshape = NULL, dshape = NULL;
+
+ /* geometry */
+ if (src->geom) {
+ if (!dst->geom) {
+ dst->geom = calloc(sizeof(XkbGeometryRec), 1);
+ if (!dst->geom)
+ return FALSE;
+ }
+
+ /* properties */
+ if (src->geom->num_properties) {
+ if (src->geom->num_properties != dst->geom->sz_properties) {
+ /* If we've got more properties in the destination than
+ * the source, run through and free all the excess ones
+ * first. */
+ if (src->geom->num_properties < dst->geom->sz_properties) {
+ for (i = src->geom->num_properties,
+ dprop = dst->geom->properties + i;
+ i < dst->geom->num_properties;
+ i++, dprop++) {
+ free(dprop->name);
+ free(dprop->value);
+ }
+ }
+
+ if (dst->geom->sz_properties)
+ tmp = realloc(dst->geom->properties,
+ src->geom->num_properties *
+ sizeof(XkbPropertyRec));
+ else
+ tmp = malloc(src->geom->num_properties *
+ sizeof(XkbPropertyRec));
+ if (!tmp)
+ return FALSE;
+ dst->geom->properties = tmp;
+ }
+
+ /* We don't set num_properties as we need it to try and avoid
+ * too much reallocing. */
+ dst->geom->sz_properties = src->geom->num_properties;
+
+ if (dst->geom->sz_properties > dst->geom->num_properties) {
+ memset(dst->geom->properties + dst->geom->num_properties, 0,
+ (dst->geom->sz_properties - dst->geom->num_properties) *
+ sizeof(XkbPropertyRec));
+ }
+
+ for (i = 0,
+ sprop = src->geom->properties,
+ dprop = dst->geom->properties;
+ i < src->geom->num_properties;
+ i++, sprop++, dprop++) {
+ if (i < dst->geom->num_properties) {
+ if (strlen(sprop->name) != strlen(dprop->name)) {
+ tmp = realloc(dprop->name, strlen(sprop->name) + 1);
+ if (!tmp)
+ return FALSE;
+ dprop->name = tmp;
+ }
+ if (strlen(sprop->value) != strlen(dprop->value)) {
+ tmp = realloc(dprop->value, strlen(sprop->value) + 1);
+ if (!tmp)
+ return FALSE;
+ dprop->value = tmp;
+ }
+ strcpy(dprop->name, sprop->name);
+ strcpy(dprop->value, sprop->value);
+ }
+ else {
+ dprop->name = xstrdup(sprop->name);
+ dprop->value = xstrdup(sprop->value);
+ }
+ }
+
+ /* ... which is already src->geom->num_properties. */
+ dst->geom->num_properties = dst->geom->sz_properties;
+ }
+ else {
+ if (dst->geom->sz_properties) {
+ for (i = 0, dprop = dst->geom->properties;
+ i < dst->geom->num_properties;
+ i++, dprop++) {
+ free(dprop->name);
+ free(dprop->value);
+ }
+ free(dst->geom->properties);
+ dst->geom->properties = NULL;
+ }
+
+ dst->geom->num_properties = 0;
+ dst->geom->sz_properties = 0;
+ }
+
+ /* colors */
+ if (src->geom->num_colors) {
+ if (src->geom->num_colors != dst->geom->sz_colors) {
+ if (src->geom->num_colors < dst->geom->sz_colors) {
+ for (i = src->geom->num_colors,
+ dcolor = dst->geom->colors + i;
+ i < dst->geom->num_colors;
+ i++, dcolor++) {
+ free(dcolor->spec);
+ }
+ }
+
+ if (dst->geom->sz_colors)
+ tmp = realloc(dst->geom->colors,
+ src->geom->num_colors *
+ sizeof(XkbColorRec));
+ else
+ tmp = malloc(src->geom->num_colors *
+ sizeof(XkbColorRec));
+ if (!tmp)
+ return FALSE;
+ dst->geom->colors = tmp;
+ }
+
+ dst->geom->sz_colors = src->geom->num_colors;
+
+ if (dst->geom->sz_colors > dst->geom->num_colors) {
+ memset(dst->geom->colors + dst->geom->num_colors, 0,
+ (dst->geom->sz_colors - dst->geom->num_colors) *
+ sizeof(XkbColorRec));
+ }
+
+ for (i = 0,
+ scolor = src->geom->colors,
+ dcolor = dst->geom->colors;
+ i < src->geom->num_colors;
+ i++, scolor++, dcolor++) {
+ if (i < dst->geom->num_colors) {
+ if (strlen(scolor->spec) != strlen(dcolor->spec)) {
+ tmp = realloc(dcolor->spec, strlen(scolor->spec) + 1);
+ if (!tmp)
+ return FALSE;
+ dcolor->spec = tmp;
+ }
+ strcpy(dcolor->spec, scolor->spec);
+ }
+ else {
+ dcolor->spec = xstrdup(scolor->spec);
+ }
+ dcolor->pixel = scolor->pixel;
+ }
+
+ dst->geom->num_colors = dst->geom->sz_colors;
+ }
+ else {
+ if (dst->geom->sz_colors) {
+ for (i = 0, dcolor = dst->geom->colors;
+ i < dst->geom->num_colors;
+ i++, dcolor++) {
+ free(dcolor->spec);
+ }
+ free(dst->geom->colors);
+ dst->geom->colors = NULL;
+ }
+
+ dst->geom->num_colors = 0;
+ dst->geom->sz_colors = 0;
+ }
+
+ /* shapes */
+ /* shapes break down into outlines, which break down into points. */
+ if (dst->geom->num_shapes) {
+ for (i = 0, dshape = dst->geom->shapes;
+ i < dst->geom->num_shapes;
+ i++, dshape++) {
+ for (j = 0, doutline = dshape->outlines;
+ j < dshape->num_outlines;
+ j++, doutline++) {
+ if (doutline->sz_points)
+ free(doutline->points);
+ }
+
+ if (dshape->sz_outlines) {
+ free(dshape->outlines);
+ dshape->outlines = NULL;
+ }
+
+ dshape->num_outlines = 0;
+ dshape->sz_outlines = 0;
+ }
+ }
+
+ if (src->geom->num_shapes) {
+ tmp = calloc(src->geom->num_shapes, sizeof(XkbShapeRec));
+ if (!tmp)
+ return FALSE;
+ dst->geom->shapes = tmp;
+
+ for (i = 0, sshape = src->geom->shapes, dshape = dst->geom->shapes;
+ i < src->geom->num_shapes;
+ i++, sshape++, dshape++) {
+ if (sshape->num_outlines) {
+ tmp = calloc(sshape->num_outlines, sizeof(XkbOutlineRec));
+ if (!tmp)
+ return FALSE;
+ dshape->outlines = tmp;
+
+ for (j = 0,
+ soutline = sshape->outlines,
+ doutline = dshape->outlines;
+ j < sshape->num_outlines;
+ j++, soutline++, doutline++) {
+ if (soutline->num_points) {
+ tmp = malloc(soutline->num_points *
+ sizeof(XkbPointRec));
+ if (!tmp)
+ return FALSE;
+ doutline->points = tmp;
+
+ memcpy(doutline->points, soutline->points,
+ soutline->num_points * sizeof(XkbPointRec));
+
+ doutline->corner_radius = soutline->corner_radius;
+ }
+
+ doutline->num_points = soutline->num_points;
+ doutline->sz_points = soutline->num_points;
+ }
+ }
+
+ dshape->num_outlines = sshape->num_outlines;
+ dshape->sz_outlines = sshape->num_outlines;
+ dshape->name = sshape->name;
+ dshape->bounds = sshape->bounds;
+
+ dshape->approx = NULL;
+ if (sshape->approx && sshape->num_outlines > 0) {
+
+ const ptrdiff_t approx_idx =
+ sshape->approx - sshape->outlines;
+
+ if (approx_idx < dshape->num_outlines) {
+ dshape->approx = dshape->outlines + approx_idx;
+ } else {
+ LogMessage(X_WARNING, "XKB: approx outline "
+ "index is out of range\n");
+ }
+ }
+
+ dshape->primary = NULL;
+ if (sshape->primary && sshape->num_outlines > 0) {
+
+ const ptrdiff_t primary_idx =
+ sshape->primary - sshape->outlines;
+
+ if (primary_idx < dshape->num_outlines) {
+ dshape->primary = dshape->outlines + primary_idx;
+ } else {
+ LogMessage(X_WARNING, "XKB: primary outline "
+ "index is out of range\n");
+ }
+ }
+ }
+
+ dst->geom->num_shapes = src->geom->num_shapes;
+ dst->geom->sz_shapes = src->geom->num_shapes;
+ }
+ else {
+ if (dst->geom->sz_shapes) {
+ free(dst->geom->shapes);
+ }
+ dst->geom->shapes = NULL;
+ dst->geom->num_shapes = 0;
+ dst->geom->sz_shapes = 0;
+ }
+
+ /* sections */
+ /* sections break down into doodads, and also into rows, which break
+ * down into keys. */
+ if (dst->geom->num_sections) {
+ for (i = 0, dsection = dst->geom->sections;
+ i < dst->geom->num_sections;
+ i++, dsection++) {
+ for (j = 0, drow = dsection->rows;
+ j < dsection->num_rows;
+ j++, drow++) {
+ if (drow->num_keys)
+ free(drow->keys);
+ }
+
+ if (dsection->num_rows)
+ free(dsection->rows);
+
+ /* cut and waste from geom/doodad below. */
+ for (j = 0, ddoodad = dsection->doodads;
+ j < dsection->num_doodads;
+ j++, ddoodad++) {
+ if (ddoodad->any.type == XkbTextDoodad) {
+ free(ddoodad->text.text);
+ ddoodad->text.text = NULL;
+ free(ddoodad->text.font);
+ ddoodad->text.font = NULL;
+ }
+ else if (ddoodad->any.type == XkbLogoDoodad) {
+ free(ddoodad->logo.logo_name);
+ ddoodad->logo.logo_name = NULL;
+ }
+ }
+
+ free(dsection->doodads);
+ }
+
+ dst->geom->num_sections = 0;
+ dst->geom->sections = NULL;
+ }
+
+ if (src->geom->num_sections) {
+ if (dst->geom->sz_sections)
+ tmp = realloc(dst->geom->sections,
+ src->geom->num_sections *
+ sizeof(XkbSectionRec));
+ else
+ tmp = malloc(src->geom->num_sections * sizeof(XkbSectionRec));
+ if (!tmp)
+ return FALSE;
+ memset(tmp, 0, src->geom->num_sections * sizeof(XkbSectionRec));
+ dst->geom->sections = tmp;
+ dst->geom->num_sections = src->geom->num_sections;
+ dst->geom->sz_sections = src->geom->num_sections;
+
+ for (i = 0,
+ ssection = src->geom->sections,
+ dsection = dst->geom->sections;
+ i < src->geom->num_sections;
+ i++, ssection++, dsection++) {
+ *dsection = *ssection;
+ if (ssection->num_rows) {
+ tmp = calloc(ssection->num_rows, sizeof(XkbRowRec));
+ if (!tmp)
+ return FALSE;
+ dsection->rows = tmp;
+ }
+ dsection->num_rows = ssection->num_rows;
+ dsection->sz_rows = ssection->num_rows;
+
+ for (j = 0, srow = ssection->rows, drow = dsection->rows;
+ j < ssection->num_rows;
+ j++, srow++, drow++) {
+ if (srow->num_keys) {
+ tmp = malloc(srow->num_keys * sizeof(XkbKeyRec));
+ if (!tmp)
+ return FALSE;
+ drow->keys = tmp;
+ memcpy(drow->keys, srow->keys,
+ srow->num_keys * sizeof(XkbKeyRec));
+ }
+ drow->num_keys = srow->num_keys;
+ drow->sz_keys = srow->num_keys;
+ drow->top = srow->top;
+ drow->left = srow->left;
+ drow->vertical = srow->vertical;
+ drow->bounds = srow->bounds;
+ }
+
+ if (ssection->num_doodads) {
+ tmp = calloc(ssection->num_doodads, sizeof(XkbDoodadRec));
+ if (!tmp)
+ return FALSE;
+ dsection->doodads = tmp;
+ }
+ else {
+ dsection->doodads = NULL;
+ }
+
+ dsection->sz_doodads = ssection->num_doodads;
+ for (k = 0,
+ sdoodad = ssection->doodads,
+ ddoodad = dsection->doodads;
+ k < ssection->num_doodads;
+ k++, sdoodad++, ddoodad++) {
+ memcpy(ddoodad , sdoodad, sizeof(XkbDoodadRec));
+ if (sdoodad->any.type == XkbTextDoodad) {
+ if (sdoodad->text.text)
+ ddoodad->text.text =
+ strdup(sdoodad->text.text);
+ if (sdoodad->text.font)
+ ddoodad->text.font =
+ strdup(sdoodad->text.font);
+ }
+ else if (sdoodad->any.type == XkbLogoDoodad) {
+ if (sdoodad->logo.logo_name)
+ ddoodad->logo.logo_name =
+ strdup(sdoodad->logo.logo_name);
+ }
+ }
+ dsection->overlays = NULL;
+ dsection->sz_overlays = 0;
+ dsection->num_overlays = 0;
+ }
+ }
+ else {
+ if (dst->geom->sz_sections) {
+ free(dst->geom->sections);
+ }
+
+ dst->geom->sections = NULL;
+ dst->geom->num_sections = 0;
+ dst->geom->sz_sections = 0;
+ }
+
+ /* doodads */
+ if (dst->geom->num_doodads) {
+ for (i = src->geom->num_doodads,
+ ddoodad = dst->geom->doodads +
+ src->geom->num_doodads;
+ i < dst->geom->num_doodads;
+ i++, ddoodad++) {
+ if (ddoodad->any.type == XkbTextDoodad) {
+ free(ddoodad->text.text);
+ ddoodad->text.text = NULL;
+ free(ddoodad->text.font);
+ ddoodad->text.font = NULL;
+ }
+ else if (ddoodad->any.type == XkbLogoDoodad) {
+ free(ddoodad->logo.logo_name);
+ ddoodad->logo.logo_name = NULL;
+ }
+ }
+ dst->geom->num_doodads = 0;
+ dst->geom->doodads = NULL;
+ }
+
+ if (src->geom->num_doodads) {
+ if (dst->geom->sz_doodads)
+ tmp = realloc(dst->geom->doodads,
+ src->geom->num_doodads *
+ sizeof(XkbDoodadRec));
+ else
+ tmp = malloc(src->geom->num_doodads *
+ sizeof(XkbDoodadRec));
+ if (!tmp)
+ return FALSE;
+ memset(tmp, 0, src->geom->num_doodads * sizeof(XkbDoodadRec));
+ dst->geom->doodads = tmp;
+
+ dst->geom->sz_doodads = src->geom->num_doodads;
+
+ for (i = 0,
+ sdoodad = src->geom->doodads,
+ ddoodad = dst->geom->doodads;
+ i < src->geom->num_doodads;
+ i++, sdoodad++, ddoodad++) {
+ memcpy(ddoodad , sdoodad, sizeof(XkbDoodadRec));
+ if (sdoodad->any.type == XkbTextDoodad) {
+ if (sdoodad->text.text)
+ ddoodad->text.text = strdup(sdoodad->text.text);
+ if (sdoodad->text.font)
+ ddoodad->text.font = strdup(sdoodad->text.font);
+ }
+ else if (sdoodad->any.type == XkbLogoDoodad) {
+ if (sdoodad->logo.logo_name)
+ ddoodad->logo.logo_name =
+ strdup(sdoodad->logo.logo_name);
+ }
+ }
+
+ dst->geom->num_doodads = dst->geom->sz_doodads;
+ }
+ else {
+ if (dst->geom->sz_doodads) {
+ free(dst->geom->doodads);
+ }
+
+ dst->geom->doodads = NULL;
+ dst->geom->num_doodads = 0;
+ dst->geom->sz_doodads = 0;
+ }
+
+ /* key aliases */
+ if (src->geom->num_key_aliases) {
+ if (src->geom->num_key_aliases != dst->geom->sz_key_aliases) {
+ if (dst->geom->sz_key_aliases)
+ tmp = realloc(dst->geom->key_aliases,
+ src->geom->num_key_aliases *
+ 2 * XkbKeyNameLength);
+ else
+ tmp = malloc(src->geom->num_key_aliases *
+ 2 * XkbKeyNameLength);
+ if (!tmp)
+ return FALSE;
+ dst->geom->key_aliases = tmp;
+
+ dst->geom->sz_key_aliases = src->geom->num_key_aliases;
+ }
+
+ memcpy(dst->geom->key_aliases, src->geom->key_aliases,
+ src->geom->num_key_aliases * 2 * XkbKeyNameLength);
+
+ dst->geom->num_key_aliases = dst->geom->sz_key_aliases;
+ }
+ else {
+ free(dst->geom->key_aliases);
+ dst->geom->key_aliases = NULL;
+ dst->geom->num_key_aliases = 0;
+ dst->geom->sz_key_aliases = 0;
+ }
+
+ /* font */
+ if (src->geom->label_font) {
+ if (!dst->geom->label_font) {
+ tmp = malloc(strlen(src->geom->label_font) + 1);
+ if (!tmp)
+ return FALSE;
+ dst->geom->label_font = tmp;
+ }
+ else if (strlen(src->geom->label_font) !=
+ strlen(dst->geom->label_font)) {
+ tmp = realloc(dst->geom->label_font,
+ strlen(src->geom->label_font) + 1);
+ if (!tmp)
+ return FALSE;
+ dst->geom->label_font = tmp;
+ }
+
+ strcpy(dst->geom->label_font, src->geom->label_font);
+ i = XkbGeomColorIndex(src->geom, src->geom->label_color);
+ dst->geom->label_color = &(dst->geom->colors[i]);
+ i = XkbGeomColorIndex(src->geom, src->geom->base_color);
+ dst->geom->base_color = &(dst->geom->colors[i]);
+ }
+ else {
+ free(dst->geom->label_font);
+ dst->geom->label_font = NULL;
+ dst->geom->label_color = NULL;
+ dst->geom->base_color = NULL;
+ }
+
+ dst->geom->name = src->geom->name;
+ dst->geom->width_mm = src->geom->width_mm;
+ dst->geom->height_mm = src->geom->height_mm;
+ }
+ else
+ {
+ if (dst->geom) {
+ /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */
+ XkbFreeGeometry(dst->geom, XkbGeomAllMask, TRUE);
+ dst->geom = NULL;
+ }
+ }
+
+ return TRUE;
+}
+
+static Bool
+_XkbCopyIndicators(XkbDescPtr src, XkbDescPtr dst)
+{
+ /* indicators */
+ if (src->indicators) {
+ if (!dst->indicators) {
+ dst->indicators = malloc(sizeof(XkbIndicatorRec));
+ if (!dst->indicators)
+ return FALSE;
+ }
+ memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec));
+ }
+ else {
+ free(dst->indicators);
+ dst->indicators = NULL;
+ }
+ return TRUE;
+}
+
+static Bool
+_XkbCopyControls(XkbDescPtr src, XkbDescPtr dst)
+{
+ /* controls */
+ if (src->ctrls) {
+ if (!dst->ctrls) {
+ dst->ctrls = malloc(sizeof(XkbControlsRec));
+ if (!dst->ctrls)
+ return FALSE;
+ }
+ memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec));
+ }
+ else {
+ free(dst->ctrls);
+ dst->ctrls = NULL;
+ }
+ return TRUE;
+}
+
+/**
+ * Copy an XKB map from src to dst, reallocating when necessary: if some
+ * map components are present in one, but not in the other, the destination
+ * components will be allocated or freed as necessary.
+ *
+ * Basic map consistency is assumed on both sides, so maps with random
+ * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19)
+ * _will_ cause failures. You've been warned.
+ *
+ * Returns TRUE on success, or FALSE on failure. If this function fails,
+ * dst may be in an inconsistent state: all its pointers are guaranteed
+ * to remain valid, but part of the map may be from src and part from dst.
+ *
+ */
+
+Bool
+XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src)
+{
+
+ if (!src || !dst) {
+ DebugF("XkbCopyKeymap: src (%p) or dst (%p) is NULL\n", src, dst);
+ return FALSE;
+ }
+
+ if (src == dst)
+ return TRUE;
+
+ if (!_XkbCopyClientMap(src, dst)) {
+ DebugF("XkbCopyKeymap: failed to copy client map\n");
+ return FALSE;
+ }
+ if (!_XkbCopyServerMap(src, dst)) {
+ DebugF("XkbCopyKeymap: failed to copy server map\n");
+ return FALSE;
+ }
+ if (!_XkbCopyIndicators(src, dst)) {
+ DebugF("XkbCopyKeymap: failed to copy indicators\n");
+ return FALSE;
+ }
+ if (!_XkbCopyControls(src, dst)) {
+ DebugF("XkbCopyKeymap: failed to copy controls\n");
+ return FALSE;
+ }
+ if (!_XkbCopyNames(src, dst)) {
+ DebugF("XkbCopyKeymap: failed to copy names\n");
+ return FALSE;
+ }
+ if (!_XkbCopyCompat(src, dst)) {
+ DebugF("XkbCopyKeymap: failed to copy compat map\n");
+ return FALSE;
+ }
+ if (!_XkbCopyGeom(src, dst)) {
+ DebugF("XkbCopyKeymap: failed to copy geometry\n");
+ return FALSE;
+ }
+
+ dst->min_key_code = src->min_key_code;
+ dst->max_key_code = src->max_key_code;
+
+ return TRUE;
+}
+
+Bool
+XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src)
+{
+ xkbNewKeyboardNotify nkn;
+ Bool ret;
+
+ if (!dst->key || !src->key)
+ return FALSE;
+
+ memset(&nkn, 0, sizeof(xkbNewKeyboardNotify));
+ nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code;
+ nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code;
+ nkn.deviceID = dst->id;
+ nkn.oldDeviceID = dst->id; /* maybe src->id? */
+ nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code;
+ nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code;
+ nkn.requestMajor = XkbReqCode;
+ nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */
+ nkn.changed = XkbNKN_KeycodesMask;
+ if (src->key->xkbInfo->desc->geom)
+ nkn.changed |= XkbNKN_GeometryMask;
+
+ ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc);
+ if (ret)
+ XkbSendNewKeyboardNotify(dst, &nkn);
+
+ return ret;
+}
+
+int
+XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode)
+{
+ XkbDescPtr xkb = xkbi->desc;
+ int effectiveGroup = xkbState->group;
+
+ if (!XkbKeycodeInRange(xkb, keycode))
+ return -1;
+
+ if (effectiveGroup == XkbGroup1Index)
+ return effectiveGroup;
+
+ if (XkbKeyNumGroups(xkb,keycode) > 1U) {
+ if (effectiveGroup >= XkbKeyNumGroups(xkb,keycode)) {
+ unsigned int gi = XkbKeyGroupInfo(xkb,keycode);
+ switch (XkbOutOfRangeGroupAction(gi)) {
+ default:
+ case XkbWrapIntoRange:
+ effectiveGroup %= XkbKeyNumGroups(xkb, keycode);
+ break;
+ case XkbClampIntoRange:
+ effectiveGroup = XkbKeyNumGroups(xkb, keycode) - 1;
+ break;
+ case XkbRedirectIntoRange:
+ effectiveGroup = XkbOutOfRangeGroupInfo(gi);
+ if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode))
+ effectiveGroup = 0;
+ break;
+ }
+ }
+ }
+ else effectiveGroup = XkbGroup1Index;
+
+ return effectiveGroup;
+}
+
+/* Merge the lockedPtrButtons from all attached SDs for the given master
+ * device into the MD's state.
+ */
+void
+XkbMergeLockedPtrBtns(DeviceIntPtr master)
+{
+ DeviceIntPtr d = inputInfo.devices;
+ XkbSrvInfoPtr xkbi = NULL;
+
+ if (!IsMaster(master))
+ return;
+
+ if (!master->key)
+ return;
+
+ xkbi = master->key->xkbInfo;
+ xkbi->lockedPtrButtons = 0;
+
+ for (; d; d = d->next) {
+ if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key)
+ continue;
+
+ xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons;
+ }
+}