summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--doc/how-to-get-focus-right.txt15
-rw-r--r--src/display.c79
3 files changed, 59 insertions, 51 deletions
diff --git a/ChangeLog b/ChangeLog
index 66a5847..69be3d4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2006-10-01 Elijah Newren <newren gmail com>
+
+ Fix longstanding focus bug with mouse (not sloppy) focus mode with
+ popup override-redirect windows, particularly mozilla and
+ firefox's location bar autocompletion. #357695.
+
+ * src/display.c (event_callback -- EnterNotify & LeaveNotify events):
+ for mouse focus, defocus the focused window when the mouse enters
+ the desktop window rather than when the mouse leaves the focused
+ window.
+
+ * doc/how-to-get-focus-right.txt:
+ update for the slightly nuanced definition of mouse focus (people
+ without a DESKTOP window like nautilus get sloppy focus behavior
+ now)
+
2006-09-27 Elijah Newren <newren gmail com>
* src/menu.c (var menuitems): Patch from Bruno Boaventura to add
diff --git a/doc/how-to-get-focus-right.txt b/doc/how-to-get-focus-right.txt
index ccef493..c7d807b 100644
--- a/doc/how-to-get-focus-right.txt
+++ b/doc/how-to-get-focus-right.txt
@@ -9,7 +9,8 @@ basics are easy:
Focus method Behavior
click When a user clicks on a window, focus it
sloppy When an EnterNotify is received, focus the window
- mouse Same as sloppy, but also defocus on LeaveNotify
+ mouse Same as sloppy, but also defocus when mouse enters DESKTOP
+ window
Note that these choices (along with the choice that clicking on a
window raises it for the click focus method) introduces the following
@@ -20,8 +21,9 @@ Focus method Invariant
sloppy If the mouse is in a window, then it is focused; if the
mouse is not in a window, then the most recently used
window is focused.
- mouse If the mouse is in a window, then it is focused; otherwise,
- the designated "no_focus_window" is focused
+
+ mouse If the mouse is in a non-DESKTOP window, then it is focused;
+ otherwise, the designated "no_focus_window" is focused
However, there are a number of cases where the current focus window
becomes invalid and another should be chosen. Some examples are when
@@ -34,8 +36,10 @@ Focus method Behavior
on top)
sloppy Focus the window containing the pointer if there is such
a window, otherwise focus the most recently used window.
- mouse Focus the window containing the pointer if there is one,
- otherwise focus the designated "no_focus_window".
+
+ mouse Focus the non-DESKTOP window containing the pointer if
+ there is one, otherwise focus the designated
+ "no_focus_window".
Note that "most recently used window", as used here, has a slightly
different connotation than "most recent to have keyboard focus". This
@@ -123,6 +127,7 @@ To read more about the bugs that inspired these choices:
- Mousenav vs. Keynav in mouse and sloppy focus modes
http://bugzilla.gnome.org/show_bug.cgi?id=167545
http://bugzilla.gnome.org/show_bug.cgi?id=101190
+ http://bugzilla.gnome.org/show_bug.cgi?id=357695
- Not focusing panels
http://bugzilla.gnome.org/show_bug.cgi?id=160470
http://bugzilla.gnome.org/show_bug.cgi?id=120100
diff --git a/src/display.c b/src/display.c
index d176acc..0f1d82e 100644
--- a/src/display.c
+++ b/src/display.c
@@ -1847,6 +1847,7 @@ event_callback (XEvent *event,
{
case META_FOCUS_MODE_SLOPPY:
case META_FOCUS_MODE_MOUSE:
+ display->mouse_mode = TRUE;
if (window->type != META_WINDOW_DOCK &&
window->type != META_WINDOW_DESKTOP)
{
@@ -1858,21 +1859,41 @@ event_callback (XEvent *event,
event->xany.serial,
event->xcrossing.time);
- display->mouse_mode = TRUE;
meta_window_focus (window, event->xcrossing.time);
- /* stop ignoring stuff */
- reset_ignores (display);
-
- if (meta_prefs_get_auto_raise ())
- {
+ /* stop ignoring stuff */
+ reset_ignores (display);
+
+ if (meta_prefs_get_auto_raise ())
+ {
meta_display_queue_autoraise_callback (display, window);
- }
- else
- {
- meta_topic (META_DEBUG_FOCUS,
- "Auto raise is disabled\n");
- }
+ }
+ else
+ {
+ meta_topic (META_DEBUG_FOCUS,
+ "Auto raise is disabled\n");
+ }
+ }
+ /* In mouse focus mode, we defocus when the mouse *enters*
+ * the DESKTOP window, instead of defocusing on LeaveNotify.
+ * This is because having the mouse enter override-redirect
+ * child windows unfortunately causes LeaveNotify events that
+ * we can't distinguish from the mouse actually leaving the
+ * toplevel window as we expect. But, since we filter out
+ * EnterNotify events on override-redirect windows, this
+ * alternative mechanism works great.
+ */
+ if (window->type == META_WINDOW_DESKTOP &&
+ meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE &&
+ display->expected_focus_window != NULL)
+ {
+ meta_topic (META_DEBUG_FOCUS,
+ "Unsetting focus from %s due to mouse entering "
+ "the DESKTOP window\n",
+ display->expected_focus_window->desc);
+ meta_display_focus_the_no_focus_window (display,
+ window->screen,
+ event->xcrossing.time);
}
break;
case META_FOCUS_MODE_CLICK:
@@ -1890,40 +1911,6 @@ event_callback (XEvent *event,
meta_window_handle_mouse_grab_op_event (window, event);
else if (window != NULL)
{
- switch (meta_prefs_get_focus_mode ())
- {
- case META_FOCUS_MODE_MOUSE:
- if ((window->frame == NULL || frame_was_receiver) &&
- event->xcrossing.mode != NotifyGrab &&
- event->xcrossing.mode != NotifyUngrab &&
- event->xcrossing.detail != NotifyInferior &&
- meta_display_focus_sentinel_clear (display))
- {
- if (window == display->expected_focus_window)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Unsetting focus from %s due to LeaveNotify\n",
- window->desc);
- meta_display_focus_the_no_focus_window (display,
- window->screen,
- event->xcrossing.time);
- }
- if (window->type != META_WINDOW_DOCK &&
- window->type != META_WINDOW_DESKTOP)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Setting display->mouse_mode to TRUE due to "
- "LeaveNotify at time %lu.\n",
- event->xcrossing.time);
- display->mouse_mode = TRUE;
- }
- }
- break;
- case META_FOCUS_MODE_SLOPPY:
- case META_FOCUS_MODE_CLICK:
- break;
- }
-
if (window->type == META_WINDOW_DOCK &&
event->xcrossing.mode != NotifyGrab &&
event->xcrossing.mode != NotifyUngrab &&