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