mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 10:50:10 +00:00
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)
This commit is contained in:
parent
8031432c09
commit
9044ec9bb9
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user