]> Pileus Git - ~andy/gtk/blob - gdk/gdkdevice.c
gdk: Move get_device_state out of the display hooks
[~andy/gtk] / gdk / gdkdevice.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
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 #include "config.h"
21
22 #include "gdkdeviceprivate.h"
23 #include "gdkdisplayprivate.h"
24 #include "gdkinternals.h"
25 #include "gdkintl.h"
26
27 /**
28  * SECTION:gdkdevice
29  * @Short_description: Object representing an input device
30  * @Title: GdkDevice
31  * @See_also: #GdkDeviceManager
32  *
33  * The #GdkDevice object represents a single input device.
34  *
35  * See the #GdkDeviceManager documentation for more information
36  * about the various kinds of master and slave devices, and their
37  * relationships.
38  */
39
40 typedef struct _GdkAxisInfo GdkAxisInfo;
41
42 struct _GdkAxisInfo
43 {
44   GdkAtom label;
45   GdkAxisUse use;
46
47   gdouble min_axis;
48   gdouble max_axis;
49
50   gdouble min_value;
51   gdouble max_value;
52   gdouble resolution;
53 };
54
55 enum {
56   CHANGED,
57   LAST_SIGNAL
58 };
59
60 static guint signals [LAST_SIGNAL] = { 0 };
61
62
63 static void gdk_device_dispose      (GObject      *object);
64 static void gdk_device_set_property (GObject      *object,
65                                      guint         prop_id,
66                                      const GValue *value,
67                                      GParamSpec   *pspec);
68 static void gdk_device_get_property (GObject      *object,
69                                      guint         prop_id,
70                                      GValue       *value,
71                                      GParamSpec   *pspec);
72
73
74 G_DEFINE_ABSTRACT_TYPE (GdkDevice, gdk_device, G_TYPE_OBJECT)
75
76 enum {
77   PROP_0,
78   PROP_DISPLAY,
79   PROP_DEVICE_MANAGER,
80   PROP_NAME,
81   PROP_ASSOCIATED_DEVICE,
82   PROP_TYPE,
83   PROP_INPUT_SOURCE,
84   PROP_INPUT_MODE,
85   PROP_HAS_CURSOR,
86   PROP_N_AXES
87 };
88
89
90 static void
91 gdk_device_class_init (GdkDeviceClass *klass)
92 {
93   GObjectClass *object_class = G_OBJECT_CLASS (klass);
94
95   object_class->dispose = gdk_device_dispose;
96   object_class->set_property = gdk_device_set_property;
97   object_class->get_property = gdk_device_get_property;
98
99   /**
100    * GdkDevice:display:
101    *
102    * The #GdkDisplay the #GdkDevice pertains to.
103    *
104    * Since: 3.0
105    */
106   g_object_class_install_property (object_class,
107                                    PROP_DISPLAY,
108                                    g_param_spec_object ("display",
109                                                         P_("Device Display"),
110                                                         P_("Display which the device belongs to"),
111                                                         GDK_TYPE_DISPLAY,
112                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
113                                                         G_PARAM_STATIC_STRINGS));
114   /**
115    * GdkDevice:device-manager:
116    *
117    * The #GdkDeviceManager the #GdkDevice pertains to.
118    *
119    * Since: 3.0
120    */
121   g_object_class_install_property (object_class,
122                                    PROP_DEVICE_MANAGER,
123                                    g_param_spec_object ("device-manager",
124                                                         P_("Device manager"),
125                                                         P_("Device manager which the device belongs to"),
126                                                         GDK_TYPE_DEVICE_MANAGER,
127                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
128                                                         G_PARAM_STATIC_STRINGS));
129   /**
130    * GdkDevice:name:
131    *
132    * The device name.
133    *
134    * Since: 3.0
135    */
136   g_object_class_install_property (object_class,
137                                    PROP_NAME,
138                                    g_param_spec_string ("name",
139                                                         P_("Device name"),
140                                                         P_("Device name"),
141                                                         NULL,
142                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
143                                                         G_PARAM_STATIC_STRINGS));
144   /**
145    * GdkDevice:type:
146    *
147    * Device role in the device manager.
148    *
149    * Since: 3.0
150    */
151   g_object_class_install_property (object_class,
152                                    PROP_TYPE,
153                                    g_param_spec_enum ("type",
154                                                       P_("Device type"),
155                                                       P_("Device role in the device manager"),
156                                                       GDK_TYPE_DEVICE_TYPE,
157                                                       GDK_DEVICE_TYPE_MASTER,
158                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
159                                                       G_PARAM_STATIC_STRINGS));
160   /**
161    * GdkDevice:associated-device:
162    *
163    * Associated pointer or keyboard with this device, if any. Devices of type #GDK_DEVICE_TYPE_MASTER
164    * always come in keyboard/pointer pairs. Other device types will have a %NULL associated device.
165    *
166    * Since: 3.0
167    */
168   g_object_class_install_property (object_class,
169                                    PROP_ASSOCIATED_DEVICE,
170                                    g_param_spec_object ("associated-device",
171                                                         P_("Associated device"),
172                                                         P_("Associated pointer or keyboard with this device"),
173                                                         GDK_TYPE_DEVICE,
174                                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
175   /**
176    * GdkDevice:input-source:
177    *
178    * Source type for the device.
179    *
180    * Since: 3.0
181    */
182   g_object_class_install_property (object_class,
183                                    PROP_INPUT_SOURCE,
184                                    g_param_spec_enum ("input-source",
185                                                       P_("Input source"),
186                                                       P_("Source type for the device"),
187                                                       GDK_TYPE_INPUT_SOURCE,
188                                                       GDK_SOURCE_MOUSE,
189                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
190                                                       G_PARAM_STATIC_STRINGS));
191   /**
192    * GdkDevice:input-mode:
193    *
194    * Input mode for the device.
195    *
196    * Since: 3.0
197    */
198   g_object_class_install_property (object_class,
199                                    PROP_INPUT_MODE,
200                                    g_param_spec_enum ("input-mode",
201                                                       P_("Input mode for the device"),
202                                                       P_("Input mode for the device"),
203                                                       GDK_TYPE_INPUT_MODE,
204                                                       GDK_MODE_DISABLED,
205                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
206   /**
207    * GdkDevice:has-cursor:
208    *
209    * Whether the device is represented by a cursor on the screen. Devices of type
210    * %GDK_DEVICE_TYPE_MASTER will have %TRUE here.
211    *
212    * Since: 3.0
213    */
214   g_object_class_install_property (object_class,
215                                    PROP_HAS_CURSOR,
216                                    g_param_spec_boolean ("has-cursor",
217                                                          P_("Whether the device has a cursor"),
218                                                          P_("Whether there is a visible cursor following device motion"),
219                                                          FALSE,
220                                                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
221                                                          G_PARAM_STATIC_STRINGS));
222   /**
223    * GdkDevice:n-axes:
224    *
225    * Number of axes in the device.
226    *
227    * Since: 3.0
228    */
229   g_object_class_install_property (object_class,
230                                    PROP_N_AXES,
231                                    g_param_spec_uint ("n-axes",
232                                                       P_("Number of axes in the device"),
233                                                       P_("Number of axes in the device"),
234                                                       0, G_MAXUINT, 0,
235                                                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
236
237   /**
238    * GdkDevice::changed:
239    * @device: the #GdkDevice that changed.
240    *
241    * The ::changed signal is emitted either when the #GdkDevice
242    * has changed the number of either axes or keys. For example
243    * In X this will normally happen when the slave device routing
244    * events through the master device changes (for example, user
245    * switches from the USB mouse to a tablet), in that case the
246    * master device will change to reflect the new slave device
247    * axes and keys.
248    */
249   signals[CHANGED] =
250     g_signal_new (g_intern_static_string ("changed"),
251                   G_TYPE_FROM_CLASS (object_class),
252                   G_SIGNAL_RUN_LAST,
253                   0, NULL, NULL,
254                   g_cclosure_marshal_VOID__VOID,
255                   G_TYPE_NONE, 0);
256 }
257
258 static void
259 gdk_device_init (GdkDevice *device)
260 {
261   device->axes = g_array_new (FALSE, TRUE, sizeof (GdkAxisInfo));
262 }
263
264 static void
265 gdk_device_dispose (GObject *object)
266 {
267   GdkDevice *device = GDK_DEVICE (object);
268
269   if (device->type == GDK_DEVICE_TYPE_SLAVE)
270     _gdk_device_remove_slave (device->associated, device);
271
272   if (device->associated)
273     {
274       _gdk_device_set_associated_device (device->associated, NULL);
275       g_object_unref (device->associated);
276       device->associated = NULL;
277     }
278
279   if (device->axes)
280     {
281       g_array_free (device->axes, TRUE);
282       device->axes = NULL;
283     }
284
285   g_free (device->name);
286   g_free (device->keys);
287
288   device->name = NULL;
289   device->keys = NULL;
290
291   G_OBJECT_CLASS (gdk_device_parent_class)->dispose (object);
292 }
293
294 static void
295 gdk_device_set_property (GObject      *object,
296                          guint         prop_id,
297                          const GValue *value,
298                          GParamSpec   *pspec)
299 {
300   GdkDevice *device = GDK_DEVICE (object);
301
302   switch (prop_id)
303     {
304     case PROP_DISPLAY:
305       device->display = g_value_get_object (value);
306       break;
307     case PROP_DEVICE_MANAGER:
308       device->manager = g_value_get_object (value);
309       break;
310     case PROP_NAME:
311       if (device->name)
312         g_free (device->name);
313
314       device->name = g_value_dup_string (value);
315       break;
316     case PROP_TYPE:
317       device->type = g_value_get_enum (value);
318       break;
319     case PROP_INPUT_SOURCE:
320       device->source = g_value_get_enum (value);
321       break;
322     case PROP_INPUT_MODE:
323       gdk_device_set_mode (device, g_value_get_enum (value));
324       break;
325     case PROP_HAS_CURSOR:
326       device->has_cursor = g_value_get_boolean (value);
327       break;
328     default:
329       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
330       break;
331     }
332 }
333
334 static void
335 gdk_device_get_property (GObject    *object,
336                          guint       prop_id,
337                          GValue     *value,
338                          GParamSpec *pspec)
339 {
340   GdkDevice *device = GDK_DEVICE (object);
341
342   switch (prop_id)
343     {
344     case PROP_DISPLAY:
345       g_value_set_object (value, device->display);
346       break;
347     case PROP_DEVICE_MANAGER:
348       g_value_set_object (value, device->manager);
349       break;
350     case PROP_ASSOCIATED_DEVICE:
351       g_value_set_object (value, device->associated);
352       break;
353     case PROP_NAME:
354       g_value_set_string (value, device->name);
355       break;
356     case PROP_TYPE:
357       g_value_set_enum (value, device->type);
358       break;
359     case PROP_INPUT_SOURCE:
360       g_value_set_enum (value, device->source);
361       break;
362     case PROP_INPUT_MODE:
363       g_value_set_enum (value, device->mode);
364       break;
365     case PROP_HAS_CURSOR:
366       g_value_set_boolean (value, device->has_cursor);
367       break;
368     case PROP_N_AXES:
369       g_value_set_uint (value, device->axes->len);
370       break;
371     default:
372       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
373       break;
374     }
375 }
376
377 /**
378  * gdk_device_get_state:
379  * @device: a #GdkDevice.
380  * @window: a #GdkWindow.
381  * @axes: an array of doubles to store the values of the axes of @device in,
382  * or %NULL.
383  * @mask: location to store the modifiers, or %NULL.
384  *
385  * Gets the current state of a pointer device relative to @window.
386  */
387 void
388 gdk_device_get_state (GdkDevice       *device,
389                       GdkWindow       *window,
390                       gdouble         *axes,
391                       GdkModifierType *mask)
392 {
393   g_return_if_fail (GDK_IS_DEVICE (device));
394   g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
395   g_return_if_fail (GDK_IS_WINDOW (window));
396
397   if (GDK_DEVICE_GET_CLASS (device)->get_state)
398     GDK_DEVICE_GET_CLASS (device)->get_state (device, window, axes, mask);
399 }
400
401 /**
402  * gdk_device_get_position:
403  * @device: pointer device to query status about.
404  * @screen: (out) (transfer none) (allow-none): location to store the #GdkScreen
405  *          the @device is on, or %NULL.
406  * @x: (out) (allow-none): location to store root window X coordinate of @device, or %NULL.
407  * @y: (out) (allow-none): location to store root window Y coordinate of @device, or %NULL.
408  *
409  * Gets the current location of @device.
410  *
411  * Since: 3.0
412  **/
413 void
414 gdk_device_get_position (GdkDevice        *device,
415                          GdkScreen       **screen,
416                          gint             *x,
417                          gint             *y)
418 {
419   GdkDisplay *display;
420   gint tmp_x, tmp_y;
421   GdkScreen *default_screen;
422   GdkWindow *root;
423
424   g_return_if_fail (GDK_IS_DEVICE (device));
425   g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
426
427   display = gdk_device_get_display (device);
428   default_screen = gdk_display_get_default_screen (display);
429
430   _gdk_device_query_state (device,
431                            gdk_screen_get_root_window (default_screen),
432                            &root, NULL,
433                            &tmp_x, &tmp_y,
434                            NULL, NULL, NULL);
435
436   if (screen)
437     *screen = gdk_window_get_screen (root);
438   if (x)
439     *x = tmp_x;
440   if (y)
441     *y = tmp_y;
442 }
443
444 /**
445  * gdk_device_get_window_at_position:
446  * @device: pointer #GdkDevice to query info to.
447  * @win_x: (out) (allow-none): return location for the X coordinate of the device location,
448  *         relative to the window origin, or %NULL.
449  * @win_y: (out) (allow-none): return location for the Y coordinate of the device location,
450  *         relative to the window origin, or %NULL.
451  *
452  * Obtains the window underneath @device, returning the location of the device in @win_x and @win_y. Returns
453  * %NULL if the window tree under @device is not known to GDK (for example, belongs to another application).
454  *
455  * Returns: (transfer none): the #GdkWindow under the device position, or %NULL.
456  *
457  * Since: 3.0
458  **/
459 GdkWindow *
460 gdk_device_get_window_at_position (GdkDevice  *device,
461                                    gint       *win_x,
462                                    gint       *win_y)
463 {
464   GdkDisplay *display;
465   gint tmp_x, tmp_y;
466   GdkWindow *window;
467
468   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
469   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
470
471   display = gdk_device_get_display (device);
472
473   window = display->device_hooks->window_at_device_position (display, device, &tmp_x, &tmp_y);
474
475   if (win_x)
476     *win_x = tmp_x;
477   if (win_y)
478     *win_y = tmp_y;
479
480   return window;
481 }
482
483 /**
484  * gdk_device_get_history:
485  * @device: a #GdkDevice
486  * @window: the window with respect to which which the event coordinates will be reported
487  * @start: starting timestamp for range of events to return
488  * @stop: ending timestamp for the range of events to return
489  * @events: (array length=n_events) (out) (transfer none): location to store a newly-allocated array of #GdkTimeCoord, or %NULL
490  * @n_events: location to store the length of @events, or %NULL
491  *
492  * Obtains the motion history for a pointer device; given a starting and
493  * ending timestamp, return all events in the motion history for
494  * the device in the given range of time. Some windowing systems
495  * do not support motion history, in which case, %FALSE will
496  * be returned. (This is not distinguishable from the case where
497  * motion history is supported and no events were found.)
498  *
499  * Return value: %TRUE if the windowing system supports motion history and
500  *  at least one event was found.
501  **/
502 gboolean
503 gdk_device_get_history (GdkDevice      *device,
504                         GdkWindow      *window,
505                         guint32         start,
506                         guint32         stop,
507                         GdkTimeCoord ***events,
508                         gint           *n_events)
509 {
510   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
511   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, FALSE);
512   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
513
514   if (n_events)
515     *n_events = 0;
516
517   if (events)
518     *events = NULL;
519
520   if (GDK_WINDOW_DESTROYED (window))
521     return FALSE;
522
523   if (!GDK_DEVICE_GET_CLASS (device)->get_history)
524     return FALSE;
525
526   return GDK_DEVICE_GET_CLASS (device)->get_history (device, window,
527                                                      start, stop,
528                                                      events, n_events);
529 }
530
531 GdkTimeCoord **
532 _gdk_device_allocate_history (GdkDevice *device,
533                               gint       n_events)
534 {
535   GdkTimeCoord **result = g_new (GdkTimeCoord *, n_events);
536   gint i;
537
538   for (i = 0; i < n_events; i++)
539     result[i] = g_malloc (sizeof (GdkTimeCoord) -
540                           sizeof (double) * (GDK_MAX_TIMECOORD_AXES - device->axes->len));
541   return result;
542 }
543
544 /**
545  * gdk_device_free_history:
546  * @events: (inout) (transfer none): an array of #GdkTimeCoord.
547  * @n_events: the length of the array.
548  *
549  * Frees an array of #GdkTimeCoord that was returned by gdk_device_get_history().
550  */
551 void
552 gdk_device_free_history (GdkTimeCoord **events,
553                          gint           n_events)
554 {
555   gint i;
556
557   for (i = 0; i < n_events; i++)
558     g_free (events[i]);
559
560   g_free (events);
561 }
562
563 /**
564  * gdk_device_get_name:
565  * @device: a #GdkDevice
566  *
567  * Determines the name of the device.
568  *
569  * Return value: a name
570  *
571  * Since: 2.20
572  **/
573 const gchar *
574 gdk_device_get_name (GdkDevice *device)
575 {
576   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
577
578   return device->name;
579 }
580
581 /**
582  * gdk_device_get_has_cursor:
583  * @device: a #GdkDevice
584  *
585  * Determines whether the pointer follows device motion.
586  *
587  * Return value: %TRUE if the pointer follows device motion
588  *
589  * Since: 2.20
590  **/
591 gboolean
592 gdk_device_get_has_cursor (GdkDevice *device)
593 {
594   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
595   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, FALSE);
596
597   return device->has_cursor;
598 }
599
600 /**
601  * gdk_device_get_source:
602  * @device: a #GdkDevice
603  *
604  * Determines the type of the device.
605  *
606  * Return value: a #GdkInputSource
607  *
608  * Since: 2.20
609  **/
610 GdkInputSource
611 gdk_device_get_source (GdkDevice *device)
612 {
613   g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
614
615   return device->source;
616 }
617
618 /**
619  * gdk_device_get_mode:
620  * @device: a #GdkDevice
621  *
622  * Determines the mode of the device.
623  *
624  * Return value: a #GdkInputSource
625  *
626  * Since: 2.20
627  **/
628 GdkInputMode
629 gdk_device_get_mode (GdkDevice *device)
630 {
631   g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
632
633   return device->mode;
634 }
635
636 /**
637  * gdk_device_set_mode:
638  * @device: a #GdkDevice.
639  * @mode: the input mode.
640  *
641  * Sets a the mode of an input device. The mode controls if the
642  * device is active and whether the device's range is mapped to the
643  * entire screen or to a single window.
644  *
645  * Returns: %TRUE if the mode was successfully changed.
646  **/
647 gboolean
648 gdk_device_set_mode (GdkDevice    *device,
649                      GdkInputMode  mode)
650 {
651   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
652
653   if (device->mode == mode)
654     return TRUE;
655
656   if (mode == GDK_MODE_DISABLED &&
657       gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER)
658     return FALSE;
659
660   device->mode = mode;
661   g_object_notify (G_OBJECT (device), "input-mode");
662
663   return TRUE;
664 }
665
666 /**
667  * gdk_device_get_n_keys:
668  * @device: a #GdkDevice
669  *
670  * Returns the number of keys the device currently has.
671  *
672  * Returns: the number of keys.
673  *
674  * Since: 2.24
675  **/
676 gint
677 gdk_device_get_n_keys (GdkDevice *device)
678 {
679   g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
680
681   return device->num_keys;
682 }
683
684 /**
685  * gdk_device_get_key:
686  * @device: a #GdkDevice.
687  * @index_: the index of the macro button to get.
688  * @keyval: return value for the keyval.
689  * @modifiers: return value for modifiers.
690  *
691  * If @index_ has a valid keyval, this function will return %TRUE
692  * and fill in @keyval and @modifiers with the keyval settings.
693  *
694  * Returns: %TRUE if keyval is set for @index.
695  *
696  * Since: 2.20
697  **/
698 gboolean
699 gdk_device_get_key (GdkDevice       *device,
700                     guint            index_,
701                     guint           *keyval,
702                     GdkModifierType *modifiers)
703 {
704   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
705   g_return_val_if_fail (index_ < device->num_keys, FALSE);
706
707   if (!device->keys[index_].keyval &&
708       !device->keys[index_].modifiers)
709     return FALSE;
710
711   if (keyval)
712     *keyval = device->keys[index_].keyval;
713
714   if (modifiers)
715     *modifiers = device->keys[index_].modifiers;
716
717   return TRUE;
718 }
719
720 /**
721  * gdk_device_set_key:
722  * @device: a #GdkDevice
723  * @index_: the index of the macro button to set
724  * @keyval: the keyval to generate
725  * @modifiers: the modifiers to set
726  *
727  * Specifies the X key event to generate when a macro button of a device
728  * is pressed.
729  **/
730 void
731 gdk_device_set_key (GdkDevice      *device,
732                     guint           index_,
733                     guint           keyval,
734                     GdkModifierType modifiers)
735 {
736   g_return_if_fail (GDK_IS_DEVICE (device));
737   g_return_if_fail (index_ < device->num_keys);
738
739   device->keys[index_].keyval = keyval;
740   device->keys[index_].modifiers = modifiers;
741 }
742
743 /**
744  * gdk_device_get_axis_use:
745  * @device: a pointer #GdkDevice.
746  * @index_: the index of the axis.
747  *
748  * Returns the axis use for @index_.
749  *
750  * Returns: a #GdkAxisUse specifying how the axis is used.
751  *
752  * Since: 2.20
753  **/
754 GdkAxisUse
755 gdk_device_get_axis_use (GdkDevice *device,
756                          guint      index_)
757 {
758   GdkAxisInfo *info;
759
760   g_return_val_if_fail (GDK_IS_DEVICE (device), GDK_AXIS_IGNORE);
761   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, GDK_AXIS_IGNORE);
762   g_return_val_if_fail (index_ < device->axes->len, GDK_AXIS_IGNORE);
763
764   info = &g_array_index (device->axes, GdkAxisInfo, index_);
765
766   return info->use;
767 }
768
769 /**
770  * gdk_device_set_axis_use:
771  * @device: a pointer #GdkDevice
772  * @index_: the index of the axis
773  * @use: specifies how the axis is used
774  *
775  * Specifies how an axis of a device is used.
776  **/
777 void
778 gdk_device_set_axis_use (GdkDevice   *device,
779                          guint        index_,
780                          GdkAxisUse   use)
781 {
782   GdkAxisInfo *info;
783
784   g_return_if_fail (GDK_IS_DEVICE (device));
785   g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
786   g_return_if_fail (index_ < device->axes->len);
787
788   info = &g_array_index (device->axes, GdkAxisInfo, index_);
789   info->use = use;
790
791   switch (use)
792     {
793     case GDK_AXIS_X:
794     case GDK_AXIS_Y:
795       info->min_axis = 0;
796       info->max_axis = 0;
797       break;
798     case GDK_AXIS_XTILT:
799     case GDK_AXIS_YTILT:
800       info->min_axis = -1;
801       info->max_axis = 1;
802       break;
803     default:
804       info->min_axis = 0;
805       info->max_axis = 1;
806       break;
807     }
808 }
809
810 /**
811  * gdk_device_get_display:
812  * @device: a #GdkDevice
813  *
814  * Returns the #GdkDisplay to which @device pertains.
815  *
816  * Returns: (transfer none): a #GdkDisplay. This memory is owned
817  *          by GTK+, and must not be freed or unreffed.
818  *
819  * Since: 3.0
820  **/
821 GdkDisplay *
822 gdk_device_get_display (GdkDevice *device)
823 {
824   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
825
826   return device->display;
827 }
828
829 /**
830  * gdk_device_get_associated_device:
831  * @device: a #GdkDevice
832  *
833  * Returns the associated device to @device, if @device is of type
834  * %GDK_DEVICE_TYPE_MASTER, it will return the paired pointer or
835  * keyboard.
836  *
837  * If @device is of type %GDK_DEVICE_TYPE_SLAVE, it will return
838  * the master device to which @device is attached to.
839  *
840  * If @device is of type %GDK_DEVICE_TYPE_FLOATING, %NULL will be
841  * returned, as there is no associated device.
842  *
843  * Returns: (transfer none): The associated device, or %NULL
844  *
845  * Since: 3.0
846  **/
847 GdkDevice *
848 gdk_device_get_associated_device (GdkDevice *device)
849 {
850   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
851
852   return device->associated;
853 }
854
855 static void
856 _gdk_device_set_device_type (GdkDevice     *device,
857                              GdkDeviceType  type)
858 {
859   if (device->type != type)
860     {
861       device->type = type;
862
863       g_object_notify (G_OBJECT (device), "type");
864     }
865 }
866
867 void
868 _gdk_device_set_associated_device (GdkDevice *device,
869                                    GdkDevice *associated)
870 {
871   g_return_if_fail (GDK_IS_DEVICE (device));
872   g_return_if_fail (associated == NULL || GDK_IS_DEVICE (associated));
873
874   if (device->associated == associated)
875     return;
876
877   if (device->associated)
878     {
879       g_object_unref (device->associated);
880       device->associated = NULL;
881     }
882
883   if (associated)
884     device->associated = g_object_ref (associated);
885
886   if (device->type != GDK_DEVICE_TYPE_MASTER)
887     {
888       if (device->associated)
889         _gdk_device_set_device_type (device, GDK_DEVICE_TYPE_SLAVE);
890       else
891         _gdk_device_set_device_type (device, GDK_DEVICE_TYPE_FLOATING);
892     }
893 }
894
895 /**
896  * gdk_device_list_slave_devices:
897  * @device: a #GdkDevice
898  *
899  * If the device if of type %GDK_DEVICE_TYPE_MASTER, it will return
900  * the list of slave devices attached to it, otherwise it will return
901  * %NULL
902  *
903  * Returns: (transfer container): the list of slave devices, or %NULL. The
904  *          list must be freed with g_list_free(), the contents of the list
905  *          are owned by GTK+ and should not be freed.
906  **/
907 GList *
908 gdk_device_list_slave_devices (GdkDevice *device)
909 {
910   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
911   g_return_val_if_fail (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER, NULL);
912
913   return g_list_copy (device->slaves);
914 }
915
916 void
917 _gdk_device_add_slave (GdkDevice *device,
918                        GdkDevice *slave)
919 {
920   g_return_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER);
921   g_return_if_fail (gdk_device_get_device_type (slave) != GDK_DEVICE_TYPE_MASTER);
922
923   if (!g_list_find (device->slaves, slave))
924     device->slaves = g_list_prepend (device->slaves, slave);
925 }
926
927 void
928 _gdk_device_remove_slave (GdkDevice *device,
929                           GdkDevice *slave)
930 {
931   GList *elem;
932
933   g_return_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER);
934   g_return_if_fail (gdk_device_get_device_type (slave) != GDK_DEVICE_TYPE_MASTER);
935
936   elem = g_list_find (device->slaves, slave);
937
938   if (!elem)
939     return;
940
941   device->slaves = g_list_delete_link (device->slaves, elem);
942 }
943
944 /**
945  * gdk_device_get_device_type:
946  * @device: a #GdkDevice
947  *
948  * Returns the device type for @device.
949  *
950  * Returns: the #GdkDeviceType for @device.
951  *
952  * Since: 3.0
953  **/
954 GdkDeviceType
955 gdk_device_get_device_type (GdkDevice *device)
956 {
957   g_return_val_if_fail (GDK_IS_DEVICE (device), GDK_DEVICE_TYPE_MASTER);
958
959   return device->type;
960 }
961
962 /**
963  * gdk_device_get_n_axes:
964  * @device: a pointer #GdkDevice
965  *
966  * Returns the number of axes the device currently has.
967  *
968  * Returns: the number of axes.
969  *
970  * Since: 3.0
971  **/
972 gint
973 gdk_device_get_n_axes (GdkDevice *device)
974 {
975   g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
976   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, 0);
977
978   return device->axes->len;
979 }
980
981 /**
982  * gdk_device_list_axes:
983  * @device: a pointer #GdkDevice
984  *
985  * Returns a #GList of #GdkAtom<!-- -->s, containing the labels for
986  * the axes that @device currently has.
987  *
988  * Returns: (transfer container) (element-type GdkAtom):
989  *     A #GList of #GdkAtom<!-- -->s, free with g_list_free().
990  *
991  * Since: 3.0
992  **/
993 GList *
994 gdk_device_list_axes (GdkDevice *device)
995 {
996   GList *axes = NULL;
997   gint i;
998
999   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
1000   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
1001
1002   for (i = 0; i < device->axes->len; i++)
1003     {
1004       GdkAxisInfo axis_info;
1005
1006       axis_info = g_array_index (device->axes, GdkAxisInfo, i);
1007       axes = g_list_prepend (axes, GDK_ATOM_TO_POINTER (axis_info.label));
1008     }
1009
1010   return g_list_reverse (axes);
1011 }
1012
1013 /**
1014  * gdk_device_get_axis_value:
1015  * @device: a pointer #GdkDevice.
1016  * @axes: pointer to an array of axes
1017  * @axis_label: #GdkAtom with the axis label.
1018  * @value: location to store the found value.
1019  *
1020  * Interprets an array of double as axis values for a given device,
1021  * and locates the value in the array for a given axis label, as returned
1022  * by gdk_device_list_axes()
1023  *
1024  * Returns: %TRUE if the given axis use was found, otherwise %FALSE.
1025  *
1026  * Since: 3.0
1027  **/
1028 gboolean
1029 gdk_device_get_axis_value (GdkDevice *device,
1030                            gdouble   *axes,
1031                            GdkAtom    axis_label,
1032                            gdouble   *value)
1033 {
1034   gint i;
1035
1036   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1037   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, FALSE);
1038
1039   if (axes == NULL)
1040     return FALSE;
1041
1042   for (i = 0; i < device->axes->len; i++)
1043     {
1044       GdkAxisInfo axis_info;
1045
1046       axis_info = g_array_index (device->axes, GdkAxisInfo, i);
1047
1048       if (axis_info.label != axis_label)
1049         continue;
1050
1051       if (value)
1052         *value = axes[i];
1053
1054       return TRUE;
1055     }
1056
1057   return FALSE;
1058 }
1059
1060 /**
1061  * gdk_device_get_axis:
1062  * @device: a #GdkDevice
1063  * @axes: pointer to an array of axes
1064  * @use: the use to look for
1065  * @value: location to store the found value.
1066  *
1067  * Interprets an array of double as axis values for a given device,
1068  * and locates the value in the array for a given axis use.
1069  *
1070  * Return value: %TRUE if the given axis use was found, otherwise %FALSE
1071  **/
1072 gboolean
1073 gdk_device_get_axis (GdkDevice  *device,
1074                      gdouble    *axes,
1075                      GdkAxisUse  use,
1076                      gdouble    *value)
1077 {
1078   gint i;
1079
1080   g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
1081   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, FALSE);
1082
1083   if (axes == NULL)
1084     return FALSE;
1085
1086   g_return_val_if_fail (device->axes != NULL, FALSE);
1087
1088   for (i = 0; i < device->axes->len; i++)
1089     {
1090       GdkAxisInfo axis_info;
1091
1092       axis_info = g_array_index (device->axes, GdkAxisInfo, i);
1093
1094       if (axis_info.use != use)
1095         continue;
1096
1097       if (value)
1098         *value = axes[i];
1099
1100       return TRUE;
1101     }
1102
1103   return FALSE;
1104 }
1105
1106 static GdkEventMask
1107 get_native_grab_event_mask (GdkEventMask grab_mask)
1108 {
1109   /* Similar to the above but for pointer events only */
1110   return
1111     GDK_POINTER_MOTION_MASK |
1112     GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1113     GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1114     GDK_SCROLL_MASK |
1115     (grab_mask &
1116      ~(GDK_POINTER_MOTION_HINT_MASK |
1117        GDK_BUTTON_MOTION_MASK |
1118        GDK_BUTTON1_MOTION_MASK |
1119        GDK_BUTTON2_MOTION_MASK |
1120        GDK_BUTTON3_MOTION_MASK));
1121 }
1122
1123 /**
1124  * gdk_device_grab:
1125  * @device: a #GdkDevice. To get the device you can use gtk_get_current_event_device()
1126  *   or gdk_event_get_device() if the grab is in reaction to an event. Also, you can use
1127  *   gdk_device_manager_get_client_pointer() but only in code that isn't triggered by a
1128  *   #GdkEvent and there aren't other means to get a meaningful #GdkDevice to operate on.
1129  * @window: the #GdkWindow which will own the grab (the grab window)
1130  * @grab_ownership: specifies the grab ownership.
1131  * @owner_events: if %FALSE then all device events are reported with respect to
1132  *                @window and are only reported if selected by @event_mask. If
1133  *                %TRUE then pointer events for this application are reported
1134  *                as normal, but pointer events outside this application are
1135  *                reported with respect to @window and only if selected by
1136  *                @event_mask. In either mode, unreported events are discarded.
1137  * @event_mask: specifies the event mask, which is used in accordance with
1138  *              @owner_events.
1139  * @cursor: the cursor to display while the grab is active if the device is
1140  *          a pointer. If this is %NULL then the normal cursors are used for
1141  *          @window and its descendants, and the cursor for @window is used
1142  *          elsewhere.
1143  * @time_: the timestamp of the event which led to this pointer grab. This
1144  *         usually comes from the #GdkEvent struct, though %GDK_CURRENT_TIME
1145  *         can be used if the time isn't known.
1146  *
1147  * Grabs the device so that all events coming from this device are passed to
1148  * this application until the device is ungrabbed with gdk_device_ungrab(),
1149  * or the window becomes unviewable. This overrides any previous grab on the device
1150  * by this client.
1151  *
1152  * Device grabs are used for operations which need complete control over the
1153  * given device events (either pointer or keyboard). For example in GTK+ this
1154  * is used for Drag and Drop operations, popup menus and such.
1155  *
1156  * Note that if the event mask of an X window has selected both button press
1157  * and button release events, then a button press event will cause an automatic
1158  * pointer grab until the button is released. X does this automatically since
1159  * most applications expect to receive button press and release events in pairs.
1160  * It is equivalent to a pointer grab on the window with @owner_events set to
1161  * %TRUE.
1162  *
1163  * If you set up anything at the time you take the grab that needs to be
1164  * cleaned up when the grab ends, you should handle the #GdkEventGrabBroken
1165  * events that are emitted when the grab ends unvoluntarily.
1166  *
1167  * Returns: %GDK_GRAB_SUCCESS if the grab was successful.
1168  *
1169  * Since: 3.0
1170  **/
1171 GdkGrabStatus
1172 gdk_device_grab (GdkDevice        *device,
1173                  GdkWindow        *window,
1174                  GdkGrabOwnership  grab_ownership,
1175                  gboolean          owner_events,
1176                  GdkEventMask      event_mask,
1177                  GdkCursor        *cursor,
1178                  guint32           time_)
1179 {
1180   GdkGrabStatus res;
1181   GdkWindow *native;
1182
1183   g_return_val_if_fail (GDK_IS_DEVICE (device), GDK_GRAB_SUCCESS);
1184   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_GRAB_SUCCESS);
1185
1186   if (_gdk_native_windows)
1187     native = window;
1188   else
1189     native = gdk_window_get_toplevel (window);
1190
1191   while (native->window_type == GDK_WINDOW_OFFSCREEN)
1192     {
1193       native = gdk_offscreen_window_get_embedder (native);
1194
1195       if (native == NULL ||
1196           (!_gdk_window_has_impl (native) &&
1197            !gdk_window_is_viewable (native)))
1198         return GDK_GRAB_NOT_VIEWABLE;
1199
1200       native = gdk_window_get_toplevel (native);
1201     }
1202
1203   if (native == NULL || GDK_WINDOW_DESTROYED (native))
1204     return GDK_GRAB_NOT_VIEWABLE;
1205
1206   res = GDK_DEVICE_GET_CLASS (device)->grab (device,
1207                                              native,
1208                                              owner_events,
1209                                              get_native_grab_event_mask (event_mask),
1210                                              NULL,
1211                                              cursor,
1212                                              time_);
1213
1214   if (res == GDK_GRAB_SUCCESS)
1215     {
1216       GdkDisplay *display;
1217       gulong serial;
1218
1219       display = gdk_window_get_display (window);
1220       serial = _gdk_display_get_next_serial (display);
1221
1222       _gdk_display_add_device_grab (display,
1223                                     device,
1224                                     window,
1225                                     native,
1226                                     grab_ownership,
1227                                     owner_events,
1228                                     event_mask,
1229                                     serial,
1230                                     time_,
1231                                     FALSE);
1232     }
1233
1234   return res;
1235 }
1236
1237 /**
1238  * gdk_device_ungrab:
1239  * @device: a #GdkDevice
1240  * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
1241  *
1242  * Release any grab on @device.
1243  *
1244  * Since: 3.0
1245  */
1246 void
1247 gdk_device_ungrab (GdkDevice  *device,
1248                    guint32     time_)
1249 {
1250   g_return_if_fail (GDK_IS_DEVICE (device));
1251
1252   GDK_DEVICE_GET_CLASS (device)->ungrab (device, time_);
1253 }
1254
1255 /**
1256  * gdk_device_warp:
1257  * @device: the device to warp.
1258  * @screen: the screen to warp @device to.
1259  * @x: the X coordinate of the destination.
1260  * @y: the Y coordinate of the destination.
1261  *
1262  * Warps @device in @display to the point @x,@y on
1263  * the screen @screen, unless the device is confined
1264  * to a window by a grab, in which case it will be moved
1265  * as far as allowed by the grab. Warping the pointer
1266  * creates events as if the user had moved the mouse
1267  * instantaneously to the destination.
1268  *
1269  * Note that the pointer should normally be under the
1270  * control of the user. This function was added to cover
1271  * some rare use cases like keyboard navigation support
1272  * for the color picker in the #GtkColorSelectionDialog.
1273  *
1274  * Since: 3.0
1275  **/
1276 void
1277 gdk_device_warp (GdkDevice  *device,
1278                  GdkScreen  *screen,
1279                  gint        x,
1280                  gint        y)
1281 {
1282   g_return_if_fail (GDK_IS_DEVICE (device));
1283   g_return_if_fail (GDK_IS_SCREEN (screen));
1284   g_return_if_fail (gdk_device_get_display (device) == gdk_screen_get_display (screen));
1285
1286   GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
1287 }
1288
1289 /* Private API */
1290 void
1291 _gdk_device_reset_axes (GdkDevice *device)
1292 {
1293   gint i;
1294
1295   for (i = device->axes->len - 1; i >= 0; i--)
1296     g_array_remove_index (device->axes, i);
1297
1298   g_object_notify (G_OBJECT (device), "n-axes");
1299 }
1300
1301 guint
1302 _gdk_device_add_axis (GdkDevice   *device,
1303                       GdkAtom      label_atom,
1304                       GdkAxisUse   use,
1305                       gdouble      min_value,
1306                       gdouble      max_value,
1307                       gdouble      resolution)
1308 {
1309   GdkAxisInfo axis_info;
1310   guint pos;
1311
1312   axis_info.use = use;
1313   axis_info.label = label_atom;
1314   axis_info.min_value = min_value;
1315   axis_info.max_value = max_value;
1316   axis_info.resolution = resolution;
1317
1318   switch (use)
1319     {
1320     case GDK_AXIS_X:
1321     case GDK_AXIS_Y:
1322       axis_info.min_axis = 0;
1323       axis_info.max_axis = 0;
1324       break;
1325     case GDK_AXIS_XTILT:
1326     case GDK_AXIS_YTILT:
1327       axis_info.min_axis = -1;
1328       axis_info.max_axis = 1;
1329       break;
1330     default:
1331       axis_info.min_axis = 0;
1332       axis_info.max_axis = 1;
1333       break;
1334     }
1335
1336   device->axes = g_array_append_val (device->axes, axis_info);
1337   pos = device->axes->len - 1;
1338
1339   g_object_notify (G_OBJECT (device), "n-axes");
1340
1341   return pos;
1342 }
1343
1344 void
1345 _gdk_device_set_keys (GdkDevice *device,
1346                       guint      num_keys)
1347 {
1348   if (device->keys)
1349     g_free (device->keys);
1350
1351   device->num_keys = num_keys;
1352   device->keys = g_new0 (GdkDeviceKey, num_keys);
1353 }
1354
1355 static GdkAxisInfo *
1356 find_axis_info (GArray     *array,
1357                 GdkAxisUse  use)
1358 {
1359   GdkAxisInfo *info;
1360   gint i;
1361
1362   for (i = 0; i < GDK_AXIS_LAST; i++)
1363     {
1364       info = &g_array_index (array, GdkAxisInfo, i);
1365
1366       if (info->use == use)
1367         return info;
1368     }
1369
1370   return NULL;
1371 }
1372
1373 GdkAxisUse
1374 _gdk_device_get_axis_use (GdkDevice *device,
1375                           guint      index_)
1376 {
1377   GdkAxisInfo info;
1378
1379   info = g_array_index (device->axes, GdkAxisInfo, index_);
1380   return info.use;
1381 }
1382
1383 gboolean
1384 _gdk_device_translate_window_coord (GdkDevice *device,
1385                                     GdkWindow *window,
1386                                     guint      index_,
1387                                     gdouble    value,
1388                                     gdouble   *axis_value)
1389 {
1390   GdkAxisInfo axis_info;
1391   GdkAxisInfo *axis_info_x, *axis_info_y;
1392   gdouble device_width, device_height;
1393   gdouble x_offset, y_offset;
1394   gdouble x_scale, y_scale;
1395   gdouble x_min, y_min;
1396   gdouble x_resolution, y_resolution;
1397   gdouble device_aspect;
1398   gint window_width, window_height;
1399
1400   if (index_ >= device->axes->len)
1401     return FALSE;
1402
1403   axis_info = g_array_index (device->axes, GdkAxisInfo, index_);
1404
1405   if (axis_info.use != GDK_AXIS_X &&
1406       axis_info.use != GDK_AXIS_Y)
1407     return FALSE;
1408
1409   if (axis_info.use == GDK_AXIS_X)
1410     {
1411       axis_info_x = &axis_info;
1412       axis_info_y = find_axis_info (device->axes, GDK_AXIS_Y);
1413     }
1414   else
1415     {
1416       axis_info_x = find_axis_info (device->axes, GDK_AXIS_X);
1417       axis_info_y = &axis_info;
1418     }
1419
1420   device_width = axis_info_x->max_value - axis_info_x->min_value;
1421   device_height = axis_info_y->max_value - axis_info_y->min_value;
1422
1423   if (device_width > 0)
1424     x_min = axis_info_x->min_value;
1425   else
1426     {
1427       device_width = gdk_screen_get_width (gdk_window_get_screen (window));
1428       x_min = 0;
1429     }
1430
1431   if (device_height > 0)
1432     y_min = axis_info_y->min_value;
1433   else
1434     {
1435       device_height = gdk_screen_get_height (gdk_window_get_screen (window));
1436       y_min = 0;
1437     }
1438
1439   window_width = gdk_window_get_width (window);
1440   window_height = gdk_window_get_height (window);
1441
1442   x_resolution = axis_info_x->resolution;
1443   y_resolution = axis_info_y->resolution;
1444
1445   /*
1446    * Some drivers incorrectly report the resolution of the device
1447    * as zero (in partiular linuxwacom < 0.5.3 with usb tablets).
1448    * This causes the device_aspect to become NaN and totally
1449    * breaks windowed mode.  If this is the case, the best we can
1450    * do is to assume the resolution is non-zero is equal in both
1451    * directions (which is true for many devices).  The absolute
1452    * value of the resolution doesn't matter since we only use the
1453    * ratio.
1454    */
1455   if (x_resolution == 0 || y_resolution == 0)
1456     {
1457       x_resolution = 1;
1458       y_resolution = 1;
1459     }
1460
1461   device_aspect = (device_height * y_resolution) /
1462     (device_width * x_resolution);
1463
1464   if (device_aspect * window_width >= window_height)
1465     {
1466       /* device taller than window */
1467       x_scale = window_width / device_width;
1468       y_scale = (x_scale * x_resolution) / y_resolution;
1469
1470       x_offset = 0;
1471       y_offset = - (device_height * y_scale - window_height) / 2;
1472     }
1473   else
1474     {
1475       /* window taller than device */
1476       y_scale = window_height / device_height;
1477       x_scale = (y_scale * y_resolution) / x_resolution;
1478
1479       y_offset = 0;
1480       x_offset = - (device_width * x_scale - window_width) / 2;
1481     }
1482
1483   if (axis_value)
1484     {
1485       if (axis_info.use == GDK_AXIS_X)
1486         *axis_value = x_offset + x_scale * (value - x_min);
1487       else
1488         *axis_value = y_offset + y_scale * (value - y_min);
1489     }
1490
1491   return TRUE;
1492 }
1493
1494 gboolean
1495 _gdk_device_translate_screen_coord (GdkDevice *device,
1496                                     GdkWindow *window,
1497                                     gint       window_root_x,
1498                                     gint       window_root_y,
1499                                     guint      index_,
1500                                     gdouble    value,
1501                                     gdouble   *axis_value)
1502 {
1503   GdkAxisInfo axis_info;
1504   gdouble axis_width, scale, offset;
1505
1506   if (device->mode != GDK_MODE_SCREEN)
1507     return FALSE;
1508
1509   if (index_ >= device->axes->len)
1510     return FALSE;
1511
1512   axis_info = g_array_index (device->axes, GdkAxisInfo, index_);
1513
1514   if (axis_info.use != GDK_AXIS_X &&
1515       axis_info.use != GDK_AXIS_Y)
1516     return FALSE;
1517
1518   axis_width = axis_info.max_value - axis_info.min_value;
1519
1520   if (axis_info.use == GDK_AXIS_X)
1521     {
1522       if (axis_width > 0)
1523         scale = gdk_screen_get_width (gdk_window_get_screen (window)) / axis_width;
1524       else
1525         scale = 1;
1526
1527       offset = - window_root_x - window->abs_x;
1528     }
1529   else
1530     {
1531       if (axis_width > 0)
1532         scale = gdk_screen_get_height (gdk_window_get_screen (window)) / axis_width;
1533       else
1534         scale = 1;
1535
1536       offset = - window_root_y - window->abs_y;
1537     }
1538
1539   if (axis_value)
1540     *axis_value = offset + scale * (value - axis_info.min_value);
1541
1542   return TRUE;
1543 }
1544
1545 gboolean
1546 _gdk_device_translate_axis (GdkDevice *device,
1547                             guint      index_,
1548                             gdouble    value,
1549                             gdouble   *axis_value)
1550 {
1551   GdkAxisInfo axis_info;
1552   gdouble axis_width, out;
1553
1554   if (index_ >= device->axes->len)
1555     return FALSE;
1556
1557   axis_info = g_array_index (device->axes, GdkAxisInfo, index_);
1558
1559   if (axis_info.use == GDK_AXIS_X ||
1560       axis_info.use == GDK_AXIS_Y)
1561     return FALSE;
1562
1563   axis_width = axis_info.max_value - axis_info.min_value;
1564   out = (axis_info.max_axis * (value - axis_info.min_value) +
1565          axis_info.min_axis * (axis_info.max_value - value)) / axis_width;
1566
1567   if (axis_value)
1568     *axis_value = out;
1569
1570   return TRUE;
1571 }
1572
1573 gboolean
1574 _gdk_device_query_state (GdkDevice        *device,
1575                          GdkWindow        *window,
1576                          GdkWindow       **root_window,
1577                          GdkWindow       **child_window,
1578                          gint             *root_x,
1579                          gint             *root_y,
1580                          gint             *win_x,
1581                          gint             *win_y,
1582                          GdkModifierType  *mask)
1583 {
1584   return GDK_DEVICE_GET_CLASS (device)->query_state (device,
1585                                                      window,
1586                                                      root_window,
1587                                                      child_window,
1588                                                      root_x,
1589                                                      root_y,
1590                                                      win_x,
1591                                                      win_y,
1592                                                      mask);
1593 }
1594
1595 GdkWindow *
1596 _gdk_device_window_at_position (GdkDevice        *device,
1597                                 gint             *win_x,
1598                                 gint             *win_y,
1599                                 GdkModifierType  *mask,
1600                                 gboolean          get_toplevel)
1601 {
1602   return GDK_DEVICE_GET_CLASS (device)->window_at_position (device,
1603                                                             win_x,
1604                                                             win_y,
1605                                                             mask,
1606                                                             get_toplevel);
1607 }