diff --git a/src/servers/app/server/Layer.cpp b/src/servers/app/server/Layer.cpp index 94649cdb39..9b07f90576 100644 --- a/src/servers/app/server/Layer.cpp +++ b/src/servers/app/server/Layer.cpp @@ -685,12 +685,7 @@ void Layer::Show(bool invalidate) fHidden = false; if(invalidate) - { - if(fParent) - fParent->FullInvalidate( BRegion(fFull) ); - else - FullInvalidate( BRegion(fFull) ); - } + GetRootLayer()->GoInvalidate(this, fFull); } /*! @@ -706,12 +701,7 @@ void Layer::Hide(bool invalidate) fHidden = true; if(invalidate) - { - if(fParent) - fParent->FullInvalidate( BRegion(fFullVisible) ); - else - FullInvalidate( BRegion(fFullVisible) ); - } + GetRootLayer()->GoInvalidate(this, fFullVisible); } //! Returns true if the layer is hidden diff --git a/src/servers/app/server/RootLayer.cpp b/src/servers/app/server/RootLayer.cpp index 7d360dd18c..a7551972ee 100644 --- a/src/servers/app/server/RootLayer.cpp +++ b/src/servers/app/server/RootLayer.cpp @@ -139,7 +139,7 @@ int32 RootLayer::WorkingThread(void *data) // first make sure we are actualy visible oneRootLayer->Lock(); oneRootLayer->RebuildFullRegion(); - oneRootLayer->FullInvalidate(oneRootLayer->Bounds()); + oneRootLayer->invalidate_layer(oneRootLayer, oneRootLayer->Bounds()); oneRootLayer->Unlock(); for(;;) @@ -181,16 +181,34 @@ int32 RootLayer::WorkingThread(void *data) case AS_ROOTLAYER_SHOW_WINBORDER: { - WinBorder *winBorder = NULL; - messageQueue.Read(&winBorder); - oneRootLayer->show_winBorder(winBorder); + WinBorder *winBorder = NULL; + messageQueue.Read(&winBorder); + oneRootLayer->show_winBorder(winBorder); break; } case AS_ROOTLAYER_HIDE_WINBORDER: { - WinBorder *winBorder = NULL; - messageQueue.Read(&winBorder); - oneRootLayer->hide_winBorder(winBorder); + WinBorder *winBorder = NULL; + messageQueue.Read(&winBorder); + oneRootLayer->hide_winBorder(winBorder); + break; + } + case AS_ROOTLAYER_DO_INVALIDATE: + { + BRegion invalidRegion; + Layer *layer = NULL; + messageQueue.Read(&layer); + messageQueue.ReadRegion(&invalidRegion); + oneRootLayer->invalidate_layer(layer, invalidRegion); + break; + } + case AS_ROOTLAYER_DO_REDRAW: + { + BRegion redrawRegion; + Layer *layer = NULL; + messageQueue.Read(&layer); + messageQueue.ReadRegion(&redrawRegion); + oneRootLayer->redraw_layer(layer, redrawRegion); break; } default: @@ -207,6 +225,43 @@ int32 RootLayer::WorkingThread(void *data) return 0; } +void RootLayer::GoInvalidate(const Layer *layer, const BRegion ®ion) +{ + BPortLink msg(fListenPort, -1); + msg.StartMessage(AS_ROOTLAYER_DO_INVALIDATE); + msg.Attach(layer); + msg.AttachRegion(region); + msg.Flush(); +} + +void RootLayer::invalidate_layer(Layer *layer, const BRegion ®ion) +{ + // NOTE: our thread (WorkingThread) is locked here. + + if (layer->fParent) + layer = layer->fParent; + + layer->FullInvalidate(region); +} + +void RootLayer::GoRedraw(const Layer *layer, const BRegion ®ion) +{ + BPortLink msg(fListenPort, -1); + msg.StartMessage(AS_ROOTLAYER_DO_REDRAW); + msg.Attach(layer); + msg.AttachRegion(region); + msg.Flush(); +} + +void RootLayer::redraw_layer(Layer *layer, const BRegion ®ion) +{ + // NOTE: our thread (WorkingThread) is locked here. + + layer->Invalidate(region); +} + + + void RootLayer::MoveBy(float x, float y) { } @@ -1616,7 +1671,6 @@ void RootLayer::hide_winBorder(WinBorder *winBorder) ws->SearchAndSetNewFocus(winBorder); else{ // TODO: RootLayer or Desktop class should take care of invalidating -// ws->Invalidate(); } } } diff --git a/src/servers/app/server/RootLayer.h b/src/servers/app/server/RootLayer.h index 771a48f8b9..ccf13862c2 100644 --- a/src/servers/app/server/RootLayer.h +++ b/src/servers/app/server/RootLayer.h @@ -115,6 +115,8 @@ public: void Unlock() { fAllRegionsLock.Unlock(); } bool IsLocked() { return fAllRegionsLock.IsLocked(); } void RunThread(); + void GoInvalidate(const Layer *layer, const BRegion ®ion); + void GoRedraw(const Layer *layer, const BRegion ®ion); // Debug methods void PrintToStream(void); @@ -130,6 +132,9 @@ private: void show_winBorder(WinBorder* winBorder); void hide_winBorder(WinBorder* winBorder); + void invalidate_layer(Layer *layer, const BRegion ®ion); + void redraw_layer(Layer *layer, const BRegion ®ion); + Desktop *fDesktop; BMessage *fDragMessage; WinBorder *fMouseTarget; diff --git a/src/servers/app/server/ServerWindow.cpp b/src/servers/app/server/ServerWindow.cpp index 6ab4119929..8e2c49a7bc 100644 --- a/src/servers/app/server/ServerWindow.cpp +++ b/src/servers/app/server/ServerWindow.cpp @@ -590,7 +590,9 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link) printf("ServerWindow %s received unexpected code - message offset %ld before top_view attached.\n",fTitle.String(), code - SERVER_TRUE); return; } - + + RootLayer *myRootLayer = fWinBorder->GetRootLayer(); + switch(code) { //--------- BView Messages ----------------- @@ -741,8 +743,7 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link) cl->AddChild(newLayer, this); if (!(newLayer->IsHidden())){ - // cl is the parent of newLayer, so this call is OK. - cl->FullInvalidate(BRegion(newLayer->fFull)); + myRootLayer->GoInvalidate(newLayer, newLayer->fFull); } break; @@ -762,7 +763,8 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link) cl->RemoveSelf(); cl->PruneTree(); - parent->Invalidate(cl->Frame()); + if (parent) + myRootLayer->GoInvalidate(parent, BRegion(cl->Frame())); #ifdef DEBUG_SERVERWINDOW parent->PrintTree(); @@ -1073,7 +1075,7 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link) cl->fLayerData->viewcolor.SetColor(c); - cl->Invalidate(cl->fVisible); + myRootLayer->GoRedraw(cl, cl->fVisible); break; } @@ -1215,7 +1217,7 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link) // redraw if we previously had or if we have acquired a picture to clip to. if (redraw) - cl->Invalidate(reg); + myRootLayer->GoRedraw(cl, reg); break; } @@ -1321,12 +1323,7 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link) cl->RebuildFullRegion(); if (!(cl->IsHidden())) - { - if (cl->fParent) - cl->fParent->FullInvalidate(BRegion(cl->fFull)); - else - cl->FullInvalidate(BRegion(cl->fFull)); - } + myRootLayer->GoInvalidate(cl, cl->fFull); break; } @@ -1338,8 +1335,8 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link) BRect invalRect; link.Read(&invalRect); - - cl->Invalidate(invalRect); + + myRootLayer->GoRedraw(cl, BRegion(invalRect)); break; } @@ -1360,7 +1357,7 @@ void ServerWindow::DispatchMessage(int32 code, LinkMsgReader &link) invalReg.Include(rect); } - cl->Invalidate(invalReg); + myRootLayer->GoRedraw(cl, invalReg); break; } @@ -2191,17 +2188,32 @@ int32 ServerWindow::MonitorWin(void *data) { // this means the client has been killed STRACE(("ServerWindow %s received 'AS_CLIENT_DEAD/AS_DELETE_WINDOW' message code\n",win->Title())); + RootLayer *myRootLayer = win->fWinBorder->GetRootLayer(); + quitting = true; - + + // we are preparing to delete a ServerWindow, RootLayer should be aware + // of that and stop for a moment. + // also we must wait a bit for the associated WinBorder to become hidden + while(1) + { + myRootLayer->Lock(); + if (win->IsHidden()) + break; + else + myRootLayer->Unlock(); + } // ServerWindow's destructor takes care of pulling this object off the desktop. delete win; + myRootLayer->Unlock(); + + exit_thread(0); break; } case B_QUIT_REQUESTED: { STRACE(("ServerWindow %s received Quit request\n",win->Title())); - quitting = true; - delete win; + win->Quit(); break; } default: