]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkinput-x11.c
Initial version of input support
[~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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser 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-2000.  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 #include "config.h"
28 #include "gdkinputprivate.h"
29 #include "gdkinternals.h"
30 #include "gdkx.h"
31 #include "gdk.h"                /* For gdk_error_trap_push()/pop() */
32 #include "gdkdisplay-x11.h"
33 #include "gdkalias.h"
34
35 #include <string.h>
36
37 /* Forward declarations */
38 static GdkDevicePrivate *gdk_input_device_new            (GdkDisplay       *display,
39                                                           XDeviceInfo      *device,
40                                                           gint              include_core);
41 static void              gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
42                                                           GdkWindow        *window,
43                                                           gint             *axis_data,
44                                                           gdouble          *axis_out,
45                                                           gdouble          *x_out,
46                                                           gdouble          *y_out);
47 static guint             gdk_input_translate_state       (guint             state,
48                                                           guint             device_state);
49
50 GdkDevicePrivate *
51 _gdk_input_find_device (GdkDisplay *display,
52                         guint32     id)
53 {
54   GList *tmp_list = GDK_DISPLAY_X11 (display)->input_devices;
55   GdkDevicePrivate *gdkdev;
56   while (tmp_list)
57     {
58       gdkdev = (GdkDevicePrivate *)(tmp_list->data);
59       if (gdkdev->deviceid == id)
60         return gdkdev;
61       tmp_list = tmp_list->next;
62     }
63   return NULL;
64 }
65
66 void
67 _gdk_input_get_root_relative_geometry (GdkWindow *window,
68                                        int *x_ret, int *y_ret)
69 {
70   Window child;
71   gint x,y;
72
73   XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
74                          GDK_WINDOW_XWINDOW (window),
75                          GDK_WINDOW_XROOTWIN (window),
76                          0, 0, &x, &y, &child);
77
78   if (x_ret)
79     *x_ret = x;
80   if (y_ret)
81     *y_ret = y;
82 }
83
84 static GdkDevicePrivate *
85 gdk_input_device_new (GdkDisplay  *display,
86                       XDeviceInfo *device,
87                       gint         include_core)
88 {
89   GdkDevicePrivate *gdkdev;
90   gchar *tmp_name;
91   XAnyClassPtr class;
92   gint i,j;
93
94   gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
95
96   gdkdev->deviceid = device->id;
97   gdkdev->display = display;
98
99   if (device->name[0])
100     gdkdev->info.name = g_strdup (device->name);
101  else
102    /* XFree86 3.2 gives an empty name to the default core devices,
103       (fixed in 3.2A) */
104    gdkdev->info.name = g_strdup ("pointer");
105
106   gdkdev->info.mode = GDK_MODE_DISABLED;
107
108   /* Try to figure out what kind of device this is by its name -
109      could invite a very, very, long list... Lowercase name
110      for comparison purposes */
111
112   tmp_name = g_ascii_strdown (gdkdev->info.name, -1);
113
114   if (!strcmp (tmp_name, "pointer"))
115     gdkdev->info.source = GDK_SOURCE_MOUSE;
116   else if (!strcmp (tmp_name, "wacom") ||
117            !strcmp (tmp_name, "pen"))
118     gdkdev->info.source = GDK_SOURCE_PEN;
119   else if (!strcmp (tmp_name, "eraser"))
120     gdkdev->info.source = GDK_SOURCE_ERASER;
121   else if (!strcmp (tmp_name, "cursor"))
122     gdkdev->info.source = GDK_SOURCE_CURSOR;
123   else
124     gdkdev->info.source = GDK_SOURCE_PEN;
125
126   g_free(tmp_name);
127
128   gdkdev->xdevice = NULL;
129
130   /* step through the classes */
131
132   gdkdev->info.num_axes = 0;
133   gdkdev->info.num_keys = 0;
134   gdkdev->info.axes = NULL;
135   gdkdev->info.keys = NULL;
136   gdkdev->axes = 0;
137   gdkdev->info.has_cursor = 0;
138   gdkdev->needs_update = FALSE;
139   gdkdev->claimed = FALSE;
140   gdkdev->button_state = 0;
141
142   class = device->inputclassinfo;
143   for (i=0;i<device->num_classes;i++)
144     {
145       switch (class->class) {
146       case ButtonClass:
147         break;
148       case KeyClass:
149         {
150           XKeyInfo *xki = (XKeyInfo *)class;
151           /* Hack to catch XFree86 3.3.1 bug. Other devices better
152            * not have exactly 25 keys...
153            */
154           if ((xki->min_keycode == 8) && (xki->max_keycode == 32))
155             {
156               gdkdev->info.num_keys = 32;
157               gdkdev->min_keycode = 1;
158             }
159           else
160             {
161               gdkdev->info.num_keys = xki->max_keycode - xki->min_keycode + 1;
162               gdkdev->min_keycode = xki->min_keycode;
163             }
164           gdkdev->info.keys = g_new (GdkDeviceKey, gdkdev->info.num_keys);
165
166           for (j=0; j<gdkdev->info.num_keys; j++)
167             {
168               gdkdev->info.keys[j].keyval = 0;
169               gdkdev->info.keys[j].modifiers = 0;
170             }
171
172           break;
173         }
174       case ValuatorClass:
175         {
176           XValuatorInfo *xvi = (XValuatorInfo *)class;
177           gdkdev->info.num_axes = xvi->num_axes;
178           gdkdev->axes = g_new (GdkAxisInfo, xvi->num_axes);
179           gdkdev->info.axes = g_new0 (GdkDeviceAxis, xvi->num_axes);
180           for (j=0;j<xvi->num_axes;j++)
181             {
182               gdkdev->axes[j].resolution =
183                 gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
184               gdkdev->axes[j].min_value =
185                 gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
186               gdkdev->axes[j].max_value =
187                 gdkdev->axes[j].xmax_value = xvi->axes[j].max_value;
188               gdkdev->info.axes[j].use = GDK_AXIS_IGNORE;
189             }
190           j=0;
191           if (j<xvi->num_axes)
192             gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_X);
193           if (j<xvi->num_axes)
194             gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_Y);
195           if (j<xvi->num_axes)
196             gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_PRESSURE);
197           if (j<xvi->num_axes)
198             gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_XTILT);
199           if (j<xvi->num_axes)
200             gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_YTILT);
201           if (j<xvi->num_axes)
202             gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_WHEEL);
203
204           break;
205         }
206       }
207       class = (XAnyClassPtr)(((char *)class) + class->length);
208     }
209   /* return NULL if no axes */
210   if (!gdkdev->info.num_axes || !gdkdev->axes ||
211       (!include_core && device->use == IsXPointer))
212     goto error;
213
214   if (device->use != IsXPointer)
215     {
216       gdk_error_trap_push ();
217       gdkdev->xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (display),
218                                      gdkdev->deviceid);
219
220       /* return NULL if device is not ready */
221       if (gdk_error_trap_pop ())
222         goto error;
223     }
224
225   gdkdev->buttonpress_type = 0;
226   gdkdev->buttonrelease_type = 0;
227   gdkdev->keypress_type = 0;
228   gdkdev->keyrelease_type = 0;
229   gdkdev->motionnotify_type = 0;
230   gdkdev->proximityin_type = 0;
231   gdkdev->proximityout_type = 0;
232   gdkdev->changenotify_type = 0;
233
234   return gdkdev;
235
236  error:
237
238   g_object_unref (gdkdev);
239
240   return NULL;
241 }
242
243 void
244 _gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
245                                gint mask,
246                                XEventClass *classes,
247                                int *num_classes)
248 {
249   gint i;
250   XEventClass class;
251
252   i = 0;
253   if (mask & GDK_BUTTON_PRESS_MASK)
254     {
255       DeviceButtonPress (gdkdev->xdevice, gdkdev->buttonpress_type,
256                              class);
257       if (class != 0)
258           classes[i++] = class;
259       DeviceButtonPressGrab (gdkdev->xdevice, 0, class);
260       if (class != 0)
261           classes[i++] = class;
262     }
263   if (mask & GDK_BUTTON_RELEASE_MASK)
264     {
265       DeviceButtonRelease (gdkdev->xdevice, gdkdev->buttonrelease_type,
266                            class);
267       if (class != 0)
268           classes[i++] = class;
269     }
270   if (mask & GDK_POINTER_MOTION_MASK)
271     {
272       DeviceMotionNotify  (gdkdev->xdevice, gdkdev->motionnotify_type, class);
273       if (class != 0)
274           classes[i++] = class;
275     }
276   else
277     if (mask & (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK |
278                 GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_MOTION_MASK |
279                 GDK_POINTER_MOTION_HINT_MASK))
280       {
281         /* Make sure gdkdev->motionnotify_type is set */
282         DeviceMotionNotify  (gdkdev->xdevice, gdkdev->motionnotify_type, class);
283       }
284   if (mask & GDK_BUTTON1_MOTION_MASK)
285     {
286       DeviceButton1Motion  (gdkdev->xdevice, 0, class);
287       if (class != 0)
288           classes[i++] = class;
289     }
290   if (mask & GDK_BUTTON2_MOTION_MASK)
291     {
292       DeviceButton2Motion  (gdkdev->xdevice, 0, class);
293       if (class != 0)
294           classes[i++] = class;
295     }
296   if (mask & GDK_BUTTON3_MOTION_MASK)
297     {
298       DeviceButton3Motion  (gdkdev->xdevice, 0, class);
299       if (class != 0)
300           classes[i++] = class;
301     }
302   if (mask & GDK_BUTTON_MOTION_MASK)
303     {
304       DeviceButtonMotion  (gdkdev->xdevice, 0, class);
305       if (class != 0)
306           classes[i++] = class;
307     }
308   if (mask & GDK_POINTER_MOTION_HINT_MASK)
309     {
310       /* We'll get into trouble if the macros change, but at least we'll
311          know about it, and we avoid warnings now */
312       DevicePointerMotionHint (gdkdev->xdevice, 0, class);
313       if (class != 0)
314           classes[i++] = class;
315     }
316   if (mask & GDK_KEY_PRESS_MASK)
317     {
318       DeviceKeyPress (gdkdev->xdevice, gdkdev->keypress_type, class);
319       if (class != 0)
320           classes[i++] = class;
321     }
322   if (mask & GDK_KEY_RELEASE_MASK)
323     {
324       DeviceKeyRelease (gdkdev->xdevice, gdkdev->keyrelease_type, class);
325       if (class != 0)
326           classes[i++] = class;
327     }
328   if (mask & GDK_PROXIMITY_IN_MASK)
329     {
330       ProximityIn   (gdkdev->xdevice, gdkdev->proximityin_type, class);
331       if (class != 0)
332           classes[i++] = class;
333     }
334   if (mask & GDK_PROXIMITY_OUT_MASK)
335     {
336       ProximityOut  (gdkdev->xdevice, gdkdev->proximityout_type, class);
337       if (class != 0)
338           classes[i++] = class;
339     }
340
341   *num_classes = i;
342 }
343
344 void
345 _gdk_input_select_events (GdkWindow *impl_window,
346                           GdkDevicePrivate *gdkdev)
347 {
348   XEventClass classes[GDK_MAX_DEVICE_CLASSES];
349   gint num_classes;
350   guint event_mask;
351   GdkWindowObject *w;
352   GdkInputWindow *iw;
353   GList *l;
354
355   event_mask = 0;
356   iw = ((GdkWindowObject *)impl_window)->input_window;
357
358   if (gdkdev->info.mode != GDK_MODE_DISABLED &&
359       iw != NULL)
360     {
361       for (l = iw->windows; l != NULL; l = l->next)
362         {
363           w = l->data;
364           if (gdkdev->info.has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK))
365             event_mask |= w->extension_events;
366         }
367     }
368   event_mask &= ~GDK_ALL_DEVICES_MASK;
369
370   if (event_mask)
371     event_mask |= GDK_PROXIMITY_OUT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
372
373   _gdk_input_common_find_events (gdkdev, event_mask,
374                                  classes, &num_classes);
375   XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (impl_window),
376                          GDK_WINDOW_XWINDOW (impl_window),
377                          classes, num_classes);
378 }
379
380 gint
381 _gdk_input_common_init (GdkDisplay *display,
382                         gint        include_core)
383 {
384   XDeviceInfo   *devices;
385   int num_devices, loop;
386   int ignore, event_base;
387   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
388
389   /* Init XInput extension */
390
391   display_x11->input_devices = NULL;
392   if (XQueryExtension (display_x11->xdisplay, "XInputExtension",
393                        &ignore, &event_base, &ignore))
394     {
395       gdk_x11_register_standard_event_type (display,
396                                             event_base, 15 /* Number of events */);
397
398       devices = XListInputDevices(display_x11->xdisplay, &num_devices);
399
400       for(loop=0; loop<num_devices; loop++)
401         {
402           GdkDevicePrivate *gdkdev = gdk_input_device_new(display,
403                                                           &devices[loop],
404                                                           include_core);
405           if (gdkdev)
406             display_x11->input_devices = g_list_append(display_x11->input_devices, gdkdev);
407         }
408       XFreeDeviceList(devices);
409     }
410
411   display_x11->input_devices = g_list_append (display_x11->input_devices, display->core_pointer);
412
413   return TRUE;
414 }
415
416 static void
417 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
418                                  GdkWindow        *window,
419                                  gint             *axis_data,
420                                  gdouble          *axis_out,
421                                  gdouble          *x_out,
422                                  gdouble          *y_out)
423 {
424   GdkWindowObject *priv, *impl_window;
425
426   int i;
427   int x_axis = 0;
428   int y_axis = 0;
429
430   double device_width, device_height;
431   double x_offset, y_offset, x_scale, y_scale;
432
433   priv = (GdkWindowObject *) window;
434   impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
435
436   for (i=0; i<gdkdev->info.num_axes; i++)
437     {
438       switch (gdkdev->info.axes[i].use)
439         {
440         case GDK_AXIS_X:
441           x_axis = i;
442           break;
443         case GDK_AXIS_Y:
444           y_axis = i;
445           break;
446         default:
447           break;
448         }
449     }
450
451   device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
452   device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
453
454   if (gdkdev->info.mode == GDK_MODE_SCREEN)
455     {
456       x_scale = gdk_screen_get_width (gdk_drawable_get_screen (window)) / device_width;
457       y_scale = gdk_screen_get_height (gdk_drawable_get_screen (window)) / device_height;
458
459       x_offset = - impl_window->input_window->root_x;
460       y_offset = - impl_window->input_window->root_y;
461     }
462   else                          /* GDK_MODE_WINDOW */
463     {
464       double x_resolution = gdkdev->axes[x_axis].resolution;
465       double y_resolution = gdkdev->axes[y_axis].resolution;
466       double device_aspect;
467       /*
468        * Some drivers incorrectly report the resolution of the device
469        * as zero (in partiular linuxwacom < 0.5.3 with usb tablets).
470        * This causes the device_aspect to become NaN and totally
471        * breaks windowed mode.  If this is the case, the best we can
472        * do is to assume the resolution is non-zero is equal in both
473        * directions (which is true for many devices).  The absolute
474        * value of the resolution doesn't matter since we only use the
475        * ratio.
476        */
477       if ((x_resolution == 0) || (y_resolution == 0))
478         {
479           x_resolution = 1;
480           y_resolution = 1;
481         }
482       device_aspect = (device_height*y_resolution) /
483         (device_width*x_resolution);
484       if (device_aspect * priv->width >= priv->height)
485         {
486           /* device taller than window */
487           x_scale = priv->width / device_width;
488           y_scale = (x_scale * x_resolution) / y_resolution;
489
490           x_offset = 0;
491           y_offset = -(device_height * y_scale -  priv->height)/2;
492         }
493       else
494         {
495           /* window taller than device */
496           y_scale = priv->height / device_height;
497           x_scale = (y_scale * y_resolution) / x_resolution;
498
499           y_offset = 0;
500           x_offset = - (device_width * x_scale - priv->width)/2;
501         }
502     }
503
504   for (i=0; i<gdkdev->info.num_axes; i++)
505     {
506       switch (gdkdev->info.axes[i].use)
507         {
508         case GDK_AXIS_X:
509           axis_out[i] = x_offset + x_scale * (axis_data[x_axis] -
510             gdkdev->axes[x_axis].min_value);
511           if (x_out)
512             *x_out = axis_out[i];
513           break;
514         case GDK_AXIS_Y:
515           axis_out[i] = y_offset + y_scale * (axis_data[y_axis] -
516             gdkdev->axes[y_axis].min_value);
517           if (y_out)
518             *y_out = axis_out[i];
519           break;
520         default:
521           axis_out[i] =
522             (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
523              gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
524             (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
525           break;
526         }
527     }
528 }
529
530 /* combine the state of the core device and the device state
531  * into one - for now we do this in a simple-minded manner -
532  * we just take the keyboard portion of the core device and
533  * the button portion (all of?) the device state.
534  * Any button remapping should go on here.
535  */
536 static guint
537 gdk_input_translate_state(guint state, guint device_state)
538 {
539   return device_state | (state & 0xFF);
540 }
541
542
543 gboolean
544 _gdk_input_common_other_event (GdkEvent         *event,
545                                XEvent           *xevent,
546                                GdkWindow        *window,
547                                GdkDevicePrivate *gdkdev)
548 {
549   GdkWindowObject *priv, *impl_window;
550   GdkInputWindow *input_window;
551
552   priv = (GdkWindowObject *) window;
553   impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
554   input_window = impl_window->input_window;
555
556   if ((xevent->type == gdkdev->buttonpress_type) ||
557       (xevent->type == gdkdev->buttonrelease_type))
558     {
559       XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
560
561       if (xdbe->type == gdkdev->buttonpress_type)
562         {
563           event->button.type = GDK_BUTTON_PRESS;
564           gdkdev->button_state |= 1 << xdbe->button;
565         }
566       else
567         {
568           event->button.type = GDK_BUTTON_RELEASE;
569           gdkdev->button_state &= ~(1 << xdbe->button);
570         }
571       event->button.device = &gdkdev->info;
572       event->button.window = window;
573       event->button.time = xdbe->time;
574
575       event->button.axes = g_new (gdouble, gdkdev->info.num_axes);
576       gdk_input_translate_coordinates (gdkdev, window, xdbe->axis_data,
577                                        event->button.axes,
578                                        &event->button.x, &event->button.y);
579       event->button.x_root = event->button.x + priv->abs_x + input_window->root_x;
580       event->button.y_root = event->button.y + priv->abs_y + input_window->root_y;
581       event->button.state = gdk_input_translate_state (xdbe->state,xdbe->device_state);
582       event->button.button = xdbe->button;
583
584       if (event->button.type == GDK_BUTTON_PRESS)
585         _gdk_event_button_generate (gdk_drawable_get_display (event->button.window),
586                                     event);
587
588       GDK_NOTE (EVENTS,
589         g_print ("button %s:\t\twindow: %ld  device: %ld  x,y: %f %f  button: %d\n",
590                  (event->button.type == GDK_BUTTON_PRESS) ? "press" : "release",
591                  xdbe->window,
592                  xdbe->deviceid,
593                  event->button.x, event->button.y,
594                  xdbe->button));
595
596       /* Update the timestamp of the latest user interaction, if the event has
597        * a valid timestamp.
598        */
599       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
600         gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
601                                       gdk_event_get_time (event));
602       return TRUE;
603   }
604
605   if ((xevent->type == gdkdev->keypress_type) ||
606       (xevent->type == gdkdev->keyrelease_type))
607     {
608       XDeviceKeyEvent *xdke = (XDeviceKeyEvent *)(xevent);
609
610       GDK_NOTE (EVENTS,
611         g_print ("device key %s:\twindow: %ld  device: %ld  keycode: %d\n",
612                  (event->key.type == GDK_KEY_PRESS) ? "press" : "release",
613                  xdke->window,
614                  xdke->deviceid,
615                  xdke->keycode));
616
617       if (xdke->keycode < gdkdev->min_keycode ||
618           xdke->keycode >= gdkdev->min_keycode + gdkdev->info.num_keys)
619         {
620           g_warning ("Invalid device key code received");
621           return FALSE;
622         }
623
624       event->key.keyval = gdkdev->info.keys[xdke->keycode - gdkdev->min_keycode].keyval;
625
626       if (event->key.keyval == 0)
627         {
628           GDK_NOTE (EVENTS,
629             g_print ("\t\ttranslation - NONE\n"));
630
631           return FALSE;
632         }
633
634       event->key.type = (xdke->type == gdkdev->keypress_type) ?
635         GDK_KEY_PRESS : GDK_KEY_RELEASE;
636
637       event->key.window = window;
638       event->key.time = xdke->time;
639
640       event->key.state = gdk_input_translate_state(xdke->state, xdke->device_state)
641         | gdkdev->info.keys[xdke->keycode - gdkdev->min_keycode].modifiers;
642
643       /* Add a string translation for the key event */
644       if ((event->key.keyval >= 0x20) && (event->key.keyval <= 0xFF))
645         {
646           event->key.length = 1;
647           event->key.string = g_new (gchar, 2);
648           event->key.string[0] = (gchar)event->key.keyval;
649           event->key.string[1] = 0;
650         }
651       else
652         {
653           event->key.length = 0;
654           event->key.string = g_new0 (gchar, 1);
655         }
656
657       GDK_NOTE (EVENTS,
658         g_print ("\t\ttranslation - keyval: %d modifiers: %#x\n",
659                  event->key.keyval,
660                  event->key.state));
661
662       /* Update the timestamp of the latest user interaction, if the event has
663        * a valid timestamp.
664        */
665       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
666         gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
667                                       gdk_event_get_time (event));
668       return TRUE;
669     }
670
671   if (xevent->type == gdkdev->motionnotify_type)
672     {
673       XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
674
675       event->motion.device = &gdkdev->info;
676
677       event->motion.axes = g_new (gdouble, gdkdev->info.num_axes);
678       gdk_input_translate_coordinates(gdkdev,window,xdme->axis_data,
679                                       event->motion.axes,
680                                       &event->motion.x,&event->motion.y);
681       event->motion.x_root = event->motion.x + priv->abs_x + input_window->root_x;
682       event->motion.y_root = event->motion.y + priv->abs_y + input_window->root_y;
683
684       event->motion.type = GDK_MOTION_NOTIFY;
685       event->motion.window = window;
686       event->motion.time = xdme->time;
687       event->motion.state = gdk_input_translate_state(xdme->state,
688                                                       xdme->device_state);
689       event->motion.is_hint = xdme->is_hint;
690
691       GDK_NOTE (EVENTS,
692         g_print ("motion notify:\t\twindow: %ld  device: %ld  x,y: %f %f  state %#4x  hint: %s\n",
693                  xdme->window,
694                  xdme->deviceid,
695                  event->motion.x, event->motion.y,
696                  event->motion.state,
697                  (xdme->is_hint) ? "true" : "false"));
698
699
700       /* Update the timestamp of the latest user interaction, if the event has
701        * a valid timestamp.
702        */
703       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
704         gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
705                                       gdk_event_get_time (event));
706       return TRUE;
707     }
708
709   if (xevent->type == gdkdev->proximityin_type ||
710       xevent->type == gdkdev->proximityout_type)
711     {
712       XProximityNotifyEvent *xpne = (XProximityNotifyEvent *)(xevent);
713
714       event->proximity.device = &gdkdev->info;
715       event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
716         GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
717       event->proximity.window = window;
718       event->proximity.time = xpne->time;
719
720       /* Update the timestamp of the latest user interaction, if the event has
721        * a valid timestamp.
722        */
723       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
724         gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
725                                       gdk_event_get_time (event));
726       return TRUE;
727   }
728
729   return FALSE;                 /* wasn't one of our event types */
730 }
731
732 gboolean
733 _gdk_device_get_history (GdkDevice         *device,
734                          GdkWindow         *window,
735                          guint32            start,
736                          guint32            stop,
737                          GdkTimeCoord    ***events,
738                          gint              *n_events)
739 {
740   GdkTimeCoord **coords;
741   XDeviceTimeCoord *device_coords;
742   GdkWindow *impl_window;
743   GdkDevicePrivate *gdkdev;
744   gint mode_return;
745   gint axis_count_return;
746   gint i;
747
748   gdkdev = (GdkDevicePrivate *)device;
749
750   impl_window = _gdk_window_get_impl_window (window);
751
752   device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (impl_window),
753                                           gdkdev->xdevice,
754                                           start, stop,
755                                           n_events, &mode_return,
756                                           &axis_count_return);
757
758   if (device_coords)
759     {
760       coords = _gdk_device_allocate_history (device, *n_events);
761
762       for (i = 0; i < *n_events; i++)
763         {
764           coords[i]->time = device_coords[i].time;
765
766           gdk_input_translate_coordinates (gdkdev, window,
767                                            device_coords[i].data,
768                                            coords[i]->axes, NULL, NULL);
769         }
770
771       XFreeDeviceMotionEvents (device_coords);
772
773       *events = coords;
774
775       return TRUE;
776     }
777   else
778     return FALSE;
779 }
780
781 void
782 gdk_device_get_state (GdkDevice       *device,
783                       GdkWindow       *window,
784                       gdouble         *axes,
785                       GdkModifierType *mask)
786 {
787   gint i;
788
789   g_return_if_fail (device != NULL);
790   g_return_if_fail (GDK_IS_WINDOW (window));
791
792   if (GDK_IS_CORE (device))
793     {
794       gint x_int, y_int;
795
796       gdk_window_get_pointer (window, &x_int, &y_int, mask);
797
798       if (axes)
799         {
800           axes[0] = x_int;
801           axes[1] = y_int;
802         }
803     }
804   else
805     {
806       GdkDevicePrivate *gdkdev;
807       XDeviceState *state;
808       XInputClass *input_class;
809
810       if (mask)
811         gdk_window_get_pointer (window, NULL, NULL, mask);
812
813       gdkdev = (GdkDevicePrivate *)device;
814
815       state = XQueryDeviceState (GDK_WINDOW_XDISPLAY (window),
816                                  gdkdev->xdevice);
817       input_class = state->data;
818       for (i=0; i<state->num_classes; i++)
819         {
820           switch (input_class->class)
821             {
822             case ValuatorClass:
823               if (axes)
824                 gdk_input_translate_coordinates (gdkdev, window,
825                                                  ((XValuatorState *)input_class)->valuators,
826                                                  axes, NULL, NULL);
827               break;
828
829             case ButtonClass:
830               if (mask)
831                 {
832                   *mask &= 0xFF;
833                   if (((XButtonState *)input_class)->num_buttons > 0)
834                     *mask |= ((XButtonState *)input_class)->buttons[0] << 7;
835                   /* GDK_BUTTON1_MASK = 1 << 8, and button n is stored
836                    * in bit 1<<(n%8) in byte n/8. n = 1,2,... */
837                 }
838               break;
839             }
840           input_class = (XInputClass *)(((char *)input_class)+input_class->length);
841         }
842       XFreeDeviceState (state);
843     }
844 }
845
846 #define __GDK_INPUT_X11_C__
847 #include "gdkaliasdef.c"