bool StackAndTile::_HandleMessage(BPrivate::LinkReceiver& link, BPrivate::LinkSender& reply) { int32 what; link.Read<int32>(&what); switch (what) { case BPrivate::kSaveAllGroups: { BMessage allGroupsArchive; GroupIterator groups(this, fDesktop); while (true) { SATGroup* group = groups.NextGroup(); if (group == NULL) break; if (group->CountItems() <= 1) continue; BMessage groupArchive; if (group->ArchiveGroup(groupArchive) != B_OK) continue; allGroupsArchive.AddMessage("group", &groupArchive); } int32 size = allGroupsArchive.FlattenedSize(); char buffer[size]; if (allGroupsArchive.Flatten(buffer, size) == B_OK) { reply.StartMessage(B_OK); reply.Attach<int32>(size); reply.Attach(buffer, size); } else reply.StartMessage(B_ERROR); reply.Flush(); break; } case BPrivate::kRestoreGroup: { int32 size; if (link.Read<int32>(&size) == B_OK) { char buffer[size]; BMessage group; if (link.Read(buffer, size) == B_OK && group.Unflatten(buffer) == B_OK) { status_t status = SATGroup::RestoreGroup(group, this); reply.StartMessage(status); reply.Flush(); } } break; } default: return false; } return true; }
void SATStacking::WindowLookChanged(window_look look) { Window* window = fSATWindow->GetWindow(); WindowStack* stack = window->GetWindowStack(); if (stack == NULL) return; SATGroup* group = fSATWindow->GetGroup(); if (group == NULL) return; if (stack->CountWindows() > 1 && _IsStackableWindow(window) == false) group->RemoveWindow(fSATWindow); }
void StackAndTile::WindowHidden(Window* window, bool fromMinimize) { SATWindow* satWindow = GetSATWindow(window); if (satWindow == NULL) return; SATGroup* group = satWindow->GetGroup(); if (group == NULL) return; if (fromMinimize == false && group->CountItems() > 1) group->RemoveWindow(satWindow, false); }
SATGroup* StackAndTile::_GetSATGroup(SATWindow* window) { if (window == NULL) return NULL; SATGroup* group = window->GetGroup(); if (group == NULL) return NULL; if (group->CountItems() < 1) return NULL; return group; }
void StackAndTile::WindowFeelChanged(Window* window, window_feel feel) { // check if it is still a compatible feel if (feel == B_NORMAL_WINDOW_FEEL) return; SATWindow* satWindow = GetSATWindow(window); if (satWindow == NULL) return; SATGroup* group = satWindow->GetGroup(); if (group == NULL) return; if (group->CountItems() > 1) group->RemoveWindow(satWindow, false); }
void StackAndTile::_StartSAT() { STRACE_SAT("StackAndTile::_StartSAT()\n"); if (!fCurrentSATWindow) return; // Remove window from the group. SATGroup* group = fCurrentSATWindow->GetGroup(); if (group == NULL) return; group->RemoveWindow(fCurrentSATWindow, false); // Bring window to the front. (in focus follow mouse this is not // automatically the case) _ActivateWindow(fCurrentSATWindow); fCurrentSATWindow->FindSnappingCandidates(); }
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; }
void StackAndTile::WindowMinimized(Window* window, bool minimize) { 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; for (int i = 0; i < group->CountItems(); i++) { SATWindow* listWindow = group->WindowAt(i); if (listWindow != satWindow) listWindow->GetWindow()->ServerWindow()->NotifyMinimize(minimize); } }
bool SATWindowBehaviour::AlterDeltaForSnap(Window* window, BPoint& delta, bigtime_t now) { if (DefaultWindowBehaviour::AlterDeltaForSnap(window, delta, now) == true) return true; SATWindow* satWindow = fStackAndTile->GetSATWindow(window); if (satWindow == NULL) return false; SATGroup* group = satWindow->GetGroup(); if (group == NULL) return false; BRect groupFrame = group->WindowAt(0)->CompleteWindowFrame(); for (int32 i = 1; i < group->CountItems(); i++) groupFrame = groupFrame | group->WindowAt(i)->CompleteWindowFrame(); return fMagneticBorder.AlterDeltaForSnap(window->Screen(), groupFrame, delta, now); }
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()); }
void SATWindow::FindSnappingCandidates() { fOngoingSnapping = NULL; if (fWindow->Feel() != B_NORMAL_WINDOW_FEEL) return; GroupIterator groupIterator(fStackAndTile, GetWindow()->Desktop()); for (SATGroup* group = groupIterator.NextGroup(); group; group = groupIterator.NextGroup()) { if (group->CountItems() == 1 && group->WindowAt(0)->GetWindow()->Feel() != B_NORMAL_WINDOW_FEEL) continue; for (int i = 0; i < fSATSnappingBehaviourList.CountItems(); i++) { if (fSATSnappingBehaviourList.ItemAt(i)->FindSnappingCandidates( group)) { fOngoingSnapping = fSATSnappingBehaviourList.ItemAt(i); return; } } } }
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 StackAndTile::KeyPressed(uint32 what, int32 key, int32 modifiers) { if (what == B_MODIFIERS_CHANGED || (what == B_UNMAPPED_KEY_DOWN && key == kRightOptionKey) || (what == B_UNMAPPED_KEY_UP && key == kRightOptionKey)) { // switch to and from stacking and snapping mode bool wasPressed = fSATKeyPressed; fSATKeyPressed = (what == B_MODIFIERS_CHANGED && (modifiers & kModifiers) == B_OPTION_KEY) || (what == B_UNMAPPED_KEY_DOWN && key == kRightOptionKey); if (wasPressed && !fSATKeyPressed) _StopSAT(); if (!wasPressed && fSATKeyPressed) _StartSAT(); } if (!SATKeyPressed() || what != B_KEY_DOWN) return false; SATWindow* frontWindow = GetSATWindow(fDesktop->FocusWindow()); SATGroup* currentGroup = _GetSATGroup(frontWindow); switch (key) { case kLeftArrowKey: case kRightArrowKey: case kTabKey: { // go to previous or next window tab in current window group if (currentGroup == NULL) return false; int32 groupSize = currentGroup->CountItems(); if (groupSize <= 1) return false; for (int32 i = 0; i < groupSize; i++) { SATWindow* targetWindow = currentGroup->WindowAt(i); if (targetWindow == frontWindow) { if (key == kLeftArrowKey || (key == kTabKey && (modifiers & B_SHIFT_KEY) != 0)) { // Go to previous window tab (wrap around) int32 previousIndex = i > 0 ? i - 1 : groupSize - 1; targetWindow = currentGroup->WindowAt(previousIndex); } else { // Go to next window tab (wrap around) int32 nextIndex = i < groupSize - 1 ? i + 1 : 0; targetWindow = currentGroup->WindowAt(nextIndex); } _ActivateWindow(targetWindow); return true; } } break; } case kUpArrowKey: case kPageUpKey: { // go to previous window group GroupIterator groups(this, fDesktop); groups.SetCurrentGroup(currentGroup); SATGroup* backmostGroup = NULL; while (true) { SATGroup* group = groups.NextGroup(); if (group == NULL || group == currentGroup) break; else if (group->CountItems() < 1) continue; if (currentGroup == NULL) { SATWindow* activeWindow = group->ActiveWindow(); if (activeWindow != NULL) _ActivateWindow(activeWindow); else _ActivateWindow(group->WindowAt(0)); return true; } backmostGroup = group; } if (backmostGroup != NULL && backmostGroup != currentGroup) { SATWindow* activeWindow = backmostGroup->ActiveWindow(); if (activeWindow != NULL) _ActivateWindow(activeWindow); else _ActivateWindow(backmostGroup->WindowAt(0)); return true; } break; } case kDownArrowKey: case kPageDownKey: { // go to next window group GroupIterator groups(this, fDesktop); groups.SetCurrentGroup(currentGroup); while (true) { SATGroup* group = groups.NextGroup(); if (group == NULL || group == currentGroup) break; else if (group->CountItems() < 1) continue; SATWindow* activeWindow = group->ActiveWindow(); if (activeWindow != NULL) _ActivateWindow(activeWindow); else _ActivateWindow(group->WindowAt(0)); if (currentGroup != NULL && frontWindow != NULL) { Window* window = frontWindow->GetWindow(); fDesktop->SendWindowBehind(window); WindowSentBehind(window, NULL); } return true; } break; } } return false; }
status_t SATGroup::RestoreGroup(const BMessage& archive, StackAndTile* sat) { // create new group SATGroup* group = new (std::nothrow)SATGroup; if (!group) return B_NO_MEMORY; BReference<SATGroup> groupRef; groupRef.SetTo(group, true); int32 nHTabs, nVTabs; status_t status; status = archive.FindInt32("htab_count", &nHTabs); if (status != B_OK) return status; status = archive.FindInt32("vtab_count", &nVTabs); if (status != B_OK) return status; vector<BReference<Tab> > tempHTabs; for (int i = 0; i < nHTabs; i++) { BReference<Tab> tab = group->_AddHorizontalTab(); if (!tab) return B_NO_MEMORY; tempHTabs.push_back(tab); } vector<BReference<Tab> > tempVTabs; for (int i = 0; i < nVTabs; i++) { BReference<Tab> tab = group->_AddVerticalTab(); if (!tab) return B_NO_MEMORY; tempVTabs.push_back(tab); } BMessage areaArchive; for (int32 i = 0; archive.FindMessage("area", i, &areaArchive) == B_OK; i++) { uint32 leftTab, rightTab, topTab, bottomTab; if (areaArchive.FindInt32("left_tab", (int32*)&leftTab) != B_OK || areaArchive.FindInt32("right_tab", (int32*)&rightTab) != B_OK || areaArchive.FindInt32("top_tab", (int32*)&topTab) != B_OK || areaArchive.FindInt32("bottom_tab", (int32*)&bottomTab) != B_OK) return B_ERROR; if (leftTab >= tempVTabs.size() || rightTab >= tempVTabs.size()) return B_BAD_VALUE; if (topTab >= tempHTabs.size() || bottomTab >= tempHTabs.size()) return B_BAD_VALUE; Tab* left = tempVTabs[leftTab]; Tab* right = tempVTabs[rightTab]; Tab* top = tempHTabs[topTab]; Tab* bottom = tempHTabs[bottomTab]; // adding windows to area uint64 windowId; SATWindow* prevWindow = NULL; for (int32 i = 0; areaArchive.FindInt64("window", i, (int64*)&windowId) == B_OK; i++) { SATWindow* window = sat->FindSATWindow(windowId); if (!window) continue; if (prevWindow == NULL) { if (!group->AddWindow(window, left, top, right, bottom)) continue; prevWindow = window; } else { if (!prevWindow->StackWindow(window)) continue; prevWindow = window; } } } return B_OK; }
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; }