- If there is no SATWindow because of lack of memory try to create a SATWindow when asking for it.

- Add untested code to save a SATGroup and to restore a SATGroup.
- Splitting of a SATGroup is now triggered from the WindowArea destructor. This make it easier to restore S&T groups when windows in a group are missing. A group decays automatically in multiple groups when the missing window connected multiple windows.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39461 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Clemens Zeidler
2010-11-17 03:06:09 +00:00
parent 631cc3ea7b
commit f72d191b12
6 changed files with 202 additions and 27 deletions
+129 -15
View File
@@ -9,13 +9,19 @@
#include "SATGroup.h"
#include <vector>
#include <Debug.h>
#include <Message.h>
#include "SATWindow.h"
#include "StackAndTile.h"
#include "Window.h"
using namespace std;
WindowArea::WindowArea(Crossing* leftTop, Crossing* rightTop,
Crossing* leftBottom, Crossing* rightBottom)
:
@@ -46,6 +52,9 @@ WindowArea::SetGroup(SATGroup* group)
WindowArea::~WindowArea()
{
if (fGroup)
fGroup->WindowAreaRemoved(this);
_CleanupCorners();
SetGroup(NULL);
}
@@ -706,8 +715,6 @@ SATGroup::RemoveWindow(SATWindow* window)
if (!fSATWindowList.RemoveItem(window))
return false;
_SplitGroupIfNecessary(window);
WindowArea* area = window->GetWindowArea();
if (area)
area->_RemoveWindow(window);
@@ -784,6 +791,119 @@ SATGroup::AdjustWindows(SATWindow* triggerWindow)
}
void
SATGroup::WindowAreaRemoved(WindowArea* area)
{
_SplitGroupIfNecessary(area);
}
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
int64 windowId;
WindowArea* area = NULL;
for (int32 i = 0;
areaArchive.FindInt64("window", i, &windowId) == B_OK; i++) {
SATWindow* window = sat->FindSATWindow(windowId);
if (!window)
continue;
if (area == NULL) {
if (!group->AddWindow(window, left, top, right, bottom))
return B_ERROR;
area = window->GetWindowArea();
} else {
if (!group->AddWindow(window, area))
return B_ERROR;
}
}
}
return B_OK;
}
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;
}
BReference<Tab>
SATGroup::_AddHorizontalTab(float position)
{
@@ -860,20 +980,19 @@ SATGroup::_FindTab(const TabList& list, float position)
void
SATGroup::_SplitGroupIfNecessary(SATWindow* removedWindow)
SATGroup::_SplitGroupIfNecessary(WindowArea* removedArea)
{
// if there are windows stacked in the area we don't need to split
WindowArea* area = removedWindow->GetWindowArea();
if (!area || area->WindowList().CountItems() > 1)
if (!removedArea || removedArea->WindowList().CountItems() > 1)
return;
WindowAreaList neighbourWindows;
_FillNeighbourList(neighbourWindows, removedWindow->GetWindowArea());
_FillNeighbourList(neighbourWindows, removedArea);
bool ownGroupProcessed = false;
WindowAreaList newGroup;
while (_FindConnectedGroup(neighbourWindows, removedWindow, newGroup)) {
while (_FindConnectedGroup(neighbourWindows, removedArea, newGroup)) {
STRACE_SAT("Connected group found; %i windows:\n",
(int)newGroup.CountItems());
for (int i = 0; i < newGroup.CountItems(); i++) {
@@ -903,8 +1022,6 @@ void
SATGroup::_FillNeighbourList(WindowAreaList& neighbourWindows,
WindowArea* area)
{
if (!area)
return;
_LeftNeighbours(neighbourWindows, area);
_RightNeighbours(neighbourWindows, area);
_TopNeighbours(neighbourWindows, area);
@@ -1018,19 +1135,16 @@ SATGroup::_BottomNeighbours(WindowAreaList& neighbourWindows,
bool
SATGroup::_FindConnectedGroup(WindowAreaList& seedList,
SATWindow* removedWindow, WindowAreaList& newGroup)
SATGroup::_FindConnectedGroup(WindowAreaList& seedList, WindowArea* removedArea,
WindowAreaList& newGroup)
{
if (seedList.CountItems() == 0)
return false;
WindowArea* vetoArea = removedWindow->GetWindowArea();
if (!vetoArea)
return false;
WindowArea* area = seedList.RemoveItemAt(0);
newGroup.AddItem(area);
_FollowSeed(area, vetoArea, seedList, newGroup);
_FollowSeed(area, removedArea, seedList, newGroup);
return true;
}
+12 -3
View File
@@ -133,7 +133,7 @@ public:
Crossing* rightBottom);
~WindowArea();
bool SetGroup(SATGroup* group);
bool SetGroup(SATGroup* group);
const SATWindowList& WindowList() { return fWindowList; }
const SATWindowList& LayerOrder() { return fWindowLayerOrder; }
@@ -200,6 +200,9 @@ private:
typedef BObjectList<WindowArea> WindowAreaList;
typedef BObjectList<Tab> TabList;
class BMessage;
class StackAndTile;
class SATGroup : public BReferenceable {
public:
@@ -233,6 +236,12 @@ public:
Tab* FindHorizontalTab(float position);
Tab* FindVerticalTab(float position);
void WindowAreaRemoved(WindowArea* area);
static status_t RestoreGroup(const BMessage& archive,
StackAndTile* sat);
status_t ArchiveGroup(BMessage& archive);
private:
BReference<Tab> _AddHorizontalTab(float position = 0);
BReference<Tab> _AddVerticalTab(float position = 0);
@@ -243,7 +252,7 @@ private:
Tab* _FindTab(const TabList& list, float position);
void _SplitGroupIfNecessary(
SATWindow* removedWindow);
WindowArea* removedArea);
void _FillNeighbourList(
WindowAreaList& neighbourWindows,
WindowArea* area);
@@ -260,7 +269,7 @@ private:
WindowAreaList& neighbourWindows,
WindowArea* window);
bool _FindConnectedGroup(WindowAreaList& seedList,
SATWindow* removedWindow,
WindowArea* removedArea,
WindowAreaList& newGroup);
void _FollowSeed(WindowArea* area, WindowArea* veto,
WindowAreaList& seedList,
@@ -289,6 +289,8 @@ SATWindow::SATWindow(StackAndTile* sat, Window* window)
fSATTiling(this),
fShutdown(false)
{
fId = _GenerateId();
fDesktop = fWindow->Desktop();
fGroupCookie = &fOwnGroupCookie;
@@ -680,6 +682,29 @@ SATWindow::TabLocationMoved(float location, bool shifting)
}
uint64
SATWindow::Id()
{
return fId;
}
bool
SATWindow::SetSettings(const BMessage& message)
{
if (message.FindInt64("window_id", (int64*)&fId) != B_OK)
return false;
return true;
}
void
SATWindow::GetSettings(BMessage& message)
{
message.AddInt64("window_id", fId);
}
void
SATWindow::_InitGroup()
{
@@ -744,3 +769,13 @@ SATWindow::_UpdateSizeLimits()
fGroupCookie->SetSizeLimits(minWidth, B_SIZE_UNLIMITED, minHeight,
B_SIZE_UNLIMITED);
}
uint64
SATWindow::_GenerateId()
{
bigtime_t time = real_time_clock_usecs();
srand(time);
int16 randNumber = rand();
return (time & ~0xFFFF) | randNumber;
}
@@ -128,9 +128,14 @@ public:
bool SetStackedTabMoving(bool moving = true);
void TabLocationMoved(float location, bool shifting);
uint64 Id();
bool SetSettings(const BMessage& message);
void GetSettings(BMessage& message);
private:
void _InitGroup();
void _UpdateSizeLimits();
uint64 _GenerateId();
Window* fWindow;
StackAndTile* fStackAndTile;
@@ -158,6 +163,8 @@ private:
float fOriginalWidth;
float fOriginalHeight;
uint64 fId;
};
@@ -334,8 +334,7 @@ StackAndTile::SetDecoratorSettings(Window* window, const BMessage& settings)
if (!satWindow)
return false;
//return satWindow->SetSettings(settings);
return false;
return satWindow->SetSettings(settings);
}
@@ -346,7 +345,7 @@ StackAndTile::GetDecoratorSettings(Window* window, BMessage& settings)
if (!satWindow)
return;
//satWindow->GetSettings(&settings);
satWindow->GetSettings(settings);
}
@@ -358,16 +357,26 @@ StackAndTile::GetSATWindow(Window* window)
if (it != fSATWindowMap.end())
return it->second;
// for now don't create window on the fly
return NULL;
// If we don't know this window, memory allocation might has been failed
// previously. Try to add window now
/* SATWindow* satWindow = new (std::nothrow)SATWindow(
window, this);
// previously. Try to add the window now.
SATWindow* satWindow = new (std::nothrow)SATWindow(this, window);
if (satWindow)
fSATWindowMap[window] = satWindow;
return satWindow;*/
return satWindow;
}
SATWindow*
StackAndTile::FindSATWindow(uint64 id)
{
for (SATWindowMap::const_iterator it = fSATWindowMap.begin();
it != fSATWindowMap.end(); it++) {
SATWindow* window = it->second;
if (window->Id() == id)
return window;
}
return NULL;
}
@@ -89,6 +89,7 @@ public:
{ return fSATKeyPressed; }
SATWindow* GetSATWindow(Window* window);
SATWindow* FindSATWindow(uint64 id);
private:
void _StartSAT();