]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkinput-xfree.c
b51516b3e1d5367083bd528da31adb309a6b046f
[~andy/gtk] / gdk / x11 / gdkinput-xfree.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 #include "config.h"
21 #include "gdkinputprivate.h"
22 #include "gdkdisplay-x11.h"
23 #include "gdkalias.h"
24
25 /*
26  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
27  * file for a list of people on the GTK+ Team.  See the ChangeLog
28  * files for a list of changes.  These files are distributed with
29  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
30  */
31
32 /* forward declarations */
33
34 static void gdk_input_check_proximity (GdkDisplay *display);
35
36 void 
37 _gdk_input_init(GdkDisplay *display)
38 {
39   _gdk_init_input_core (display);
40   GDK_DISPLAY_X11 (display)->input_ignore_core = FALSE;
41   _gdk_input_common_init (display, FALSE);
42 }
43
44 gboolean
45 gdk_device_set_mode (GdkDevice      *device,
46                      GdkInputMode    mode)
47 {
48   GList *tmp_list;
49   GdkDevicePrivate *gdkdev;
50   GdkInputMode old_mode;
51   GdkInputWindow *input_window;
52   GdkDisplayX11 *display_impl;
53
54   if (GDK_IS_CORE (device))
55     return FALSE;
56
57   gdkdev = (GdkDevicePrivate *)device;
58
59   if (device->mode == mode)
60     return TRUE;
61
62   old_mode = device->mode;
63   device->mode = mode;
64
65   display_impl = GDK_DISPLAY_X11 (gdkdev->display);
66
67   if (mode == GDK_MODE_WINDOW)
68     {
69       device->has_cursor = FALSE;
70       for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
71         {
72           input_window = (GdkInputWindow *)tmp_list->data;
73           if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
74             _gdk_input_enable_window (input_window->window, gdkdev);
75           else
76             if (old_mode != GDK_MODE_DISABLED)
77               _gdk_input_disable_window (input_window->window, gdkdev);
78         }
79     }
80   else if (mode == GDK_MODE_SCREEN)
81     {
82       device->has_cursor = TRUE;
83       for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
84         _gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
85                                   gdkdev);
86     }
87   else  /* mode == GDK_MODE_DISABLED */
88     {
89       for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
90         {
91           input_window = (GdkInputWindow *)tmp_list->data;
92           if (old_mode != GDK_MODE_WINDOW ||
93               input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
94             _gdk_input_disable_window (input_window->window, gdkdev);
95         }
96     }
97
98   return TRUE;
99   
100 }
101
102 static void
103 gdk_input_check_proximity (GdkDisplay *display)
104 {
105   gint new_proximity = 0;
106   GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
107   GList *tmp_list = display_impl->input_devices;
108
109   while (tmp_list && !new_proximity) 
110     {
111       GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
112
113       if (gdkdev->info.mode != GDK_MODE_DISABLED 
114           && !GDK_IS_CORE (gdkdev)
115           && gdkdev->xdevice)
116         {
117           XDeviceState *state = XQueryDeviceState(display_impl->xdisplay,
118                                                   gdkdev->xdevice);
119           XInputClass *xic;
120           int i;
121           
122           xic = state->data;
123           for (i=0; i<state->num_classes; i++)
124             {
125               if (xic->class == ValuatorClass)
126                 {
127                   XValuatorState *xvs = (XValuatorState *)xic;
128                   if ((xvs->mode & ProximityState) == InProximity)
129                     {
130                       new_proximity = TRUE;
131                     }
132                   break;
133                 }
134               xic = (XInputClass *)((char *)xic + xic->length);
135             }
136
137           XFreeDeviceState (state);
138         }
139       tmp_list = tmp_list->next;
140     }
141
142   display_impl->input_ignore_core = new_proximity;
143 }
144
145 void
146 _gdk_input_configure_event (XConfigureEvent *xevent,
147                             GdkWindow       *window)
148 {
149   GdkInputWindow *input_window;
150   gint root_x, root_y;
151
152   input_window = _gdk_input_window_find(window);
153   g_return_if_fail (input_window != NULL);
154
155   _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
156                                         GDK_WINDOW_XWINDOW (window),
157                                         &root_x, &root_y, NULL, NULL);
158
159   input_window->root_x = root_x;
160   input_window->root_y = root_y;
161 }
162
163 void 
164 _gdk_input_enter_event (XCrossingEvent *xevent, 
165                         GdkWindow      *window)
166 {
167   GdkInputWindow *input_window;
168   gint root_x, root_y;
169
170   input_window = _gdk_input_window_find (window);
171   g_return_if_fail (input_window != NULL);
172
173   gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
174
175   _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
176                                         GDK_WINDOW_XWINDOW(window),
177                                         &root_x, &root_y, NULL, NULL);
178
179   input_window->root_x = root_x;
180   input_window->root_y = root_y;
181 }
182
183 gboolean 
184 _gdk_input_other_event (GdkEvent *event, 
185                         XEvent *xevent, 
186                         GdkWindow *window)
187 {
188   GdkInputWindow *input_window;
189   
190   GdkDevicePrivate *gdkdev;
191   gint return_val;
192   GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
193
194   input_window = _gdk_input_window_find(window);
195   g_return_val_if_fail (input_window != NULL, FALSE);
196
197   /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
198      but it's potentially faster than scanning through the types of
199      every device. If we were deceived, then it won't match any of
200      the types for the device anyways */
201   gdkdev = _gdk_input_find_device (GDK_WINDOW_DISPLAY (window),
202                                    ((XDeviceButtonEvent *)xevent)->deviceid);
203   if (!gdkdev)
204     return FALSE;                       /* we don't handle it - not an XInput event */
205
206   /* FIXME: It would be nice if we could just get rid of the events 
207      entirely, instead of having to ignore them */
208   if (gdkdev->info.mode == GDK_MODE_DISABLED ||
209       (gdkdev->info.mode == GDK_MODE_WINDOW 
210        && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
211     return FALSE;
212   
213   if (!display_impl->input_ignore_core)
214     gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
215
216   return_val = _gdk_input_common_other_event (event, xevent, 
217                                               input_window, gdkdev);
218
219   if (return_val && event->type == GDK_PROXIMITY_OUT &&
220       display_impl->input_ignore_core)
221     gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
222
223   return return_val;
224 }
225
226 gboolean
227 _gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
228 {
229   /* FIXME: watchout, gdkdev might be core pointer, never opened */
230   _gdk_input_common_select_events (window, gdkdev);
231   return TRUE;
232 }
233
234 gboolean
235 _gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
236 {
237   _gdk_input_common_select_events (window, gdkdev);
238   return TRUE;
239 }
240
241 gint 
242 _gdk_input_grab_pointer (GdkWindow *     window,
243                          gint            owner_events,
244                          GdkEventMask    event_mask,
245                          GdkWindow *     confine_to,
246                          guint32         time)
247 {
248   GdkInputWindow *input_window, *new_window;
249   gboolean need_ungrab;
250   GdkDevicePrivate *gdkdev;
251   GList *tmp_list;
252   XEventClass event_classes[GDK_MAX_DEVICE_CLASSES];
253   gint num_classes;
254   gint result;
255   GdkDisplayX11 *display_impl  = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
256
257   tmp_list = display_impl->input_windows;
258   new_window = NULL;
259   need_ungrab = FALSE;
260
261   while (tmp_list)
262     {
263       input_window = (GdkInputWindow *)tmp_list->data;
264
265       if (input_window->window == window)
266         new_window = input_window;
267       else if (input_window->grabbed)
268         {
269           input_window->grabbed = FALSE;
270           need_ungrab = TRUE;
271         }
272
273       tmp_list = tmp_list->next;
274     }
275
276   if (new_window)
277     {
278       new_window->grabbed = TRUE;
279       
280       tmp_list = display_impl->input_devices;
281       while (tmp_list)
282         {
283           gdkdev = (GdkDevicePrivate *)tmp_list->data;
284           if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
285             {
286               _gdk_input_common_find_events (window, gdkdev,
287                                              event_mask,
288                                              event_classes, &num_classes);
289 #ifdef G_ENABLE_DEBUG
290               if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
291                 result = GrabSuccess;
292               else
293 #endif
294                 result = XGrabDevice (display_impl->xdisplay, gdkdev->xdevice,
295                                       GDK_WINDOW_XWINDOW (window),
296                                       owner_events, num_classes, event_classes,
297                                       GrabModeAsync, GrabModeAsync, time);
298               
299               /* FIXME: if failure occurs on something other than the first
300                  device, things will be badly inconsistent */
301               if (result != Success)
302                 return result;
303             }
304           tmp_list = tmp_list->next;
305         }
306     }
307   else
308     { 
309       tmp_list = display_impl->input_devices;
310       while (tmp_list)
311         {
312           gdkdev = (GdkDevicePrivate *)tmp_list->data;
313           if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice &&
314               ((gdkdev->button_state != 0) || need_ungrab))
315             {
316               XUngrabDevice (display_impl->xdisplay, gdkdev->xdevice, time);
317               gdkdev->button_state = 0;
318             }
319           
320           tmp_list = tmp_list->next;
321         }
322     }
323
324   return Success;
325       
326 }
327
328 void 
329 _gdk_input_ungrab_pointer (GdkDisplay *display, 
330                            guint32 time)
331 {
332   GdkInputWindow *input_window = NULL; /* Quiet GCC */
333   GdkDevicePrivate *gdkdev;
334   GList *tmp_list;
335   GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
336
337   tmp_list = display_impl->input_windows;
338   while (tmp_list)
339     {
340       input_window = (GdkInputWindow *)tmp_list->data;
341       if (input_window->grabbed)
342         break;
343       tmp_list = tmp_list->next;
344     }
345
346   if (tmp_list)                 /* we found a grabbed window */
347     {
348       input_window->grabbed = FALSE;
349
350       tmp_list = display_impl->input_devices;
351       while (tmp_list)
352         {
353           gdkdev = (GdkDevicePrivate *)tmp_list->data;
354           if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
355             XUngrabDevice( display_impl->xdisplay, gdkdev->xdevice, time);
356
357           tmp_list = tmp_list->next;
358         }
359     }
360 }
361
362 #define __GDK_INPUT_XFREE_C__
363 #include "gdkaliasdef.c"