From: Alexander Larsson Date: Fri, 29 May 2009 14:39:12 +0000 (+0200) Subject: Initial version of input support X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=7372379c24d183aa23e33cef031b774a5cb25ce4;p=~andy%2Fgtk Initial version of input support --- diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h index 3c7bde322..2838d44a0 100644 --- a/gdk/gdkdisplay.h +++ b/gdk/gdkdisplay.h @@ -91,6 +91,7 @@ struct _GdkDisplay const GdkDisplayPointerHooks *pointer_hooks; /* Current hooks for querying pointer */ guint closed : 1; /* Whether this display has been closed */ + guint ignore_core_events : 1; /* Don't send core motion and button event */ guint double_click_distance; /* Maximum distance between clicks in pixels */ gint button_x[2]; /* The last 2 button click positions. */ diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index 94cce6aa0..a0c2d518d 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -187,6 +187,7 @@ typedef struct gboolean grab_one_pointer_release_event; } GdkPointerGrabInfo; +typedef struct _GdkInputWindow GdkInputWindow; /* Private version of GdkWindowObject. The initial part of this strucuture is public for historical reasons. Don't change that part */ @@ -260,6 +261,7 @@ struct _GdkWindowObject guint native_visibility : 2; /* the native visibility of a impl windows */ GdkWindowPaint *implicit_paint; + GdkInputWindow *input_window; /* only for impl windows */ GList *outstanding_moves; @@ -640,6 +642,10 @@ GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window, gint *base_y_offset); gboolean _gdk_window_has_impl (GdkWindow *window); GdkWindow * _gdk_window_get_impl_window (GdkWindow *window); +GdkWindow *_gdk_window_get_input_window_for_event (GdkWindow *native_window, + GdkEventType event_type, + int x, int y, + gulong serial); GdkRegion *_gdk_region_new_from_yxbanded_rects (GdkRectangle *rects, int n_rects); /***************************** diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index a2b5d6d61..b20cf6950 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -1596,6 +1596,10 @@ _gdk_window_destroy_hierarchy (GdkWindow *window, NULL, NULL); } + + if (private->extension_events) + GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window); + if (gdk_window_has_impl (private)) { GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy); @@ -8240,6 +8244,10 @@ send_crossing_event (GdkDisplay *display, else event_mask = GDK_ENTER_NOTIFY_MASK; + if (window->extension_events != 0) + GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing (window, + type == GDK_ENTER_NOTIFY); + if (window->event_mask & event_mask) { event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE); @@ -8724,7 +8732,7 @@ proxy_pointer_event (GdkDisplay *display, } } - if (event_win) + if (event_win && !display->ignore_core_events) { event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE); event->motion.time = time_; @@ -8814,7 +8822,7 @@ proxy_button_event (GdkEvent *source_event, type, state, NULL, serial); - if (event_win == NULL) + if (event_win == NULL || display->ignore_core_events) return TRUE; event = _gdk_make_event (event_win, type, source_event, FALSE); @@ -8914,6 +8922,22 @@ gdk_window_print_tree (GdkWindow *window, #endif /* DEBUG_WINDOW_PRINTING */ +static gboolean +is_input_event (GdkDisplay *display, + GdkEvent *event) +{ + GdkDevice *core_pointer; + + core_pointer = gdk_display_get_core_pointer (display); + if ((event->type == GDK_MOTION_NOTIFY && + event->motion.device != core_pointer) || + (event->type == GDK_BUTTON_PRESS || + event->type == GDK_BUTTON_RELEASE) && + event->button.device != core_pointer) + return TRUE; + return FALSE; +} + void _gdk_windowing_got_event (GdkDisplay *display, GList *event_link, @@ -8958,6 +8982,9 @@ _gdk_windowing_got_event (GdkDisplay *display, return; } + if (is_input_event (display, event)) + return; + if (!(is_button_type (event->type) || is_motion_type (event->type)) || GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT) @@ -9075,5 +9102,87 @@ _gdk_windowing_got_event (GdkDisplay *display, } } + +static GdkWindow * +get_extension_event_window (GdkDisplay *display, + GdkWindow *pointer_window, + GdkEventType type, + gulong serial) +{ + guint evmask; + GdkWindow *grab_window; + GdkWindowObject *w; + GdkPointerGrabInfo *grab; + + grab = _gdk_display_has_pointer_grab (display, serial); + + if (grab != NULL && !grab->owner_events) + { + evmask = grab->event_mask; + + grab_window = grab->window; + + if (evmask & type_masks[type]) + return grab_window; + else + return NULL; + } + + w = (GdkWindowObject *)pointer_window; + while (w != NULL) + { + evmask = w->extension_events; + + if (evmask & type_masks[type]) + return (GdkWindow *)w; + + w = w->parent; + } + + if (grab != NULL && + grab->owner_events) + { + evmask = grab->event_mask; + + if (evmask & type_masks[type]) + return grab->window; + else + return NULL; + } + + return NULL; +} + + +GdkWindow * +_gdk_window_get_input_window_for_event (GdkWindow *native_window, + GdkEventType event_type, + int x, int y, + gulong serial) +{ + GdkDisplay *display; + GdkWindow *toplevel_window; + GdkWindow *pointer_window; + GdkWindow *event_win; + gdouble toplevel_x, toplevel_y; + + toplevel_x = x; + toplevel_y = y; + + display = gdk_drawable_get_display (native_window); + toplevel_window = convert_coords_to_toplevel (native_window, + toplevel_x, toplevel_y, + &toplevel_x, &toplevel_y); + pointer_window = get_pointer_window (display, toplevel_window, + toplevel_x, toplevel_y, serial); + event_win = get_extension_event_window (display, + pointer_window, + event_type, + serial); + + return event_win; +} + + #define __GDK_WINDOW_C__ #include "gdkaliasdef.c" diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h index d63e5a1ff..1bedb3589 100644 --- a/gdk/gdkwindowimpl.h +++ b/gdk/gdkwindowimpl.h @@ -128,6 +128,10 @@ struct _GdkWindowImplIface void (* destroy) (GdkWindow *window, gboolean recursing, gboolean foreign_destroy); + + void (* input_window_destroy) (GdkWindow *window); + void (* input_window_crossing)(GdkWindow *window, + gboolean enter); }; /* Interface Functions */ diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h index e92418d37..2873c2d67 100644 --- a/gdk/x11/gdkdisplay-x11.h +++ b/gdk/x11/gdkdisplay-x11.h @@ -133,11 +133,6 @@ struct _GdkDisplayX11 /* input GdkWindow list */ GList *input_windows; - gint input_ignore_core; - /* information about network port and host for gxid daemon */ - gchar *input_gxid_host; - gint input_gxid_port; - /* Startup notification */ gchar *startup_notification_id; diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 8d3141a8e..4565b3961 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -1125,9 +1125,7 @@ gdk_event_translate (GdkDisplay *display, xevent->xbutton.x, xevent->xbutton.y, xevent->xbutton.button)); - if (window_private == NULL || - ((window_private->extension_events != 0) && - display_x11->input_ignore_core)) + if (window_private == NULL) { return_val = FALSE; break; @@ -1201,9 +1199,7 @@ gdk_event_translate (GdkDisplay *display, xevent->xbutton.x, xevent->xbutton.y, xevent->xbutton.button)); - if (window_private == NULL || - ((window_private->extension_events != 0) && - display_x11->input_ignore_core)) + if (window_private == NULL) { return_val = FALSE; break; @@ -1241,9 +1237,7 @@ gdk_event_translate (GdkDisplay *display, xevent->xmotion.x, xevent->xmotion.y, (xevent->xmotion.is_hint) ? "true" : "false")); - if (window_private == NULL || - ((window_private->extension_events != 0) && - display_x11->input_ignore_core)) + if (window_private == NULL) { return_val = FALSE; break; @@ -1304,12 +1298,6 @@ gdk_event_translate (GdkDisplay *display, } } - /* Tell XInput stuff about it if appropriate */ - if (window_private && - !GDK_WINDOW_DESTROYED (window) && - window_private->extension_events != 0) - _gdk_input_enter_event (&xevent->xcrossing, window); - event->crossing.type = GDK_ENTER_NOTIFY; event->crossing.window = window; @@ -1854,7 +1842,7 @@ gdk_event_translate (GdkDisplay *display, if (window && xevent->xconfigure.event == xevent->xconfigure.window && !GDK_WINDOW_DESTROYED (window) && - (window_private->extension_events != 0)) + window_private->input_window != NULL) _gdk_input_configure_event (&xevent->xconfigure, window); #ifdef HAVE_XSYNC @@ -2171,8 +2159,8 @@ gdk_event_translate (GdkDisplay *display, if (window_private && !GDK_WINDOW_DESTROYED (window_private) && - (window_private->extension_events != 0)) - return_val = _gdk_input_other_event(event, xevent, window); + window_private->input_window) + return_val = _gdk_input_other_event (event, xevent, window); else return_val = FALSE; diff --git a/gdk/x11/gdkinput-x11.c b/gdk/x11/gdkinput-x11.c index 9e2d81889..22e39a05c 100644 --- a/gdk/x11/gdkinput-x11.c +++ b/gdk/x11/gdkinput-x11.c @@ -21,7 +21,7 @@ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "config.h" @@ -39,7 +39,7 @@ static GdkDevicePrivate *gdk_input_device_new (GdkDisplay *disp XDeviceInfo *device, gint include_core); static void gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev, - GdkInputWindow *input_window, + GdkWindow *window, gint *axis_data, gdouble *axis_out, gdouble *x_out, @@ -64,37 +64,26 @@ _gdk_input_find_device (GdkDisplay *display, } void -_gdk_input_get_root_relative_geometry(Display *display, Window w, int *x_ret, int *y_ret, - int *width_ret, int *height_ret) +_gdk_input_get_root_relative_geometry (GdkWindow *window, + int *x_ret, int *y_ret) { - Window root, parent, child; - Window *children; - guint nchildren; + Window child; gint x,y; - guint width, height; - guint border_widthc, depthc; - - XQueryTree (display, w, &root, &parent, &children, &nchildren); - if (children) - XFree(children); - - XGetGeometry (display, w, &root, &x, &y, &width, &height, &border_widthc, &depthc); - - XTranslateCoordinates (display, w, root, 0, 0, &x, &y, &child); - + + XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XWINDOW (window), + GDK_WINDOW_XROOTWIN (window), + 0, 0, &x, &y, &child); + if (x_ret) *x_ret = x; if (y_ret) *y_ret = y; - if (width_ret) - *width_ret = width; - if (height_ret) - *height_ret = height; } static GdkDevicePrivate * gdk_input_device_new (GdkDisplay *display, - XDeviceInfo *device, + XDeviceInfo *device, gint include_core) { GdkDevicePrivate *gdkdev; @@ -121,7 +110,7 @@ gdk_input_device_new (GdkDisplay *display, for comparison purposes */ tmp_name = g_ascii_strdown (gdkdev->info.name, -1); - + if (!strcmp (tmp_name, "pointer")) gdkdev->info.source = GDK_SOURCE_MOUSE; else if (!strcmp (tmp_name, "wacom") || @@ -151,7 +140,7 @@ gdk_input_device_new (GdkDisplay *display, gdkdev->button_state = 0; class = device->inputclassinfo; - for (i=0;inum_classes;i++) + for (i=0;inum_classes;i++) { switch (class->class) { case ButtonClass: @@ -160,7 +149,7 @@ gdk_input_device_new (GdkDisplay *display, { XKeyInfo *xki = (XKeyInfo *)class; /* Hack to catch XFree86 3.3.1 bug. Other devices better - * not have exactly 25 keys... + * not have exactly 25 keys... */ if ((xki->min_keycode == 8) && (xki->max_keycode == 32)) { @@ -190,7 +179,7 @@ gdk_input_device_new (GdkDisplay *display, gdkdev->info.axes = g_new0 (GdkDeviceAxis, xvi->num_axes); for (j=0;jnum_axes;j++) { - gdkdev->axes[j].resolution = + gdkdev->axes[j].resolution = gdkdev->axes[j].xresolution = xvi->axes[j].resolution; gdkdev->axes[j].min_value = gdkdev->axes[j].xmin_value = xvi->axes[j].min_value; @@ -211,7 +200,7 @@ gdk_input_device_new (GdkDisplay *display, gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_YTILT); if (jnum_axes) gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_WHEEL); - + break; } } @@ -247,20 +236,19 @@ gdk_input_device_new (GdkDisplay *display, error: g_object_unref (gdkdev); - + return NULL; } void -_gdk_input_common_find_events(GdkWindow *window, - GdkDevicePrivate *gdkdev, - gint mask, - XEventClass *classes, - int *num_classes) +_gdk_input_common_find_events (GdkDevicePrivate *gdkdev, + gint mask, + XEventClass *classes, + int *num_classes) { gint i; XEventClass class; - + i = 0; if (mask & GDK_BUTTON_PRESS_MASK) { @@ -354,25 +342,42 @@ _gdk_input_common_find_events(GdkWindow *window, } void -_gdk_input_common_select_events(GdkWindow *window, - GdkDevicePrivate *gdkdev) +_gdk_input_select_events (GdkWindow *impl_window, + GdkDevicePrivate *gdkdev) { XEventClass classes[GDK_MAX_DEVICE_CLASSES]; gint num_classes; + guint event_mask; + GdkWindowObject *w; + GdkInputWindow *iw; + GList *l; - if (gdkdev->info.mode == GDK_MODE_DISABLED) - _gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes); - else - _gdk_input_common_find_events(window, gdkdev, - ((GdkWindowObject *)window)->extension_events, - classes, &num_classes); - - XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XWINDOW (window), + event_mask = 0; + iw = ((GdkWindowObject *)impl_window)->input_window; + + if (gdkdev->info.mode != GDK_MODE_DISABLED && + iw != NULL) + { + for (l = iw->windows; l != NULL; l = l->next) + { + w = l->data; + if (gdkdev->info.has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK)) + event_mask |= w->extension_events; + } + } + event_mask &= ~GDK_ALL_DEVICES_MASK; + + if (event_mask) + event_mask |= GDK_PROXIMITY_OUT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK; + + _gdk_input_common_find_events (gdkdev, event_mask, + classes, &num_classes); + XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (impl_window), + GDK_WINDOW_XWINDOW (impl_window), classes, num_classes); } -gint +gint _gdk_input_common_init (GdkDisplay *display, gint include_core) { @@ -391,7 +396,7 @@ _gdk_input_common_init (GdkDisplay *display, event_base, 15 /* Number of events */); devices = XListInputDevices(display_x11->xdisplay, &num_devices); - + for(loop=0; loopwindow; + + priv = (GdkWindowObject *) window; + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); for (i=0; iinfo.num_axes; i++) { @@ -440,26 +447,24 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev, break; } } - - device_width = gdkdev->axes[x_axis].max_value - - gdkdev->axes[x_axis].min_value; - device_height = gdkdev->axes[y_axis].max_value - - gdkdev->axes[y_axis].min_value; - if (gdkdev->info.mode == GDK_MODE_SCREEN) + device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value; + device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value; + + if (gdkdev->info.mode == GDK_MODE_SCREEN) { - x_scale = gdk_screen_get_width (gdk_drawable_get_screen (input_window->window)) / device_width; - y_scale = gdk_screen_get_height (gdk_drawable_get_screen (input_window->window)) / device_height; + x_scale = gdk_screen_get_width (gdk_drawable_get_screen (window)) / device_width; + y_scale = gdk_screen_get_height (gdk_drawable_get_screen (window)) / device_height; - x_offset = - input_window->root_x; - y_offset = - input_window->root_y; + x_offset = - impl_window->input_window->root_x; + y_offset = - impl_window->input_window->root_y; } else /* GDK_MODE_WINDOW */ { double x_resolution = gdkdev->axes[x_axis].resolution; double y_resolution = gdkdev->axes[y_axis].resolution; double device_aspect; - /* + /* * Some drivers incorrectly report the resolution of the device * as zero (in partiular linuxwacom < 0.5.3 with usb tablets). * This causes the device_aspect to become NaN and totally @@ -475,27 +480,24 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev, y_resolution = 1; } device_aspect = (device_height*y_resolution) / - (device_width*x_resolution); - if (device_aspect * window_private->width >= window_private->height) + (device_width*x_resolution); + if (device_aspect * priv->width >= priv->height) { /* device taller than window */ - x_scale = window_private->width / device_width; - y_scale = (x_scale * x_resolution) - / y_resolution; + x_scale = priv->width / device_width; + y_scale = (x_scale * x_resolution) / y_resolution; x_offset = 0; - y_offset = -(device_height * y_scale - - window_private->height)/2; + y_offset = -(device_height * y_scale - priv->height)/2; } else { /* window taller than device */ - y_scale = window_private->height / device_height; - x_scale = (y_scale * y_resolution) - / x_resolution; + y_scale = priv->height / device_height; + x_scale = (y_scale * y_resolution) / x_resolution; y_offset = 0; - x_offset = - (device_width * x_scale - window_private->width)/2; + x_offset = - (device_width * x_scale - priv->width)/2; } } @@ -504,13 +506,13 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev, switch (gdkdev->info.axes[i].use) { case GDK_AXIS_X: - axis_out[i] = x_offset + x_scale * (axis_data[x_axis] - + axis_out[i] = x_offset + x_scale * (axis_data[x_axis] - gdkdev->axes[x_axis].min_value); if (x_out) *x_out = axis_out[i]; break; case GDK_AXIS_Y: - axis_out[i] = y_offset + y_scale * (axis_data[y_axis] - + axis_out[i] = y_offset + y_scale * (axis_data[y_axis] - gdkdev->axes[y_axis].min_value); if (y_out) *y_out = axis_out[i]; @@ -541,11 +543,18 @@ gdk_input_translate_state(guint state, guint device_state) gboolean _gdk_input_common_other_event (GdkEvent *event, XEvent *xevent, - GdkInputWindow *input_window, + GdkWindow *window, GdkDevicePrivate *gdkdev) { + GdkWindowObject *priv, *impl_window; + GdkInputWindow *input_window; + + priv = (GdkWindowObject *) window; + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); + input_window = impl_window->input_window; + if ((xevent->type == gdkdev->buttonpress_type) || - (xevent->type == gdkdev->buttonrelease_type)) + (xevent->type == gdkdev->buttonrelease_type)) { XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent); @@ -560,16 +569,16 @@ _gdk_input_common_other_event (GdkEvent *event, gdkdev->button_state &= ~(1 << xdbe->button); } event->button.device = &gdkdev->info; - event->button.window = input_window->window; + event->button.window = window; event->button.time = xdbe->time; event->button.axes = g_new (gdouble, gdkdev->info.num_axes); - gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data, - event->button.axes, - &event->button.x,&event->button.y); - event->button.x_root = event->button.x + input_window->root_x; - event->button.y_root = event->button.y + input_window->root_y; - event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state); + gdk_input_translate_coordinates (gdkdev, window, xdbe->axis_data, + event->button.axes, + &event->button.x, &event->button.y); + event->button.x_root = event->button.x + priv->abs_x + input_window->root_x; + event->button.y_root = event->button.y + priv->abs_y + input_window->root_y; + event->button.state = gdk_input_translate_state (xdbe->state,xdbe->device_state); event->button.button = xdbe->button; if (event->button.type == GDK_BUTTON_PRESS) @@ -588,8 +597,8 @@ _gdk_input_common_other_event (GdkEvent *event, * a valid timestamp. */ if (gdk_event_get_time (event) != GDK_CURRENT_TIME) - gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window), - gdk_event_get_time (event)); + gdk_x11_window_set_user_time (gdk_window_get_toplevel (window), + gdk_event_get_time (event)); return TRUE; } @@ -611,21 +620,21 @@ _gdk_input_common_other_event (GdkEvent *event, g_warning ("Invalid device key code received"); return FALSE; } - + event->key.keyval = gdkdev->info.keys[xdke->keycode - gdkdev->min_keycode].keyval; - if (event->key.keyval == 0) + if (event->key.keyval == 0) { GDK_NOTE (EVENTS, g_print ("\t\ttranslation - NONE\n")); - + return FALSE; } event->key.type = (xdke->type == gdkdev->keypress_type) ? GDK_KEY_PRESS : GDK_KEY_RELEASE; - event->key.window = input_window->window; + event->key.window = window; event->key.time = xdke->time; event->key.state = gdk_input_translate_state(xdke->state, xdke->device_state) @@ -654,26 +663,26 @@ _gdk_input_common_other_event (GdkEvent *event, * a valid timestamp. */ if (gdk_event_get_time (event) != GDK_CURRENT_TIME) - gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window), - gdk_event_get_time (event)); + gdk_x11_window_set_user_time (gdk_window_get_toplevel (window), + gdk_event_get_time (event)); return TRUE; } - if (xevent->type == gdkdev->motionnotify_type) + if (xevent->type == gdkdev->motionnotify_type) { XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent); event->motion.device = &gdkdev->info; - + event->motion.axes = g_new (gdouble, gdkdev->info.num_axes); - gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data, + gdk_input_translate_coordinates(gdkdev,window,xdme->axis_data, event->motion.axes, &event->motion.x,&event->motion.y); - event->motion.x_root = event->motion.x + input_window->root_x; - event->motion.y_root = event->motion.y + input_window->root_y; + event->motion.x_root = event->motion.x + priv->abs_x + input_window->root_x; + event->motion.y_root = event->motion.y + priv->abs_y + input_window->root_y; event->motion.type = GDK_MOTION_NOTIFY; - event->motion.window = input_window->window; + event->motion.window = window; event->motion.time = xdme->time; event->motion.state = gdk_input_translate_state(xdme->state, xdme->device_state); @@ -686,14 +695,14 @@ _gdk_input_common_other_event (GdkEvent *event, event->motion.x, event->motion.y, event->motion.state, (xdme->is_hint) ? "true" : "false")); - - + + /* Update the timestamp of the latest user interaction, if the event has * a valid timestamp. */ if (gdk_event_get_time (event) != GDK_CURRENT_TIME) - gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window), - gdk_event_get_time (event)); + gdk_x11_window_set_user_time (gdk_window_get_toplevel (window), + gdk_event_get_time (event)); return TRUE; } @@ -704,16 +713,16 @@ _gdk_input_common_other_event (GdkEvent *event, event->proximity.device = &gdkdev->info; event->proximity.type = (xevent->type == gdkdev->proximityin_type)? - GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT; - event->proximity.window = input_window->window; + GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT; + event->proximity.window = window; event->proximity.time = xpne->time; - + /* Update the timestamp of the latest user interaction, if the event has * a valid timestamp. */ if (gdk_event_get_time (event) != GDK_CURRENT_TIME) - gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window), - gdk_event_get_time (event)); + gdk_x11_window_set_user_time (gdk_window_get_toplevel (window), + gdk_event_get_time (event)); return TRUE; } @@ -730,18 +739,17 @@ _gdk_device_get_history (GdkDevice *device, { GdkTimeCoord **coords; XDeviceTimeCoord *device_coords; - GdkInputWindow *input_window; + GdkWindow *impl_window; GdkDevicePrivate *gdkdev; gint mode_return; gint axis_count_return; gint i; gdkdev = (GdkDevicePrivate *)device; - input_window = _gdk_input_window_find (window); - g_return_val_if_fail (input_window != NULL, FALSE); + impl_window = _gdk_window_get_impl_window (window); - device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (window), + device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (impl_window), gdkdev->xdevice, start, stop, n_events, &mode_return, @@ -752,13 +760,13 @@ _gdk_device_get_history (GdkDevice *device, coords = _gdk_device_allocate_history (device, *n_events); for (i = 0; i < *n_events; i++) - { - coords[i]->time = device_coords[i].time; + { + coords[i]->time = device_coords[i].time; - gdk_input_translate_coordinates (gdkdev, input_window, - device_coords[i].data, - coords[i]->axes, NULL, NULL); - } + gdk_input_translate_coordinates (gdkdev, window, + device_coords[i].data, + coords[i]->axes, NULL, NULL); + } XFreeDeviceMotionEvents (device_coords); @@ -770,7 +778,7 @@ _gdk_device_get_history (GdkDevice *device, return FALSE; } -void +void gdk_device_get_state (GdkDevice *device, GdkWindow *window, gdouble *axes, @@ -784,7 +792,7 @@ gdk_device_get_state (GdkDevice *device, if (GDK_IS_CORE (device)) { gint x_int, y_int; - + gdk_window_get_pointer (window, &x_int, &y_int, mask); if (axes) @@ -796,16 +804,13 @@ gdk_device_get_state (GdkDevice *device, else { GdkDevicePrivate *gdkdev; - GdkInputWindow *input_window; XDeviceState *state; XInputClass *input_class; - + if (mask) gdk_window_get_pointer (window, NULL, NULL, mask); - + gdkdev = (GdkDevicePrivate *)device; - input_window = _gdk_input_window_find (window); - g_return_if_fail (input_window != NULL); state = XQueryDeviceState (GDK_WINDOW_XDISPLAY (window), gdkdev->xdevice); @@ -816,11 +821,11 @@ gdk_device_get_state (GdkDevice *device, { case ValuatorClass: if (axes) - gdk_input_translate_coordinates (gdkdev, input_window, + gdk_input_translate_coordinates (gdkdev, window, ((XValuatorState *)input_class)->valuators, axes, NULL, NULL); break; - + case ButtonClass: if (mask) { diff --git a/gdk/x11/gdkinput-xfree.c b/gdk/x11/gdkinput-xfree.c index b51516b3e..10fd33d91 100644 --- a/gdk/x11/gdkinput-xfree.c +++ b/gdk/x11/gdkinput-xfree.c @@ -26,18 +26,18 @@ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ /* forward declarations */ static void gdk_input_check_proximity (GdkDisplay *display); -void +void _gdk_input_init(GdkDisplay *display) { _gdk_init_input_core (display); - GDK_DISPLAY_X11 (display)->input_ignore_core = FALSE; + display->ignore_core_events = FALSE; _gdk_input_common_init (display, FALSE); } @@ -47,7 +47,6 @@ gdk_device_set_mode (GdkDevice *device, { GList *tmp_list; GdkDevicePrivate *gdkdev; - GdkInputMode old_mode; GdkInputWindow *input_window; GdkDisplayX11 *display_impl; @@ -59,58 +58,35 @@ gdk_device_set_mode (GdkDevice *device, if (device->mode == mode) return TRUE; - old_mode = device->mode; device->mode = mode; - display_impl = GDK_DISPLAY_X11 (gdkdev->display); - if (mode == GDK_MODE_WINDOW) - { - device->has_cursor = FALSE; - for (tmp_list = display_impl->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); - } - } + device->has_cursor = FALSE; else if (mode == GDK_MODE_SCREEN) + device->has_cursor = TRUE; + + display_impl = GDK_DISPLAY_X11 (gdkdev->display); + for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next) { - device->has_cursor = TRUE; - for (tmp_list = display_impl->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 = display_impl->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); - } + input_window = (GdkInputWindow *)tmp_list->data; + _gdk_input_select_events (input_window->impl_window, gdkdev); } return TRUE; - } static void gdk_input_check_proximity (GdkDisplay *display) { - gint new_proximity = 0; GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display); GList *tmp_list = display_impl->input_devices; + gint new_proximity = 0; - while (tmp_list && !new_proximity) + while (tmp_list && !new_proximity) { GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data); - if (gdkdev->info.mode != GDK_MODE_DISABLED + if (gdkdev->info.mode != GDK_MODE_DISABLED && !GDK_IS_CORE (gdkdev) && gdkdev->xdevice) { @@ -118,7 +94,7 @@ gdk_input_check_proximity (GdkDisplay *display) gdkdev->xdevice); XInputClass *xic; int i; - + xic = state->data; for (i=0; inum_classes; i++) { @@ -135,117 +111,197 @@ gdk_input_check_proximity (GdkDisplay *display) } XFreeDeviceState (state); - } + } tmp_list = tmp_list->next; } - display_impl->input_ignore_core = new_proximity; + display->ignore_core_events = new_proximity; } void _gdk_input_configure_event (XConfigureEvent *xevent, GdkWindow *window) { + GdkWindowObject *priv = (GdkWindowObject *)window; GdkInputWindow *input_window; gint root_x, root_y; - input_window = _gdk_input_window_find(window); - g_return_if_fail (input_window != NULL); - - _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XWINDOW (window), - &root_x, &root_y, NULL, NULL); - - input_window->root_x = root_x; - input_window->root_y = root_y; + input_window = priv->input_window; + if (input_window != NULL) + { + _gdk_input_get_root_relative_geometry (window, &root_x, &root_y); + input_window->root_x = root_x; + input_window->root_y = root_y; + } } -void -_gdk_input_enter_event (XCrossingEvent *xevent, - GdkWindow *window) +void +_gdk_input_crossing_event (GdkWindow *window, + gboolean enter) { + GdkDisplay *display = GDK_WINDOW_DISPLAY (window); + GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display); + GdkWindowObject *priv = (GdkWindowObject *)window; GdkInputWindow *input_window; gint root_x, root_y; - input_window = _gdk_input_window_find (window); - g_return_if_fail (input_window != NULL); + if (enter) + { + gdk_input_check_proximity(display); + + input_window = priv->input_window; + if (input_window != NULL) + { + _gdk_input_get_root_relative_geometry (window, &root_x, &root_y); + input_window->root_x = root_x; + input_window->root_y = root_y; + } + } + else + display->ignore_core_events = FALSE; +} + +static GdkEventType +get_input_event_type (GdkDevicePrivate *gdkdev, + XEvent *xevent, + int *core_x, int *core_y) +{ + if (xevent->type == gdkdev->buttonpress_type) + { + XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent); + *core_x = xie->x; + *core_y = xie->y; + return GDK_BUTTON_PRESS; + } + + if (xevent->type == gdkdev->buttonrelease_type) + { + XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent); + *core_x = xie->x; + *core_y = xie->y; + return GDK_BUTTON_RELEASE; + } + + if (xevent->type == gdkdev->keypress_type) + { + XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent); + *core_x = xie->x; + *core_y = xie->y; + return GDK_KEY_PRESS; + } + + if (xevent->type == gdkdev->keyrelease_type) + { + XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent); + *core_x = xie->x; + *core_y = xie->y; + return GDK_KEY_RELEASE; + } + + if (xevent->type == gdkdev->motionnotify_type) + { + XDeviceMotionEvent *xie = (XDeviceMotionEvent *)(xevent); + *core_x = xie->x; + *core_y = xie->y; + return GDK_MOTION_NOTIFY; + } - gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window)); + if (xevent->type == gdkdev->proximityin_type) + { + XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent); + *core_x = xie->x; + *core_y = xie->y; + return GDK_PROXIMITY_IN; + } - _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XWINDOW(window), - &root_x, &root_y, NULL, NULL); + if (xevent->type == gdkdev->proximityout_type) + { + XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent); + *core_x = xie->x; + *core_y = xie->y; + return GDK_PROXIMITY_OUT; + } - input_window->root_x = root_x; - input_window->root_y = root_y; + *core_x = 0; + *core_y = 0; + return GDK_NOTHING; } -gboolean -_gdk_input_other_event (GdkEvent *event, - XEvent *xevent, - GdkWindow *window) + +gboolean +_gdk_input_other_event (GdkEvent *event, + XEvent *xevent, + GdkWindow *event_window) { - GdkInputWindow *input_window; - + GdkWindow *window; + GdkWindowObject *priv; + GdkInputWindow *iw; GdkDevicePrivate *gdkdev; gint return_val; - GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window)); - - input_window = _gdk_input_window_find(window); - g_return_val_if_fail (input_window != NULL, FALSE); + GdkEventType event_type; + int x, y; + GdkDisplay *display = GDK_WINDOW_DISPLAY (event_window); + GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display); /* 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 (GDK_WINDOW_DISPLAY (window), + gdkdev = _gdk_input_find_device (display, ((XDeviceButtonEvent *)xevent)->deviceid); if (!gdkdev) return FALSE; /* 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 */ + event_type = get_input_event_type (gdkdev, xevent, &x, &y); + if (event_type == GDK_NOTHING) + return FALSE; + + window = _gdk_window_get_input_window_for_event (event_window, + event_type, + x, y, + xevent->xany.serial); + /* If we're not getting any event window its likely because we're outside the + window and there is no grab. We should still report according to the + implicit grab though. */ + iw = ((GdkWindowObject *)event_window)->input_window; + if (window == NULL) + window = iw->button_down_window; + + priv = (GdkWindowObject *)window; + if (window == NULL) + return FALSE; + if (gdkdev->info.mode == GDK_MODE_DISABLED || - (gdkdev->info.mode == GDK_MODE_WINDOW - && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR)) + !(gdkdev->info.has_cursor || (priv->extension_events & GDK_ALL_DEVICES_MASK))) return FALSE; - - if (!display_impl->input_ignore_core) - gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window)); - return_val = _gdk_input_common_other_event (event, xevent, - input_window, gdkdev); + if (!display->ignore_core_events && priv->extension_events != 0) + gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window)); - if (return_val && event->type == GDK_PROXIMITY_OUT && - display_impl->input_ignore_core) - gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window)); + return_val = _gdk_input_common_other_event (event, xevent, window, gdkdev); - return return_val; -} + if (return_val && event->type == GDK_BUTTON_PRESS) + iw->button_down_window = window; + if (return_val && event->type == GDK_BUTTON_RELEASE) + iw->button_down_window = NULL; -gboolean -_gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev) -{ - /* FIXME: watchout, gdkdev might be core pointer, never opened */ - _gdk_input_common_select_events (window, gdkdev); - return TRUE; -} + if (return_val && event->type == GDK_PROXIMITY_OUT && + display->ignore_core_events) + gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window)); -gboolean -_gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev) -{ - _gdk_input_common_select_events (window, gdkdev); - return TRUE; + return return_val; } -gint -_gdk_input_grab_pointer (GdkWindow * window, +gint +_gdk_input_grab_pointer (GdkWindow *window, + GdkWindow *native_window, /* This is the toplevel */ gint owner_events, GdkEventMask event_mask, GdkWindow * confine_to, guint32 time) { - GdkInputWindow *input_window, *new_window; + GdkInputWindow *input_window; + GdkWindowObject *priv, *impl_window; gboolean need_ungrab; GdkDevicePrivate *gdkdev; GList *tmp_list; @@ -255,36 +311,36 @@ _gdk_input_grab_pointer (GdkWindow * window, GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window)); tmp_list = display_impl->input_windows; - new_window = NULL; need_ungrab = FALSE; while (tmp_list) { input_window = (GdkInputWindow *)tmp_list->data; - if (input_window->window == window) - new_window = input_window; - else if (input_window->grabbed) + if (input_window->grabbed) { input_window->grabbed = FALSE; need_ungrab = TRUE; + break; } - tmp_list = tmp_list->next; } - if (new_window) + priv = (GdkWindowObject *)window; + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); + input_window = impl_window->input_window; + if (priv->extension_events) { - new_window->grabbed = TRUE; - + g_assert (input_window != NULL); + input_window->grabbed = TRUE; + tmp_list = display_impl->input_devices; while (tmp_list) { gdkdev = (GdkDevicePrivate *)tmp_list->data; if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice) { - _gdk_input_common_find_events (window, gdkdev, - event_mask, + _gdk_input_common_find_events (gdkdev, event_mask, event_classes, &num_classes); #ifdef G_ENABLE_DEBUG if (_gdk_debug_flags & GDK_DEBUG_NOGRABS) @@ -292,10 +348,10 @@ _gdk_input_grab_pointer (GdkWindow * window, else #endif result = XGrabDevice (display_impl->xdisplay, gdkdev->xdevice, - GDK_WINDOW_XWINDOW (window), + GDK_WINDOW_XWINDOW (native_window), owner_events, num_classes, event_classes, GrabModeAsync, GrabModeAsync, time); - + /* FIXME: if failure occurs on something other than the first device, things will be badly inconsistent */ if (result != Success) @@ -305,7 +361,7 @@ _gdk_input_grab_pointer (GdkWindow * window, } } else - { + { tmp_list = display_impl->input_devices; while (tmp_list) { @@ -316,17 +372,16 @@ _gdk_input_grab_pointer (GdkWindow * window, XUngrabDevice (display_impl->xdisplay, gdkdev->xdevice, time); gdkdev->button_state = 0; } - + tmp_list = tmp_list->next; } } return Success; - } -void -_gdk_input_ungrab_pointer (GdkDisplay *display, +void +_gdk_input_ungrab_pointer (GdkDisplay *display, guint32 time) { GdkInputWindow *input_window = NULL; /* Quiet GCC */ diff --git a/gdk/x11/gdkinput.c b/gdk/x11/gdkinput.c index 95a301d24..c33f09c9e 100644 --- a/gdk/x11/gdkinput.c +++ b/gdk/x11/gdkinput.c @@ -21,7 +21,7 @@ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "config.h" @@ -47,10 +47,10 @@ void _gdk_init_input_core (GdkDisplay *display) { GdkDevicePrivate *private; - + display->core_pointer = g_object_new (GDK_TYPE_DEVICE, NULL); private = (GdkDevicePrivate *)display->core_pointer; - + display->core_pointer->name = "Core Pointer"; display->core_pointer->source = GDK_SOURCE_MOUSE; display->core_pointer->mode = GDK_MODE_SCREEN; @@ -87,12 +87,12 @@ gdk_device_get_type (void) 0, /* n_preallocs */ (GInstanceInitFunc) NULL, }; - + object_type = g_type_register_static (G_TYPE_OBJECT, - g_intern_static_string ("GdkDevice"), - &object_info, 0); + g_intern_static_string ("GdkDevice"), + &object_info, 0); } - + return object_type; } @@ -115,10 +115,10 @@ gdk_device_dispose (GObject *object) { #ifndef XINPUT_NONE if (gdkdev->xdevice) - { - XCloseDevice (GDK_DISPLAY_XDISPLAY (gdkdev->display), gdkdev->xdevice); - gdkdev->xdevice = NULL; - } + { + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdkdev->display), gdkdev->xdevice); + gdkdev->xdevice = NULL; + } g_free (gdkdev->axes); gdkdev->axes = NULL; #endif /* !XINPUT_NONE */ @@ -140,7 +140,7 @@ gdk_device_dispose (GObject *object) * * Returns the list of available input devices for the default display. * The list is statically allocated and should not be freed. - * + * * Return value: a list of #GdkDevice **/ GList * @@ -155,16 +155,16 @@ gdk_devices_list (void) * * Returns the list of available input devices attached to @display. * The list is statically allocated and should not be freed. - * + * * Return value: a list of #GdkDevice * * Since: 2.2 **/ -GList * +GList * gdk_display_list_devices (GdkDisplay *display) { g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); - + return GDK_DISPLAY_X11 (display)->input_devices; } @@ -219,6 +219,22 @@ gdk_device_set_axis_use (GdkDevice *device, } } +static gboolean +impl_coord_in_window (GdkWindow *window, + int impl_x, + int impl_y) +{ + GdkWindowObject *priv = (GdkWindowObject *)window; + + if (impl_x < priv->abs_x || + impl_x > priv->abs_x + priv->width) + return FALSE; + if (impl_y < priv->abs_y || + impl_y > priv->abs_y + priv->height) + return FALSE; + return TRUE; +} + /** * gdk_device_get_history: * @device: a #GdkDevice @@ -227,14 +243,14 @@ gdk_device_set_axis_use (GdkDevice *device, * @stop: ending timestamp for the range of events to return * @events: location to store a newly-allocated array of #GdkTimeCoord, or %NULL * @n_events: location to store the length of @events, or %NULL - * + * * Obtains the motion history for a device; given a starting and * ending timestamp, return all events in the motion history for * the device in the given range of time. Some windowing systems * do not support motion history, in which case, %FALSE will * be returned. (This is not distinguishable from the case where * motion history is supported and no events were found.) - * + * * Return value: %TRUE if the windowing system supports motion history and * at least one event was found. **/ @@ -247,29 +263,38 @@ gdk_device_get_history (GdkDevice *device, gint *n_events) { GdkTimeCoord **coords = NULL; + GdkWindow *impl_window; gboolean result = FALSE; int tmp_n_events = 0; - int i; + int i, j; g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE); + impl_window = _gdk_window_get_impl_window (window); + if (GDK_WINDOW_DESTROYED (window)) /* Nothing */ ; else if (GDK_IS_CORE (device)) { XTimeCoord *xcoords; - + xcoords = XGetMotionEvents (GDK_DRAWABLE_XDISPLAY (window), - GDK_DRAWABLE_XID (window), + GDK_DRAWABLE_XID (impl_window), start, stop, &tmp_n_events); if (xcoords) { + GdkWindowObject *priv = (GdkWindowObject *)window; coords = _gdk_device_allocate_history (device, tmp_n_events); + j = 0; for (i=0; itime = xcoords[i].time; - coords[i]->axes[0] = xcoords[i].x; - coords[i]->axes[1] = xcoords[i].y; + if (impl_coord_in_window (window, xcoords[i].x, xcoords[i].y)) + { + coords[j]->time = xcoords[i].time; + coords[j]->axes[0] = xcoords[i].x - priv->abs_x; + coords[j]->axes[1] = xcoords[i].y - priv->abs_y; + j++; + } } XFree (xcoords); @@ -292,7 +317,7 @@ gdk_device_get_history (GdkDevice *device, return result; } -GdkTimeCoord ** +GdkTimeCoord ** _gdk_device_allocate_history (GdkDevice *device, gint n_events) { @@ -306,41 +331,48 @@ _gdk_device_allocate_history (GdkDevice *device, return result; } -void +void gdk_device_free_history (GdkTimeCoord **events, gint n_events) { gint i; - + for (i=0; iinput_window; - for (tmp_list=display_x11->input_windows; tmp_list; tmp_list=tmp_list->next) - if (((GdkInputWindow *)(tmp_list->data))->window == window) - return (GdkInputWindow *)(tmp_list->data); + display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window)); - return NULL; /* Not found */ -} + if (window_private->extension_events != 0) + { + g_assert (iw != NULL); + g_assert (g_list_find (iw->windows, window) != NULL); + + iw->windows = g_list_remove (iw->windows, window); + if (iw->windows == NULL) + { + impl_window->input_window = NULL; + display_x11->input_windows = g_list_remove (display_x11->input_windows, iw); + g_free (iw); + } + } -/* FIXME: this routine currently needs to be called between creation - and the corresponding configure event (because it doesn't get the - root_relative_geometry). This should work with - gtk_window_set_extension_events, but will likely fail in other - cases */ + window_private->extension_events = 0; +} void gdk_input_set_extension_events (GdkWindow *window, gint mask, @@ -348,6 +380,7 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask, { GdkWindowObject *window_private; GList *tmp_list; + GdkWindowObject *impl_window; GdkInputWindow *iw; GdkDisplayX11 *display_x11; @@ -359,52 +392,44 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask, if (GDK_WINDOW_DESTROYED (window)) return; + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); + + if (mode == GDK_EXTENSION_EVENTS_ALL && mask != 0) + mask |= GDK_ALL_DEVICES_MASK; + if (mode == GDK_EXTENSION_EVENTS_NONE) mask = 0; - iw = _gdk_input_window_find (window); + iw = impl_window->input_window; if (mask != 0) { if (!iw) - { - iw = g_new(GdkInputWindow,1); - - iw->window = window; - iw->mode = mode; + { + iw = g_new0 (GdkInputWindow,1); - iw->obscuring = NULL; - iw->num_obscuring = 0; - iw->grabbed = FALSE; + iw->impl_window = (GdkWindow *)impl_window; - display_x11->input_windows = g_list_append(display_x11->input_windows,iw); - } + iw->windows = NULL; + iw->grabbed = FALSE; - window_private->extension_events = mask; + display_x11->input_windows = g_list_append (display_x11->input_windows, iw); #ifndef XINPUT_NONE - /* Add enter window events to the event mask */ - /* this is not needed for XINPUT_NONE */ - gdk_window_set_events (window, - gdk_window_get_events (window) | - GDK_ENTER_NOTIFY_MASK); - - /* we might not receive ConfigureNotify so get the root_relative_geometry - * now, just in case */ - _gdk_input_get_root_relative_geometry (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XWINDOW (window), - &iw->root_x, &iw->root_y, NULL, NULL); + /* we might not receive ConfigureNotify so get the root_relative_geometry + * now, just in case */ + _gdk_input_get_root_relative_geometry (window, &iw->root_x, &iw->root_y); #endif /* !XINPUT_NONE */ + impl_window->input_window = iw; + } + + if (window_private->extension_events == 0) + iw->windows = g_list_append (iw->windows, window); + window_private->extension_events = mask; } else { - if (iw) - { - display_x11->input_windows = g_list_remove(display_x11->input_windows,iw); - g_free(iw); - } - - window_private->extension_events = 0; + unset_extension_events (window); } for (tmp_list = display_x11->input_devices; tmp_list; tmp_list = tmp_list->next) @@ -412,57 +437,14 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask, GdkDevicePrivate *gdkdev = tmp_list->data; if (!GDK_IS_CORE (gdkdev)) - { - if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED - && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL)) - _gdk_input_enable_window (window,gdkdev); - else - _gdk_input_disable_window (window,gdkdev); - } + _gdk_input_select_events ((GdkWindow *)impl_window, gdkdev); } } void _gdk_input_window_destroy (GdkWindow *window) { - GdkInputWindow *input_window; - GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window)); - - input_window = _gdk_input_window_find (window); - g_return_if_fail (input_window != NULL); - - display_x11->input_windows = g_list_remove (display_x11->input_windows, input_window); - g_free(input_window); -} - -void -_gdk_input_exit (void) -{ - GList *tmp_list; - GSList *display_list; - GdkDevicePrivate *gdkdev; - - for (display_list = _gdk_displays ; display_list ; display_list = display_list->next) - { - GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display_list->data); - - for (tmp_list = display_x11->input_devices; tmp_list; tmp_list = tmp_list->next) - { - gdkdev = (GdkDevicePrivate *)(tmp_list->data); - if (!GDK_IS_CORE (gdkdev)) - { - gdk_device_set_mode (&gdkdev->info, GDK_MODE_DISABLED); - g_object_unref(gdkdev); - } - } - - g_list_free(display_x11->input_devices); - - for (tmp_list = display_x11->input_windows; tmp_list; tmp_list = tmp_list->next) - g_free(tmp_list->data); - - g_list_free(display_x11->input_windows); - } + unset_extension_events (window); } /** @@ -471,10 +453,10 @@ _gdk_input_exit (void) * @axes: pointer to an array of axes * @use: the use to look for * @value: location to store the found value. - * + * * Interprets an array of double as axis values for a given device, * and locates the value in the array for a given axis use. - * + * * Return value: %TRUE if the given axis use was found, otherwise %FALSE **/ gboolean @@ -484,12 +466,12 @@ gdk_device_get_axis (GdkDevice *device, gdouble *value) { gint i; - + g_return_val_if_fail (device != NULL, FALSE); if (axes == NULL) return FALSE; - + for (i=0; inum_axes; i++) if (device->axes[i].use == use) { @@ -497,7 +479,7 @@ gdk_device_get_axis (GdkDevice *device, *value = axes[i]; return TRUE; } - + return FALSE; } diff --git a/gdk/x11/gdkinputprivate.h b/gdk/x11/gdkinputprivate.h index 5cbd809de..217e28c00 100644 --- a/gdk/x11/gdkinputprivate.h +++ b/gdk/x11/gdkinputprivate.h @@ -41,7 +41,6 @@ typedef struct _GdkAxisInfo GdkAxisInfo; typedef struct _GdkDevicePrivate GdkDevicePrivate; -typedef struct _GdkInputWindow GdkInputWindow; /* information about a device axis */ struct _GdkAxisInfo @@ -102,28 +101,25 @@ struct _GdkDeviceClass GObjectClass parent_class; }; +/* Addition used for extension_events mask */ +#define GDK_ALL_DEVICES_MASK (1<<30) + struct _GdkInputWindow { - /* gdk window */ - GdkWindow *window; + GList *windows; /* GdkWindow:s with extension_events set */ - /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */ - GdkExtensionMode mode; + /* gdk window */ + GdkWindow *impl_window; /* an impl window */ + GdkWindow *button_down_window; /* position relative to root window */ gint root_x; gint root_y; - /* rectangles relative to window of windows obscuring this one */ - GdkRectangle *obscuring; - gint num_obscuring; - /* Is there a pointer grab for this window ? */ gint grabbed; }; - - /* Global data */ #define GDK_IS_CORE(d) (((GdkDevice *)(d)) == ((GdkDevicePrivate *)(d))->display->core_pointer) @@ -139,18 +135,15 @@ void _gdk_init_input_core (GdkDisplay *display); /* The following functions are provided by each implementation * (xfree, gxi, and none) */ -gint _gdk_input_enable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev); -gint _gdk_input_disable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev); void _gdk_input_configure_event (XConfigureEvent *xevent, GdkWindow *window); -void _gdk_input_enter_event (XCrossingEvent *xevent, - GdkWindow *window); +void _gdk_input_crossing_event (GdkWindow *window, + gboolean enter); gboolean _gdk_input_other_event (GdkEvent *event, XEvent *xevent, GdkWindow *window); gint _gdk_input_grab_pointer (GdkWindow *window, + GdkWindow *native_window, gint owner_events, GdkEventMask event_mask, GdkWindow *confine_to, @@ -172,22 +165,18 @@ gint _gdk_input_common_init (GdkDisplay *display, gint include_core); GdkDevicePrivate * _gdk_input_find_device (GdkDisplay *display, guint32 id); -void _gdk_input_get_root_relative_geometry(Display *display, - Window w, +void _gdk_input_get_root_relative_geometry(GdkWindow *window, int *x_ret, - int *y_ret, - int *width_ret, - int *height_ret); -void _gdk_input_common_find_events (GdkWindow *window, - GdkDevicePrivate *gdkdev, + int *y_ret); +void _gdk_input_common_find_events (GdkDevicePrivate *gdkdev, gint mask, XEventClass *classes, int *num_classes); -void _gdk_input_common_select_events (GdkWindow *window, +void _gdk_input_select_events (GdkWindow *impl_window, GdkDevicePrivate *gdkdev); gint _gdk_input_common_other_event (GdkEvent *event, XEvent *xevent, - GdkInputWindow *input_window, + GdkWindow *window, GdkDevicePrivate *gdkdev); #endif /* !XINPUT_NONE */ diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index 41639c478..08c7cffb4 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -251,7 +251,8 @@ gdk_pointer_grab (GdkWindow * window, */ xevent_mask &= ~PointerMotionHintMask; - return_val = _gdk_input_grab_pointer (native, + return_val = _gdk_input_grab_pointer (window, + native, owner_events, event_mask, confine_to, diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index e29dc7b14..4d38fcbc4 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -1036,9 +1036,6 @@ _gdk_x11_window_destroy (GdkWindow *window, _gdk_selection_window_destroyed (window); - if (private->extension_events != 0) - _gdk_input_window_destroy (window); - toplevel = _gdk_x11_window_get_toplevel (window); if (toplevel) gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel); @@ -5585,6 +5582,8 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose; iface->queue_translation = _gdk_x11_window_queue_translation; iface->destroy = _gdk_x11_window_destroy; + iface->input_window_destroy = _gdk_input_window_destroy; + iface->input_window_crossing = _gdk_input_crossing_event; } #define __GDK_WINDOW_X11_C__