From 7052fe60fa6ce85957cc850ffc9e77c450865769 Mon Sep 17 00:00:00 2001 From: Adi Oanca Date: Fri, 14 Nov 2003 00:15:29 +0000 Subject: [PATCH] new optinized clipping code new optimized redrawing code changes in some handlers in ServerWindow. other minor changes. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5355 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/server/DesktopClasses.cpp | 2 +- src/servers/app/server/Layer.cpp | 1226 +++++++++++---------- src/servers/app/server/Layer.h | 160 +-- src/servers/app/server/RootLayer.cpp | 117 +- src/servers/app/server/RootLayer.h | 28 +- src/servers/app/server/ServerWindow.cpp | 198 ++-- src/servers/app/server/WinBorder.cpp | 583 +++++++--- src/servers/app/server/WinBorder.h | 88 +- 8 files changed, 1318 insertions(+), 1084 deletions(-) diff --git a/src/servers/app/server/DesktopClasses.cpp b/src/servers/app/server/DesktopClasses.cpp index 32f193b73b..a9387974e2 100644 --- a/src/servers/app/server/DesktopClasses.cpp +++ b/src/servers/app/server/DesktopClasses.cpp @@ -224,7 +224,7 @@ STRACE_SCREEN(("Screen::Screen(%s,%u)\n",gfxmodule?"driver":"NULL",workspaces)); _activeworkspace=(Workspace*)_workspacelist->ItemAt(0); _workspacecount=workspaces; _activeworkspace->GetRoot()->Show(); - _activeworkspace->GetRoot()->RequestDraw(); +// _activeworkspace->GetRoot()->RequestDraw(); } } } diff --git a/src/servers/app/server/Layer.cpp b/src/servers/app/server/Layer.cpp index a5fc41eb9c..7bc8a410d2 100644 --- a/src/servers/app/server/Layer.cpp +++ b/src/servers/app/server/Layer.cpp @@ -41,6 +41,9 @@ #include "TokenHandler.h" #include "RectUtils.h" #include "RootLayer.h" +#include "DisplayDriver.h" +#include "Desktop.h" +#include "RGBColor.h" //#define DEBUG_LAYER #ifdef DEBUG_LAYER @@ -61,10 +64,11 @@ Layer::Layer(BRect frame, const char *name, int32 token, uint32 resize, uint32 flags, ServerWindow *win) { - // frame is in _parent layer's coordinates + // frame is in _parent coordinates if(frame.IsValid()) _frame = frame; else + // TODO: Decorator class should have a method witch returns the minimum frame width. _frame.Set(0.0f, 0.0f, 5.0f, 5.0f); _boundsLeftTop.Set( 0.0f, 0.0f ); @@ -78,51 +82,40 @@ Layer::Layer(BRect frame, const char *name, int32 token, uint32 resize, _topchild = NULL; _bottomchild = NULL; - _visible = new BRegion( _frame ); - _full = new BRegion( _frame ); - _invalid = new BRegion( _frame ); - + /* NOW all regions (_visible, _fullVisible, _full) are empty */ + _flags = flags; _resize_mode = resize; _hidden = false; - _is_dirty = false; _is_updating = false; - _regions_invalid= false; _level = 0; _view_token = token; _layerdata = new LayerData; _serverwin = win; _cursor = NULL; + + fDriver = GetGfxDriver(ActiveScreen()); } //! Destructor frees all allocated heap space Layer::~Layer(void) { - if(_visible) - { - delete _visible; - _visible=NULL; - } - if(_full) - { - delete _full; - _full=NULL; - } - if(_invalid) - { - delete _invalid; - _invalid=NULL; - } if(_name) { delete _name; - _name=NULL; + _name = NULL; } if(_layerdata) { delete _layerdata; - _layerdata=NULL; + _layerdata = NULL; + } + if (clipToPicture) + { + delete clipToPicture; + clipToPicture = NULL; +// TODO: allocate and relase a ServerPicture Object. } } @@ -132,77 +125,41 @@ Layer::~Layer(void) \param before Add the child in front of this layer \param rebuild Flag to fully rebuild all visibility regions */ -void Layer::AddChild(Layer *layer, Layer *before, bool rebuild) +void Layer::AddChild(Layer *layer, Layer *before) { - // TODO: Add before support -//printf("Layer::AddChild lacks before support\n"); -/* -STRACE(("\nIn Layer(%s)::AddChild(%s) START\n", _name->String(), layer->_name->String() )); -STRACE(("\nVisible region:\n")); -_visible->PrintToStream(); -STRACE(("Child's visible region:\n")); -layer->_visible->PrintToStream(); -*/ - if(layer->_parent!=NULL) - { + if( layer->_parent != NULL ) { printf("ERROR: AddChild(): Layer already has a _parent\n"); return; } - layer->_parent=this; - if(layer->_visible && layer->_hidden==false && _visible) - { - RootLayer *rl; - rl = dynamic_cast(this); - if ( rl ){ - // RootLayer enters here. It does not need to exclude WinBorder's - // visible area! - } - else{ - // Technically, we could safely take the address of ConvertToParent(BRegion) - // but we don't just to avoid a compiler nag - - /* we don't transformate into parent coords because Layer's - * _visible member is already in parent coords - because in - * Layer's constructor there is a line like this: - * _visible = new BRegion( _frame ); - * and _frame is in parent coords - */ - //BRegion reg(layer->ConvertToParent(layer->_visible)); - - _visible->Exclude( layer->_visible ); + + // attach layer to the tree structure + layer->_parent = this; + if( _bottomchild ){ + layer->_uppersibling = _bottomchild; + _bottomchild->_lowersibling = layer; + } + else{ + _topchild = layer; + } + _bottomchild = layer; + + layer->_level = _level+1; + + + layer->RebuildFullRegion(); + + if ( !(layer->_hidden) ){ + // _layer->_full.Frame() is the maximum(layer's PoV), yet minimum(parent's PoV) + // region to be rebuilt. + RebuildChildRegions( layer->_full.Frame(), layer ); + + // REDRAWING CODE: + + // RebuildChildRegion gave us a valid visible region. + if (layer->_visible.CountRects() > 0){ + layer->Invalidate( layer->_visible ); } } -/* -STRACE(("\n AFTER exclude: Visible region:\n")); -_visible->PrintToStream(); -STRACE(("Child's visible region:\n")); -layer->_visible->PrintToStream(); -*/ - // we need to change this to a loop for each _lowersibling of the layer - if(_bottomchild) - { - // we're adding to the front side of the stack - layer->_uppersibling=_bottomchild; - - // added layer will be at the bottom of the stack - _bottomchild->_lowersibling=layer; - - } - else - _topchild=layer; - - _bottomchild=layer; - layer->_level=_level+1; - - if(rebuild) - RebuildRegions(true); -/* -STRACE(("\n AFTER RebuildRegions: Visible region:\n")); -_visible->PrintToStream(); -STRACE(("Child's visible region:\n")); -layer->_visible->PrintToStream(); -STRACE(("\nEND: Layer(%s)::AddChild(%s)\n", _name->String(), layer->_name->String() )); -*/ } /*! @@ -210,31 +167,19 @@ STRACE(("\nEND: Layer(%s)::AddChild(%s)\n", _name->String(), layer->_name->Strin \param layer The layer to remove \param rebuild Flag to rebuild all visibility regions */ -void Layer::RemoveChild(Layer *layer, bool rebuild) +void Layer::RemoveChild(Layer *layer) { - if(layer->_parent == NULL){ + if( layer->_parent == NULL ){ printf("ERROR: RemoveChild(): Layer doesn't have a _parent\n"); return; } - if(layer->_parent != this){ + if( layer->_parent != this ){ printf("ERROR: RemoveChild(): Layer is not a child of this layer\n"); return; } - if( !_hidden && layer->_visible && layer->_parent->_visible) - { - BRegion reg(ConvertToParent(_visible)); - layer->_parent->_visible->Include(®); - //TODO: have a REVIEW of this code!!!!!!!!!!! the above 2 line are NOT good! - /* - * in _visible we should add layer->_visible if layer is not hidden - * in _invalid we should add layer->_visible if layer is not hidden - - * this is OK, Because, for the moment we include only what we need. - Later, RebuildRegions will not include layer->_frame into calculations - because layer was removed from the tree. (deleted - better said :-) - */ - } + // cache some things. The rebuilding/redrawing process will need those. + Layer* cachedUpperSibling = layer->_uppersibling; // Take care of _parent layer->_parent = NULL; @@ -251,27 +196,38 @@ void Layer::RemoveChild(Layer *layer, bool rebuild) layer->_uppersibling = NULL; layer->_lowersibling = NULL; - if(rebuild) - RebuildRegions(true); + // eliminate layer's full visible region + if ( !(layer->_hidden) ) + { + bool invalidate = false; + BRect invalidRect; + + if (layer->_fullVisible.CountRects() > 0){ + invalidate = true; + invalidRect = layer->_fullVisible.Frame(); + RebuildChildRegions( layer->_fullVisible.Frame(), cachedUpperSibling ); + } + + // REDRAWING CODE: + + if (invalidate){ + DoInvalidate( BRegion(invalidRect), cachedUpperSibling ); + } + } } /*! \brief Removes the layer from its parent's child stack \param rebuild Flag to rebuild visibility regions */ -void Layer::RemoveSelf(bool rebuild) +void Layer::RemoveSelf() { // A Layer removes itself from the tree (duh) - if(_parent==NULL) - { + if( _parent == NULL ){ printf("ERROR: RemoveSelf(): Layer doesn't have a _parent\n"); return; } - Layer *p=_parent; _parent->RemoveChild(this); - - if(rebuild) - p->RebuildRegions(true); } /*! @@ -286,33 +242,20 @@ void Layer::RemoveSelf(bool rebuild) which has no children, i.e. a layer that is at the top of its 'branch' in the layer tree */ -Layer *Layer::GetChildAt(BPoint pt, bool recursive) +Layer* Layer::GetLayerAt(const BPoint &pt) { - Layer *child; - if(recursive) - { - for(child=_bottomchild; child!=NULL; child=child->_uppersibling) - { - if(child->_bottomchild!=NULL) - child->GetChildAt(pt,true); - - if(child->_hidden) - continue; - - if(child->_frame.Contains(pt)) - return child; - } - } - else - { - for(child=_bottomchild; child!=NULL; child=child->_uppersibling) - { - if(child->_hidden) - continue; - if(child->_frame.Contains(pt)) - return child; + if (_visible.Contains(pt)){ + return this; + } + + if (_fullVisible.Contains(pt)){ + Layer *lay = NULL; + for ( Layer* child = _bottomchild; child != NULL; child = child->_uppersibling ){ + if ( (lay = child->GetLayerAt( pt )) ) + return lay; } } + return NULL; } @@ -320,16 +263,18 @@ Layer *Layer::GetChildAt(BPoint pt, bool recursive) \brief Returns the size of the layer \return the size of the layer */ -BRect Layer::Bounds(void) +BRect Layer::Bounds(void) const { - return _frame.OffsetToCopy( _boundsLeftTop ); + BRect r(_frame); + r.OffsetTo( _boundsLeftTop ); + return r; } /*! \brief Returns the layer's size and position in its parent coordinates \return The layer's size and position in its parent coordinates */ -BRect Layer::Frame(void) +BRect Layer::Frame(void) const { return _frame; } @@ -341,21 +286,22 @@ BRect Layer::Frame(void) */ void Layer::PruneTree(void) { - Layer *lay,*nextlay; + Layer *lay, + *nextlay; - lay=_topchild; - _topchild=NULL; + lay = _topchild; + _topchild = NULL; - while(lay!=NULL) + while(lay != NULL) { - if(lay->_topchild!=NULL) - { + if(lay->_topchild != NULL) { lay->PruneTree(); } - nextlay=lay->_lowersibling; - lay->_lowersibling=NULL; + nextlay = lay->_lowersibling; + lay->_lowersibling = NULL; + delete lay; - lay=nextlay; + lay = nextlay; } // Man, this thing is short. Elegant, ain't it? :P } @@ -364,22 +310,23 @@ void Layer::PruneTree(void) \brief Finds a layer based on its token ID \return non-NULL if found, NULL if not */ -Layer *Layer::FindLayer(int32 token) +Layer* Layer::FindLayer(const int32 token) { // recursive search for a layer based on its view token - Layer *lay, *trylay; + Layer *lay, + *trylay; // Search child layers first - for(lay=_topchild; lay!=NULL; lay=lay->_lowersibling) + for(lay = _topchild; lay != NULL; lay = lay->_lowersibling) { - if(lay->_view_token==token) + if(lay->_view_token == token) return lay; } // Hmmm... not in this layer's children. Try lower descendants - for(lay=_topchild; lay!=NULL; lay=lay->_lowersibling) + for(lay = _topchild; lay != NULL; lay = lay->_lowersibling) { - trylay=lay->FindLayer(token); + trylay = lay->FindLayer(token); if(trylay) return trylay; } @@ -395,7 +342,7 @@ Layer *Layer::FindLayer(int32 token) */ void Layer::SetLayerCursor(ServerCursor *csr) { - _cursor=csr; + _cursor = csr; } /*! @@ -417,7 +364,7 @@ ServerCursor *Layer::GetLayerCursor(void) const */ void Layer::MouseTransit(uint32 transit) { - if(transit==B_ENTERED_VIEW) + if(transit == B_ENTERED_VIEW) { if(_cursor) cursormanager->SetCursor(_cursor->ID()); @@ -431,6 +378,65 @@ void Layer::MouseTransit(uint32 transit) } } +void Layer::DoInvalidate(const BRegion ®, Layer *start){ +//TODO: REMOVE this! For Test purposes only! + return; + + if (_hidden || !(_fullVisible.Intersects(reg.Frame())) ){ + printf("SERVER: WARNING: Layer(%s)::DoInvalidate() 1 \n\n", _name->String()); + return; + } + + // we're here! that means that our view is not hidden, HAS a valid '_fullVisible' region, + // AND, of course, it intersects the update region. + + // redraw one of our regions if needed. + if ( _visible.CountRects() > 0 ){ + BRegion iReg(_visible); + + iReg.IntersectWith( ® ); + if ( iReg.CountRects() > 0 ){ + if (_serverwin){ + RequestClientUpdate( iReg.Frame() ); + } + else{ + RequestDraw( iReg.Frame() ); + } + } + } + + if (start == NULL){ + printf("SERVER: WARNING: Layer(%s)::DoInvalidate() 2 \n\n", _name->String()); + return; + } + + // redraw parts of our children, if needed. + bool redraw = false; + + // Redraw regions for children... if needed! + for(Layer *lay = _bottomchild; lay != NULL; lay = lay->_uppersibling) + { + // for layers in front of 'start' no redraw is needed. + // so avoid unnecessary CPU cycles. + if ( lay == start && redraw == false) + redraw = true; + + if ( redraw && !(lay->_hidden) && (lay->_fullVisible.CountRects() > 0) ){ + BRegion layReg(lay->_fullVisible); + + layReg.IntersectWith( ® ); + if ( layReg.CountRects() > 0 ){ + if (lay->_serverwin){ + lay->RequestClientUpdate( layReg.Frame() ); + } + else{ + lay->RequestDraw( layReg.Frame() ); + } + } + } + } +} + /*! \brief Sets a region as invalid and, thus, needing to be drawn \param The region to invalidate @@ -438,44 +444,14 @@ void Layer::MouseTransit(uint32 transit) All children of the layer also receive this call, so only 1 Invalidate call is needed to set a section as invalid on the screen. */ -void Layer::Invalidate(BRegion& region) +void Layer::Invalidate(const BRegion& region) { - int32 i; - BRect r; - - // See if the region intersects with our current area - if(region.Intersects(Bounds()) && !_hidden) - { - BRegion clippedreg(region); - clippedreg.IntersectWith(_visible); - if(clippedreg.CountRects()>0) - { - _is_dirty=true; - if(_invalid) - _invalid->Include(&clippedreg); - else - _invalid=new BRegion(clippedreg); - } + if (_parent){ + _parent->DoInvalidate(region, this); } - - BRegion *reg; - for(Layer *lay=_topchild;lay!=NULL; lay=lay->_lowersibling) - { - if(lay->_hidden==false) - { - reg=new BRegion(lay->ConvertFromParent(®ion)); - - for(i=0;iCountRects();i++) - { - r=reg->RectAt(i); - if(_frame.Intersects(r)) - lay->Invalidate(r); - } - - delete reg; - } + else{ + DoInvalidate(region, _topchild); } - } /*! @@ -487,143 +463,84 @@ void Layer::Invalidate(BRegion& region) */ void Layer::Invalidate(const BRect &rect) { - // Make our own section dirty and pass it on to any children, if necessary.... - // YES, WE ARE SHARING DIRT! Mudpies anyone? :D - if(TestRectIntersection(Bounds(),rect)) - { - // Clip the rectangle to the _visible region of the layer - if(TestRegionIntersection(_visible,rect)) - { - BRegion reg(*_visible); - BRegion rectreg(rect); - -// IntersectRegionWith(®,rect); - reg.IntersectWith(&rectreg); - if(reg.CountRects()>0) - { - _is_dirty=true; - if(_invalid) - _invalid->Include(®); - else - _invalid=new BRegion(reg); - } - else - { - } - } - else - { - } - } - for(Layer *lay=_topchild;lay!=NULL; lay=lay->_lowersibling) - lay->Invalidate(lay->ConvertFromParent(rect)); + Invalidate( BRegion(rect) ); } /*! - \brief Ask the layer's BView to draw itself - \param r The area that needs to be drawn + \brief Sends update requests to client(BViews) + \param The rectangle into witch the client so draw + + All children of the layer also receive this call. +*/ +void Layer::RequestClientUpdate(const BRect &rect){ + + if (_hidden){ + // this layer has nothing visible on screen, so bail out. + return; + } + + // this method assumes _fullVisible.CountRects() is positive !!!!!!!!!!!!! + + // clear the area in the low color + // only the visible area is cleared, because DisplayDriver does the clipping to it. + // draw background, *only IF* our view color is different to B_TRANSPARENT_COLOR! + if ( !(_layerdata->viewcolor == RGBColor(B_TRANSPARENT_COLOR)) ) { + // a quick hack for drawing in other color than the low one. + RGBColor tempColor = _layerdata->lowcolor; + _layerdata->lowcolor.SetColor( B_TRANSPARENT_COLOR ); + + fDriver->StrokeRect(rect, _layerdata, pat_solidlow); + // .. hack continued + _layerdata->lowcolor = tempColor; + } + + BMessage msg; + + msg.what = _UPDATE_; + msg.AddInt32("_token", _view_token); + msg.AddRect("_rect", ConvertFromTop(rect) ); + + _serverwin->SendMessageToClient( &msg ); + + // This layer's BView counterpart will tell its children to redraw. +} + +/*! + \brief Ask internal server layers to do their drawing + \param r The area that needs to be drawn. In SCREEN COORDINATES!!! */ void Layer::RequestDraw(const BRect &r) { -printf("Layer: %s: RequestDraw(%.1f,%.1f,%.1f,%.1f) - unimplemented\n", - _name->String(),r.left,r.top,r.right,r.bottom); - // TODO: Implement and fix -/* if(_visible==NULL || _hidden) - return; + if (_visible.CountRects() > 0){ + // a quick hack for drawing in other color than the low one. + RGBColor tempColor = _layerdata->lowcolor; + _layerdata->lowcolor.SetColor( B_TRANSPARENT_COLOR ); - if(_serverwin) - { - if(_invalid==NULL) - _invalid=new BRegion(*_visible); - _serverwin->RequestDraw(_invalid->Frame()); - delete _invalid; - _invalid=NULL; + fDriver->StrokeRect(r, _layerdata, pat_solidlow); + // .. hack continued + _layerdata->lowcolor = tempColor; + + // draw itself. + Draw(r); } - _is_dirty=false; - for(Layer *lay=_topchild; lay!=NULL; lay=lay->_lowersibling) - { - if(lay->IsDirty()) - lay->RequestDraw(); + // tell children to draw. + for (Layer *lay = _topchild; lay != NULL; lay = lay->_lowersibling){ + if ( !(lay->_hidden) && r.Intersects(lay->_fullVisible.Frame()) ){ + BRect newRect = (r & lay->_fullVisible.Frame()); + lay->RequestDraw( newRect ); + } } -*/ -} - -void Layer::RequestDraw(void) -{ - RequestDraw(Bounds()); } /*! - \brief Determines whether the layer needs to be redrawn - \return True if the layer needs to be redrawn, false if not + \brief Ask the layer to draw itself + \param r The area that needs to be drawn */ -bool Layer::IsDirty(void) const +void Layer::Draw(const BRect &r) { - //return (!_invalid)?true:false; - return _is_dirty; -} - -/*! - \brief Forces a repaint if there are invalid areas - \param force_update Force an update. False by default. -*/ -void Layer::UpdateIfNeeded(bool force_update) -{ - if(IsHidden()) - return; - - Layer *child; - - if(force_update) - { - if(_invalid) - RequestDraw(_invalid->Frame()); - else - RequestDraw(); - } - else - { - if(_invalid) - RequestDraw(_invalid->Frame()); - } - - for(child=_bottomchild; child!=NULL; child=child->_uppersibling) - child->UpdateIfNeeded(force_update); - _is_dirty=false; -} - -/*! - \brief Marks the layer as needing a region rebuild if intersecting the given rect - \param rect The rectangle for checking to see if the layer needs to be rebuilt -*/ -void Layer::MarkModified(BRect rect) -{ - if(TestRectIntersection(Bounds(),rect)) - _regions_invalid=true; - - Layer *child; - for(child=_bottomchild; child!=NULL; child=child->_uppersibling) - child->MarkModified(rect.OffsetByCopy(-child->_frame.left,-child->_frame.top)); -} - -/*! - \brief Rebuilds the layer's regions and updates the screen as needed - \param force Force an update -*/ -void Layer::UpdateRegions(bool force) -{ -STRACE(("*Layer(%s)::UpdateRegions()\n", _name->String())); - if(force) - { - RebuildRegions(true); -// MoveChildren(); -// InvalidateNewAreas(); - } - - if( (_regions_invalid && (_parent==NULL) && _invalid) || force) - UpdateIfNeeded(force); + // empty HOOK function. } //! Show the layer. Operates just like the BView call with the same name @@ -634,32 +551,18 @@ void Layer::Show(void) _hidden = false; - if( _parent ){ - BRegion reg(ConvertToParent(_visible)); - _parent->_visible->Exclude( ® ); - _parent->_is_dirty=true; + // rebuild layer visible region based on its parent's and those supplied by user + if (_parent){ + _parent->RebuildChildRegions( _full.Frame(), this ); } - _is_dirty=true; - - if( _parent ){ - Layer *sibling; - for (sibling=_parent->_bottomchild; sibling!=NULL; sibling=sibling->_uppersibling) - { - if(TestRectIntersection(sibling->_frame,_frame)) - sibling->MarkModified(_frame.OffsetByCopy(-sibling->_frame.left,-sibling->_frame.top)); - } + else{ + RebuildRegions( _full.Frame() ); } - Layer *child; - for(child=_topchild; child!=NULL; child=child->_lowersibling) - child->Show(); + // REDRAWING CODE: - if(_parent){ - _parent->RebuildRegions(true); - _parent->UpdateIfNeeded(); - } - - UpdateIfNeeded(); + if (_fullVisible.CountRects() > 0) + Invalidate( _fullVisible ); } //! Hide the layer. Operates just like the BView call with the same name @@ -668,24 +571,30 @@ void Layer::Hide(void) if ( _hidden ) return; - _hidden = true; + _hidden = true; - BRegion reg(ConvertToParent(_visible)); - _parent->_visible->Include( ® ); + if (_fullVisible.CountRects() > 0){ - _parent->_is_dirty=true; - _is_dirty=true; - - Layer *child; - for(child=_topchild; child!=NULL; child=child->_lowersibling) - child->Hide(); + BRegion cachedFullVisible = _fullVisible; + + if (_parent){ + _parent->RebuildChildRegions( _fullVisible.Frame(), this ); + } + else{ + RebuildRegions( _full.Frame() ); + } + + // REDRAWING CODE: + + Invalidate( cachedFullVisible ); + } } /*! \brief Determines whether the layer is hidden or not \return true if hidden, false if not. */ -bool Layer::IsHidden(void) +bool Layer::IsHidden(void) const { return _hidden; } @@ -694,7 +603,7 @@ bool Layer::IsHidden(void) \brief Counts the number of children the layer has \return the number of children the layer has, not including grandchildren */ -uint32 Layer::CountChildren(void) +uint32 Layer::CountChildren(void) const { uint32 i=0; Layer *lay=_topchild; @@ -706,6 +615,16 @@ uint32 Layer::CountChildren(void) return i; } +void Layer::MoveRegionsBy(float x, float y){ + + // currently just the full region needs to be moved. + _full.OffsetBy(x, y); + + for (Layer *lay = _topchild; lay != NULL; lay = lay->_lowersibling){ + lay->MoveRegionsBy(x, y); + } +} + /*! \brief Moves a layer in its parent coordinate space \param x X offset @@ -713,45 +632,236 @@ uint32 Layer::CountChildren(void) */ void Layer::MoveBy(float x, float y) { - _frame.OffsetBy(x,y); + BRegion oldFullVisible( _fullVisible ); +// BPoint oldFullVisibleOrigin( _fullVisible.Frame().LeftTop() ); - BRegion oldVisible( *_visible ); - _visible->OffsetBy( x, y ); - _full->OffsetBy( x, y ); + _frame.OffsetBy(x, y); - if(_parent) - { - BRegion exclude(oldVisible); - exclude.Exclude(_visible); + MoveRegionsBy(x, y); - if(_parent->_invalid == NULL) - _parent->_invalid = new BRegion( exclude ); - else - _parent->_invalid->Include( &exclude ); - - _parent->_is_dirty = true; - - // if _uppersibling is non-NULL, we have other layers which we may have been - // covering up. If we did cover up some siblings, they need to be redrawn - for(Layer *sib=_uppersibling;sib!=NULL;sib=sib->_uppersibling) - { - BRegion exclude2(oldVisible); - exclude2.Exclude(sib->_visible); - - if( exclude2.CountRects() != 0 ) - { - // The boundaries intersect on screen, so invalidate the area that - // was hidden - // a new region, becase we do not want to modify 'oldVisible' - BRegion exclude3(oldVisible); - exclude3.IntersectWith(sib->_visible); - - sib->Invalidate( exclude3 ); - sib->_is_dirty=true; + if (_parent){ + if ( !_hidden ){ + // to clear the area occupied on its parent _visible + if (_fullVisible.CountRects() > 0){ + _hidden = true; + _parent->RebuildChildRegions( _fullVisible.Frame(), this ); + _hidden = false; } + _parent->RebuildChildRegions( _full.Frame(), this ); } } - _is_dirty=true; + else{ + if ( !_hidden ) { + RebuildRegions( _full.Frame() ); + } + } + + // send a message to client if requested. + if(_flags & B_FRAME_EVENTS && _serverwin){ + BMessage msg; + // no locking? + msg.what = B_VIEW_MOVED; + msg.AddInt64( "when", real_time_clock_usecs() ); + msg.AddInt32( "_token", _view_token ); + msg.AddPoint( "where", _frame.LeftTop() ); + + _serverwin->SendMessageToClient( &msg ); + } + + // REDRAWING CODE: + + if ( !(_hidden) ) + { + /* The region(on screen) that will be invalidated. + * It is composed by: + * the regions that were visible, and now they aren't + + * the regions that are now visible, and they were not visible before. + * (oldFullVisible - _fullVisible) + (_fullVisible - oldFullVisible) + */ + BRegion clipReg; + + // first offset the old region so we can do the correct operations. + oldFullVisible.OffsetBy(x, y); + + // + (oldFullVisible - _fullVisible) + if ( oldFullVisible.CountRects() > 0 ){ + BRegion tempReg( oldFullVisible ); + tempReg.Exclude( &_fullVisible ); + + if (tempReg.CountRects() > 0){ + clipReg.Include( &tempReg ); + } + } + + // + (_fullVisible - oldFullVisible) + if ( _fullVisible.CountRects() > 0 ){ + BRegion tempReg( _fullVisible ); + tempReg.Exclude( &oldFullVisible ); + + if (tempReg.CountRects() > 0){ + clipReg.Include( &tempReg ); + } + } + + // there is no point in redrawing what already is visible. So just copy + // on-screen pixels to layer's new location. + if ( (oldFullVisible.CountRects() > 0) && (_fullVisible.CountRects() > 0) ){ + BRegion tempReg( oldFullVisible ); + tempReg.IntersectWith( &_fullVisible ); + + if (tempReg.CountRects() > 0){ +// TODO: when you have such a method in DisplayDriver/Clipper, uncomment! + //fDriver->CopyBits( &tempReg, oldFullVisibleOrigin, oldFullVisibleOrigin.OffsetByCopy(x,y) ); + } + } + + // invalidate 'clipReg' so we can see the results of this move. + if (clipReg.CountRects() > 0){ + Invalidate( clipReg ); + } + } +} + +void Layer::ResizeRegionsBy(float x, float y){ + _frame.right = _frame.right + x; + _frame.bottom = _frame.bottom + y; + + RebuildFullRegion(); + + /* Send messages to BViews only if this Layer belongs to a + * ServerWindow object + */ + BMessage msg; + if( _serverwin ) + { + msg.what = B_VIEW_RESIZED; + msg.AddInt64( "when", real_time_clock_usecs() ); + msg.AddInt32( "_token", _view_token ); + msg.AddFloat( "width", _frame.Width() ); + msg.AddFloat( "height", _frame.Height() ); + // no need for that... it's here because of backward compatibility + msg.AddPoint( "where", _frame.LeftTop() ); + + _serverwin->SendMessageToClient( &msg ); + msg.MakeEmpty(); + } + + Layer *c = _topchild; //c = short for: current + + if( c != NULL ) + while( true ){ + // action block + { + bool sendMovedToMsg = false; + bool sendResizedToMsg = false; + + { + BRect newFrame = c->_frame; + uint32 rmask = c->_resize_mode; + if (rmask == B_FOLLOW_NONE) + rmask = B_FOLLOW_LEFT | B_FOLLOW_TOP; + + // resize/move horizontaly + if (rmask & B_FOLLOW_LEFT){ + // nothing to do + } + else if (rmask & B_FOLLOW_RIGHT){ + newFrame.OffsetBy(x, 0.0f); + sendMovedToMsg = true; + } + else if (rmask & B_FOLLOW_LEFT_RIGHT){ + newFrame.SetRightBottom( BPoint(newFrame.right + x, newFrame.bottom) ); + sendResizedToMsg = true; + } + else if (rmask & B_FOLLOW_H_CENTER){ + newFrame.OffsetBy(x/2, 0.0f); + sendMovedToMsg = true; + } + else { // illegal flag. Do nothing. + } + + // resize/move verticaly + if (rmask & B_FOLLOW_TOP){ + // nothing to do + } + else if (rmask & B_FOLLOW_BOTTOM){ + newFrame.OffsetBy(0.0f, y); + sendMovedToMsg = true; + } + else if (rmask & B_FOLLOW_TOP_BOTTOM){ + newFrame.SetRightBottom( BPoint(newFrame.right, newFrame.bottom + y) ); + sendResizedToMsg = true; + } + else if (rmask & B_FOLLOW_V_CENTER){ + newFrame.OffsetBy(0.0f, y/2); + sendMovedToMsg = true; + } + else { // illegal flag. Do nothing. + } + + if (sendMovedToMsg && !sendResizedToMsg){ + c->_full.OffsetBy( (newFrame.left - c->_frame.left), + (newFrame.top - c->_frame.top) ); + } + + c->_frame = newFrame; + + if (sendResizedToMsg){ + c->RebuildFullRegion(); + } + } + + // send message to client it requested (flags & B_FRAME_EVENTS) + if ( c->_serverwin ){ + if ( sendMovedToMsg && (c->_flags & B_FRAME_EVENTS) ) { + msg.what = B_VIEW_MOVED; + msg.AddInt64( "when", real_time_clock_usecs() ); + msg.AddInt32( "_token", c->_view_token ); + msg.AddPoint( "where", c->_frame.LeftTop() ); + + c->_serverwin->SendMessageToClient( &msg ); + msg.MakeEmpty(); + } + + if ( sendResizedToMsg && (c->_flags & B_FRAME_EVENTS) ){ + msg.what = B_VIEW_RESIZED; + msg.AddInt64( "when", real_time_clock_usecs() ); + msg.AddInt32( "_token", c->_view_token ); + msg.AddFloat( "width", c->_frame.Width() ); + msg.AddFloat( "height", c->_frame.Height() ); + // no need for that... it's here because of backward compatibility + msg.AddPoint( "where", c->_frame.LeftTop() ); + + c->_serverwin->SendMessageToClient( &msg ); + msg.MakeEmpty(); + } + } + } + + // tree parsing algorithm + + // go deep + if( c->_topchild ){ + c = c->_topchild; + } + // go right or up + else + // go right + if( c->_lowersibling ){ + c = c->_lowersibling; + } + // go up + else{ + while( !c->_parent->_lowersibling && c->_parent != this ){ + c = c->_parent; + } + // that enough! We've reached this view. + if( c->_parent == this ) + break; + + c = c->_parent->_lowersibling; + } + } } /*! @@ -764,98 +874,150 @@ void Layer::MoveBy(float x, float y) */ void Layer::ResizeBy(float x, float y) { - // TODO: Implement and test child resizing based on flags - - BRect oldframe=_frame; - _frame.right+=x; - _frame.bottom+=y; + BRegion oldFullVisible( _fullVisible ); -// for(Layer *lay=_topchild; lay!=NULL; lay=lay->_lowersibling) -// lay->ResizeBy(x,y); + ResizeRegionsBy(x, y); - if(_parent) - _parent->RebuildRegions(true); - else - RebuildRegions(true); - if(x<0 || y<0) - _parent->Invalidate(oldframe); + if (_parent){ + if ( !_hidden ){ + _parent->RebuildChildRegions( _full.Frame(), this ); + } + } + else{ + if ( !_hidden ){ + RebuildRegions( _full.Frame() ); + } + } + + // REDRAWING CODE: + + if ( !(_hidden) ) + { + /* The region(on screen) that will be invalidated. + * It is composed by: + * the regions that were visible, and now they aren't + + * the regions that are now visible, and they were not visible before. + * (oldFullVisible - _fullVisible) + (_fullVisible - oldFullVisible) + */ + BRegion clipReg; + + // + (oldFullVisible - _fullVisible) + if ( oldFullVisible.CountRects() > 0 ){ + BRegion tempReg( oldFullVisible ); + tempReg.Exclude( &_fullVisible ); + + if (tempReg.CountRects() > 0){ + clipReg.Include( &tempReg ); + } + } + + // + (_fullVisible - oldFullVisible) + if ( _fullVisible.CountRects() > 0 ){ + BRegion tempReg( _fullVisible ); + tempReg.Exclude( &oldFullVisible ); + + if (tempReg.CountRects() > 0){ + clipReg.Include( &tempReg ); + } + } + + // invalidate 'clipReg' so we can see the results of this resize operation. + if (clipReg.CountRects() > 0){ + Invalidate( clipReg ); + } + } } +void Layer::RebuildChildRegions( const BRect &r, Layer* startFrom ){ + // just in case something goes wrong. + if ( _hidden ){ + printf("\nSERVER PANIC: Layer(%s)::RebuildChildRegions() - This should NOT happen.\n\n", _name->String()); + return; + } + + // here is the actual start of this method. :-)) + bool rebuild = false; + + _visible = _fullVisible; + + // Rebuild regions for children... if needed! + for(Layer *lay = _bottomchild; lay != NULL; lay = lay->_uppersibling) + { + // for layers in front of 'startLayer' no region rebuild is needed. + // so avoid unnecessary CPU cycles. + if ( lay == startFrom && rebuild == false) + rebuild = true; + + if ( !(lay->_hidden) ){ + if ( !rebuild ){ + // do not rebuild, but exclude lay's FULL visible region from its parent v.r. + _visible.Exclude( &(lay->_fullVisible) ); + } + else{ + lay->RebuildRegions( r ); + } + } + } +} /*! - \brief Rebuilds visibility regions for child layers + \brief Rebuilds visibility regions for this and child layers \param include_children Flag to rebuild all children and subchildren */ -void Layer::RebuildRegions(bool include_children) +void Layer::RebuildRegions( const BRect& r ) { -/* -STRACE(("\n*****Layer(%s)::RebuildRegions() START\n", _name->String())); -PrintTree(); -_visible->PrintToStream(); -*/ - // Algorithm: - // 1) Reset child visibility regions to completely visible - // 2) Clip each child to visible region of this layer - // 3) Clip each child to its siblings, going front to back - // 4) Remove the visible regions of the children from the current one + // if we're in the rebuild area, rebuild our v.r. + if ( _full.Intersects( r ) ){ + _visible = _full; - *_visible = *_full; - // Reset children to fully visible and clip to this layer's visible region - for(Layer *childlay=_topchild; childlay!=NULL; childlay=childlay->_lowersibling) - { - childlay->_visible->MakeEmpty(); - childlay->_visible->Include(childlay->_full); - - if( childlay->_hidden == false ) - childlay->_visible->IntersectWith( _visible ); - - _visible->Exclude( childlay->_visible ); -/* -STRACE(("\n\t*****Child Layer(%s) STEP 1\n", childlay->_name->String())); -childlay->PrintTree(); -childlay->_visible->PrintToStream(); -*/ - } - - // This region is the common clipping region used when clipping children to their - // siblings. We will use this because of efficiency - it is gradually built by - // first clipping a child to the region if the region is not empty and then - // adding the child's resulting footprint to the clipping region. Once all the - // children have been clipped, then the resulting region will allow for one call - // to remove the footprints of all the children from the layer's visible region. - BRegion clipregion; - - // Clip children to siblings which are closer to the front - for(Layer *siblay=_bottomchild; siblay!=NULL; siblay=siblay->_uppersibling) - { - if( clipregion.CountRects()>0 && - TestRectIntersection(siblay->Frame(),clipregion.Frame()) && - siblay->_visible && - siblay->_hidden==false ) - { - siblay->_visible->Exclude(&clipregion); + if (_parent){ + _visible.IntersectWith( &(_parent->_visible) ); + // exclude from parent's visible area. + if ( !(_hidden) ) + _parent->_visible.Exclude( &(_visible) ); } - clipregion.Include(siblay->_visible); -/* -STRACE(("\n\t*****Child Layer(%s) STEP 2\n", siblay->_name->String())); -siblay->PrintTree(); -siblay->_visible->PrintToStream(); -*/ + + _fullVisible = _visible; } - - // Rebuild the regions for subchildren if we're supposed to - if(include_children) + else{ + // our visible region will stay the same + + // exclude our FULL visible region from parent's visible region. + if ( !(_hidden) && _parent ) + _parent->_visible.Exclude( &(_fullVisible) ); + + // we're not in the rebuild area so our children's v.r.s are OK. + return; + } + + // Rebuild regions for children... + for(Layer *lay = _bottomchild; lay != NULL; lay = lay->_uppersibling) { - for(Layer *lay=_topchild; lay!=NULL; lay=lay->_lowersibling) - { - if(lay->_topchild) - lay->RebuildRegions(true); + if ( !(lay->_hidden) ){ + lay->RebuildRegions( r ); } } - _regions_invalid=false; -/* -STRACE(("\n*****Layer(%s)::RebuildRegions() END\n", _name->String())); -_visible->PrintToStream(); -*/ +} + +void Layer::RebuildFullRegion( ){ + _full.Set( ConvertToTop( _frame ) ); + + LayerData *ld; + + ld = _layerdata; + do{ + // clip to user region + if ( ld->clippReg ) + _full.IntersectWith( ld->clippReg ); + } while( (ld = ld->prevState) ); + + // clip to user picture region + if ( clipToPicture ) + if ( clipToPictureInverse ) { + _full.Exclude( clipToPicture ); + } + else{ + _full.IntersectWith( clipToPicture ); + } } //! Prints all relevant layer data to stdout @@ -885,18 +1047,7 @@ void Layer::PrintToStream(void) printf("Frame: "); _frame.PrintToStream(); printf("Token: %ld\nLevel: %ld\n",_view_token, _level); printf("Hide count: %s\n",_hidden?"true":"false"); - if(_invalid) - { - printf("Invalid Areas: "); _invalid->PrintToStream(); - } - else - printf("Invalid Areas: NULL\n"); - if(_visible) - { - printf("Visible Areas: "); _visible->PrintToStream(); - } - else - printf("Visible Areas: NULL\n"); + printf("Visible Areas: "); _visible.PrintToStream(); printf("Is updating = %s\n",(_is_updating)?"yes":"no"); } @@ -924,12 +1075,7 @@ void Layer::PrintNode(void) printf("Bottom child: %s (%p)\n",_bottomchild->_name->String(), _bottomchild); else printf("Bottom child: NULL\n"); - if(_visible) - { - printf("Visible Areas: "); _visible->PrintToStream(); - } - else - printf("Visible Areas: NULL\n"); + printf("Visible Areas: "); _visible.PrintToStream(); } //! Prints the tree structure starting from this layer @@ -1031,7 +1177,7 @@ BRegion Layer::ConvertToTop(BRegion *reg) BRegion newreg; for(int32 i=0; iCountRects();i++) newreg.Include(ConvertToTop(reg->RectAt(i))); - return BRegion(newreg); + return newreg; } /*! @@ -1057,7 +1203,7 @@ BRegion Layer::ConvertFromTop(BRegion *reg) BRegion newreg; for(int32 i=0; iCountRects();i++) newreg.Include(ConvertFromTop(reg->RectAt(i))); - return BRegion(newreg); + return newreg; } /*! @@ -1131,130 +1277,8 @@ void Layer::MakeBottomChild(void) } -void Layer::DoMoveTo(float x, float y){ -printf("Layer(%s)::DoMoveTo()...\n", _name->String()); - _frame.OffsetTo(x, y); - - if(_flags & B_FRAME_EVENTS && _serverwin){ - BMessage msg; - printf("\tLayer(%s)::DoMoveTo()...sending message to client\n", _name->String()); - // no locking? - msg.what = B_VIEW_MOVED; - msg.AddInt64( "when", real_time_clock_usecs() ); - msg.AddInt32( "_token", _view_token ); - msg.AddPoint( "where", _frame.LeftTop() ); - - _serverwin->SendMessageToClient( &msg ); - } -printf("\t DONE Layer(%s)::DoMoveTo()...\n", _name->String()); -} - - -void Layer::DoResizeTo(float newWidth, float newHeight){ -printf("Layer(%s)::DoResizeTo()...\n", _name->String()); - _frame.right = _frame.left + newWidth; - _frame.bottom = _frame.top + newHeight; - - /* Send messages to BViews only if this Layer belongs to a - * ServerWindow object - */ - if( _serverwin) - { - BMessage msg; - printf("\tLayer(%s)::DoResizeTo()...sending message to client\n", _name->String()); - msg.what = B_VIEW_RESIZED; - msg.AddInt64( "when", real_time_clock_usecs() ); - msg.AddInt32( "_token", _view_token ); - msg.AddFloat( "width", _frame.Width() ); - msg.AddFloat( "height", _frame.Height() ); - // no need for that... it's here because of backward compatibility - msg.AddPoint( "where", _frame.LeftTop() ); - - _serverwin->SendMessageToClient( &msg ); - msg.MakeEmpty(); - - Layer *c = _topchild; //c = short for: current - - if( c != NULL ) - while( true ){ - // action block - { - bool sendMovedToMsg = false; - bool sendResizedToMsg = false; - - { - // TODO: add resizing algorithm HERE. - /* NOTES: - * - use 'c' as the Layer for witch operations are done - * - IF the position of Layer 'c' was modified, set - * sendMovedToMsg to TRUE !!! - * - IF Layer 'c' has been resized, set - * sendResizedToMsg to TRUE !!! - */ - } - - /* Note: We do this because of optimization reasons. - * Calling DoMoveTo() would result in BSession::Sync() - * being called also; thus a performace loss. - */ - if ( sendMovedToMsg && (c->_flags & B_FRAME_EVENTS) ) { - msg.what = B_VIEW_MOVED; - msg.AddInt64( "when", real_time_clock_usecs() ); - msg.AddInt32( "_token", c->_view_token ); - msg.AddPoint( "where", c->_frame.LeftTop() ); - - c->_serverwin->SendMessageToClient( &msg ); - msg.MakeEmpty(); - } - - if ( sendResizedToMsg && (c->_flags & B_FRAME_EVENTS) ){ - msg.what = B_VIEW_RESIZED; - msg.AddInt64( "when", real_time_clock_usecs() ); - msg.AddInt32( "_token", c->_view_token ); - msg.AddFloat( "width", c->_frame.Width() ); - msg.AddFloat( "height", c->_frame.Height() ); - // no need for that... it's here because of backward compatibility - msg.AddPoint( "where", c->_frame.LeftTop() ); - - c->_serverwin->SendMessageToClient( &msg ); - msg.MakeEmpty(); - } - } - - // go deep - if( c->_topchild ){ - c = c->_topchild; - } - // go right or up - else - // go right - if( c->_lowersibling ){ - c = c->_lowersibling; - } - // go up - else{ - while( !c->_parent->_lowersibling && c->_parent != this ){ - c = c->_parent; - } - // that enough! We've reached this view. - if( c->_parent == this ) - break; - - c = c->_parent->_lowersibling; - } - } - } // END: if(_serverwin) -printf("\t DONE Layer(%s)::DoResizeTo()...\n", _name->String()); -} - /* @log * added 2 new methods - DoMoveTo and DoResizeTo. They move/resize the frame rectangle of Layer class. In DoResizeTo() I added some code for autoresizing(based on BView's resizeMask parameter) of children. Still, the effective code for resizing need to be written. :-) I could do that, but other things have greater priority. :-) */ - -LayerData* Layer::GetDrawData() -{ - _layerdata->fVisibleRegion = _visible; - return _layerdata; -} diff --git a/src/servers/app/server/Layer.h b/src/servers/app/server/Layer.h index f7275a0ebf..8087ea135b 100644 --- a/src/servers/app/server/Layer.h +++ b/src/servers/app/server/Layer.h @@ -44,6 +44,7 @@ class RootLayer; class WinBorder; class Screen; class ServerCursor; +class DisplayDriver; /*! \class Layer Layer.h @@ -56,65 +57,66 @@ class ServerCursor; class Layer { public: - Layer(BRect frame, const char *name, int32 token, uint32 resize, - uint32 flags, ServerWindow *win); - virtual ~Layer(void); + Layer(BRect frame, const char *name, int32 token, uint32 resize, + uint32 flags, ServerWindow *win); + virtual ~Layer(void); - void AddChild(Layer *child, Layer *before=NULL, bool rebuild=true); - void RemoveChild(Layer *child, bool rebuild=true); - void RemoveSelf(bool rebuild=true); - uint32 CountChildren(void); - void MakeTopChild(void); - void MakeBottomChild(void); - Layer *FindLayer(int32 token); - Layer *GetChildAt(BPoint pt, bool recursive=false); - Layer *GetUpperSibling() { return _uppersibling; } - Layer *GetLowerSibling() { return _lowersibling; } - PortLink *GetLink(void); - const char *GetName(void) { return (_name)?_name->String():NULL; } - LayerData *GetLayerData(void) { return _layerdata; } - LayerData *GetDrawData(void); + void AddChild(Layer *child, Layer *before=NULL); + void RemoveChild(Layer *child); + void RemoveSelf(); + uint32 CountChildren(void) const; + void MakeTopChild(void); + void MakeBottomChild(void); + Layer* FindLayer(const int32 token); + Layer* GetLayerAt(const BPoint &pt); + Layer* GetUpperSibling() const { return _uppersibling; } + Layer* GetLowerSibling() const { return _lowersibling; } + + const char* GetName(void) const { return (_name)?_name->String():NULL; } + LayerData* GetLayerData(void) const { return _layerdata; } - void SetLayerCursor(ServerCursor *csr); - ServerCursor *GetLayerCursor(void) const; - virtual void MouseTransit(uint32 transit); + void SetLayerCursor(ServerCursor *csr); + ServerCursor* GetLayerCursor(void) const; + virtual void MouseTransit(uint32 transit); - void Invalidate(const BRect &rect); - void Invalidate(BRegion& region); - void RebuildRegions(bool include_children=true); - virtual void RequestDraw(const BRect &r); - virtual void RequestDraw(void); - bool IsDirty(void) const; - void UpdateIfNeeded(bool force_update=false); - void MarkModified(BRect rect); - void UpdateRegions(bool force=false); - - void Show(void); - void Hide(void); - bool IsHidden(void); - - BRect Bounds(void); - BRect Frame(void); - - void DoMoveTo(float x, float y); - void DoResizeTo(float newWidth, float newHeight); - - virtual void MoveBy(float x, float y); - void ResizeBy(float x, float y); - - BRect ConvertToParent(BRect rect); - BRegion ConvertToParent(BRegion *reg); - BRect ConvertFromParent(BRect rect); - BRegion ConvertFromParent(BRegion *reg); - BRegion ConvertToTop(BRegion *reg); - BRect ConvertToTop(BRect rect); - BRegion ConvertFromTop(BRegion *reg); - BRect ConvertFromTop(BRect rect); + void Invalidate(const BRect &rect); + void Invalidate(const BRegion ®ion); + void DoInvalidate(const BRegion ®, Layer *start); + + virtual void RebuildRegions( const BRect& r ); + void RebuildChildRegions( const BRect &r, Layer* startFrom ); + void RebuildFullRegion(void); + void MoveRegionsBy(float x, float y); + void ResizeRegionsBy(float x, float y); - void PrintToStream(void); - void PrintNode(void); - void PruneTree(void); - void PrintTree(); + void RequestClientUpdate(const BRect &rect); + void RequestDraw(const BRect &r); + virtual void Draw(const BRect &r); + + void Show(void); + void Hide(void); + bool IsHidden(void) const; + + BRect Bounds(void) const; + BRect Frame(void) const; + + virtual void MoveBy(float x, float y); + virtual void ResizeBy(float x, float y); + + BRect ConvertToParent(BRect rect); + BRegion ConvertToParent(BRegion *reg); + BRect ConvertFromParent(BRect rect); + BRegion ConvertFromParent(BRegion *reg); + BRegion ConvertToTop(BRegion *reg); + BRect ConvertToTop(BRect rect); + BRegion ConvertFromTop(BRegion *reg); + BRect ConvertFromTop(BRect rect); + + void PruneTree(void); + + void PrintToStream(void); + void PrintNode(void); + void PrintTree(); protected: friend class RootLayer; @@ -122,28 +124,32 @@ protected: friend class Screen; friend class ServerWindow; - BRect _frame; - BPoint _boundsLeftTop; - Layer *_parent, - *_uppersibling, - *_lowersibling, - *_topchild, - *_bottomchild; - BRegion *_visible, - *_invalid, - *_full; - ServerWindow *_serverwin; - BString *_name; - int32 _view_token; - int32 _level; - uint32 _flags; - uint32 _resize_mode; - bool _hidden; - bool _is_dirty; - bool _is_updating; - bool _regions_invalid; - LayerData *_layerdata; - ServerCursor *_cursor; + BRect _frame; + BPoint _boundsLeftTop; + Layer *_parent, + *_uppersibling, + *_lowersibling, + *_topchild, + *_bottomchild; + + BRegion _visible, + _fullVisible, + _full; + + BRegion *clipToPicture; + bool clipToPictureInverse; + + ServerWindow *_serverwin; + BString *_name; + int32 _view_token; + int32 _level; + uint32 _flags; + uint32 _resize_mode; + bool _hidden; + bool _is_updating; + LayerData *_layerdata; + ServerCursor *_cursor; + DisplayDriver* fDriver; }; #endif diff --git a/src/servers/app/server/RootLayer.cpp b/src/servers/app/server/RootLayer.cpp index e2269fb5c5..c9088554fc 100644 --- a/src/servers/app/server/RootLayer.cpp +++ b/src/servers/app/server/RootLayer.cpp @@ -52,66 +52,25 @@ RootLayer::RootLayer(BRect rect, const char *layername, DisplayDriver *gfxdriver : Layer(rect, layername, B_NULL_TOKEN, B_FOLLOW_NONE, 0, NULL) { _view_token = rlayer_token_handler.GetToken(); - - _driver = gfxdriver; - _is_dirty = true; - _bgcolor = new RGBColor(); - _invalid->MakeEmpty(); - _invalid->Include(Bounds()); + + fDriver = gfxdriver; + + _hidden = false; } //! Frees all allocated heap memory (which happens to be none) ;) RootLayer::~RootLayer() { - delete _bgcolor; } /*! - \brief Requests that the layer be drawn on screen - \param r The bounding rectangle of the area given in the Layer's coordinates + \brief Draws this entire layer on screen */ -void RootLayer::RequestDraw(const BRect &r) +void RootLayer::Draw(const BRect &r) { - Invalidate(r); - RequestDraw(); -} - -/*! - \brief Requests that the layer be drawn on screen -*/ -void RootLayer::RequestDraw(void) -{ - if(!_is_dirty) - return; - - // Redraw the base - if(_invalid) - { - #ifdef DEBUG_ROOTLAYER - printf("ROOTLAYER: "); - _invalid->PrintToStream(); - printf("===========\n"); - #endif - for(int32 i=0; _invalid->CountRects();i++) - { - if(_invalid->RectAt(i).IsValid()) - _driver->FillRect(_invalid->RectAt(i),_layerdata, pat_solidlow); - else - break; - } - - delete _invalid; - _invalid=NULL; - } - - // force redraw of all dirty windows - for(Layer *lay=_topchild; lay!=NULL; lay=lay->_lowersibling) - { - if(lay->IsDirty()) - lay->RequestDraw(); - } - - _is_dirty=false; +/* THIS method is here because of DisplayDriver testing! + * It SHOULD BE REMOVED as soon as testing is done!!!! + */ #ifdef DISPLAYDRIVER_TEST_HACK int8 pattern[8]; @@ -182,7 +141,7 @@ void RootLayer::RequestDraw(void) */ void RootLayer::SetColor(const RGBColor &col) { - _layerdata->lowcolor=col; + _layerdata->viewcolor = col; } /*! @@ -191,7 +150,7 @@ void RootLayer::SetColor(const RGBColor &col) */ RGBColor RootLayer::GetColor(void) const { - return _layerdata->lowcolor; + return _layerdata->viewcolor; } //! Empty function to disable moving the RootLayer @@ -199,39 +158,21 @@ void RootLayer::MoveBy(float x, float y) { } -//! Empty function to disable moving the RootLayer -void RootLayer::MoveBy(BPoint pt) -{ -} - //! Reimplemented for RootLayer special case void RootLayer::ResizeBy(float x, float y) { - BRect oldframe=_frame; - _frame.right+=x; - _frame.bottom+=y; + _frame.right += x; + _frame.bottom += y; - // We'll need to rebuild the regions of the child layers - // because resizing will affect the visible regions - RebuildRegions(true); - - // If we've gotten bigger, we'll need to repaint the new areas - if(x>0) - { - BRect dx(oldframe.right,oldframe.top, _frame.right, _frame.bottom); - Invalidate(dx); - } - if(y>0) - { - BRect dy(oldframe.left,oldframe.bottom, _frame.right, _frame.bottom); - Invalidate(dy); - } -} + _full.Set( _frame ); // NO ConvertTopTop !!! -//! Reimplemented for RootLayer special case -void RootLayer::ResizeBy(BPoint pt) -{ - ResizeBy(pt.x,pt.y); + // We need to rebuild ALL regions because the screen is black now, + // and ALL views/Layers need redrawing. + RebuildRegions( _frame ); + + // Invalidate the hole screen, because we've changed resolution + // and the screen is black. + Invalidate( _frame ); } /*! @@ -240,19 +181,5 @@ void RootLayer::ResizeBy(BPoint pt) */ void RootLayer::SetDriver(DisplayDriver *driver) { - _driver=driver; -} - -/*! - \brief Rebuilds the visible and invalid layers based on the layer hierarchy - \param recursive (Defaults to false) -*/ -void RootLayer::RebuildRegions(bool recursive) -{ - // Unlike the other layers, RootLayers can't depend on their parent layer to reset its - // visible region, so we have to do it itself. - _visible->MakeEmpty(); - _visible->Include(_full); - - Layer::RebuildRegions(recursive); + fDriver = driver; } diff --git a/src/servers/app/server/RootLayer.h b/src/servers/app/server/RootLayer.h index de7e7accb0..f563324319 100644 --- a/src/servers/app/server/RootLayer.h +++ b/src/servers/app/server/RootLayer.h @@ -43,22 +43,20 @@ class RGBColor; class RootLayer : public Layer { public: - RootLayer(BRect rect, const char *layername, DisplayDriver *gfxdriver); - ~RootLayer(); - virtual void RequestDraw(); - virtual void RequestDraw(const BRect &r); - virtual void MoveBy(float x, float y); - void MoveBy(BPoint pt); - void ResizeBy(float x, float y); - void ResizeBy(BPoint pt); - void SetDriver(DisplayDriver *driver); - void SetColor(const RGBColor &col); - RGBColor GetColor(void) const; - void RebuildRegions(bool recursive=false); + RootLayer(BRect rect, const char *layername, + DisplayDriver *gfxdriver); + virtual ~RootLayer(); + + virtual void Draw(const BRect &r); + virtual void MoveBy(float x, float y); + virtual void ResizeBy(float x, float y); + + void SetDriver(DisplayDriver *driver); + + void SetColor(const RGBColor &col); + RGBColor GetColor(void) const; private: - DisplayDriver *_driver; - RGBColor *_bgcolor; - bool _isvisible; + }; #endif diff --git a/src/servers/app/server/ServerWindow.cpp b/src/servers/app/server/ServerWindow.cpp index 89b454a36d..45dba7f1fe 100644 --- a/src/servers/app/server/ServerWindow.cpp +++ b/src/servers/app/server/ServerWindow.cpp @@ -130,42 +130,60 @@ ServerWindow::ServerWindow(BRect rect, const char *string, uint32 wlook, _look = wlook; _feel = wfeel; _handlertoken = handlerID; - cl = NULL; winLooperPort = looperPort; + _workspace_index= index; + _workspace = NULL; + _token = win_token_handler.GetToken(); - _winborder = new WinBorder(_frame,_title->String(),wlook,wfeel,wflags,this); - // _sender is the monitored window's event port + // HAVE messaging working. + // _sender is the port to which the app awaits messages from the server _sender = winport; - - _winlink = new PortLink(_sender); - _applink = (winapp)? new PortLink(winapp->_receiver) : NULL; - - // _receiver is the port to which the app sends messages for the server + // _receiver is the port to which the app sends messages for the server _receiver = create_port(30,_title->String()); - ses = new BSession( _receiver, _sender ); // Send a reply to our window - it is expecting _receiver port. ses->WriteData( &_receiver, sizeof(port_id) ); ses->Sync(); - top_layer = NULL; - - _active = false; + // WAIT for top_view data and create ServerWindow's top most Layer + int32 vMsg; + int32 vToken; + BRect vFrame; + uint32 vResizeMode; + uint32 vFlags; + char* vName = NULL; - // Spawn our message monitoring _monitorthread - _monitorthread = spawn_thread( MonitorWin, _title->String(), - B_NORMAL_PRIORITY, this ); - if(_monitorthread != B_NO_MORE_THREADS && - _monitorthread != B_NO_MEMORY) + ses->ReadInt32( &vMsg ); + if (vMsg != AS_LAYER_CREATE_ROOT){ + debugger("SERVER ERROR: ServerWindow(xxx): NO top_view data received!\n"); + } + ses->ReadInt32( &vToken ); + ses->ReadRect( &vFrame ); + ses->ReadUInt32( &vResizeMode ); + ses->ReadUInt32( &vFlags ); + vName = ses->ReadString(); + + top_layer = new Layer( vFrame, vName, vToken, vResizeMode, + vFlags, this ); + delete vName; + + cl = top_layer; + + + // CREATE a WindoBorder object for our ServerWindow. + _winborder = new WinBorder(_frame,_title->String(),wlook,wfeel,wflags,this); + + + // SPAWN our message monitoring _monitorthread + _monitorthread = spawn_thread( MonitorWin, _title->String(), B_NORMAL_PRIORITY, this ); + if(_monitorthread != B_NO_MORE_THREADS && _monitorthread != B_NO_MEMORY) resume_thread( _monitorthread ); - _workspace_index= index; - _workspace = NULL; - _token = win_token_handler.GetToken(); + // ADD window to desktop structure. AddWindowToDesktop(this,index,ActiveScreen()); STRACE(("ServerWindow %s:\n",_title->String() )); STRACE(("\tFrame (%.1f,%.1f,%.1f,%.1f)\n",rect.left,rect.top,rect.right,rect.bottom)); @@ -262,7 +280,7 @@ STRACE(("ServerWindow %s: Show\n",_title->String())); { _winborder->Show(); _winborder->SetFocus(true); - _winborder->UpdateRegions(true); +// _winborder->UpdateRegions(true); } } @@ -297,7 +315,7 @@ STRACE(("ServerWindow %s: Set Focus to %s\n",_title->String(),value?"true":"fals { _active=value; _winborder->SetFocus(value); - _winborder->RequestDraw(); +// _winborder->RequestDraw(); } } @@ -473,15 +491,7 @@ void ServerWindow::DispatchMessage( int32 code ) // there is no way of setting this, other than manual. :-) newLayer->_hidden = hidden; - // TODO: 'before' Layer support??? - - // TODO: review Layer::AddChild - // newLayer's parent will invalidate the area that its new child - // occupies, here in AddChild() - cl->AddChild( newLayer ); - cl->PrintTree(); - - // we set Layer attributes (BView's state)... + // we set Layer's attributes (BView's state) cl = newLayer; int32 msgCode; @@ -490,8 +500,11 @@ void ServerWindow::DispatchMessage( int32 code ) ses->ReadInt32( &msgCode ); // this is AS_LAYER_SET_STATE DispatchMessage( msgCode ); + + // attach the view to the tree structure. + oldCL->AddChild( newLayer ); - // ... and attach its children. + // attach its children. for(int i = 0; i < childCount; i++){ ses->ReadInt32( &msgCode ); // this is AS_LAYER_CREATE DispatchMessage( msgCode ); @@ -513,7 +526,7 @@ void ServerWindow::DispatchMessage( int32 code ) parent = cl->_parent; // here we remove current layer from list. - cl->RemoveSelf( false ); + cl->RemoveSelf(); // TODO: invalidate the region occupied by this view. // Should be done in Layer::RemoveChild() though! cl->PruneTree(); @@ -568,11 +581,15 @@ void ServerWindow::DispatchMessage( int32 code ) ses->ReadRect( &rect ); cl->_layerdata->clippReg->Include( rect ); } + + cl->RebuildFullRegion(); } else{ if ( cl->_layerdata->clippReg ){ delete cl->_layerdata->clippReg; cl->_layerdata->clippReg = NULL; + + cl->RebuildFullRegion(); } } @@ -703,7 +720,7 @@ void ServerWindow::DispatchMessage( int32 code ) ses->ReadFloat( &x ); ses->ReadFloat( &y ); - cl->DoMoveTo(x, y); + cl->MoveBy(x, y); STRACE(("ServerWindow %s: Message AS_LAYER_MOVETO: Layer: %s\n",_title->String(), cl->_name->String())); break; @@ -717,7 +734,7 @@ void ServerWindow::DispatchMessage( int32 code ) /* TODO: check for minimum alowed. WinBorder should provide such * a method, based on its decorator. */ - cl->DoResizeTo( newWidth, newHeight ); + cl->ResizeBy( newWidth, newHeight ); STRACE(("ServerWindow %s: Message AS_LAYER_RESIZETO: Layer: %s\n",_title->String(), cl->_name->String())); break; @@ -824,6 +841,8 @@ void ServerWindow::DispatchMessage( int32 code ) LayerData *ld = new LayerData(); ld->prevState = cl->_layerdata; cl->_layerdata = ld; + + cl->RebuildFullRegion(); STRACE(("ServerWindow %s: Message AS_LAYER_PUSH_STATE: Layer: %s\n",_title->String(), cl->_name->String())); break; @@ -838,6 +857,8 @@ void ServerWindow::DispatchMessage( int32 code ) LayerData *ld = cl->_layerdata; cl->_layerdata = cl->_layerdata->prevState; delete ld; + + cl->RebuildFullRegion(); STRACE(("ServerWindow %s: Message AS_LAYER_POP_STATE: Layer: %s\n",_title->String(), cl->_name->String())); break; @@ -1004,16 +1025,27 @@ void ServerWindow::DispatchMessage( int32 code ) ses->ReadInt32( &pictureToken ); ses->ReadPoint( &where ); + + BRegion reg; + bool redraw = false; + + // if we had a picture to clip to, include the FULL visible region(if any) in the area to be redrawn + // in other words: invalidate what ever is visible for this layer and his children. + if ( cl->clipToPicture && cl->_fullVisible.CountRects() > 0 ){ + reg.Include( &cl->_fullVisible ); + redraw = true; + } + + // search for a picture with the specified token. ServerPicture *sp = NULL; int32 i = 0; - for(;;){ sp = static_cast(cl->_serverwin->_app->_piclist->ItemAt(i++)); if (!sp) break; if( sp->GetToken() == pictureToken ){ - cl->_layerdata->clippPicture = sp; +// cl->clipToPicture = sp; // TODO: increase that picture's reference count.( ~ allocate a picture ) break; } @@ -1021,14 +1053,34 @@ void ServerWindow::DispatchMessage( int32 code ) // avoid compiler warning i = 0; - cl->_layerdata->clippInverse = false; + // we have a new picture to clip to, so rebuild our full region + if( cl->clipToPicture ) { + + cl->clipToPictureInverse = false; + + cl->RebuildFullRegion(); + } + + // we need to rebuild the visible region, we may have a valid one. + if (cl->_parent && !(cl->_hidden) ){ + cl->_parent->RebuildChildRegions(cl->_full.Frame(), cl); + } + else{ + // will this happen? Maybe... + cl->RebuildRegions(cl->_full.Frame()); + } + + // include our full visible region in the region to be redrawn + if ( !(cl->_hidden) && (cl->_fullVisible.CountRects() > 0) ){ + reg.Include( &(cl->_fullVisible) ); + redraw = true; + } + + // redraw if: we had OR if we NOW have a picture to clip to. + if (redraw){ + cl->Invalidate( reg ); + } - /* TODO: modify when you have a function that returns the clipping - * region composed by: the visible region & local clipping - * region(across states) & the picture clipping region. - */ - cl->RequestDraw( cl->_layerdata->clippReg->Frame() ); - STRACE(("ServerWindow %s: Message AS_LAYER_CLIP_TO_PICTURE: Layer: %s\n",_title->String(), cl->_name->String())); break; } @@ -1050,7 +1102,7 @@ void ServerWindow::DispatchMessage( int32 code ) break; if( sp->GetToken() == pictureToken ){ - cl->_layerdata->clippPicture = sp; +// cl->clipToPicture = sp; // TODO: increase that picture's reference count.( ~ allocate a picture ) break; } @@ -1058,13 +1110,15 @@ void ServerWindow::DispatchMessage( int32 code ) // avoid compiler warning i = 0; - cl->_layerdata->clippInverse = true; + // if a picture has been found... + if( cl->clipToPicture ) { - /* TODO: modify when you have a function that returns the clipping - * region composed by: the visible region & local clipping - * region(across states) & the picture clipping region. - */ - cl->RequestDraw( cl->_layerdata->clippReg->Frame() ); + cl->clipToPictureInverse = true; + + cl->RebuildFullRegion(); + + cl->RequestDraw( cl->clipToPicture->Frame() ); + } STRACE(("ServerWindow %s: Message AS_LAYER_CLIP_TO_INVERSE_PICTURE: Layer: %s\n",_title->String(), cl->_name->String())); break; @@ -1077,7 +1131,7 @@ void ServerWindow::DispatchMessage( int32 code ) int32 noOfRects; ld = cl->_layerdata; - reg = cl->ConvertFromParent( cl->_visible ); + reg = cl->ConvertFromParent( &(cl->_visible) ); if( ld->clippReg ) reg.IntersectWith( ld->clippReg ); @@ -1115,12 +1169,10 @@ void ServerWindow::DispatchMessage( int32 code ) ses->ReadRect( &r ); cl->_layerdata->clippReg->Include( r ); } - - /* TODO: modify when you have a function that returns the clipping - * region composed by: the visible region & local clipping - * region(across states) & the picture clipping region. - */ - cl->RequestDraw( cl->_layerdata->clippReg->Frame() ); + + cl->RebuildFullRegion(); + + cl->RequestDraw( cl->clipToPicture->Frame() ); STRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: Layer: %s\n",_title->String(), cl->_name->String())); break; @@ -1166,30 +1218,6 @@ void ServerWindow::DispatchMessage( int32 code ) /********** END: BView Messages ***********/ /********** BWindow Messages ***********/ - case AS_LAYER_CREATE_ROOT: - { - // Received when a window creates its internal top view - int32 token; - BRect frame; - uint32 resizeMode; - uint32 flags; - char* name = NULL; - - ses->ReadInt32( &token ); - ses->ReadRect( &frame ); - ses->ReadInt32( (int32*)&resizeMode ); - ses->ReadInt32( (int32*)&flags ); - name = ses->ReadString(); - - top_layer = new Layer( frame, name, token, resizeMode, - flags, this ); - cl = top_layer; - - STRACE(("ServerWindow %s: Setting currentLayer to: '%s'\n", _title->String(), name )); - STRACE(("ServerWindow %s: Message Create_Layer_Root\n",_title->String())); - delete name; - break; - } case AS_LAYER_DELETE_ROOT: { // Received when a window deletes its internal top view @@ -2150,15 +2178,13 @@ Layer* ServerWindow::FindLayer(const Layer* start, int32 token) const //----------------------------------------------------------------------- -void ServerWindow::SendMessageToClient( const BMessage* msg ) const -{ +void ServerWindow::SendMessageToClient( const BMessage* msg ) const{ ssize_t size; char *buffer; size = msg->FlattenedSize(); buffer = new char[size]; - if ( msg->Flatten( buffer, size ) == B_OK ) - { + if ( msg->Flatten( buffer, size ) == B_OK ){ write_port( winLooperPort, msg->what, buffer, size ); } else diff --git a/src/servers/app/server/WinBorder.cpp b/src/servers/app/server/WinBorder.cpp index 945514b67a..7300412501 100644 --- a/src/servers/app/server/WinBorder.cpp +++ b/src/servers/app/server/WinBorder.cpp @@ -97,41 +97,59 @@ WinBorder::WinBorder(const BRect &r, const char *name, const int32 look, const i { // unlike BViews, windows start off as hidden, so we need to tweak the hidecount // assignment made by Layer(). - _hidden = true; - _mbuttons = 0; - _kmodifiers = 0; - _win = win; + _hidden = true; + _mbuttons = 0; + _kmodifiers = 0; + _win = win; + _update = false; + _hresizewin = false; + _vresizewin = false; _mousepos.Set(0,0); - _update = false; - _title = new BString(name); - _hresizewin = false; - _vresizewin = false; - _driver = GetGfxDriver(ActiveScreen()); - _decorator = new_decorator(r,name,look,feel,flags,GetGfxDriver(ActiveScreen())); - _decorator->GetFootprint(_visible); + _decorator = NULL; - *_full = *_visible; - *_invalid = *_visible; - _frame = _visible->Frame(); - - // I tend to think it is not needed, so if it isn't, DW, please remove it. - _view_token = border_token_handler.GetToken(); + if (feel == B_NO_BORDER_WINDOW_LOOK){ + _full = _win->top_layer->_full; + fDecFull = NULL; + fDecFullVisible = NULL; + fDecVisible = NULL; + } + else{ + _decorator = new_decorator(r, name, look, feel, flags, fDriver); + fDecFull = new BRegion(); + fDecVisible = new BRegion(); + fDecFullVisible = fDecVisible; - _decorator->SetDriver(_driver); - _decorator->SetTitle(name); - + _decorator->GetFootprint( fDecFull ); - STRACE(("WinBorder %s:\n",_title->String())); - STRACE(("\tFrame: (%.1f,%.1f,%.1f,%.1f)\n",r.left,r.top,r.right,r.bottom)); - STRACE(("\tWindow %s\n",win?win->Title():"NULL")); + // our full region is the union between decorator's region and top_layer's region + _full = _win->top_layer->_full; + _full.Include( fDecFull ); + } + + // get a token + _view_token = border_token_handler.GetToken(); + +STRACE(("WinBorder %s:\n",_title->String())); +STRACE(("\tFrame: (%.1f,%.1f,%.1f,%.1f)\n",r.left,r.top,r.right,r.bottom)); +STRACE(("\tWindow %s\n",win?win->Title():"NULL")); } WinBorder::~WinBorder(void) { - STRACE(("WinBorder %s:~WinBorder()\n",_title->String())); - delete _title; +STRACE(("WinBorder %s:~WinBorder()\n",_title->String())); + if (_decorator) { + delete _decorator; + _decorator = NULL; + + delete fDecFull; + fDecFull = NULL; + + delete fDecFullVisible; // NOTE: fDecFullVisible == fDecVisible + fDecFullVisible = NULL; + fDecVisible = NULL; + } } void WinBorder::MouseDown(int8 *buffer) @@ -143,94 +161,88 @@ void WinBorder::MouseDown(int8 *buffer) // 4) int32 - modifier keys down // 5) int32 - buttons down // 6) int32 - clicks - int8 *index=buffer; index+=sizeof(int64); - float x=*((float*)index); index+=sizeof(float); - float y=*((float*)index); index+=sizeof(float); - int32 modifiers=*((int32*)index); index+=sizeof(int32); - int32 buttons=*((int32*)index); + int8 *index = buffer; index+=sizeof(int64); + float x = *((float*)index); index+=sizeof(float); + float y = *((float*)index); index+=sizeof(float); + int32 modifiers = *((int32*)index); index+=sizeof(int32); + int32 buttons = *((int32*)index); BPoint pt(x,y); - _mbuttons=buttons; - _kmodifiers=modifiers; - click_type click=_decorator->Clicked(pt, _mbuttons, _kmodifiers); - _mousepos=pt; - - switch(click) - { - case CLICK_MOVETOBACK: - { - STRACE_CLICK(("Click: MoveToBack\n")); - MakeTopChild(); - break; - } - case CLICK_MOVETOFRONT: - { - STRACE_CLICK(("Click: MoveToFront\n")); - MakeBottomChild(); - break; - } - case CLICK_CLOSE: - { - STRACE_CLICK(("Click: Close\n")); - _decorator->SetClose(true); - _decorator->DrawClose(); - break; - } - case CLICK_ZOOM: - { - STRACE_CLICK(("Click: Zoom\n")); - _decorator->SetZoom(true); - _decorator->DrawZoom(); - break; - } - case CLICK_MINIMIZE: - { - STRACE_CLICK(("Click: Minimize\n")); - _decorator->SetMinimize(true); - _decorator->DrawMinimize(); - break; - } - case CLICK_DRAG: - { - if(buttons==B_PRIMARY_MOUSE_BUTTON) - { - STRACE_CLICK(("Click: Drag\n")); - MakeBottomChild(); - set_is_moving_window(true); - } - - if(buttons==B_SECONDARY_MOUSE_BUTTON) + // user clicked on decorator + if (fDecFullVisible->Contains(pt)){ + click_type click; + click = _decorator->Clicked(pt, buttons, modifiers); + + switch(click){ + case CLICK_MOVETOBACK: { STRACE_CLICK(("Click: MoveToBack\n")); - MakeTopChild(); + MoveToBack(); + break; } - break; - } - case CLICK_SLIDETAB: - { - STRACE_CLICK(("Click: Slide Tab\n")); - set_is_sliding_tab(true); - break; - } - case CLICK_RESIZE: - { - if(buttons==B_PRIMARY_MOUSE_BUTTON) + case CLICK_MOVETOFRONT: + { + STRACE_CLICK(("Click: MoveToFront\n")); + MoveToFront(); + break; + } + case CLICK_CLOSE: + { + STRACE_CLICK(("Click: Close\n")); + RemoveSelf(); + break; + } + case CLICK_ZOOM: + { + STRACE_CLICK(("Click: Zoom\n")); + // TODO: implement + // if (actual_coods != max_zoom_coords) + // MoveBy(X, Y); + // ResizeBy(X, Y); + break; + } + case CLICK_MINIMIZE: + { + STRACE_CLICK(("Click: Minimize\n")); + if ( !IsHidden() ){ + Hide(); + } + break; + } + case CLICK_DRAG: + { + STRACE_CLICK(("Click: Drag\n")); + set_is_moving_window(true); + break; + } + case CLICK_SLIDETAB: + { + STRACE_CLICK(("Click: Slide Tab\n")); + set_is_sliding_tab(true); + break; + } + case CLICK_RESIZE: { STRACE_CLICK(("Click: Resize\n")); set_is_resizing_window(true); + break; + } + case CLICK_NONE: + default: + { + break; } - break; - } - case CLICK_NONE: - { - break; - } - default: - { - break; } } + // user clicked in window's area + else{ + /* + TODO: implement!!! + NOTE: send that message to BViews registered for receiving mouse&keyboard events. + SendMouseMessage( B_MOUSE_DOWN ); + */ + } } void WinBorder::MouseMoved(int8 *buffer) @@ -268,7 +280,7 @@ void WinBorder::MouseMoved(int8 *buffer) if(is_sliding_tab()) { - STRACE_CLICK(("ClickMove: Slide Tab\n")); +STRACE_CLICK(("ClickMove: Slide Tab\n")); float dx=pt.x-_mousepos.x; float dy=pt.y-_mousepos.y; @@ -279,7 +291,7 @@ void WinBorder::MouseMoved(int8 *buffer) // we can invalidate the proper area. lock_layers(); _parent->Invalidate(_decorator->SlideTab(dx,dy)); - _parent->RequestDraw(); +// _parent->RequestDraw(); // _decorator->DrawTab(); unlock_layers(); } @@ -291,7 +303,7 @@ void WinBorder::MouseMoved(int8 *buffer) // We are moving the window. Because speed is of the essence, we need to handle a lot // of stuff which we might otherwise not need to. - STRACE_CLICK(("ClickMove: Drag\n")); +STRACE_CLICK(("ClickMove: Drag\n")); float dx = pt.x - _mousepos.x, dy = pt.y - _mousepos.y; if(buttons!=0 && (dx!=0 || dy!=0)) @@ -320,7 +332,7 @@ void WinBorder::MouseMoved(int8 *buffer) _decorator->MoveBy(BPoint(dx, dy)); // 3) quickly move the window - _driver->CopyRegion(®,reg2.Frame().LeftTop()); +// _driver->CopyRegion(®,reg2.Frame().LeftTop()); // 4) Invalidate only the areas which we can't redraw directly for(int32 i=0; iInvalidate(reg); - _parent->RebuildRegions(); - _parent->RequestDraw(); +// _parent->RebuildRegions(); +// _parent->RequestDraw(); unlock_layers(); } @@ -352,7 +364,7 @@ void WinBorder::MouseMoved(int8 *buffer) if(is_resizing_window()) { - STRACE_CLICK(("ClickMove: Resize\n")); +STRACE_CLICK(("ClickMove: Resize\n")); float dx = pt.x - _mousepos.x, dy = pt.y - _mousepos.y; if(buttons!=0 && (dx!=0 || dy!=0)) @@ -367,10 +379,10 @@ void WinBorder::MouseMoved(int8 *buffer) lock_layers(); ResizeBy(dx,dy); - _parent->RequestDraw(); +// _parent->RequestDraw(); unlock_layers(); _decorator->ResizeBy(dx,dy); - _decorator->Draw(); +// _decorator->Draw(); } } @@ -380,8 +392,7 @@ void WinBorder::MouseMoved(int8 *buffer) void WinBorder::MouseUp(int8 *buffer) { - STRACE_MOUSE(("WinBorder %s: MouseUp() \n",_title->String())); - +STRACE_MOUSE(("WinBorder %s: MouseUp() \n",_title->String())); // buffer data: // 1) int64 - time of mouse click // 2) float - x coordinate of mouse click @@ -446,93 +457,325 @@ void WinBorder::MouseUp(int8 *buffer) */ void WinBorder::SetFocus(const bool &active) { - if(_decorator) - _decorator->SetFocus(active); + _decorator->SetFocus(active); } -void WinBorder::RequestDraw(const BRect &r) -{ - STRACE(("WinBorder %s: RequestDraw(BRect)\n",_title->String())); - #ifdef DEBUG_WINBORDER - PrintToStream(); - #endif +void WinBorder::RebuildRegions( const BRect& r ){ + /* WinBorder is a little bit special. It doesn't have a visible region + in witch to do its drawings. Instead the hole visible region is split + between decorator and top_layer. + */ - _decorator->Draw(r); - delete _invalid; - _invalid = NULL; -} + // if we're in the rebuild area, rebuild our v.r. + if ( _full.Intersects( r ) ){ + _visible = _full; -void WinBorder::RequestDraw(void) -{ - STRACE(("WinBorder %s::RequestDraw()\n",_title->String())); - #ifdef DEBUG_WINBORDER - PrintToStream(); - #endif - - if(_invalid) - { - for(int32 i=0;i<_invalid->CountRects();i++) - _decorator->Draw(_invalid->RectAt(i)); - - delete _invalid; - _invalid = NULL; + if (_parent){ + _visible.IntersectWith( &(_parent->_visible) ); + // exclude from parent's visible area. + if ( !(_hidden) ) + _parent->_visible.Exclude( &(_visible) ); + } + + _fullVisible = _visible; + } + else{ + // our visible region will stay the same + + // exclude our FULL visible region from parent's visible region. + if ( !(_hidden) && _parent ) + _parent->_visible.Exclude( &(_fullVisible) ); + + // we're not in the rebuild area so our children's v.r.s are OK. + return; + } + + // rebuild top_layer: + if ( _win->top_layer->_full.Intersects( r ) ){ + // build top_layer's visible region by intersecting its _full with winborder's _visible region. + _win->top_layer->_visible = _win->top_layer->_full; + _win->top_layer->_visible.IntersectWith( &(_visible) ); + + // then exclude it from winborder's _visible... + _visible.Exclude( &(_win->top_layer->_visible) ); + + _win->top_layer->_fullVisible = _win->top_layer->_visible; + + // Rebuild regions for children... + for(Layer *lay = _win->top_layer->_bottomchild; lay != NULL; lay = lay->_uppersibling){ + if ( !(lay->_hidden) ){ + lay->RebuildRegions( r ); + } + } + } + else{ + _visible.Exclude( &(_win->top_layer->_fullVisible) ); + } + + // rebuild decorator. + if (_decorator){ + if ( fDecFull->Intersects( r ) ){ + *fDecVisible = *fDecFull; + fDecVisible->IntersectWith( &(_visible) ); + + _visible.Exclude( fDecVisible ); + + // !!!! Pointer assignement !!!! + fDecFullVisible = fDecVisible; + } + else{ + _visible.Exclude( fDecFullVisible ); + } } - else - _decorator->Draw(); } -/* -void WinBorder::MoveBy(BPoint pt) + +void WinBorder::Draw(const BRect &r) { + // draw the decorator + BRegion reg(r); + if (_decorator){ + reg.IntersectWith( fDecVisible ); + if (reg.CountRects() > 0){ + _decorator->Draw( reg.Frame() ); + } + } + + // draw the top_layer + reg.Set( r ); + reg.IntersectWith( &(_win->top_layer->_visible) ); + if (reg.CountRects() > 0){ + _win->top_layer->RequestClientUpdate( reg.Frame() ); + } } void WinBorder::MoveBy(float x, float y) { -} + BRegion oldFullVisible( _fullVisible ); +// BPoint oldFullVisibleOrigin( _fullVisible.Frame().LeftTop() ); -void WinBorder::ResizeBy(BPoint pt) -{ + _frame.OffsetBy(x, y); + _full.OffsetBy(x, y); + + _win->top_layer->_frame.OffsetBy(x, y); + _win->top_layer->MoveRegionsBy(x, y); + + if (_decorator){ + // allow decorator to make its internal calculations. + _decorator->MoveBy(x, y); + + fDecFull->OffsetBy(x, y); + } + + if ( !_hidden ){ + // to clear the area occupied on its parent _visible + if (_fullVisible.CountRects() > 0){ + _hidden = true; + _parent->RebuildChildRegions( _fullVisible.Frame(), this ); + _hidden = false; + } + _parent->RebuildChildRegions( _full.Frame(), this ); + } + + // REDRAWING CODE: + + if ( !(_hidden) ) + { + /* The region(on screen) that will be invalidated. + * It is composed by: + * the regions that were visible, and now they aren't + + * the regions that are now visible, and they were not visible before. + * (oldFullVisible - _fullVisible) + (_fullVisible - oldFullVisible) + */ + BRegion clipReg; + + // first offset the old region so we can do the correct operations. + oldFullVisible.OffsetBy(x, y); + + // + (oldFullVisible - _fullVisible) + if ( oldFullVisible.CountRects() > 0 ){ + BRegion tempReg( oldFullVisible ); + tempReg.Exclude( &_fullVisible ); + + if (tempReg.CountRects() > 0){ + clipReg.Include( &tempReg ); + } + } + + // + (_fullVisible - oldFullVisible) + if ( _fullVisible.CountRects() > 0 ){ + BRegion tempReg( _fullVisible ); + tempReg.Exclude( &oldFullVisible ); + + if (tempReg.CountRects() > 0){ + clipReg.Include( &tempReg ); + } + } + + // there is no point in redrawing what already is visible. So just copy + // on-screen pixels to layer's new location. + if ( (oldFullVisible.CountRects() > 0) && (_fullVisible.CountRects() > 0) ){ + BRegion tempReg( oldFullVisible ); + tempReg.IntersectWith( &_fullVisible ); + + if (tempReg.CountRects() > 0){ +// TODO: when you have such a method in DisplayDriver/Clipper, uncomment! + //fDriver->CopyBits( &tempReg, oldFullVisibleOrigin, oldFullVisibleOrigin.OffsetByCopy(x,y) ); + } + } + + // invalidate 'clipReg' so we can see the results of this move. + if (clipReg.CountRects() > 0){ + Invalidate( clipReg ); + } + } } void WinBorder::ResizeBy(float x, float y) { + BRegion oldFullVisible( _fullVisible ); + + _frame.right = _frame.right + x; + _frame.bottom = _frame.bottom + y; + + _win->top_layer->ResizeRegionsBy(x, y); + + _full = _win->top_layer->_full; + + if (_decorator){ + // allow decorator to make its internal calculations. + _decorator->ResizeBy(x, y); + + _decorator->GetFootprint( fDecFull ); + + _full.Include( fDecFull ); + } + + if ( !_hidden ){ + _parent->RebuildChildRegions( _full.Frame(), this ); + } + + + // REDRAWING CODE: + + if ( !(_hidden) ) + { + /* The region(on screen) that will be invalidated. + * It is composed by: + * the regions that were visible, and now they aren't + + * the regions that are now visible, and they were not visible before. + * (oldFullVisible - _fullVisible) + (_fullVisible - oldFullVisible) + */ + BRegion clipReg; + + // + (oldFullVisible - _fullVisible) + if ( oldFullVisible.CountRects() > 0 ){ + BRegion tempReg( oldFullVisible ); + tempReg.Exclude( &_fullVisible ); + + if (tempReg.CountRects() > 0){ + clipReg.Include( &tempReg ); + } + } + + // + (_fullVisible - oldFullVisible) + if ( _fullVisible.CountRects() > 0 ){ + BRegion tempReg( _fullVisible ); + tempReg.Exclude( &oldFullVisible ); + + if (tempReg.CountRects() > 0){ + clipReg.Include( &tempReg ); + } + } + + // invalidate 'clipReg' so we can see the results of this resize operation. + if (clipReg.CountRects() > 0){ + Invalidate( clipReg ); + } + } } -*/ + +void WinBorder::MoveToBack(){ + if (this == _parent->_topchild) + return; + + if (_uppersibling){ + _uppersibling->_lowersibling = _lowersibling; + } + else{ + _parent->_topchild = _lowersibling; + } + + if (_lowersibling){ + _lowersibling->_uppersibling = _uppersibling; + } + else{ + _parent->_bottomchild = _uppersibling; + } + + this->_lowersibling = _parent->_topchild; + this->_uppersibling = NULL; + _parent->_topchild = this; + + // cache WinBorder's fullVisible region for use later + BRegion cachedFullVisible = _fullVisible; + // rebuild only that area the encloses the full visible part of this layer. + _parent->RebuildChildRegions(_fullVisible.Frame(), this); + // we now have <= fullVisible region, so invalidate the parts that are not common. + cachedFullVisible.Exclude(&_fullVisible); + Invalidate( cachedFullVisible ); +} + +void WinBorder::MoveToFront(){ + if (this == _parent->_bottomchild) + return; + + if (_uppersibling){ + _uppersibling->_lowersibling = _lowersibling; + } + else{ + _parent->_topchild = _lowersibling; + } + + if (_lowersibling){ + _lowersibling->_uppersibling = _uppersibling; + } + else{ + _parent->_bottomchild = _uppersibling; + } + + this->_lowersibling = NULL; + this->_uppersibling = _parent->_bottomchild; + _parent->_bottomchild = this; + + // cache WinBorder's fullVisible region for use later + BRegion cachedFullVisible = _fullVisible; + // rebuild the area that this WinBorder will occupy. + _parent->RebuildChildRegions(_full.Frame(), this); + // make a copy of the fullVisible region because it needs + // to be modified for invalidating a minimum area. + BRegion tempFullVisible = _fullVisible; + // invalidate only the difference between the present and + // the old fullVisible regions. We only need to update that area. + tempFullVisible.Exclude(&cachedFullVisible); + Invalidate( tempFullVisible ); +} + void WinBorder::UpdateColors(void) { - gui_colorset.Lock(); - _decorator->SetColors(gui_colorset); - gui_colorset.Unlock(); - - // Tell the decorator to update all visible regions of the window border - if(_visible) - for(int32 i=0; i<_visible->CountRects(); i++) - _decorator->Draw(_visible->RectAt(i)); +STRACE(("WinBorder %s: UpdateColors unimplemented\n",_title->String())); } void WinBorder::UpdateDecorator(void) { - STRACE(("WinBorder %s: UpdateDecorator unimplemented\n",_title->String())); - - // TODO: Implement - - // What needs done here is to delete the current decorator and do a lot of the - // decorator-related setup done in the constructor. This definitely needs to be - // done *after* all the silliness with figuring out the clipping code is taken care of +STRACE(("WinBorder %s: UpdateDecorator unimplemented\n",_title->String())); } void WinBorder::UpdateFont(void) { - STRACE(("WinBorder %s: UpdateFont unimplemented\n",_title->String())); - - // TODO: Implement - - // What needs done here is to first call _decorator->SetFont(). Following that, - // GetFootprint() will need to be called to obtain changes in the decorator's size due to - // changes in the font, whether they are face, size, or whatever. Thus, the WinBorder will - // need to do some region-related recalculation, as well. +STRACE(("WinBorder %s: UpdateFont unimplemented\n",_title->String())); } void WinBorder::UpdateScreen(void) { - STRACE(("WinBorder %s: UpdateScreen unimplemented\n",_title->String())); +STRACE(("WinBorder %s: UpdateScreen unimplemented\n",_title->String())); } diff --git a/src/servers/app/server/WinBorder.h b/src/servers/app/server/WinBorder.h index acee0a624e..94c557f5c0 100644 --- a/src/servers/app/server/WinBorder.h +++ b/src/servers/app/server/WinBorder.h @@ -38,47 +38,57 @@ class DisplayDriver; class WinBorder : public Layer { public: - WinBorder(const BRect &r, const char *name, const int32 look, const int32 feel, - const int32 flags, ServerWindow *win); - virtual ~WinBorder(void); - virtual void RequestDraw(void); - virtual void RequestDraw(const BRect &r); -// void MoveBy(BPoint pt); -// void MoveBy(float x, float y); -// void ResizeBy(BPoint pt); -// void ResizeBy(float x, float y); - void MouseDown(int8 *buffer); - void MouseMoved(int8 *buffer); - void MouseUp(int8 *buffer); - void UpdateColors(void); - void UpdateDecorator(void); - void UpdateFont(void); - void UpdateScreen(void); - void RebuildRegions(const bool &recursive=true); - void SetFocus(const bool &active=false); - ServerWindow *Window(void) { return _win; } - Decorator *GetDecorator(void) { return _decorator; } + WinBorder(const BRect &r, const char *name, const int32 look, + const int32 feel, const int32 flags, ServerWindow *win); + virtual ~WinBorder(void); + + virtual void RebuildRegions( const BRect& r ); + virtual void Draw(const BRect &r); + + virtual void MoveBy(float x, float y); + virtual void ResizeBy(float x, float y); + + void MoveToBack(); + void MoveToFront(); + + void MouseDown(int8 *buffer); + void MouseMoved(int8 *buffer); + void MouseUp(int8 *buffer); + + void UpdateColors(void); + void UpdateDecorator(void); + void UpdateFont(void); + void UpdateScreen(void); + + void SetFocus(const bool &active); + ServerWindow* Window(void) const { return _win; } + Decorator* GetDecorator(void) const { return _decorator; } + protected: - ServerWindow *_win; - BString *_title; - Decorator *_decorator; - int32 _flags; - BRect _clientframe; - int32 _mbuttons,_kmodifiers; - BPoint _mousepos; - bool _update; - bool _hresizewin,_vresizewin; - DisplayDriver *_driver; + ServerWindow *_win; + //BString *_title; + Decorator *_decorator; + int32 _flags; + BRect _clientframe; + int32 _mbuttons, + _kmodifiers; + BPoint _mousepos; + bool _update; + bool _hresizewin,_vresizewin; + + BRegion *fDecFull, + *fDecFullVisible, + *fDecVisible; }; -bool is_moving_window(void); -void set_is_moving_window(bool state); -bool is_resizing_window(void); -void set_is_resizing_window(bool state); -void set_active_winborder(WinBorder *win); -WinBorder * get_active_winborder(void); -void set_is_resizing_window(bool state); -void set_is_sliding_tab(bool state); -bool is_sliding_tab(void); +bool is_moving_window(void); +void set_is_moving_window(bool state); +bool is_resizing_window(void); +void set_is_resizing_window(bool state); +void set_active_winborder(WinBorder *win); +WinBorder* get_active_winborder(void); +void set_is_resizing_window(bool state); +void set_is_sliding_tab(bool state); +bool is_sliding_tab(void); #endif