* 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
This commit is contained in:
Clemens Zeidler 2011-08-09 22:55:20 +00:00
parent d51bfbb57c
commit e0bc3d9e2b
5 changed files with 335 additions and 431 deletions

View File

@ -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<SATGroup> 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<Crossing>
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;

View File

@ -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<Tab> fVerticalTab;
BReference<Tab> 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<Crossing> _CrossingByPosition(Crossing* crossing,
SATGroup* group);
SATGroup* fGroup;
void _MoveToSAT(SATWindow* topWindow);
BReference<SATGroup> fGroup;
SATWindowList fWindowList;
@ -198,6 +215,17 @@ private:
BReference<Crossing> fRightTopCrossing;
BReference<Crossing> fLeftBottomCrossing;
BReference<Crossing> 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);

View File

@ -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<SATGroup> 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<SATGroup> 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()
{

View File

@ -11,8 +11,8 @@
#include <Region.h>
#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<SATGroup> 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;

View File

@ -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)) {