summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog14
-rw-r--r--Xi/Makefile.am2
-rw-r--r--Xi/chdevcur.c123
-rw-r--r--Xi/chdevcur.h39
-rw-r--r--Xi/extinit.c3
-rw-r--r--dix/events.c17
-rw-r--r--dix/window.c242
-rw-r--r--include/window.h13
-rw-r--r--include/windowstr.h8
9 files changed, 456 insertions, 5 deletions
diff --git a/Changelog b/Changelog
index ef42159ff..431e008b9 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,17 @@
+== 08.01.06 ==
+Xi: Adding ChangeDeviceCursor request
+
+Files:
+ dix/window.c
+ dix/events.c
+ include/window.h
+ include/windowstr.h
+ Xi/extinit.c
+ Xi/chdevcur.c
+ Xi/chdevcur.h
+ Xi/Makefile.am
+
+
== 20.12.06 ==
xfree86: Changing "IsMPDevice" to "SharedPointer" option. Devices will default
to MP devices.
diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 0aa58449f..9e7d1c43e 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -5,6 +5,8 @@ AM_CFLAGS = $(DIX_CFLAGS)
libXi_la_SOURCES = \
allowev.c \
allowev.h \
+ chdevcur.c \
+ chdevcur.h \
chgdctl.c \
chgdctl.h \
chgfctl.c \
diff --git a/Xi/chdevcur.c b/Xi/chdevcur.c
new file mode 100644
index 000000000..fc4b0e01d
--- /dev/null
+++ b/Xi/chdevcur.c
@@ -0,0 +1,123 @@
+/*
+
+Copyright 2006 Peter Hutterer <peter@cs.unisa.edu.au>
+
+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 AUTHOR 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 author 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 author.
+
+*/
+
+/***********************************************************************
+ *
+ * Request to change a given device pointer's cursor.
+ *
+ */
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include "scrnintstr.h" /* screen structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "extinit.h" /* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+
+#include "chdevcur.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to set one pointer's cursor.
+ *
+ */
+
+int
+SProcXChangeDeviceCursor(register ClientPtr client)
+{
+ register char n;
+
+ REQUEST(xChangeDeviceCursorReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
+ return (ProcXChangeDeviceCursor(client));
+}
+
+int ProcXChangeDeviceCursor(register ClientPtr client)
+{
+ int err;
+ WindowPtr pWin = NULL;
+ DeviceIntPtr pDev = NULL;
+ CursorPtr pCursor = NULL;
+
+ REQUEST(xChangeDeviceCursorReq);
+ REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
+
+ pDev = LookupDeviceIntRec(stuff->deviceid);
+ if (pDev == NULL) {
+ SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 0,
+ BadDevice);
+ return Success;
+ }
+
+ if (stuff->win != None)
+ {
+ err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
+ if (err != Success)
+ {
+ SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor,
+ stuff->win, err);
+ return Success;
+ }
+ }
+
+ if (stuff->cursor == None)
+ {
+ if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
+ pCursor = rootCursor;
+ else
+ pCursor = (CursorPtr)None;
+ }
+ else
+ {
+ pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
+ RT_CURSOR, DixReadAccess);
+ if (!pCursor)
+ {
+ SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor,
+ stuff->cursor, BadCursor);
+ return Success;
+ }
+ }
+
+ ChangeWindowDeviceCursor(pWin, pDev, pCursor);
+
+ return Success;
+}
+
diff --git a/Xi/chdevcur.h b/Xi/chdevcur.h
new file mode 100644
index 000000000..92c8d4f0d
--- /dev/null
+++ b/Xi/chdevcur.h
@@ -0,0 +1,39 @@
+/************************************************************
+
+Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au>
+
+ 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 the above listed
+copyright holder(s) not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef CHDEVCUR_H
+#define CHDEVCUR_H 1
+
+int SProcXChangeDeviceCursor(ClientPtr /* client */
+ );
+
+int ProcXChangeDeviceCursor(ClientPtr /* client */
+ );
+
+#endif /* CHDEVCUR_H */
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 7c737a143..82bed5000 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -74,6 +74,7 @@ SOFTWARE.
/* modules local to Xi */
#include "allowev.h"
+#include "chdevcur.h"
#include "chgdctl.h"
#include "chgfctl.h"
#include "chgkbd.h"
@@ -340,6 +341,8 @@ ProcIDispatch(register ClientPtr client)
return (ProcXQueryDevicePointer(client));
else if (stuff->data == X_WarpDevicePointer)
return (ProcXWarpDevicePointer(client));
+ else if (stuff->data == X_ChangeDeviceCursor)
+ return (ProcXChangeDeviceCursor(client));
else {
SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
}
diff --git a/dix/events.c b/dix/events.c
index 81efb708a..3c11723c1 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -921,6 +921,7 @@ PostNewCursor(DeviceIntPtr pDev)
register WindowPtr win;
register GrabPtr grab = pDev->grab;
SpritePtr pSprite = pDev->pSprite;
+ CursorPtr pCursor;
if (syncEvents.playingEvents)
return;
@@ -939,11 +940,19 @@ PostNewCursor(DeviceIntPtr pDev)
else
win = pSprite->win;
for (; win; win = win->parent)
- if (win->optional && win->optional->cursor != NullCursor)
- {
- ChangeToCursor(pDev, win->optional->cursor);
- return;
+ {
+ if (win->optional)
+ {
+ pCursor = WindowGetDeviceCursor(win, pDev);
+ if (!pCursor && win->optional->cursor != NullCursor)
+ pCursor = win->optional->cursor;
+ if (pCursor)
+ {
+ ChangeToCursor(pDev, pCursor);
+ return;
+ }
}
+ }
}
_X_EXPORT WindowPtr
diff --git a/dix/window.c b/dix/window.c
index e33140dd4..604af384d 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -110,6 +110,7 @@ Equipment Corporation.
#include "validate.h"
#include "windowstr.h"
#include "input.h"
+#include "inputstr.h"
#include "resource.h"
#include "colormapst.h"
#include "cursorstr.h"
@@ -135,12 +136,21 @@ Equipment Corporation.
* GetWindowAttributes, DeleteWindow, DestroySubWindows,
* HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
* UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
- *
+ * ChangeWindowDeviceCursor
******/
static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11};
static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88};
+static Bool WindowParentHasDeviceCursor(WindowPtr pWin,
+ DeviceIntPtr pDev,
+ CursorPtr pCurs);
+static Bool
+WindowSeekDeviceCursor(WindowPtr pWin,
+ DeviceIntPtr pDev,
+ DevCursNodePtr* pNode,
+ DevCursNodePtr* pPrev);
+
_X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF;
_X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
@@ -440,6 +450,7 @@ CreateRootWindow(ScreenPtr pScreen)
#endif
#ifdef XINPUT
pWin->optional->inputMasks = NULL;
+ pWin->optional->deviceCursors = NULL;
#endif
pWin->optional->colormap = pScreen->defColormap;
pWin->optional->visual = pScreen->rootVisual;
@@ -3639,6 +3650,17 @@ CheckWindowOptionalNeed (register WindowPtr w)
if (optional->inputMasks != NULL)
return;
#endif
+ if (optional->deviceCursors != NULL)
+ {
+ DevCursNodePtr pNode = optional->deviceCursors;
+ while(pNode)
+ {
+ if (pNode->cursor != None)
+ return;
+ pNode = pNode->next;
+ }
+ }
+
parentOptional = FindWindowWithOptional(w)->optional;
if (optional->visual != parentOptional->visual)
return;
@@ -3683,6 +3705,7 @@ MakeWindowOptional (register WindowPtr pWin)
#endif
#ifdef XINPUT
optional->inputMasks = NULL;
+ optional->deviceCursors = NULL;
#endif
parentOptional = FindWindowWithOptional(pWin)->optional;
optional->visual = parentOptional->visual;
@@ -3731,10 +3754,227 @@ DisposeWindowOptional (register WindowPtr pWin)
}
else
pWin->cursorIsNone = TRUE;
+
+ if (pWin->optional->deviceCursors)
+ {
+ DevCursorList pList;
+ DevCursorList pPrev;
+ pList = pWin->optional->deviceCursors;
+ while(pList)
+ {
+ if (pList->cursor)
+ FreeCursor(pList->cursor, (XID)0);
+ pPrev = pList;
+ pList = pList->next;
+ xfree(pPrev);
+ }
+ pWin->optional->deviceCursors = NULL;
+ }
+
xfree (pWin->optional);
pWin->optional = NULL;
}
+/*
+ * Changes the cursor struct for the given device and the given window.
+ * A cursor that does not have a device cursor set will use whatever the
+ * standard cursor is for the window. If all devices have a cursor set,
+ * changing the window cursor (e.g. using XDefineCursor()) will not have any
+ * visible effect. Only when one of the device cursors is set to None again,
+ * this device's cursor will display the changed standard cursor.
+ *
+ * CursorIsNone of the window struct is NOT modified if you set a device
+ * cursor.
+ *
+ * Assumption: If there is a node for a device in the list, the device has a
+ * cursor. If the cursor is set to None, it is inherited by the parent.
+ */
+int ChangeWindowDeviceCursor(register WindowPtr pWin,
+ DeviceIntPtr pDev,
+ CursorPtr pCursor)
+{
+ DevCursNodePtr pNode, pPrev;
+ CursorPtr pOldCursor = NULL;
+ ScreenPtr pScreen;
+ WindowPtr pChild;
+
+ if (!pWin->optional && !MakeWindowOptional(pWin))
+ return BadAlloc;
+
+ /* 1) Check if window has device cursor set
+ * Yes: 1.1) swap cursor with given cursor if parent does not have same
+ * cursor, free old cursor
+ * 1.2) free old cursor, use parent cursor
+ * No: 1.1) add node to beginning of list.
+ * 1.2) add cursor to node if parent does not have same cursor
+ * 1.3) use parent cursor if parent does not have same cursor
+ * 2) Patch up children if child has a devcursor
+ * 2.1) if child has cursor None, it inherited from parent, set to old
+ * cursor
+ * 2.2) if child has same cursor as new cursor, remove and set to None
+ */
+
+ pScreen = pWin->drawable.pScreen;
+
+ if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev))
+ {
+ /* has device cursor */
+
+ if (pNode->cursor == pCursor)
+ return Success;
+
+ pOldCursor = pNode->cursor;
+
+ if (!pCursor) /* remove from list */
+ {
+ pPrev->next = pNode->next;
+ xfree(pNode);
+ }
+
+ } else
+ {
+ /* no device cursor yet */
+ DevCursNodePtr pNewNode;
+
+ if (!pCursor)
+ return Success;
+
+ pNewNode = (DevCursNodePtr)xalloc(sizeof(DevCursNodeRec));
+ pNewNode->dev = pDev;
+ pNewNode->next = pWin->optional->deviceCursors;
+ pWin->optional->deviceCursors = pNewNode;
+ pNode = pNewNode;
+
+ }
+
+ if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
+ pNode->cursor = None;
+ else
+ {
+ pNode->cursor = pCursor;
+ pCursor->refcnt++;
+ }
+
+ pNode = pPrev = NULL;
+ /* fix up children */
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev))
+ {
+ if (pNode->cursor == None) /* inherited from parent */
+ {
+ pNode->cursor = pOldCursor;
+ pOldCursor->refcnt++;
+ } else if (pNode->cursor == pCursor)
+ {
+ pNode->cursor = None;
+ FreeCursor(pCursor, (Cursor)0); /* fix up refcnt */
+ }
+ }
+ }
+
+ if (pWin->realized)
+ WindowHasNewCursor(pWin);
+
+ if (pOldCursor)
+ FreeCursor(pOldCursor, (Cursor)0);
+
+ /* FIXME: We SHOULD check for an error value here XXX
+ (comment taken from ChangeWindowAttributes) */
+ (*pScreen->ChangeWindowAttributes)(pWin, CWCursor);
+
+ return Success;
+}
+
+/* Get device cursor for given device or None if none is set */
+CursorPtr WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
+{
+ DevCursorList pList;
+
+ if (!pWin->optional || !pWin->optional->deviceCursors)
+ return NULL;
+
+ pList = pWin->optional->deviceCursors;
+
+ while(pList)
+ {
+ if (pList->dev == pDev)
+ {
+ if (pList->cursor == None) /* inherited from parent */
+ return WindowGetDeviceCursor(pWin->parent, pDev);
+ else
+ return pList->cursor;
+ }
+ pList = pList->next;
+ }
+ return NULL;
+}
+
+/* Searches for a DevCursorNode for the given window and device. If one is
+ * found, return True and set pNode and pPrev to the node and to the node
+ * before the node respectively. Otherwise return False.
+ */
+static Bool
+WindowSeekDeviceCursor(WindowPtr pWin,
+ DeviceIntPtr pDev,
+ DevCursNodePtr* pNode,
+ DevCursNodePtr* pPrev)
+{
+ DevCursorList pList;
+
+ if (!pWin->optional)
+ return FALSE;
+
+ pList = pWin->optional->deviceCursors;
+ while(pList)
+ {
+ if (pList->next)
+ {
+ if (pList->next->dev == pDev)
+ {
+ *pNode = pList->next;
+ *pPrev = pList;
+ return TRUE;
+ }
+ }
+ pList = pList->next;
+ }
+ return FALSE;
+}
+
+/* Return True if a parent has the same device cursor set or False if
+ * otherwise
+ */
+static Bool
+WindowParentHasDeviceCursor(WindowPtr pWin,
+ DeviceIntPtr pDev,
+ CursorPtr pCursor)
+{
+ WindowPtr pParent;
+ DevCursNodePtr pParentNode, pParentPrev;
+
+ pParent = pWin->parent;
+ while(pParent)
+ {
+ if (WindowSeekDeviceCursor(pParent, pDev,
+ &pParentNode, &pParentPrev))
+ {
+ /* if there is a node in the list, the win has a dev cursor */
+ if (!pParentNode->cursor) /* inherited. loop needs to cont. */
+ {
+ } else if (pParentNode->cursor == pCursor) /* inherit */
+ return TRUE;
+ else /* different cursor */
+ return FALSE;
+ }
+ else
+ /* parent does not have a device cursor for our device */
+ return FALSE;
+ }
+ return FALSE;
+}
+
+
#ifndef NOLOGOHACK
static void
DrawLogo(WindowPtr pWin)
diff --git a/include/window.h b/include/window.h
index bddeb252b..8f2522cbb 100644
--- a/include/window.h
+++ b/include/window.h
@@ -67,6 +67,10 @@ SOFTWARE.
#define WT_NOMATCH 3
#define NullWindow ((WindowPtr) 0)
+/* Forward declaration, we can't include input.h here */
+struct _DeviceIntRec;
+struct _Cursor;
+
typedef struct _BackingStore *BackingStorePtr;
typedef struct _Window *WindowPtr;
@@ -143,6 +147,15 @@ extern int ChangeWindowAttributes(
XID* /*vlist*/,
ClientPtr /*client*/);
+extern int ChangeWindowDeviceCursor(
+ WindowPtr /*pWin*/,
+ struct _DeviceIntRec* /*pDev*/,
+ struct _Cursor* /*pCursor*/);
+
+extern struct _Cursor* WindowGetDeviceCursor(
+ WindowPtr /*pWin*/,
+ struct _DeviceIntRec* /*pDev*/);
+
/* Quartz support on Mac OS X uses the HIToolbox
framework whose GetWindowAttributes function conflicts here. */
#ifdef __DARWIN__
diff --git a/include/windowstr.h b/include/windowstr.h
index a37dc6b75..4e9c82cb5 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -70,6 +70,13 @@ SOFTWARE.
#define SameBorder(as, a, bs, b) \
EqualPixUnion(as, a, bs, b)
+/* used as NULL-terminated list */
+typedef struct _DevCursorNode {
+ CursorPtr cursor;
+ DeviceIntPtr dev;
+ struct _DevCursorNode* next;
+} DevCursNodeRec, *DevCursNodePtr, *DevCursorList;
+
typedef struct _WindowOpt {
VisualID visual; /* default: same as parent */
CursorPtr cursor; /* default: window.cursorNone */
@@ -89,6 +96,7 @@ typedef struct _WindowOpt {
#ifdef XINPUT
struct _OtherInputMasks *inputMasks; /* default: NULL */
#endif
+ DevCursorList deviceCursors; /* default: NULL */
} WindowOptRec, *WindowOptPtr;
#define BackgroundPixel 2L