summaryrefslogtreecommitdiff
path: root/gdk/x11/gdkinput-xfree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/x11/gdkinput-xfree.c')
-rw-r--r--gdk/x11/gdkinput-xfree.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/gdk/x11/gdkinput-xfree.c b/gdk/x11/gdkinput-xfree.c
new file mode 100644
index 000000000..f74249008
--- /dev/null
+++ b/gdk/x11/gdkinput-xfree.c
@@ -0,0 +1,368 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef XINPUT_XFREE
+
+/* forward declarations */
+
+static gint gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode);
+static void gdk_input_check_proximity();
+static void gdk_input_xfree_configure_event (XConfigureEvent *xevent,
+ GdkWindow *window);
+static void gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window);
+static gint gdk_input_xfree_enable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_disable_window(GdkWindow *window,
+ GdkDevicePrivate *gdkdev);
+static gint gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time);
+static void gdk_input_xfree_ungrab_pointer (guint32 time);
+
+void
+gdk_input_init(void)
+{
+ gdk_input_vtable.set_mode = gdk_input_xfree_set_mode;
+ gdk_input_vtable.set_axes = gdk_input_common_set_axes;
+ gdk_input_vtable.motion_events = gdk_input_common_motion_events;
+ gdk_input_vtable.get_pointer = gdk_input_common_get_pointer;
+ gdk_input_vtable.grab_pointer = gdk_input_xfree_grab_pointer;
+ gdk_input_vtable.ungrab_pointer = gdk_input_xfree_ungrab_pointer;
+ gdk_input_vtable.configure_event = gdk_input_xfree_configure_event;
+ gdk_input_vtable.enter_event = gdk_input_xfree_enter_event;
+ gdk_input_vtable.other_event = gdk_input_xfree_other_event;
+ gdk_input_vtable.window_none_event = NULL;
+ gdk_input_vtable.enable_window = gdk_input_xfree_enable_window;
+ gdk_input_vtable.disable_window = gdk_input_xfree_disable_window;
+
+ gdk_input_ignore_core = FALSE;
+ gdk_input_common_init(FALSE);
+}
+
+static gint
+gdk_input_xfree_set_mode (guint32 deviceid, GdkInputMode mode)
+{
+ GList *tmp_list;
+ GdkDevicePrivate *gdkdev;
+ GdkInputMode old_mode;
+ GdkInputWindow *input_window;
+
+ gdkdev = gdk_input_find_device(deviceid);
+ g_return_val_if_fail (gdkdev != NULL,FALSE);
+ old_mode = gdkdev->info.mode;
+
+ if (gdkdev->info.mode == mode)
+ return TRUE;
+
+ gdkdev->info.mode = mode;
+
+ if (mode == GDK_MODE_WINDOW)
+ {
+ gdkdev->info.has_cursor = FALSE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_enable_window (input_window->window, gdkdev);
+ else
+ if (old_mode != GDK_MODE_DISABLED)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+ else if (mode == GDK_MODE_SCREEN)
+ {
+ gdkdev->info.has_cursor = TRUE;
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
+ gdkdev);
+ }
+ else /* mode == GDK_MODE_DISABLED */
+ {
+ for (tmp_list = gdk_input_windows; tmp_list; tmp_list = tmp_list->next)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (old_mode != GDK_MODE_WINDOW ||
+ input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
+ gdk_input_disable_window (input_window->window, gdkdev);
+ }
+ }
+
+ return TRUE;
+
+}
+
+static void
+gdk_input_check_proximity()
+{
+ gint new_proximity = 0;
+ GList *tmp_list = gdk_input_devices;
+
+ while (tmp_list && !new_proximity)
+ {
+ GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
+
+ if (gdkdev->info.mode != GDK_MODE_DISABLED
+ && gdkdev->info.deviceid != GDK_CORE_POINTER
+ && gdkdev->xdevice)
+ {
+ XDeviceState *state = XQueryDeviceState(GDK_DISPLAY(),
+ gdkdev->xdevice);
+ XInputClass *xic;
+ int i;
+
+ xic = state->data;
+ for (i=0; i<state->num_classes; i++)
+ {
+ if (xic->class == ValuatorClass)
+ {
+ XValuatorState *xvs = (XValuatorState *)xic;
+ if ((xvs->mode & ProximityState) == InProximity)
+ {
+ new_proximity = TRUE;
+ }
+ break;
+ }
+ xic = (XInputClass *)((char *)xic + xic->length);
+ }
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ gdk_input_ignore_core = new_proximity;
+}
+
+static void
+gdk_input_xfree_configure_event (XConfigureEvent *xevent, GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static void
+gdk_input_xfree_enter_event (XCrossingEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+ gint root_x, root_y;
+
+ input_window = gdk_input_window_find(window);
+ g_return_if_fail (window != NULL);
+
+ gdk_input_check_proximity();
+
+ gdk_input_get_root_relative_geometry(GDK_DISPLAY(),GDK_WINDOW_XWINDOW(window),
+ &root_x,
+ &root_y, NULL, NULL);
+
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+}
+
+static gint
+gdk_input_xfree_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *window)
+{
+ GdkInputWindow *input_window;
+
+ GdkDevicePrivate *gdkdev;
+ gint return_val;
+
+ input_window = gdk_input_window_find(window);
+ g_return_val_if_fail (window != NULL, -1);
+
+ /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
+ but it's potentially faster than scanning through the types of
+ every device. If we were deceived, then it won't match any of
+ the types for the device anyways */
+ gdkdev = gdk_input_find_device(((XDeviceButtonEvent *)xevent)->deviceid);
+
+ if (!gdkdev) {
+ return -1; /* we don't handle it - not an XInput event */
+ }
+
+ /* FIXME: It would be nice if we could just get rid of the events
+ entirely, instead of having to ignore them */
+ if (gdkdev->info.mode == GDK_MODE_DISABLED ||
+ (gdkdev->info.mode == GDK_MODE_WINDOW
+ && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
+ return FALSE;
+
+ if (!gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ return_val = gdk_input_common_other_event (event, xevent,
+ input_window, gdkdev);
+
+ if (return_val > 0 && event->type == GDK_PROXIMITY_OUT &&
+ gdk_input_ignore_core)
+ gdk_input_check_proximity();
+
+ /* Do a passive button grab. We have to be careful not to release
+ an explicit grab, if any. Doubling the grab should be harmless,
+ but we check anyways. */
+
+ /* FIXME, finding the proper events here is going to be SLOW - but
+ we might have different sets for each window/device combination */
+
+ if (return_val> 0 && !input_window->grabbed)
+ {
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, event->button.time);
+ }
+ else if (event->type == GDK_BUTTON_RELEASE)
+ XUngrabDevice( GDK_DISPLAY(), gdkdev->xdevice, event->button.time);
+ }
+
+ return return_val;
+}
+
+static gint
+gdk_input_xfree_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ /* FIXME: watchout, gdkdev might be core pointer, never opened */
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+{
+ gdk_input_common_select_events (window, gdkdev);
+ return TRUE;
+}
+
+static gint
+gdk_input_xfree_grab_pointer (GdkWindow * window,
+ gint owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ guint32 time)
+{
+ GdkInputWindow *input_window, *new_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+ XEventClass event_classes[6];
+ gint num_classes;
+
+ tmp_list = gdk_input_windows;
+ new_window = NULL;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ return AlreadyGrabbed;
+
+ if (input_window->window == window)
+ {
+ new_window = input_window;
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_return_if_fail (new_window == NULL);
+
+ new_window->grabbed = TRUE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ gdk_input_common_find_events (window, gdkdev,
+ ((GdkWindowPrivate *)window)->extension_events,
+ event_classes, &num_classes);
+
+ /* FIXME: we should do something on failure */
+ XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice,
+ GDK_WINDOW_XWINDOW (window),
+ TRUE, num_classes, event_classes,
+ GrabModeAsync, GrabModeAsync, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ return Success;
+}
+
+static void
+gdk_input_xfree_ungrab_pointer (guint32 time)
+{
+ GdkInputWindow *input_window;
+ GdkDevicePrivate *gdkdev;
+ GList *tmp_list;
+
+ tmp_list = gdk_input_windows;
+ while (tmp_list)
+ {
+ input_window = (GdkInputWindow *)tmp_list->data;
+ if (input_window->grabbed)
+ break;
+ tmp_list = tmp_list->next;
+ }
+
+ if (tmp_list) /* we found a grabbed window */
+ {
+ input_window->grabbed = FALSE;
+
+ tmp_list = gdk_input_devices;
+ while (tmp_list)
+ {
+ gdkdev = (GdkDevicePrivate *)tmp_list->data;
+ if (gdkdev->info.deviceid != GDK_CORE_POINTER &&
+ gdkdev->xdevice && !gdkdev->button_state)
+ {
+ XUngrabDevice( gdk_display, gdkdev->xdevice, time);
+ }
+ tmp_list = tmp_list->next;
+ }
+ }
+}
+
+#endif /* XINPUT_XFREE */