aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/dmx/dmxprop.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2009-06-28 22:07:26 +0000
committermarha <marha@users.sourceforge.net>2009-06-28 22:07:26 +0000
commit3562e78743202e43aec8727005182a2558117eca (patch)
tree8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xorg-server/hw/dmx/dmxprop.c
downloadvcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz
vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2
vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip
Checked in the following released items:
xkeyboard-config-1.4.tar.gz ttf-bitstream-vera-1.10.tar.gz font-alias-1.0.1.tar.gz font-sun-misc-1.0.0.tar.gz font-sun-misc-1.0.0.tar.gz font-sony-misc-1.0.0.tar.gz font-schumacher-misc-1.0.0.tar.gz font-mutt-misc-1.0.0.tar.gz font-misc-misc-1.0.0.tar.gz font-misc-meltho-1.0.0.tar.gz font-micro-misc-1.0.0.tar.gz font-jis-misc-1.0.0.tar.gz font-isas-misc-1.0.0.tar.gz font-dec-misc-1.0.0.tar.gz font-daewoo-misc-1.0.0.tar.gz font-cursor-misc-1.0.0.tar.gz font-arabic-misc-1.0.0.tar.gz font-winitzki-cyrillic-1.0.0.tar.gz font-misc-cyrillic-1.0.0.tar.gz font-cronyx-cyrillic-1.0.0.tar.gz font-screen-cyrillic-1.0.1.tar.gz font-xfree86-type1-1.0.1.tar.gz font-adobe-utopia-type1-1.0.1.tar.gz font-ibm-type1-1.0.0.tar.gz font-bitstream-type1-1.0.0.tar.gz font-bitstream-speedo-1.0.0.tar.gz font-bh-ttf-1.0.0.tar.gz font-bh-type1-1.0.0.tar.gz font-bitstream-100dpi-1.0.0.tar.gz font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz font-bh-100dpi-1.0.0.tar.gz font-adobe-utopia-100dpi-1.0.1.tar.gz font-adobe-100dpi-1.0.0.tar.gz font-util-1.0.1.tar.gz font-bitstream-75dpi-1.0.0.tar.gz font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz font-adobe-utopia-75dpi-1.0.1.tar.gz font-bh-75dpi-1.0.0.tar.gz bdftopcf-1.0.1.tar.gz font-adobe-75dpi-1.0.0.tar.gz mkfontscale-1.0.6.tar.gz openssl-0.9.8k.tar.gz bigreqsproto-1.0.2.tar.gz xtrans-1.2.2.tar.gz resourceproto-1.0.2.tar.gz inputproto-1.4.4.tar.gz compositeproto-0.4.tar.gz damageproto-1.1.0.tar.gz zlib-1.2.3.tar.gz xkbcomp-1.0.5.tar.gz freetype-2.3.9.tar.gz pthreads-w32-2-8-0-release.tar.gz pixman-0.12.0.tar.gz kbproto-1.0.3.tar.gz evieext-1.0.2.tar.gz fixesproto-4.0.tar.gz recordproto-1.13.2.tar.gz randrproto-1.2.2.tar.gz scrnsaverproto-1.1.0.tar.gz renderproto-0.9.3.tar.gz xcmiscproto-1.1.2.tar.gz fontsproto-2.0.2.tar.gz xextproto-7.0.3.tar.gz xproto-7.0.14.tar.gz libXdmcp-1.0.2.tar.gz libxkbfile-1.0.5.tar.gz libfontenc-1.0.4.tar.gz libXfont-1.3.4.tar.gz libX11-1.1.5.tar.gz libXau-1.0.4.tar.gz libxcb-1.1.tar.gz xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xorg-server/hw/dmx/dmxprop.c')
-rw-r--r--xorg-server/hw/dmx/dmxprop.c347
1 files changed, 347 insertions, 0 deletions
diff --git a/xorg-server/hw/dmx/dmxprop.c b/xorg-server/hw/dmx/dmxprop.c
new file mode 100644
index 000000000..376313d8d
--- /dev/null
+++ b/xorg-server/hw/dmx/dmxprop.c
@@ -0,0 +1,347 @@
+/*
+ * 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
+ *
+ * It is possible for one of the DMX "backend displays" to actually be
+ * smaller than the dimensions of the backend X server. Therefore, it
+ * is possible for more than one of the DMX "backend displays" to be
+ * physically located on the same backend X server. This situation must
+ * be detected so that cursor motion can be handled in an expected
+ * fashion.
+ *
+ * We could analyze the names used for the DMX "backend displays" (e.g.,
+ * the names passed to the -display command-line parameter), but there
+ * are many possible names for a single X display, and failing to detect
+ * sameness leads to very unexpected results. Therefore, whenever the
+ * DMX server opens a window on a backend X server, a property value is
+ * queried and set on that backend to detect when another window is
+ * already open on that server.
+ *
+ * Further, it is possible that two different DMX server instantiations
+ * both have windows on the same physical backend X server. This case
+ * is also detected so that pointer input is not taken from that
+ * particular backend X server.
+ *
+ * The routines in this file handle the property management. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxprop.h"
+#include "dmxlog.h"
+
+/** Holds the window id of all DMX windows on the backend X server. */
+#define DMX_ATOMNAME "DMX_NAME"
+
+/** The identification string of this DMX server */
+#define DMX_IDENT "Xdmx"
+
+extern char *display;
+
+static int dmxPropertyErrorHandler(Display *dpy, XErrorEvent *ev)
+{
+ return 0;
+}
+
+static const unsigned char *dmxPropertyIdentifier(void)
+{
+ /* RATS: These buffers are only used in
+ * length-limited calls. */
+ char hostname[256];
+ static char buf[128];
+ static int initialized = 0;
+
+ if (initialized++) return (unsigned char *)buf;
+
+ XmuGetHostname(hostname, sizeof(hostname));
+ XmuSnprintf(buf, sizeof(buf), "%s:%s:%s", DMX_IDENT, hostname, display);
+ return (unsigned char *)buf;
+}
+
+/** Starting with the \a start screen, iterate over all of the screens
+ * on the same physical X server as \a start, calling \a f with the
+ * screen and the \a closure. (The common case is that \a start is the
+ * only DMX window on the backend X server.) */
+void *dmxPropertyIterate(DMXScreenInfo *start,
+ void *(*f)(DMXScreenInfo *dmxScreen, void *),
+ void *closure)
+{
+ DMXScreenInfo *pt;
+
+ if (!start->next) {
+ if (!start->beDisplay) return NULL;
+ return f(start, closure);
+ }
+
+ for (pt = start->next; /* condition at end of loop */; pt = pt->next) {
+ void *retval;
+ /* beDisplay ban be NULL if a screen was detached */
+ dmxLog(dmxDebug, "pt = %p\n", pt);
+ dmxLog(dmxDebug, "pt->beDisplay = %p\n", pt->beDisplay);
+ if (pt->beDisplay && (retval = f(pt, closure))) return retval;
+ if (pt == start) break;
+ }
+ return NULL;
+}
+
+/** Returns 0 if this is the only Xdmx session on the display; 1
+ * otherwise. */
+static int dmxPropertyCheckOtherServers(DMXScreenInfo *dmxScreen, Atom atom)
+{
+ Display *dpy = dmxScreen->beDisplay;
+ XTextProperty tp;
+ XTextProperty tproot;
+ const char *pt;
+ int retcode = 0;
+ char **list = NULL;
+ int count = 0;
+ int i;
+ int (*dmxOldHandler)(Display *, XErrorEvent *);
+
+ if (!dpy)
+ return 0;
+
+ if (!XGetTextProperty(dpy, RootWindow(dpy,0), &tproot, atom)
+ || !tproot.nitems) return 0;
+
+ /* Ignore BadWindow errors for this
+ * routine because the window id stored
+ * in the property might be old */
+ dmxOldHandler = XSetErrorHandler(dmxPropertyErrorHandler);
+ for (pt = (const char *)tproot.value; pt && *pt; pt = pt ? pt + 1 : NULL) {
+ if ((pt = strchr(pt, ','))) {
+ Window win = strtol(pt+1, NULL, 10);
+ if (XGetTextProperty(dpy, win, &tp, atom) && tp.nitems) {
+ if (!strncmp((char *)tp.value, DMX_IDENT, strlen(DMX_IDENT))) {
+ int flag = 0;
+ for (i = 0; i < count; i++)
+ if (!strcmp(list[i], (char *)tp.value)) {
+ ++flag;
+ break;
+ }
+ if (flag) continue;
+ ++retcode;
+ dmxLogOutputWarning(dmxScreen,
+ "%s also running on %s\n",
+ tp.value, dmxScreen->name);
+ list = xrealloc(list, ++count * sizeof(*list));
+ list[count-1] = xalloc(tp.nitems + 2);
+ strncpy(list[count-1], (char *)tp.value, tp.nitems + 1);
+ }
+ XFree(tp.value);
+ }
+ }
+ }
+ XSetErrorHandler(dmxOldHandler);
+
+ for (i = 0; i < count; i++) xfree(list[i]);
+ xfree(list);
+ XFree(tproot.value);
+ if (!retcode)
+ dmxLogOutput(dmxScreen, "No Xdmx server running on backend\n");
+ return retcode;
+}
+
+/** Returns NULL if this is the only Xdmx window on the display.
+ * Otherwise, returns a pointer to the dmxScreen of the other windows on
+ * the display. */
+static DMXScreenInfo *dmxPropertyCheckOtherWindows(DMXScreenInfo *dmxScreen,
+ Atom atom)
+{
+ Display *dpy = dmxScreen->beDisplay;
+ const unsigned char *id = dmxPropertyIdentifier();
+ XTextProperty tproot;
+ XTextProperty tp;
+ const char *pt;
+ int (*dmxOldHandler)(Display *, XErrorEvent *);
+
+ if (!dpy)
+ return NULL;
+
+ if (!XGetTextProperty(dpy, RootWindow(dpy,0), &tproot, atom)
+ || !tproot.nitems) return 0;
+
+ /* Ignore BadWindow errors for this
+ * routine because the window id stored
+ * in the property might be old */
+ dmxOldHandler = XSetErrorHandler(dmxPropertyErrorHandler);
+ for (pt = (const char *)tproot.value; pt && *pt; pt = pt ? pt + 1 : NULL) {
+ if ((pt = strchr(pt, ','))) {
+ Window win = strtol(pt+1, NULL, 10);
+ if (XGetTextProperty(dpy, win, &tp, atom) && tp.nitems) {
+ dmxLog(dmxDebug,"On %s/%lu: %s\n",
+ dmxScreen->name, win, tp.value);
+ if (!strncmp((char *)tp.value, (char *)id,
+ strlen((char *)id))) {
+ int idx;
+
+ if (!(pt = strchr((char *)tp.value, ','))) continue;
+ idx = strtol(pt+1, NULL, 10);
+ if (idx < 0 || idx >= dmxNumScreens) continue;
+ if (dmxScreens[idx].scrnWin != win) continue;
+ XSetErrorHandler(dmxOldHandler);
+ return &dmxScreens[idx];
+ }
+ XFree(tp.value);
+ }
+ }
+ }
+ XSetErrorHandler(dmxOldHandler);
+ XFree(tproot.value);
+ return 0;
+}
+
+/** Returns 0 if this is the only Xdmx session on the display; 1
+ * otherwise. */
+int dmxPropertyDisplay(DMXScreenInfo *dmxScreen)
+{
+ Atom atom;
+ const unsigned char *id = dmxPropertyIdentifier();
+ Display *dpy = dmxScreen->beDisplay;
+
+ if (!dpy)
+ return 0;
+
+ atom = XInternAtom(dpy, DMX_ATOMNAME, False);
+ if (dmxPropertyCheckOtherServers(dmxScreen, atom)) {
+ dmxScreen->shared = 1;
+ return 1;
+ }
+ XChangeProperty(dpy, RootWindow(dpy,0), atom, XA_STRING, 8,
+ PropModeReplace, id, strlen((char *)id));
+ return 0;
+}
+
+/** Returns 1 if the dmxScreen and the display in \a name are on the
+ * same display, or 0 otherwise. We can't just compare the display
+ * names because there can be multiple synonyms for the same display,
+ * some of which cannot be determined without accessing the display
+ * itself (e.g., domain aliases or machines with multiple NICs). */
+int dmxPropertySameDisplay(DMXScreenInfo *dmxScreen, const char *name)
+{
+ Display *dpy0 = dmxScreen->beDisplay;
+ Atom atom0;
+ XTextProperty tp0;
+ Display *dpy1 = NULL;
+ Atom atom1;
+ XTextProperty tp1;
+ int retval = 0;
+
+ if (!dpy0)
+ return 0;
+
+ tp0.nitems = 0;
+ tp1.nitems = 0;
+
+ if ((atom0 = XInternAtom(dpy0, DMX_ATOMNAME, True)) == None) {
+ dmxLog(dmxWarning, "No atom on %s\n", dmxScreen->name);
+ return 0;
+ }
+ if (!XGetTextProperty(dpy0, RootWindow(dpy0,0), &tp0, atom0)
+ || !tp0.nitems) {
+ dmxLog(dmxWarning, "No text property on %s\n", dmxScreen->name);
+ return 0;
+ }
+
+ if (!(dpy1 = XOpenDisplay(name))) {
+ dmxLog(dmxWarning, "Cannot open %s\n", name);
+ goto cleanup;
+ }
+ atom1 = XInternAtom(dpy1, DMX_ATOMNAME, True);
+ if (atom1 == None) {
+ dmxLog(dmxDebug, "No atom on %s\n", name);
+ goto cleanup;
+ }
+ if (!XGetTextProperty(dpy1, RootWindow(dpy1,0), &tp1, atom1)
+ || !tp1.nitems) {
+ dmxLog(dmxDebug, "No text property on %s\n", name);
+ goto cleanup;
+ }
+ if (!strcmp((char *)tp0.value, (char *)tp1.value)) retval = 1;
+
+ cleanup:
+ if (tp0.nitems) XFree(tp0.value);
+ if (tp1.nitems) XFree(tp1.value);
+ if (dpy1) XCloseDisplay(dpy1);
+ return retval;
+}
+
+/** Prints a log message if \a dmxScreen is on the same backend X server
+ * as some other DMX backend (output) screen. Modifies the property
+ * (#DMX_ATOMNAME) on the backend X server to reflect the creation of \a
+ * dmxScreen.
+ *
+ * The root window of the backend X server holds a list of window ids
+ * for all DMX windows (on this DMX server or some other DMX server).
+ *
+ * This list can then be iterated, and the property for each window can
+ * be examined. This property contains the following tuple (no quotes):
+ *
+ * "#DMX_IDENT:<hostname running DMX>:<display name of DMX>,<screen number>"
+ */
+void dmxPropertyWindow(DMXScreenInfo *dmxScreen)
+{
+ Atom atom;
+ const unsigned char *id = dmxPropertyIdentifier();
+ Display *dpy = dmxScreen->beDisplay;
+ Window win = dmxScreen->scrnWin;
+ DMXScreenInfo *other;
+ char buf[128]; /* RATS: only used with XmuSnprintf */
+
+ if (!dpy)
+ return; /* FIXME: What should be done here if Xdmx is started
+ * with this screen initially detached?
+ */
+
+ atom = XInternAtom(dpy, DMX_ATOMNAME, False);
+ if ((other = dmxPropertyCheckOtherWindows(dmxScreen, atom))) {
+ DMXScreenInfo *tmp = dmxScreen->next;
+ dmxScreen->next = (other->next ? other->next : other);
+ other->next = (tmp ? tmp : dmxScreen);
+ dmxLog(dmxDebug, "%d/%s/%lu and %d/%s/%lu are on the same backend\n",
+ dmxScreen->index, dmxScreen->name, dmxScreen->scrnWin,
+ other->index, other->name, other->scrnWin);
+ }
+
+ XmuSnprintf(buf, sizeof(buf), ".%d,%lu", dmxScreen->index,
+ (long unsigned)win);
+ XChangeProperty(dpy, RootWindow(dpy,0), atom, XA_STRING, 8,
+ PropModeAppend, (unsigned char *)buf, strlen(buf));
+
+ XmuSnprintf(buf, sizeof(buf), "%s,%d", id, dmxScreen->index);
+ XChangeProperty(dpy, win, atom, XA_STRING, 8,
+ PropModeAppend, (unsigned char *)buf, strlen(buf));
+}