* a bit more sophisticated
* now with actual view layers inside the windows * implemented the resize modes (from Adis code) * windows have resize handles and more correctly clip the views inside * bringing windows to front or sending them behind all others * one active window, the others are inactive * with and without focus follows mouse mode * bugs: - the region marked dirty when views are resized is not correct yet * todo: - move the dirty region from being managed by the desktop to being managed in each window (and being local too) - scrolling - hiding/showing of windows and views I plan to extend this to fully simulate asynchronous drawing from clients, to see any problems before using this in the real server one day. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15132 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -28,7 +28,10 @@ Desktop::Desktop(DrawView* drawView)
|
|||||||
fDrawView(drawView),
|
fDrawView(drawView),
|
||||||
fDrawingEngine(fDrawView->GetDrawingEngine()),
|
fDrawingEngine(fDrawView->GetDrawingEngine()),
|
||||||
|
|
||||||
fWindows(64)
|
fWindows(64),
|
||||||
|
|
||||||
|
fFocusFollowsMouse(true),
|
||||||
|
fFocusWindow(NULL)
|
||||||
{
|
{
|
||||||
fDrawView->SetDesktop(this);
|
fDrawView->SetDesktop(this);
|
||||||
|
|
||||||
@@ -134,6 +137,10 @@ Desktop::MouseUp(BPoint where)
|
|||||||
void
|
void
|
||||||
Desktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
|
Desktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
|
||||||
{
|
{
|
||||||
|
WindowLayer* window;
|
||||||
|
if (!fTracking && fFocusFollowsMouse && (window = WindowAt(where))) {
|
||||||
|
SetFocusWindow(window);
|
||||||
|
}
|
||||||
if (fTracking) {
|
if (fTracking) {
|
||||||
int32 dx = (int32)(where.x - fLastMousePos.x);
|
int32 dx = (int32)(where.x - fLastMousePos.x);
|
||||||
int32 dy = (int32)(where.y - fLastMousePos.y);
|
int32 dy = (int32)(where.y - fLastMousePos.y);
|
||||||
@@ -239,6 +246,8 @@ Desktop::AddWindow(WindowLayer* window)
|
|||||||
|
|
||||||
UnlockClipping();
|
UnlockClipping();
|
||||||
}
|
}
|
||||||
|
SetFocusWindow(window);
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
@@ -436,6 +445,9 @@ Desktop::BringToFront(WindowLayer* window)
|
|||||||
|
|
||||||
UnlockClipping();
|
UnlockClipping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fFocusFollowsMouse)
|
||||||
|
SetFocusWindow(TopWindow());
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendToBack
|
// SendToBack
|
||||||
@@ -467,8 +479,31 @@ Desktop::SendToBack(WindowLayer* window)
|
|||||||
|
|
||||||
UnlockClipping();
|
UnlockClipping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fFocusFollowsMouse)
|
||||||
|
SetFocusWindow(TopWindow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFocusWindow
|
||||||
|
void
|
||||||
|
Desktop::SetFocusWindow(WindowLayer* window)
|
||||||
|
{
|
||||||
|
// TODO: find bug, this invalidates too many regions
|
||||||
|
|
||||||
|
if (fFocusWindow == window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fFocusWindow)
|
||||||
|
fFocusWindow->SetFocus(false);
|
||||||
|
|
||||||
|
fFocusWindow = window;
|
||||||
|
|
||||||
|
if (fFocusWindow)
|
||||||
|
fFocusWindow->SetFocus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
// MarkDirty
|
// MarkDirty
|
||||||
@@ -554,6 +589,11 @@ Desktop::_TriggerWindowRedrawing(BRegion* newDirtyRegion)
|
|||||||
void
|
void
|
||||||
Desktop::_SetBackground(BRegion* background)
|
Desktop::_SetBackground(BRegion* background)
|
||||||
{
|
{
|
||||||
|
// NOTE: the drawing operation is caried out
|
||||||
|
// in the clipping region rebuild, but it is
|
||||||
|
// ok actually, because it also avoids trails on
|
||||||
|
// moving windows
|
||||||
|
|
||||||
// remember the region not covered by any windows
|
// remember the region not covered by any windows
|
||||||
// and redraw the dirty background
|
// and redraw the dirty background
|
||||||
BRegion dirtyBackground(*background);
|
BRegion dirtyBackground(*background);
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ class Desktop : public BLooper {
|
|||||||
void BringToFront(WindowLayer* window);
|
void BringToFront(WindowLayer* window);
|
||||||
void SendToBack(WindowLayer* window);
|
void SendToBack(WindowLayer* window);
|
||||||
|
|
||||||
|
void SetFocusWindow(WindowLayer* window);
|
||||||
|
|
||||||
#if MULTI_LOCKER
|
#if MULTI_LOCKER
|
||||||
# if 0
|
# if 0
|
||||||
bool ReadLockClipping() { return fClippingLock.ReadLock(); }
|
bool ReadLockClipping() { return fClippingLock.ReadLock(); }
|
||||||
@@ -105,6 +107,9 @@ private:
|
|||||||
DrawingEngine* fDrawingEngine;
|
DrawingEngine* fDrawingEngine;
|
||||||
|
|
||||||
BList fWindows;
|
BList fWindows;
|
||||||
|
|
||||||
|
bool fFocusFollowsMouse;
|
||||||
|
WindowLayer* fFocusWindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DESKTOP_H
|
#endif // DESKTOP_H
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "Desktop.h"
|
#include "Desktop.h"
|
||||||
#include "DrawingEngine.h"
|
#include "DrawingEngine.h"
|
||||||
|
#include "WindowLayer.h"
|
||||||
|
|
||||||
#include "ViewLayer.h"
|
#include "ViewLayer.h"
|
||||||
|
|
||||||
@@ -39,6 +40,10 @@ ViewLayer::ViewLayer(BRect frame, const char* name,
|
|||||||
fScreenClipping(),
|
fScreenClipping(),
|
||||||
fScreenClippingValid(false)
|
fScreenClippingValid(false)
|
||||||
{
|
{
|
||||||
|
fFrame.left = float((int32)fFrame.left);
|
||||||
|
fFrame.top = float((int32)fFrame.top);
|
||||||
|
fFrame.right = float((int32)fFrame.right);
|
||||||
|
fFrame.bottom = float((int32)fFrame.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
@@ -103,8 +108,11 @@ ViewLayer::AddChild(ViewLayer* layer)
|
|||||||
}
|
}
|
||||||
fLastChild = layer;
|
fLastChild = layer;
|
||||||
|
|
||||||
if (fParent) {
|
RebuildClipping(false);
|
||||||
RebuildClipping(false);
|
|
||||||
|
if (fWindow) {
|
||||||
|
layer->AttachedToWindow(fWindow);
|
||||||
|
fWindow->MarkDirty(&layer->ScreenClipping());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +146,12 @@ ViewLayer::RemoveChild(ViewLayer* layer)
|
|||||||
layer->fPreviousSibling = NULL;
|
layer->fPreviousSibling = NULL;
|
||||||
layer->fNextSibling = NULL;
|
layer->fNextSibling = NULL;
|
||||||
|
|
||||||
// TODO: track regions
|
if (fParent) {
|
||||||
RebuildClipping(false);
|
RebuildClipping(false);
|
||||||
|
}
|
||||||
|
if (fWindow) {
|
||||||
|
layer->DetachedFromWindow();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -201,13 +213,38 @@ ViewLayer::CountChildren() const
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertToTop
|
// ConvertToParent
|
||||||
void
|
void
|
||||||
ViewLayer::ConvertToTop(BPoint* point) const
|
ViewLayer::ConvertToParent(BPoint* point) const
|
||||||
{
|
{
|
||||||
// remove scrolling offset and convert to parent coordinate space
|
// remove scrolling offset and convert to parent coordinate space
|
||||||
point->x += fFrame.left - fScrollingOffset.x;
|
point->x += fFrame.left - fScrollingOffset.x;
|
||||||
point->y += fFrame.top - fScrollingOffset.y;
|
point->y += fFrame.top - fScrollingOffset.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertToParent
|
||||||
|
void
|
||||||
|
ViewLayer::ConvertToParent(BRect* rect) const
|
||||||
|
{
|
||||||
|
// remove scrolling offset and convert to parent coordinate space
|
||||||
|
rect->OffsetBy(fFrame.left - fScrollingOffset.x,
|
||||||
|
fFrame.top - fScrollingOffset.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertToParent
|
||||||
|
void
|
||||||
|
ViewLayer::ConvertToParent(BRegion* region) const
|
||||||
|
{
|
||||||
|
// remove scrolling offset and convert to parent coordinate space
|
||||||
|
region->OffsetBy(fFrame.left - fScrollingOffset.x,
|
||||||
|
fFrame.top - fScrollingOffset.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertToTop
|
||||||
|
void
|
||||||
|
ViewLayer::ConvertToTop(BPoint* point) const
|
||||||
|
{
|
||||||
|
ConvertToParent(point);
|
||||||
|
|
||||||
if (fParent)
|
if (fParent)
|
||||||
fParent->ConvertToTop(point);
|
fParent->ConvertToTop(point);
|
||||||
@@ -217,9 +254,7 @@ ViewLayer::ConvertToTop(BPoint* point) const
|
|||||||
void
|
void
|
||||||
ViewLayer::ConvertToTop(BRect* rect) const
|
ViewLayer::ConvertToTop(BRect* rect) const
|
||||||
{
|
{
|
||||||
// remove scrolling offset and convert to parent coordinate space
|
ConvertToParent(rect);
|
||||||
rect->OffsetBy(fFrame.left - fScrollingOffset.x,
|
|
||||||
fFrame.top - fScrollingOffset.y);
|
|
||||||
|
|
||||||
if (fParent)
|
if (fParent)
|
||||||
fParent->ConvertToTop(rect);
|
fParent->ConvertToTop(rect);
|
||||||
@@ -229,9 +264,7 @@ ViewLayer::ConvertToTop(BRect* rect) const
|
|||||||
void
|
void
|
||||||
ViewLayer::ConvertToTop(BRegion* region) const
|
ViewLayer::ConvertToTop(BRegion* region) const
|
||||||
{
|
{
|
||||||
// remove scrolling offset and convert to parent coordinate space
|
ConvertToParent(region);
|
||||||
region->OffsetBy(fFrame.left - fScrollingOffset.x,
|
|
||||||
fFrame.top - fScrollingOffset.y);
|
|
||||||
|
|
||||||
if (fParent)
|
if (fParent)
|
||||||
fParent->ConvertToTop(region);
|
fParent->ConvertToTop(region);
|
||||||
@@ -263,20 +296,22 @@ ViewLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|||||||
fFrame.right += x;
|
fFrame.right += x;
|
||||||
fFrame.bottom += y;
|
fFrame.bottom += y;
|
||||||
|
|
||||||
// TODO: broken when getting smaller
|
// layout the children
|
||||||
// ... either here or in WindowLayer::ResizeBy()
|
for (ViewLayer* child = FirstChild(); child; child = NextChild())
|
||||||
|
child->ParentResized(x, y, dirtyRegion);
|
||||||
|
|
||||||
|
// TODO: the dirty region must not include children!
|
||||||
BRegion dirty(Bounds());
|
BRegion dirty(Bounds());
|
||||||
dirty.Exclude(oldBounds);
|
if (!(fFlags & B_FULL_UPDATE_ON_RESIZE))
|
||||||
|
dirty.Exclude(oldBounds);
|
||||||
|
|
||||||
if (dirty.CountRects() > 0) {
|
if (dirty.CountRects() > 0) {
|
||||||
ConvertToTop(&dirty);
|
ConvertToTop(&dirty);
|
||||||
dirtyRegion->Include(&dirty);
|
dirtyRegion->Include(&dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
RebuildClipping(false);
|
RebuildClipping(false);
|
||||||
_InvalidateScreenClipping(false);
|
_InvalidateScreenClipping(true);
|
||||||
// TODO: layout children
|
|
||||||
// TODO: ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScrollBy
|
// ScrollBy
|
||||||
@@ -287,26 +322,91 @@ ViewLayer::ScrollBy(int32 x, int32 y)
|
|||||||
fScrollingOffset.y += y;
|
fScrollingOffset.y += y;
|
||||||
// TODO: CopyRegion...
|
// TODO: CopyRegion...
|
||||||
// TODO: ...
|
// TODO: ...
|
||||||
|
|
||||||
|
_InvalidateScreenClipping(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentResized
|
||||||
|
void
|
||||||
|
ViewLayer::ParentResized(int32 x, int32 y, BRegion* dirtyRegion)
|
||||||
|
{
|
||||||
|
uint16 rm = fResizeMode & 0x0000FFFF;
|
||||||
|
BRect newFrame = fFrame;
|
||||||
|
|
||||||
|
// follow with left side
|
||||||
|
if ((rm & 0x0F00U) == _VIEW_RIGHT_ << 8)
|
||||||
|
newFrame.left += x;
|
||||||
|
else if ((rm & 0x0F00U) == _VIEW_CENTER_ << 8)
|
||||||
|
newFrame.left += x / 2;
|
||||||
|
|
||||||
|
// follow with right side
|
||||||
|
if ((rm & 0x000FU) == _VIEW_RIGHT_)
|
||||||
|
newFrame.right += x;
|
||||||
|
else if ((rm & 0x000FU) == _VIEW_CENTER_)
|
||||||
|
newFrame.right += x / 2;
|
||||||
|
|
||||||
|
// follow with top side
|
||||||
|
if ((rm & 0xF000U) == _VIEW_BOTTOM_ << 12)
|
||||||
|
newFrame.top += y;
|
||||||
|
else if ((rm & 0xF000U) == _VIEW_CENTER_ << 12)
|
||||||
|
newFrame.top += y / 2;
|
||||||
|
|
||||||
|
// follow with bottom side
|
||||||
|
if ((rm & 0x00F0U) == _VIEW_BOTTOM_ << 4)
|
||||||
|
newFrame.bottom += y;
|
||||||
|
else if ((rm & 0x00F0U) == _VIEW_CENTER_ << 4)
|
||||||
|
newFrame.bottom += y / 2;
|
||||||
|
|
||||||
|
if (newFrame != fFrame) {
|
||||||
|
// MoveBy will change fFrame, so cache it
|
||||||
|
BRect oldFrame = fFrame;
|
||||||
|
MoveBy(newFrame.left - oldFrame.left,
|
||||||
|
newFrame.top - oldFrame.top);
|
||||||
|
|
||||||
|
ResizeBy(newFrame.Width() - oldFrame.Width(),
|
||||||
|
newFrame.Height() - oldFrame.Height(), dirtyRegion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
void
|
void
|
||||||
ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, bool deep)
|
ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, bool deep)
|
||||||
{
|
{
|
||||||
if (drawingEngine->Lock()) {
|
// we can only draw within our own area
|
||||||
// TODO intersect with local dirtyRegion
|
BRegion redraw(ScreenClipping());
|
||||||
// fill visible region with view color
|
// add the current clipping
|
||||||
drawingEngine->SetHighColor(fViewColor);
|
redraw.IntersectWith(effectiveClipping);
|
||||||
drawingEngine->FillRegion(effectiveClipping);
|
|
||||||
|
|
||||||
drawingEngine->MarkDirty(effectiveClipping);
|
if (drawingEngine->Lock()) {
|
||||||
|
drawingEngine->ConstrainClippingRegion(&redraw);
|
||||||
|
|
||||||
|
// fill visible region with white
|
||||||
|
drawingEngine->SetHighColor(255, 255, 255);
|
||||||
|
BRect b(Bounds());
|
||||||
|
ConvertToTop(&b);
|
||||||
|
drawingEngine->FillRect(b);
|
||||||
|
|
||||||
|
// draw a frame with the view color
|
||||||
|
b.OffsetTo(0.0, 0.0);
|
||||||
|
ConvertToTop(&b);
|
||||||
|
drawingEngine->SetHighColor(fViewColor);
|
||||||
|
drawingEngine->StrokeRect(b);
|
||||||
|
drawingEngine->StrokeLine(b.LeftTop(), b.RightBottom());
|
||||||
|
|
||||||
|
drawingEngine->ConstrainClippingRegion(NULL);
|
||||||
|
|
||||||
|
drawingEngine->MarkDirty(&redraw);
|
||||||
drawingEngine->Unlock();
|
drawingEngine->Unlock();
|
||||||
|
}
|
||||||
// let children draw
|
|
||||||
if (deep) {
|
// let children draw
|
||||||
for (ViewLayer* child = FirstChild(); child; child = NextChild()) {
|
if (deep) {
|
||||||
child->Draw(drawingEngine, effectiveClipping, deep);
|
// before passing the clipping on to children, exclude our
|
||||||
}
|
// own region from the available clipping
|
||||||
|
effectiveClipping->Exclude(&ScreenClipping());
|
||||||
|
|
||||||
|
for (ViewLayer* child = FirstChild(); child; child = NextChild()) {
|
||||||
|
child->Draw(drawingEngine, effectiveClipping, deep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ class ViewLayer {
|
|||||||
uint32 CountChildren() const;
|
uint32 CountChildren() const;
|
||||||
|
|
||||||
// coordinate conversion
|
// coordinate conversion
|
||||||
|
void ConvertToParent(BPoint* point) const;
|
||||||
|
void ConvertToParent(BRect* rect) const;
|
||||||
|
void ConvertToParent(BRegion* region) const;
|
||||||
|
|
||||||
void ConvertToTop(BPoint* point) const;
|
void ConvertToTop(BPoint* point) const;
|
||||||
void ConvertToTop(BRect* rect) const;
|
void ConvertToTop(BRect* rect) const;
|
||||||
void ConvertToTop(BRegion* region) const;
|
void ConvertToTop(BRegion* region) const;
|
||||||
@@ -59,6 +63,9 @@ class ViewLayer {
|
|||||||
void ResizeBy(int32 dx, int32 dy, BRegion* dirtyRegion);
|
void ResizeBy(int32 dx, int32 dy, BRegion* dirtyRegion);
|
||||||
void ScrollBy(int32 dx, int32 dy);
|
void ScrollBy(int32 dx, int32 dy);
|
||||||
|
|
||||||
|
void ParentResized(int32 dx, int32 dy,
|
||||||
|
BRegion* dirtyRegion);
|
||||||
|
|
||||||
void Draw(DrawingEngine* drawingEngine,
|
void Draw(DrawingEngine* drawingEngine,
|
||||||
BRegion* effectiveClipping,
|
BRegion* effectiveClipping,
|
||||||
bool deep = false);
|
bool deep = false);
|
||||||
|
|||||||
@@ -19,7 +19,12 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
|
|||||||
fFrame(frame),
|
fFrame(frame),
|
||||||
fVisibleRegion(),
|
fVisibleRegion(),
|
||||||
|
|
||||||
fBorderColor((rgb_color){ 255, 203, 0, 255 }),
|
fBorderRegion(),
|
||||||
|
fBorderRegionValid(false),
|
||||||
|
fContentRegion(),
|
||||||
|
fContentRegionValid(false),
|
||||||
|
|
||||||
|
fFocus(false),
|
||||||
|
|
||||||
fTopLayer(NULL),
|
fTopLayer(NULL),
|
||||||
|
|
||||||
@@ -95,6 +100,10 @@ WindowLayer::GetFullRegion(BRegion* region) const
|
|||||||
void
|
void
|
||||||
WindowLayer::GetBorderRegion(BRegion* region) const
|
WindowLayer::GetBorderRegion(BRegion* region) const
|
||||||
{
|
{
|
||||||
|
if (fBorderRegionValid) {
|
||||||
|
*region = fBorderRegion;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: speed up by avoiding "Exclude()"
|
// TODO: speed up by avoiding "Exclude()"
|
||||||
// start from the frame, extend to include decorator border
|
// start from the frame, extend to include decorator border
|
||||||
region->Set(BRect(fFrame.left - 4, fFrame.top - 4,
|
region->Set(BRect(fFrame.left - 4, fFrame.top - 4,
|
||||||
@@ -112,6 +121,45 @@ WindowLayer::GetBorderRegion(BRegion* region) const
|
|||||||
fFrame.right, fFrame.bottom));
|
fFrame.right, fFrame.bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetContentRegion
|
||||||
|
void
|
||||||
|
WindowLayer::GetContentRegion(BRegion* region) const
|
||||||
|
{
|
||||||
|
if (fContentRegionValid) {
|
||||||
|
*region = fContentRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: speed up by avoiding "Exclude()"
|
||||||
|
// start from the frame, extend to include decorator border
|
||||||
|
region->Set(fFrame);
|
||||||
|
|
||||||
|
// resize handle
|
||||||
|
// if (B_DOCUMENT_WINDOW_LOOK)
|
||||||
|
region->Exclude(BRect(fFrame.right - 10, fFrame.bottom - 10,
|
||||||
|
fFrame.right, fFrame.bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFocus
|
||||||
|
void
|
||||||
|
WindowLayer::SetFocus(bool focus)
|
||||||
|
{
|
||||||
|
if (Lock()) {
|
||||||
|
// executed from Desktop thread, so it's fine
|
||||||
|
// to use the clipping without locking
|
||||||
|
if (fDesktop->ReadLockClipping()) {
|
||||||
|
BRegion dirty(fBorderRegion);
|
||||||
|
dirty.IntersectWith(&fVisibleRegion);
|
||||||
|
MarkDirty(&dirty);
|
||||||
|
|
||||||
|
fDesktop->ReadUnlockClipping();
|
||||||
|
}
|
||||||
|
|
||||||
|
fFocus = focus;
|
||||||
|
|
||||||
|
Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MoveBy
|
// MoveBy
|
||||||
void
|
void
|
||||||
WindowLayer::MoveBy(int32 x, int32 y)
|
WindowLayer::MoveBy(int32 x, int32 y)
|
||||||
@@ -121,6 +169,11 @@ WindowLayer::MoveBy(int32 x, int32 y)
|
|||||||
|
|
||||||
fFrame.OffsetBy(x, y);
|
fFrame.OffsetBy(x, y);
|
||||||
|
|
||||||
|
if (fBorderRegionValid)
|
||||||
|
fBorderRegion.OffsetBy(x, y);
|
||||||
|
if (fContentRegionValid)
|
||||||
|
fContentRegion.OffsetBy(x, y);
|
||||||
|
|
||||||
fTopLayer->MoveBy(x, y);
|
fTopLayer->MoveBy(x, y);
|
||||||
|
|
||||||
// TODO: move a local dirty region!
|
// TODO: move a local dirty region!
|
||||||
@@ -133,15 +186,21 @@ WindowLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|||||||
if (x == 0 && y == 0)
|
if (x == 0 && y == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// BRegion previousBorder();
|
|
||||||
//
|
|
||||||
fFrame.right += x;
|
fFrame.right += x;
|
||||||
fFrame.bottom += y;
|
fFrame.bottom += y;
|
||||||
|
|
||||||
|
fBorderRegionValid = false;
|
||||||
|
fContentRegionValid = false;
|
||||||
|
|
||||||
// the border is dirty, put it into
|
// the border is dirty, put it into
|
||||||
// dirtyRegion for a start
|
// dirtyRegion for a start
|
||||||
GetBorderRegion(dirtyRegion);
|
GetBorderRegion(dirtyRegion);
|
||||||
|
|
||||||
|
// put the previous border region into the dirty region as well
|
||||||
|
// to handle the part that was overlapping a layer
|
||||||
|
// if B_DOCUMENT_WINDOW_LOOK
|
||||||
|
dirtyRegion->Include(&fBorderRegion);
|
||||||
|
|
||||||
fTopLayer->ResizeBy(x, y, dirtyRegion);
|
fTopLayer->ResizeBy(x, y, dirtyRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +217,8 @@ WindowLayer::AddChild(ViewLayer* layer)
|
|||||||
void
|
void
|
||||||
WindowLayer::MarkDirty(BRegion* regionOnScreen)
|
WindowLayer::MarkDirty(BRegion* regionOnScreen)
|
||||||
{
|
{
|
||||||
fDesktop->MarkDirty(regionOnScreen);
|
if (fDesktop)
|
||||||
|
fDesktop->MarkDirty(regionOnScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
# pragma mark -
|
# pragma mark -
|
||||||
@@ -175,12 +235,24 @@ WindowLayer::_DrawContents(ViewLayer* layer)
|
|||||||
if (!layer)
|
if (!layer)
|
||||||
layer = fTopLayer;
|
layer = fTopLayer;
|
||||||
|
|
||||||
BRegion effectiveLayerClipping(layer->ScreenClipping());
|
if (!fContentRegionValid) {
|
||||||
effectiveLayerClipping.IntersectWith(&fVisibleRegion);
|
GetContentRegion(&fContentRegion);
|
||||||
effectiveLayerClipping.IntersectWith(fDesktop->DirtyRegion());
|
fContentRegionValid = true;
|
||||||
if (effectiveLayerClipping.Frame().IsValid()) {
|
}
|
||||||
layer->Draw(fDrawingEngine, &effectiveLayerClipping, true);
|
|
||||||
fDesktop->MarkClean(&effectiveLayerClipping);
|
BRegion effectiveWindowClipping(fContentRegion);
|
||||||
|
// TODO: simplify
|
||||||
|
// ideally, there would only be a local fDirtyRegion,
|
||||||
|
// that we need to intersect with. fDirtyRegion would
|
||||||
|
// alread only include fVisibleRegion
|
||||||
|
effectiveWindowClipping.IntersectWith(&fVisibleRegion);
|
||||||
|
effectiveWindowClipping.IntersectWith(fDesktop->DirtyRegion());
|
||||||
|
if (effectiveWindowClipping.Frame().IsValid()) {
|
||||||
|
layer->Draw(fDrawingEngine, &effectiveWindowClipping, true);
|
||||||
|
|
||||||
|
fDesktop->MarkClean(&fContentRegion);
|
||||||
|
|
||||||
|
// send UPDATE message to the client here
|
||||||
}
|
}
|
||||||
//else {
|
//else {
|
||||||
//printf(" nothing to do\n");
|
//printf(" nothing to do\n");
|
||||||
@@ -197,20 +269,29 @@ WindowLayer::_DrawBorder()
|
|||||||
snooze(10000);
|
snooze(10000);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// construct the region containing just the border
|
if (!fBorderRegionValid) {
|
||||||
BRegion borderRegion(fVisibleRegion);
|
GetBorderRegion(&fBorderRegion);
|
||||||
borderRegion.Exclude(fFrame);
|
fBorderRegionValid = true;
|
||||||
// intersect with the Desktop's dirty region
|
}
|
||||||
borderRegion.IntersectWith(fDesktop->DirtyRegion());
|
|
||||||
|
|
||||||
if (borderRegion.Frame().IsValid()) {
|
// construct the region of the border that needs redrawing
|
||||||
|
BRegion dirtyBorderRegion(fBorderRegion);
|
||||||
|
// intersect with our visible region
|
||||||
|
dirtyBorderRegion.IntersectWith(&fVisibleRegion);
|
||||||
|
// intersect with the Desktop's dirty region
|
||||||
|
dirtyBorderRegion.IntersectWith(fDesktop->DirtyRegion());
|
||||||
|
|
||||||
|
if (dirtyBorderRegion.Frame().IsValid()) {
|
||||||
if (fDrawingEngine->Lock()) {
|
if (fDrawingEngine->Lock()) {
|
||||||
fDrawingEngine->SetHighColor(fBorderColor);
|
if (fFocus)
|
||||||
fDrawingEngine->FillRegion(&borderRegion);
|
fDrawingEngine->SetHighColor(255, 203, 0, 255);
|
||||||
fDrawingEngine->MarkDirty(&borderRegion);
|
else
|
||||||
|
fDrawingEngine->SetHighColor(216, 216, 216, 0);
|
||||||
|
fDrawingEngine->FillRegion(&dirtyBorderRegion);
|
||||||
|
fDrawingEngine->MarkDirty(&dirtyBorderRegion);
|
||||||
fDrawingEngine->Unlock();
|
fDrawingEngine->Unlock();
|
||||||
}
|
}
|
||||||
fDesktop->MarkClean(&borderRegion);
|
fDesktop->MarkClean(&dirtyBorderRegion);
|
||||||
}
|
}
|
||||||
//else {
|
//else {
|
||||||
//printf(" nothing to do\n");
|
//printf(" nothing to do\n");
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ class WindowLayer : public BLooper {
|
|||||||
{ return fVisibleRegion; }
|
{ return fVisibleRegion; }
|
||||||
void GetFullRegion(BRegion* region) const;
|
void GetFullRegion(BRegion* region) const;
|
||||||
void GetBorderRegion(BRegion* region) const;
|
void GetBorderRegion(BRegion* region) const;
|
||||||
|
void GetContentRegion(BRegion* region) const;
|
||||||
|
|
||||||
|
void SetFocus(bool focus);
|
||||||
|
|
||||||
void MoveBy(int32 x, int32 y);
|
void MoveBy(int32 x, int32 y);
|
||||||
void ResizeBy(int32 x, int32 y, BRegion* dirtyRegion);
|
void ResizeBy(int32 x, int32 y, BRegion* dirtyRegion);
|
||||||
@@ -50,7 +53,13 @@ class WindowLayer : public BLooper {
|
|||||||
// has to be called
|
// has to be called
|
||||||
BRegion fVisibleRegion;
|
BRegion fVisibleRegion;
|
||||||
|
|
||||||
rgb_color fBorderColor;
|
// caching local regions
|
||||||
|
BRegion fBorderRegion;
|
||||||
|
bool fBorderRegionValid;
|
||||||
|
BRegion fContentRegion;
|
||||||
|
bool fContentRegionValid;
|
||||||
|
|
||||||
|
bool fFocus;
|
||||||
|
|
||||||
ViewLayer* fTopLayer;
|
ViewLayer* fTopLayer;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
class App : public BApplication {
|
class App : public BApplication {
|
||||||
public:
|
public:
|
||||||
App();
|
App();
|
||||||
~App();
|
|
||||||
|
|
||||||
virtual void ReadyToRun();
|
virtual void ReadyToRun();
|
||||||
};
|
};
|
||||||
@@ -22,7 +21,7 @@ class App : public BApplication {
|
|||||||
class Window : public BWindow {
|
class Window : public BWindow {
|
||||||
public:
|
public:
|
||||||
Window(const char* title);
|
Window(const char* title);
|
||||||
~Window();
|
virtual ~Window();
|
||||||
|
|
||||||
void AddWindow(BRect frame, const char* name);
|
void AddWindow(BRect frame, const char* name);
|
||||||
void Test();
|
void Test();
|
||||||
@@ -31,16 +30,14 @@ class Window : public BWindow {
|
|||||||
Desktop* fDesktop;
|
Desktop* fDesktop;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
App::App()
|
App::App()
|
||||||
: BApplication("application/x-vnd.stippi.ClippingTest")
|
: BApplication("application/x-vnd.stippi.ClippingTest")
|
||||||
{
|
{
|
||||||
srand(real_time_clock_usecs());
|
srand(real_time_clock_usecs());
|
||||||
}
|
}
|
||||||
|
|
||||||
App::~App()
|
// ReadyToRun
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
App::ReadyToRun()
|
App::ReadyToRun()
|
||||||
{
|
{
|
||||||
@@ -50,6 +47,7 @@ App::ReadyToRun()
|
|||||||
win->Test();
|
win->Test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
Window::Window(const char* title)
|
Window::Window(const char* title)
|
||||||
: BWindow(BRect(50, 50, 800, 650), title,
|
: BWindow(BRect(50, 50, 800, 650), title,
|
||||||
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
||||||
@@ -62,6 +60,7 @@ Window::Window(const char* title)
|
|||||||
fView->MakeFocus(true);
|
fView->MakeFocus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
Window::~Window()
|
Window::~Window()
|
||||||
{
|
{
|
||||||
fDesktop->Lock();
|
fDesktop->Lock();
|
||||||
@@ -75,6 +74,41 @@ Window::AddWindow(BRect frame, const char* name)
|
|||||||
WindowLayer* window = new WindowLayer(frame, name,
|
WindowLayer* window = new WindowLayer(frame, name,
|
||||||
fDesktop->GetDrawingEngine(),
|
fDesktop->GetDrawingEngine(),
|
||||||
fDesktop);
|
fDesktop);
|
||||||
|
|
||||||
|
// add a coupld children
|
||||||
|
frame.OffsetTo(B_ORIGIN);
|
||||||
|
frame.InsetBy(5.0, 5.0);
|
||||||
|
if (frame.IsValid()) {
|
||||||
|
ViewLayer* layer1 = new ViewLayer(frame, "View 1",
|
||||||
|
B_FOLLOW_ALL,
|
||||||
|
B_FULL_UPDATE_ON_RESIZE,
|
||||||
|
(rgb_color){ 180, 180, 180, 255 });
|
||||||
|
|
||||||
|
frame.OffsetTo(B_ORIGIN);
|
||||||
|
frame.InsetBy(15.0, 15.0);
|
||||||
|
if (frame.IsValid()) {
|
||||||
|
frame.bottom = (frame.top + frame.bottom) / 2 - 5;
|
||||||
|
|
||||||
|
ViewLayer* layer2 = new ViewLayer(frame, "View 2",
|
||||||
|
B_FOLLOW_ALL,
|
||||||
|
0,
|
||||||
|
(rgb_color){ 120, 120, 120, 255 });
|
||||||
|
|
||||||
|
frame.OffsetBy(0.0, frame.Height() + 10);
|
||||||
|
|
||||||
|
ViewLayer* layer3 = new ViewLayer(frame, "View 3",
|
||||||
|
B_FOLLOW_BOTTOM,
|
||||||
|
0,
|
||||||
|
(rgb_color){ 120, 120, 120, 255 });
|
||||||
|
|
||||||
|
|
||||||
|
layer1->AddChild(layer2);
|
||||||
|
layer1->AddChild(layer3);
|
||||||
|
}
|
||||||
|
|
||||||
|
window->AddChild(layer1);
|
||||||
|
}
|
||||||
|
|
||||||
window->Run();
|
window->Run();
|
||||||
|
|
||||||
BMessage message(MSG_ADD_WINDOW);
|
BMessage message(MSG_ADD_WINDOW);
|
||||||
|
|||||||
Reference in New Issue
Block a user