1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
20 #include "gdkinputprivate.h"
23 * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
24 * file for a list of people on the GTK+ Team. See the ChangeLog
25 * files for a list of changes. These files are distributed with
26 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 /* forward declarations */
31 static gint gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode);
32 static void gdk_input_check_proximity (void);
33 static void gdk_input_xfree_configure_event (XConfigureEvent *xevent,
35 static void gdk_input_xfree_enter_event (XCrossingEvent *xevent,
37 static gint gdk_input_xfree_other_event (GdkEvent *event,
40 static gint gdk_input_xfree_enable_window(GdkWindow *window,
41 GdkDevicePrivate *gdkdev);
42 static gint gdk_input_xfree_disable_window(GdkWindow *window,
43 GdkDevicePrivate *gdkdev);
44 static gint gdk_input_xfree_grab_pointer (GdkWindow * window,
46 GdkEventMask event_mask,
47 GdkWindow * confine_to,
49 static void gdk_input_xfree_ungrab_pointer (guint32 time);
54 gdk_input_vtable.set_mode = gdk_input_xfree_set_mode;
55 gdk_input_vtable.set_axes = gdk_input_common_set_axes;
56 gdk_input_vtable.set_key = gdk_input_common_set_key;
57 gdk_input_vtable.motion_events = gdk_input_common_motion_events;
58 gdk_input_vtable.get_pointer = gdk_input_common_get_pointer;
59 gdk_input_vtable.grab_pointer = gdk_input_xfree_grab_pointer;
60 gdk_input_vtable.ungrab_pointer = gdk_input_xfree_ungrab_pointer;
61 gdk_input_vtable.configure_event = gdk_input_xfree_configure_event;
62 gdk_input_vtable.enter_event = gdk_input_xfree_enter_event;
63 gdk_input_vtable.other_event = gdk_input_xfree_other_event;
64 gdk_input_vtable.window_none_event = NULL;
65 gdk_input_vtable.enable_window = gdk_input_xfree_enable_window;
66 gdk_input_vtable.disable_window = gdk_input_xfree_disable_window;
68 gdk_input_ignore_core = FALSE;
69 gdk_input_common_init(FALSE);
73 gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode)
76 GdkDevicePrivate *gdkdev;
77 GdkInputMode old_mode;
78 GdkInputWindow *input_window;
80 gdkdev = gdk_input_find_device(deviceid);
81 g_return_val_if_fail (gdkdev != NULL,FALSE);
82 old_mode = gdkdev->info.mode;
84 if (gdkdev->info.mode == mode)
87 gdkdev->info.mode = mode;
89 if (mode == GDK_MODE_WINDOW)
91 gdkdev->info.has_cursor = FALSE;
92 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
94 input_window = (GdkInputWindow *)tmp_list->data;
95 if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
96 gdk_input_enable_window (input_window->window, gdkdev);
98 if (old_mode != GDK_MODE_DISABLED)
99 gdk_input_disable_window (input_window->window, gdkdev);
102 else if (mode == GDK_MODE_SCREEN)
104 gdkdev->info.has_cursor = TRUE;
105 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
106 gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
109 else /* mode == GDK_MODE_DISABLED */
111 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
113 input_window = (GdkInputWindow *)tmp_list->data;
114 if (old_mode != GDK_MODE_WINDOW ||
115 input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
116 gdk_input_disable_window (input_window->window, gdkdev);
125 gdk_input_check_proximity (void)
127 gint new_proximity = 0;
128 GList *tmp_list = gdk_input_devices;
130 while (tmp_list && !new_proximity)
132 GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
134 if (gdkdev->info.mode != GDK_MODE_DISABLED
135 && gdkdev->info.deviceid != GDK_CORE_POINTER
138 XDeviceState *state = XQueryDeviceState(GDK_DISPLAY(),
144 for (i=0; i<state->num_classes; i++)
146 if (xic->class == ValuatorClass)
148 XValuatorState *xvs = (XValuatorState *)xic;
149 if ((xvs->mode & ProximityState) == InProximity)
151 new_proximity = TRUE;
155 xic = (XInputClass *)((char *)xic + xic->length);
158 tmp_list = tmp_list->next;
161 gdk_input_ignore_core = new_proximity;
165 gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
167 GdkInputWindow *input_window;
170 input_window = gdk_input_window_find(window);
171 g_return_if_fail (window != NULL);
173 gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
175 &root_y, NULL, NULL);
177 input_window->root_x = root_x;
178 input_window->root_y = root_y;
182 gdk_input_xfree_enter_event (XCrossingEvent *xevent,
185 GdkInputWindow *input_window;
188 input_window = gdk_input_window_find(window);
189 g_return_if_fail (window != NULL);
191 gdk_input_check_proximity();
193 gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
195 &root_y, NULL, NULL);
197 input_window->root_x = root_x;
198 input_window->root_y = root_y;
202 gdk_input_xfree_other_event (GdkEvent *event,
206 GdkInputWindow *input_window;
208 GdkDevicePrivate *gdkdev;
211 input_window = gdk_input_window_find(window);
212 g_return_val_if_fail (window != NULL, -1);
214 /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
215 but it's potentially faster than scanning through the types of
216 every device. If we were deceived, then it won't match any of
217 the types for the device anyways */
218 gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
221 return -1; /* we don't handle it - not an XInput event */
224 /* FIXME: It would be nice if we could just get rid of the events
225 entirely, instead of having to ignore them */
226 if (gdkdev->info.mode == GDK_MODE_DISABLED ||
227 (gdkdev->info.mode == GDK_MODE_WINDOW
228 && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
231 if (!gdk_input_ignore_core)
232 gdk_input_check_proximity();
234 return_val = gdk_input_common_other_event (event, xevent,
235 input_window, gdkdev);
237 if (return_val > 0 && event->type == GDK_PROXIMITY_OUT &&
238 gdk_input_ignore_core)
239 gdk_input_check_proximity();
245 gdk_input_xfree_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
247 /* FIXME: watchout, gdkdev might be core pointer, never opened */
248 gdk_input_common_select_events (window, gdkdev);
253 gdk_input_xfree_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
255 gdk_input_common_select_events (window, gdkdev);
260 gdk_input_xfree_grab_pointer (GdkWindow * window,
262 GdkEventMask event_mask,
263 GdkWindow * confine_to,
266 GdkInputWindow *input_window, *new_window;
267 gboolean need_ungrab;
268 GdkDevicePrivate *gdkdev;
270 XEventClass event_classes[GDK_MAX_DEVICE_CLASSES];
274 tmp_list = gdk_input_windows;
280 input_window = (GdkInputWindow *)tmp_list->data;
282 if (input_window->window == window)
283 new_window = input_window;
284 else if (input_window->grabbed)
286 input_window->grabbed = FALSE;
290 tmp_list = tmp_list->next;
295 new_window->grabbed = TRUE;
297 tmp_list = gdk_input_devices;
300 gdkdev = (GdkDevicePrivate *)tmp_list->data;
301 if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
304 gdk_input_common_find_events (window, gdkdev,
306 event_classes, &num_classes);
308 result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
309 GDK_WINDOW_XWINDOW (window),
310 owner_events, num_classes, event_classes,
311 GrabModeAsync, GrabModeAsync, time);
313 /* FIXME: if failure occurs on something other than the first
314 device, things will be badly inconsistent */
315 if (result != Success)
318 tmp_list = tmp_list->next;
323 tmp_list = gdk_input_devices;
326 gdkdev = (GdkDevicePrivate *)tmp_list->data;
327 if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice &&
328 ((gdkdev->button_state != 0) || need_ungrab))
330 XUngrabDevice( gdk_display, gdkdev->xdevice, time);
331 gdkdev->button_state = 0;
334 tmp_list = tmp_list->next;
343 gdk_input_xfree_ungrab_pointer (guint32 time)
345 GdkInputWindow *input_window;
346 GdkDevicePrivate *gdkdev;
349 tmp_list = gdk_input_windows;
352 input_window = (GdkInputWindow *)tmp_list->data;
353 if (input_window->grabbed)
355 tmp_list = tmp_list->next;
358 if (tmp_list) /* we found a grabbed window */
360 input_window->grabbed = FALSE;
362 tmp_list = gdk_input_devices;
365 gdkdev = (GdkDevicePrivate *)tmp_list->data;
366 if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
367 XUngrabDevice( gdk_display, gdkdev->xdevice, time);
369 tmp_list = tmp_list->next;