summaryrefslogtreecommitdiff
path: root/mi/mipointer.c
diff options
context:
space:
mode:
Diffstat (limited to 'mi/mipointer.c')
-rw-r--r--mi/mipointer.c498
1 files changed, 498 insertions, 0 deletions
diff --git a/mi/mipointer.c b/mi/mipointer.c
new file mode 100644
index 000000000..8617861cd
--- /dev/null
+++ b/mi/mipointer.c
@@ -0,0 +1,498 @@
+/*
+ * mipointer.c
+ */
+
+/* $Xorg: mipointer.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */
+
+/*
+
+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.
+*/
+
+# define NEED_EVENTS
+# include "X.h"
+# include "Xmd.h"
+# include "Xproto.h"
+# include "misc.h"
+# include "windowstr.h"
+# include "pixmapstr.h"
+# include "mi.h"
+# include "scrnintstr.h"
+# include "mipointrst.h"
+# include "cursorstr.h"
+# include "dixstruct.h"
+
+static int miPointerScreenIndex;
+static unsigned long miPointerGeneration = 0;
+
+#define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr))
+#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
+
+/*
+ * until more than one pointer device exists.
+ */
+
+static miPointerRec miPointer;
+
+static Bool miPointerRealizeCursor (), miPointerUnrealizeCursor ();
+static Bool miPointerDisplayCursor ();
+static void miPointerConstrainCursor (), miPointerPointerNonInterestBox();
+static void miPointerCursorLimits ();
+static Bool miPointerSetCursorPosition ();
+
+static Bool miPointerCloseScreen();
+
+static void miPointerMove ();
+
+Bool
+miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
+ ScreenPtr pScreen;
+ miPointerSpriteFuncPtr spriteFuncs;
+ miPointerScreenFuncPtr screenFuncs;
+ Bool waitForUpdate;
+{
+ miPointerScreenPtr pScreenPriv;
+
+ if (miPointerGeneration != serverGeneration)
+ {
+ miPointerScreenIndex = AllocateScreenPrivateIndex();
+ if (miPointerScreenIndex < 0)
+ return FALSE;
+ miPointerGeneration = serverGeneration;
+ }
+ pScreenPriv = (miPointerScreenPtr) xalloc (sizeof (miPointerScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+ pScreenPriv->spriteFuncs = spriteFuncs;
+ pScreenPriv->screenFuncs = screenFuncs;
+ /*
+ * check for uninitialized methods
+ */
+ if (!screenFuncs->EnqueueEvent)
+ screenFuncs->EnqueueEvent = mieqEnqueue;
+ if (!screenFuncs->NewEventScreen)
+ screenFuncs->NewEventScreen = mieqSwitchScreen;
+ pScreenPriv->waitForUpdate = waitForUpdate;
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = miPointerCloseScreen;
+ pScreen->devPrivates[miPointerScreenIndex].ptr = (pointer) pScreenPriv;
+ /*
+ * set up screen cursor method table
+ */
+ pScreen->ConstrainCursor = miPointerConstrainCursor;
+ pScreen->CursorLimits = miPointerCursorLimits;
+ pScreen->DisplayCursor = miPointerDisplayCursor;
+ pScreen->RealizeCursor = miPointerRealizeCursor;
+ pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
+ pScreen->SetCursorPosition = miPointerSetCursorPosition;
+ pScreen->RecolorCursor = miRecolorCursor;
+ pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
+ /*
+ * set up the pointer object
+ */
+ miPointer.pScreen = NULL;
+ miPointer.pSpriteScreen = NULL;
+ miPointer.pCursor = NULL;
+ miPointer.pSpriteCursor = NULL;
+ miPointer.limits.x1 = 0;
+ miPointer.limits.x2 = 32767;
+ miPointer.limits.y1 = 0;
+ miPointer.limits.y2 = 32767;
+ miPointer.confined = FALSE;
+ miPointer.x = 0;
+ miPointer.y = 0;
+ miPointer.history_start = miPointer.history_end = 0;
+ return TRUE;
+}
+
+static Bool
+miPointerCloseScreen (index, pScreen)
+ int index;
+ ScreenPtr pScreen;
+{
+ SetupScreen(pScreen);
+
+ if (pScreen == miPointer.pScreen)
+ miPointer.pScreen = 0;
+ if (pScreen == miPointer.pSpriteScreen)
+ miPointer.pSpriteScreen = 0;
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ xfree ((pointer) pScreenPriv);
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+/*
+ * DIX/DDX interface routines
+ */
+
+static Bool
+miPointerRealizeCursor (pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ SetupScreen(pScreen);
+
+ return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor);
+}
+
+static Bool
+miPointerUnrealizeCursor (pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ SetupScreen(pScreen);
+
+ return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor);
+}
+
+static Bool
+miPointerDisplayCursor (pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ SetupScreen(pScreen);
+
+ miPointer.pCursor = pCursor;
+ miPointer.pScreen = pScreen;
+ miPointerUpdate ();
+ return TRUE;
+}
+
+static void
+miPointerConstrainCursor (pScreen, pBox)
+ ScreenPtr pScreen;
+ BoxPtr pBox;
+{
+ miPointer.limits = *pBox;
+ miPointer.confined = PointerConfinedToScreen();
+}
+
+/*ARGSUSED*/
+static void
+miPointerPointerNonInterestBox (pScreen, pBox)
+ ScreenPtr pScreen;
+ BoxPtr pBox;
+{
+ /* until DIX uses this, this will remain a stub */
+}
+
+/*ARGSUSED*/
+static void
+miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+ BoxPtr pHotBox;
+ BoxPtr pTopLeftBox;
+{
+ *pTopLeftBox = *pHotBox;
+}
+
+static Bool GenerateEvent;
+
+static Bool
+miPointerSetCursorPosition(pScreen, x, y, generateEvent)
+ ScreenPtr pScreen;
+ int x, y;
+ Bool generateEvent;
+{
+ SetupScreen (pScreen);
+
+ GenerateEvent = generateEvent;
+ /* device dependent - must pend signal and call miPointerWarpCursor */
+ (*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y);
+ if (!generateEvent)
+ miPointerUpdate();
+ return TRUE;
+}
+
+/* Once signals are ignored, the WarpCursor function can call this */
+
+void
+miPointerWarpCursor (pScreen, x, y)
+ ScreenPtr pScreen;
+ int x, y;
+{
+ SetupScreen (pScreen);
+
+ if (miPointer.pScreen != pScreen)
+ (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
+
+ if (GenerateEvent)
+ {
+ miPointerMove (pScreen, x, y, GetTimeInMillis());
+ }
+ else
+ {
+ /* everything from miPointerMove except the event and history */
+
+ if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
+ {
+ miPointer.devx = x;
+ miPointer.devy = y;
+ (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
+ }
+ miPointer.x = x;
+ miPointer.y = y;
+ miPointer.pScreen = pScreen;
+ }
+}
+
+/*
+ * Pointer/CursorDisplay interface routines
+ */
+
+int
+miPointerGetMotionBufferSize ()
+{
+ return MOTION_SIZE;
+}
+
+int
+miPointerGetMotionEvents (pPtr, coords, start, stop, pScreen)
+ DeviceIntPtr pPtr;
+ xTimecoord *coords;
+ unsigned long start, stop;
+ ScreenPtr pScreen;
+{
+ int i;
+ int count = 0;
+ miHistoryPtr h;
+
+ for (i = miPointer.history_start; i != miPointer.history_end;)
+ {
+ h = &miPointer.history[i];
+ if (h->event.time >= stop)
+ break;
+ if (h->event.time >= start)
+ {
+ *coords++ = h->event;
+ count++;
+ }
+ if (++i == MOTION_SIZE) i = 0;
+ }
+ return count;
+}
+
+
+/*
+ * miPointerUpdate
+ *
+ * Syncronize the sprite with the cursor - called from ProcessInputEvents
+ */
+
+void
+miPointerUpdate ()
+{
+ ScreenPtr pScreen;
+ miPointerScreenPtr pScreenPriv;
+ int x, y, devx, devy;
+
+ pScreen = miPointer.pScreen;
+ x = miPointer.x;
+ y = miPointer.y;
+ devx = miPointer.devx;
+ devy = miPointer.devy;
+ if (!pScreen)
+ return;
+ pScreenPriv = GetScreenPrivate (pScreen);
+ /*
+ * if the cursor has switched screens, disable the sprite
+ * on the old screen
+ */
+ if (pScreen != miPointer.pSpriteScreen)
+ {
+ if (miPointer.pSpriteScreen)
+ {
+ miPointerScreenPtr pOldPriv;
+
+ pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen);
+ if (miPointer.pCursor)
+ {
+ (*pOldPriv->spriteFuncs->SetCursor)
+ (miPointer.pSpriteScreen, NullCursor, 0, 0);
+ }
+ (*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE);
+ }
+ (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
+ (*pScreenPriv->spriteFuncs->SetCursor)
+ (pScreen, miPointer.pCursor, x, y);
+ miPointer.devx = x;
+ miPointer.devy = y;
+ miPointer.pSpriteCursor = miPointer.pCursor;
+ miPointer.pSpriteScreen = pScreen;
+ }
+ /*
+ * if the cursor has changed, display the new one
+ */
+ else if (miPointer.pCursor != miPointer.pSpriteCursor)
+ {
+ (*pScreenPriv->spriteFuncs->SetCursor)
+ (pScreen, miPointer.pCursor, x, y);
+ miPointer.devx = x;
+ miPointer.devy = y;
+ miPointer.pSpriteCursor = miPointer.pCursor;
+ }
+ else if (x != devx || y != devy)
+ {
+ miPointer.devx = x;
+ miPointer.devy = y;
+ (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
+ }
+}
+
+/*
+ * miPointerDeltaCursor. The pointer has moved dx,dy from it's previous
+ * position.
+ */
+
+void
+miPointerDeltaCursor (dx, dy, time)
+ int dx, dy;
+ unsigned long time;
+{
+ miPointerAbsoluteCursor (miPointer.x + dx, miPointer.y + dy, time);
+}
+
+/*
+ * miPointerAbsoluteCursor. The pointer has moved to x,y
+ */
+
+void
+miPointerAbsoluteCursor (x, y, time)
+ int x, y;
+ unsigned long time;
+{
+ miPointerScreenPtr pScreenPriv;
+ ScreenPtr pScreen;
+ ScreenPtr newScreen;
+
+ pScreen = miPointer.pScreen;
+ if (!pScreen)
+ return; /* called before ready */
+ if (x < 0 || x >= pScreen->width || y < 0 || y >= pScreen->height)
+ {
+ pScreenPriv = GetScreenPrivate (pScreen);
+ if (!miPointer.confined)
+ {
+ newScreen = pScreen;
+ (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y);
+ if (newScreen != pScreen)
+ {
+ pScreen = newScreen;
+ (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
+ pScreenPriv = GetScreenPrivate (pScreen);
+ /* Smash the confine to the new screen */
+ miPointer.limits.x2 = pScreen->width;
+ miPointer.limits.y2 = pScreen->height;
+ }
+ }
+ }
+ /*
+ * constrain the hot-spot to the current
+ * limits
+ */
+ if (x < miPointer.limits.x1)
+ x = miPointer.limits.x1;
+ if (x >= miPointer.limits.x2)
+ x = miPointer.limits.x2 - 1;
+ if (y < miPointer.limits.y1)
+ y = miPointer.limits.y1;
+ if (y >= miPointer.limits.y2)
+ y = miPointer.limits.y2 - 1;
+ if (miPointer.x == x && miPointer.y == y && miPointer.pScreen == pScreen)
+ return;
+ miPointerMove (pScreen, x, y, time);
+}
+
+void
+miPointerPosition (x, y)
+ int *x, *y;
+{
+ *x = miPointer.x;
+ *y = miPointer.y;
+}
+
+/*
+ * miPointerMove. The pointer has moved to x,y on current screen
+ */
+
+static void
+miPointerMove (pScreen, x, y, time)
+ ScreenPtr pScreen;
+ int x, y;
+ unsigned long time;
+{
+ SetupScreen(pScreen);
+ xEvent xE;
+ miHistoryPtr history;
+ int prev, end, start;
+
+ if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
+ {
+ miPointer.devx = x;
+ miPointer.devy = y;
+ (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
+ }
+ miPointer.x = x;
+ miPointer.y = y;
+ miPointer.pScreen = pScreen;
+
+ xE.u.u.type = MotionNotify;
+ xE.u.keyButtonPointer.rootX = x;
+ xE.u.keyButtonPointer.rootY = y;
+ xE.u.keyButtonPointer.time = time;
+ (*pScreenPriv->screenFuncs->EnqueueEvent) (&xE);
+
+ end = miPointer.history_end;
+ start = miPointer.history_start;
+ prev = end - 1;
+ if (end == 0)
+ prev = MOTION_SIZE - 1;
+ history = &miPointer.history[prev];
+ if (end == start || history->event.time != time)
+ {
+ history = &miPointer.history[end];
+ if (++end == MOTION_SIZE)
+ end = 0;
+ if (end == start)
+ {
+ start = end + 1;
+ if (start == MOTION_SIZE)
+ start = 0;
+ miPointer.history_start = start;
+ }
+ miPointer.history_end = end;
+ }
+ history->event.x = x;
+ history->event.y = y;
+ history->event.time = time;
+ history->pScreen = pScreen;
+}
+
+void
+miRegisterPointerDevice (pScreen, pDevice)
+ ScreenPtr pScreen;
+ DevicePtr pDevice;
+{
+ miPointer.pPointer = pDevice;
+}