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 display->ignore_core_events = FALSE;
41 _gdk_input_common_init (display, FALSE);
45 gdk_device_set_mode (GdkDevice *device,
49 GdkDevicePrivate *gdkdev;
50 GdkInputWindow *input_window;
51 GdkDisplayX11 *display_impl;
53 if (GDK_IS_CORE (device))
56 gdkdev = (GdkDevicePrivate *)device;
58 if (device->mode == mode)
63 if (mode == GDK_MODE_WINDOW)
64 device->has_cursor = FALSE;
65 else if (mode == GDK_MODE_SCREEN)
66 device->has_cursor = TRUE;
68 display_impl = GDK_DISPLAY_X11 (gdkdev->display);
69 for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
71 input_window = (GdkInputWindow *)tmp_list->data;
72 _gdk_input_select_events (input_window->impl_window, gdkdev);
79 gdk_input_check_proximity (GdkDisplay *display)
81 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
82 GList *tmp_list = display_impl->input_devices;
83 gint new_proximity = 0;
85 while (tmp_list && !new_proximity)
87 GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
89 if (gdkdev->info.mode != GDK_MODE_DISABLED
90 && !GDK_IS_CORE (gdkdev)
93 XDeviceState *state = XQueryDeviceState(display_impl->xdisplay,
99 for (i=0; i<state->num_classes; i++)
101 if (xic->class == ValuatorClass)
103 XValuatorState *xvs = (XValuatorState *)xic;
104 if ((xvs->mode & ProximityState) == InProximity)
106 new_proximity = TRUE;
110 xic = (XInputClass *)((char *)xic + xic->length);
113 XFreeDeviceState (state);
115 tmp_list = tmp_list->next;
118 display->ignore_core_events = new_proximity;
122 _gdk_input_configure_event (XConfigureEvent *xevent,
125 GdkWindowObject *priv = (GdkWindowObject *)window;
126 GdkInputWindow *input_window;
129 input_window = priv->input_window;
130 if (input_window != NULL)
132 _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
133 input_window->root_x = root_x;
134 input_window->root_y = root_y;
139 _gdk_input_crossing_event (GdkWindow *window,
142 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
143 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
144 GdkWindowObject *priv = (GdkWindowObject *)window;
145 GdkInputWindow *input_window;
150 gdk_input_check_proximity(display);
152 input_window = priv->input_window;
153 if (input_window != NULL)
155 _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
156 input_window->root_x = root_x;
157 input_window->root_y = root_y;
161 display->ignore_core_events = FALSE;
165 get_input_event_type (GdkDevicePrivate *gdkdev,
167 int *core_x, int *core_y)
169 if (xevent->type == gdkdev->buttonpress_type)
171 XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
174 return GDK_BUTTON_PRESS;
177 if (xevent->type == gdkdev->buttonrelease_type)
179 XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
182 return GDK_BUTTON_RELEASE;
185 if (xevent->type == gdkdev->keypress_type)
187 XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
190 return GDK_KEY_PRESS;
193 if (xevent->type == gdkdev->keyrelease_type)
195 XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
198 return GDK_KEY_RELEASE;
201 if (xevent->type == gdkdev->motionnotify_type)
203 XDeviceMotionEvent *xie = (XDeviceMotionEvent *)(xevent);
206 return GDK_MOTION_NOTIFY;
209 if (xevent->type == gdkdev->proximityin_type)
211 XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
214 return GDK_PROXIMITY_IN;
217 if (xevent->type == gdkdev->proximityout_type)
219 XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
222 return GDK_PROXIMITY_OUT;
232 _gdk_input_other_event (GdkEvent *event,
234 GdkWindow *event_window)
237 GdkWindowObject *priv;
239 GdkDevicePrivate *gdkdev;
241 GdkEventType event_type;
243 GdkDisplay *display = GDK_WINDOW_DISPLAY (event_window);
244 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
246 /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
247 but it's potentially faster than scanning through the types of
248 every device. If we were deceived, then it won't match any of
249 the types for the device anyways */
250 gdkdev = _gdk_input_find_device (display,
251 ((XDeviceButtonEvent *)xevent)->deviceid);
253 return FALSE; /* we don't handle it - not an XInput event */
255 event_type = get_input_event_type (gdkdev, xevent, &x, &y);
256 if (event_type == GDK_NOTHING)
259 window = _gdk_window_get_input_window_for_event (event_window,
262 xevent->xany.serial);
263 /* If we're not getting any event window its likely because we're outside the
264 window and there is no grab. We should still report according to the
265 implicit grab though. */
266 iw = ((GdkWindowObject *)event_window)->input_window;
268 window = iw->button_down_window;
270 priv = (GdkWindowObject *)window;
274 if (gdkdev->info.mode == GDK_MODE_DISABLED ||
275 !(gdkdev->info.has_cursor || (priv->extension_events & GDK_ALL_DEVICES_MASK)))
278 if (!display->ignore_core_events && priv->extension_events != 0)
279 gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window));
281 return_val = _gdk_input_common_other_event (event, xevent, window, gdkdev);
283 if (return_val && event->type == GDK_BUTTON_PRESS)
284 iw->button_down_window = window;
285 if (return_val && event->type == GDK_BUTTON_RELEASE)
286 iw->button_down_window = NULL;
288 if (return_val && event->type == GDK_PROXIMITY_OUT &&
289 display->ignore_core_events)
290 gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window));
296 _gdk_input_grab_pointer (GdkWindow *window,
297 GdkWindow *native_window, /* This is the toplevel */
299 GdkEventMask event_mask,
300 GdkWindow * confine_to,
303 GdkInputWindow *input_window;
304 GdkWindowObject *priv, *impl_window;
305 gboolean need_ungrab;
306 GdkDevicePrivate *gdkdev;
308 XEventClass event_classes[GDK_MAX_DEVICE_CLASSES];
311 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
313 tmp_list = display_impl->input_windows;
318 input_window = (GdkInputWindow *)tmp_list->data;
320 if (input_window->grabbed)
322 input_window->grabbed = FALSE;
326 tmp_list = tmp_list->next;
329 priv = (GdkWindowObject *)window;
330 impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
331 input_window = impl_window->input_window;
332 if (priv->extension_events)
334 g_assert (input_window != NULL);
335 input_window->grabbed = TRUE;
337 tmp_list = display_impl->input_devices;
340 gdkdev = (GdkDevicePrivate *)tmp_list->data;
341 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
343 _gdk_input_common_find_events (gdkdev, event_mask,
344 event_classes, &num_classes);
345 #ifdef G_ENABLE_DEBUG
346 if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
347 result = GrabSuccess;
350 result = XGrabDevice (display_impl->xdisplay, gdkdev->xdevice,
351 GDK_WINDOW_XWINDOW (native_window),
352 owner_events, num_classes, event_classes,
353 GrabModeAsync, GrabModeAsync, time);
355 /* FIXME: if failure occurs on something other than the first
356 device, things will be badly inconsistent */
357 if (result != Success)
360 tmp_list = tmp_list->next;
365 tmp_list = display_impl->input_devices;
368 gdkdev = (GdkDevicePrivate *)tmp_list->data;
369 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice &&
370 ((gdkdev->button_state != 0) || need_ungrab))
372 XUngrabDevice (display_impl->xdisplay, gdkdev->xdevice, time);
373 gdkdev->button_state = 0;
376 tmp_list = tmp_list->next;
384 _gdk_input_ungrab_pointer (GdkDisplay *display,
387 GdkInputWindow *input_window = NULL; /* Quiet GCC */
388 GdkDevicePrivate *gdkdev;
390 GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
392 tmp_list = display_impl->input_windows;
395 input_window = (GdkInputWindow *)tmp_list->data;
396 if (input_window->grabbed)
398 tmp_list = tmp_list->next;
401 if (tmp_list) /* we found a grabbed window */
403 input_window->grabbed = FALSE;
405 tmp_list = display_impl->input_devices;
408 gdkdev = (GdkDevicePrivate *)tmp_list->data;
409 if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
410 XUngrabDevice( display_impl->xdisplay, gdkdev->xdevice, time);
412 tmp_list = tmp_list->next;
417 #define __GDK_INPUT_XFREE_C__
418 #include "gdkaliasdef.c"