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 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.
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.
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.
21 #include "gdkinputprivate.h"
22 #include "gdkdisplay-x11.h"
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/.
32 /* forward declarations */
34 static void gdk_input_check_proximity (GdkDisplay *display);
37 _gdk_input_init(GdkDisplay *display)
39 _gdk_init_input_core (display);
40 GDK_DISPLAY_X11 (display)->input_ignore_core = FALSE;
41 _gdk_input_common_init (display, FALSE);
45 gdk_device_set_mode (GdkDevice *device,
49 GdkDevicePrivate *gdkdev;
50 GdkInputMode old_mode;
51 GdkInputWindow *input_window;
52 GdkDisplayX11 *display_impl;
54 if (GDK_IS_CORE (device))
57 gdkdev = (GdkDevicePrivate *)device;
59 if (device->mode == mode)
62 old_mode = device->mode;
65 display_impl = GDK_DISPLAY_X11 (gdkdev->display);
67 if (mode == GDK_MODE_WINDOW)
69 device->has_cursor = FALSE;
70 for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
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);
76 if (old_mode != GDK_MODE_DISABLED)
77 _gdk_input_disable_window (input_window->window, gdkdev);
80 else if (mode == GDK_MODE_SCREEN)
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,
87 else /* mode == GDK_MODE_DISABLED */
89 for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
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);
103 gdk_input_check_proximity (GdkDisplay *display)
105 gint new_proximity = 0;
106 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
107 GList *tmp_list = display_impl->input_devices;
109 while (tmp_list && !new_proximity)
111 GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
113 if (gdkdev->info.mode != GDK_MODE_DISABLED
114 && !GDK_IS_CORE (gdkdev)
117 XDeviceState *state = XQueryDeviceState(display_impl->xdisplay,
123 for (i=0; i<state->num_classes; i++)
125 if (xic->class == ValuatorClass)
127 XValuatorState *xvs = (XValuatorState *)xic;
128 if ((xvs->mode & ProximityState) == InProximity)
130 new_proximity = TRUE;
134 xic = (XInputClass *)((char *)xic + xic->length);
137 XFreeDeviceState (state);
139 tmp_list = tmp_list->next;
142 display_impl->input_ignore_core = new_proximity;
146 _gdk_input_configure_event (XConfigureEvent *xevent,
149 GdkInputWindow *input_window;
152 input_window = _gdk_input_window_find(window);
153 g_return_if_fail (input_window != NULL);
155 _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
156 GDK_WINDOW_XWINDOW (window),
157 &root_x, &root_y, NULL, NULL);
159 input_window->root_x = root_x;
160 input_window->root_y = root_y;
164 _gdk_input_enter_event (XCrossingEvent *xevent,
167 GdkInputWindow *input_window;
170 input_window = _gdk_input_window_find (window);
171 g_return_if_fail (input_window != NULL);
173 gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
175 _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
176 GDK_WINDOW_XWINDOW(window),
177 &root_x, &root_y, NULL, NULL);
179 input_window->root_x = root_x;
180 input_window->root_y = root_y;
184 _gdk_input_other_event (GdkEvent *event,
188 GdkInputWindow *input_window;
190 GdkDevicePrivate *gdkdev;
192 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
194 input_window = _gdk_input_window_find(window);
195 g_return_val_if_fail (input_window != NULL, FALSE);
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);
204 return FALSE; /* we don't handle it - not an XInput event */
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))
213 if (!display_impl->input_ignore_core)
214 gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
216 return_val = _gdk_input_common_other_event (event, xevent,
217 input_window, gdkdev);
219 if (return_val && event->type == GDK_PROXIMITY_OUT &&
220 display_impl->input_ignore_core)
221 gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
227 _gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
229 /* FIXME: watchout, gdkdev might be core pointer, never opened */
230 _gdk_input_common_select_events (window, gdkdev);
235 _gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
237 _gdk_input_common_select_events (window, gdkdev);
242 _gdk_input_grab_pointer (GdkWindow * window,
244 GdkEventMask event_mask,
245 GdkWindow * confine_to,
248 GdkInputWindow *input_window, *new_window;
249 gboolean need_ungrab;
250 GdkDevicePrivate *gdkdev;
252 XEventClass event_classes[GDK_MAX_DEVICE_CLASSES];
255 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
257 tmp_list = display_impl->input_windows;
263 input_window = (GdkInputWindow *)tmp_list->data;
265 if (input_window->window == window)
266 new_window = input_window;
267 else if (input_window->grabbed)
269 input_window->grabbed = FALSE;
273 tmp_list = tmp_list->next;
278 new_window->grabbed = TRUE;
280 tmp_list = display_impl->input_devices;
283 gdkdev = (GdkDevicePrivate *)tmp_list->data;
284 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
286 _gdk_input_common_find_events (window, gdkdev,
288 event_classes, &num_classes);
289 #ifdef G_ENABLE_DEBUG
290 if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
291 result = GrabSuccess;
294 result = XGrabDevice (display_impl->xdisplay, gdkdev->xdevice,
295 GDK_WINDOW_XWINDOW (window),
296 owner_events, num_classes, event_classes,
297 GrabModeAsync, GrabModeAsync, time);
299 /* FIXME: if failure occurs on something other than the first
300 device, things will be badly inconsistent */
301 if (result != Success)
304 tmp_list = tmp_list->next;
309 tmp_list = display_impl->input_devices;
312 gdkdev = (GdkDevicePrivate *)tmp_list->data;
313 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice &&
314 ((gdkdev->button_state != 0) || need_ungrab))
316 XUngrabDevice (display_impl->xdisplay, gdkdev->xdevice, time);
317 gdkdev->button_state = 0;
320 tmp_list = tmp_list->next;
329 _gdk_input_ungrab_pointer (GdkDisplay *display,
332 GdkInputWindow *input_window = NULL; /* Quiet GCC */
333 GdkDevicePrivate *gdkdev;
335 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
337 tmp_list = display_impl->input_windows;
340 input_window = (GdkInputWindow *)tmp_list->data;
341 if (input_window->grabbed)
343 tmp_list = tmp_list->next;
346 if (tmp_list) /* we found a grabbed window */
348 input_window->grabbed = FALSE;
350 tmp_list = display_impl->input_devices;
353 gdkdev = (GdkDevicePrivate *)tmp_list->data;
354 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
355 XUngrabDevice( display_impl->xdisplay, gdkdev->xdevice, time);
357 tmp_list = tmp_list->next;
362 #define __GDK_INPUT_XFREE_C__
363 #include "gdkaliasdef.c"