* adds drawing commands from clients
* adds concept of a current and a pending update session * marks dirty views being resized or moved Some aspects of the design are buggy, others are slow, but I'm approaching a good overview of what's needed and what problems lurk in the details. In the end I hope to make things work fast and correctly at all times. Adi or anybody else, feel free to join the efforts. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15158 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Message.h>
|
||||||
|
#include <MessageQueue.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "WindowLayer.h"
|
||||||
|
|
||||||
|
#include "ClientLooper.h"
|
||||||
|
|
||||||
|
#define SLOW_DRAWING 0
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ClientLooper::ClientLooper(const char* name, WindowLayer* serverWindow)
|
||||||
|
: BLooper(""),
|
||||||
|
fServerWindow(serverWindow),
|
||||||
|
fViewCount(0)
|
||||||
|
{
|
||||||
|
BString clientName(name);
|
||||||
|
clientName << " client";
|
||||||
|
SetName(clientName.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ClientLooper::~ClientLooper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReceived
|
||||||
|
void
|
||||||
|
ClientLooper::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case MSG_UPDATE:
|
||||||
|
|
||||||
|
fServerWindow->PostMessage(MSG_BEGIN_UPDATE);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fViewCount; i++) {
|
||||||
|
// the client is slow
|
||||||
|
snooze(1000L);
|
||||||
|
// send the command to redraw a view
|
||||||
|
BMessage command(MSG_DRAWING_COMMAND);
|
||||||
|
command.AddInt32("token", i);
|
||||||
|
fServerWindow->PostMessage(&command);
|
||||||
|
}
|
||||||
|
|
||||||
|
fServerWindow->PostMessage(MSG_END_UPDATE);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MSG_VIEWS_ADDED: {
|
||||||
|
int32 count;
|
||||||
|
if (message->FindInt32("count", &count) >= B_OK) {
|
||||||
|
fViewCount += count;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MSG_VIEWS_REMOVED: {
|
||||||
|
int32 count;
|
||||||
|
if (message->FindInt32("count", &count) >= B_OK)
|
||||||
|
fViewCount -= count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
BLooper::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
#ifndef CLIENT_LOOPER_H
|
||||||
|
#define CLIENT_LOOPER_H
|
||||||
|
|
||||||
|
#include <Looper.h>
|
||||||
|
|
||||||
|
class WindowLayer;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MSG_UPDATE = 'updt',
|
||||||
|
MSG_VIEWS_ADDED = 'vwad',
|
||||||
|
MSG_VIEWS_REMOVED = 'vwrm',
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClientLooper : public BLooper {
|
||||||
|
public:
|
||||||
|
ClientLooper(const char* name,
|
||||||
|
WindowLayer* serverWindow);
|
||||||
|
virtual ~ClientLooper();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
WindowLayer* fServerWindow;
|
||||||
|
int32 fViewCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CLIENT_LOOPER_H
|
||||||
@@ -114,6 +114,8 @@ Desktop::MouseDown(BPoint where, uint32 buttons)
|
|||||||
// complete redraw
|
// complete redraw
|
||||||
#if RUN_WITH_FRAME_BUFFER
|
#if RUN_WITH_FRAME_BUFFER
|
||||||
if (fDrawingEngine->Lock()) {
|
if (fDrawingEngine->Lock()) {
|
||||||
|
fDirtyRegion.MakeEmpty();
|
||||||
|
|
||||||
BRegion region(fDrawingEngine->Bounds());
|
BRegion region(fDrawingEngine->Bounds());
|
||||||
fDrawingEngine->Unlock();
|
fDrawingEngine->Unlock();
|
||||||
|
|
||||||
@@ -123,6 +125,7 @@ Desktop::MouseDown(BPoint where, uint32 buttons)
|
|||||||
_SetBackground(®ion);
|
_SetBackground(®ion);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
fDirtyRegion.MakeEmpty();
|
||||||
fDrawingEngine->MarkDirty();
|
fDrawingEngine->MarkDirty();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -156,10 +159,13 @@ Desktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
|
|||||||
|
|
||||||
if (dx != 0 || dy != 0) {
|
if (dx != 0 || dy != 0) {
|
||||||
if (fClickedWindow) {
|
if (fClickedWindow) {
|
||||||
|
//bigtime_t now = system_time();
|
||||||
if (fResizing) {
|
if (fResizing) {
|
||||||
ResizeWindowBy(fClickedWindow, dx, dy);
|
ResizeWindowBy(fClickedWindow, dx, dy);
|
||||||
|
//printf("resizing: %lld\n", system_time() - now);
|
||||||
} else {
|
} else {
|
||||||
MoveWindowBy(fClickedWindow, dx, dy);
|
MoveWindowBy(fClickedWindow, dx, dy);
|
||||||
|
//printf("moving: %lld\n", system_time() - now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,9 +361,9 @@ Desktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y)
|
|||||||
if (LockClipping()) {
|
if (LockClipping()) {
|
||||||
// the dirty region starts with the visible area of the window being moved
|
// the dirty region starts with the visible area of the window being moved
|
||||||
BRegion newDirtyRegion(window->VisibleRegion());
|
BRegion newDirtyRegion(window->VisibleRegion());
|
||||||
BRegion alreadyDirtyRegion(fDirtyRegion);
|
|
||||||
// we have to move along the part of the current dirty region
|
// we have to move along the part of the current dirty region
|
||||||
// that intersects with the window being moved
|
// that intersects with the window being moved
|
||||||
|
BRegion alreadyDirtyRegion(fDirtyRegion);
|
||||||
alreadyDirtyRegion.IntersectWith(&window->VisibleRegion());
|
alreadyDirtyRegion.IntersectWith(&window->VisibleRegion());
|
||||||
|
|
||||||
window->MoveBy(x, y);
|
window->MoveBy(x, y);
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ class Desktop : public BLooper {
|
|||||||
void ReadUnlockClipping() { fClippingLock.WriteUnlock(); }
|
void ReadUnlockClipping() { fClippingLock.WriteUnlock(); }
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
bool ReadLockClipping() { return fClippingLock.LockWithTimeout(10000) >= B_OK; }
|
bool ReadLockClipping() { return fClippingLock.Lock(); }
|
||||||
|
bool ReadLockClippingWithTimeout() { return fClippingLock.LockWithTimeout(10000) >= B_OK; }
|
||||||
void ReadUnlockClipping() { fClippingLock.Unlock(); }
|
void ReadUnlockClipping() { fClippingLock.Unlock(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,10 +2,11 @@
|
|||||||
#ifndef VIEW_LAYER_H
|
#ifndef VIEW_LAYER_H
|
||||||
#define VIEW_LAYER_H
|
#define VIEW_LAYER_H
|
||||||
|
|
||||||
|
#include <GraphicsDefs.h>
|
||||||
#include <Region.h>
|
#include <Region.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
class BList;
|
||||||
class DrawingEngine;
|
class DrawingEngine;
|
||||||
class WindowLayer;
|
class WindowLayer;
|
||||||
|
|
||||||
@@ -26,7 +27,8 @@ class ViewLayer {
|
|||||||
inline rgb_color ViewColor() const
|
inline rgb_color ViewColor() const
|
||||||
{ return fViewColor; }
|
{ return fViewColor; }
|
||||||
|
|
||||||
void AttachedToWindow(WindowLayer* window);
|
void AttachedToWindow(WindowLayer* window,
|
||||||
|
bool topLayer = false);
|
||||||
void DetachedFromWindow();
|
void DetachedFromWindow();
|
||||||
|
|
||||||
// tree stuff
|
// tree stuff
|
||||||
@@ -43,7 +45,8 @@ class ViewLayer {
|
|||||||
|
|
||||||
ViewLayer* TopLayer();
|
ViewLayer* TopLayer();
|
||||||
|
|
||||||
uint32 CountChildren() const;
|
uint32 CountChildren(bool deep = false) const;
|
||||||
|
void CollectTokensForChildren(BList* tokenMap) const;
|
||||||
|
|
||||||
// coordinate conversion
|
// coordinate conversion
|
||||||
void ConvertToParent(BPoint* point) const;
|
void ConvertToParent(BPoint* point) const;
|
||||||
@@ -66,23 +69,30 @@ class ViewLayer {
|
|||||||
void ParentResized(int32 dx, int32 dy,
|
void ParentResized(int32 dx, int32 dy,
|
||||||
BRegion* dirtyRegion);
|
BRegion* dirtyRegion);
|
||||||
|
|
||||||
|
// for background clearing
|
||||||
void Draw(DrawingEngine* drawingEngine,
|
void Draw(DrawingEngine* drawingEngine,
|
||||||
BRegion* effectiveClipping,
|
BRegion* effectiveClipping,
|
||||||
bool deep = false);
|
bool deep = false);
|
||||||
|
|
||||||
|
// to simulate drawing done from client side
|
||||||
|
void ClientDraw(DrawingEngine* drawingEngine,
|
||||||
|
BRegion* effectiveClipping);
|
||||||
|
|
||||||
bool IsHidden() const;
|
bool IsHidden() const;
|
||||||
void Hide();
|
void Hide();
|
||||||
void Show();
|
void Show();
|
||||||
|
|
||||||
// clipping
|
// clipping
|
||||||
void RebuildClipping(bool deep = false);
|
void RebuildClipping(bool deep);
|
||||||
BRegion& ScreenClipping() const;
|
BRegion& ScreenClipping() const;
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
void PrintToStream() const;
|
void PrintToStream() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _InvalidateScreenClipping(bool deep = false);
|
void _InvalidateScreenClipping(bool deep);
|
||||||
|
void _MoveScreenClipping(int32 x, int32 y,
|
||||||
|
bool deep);
|
||||||
|
|
||||||
BString fName;
|
BString fName;
|
||||||
// area within parent coordinate space
|
// area within parent coordinate space
|
||||||
@@ -98,6 +108,7 @@ private:
|
|||||||
|
|
||||||
WindowLayer* fWindow;
|
WindowLayer* fWindow;
|
||||||
ViewLayer* fParent;
|
ViewLayer* fParent;
|
||||||
|
bool fIsTopLayer;
|
||||||
|
|
||||||
ViewLayer* fFirstChild;
|
ViewLayer* fFirstChild;
|
||||||
ViewLayer* fPreviousSibling;
|
ViewLayer* fPreviousSibling;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <MessageQueue.h>
|
#include <MessageQueue.h>
|
||||||
|
|
||||||
|
#include "ClientLooper.h"
|
||||||
#include "Desktop.h"
|
#include "Desktop.h"
|
||||||
#include "DrawingEngine.h"
|
#include "DrawingEngine.h"
|
||||||
|
|
||||||
@@ -29,7 +30,15 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
|
|||||||
fTopLayer(NULL),
|
fTopLayer(NULL),
|
||||||
|
|
||||||
fDrawingEngine(drawingEngine),
|
fDrawingEngine(drawingEngine),
|
||||||
fDesktop(desktop)
|
fDesktop(desktop),
|
||||||
|
|
||||||
|
fTokenViewMap(64),
|
||||||
|
|
||||||
|
fClient(new ClientLooper(name, this)),
|
||||||
|
fCurrentUpdateSession(NULL),
|
||||||
|
fPendingUpdateSession(NULL),
|
||||||
|
fUpdateRequested(false),
|
||||||
|
fInUpdate(false)
|
||||||
{
|
{
|
||||||
// the top layer is special, it has a coordinate system
|
// the top layer is special, it has a coordinate system
|
||||||
// as if it was attached directly to the desktop, therefor,
|
// as if it was attached directly to the desktop, therefor,
|
||||||
@@ -38,6 +47,9 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
|
|||||||
// fFrame as if it had
|
// fFrame as if it had
|
||||||
fTopLayer = new(nothrow) ViewLayer(fFrame, "top view", B_FOLLOW_ALL, 0,
|
fTopLayer = new(nothrow) ViewLayer(fFrame, "top view", B_FOLLOW_ALL, 0,
|
||||||
(rgb_color){ 255, 255, 255, 255 });
|
(rgb_color){ 255, 255, 255, 255 });
|
||||||
|
fTopLayer->AttachedToWindow(this, true);
|
||||||
|
|
||||||
|
fClient->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@@ -53,7 +65,7 @@ WindowLayer::MessageReceived(BMessage* message)
|
|||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
case MSG_REDRAW: {
|
case MSG_REDRAW: {
|
||||||
if (!MessageQueue()->FindMessage(MSG_REDRAW, 0)) {
|
if (!MessageQueue()->FindMessage(MSG_REDRAW, 0)) {
|
||||||
while (!fDesktop->ReadLockClipping()) {
|
while (!fDesktop->ReadLockClippingWithTimeout()) {
|
||||||
//printf("%s MSG_REDRAW -> timeout\n", Name());
|
//printf("%s MSG_REDRAW -> timeout\n", Name());
|
||||||
if (MessageQueue()->FindMessage(MSG_REDRAW, 0)) {
|
if (MessageQueue()->FindMessage(MSG_REDRAW, 0)) {
|
||||||
//printf("%s MSG_REDRAW -> timeout - leaving because there are pending redraws\n", Name());
|
//printf("%s MSG_REDRAW -> timeout - leaving because there are pending redraws\n", Name());
|
||||||
@@ -62,12 +74,25 @@ WindowLayer::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
_DrawContents(fTopLayer);
|
_DrawContents(fTopLayer);
|
||||||
_DrawBorder();
|
_DrawBorder();
|
||||||
|
|
||||||
fDesktop->ReadUnlockClipping();
|
fDesktop->ReadUnlockClipping();
|
||||||
} else {
|
} else {
|
||||||
//printf("%s MSG_REDRAW -> pending redraws\n", Name());
|
//printf("%s MSG_REDRAW -> pending redraws\n", Name());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MSG_BEGIN_UPDATE:
|
||||||
|
_BeginUpdate();
|
||||||
|
break;
|
||||||
|
case MSG_END_UPDATE:
|
||||||
|
_EndUpdate();
|
||||||
|
break;
|
||||||
|
case MSG_DRAWING_COMMAND: {
|
||||||
|
int32 token;
|
||||||
|
if (message->FindInt32("token", &token) >= B_OK)
|
||||||
|
_DrawClient(token);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
BLooper::MessageReceived(message);
|
BLooper::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
@@ -174,6 +199,11 @@ WindowLayer::MoveBy(int32 x, int32 y)
|
|||||||
if (fContentRegionValid)
|
if (fContentRegionValid)
|
||||||
fContentRegion.OffsetBy(x, y);
|
fContentRegion.OffsetBy(x, y);
|
||||||
|
|
||||||
|
if (fCurrentUpdateSession)
|
||||||
|
fCurrentUpdateSession->MoveBy(x, y);
|
||||||
|
if (fPendingUpdateSession)
|
||||||
|
fPendingUpdateSession->MoveBy(x, y);
|
||||||
|
|
||||||
fTopLayer->MoveBy(x, y);
|
fTopLayer->MoveBy(x, y);
|
||||||
|
|
||||||
// TODO: move a local dirty region!
|
// TODO: move a local dirty region!
|
||||||
@@ -210,6 +240,14 @@ WindowLayer::AddChild(ViewLayer* layer)
|
|||||||
{
|
{
|
||||||
fTopLayer->AddChild(layer);
|
fTopLayer->AddChild(layer);
|
||||||
|
|
||||||
|
// inform client about the view
|
||||||
|
// (just a part of the simulation)
|
||||||
|
fTokenViewMap.MakeEmpty();
|
||||||
|
fTopLayer->CollectTokensForChildren(&fTokenViewMap);
|
||||||
|
BMessage message(MSG_VIEWS_ADDED);
|
||||||
|
message.AddInt32("count", fTokenViewMap.CountItems());
|
||||||
|
fClient->PostMessage(&message);
|
||||||
|
|
||||||
// TODO: trigger redraw for dirty regions
|
// TODO: trigger redraw for dirty regions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +259,18 @@ WindowLayer::MarkDirty(BRegion* regionOnScreen)
|
|||||||
fDesktop->MarkDirty(regionOnScreen);
|
fDesktop->MarkDirty(regionOnScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DirtyRegion
|
||||||
|
BRegion
|
||||||
|
WindowLayer::DirtyRegion()
|
||||||
|
{
|
||||||
|
BRegion dirty;
|
||||||
|
if (fDesktop->ReadLockClipping()) {
|
||||||
|
dirty = *fDesktop->DirtyRegion();
|
||||||
|
fDesktop->ReadUnlockClipping();
|
||||||
|
}
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
# pragma mark -
|
# pragma mark -
|
||||||
|
|
||||||
// _DrawContents
|
// _DrawContents
|
||||||
@@ -244,15 +294,16 @@ WindowLayer::_DrawContents(ViewLayer* layer)
|
|||||||
// TODO: simplify
|
// TODO: simplify
|
||||||
// ideally, there would only be a local fDirtyRegion,
|
// ideally, there would only be a local fDirtyRegion,
|
||||||
// that we need to intersect with. fDirtyRegion would
|
// that we need to intersect with. fDirtyRegion would
|
||||||
// alread only include fVisibleRegion
|
// already only include fVisibleRegion
|
||||||
effectiveWindowClipping.IntersectWith(&fVisibleRegion);
|
effectiveWindowClipping.IntersectWith(&fVisibleRegion);
|
||||||
effectiveWindowClipping.IntersectWith(fDesktop->DirtyRegion());
|
effectiveWindowClipping.IntersectWith(fDesktop->DirtyRegion());
|
||||||
if (effectiveWindowClipping.Frame().IsValid()) {
|
if (effectiveWindowClipping.Frame().IsValid()) {
|
||||||
|
// send UPDATE message to the client here
|
||||||
|
_MarkContentDirty(&effectiveWindowClipping);
|
||||||
|
|
||||||
layer->Draw(fDrawingEngine, &effectiveWindowClipping, true);
|
layer->Draw(fDrawingEngine, &effectiveWindowClipping, true);
|
||||||
|
|
||||||
fDesktop->MarkClean(&fContentRegion);
|
fDesktop->MarkClean(&fContentRegion);
|
||||||
|
|
||||||
// send UPDATE message to the client here
|
|
||||||
}
|
}
|
||||||
//else {
|
//else {
|
||||||
//printf(" nothing to do\n");
|
//printf(" nothing to do\n");
|
||||||
@@ -260,6 +311,35 @@ WindowLayer::_DrawContents(ViewLayer* layer)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _DrawClient
|
||||||
|
void
|
||||||
|
WindowLayer::_DrawClient(int32 token)
|
||||||
|
{
|
||||||
|
ViewLayer* layer = (ViewLayer*)fTokenViewMap.ItemAt(token);
|
||||||
|
if (!layer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BRegion effectiveClipping(layer->ScreenClipping());
|
||||||
|
if (fInUpdate) {
|
||||||
|
// enforce the dirty region of the update session
|
||||||
|
effectiveClipping.IntersectWith(&fCurrentUpdateSession->DirtyRegion());
|
||||||
|
} else {
|
||||||
|
printf("%s - _DrawClient(token: %ld) - not in update\n", Name(), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effectiveClipping.CountRects() > 0 && fDesktop->ReadLockClipping()) {
|
||||||
|
effectiveClipping.IntersectWith(&fVisibleRegion);
|
||||||
|
// TODO: This step seems too much
|
||||||
|
BRegion contentRegion;
|
||||||
|
GetContentRegion(&contentRegion);
|
||||||
|
effectiveClipping.IntersectWith(&contentRegion);
|
||||||
|
|
||||||
|
layer->ClientDraw(fDrawingEngine, &effectiveClipping);
|
||||||
|
|
||||||
|
fDesktop->ReadUnlockClipping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// _DrawBorder
|
// _DrawBorder
|
||||||
void
|
void
|
||||||
WindowLayer::_DrawBorder()
|
WindowLayer::_DrawBorder()
|
||||||
@@ -298,3 +378,90 @@ WindowLayer::_DrawBorder()
|
|||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _MarkContentDirty
|
||||||
|
void
|
||||||
|
WindowLayer::_MarkContentDirty(BRegion* localDirty)
|
||||||
|
{
|
||||||
|
if (localDirty->CountRects() <= 0)
|
||||||
|
return;
|
||||||
|
if (!fPendingUpdateSession) {
|
||||||
|
// create new pending
|
||||||
|
fPendingUpdateSession = new UpdateSession(*localDirty);
|
||||||
|
} else {
|
||||||
|
// add to pending
|
||||||
|
fPendingUpdateSession->Include(localDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fUpdateRequested) {
|
||||||
|
// send this to client
|
||||||
|
fClient->PostMessage(MSG_UPDATE);
|
||||||
|
fUpdateRequested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _BeginUpdate
|
||||||
|
void
|
||||||
|
WindowLayer::_BeginUpdate()
|
||||||
|
{
|
||||||
|
if (fUpdateRequested && !fCurrentUpdateSession) {
|
||||||
|
fCurrentUpdateSession = fPendingUpdateSession;
|
||||||
|
fPendingUpdateSession = NULL;
|
||||||
|
|
||||||
|
if (fCurrentUpdateSession) {
|
||||||
|
// all drawing command from the client
|
||||||
|
// will have the dirty region from the update
|
||||||
|
// session enforced
|
||||||
|
fInUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// _EndUpdate
|
||||||
|
void
|
||||||
|
WindowLayer::_EndUpdate()
|
||||||
|
{
|
||||||
|
if (fInUpdate) {
|
||||||
|
delete fCurrentUpdateSession;
|
||||||
|
fCurrentUpdateSession = NULL;
|
||||||
|
|
||||||
|
fInUpdate = false;
|
||||||
|
}
|
||||||
|
if (fPendingUpdateSession) {
|
||||||
|
// send this to client
|
||||||
|
fClient->PostMessage(MSG_UPDATE);
|
||||||
|
fUpdateRequested = true;
|
||||||
|
} else {
|
||||||
|
fUpdateRequested = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
UpdateSession::UpdateSession(const BRegion& dirtyRegion)
|
||||||
|
: fDirtyRegion(dirtyRegion)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
UpdateSession::~UpdateSession()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include
|
||||||
|
void
|
||||||
|
UpdateSession::Include(BRegion* additionalDirty)
|
||||||
|
{
|
||||||
|
fDirtyRegion.Include(additionalDirty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MoveBy
|
||||||
|
void
|
||||||
|
UpdateSession::MoveBy(int32 x, int32 y)
|
||||||
|
{
|
||||||
|
fDirtyRegion.OffsetBy(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,39 @@
|
|||||||
#ifndef WINDOW_LAYER_H
|
#ifndef WINDOW_LAYER_H
|
||||||
#define WINDOW_LAYER_H
|
#define WINDOW_LAYER_H
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
#include <Looper.h>
|
#include <Looper.h>
|
||||||
#include <Region.h>
|
#include <Region.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#include "ViewLayer.h"
|
#include "ViewLayer.h"
|
||||||
|
|
||||||
|
class ClientLooper;
|
||||||
class Desktop;
|
class Desktop;
|
||||||
class DrawingEngine;
|
class DrawingEngine;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MSG_REDRAW = 'rdrw',
|
MSG_REDRAW = 'rdrw',
|
||||||
|
|
||||||
|
MSG_BEGIN_UPDATE = 'bgud',
|
||||||
|
MSG_END_UPDATE = 'edud',
|
||||||
|
MSG_DRAWING_COMMAND = 'draw',
|
||||||
|
};
|
||||||
|
|
||||||
|
class UpdateSession {
|
||||||
|
public:
|
||||||
|
UpdateSession(const BRegion& dirtyRegion);
|
||||||
|
virtual ~UpdateSession();
|
||||||
|
|
||||||
|
void Include(BRegion* additionalDirty);
|
||||||
|
|
||||||
|
inline BRegion& DirtyRegion()
|
||||||
|
{ return fDirtyRegion; }
|
||||||
|
|
||||||
|
void MoveBy(int32 x, int32 y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BRegion fDirtyRegion;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WindowLayer : public BLooper {
|
class WindowLayer : public BLooper {
|
||||||
@@ -42,10 +64,20 @@ class WindowLayer : public BLooper {
|
|||||||
|
|
||||||
void MarkDirty(BRegion* regionOnScreen);
|
void MarkDirty(BRegion* regionOnScreen);
|
||||||
|
|
||||||
|
DrawingEngine* GetDrawingEngine() const
|
||||||
|
{ return fDrawingEngine; }
|
||||||
|
|
||||||
|
BRegion DirtyRegion();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _DrawContents(ViewLayer* layer = NULL);
|
void _DrawContents(ViewLayer* layer = NULL);
|
||||||
|
void _DrawClient(int32 token);
|
||||||
void _DrawBorder();
|
void _DrawBorder();
|
||||||
|
|
||||||
|
void _MarkContentDirty(BRegion* localDirty);
|
||||||
|
void _BeginUpdate();
|
||||||
|
void _EndUpdate();
|
||||||
|
|
||||||
|
|
||||||
BRect fFrame;
|
BRect fFrame;
|
||||||
// the visible region is only recalculated from the
|
// the visible region is only recalculated from the
|
||||||
@@ -65,6 +97,14 @@ class WindowLayer : public BLooper {
|
|||||||
|
|
||||||
DrawingEngine* fDrawingEngine;
|
DrawingEngine* fDrawingEngine;
|
||||||
Desktop* fDesktop;
|
Desktop* fDesktop;
|
||||||
|
|
||||||
|
BList fTokenViewMap;
|
||||||
|
|
||||||
|
ClientLooper* fClient;
|
||||||
|
UpdateSession* fCurrentUpdateSession;
|
||||||
|
UpdateSession* fPendingUpdateSession;
|
||||||
|
bool fUpdateRequested;
|
||||||
|
bool fInUpdate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WINDOW_LAYER_H
|
#endif // WINDOW_LAYER_H
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ TYPE= APP
|
|||||||
# if two source files with the same name (source.c or source.cpp)
|
# if two source files with the same name (source.c or source.cpp)
|
||||||
# are included from different directories. Also note that spaces
|
# are included from different directories. Also note that spaces
|
||||||
# in folder names do not work well with this makefile.
|
# in folder names do not work well with this makefile.
|
||||||
SRCS= Desktop.cpp \
|
SRCS= ClientLooper.cpp \
|
||||||
|
Desktop.cpp \
|
||||||
DrawingEngine.cpp \
|
DrawingEngine.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
MultiLocker.cpp \
|
MultiLocker.cpp \
|
||||||
|
|||||||
Reference in New Issue
Block a user