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.
22 /* forward declarations */
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,
28 static void gdk_input_xfree_enter_event (XCrossingEvent *xevent,
30 static gint gdk_input_xfree_other_event (GdkEvent *event,
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,
39 GdkEventMask event_mask,
40 GdkWindow * confine_to,
42 static void gdk_input_xfree_ungrab_pointer (guint32 time);
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;
61 gdk_input_ignore_core = FALSE;
62 gdk_input_common_init(FALSE);
66 gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode)
69 GdkDevicePrivate *gdkdev;
70 GdkInputMode old_mode;
71 GdkInputWindow *input_window;
73 gdkdev = gdk_input_find_device(deviceid);
74 g_return_val_if_fail (gdkdev != NULL,FALSE);
75 old_mode = gdkdev->info.mode;
77 if (gdkdev->info.mode == mode)
80 gdkdev->info.mode = mode;
82 if (mode == GDK_MODE_WINDOW)
84 gdkdev->info.has_cursor = FALSE;
85 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
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);
91 if (old_mode != GDK_MODE_DISABLED)
92 gdk_input_disable_window (input_window->window, gdkdev);
95 else if (mode == GDK_MODE_SCREEN)
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,
102 else /* mode == GDK_MODE_DISABLED */
104 for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
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);
118 gdk_input_check_proximity (void)
120 gint new_proximity = 0;
121 GList *tmp_list = gdk_input_devices;
123 while (tmp_list && !new_proximity)
125 GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
127 if (gdkdev->info.mode != GDK_MODE_DISABLED
128 && gdkdev->info.deviceid != GDK_CORE_POINTER
131 XDeviceState *state = XQueryDeviceState(GDK_DISPLAY(),
137 for (i=0; i<state->num_classes; i++)
139 if (xic->class == ValuatorClass)
141 XValuatorState *xvs = (XValuatorState *)xic;
142 if ((xvs->mode & ProximityState) == InProximity)
144 new_proximity = TRUE;
148 xic = (XInputClass *)((char *)xic + xic->length);
151 tmp_list = tmp_list->next;
154 gdk_input_ignore_core = new_proximity;
158 gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
160 GdkInputWindow *input_window;
163 input_window = gdk_input_window_find(window);
164 g_return_if_fail (window != NULL);
166 gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
168 &root_y, NULL, NULL);
170 input_window->root_x = root_x;
171 input_window->root_y = root_y;
175 gdk_input_xfree_enter_event (XCrossingEvent *xevent,
178 GdkInputWindow *input_window;
181 input_window = gdk_input_window_find(window);
182 g_return_if_fail (window != NULL);
184 gdk_input_check_proximity();
186 gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
188 &root_y, NULL, NULL);
190 input_window->root_x = root_x;
191 input_window->root_y = root_y;
195 gdk_input_xfree_other_event (GdkEvent *event,
199 GdkInputWindow *input_window;
201 GdkDevicePrivate *gdkdev;
204 input_window = gdk_input_window_find(window);
205 g_return_val_if_fail (window != NULL, -1);
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);
214 return -1; /* we don't handle it - not an XInput event */
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))
224 if (!gdk_input_ignore_core)
225 gdk_input_check_proximity();
227 return_val = gdk_input_common_other_event (event, xevent,
228 input_window, gdkdev);
230 if (return_val > 0 && event->type == GDK_PROXIMITY_OUT &&
231 gdk_input_ignore_core)
232 gdk_input_check_proximity();
238 gdk_input_xfree_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
240 /* FIXME: watchout, gdkdev might be core pointer, never opened */
241 gdk_input_common_select_events (window, gdkdev);
246 gdk_input_xfree_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
248 gdk_input_common_select_events (window, gdkdev);
253 gdk_input_xfree_grab_pointer (GdkWindow * window,
255 GdkEventMask event_mask,
256 GdkWindow * confine_to,
259 GdkInputWindow *input_window, *new_window;
260 gboolean need_ungrab;
261 GdkDevicePrivate *gdkdev;
263 XEventClass event_classes[GDK_MAX_DEVICE_CLASSES];
267 tmp_list = gdk_input_windows;
273 input_window = (GdkInputWindow *)tmp_list->data;
275 if (input_window->window == window)
276 new_window = input_window;
277 else if (input_window->grabbed)
279 input_window->grabbed = FALSE;
283 tmp_list = tmp_list->next;
288 new_window->grabbed = TRUE;
290 tmp_list = gdk_input_devices;
293 gdkdev = (GdkDevicePrivate *)tmp_list->data;
294 if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
297 gdk_input_common_find_events (window, gdkdev,
299 event_classes, &num_classes);
301 result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
302 GDK_WINDOW_XWINDOW (window),
303 owner_events, num_classes, event_classes,
304 GrabModeAsync, GrabModeAsync, time);
306 /* FIXME: if failure occurs on something other than the first
307 device, things will be badly inconsistent */
308 if (result != Success)
311 tmp_list = tmp_list->next;
316 tmp_list = gdk_input_devices;
319 gdkdev = (GdkDevicePrivate *)tmp_list->data;
320 if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice &&
321 ((gdkdev->button_state != 0) || need_ungrab))
323 XUngrabDevice( gdk_display, gdkdev->xdevice, time);
324 gdkdev->button_state = 0;
327 tmp_list = tmp_list->next;
336 gdk_input_xfree_ungrab_pointer (guint32 time)
338 GdkInputWindow *input_window;
339 GdkDevicePrivate *gdkdev;
342 tmp_list = gdk_input_windows;
345 input_window = (GdkInputWindow *)tmp_list->data;
346 if (input_window->grabbed)
348 tmp_list = tmp_list->next;
351 if (tmp_list) /* we found a grabbed window */
353 input_window->grabbed = FALSE;
355 tmp_list = gdk_input_devices;
358 gdkdev = (GdkDevicePrivate *)tmp_list->data;
359 if (gdkdev->info.deviceid != GDK_CORE_POINTER && gdkdev->xdevice)
360 XUngrabDevice( gdk_display, gdkdev->xdevice, time);
362 tmp_list = tmp_list->next;
367 #endif /* XINPUT_XFREE */