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.
This commit is contained in:
Axel Dörfler
2013-02-08 00:59:15 +01:00
parent d6bb64d848
commit 4db1a8c61d
2 changed files with 45 additions and 30 deletions
+42 -28
View File
@@ -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
+3 -2
View File
@@ -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);