From 53511cb65312133777f8a77b78aa82f0f4210fb3 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 4 Feb 2009 11:22:54 +0100 Subject: [PATCH] Enable custom event masks for native windows Some apps really need to set custom event masks on native child windows, for example emacs sets the event masks with gdk, but then reads out the raw X events via a filter, so gdk event emulation doesn't work for that. When we get motion or button events we map back from the event position and window to the toplevel before doing anything, because a toplevel native window could e.g. overlap a child window or whatever. --- gdk/gdkwindow.c | 66 ++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index aa96c072fd..57d3fe35d3 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -746,17 +746,30 @@ find_native_sibling_above (GdkWindowObject *parent, static GdkEventMask get_native_event_mask (GdkWindowObject *private) { - if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT) - return - GDK_EXPOSURE_MASK | - GDK_POINTER_MOTION_MASK | - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | - GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | - GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | - GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SCROLL_MASK; + if (private->window_type != GDK_WINDOW_ROOT && + private->window_type != GDK_WINDOW_FOREIGN) + { + return + /* We need thse for all native window so we can emulate + events on children: */ + GDK_EXPOSURE_MASK | + GDK_POINTER_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | + GDK_SCROLL_MASK | + /* Then do whatever the app asks to, since the app + * may be asking for weird things for native windows, + * but filter out things that override the above + * requests somehow. */ + (private->event_mask & + ~(GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_MOTION_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON2_MOTION_MASK | + GDK_BUTTON3_MOTION_MASK)); + } else - return GDK_EXPOSURE_MASK; + return private->event_mask; } /** @@ -5839,6 +5852,11 @@ gdk_window_set_events (GdkWindow *window, _gdk_display_enable_motion_hints (display); private->event_mask = event_mask; + + if (gdk_window_has_impl (private)) + GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, + get_native_event_mask (private)); + } /** @@ -8425,7 +8443,7 @@ static gboolean proxy_button_event (GdkEvent *source_event, gulong serial) { - GdkWindow *toplevel_window; + GdkWindow *toplevel_window, *event_window; GdkWindow *event_win; GdkWindow *pointer_window; GdkEvent *event; @@ -8437,11 +8455,14 @@ proxy_button_event (GdkEvent *source_event, GdkWindowObject *w; type = source_event->any.type; - toplevel_window = source_event->any.window; + event_window = source_event->any.window; gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y); gdk_event_get_state (source_event, &state); time_ = gdk_event_get_time (source_event); display = gdk_drawable_get_display (source_event->any.window); + toplevel_window = convert_coords_to_toplevel (event_window, + toplevel_x, toplevel_y, + &toplevel_x, &toplevel_y); if (type == GDK_BUTTON_PRESS && _gdk_display_has_pointer_grab (display, serial) == NULL) @@ -8626,27 +8647,6 @@ _gdk_windowing_got_event (GdkDisplay *display, event_private->parent == NULL || GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT; - if (!is_toplevel && - (event->type != GDK_ENTER_NOTIFY && event->type != GDK_LEAVE_NOTIFY)) - { - GEnumValue *event_type_value, *window_type_value; - - if (GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_FOREIGN) - return; - - event_type_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (GDK_TYPE_EVENT_TYPE), - event->type); - window_type_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (GDK_TYPE_WINDOW_TYPE), - event_private->window_type); - - /* We should only get these events on toplevel windows */ - g_warning ("got unexpected event of type %s on non-toplevel window (gtype %s, type %d)", - event_type_value->value_name, - window_type_value->value_name, - GDK_WINDOW_TYPE (event_window)); - return; - } - if ((event->type == GDK_ENTER_NOTIFY || event->type == GDK_LEAVE_NOTIFY) && (event->crossing.mode == GDK_CROSSING_GRAB ||