summaryrefslogtreecommitdiff
path: root/gdk/x11/gxid.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/x11/gxid.c')
-rw-r--r--gdk/x11/gxid.c863
1 files changed, 0 insertions, 863 deletions
diff --git a/gdk/x11/gxid.c b/gdk/x11/gxid.c
deleted file mode 100644
index 40b48fa31c..0000000000
--- a/gdk/x11/gxid.c
+++ /dev/null
@@ -1,863 +0,0 @@
-/*
- * gxid version 0.3
- *
- * Copyright 1997 Owen Taylor <owt1@cornell.edu>
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/XInput.h>
-
-#include "gxid_proto.h"
-
-/* #define DEBUG_CLIENTS */
-/* #define DEBUG_EVENTS */
-
-char *program_name;
-Display *dpy;
-Window root_window; /* default root window of dpy */
-int port = 0; /* port to listen on */
-int socket_fd = 0; /* file descriptor of socket */
-typedef struct GxidWindow_ GxidWindow;
-
-typedef struct GxidDevice_ GxidDevice;
-struct GxidDevice_ {
- XID id;
- int exclusive;
- int ispointer;
-
- XDevice *xdevice;
- int motionnotify_type;
- int changenotify_type;
-};
-
-struct GxidWindow_ {
- Window xwindow;
- /* Immediate child of root that is ancestor of window */
- Window root_child;
- int num_devices;
- GxidDevice **devices;
-};
-
-GxidDevice **devices = NULL;
-int num_devices = 0;
-GxidWindow **windows = NULL;
-int num_windows = 0;
-
-void
-handler(int signal)
-{
- fprintf(stderr,"%s: dying on signal %d\n",program_name,signal);
- if (socket_fd)
- close(socket_fd);
- exit(1);
-}
-
-void
-init_socket(void)
-{
- struct sockaddr_in sin;
-
- socket_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- if (socket_fd < 0)
- {
- fprintf (stderr, "%s: error getting socket\n",
- program_name);
- exit(1);
- }
-
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = INADDR_ANY;
-
- if (bind(socket_fd,(struct sockaddr *)(&sin),
- sizeof(struct sockaddr_in)) < 0)
- {
- fprintf (stderr,"%s: cannot bind to port %d\n",
- program_name,port);
- exit(1);
- }
-
- if (listen(socket_fd,5) < 0)
- {
- fprintf (stderr,"%s: error listening on socket\n",
- program_name);
- exit(1);
- };
-}
-
-#define NUM_EVENTC 2
-static void
-enable_device(GxidDevice *dev)
-{
- XEventClass xevc[NUM_EVENTC];
- int num_eventc = NUM_EVENTC;
- int i,j;
-
- if (!dev->xdevice)
- {
- if (dev->ispointer) return;
-
- dev->xdevice = XOpenDevice(dpy, dev->id);
- if (!dev->xdevice) return;
-
- DeviceMotionNotify (dev->xdevice, dev->motionnotify_type,
- xevc[0]);
- ChangeDeviceNotify (dev->xdevice, dev->changenotify_type,
- xevc[1]);
-
- /* compress out zero event classes */
- for (i=0,j=0;i<NUM_EVENTC;i++)
- {
- if (xevc[i]) {
- xevc[j] = xevc[i];
- j++;
- }
- }
- num_eventc = j;
-
- XSelectExtensionEvent (dpy, root_window, xevc, num_eventc);
- }
-}
-
-/* switch the core pointer from whatever it is now to something else,
- return true on success, false otherwise */
-static int
-switch_core_pointer(void)
-{
- GxidDevice *old_pointer = 0;
- GxidDevice *new_pointer = 0;
- int result;
- int i;
-
- for (i=0;i<num_devices;i++)
- {
- if (devices[i]->ispointer)
- old_pointer = devices[i];
- else
- if (!new_pointer && !devices[i]->exclusive)
- new_pointer = devices[i];
- }
-
- if (!old_pointer || !new_pointer)
- return 0;
-
-#ifdef DEBUG_EVENTS
- fprintf(stderr,"gxid: Switching core from %ld to %ld\n",
- old_pointer->id,new_pointer->id);
-#endif
- result = XChangePointerDevice(dpy,new_pointer->xdevice, 0, 1);
- if (result != Success)
- {
- fprintf(stderr,"gxid: Error %d switching core from %ld to %ld\n",
- result, old_pointer->id, new_pointer->id);
- }
- else
- {
- new_pointer->ispointer = 1;
- old_pointer->ispointer = 0;
- if (!old_pointer->xdevice)
- enable_device(old_pointer);
- }
-
- return 1;
-}
-
-void
-disable_device(GxidDevice *dev)
-{
- if (dev->xdevice)
- {
- if (dev->ispointer)
- return;
- XCloseDevice(dpy,dev->xdevice);
- dev->xdevice = 0;
- }
-}
-
-GxidDevice *
-init_device(XDeviceInfo *xdevice)
-{
- GxidDevice *dev = (GxidDevice *)malloc(sizeof(GxidDevice));
- XAnyClassPtr class;
- int num_axes, i;
-
- dev->id = xdevice->id;
- dev->exclusive = 0;
- dev->xdevice = NULL;
-
- dev->ispointer = (xdevice->use == IsXPointer);
-
- /* step through the classes */
-
- num_axes = 0;
- class = xdevice->inputclassinfo;
- for (i=0;i<xdevice->num_classes;i++)
- {
- if (class->class == ValuatorClass)
- {
- XValuatorInfo *xvi = (XValuatorInfo *)class;
- num_axes = xvi->num_axes;
- }
- class = (XAnyClassPtr)(((char *)class) + class->length);
- }
-
- /* return NULL if insufficient axes */
- if (num_axes < 2)
- {
- free((void *)dev);
- return NULL;
- }
-
- if (!dev->ispointer)
- enable_device(dev);
- return dev;
-}
-
-void
-init_xinput(void)
-{
- char **extensions;
- XDeviceInfo *xdevices;
- int num_xdevices;
- int num_extensions;
- int i;
-
- extensions = XListExtensions(dpy, &num_extensions);
- for (i = 0; i < num_extensions &&
- (strcmp(extensions[i], "XInputExtension") != 0); i++);
- XFreeExtensionList(extensions);
- if (i == num_extensions) /* XInput extension not found */
- {
- fprintf(stderr,"XInput extension not found\n");
- exit(1);
- }
-
- xdevices = XListInputDevices(dpy, &num_xdevices);
- devices = (GxidDevice **)malloc(num_xdevices * sizeof(GxidDevice *));
-
- num_devices = 0;
- for(i=0; i<num_xdevices; i++)
- {
- GxidDevice *dev = init_device(&xdevices[i]);
- if (dev)
- devices[num_devices++] = dev;
- }
- XFreeDeviceList(xdevices);
-}
-
-/* If this routine needs fixing, the corresponding routine
- in gdkinputgxi.h will need it too. */
-
-Window
-gxi_find_root_child(Display *dpy, Window w)
-{
- Window root,parent;
- Window *children;
- int nchildren;
-
- parent = w;
- do
- {
- w = parent;
- XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
- if (children) XFree(children);
- }
- while (parent != root);
-
- return w;
-}
-
-int
-handle_claim_device(GxidClaimDevice *msg)
-{
- int i,j;
- XID devid;
- XID winid;
- int exclusive;
- GxidDevice *device = NULL;
- GxidWindow *window = NULL;
-
- if (msg->length != sizeof(GxidClaimDevice))
- {
- fprintf(stderr,"Bad length for ClaimDevice message\n");
- return GXID_RETURN_ERROR;
- }
-
- devid = ntohl(msg->device);
- winid = ntohl(msg->window);
- exclusive = ntohl(msg->exclusive);
-
-#ifdef DEBUG_CLIENTS
- fprintf(stderr,"device %ld claimed (window 0x%lx)\n",devid,winid);
-#endif
-
- for (i=0;i<num_devices;i++)
- {
- if (devices[i]->id == devid)
- {
- device = devices[i];
- break;
- }
- }
- if (!device)
- {
- fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
- return GXID_RETURN_ERROR;
- }
-
- if (device->exclusive)
- {
- /* already in use */
- fprintf(stderr,
- "%s: Device %ld already claimed in exclusive mode\n",
- program_name,devid);
- return GXID_RETURN_ERROR;
- }
-
- if (exclusive)
- {
- for (i=0;i<num_windows;i++)
- {
- for (j=0;j<windows[i]->num_devices;j++)
- if (windows[i]->devices[j]->id == devid)
- {
- /* already in use */
- fprintf(stderr,
- "%s: Can't establish exclusive use of device %ld\n",
- program_name,devid);
- return GXID_RETURN_ERROR;
- }
- }
- if (device->ispointer)
- if (!switch_core_pointer())
- {
- fprintf(stderr,
- "%s: Can't free up core pointer %ld\n",
- program_name,devid);
- return GXID_RETURN_ERROR;
- }
-
- device->exclusive = 1;
- disable_device(device);
- XSelectInput(dpy,winid,StructureNotifyMask);
- }
- else /* !exclusive */
- {
- /* FIXME: this is a bit improper. We probably should do this only
- when a window is first claimed. But we might be fooled if
- an old client died without releasing it's windows. So until
- we look for client-window closings, do it here
-
- (We do look for closings now...)
- */
-
- XSelectInput(dpy,winid,EnterWindowMask|StructureNotifyMask);
- }
-
- for (i=0;i<num_windows;i++)
- {
- if (windows[i]->xwindow == winid)
- {
- window = windows[i];
- break;
- }
- }
-
- /* Create window structure if no devices have been previously
- claimed on it */
- if (!window)
- {
- num_windows++;
- windows = (GxidWindow **)realloc(windows,
- sizeof(GxidWindow*)*num_windows);
- window = (GxidWindow *)malloc(sizeof(GxidWindow));
- windows[num_windows-1] = window;
-
- window->xwindow = winid;
- window->root_child = gxi_find_root_child(dpy,winid);
- window->num_devices = 0;
- window->devices = 0;
- }
-
-
- for (i=0;i<window->num_devices;i++)
- {
- if (window->devices[i] == device)
- return GXID_RETURN_OK;
- }
-
- window->num_devices++;
- window->devices = (GxidDevice **)realloc(window->devices,
- sizeof(GxidDevice*)*num_devices);
- /* we need add the device to the window */
- window->devices[i] = device;
-
- return GXID_RETURN_OK;
-}
-
-int
-handle_release_device(GxidReleaseDevice *msg)
-{
- int i,j;
- XID devid;
- XID winid;
-
- GxidDevice *device = NULL;
-
- if (msg->length != sizeof(GxidReleaseDevice))
- {
- fprintf(stderr,"Bad length for ReleaseDevice message\n");
- return GXID_RETURN_ERROR;
- }
-
- devid = ntohl(msg->device);
- winid = ntohl(msg->window);
-
-#ifdef DEBUG_CLIENTS
- fprintf(stderr,"device %ld released (window 0x%lx)\n",devid,winid);
-#endif
-
- for (i=0;i<num_devices;i++)
- {
- if (devices[i]->id == devid)
- {
- device = devices[i];
- break;
- }
- }
- if (!device)
- {
- fprintf(stderr,"%s: Unknown device id %ld\n",program_name,devid);
- return GXID_RETURN_ERROR;
- }
-
- for (i=0;i<num_windows;i++)
- {
- GxidWindow *w = windows[i];
-
- if (w->xwindow == winid)
- for (j=0;j<w->num_devices;j++)
- if (w->devices[j]->id == devid)
- {
- if (j<w->num_devices-1)
- w->devices[j] = w->devices[w->num_devices-1];
- w->num_devices--;
-
- if (w->num_devices == 0)
- {
- if (i<num_windows-1)
- windows[i] = windows[num_windows-1];
- num_windows--;
-
- free((void *)w);
- /* FIXME: should we deselect input? But what
- what if window is already destroyed */
- }
-
- if (device->exclusive)
- {
- device->exclusive = 0;
- enable_device(device);
- }
- return GXID_RETURN_OK;
- }
- }
-
- /* device/window combination not found */
- fprintf(stderr,
- "%s: Device %ld not claimed for window 0x%lx\n",
- program_name,devid,winid);
- return GXID_RETURN_ERROR;
-}
-
-void
-handle_connection (void)
-{
- GxidMessage msg;
- GxidU32 type;
- GxidU32 length;
- GxidI32 retval;
-
- int conn_fd;
- struct sockaddr_in sin;
- int sin_length;
- int count;
-
- sin_length = sizeof(struct sockaddr_in);
- conn_fd = accept(socket_fd,(struct sockaddr *)&sin,&sin_length);
- if (conn_fd < 0)
- {
- fprintf(stderr,"%s: Error accepting connection\n",
- program_name);
- exit(1);
- }
-
- /* read type and length of message */
-
- count = read(conn_fd,(char *)&msg,2*sizeof(GxidU32));
- if (count != 2*sizeof(GxidU32))
- {
- fprintf(stderr,"%s: Error reading message header\n",
- program_name);
- close(conn_fd);
- return;
- }
- type = ntohl(msg.any.type);
- length = ntohl(msg.any.length);
-
- /* read rest of message */
-
- if ((length > sizeof(GxidMessage)) || (length < 2*sizeof(GxidU32)))
- {
- fprintf(stderr,"%s: Bad message length\n",
- program_name);
- close(conn_fd);
- return;
- }
-
- count = read(conn_fd,2*sizeof(GxidU32) + (char *)&msg,
- length - 2*sizeof(GxidU32));
- if (count != length - 2*sizeof(GxidU32))
- {
- fprintf(stderr,"%s: Error reading message body\n",
- program_name);
- close(conn_fd);
- return;
- }
-
- switch (type)
- {
- case GXID_CLAIM_DEVICE:
- retval = handle_claim_device((GxidClaimDevice *)&msg);
- break;
- case GXID_RELEASE_DEVICE:
- retval = handle_release_device((GxidReleaseDevice *)&msg);
- break;
- default:
- fprintf(stderr,"%s: Unknown message type: %ld (ignoring)\n",
- program_name,type);
- close(conn_fd);
- return;
- }
-
- count = write(conn_fd,&retval,sizeof(GxidI32));
- if (count != sizeof(GxidI32))
- {
- fprintf(stderr,"%s: Error writing return code\n",
- program_name);
- }
-
- close(conn_fd);
-}
-
-void
-handle_motion_notify(XDeviceMotionEvent *event)
-{
- int i,j;
- GxidDevice *old_device = NULL;
- GxidDevice *new_device = NULL;
- Window w, root, child;
- int root_x, root_y, x, y, mask;
-
- for (j=0;j<num_devices;j++)
- {
- if (devices[j]->ispointer)
- old_device = devices[j];
- if (devices[j]->id == event->deviceid)
- new_device = devices[j];
- }
-
- if (new_device && !new_device->exclusive && !new_device->ispointer)
- {
- /* make sure we aren't stealing the pointer back from a slow
- client */
- child = root_window;
- do
- {
- w = child;
- /* FIXME: this fails disasterously if child vanishes between
- calls. (Which is prone to happening since we get events
- on root just as the client exits) */
-
- XQueryPointer(dpy,w,&root,&child,&root_x,&root_y,
- &x,&y,&mask);
- }
- while (child != None);
-
- for (i=0;i<num_windows;i++)
- if (windows[i]->xwindow == w)
- for (j=0;j<windows[i]->num_devices;j++)
- if (windows[i]->devices[j] == new_device)
- return;
-
- /* FIXME: do something smarter with axes */
- XChangePointerDevice(dpy,new_device->xdevice, 0, 1);
- new_device->ispointer = 1;
-
- old_device->ispointer = 0;
- if (!old_device->xdevice)
- enable_device(old_device);
- }
-}
-
-void
-handle_change_notify(XChangeDeviceNotifyEvent *event)
-{
- int j;
- GxidDevice *old_device = NULL;
- GxidDevice *new_device = NULL;
-
-
- for (j=0;j<num_devices;j++)
- {
- if (devices[j]->ispointer)
- old_device = devices[j];
- if (devices[j]->id == event->deviceid)
- new_device = devices[j];
- }
-
-#ifdef DEBUG_EVENTS
- fprintf(stderr,"gxid: ChangeNotify event; old = %ld; new = %ld\n",
- old_device->id, new_device->id);
-#endif
-
- if (old_device != new_device)
- {
- new_device->ispointer = 1;
-
- old_device->ispointer = 0;
- if (!old_device->xdevice)
- enable_device(old_device);
- }
-}
-
-void
-handle_enter_notify(XEnterWindowEvent *event, GxidWindow *window)
-{
- int i;
- GxidDevice *old_pointer = NULL;
- for (i=0;i<num_devices;i++)
- {
- if (devices[i]->ispointer)
- {
- old_pointer = devices[i];
- break;
- }
- }
-
-#ifdef DEBUG_EVENTS
- fprintf(stderr,"gxid: Enter event; oldpointer = %ld\n",
- old_pointer->id);
-#endif
-
- if (old_pointer)
- for (i=0;i<window->num_devices;i++)
- {
- if (window->devices[i] == old_pointer)
- {
- switch_core_pointer();
- break;
- }
- }
-}
-
-void
-handle_destroy_notify(XDestroyWindowEvent *event)
-{
- int i,j;
-
- for (i=0;i<num_windows;i++)
- if (windows[i]->xwindow == event->window)
- {
- GxidWindow *w = windows[i];
-
- for (j=0;j<w->num_devices;j++)
- {
-#ifdef DEBUG_CLIENTS
- fprintf(stderr,"device %ld released on destruction of window 0x%lx.\n",
- w->devices[j]->id,w->xwindow);
-#endif
-
- if (w->devices[j]->exclusive)
- {
- w->devices[j]->exclusive = 0;
- enable_device(devices[j]);
- }
- }
-
- if (i<num_windows-1)
- windows[i] = windows[num_windows-1];
- num_windows--;
-
- if (w->devices)
- free((void *)w->devices);
- free((void *)w);
- /* FIXME: should we deselect input? But what
- what if window is already destroyed */
-
- return;
- }
-}
-
-void
-handle_xevent(void)
-{
- int i;
- XEvent event;
-
- XNextEvent (dpy, &event);
-
-#ifdef DEBUG_EVENTS
- fprintf(stderr,"Event - type = %d; window = 0x%lx\n",
- event.type,event.xany.window);
-#endif
-
- if (event.type == ConfigureNotify)
- {
-#ifdef DEBUG_EVENTS
- XConfigureEvent *xce = (XConfigureEvent *)&event;
- fprintf(stderr," configureNotify: window = 0x%lx\n",xce->window);
-#endif
- }
- else if (event.type == EnterNotify)
- {
- /* pointer entered a claimed window */
- for (i=0;i<num_windows;i++)
- {
- if (event.xany.window == windows[i]->xwindow)
- handle_enter_notify((XEnterWindowEvent *)&event,windows[i]);
- }
- }
- else if (event.type == DestroyNotify)
- {
- /* A claimed window was destroyed */
- for (i=0;i<num_windows;i++)
- {
- if (event.xany.window == windows[i]->xwindow)
- handle_destroy_notify((XDestroyWindowEvent *)&event);
- }
- }
- else
- for (i=0;i<num_devices;i++)
- {
- if (event.type == devices[i]->motionnotify_type)
- {
- handle_motion_notify((XDeviceMotionEvent *)&event);
- break;
- }
- else if (event.type == devices[i]->changenotify_type)
- {
- handle_change_notify((XChangeDeviceNotifyEvent *)&event);
- break;
- }
- }
-}
-
-void
-usage(void)
-{
- fprintf(stderr,"Usage: %s [-d display] [-p --gxid-port port]\n",
- program_name);
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- int i;
- char *display_name = NULL;
- fd_set readfds;
-
- program_name = argv[0];
-
- for (i=1;i<argc;i++)
- {
- if (!strcmp(argv[i],"-d"))
- {
- if (++i >= argc) usage();
- display_name = argv[i];
- }
- else if (!strcmp(argv[i],"--gxid-port") ||
- !strcmp(argv[i],"-p"))
- {
- if (++i >= argc) usage();
- port = atoi(argv[i]);
- break;
- }
- else
- usage();
- }
-
- if (!port)
- {
- char *t = getenv("GXID_PORT");
- if (t)
- port = atoi(t);
- else
- port = 6951;
- }
- /* set up a signal handler so we can clean up if killed */
-
- signal(SIGTERM,handler);
- signal(SIGINT,handler);
-
- /* initialize the X connection */
-
- dpy = XOpenDisplay (display_name);
- if (!dpy)
- {
- fprintf (stderr, "%s: unable to open display '%s'\n",
- program_name, XDisplayName (display_name));
- exit (1);
- }
-
- root_window = DefaultRootWindow(dpy);
-
- /* We'll want to do this in the future if we are to support
- gxid monitoring visibility information for clients */
-#if 0
- XSelectInput(dpy,root_window,SubstructureNotifyMask);
-#endif
- init_xinput();
-
- /* set up our server connection */
-
- init_socket();
-
- /* main loop */
-
- if (XPending(dpy)) /* this seems necessary to get things
- in sync */
- handle_xevent();
- while (1)
- {
-
- FD_ZERO(&readfds);
- FD_SET(ConnectionNumber(dpy),&readfds);
- FD_SET(socket_fd,&readfds);
-
- if (select(8*sizeof(readfds),&readfds,
- (fd_set *)0,(fd_set *)0, (struct timeval *)0) < 0)
- {
- fprintf(stderr,"Error in select\n");
- exit(1);
- }
-
- if (FD_ISSET(socket_fd,&readfds))
- handle_connection();
-
- while (XPending(dpy))
- handle_xevent();
- }
-
- XCloseDisplay (dpy);
- exit (0);
-}