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:
@@ -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(©Region, -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; }
|
||||
|
||||
Reference in New Issue
Block a user