source: trunk/third/gtk/gdk/gdkinputcommon.h @ 14482

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