]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkinput-x11.c
Added notice to look in AUTHORS and ChangeLog files for a list of changes.
[~andy/gtk] / gdk / x11 / gdkinput-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #if defined(XINPUT_GXI) || defined(XINPUT_XFREE)
28
29 /* Forward declarations */
30 static void gdk_input_get_root_relative_geometry (Display *dpy, Window w, 
31                                                   int *x_ret, int *y_ret,
32                                                   int *width_ret, 
33                                                   int *height_ret);
34 static GdkDevicePrivate *gdk_input_device_new(XDeviceInfo *device, 
35                                               gint include_core);
36 static void gdk_input_common_find_events(GdkWindow *window,
37                                          GdkDevicePrivate *gdkdev,
38                                          gint mask,
39                                          XEventClass *classes,
40                                          int *num_classes);
41 static void gdk_input_common_select_events(GdkWindow *window,
42                                            GdkDevicePrivate *gdkdev);
43 static void gdk_input_translate_coordinates(GdkDevicePrivate *gdkdev,
44                                             GdkInputWindow *input_window,
45                                             gint *axis_data,
46                                             gdouble *x, gdouble *y,
47                                             gdouble *pressure,
48                                             gdouble *xtilt, gdouble *ytilt);
49 static guint gdk_input_translate_state(guint state, guint device_state);
50 static gint gdk_input_common_init(gint include_core);
51 static gint  gdk_input_common_other_event (GdkEvent *event, 
52                                            XEvent *xevent, 
53                                            GdkInputWindow *input_window,
54                                            GdkDevicePrivate *gdkdev);
55 static void gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes);
56 static GdkTimeCoord * gdk_input_common_motion_events (GdkWindow *window,
57                                                       guint32 deviceid,
58                                                       guint32 start,
59                                                       guint32 stop,
60                                                       gint *nevents_return);
61 static void  gdk_input_common_get_pointer     (GdkWindow       *window,
62                                                guint32     deviceid,
63                                                gdouble         *x,
64                                                gdouble         *y,
65                                                gdouble         *pressure,
66                                                gdouble         *xtilt,
67                                                gdouble         *ytilt,
68                                                GdkModifierType *mask);
69
70 #define GDK_MAX_DEVICE_CLASSES 13
71
72 /* Global variables */
73
74 static gint gdk_input_root_width;
75 static gint gdk_input_root_height;
76
77 static void
78 gdk_input_get_root_relative_geometry(Display *dpy, Window w, int *x_ret, int *y_ret,
79                                int *width_ret, int *height_ret)
80 {
81   Window root,parent;
82   Window *children;
83   guint nchildren;
84   gint x,y;
85   guint width, height;
86   gint xc,yc;
87   guint widthc,heightc,border_widthc,depthc;
88   
89   XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
90   if (children) XFree(children);
91   XGetGeometry(dpy,w,&root,&x,&y,&width,&height,&border_widthc,
92                &depthc);
93   x += border_widthc;
94   y += border_widthc;
95
96   while (root != parent)
97     {
98       w = parent;
99       XQueryTree(dpy,w,&root,&parent,&children,&nchildren);
100       if (children) XFree(children);
101       XGetGeometry(dpy,w,&root,&xc,&yc,&widthc,&heightc,
102                    &border_widthc,&depthc);
103       x += xc + border_widthc;
104       y += yc + border_widthc;
105     }
106
107   if (x_ret)
108     *x_ret = x;
109   if (y_ret)
110     *y_ret = y;
111   if (width_ret)
112     *width_ret = width;
113   if (height_ret)
114     *height_ret = height;
115 }
116
117 static GdkDevicePrivate *
118 gdk_input_device_new(XDeviceInfo *device, gint include_core)
119 {
120   GdkDevicePrivate *gdkdev;
121   gchar *tmp_name, *p;
122   XAnyClassPtr class;
123   gint i,j;
124
125   gdkdev = g_new(GdkDevicePrivate,1);
126
127   gdkdev->info.deviceid = device->id;
128   if (device->name[0]) {
129     gdkdev->info.name = g_new(char, strlen(device->name)+1);
130     strcpy(gdkdev->info.name,device->name);
131   } else {
132     /* XFree86 3.2 gives an empty name to the default core devices,
133        (fixed in 3.2A) */
134     gdkdev->info.name = g_strdup("pointer");
135     strcpy(gdkdev->info.name,"pointer");
136     gdkdev->info.source = GDK_SOURCE_MOUSE;
137   }
138
139   gdkdev->info.mode = GDK_MODE_DISABLED;
140
141   /* Try to figure out what kind of device this is by its name -
142      could invite a very, very, long list... Lowercase name
143      for comparison purposes */
144
145   tmp_name = g_strdup(gdkdev->info.name);
146   for (p = tmp_name; *p; p++)
147     {
148       if (*p >= 'A' && *p <= 'Z')
149         *p += 'a' - 'A';
150     }
151   
152   if (!strcmp (tmp_name, "pointer"))
153     gdkdev->info.source = GDK_SOURCE_MOUSE;
154   else if (!strcmp (tmp_name, "wacom") ||
155            !strcmp (tmp_name, "pen"))
156     gdkdev->info.source = GDK_SOURCE_PEN;
157   else if (!strcmp (tmp_name, "eraser"))
158     gdkdev->info.source = GDK_SOURCE_ERASER;
159   else if (!strcmp (tmp_name, "cursor"))
160     gdkdev->info.source = GDK_SOURCE_CURSOR;
161   else
162     gdkdev->info.source = GDK_SOURCE_PEN;
163
164   g_free(tmp_name);
165
166   gdkdev->xdevice = NULL;
167
168   /* step through the classes */
169
170   gdkdev->info.num_axes = 0;
171   gdkdev->info.num_keys = 0;
172   gdkdev->info.keys = NULL;
173   gdkdev->axes = 0;
174   gdkdev->info.has_cursor = 0;
175   gdkdev->needs_update = FALSE;
176   gdkdev->claimed = FALSE;
177   gdkdev->button_state = 0;
178
179   class = device->inputclassinfo;
180   for (i=0;i<device->num_classes;i++) 
181     {
182       switch (class->class) {
183       case ButtonClass:
184         {
185           break;
186         }
187       case KeyClass:
188         {
189           XKeyInfo *xki = (XKeyInfo *)class;
190           /* Hack to catch XFree86 3.3.1 bug. Other devices better
191            * not have exactly 25 keys... 
192            */
193           if ((xki->min_keycode == 8) && (xki->max_keycode == 32))
194             {
195               gdkdev->info.num_keys = 32;
196               gdkdev->min_keycode = 1;
197             }
198           else
199             {
200               gdkdev->info.num_keys = xki->max_keycode - xki->min_keycode + 1;
201               gdkdev->min_keycode = xki->min_keycode;
202             }
203           gdkdev->info.keys = g_new (GdkDeviceKey, gdkdev->info.num_keys);
204
205           for (j=0; j<gdkdev->info.num_keys; j++)
206             {
207               gdkdev->info.keys[j].keyval = 0;
208               gdkdev->info.keys[j].modifiers = 0;
209             }
210
211           break;
212         }
213       case ValuatorClass:
214         {
215           XValuatorInfo *xvi = (XValuatorInfo *)class;
216           gdkdev->info.num_axes = xvi->num_axes;
217           gdkdev->axes = g_new(GdkAxisInfo, xvi->num_axes);
218           gdkdev->info.axes = g_new(GdkAxisUse, xvi->num_axes);
219           for (j=0;j<xvi->num_axes;j++)
220             {
221               gdkdev->axes[j].resolution = 
222                 gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
223               gdkdev->axes[j].min_value =
224                 gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
225               gdkdev->axes[j].max_value =
226                 gdkdev->axes[j].xmax_value = xvi->axes[j].max_value;
227               gdkdev->info.axes[j] = GDK_AXIS_IGNORE;
228             }
229           j=0;
230           if (j<xvi->num_axes)
231             gdkdev->info.axes[j++] = GDK_AXIS_X;
232           if (j<xvi->num_axes)
233             gdkdev->info.axes[j++] = GDK_AXIS_Y;
234           if (j<xvi->num_axes)
235             gdkdev->info.axes[j++] = GDK_AXIS_PRESSURE;
236           if (j<xvi->num_axes)
237             gdkdev->info.axes[j++] = GDK_AXIS_XTILT;
238           if (j<xvi->num_axes)
239             gdkdev->info.axes[j++] = GDK_AXIS_YTILT;
240           
241           /* set up reverse lookup on axis use */
242           for (j=GDK_AXIS_IGNORE;j<GDK_AXIS_LAST;j++)
243             gdkdev->axis_for_use[j] = -1;
244           
245           for (j=0;j<xvi->num_axes;j++)
246             if (gdkdev->info.axes[j] != GDK_AXIS_IGNORE)
247               gdkdev->axis_for_use[gdkdev->info.axes[j]] = j;
248                        
249           break;
250         }
251       }
252       class = (XAnyClassPtr)(((char *)class) + class->length);
253     }
254   /* return NULL if no axes */
255   if (!gdkdev->info.num_axes || !gdkdev->axes ||
256       (!include_core && device->use == IsXPointer))
257     {
258       g_free(gdkdev->info.name);
259       if (gdkdev->axes)
260         g_free(gdkdev->axes);
261       if (gdkdev->info.keys)
262         g_free(gdkdev->info.keys);
263       g_free(gdkdev);
264       return NULL;
265     }
266
267   if (device->use != IsXPointer)
268     {
269       int error_warn = gdk_error_warnings;
270
271       gdk_error_warnings = 0;
272       gdk_error_code = 0;
273       gdkdev->xdevice = XOpenDevice(gdk_display, gdkdev->info.deviceid);
274       gdk_error_warnings = error_warn;
275
276       /* return NULL if device is not ready */
277       if (gdk_error_code)
278         {
279           g_free (gdkdev->info.name);
280           if (gdkdev->axes)
281             g_free (gdkdev->axes);
282           if (gdkdev->info.keys)
283             g_free (gdkdev->info.keys);
284           if (gdkdev->info.axes)
285             g_free (gdkdev->info.axes);
286           g_free (gdkdev);
287
288           return NULL;
289         }
290     }
291
292   gdkdev->buttonpress_type = 0;
293   gdkdev->buttonrelease_type = 0;
294   gdkdev->keypress_type = 0;
295   gdkdev->keyrelease_type = 0;
296   gdkdev->motionnotify_type = 0;
297   gdkdev->proximityin_type = 0;
298   gdkdev->proximityout_type = 0;
299   gdkdev->changenotify_type = 0;
300
301   return gdkdev;
302 }
303
304 static void
305 gdk_input_common_find_events(GdkWindow *window,
306                              GdkDevicePrivate *gdkdev,
307                              gint mask,
308                              XEventClass *classes,
309                              int *num_classes)
310 {
311   gint i;
312   XEventClass class;
313   
314   i = 0;
315   /* We have to track press and release events in pairs to keep
316      track of button state correctly and implement grabbing for
317      the gxi support */
318   if (mask & GDK_BUTTON_PRESS_MASK || mask & GDK_BUTTON_RELEASE_MASK)
319     {
320       DeviceButtonPress (gdkdev->xdevice, gdkdev->buttonpress_type,
321                              class);
322       if (class != 0)
323           classes[i++] = class;
324       DeviceButtonPressGrab (gdkdev->xdevice, 0, class);
325       if (class != 0)
326           classes[i++] = class;
327       DeviceButtonRelease (gdkdev->xdevice, gdkdev->buttonrelease_type,
328                            class);
329       if (class != 0)
330           classes[i++] = class;
331     }
332   if (mask & GDK_POINTER_MOTION_MASK)
333     {
334       DeviceMotionNotify  (gdkdev->xdevice, gdkdev->motionnotify_type, class);
335       if (class != 0)
336           classes[i++] = class;
337     }
338   else
339     if (mask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK |
340                 GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_MOTION_MASK |
341                 GDK_POINTER_MOTION_HINT_MASK))
342       {
343         /* Make sure gdkdev->motionnotify_type is set */
344         DeviceMotionNotify  (gdkdev->xdevice, gdkdev->motionnotify_type, class);
345       }
346   if (mask & GDK_BUTTON1_MOTION_MASK)
347     {
348       DeviceButton1Motion  (gdkdev->xdevice, 0, class);
349       if (class != 0)
350           classes[i++] = class;
351     }
352   if (mask & GDK_BUTTON2_MOTION_MASK)
353     {
354       DeviceButton2Motion  (gdkdev->xdevice, 0, class);
355       if (class != 0)
356           classes[i++] = class;
357     }
358   if (mask & GDK_BUTTON3_MOTION_MASK)
359     {
360       DeviceButton3Motion  (gdkdev->xdevice, 0, class);
361       if (class != 0)
362           classes[i++] = class;
363     }
364   if (mask & GDK_BUTTON_MOTION_MASK)
365     {
366       DeviceButtonMotion  (gdkdev->xdevice, 0, class);
367       if (class != 0)
368           classes[i++] = class;
369     }
370   if (mask & GDK_POINTER_MOTION_HINT_MASK)
371     {
372       /* We'll get into trouble if the macros change, but at least we'll
373          know about it, and we avoid warnings now */
374       DevicePointerMotionHint (gdkdev->xdevice, 0, class);
375       if (class != 0)
376           classes[i++] = class;
377     }
378   if (mask & GDK_KEY_PRESS_MASK)
379     {
380       DeviceKeyPress (gdkdev->xdevice, gdkdev->keypress_type, class);
381       if (class != 0)
382           classes[i++] = class;
383     }
384   if (mask & GDK_KEY_RELEASE_MASK)
385     {
386       DeviceKeyRelease (gdkdev->xdevice, gdkdev->keyrelease_type, class);
387       if (class != 0)
388           classes[i++] = class;
389     }
390   if (mask & GDK_PROXIMITY_IN_MASK)
391     {
392       ProximityIn   (gdkdev->xdevice, gdkdev->proximityin_type, class);
393       if (class != 0)
394           classes[i++] = class;
395     }
396   if (mask & GDK_PROXIMITY_OUT_MASK)
397     {
398       ProximityOut  (gdkdev->xdevice, gdkdev->proximityout_type, class);
399       if (class != 0)
400           classes[i++] = class;
401     }
402
403   *num_classes = i;
404 }
405
406 static void
407 gdk_input_common_select_events(GdkWindow *window,
408                                GdkDevicePrivate *gdkdev)
409 {
410   XEventClass classes[GDK_MAX_DEVICE_CLASSES];
411   gint num_classes;
412
413   if (gdkdev->info.mode == GDK_MODE_DISABLED)
414     gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes);
415   else
416     gdk_input_common_find_events(window, gdkdev, 
417                                  ((GdkWindowPrivate *)window)->extension_events,
418                                  classes, &num_classes);
419   
420   XSelectExtensionEvent (gdk_display,
421                          GDK_WINDOW_XWINDOW(window),
422                          classes, num_classes);
423 }
424
425 gint 
426 gdk_input_common_init(gint include_core)
427 {
428   char **extensions;
429   XDeviceInfo   *devices;
430   int num_devices;
431   int num_extensions, loop;
432   Display *display = gdk_display;
433
434   /* Init global vars */
435   gdk_window_get_geometry(NULL, /* use root window */
436                           NULL,NULL,
437                           &gdk_input_root_width,&gdk_input_root_height, 
438                           NULL);
439
440   /* Init XInput extension */
441   
442   extensions = XListExtensions(display, &num_extensions);
443   for (loop = 0; loop < num_extensions &&
444          (strcmp(extensions[loop], "XInputExtension") != 0); loop++);
445   XFreeExtensionList(extensions);
446   gdk_input_devices = NULL;
447   if (loop < num_extensions)
448     {
449       /* XInput extension found */
450
451       devices = XListInputDevices(display, &num_devices);
452   
453       for(loop=0; loop<num_devices; loop++)
454         {
455           GdkDevicePrivate *gdkdev = gdk_input_device_new(&devices[loop],
456                                                       include_core);
457           if (gdkdev)
458             gdk_input_devices = g_list_append(gdk_input_devices, gdkdev);
459         }
460       XFreeDeviceList(devices);
461     }
462
463   gdk_input_devices = g_list_append (gdk_input_devices, &gdk_input_core_info);
464
465   return TRUE;
466 }
467
468 static void
469 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
470                                  GdkInputWindow *input_window,
471                                  gint *axis_data,
472                                  gdouble *x, gdouble *y, gdouble *pressure,
473                                  gdouble *xtilt, gdouble *ytilt)
474 {
475   GdkWindowPrivate *win_priv;
476
477   int x_axis, y_axis, pressure_axis, xtilt_axis, ytilt_axis;
478
479   double device_width, device_height;
480   double x_offset, y_offset, x_scale, y_scale;
481
482   win_priv = (GdkWindowPrivate *) input_window->window;
483
484   x_axis = gdkdev->axis_for_use[GDK_AXIS_X];
485   y_axis = gdkdev->axis_for_use[GDK_AXIS_Y];
486   pressure_axis = gdkdev->axis_for_use[GDK_AXIS_PRESSURE];
487   xtilt_axis = gdkdev->axis_for_use[GDK_AXIS_XTILT];
488   ytilt_axis = gdkdev->axis_for_use[GDK_AXIS_YTILT];
489
490   device_width = gdkdev->axes[x_axis].max_value - 
491                    gdkdev->axes[x_axis].min_value;
492   device_height = gdkdev->axes[y_axis].max_value - 
493                     gdkdev->axes[y_axis].min_value;
494
495   if (gdkdev->info.mode == GDK_MODE_SCREEN) 
496     {
497       x_scale = gdk_input_root_width / device_width;
498       y_scale = gdk_input_root_height / device_height;
499
500       x_offset = - input_window->root_x;
501       y_offset = - input_window->root_y;
502     }
503   else                          /* GDK_MODE_WINDOW */
504     {
505       double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
506         (device_width*gdkdev->axes[x_axis].resolution);
507
508       if (device_aspect * win_priv->width >= win_priv->height)
509         {
510           /* device taller than window */
511           x_scale = win_priv->width / device_width;
512           y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
513             / gdkdev->axes[y_axis].resolution;
514
515           x_offset = 0;
516           y_offset = -(device_height * y_scale - 
517                                win_priv->height)/2;
518         }
519       else
520         {
521           /* window taller than device */
522           y_scale = win_priv->height / device_height;
523           x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
524             / gdkdev->axes[x_axis].resolution;
525
526           y_offset = 0;
527           x_offset = - (device_width * x_scale - win_priv->width)/2;
528         }
529     }
530   
531   if (x) *x = x_offset + x_scale*axis_data[x_axis];
532   if (y) *y = y_offset + y_scale*axis_data[y_axis];
533
534   if (pressure)
535     {
536       if (pressure_axis != -1)
537         *pressure = ((double)axis_data[pressure_axis] 
538                      - gdkdev->axes[pressure_axis].min_value) 
539           / (gdkdev->axes[pressure_axis].max_value 
540              - gdkdev->axes[pressure_axis].min_value);
541       else
542         *pressure = 0.5;
543     }
544
545   if (xtilt)
546     {
547       if (xtilt_axis != -1)
548         {
549           *xtilt = 2. * (double)(axis_data[xtilt_axis] - 
550                                  (gdkdev->axes[xtilt_axis].min_value +
551                                   gdkdev->axes[xtilt_axis].max_value)/2) /
552             (gdkdev->axes[xtilt_axis].max_value -
553              gdkdev->axes[xtilt_axis].min_value);
554         }
555       else *xtilt = 0;
556     }
557   
558   if (ytilt)
559     {
560       if (ytilt_axis != -1)
561         {
562           *ytilt = 2. * (double)(axis_data[ytilt_axis] - 
563                                  (gdkdev->axes[ytilt_axis].min_value +
564                                   gdkdev->axes[ytilt_axis].max_value)/2) /
565             (gdkdev->axes[ytilt_axis].max_value -
566              gdkdev->axes[ytilt_axis].min_value);
567         }
568       else
569         *ytilt = 0;
570     }
571 }
572
573 /* combine the state of the core device and the device state
574    into one - for now we do this in a simple-minded manner -
575    we just take the keyboard portion of the core device and
576    the button portion (all of?) the device state.
577    Any button remapping should go on here. */
578 static guint
579 gdk_input_translate_state(guint state, guint device_state)
580 {
581   return device_state | (state & 0xFF);
582 }
583
584 static gint 
585 gdk_input_common_other_event (GdkEvent *event, 
586                               XEvent *xevent, 
587                               GdkInputWindow *input_window,
588                               GdkDevicePrivate *gdkdev)
589 {
590   if ((xevent->type == gdkdev->buttonpress_type) ||
591       (xevent->type == gdkdev->buttonrelease_type)) 
592     {
593       XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
594
595       if (xdbe->type == gdkdev->buttonpress_type)
596         {
597           event->button.type = GDK_BUTTON_PRESS;
598           gdkdev->button_state |= 1 << xdbe->button;
599         }
600       else
601         {
602           event->button.type = GDK_BUTTON_RELEASE;
603           gdkdev->button_state &= ~(1 << xdbe->button);
604         }
605       event->button.window = input_window->window;
606       event->button.time = xdbe->time;
607       event->button.source = gdkdev->info.source;
608       event->button.deviceid = xdbe->deviceid;
609
610       gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data,
611                                        &event->button.x,&event->button.y,
612                                        &event->button.pressure,
613                                        &event->button.xtilt, 
614                                        &event->button.ytilt);
615       event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state);
616       event->button.button = xdbe->button;
617
618       GDK_NOTE (EVENTS,
619         g_print ("button %s:\t\twindow: %ld  device: %ld  x,y: %f %f  button: %d\n",
620                  (event->button.type == GDK_BUTTON_PRESS) ? "press" : "release",
621                  xdbe->window,
622                  xdbe->deviceid,
623                  event->button.x, event->button.y,
624                  xdbe->button));
625
626       return TRUE;
627   }
628
629   if ((xevent->type == gdkdev->keypress_type) ||
630       (xevent->type == gdkdev->keyrelease_type))
631     {
632       XDeviceKeyEvent *xdke = (XDeviceKeyEvent *)(xevent);
633
634       GDK_NOTE (EVENTS,
635         g_print ("device key %s:\twindow: %ld  device: %ld  keycode: %d\n",
636                  (event->key.type == GDK_KEY_PRESS) ? "press" : "release",
637                  xdke->window,
638                  xdke->deviceid,
639                  xdke->keycode));
640
641       if (xdke->keycode < gdkdev->min_keycode ||
642           xdke->keycode >= gdkdev->min_keycode + gdkdev->info.num_keys)
643         {
644           g_warning ("Invalid device key code received");
645           return FALSE;
646         }
647       
648       event->key.keyval = gdkdev->info.keys[xdke->keycode - gdkdev->min_keycode].keyval;
649
650       if (event->key.keyval == 0) 
651         {
652           GDK_NOTE (EVENTS,
653             g_print ("\t\ttranslation - NONE\n"));
654           
655           return FALSE;
656         }
657
658       event->key.type = (xdke->type == gdkdev->keypress_type) ?
659         GDK_KEY_PRESS : GDK_KEY_RELEASE;
660
661       event->key.window = input_window->window;
662       event->key.time = xdke->time;
663
664       event->key.state = gdk_input_translate_state(xdke->state, xdke->device_state)
665         | gdkdev->info.keys[xdke->keycode - gdkdev->min_keycode].modifiers;
666
667       /* Add a string translation for the key event */
668       if ((event->key.keyval >= 0x20) && (event->key.keyval <= 0xFF))
669         {
670           event->key.length = 1;
671           event->key.string = g_new (gchar, 2);
672           event->key.string[0] = (gchar)event->key.keyval;
673           event->key.string[1] = 0;
674         }
675       else
676         {
677           event->key.length = 0;
678           event->key.string = g_new0 (gchar, 1);
679         }
680
681       GDK_NOTE (EVENTS,
682         g_print ("\t\ttranslation - keyval: %d modifiers: %#x\n",
683                  event->key.keyval,
684                  event->key.state));
685
686       return TRUE;
687     }
688
689   if (xevent->type == gdkdev->motionnotify_type) 
690     {
691       XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
692
693       gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data,
694                                       &event->motion.x,&event->motion.y,
695                                       &event->motion.pressure,
696                                       &event->motion.xtilt, 
697                                       &event->motion.ytilt);
698
699       event->motion.type = GDK_MOTION_NOTIFY;
700       event->motion.window = input_window->window;
701       event->motion.time = xdme->time;
702       event->motion.deviceid = xdme->deviceid;
703       event->motion.state = gdk_input_translate_state(xdme->state,
704                                                       xdme->device_state);
705       event->motion.is_hint = xdme->is_hint;
706       event->motion.source = gdkdev->info.source;
707       event->motion.deviceid = xdme->deviceid;
708
709       GDK_NOTE (EVENTS,
710         g_print ("motion notify:\t\twindow: %ld  device: %ld  x,y: %f %f  state %#4x  hint: %s\n",
711                  xdme->window,
712                  xdme->deviceid,
713                  event->motion.x, event->motion.y,
714                  event->motion.state,
715                  (xdme->is_hint) ? "true" : "false"));
716       
717       
718       return TRUE;
719     }
720
721   if (xevent->type == gdkdev->proximityin_type ||
722       xevent->type == gdkdev->proximityout_type)
723     {
724       XProximityNotifyEvent *xpne = (XProximityNotifyEvent *)(xevent);
725
726       event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
727         GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
728       event->proximity.window = input_window->window;
729       event->proximity.time = xpne->time;
730       event->proximity.source = gdkdev->info.source;
731       event->proximity.deviceid = xpne->deviceid;
732       
733       return TRUE;
734   }
735
736   return -1;                    /* wasn't one of our event types */
737 }
738
739 static void
740 gdk_input_common_set_axes (guint32 deviceid, GdkAxisUse *axes)
741 {
742   int i;
743   GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
744   g_return_if_fail (gdkdev != NULL);
745
746   for (i=GDK_AXIS_IGNORE;i<GDK_AXIS_LAST;i++)
747     {
748       gdkdev->axis_for_use[i] = -1;
749     }
750
751   for (i=0;i<gdkdev->info.num_axes;i++)
752     {
753       gdkdev->info.axes[i] = axes[i];
754       gdkdev->axis_for_use[axes[i]] = i;
755     }
756 }
757
758 void gdk_input_common_set_key (guint32 deviceid,
759                                guint   index,
760                                guint   keyval,
761                                GdkModifierType modifiers)
762 {
763   GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
764   
765   gdkdev = gdk_input_find_device (deviceid);
766   g_return_if_fail (gdkdev != NULL);
767   g_return_if_fail (index < gdkdev->info.num_keys);
768
769   gdkdev->info.keys[index].keyval = keyval;
770   gdkdev->info.keys[index].modifiers = modifiers;
771 }
772
773 static GdkTimeCoord *
774 gdk_input_common_motion_events (GdkWindow *window,
775                                 guint32 deviceid,
776                                 guint32 start,
777                                 guint32 stop,
778                                 gint *nevents_return)
779 {
780   GdkTimeCoord *coords;
781   XDeviceTimeCoord *device_coords;
782   GdkInputWindow *input_window;
783   GdkDevicePrivate *gdkdev;
784
785   int mode_return;
786   int axis_count_return;
787   int i;
788
789   gdkdev = gdk_input_find_device (deviceid);
790   input_window = gdk_input_window_find (window);
791
792   g_return_val_if_fail (gdkdev != NULL, NULL);
793   g_return_val_if_fail (gdkdev->xdevice != NULL, NULL);
794   g_return_val_if_fail (input_window != NULL, NULL);
795
796   device_coords = XGetDeviceMotionEvents (gdk_display,
797                                           gdkdev->xdevice,
798                                           start, stop,
799                                           nevents_return, &mode_return,
800                                           &axis_count_return);
801
802   if (device_coords)
803     {
804       coords = g_new (GdkTimeCoord, *nevents_return);
805       
806       for (i=0; i<*nevents_return; i++)
807         {
808           gdk_input_translate_coordinates (gdkdev, input_window,
809                                            device_coords[i].data,
810                                            &coords[i].x, &coords[i].y,
811                                            &coords[i].pressure,
812                                            &coords[i].xtilt, &coords[i].ytilt);
813         }
814       XFreeDeviceMotionEvents (device_coords);
815
816       return coords;
817     }
818   else
819     return NULL;
820 }
821
822 static void 
823 gdk_input_common_get_pointer     (GdkWindow       *window,
824                                   guint32          deviceid,
825                                   gdouble         *x,
826                                   gdouble         *y,
827                                   gdouble         *pressure,
828                                   gdouble         *xtilt,
829                                   gdouble         *ytilt,
830                                   GdkModifierType *mask)
831 {
832   GdkDevicePrivate *gdkdev;
833   GdkInputWindow *input_window;
834   XDeviceState *state;
835   XInputClass *input_class;
836   gint x_int, y_int;
837   gint i;
838
839   /* we probably need to get the mask in any case */
840
841   if (deviceid == GDK_CORE_POINTER)
842     {
843       gdk_window_get_pointer (window, &x_int, &y_int, mask);
844       if (x) *x = x_int;
845       if (y) *y = y_int;
846       if (pressure) *pressure = 0.5;
847       if (xtilt) *xtilt = 0;
848       if (ytilt) *ytilt = 0;
849     }
850   else
851     {
852       if (mask)
853         gdk_window_get_pointer (window, NULL, NULL, mask);
854       
855       gdkdev = gdk_input_find_device (deviceid);
856       input_window = gdk_input_window_find (window);
857
858       g_return_if_fail (gdkdev != NULL);
859       g_return_if_fail (gdkdev->xdevice != NULL);
860       g_return_if_fail (input_window != NULL);
861
862       state = XQueryDeviceState (gdk_display, gdkdev->xdevice);
863       input_class = state->data;
864       for (i=0; i<state->num_classes; i++)
865         {
866           switch (input_class->class)
867             {
868             case ValuatorClass:
869               gdk_input_translate_coordinates (gdkdev, input_window,
870                                                ((XValuatorState *)input_class)->valuators,
871                                                x, y, pressure,
872                                                xtilt, ytilt);
873                                                        
874                                                        
875                 break;
876             case ButtonClass:
877               if (mask)
878                 {
879                   *mask &= 0xFF;
880                   if (((XButtonState *)input_class)->num_buttons > 0)
881                     *mask |= ((XButtonState *)input_class)->buttons[0] << 7;
882                   /* GDK_BUTTON1_MASK = 1 << 8, and button n is stored
883                    * in bit 1<<(n%8) in byte n/8. n = 1,2,... */
884                 }
885               break;
886             }
887           input_class = (XInputClass *)(((char *)input_class)+input_class->length);
888         }
889     }
890 }
891
892 #endif