void SATGroup::_BottomNeighbours(WindowAreaList& neighbourWindows, WindowArea* parent) { float startPos = parent->LeftBottomCrossing()->VerticalTab()->Position(); float endPos = parent->RightBottomCrossing()->VerticalTab()->Position(); Tab* tab = parent->LeftBottomCrossing()->HorizontalTab(); const CrossingList* crossingList = tab->GetCrossingList(); for (int i = 0; i < crossingList->CountItems(); i++) { Corner* corner = crossingList->ItemAt(i)->LeftBottomCorner(); if (corner->status != Corner::kUsed) continue; WindowArea* area = corner->windowArea; float pos1 = area->LeftBottomCrossing()->VerticalTab()->Position(); float pos2 = area->RightBottomCrossing()->VerticalTab()->Position(); if (pos1 < endPos && pos2 > startPos) neighbourWindows.AddItem(area); if (pos2 > endPos) break; } }
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); }
bool SATWindow::StackWindow(SATWindow* child) { SATGroup* group = GetGroup(); WindowArea* area = GetWindowArea(); if (!group || !area) return false; bool status = group->AddWindow(child, area, this); if (status) { area->WindowList().ItemAt(0)->SetStackedMode(true); // for the case we are the first added window child->SetStackedMode(true); } DoGroupLayout(); return true; }
SATGroup* SATWindow::GetGroup() { if (!fGroupCookie->GetGroup()) _InitGroup(); // manually set the tabs of the single window WindowArea* windowArea = fGroupCookie->GetWindowArea(); if (!PositionManagedBySAT() && windowArea) { BRect frame = CompleteWindowFrame(); windowArea->LeftTopCrossing()->VerticalTab()->SetPosition(frame.left); windowArea->LeftTopCrossing()->HorizontalTab()->SetPosition(frame.top); windowArea->RightBottomCrossing()->VerticalTab()->SetPosition( frame.right); windowArea->RightBottomCrossing()->HorizontalTab()->SetPosition( frame.bottom); } return fGroupCookie->GetGroup(); }
void StackAndTile::_ActivateWindow(SATWindow* satWindow) { if (satWindow == NULL) return; SATGroup* group = satWindow->GetGroup(); if (group == NULL) return; Desktop* desktop = satWindow->GetWindow()->Desktop(); if (desktop == NULL) return; WindowArea* area = satWindow->GetWindowArea(); if (area == NULL) return; area->MoveToTopLayer(satWindow); // save the active window of the current group SATWindow* frontWindow = GetSATWindow(fDesktop->FocusWindow()); SATGroup* currentGroup = _GetSATGroup(frontWindow); if (currentGroup != NULL && currentGroup != group && frontWindow != NULL) currentGroup->SetActiveWindow(frontWindow); else group->SetActiveWindow(satWindow); const WindowAreaList& areas = group->GetAreaList(); int32 areasCount = areas.CountItems(); for (int32 i = 0; i < areasCount; i++) { WindowArea* currentArea = areas.ItemAt(i); if (currentArea == area) continue; desktop->ActivateWindow(currentArea->TopWindow()->GetWindow()); } desktop->ActivateWindow(satWindow->GetWindow()); }
status_t SATGroup::ArchiveGroup(BMessage& archive) { archive.AddInt32("htab_count", fHorizontalTabs.CountItems()); archive.AddInt32("vtab_count", fVerticalTabs.CountItems()); for (int i = 0; i < fWindowAreaList.CountItems(); i++) { WindowArea* area = fWindowAreaList.ItemAt(i); int32 leftTab = fVerticalTabs.IndexOf(area->LeftTab()); int32 rightTab = fVerticalTabs.IndexOf(area->RightTab()); int32 topTab = fHorizontalTabs.IndexOf(area->TopTab()); int32 bottomTab = fHorizontalTabs.IndexOf(area->BottomTab()); BMessage areaMessage; areaMessage.AddInt32("left_tab", leftTab); areaMessage.AddInt32("right_tab", rightTab); areaMessage.AddInt32("top_tab", topTab); areaMessage.AddInt32("bottom_tab", bottomTab); const SATWindowList& windowList = area->WindowList(); for (int a = 0; a < windowList.CountItems(); a++) areaMessage.AddInt64("window", windowList.ItemAt(a)->Id()); archive.AddMessage("area", &areaMessage); } return B_OK; }
void StackAndTile::WindowWorkspacesChanged(Window* window, uint32 workspaces) { SATWindow* satWindow = GetSATWindow(window); if (satWindow == NULL) return; SATGroup* group = satWindow->GetGroup(); if (group == NULL) return; Desktop* desktop = satWindow->GetWindow()->Desktop(); if (desktop == NULL) return; const WindowAreaList& areaList = group->GetAreaList(); for (int32 i = 0; i < areaList.CountItems(); i++) { WindowArea* area = areaList.ItemAt(i); if (area->WindowList().HasItem(satWindow)) continue; SATWindow* topWindow = area->TopWindow(); desktop->SetWindowWorkspaces(topWindow->GetWindow(), workspaces); } }
void StackAndTile::WindowSentBehind(Window* window, Window* behindOf) { SATWindow* satWindow = GetSATWindow(window); if (satWindow == NULL) return; SATGroup* group = satWindow->GetGroup(); if (group == NULL) return; Desktop* desktop = satWindow->GetWindow()->Desktop(); if (desktop == NULL) return; const WindowAreaList& areaList = group->GetAreaList(); for (int32 i = 0; i < areaList.CountItems(); i++) { WindowArea* area = areaList.ItemAt(i); SATWindow* topWindow = area->TopWindow(); if (topWindow == NULL || topWindow == satWindow) continue; desktop->SendWindowBehind(topWindow->GetWindow(), behindOf); } }
bool SATGroup::AddWindow(SATWindow* window, Tab* left, Tab* top, Tab* right, Tab* bottom) { STRACE_SAT("SATGroup::AddWindow\n"); // first check if we have to create tabs and missing corners. BReference<Tab> leftRef, rightRef, topRef, bottomRef; BReference<Crossing> leftTopRef, rightTopRef, leftBottomRef, rightBottomRef; if (left && top) leftTopRef = left->FindCrossing(top); if (right && top) rightTopRef = right->FindCrossing(top); if (left && bottom) leftBottomRef = left->FindCrossing(bottom); if (right && bottom) rightBottomRef = right->FindCrossing(bottom); if (!left) { leftRef = _AddVerticalTab(); left = leftRef.Get(); } if (!top) { topRef = _AddHorizontalTab(); top = topRef.Get(); } if (!right) { rightRef = _AddVerticalTab(); right = rightRef.Get(); } if (!bottom) { bottomRef = _AddHorizontalTab(); bottom = bottomRef.Get(); } if (!left || !top || !right || !bottom) return false; if (!leftTopRef) { leftTopRef = left->AddCrossing(top); if (!leftTopRef) return false; } if (!rightTopRef) { rightTopRef = right->AddCrossing(top); if (!rightTopRef) return false; } if (!leftBottomRef) { leftBottomRef = left->AddCrossing(bottom); if (!leftBottomRef) return false; } if (!rightBottomRef) { rightBottomRef = right->AddCrossing(bottom); if (!rightBottomRef) return false; } WindowArea* area = new(std::nothrow) WindowArea(leftTopRef, rightTopRef, leftBottomRef, rightBottomRef); if (!area) return false; // the area register itself in our area list if (area->Init(this) == false) { delete area; return false; } // delete the area if AddWindow failed / release our reference on it BReference<WindowArea> areaRef(area, true); return AddWindow(window, area); }
bool StackingEventHandler::HandleMessage(SATWindow* sender, BPrivate::LinkReceiver& link, BPrivate::LinkSender& reply) { Desktop* desktop = sender->GetDesktop(); StackAndTile* stackAndTile = sender->GetStackAndTile(); int32 what; link.Read<int32>(&what); switch (what) { case kAddWindowToStack: { port_id port; int32 token; team_id team; link.Read<port_id>(&port); link.Read<int32>(&token); link.Read<team_id>(&team); int32 position; if (link.Read<int32>(&position) != B_OK) return false; WindowArea* area = sender->GetWindowArea(); if (!area) return false; if (position < 0) position = area->WindowList().CountItems() - 1; SATWindow* parent = area->WindowList().ItemAt(position); Window* window = desktop->WindowForClientLooperPort(port); if (!parent || !window) { reply.StartMessage(B_BAD_VALUE); reply.Flush(); break; } SATWindow* candidate = stackAndTile->GetSATWindow(window); if (!candidate) return false; if (!parent->StackWindow(candidate)) return false; reply.StartMessage(B_OK); reply.Flush(); break; } case kRemoveWindowFromStack: { port_id port; int32 token; team_id team; link.Read<port_id>(&port); link.Read<int32>(&token); if (link.Read<team_id>(&team) != B_OK) return false; SATGroup* group = sender->GetGroup(); if (!group) return false; Window* window = desktop->WindowForClientLooperPort(port); if (!window) { reply.StartMessage(B_BAD_VALUE); reply.Flush(); break; } SATWindow* candidate = stackAndTile->GetSATWindow(window); if (!candidate) return false; if (!group->RemoveWindow(candidate, false)) return false; break; } case kRemoveWindowFromStackAt: { int32 position; if (link.Read<int32>(&position) != B_OK) return false; SATGroup* group = sender->GetGroup(); WindowArea* area = sender->GetWindowArea(); if (!area || !group) return false; SATWindow* removeWindow = area->WindowList().ItemAt(position); if (!removeWindow) { reply.StartMessage(B_BAD_VALUE); reply.Flush(); break; } if (!group->RemoveWindow(removeWindow, false)) return false; ServerWindow* window = removeWindow->GetWindow()->ServerWindow(); reply.StartMessage(B_OK); reply.Attach<port_id>(window->ClientLooperPort()); reply.Attach<int32>(window->ClientToken()); reply.Attach<team_id>(window->ClientTeam()); reply.Flush(); break; } case kCountWindowsOnStack: { WindowArea* area = sender->GetWindowArea(); if (!area) return false; reply.StartMessage(B_OK); reply.Attach<int32>(area->WindowList().CountItems()); reply.Flush(); break; } case kWindowOnStackAt: { int32 position; if (link.Read<int32>(&position) != B_OK) return false; WindowArea* area = sender->GetWindowArea(); if (!area) return false; SATWindow* satWindow = area->WindowList().ItemAt(position); if (!satWindow) { reply.StartMessage(B_BAD_VALUE); reply.Flush(); break; } ServerWindow* window = satWindow->GetWindow()->ServerWindow(); reply.StartMessage(B_OK); reply.Attach<port_id>(window->ClientLooperPort()); reply.Attach<int32>(window->ClientToken()); reply.Attach<team_id>(window->ClientTeam()); reply.Flush(); break; } case kStackHasWindow: { port_id port; int32 token; team_id team; link.Read<port_id>(&port); link.Read<int32>(&token); if (link.Read<team_id>(&team) != B_OK) return false; Window* window = desktop->WindowForClientLooperPort(port); if (!window) { reply.StartMessage(B_BAD_VALUE); reply.Flush(); break; } SATWindow* candidate = stackAndTile->GetSATWindow(window); if (!candidate) return false; WindowArea* area = sender->GetWindowArea(); if (!area) return false; reply.StartMessage(B_OK); reply.Attach<bool>(area->WindowList().HasItem(candidate)); reply.Flush(); break; } default: return false; } return true; }