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