A couple of changes related to modal and floating windows:

* Desktop::SetWindowFeel() is now working, but doesn't respect the window
  position yet (ie. floating windows would have to be moved to front).
* WindowLayer::Workspaces() now always reflects exactly the lists it's in
  (at least after Desktop::AddWindow() has been called). WindowList::AddWindow()
  and RemoveWindow() now update this flag to be correct at all times.
* Fixed Desktop::_ChangeWindowWorkspaces() to not set the current workspace
  for windows that are not on the current workspace, and vice versa.
  It also would hide windows that were already hidden, and tried to show
  windows that actually were hidden (did no other harm than triggering
  a rebuild of the global clipping).
* Floating windows now work as expected.
* Desktop::SetFocusWindow() won't give a window focus that has a modal.
* Renamed OnWorkspace() to InWorkspace().
* ServerApp::InWorkspace() now works correctly, added ServerApp::Workspaces()
  as well.
* WindowLayer::SubsetWorkspaces() returns the workspaces mask this modal or
  floating window should be in.
* New window flag B_SAME_POSITION_IN_ALL_WORKSPACES should work as well.
* Floating and modal windows now have always set this flag.
* Added a WindowList::HasWindow() method.
* Desktop windows (windows with the desktop feel) can now have focus again
  (I accidently broke that before).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15434 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-12-09 13:17:43 +00:00
parent 463e791c29
commit 34227d2c34
9 changed files with 380 additions and 83 deletions

View File

@ -258,6 +258,7 @@ Desktop::Desktop(uid_t userID)
fApplicationsLock("application list"),
fShutdownSemaphore(-1),
fAllWindows(kAllWindowList),
fSubsetWindows(kSubsetList),
fActiveScreen(NULL),
fWindowLock("window lock")
{
@ -265,7 +266,7 @@ Desktop::Desktop(uid_t userID)
Desktop::_GetLooperName(name, sizeof(name));
for (int32 i = 0; i < kMaxWorkspaces; i++) {
fWorkspaces[i].Windows().SetIndex(i);
_Windows(i).SetIndex(i);
}
fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name);
@ -584,19 +585,19 @@ Desktop::SetWorkspace(int32 index)
int32 previousIndex = fCurrentWorkspace;
if (fMouseEventWindow != NULL) {
// the window currently being dragged will follow us to this workspace
// if it's not already on it
if (!fMouseEventWindow->OnWorkspace(index)) {
fWorkspaces[index].Windows().AddWindow(fMouseEventWindow);
fMouseEventWindow->SetWorkspaces((fMouseEventWindow->Workspaces()
| workspace_to_workspaces(index))
& ~workspace_to_workspaces(previousIndex));
fWorkspaces[previousIndex].Windows().RemoveWindow(fMouseEventWindow);
if (!fMouseEventWindow->InWorkspace(index)) {
// the window currently being dragged will follow us to this workspace
// if it's not already on it
if (fMouseEventWindow->IsNormal()) {
// but only normal windows are following
_Windows(index).AddWindow(fMouseEventWindow);
_Windows(previousIndex).RemoveWindow(fMouseEventWindow);
}
} else {
// make sure it's frontmost
fWorkspaces[index].Windows().RemoveWindow(fMouseEventWindow);
fWorkspaces[index].Windows().AddWindow(fMouseEventWindow,
fMouseEventWindow->Frontmost(fWorkspaces[index].Windows().FirstWindow(), index));
_Windows(index).RemoveWindow(fMouseEventWindow);
_Windows(index).AddWindow(fMouseEventWindow,
fMouseEventWindow->Frontmost(_Windows(index).FirstWindow(), index));
}
fMouseEventWindow->Anchor(index).position = fMouseEventWindow->Frame().LeftTop();
@ -605,11 +606,13 @@ Desktop::SetWorkspace(int32 index)
// build region of windows that are no longer visible in the new workspace
BRegion dirty;
for (WindowLayer* window = _CurrentWindows().FirstWindow();
window != NULL; window = window->NextWindow(previousIndex)) {
// store current position in Workspace anchor
window->Anchor(previousIndex).position = window->Frame().LeftTop();
if (window->OnWorkspace(index))
if (window->InWorkspace(index))
continue;
if (!window->IsHidden()) {
@ -617,7 +620,7 @@ Desktop::SetWorkspace(int32 index)
dirty.Include(&window->VisibleRegion());
}
window->SetCurrentWorkspace(-1);
window->SetCurrentWorkspace(-1);
}
fCurrentWorkspace = index;
@ -625,7 +628,7 @@ Desktop::SetWorkspace(int32 index)
// show windows, and include them in the changed region - but only
// those that were not visible before (or whose position changed)
for (WindowLayer* window = _CurrentWindows().FirstWindow();
for (WindowLayer* window = _Windows(index).FirstWindow();
window != NULL; window = window->NextWindow(index)) {
BPoint position = window->Anchor(index).position;
@ -642,7 +645,7 @@ Desktop::SetWorkspace(int32 index)
// was before!
}
if (!window->OnWorkspace(previousIndex)) {
if (!window->InWorkspace(previousIndex)) {
// this window was not visible before
continue;
}
@ -659,9 +662,9 @@ Desktop::SetWorkspace(int32 index)
_RebuildClippingForAllWindows(stillAvailableOnScreen);
_SetBackground(stillAvailableOnScreen);
for (WindowLayer* window = _CurrentWindows().FirstWindow(); window != NULL;
for (WindowLayer* window = _Windows(index).FirstWindow(); window != NULL;
window = window->NextWindow(index)) {
if (window->OnWorkspace(previousIndex) || window == fMouseEventWindow) {
if (window->InWorkspace(previousIndex) || window == fMouseEventWindow) {
// this window was visible before, and is already handled in the above loop
continue;
}
@ -669,7 +672,9 @@ Desktop::SetWorkspace(int32 index)
dirty.Include(&window->VisibleRegion());
}
_UpdateFronts();
_UpdateFronts(false);
_UpdateFloating(previousIndex, index);
SetFocusWindow(FrontWindow());
MarkDirty(dirty);
@ -730,7 +735,62 @@ Desktop::_CurrentWindows()
}
/*! Search the visible windows for a valid back window
WindowList&
Desktop::_Windows(int32 index)
{
return fWorkspaces[index].Windows();
}
void
Desktop::_UpdateFloating(int32 previousWorkspace, int32 nextWorkspace)
{
if (fFront == NULL)
return;
if (previousWorkspace == -1)
previousWorkspace = fCurrentWorkspace;
if (nextWorkspace == -1)
nextWorkspace = previousWorkspace;
for (WindowLayer* floating = fSubsetWindows.FirstWindow(); floating != NULL;
floating = floating->NextWindow(kSubsetList)) {
// we only care about app/subset floating windows
if (floating->Feel() != B_FLOATING_SUBSET_WINDOW_FEEL
&& floating->Feel() != B_FLOATING_APP_WINDOW_FEEL)
continue;
if (fFront->IsNormal() && floating->HasInSubset(fFront)) {
// is now visible
if (_Windows(previousWorkspace).HasWindow(floating)
&& previousWorkspace != nextWorkspace) {
// but no longer on the previous workspace
_Windows(previousWorkspace).RemoveWindow(floating);
floating->SetCurrentWorkspace(-1);
}
if (!_Windows(nextWorkspace).HasWindow(floating)) {
// but wasn't before
_Windows(nextWorkspace).AddWindow(floating,
floating->Frontmost(_Windows(nextWorkspace).FirstWindow(), nextWorkspace));
floating->SetCurrentWorkspace(nextWorkspace);
_ShowWindow(floating);
// TODO:
// put the floating last in the floating window list to preserve
// the on screen window order
}
} else if (_Windows(previousWorkspace).HasWindow(floating)) {
// was visible, but is no longer
_Windows(previousWorkspace).RemoveWindow(floating);
floating->SetCurrentWorkspace(-1);
_HideWindow(floating);
}
}
}
/*!
Search the visible windows for a valid back window
(only normal windows can be back windows)
*/
void
@ -749,58 +809,96 @@ Desktop::_UpdateBack()
}
/*! Search the visible windows for a valid front window
(only normal windows can be front windows)
/*!
Search the visible windows for a valid front window
(only normal and modal windows can be front windows)
The only place where you don't want to update floating windows is
during a workspace change - because then you'll call _UpdateFloating()
yourself.
*/
void
Desktop::_UpdateFront()
Desktop::_UpdateFront(bool updateFloating)
{
// TODO: for now, just choose the top window
fFront = NULL;
for (WindowLayer* window = _CurrentWindows().LastWindow();
window != NULL; window = window->PreviousWindow(fCurrentWorkspace)) {
if (window->IsHidden() || !window->SupportsFront())
if (window->IsHidden() || window->IsFloating() || !window->SupportsFront())
continue;
fFront = window;
break;
}
if (updateFloating)
_UpdateFloating();
}
void
Desktop::_UpdateFronts()
Desktop::_UpdateFronts(bool updateFloating)
{
_UpdateBack();
_UpdateFront();
_UpdateFront(updateFloating);
}
bool
Desktop::_WindowHasModal(WindowLayer* window)
{
if (window == NULL || window->IsFloating())
return false;
for (WindowLayer* modal = fSubsetWindows.FirstWindow(); modal != NULL;
modal = modal->NextWindow(kSubsetList)) {
// only visible modal windows count
if (!modal->IsModal() || modal->IsHidden())
continue;
if (modal->HasInSubset(window))
return true;
}
return false;
}
void
Desktop::SetFocusWindow(WindowLayer* focus)
{
// TODO: test for FFM and B_LOCK_WINDOW_FOCUS
if (focus == fFocus && focus != NULL && (focus->Flags() & B_AVOID_FOCUS) == 0)
if (!WriteLockWindows())
return;
if (WriteLockWindows()) {
// make sure no window is chosen that doesn't want focus
while (focus != NULL && (focus->Flags() & B_AVOID_FOCUS) != 0) {
focus = focus->PreviousWindow(fCurrentWorkspace);
}
bool hasModal = _WindowHasModal(focus);
if (fFocus != NULL)
fFocus->SetFocus(false);
fFocus = focus;
if (focus != NULL)
focus->SetFocus(true);
// TODO: test for FFM and B_LOCK_WINDOW_FOCUS
if (focus == fFocus && focus != NULL && (focus->Flags() & B_AVOID_FOCUS) == 0
&& !hasModal) {
// the window that is supposed to get focus already has focus
WriteUnlockWindows();
return;
}
if (focus == NULL || hasModal)
focus = FrontWindow();
// make sure no window is chosen that doesn't want focus or cannot have it
while (focus != NULL
&& ((focus->Flags() & B_AVOID_FOCUS) != 0 || _WindowHasModal(focus))) {
focus = focus->PreviousWindow(fCurrentWorkspace);
}
if (fFocus != NULL)
fFocus->SetFocus(false);
fFocus = focus;
if (focus != NULL)
focus->SetFocus(true);
WriteUnlockWindows();
}
@ -840,8 +938,6 @@ Desktop::_BringWindowsToFront(WindowList& windows, int32 list,
if (windows.FirstWindow() == fBack || fBack == NULL)
_UpdateBack();
SetFocusWindow(FrontWindow());
}
@ -863,14 +959,21 @@ Desktop::ActivateWindow(WindowLayer* window)
fFront = NULL;
return;
}
if (window == FrontWindow())
return;
// TODO: support B_NO_WORKSPACE_ACTIVATION
// TODO: support B_NOT_ANCHORED_ON_ACTIVATE
// TODO: take care about floating windows
if (!WriteLockWindows())
return;
if (window == FrontWindow()) {
SetFocusWindow(window);
WriteUnlockWindows();
return;
}
// we don't need to redraw what is currently
// visible of the window
BRegion clean(window->VisibleRegion());
@ -902,6 +1005,8 @@ Desktop::ActivateWindow(WindowLayer* window)
}
_BringWindowsToFront(windows, kWorkingList, true);
SetFocusWindow(window);
WriteUnlockWindows();
}
@ -955,8 +1060,9 @@ Desktop::ShowWindow(WindowLayer* window)
window->SetHidden(false);
if (window->OnWorkspace(fCurrentWorkspace)) {
if (window->InWorkspace(fCurrentWorkspace)) {
_ShowWindow(window, true);
_UpdateSubsetWorkspaces(window);
ActivateWindow(window);
} else {
// then we don't need to send the fake mouse event either
@ -1001,7 +1107,8 @@ Desktop::HideWindow(WindowLayer* window)
window->SetHidden(true);
if (window->OnWorkspace(fCurrentWorkspace)) {
if (window->InWorkspace(fCurrentWorkspace)) {
_UpdateSubsetWorkspaces(window);
_HideWindow(window);
_UpdateFronts();
@ -1133,6 +1240,41 @@ Desktop::ResizeWindowBy(WindowLayer* window, float x, float y)
}
/*!
Updates the workspaces of all subset windows with regard to the
specifed window.
*/
void
Desktop::_UpdateSubsetWorkspaces(WindowLayer* window)
{
// if the window is hidden, the subset windows are up-to-date already
if (!window->IsNormal() || window->IsHidden())
return;
for (WindowLayer* subset = fSubsetWindows.FirstWindow(); subset != NULL;
subset = subset->NextWindow(kSubsetList)) {
if (subset->Feel() == B_MODAL_ALL_WINDOW_FEEL
|| subset->Feel() == B_FLOATING_ALL_WINDOW_FEEL) {
// These windows are always visible on all workspaces,
// no need to update them.
continue;
}
if (subset->IsFloating()) {
// Floating windows are inserted and removed to the current
// workspace as the need arises - they are not handled here
// but in _UpdateFront()
continue;
}
if (subset->HasInSubset(window)) {
// adopt the workspace change
SetWindowWorkspaces(subset, subset->SubsetWorkspaces());
}
}
}
/*!
\brief Adds or removes the window to or from the workspaces it's on.
*/
@ -1148,28 +1290,40 @@ Desktop::_ChangeWindowWorkspaces(WindowLayer* window, uint32 oldWorkspaces,
if (workspaces_on_workspace(i, oldWorkspaces)) {
// window is on this workspace, is it anymore?
if (!workspaces_on_workspace(i, newWorkspaces)) {
fWorkspaces[i].Windows().RemoveWindow(window);
window->SetCurrentWorkspace(-1);
_Windows(i).RemoveWindow(window);
if (i == CurrentWorkspace())
_HideWindow(window);
if (i == CurrentWorkspace()) {
// remove its appearance from the current workspace
window->SetCurrentWorkspace(-1);
if (!window->IsHidden())
_HideWindow(window);
}
}
} else {
// window was not on this workspace, is it now?
if (workspaces_on_workspace(i, newWorkspaces)) {
fWorkspaces[i].Windows().AddWindow(window);
window->SetCurrentWorkspace(fCurrentWorkspace);
_Windows(i).AddWindow(window,
window->Frontmost(_Windows(i).FirstWindow(), i));
if (i == CurrentWorkspace()) {
// this only affects other windows if this windows has floating or
// modal windows that need to be shown as well
// TODO: take care of this
_ShowWindow(window, FrontWindow() == window);
// make the window visible in current workspace
window->SetCurrentWorkspace(fCurrentWorkspace);
if (!window->IsHidden()) {
// this only affects other windows if this windows has floating or
// modal windows that need to be shown as well
// TODO: take care of this
_ShowWindow(window, FrontWindow() == window);
}
}
}
}
}
// take care about modals and floating windows
_UpdateSubsetWorkspaces(window);
WriteUnlockWindows();
}
@ -1179,13 +1333,10 @@ Desktop::SetWindowWorkspaces(WindowLayer* window, uint32 workspaces)
{
BAutolock _(this);
if (workspaces == B_CURRENT_WORKSPACE)
if (window->IsNormal() && workspaces == B_CURRENT_WORKSPACE)
workspaces = workspace_to_workspaces(CurrentWorkspace());
WriteLockWindows();
_ChangeWindowWorkspaces(window, window->Workspaces(), workspaces);
window->SetWorkspaces(workspaces);
WriteUnlockWindows();
}
@ -1195,9 +1346,16 @@ Desktop::AddWindow(WindowLayer *window)
BAutolock _(this);
fAllWindows.AddWindow(window);
if (!window->IsNormal())
fSubsetWindows.AddWindow(window);
if (window->Workspaces() == B_CURRENT_WORKSPACE)
window->SetWorkspaces(workspace_to_workspaces(CurrentWorkspace()));
if (window->IsNormal()) {
if (window->Workspaces() == B_CURRENT_WORKSPACE)
window->SetWorkspaces(workspace_to_workspaces(CurrentWorkspace()));
} else {
// subset windows are visible on all workspaces their subset is on
window->SetWorkspaces(window->SubsetWorkspaces());
}
_ChangeWindowWorkspaces(window, 0, window->Workspaces());
}
@ -1209,7 +1367,9 @@ Desktop::RemoveWindow(WindowLayer *window)
BAutolock _(this);
fAllWindows.RemoveWindow(window);
// _CurrentWindows().RemoveWindow(window);
if (!window->IsNormal())
fSubsetWindows.RemoveWindow(window);
_ChangeWindowWorkspaces(window, window->Workspaces(), 0);
// make sure this window won't get any events anymore
@ -1218,6 +1378,25 @@ Desktop::RemoveWindow(WindowLayer *window)
}
bool
Desktop::AddWindowToSubset(WindowLayer* subset, WindowLayer* window)
{
if (!subset->AddToSubset(window))
return false;
_ChangeWindowWorkspaces(subset, subset->Workspaces(), subset->SubsetWorkspaces());
return true;
}
void
Desktop::RemoveWindowFromSubset(WindowLayer* subset, WindowLayer* window)
{
subset->RemoveFromSubset(window);
_ChangeWindowWorkspaces(subset, subset->Workspaces(), subset->SubsetWorkspaces());
}
void
Desktop::SetWindowLook(WindowLayer *window, window_look newLook)
{
@ -1252,9 +1431,26 @@ Desktop::SetWindowFeel(WindowLayer *window, window_feel newFeel)
BAutolock _(this);
bool wasNormal = window->IsNormal();
window->SetFeel(newFeel);
// TODO: implement window feels!
// move the window out of or into the subset window list as needed
if (window->IsNormal() && !wasNormal)
fSubsetWindows.RemoveWindow(window);
else if (!window->IsNormal() && wasNormal)
fSubsetWindows.AddWindow(window);
// A normal window that was once a floating or modal window will
// adopt the window's current workspaces
if (!window->IsNormal())
_ChangeWindowWorkspaces(window, window->Workspaces(), window->SubsetWorkspaces());
// TODO: make sure the window has the correct position in the window list
// (ie. all floating windows have to be on the top, ...)
_UpdateFronts();
}

View File

@ -111,6 +111,11 @@ class Desktop : public MessageLooper, public ScreenOwner {
void AddWindow(WindowLayer* window);
void RemoveWindow(WindowLayer* window);
bool AddWindowToSubset(WindowLayer* subset,
WindowLayer* window);
void RemoveWindowFromSubset(WindowLayer* subset,
WindowLayer* window);
void SetWindowLook(WindowLayer* window, window_look look);
void SetWindowFeel(WindowLayer* window, window_feel feel);
void SetWindowFlags(WindowLayer* window, uint32 flags);
@ -159,6 +164,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
bool affectsOtherWindows = true);
void _HideWindow(WindowLayer* window);
void _UpdateSubsetWorkspaces(WindowLayer* window);
void _ChangeWindowWorkspaces(WindowLayer* window,
uint32 oldWorkspaces, uint32 newWorkspaces);
void _BringWindowsToFront(WindowList& windows,
@ -169,9 +175,12 @@ class Desktop : public MessageLooper, public ScreenOwner {
void _TriggerWindowRedrawing(BRegion& newDirtyRegion);
void _SetBackground(BRegion& background);
void _UpdateFloating(int32 previousWorkspace = -1,
int32 nextWorkspace = -1);
void _UpdateBack();
void _UpdateFront();
void _UpdateFronts();
void _UpdateFront(bool updateFloating = true);
void _UpdateFronts(bool updateFloating = true);
bool _WindowHasModal(WindowLayer* window);
void _GetLooperName(char* name, size_t size);
void _PrepareQuit();
@ -179,6 +188,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
BPrivate::LinkReceiver &link);
WindowList& _CurrentWindows();
WindowList& _Windows(int32 index);
private:
friend class DesktopSettings;
@ -200,6 +210,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
int32 fCurrentWorkspace;
WindowList fAllWindows;
WindowList fSubsetWindows;
::RootLayer* fRootLayer;
Screen* fActiveScreen;

View File

@ -2403,25 +2403,51 @@ ServerApp::RemoveWindow(ServerWindow* window)
bool
ServerApp::OnWorkspace(int32 index) const
ServerApp::InWorkspace(int32 index) const
{
BAutolock locker(fWindowListLock);
// we could cache this, but then we'd have to recompute the cached
// value everytime a window has closed or changed workspaces
// TODO: support initial application workspace!
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* window = fWindowList.ItemAt(i);
const WindowLayer* layer = window->GetWindowLayer();
// only normal and unhidden windows count
if (layer->IsNormal() && !layer->IsHidden() && layer->InWorkspace(index))
return true;
}
return false;
}
uint32
ServerApp::Workspaces() const
{
uint32 workspaces = 0;
BAutolock locker(fWindowListLock);
// we could cache this, but then we'd have to recompute the cached
// value everytime a window has closed or changed workspaces
for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* window = fWindowList.ItemAt(i);
const WindowLayer* layer = window->GetWindowLayer();
// only normal windows count
// only normal and unhidden windows count
if (layer->Feel() == B_NORMAL_WINDOW_FEEL
&& layer->OnWorkspace(index))
return true;
if (layer->IsNormal() && !layer->IsHidden())
workspaces |= layer->Workspaces();
}
return false;
// TODO: add initial application workspace!
return workspaces;
}

View File

@ -64,7 +64,8 @@ class ServerApp : public MessageLooper {
const char *Signature() const { return fSignature.String(); }
void RemoveWindow(ServerWindow* window);
bool OnWorkspace(int32 index) const;
bool InWorkspace(int32 index) const;
uint32 Workspaces() const;
int32 CountBitmaps() const;
ServerBitmap *FindBitmap(int32 token) const;

View File

@ -662,7 +662,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|| windowLayer->Feel() != B_NORMAL_WINDOW_FEEL) {
status = B_BAD_VALUE;
} else {
status = fWindowLayer->AddToSubset(windowLayer)
status = fDesktop->AddWindowToSubset(fWindowLayer, windowLayer)
? B_OK : B_NO_MEMORY;
}
}
@ -681,7 +681,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken(
token, App()->ClientTeam());
if (windowLayer != NULL) {
fWindowLayer->RemoveFromSubset(windowLayer);
fDesktop->RemoveWindowFromSubset(fWindowLayer, windowLayer);
status = B_OK;
} else
status = B_BAD_VALUE;

View File

@ -383,6 +383,13 @@ WindowLayer::MoveBy(int32 x, int32 y)
fFrame.OffsetBy(x, y);
// propagate position if asked for
if (fFlags & B_SAME_POSITION_IN_ALL_WORKSPACES) {
for (int32 i = 0; i <= kWorkingList; i++) {
Anchor(i).position = fFrame.LeftTop();
}
}
fWindow->HandleDirectConnection(B_DIRECT_START | B_BUFFER_MOVED);
// take along the dirty region which have not
@ -1216,6 +1223,9 @@ 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
fFlags &= ~ValidWindowFlags(fFeel);
if (!IsNormal())
fFlags |= B_SAME_POSITION_IN_ALL_WORKSPACES;
}
@ -1247,22 +1257,24 @@ WindowLayer::SetFlags(uint32 flags, BRegion* updateRegion)
of its subset windows is visible there.
*/
bool
WindowLayer::OnWorkspace(int32 index) const
WindowLayer::InWorkspace(int32 index) const
{
if ((fWorkspaces & (1UL << index)) != 0
|| fFeel == B_MODAL_ALL_WINDOW_FEEL
if (IsNormal())
return (fWorkspaces & (1UL << index)) != 0;
if (fFeel == B_MODAL_ALL_WINDOW_FEEL
|| fFeel == B_FLOATING_ALL_WINDOW_FEEL)
return true;
if (fFeel == B_MODAL_APP_WINDOW_FEEL
|| fFeel == B_FLOATING_APP_WINDOW_FEEL)
return ServerWindow()->App()->OnWorkspace(index);
return ServerWindow()->App()->InWorkspace(index);
if (fFeel == B_MODAL_SUBSET_WINDOW_FEEL
|| fFeel == B_FLOATING_SUBSET_WINDOW_FEEL) {
for (int32 i = 0; i < fSubsets.CountItems(); i++) {
WindowLayer* window = fSubsets.ItemAt(i);
if (window->OnWorkspace(index))
if (window->InWorkspace(index))
return true;
}
}
@ -1432,6 +1444,34 @@ WindowLayer::SameSubset(WindowLayer* window)
}
uint32
WindowLayer::SubsetWorkspaces() const
{
if (fFeel == B_MODAL_ALL_WINDOW_FEEL
|| fFeel == B_FLOATING_ALL_WINDOW_FEEL)
return B_ALL_WORKSPACES;
if (fFeel == B_MODAL_APP_WINDOW_FEEL
|| fFeel == B_FLOATING_APP_WINDOW_FEEL)
return ServerWindow()->App()->Workspaces();
if (fFeel == B_MODAL_SUBSET_WINDOW_FEEL
|| fFeel == B_FLOATING_SUBSET_WINDOW_FEEL) {
uint32 workspaces = 0;
for (int32 i = 0; i < fSubsets.CountItems(); i++) {
WindowLayer* window = fSubsets.ItemAt(i);
if (!window->IsHidden())
workspaces |= window->Workspaces();
}
return workspaces;
}
return 0;
}
// #pragma mark - static

View File

@ -160,7 +160,7 @@ class WindowLayer {
uint32 Workspaces() const { return fWorkspaces; }
void SetWorkspaces(uint32 workspaces)
{ fWorkspaces = workspaces; }
bool OnWorkspace(int32 index) const;
bool InWorkspace(int32 index) const;
bool SupportsFront();
@ -175,6 +175,7 @@ class WindowLayer {
void RemoveFromSubset(WindowLayer* window);
bool HasInSubset(WindowLayer* window);
bool SameSubset(WindowLayer* window);
uint32 SubsetWorkspaces() const;
static bool IsValidLook(window_look look);
static bool IsValidFeel(window_feel feel);

View File

@ -7,6 +7,7 @@
*/
#include "DesktopSettings.h"
#include "WindowLayer.h"
@ -76,6 +77,9 @@ WindowList::AddWindow(WindowLayer* window, WindowLayer* before)
windowAnchor.next = NULL;
fLastWindow = window;
}
if (fIndex < kMaxWorkspaces)
window->SetWorkspaces(window->Workspaces() | (1UL << fIndex));
}
@ -100,7 +104,23 @@ WindowList::RemoveWindow(WindowLayer* window)
windowAnchor.next->Anchor(fIndex).previous = windowAnchor.previous;
}
if (fIndex < kMaxWorkspaces)
window->SetWorkspaces(window->Workspaces() & ~(1UL << fIndex));
windowAnchor.previous = NULL;
windowAnchor.next = NULL;
}
bool
WindowList::HasWindow(WindowLayer* window) const
{
if (window == NULL)
return false;
return window->Anchor(fIndex).next != NULL
|| window->Anchor(fIndex).previous != NULL
|| fFirstWindow == window
|| fLastWindow == window;
}

View File

@ -30,6 +30,8 @@ class WindowList {
void AddWindow(WindowLayer* window, WindowLayer* before = NULL);
void RemoveWindow(WindowLayer* window);
bool HasWindow(WindowLayer* window) const;
private:
int32 fIndex;
WindowLayer* fFirstWindow;
@ -38,7 +40,7 @@ class WindowList {
enum window_lists {
kAllWindowList = 32,
kFloatingList,
kSubsetList,
kWorkingList,
};