From 4db1a8c61d68370bc8cccadcb8793679774a7426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 8 Feb 2013 00:54:33 +0100 Subject: [PATCH] app_server: reworked SetFocusWindow() logic a bit. * The normal mouse mode now only uses the window that had focus last if that window is one that does not support to be the front window (such as the desktop). * This should keep the logic of r41264 without the drawbacks (see #7280 for more information). * Added _WindowCanHaveFocus() method. * This should fix #7630. --- src/servers/app/Desktop.cpp | 70 ++++++++++++++++++++++--------------- src/servers/app/Desktop.h | 5 +-- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index 845414aad1..76c8084eef 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2011, Haiku. + * Copyright 2001-2013, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -1017,7 +1017,7 @@ Desktop::RemoveWorkspacesView(WorkspacesView* view) void Desktop::SelectWindow(Window* window) { - if (fSettings->MouseMode() == B_CLICK_TO_FOCUS_MOUSE) { + if (fSettings->ClickToFocusMouse()) { // Only bring the window to front when it is not the window under the // mouse pointer. This should result in sensible behaviour. if (window != fWindowUnderMouse @@ -1201,9 +1201,9 @@ Desktop::SendWindowBehind(Window* window, Window* behindOf, bool sendStack) } _UpdateFronts(); - if (fSettings->MouseMode() == B_FOCUS_FOLLOWS_MOUSE) + if (fSettings->FocusFollowsMouse()) SetFocusWindow(WindowAt(fLastMousePosition)); - else if (fSettings->MouseMode() == B_NORMAL_MOUSE) + else if (fSettings->NormalMouse()) SetFocusWindow(NULL); bool sendFakeMouseMoved = false; @@ -1868,24 +1868,24 @@ Desktop::KeyboardEventTarget() is any window at all, that is. */ void -Desktop::SetFocusWindow(Window* focus) +Desktop::SetFocusWindow(Window* nextFocus) { if (!LockAllWindows()) return; // test for B_LOCK_WINDOW_FOCUS - if (fLockedFocusWindow && focus != fLockedFocusWindow) { + if (fLockedFocusWindow && nextFocus != fLockedFocusWindow) { UnlockAllWindows(); return; } - bool hasModal = _WindowHasModal(focus); + bool hasModal = _WindowHasModal(nextFocus); bool hasWindowScreen = false; - if (!hasModal && focus != NULL) { + if (!hasModal && nextFocus != NULL) { // Check whether or not a window screen is in front of the window // (if it has a modal, the right thing is done, anyway) - Window* window = focus; + Window* window = nextFocus; while (true) { window = window->NextWindow(fCurrentWorkspace); if (window == NULL || window->Feel() == kWindowScreenFeel) @@ -1895,35 +1895,36 @@ Desktop::SetFocusWindow(Window* focus) hasWindowScreen = true; } - if (focus == fFocus && focus != NULL && !focus->IsHidden() - && (focus->Flags() & B_AVOID_FOCUS) == 0 + if (nextFocus == fFocus && nextFocus != NULL && !nextFocus->IsHidden() + && (nextFocus->Flags() & B_AVOID_FOCUS) == 0 && !hasModal && !hasWindowScreen) { // the window that is supposed to get focus already has focus UnlockAllWindows(); return; } - uint32 list = /*fCurrentWorkspace; - if (fSettings->FocusFollowsMouse()) - list = */kFocusList; + uint32 list = fCurrentWorkspace; + if (!fSettings->NormalMouse()) + list = kFocusList; - if (focus == NULL || hasModal || hasWindowScreen) { - /*if (!fSettings->FocusFollowsMouse()) - focus = CurrentWindows().LastWindow(); - else*/ - focus = fFocusList.LastWindow(); + if (nextFocus == NULL || hasModal || hasWindowScreen) { + nextFocus = _Windows(list).LastWindow(); + + if (fSettings->NormalMouse()) { + // If the last window having focus is a window that cannot make it + // to the front, we use that as the next focus + Window* lastFocus = fFocusList.LastWindow(); + if (!lastFocus->SupportsFront() && _WindowCanHaveFocus(lastFocus)) + nextFocus = lastFocus; + } } // make sure no window is chosen that doesn't want focus or cannot have it - while (focus != NULL - && (!focus->InWorkspace(fCurrentWorkspace) - || (focus->Flags() & B_AVOID_FOCUS) != 0 - || _WindowHasModal(focus) - || focus->IsHidden())) { - focus = focus->PreviousWindow(list); + while (nextFocus != NULL && !_WindowCanHaveFocus(nextFocus)) { + nextFocus = nextFocus->PreviousWindow(list); } - if (fFocus == focus) { + if (fFocus == nextFocus) { // turns out the window that is supposed to get focus now already has it UnlockAllWindows(); return; @@ -1937,7 +1938,7 @@ Desktop::SetFocusWindow(Window* focus) oldActiveApp = fFocus->ServerWindow()->App()->ClientTeam(); } - fFocus = focus; + fFocus = nextFocus; if (fFocus != NULL) { fFocus->SetFocus(true); @@ -2811,7 +2812,7 @@ Desktop::_UpdateFronts(bool updateFloating) bool -Desktop::_WindowHasModal(Window* window) +Desktop::_WindowHasModal(Window* window) const { if (window == NULL) return false; @@ -2830,6 +2831,19 @@ Desktop::_WindowHasModal(Window* window) } +/*! Determines whether or not the specified \a window can have focus at all. +*/ +bool +Desktop::_WindowCanHaveFocus(Window* window) const +{ + return window != NULL + && window->InWorkspace(fCurrentWorkspace) + && (window->Flags() & B_AVOID_FOCUS) == 0 + && !_WindowHasModal(window) + && !window->IsHidden(); +} + + /*! You must at least hold a single window lock when calling this method. */ void diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index daa6f78c4b..5c7b565233 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2010, Haiku. + * Copyright 2001-2013, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -265,7 +265,8 @@ private: void _UpdateBack(); void _UpdateFront(bool updateFloating = true); void _UpdateFronts(bool updateFloating = true); - bool _WindowHasModal(Window* window); + bool _WindowHasModal(Window* window) const; + bool _WindowCanHaveFocus(Window* window) const; void _WindowChanged(Window* window); void _WindowRemoved(Window* window);