[gtk+] Correctly set enter/leave events as detail=nonlinear
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gtk+] Correctly set enter/leave events as detail=nonlinear
- Date: Thu, 9 Jul 2009 15:08:02 +0000 (UTC)
commit 9044ec9bb9b1d08bd6674f17c7ea25fdbe3ac1ab
Author: Alexander Larsson <alexl redhat com>
Date: Thu Jul 9 16:48:22 2009 +0200
Correctly set enter/leave events as detail=nonlinear
If we get a nonlinear enter/leave notify on the toplevel we need
to set nonlinear in all the events we send, even if the in-toplevel
tree is linear.
This fixes combobox menus popping down immediately when you click
(not hold). (bug #587559)
gdk/gdkdisplay.c | 56 ++++++++++++++++----------------
gdk/gdkinternals.h | 19 ++++++-----
gdk/gdkwindow.c | 91 ++++++++++++++++++++++++++++-----------------------
gtk/gtkmenu.c | 50 ++++++++++++++++++++++++++++
4 files changed, 138 insertions(+), 78 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index d599ba7..399d193 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -856,26 +856,26 @@ synthesize_crossing_events (GdkDisplay *display,
gdk_window_get_pointer (dest_toplevel,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
- src_window,
- dest_window,
- crossing_mode,
- x, y, state,
- time,
- NULL,
- serial);
+ src_window,
+ dest_window,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial, FALSE);
}
else if (dest_toplevel == NULL)
{
gdk_window_get_pointer (src_toplevel,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
- src_window,
- NULL,
- crossing_mode,
- x, y, state,
- time,
- NULL,
- serial);
+ src_window,
+ NULL,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial, FALSE);
}
else
{
@@ -883,23 +883,23 @@ synthesize_crossing_events (GdkDisplay *display,
gdk_window_get_pointer (src_toplevel,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
- src_window,
- NULL,
- crossing_mode,
- x, y, state,
- time,
- NULL,
- serial);
+ src_window,
+ NULL,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial, FALSE);
gdk_window_get_pointer (dest_toplevel,
&x, &y, &state);
_gdk_synthesize_crossing_events (display,
- NULL,
- dest_window,
- crossing_mode,
- x, y, state,
- time,
- NULL,
- serial);
+ NULL,
+ dest_window,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial, FALSE);
}
}
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index c984386..6d1a4d0 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -628,15 +628,16 @@ GdkEvent * _gdk_make_event (GdkWindow *window,
gboolean before_event);
void _gdk_synthesize_crossing_events (GdkDisplay *display,
- GdkWindow *src,
- GdkWindow *dest,
- GdkCrossingMode mode,
- gint toplevel_x,
- gint toplevel_y,
- GdkModifierType mask,
- guint32 time_,
- GdkEvent *event_in_queue,
- gulong serial);
+ GdkWindow *src,
+ GdkWindow *dest,
+ GdkCrossingMode mode,
+ gint toplevel_x,
+ gint toplevel_y,
+ GdkModifierType mask,
+ guint32 time_,
+ GdkEvent *event_in_queue,
+ gulong serial,
+ gboolean non_linear);
void _gdk_display_set_window_under_pointer (GdkDisplay *display,
GdkWindow *window);
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index bd253c7..dd7df89 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -8494,20 +8494,20 @@ send_crossing_event (GdkDisplay *display,
*/
void
_gdk_synthesize_crossing_events (GdkDisplay *display,
- GdkWindow *src,
- GdkWindow *dest,
- GdkCrossingMode mode,
- gint toplevel_x,
- gint toplevel_y,
- GdkModifierType mask,
- guint32 time_,
- GdkEvent *event_in_queue,
- gulong serial)
+ GdkWindow *src,
+ GdkWindow *dest,
+ GdkCrossingMode mode,
+ gint toplevel_x,
+ gint toplevel_y,
+ GdkModifierType mask,
+ guint32 time_,
+ GdkEvent *event_in_queue,
+ gulong serial,
+ gboolean non_linear)
{
GdkWindowObject *c;
GdkWindowObject *win, *last, *next;
GList *path, *list;
- gboolean non_linear;
GdkWindowObject *a;
GdkWindowObject *b;
GdkWindowObject *toplevel;
@@ -8522,7 +8522,7 @@ _gdk_synthesize_crossing_events (GdkDisplay *display,
c = find_common_ancestor (a, b);
- non_linear = (c != a) && (c != b);
+ non_linear |= (c != a) && (c != b);
if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
{
@@ -8821,15 +8821,16 @@ do_synthesize_crossing_event (gpointer data)
display->pointer_info.window_under_pointer)
{
_gdk_synthesize_crossing_events (display,
- display->pointer_info.window_under_pointer,
- new_window_under_pointer,
- GDK_CROSSING_NORMAL,
- display->pointer_info.toplevel_x,
- display->pointer_info.toplevel_y,
- display->pointer_info.state,
- GDK_CURRENT_TIME,
- NULL,
- serial);
+ display->pointer_info.window_under_pointer,
+ new_window_under_pointer,
+ GDK_CROSSING_NORMAL,
+ display->pointer_info.toplevel_x,
+ display->pointer_info.toplevel_y,
+ display->pointer_info.state,
+ GDK_CURRENT_TIME,
+ NULL,
+ serial,
+ FALSE);
_gdk_display_set_window_under_pointer (display, new_window_under_pointer);
}
}
@@ -8939,6 +8940,7 @@ proxy_pointer_event (GdkDisplay *display,
guint state;
gdouble toplevel_x, toplevel_y;
guint32 time_;
+ gboolean non_linear;
event_window = source_event->any.window;
gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
@@ -8948,6 +8950,12 @@ proxy_pointer_event (GdkDisplay *display,
toplevel_x, toplevel_y,
&toplevel_x, &toplevel_y);
+ non_linear = FALSE;
+ if ((source_event->type == GDK_LEAVE_NOTIFY ||
+ source_event->type == GDK_ENTER_NOTIFY) &&
+ (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
+ source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
+ non_linear = TRUE;
/* If we get crossing events with subwindow unexpectedly being NULL
that means there is a native subwindow that gdk doesn't know about.
@@ -8968,13 +8976,14 @@ proxy_pointer_event (GdkDisplay *display,
/* Send leave events from window under pointer to event window
that will get the subwindow == NULL window */
_gdk_synthesize_crossing_events (display,
- display->pointer_info.window_under_pointer,
- event_window,
- source_event->crossing.mode,
- toplevel_x, toplevel_y,
- state, time_,
- source_event,
- serial);
+ display->pointer_info.window_under_pointer,
+ event_window,
+ source_event->crossing.mode,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial,
+ non_linear);
/* Send subwindow == NULL event */
send_crossing_event (display,
@@ -9020,13 +9029,13 @@ proxy_pointer_event (GdkDisplay *display,
/* Send enter events from event window to pointer_window */
_gdk_synthesize_crossing_events (display,
- event_window,
- pointer_window,
- source_event->crossing.mode,
- toplevel_x, toplevel_y,
- state, time_,
- source_event,
- serial);
+ event_window,
+ pointer_window,
+ source_event->crossing.mode,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial, non_linear);
_gdk_display_set_window_under_pointer (display, pointer_window);
return TRUE;
}
@@ -9038,13 +9047,13 @@ proxy_pointer_event (GdkDisplay *display,
/* Different than last time, send crossing events */
_gdk_synthesize_crossing_events (display,
- display->pointer_info.window_under_pointer,
- pointer_window,
- GDK_CROSSING_NORMAL,
- toplevel_x, toplevel_y,
- state, time_,
- source_event,
- serial);
+ display->pointer_info.window_under_pointer,
+ pointer_window,
+ GDK_CROSSING_NORMAL,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial, non_linear);
_gdk_display_set_window_under_pointer (display, pointer_window);
}
else if (source_event->type == GDK_MOTION_NOTIFY)
diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c
index 0fd5d3d..98aeb21 100644
--- a/gtk/gtkmenu.c
+++ b/gtk/gtkmenu.c
@@ -3792,6 +3792,47 @@ gtk_menu_handle_scrolling (GtkMenu *menu,
}
}
+static char *mode[] = {
+ "GDK_CROSSING_NORMAL",
+ "GDK_CROSSING_GRAB",
+ "GDK_CROSSING_UNGRAB",
+ "GDK_CROSSING_GTK_GRAB",
+ "GDK_CROSSING_GTK_UNGRAB",
+ "GDK_CROSSING_STATE_CHANGED",
+ NULL
+};
+
+static char *detail[] = {
+ "GDK_NOTIFY_ANCESTOR",
+ "GDK_NOTIFY_VIRTUAL",
+ "GDK_NOTIFY_INFERIOR",
+ "GDK_NOTIFY_NONLINEAR",
+ "GDK_NOTIFY_NONLINEAR_VIRTUAL",
+ "GDK_NOTIFY_UNKNOWN",
+ NULL
+};
+
+char *
+get_window_name (GtkWidget *widget, GdkWindow *window)
+{
+ GtkMenu *menu;
+ gpointer w;
+ menu = GTK_MENU (widget);
+
+ if (window == widget->window)
+ return "widget->window";
+
+ if (window == menu->view_window)
+ return "menu->view_window";
+
+ if (window == menu->bin_window)
+ return "menu->bin_window";
+
+ gdk_window_get_user_data (window, &w);
+
+ return g_type_name_from_instance (w);
+}
+
static gboolean
gtk_menu_enter_notify (GtkWidget *widget,
GdkEventCrossing *event)
@@ -3804,6 +3845,10 @@ gtk_menu_enter_notify (GtkWidget *widget,
event->mode == GDK_CROSSING_STATE_CHANGED)
return TRUE;
+ g_print ("menu ENTER notify for %s mode: %s, detail %s\n",
+ get_window_name (widget, event->window),
+ mode[event->mode], detail[event->detail]);
+
g_object_get (gtk_widget_get_settings (widget),
"gtk-touchscreen-mode", &touchscreen_mode,
NULL);
@@ -3846,6 +3891,7 @@ gtk_menu_enter_notify (GtkWidget *widget,
* far enough away from the enter point. (see
* gtk_menu_motion_notify())
*/
+ g_print ("user-enter, not pop-under\n");
menu_shell->activate_time = 0;
}
}
@@ -3880,6 +3926,10 @@ gtk_menu_leave_notify (GtkWidget *widget,
event->mode == GDK_CROSSING_STATE_CHANGED)
return TRUE;
+ g_print ("menu LEAVE notify for %s mode: %s, detail %s\n",
+ get_window_name (widget, event->window),
+ mode[event->mode], detail[event->detail]);
+
menu = GTK_MENU (widget);
menu_shell = GTK_MENU_SHELL (widget);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]