]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkinput.c
87862f1915baed264a4ffcc2be502a14f1d1fcde
[~andy/gtk] / gdk / win32 / gdkinput.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* This file should really be one level up, in the backend-independent
28  * GDK, and the x11/gdkinput.c could also be removed.
29  * 
30  * That stuff in x11/gdkinput.c which really *is* X11-dependent should
31  * be in x11/gdkinput-x11.c.
32  */
33
34 #include "config.h"
35
36 #include "gdkdisplay.h"
37 #include "gdkinput.h"
38
39 #include "gdkprivate-win32.h"
40 #include "gdkinput-win32.h"
41
42 static GdkDeviceAxis gdk_input_core_axes[] = {
43   { GDK_AXIS_X, 0, 0 },
44   { GDK_AXIS_Y, 0, 0 }
45 };
46
47 /* Global variables  */
48
49 gint              _gdk_input_ignore_core;
50
51 GList            *_gdk_input_devices;
52 GList            *_gdk_input_windows;
53
54 void
55 _gdk_init_input_core (GdkDisplay *display)
56 {
57   display->core_pointer = g_object_new (GDK_TYPE_DEVICE, NULL);
58   
59   display->core_pointer->name = "Core Pointer";
60   display->core_pointer->source = GDK_SOURCE_MOUSE;
61   display->core_pointer->mode = GDK_MODE_SCREEN;
62   display->core_pointer->has_cursor = TRUE;
63   display->core_pointer->num_axes = 2;
64   display->core_pointer->axes = gdk_input_core_axes;
65   display->core_pointer->num_keys = 0;
66   display->core_pointer->keys = NULL;
67 }
68
69 GType
70 gdk_device_get_type (void)
71 {
72   static GType object_type = 0;
73
74   if (!object_type)
75     {
76       const GTypeInfo object_info =
77         {
78           sizeof (GdkDeviceClass),
79           (GBaseInitFunc) NULL,
80           (GBaseFinalizeFunc) NULL,
81           (GClassInitFunc) NULL,
82           NULL,                 /* class_finalize */
83           NULL,                 /* class_data */
84           sizeof (GdkDevicePrivate),
85           0,                    /* n_preallocs */
86           (GInstanceInitFunc) NULL,
87         };
88       
89       object_type = g_type_register_static (G_TYPE_OBJECT,
90                                             g_intern_static_string ("GdkDevice"),
91                                             &object_info, 0);
92     }
93   
94   return object_type;
95 }
96
97 GList *
98 gdk_devices_list (void)
99 {
100   return gdk_display_list_devices (_gdk_display);
101 }
102
103 GList *
104 gdk_display_list_devices (GdkDisplay *dpy)
105 {
106   g_return_val_if_fail (dpy == _gdk_display, NULL);
107
108   _gdk_input_wintab_init_check ();
109   return _gdk_input_devices;
110 }
111
112 void
113 gdk_device_set_source (GdkDevice      *device,
114                        GdkInputSource  source)
115 {
116   g_return_if_fail (device != NULL);
117
118   device->source = source;
119 }
120
121 void
122 gdk_device_set_key (GdkDevice      *device,
123                     guint           index,
124                     guint           keyval,
125                     GdkModifierType modifiers)
126 {
127   g_return_if_fail (device != NULL);
128   g_return_if_fail (index < device->num_keys);
129
130   device->keys[index].keyval = keyval;
131   device->keys[index].modifiers = modifiers;
132 }
133
134 void
135 gdk_device_set_axis_use (GdkDevice   *device,
136                          guint        index,
137                          GdkAxisUse   use)
138 {
139   g_return_if_fail (device != NULL);
140   g_return_if_fail (index < device->num_axes);
141
142   device->axes[index].use = use;
143
144   switch (use)
145     {
146     case GDK_AXIS_X:
147     case GDK_AXIS_Y:
148       device->axes[index].min = 0.;
149       device->axes[index].max = 0.;
150       break;
151     case GDK_AXIS_XTILT:
152     case GDK_AXIS_YTILT:
153       device->axes[index].min = -1.;
154       device->axes[index].max = 1;
155       break;
156     default:
157       device->axes[index].min = 0.;
158       device->axes[index].max = 1;
159       break;
160     }
161 }
162
163 gboolean
164 gdk_device_get_history  (GdkDevice         *device,
165                          GdkWindow         *window,
166                          guint32            start,
167                          guint32            stop,
168                          GdkTimeCoord    ***events,
169                          gint              *n_events)
170 {
171   g_return_val_if_fail (window != NULL, FALSE);
172   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
173   g_return_val_if_fail (events != NULL, FALSE);
174   g_return_val_if_fail (n_events != NULL, FALSE);
175
176   if (n_events)
177     *n_events = 0;
178   if (events)
179     *events = NULL;
180
181   if (GDK_WINDOW_DESTROYED (window))
182     return FALSE;
183     
184   if (GDK_IS_CORE (device))
185     return FALSE;
186   else
187     return _gdk_device_get_history (device, window, start, stop, events, n_events);
188 }
189
190 GdkTimeCoord ** 
191 _gdk_device_allocate_history (GdkDevice *device,
192                               gint       n_events)
193 {
194   GdkTimeCoord **result = g_new (GdkTimeCoord *, n_events);
195   gint i;
196
197   for (i=0; i<n_events; i++)
198     result[i] = g_malloc (sizeof (GdkTimeCoord) -
199                           sizeof (double) * (GDK_MAX_TIMECOORD_AXES - device->num_axes));
200
201   return result;
202 }
203
204 void 
205 gdk_device_free_history (GdkTimeCoord **events,
206                          gint           n_events)
207 {
208   gint i;
209   
210   for (i=0; i<n_events; i++)
211     g_free (events[i]);
212
213   g_free (events);
214 }
215
216 GdkInputWindow *
217 _gdk_input_window_find(GdkWindow *window)
218 {
219   GList *tmp_list;
220
221   for (tmp_list=_gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
222     if (((GdkInputWindow *)(tmp_list->data))->window == window)
223       return (GdkInputWindow *)(tmp_list->data);
224
225   return NULL;      /* Not found */
226 }
227
228 /* FIXME: this routine currently needs to be called between creation
229    and the corresponding configure event (because it doesn't get the
230    root_relative_geometry).  This should work with
231    gtk_window_set_extension_events, but will likely fail in other
232    cases */
233
234 void
235 gdk_input_set_extension_events (GdkWindow *window, gint mask,
236                                 GdkExtensionMode mode)
237 {
238   GdkWindowObject *window_private;
239   GList *tmp_list;
240   GdkInputWindow *iw;
241
242   g_return_if_fail (window != NULL);
243   g_return_if_fail (GDK_IS_WINDOW (window));
244
245   window_private = (GdkWindowObject*) window;
246   if (GDK_WINDOW_DESTROYED (window))
247     return;
248
249   if (mode == GDK_EXTENSION_EVENTS_NONE)
250     mask = 0;
251
252   if (mask != 0)
253     {
254       _gdk_input_wintab_init_check ();
255
256       iw = g_new(GdkInputWindow,1);
257
258       iw->window = window;
259       iw->mode = mode;
260
261       iw->obscuring = NULL;
262       iw->num_obscuring = 0;
263       iw->grabbed = FALSE;
264
265       _gdk_input_windows = g_list_append(_gdk_input_windows,iw);
266       window_private->extension_events = mask;
267
268       /* Add enter window events to the event mask */
269       if (g_list_length (_gdk_input_devices) > 1)
270         gdk_window_set_events (window,
271                                gdk_window_get_events (window) | 
272                                GDK_ENTER_NOTIFY_MASK);
273     }
274   else
275     {
276       iw = _gdk_input_window_find (window);
277       if (iw)
278         {
279           _gdk_input_windows = g_list_remove(_gdk_input_windows,iw);
280           g_free(iw);
281         }
282
283       window_private->extension_events = 0;
284     }
285
286   for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
287     {
288       GdkDevicePrivate *gdkdev = tmp_list->data;
289
290       if (!GDK_IS_CORE (gdkdev))
291         {
292           if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
293               && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
294             _gdk_input_enable_window (window,gdkdev);
295           else
296             _gdk_input_disable_window (window,gdkdev);
297         }
298     }
299 }
300
301 void
302 _gdk_input_window_destroy (GdkWindow *window)
303 {
304   GdkInputWindow *input_window;
305
306   input_window = _gdk_input_window_find (window);
307   g_return_if_fail (input_window != NULL);
308
309   _gdk_input_windows = g_list_remove (_gdk_input_windows,input_window);
310   g_free(input_window);
311 }
312
313 void
314 _gdk_input_crossing_event (GdkWindow *window,
315                            gboolean enter)
316 {
317   GdkWindowObject *priv = (GdkWindowObject *)window;
318   GdkInputWindow *input_window;
319   gint root_x, root_y;
320
321   if (enter)
322     {
323 #if 0
324       /* No idea what to do... */
325 #if 0
326       gdk_input_check_proximity(display);
327 #endif
328       input_window = priv->input_window;
329       if (input_window != NULL)
330         {
331           _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
332           input_window->root_x = root_x;
333           input_window->root_y = root_y;
334         }
335 #endif
336     }
337   else
338     _gdk_input_ignore_core = FALSE;
339 }
340
341 void
342 _gdk_input_exit (void)
343 {
344   GList *tmp_list;
345   GdkDevicePrivate *gdkdev;
346
347   for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
348     {
349       gdkdev = (GdkDevicePrivate *)(tmp_list->data);
350       if (!GDK_IS_CORE (gdkdev))
351         {
352           gdk_device_set_mode (&gdkdev->info, GDK_MODE_DISABLED);
353
354           g_free(gdkdev->info.name);
355           g_free(gdkdev->axes);
356           g_free(gdkdev->info.axes);
357           g_free(gdkdev->info.keys);
358           g_free(gdkdev);
359         }
360     }
361
362   g_list_free(_gdk_input_devices);
363
364   for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
365     g_free(tmp_list->data);
366
367   g_list_free(_gdk_input_windows);
368 }
369
370 gboolean
371 gdk_device_get_axis (GdkDevice  *device,
372                      gdouble    *axes,
373                      GdkAxisUse  use,
374                      gdouble    *value)
375 {
376   gint i;
377   
378   g_return_val_if_fail (device != NULL, FALSE);
379
380   if (axes == NULL)
381     return FALSE;
382   
383   for (i=0; i<device->num_axes; i++)
384     if (device->axes[i].use == use)
385       {
386         if (value)
387           *value = axes[i];
388         return TRUE;
389       }
390   
391   return FALSE;
392 }
393
394 gboolean
395 gdk_device_set_mode (GdkDevice   *device,
396                      GdkInputMode mode)
397 {
398   GList *tmp_list;
399   GdkDevicePrivate *gdkdev;
400   GdkInputMode old_mode;
401   GdkInputWindow *input_window;
402
403   if (GDK_IS_CORE (device))
404     return FALSE;
405
406   gdkdev = (GdkDevicePrivate *)device;
407
408   if (device->mode == mode)
409     return TRUE;
410
411   old_mode = device->mode;
412   device->mode = mode;
413
414   if (mode == GDK_MODE_WINDOW)
415     {
416       device->has_cursor = FALSE;
417       for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
418         {
419           input_window = (GdkInputWindow *)tmp_list->data;
420           if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
421             _gdk_input_enable_window (input_window->window, gdkdev);
422           else
423             if (old_mode != GDK_MODE_DISABLED)
424               _gdk_input_disable_window (input_window->window, gdkdev);
425         }
426     }
427   else if (mode == GDK_MODE_SCREEN)
428     {
429       device->has_cursor = TRUE;
430       for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
431         _gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
432                                   gdkdev);
433     }
434   else  /* mode == GDK_MODE_DISABLED */
435     {
436       for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
437         {
438           input_window = (GdkInputWindow *)tmp_list->data;
439           if (old_mode != GDK_MODE_WINDOW ||
440               input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
441             _gdk_input_disable_window (input_window->window, gdkdev);
442         }
443     }
444
445   return TRUE;
446 }