aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/nxagent/Cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/Cursor.c')
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Cursor.c601
1 files changed, 601 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Cursor.c b/nx-X11/programs/Xserver/hw/nxagent/Cursor.c
new file mode 100644
index 000000000..3ca29fa5e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Cursor.c
@@ -0,0 +1,601 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of NoMachine. Redistribution and use of the present */
+/* software is allowed according to terms specified in the file LICENSE */
+/* which comes in the source distribution. */
+/* */
+/* Check http://www.nomachine.com/licensing.html for applicability. */
+/* */
+/* NX and NoMachine are trademarks of NoMachine S.r.l. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include "X.h"
+#include "Xproto.h"
+#include "screenint.h"
+#include "input.h"
+#include "misc.h"
+#include "cursor.h"
+#include "cursorstr.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "inputstr.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Options.h"
+#include "Screen.h"
+#include "Cursor.h"
+#include "Image.h"
+#include "Visual.h"
+#include "Keyboard.h"
+#include "Args.h"
+#include "Windows.h"
+#include "Events.h"
+#include "Render.h"
+#include "Client.h"
+
+#include "windowstr.h"
+#include "resource.h"
+
+#include "NXlib.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Defined in Display.c. There are huge
+ * problems mixing the GC definition in
+ * Xlib with the server code. This must
+ * be reworked.
+ */
+
+extern XlibGC nxagentBitmapGC;
+
+/*
+ * From NXevents.c.
+ */
+
+extern CursorPtr GetSpriteCursor(void);
+
+void nxagentConstrainCursor(ScreenPtr pScreen, BoxPtr pBox)
+{
+ #ifdef TEST
+
+ int width, height;
+
+ width = nxagentOption(RootWidth);
+ height = nxagentOption(RootHeight);
+
+ if (pBox->x1 <= 0 && pBox->y1 <= 0 &&
+ pBox->x2 >= width && pBox->y2 >= height)
+ {
+ fprintf(stderr, "nxagentConstrainCursor: Called with box [%d,%d,%d,%d]. "
+ "Skipping the operation.\n", pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentConstrainCursor: WARNING! Called with box [%d,%d,%d,%d].\n",
+ pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ }
+
+ #endif
+}
+
+void nxagentCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
+ BoxPtr pHotBox, BoxPtr pTopLeftBox)
+{
+ *pTopLeftBox = *pHotBox;
+}
+
+Bool nxagentDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+
+ /*
+ * Don't define the root cursor
+ * so that nxagent root window
+ * inherits the parent's cursor.
+ */
+
+ Cursor cursor;
+
+ cursor = (pCursor != rootCursor) ? nxagentCursor(pCursor, pScreen): None;
+
+ if (nxagentOption(Rootless) == False)
+ {
+ XDefineCursor(nxagentDisplay,
+ nxagentInputWindows[pScreen -> myNum],
+ cursor);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisplayCursor: Called for cursor at [%p] with private [%p].\n",
+ (void *) pCursor, pCursor->devPriv[pScreen->myNum]);
+ #endif
+ }
+
+ return True;
+}
+
+Bool nxagentRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ XImage *image;
+ Pixmap source, mask;
+ XColor fg_color, bg_color;
+ unsigned long valuemask;
+ XGCValues values;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRealizeCursor: Called for cursor at [%p].\n", (void *) pCursor);
+ #endif
+
+ valuemask = GCFunction |
+ GCPlaneMask |
+ GCForeground |
+ GCBackground |
+ GCClipMask;
+
+ values.function = GXcopy;
+ values.plane_mask = AllPlanes;
+ values.foreground = 1L;
+ values.background = 0L;
+ values.clip_mask = None;
+
+ XChangeGC(nxagentDisplay, nxagentBitmapGC, valuemask, &values);
+
+ source = XCreatePixmap(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ pCursor->bits->width,
+ pCursor->bits->height,
+ 1);
+
+ mask = XCreatePixmap(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ pCursor->bits->width,
+ pCursor->bits->height,
+ 1);
+
+ image = XCreateImage(nxagentDisplay,
+ nxagentDefaultVisual(pScreen),
+ 1, XYBitmap, 0,
+ (char *)pCursor->bits->source,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ BitmapPad(nxagentDisplay), 0);
+
+ /*
+ * If we used nxagentImageNormalize() here,
+ * we'd swap our own cursor data in place.
+ * Change byte_order and bitmap_bit_order
+ * in the image struct to let Xlib do the
+ * swap for us.
+ */
+
+ image -> byte_order = IMAGE_BYTE_ORDER;
+ image -> bitmap_bit_order = BITMAP_BIT_ORDER;
+
+ NXCleanImage(image);
+
+ XPutImage(nxagentDisplay, source, nxagentBitmapGC, image,
+ 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
+
+ XFree(image);
+
+ image = XCreateImage(nxagentDisplay,
+ nxagentDefaultVisual(pScreen),
+ 1, XYBitmap, 0,
+ (char *)pCursor->bits->mask,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ BitmapPad(nxagentDisplay), 0);
+
+ image -> byte_order = IMAGE_BYTE_ORDER;
+ image -> bitmap_bit_order = BITMAP_BIT_ORDER;
+
+ NXCleanImage(image);
+
+ XPutImage(nxagentDisplay, mask, nxagentBitmapGC, image,
+ 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
+
+ XFree(image);
+
+ fg_color.red = pCursor->foreRed;
+ fg_color.green = pCursor->foreGreen;
+ fg_color.blue = pCursor->foreBlue;
+
+ bg_color.red = pCursor->backRed;
+ bg_color.green = pCursor->backGreen;
+ bg_color.blue = pCursor->backBlue;
+
+ pCursor->devPriv[pScreen->myNum] = (pointer) xalloc(sizeof(nxagentPrivCursor));
+
+ nxagentCursorPriv(pCursor, pScreen)->cursor =
+ XCreatePixmapCursor(nxagentDisplay, source, mask, &fg_color,
+ &bg_color, pCursor->bits->xhot, pCursor->bits->yhot);
+
+ nxagentCursorUsesRender(pCursor, pScreen) = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRealizeCursor: Set cursor private at [%p] cursor is [%ld].\n",
+ (void *) nxagentCursorPriv(pCursor, pScreen),
+ nxagentCursorPriv(pCursor, pScreen) -> cursor);
+ #endif
+
+ XFreePixmap(nxagentDisplay, source);
+ XFreePixmap(nxagentDisplay, mask);
+
+ return True;
+}
+
+Bool nxagentUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ if (nxagentCursorUsesRender(pCursor, pScreen))
+ {
+ PicturePtr pPicture = nxagentCursorPicture(pCursor, pScreen);
+
+ FreePicture(pPicture, pPicture -> id);
+ }
+
+ if (nxagentCursor(pCursor, pScreen) != None)
+ {
+ XFreeCursor(nxagentDisplay, nxagentCursor(pCursor, pScreen));
+
+ nxagentCursor(pCursor, pScreen) = None;
+ }
+
+ xfree(nxagentCursorPriv(pCursor, pScreen));
+
+ return True;
+}
+
+void nxagentRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor,
+ Bool displayed)
+{
+ XColor fg_color, bg_color;
+
+ fg_color.red = pCursor->foreRed;
+ fg_color.green = pCursor->foreGreen;
+ fg_color.blue = pCursor->foreBlue;
+
+ bg_color.red = pCursor->backRed;
+ bg_color.green = pCursor->backGreen;
+ bg_color.blue = pCursor->backBlue;
+
+ XRecolorCursor(nxagentDisplay,
+ nxagentCursor(pCursor, pScreen),
+ &fg_color, &bg_color);
+}
+
+Bool nxagentSetCursorPosition(ScreenPtr pScreen, int x, int y,
+ Bool generateEvent)
+{
+ /*
+ * Don't warp the cursor if the requesting client
+ * is the server client itself or a shadow agent.
+ */
+
+ if (requestingClient != NULL &&
+ requestingClient != serverClient &&
+ nxagentClientHint(requestingClient) != NXAGENT_SHADOW)
+ {
+ int i;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetCursorPosition: Moving the cursor at position [%d,%d].\n",
+ x, y);
+ #endif
+
+ for (i = 0; i < nxagentNumScreens; i++)
+ {
+ XWarpPointer(nxagentDisplay, nxagentDefaultWindows[i],
+ nxagentDefaultWindows[pScreen->myNum],
+ 0, 0, 0, 0, x, y);
+ }
+ }
+
+ return True;
+}
+
+void nxagentReconnectCursor(pointer p0, XID x1, pointer p2)
+{
+ Bool* pBool = (Bool*)p2;
+ CursorPtr pCursor = (CursorPtr) p0;
+
+ AnimCurPtr ac;
+ int j;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectCursor: pCursor at [%p]\n", pCursor);
+ #endif
+
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+ fprintf(stderr, "nxagentReconnectCursor: pCursor at [%p]\n", pCursor);
+ #endif
+
+ if (!*pBool || !pCursor)
+ {
+ return;
+ }
+
+ if (nxagentCursorPriv(pCursor, nxagentDefaultScreen) == 0)
+ {
+ if (nxagentIsAnimCursor(pCursor))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectCursor: nxagentIsAnimCursor pCursor at [%p]\n", pCursor);
+ #endif
+
+ ac = nxagentGetAnimCursor(pCursor);
+
+ for (j = 0; j < ac->nelt; j++)
+ {
+ nxagentReconnectCursor (ac->elts[j].pCursor, x1, p2);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectCursor: Iteration [%d] pCursor at [%p]\n", j, ac->elts[j].pCursor);
+ #endif
+ }
+ }
+ }
+
+ else
+ {
+ if (nxagentCursorUsesRender(pCursor, nxagentDefaultScreen))
+ {
+ PicturePtr pPicture = nxagentCursorPicture(pCursor, nxagentDefaultScreen);
+ int ret = 1;
+
+ nxagentReconnectPicture(pPicture, 0, &ret);
+
+ nxagentRenderRealizeCursor(nxagentDefaultScreen, pCursor);
+ }
+ else
+ {
+ xfree(nxagentCursorPriv(pCursor, nxagentDefaultScreen));
+ if (!nxagentRealizeCursor(nxagentDefaultScreen, pCursor))
+ {
+ fprintf(stderr, "nxagentReconnectCursor: nxagentRealizeCursor failed\n");
+ *pBool = False;
+ }
+ }
+ }
+
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+ fprintf(stderr, "nxagentReconnectCursor: %p - ID %lx\n", pCursor, nxagentCursor(pCursor, nxagentDefaultScreen));
+ #endif
+}
+
+/*
+ * The parameter is ignored at the moment.
+ */
+
+void nxagentReDisplayCurrentCursor()
+{
+ CursorPtr pCursor = GetSpriteCursor();
+
+ if (pCursor &&
+ nxagentCursorPriv(pCursor, nxagentDefaultScreen) &&
+ nxagentCursor(pCursor, nxagentDefaultScreen))
+ {
+ nxagentDisplayCursor(nxagentDefaultScreen, pCursor);
+ }
+}
+
+Bool nxagentReconnectAllCursor(void *p0)
+{
+ int i;
+ Bool r = True;
+
+ GrabPtr grab = inputInfo.pointer -> grab;
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_CURSOR_DEBUG)
+ fprintf(stderr, "nxagentReconnectAllCursor\n");
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], RT_CURSOR, nxagentReconnectCursor, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentReconnectAllCursor: WARNING! Failed to recreate "
+ "cursor for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ if (grab)
+ {
+ nxagentReconnectCursor(grab -> cursor, 0, &r);
+ }
+
+ return r;
+}
+
+void nxagentDisconnectCursor(pointer p0, XID x1, pointer p2)
+{
+ Bool* pBool = (Bool *) p2;
+ CursorPtr pCursor = (CursorPtr) p0;
+
+ AnimCurPtr ac;
+ int j;
+
+ if (!*pBool || !pCursor)
+ {
+ return;
+ }
+
+ if (nxagentCursorPriv(pCursor, nxagentDefaultScreen) == 0)
+ {
+ if (nxagentIsAnimCursor(pCursor))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectCursor: nxagentIsAnimCursor pCursor at [%p]\n", pCursor);
+ #endif
+
+ ac = nxagentGetAnimCursor(pCursor);
+
+ for (j = 0; j < ac->nelt; j++)
+ {
+ nxagentDisconnectCursor (ac->elts[j].pCursor, x1, p2);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectCursor: Iteration [%d] pCursor at [%p]\n", j, ac->elts[j].pCursor);
+ #endif
+ }
+ }
+ return;
+ }
+
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+ fprintf(stderr, "nxagentDisconnectCursor: %p - ID %lx\n",
+ pCursor,
+ nxagentCursor(pCursor, nxagentDefaultScreen));
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectCursor: Called with bool [%d].\n", *pBool);
+
+ fprintf(stderr, "nxagentDisconnectCursor: Pointer to cursor is [%p] with counter [%d].\n",
+ (void *) pCursor, pCursor -> refcnt);
+
+ fprintf(stderr, "nxagentDisconnectCursor: Dummy screen is at [%p].\n",
+ (void *) nxagentDefaultScreen);
+
+ fprintf(stderr, "nxagentDisconnectCursor: Cursor private is at [%p].\n",
+ (void *) nxagentCursorPriv(pCursor, nxagentDefaultScreen));
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectCursor: Dummy screen number is [%d].\n",
+ nxagentDefaultScreen -> myNum);
+
+ fprintf(stderr, "nxagentDisconnectCursor: Cursor is [%ld].\n",
+ nxagentCursor(pCursor, nxagentDefaultScreen));
+ #endif
+
+ nxagentCursor(pCursor, nxagentDefaultScreen) = None;
+
+ if (nxagentCursorUsesRender(pCursor, nxagentDefaultScreen))
+ {
+ PicturePtr pPicture = nxagentCursorPicture(pCursor, nxagentDefaultScreen);
+ int ret = 1;
+
+ #if defined(NXAGENT_RECONNECT_CURSOR_DEBUG) || defined(NXAGENT_RECONNECT_PICTURE_DEBUG)
+ fprintf(stderr, "nxagentDisconnectCursor: disconnecting attached picture %p\n", pPicture);
+ #endif
+
+ nxagentDisconnectPicture(pPicture, 0, &ret);
+ }
+}
+
+Bool nxagentDisconnectAllCursor()
+{
+ int i;
+ Bool r = True;
+
+ GrabPtr grab = inputInfo.pointer -> grab;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectAllCursor: Going to iterate through cursor resources.\n");
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], RT_CURSOR, nxagentDisconnectCursor, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentDisconnectAllCursor: WARNING! Failed to disconnect "
+ "cursor for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ if (grab)
+ {
+ nxagentDisconnectCursor(grab -> cursor, 0, &r);
+ }
+
+ return r;
+}
+
+
+#ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+
+void nxagentPrintCursorInfo(CursorPtr pCursor, char msg[])
+{
+ fprintf(stderr, "%s: %p - ID %lx - ref count %d\n",
+ msg, pCursor, nxagentCursor(pCursor, nxagentDefaultScreen), pCursor->refcnt);
+}
+
+void nxagentListCursor(void *p0, void *p1, void *p2)
+{
+ CursorPtr pCursor = (CursorPtr)p0;
+
+ nxagentPrintCursorInfo(pCursor, "CursorDebug:");
+}
+
+void nxagentListCursors(void)
+{
+ int i;
+ Bool r;
+
+ for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], RT_CURSOR, nxagentListCursor, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentListCursors: WARNING! Failed to list "
+ "cursor for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ return True;
+}
+
+#endif /* NXAGENT_RECONNECT_CURSOR_DEBUG */