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 Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /* forward declarations */
23 static gint gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode);
24 static void gdk_input_check_proximity();
25 static void gdk_input_xfree_configure_event (XConfigureEvent *xevent,
27 static void gdk_input_xfree_enter_event (XCrossingEvent *xevent,
29 static gint gdk_input_xfree_other_event (GdkEvent *event,
32 static gint gdk_input_xfree_enable_window(GdkWindow *window,
33 GdkDevicePrivate *gdkdev);
34 static gint gdk_input_xfree_disable_window(GdkWindow *window,
35 GdkDevicePrivate *gdkdev);
36 static gint gdk_input_xfree_grab_pointer (GdkWindow * window,
38 GdkEventMask event_mask,
39 GdkWindow * confine_to,
41 static void gdk_input_xfree_ungrab_pointer (guint32 time);
46 gdk_input_vtable.set_mode = gdk_input_xfree_set_mode;
47 gdk_input_vtable.set_axes = gdk_input_common_set_axes;
48 gdk_input_vtable.motion_events = gdk_input_common_motion_events;
49 gdk_input_vtable.get_pointer = gdk_input_common_get_pointer;
50 gdk_input_vtable.grab_pointer = gdk_input_xfree_grab_pointer;
51 gdk_input_vtable.ungrab_pointer = gdk_input_xfree_ungrab_pointer;
52 gdk_input_vtable.configure_event = gdk_input_xfree_configure_event;
53 gdk_input_vtable.enter_event = gdk_input_xfree_enter_event;
54 gdk_input_vtable.other_event = gdk_input_xfree_other_event;
55 gdk_input_vtable.window_none_event = NULL;
56 gdk_input_vtable.enable_window = gdk_input_xfree_enable_window;
57 gdk_input_vtable.disable_window = gdk_input_xfree_disable_window;
59 gdk_input_ignore_core = FALSE;
60 gdk_input_common_init(FALSE);
64 gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode)
67 GdkDevicePrivate *gdkdev;
68 GdkInputMode old_mode;
69 GdkInputWindow *input_window;
71 gdkdev = gdk_input_find_device(deviceid);
72 g_return_val_if_fail (gdkdev != NULL,FALSE);
73 old_mode = gdkdev->info.mode;
75 if (gdkdev->info.mode == mode)
78 gdkdev->info.mode = mode;
80 if (mode == GDK_MODE_WINDOW)
82 gdkdev->info.has_cursor = FALSE;
83 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
85 input_window = (GdkInputWindow *)tmp_list->data;
86 if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
87 gdk_input_enable_window (input_window->window, gdkdev);
89 if (old_mode != GDK_MODE_DISABLED)
90 gdk_input_disable_window (input_window->window, gdkdev);
93 else if (mode == GDK_MODE_SCREEN)
95 gdkdev->info.has_cursor = TRUE;
96 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
97 gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
100 else /* mode == GDK_MODE_DISABLED */
102 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
104 input_window = (GdkInputWindow *)tmp_list->data;
105 if (old_mode != GDK_MODE_WINDOW ||
106 input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
107 gdk_input_disable_window (input_window->window, gdkdev);
116 gdk_input_check_proximity()
118 gint new_proximity = 0;
119 GList *tmp_list = gdk_input_devices;
121 while (tmp_list && !new_proximity)
123 GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
125 if (gdkdev->info.mode != GDK_MODE_DISABLED
126 && gdkdev->info.deviceid != GDK_CORE_POINTER
129 XDeviceState *state = XQueryDeviceState(GDK_DISPLAY(),
135 for (i=0; i<state->num_classes; i++)
137 if (xic->class == ValuatorClass)
139 XValuatorState *xvs = (XValuatorState *)xic;
140 if ((xvs->mode & ProximityState) == InProximity)
142 new_proximity = TRUE;
146 xic = (XInputClass *)((char *)xic + xic->length);
149 tmp_list = tmp_list->next;
152 gdk_input_ignore_core = new_proximity;
156 gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
158 GdkInputWindow *input_window;
161 input_window = gdk_input_window_find(window);
162 g_return_if_fail (window != NULL);
164 gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
166 &root_y, NULL, NULL);
168 input_window->root_x = root_x;
169 input_window->root_y = root_y;
173 gdk_input_xfree_enter_event (XCrossingEvent *xevent,
176 GdkInputWindow *input_window;
179 input_window = gdk_input_window_find(window);
180 g_return_if_fail (window != NULL);
182 gdk_input_check_proximity();
184 gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
186 &root_y, NULL, NULL);
188 input_window->root_x = root_x;
189 input_window->root_y = root_y;
193 gdk_input_xfree_other_event (GdkEvent *event,
197 GdkInputWindow *input_window;
199 GdkDevicePrivate *gdkdev;
202 input_window = gdk_input_window_find(window);
203 g_return_val_if_fail (window != NULL, -1);
205 /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
206 but it's potentially faster than scanning through the types of
207 every device. If we were deceived, then it won't match any of
208 the types for the device anyways */
209 gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
212 return -1; /* we don't handle it - not an XInput event */
215 /* FIXME: It would be nice if we could just get rid of the events
216 entirely, instead of having to ignore them */
217 if (gdkdev->info.mode == GDK_MODE_DISABLED ||
218 (gdkdev->info.mode == GDK_MODE_WINDOW
219 && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
222 if (!gdk_input_ignore_core)
223 gdk_input_check_proximity();
225 return_val = gdk_input_common_other_event (event, xevent,
226 input_window, gdkdev);
228 if (return_val > 0 && event->type == GDK_PROXIMITY_OUT &&
229 gdk_input_ignore_core)
230 gdk_input_check_proximity();
232 /* Do a passive button grab. We have to be careful not to release
233 an explicit grab, if any. Doubling the grab should be harmless,
234 but we check anyways. */
236 /* FIXME, finding the proper events here is going to be SLOW - but
237 we might have different sets for each window/device combination */
239 if (return_val> 0 && !input_window->grabbed)
241 if (event->type == GDK_BUTTON_PRESS)
243 XEventClass event_classes[6];
246 gdk_input_common_find_events (window, gdkdev,
247 ((GdkWindowPrivate *)window)->extension_events,
248 event_classes, &num_classes);
250 XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
251 GDK_WINDOW_XWINDOW (window),
252 TRUE, num_classes, event_classes,
253 GrabModeAsync, GrabModeAsync, event->button.time);
255 else if (event->type == GDK_BUTTON_RELEASE)
256 XUngrabDevice( GDK_DISPLAY(), gdkdev->xdevice, event->button.time);
263 gdk_input_xfree_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
265 /* FIXME: watchout, gdkdev might be core pointer, never opened */
266 gdk_input_common_select_events (window, gdkdev);
271 gdk_input_xfree_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
273 gdk_input_common_select_events (window, gdkdev);
278 gdk_input_xfree_grab_pointer (GdkWindow * window,
280 GdkEventMask event_mask,
281 GdkWindow * confine_to,
284 GdkInputWindow *input_window, *new_window;
285 GdkDevicePrivate *gdkdev;
287 XEventClass event_classes[6];
290 tmp_list = gdk_input_windows;
294 input_window = (GdkInputWindow *)tmp_list->data;
295 if (input_window->grabbed)
296 return AlreadyGrabbed;
298 if (input_window->window == window)
300 new_window = input_window;
304 tmp_list = tmp_list->next;
307 g_return_if_fail (new_window == NULL);
309 new_window->grabbed = TRUE;
311 tmp_list = gdk_input_devices;
314 gdkdev = (GdkDevicePrivate *)tmp_list->data;
315 if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
316 gdkdev->xdevice && !gdkdev->button_state)
318 gdk_input_common_find_events (window, gdkdev,
319 ((GdkWindowPrivate *)window)->extension_events,
320 event_classes, &num_classes);
322 /* FIXME: we should do something on failure */
323 XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
324 GDK_WINDOW_XWINDOW (window),
325 TRUE, num_classes, event_classes,
326 GrabModeAsync, GrabModeAsync, time);
328 tmp_list = tmp_list->next;
335 gdk_input_xfree_ungrab_pointer (guint32 time)
337 GdkInputWindow *input_window;
338 GdkDevicePrivate *gdkdev;
341 tmp_list = gdk_input_windows;
344 input_window = (GdkInputWindow *)tmp_list->data;
345 if (input_window->grabbed)
347 tmp_list = tmp_list->next;
350 if (tmp_list) /* we found a grabbed window */
352 input_window->grabbed = FALSE;
354 tmp_list = gdk_input_devices;
357 gdkdev = (GdkDevicePrivate *)tmp_list->data;
358 if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
359 gdkdev->xdevice && !gdkdev->button_state)
361 XUngrabDevice( gdk_display, gdkdev->xdevice, time);
363 tmp_list = tmp_list->next;
368 #endif /* XINPUT_XFREE */