📄 gxid.c
字号:
/* * gxid version 0.3 * * Copyright 1997 Owen Taylor <owt1@cornell.edu>*/#undef G_LOG_DOMAIN#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;voidhandler(int signal){ fprintf(stderr,"%s: dying on signal %d\n",program_name,signal); if (socket_fd) close(socket_fd); exit(1);}voidinit_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 2static voidenable_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 intswitch_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;}voiddisable_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;}voidinit_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. */Windowgxi_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;}inthandle_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;}inthandle_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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -