From bde8b9c6e0e93228febce69548748d26d62cb254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 24 Nov 2005 13:14:49 +0000 Subject: [PATCH] * 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 --- src/servers/app/Layer.cpp | 167 +++++++++++++------------------ src/servers/app/Layer.h | 1 - src/servers/app/ServerApp.h | 7 +- src/servers/app/ServerWindow.cpp | 30 +++--- src/servers/app/WinBorder.cpp | 14 ++- 5 files changed, 103 insertions(+), 116 deletions(-) diff --git a/src/servers/app/Layer.cpp b/src/servers/app/Layer.cpp index 85b2a6e4f4..a9b27bb0c6 100644 --- a/src/servers/app/Layer.cpp +++ b/src/servers/app/Layer.cpp @@ -26,6 +26,7 @@ #include "DrawState.h" #include "PortLink.h" #include "RootLayer.h" +#include "ServerApp.h" #include "ServerProtocol.h" #include "ServerWindow.h" #include "WinBorder.h" @@ -105,6 +106,9 @@ Layer::~Layer() { delete fDrawState; + if (fWindow != NULL) + fWindow->App()->ViewTokens().RemoveToken(ViewToken()); + Layer* child = fFirstChild; while (child != NULL) { Layer* nextChild = child->fNextSibling; @@ -124,79 +128,79 @@ Layer::~Layer() it spits an error to stdout and returns. */ void -Layer::AddChild(Layer* layer, ServerWindow* window) +Layer::AddChild(Layer* child, ServerWindow* window) { - STRACE(("Layer(%s)::AddChild(%s) START\n", Name(), layer->Name())); - - if (layer->fParent != NULL) { + STRACE(("Layer(%s)::AddChild(%s)\n", Name(), child->Name())); + + if (child->fParent != NULL) { printf("ERROR: AddChild(): Layer already has a parent\n"); return; } - + // 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 // make the new child the last layer if (fLastChild) { - layer->fPreviousSibling = fLastChild; - fLastChild->fNextSibling = layer; + child->fPreviousSibling = fLastChild; + fLastChild->fNextSibling = child; } else { - fFirstChild = layer; + fFirstChild = child; } - fLastChild = layer; + fLastChild = child; // 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 // to the main tree structure. if (!fRootLayer) { - STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), layer->Name())); + STRACE(("Layer(%s)::AddChild(%s) END\n", Name(), child->Name())); return; } // 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 // for every descendant of the newly-added layer - - //c = short for: current - Layer* c = layer; - Layer* stop = layer; + + Layer* stop = child; while (true) { // action block // 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. - 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 - if (c->fFirstChild) { + if (child->fFirstChild) { // go deep - c = c->fFirstChild; + child = child->fFirstChild; } else { // go right or up - if (c == stop) // our trip is over + if (child == stop) // our trip is over break; - if (c->fNextSibling) { + if (child->fNextSibling) { // go right - c = c->fNextSibling; + child = child->fNextSibling; } else { // go up - while (!c->fParent->fNextSibling && c->fParent != stop) - c = c->fParent; + while (child->fParent->fNextSibling == NULL && child->fParent != stop) + child = child->fParent; - if (c->fParent == stop) // that's enough! + if (child->fParent == stop) // that's enough! 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 */ void -Layer::RemoveChild(Layer *layer) +Layer::RemoveChild(Layer *child) { - STRACE(("Layer(%s)::RemoveChild(%s) START\n", Name(), layer->Name())); - - if (!layer->fParent) { + STRACE(("Layer(%s)::RemoveChild(%s)\n", Name(), child->Name())); + + if (!child->fParent) { printf("ERROR: RemoveChild(): Layer doesn't have a parent\n"); return; } - - if (layer->fParent != this) { + if (child->fParent != this) { printf("ERROR: RemoveChild(): Layer is not a child of this layer\n"); return; } @@ -225,65 +228,63 @@ Layer::RemoveChild(Layer *layer) // 1) remove this layer from the main tree. // Take care of fParent - layer->fParent = NULL; + child->fParent = NULL; - if (fFirstChild == layer) - fFirstChild = layer->fNextSibling; + if (fFirstChild == child) + fFirstChild = child->fNextSibling; - if (fLastChild == layer) - fLastChild = layer->fPreviousSibling; + if (fLastChild == child) + fLastChild = child->fPreviousSibling; // Take care of siblings - if (layer->fPreviousSibling != NULL) - layer->fPreviousSibling->fNextSibling = layer->fNextSibling; - - if (layer->fNextSibling != NULL) - layer->fNextSibling->fPreviousSibling = layer->fPreviousSibling; - - layer->fPreviousSibling = NULL; - layer->fNextSibling = NULL; - layer->_ClearVisibleRegions(); + if (child->fPreviousSibling != NULL) + child->fPreviousSibling->fNextSibling = child->fNextSibling; + + if (child->fNextSibling != NULL) + child->fNextSibling->fPreviousSibling = child->fPreviousSibling; + + child->fPreviousSibling = NULL; + child->fNextSibling = NULL; + child->_ClearVisibleRegions(); // 2) Iterate over all of the removed-layer's descendants and unset the // root layer, server window, and all redraw-related regions - - Layer* c = layer; //c = short for: current - Layer* stop = layer; - + + Layer* stop = child; while (true) { // action block - { - // 2.1) set the RootLayer for this object. - c->SetRootLayer(NULL); - // 2.2) this Layer must know if it has a ServerWindow object attached. - c->fWindow = NULL; - } + + // 2.1) set the RootLayer for this object. + child->SetRootLayer(NULL); + // 2.2) this Layer must know if it has a ServerWindow object attached. + if (child->Window()) + child->Window()->App()->ViewTokens().RemoveToken(child->ViewToken()); + child->fWindow = NULL; // tree parsing algorithm - if (c->fFirstChild) { + if (child->fFirstChild) { // go deep - c = c->fFirstChild; + child = child->fFirstChild; } else { // go right or up - if (c == stop) // out trip is over + if (child == stop) // out trip is over break; - if (c->fNextSibling) { + if (child->fNextSibling) { // go right - c = c->fNextSibling; + child = child->fNextSibling; } else { // go up - while(!c->fParent->fNextSibling && c->fParent != stop) - c = c->fParent; - - if (c->fParent == stop) // that enough! + while (child->fParent->fNextSibling == NULL && child->fParent != stop) + child = child->fParent; + + if (child->fParent == stop) // that enough! 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; } -/*! - \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 diff --git a/src/servers/app/Layer.h b/src/servers/app/Layer.h index 9a24bd13ce..5a7bbb8c07 100644 --- a/src/servers/app/Layer.h +++ b/src/servers/app/Layer.h @@ -80,7 +80,6 @@ class Layer { { return fParent; } uint32 CountChildren() const; - Layer* FindLayer(const int32 token); Layer* LayerAt(BPoint where); Layer* FirstChild() const; diff --git a/src/servers/app/ServerApp.h b/src/servers/app/ServerApp.h index 295f6dc521..44a162e29a 100644 --- a/src/servers/app/ServerApp.h +++ b/src/servers/app/ServerApp.h @@ -17,9 +17,11 @@ #include "SubWindowList.h" #include "BGet++.h" -#include #include +#include +#include + class AreaPool; class BMessage; @@ -74,6 +76,8 @@ class ServerApp : public MessageLooper { Desktop* GetDesktop() const { return fDesktop; } + BPrivate::BTokenSpace& ViewTokens() { return fViewTokens; } + // ToDo: public? SubWindowList fAppSubWindowList; @@ -97,6 +101,7 @@ class ServerApp : public MessageLooper { BLocker fWindowListLock; BObjectList fWindowList; + BPrivate::BTokenSpace fViewTokens; // TODO: // - Are really Bitmaps and Pictures stored per application and not globally ? diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 1fda646767..b188057c59 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -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() { STRACE(("*ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this)); @@ -522,9 +522,13 @@ if (fWinBorder->IsOffscreenWindow()) { } if (_parent) { - Layer *parent = fWinBorder->FindLayer(parentToken); - if (parent == NULL) + Layer *parent; + if (App()->ViewTokens().GetToken(parentToken, B_HANDLER_TOKEN, + (void**)&parent) != B_OK + || parent->Window() != this) { CRITICAL("View token not found!\n"); + parent = NULL; + } *_parent = parent; } @@ -583,7 +587,6 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) int32 yOffset = (int32)(dst.top - src.top); fCurrentLayer->CopyBits(src, dst, xOffset, yOffset); - break; } case AS_SET_CURRENT_LAYER: @@ -592,18 +595,17 @@ ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link) link.Read(&token); - Layer *current = fWinBorder->FindLayer(token); - if (current) { - DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token)); - } else { + Layer *current; + if (App()->ViewTokens().GetToken(token, B_HANDLER_TOKEN, + (void**)¤t) != B_OK + || 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)); - } - - if (current) + current = NULL; + } else { + DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token)); 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; } diff --git a/src/servers/app/WinBorder.cpp b/src/servers/app/WinBorder.cpp index 01a5a737bb..0be7eb45a8 100644 --- a/src/servers/app/WinBorder.cpp +++ b/src/servers/app/WinBorder.cpp @@ -831,12 +831,16 @@ WinBorder::RequestClientRedraw(const BRegion &invalid) void WinBorder::SetTopLayer(Layer* layer) { - if (layer) { - fTopLayer = layer; - fTopLayer->SetAsTopLayer(true); + if (fTopLayer != NULL) { + RemoveChild(fTopLayer); + fTopLayer->SetAsTopLayer(false); + } - // connect decorator and top layer. (?) - AddChild(fTopLayer, NULL); + fTopLayer = layer; + + if (layer != NULL) { + AddChild(fTopLayer, Window()); + fTopLayer->SetAsTopLayer(true); } }