#ifndef WINDOW_LAYER_H #define WINDOW_LAYER_H #include #include #include #include #include "ViewLayer.h" class ClientLooper; class Desktop; class DrawingEngine; enum { MSG_REDRAW = 'rdrw', // client messages MSG_BEGIN_UPDATE = 'bgud', MSG_END_UPDATE = 'edud', MSG_DRAWING_COMMAND = 'draw', MSG_SHOW = 'show', MSG_INVALIDATE_VIEW = 'invl', MSG_DRAW_POLYGON = 'drwp', }; class UpdateSession { public: UpdateSession(); virtual ~UpdateSession(); void Include(BRegion* additionalDirty); void Exclude(BRegion* dirtyInNextSession); inline BRegion& DirtyRegion() { return fDirtyRegion; } void MoveBy(int32 x, int32 y); void SetUsed(bool used); inline bool IsUsed() const { return fInUse; } UpdateSession& operator=(const UpdateSession& other); private: BRegion fDirtyRegion; bool fInUse; }; class WindowLayer : public BLooper { public: WindowLayer(BRect frame, const char* name, DrawingEngine* drawingEngine, Desktop* desktop); virtual ~WindowLayer(); virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); inline BRect Frame() const { return fFrame; } // setting and getting the "hard" clipping void SetClipping(BRegion* stillAvailableOnScreen); inline BRegion& VisibleRegion() { return fVisibleRegion; } BRegion& VisibleContentRegion(); void GetFullRegion(BRegion* region) const; void GetBorderRegion(BRegion* region); void GetContentRegion(BRegion* region); void SetFocus(bool focus); void MoveBy(int32 x, int32 y); void ResizeBy(int32 x, int32 y, BRegion* dirtyRegion); void ScrollViewBy(ViewLayer* view, int32 dx, int32 dy); void AddChild(ViewLayer* layer); ViewLayer* ViewAt(const BPoint& where); void SetHidden(bool hidden); inline bool IsHidden() const { return fHidden; } void MarkDirty(BRegion* regionOnScreen); void MarkContentDirty(BRegion* regionOnScreen); void InvalidateView(int32 token); void ProcessDirtyRegion(BRegion* region); DrawingEngine* GetDrawingEngine() const { return fDrawingEngine; } void CopyContents(BRegion* region, int32 xOffset, int32 yOffset); private: void _ShiftPartOfRegion(BRegion* region, BRegion* regionToShift, int32 xOffset, int32 yOffset); // different types of drawing void _TriggerContentRedraw(); void _DrawClient(int32 token); void _DrawClientPolygon(int32 token, BPoint polygon[4]); void _DrawBorder(); // handling update sessions void _MarkContentDirty(BRegion* contentDirtyRegion); void _BeginUpdate(); void _EndUpdate(); void _UpdateContentRegion(); BRect fFrame; // the visible region is only recalculated from the // Desktop thread, when using it, Desktop::ReadLockClipping() // has to be called BRegion fVisibleRegion; BRegion fVisibleContentRegion; bool fVisibleContentRegionValid; // our part of the "global" dirty region // it is calculated from the desktop thread, // but we can write to it when we read locked // the clipping, since it is local and the desktop // thread is blocked BRegion fDirtyRegion; // caching local regions BRegion fBorderRegion; bool fBorderRegionValid; BRegion fContentRegion; bool fContentRegionValid; BRegion fEffectiveDrawingRegion; bool fEffectiveDrawingRegionValid; bool fFocus; ViewLayer* fTopLayer; bool fHidden; DrawingEngine* fDrawingEngine; Desktop* fDesktop; // for mapping drawing requests from the client // to the local view pointers BList fTokenViewMap; // the client looper, which will do asynchronous // drawing (the window will clear the content // and the client is supposed to draw onto // the cleared regions) ClientLooper* fClient; // The synchronization, which client drawing commands // belong to the redraw of which region is handled // through an UpdateSession. When the client has // been informed that it should redraw stuff, then // this is the current update session. All new // redraw requests from the root layer will go // into the pending update session. UpdateSession fCurrentUpdateSession; UpdateSession fPendingUpdateSession; // these two flags are supposed to ensure a sane // and consistent update session bool fUpdateRequested; bool fInUpdate; }; #endif // WINDOW_LAYER_H