mirror of
https://review.haiku-os.org/haiku
synced 2025-02-01 03:06:08 +01:00
* 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:
parent
a2a5442d81
commit
bde8b9c6e0
@ -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
|
||||
|
@ -80,7 +80,6 @@ class Layer {
|
||||
{ return fParent; }
|
||||
|
||||
uint32 CountChildren() const;
|
||||
Layer* FindLayer(const int32 token);
|
||||
Layer* LayerAt(BPoint where);
|
||||
|
||||
Layer* FirstChild() const;
|
||||
|
@ -17,9 +17,11 @@
|
||||
#include "SubWindowList.h"
|
||||
#include "BGet++.h"
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <TokenSpace.h>
|
||||
|
||||
|
||||
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<ServerWindow> fWindowList;
|
||||
BPrivate::BTokenSpace fViewTokens;
|
||||
|
||||
// TODO:
|
||||
// - Are really Bitmaps and Pictures stored per application and not globally ?
|
||||
|
@ -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<int32>(&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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user