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