From e0bc3d9e2bf8beeb2ea7159855079d2c747c7f35 Mon Sep 17 00:00:00 2001 From: Clemens Zeidler Date: Tue, 9 Aug 2011 22:55:20 +0000 Subject: [PATCH] * Remove the bad designed GroupCookie class and move its functionality into the WindowArea. As an result each WindowArea only has one set of tabs and constraints. * Fix group splitting. * Style: win -> parentWindow git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42610 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/stackandtile/SATGroup.cpp | 304 +++++++++++++++--- src/servers/app/stackandtile/SATGroup.h | 40 ++- src/servers/app/stackandtile/SATWindow.cpp | 346 +++------------------ src/servers/app/stackandtile/SATWindow.h | 67 +--- src/servers/app/stackandtile/Stacking.cpp | 9 +- 5 files changed, 335 insertions(+), 431 deletions(-) diff --git a/src/servers/app/stackandtile/SATGroup.cpp b/src/servers/app/stackandtile/SATGroup.cpp index 0eb77038f3..4154d970da 100644 --- a/src/servers/app/stackandtile/SATGroup.cpp +++ b/src/servers/app/stackandtile/SATGroup.cpp @@ -22,6 +22,12 @@ using namespace std; +using namespace LinearProgramming; + + +const float kExtentPenalty = 1; +const float kHighPenalty = 100; +const float kInequalityPenalty = 10000; WindowArea::WindowArea(Crossing* leftTop, Crossing* rightTop, @@ -32,33 +38,139 @@ WindowArea::WindowArea(Crossing* leftTop, Crossing* rightTop, fLeftTopCrossing(leftTop), fRightTopCrossing(rightTop), fLeftBottomCrossing(leftBottom), - fRightBottomCrossing(rightBottom) + fRightBottomCrossing(rightBottom), + + fMinWidthConstraint(NULL), + fMinHeightConstraint(NULL), + fMaxWidthConstraint(NULL), + fMaxHeightConstraint(NULL), + fWidthConstraint(NULL), + fHeightConstraint(NULL) { } -bool -WindowArea::SetGroup(SATGroup* group) -{ - if (group && !group->fWindowAreaList.AddItem(this)) - return false; - - if (fGroup) - fGroup->fWindowAreaList.RemoveItem(this); - - fGroup = group; - return true; -} - - WindowArea::~WindowArea() { if (fGroup) fGroup->WindowAreaRemoved(this); _CleanupCorners(); - SetGroup(NULL); + fGroup->fWindowAreaList.RemoveItem(this); + + _UninitConstraints(); +} + + +bool +WindowArea::Init(SATGroup* group) +{ + _UninitConstraints(); + + if (group != NULL && group->fWindowAreaList.AddItem(this) == false) + return false; + + fGroup = group; + + LinearSpec* linearSpec = fGroup->GetLinearSpec(); + + fMinWidthConstraint = linearSpec->AddConstraint(1.0, RightVar(), -1.0, + LeftVar(), kGE, 0); + fMinHeightConstraint = linearSpec->AddConstraint(1.0, BottomVar(), -1.0, + TopVar(), kGE, 0); + + fMaxWidthConstraint = linearSpec->AddConstraint(1.0, RightVar(), -1.0, + LeftVar(), kLE, 0, kInequalityPenalty, kInequalityPenalty); + fMaxHeightConstraint = linearSpec->AddConstraint(1.0, BottomVar(), -1.0, + TopVar(), kLE, 0, kInequalityPenalty, kInequalityPenalty); + + // Width and height have soft constraints + fWidthConstraint = linearSpec->AddConstraint(1.0, RightVar(), -1.0, + LeftVar(), kEQ, 0, kExtentPenalty, + kExtentPenalty); + fHeightConstraint = linearSpec->AddConstraint(-1.0, TopVar(), 1.0, + BottomVar(), kEQ, 0, kExtentPenalty, + kExtentPenalty); + + if (!fMinWidthConstraint || !fMinHeightConstraint || !fWidthConstraint + || !fHeightConstraint || !fMaxWidthConstraint + || !fMaxHeightConstraint) + return false; + + return true; +} + + +void +WindowArea::DoGroupLayout() +{ + SATWindow* parentWindow = fWindowLayerOrder.ItemAt(0); + if (parentWindow == NULL) + return; + + BRect frame = parentWindow->CompleteWindowFrame(); + // Make it also work for solver which don't support negative variables + frame.OffsetBy(kMakePositiveOffset, kMakePositiveOffset); + + // adjust window size soft constraints + fWidthConstraint->SetRightSide(frame.Width()); + fHeightConstraint->SetRightSide(frame.Height()); + + LinearSpec* linearSpec = fGroup->GetLinearSpec(); + Constraint* leftConstraint = linearSpec->AddConstraint(1.0, LeftVar(), + kEQ, frame.left); + Constraint* topConstraint = linearSpec->AddConstraint(1.0, TopVar(), kEQ, + frame.top); + + // give soft constraints a high penalty + fWidthConstraint->SetPenaltyNeg(kHighPenalty); + fWidthConstraint->SetPenaltyPos(kHighPenalty); + fHeightConstraint->SetPenaltyNeg(kHighPenalty); + fHeightConstraint->SetPenaltyPos(kHighPenalty); + + // After we set the new parameter solve and apply the new layout. + ResultType result; + for (int32 tries = 0; tries < 15; tries++) { + result = fGroup->GetLinearSpec()->Solve(); + if (result == kInfeasible) { + debug_printf("can't solve constraints!\n"); + break; + } + if (result == kOptimal) { + const WindowAreaList& areas = fGroup->GetAreaList(); + for (int32 i = 0; i < areas.CountItems(); i++) { + WindowArea* area = areas.ItemAt(i); + area->_MoveToSAT(parentWindow); + } + break; + } + } + + // set penalties back to normal + fWidthConstraint->SetPenaltyNeg(kExtentPenalty); + fWidthConstraint->SetPenaltyPos(kExtentPenalty); + fHeightConstraint->SetPenaltyNeg(kExtentPenalty); + fHeightConstraint->SetPenaltyPos(kExtentPenalty); + + linearSpec->RemoveConstraint(leftConstraint); + linearSpec->RemoveConstraint(topConstraint); +} + + +void +WindowArea::UpdateSizeLimits() +{ + _UpdateConstraintValues(); +} + + +void +WindowArea::UpdateSizeConstaints(const BRect& frame) +{ + // adjust window size soft constraints + fWidthConstraint->SetRightSide(frame.Width()); + fHeightConstraint->SetRightSide(frame.Height()); } @@ -78,6 +190,46 @@ WindowArea::TopWindow() } +void +WindowArea::_UpdateConstraintValues() +{ + SATWindow* topWindow = TopWindow(); + if (topWindow == NULL) + return; + + int32 minWidth, maxWidth; + int32 minHeight, maxHeight; + SATWindow* window = fWindowList.ItemAt(0); + window->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); + for (int32 i = 1; i < fWindowList.CountItems(); i++) { + window = fWindowList.ItemAt(i); + // size limit constraints + int32 minW, maxW; + int32 minH, maxH; + window->GetSizeLimits(&minW, &maxW, &minH, &maxH); + if (minWidth < minW) + minWidth = minW; + if (minHeight < minH) + minHeight = minH; + if (maxWidth < maxW) + maxWidth = maxW; + if (maxHeight < maxH) + maxHeight = maxH; + } + + topWindow->AddDecorator(&minWidth, &maxWidth, &minHeight, &maxHeight); + fMinWidthConstraint->SetRightSide(minWidth); + fMinHeightConstraint->SetRightSide(minHeight); + + fMaxWidthConstraint->SetRightSide(maxWidth); + fMaxHeightConstraint->SetRightSide(maxHeight); + + BRect frame = topWindow->CompleteWindowFrame(); + fWidthConstraint->SetRightSide(frame.Width()); + fHeightConstraint->SetRightSide(frame.Height()); +} + + bool WindowArea::_AddWindow(SATWindow* window, SATWindow* after) { @@ -94,6 +246,8 @@ WindowArea::_AddWindow(SATWindow* window, SATWindow* after) _InitCorners(); fWindowLayerOrder.AddItem(window); + + _UpdateConstraintValues(); return true; } @@ -105,6 +259,8 @@ WindowArea::_RemoveWindow(SATWindow* window) return false; fWindowLayerOrder.RemoveItem(window); + _UpdateConstraintValues(); + window->RemovedFromArea(this); ReleaseReference(); return true; @@ -169,8 +325,24 @@ WindowArea::PropagateToGroup(SATGroup* group) fLeftBottomCrossing = newLeftBottom; fRightBottomCrossing = newRightBottom; - for (int i = 0; i < fWindowList.CountItems(); i++) - fWindowList.ItemAt(i)->PropagateToGroup(group, this); + _InitCorners(); + + BReference oldGroup = fGroup; + // manage constraints + if (Init(group) == false) + return false; + oldGroup->fWindowAreaList.RemoveItem(this); + for (int32 i = 0; i < fWindowList.CountItems(); i++) { + SATWindow* window = fWindowList.ItemAt(i); + if (oldGroup->fSATWindowList.RemoveItem(window) == false) + return false; + if (group->fSATWindowList.AddItem(window) == false) { + _UninitConstraints(); + return false; + } + } + + _UpdateConstraintValues(); return true; } @@ -185,6 +357,24 @@ WindowArea::MoveToTopLayer(SATWindow* window) } +void +WindowArea::_UninitConstraints() +{ + delete fMinWidthConstraint; + delete fMinHeightConstraint; + delete fMaxWidthConstraint; + delete fMaxHeightConstraint; + delete fWidthConstraint; + delete fHeightConstraint; + fMinWidthConstraint = NULL; + fMinHeightConstraint = NULL; + fMaxWidthConstraint = NULL; + fMaxHeightConstraint = NULL; + fWidthConstraint = NULL; + fHeightConstraint = NULL; +} + + BReference WindowArea::_CrossingByPosition(Crossing* crossing, SATGroup* group) { @@ -198,7 +388,7 @@ WindowArea::_CrossingByPosition(Crossing* crossing, SATGroup* group) return crossRef; Tab* oldVTab = crossing->VerticalTab(); - crossRef = hTab->FindCrossing(oldHTab->Position()); + crossRef = hTab->FindCrossing(oldVTab->Position()); if (crossRef) return crossRef; @@ -294,6 +484,38 @@ WindowArea::_UnsetNeighbourCorner(Corner* neighbour, Corner* opponent) } +void +WindowArea::_MoveToSAT(SATWindow* topWindow) +{ + int32 workspace = topWindow->GetWindow()->CurrentWorkspace(); + Desktop* desktop = topWindow->GetWindow()->Desktop(); + + BRect frameSAT(LeftVar()->Value() - kMakePositiveOffset, + TopVar()->Value() - kMakePositiveOffset, + RightVar()->Value() - kMakePositiveOffset, + BottomVar()->Value() - kMakePositiveOffset); + + for (int32 i = 0; i < fWindowList.CountItems(); i++) { + SATWindow* window = fWindowList.ItemAt(i); + window->AdjustSizeLimits(frameSAT); + + BRect frame = window->CompleteWindowFrame(); + float deltaToX = round(frameSAT.left - frame.left); + float deltaToY = round(frameSAT.top - frame.top); + frame.OffsetBy(deltaToX, deltaToY); + float deltaByX = round(frameSAT.right - frame.right); + float deltaByY = round(frameSAT.bottom - frame.bottom); + + desktop->MoveWindowBy(window->GetWindow(), deltaToX, deltaToY, + workspace); + // Update frame to the new position + desktop->ResizeWindowBy(window->GetWindow(), deltaByX, deltaByY); + } + + UpdateSizeConstaints(frameSAT); +} + + Corner::Corner() : status(kNotDockable), @@ -308,21 +530,21 @@ Corner::Trace() const { switch (status) { case kFree: - STRACE_SAT("free corner\n"); + debug_printf("free corner\n"); break; case kUsed: { - STRACE_SAT("attached windows:\n"); + debug_printf("attached windows:\n"); const SATWindowList& list = windowArea->WindowList(); for (int i = 0; i < list.CountItems(); i++) { - STRACE_SAT("- %s\n", list.ItemAt(i)->GetWindow()->Title()); + debug_printf("- %s\n", list.ItemAt(i)->GetWindow()->Title()); } break; } case kNotDockable: - STRACE_SAT("not dockable\n"); + debug_printf("not dockable\n"); break; }; } @@ -333,8 +555,6 @@ Crossing::Crossing(Tab* vertical, Tab* horizontal) fVerticalTab(vertical), fHorizontalTab(horizontal) { - fVerticalTab->AcquireReference(); - fHorizontalTab->AcquireReference(); } @@ -342,9 +562,6 @@ Crossing::~Crossing() { fVerticalTab->RemoveCrossing(this); fHorizontalTab->RemoveCrossing(this); - - fVerticalTab->ReleaseReference(); - fHorizontalTab->ReleaseReference(); } @@ -379,13 +596,13 @@ Crossing::HorizontalTab() const void Crossing::Trace() const { - STRACE_SAT("left-top corner: "); + debug_printf("left-top corner: "); fCorners[Corner::kLeftTop].Trace(); - STRACE_SAT("right-top corner: "); + debug_printf("right-top corner: "); fCorners[Corner::kRightTop].Trace(); - STRACE_SAT("left-bottom corner: "); + debug_printf("left-bottom corner: "); fCorners[Corner::kLeftBottom].Trace(); - STRACE_SAT("right-bottom corner: "); + debug_printf("right-bottom corner: "); fCorners[Corner::kRightBottom].Trace(); } @@ -502,12 +719,14 @@ Tab::FindCrossingIndex(float pos) { if (fOrientation == kVertical) { for (int32 i = 0; i < fCrossingList.CountItems(); i++) { - if (fCrossingList.ItemAt(i)->HorizontalTab()->Position() == pos) + if (fabs(fCrossingList.ItemAt(i)->HorizontalTab()->Position() - pos) + < 0.0001) return i; } } else { for (int32 i = 0; i < fCrossingList.CountItems(); i++) { - if (fCrossingList.ItemAt(i)->VerticalTab()->Position() == pos) + if (fabs(fCrossingList.ItemAt(i)->VerticalTab()->Position() - pos) + < 0.0001) return i; } } @@ -557,7 +776,6 @@ SATGroup::SATGroup() SATGroup::~SATGroup() { - ASSERT(fSATWindowList.CountItems() == 0); // Should be empty //while (fSATWindowList.CountItems() > 0) // RemoveWindow(fSATWindowList.ItemAt(0)); @@ -628,7 +846,7 @@ SATGroup::AddWindow(SATWindow* window, Tab* left, Tab* top, Tab* right, if (!area) return false; // the area register itself in our area list - if (!area->SetGroup(this)) { + if (area->Init(this) == false) { delete area; return false; } @@ -733,18 +951,6 @@ SATGroup::FindVerticalTab(float position) } -void -SATGroup::AdjustWindows(SATWindow* triggerWindow) -{ - // set window locations and sizes - for (int i = 0; i < fSATWindowList.CountItems(); i++) { - SATWindow* windowSAT = fSATWindowList.ItemAt(i); - windowSAT->MoveWindowToSAT( - triggerWindow->GetWindow()->CurrentWorkspace()); - } -} - - void SATGroup::WindowAreaRemoved(WindowArea* area) { @@ -927,7 +1133,7 @@ Tab* SATGroup::_FindTab(const TabList& list, float position) { for (int i = 0; i < list.CountItems(); i++) - if (list.ItemAt(i)->Position() == position) + if (fabs(list.ItemAt(i)->Position() - position) < 0.00001) return list.ItemAt(i); return NULL; diff --git a/src/servers/app/stackandtile/SATGroup.h b/src/servers/app/stackandtile/SATGroup.h index df8feeaefb..74b081adfb 100644 --- a/src/servers/app/stackandtile/SATGroup.h +++ b/src/servers/app/stackandtile/SATGroup.h @@ -14,6 +14,8 @@ #include "ObjectList.h" #include "Referenceable.h" +#include "MagneticBorder.h" + #include "LinearSpec.h" @@ -72,10 +74,10 @@ public: void Trace() const; private: - Corner fCorners[4]; + Corner fCorners[4]; - Tab* fVerticalTab; - Tab* fHorizontalTab; + BReference fVerticalTab; + BReference fHorizontalTab; }; @@ -137,7 +139,12 @@ public: Crossing* rightBottom); ~WindowArea(); - bool SetGroup(SATGroup* group); + bool Init(SATGroup* group); + SATGroup* Group() { return fGroup; } + + void DoGroupLayout(); + void UpdateSizeLimits(); + void UpdateSizeConstaints(const BRect& frame); const SATWindowList& WindowList() { return fWindowList; } const SATWindowList& LayerOrder() { return fWindowLayerOrder; } @@ -159,6 +166,11 @@ public: Tab* TopTab(); Tab* BottomTab(); + Variable* LeftVar() { return LeftTab()->Var(); } + Variable* RightVar() { return RightTab()->Var(); } + Variable* TopVar() { return TopTab()->Var(); } + Variable* BottomVar() { return BottomTab()->Var(); } + BRect Frame(); bool PropagateToGroup(SATGroup* group); @@ -167,6 +179,9 @@ public: private: friend class SATGroup; + void _UninitConstraints(); + void _UpdateConstraintValues(); + /*! SATGroup adds new windows to the area. */ bool _AddWindow(SATWindow* window, SATWindow* after = NULL); @@ -188,7 +203,9 @@ private: BReference _CrossingByPosition(Crossing* crossing, SATGroup* group); - SATGroup* fGroup; + void _MoveToSAT(SATWindow* topWindow); + + BReference fGroup; SATWindowList fWindowList; @@ -198,6 +215,17 @@ private: BReference fRightTopCrossing; BReference fLeftBottomCrossing; BReference fRightBottomCrossing; + + Constraint* fMinWidthConstraint; + Constraint* fMinHeightConstraint; + Constraint* fMaxWidthConstraint; + Constraint* fMaxHeightConstraint; + Constraint* fKeepMaxWidthConstraint; + Constraint* fKeepMaxHeightConstraint; + Constraint* fWidthConstraint; + Constraint* fHeightConstraint; + + MagneticBorder fMagneticBorder; }; @@ -219,8 +247,6 @@ public: LinearSpec* GetLinearSpec() { return &fLinearSpec; } - void AdjustWindows(SATWindow* triggerWindow); - /*! Create a new WindowArea from the crossing and add the window. */ bool AddWindow(SATWindow* window, Tab* left, Tab* top, Tab* right, Tab* bottom); diff --git a/src/servers/app/stackandtile/SATWindow.cpp b/src/servers/app/stackandtile/SATWindow.cpp index 06f5f92f2f..72bed893cf 100644 --- a/src/servers/app/stackandtile/SATWindow.cpp +++ b/src/servers/app/stackandtile/SATWindow.cpp @@ -20,235 +20,6 @@ using namespace BPrivate; -using namespace LinearProgramming; - - -const float kExtentPenalty = 1; -const float kHighPenalty = 10; -const float kInequalityPenalty = 10000; - - -GroupCookie::GroupCookie(SATWindow* satWindow) - : - fSATWindow(satWindow), - - fWindowArea(NULL), - - fLeftBorder(NULL), - fTopBorder(NULL), - fRightBorder(NULL), - fBottomBorder(NULL), - - fMinWidthConstraint(NULL), - fMinHeightConstraint(NULL), - fMaxWidthConstraint(NULL), - fMaxHeightConstraint(NULL), - fWidthConstraint(NULL), - fHeightConstraint(NULL) -{ -} - - -GroupCookie::~GroupCookie() -{ - Uninit(); -} - - -void -GroupCookie::DoGroupLayout() -{ - if (!fSATGroup.Get()) - return; - - BRect frame = fSATWindow->CompleteWindowFrame(); - // Make it also work for solver which don't support negative variables - frame.OffsetBy(kMakePositiveOffset, kMakePositiveOffset); - - // adjust window size soft constraints - fWidthConstraint->SetRightSide(frame.Width()); - fHeightConstraint->SetRightSide(frame.Height()); - - LinearSpec* linearSpec = fSATGroup->GetLinearSpec(); - Constraint* leftConstraint = linearSpec->AddConstraint(1.0, fLeftBorder, - kEQ, frame.left); - Constraint* topConstraint = linearSpec->AddConstraint(1.0, fTopBorder, kEQ, - frame.top); - - // give soft constraints a high penalty - fWidthConstraint->SetPenaltyNeg(kHighPenalty); - fWidthConstraint->SetPenaltyPos(kHighPenalty); - fHeightConstraint->SetPenaltyNeg(kHighPenalty); - fHeightConstraint->SetPenaltyPos(kHighPenalty); - - // After we set the new parameter solve and apply the new layout. - ResultType result; - for (int32 tries = 0; tries < 15; tries++) { - result = fSATGroup->GetLinearSpec()->Solve(); - if (result == kInfeasible) { - debug_printf("can't solve constraints!\n"); - break; - } - if (result == kOptimal) { - fSATGroup->AdjustWindows(fSATWindow); - break; - } - } - - // set penalties back to normal - fWidthConstraint->SetPenaltyNeg(kExtentPenalty); - fWidthConstraint->SetPenaltyPos(kExtentPenalty); - fHeightConstraint->SetPenaltyNeg(kExtentPenalty); - fHeightConstraint->SetPenaltyPos(kExtentPenalty); - - linearSpec->RemoveConstraint(leftConstraint); - linearSpec->RemoveConstraint(topConstraint); -} - - -void -GroupCookie::MoveWindow(int32 workspace) -{ - Window* window = fSATWindow->GetWindow(); - Desktop* desktop = window->Desktop(); - - BRect frame = fSATWindow->CompleteWindowFrame(); - BRect frameSAT(fLeftBorder->Value() - kMakePositiveOffset, - fTopBorder->Value() - kMakePositiveOffset, - fRightBorder->Value() - kMakePositiveOffset, - fBottomBorder->Value() - kMakePositiveOffset); - - fSATWindow->AdjustSizeLimits(frameSAT); - desktop->MoveWindowBy(window, round(frameSAT.left - frame.left), - round(frameSAT.top - frame.top), workspace); - - // Update frame to the new position - frame.OffsetBy(round(frameSAT.left - frame.left), - round(frameSAT.top - frame.top)); - desktop->ResizeWindowBy(window, round(frameSAT.right - frame.right), - round(frameSAT.bottom - frame.bottom)); - - UpdateSizeConstaints(frameSAT); -} - - -void -GroupCookie::SetSizeLimits(int32 minWidth, int32 maxWidth, int32 minHeight, - int32 maxHeight) -{ - fMinWidthConstraint->SetRightSide(minWidth); - fMinHeightConstraint->SetRightSide(minHeight); - fMaxWidthConstraint->SetRightSide(maxWidth); - fMaxHeightConstraint->SetRightSide(maxHeight); -} - - -void -GroupCookie::UpdateSizeConstaints(const BRect& frame) -{ - // adjust window size soft constraints - if (fSATWindow->IsHResizeable() == true) - fWidthConstraint->SetRightSide(frame.Width()); - if (fSATWindow->IsVResizeable() == true) - fHeightConstraint->SetRightSide(frame.Height()); -} - - -bool -GroupCookie::Init(SATGroup* group, WindowArea* area) -{ - ASSERT(fSATGroup.Get() == NULL); - - fSATGroup.SetTo(group); - fWindowArea = area; - - LinearSpec* linearSpec = group->GetLinearSpec(); - // create variables - fLeftBorder = area->LeftTab()->Var(); - fTopBorder = area->TopTab()->Var(); - fRightBorder = area->RightTab()->Var(); - fBottomBorder = area->BottomTab()->Var(); - - // size limit constraints - int32 minWidth, maxWidth; - int32 minHeight, maxHeight; - fSATWindow->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); - fSATWindow->AddDecorator(&minWidth, &maxWidth, &minHeight, &maxHeight); - - fMinWidthConstraint = linearSpec->AddConstraint(1.0, fRightBorder, -1.0, - fLeftBorder, kGE, minWidth); - fMinHeightConstraint = linearSpec->AddConstraint(1.0, fBottomBorder, -1.0, - fTopBorder, kGE, minHeight); - - fMaxWidthConstraint = linearSpec->AddConstraint(1.0, fRightBorder, -1.0, - fLeftBorder, kLE, maxWidth, kInequalityPenalty, kInequalityPenalty); - fMaxHeightConstraint = linearSpec->AddConstraint(1.0, fBottomBorder, -1.0, - fTopBorder, kLE, maxHeight, kInequalityPenalty, kInequalityPenalty); - - // Width and height have soft constraints - BRect frame = fSATWindow->CompleteWindowFrame(); - fWidthConstraint = linearSpec->AddConstraint(1.0, fRightBorder, -1.0, - fLeftBorder, kEQ, frame.Width(), kExtentPenalty, - kExtentPenalty); - fHeightConstraint = linearSpec->AddConstraint(-1.0, fTopBorder, 1.0, - fBottomBorder, kEQ, frame.Height(), kExtentPenalty, - kExtentPenalty); - - if (!fMinWidthConstraint || !fMinHeightConstraint || !fWidthConstraint - || !fHeightConstraint || !fMaxWidthConstraint - || !fMaxHeightConstraint) { - // clean up - Uninit(); - return false; - } - - return true; -} - - -void -GroupCookie::Uninit() -{ - fLeftBorder = NULL; - fTopBorder = NULL; - fRightBorder = NULL; - fBottomBorder = NULL; - - delete fMinWidthConstraint; - delete fMinHeightConstraint; - delete fMaxWidthConstraint; - delete fMaxHeightConstraint; - delete fWidthConstraint; - delete fHeightConstraint; - fMinWidthConstraint = NULL; - fMinHeightConstraint = NULL; - fMaxWidthConstraint = NULL; - fMaxHeightConstraint = NULL; - fWidthConstraint = NULL; - fHeightConstraint = NULL; - - fSATGroup.Unset(); - fWindowArea = NULL; -} - - -bool -GroupCookie::PropagateToGroup(SATGroup* group, WindowArea* area) -{ - if (!fSATGroup->fSATWindowList.RemoveItem(fSATWindow)) - return false; - Uninit(); - - if (!Init(group, area)) - return false; - - if (!area->SetGroup(group) || !group->fSATWindowList.AddItem(fSATWindow)) { - Uninit(); - return false; - } - - return true; -} // #pragma mark - @@ -259,13 +30,11 @@ SATWindow::SATWindow(StackAndTile* sat, Window* window) fWindow(window), fStackAndTile(sat), - fOwnGroupCookie(this), - fForeignGroupCookie(this), + fWindowArea(NULL), fOngoingSnapping(NULL), fSATStacking(this), - fSATTiling(this), - fShutdown(false) + fSATTiling(this) { fId = _GenerateId(); @@ -278,9 +47,6 @@ SATWindow::SATWindow(StackAndTile* sat, Window* window) fOriginalWidth = frame.Width(); fOriginalHeight = frame.Height(); - fGroupCookie = &fOwnGroupCookie; - _InitGroup(); - fSATSnappingBehaviourList.AddItem(&fSATStacking); fSATSnappingBehaviourList.AddItem(&fSATTiling); } @@ -288,12 +54,8 @@ SATWindow::SATWindow(StackAndTile* sat, Window* window) SATWindow::~SATWindow() { - fShutdown = true; - - if (fForeignGroupCookie.GetGroup()) - fForeignGroupCookie.GetGroup()->RemoveWindow(this); - if (fOwnGroupCookie.GetGroup()) - fOwnGroupCookie.GetGroup()->RemoveWindow(this); + if (fWindowArea != NULL) + fWindowArea->Group()->RemoveWindow(this); } @@ -307,22 +69,33 @@ SATWindow::GetDecorator() const SATGroup* SATWindow::GetGroup() { - if (!fGroupCookie->GetGroup()) - _InitGroup(); + if (fWindowArea == NULL) { + SATGroup* group = new (std::nothrow)SATGroup; + if (group == NULL) + return group; + BReference groupRef; + groupRef.SetTo(group, true); - // manually set the tabs of the single window - WindowArea* windowArea = fGroupCookie->GetWindowArea(); - if (!PositionManagedBySAT() && windowArea) { + /* AddWindow also will trigger the window to hold a reference on the new + group. */ + if (group->AddWindow(this, NULL, NULL, NULL, NULL) == false) + return NULL; + } + + ASSERT(fWindowArea != NULL); + + // manually set the tabs of the single window + if (PositionManagedBySAT() == false) { BRect frame = CompleteWindowFrame(); - windowArea->LeftTopCrossing()->VerticalTab()->SetPosition(frame.left); - windowArea->LeftTopCrossing()->HorizontalTab()->SetPosition(frame.top); - windowArea->RightBottomCrossing()->VerticalTab()->SetPosition( + fWindowArea->LeftTopCrossing()->VerticalTab()->SetPosition(frame.left); + fWindowArea->LeftTopCrossing()->HorizontalTab()->SetPosition(frame.top); + fWindowArea->RightBottomCrossing()->VerticalTab()->SetPosition( frame.right); - windowArea->RightBottomCrossing()->HorizontalTab()->SetPosition( + fWindowArea->RightBottomCrossing()->HorizontalTab()->SetPosition( frame.bottom); } - return fGroupCookie->GetGroup(); + return fWindowArea->Group(); } @@ -340,16 +113,11 @@ SATWindow::HandleMessage(SATWindow* sender, BPrivate::LinkReceiver& link, bool -SATWindow::PropagateToGroup(SATGroup* group, WindowArea* area) +SATWindow::PropagateToGroup(SATGroup* group) { - return fGroupCookie->PropagateToGroup(group, area); -} - - -void -SATWindow::MoveWindowToSAT(int32 workspace) -{ - fGroupCookie->MoveWindow(workspace); + if (fWindowArea == NULL) + return false; + return fWindowArea->PropagateToGroup(group); } @@ -358,16 +126,7 @@ SATWindow::AddedToGroup(SATGroup* group, WindowArea* area) { STRACE_SAT("SATWindow::AddedToGroup group: %p window %s\n", group, fWindow->Title()); - if (fGroupCookie == &fForeignGroupCookie) - return false; - if (fOwnGroupCookie.GetGroup()) - fGroupCookie = &fForeignGroupCookie; - - if (!fGroupCookie->Init(group, area)) { - fGroupCookie = &fOwnGroupCookie; - return false; - } - + fWindowArea = area; return true; } @@ -382,18 +141,7 @@ SATWindow::RemovedFromGroup(SATGroup* group, bool stayBelowMouse) if (group->CountItems() == 1) group->WindowAt(0)->_RestoreOriginalSize(false); - if (fShutdown) { - fGroupCookie->Uninit(); - return true; - } - - ASSERT(fGroupCookie->GetGroup() == group); - fGroupCookie->Uninit(); - if (fGroupCookie == &fOwnGroupCookie) - _InitGroup(); - else - fGroupCookie = &fOwnGroupCookie; - + fWindowArea = NULL; return true; } @@ -485,7 +233,8 @@ SATWindow::DoGroupLayout() if (!PositionManagedBySAT()) return; - fGroupCookie->DoGroupLayout(); + if (fWindowArea != NULL) + fWindowArea->DoGroupLayout(); } @@ -584,9 +333,8 @@ SATWindow::SetOriginalSizeLimits(int32 minWidth, int32 maxWidth, fOriginalMinHeight = minHeight; fOriginalMaxHeight = maxHeight; - GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); - AddDecorator(&minWidth, &maxWidth, &minHeight, &maxHeight); - fGroupCookie->SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight); + if (fWindowArea != NULL) + fWindowArea->UpdateSizeLimits(); } @@ -604,7 +352,8 @@ SATWindow::Resized() if (vResizeable) fOriginalHeight = frame.Height(); - fGroupCookie->UpdateSizeConstaints(CompleteWindowFrame()); + if (fWindowArea != NULL) + fWindowArea->UpdateSizeConstaints(CompleteWindowFrame()); } @@ -653,7 +402,7 @@ SATWindow::CompleteWindowFrame() bool SATWindow::PositionManagedBySAT() { - if (fGroupCookie->GetGroup() && fGroupCookie->GetGroup()->CountItems() == 1) + if (fWindowArea == NULL || fWindowArea->Group()->CountItems() == 1) return false; return true; @@ -723,25 +472,6 @@ SATWindow::GetSettings(BMessage& message) } -void -SATWindow::_InitGroup() -{ - ASSERT(fGroupCookie == &fOwnGroupCookie); - ASSERT(fOwnGroupCookie.GetGroup() == NULL); - STRACE_SAT("SATWindow::_InitGroup %s\n", fWindow->Title()); - SATGroup* group = new (std::nothrow)SATGroup; - if (!group) - return; - BReference groupRef; - groupRef.SetTo(group, true); - - /* AddWindow also will trigger the window to hold a reference on the new - group. */ - if (!groupRef->AddWindow(this, NULL, NULL, NULL, NULL)) - STRACE_SAT("SATWindow::_InitGroup(): adding window to group failed\n"); -} - - uint64 SATWindow::_GenerateId() { diff --git a/src/servers/app/stackandtile/SATWindow.h b/src/servers/app/stackandtile/SATWindow.h index bb21fc8251..0ab566e255 100644 --- a/src/servers/app/stackandtile/SATWindow.h +++ b/src/servers/app/stackandtile/SATWindow.h @@ -11,8 +11,8 @@ #include -#include "MagneticBorder.h" #include "SATDecorator.h" +#include "SATGroup.h" #include "Stacking.h" #include "Tiling.h" @@ -23,53 +23,6 @@ class StackAndTile; class Window; -class GroupCookie -{ -public: - GroupCookie(SATWindow* satWindow); - ~GroupCookie(); - - bool Init(SATGroup* group, WindowArea* area); - void Uninit(); - - void DoGroupLayout(); - void MoveWindow(int32 workspace); - void SetSizeLimits(int32 minWidth, int32 maxWidth, - int32 minHeight, int32 maxHeight); - void UpdateSizeConstaints(const BRect& frame); - - SATGroup* GetGroup() { return fSATGroup.Get(); } - - WindowArea* GetWindowArea() { return fWindowArea; } - - bool PropagateToGroup(SATGroup* group, - WindowArea* area); - -private: - SATWindow* fSATWindow; - - BReference fSATGroup; - - WindowArea* fWindowArea; - - Variable* fLeftBorder; - Variable* fTopBorder; - Variable* fRightBorder; - Variable* fBottomBorder; - - Constraint* fMinWidthConstraint; - Constraint* fMinHeightConstraint; - Constraint* fMaxWidthConstraint; - Constraint* fMaxHeightConstraint; - Constraint* fKeepMaxWidthConstraint; - Constraint* fKeepMaxHeightConstraint; - Constraint* fWidthConstraint; - Constraint* fHeightConstraint; - - MagneticBorder fMagneticBorder; -}; - - class SATWindow { public: SATWindow(StackAndTile* sat, Window* window); @@ -81,18 +34,13 @@ public: Desktop* GetDesktop() { return fDesktop; } //! Can be NULL if memory allocation failed! SATGroup* GetGroup(); - WindowArea* GetWindowArea() { - return fGroupCookie->GetWindowArea(); } + WindowArea* GetWindowArea() { return fWindowArea; } bool HandleMessage(SATWindow* sender, BPrivate::LinkReceiver& link, BPrivate::LinkSender& reply); - bool PropagateToGroup(SATGroup* group, - WindowArea* area); - - //! Move the window to the tab's position. - void MoveWindowToSAT(int32 workspace); + bool PropagateToGroup(SATGroup* group); // hook function called from SATGroup bool AddedToGroup(SATGroup* group, WindowArea* area); @@ -139,7 +87,6 @@ public: bool SetSettings(const BMessage& message); void GetSettings(BMessage& message); private: - void _InitGroup(); uint64 _GenerateId(); void _UpdateSizeLimits(); @@ -151,11 +98,7 @@ private: Desktop* fDesktop; //! Current group. - GroupCookie* fGroupCookie; - /*! If the window is added to another group the own group is cached - here. */ - GroupCookie fOwnGroupCookie; - GroupCookie fForeignGroupCookie; + WindowArea* fWindowArea; SATSnappingBehaviour* fOngoingSnapping; SATStacking fSATStacking; @@ -163,8 +106,6 @@ private: SATSnappingBehaviourList fSATSnappingBehaviourList; - bool fShutdown; - int32 fOriginalMinWidth; int32 fOriginalMaxWidth; int32 fOriginalMinHeight; diff --git a/src/servers/app/stackandtile/Stacking.cpp b/src/servers/app/stackandtile/Stacking.cpp index d2e2710ca6..f7192d8726 100644 --- a/src/servers/app/stackandtile/Stacking.cpp +++ b/src/servers/app/stackandtile/Stacking.cpp @@ -237,13 +237,14 @@ SATStacking::FindSnappingCandidates(SATGroup* group) for (int i = 0; i < group->CountItems(); i++) { SATWindow* satWindow = group->WindowAt(i); // search for stacking parent - Window* win = satWindow->GetWindow(); - if (win == window || !win->Decorator()) + Window* parentWindow = satWindow->GetWindow(); + if (parentWindow == window || parentWindow->Decorator() == NULL) continue; - if (_IsStackableWindow(win) == false + if (_IsStackableWindow(parentWindow) == false || _IsStackableWindow(window) == false) continue; - Decorator::Tab* tab = win->Decorator()->TabAt(win->PositionInStack()); + Decorator::Tab* tab = parentWindow->Decorator()->TabAt( + parentWindow->PositionInStack()); if (tab == NULL) continue; if (tab->tabRect.Contains(mousePosition)) {