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;
}
fRootLayer->ShowWindowLayer(window);
fRootLayer->ShowWindow(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
@@ -659,7 +659,7 @@ Desktop::HideWindow(WindowLayer* window)
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?
if (!workspaces_on_workspace(i, newWorkspaces)) {
if (i == CurrentWorkspace())
RootLayer()->RemoveWindowLayer(window);
RootLayer()->RemoveWindow(window);
else
fWorkspaces[i].RemoveWindow(window);
}
@@ -700,7 +700,7 @@ Desktop::_ChangeWindowWorkspaces(WindowLayer* window, uint32 oldWorkspaces,
// window was not on this workspace, is it now?
if (workspaces_on_workspace(i, newWorkspaces)) {
if (i == CurrentWorkspace())
RootLayer()->AddWindowLayer(window);
RootLayer()->AddWindow(window);
else
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
RootLayer::_SetFront(WindowLayer* windowLayer, BRegion& update)
RootLayer::_SetFront(WindowLayer* window, BRegion& update)
{
if (windowLayer == NULL) {
if (window == NULL) {
fBack = NULL;
fFront = NULL;
return;
}
if (!windowLayer->SupportsFront() && fFront != NULL)
if (!window->SupportsFront() && fFront != NULL)
return;
BRegion previous = windowLayer->FullVisible();
BRegion previous = window->FullVisible();
WindowLayer* frontmost = window->Frontmost();
_RemoveChildFromList(windowLayer);
_AddChildToList(windowLayer);
_RemoveChildFromList(window);
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);
fFront = windowLayer;
_UpdateFront();
if (windowLayer == fBack || fBack == NULL)
if (window == fBack || fBack == NULL)
_UpdateBack();
}
@@ -280,19 +324,20 @@ RootLayer::_UpdateFronts()
void
RootLayer::ActivateWindow(WindowLayer* windowLayer)
RootLayer::ActivateWindow(WindowLayer* window)
{
BAutolock _(fAllRegionsLock);
BRegion changed;
_SetFront(windowLayer, changed);
_SetFront(window, changed);
// TODO: if this window has any floating windows, add them here
MarkForRebuild(changed);
TriggerRebuild();
_SetFocus(windowLayer, changed);
_SetFocus(Front(), changed);
_WindowsChanged(changed);
MarkForRedraw(changed);
TriggerRedraw();
@@ -336,32 +381,32 @@ RootLayer::SendBehindWindow(WindowLayer* windowLayer, WindowLayer* behindOf)
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())
_AddChildToList(windowLayer);
if (window->SupportsFront())
_AddChildToList(window, window->Frontmost((WindowLayer*)FirstChild()));
else
_AddChildToList(windowLayer, Back());
_AddChildToList(window, Back());
windowLayer->SetRootLayer(this);
window->SetRootLayer(this);
if (!windowLayer->IsHidden())
ActivateWindow(windowLayer);
if (!window->IsHidden())
ActivateWindow(window);
}
void
RootLayer::RemoveWindowLayer(WindowLayer* windowLayer)
RootLayer::RemoveWindow(WindowLayer* window)
{
if (!windowLayer->IsHidden())
HideWindowLayer(windowLayer);
if (!window->IsHidden())
HideWindow(window);
_RemoveChildFromList(windowLayer);
_RemoveChildFromList(window);
LayerRemoved(windowLayer);
windowLayer->SetRootLayer(NULL);
LayerRemoved(window);
window->SetRootLayer(NULL);
}
@@ -467,15 +512,15 @@ RootLayer::SetWorkspace(int32 index, Workspace::Private& previousWorkspace,
void
RootLayer::HideWindowLayer(WindowLayer* windowLayer)
RootLayer::HideWindow(WindowLayer* window)
{
BAutolock _(fAllRegionsLock);
BRegion changed = windowLayer->FullVisible();
windowLayer->Hide();
BRegion changed = window->FullVisible();
window->Hide();
_UpdateFronts();
if (dynamic_cast<WorkspacesLayer*>(windowLayer->TopLayer()) != NULL)
if (dynamic_cast<WorkspacesLayer*>(window->TopLayer()) != NULL)
fWorkspacesLayer = NULL;
// TODO: if this window has any floating windows, remove them here
@@ -483,7 +528,7 @@ RootLayer::HideWindowLayer(WindowLayer* windowLayer)
MarkForRebuild(changed);
TriggerRebuild();
if (windowLayer == Focus())
if (window == Focus())
_SetFocus(Front(), changed);
_WindowsChanged(changed);
@@ -493,34 +538,34 @@ RootLayer::HideWindowLayer(WindowLayer* windowLayer)
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;
BAutolock _(fAllRegionsLock);
windowLayer->Show();
BRegion changed = windowLayer->FullVisible();
window->Show();
BRegion changed = window->FullVisible();
if (toFront)
_SetFront(windowLayer, changed);
_SetFront(window, changed);
else
_UpdateFront();
// TODO: if this window has any floating windows, remove them here
// TODO: support FFM
if (Front() == windowLayer || Focus() == NULL)
_SetFocus(windowLayer, changed);
if (Front() == window || Focus() == NULL)
_SetFocus(window, changed);
_WindowsChanged(changed);
MarkForRedraw(changed);
TriggerRedraw();
if (dynamic_cast<WorkspacesLayer*>(windowLayer->TopLayer()) != NULL)
fWorkspacesLayer = windowLayer->TopLayer();
if (dynamic_cast<WorkspacesLayer*>(window->TopLayer()) != NULL)
fWorkspacesLayer = window->TopLayer();
}
+4 -4
View File
@@ -54,8 +54,8 @@ class RootLayer : public Layer {
virtual void ScrollBy(float x, float y)
{ /* not allowed */ }
void HideWindowLayer(WindowLayer* windowLayer);
void ShowWindowLayer(WindowLayer* windowLayer, bool toFront = true);
void HideWindow(WindowLayer* window);
void ShowWindow(WindowLayer* window, bool toFront = true);
void MoveWindowBy(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(); }
void AddWindowLayer(WindowLayer* windowLayer);
void RemoveWindowLayer(WindowLayer* windowLayer);
void AddWindow(WindowLayer* window);
void RemoveWindow(WindowLayer* window);
private:
bool _SetFocus(WindowLayer* focus, BRegion& update);
+67 -21
View File
@@ -5,6 +5,7 @@
* Author: DarkWyrm <[email protected]>
* Adi Oanca <[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
// make that much sense, so we filter those flags out on demand
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
WindowLayer::_ActionFor(const BMessage *msg) const
{
+10
View File
@@ -5,6 +5,7 @@
* Author: DarkWyrm <[email protected]>
* Adi Oanca <[email protected]>
* Stephan Aßmus <[email protected]>
* Axel Dörfler, [email protected]
*/
#ifndef WINDOW_LAYER_H
#define WINDOW_LAYER_H
@@ -13,6 +14,7 @@
#include "Decorator.h"
#include "Layer.h"
#include <ObjectList.h>
#include <Rect.h>
#include <String.h>
@@ -113,6 +115,12 @@ class WindowLayer : public Layer {
bool IsModal() 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 SetTopLayer(Layer* layer);
@@ -153,6 +161,8 @@ class WindowLayer : public Layer {
bool fIsFocus;
BObjectList<WindowLayer> fSubsets;
bool fIsClosing;
bool fIsMinimizing;
bool fIsZooming;