* Layers are now put into an application wide token space that mirrors the

client's token space.
* finding layers by token is now O(1) instead of O(n) (as they are looked
  up in the token space).
* removed Layer::FindView() as it's no longer needed (or should be used).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15113 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-11-24 13:14:49 +00:00
parent a2a5442d81
commit bde8b9c6e0
5 changed files with 103 additions and 116 deletions
+72 -95
View File
@@ -26,6 +26,7 @@
#include "DrawState.h" #include "DrawState.h"
#include "PortLink.h" #include "PortLink.h"
#include "RootLayer.h" #include "RootLayer.h"
#include "ServerApp.h"
#include "ServerProtocol.h" #include "ServerProtocol.h"
#include "ServerWindow.h" #include "ServerWindow.h"
#include "WinBorder.h" #include "WinBorder.h"
@@ -105,6 +106,9 @@ Layer::~Layer()
{ {
delete fDrawState; delete fDrawState;
if (fWindow != NULL)
fWindow->App()->ViewTokens().RemoveToken(ViewToken());
Layer* child = fFirstChild; Layer* child = fFirstChild;
while (child != NULL) { while (child != NULL) {
Layer* nextChild = child->fNextSibling; Layer* nextChild = child->fNextSibling;
@@ -124,79 +128,79 @@ Layer::~Layer()
it spits an error to stdout and returns. it spits an error to stdout and returns.
*/ */
void void
Layer::AddChild(Layer* layer, ServerWindow* window) Layer::AddChild(Layer* child, ServerWindow* window)
{ {
STRACE(("Layer(%s)::AddChild(%s) START\n", Name(), layer->Name())); STRACE(("Layer(%s)::AddChild(%s)\n", Name(), child->Name()));
if (layer->fParent != NULL) { if (child->fParent != NULL) {
printf("ERROR: AddChild(): Layer already has a parent\n"); printf("ERROR: AddChild(): Layer already has a parent\n");
return; return;
} }
// 1) attach layer to the tree structure // 1) attach layer to the tree structure
layer->fParent = this; child->fParent = this;
// if we have children already, bump the current last child back one and // if we have children already, bump the current last child back one and
// make the new child the last layer // make the new child the last layer
if (fLastChild) { if (fLastChild) {
layer->fPreviousSibling = fLastChild; child->fPreviousSibling = fLastChild;
fLastChild->fNextSibling = layer; fLastChild->fNextSibling = child;
} else { } else {
fFirstChild = layer; fFirstChild = child;
} }
fLastChild = layer; fLastChild = child;
// if we have no RootLayer yet, then there is no need to set any parameters -- // if we have no RootLayer yet, then there is no need to set any parameters --
// they will be set when the RootLayer for this tree will be added // they will be set when the RootLayer for this tree will be added
// to the main tree structure. // to the main tree structure.
if (!fRootLayer) { if (!fRootLayer) {
STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name())); STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), child->Name()));
return; return;
} }
// 2) Iterate over the newly-added layer and all its children, setting the // 2) Iterate over the newly-added layer and all its children, setting the
// root layer and server window and also rebuilding the full-size region // root layer and server window and also rebuilding the full-size region
// for every descendant of the newly-added layer // for every descendant of the newly-added layer
//c = short for: current Layer* stop = child;
Layer* c = layer;
Layer* stop = layer;
while (true) { while (true) {
// action block // action block
// 2.1) set the RootLayer for this object. // 2.1) set the RootLayer for this object.
c->SetRootLayer(c->fParent->fRootLayer); child->SetRootLayer(child->fParent->fRootLayer);
// 2.2) this Layer must know if it has a ServerWindow object attached. // 2.2) this Layer must know if it has a ServerWindow object attached.
c->fWindow = window; child->fWindow = window;
// insert view into local token space
window->App()->ViewTokens().SetToken(child->ViewToken(),
B_HANDLER_TOKEN, child);
// tree parsing algorithm // tree parsing algorithm
if (c->fFirstChild) { if (child->fFirstChild) {
// go deep // go deep
c = c->fFirstChild; child = child->fFirstChild;
} else { } else {
// go right or up // go right or up
if (c == stop) // our trip is over if (child == stop) // our trip is over
break; break;
if (c->fNextSibling) { if (child->fNextSibling) {
// go right // go right
c = c->fNextSibling; child = child->fNextSibling;
} else { } else {
// go up // go up
while (!c->fParent->fNextSibling && c->fParent != stop) while (child->fParent->fNextSibling == NULL && child->fParent != stop)
c = c->fParent; child = child->fParent;
if (c->fParent == stop) // that's enough! if (child->fParent == stop) // that's enough!
break; break;
c = c->fParent->fNextSibling; child = child->fParent->fNextSibling;
} }
} }
} }
STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name()));
} }
@@ -208,16 +212,15 @@ Layer::AddChild(Layer* layer, ServerWindow* window)
spits out an error to stdout and returns spits out an error to stdout and returns
*/ */
void void
Layer::RemoveChild(Layer *layer) Layer::RemoveChild(Layer *child)
{ {
STRACE(("Layer(%s)::RemoveChild(%s) START\n", Name(), layer->Name())); STRACE(("Layer(%s)::RemoveChild(%s)\n", Name(), child->Name()));
if (!layer->fParent) { if (!child->fParent) {
printf("ERROR: RemoveChild(): Layer doesn't have a parent\n"); printf("ERROR: RemoveChild(): Layer doesn't have a parent\n");
return; return;
} }
if (child->fParent != this) {
if (layer->fParent != this) {
printf("ERROR: RemoveChild(): Layer is not a child of this layer\n"); printf("ERROR: RemoveChild(): Layer is not a child of this layer\n");
return; return;
} }
@@ -225,65 +228,63 @@ Layer::RemoveChild(Layer *layer)
// 1) remove this layer from the main tree. // 1) remove this layer from the main tree.
// Take care of fParent // Take care of fParent
layer->fParent = NULL; child->fParent = NULL;
if (fFirstChild == layer) if (fFirstChild == child)
fFirstChild = layer->fNextSibling; fFirstChild = child->fNextSibling;
if (fLastChild == layer) if (fLastChild == child)
fLastChild = layer->fPreviousSibling; fLastChild = child->fPreviousSibling;
// Take care of siblings // Take care of siblings
if (layer->fPreviousSibling != NULL) if (child->fPreviousSibling != NULL)
layer->fPreviousSibling->fNextSibling = layer->fNextSibling; child->fPreviousSibling->fNextSibling = child->fNextSibling;
if (layer->fNextSibling != NULL) if (child->fNextSibling != NULL)
layer->fNextSibling->fPreviousSibling = layer->fPreviousSibling; child->fNextSibling->fPreviousSibling = child->fPreviousSibling;
layer->fPreviousSibling = NULL; child->fPreviousSibling = NULL;
layer->fNextSibling = NULL; child->fNextSibling = NULL;
layer->_ClearVisibleRegions(); child->_ClearVisibleRegions();
// 2) Iterate over all of the removed-layer's descendants and unset the // 2) Iterate over all of the removed-layer's descendants and unset the
// root layer, server window, and all redraw-related regions // root layer, server window, and all redraw-related regions
Layer* c = layer; //c = short for: current Layer* stop = child;
Layer* stop = layer;
while (true) { while (true) {
// action block // action block
{
// 2.1) set the RootLayer for this object. // 2.1) set the RootLayer for this object.
c->SetRootLayer(NULL); child->SetRootLayer(NULL);
// 2.2) this Layer must know if it has a ServerWindow object attached. // 2.2) this Layer must know if it has a ServerWindow object attached.
c->fWindow = NULL; if (child->Window())
} child->Window()->App()->ViewTokens().RemoveToken(child->ViewToken());
child->fWindow = NULL;
// tree parsing algorithm // tree parsing algorithm
if (c->fFirstChild) { if (child->fFirstChild) {
// go deep // go deep
c = c->fFirstChild; child = child->fFirstChild;
} else { } else {
// go right or up // go right or up
if (c == stop) // out trip is over if (child == stop) // out trip is over
break; break;
if (c->fNextSibling) { if (child->fNextSibling) {
// go right // go right
c = c->fNextSibling; child = child->fNextSibling;
} else { } else {
// go up // go up
while(!c->fParent->fNextSibling && c->fParent != stop) while (child->fParent->fNextSibling == NULL && child->fParent != stop)
c = c->fParent; child = child->fParent;
if (c->fParent == stop) // that enough! if (child->fParent == stop) // that enough!
break; break;
c = c->fParent->fNextSibling; child = child->fParent->fNextSibling;
} }
} }
} }
STRACE(("Layer(%s)::RemoveChild(%s) END\n", Name(), layer->Name()));
} }
@@ -327,30 +328,6 @@ Layer::CountChildren() const
return count; return count;
} }
/*!
\brief Finds a child of the caller based on its token ID
\param token ID of the layer to find
\return Pointer to the layer or NULL if not found
*/
Layer*
Layer::FindLayer(const int32 token)
{
// (recursive) search for a layer based on its view token
// iterate only over direct child layers first
for (Layer* child = FirstChild(); child; child = child->NextLayer()) {
if (child->fViewToken == token)
return child;
}
// try a recursive search
for (Layer* child = FirstChild(); child; child = child->NextLayer()) {
if (Layer* layer = child->FindLayer(token))
return layer;
}
return NULL;
}
/*! /*!
\brief Returns the layer at the given point \brief Returns the layer at the given point
-1
View File
@@ -80,7 +80,6 @@ class Layer {
{ return fParent; } { return fParent; }
uint32 CountChildren() const; uint32 CountChildren() const;
Layer* FindLayer(const int32 token);
Layer* LayerAt(BPoint where); Layer* LayerAt(BPoint where);
Layer* FirstChild() const; Layer* FirstChild() const;
+6 -1
View File
@@ -17,9 +17,11 @@
#include "SubWindowList.h" #include "SubWindowList.h"
#include "BGet++.h" #include "BGet++.h"
#include <ObjectList.h>
#include <String.h> #include <String.h>
#include <ObjectList.h>
#include <TokenSpace.h>
class AreaPool; class AreaPool;
class BMessage; class BMessage;
@@ -74,6 +76,8 @@ class ServerApp : public MessageLooper {
Desktop* GetDesktop() const { return fDesktop; } Desktop* GetDesktop() const { return fDesktop; }
BPrivate::BTokenSpace& ViewTokens() { return fViewTokens; }
// ToDo: public? // ToDo: public?
SubWindowList fAppSubWindowList; SubWindowList fAppSubWindowList;
@@ -97,6 +101,7 @@ class ServerApp : public MessageLooper {
BLocker fWindowListLock; BLocker fWindowListLock;
BObjectList<ServerWindow> fWindowList; BObjectList<ServerWindow> fWindowList;
BPrivate::BTokenSpace fViewTokens;
// TODO: // TODO:
// - Are really Bitmaps and Pictures stored per application and not globally ? // - Are really Bitmaps and Pictures stored per application and not globally ?
+16 -14
View File
@@ -157,7 +157,7 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app,
} }
//!Tears down all connections the main app_server objects, and deletes some internals. //! Tears down all connections the main app_server objects, and deletes some internals.
ServerWindow::~ServerWindow() ServerWindow::~ServerWindow()
{ {
STRACE(("*ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this)); STRACE(("*ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this));
@@ -522,9 +522,13 @@ if (fWinBorder->IsOffscreenWindow()) {
} }
if (_parent) { if (_parent) {
Layer *parent = fWinBorder->FindLayer(parentToken); Layer *parent;
if (parent == NULL) if (App()->ViewTokens().GetToken(parentToken, B_HANDLER_TOKEN,
(void**)&parent) != B_OK
|| parent->Window() != this) {
CRITICAL("View token not found!\n"); CRITICAL("View token not found!\n");
parent = NULL;
}
*_parent = parent; *_parent = parent;
} }
@@ -583,7 +587,6 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
int32 yOffset = (int32)(dst.top - src.top); int32 yOffset = (int32)(dst.top - src.top);
fCurrentLayer->CopyBits(src, dst, xOffset, yOffset); fCurrentLayer->CopyBits(src, dst, xOffset, yOffset);
break; break;
} }
case AS_SET_CURRENT_LAYER: case AS_SET_CURRENT_LAYER:
@@ -592,18 +595,17 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
link.Read<int32>(&token); link.Read<int32>(&token);
Layer *current = fWinBorder->FindLayer(token); Layer *current;
if (current) { if (App()->ViewTokens().GetToken(token, B_HANDLER_TOKEN,
DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token)); (void**)&current) != B_OK
} else { || current->Window() != this) {
// ToDo: if this happens, we probably want to kill the app and clean up
DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: layer not found, token %ld\n", fTitle, token)); DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: layer not found, token %ld\n", fTitle, token));
} current = NULL;
} else {
if (current) DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token));
fCurrentLayer = current; fCurrentLayer = current;
else // hope this NEVER happens! :-) }
CRITICAL("Server PANIC: window cannot find Layer with ID\n");
// ToDo: if this happens, we probably want to kill the app and clean up
break; break;
} }
+9 -5
View File
@@ -831,12 +831,16 @@ WinBorder::RequestClientRedraw(const BRegion &invalid)
void void
WinBorder::SetTopLayer(Layer* layer) WinBorder::SetTopLayer(Layer* layer)
{ {
if (layer) { if (fTopLayer != NULL) {
fTopLayer = layer; RemoveChild(fTopLayer);
fTopLayer->SetAsTopLayer(true); fTopLayer->SetAsTopLayer(false);
}
// connect decorator and top layer. (?) fTopLayer = layer;
AddChild(fTopLayer, NULL);
if (layer != NULL) {
AddChild(fTopLayer, Window());
fTopLayer->SetAsTopLayer(true);
} }
} }