scrolling seems to work nicely, dirty regions are tracked fine and shifted along with the scrolling if necessary

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15277 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2005-12-01 21:14:10 +00:00
parent 3d05db78ce
commit 7943e1a86d
7 changed files with 109 additions and 12 deletions
@@ -3,8 +3,8 @@
#define CLIENT_LOOPER_H
#include <Looper.h>
#include <MessageRunner.h>
class BMessageRunner;
class WindowLayer;
enum {
@@ -18,6 +18,7 @@ Desktop::Desktop(DrawView* drawView)
fTracking(false),
fLastMousePos(-1.0, -1.0),
fClickedWindow(NULL),
fScrollingView(NULL),
fResizing(false),
fIs2ndButton(false),
@@ -90,7 +91,9 @@ Desktop::MouseDown(BPoint where, uint32 buttons, int32 clicks)
if (buttons == B_PRIMARY_MOUSE_BUTTON) {
fTracking = true;
if (fClickedWindow) {
if (clicks >= 2) {
if (modifiers() & B_SHIFT_KEY) {
fScrollingView = fClickedWindow->ViewAt(where);
} else if (clicks >= 2) {
HideWindow(fClickedWindow);
fClickedWindow = NULL;
} else {
@@ -132,6 +135,7 @@ Desktop::MouseUp(BPoint where)
fTracking = false;
fIs2ndButton = false;
fClickedWindow = NULL;
fScrollingView = NULL;
}
// MouseMoved
@@ -149,8 +153,13 @@ Desktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
if (dx != 0 || dy != 0) {
if (fClickedWindow) {
if (fScrollingView) {
if (LockClipping()) {
fClickedWindow->ScrollViewBy(fScrollingView, -dx, -dy);
UnlockClipping();
}
} else if (fResizing) {
//bigtime_t now = system_time();
if (fResizing) {
ResizeWindowBy(fClickedWindow, dx, dy);
//printf("resizing: %lld\n", system_time() - now);
} else {
@@ -21,6 +21,7 @@
#endif
class WindowLayer;
class ViewLayer;
enum {
MSG_ADD_WINDOW = 'addw',
@@ -100,14 +101,13 @@ private:
bool fTracking;
BPoint fLastMousePos;
WindowLayer* fClickedWindow;
ViewLayer* fScrollingView;
bool fResizing;
bigtime_t fClickTime;
bool fIs2ndButton;
#if MULTI_LOCKER
MultiLocker fClippingLock;
#elif RW_LOCKER
RWLocker fClippingLock;
#else
BLocker fClippingLock;
#endif
@@ -258,6 +258,24 @@ ViewLayer::CollectTokensForChildren(BList* tokenMap) const
}
}
// ViewAt
ViewLayer*
ViewLayer::ViewAt(const BPoint& where, BRegion* windowContentClipping)
{
if (!fVisible)
return NULL;
if (ScreenClipping(windowContentClipping).Contains(where))
return this;
for (ViewLayer* child = FirstChild(); child; child = NextChild()) {
ViewLayer* layer = child->ViewAt(where, windowContentClipping);
if (layer)
return layer;
}
return NULL;
}
// ConvertToParent
void
ViewLayer::ConvertToParent(BPoint* point) const
@@ -549,12 +567,43 @@ ViewLayer::ParentResized(int32 x, int32 y, BRegion* dirtyRegion)
void
ViewLayer::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
{
// blitting version, invalidates
// old contents
// remember old bounds for tracking dirty region
BRect oldBounds(Bounds());
// find the area of the view that can be scrolled,
// contents are shifted in the opposite direction from scrolling
BRect stillVisibleBounds(oldBounds);
stillVisibleBounds.OffsetBy(x, y);
// NOTE: using ConvertToVisibleInTopView()
// instead of ConvertToTop(), this makes
// sure we don't try to move or invalidate an
// area hidden underneath the parent view
ConvertToVisibleInTopView(&oldBounds);
ConvertToVisibleInTopView(&stillVisibleBounds);
fScrollingOffset.x += x;
fScrollingOffset.y += y;
// TODO: CopyRegion...
// TODO: ...
// do the blit, this will make sure
// that other more complex dirty regions
// are taken care of
BRegion copyRegion(stillVisibleBounds);
fWindow->CopyContents(&copyRegion, -x, -y);
// find the dirty region as far as we are
// concerned
BRegion dirty(oldBounds);
stillVisibleBounds.OffsetBy(-x, -y);
dirty.Exclude(stillVisibleBounds);
dirtyRegion->Include(&dirty);
// the screen clipping of this view and it's
// childs is no longer valid
InvalidateScreenClipping(true);
RebuildClipping(false);
}
// #pragma mark -
@@ -572,8 +621,6 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
if (drawingEngine->Lock()) {
// fill visible region with white
drawingEngine->SetHighColor(255, 255, 255);
BRect b(Bounds());
ConvertToTop(&b);
drawingEngine->FillRegion(&redraw);
drawingEngine->MarkDirty(&redraw);
@@ -50,6 +50,9 @@ class ViewLayer {
uint32 CountChildren(bool deep = false) const;
void CollectTokensForChildren(BList* tokenMap) const;
ViewLayer* ViewAt(const BPoint& where,
BRegion* windowContentClipping);
// coordinate conversion
void ConvertToParent(BPoint* point) const;
void ConvertToParent(BRect* rect) const;
@@ -321,6 +321,30 @@ WindowLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
fTopLayer->ResizeBy(x, y, dirtyRegion);
}
// ScrollViewBy
void
WindowLayer::ScrollViewBy(ViewLayer* view, int32 dx, int32 dy)
{
// this can be executed from any thread, but if the
// desktop thread is executing this, it should have
// the write lock, otherwise it is not prevented
// from executing this at the same time as the window
// is doing something else here!
if (!view || (dx == 0 && dy == 0))
return;
if (fDesktop && fDesktop->ReadLockClipping()) {
BRegion dirty;
view->ScrollBy(dx, dy, &dirty);
_MarkContentDirty(&dirty);
fDesktop->ReadUnlockClipping();
}
}
// AddChild
void
WindowLayer::AddChild(ViewLayer* layer)
@@ -338,11 +362,21 @@ WindowLayer::AddChild(ViewLayer* layer)
// TODO: trigger redraw for dirty regions
}
// ViewAt
ViewLayer*
WindowLayer::ViewAt(const BPoint& where)
{
if (!fContentRegionValid)
_UpdateContentRegion();
return fTopLayer->ViewAt(where, &fContentRegion);
}
// SetHidden
void
WindowLayer::SetHidden(bool hidden)
{
// the desktop takes care of
// dirty regions
// the desktop takes care of dirty regions
if (fHidden != hidden) {
fHidden = hidden;
@@ -618,7 +652,7 @@ WindowLayer::_DrawClientPolygon(int32 token, BPoint polygon[4])
// enforce the dirty region of the update session
fEffectiveDrawingRegion.IntersectWith(&fCurrentUpdateSession.DirtyRegion());
} else {
printf("%s - _DrawClient(token: %ld) - not in update\n", Name(), token);
printf("%s - _DrawClientPolygon(token: %ld) - not in update\n", Name(), token);
}
fEffectiveDrawingRegionValid = true;
}
@@ -77,8 +77,12 @@ class WindowLayer : public BLooper {
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; }