From 787d603e12de38f6ab06bffa3d9b4d2d714cc7a1 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Thu, 5 May 2005 00:09:43 +0000 Subject: [PATCH] Fix a bug in focus tracking when we move between has_pointer_focus and 2005-05-04 Owen Taylor * gdk/x11/gdkevents-x11.c gdk/x11/gdkwindow-x11.h: Fix a bug in focus tracking when we move between has_pointer_focus and has_focus_window directly. (#109246, Billy Biggs, Niko Tyni and others) * gdk/x11/gdkevents-x11.c: Also fix some extremely confusion that could happen in the case of no window manager + keyboard grabs, by moving to a more consistent model of when we pay attention to mode=NotifyGrab/NotifyUngrab events. --- ChangeLog | 12 ++++++ ChangeLog.pre-2-10 | 12 ++++++ ChangeLog.pre-2-8 | 12 ++++++ gdk/x11/gdkevents-x11.c | 84 ++++++++++++++++++++++++++++++----------- gdk/x11/gdkwindow-x11.h | 11 ++++-- 5 files changed, 105 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 220db5e157..870e4a9de6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-05-04 Owen Taylor + + * gdk/x11/gdkevents-x11.c gdk/x11/gdkwindow-x11.h: Fix a bug + in focus tracking when we move between has_pointer_focus and + has_focus_window directly. (#109246, Billy Biggs, Niko Tyni + and others) + + * gdk/x11/gdkevents-x11.c: Also fix some extremely confusion + that could happen in the case of no window manager + keyboard grabs, + by moving to a more consistent model of when we pay attention + to mode=NotifyGrab/NotifyUngrab events. + 2005-05-02 Federico Mena Quintero * tests/testfilechooser.c: Oops, remove mtrace() stuff. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 220db5e157..870e4a9de6 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,15 @@ +2005-05-04 Owen Taylor + + * gdk/x11/gdkevents-x11.c gdk/x11/gdkwindow-x11.h: Fix a bug + in focus tracking when we move between has_pointer_focus and + has_focus_window directly. (#109246, Billy Biggs, Niko Tyni + and others) + + * gdk/x11/gdkevents-x11.c: Also fix some extremely confusion + that could happen in the case of no window manager + keyboard grabs, + by moving to a more consistent model of when we pay attention + to mode=NotifyGrab/NotifyUngrab events. + 2005-05-02 Federico Mena Quintero * tests/testfilechooser.c: Oops, remove mtrace() stuff. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 220db5e157..870e4a9de6 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,15 @@ +2005-05-04 Owen Taylor + + * gdk/x11/gdkevents-x11.c gdk/x11/gdkwindow-x11.h: Fix a bug + in focus tracking when we move between has_pointer_focus and + has_focus_window directly. (#109246, Billy Biggs, Niko Tyni + and others) + + * gdk/x11/gdkevents-x11.c: Also fix some extremely confusion + that could happen in the case of no window manager + keyboard grabs, + by moving to a more consistent model of when we pay attention + to mode=NotifyGrab/NotifyUngrab events. + 2005-05-02 Federico Mena Quintero * tests/testfilechooser.c: Oops, remove mtrace() stuff. diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index f3327fadcb..7cc35187ca 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -1218,16 +1218,19 @@ gdk_event_translate (GdkDisplay *display, } /* Handle focusing (in the case where no window manager is running */ - if (toplevel && - xevent->xcrossing.detail != NotifyInferior && - xevent->xcrossing.focus && !toplevel->has_focus_window) + if (toplevel && xevent->xcrossing.detail != NotifyInferior) { - gboolean had_focus = HAS_FOCUS (toplevel); + toplevel->has_pointer = TRUE; - toplevel->has_pointer_focus = TRUE; - - if (HAS_FOCUS (toplevel) != had_focus) - generate_focus_event (window, TRUE); + if (xevent->xcrossing.focus && !toplevel->has_focus_window) + { + gboolean had_focus = HAS_FOCUS (toplevel); + + toplevel->has_pointer_focus = TRUE; + + if (HAS_FOCUS (toplevel) != had_focus) + generate_focus_event (window, TRUE); + } } /* Tell XInput stuff about it if appropriate */ @@ -1312,16 +1315,19 @@ gdk_event_translate (GdkDisplay *display, } /* Handle focusing (in the case where no window manager is running */ - if (toplevel && - xevent->xcrossing.detail != NotifyInferior && - xevent->xcrossing.focus && !toplevel->has_focus_window) + if (toplevel && xevent->xcrossing.detail != NotifyInferior) { - gboolean had_focus = HAS_FOCUS (toplevel); - - toplevel->has_pointer_focus = FALSE; - - if (HAS_FOCUS (toplevel) != had_focus) - generate_focus_event (window, FALSE); + toplevel->has_pointer = FALSE; + + if (xevent->xcrossing.focus && !toplevel->has_focus_window) + { + gboolean had_focus = HAS_FOCUS (toplevel); + + toplevel->has_pointer_focus = FALSE; + + if (HAS_FOCUS (toplevel) != had_focus) + generate_focus_event (window, FALSE); + } } event->crossing.type = GDK_LEAVE_NOTIFY; @@ -1404,10 +1410,25 @@ gdk_event_translate (GdkDisplay *display, switch (xevent->xfocus.detail) { case NotifyAncestor: - case NotifyNonlinear: case NotifyVirtual: + /* When the focus moves from an ancestor of the window to + * the window or a descendent of the window, *and* the + * pointer is inside the window, then we were previously + * receiving keystroke events in the has_pointer_focus + * case and are now receiving them in the + * has_focus_window case. + */ + if (toplevel->has_pointer && + xevent->xfocus.mode != NotifyGrab && + xevent->xfocus.mode != NotifyUngrab) + toplevel->has_pointer_focus = FALSE; + + /* fall through */ + case NotifyNonlinear: case NotifyNonlinearVirtual: - toplevel->has_focus_window = TRUE; + if (xevent->xfocus.mode != NotifyGrab && + xevent->xfocus.mode != NotifyUngrab) + toplevel->has_focus_window = TRUE; /* We pretend that the focus moves to the grab * window, so we pay attention to NotifyGrab * NotifyUngrab, and ignore NotifyWhileGrabbed @@ -1420,7 +1441,8 @@ gdk_event_translate (GdkDisplay *display, * but the pointer focus is ignored while a * grab is in effect */ - if (xevent->xfocus.mode != NotifyGrab) + if (xevent->xfocus.mode != NotifyGrab && + xevent->xfocus.mode != NotifyUngrab) toplevel->has_pointer_focus = TRUE; break; case NotifyInferior: @@ -1447,15 +1469,31 @@ gdk_event_translate (GdkDisplay *display, switch (xevent->xfocus.detail) { case NotifyAncestor: - case NotifyNonlinear: case NotifyVirtual: + /* When the focus moves from the window or a descendent + * of the window to an ancestor of the window, *and* the + * pointer is inside the window, then we were previously + * receiving keystroke events in the has_focus_window + * case and are now receiving them in the + * has_pointer_focus case. + */ + if (toplevel->has_pointer && + xevent->xfocus.mode != NotifyGrab && + xevent->xfocus.mode != NotifyUngrab) + toplevel->has_pointer_focus = TRUE; + + /* fall through */ + case NotifyNonlinear: case NotifyNonlinearVirtual: - toplevel->has_focus_window = FALSE; + if (xevent->xfocus.mode != NotifyGrab && + xevent->xfocus.mode != NotifyUngrab) + toplevel->has_focus_window = FALSE; if (xevent->xfocus.mode != NotifyWhileGrabbed) toplevel->has_focus = FALSE; break; case NotifyPointer: - if (xevent->xfocus.mode != NotifyUngrab) + if (xevent->xfocus.mode != NotifyGrab && + xevent->xfocus.mode != NotifyUngrab) toplevel->has_pointer_focus = FALSE; break; case NotifyInferior: diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index 608c0172c8..f95505aaff 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -96,9 +96,14 @@ struct _GdkToplevelX11 */ guint has_focus : 1; - /* Set if !window->has_focus_window, but events are being sent to the - * window because the pointer is in it. (Typically, no window - * manager is running. + /* Set if the pointer is inside this window. (This is needed for + * for focus tracking) + */ + guint has_pointer : 1; + + /* Set if the window is a descendent of the focus window and the pointer is + * inside it. (This is the case where the window will receive keystroke + * events even window->has_focus_window is FALSE) */ guint has_pointer_focus : 1;