diff --git a/ChangeLog b/ChangeLog index 66a58476e..69be3d4c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2006-10-01 Elijah Newren + + 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 * 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 ccef49323..c7d807be9 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 d176acc17..0f1d82eef 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 &&