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