]> Pileus Git - ~andy/gtk/blob - gdk/gdkinput.c
Make gtk_propagate_event() non-static, we need it in gtkdnd.c so that the
[~andy/gtk] / gdk / 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 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 #include <stdlib.h>
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22 #include "config.h"
23 #include "gdk.h"
24 #include "gdkx.h"
25 #include "gdkprivate.h"
26 #include "gdkinput.h"
27
28
29 /* Forward declarations */
30
31 static gint gdk_input_enable_window (GdkWindow *window,
32                                      GdkDevicePrivate *gdkdev);
33 static gint gdk_input_disable_window (GdkWindow *window,
34                                       GdkDevicePrivate *gdkdev);
35 static GdkInputWindow *gdk_input_window_find (GdkWindow *window);
36 static GdkDevicePrivate *gdk_input_find_device (guint32 id);
37
38
39 /* Incorporate the specific routines depending on compilation options */
40
41 static const GdkAxisUse gdk_input_core_axes[] = { GDK_AXIS_X, GDK_AXIS_Y };
42
43 static const GdkDeviceInfo gdk_input_core_info =
44 {
45   GDK_CORE_POINTER,
46   "Core Pointer",
47   GDK_SOURCE_MOUSE,
48   GDK_MODE_SCREEN,
49   TRUE,
50   2,
51   gdk_input_core_axes
52 };
53
54 /* Global variables  */
55
56 GdkInputVTable    gdk_input_vtable;
57 /* information about network port and host for gxid daemon */
58 gchar            *gdk_input_gxid_host;
59 gint              gdk_input_gxid_port;
60 gint              gdk_input_ignore_core;
61
62 /* Local variables */
63
64 static GList            *gdk_input_devices;
65 static GList            *gdk_input_windows;
66
67 #include "gdkinputnone.h"
68 #include "gdkinputcommon.h"
69 #include "gdkinputxfree.h"
70 #include "gdkinputgxi.h"
71
72 GList *
73 gdk_input_list_devices (void)
74 {
75   return gdk_input_devices;
76 }
77
78 void
79 gdk_input_set_source (guint32 deviceid, GdkInputSource source)
80 {
81   GdkDevicePrivate *gdkdev = gdk_input_find_device(deviceid);
82   g_return_if_fail (gdkdev != NULL);
83
84   gdkdev->info.source = source;
85 }
86
87 gint
88 gdk_input_set_mode (guint32 deviceid, GdkInputMode mode)
89 {
90   if (deviceid == GDK_CORE_POINTER)
91     return FALSE;
92
93   if (gdk_input_vtable.set_mode)
94     return gdk_input_vtable.set_mode(deviceid,mode);
95   else
96     return FALSE;
97 }
98
99 void
100 gdk_input_set_axes (guint32 deviceid, GdkAxisUse *axes)
101 {
102   if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_axes)
103     gdk_input_vtable.set_axes (deviceid, axes);
104 }
105
106 void gdk_input_set_key (guint32 deviceid,
107                         guint   index,
108                         guint   keyval,
109                         GdkModifierType modifiers)
110 {
111   if (deviceid != GDK_CORE_POINTER && gdk_input_vtable.set_key)
112     gdk_input_vtable.set_key (deviceid, index, keyval, modifiers);
113 }
114
115 GdkTimeCoord *
116 gdk_input_motion_events (GdkWindow *window,
117                          guint32 deviceid,
118                          guint32 start,
119                          guint32 stop,
120                          gint *nevents_return)
121 {
122   GdkWindowPrivate *window_private;
123   XTimeCoord *xcoords;
124   GdkTimeCoord *coords;
125   int i;
126
127   g_return_val_if_fail (window != NULL, NULL);
128   window_private = (GdkWindowPrivate *) window;
129   if (window_private->destroyed)
130     return NULL;
131
132   if (deviceid == GDK_CORE_POINTER)
133     {
134       xcoords = XGetMotionEvents (gdk_display,
135                                   window_private->xwindow,
136                                   start, stop, nevents_return);
137       if (xcoords)
138         {
139           coords = g_new (GdkTimeCoord, *nevents_return);
140           for (i=0; i<*nevents_return; i++)
141             {
142               coords[i].time = xcoords[i].time;
143               coords[i].x = xcoords[i].x;
144               coords[i].y = xcoords[i].y;
145               coords[i].pressure = 0.5;
146               coords[i].xtilt = 0.0;
147               coords[i].ytilt = 0.0;
148             }
149
150           XFree (xcoords);
151
152           return coords;
153         }
154       else
155         return NULL;
156     }
157   else
158     {
159       if (gdk_input_vtable.motion_events)
160         {
161           return gdk_input_vtable.motion_events(window,
162                                                 deviceid, start, stop,
163                                                 nevents_return);
164         }
165       else
166         {
167           *nevents_return = 0;
168           return NULL;
169         }
170     }
171 }
172
173 static gint
174 gdk_input_enable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
175 {
176   if (gdk_input_vtable.enable_window)
177     return gdk_input_vtable.enable_window (window, gdkdev);
178   else
179     return TRUE;
180 }
181
182 static gint
183 gdk_input_disable_window (GdkWindow *window, GdkDevicePrivate *gdkdev)
184 {
185   if (gdk_input_vtable.disable_window)
186     return gdk_input_vtable.disable_window(window,gdkdev);
187   else
188     return TRUE;
189 }
190
191
192 static GdkInputWindow *
193 gdk_input_window_find(GdkWindow *window)
194 {
195   GList *tmp_list;
196
197   for (tmp_list=gdk_input_windows; tmp_list; tmp_list=tmp_list->next)
198     if (((GdkInputWindow *)(tmp_list->data))->window == window)
199       return (GdkInputWindow *)(tmp_list->data);
200
201   return NULL;      /* Not found */
202 }
203
204 /* FIXME: this routine currently needs to be called between creation
205    and the corresponding configure event (because it doesn't get the
206    root_relative_geometry).  This should work with
207    gtk_window_set_extension_events, but will likely fail in other
208    cases */
209
210 void
211 gdk_input_set_extension_events (GdkWindow *window, gint mask,
212                                 GdkExtensionMode mode)
213 {
214   GdkWindowPrivate *window_private;
215   GList *tmp_list;
216   GdkInputWindow *iw;
217
218   g_return_if_fail (window != NULL);
219   window_private = (GdkWindowPrivate*) window;
220   if (window_private->destroyed)
221     return;
222
223   if (mode == GDK_EXTENSION_EVENTS_NONE)
224     mask = 0;
225
226   if (mask != 0)
227     {
228       iw = g_new(GdkInputWindow,1);
229
230       iw->window = window;
231       iw->mode = mode;
232
233       iw->obscuring = NULL;
234       iw->num_obscuring = 0;
235       iw->grabbed = FALSE;
236
237       gdk_input_windows = g_list_append(gdk_input_windows,iw);
238       window_private->extension_events = mask;
239
240       /* Add enter window events to the event mask */
241       /* FIXME, this is not needed for XINPUT_NONE */
242       gdk_window_set_events (window,
243                              gdk_window_get_events (window) | 
244                              GDK_ENTER_NOTIFY_MASK);
245     }
246   else
247     {
248       iw = gdk_input_window_find (window);
249       if (iw)
250         {
251           gdk_input_windows = g_list_remove(gdk_input_windows,iw);
252           g_free(iw);
253         }
254
255       window_private->extension_events = 0;
256     }
257
258   for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
259     {
260       GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
261
262       if (gdkdev->info.deviceid != GDK_CORE_POINTER)
263         {
264           if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
265               && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
266             gdk_input_enable_window(window,gdkdev);
267           else
268             gdk_input_disable_window(window,gdkdev);
269         }
270     }
271 }
272
273 void
274 gdk_input_window_destroy (GdkWindow *window)
275 {
276   GdkInputWindow *input_window;
277
278   input_window = gdk_input_window_find (window);
279   g_return_if_fail (input_window != NULL);
280
281   gdk_input_windows = g_list_remove (gdk_input_windows,input_window);
282   g_free(input_window);
283 }
284
285 void
286 gdk_input_exit (void)
287 {
288   GList *tmp_list;
289   GdkDevicePrivate *gdkdev;
290
291   for (tmp_list = gdk_input_devices; tmp_list; tmp_list = tmp_list->next)
292     {
293       gdkdev = (GdkDevicePrivate *)(tmp_list->data);
294       if (gdkdev->info.deviceid != GDK_CORE_POINTER)
295         {
296           gdk_input_set_mode(gdkdev->info.deviceid,GDK_MODE_DISABLED);
297
298           g_free(gdkdev->info.name);
299 #ifndef XINPUT_NONE       
300           g_free(gdkdev->axes);
301 #endif    
302           g_free(gdkdev->info.axes);
303           g_free(gdkdev->info.keys);
304           g_free(gdkdev);
305         }
306     }
307
308   g_list_free(gdk_input_devices);
309
310   for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
311     {
312       g_free(tmp_list->data);
313     }
314   g_list_free(gdk_input_windows);
315 }
316
317 static GdkDevicePrivate *
318 gdk_input_find_device(guint32 id)
319 {
320   GList *tmp_list = gdk_input_devices;
321   GdkDevicePrivate *gdkdev;
322   while (tmp_list)
323     {
324       gdkdev = (GdkDevicePrivate *)(tmp_list->data);
325       if (gdkdev->info.deviceid == id)
326         return gdkdev;
327       tmp_list = tmp_list->next;
328     }
329   return NULL;
330 }
331
332 void
333 gdk_input_window_get_pointer (GdkWindow       *window,
334                               guint32     deviceid,
335                               gdouble         *x,
336                               gdouble         *y,
337                               gdouble         *pressure,
338                               gdouble         *xtilt,
339                               gdouble         *ytilt,
340                               GdkModifierType *mask)
341 {
342   if (gdk_input_vtable.get_pointer)
343     gdk_input_vtable.get_pointer (window, deviceid, x, y, pressure,
344                                   xtilt, ytilt, mask);
345 }