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);