Some work to get modal/floating windows back:

* B_{FLOATING|MODAL}_ALL_WINDOW_FEEL now works as expected
* reintroduced the concepts of subsets of modal/floating windows - does only
  work correctly for subset "all" window feels.
* RootLayer::_SetFront() now deals correctly with modal windows
* renamed RootLayer *WindowLayer() methods to *Window()


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15282 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-12-02 15:06:14 +00:00
parent f5e1f2163f
commit 48ccf5abef
5 changed files with 171 additions and 70 deletions
+4 -4
View File
@@ -626,7 +626,7 @@ Desktop::ShowWindow(WindowLayer* window)
return; return;
} }
fRootLayer->ShowWindowLayer(window); fRootLayer->ShowWindow(window);
// If the mouse cursor is directly over the newly visible window, // If the mouse cursor is directly over the newly visible window,
// we'll send a fake mouse moved message to the window, so that // we'll send a fake mouse moved message to the window, so that
@@ -659,7 +659,7 @@ Desktop::HideWindow(WindowLayer* window)
return; return;
} }
fRootLayer->HideWindowLayer(window); fRootLayer->HideWindow(window);
} }
@@ -692,7 +692,7 @@ Desktop::_ChangeWindowWorkspaces(WindowLayer* window, uint32 oldWorkspaces,
// window is on this workspace, is it anymore? // window is on this workspace, is it anymore?
if (!workspaces_on_workspace(i, newWorkspaces)) { if (!workspaces_on_workspace(i, newWorkspaces)) {
if (i == CurrentWorkspace()) if (i == CurrentWorkspace())
RootLayer()->RemoveWindowLayer(window); RootLayer()->RemoveWindow(window);
else else
fWorkspaces[i].RemoveWindow(window); fWorkspaces[i].RemoveWindow(window);
} }
@@ -700,7 +700,7 @@ Desktop::_ChangeWindowWorkspaces(WindowLayer* window, uint32 oldWorkspaces,
// window was not on this workspace, is it now? // window was not on this workspace, is it now?
if (workspaces_on_workspace(i, newWorkspaces)) { if (workspaces_on_workspace(i, newWorkspaces)) {
if (i == CurrentWorkspace()) if (i == CurrentWorkspace())
RootLayer()->AddWindowLayer(window); RootLayer()->AddWindow(window);
else else
fWorkspaces[i].AddWindow(window); fWorkspaces[i].AddWindow(window);
} }
+86 -41
View File
@@ -205,29 +205,73 @@ RootLayer::SetFocus(WindowLayer* focus)
} }
/*!
\brief Tries to move the specified window to the front of the screen.
If there are any modal windows on this screen, it might not actually
become the frontmost window, though, as modal windows stay in front
of their subset.
*/
void void
RootLayer::_SetFront(WindowLayer* windowLayer, BRegion& update) RootLayer::_SetFront(WindowLayer* window, BRegion& update)
{ {
if (windowLayer == NULL) { if (window == NULL) {
fBack = NULL; fBack = NULL;
fFront = NULL; fFront = NULL;
return; return;
} }
if (!windowLayer->SupportsFront() && fFront != NULL) if (!window->SupportsFront() && fFront != NULL)
return; return;
BRegion previous = windowLayer->FullVisible(); BRegion previous = window->FullVisible();
WindowLayer* frontmost = window->Frontmost();
_RemoveChildFromList(windowLayer); _RemoveChildFromList(window);
_AddChildToList(windowLayer);
windowLayer->GetOnScreenRegion(update); if (frontmost != NULL && frontmost->IsModal()) {
// all modal windows follow their subsets to the front
// (ie. they are staying in front of them, but they are
// not supposed to change their order because of that)
WindowLayer* nextModal;
for (WindowLayer* modal = frontmost; modal != NULL ; modal = nextModal) {
nextModal = (WindowLayer*)modal->NextLayer();
if (nextModal == frontmost) {
// since we're adding the modal windows to the end of the list
// we're traversing, we must stop when we've reached the initial
// starting point again
nextModal = NULL;
} else if (nextModal != NULL
&& (!nextModal->IsModal() || !nextModal->HasInSubset(window)))
nextModal = NULL;
previous.Include(&modal->FullVisible());
WindowLayer* modalFrontmost = modal->Frontmost();
_RemoveChildFromList(modal);
_AddChildToList(modal, modalFrontmost);
BRegion modalRegion;
modal->GetOnScreenRegion(modalRegion);
// TODO: this is not what we want, we'd want the new visible region
update.Include(&modalRegion);
}
}
_AddChildToList(window, frontmost);
BRegion windowRegion;
window->GetOnScreenRegion(windowRegion);
// TODO: this is not what we want, we'd want the new visible region
update.Include(&windowRegion);
update.Exclude(&previous); update.Exclude(&previous);
fFront = windowLayer; _UpdateFront();
if (windowLayer == fBack || fBack == NULL) if (window == fBack || fBack == NULL)
_UpdateBack(); _UpdateBack();
} }
@@ -280,19 +324,20 @@ RootLayer::_UpdateFronts()
void void
RootLayer::ActivateWindow(WindowLayer* windowLayer) RootLayer::ActivateWindow(WindowLayer* window)
{ {
BAutolock _(fAllRegionsLock); BAutolock _(fAllRegionsLock);
BRegion changed; BRegion changed;
_SetFront(windowLayer, changed); _SetFront(window, changed);
// TODO: if this window has any floating windows, add them here // TODO: if this window has any floating windows, add them here
MarkForRebuild(changed); MarkForRebuild(changed);
TriggerRebuild(); TriggerRebuild();
_SetFocus(windowLayer, changed); _SetFocus(Front(), changed);
_WindowsChanged(changed); _WindowsChanged(changed);
MarkForRedraw(changed); MarkForRedraw(changed);
TriggerRedraw(); TriggerRedraw();
@@ -336,32 +381,32 @@ RootLayer::SendBehindWindow(WindowLayer* windowLayer, WindowLayer* behindOf)
void void
RootLayer::AddWindowLayer(WindowLayer* windowLayer) RootLayer::AddWindow(WindowLayer* window)
{ {
STRACE(("AddWindowLayer(%p \"%s\")\n", windowLayer, windowLayer->Name())); STRACE(("AddWindowLayer(%p \"%s\")\n", window, window->Name()));
if (windowLayer->SupportsFront()) if (window->SupportsFront())
_AddChildToList(windowLayer); _AddChildToList(window, window->Frontmost((WindowLayer*)FirstChild()));
else else
_AddChildToList(windowLayer, Back()); _AddChildToList(window, Back());
windowLayer->SetRootLayer(this); window->SetRootLayer(this);
if (!windowLayer->IsHidden()) if (!window->IsHidden())
ActivateWindow(windowLayer); ActivateWindow(window);
} }
void void
RootLayer::RemoveWindowLayer(WindowLayer* windowLayer) RootLayer::RemoveWindow(WindowLayer* window)
{ {
if (!windowLayer->IsHidden()) if (!window->IsHidden())
HideWindowLayer(windowLayer); HideWindow(window);
_RemoveChildFromList(windowLayer); _RemoveChildFromList(window);
LayerRemoved(windowLayer); LayerRemoved(window);
windowLayer->SetRootLayer(NULL); window->SetRootLayer(NULL);
} }
@@ -467,15 +512,15 @@ RootLayer::SetWorkspace(int32 index, Workspace::Private& previousWorkspace,
void void
RootLayer::HideWindowLayer(WindowLayer* windowLayer) RootLayer::HideWindow(WindowLayer* window)
{ {
BAutolock _(fAllRegionsLock); BAutolock _(fAllRegionsLock);
BRegion changed = windowLayer->FullVisible(); BRegion changed = window->FullVisible();
windowLayer->Hide(); window->Hide();
_UpdateFronts(); _UpdateFronts();
if (dynamic_cast<WorkspacesLayer*>(windowLayer->TopLayer()) != NULL) if (dynamic_cast<WorkspacesLayer*>(window->TopLayer()) != NULL)
fWorkspacesLayer = NULL; fWorkspacesLayer = NULL;
// TODO: if this window has any floating windows, remove them here // TODO: if this window has any floating windows, remove them here
@@ -483,7 +528,7 @@ RootLayer::HideWindowLayer(WindowLayer* windowLayer)
MarkForRebuild(changed); MarkForRebuild(changed);
TriggerRebuild(); TriggerRebuild();
if (windowLayer == Focus()) if (window == Focus())
_SetFocus(Front(), changed); _SetFocus(Front(), changed);
_WindowsChanged(changed); _WindowsChanged(changed);
@@ -493,34 +538,34 @@ RootLayer::HideWindowLayer(WindowLayer* windowLayer)
void void
RootLayer::ShowWindowLayer(WindowLayer* windowLayer, bool toFront) RootLayer::ShowWindow(WindowLayer* window, bool toFront)
{ {
STRACE(("ShowWindowLayer(%p)\n", windowLayer)); STRACE(("ShowWindowLayer(%p)\n", window));
if (!windowLayer->IsHidden()) if (!window->IsHidden())
return; return;
BAutolock _(fAllRegionsLock); BAutolock _(fAllRegionsLock);
windowLayer->Show(); window->Show();
BRegion changed = windowLayer->FullVisible(); BRegion changed = window->FullVisible();
if (toFront) if (toFront)
_SetFront(windowLayer, changed); _SetFront(window, changed);
else else
_UpdateFront(); _UpdateFront();
// TODO: if this window has any floating windows, remove them here // TODO: if this window has any floating windows, remove them here
// TODO: support FFM // TODO: support FFM
if (Front() == windowLayer || Focus() == NULL) if (Front() == window || Focus() == NULL)
_SetFocus(windowLayer, changed); _SetFocus(window, changed);
_WindowsChanged(changed); _WindowsChanged(changed);
MarkForRedraw(changed); MarkForRedraw(changed);
TriggerRedraw(); TriggerRedraw();
if (dynamic_cast<WorkspacesLayer*>(windowLayer->TopLayer()) != NULL) if (dynamic_cast<WorkspacesLayer*>(window->TopLayer()) != NULL)
fWorkspacesLayer = windowLayer->TopLayer(); fWorkspacesLayer = window->TopLayer();
} }
+4 -4
View File
@@ -54,8 +54,8 @@ class RootLayer : public Layer {
virtual void ScrollBy(float x, float y) virtual void ScrollBy(float x, float y)
{ /* not allowed */ } { /* not allowed */ }
void HideWindowLayer(WindowLayer* windowLayer); void HideWindow(WindowLayer* window);
void ShowWindowLayer(WindowLayer* windowLayer, bool toFront = true); void ShowWindow(WindowLayer* window, bool toFront = true);
void MoveWindowBy(WindowLayer* window, float x, float y); void MoveWindowBy(WindowLayer* window, float x, float y);
void ResizeWindowBy(WindowLayer* window, float x, float y); void ResizeWindowBy(WindowLayer* window, float x, float y);
@@ -100,8 +100,8 @@ class RootLayer : public Layer {
thread_id LockingThread() { return fAllRegionsLock.LockingThread(); } thread_id LockingThread() { return fAllRegionsLock.LockingThread(); }
void AddWindowLayer(WindowLayer* windowLayer); void AddWindow(WindowLayer* window);
void RemoveWindowLayer(WindowLayer* windowLayer); void RemoveWindow(WindowLayer* window);
private: private:
bool _SetFocus(WindowLayer* focus, BRegion& update); bool _SetFocus(WindowLayer* focus, BRegion& update);
+67 -21
View File
@@ -5,6 +5,7 @@
* Author: DarkWyrm <[email protected]> * Author: DarkWyrm <[email protected]>
* Adi Oanca <[email protected]> * Adi Oanca <[email protected]>
* Stephan Aßmus <[email protected]> * Stephan Aßmus <[email protected]>
* Axel Dörfler, [email protected]
*/ */
@@ -714,27 +715,6 @@ WindowLayer::SetFeel(window_feel feel)
// having modal windows with B_AVOID_FRONT or B_AVOID_FOCUS doesn't // having modal windows with B_AVOID_FRONT or B_AVOID_FOCUS doesn't
// make that much sense, so we filter those flags out on demand // make that much sense, so we filter those flags out on demand
fWindowFlags &= ~ValidWindowFlags(fFeel); fWindowFlags &= ~ValidWindowFlags(fFeel);
// TODO: this shouldn't be necessary, but we'll see :)
// floating and modal windows must appear in every workspace where
// their main window is present. Thus their fWorkspaces will be set to
// '0x0' and they will be made visible when needed.
switch (fFeel) {
case B_MODAL_APP_WINDOW_FEEL:
break;
case B_MODAL_SUBSET_WINDOW_FEEL:
case B_FLOATING_APP_WINDOW_FEEL:
case B_FLOATING_SUBSET_WINDOW_FEEL:
fWorkspaces = 0x0UL;
break;
case B_MODAL_ALL_WINDOW_FEEL:
case B_FLOATING_ALL_WINDOW_FEEL:
fWorkspaces = 0xffffffffUL;
break;
case B_NORMAL_WINDOW_FEEL:
break;
}
} }
@@ -768,6 +748,72 @@ WindowLayer::IsFloating() const
} }
/*!
\brief Returns the windows that's in front of the frontmost position
this window can get.
Returns NULL is this window can be the frontmost window.
*/
WindowLayer*
WindowLayer::Frontmost(WindowLayer* first)
{
if (fFeel == B_FLOATING_ALL_WINDOW_FEEL)
return NULL;
if (first == NULL)
first = (WindowLayer*)NextLayer();
for (WindowLayer* window = first; window != NULL;
window = (WindowLayer*)window->NextLayer()) {
if (window->IsHidden())
continue;
// no one can be in front of a floating all window
if (window->Feel() == B_FLOATING_ALL_WINDOW_FEEL)
return window;
if (fFeel == B_NORMAL_WINDOW_FEEL
&& window->HasInSubset(this))
return window;
}
return NULL;
}
bool
WindowLayer::AddToSubset(WindowLayer* window)
{
if (fFeel == B_FLOATING_ALL_WINDOW_FEEL
|| fFeel == B_MODAL_ALL_WINDOW_FEEL)
return true;
return fSubsets.AddItem(window);
}
void
WindowLayer::RemoveFromSubset(WindowLayer* window)
{
if (fFeel == B_FLOATING_ALL_WINDOW_FEEL
|| fFeel == B_MODAL_ALL_WINDOW_FEEL)
return;
fSubsets.RemoveItem(window);
}
bool
WindowLayer::HasInSubset(WindowLayer* window)
{
if (fFeel == B_FLOATING_ALL_WINDOW_FEEL
|| fFeel == B_MODAL_ALL_WINDOW_FEEL)
return true;
return fSubsets.HasItem(window);
}
click_type click_type
WindowLayer::_ActionFor(const BMessage *msg) const WindowLayer::_ActionFor(const BMessage *msg) const
{ {
+10
View File
@@ -5,6 +5,7 @@
* Author: DarkWyrm <bpmagic@columbus.rr.com> * Author: DarkWyrm <bpmagic@columbus.rr.com>
* Adi Oanca <adioanca@gmail.com> * Adi Oanca <adioanca@gmail.com>
* Stephan Aßmus <superstippi@gmx.de> * Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de
*/ */
#ifndef WINDOW_LAYER_H #ifndef WINDOW_LAYER_H
#define WINDOW_LAYER_H #define WINDOW_LAYER_H
@@ -13,6 +14,7 @@
#include "Decorator.h" #include "Decorator.h"
#include "Layer.h" #include "Layer.h"
#include <ObjectList.h>
#include <Rect.h> #include <Rect.h>
#include <String.h> #include <String.h>
@@ -113,6 +115,12 @@ class WindowLayer : public Layer {
bool IsModal() const; bool IsModal() const;
bool IsFloating() const; bool IsFloating() const;
WindowLayer* Frontmost(WindowLayer* first = NULL);
bool AddToSubset(WindowLayer* window);
void RemoveFromSubset(WindowLayer* window);
bool HasInSubset(WindowLayer* window);
void RequestClientRedraw(const BRegion& invalid); void RequestClientRedraw(const BRegion& invalid);
void SetTopLayer(Layer* layer); void SetTopLayer(Layer* layer);
@@ -153,6 +161,8 @@ class WindowLayer : public Layer {
bool fIsFocus; bool fIsFocus;
BObjectList<WindowLayer> fSubsets;
bool fIsClosing; bool fIsClosing;
bool fIsMinimizing; bool fIsMinimizing;
bool fIsZooming; bool fIsZooming;