Commit 344e8000 authored by Owen Taylor's avatar Owen Taylor Committed by Owen Taylor

Move files into x11 subdirectory.

Sun Oct  3 14:26:15 1999  Owen Taylor  <otaylor@redhat.com>

	* gdk/gxid* gdk/x11/gxid*: Move files into x11 subdirectory.
parent 9c2dea00
Sun Oct 3 14:26:15 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gxid* gdk/x11/gxid*: Move files into x11 subdirectory.
Sun Oct 3 14:16:23 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gdkdrawable.h: Include gdk/gdkdrawable.h with
......
Sun Oct 3 14:26:15 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gxid* gdk/x11/gxid*: Move files into x11 subdirectory.
Sun Oct 3 14:16:23 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gdkdrawable.h: Include gdk/gdkdrawable.h with
......
Sun Oct 3 14:26:15 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gxid* gdk/x11/gxid*: Move files into x11 subdirectory.
Sun Oct 3 14:16:23 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gdkdrawable.h: Include gdk/gdkdrawable.h with
......
Sun Oct 3 14:26:15 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gxid* gdk/x11/gxid*: Move files into x11 subdirectory.
Sun Oct 3 14:16:23 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gdkdrawable.h: Include gdk/gdkdrawable.h with
......
Sun Oct 3 14:26:15 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gxid* gdk/x11/gxid*: Move files into x11 subdirectory.
Sun Oct 3 14:16:23 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gdkdrawable.h: Include gdk/gdkdrawable.h with
......
Sun Oct 3 14:26:15 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gxid* gdk/x11/gxid*: Move files into x11 subdirectory.
Sun Oct 3 14:16:23 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gdkdrawable.h: Include gdk/gdkdrawable.h with
......
Sun Oct 3 14:26:15 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gxid* gdk/x11/gxid*: Move files into x11 subdirectory.
Sun Oct 3 14:16:23 1999 Owen Taylor <otaylor@redhat.com>
* gdk/gdkdrawable.h: Include gdk/gdkdrawable.h with
......
/*
* 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;
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];