Ejemplo n.º 1
0
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;
	}
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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();
}
Ejemplo n.º 5
0
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());
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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);
	}
}
Ejemplo n.º 8
0
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);
	}
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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;
}