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
+261 -65
View File
@@ -258,6 +258,7 @@ Desktop::Desktop(uid_t userID)
fApplicationsLock("application list"), fApplicationsLock("application list"),
fShutdownSemaphore(-1), fShutdownSemaphore(-1),
fAllWindows(kAllWindowList), fAllWindows(kAllWindowList),
fSubsetWindows(kSubsetList),
fActiveScreen(NULL), fActiveScreen(NULL),
fWindowLock("window lock") fWindowLock("window lock")
{ {
@@ -265,7 +266,7 @@ Desktop::Desktop(uid_t userID)
Desktop::_GetLooperName(name, sizeof(name)); Desktop::_GetLooperName(name, sizeof(name));
for (int32 i = 0; i < kMaxWorkspaces; i++) { for (int32 i = 0; i < kMaxWorkspaces; i++) {
fWorkspaces[i].Windows().SetIndex(i); _Windows(i).SetIndex(i);
} }
fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name); fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name);
@@ -584,19 +585,19 @@ Desktop::SetWorkspace(int32 index)
int32 previousIndex = fCurrentWorkspace; int32 previousIndex = fCurrentWorkspace;
if (fMouseEventWindow != NULL) { if (fMouseEventWindow != NULL) {
// the window currently being dragged will follow us to this workspace if (!fMouseEventWindow->InWorkspace(index)) {
// if it's not already on it // the window currently being dragged will follow us to this workspace
if (!fMouseEventWindow->OnWorkspace(index)) { // if it's not already on it
fWorkspaces[index].Windows().AddWindow(fMouseEventWindow); if (fMouseEventWindow->IsNormal()) {
fMouseEventWindow->SetWorkspaces((fMouseEventWindow->Workspaces() // but only normal windows are following
| workspace_to_workspaces(index)) _Windows(index).AddWindow(fMouseEventWindow);
& ~workspace_to_workspaces(previousIndex)); _Windows(previousIndex).RemoveWindow(fMouseEventWindow);
fWorkspaces[previousIndex].Windows().RemoveWindow(fMouseEventWindow); }
} else { } else {
// make sure it's frontmost // make sure it's frontmost
fWorkspaces[index].Windows().RemoveWindow(fMouseEventWindow); _Windows(index).RemoveWindow(fMouseEventWindow);
fWorkspaces[index].Windows().AddWindow(fMouseEventWindow, _Windows(index).AddWindow(fMouseEventWindow,
fMouseEventWindow->Frontmost(fWorkspaces[index].Windows().FirstWindow(), index)); fMouseEventWindow->Frontmost(_Windows(index).FirstWindow(), index));
} }
fMouseEventWindow->Anchor(index).position = fMouseEventWindow->Frame().LeftTop(); 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 // build region of windows that are no longer visible in the new workspace
BRegion dirty; BRegion dirty;
for (WindowLayer* window = _CurrentWindows().FirstWindow(); for (WindowLayer* window = _CurrentWindows().FirstWindow();
window != NULL; window = window->NextWindow(previousIndex)) { window != NULL; window = window->NextWindow(previousIndex)) {
// store current position in Workspace anchor
window->Anchor(previousIndex).position = window->Frame().LeftTop(); window->Anchor(previousIndex).position = window->Frame().LeftTop();
if (window->OnWorkspace(index)) if (window->InWorkspace(index))
continue; continue;
if (!window->IsHidden()) { if (!window->IsHidden()) {
@@ -617,7 +620,7 @@ Desktop::SetWorkspace(int32 index)
dirty.Include(&window->VisibleRegion()); dirty.Include(&window->VisibleRegion());
} }
window->SetCurrentWorkspace(-1); window->SetCurrentWorkspace(-1);
} }
fCurrentWorkspace = index; fCurrentWorkspace = index;
@@ -625,7 +628,7 @@ Desktop::SetWorkspace(int32 index)
// show windows, and include them in the changed region - but only // show windows, and include them in the changed region - but only
// those that were not visible before (or whose position changed) // 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)) { window != NULL; window = window->NextWindow(index)) {
BPoint position = window->Anchor(index).position; BPoint position = window->Anchor(index).position;
@@ -642,7 +645,7 @@ Desktop::SetWorkspace(int32 index)
// was before! // was before!
} }
if (!window->OnWorkspace(previousIndex)) { if (!window->InWorkspace(previousIndex)) {
// this window was not visible before // this window was not visible before
continue; continue;
} }
@@ -659,9 +662,9 @@ Desktop::SetWorkspace(int32 index)
_RebuildClippingForAllWindows(stillAvailableOnScreen); _RebuildClippingForAllWindows(stillAvailableOnScreen);
_SetBackground(stillAvailableOnScreen); _SetBackground(stillAvailableOnScreen);
for (WindowLayer* window = _CurrentWindows().FirstWindow(); window != NULL; for (WindowLayer* window = _Windows(index).FirstWindow(); window != NULL;
window = window->NextWindow(index)) { 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 // this window was visible before, and is already handled in the above loop
continue; continue;
} }
@@ -669,7 +672,9 @@ Desktop::SetWorkspace(int32 index)
dirty.Include(&window->VisibleRegion()); dirty.Include(&window->VisibleRegion());
} }
_UpdateFronts(); _UpdateFronts(false);
_UpdateFloating(previousIndex, index);
SetFocusWindow(FrontWindow()); SetFocusWindow(FrontWindow());
MarkDirty(dirty); 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) (only normal windows can be back windows)
*/ */
void 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 void
Desktop::_UpdateFront() Desktop::_UpdateFront(bool updateFloating)
{ {
// TODO: for now, just choose the top window
fFront = NULL; fFront = NULL;
for (WindowLayer* window = _CurrentWindows().LastWindow(); for (WindowLayer* window = _CurrentWindows().LastWindow();
window != NULL; window = window->PreviousWindow(fCurrentWorkspace)) { window != NULL; window = window->PreviousWindow(fCurrentWorkspace)) {
if (window->IsHidden() || !window->SupportsFront()) if (window->IsHidden() || window->IsFloating() || !window->SupportsFront())
continue; continue;
fFront = window; fFront = window;
break; break;
} }
if (updateFloating)
_UpdateFloating();
} }
void void
Desktop::_UpdateFronts() Desktop::_UpdateFronts(bool updateFloating)
{ {
_UpdateBack(); _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 void
Desktop::SetFocusWindow(WindowLayer* focus) Desktop::SetFocusWindow(WindowLayer* focus)
{ {
// TODO: test for FFM and B_LOCK_WINDOW_FOCUS if (!WriteLockWindows())
if (focus == fFocus && focus != NULL && (focus->Flags() & B_AVOID_FOCUS) == 0)
return; return;
if (WriteLockWindows()) { bool hasModal = _WindowHasModal(focus);
// make sure no window is chosen that doesn't want focus
while (focus != NULL && (focus->Flags() & B_AVOID_FOCUS) != 0) {
focus = focus->PreviousWindow(fCurrentWorkspace);
}
if (fFocus != NULL) // TODO: test for FFM and B_LOCK_WINDOW_FOCUS
fFocus->SetFocus(false);
fFocus = focus;
if (focus != NULL)
focus->SetFocus(true);
if (focus == fFocus && focus != NULL && (focus->Flags() & B_AVOID_FOCUS) == 0
&& !hasModal) {
// the window that is supposed to get focus already has focus
WriteUnlockWindows(); 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) if (windows.FirstWindow() == fBack || fBack == NULL)
_UpdateBack(); _UpdateBack();
SetFocusWindow(FrontWindow());
} }
@@ -863,14 +959,21 @@ Desktop::ActivateWindow(WindowLayer* window)
fFront = NULL; fFront = NULL;
return; return;
} }
if (window == FrontWindow())
return;
// TODO: support B_NO_WORKSPACE_ACTIVATION
// TODO: support B_NOT_ANCHORED_ON_ACTIVATE
// TODO: take care about floating windows // TODO: take care about floating windows
if (!WriteLockWindows()) if (!WriteLockWindows())
return; return;
if (window == FrontWindow()) {
SetFocusWindow(window);
WriteUnlockWindows();
return;
}
// we don't need to redraw what is currently // we don't need to redraw what is currently
// visible of the window // visible of the window
BRegion clean(window->VisibleRegion()); BRegion clean(window->VisibleRegion());
@@ -902,6 +1005,8 @@ Desktop::ActivateWindow(WindowLayer* window)
} }
_BringWindowsToFront(windows, kWorkingList, true); _BringWindowsToFront(windows, kWorkingList, true);
SetFocusWindow(window);
WriteUnlockWindows(); WriteUnlockWindows();
} }
@@ -955,8 +1060,9 @@ Desktop::ShowWindow(WindowLayer* window)
window->SetHidden(false); window->SetHidden(false);
if (window->OnWorkspace(fCurrentWorkspace)) { if (window->InWorkspace(fCurrentWorkspace)) {
_ShowWindow(window, true); _ShowWindow(window, true);
_UpdateSubsetWorkspaces(window);
ActivateWindow(window); ActivateWindow(window);
} else { } else {
// then we don't need to send the fake mouse event either // then we don't need to send the fake mouse event either
@@ -1001,7 +1107,8 @@ Desktop::HideWindow(WindowLayer* window)
window->SetHidden(true); window->SetHidden(true);
if (window->OnWorkspace(fCurrentWorkspace)) { if (window->InWorkspace(fCurrentWorkspace)) {
_UpdateSubsetWorkspaces(window);
_HideWindow(window); _HideWindow(window);
_UpdateFronts(); _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. \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)) { if (workspaces_on_workspace(i, 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)) {
fWorkspaces[i].Windows().RemoveWindow(window); _Windows(i).RemoveWindow(window);
window->SetCurrentWorkspace(-1);
if (i == CurrentWorkspace()) if (i == CurrentWorkspace()) {
_HideWindow(window); // remove its appearance from the current workspace
window->SetCurrentWorkspace(-1);
if (!window->IsHidden())
_HideWindow(window);
}
} }
} else { } else {
// 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)) {
fWorkspaces[i].Windows().AddWindow(window); _Windows(i).AddWindow(window,
window->SetCurrentWorkspace(fCurrentWorkspace); window->Frontmost(_Windows(i).FirstWindow(), i));
if (i == CurrentWorkspace()) { if (i == CurrentWorkspace()) {
// this only affects other windows if this windows has floating or // make the window visible in current workspace
// modal windows that need to be shown as well window->SetCurrentWorkspace(fCurrentWorkspace);
// TODO: take care of this
_ShowWindow(window, FrontWindow() == window); 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(); WriteUnlockWindows();
} }
@@ -1179,13 +1333,10 @@ Desktop::SetWindowWorkspaces(WindowLayer* window, uint32 workspaces)
{ {
BAutolock _(this); BAutolock _(this);
if (workspaces == B_CURRENT_WORKSPACE) if (window->IsNormal() && workspaces == B_CURRENT_WORKSPACE)
workspaces = workspace_to_workspaces(CurrentWorkspace()); workspaces = workspace_to_workspaces(CurrentWorkspace());
WriteLockWindows();
_ChangeWindowWorkspaces(window, window->Workspaces(), workspaces); _ChangeWindowWorkspaces(window, window->Workspaces(), workspaces);
window->SetWorkspaces(workspaces);
WriteUnlockWindows();
} }
@@ -1195,9 +1346,16 @@ Desktop::AddWindow(WindowLayer *window)
BAutolock _(this); BAutolock _(this);
fAllWindows.AddWindow(window); fAllWindows.AddWindow(window);
if (!window->IsNormal())
fSubsetWindows.AddWindow(window);
if (window->Workspaces() == B_CURRENT_WORKSPACE) if (window->IsNormal()) {
window->SetWorkspaces(workspace_to_workspaces(CurrentWorkspace())); 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()); _ChangeWindowWorkspaces(window, 0, window->Workspaces());
} }
@@ -1209,7 +1367,9 @@ Desktop::RemoveWindow(WindowLayer *window)
BAutolock _(this); BAutolock _(this);
fAllWindows.RemoveWindow(window); fAllWindows.RemoveWindow(window);
// _CurrentWindows().RemoveWindow(window); if (!window->IsNormal())
fSubsetWindows.RemoveWindow(window);
_ChangeWindowWorkspaces(window, window->Workspaces(), 0); _ChangeWindowWorkspaces(window, window->Workspaces(), 0);
// make sure this window won't get any events anymore // 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 void
Desktop::SetWindowLook(WindowLayer *window, window_look newLook) Desktop::SetWindowLook(WindowLayer *window, window_look newLook)
{ {
@@ -1252,9 +1431,26 @@ Desktop::SetWindowFeel(WindowLayer *window, window_feel newFeel)
BAutolock _(this); BAutolock _(this);
bool wasNormal = window->IsNormal();
window->SetFeel(newFeel); 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();
} }
+13 -2
View File
@@ -111,6 +111,11 @@ class Desktop : public MessageLooper, public ScreenOwner {
void AddWindow(WindowLayer* window); void AddWindow(WindowLayer* window);
void RemoveWindow(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 SetWindowLook(WindowLayer* window, window_look look);
void SetWindowFeel(WindowLayer* window, window_feel feel); void SetWindowFeel(WindowLayer* window, window_feel feel);
void SetWindowFlags(WindowLayer* window, uint32 flags); void SetWindowFlags(WindowLayer* window, uint32 flags);
@@ -159,6 +164,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
bool affectsOtherWindows = true); bool affectsOtherWindows = true);
void _HideWindow(WindowLayer* window); void _HideWindow(WindowLayer* window);
void _UpdateSubsetWorkspaces(WindowLayer* window);
void _ChangeWindowWorkspaces(WindowLayer* window, void _ChangeWindowWorkspaces(WindowLayer* window,
uint32 oldWorkspaces, uint32 newWorkspaces); uint32 oldWorkspaces, uint32 newWorkspaces);
void _BringWindowsToFront(WindowList& windows, void _BringWindowsToFront(WindowList& windows,
@@ -169,9 +175,12 @@ class Desktop : public MessageLooper, public ScreenOwner {
void _TriggerWindowRedrawing(BRegion& newDirtyRegion); void _TriggerWindowRedrawing(BRegion& newDirtyRegion);
void _SetBackground(BRegion& background); void _SetBackground(BRegion& background);
void _UpdateFloating(int32 previousWorkspace = -1,
int32 nextWorkspace = -1);
void _UpdateBack(); void _UpdateBack();
void _UpdateFront(); void _UpdateFront(bool updateFloating = true);
void _UpdateFronts(); void _UpdateFronts(bool updateFloating = true);
bool _WindowHasModal(WindowLayer* window);
void _GetLooperName(char* name, size_t size); void _GetLooperName(char* name, size_t size);
void _PrepareQuit(); void _PrepareQuit();
@@ -179,6 +188,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
BPrivate::LinkReceiver &link); BPrivate::LinkReceiver &link);
WindowList& _CurrentWindows(); WindowList& _CurrentWindows();
WindowList& _Windows(int32 index);
private: private:
friend class DesktopSettings; friend class DesktopSettings;
@@ -200,6 +210,7 @@ class Desktop : public MessageLooper, public ScreenOwner {
int32 fCurrentWorkspace; int32 fCurrentWorkspace;
WindowList fAllWindows; WindowList fAllWindows;
WindowList fSubsetWindows;
::RootLayer* fRootLayer; ::RootLayer* fRootLayer;
Screen* fActiveScreen; Screen* fActiveScreen;
+32 -6
View File
@@ -2403,25 +2403,51 @@ ServerApp::RemoveWindow(ServerWindow* window)
bool bool
ServerApp::OnWorkspace(int32 index) const ServerApp::InWorkspace(int32 index) const
{ {
BAutolock locker(fWindowListLock); BAutolock locker(fWindowListLock);
// we could cache this, but then we'd have to recompute the cached // we could cache this, but then we'd have to recompute the cached
// value everytime a window has closed or changed workspaces // 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;) { for (int32 i = fWindowList.CountItems(); i-- > 0;) {
ServerWindow* window = fWindowList.ItemAt(i); ServerWindow* window = fWindowList.ItemAt(i);
const WindowLayer* layer = window->GetWindowLayer(); const WindowLayer* layer = window->GetWindowLayer();
// only normal windows count // only normal and unhidden windows count
if (layer->Feel() == B_NORMAL_WINDOW_FEEL if (layer->IsNormal() && !layer->IsHidden())
&& layer->OnWorkspace(index)) workspaces |= layer->Workspaces();
return true;
} }
return false; // TODO: add initial application workspace!
return workspaces;
} }
+2 -1
View File
@@ -64,7 +64,8 @@ class ServerApp : public MessageLooper {
const char *Signature() const { return fSignature.String(); } const char *Signature() const { return fSignature.String(); }
void RemoveWindow(ServerWindow* window); void RemoveWindow(ServerWindow* window);
bool OnWorkspace(int32 index) const; bool InWorkspace(int32 index) const;
uint32 Workspaces() const;
int32 CountBitmaps() const; int32 CountBitmaps() const;
ServerBitmap *FindBitmap(int32 token) const; ServerBitmap *FindBitmap(int32 token) const;
+2 -2
View File
@@ -662,7 +662,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|| windowLayer->Feel() != B_NORMAL_WINDOW_FEEL) { || windowLayer->Feel() != B_NORMAL_WINDOW_FEEL) {
status = B_BAD_VALUE; status = B_BAD_VALUE;
} else { } else {
status = fWindowLayer->AddToSubset(windowLayer) status = fDesktop->AddWindowToSubset(fWindowLayer, windowLayer)
? B_OK : B_NO_MEMORY; ? B_OK : B_NO_MEMORY;
} }
} }
@@ -681,7 +681,7 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken( WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken(
token, App()->ClientTeam()); token, App()->ClientTeam());
if (windowLayer != NULL) { if (windowLayer != NULL) {
fWindowLayer->RemoveFromSubset(windowLayer); fDesktop->RemoveWindowFromSubset(fWindowLayer, windowLayer);
status = B_OK; status = B_OK;
} else } else
status = B_BAD_VALUE; status = B_BAD_VALUE;
+45 -5
View File
@@ -383,6 +383,13 @@ WindowLayer::MoveBy(int32 x, int32 y)
fFrame.OffsetBy(x, 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); fWindow->HandleDirectConnection(B_DIRECT_START | B_BUFFER_MOVED);
// take along the dirty region which have not // 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 // 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
fFlags &= ~ValidWindowFlags(fFeel); 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. of its subset windows is visible there.
*/ */
bool bool
WindowLayer::OnWorkspace(int32 index) const WindowLayer::InWorkspace(int32 index) const
{ {
if ((fWorkspaces & (1UL << index)) != 0 if (IsNormal())
|| fFeel == B_MODAL_ALL_WINDOW_FEEL return (fWorkspaces & (1UL << index)) != 0;
if (fFeel == B_MODAL_ALL_WINDOW_FEEL
|| fFeel == B_FLOATING_ALL_WINDOW_FEEL) || fFeel == B_FLOATING_ALL_WINDOW_FEEL)
return true; return true;
if (fFeel == B_MODAL_APP_WINDOW_FEEL if (fFeel == B_MODAL_APP_WINDOW_FEEL
|| fFeel == B_FLOATING_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 if (fFeel == B_MODAL_SUBSET_WINDOW_FEEL
|| fFeel == B_FLOATING_SUBSET_WINDOW_FEEL) { || fFeel == B_FLOATING_SUBSET_WINDOW_FEEL) {
for (int32 i = 0; i < fSubsets.CountItems(); i++) { for (int32 i = 0; i < fSubsets.CountItems(); i++) {
WindowLayer* window = fSubsets.ItemAt(i); WindowLayer* window = fSubsets.ItemAt(i);
if (window->OnWorkspace(index)) if (window->InWorkspace(index))
return true; 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 // #pragma mark - static
+2 -1
View File
@@ -160,7 +160,7 @@ class WindowLayer {
uint32 Workspaces() const { return fWorkspaces; } uint32 Workspaces() const { return fWorkspaces; }
void SetWorkspaces(uint32 workspaces) void SetWorkspaces(uint32 workspaces)
{ fWorkspaces = workspaces; } { fWorkspaces = workspaces; }
bool OnWorkspace(int32 index) const; bool InWorkspace(int32 index) const;
bool SupportsFront(); bool SupportsFront();
@@ -175,6 +175,7 @@ class WindowLayer {
void RemoveFromSubset(WindowLayer* window); void RemoveFromSubset(WindowLayer* window);
bool HasInSubset(WindowLayer* window); bool HasInSubset(WindowLayer* window);
bool SameSubset(WindowLayer* window); bool SameSubset(WindowLayer* window);
uint32 SubsetWorkspaces() const;
static bool IsValidLook(window_look look); static bool IsValidLook(window_look look);
static bool IsValidFeel(window_feel feel); static bool IsValidFeel(window_feel feel);
+20
View File
@@ -7,6 +7,7 @@
*/ */
#include "DesktopSettings.h"
#include "WindowLayer.h" #include "WindowLayer.h"
@@ -76,6 +77,9 @@ WindowList::AddWindow(WindowLayer* window, WindowLayer* before)
windowAnchor.next = NULL; windowAnchor.next = NULL;
fLastWindow = window; 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; windowAnchor.next->Anchor(fIndex).previous = windowAnchor.previous;
} }
if (fIndex < kMaxWorkspaces)
window->SetWorkspaces(window->Workspaces() & ~(1UL << fIndex));
windowAnchor.previous = NULL; windowAnchor.previous = NULL;
windowAnchor.next = 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;
}
+3 -1
View File
@@ -30,6 +30,8 @@ class WindowList {
void AddWindow(WindowLayer* window, WindowLayer* before = NULL); void AddWindow(WindowLayer* window, WindowLayer* before = NULL);
void RemoveWindow(WindowLayer* window); void RemoveWindow(WindowLayer* window);
bool HasWindow(WindowLayer* window) const;
private: private:
int32 fIndex; int32 fIndex;
WindowLayer* fFirstWindow; WindowLayer* fFirstWindow;
@@ -38,7 +40,7 @@ class WindowList {
enum window_lists { enum window_lists {
kAllWindowList = 32, kAllWindowList = 32,
kFloatingList, kSubsetList,
kWorkingList, kWorkingList,
}; };