* implemented view bitmap options (B_BITMAP_TILE...) in
ViewLayer (for example, fixes NetPositive rendering HTML with a background image) * use BRegion pool everywhere in ViewLayer * WindowLayer update sessions distinguish between different reasons for the update: exposed and requested - on expose updates, the view backgrounds are cleared immidiately (as on R5), to keep the time previous stuff keeps showing as short as possible, while on requested updates, the background clearing is delayed until the client draws something, to keep the time until the client fills a view with content as small as possible to reduce flickering (might need more work, could be buggy yet) * HWInterface and DrawingEngine support delayed syncing to the graphics hardware at least for FillRect/Region. The speed up gained by this is minor though. * HWInterface cursor rendering uses a bit of rounding to avoid the slight transparent shadow around the cursor (I don't know if it is fully correct though, at least the shasow disappeared) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17172 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+107
-30
@@ -22,6 +22,8 @@
|
||||
#include "ServerWindow.h"
|
||||
#include "WindowLayer.h"
|
||||
|
||||
#include "drawing_support.h"
|
||||
|
||||
#include <List.h>
|
||||
#include <Message.h>
|
||||
#include <PortLink.h>
|
||||
@@ -809,14 +811,16 @@ ViewLayer::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
|
||||
// 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);
|
||||
BRegion* copyRegion = fWindow->GetRegion();
|
||||
if (!copyRegion)
|
||||
return;
|
||||
copyRegion->Set(stillVisibleBounds);
|
||||
fWindow->CopyContents(copyRegion, -x, -y);
|
||||
|
||||
// find the dirty region as far as we are
|
||||
// concerned
|
||||
BRegion* dirty = fWindow->GetRegion();
|
||||
if (!dirty)
|
||||
return;
|
||||
BRegion* dirty = copyRegion;
|
||||
// reuse copyRegion and call it dirty
|
||||
|
||||
dirty->Set(oldBounds);
|
||||
stillVisibleBounds.OffsetBy(-x, -y);
|
||||
@@ -860,17 +864,20 @@ ViewLayer::CopyBits(BRect src, BRect dst, BRegion& windowContentClipping)
|
||||
// do the blit, this will make sure
|
||||
// that other more complex dirty regions
|
||||
// are taken care of
|
||||
BRegion copyRegion(visibleSrc);
|
||||
copyRegion.IntersectWith(&ScreenClipping(&windowContentClipping));
|
||||
fWindow->CopyContents(©Region, xOffset, yOffset);
|
||||
BRegion* copyRegion = fWindow->GetRegion();
|
||||
if (!copyRegion)
|
||||
return;
|
||||
|
||||
copyRegion->Set(visibleSrc);
|
||||
copyRegion->IntersectWith(&ScreenClipping(&windowContentClipping));
|
||||
fWindow->CopyContents(copyRegion, xOffset, yOffset);
|
||||
|
||||
// find the dirty region as far as we are concerned
|
||||
BRect dirtyDst(dst);
|
||||
ConvertToVisibleInTopView(&dirtyDst);
|
||||
|
||||
BRegion* dirty = fWindow->GetRegion();
|
||||
if (!dirty)
|
||||
return;
|
||||
BRegion* dirty = copyRegion;
|
||||
// reuse copyRegion and call it "dirty"
|
||||
|
||||
dirty->Set(dirtyDst);
|
||||
// exclude the part that we could copy
|
||||
@@ -965,9 +972,11 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
|
||||
if (fViewBitmap != NULL || !fViewColor.IsTransparentMagic()) {
|
||||
// we can only draw within our own area
|
||||
BRegion redraw(ScreenClipping(windowContentClipping));
|
||||
BRegion* redraw = fWindow->GetRegion(ScreenClipping(windowContentClipping));
|
||||
if (!redraw)
|
||||
return;
|
||||
// add the current clipping
|
||||
redraw.IntersectWith(effectiveClipping);
|
||||
redraw->IntersectWith(effectiveClipping);
|
||||
|
||||
if (fViewBitmap != NULL) {
|
||||
// draw view bitmap
|
||||
@@ -975,20 +984,79 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
BRect rect = fBitmapDestination;
|
||||
ConvertToScreenForDrawing(&rect);
|
||||
|
||||
// lock the drawing engine for as long as we need the clipping
|
||||
// to be valid
|
||||
if (drawingEngine->Lock()) {
|
||||
drawingEngine->ConstrainClippingRegion(&redraw);
|
||||
align_rect_to_pixels(&rect);
|
||||
|
||||
DrawState defaultDrawState;
|
||||
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
|
||||
rect, &defaultDrawState);
|
||||
// NOTE: It is ok not to reset the clipping, that
|
||||
// would only waste time
|
||||
drawingEngine->Unlock();
|
||||
if (fBitmapOptions & B_TILE_BITMAP_Y) {
|
||||
// move rect up as much as needed
|
||||
while (rect.top > redraw->Frame().top)
|
||||
rect.OffsetBy(0.0, -(rect.Height() + 1));
|
||||
}
|
||||
if (fBitmapOptions & B_TILE_BITMAP_X) {
|
||||
// move rect left as much as needed
|
||||
while (rect.left > redraw->Frame().left)
|
||||
rect.OffsetBy(-(rect.Width() + 1), 0.0);
|
||||
}
|
||||
|
||||
// XXX: locking removed because the WindowLayer keeps the engine locked
|
||||
// because it keeps track of syncing right now
|
||||
|
||||
// lock the drawing engine for as long as we need the clipping
|
||||
// to be valid
|
||||
if (rect.IsValid()/* && drawingEngine->Lock()*/) {
|
||||
drawingEngine->ConstrainClippingRegion(redraw);
|
||||
|
||||
DrawState defaultDrawState;
|
||||
|
||||
if (fBitmapOptions & B_TILE_BITMAP) {
|
||||
// tile across entire view
|
||||
float start = rect.left;
|
||||
while (rect.top < redraw->Frame().bottom) {
|
||||
while (rect.left < redraw->Frame().right) {
|
||||
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
|
||||
rect, &defaultDrawState);
|
||||
rect.OffsetBy(rect.Width() + 1, 0.0);
|
||||
}
|
||||
rect.OffsetBy(start - rect.left, rect.Height() + 1);
|
||||
}
|
||||
// nothing left to be drawn
|
||||
redraw->MakeEmpty();
|
||||
|
||||
} else if (fBitmapOptions & B_TILE_BITMAP_X) {
|
||||
// tile in x direction
|
||||
while (rect.left < redraw->Frame().right) {
|
||||
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
|
||||
rect, &defaultDrawState);
|
||||
rect.OffsetBy(rect.Width() + 1, 0.0);
|
||||
}
|
||||
// remove horizontal stripe from clipping
|
||||
rect.left = redraw->Frame().left;
|
||||
rect.right = redraw->Frame().right;
|
||||
redraw->Exclude(rect);
|
||||
|
||||
} else if (fBitmapOptions & B_TILE_BITMAP_Y) {
|
||||
// tile in y direction
|
||||
while (rect.top < redraw->Frame().bottom) {
|
||||
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
|
||||
rect, &defaultDrawState);
|
||||
rect.OffsetBy(0.0, rect.Height() + 1);
|
||||
}
|
||||
// remove vertical stripe from clipping
|
||||
rect.top = redraw->Frame().top;
|
||||
rect.bottom = redraw->Frame().bottom;
|
||||
redraw->Exclude(rect);
|
||||
|
||||
} else {
|
||||
// no tiling at all
|
||||
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
|
||||
rect, &defaultDrawState);
|
||||
redraw->Exclude(rect);
|
||||
}
|
||||
|
||||
// NOTE: It is ok not to reset the clipping, that
|
||||
// would only waste time
|
||||
// drawingEngine->Unlock();
|
||||
}
|
||||
|
||||
redraw.Exclude(rect);
|
||||
}
|
||||
|
||||
if (!fViewColor.IsTransparentMagic()) {
|
||||
@@ -996,8 +1064,10 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
||||
// this version of FillRegion ignores any
|
||||
// clipping, that's why "redraw" needs to
|
||||
// be correct
|
||||
drawingEngine->FillRegion(redraw, fViewColor);
|
||||
drawingEngine->FillRegion(*redraw, fViewColor);
|
||||
}
|
||||
|
||||
fWindow->RecycleRegion(redraw);
|
||||
}
|
||||
|
||||
fBackgroundDirty = false;
|
||||
@@ -1176,9 +1246,12 @@ ViewLayer::RebuildClipping(bool deep)
|
||||
// hand, views for which this feature is actually used will
|
||||
// probably not have any children, so it is not that expensive
|
||||
// after all
|
||||
BRegion screenUserClipping(*userClipping);
|
||||
fDrawState->Transform(&screenUserClipping);
|
||||
fLocalClipping.IntersectWith(&screenUserClipping);
|
||||
BRegion* screenUserClipping = fWindow->GetRegion(*userClipping);
|
||||
if (!screenUserClipping)
|
||||
return;
|
||||
fDrawState->Transform(screenUserClipping);
|
||||
fLocalClipping.IntersectWith(screenUserClipping);
|
||||
fWindow->RecycleRegion(screenUserClipping);
|
||||
}
|
||||
|
||||
fScreenClippingValid = false;
|
||||
@@ -1198,8 +1271,12 @@ ViewLayer::ScreenClipping(BRegion* windowContentClipping, bool force) const
|
||||
ConvertToVisibleInTopView(&clippedBounds);
|
||||
if (clippedBounds.Width() < fScreenClipping.Frame().Width() ||
|
||||
clippedBounds.Height() < fScreenClipping.Frame().Height()) {
|
||||
BRegion temp(clippedBounds);
|
||||
fScreenClipping.IntersectWith(&temp);
|
||||
BRegion* temp = fWindow->GetRegion();
|
||||
if (temp) {
|
||||
temp->Set(clippedBounds);
|
||||
fScreenClipping.IntersectWith(temp);
|
||||
fWindow->RecycleRegion(temp);
|
||||
}
|
||||
}
|
||||
|
||||
fScreenClipping.IntersectWith(windowContentClipping);
|
||||
|
||||
@@ -65,7 +65,6 @@ using std::nothrow;
|
||||
// its previous position though if the exposed parts are not
|
||||
// cleared right away. maybe there ought to be a flag in
|
||||
// the update session, which tells us the cause of the update
|
||||
#define DELAYED_BACKGROUND_CLEARING 1
|
||||
|
||||
|
||||
WindowLayer::WindowLayer(const BRect& frame, const char *name,
|
||||
@@ -81,6 +80,7 @@ WindowLayer::WindowLayer(const BRect& frame, const char *name,
|
||||
fVisibleContentRegion(),
|
||||
fVisibleContentRegionValid(false),
|
||||
fDirtyRegion(),
|
||||
fDirtyCause(0),
|
||||
|
||||
fBorderRegion(),
|
||||
fBorderRegionValid(false),
|
||||
@@ -609,8 +609,8 @@ WindowLayer::ProcessDirtyRegion(BRegion& region)
|
||||
ServerWindow()->RequestRedraw();
|
||||
}
|
||||
|
||||
// this is executed from the desktop thread
|
||||
fDirtyRegion.Include(®ion);
|
||||
fDirtyCause |= UPDATE_EXPOSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -639,6 +639,7 @@ WindowLayer::RedrawDirtyRegion()
|
||||
// get write access, since we're holding
|
||||
// the read lock for the whole time.
|
||||
fDirtyRegion.MakeEmpty();
|
||||
fDirtyCause = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -665,6 +666,7 @@ WindowLayer::MarkContentDirty(BRegion& regionOnScreen)
|
||||
return;
|
||||
|
||||
regionOnScreen.IntersectWith(&VisibleContentRegion());
|
||||
fDirtyCause |= UPDATE_REQUEST;
|
||||
_TriggerContentRedraw(regionOnScreen);
|
||||
}
|
||||
|
||||
@@ -684,7 +686,7 @@ WindowLayer::InvalidateView(ViewLayer* layer, BRegion& layerRegion)
|
||||
|
||||
//fDrawingEngine->FillRegion(layerRegion, RGBColor(0, 255, 0, 255));
|
||||
//snooze(10000);
|
||||
|
||||
fDirtyCause |= UPDATE_REQUEST;
|
||||
_TriggerContentRedraw(layerRegion);
|
||||
}
|
||||
}
|
||||
@@ -1621,25 +1623,32 @@ WindowLayer::_TriggerContentRedraw(BRegion& dirtyContentRegion)
|
||||
if (IsVisible() && dirtyContentRegion.CountRects() > 0) {
|
||||
// put this into the pending dirty region
|
||||
// to eventually trigger a client redraw
|
||||
bool wasExpose = fPendingUpdateSession.IsExpose();
|
||||
BRegion* backgroundClearingRegion = &dirtyContentRegion;
|
||||
|
||||
_TransferToUpdateSession(&dirtyContentRegion);
|
||||
|
||||
#if DELAYED_BACKGROUND_CLEARING
|
||||
// NOTE: currently not used, might come in handy later though
|
||||
// if (!fTopLayer->IsBackgroundDirty())
|
||||
// fTopLayer->MarkBackgroundDirty();
|
||||
#else
|
||||
// NOTE: turning off DELAYED_BACKGROUND_CLEARING will
|
||||
// need investigation if it even still works...
|
||||
if (!fContentRegionValid)
|
||||
_UpdateContentRegion();
|
||||
if (fPendingUpdateSession.IsExpose()) {
|
||||
if (!fContentRegionValid)
|
||||
_UpdateContentRegion();
|
||||
|
||||
if (fDrawingEngine->Lock()) {
|
||||
fDrawingEngine->ConstrainClippingRegion(&dirtyContentRegion);
|
||||
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
|
||||
&fContentRegion, true);
|
||||
fDrawingEngine->Unlock();
|
||||
if (!wasExpose) {
|
||||
// there was suddenly added a dirty region
|
||||
// caused by exposing content, we need to clear
|
||||
// the entire background
|
||||
backgroundClearingRegion = &fPendingUpdateSession.DirtyRegion();
|
||||
}
|
||||
|
||||
if (fDrawingEngine->Lock()) {
|
||||
fDrawingEngine->SuspendAutoSync();
|
||||
|
||||
fTopLayer->Draw(fDrawingEngine, backgroundClearingRegion,
|
||||
&fContentRegion, true);
|
||||
|
||||
fDrawingEngine->Sync();
|
||||
fDrawingEngine->Unlock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1691,6 +1700,8 @@ WindowLayer::_TransferToUpdateSession(BRegion* contentDirtyRegion)
|
||||
|
||||
// add to pending
|
||||
fPendingUpdateSession.SetUsed(true);
|
||||
// if (!fPendingUpdateSession.IsExpose())
|
||||
fPendingUpdateSession.AddCause(fDirtyCause);
|
||||
fPendingUpdateSession.Include(contentDirtyRegion);
|
||||
|
||||
// clip pending update session from current
|
||||
@@ -1699,14 +1710,10 @@ WindowLayer::_TransferToUpdateSession(BRegion* contentDirtyRegion)
|
||||
// this could be done smarter (clip layers from pending
|
||||
// that have not yet been redrawn in the current update
|
||||
// session)
|
||||
#if !DELAYED_BACKGROUND_CLEARING
|
||||
// NOTE: turning off DELAYED_BACKGROUND_CLEARING will
|
||||
// need investigation if it even still works...
|
||||
if (fCurrentUpdateSession.IsUsed()) {
|
||||
if (fCurrentUpdateSession.IsUsed() && fCurrentUpdateSession.IsExpose()) {
|
||||
fCurrentUpdateSession.Exclude(contentDirtyRegion);
|
||||
fEffectiveDrawingRegionValid = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!fUpdateRequested) {
|
||||
// send this to client
|
||||
@@ -1768,8 +1775,6 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link)
|
||||
|
||||
dirty->IntersectWith(&VisibleContentRegion());
|
||||
|
||||
//fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 0, 255));
|
||||
|
||||
link.StartMessage(B_OK);
|
||||
// append the current window geometry to the
|
||||
// message, the client will need it
|
||||
@@ -1785,14 +1790,19 @@ WindowLayer::BeginUpdate(BPrivate::PortLink& link)
|
||||
link.Attach<int32>(B_NULL_TOKEN);
|
||||
link.Flush();
|
||||
|
||||
#if DELAYED_BACKGROUND_CLEARING
|
||||
// NOTE: turning off DELAYED_BACKGROUND_CLEARING will
|
||||
// need investigation if it even still works...
|
||||
fTopLayer->Draw(fDrawingEngine, dirty,
|
||||
&fContentRegion, true);
|
||||
if (!fCurrentUpdateSession.IsExpose() && fDrawingEngine->Lock()) {
|
||||
//fDrawingEngine->FillRegion(dirty, RGBColor(255, 0, 0, 255));
|
||||
fDrawingEngine->SuspendAutoSync();
|
||||
|
||||
fTopLayer->Draw(fDrawingEngine, dirty,
|
||||
&fContentRegion, true);
|
||||
|
||||
fDrawingEngine->Sync();
|
||||
fDrawingEngine->Unlock();
|
||||
} // else the background was cleared already
|
||||
|
||||
fRegionPool.Recycle(dirty);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
printf("BeginUpdate() but no update requested!!\n");
|
||||
link.StartMessage(B_ERROR);
|
||||
@@ -1908,7 +1918,8 @@ WindowLayer::_ObeySizeLimits()
|
||||
// constructor
|
||||
WindowLayer::UpdateSession::UpdateSession()
|
||||
: fDirtyRegion(),
|
||||
fInUse(false)
|
||||
fInUse(false),
|
||||
fCause(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1943,8 +1954,17 @@ void
|
||||
WindowLayer::UpdateSession::SetUsed(bool used)
|
||||
{
|
||||
fInUse = used;
|
||||
if (!fInUse)
|
||||
if (!fInUse) {
|
||||
fDirtyRegion.MakeEmpty();
|
||||
fCause = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WindowLayer::UpdateSession::AddCause(uint8 cause)
|
||||
{
|
||||
fCause |= cause;
|
||||
}
|
||||
|
||||
|
||||
@@ -1953,6 +1973,7 @@ WindowLayer::UpdateSession::operator=(const WindowLayer::UpdateSession& other)
|
||||
{
|
||||
fDirtyRegion = other.fDirtyRegion;
|
||||
fInUse = other.fInUse;
|
||||
fCause = other.fCause;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,11 @@ class WindowLayer;
|
||||
// TODO: move this into a proper place
|
||||
#define AS_REDRAW 'rdrw'
|
||||
|
||||
enum {
|
||||
UPDATE_REQUEST = 0x01,
|
||||
UPDATE_EXPOSE = 0x02,
|
||||
};
|
||||
|
||||
class WindowLayer {
|
||||
public:
|
||||
WindowLayer(const BRect& frame,
|
||||
@@ -248,6 +253,7 @@ class WindowLayer {
|
||||
// the clipping, since it is local and the desktop
|
||||
// thread is blocked
|
||||
BRegion fDirtyRegion;
|
||||
uint32 fDirtyCause;
|
||||
|
||||
// caching local regions
|
||||
BRegion fBorderRegion;
|
||||
@@ -301,12 +307,19 @@ class WindowLayer {
|
||||
void SetUsed(bool used);
|
||||
inline bool IsUsed() const
|
||||
{ return fInUse; }
|
||||
|
||||
void AddCause(uint8 cause);
|
||||
inline bool IsExpose() const
|
||||
{ return fCause & UPDATE_EXPOSE; }
|
||||
inline bool IsRequest() const
|
||||
{ return fCause & UPDATE_REQUEST; }
|
||||
|
||||
UpdateSession& operator=(const UpdateSession& other);
|
||||
|
||||
private:
|
||||
BRegion fDirtyRegion;
|
||||
bool fInUse;
|
||||
uint8 fCause;
|
||||
};
|
||||
|
||||
BRegion fDecoratorRegion;
|
||||
|
||||
@@ -733,7 +733,8 @@ AccelerantHWInterface::CopyRegion(const clipping_rect* sortedRectList,
|
||||
|
||||
// FillRegion
|
||||
void
|
||||
AccelerantHWInterface::FillRegion(/*const*/ BRegion& region, const RGBColor& color)
|
||||
AccelerantHWInterface::FillRegion(/*const*/ BRegion& region, const RGBColor& color,
|
||||
bool autoSync)
|
||||
{
|
||||
if (fAccFillRect && fAccAcquireEngine) {
|
||||
if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) {
|
||||
@@ -750,7 +751,7 @@ AccelerantHWInterface::FillRegion(/*const*/ BRegion& region, const RGBColor& col
|
||||
fAccReleaseEngine(fEngineToken, &fSyncToken);
|
||||
|
||||
// sync
|
||||
if (fAccSyncToToken)
|
||||
if (autoSync && fAccSyncToToken)
|
||||
fAccSyncToToken(&fSyncToken);
|
||||
}
|
||||
}
|
||||
@@ -781,6 +782,14 @@ AccelerantHWInterface::InvertRegion(/*const*/ BRegion& region)
|
||||
}
|
||||
}
|
||||
|
||||
// Sync
|
||||
void
|
||||
AccelerantHWInterface::Sync()
|
||||
{
|
||||
if (fAccSyncToToken)
|
||||
fAccSyncToToken(&fSyncToken);
|
||||
}
|
||||
|
||||
// SetCursor
|
||||
void
|
||||
AccelerantHWInterface::SetCursor(ServerCursor* cursor)
|
||||
|
||||
@@ -59,9 +59,12 @@ public:
|
||||
uint32 count,
|
||||
int32 xOffset, int32 yOffset);
|
||||
virtual void FillRegion(/*const*/ BRegion& region,
|
||||
const RGBColor& color);
|
||||
const RGBColor& color,
|
||||
bool autoSync);
|
||||
virtual void InvertRegion(/*const*/ BRegion& region);
|
||||
|
||||
virtual void Sync();
|
||||
|
||||
// cursor handling
|
||||
virtual void SetCursor(ServerCursor* cursor);
|
||||
virtual void SetCursorVisible(bool visible);
|
||||
|
||||
@@ -944,7 +944,7 @@ DWindowHWInterface::CopyRegion(const clipping_rect* sortedRectList,
|
||||
|
||||
// FillRegion
|
||||
void
|
||||
DWindowHWInterface::FillRegion(/*const*/ BRegion& region, const RGBColor& color)
|
||||
DWindowHWInterface::FillRegion(/*const*/ BRegion& region, const RGBColor& color, bool autoSync)
|
||||
{
|
||||
if (fAccFillRect && fAccAcquireEngine) {
|
||||
if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) {
|
||||
@@ -961,7 +961,7 @@ DWindowHWInterface::FillRegion(/*const*/ BRegion& region, const RGBColor& color)
|
||||
fAccReleaseEngine(fEngineToken, &fSyncToken);
|
||||
|
||||
// sync
|
||||
if (fAccSyncToToken)
|
||||
if (autoSync && fAccSyncToToken)
|
||||
fAccSyncToToken(&fSyncToken);
|
||||
}
|
||||
}
|
||||
@@ -997,6 +997,14 @@ DWindowHWInterface::InvertRegion(/*const*/ BRegion& region)
|
||||
}
|
||||
}
|
||||
|
||||
// Sync
|
||||
void
|
||||
DWindowHWInterface::Sync()
|
||||
{
|
||||
if (fAccSyncToToken)
|
||||
fAccSyncToToken(&fSyncToken);
|
||||
}
|
||||
|
||||
// FrontBuffer
|
||||
RenderingBuffer*
|
||||
DWindowHWInterface::FrontBuffer() const
|
||||
|
||||
@@ -59,9 +59,12 @@ class DWindowHWInterface : public HWInterface {
|
||||
uint32 count,
|
||||
int32 xOffset, int32 yOffset);
|
||||
virtual void FillRegion(/*const*/ BRegion& region,
|
||||
const RGBColor& color);
|
||||
const RGBColor& color,
|
||||
bool autoSync);
|
||||
virtual void InvertRegion(/*const*/ BRegion& region);
|
||||
|
||||
virtual void Sync();
|
||||
|
||||
// frame buffer access
|
||||
virtual RenderingBuffer* FrontBuffer() const;
|
||||
virtual RenderingBuffer* BackBuffer() const;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "ServerCursor.h"
|
||||
#include "RenderingBuffer.h"
|
||||
|
||||
#include "frame_buffer_support.h"
|
||||
#include "drawing_support.h"
|
||||
|
||||
// make_rect_valid
|
||||
static inline void
|
||||
@@ -82,7 +82,8 @@ class FontLocker {
|
||||
DrawingEngine::DrawingEngine(HWInterface* interface)
|
||||
: fPainter(new Painter()),
|
||||
fGraphicsCard(interface),
|
||||
fAvailableHWAccleration(0)
|
||||
fAvailableHWAccleration(0),
|
||||
fSuspendSyncLevel(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -152,6 +153,24 @@ DrawingEngine::ConstrainClippingRegion(const BRegion* region)
|
||||
}
|
||||
}
|
||||
|
||||
// SuspendAutoSync
|
||||
void
|
||||
DrawingEngine::SuspendAutoSync()
|
||||
{
|
||||
fSuspendSyncLevel++;
|
||||
}
|
||||
|
||||
// Sync
|
||||
void
|
||||
DrawingEngine::Sync()
|
||||
{
|
||||
fSuspendSyncLevel--;
|
||||
if (fSuspendSyncLevel == 0)
|
||||
fGraphicsCard->Sync();
|
||||
}
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// CopyRegion() does a topological sort of the rects in the
|
||||
// region. The algorithm was suggested by Ingo Weinhold.
|
||||
// It compares each rect with each rect and builds a tree
|
||||
@@ -596,20 +615,23 @@ DrawingEngine::FillRect(BRect r, const RGBColor& color)
|
||||
make_rect_valid(r);
|
||||
r = fPainter->ClipRect(r);
|
||||
if (r.IsValid()) {
|
||||
fGraphicsCard->HideSoftwareCursor(r);
|
||||
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(r);
|
||||
|
||||
// try hardware optimized version first
|
||||
if (fAvailableHWAccleration & HW_ACC_FILL_REGION) {
|
||||
BRegion region(r);
|
||||
region.IntersectWith(fPainter->ClippingRegion());
|
||||
fGraphicsCard->FillRegion(region, color);
|
||||
fGraphicsCard->FillRegion(region, color,
|
||||
fSuspendSyncLevel == 0
|
||||
|| cursorTouched);
|
||||
} else {
|
||||
fPainter->FillRect(r, color.GetColor32());
|
||||
|
||||
fGraphicsCard->Invalidate(r);
|
||||
}
|
||||
|
||||
fGraphicsCard->ShowSoftwareCursor();
|
||||
|
||||
if (cursorTouched)
|
||||
fGraphicsCard->ShowSoftwareCursor();
|
||||
}
|
||||
|
||||
WriteUnlock();
|
||||
@@ -626,13 +648,14 @@ DrawingEngine::FillRegion(BRegion& r, const RGBColor& color)
|
||||
// NOTE: region expected to be already clipped correctly!!
|
||||
if (WriteLock()) {
|
||||
BRect frame = r.Frame();
|
||||
fGraphicsCard->HideSoftwareCursor(frame);
|
||||
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(frame);
|
||||
|
||||
bool doInSoftware = true;
|
||||
// try hardware optimized version first
|
||||
if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0
|
||||
&& frame.Width() * frame.Height() > 100) {
|
||||
fGraphicsCard->FillRegion(r, color);
|
||||
fGraphicsCard->FillRegion(r, color, fSuspendSyncLevel == 0
|
||||
|| cursorTouched);
|
||||
doInSoftware = false;
|
||||
}
|
||||
|
||||
@@ -646,7 +669,8 @@ DrawingEngine::FillRegion(BRegion& r, const RGBColor& color)
|
||||
fGraphicsCard->Invalidate(r.Frame());
|
||||
}
|
||||
|
||||
fGraphicsCard->ShowSoftwareCursor();
|
||||
if (cursorTouched)
|
||||
fGraphicsCard->ShowSoftwareCursor();
|
||||
|
||||
WriteUnlock();
|
||||
}
|
||||
@@ -689,7 +713,7 @@ DrawingEngine::FillRect(BRect r, const DrawState *d)
|
||||
make_rect_valid(r);
|
||||
r = fPainter->ClipRect(r);
|
||||
if (r.IsValid()) {
|
||||
fGraphicsCard->HideSoftwareCursor(r);
|
||||
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(r);
|
||||
|
||||
bool doInSoftware = true;
|
||||
if ((r.Width() + 1) * (r.Height() + 1) > 100.0) {
|
||||
@@ -701,13 +725,17 @@ DrawingEngine::FillRect(BRect r, const DrawState *d)
|
||||
|| d->GetDrawingMode() == B_OP_OVER)) {
|
||||
BRegion region(r);
|
||||
region.IntersectWith(fPainter->ClippingRegion());
|
||||
fGraphicsCard->FillRegion(region, d->HighColor());
|
||||
fGraphicsCard->FillRegion(region, d->HighColor(),
|
||||
fSuspendSyncLevel == 0
|
||||
|| cursorTouched);
|
||||
doInSoftware = false;
|
||||
} else if (d->GetPattern() == B_SOLID_LOW
|
||||
&& d->GetDrawingMode() == B_OP_COPY) {
|
||||
BRegion region(r);
|
||||
region.IntersectWith(fPainter->ClippingRegion());
|
||||
fGraphicsCard->FillRegion(region, d->LowColor());
|
||||
fGraphicsCard->FillRegion(region, d->LowColor(),
|
||||
fSuspendSyncLevel == 0
|
||||
|| cursorTouched);
|
||||
doInSoftware = false;
|
||||
}
|
||||
}
|
||||
@@ -719,7 +747,8 @@ DrawingEngine::FillRect(BRect r, const DrawState *d)
|
||||
fGraphicsCard->Invalidate(r);
|
||||
}
|
||||
|
||||
fGraphicsCard->ShowSoftwareCursor();
|
||||
if (cursorTouched)
|
||||
fGraphicsCard->ShowSoftwareCursor();
|
||||
}
|
||||
|
||||
WriteUnlock();
|
||||
@@ -736,7 +765,7 @@ DrawingEngine::FillRegion(BRegion& r, const DrawState *d)
|
||||
if (WriteLock()) {
|
||||
BRect clipped = fPainter->ClipRect(r.Frame());
|
||||
if (clipped.IsValid()) {
|
||||
fGraphicsCard->HideSoftwareCursor(clipped);
|
||||
bool cursorTouched = fGraphicsCard->HideSoftwareCursor(clipped);
|
||||
|
||||
bool doInSoftware = true;
|
||||
// try hardware optimized version first
|
||||
@@ -745,12 +774,16 @@ DrawingEngine::FillRegion(BRegion& r, const DrawState *d)
|
||||
&& (d->GetDrawingMode() == B_OP_COPY
|
||||
|| d->GetDrawingMode() == B_OP_OVER)) {
|
||||
r.IntersectWith(fPainter->ClippingRegion());
|
||||
fGraphicsCard->FillRegion(r, d->HighColor());
|
||||
fGraphicsCard->FillRegion(r, d->HighColor(),
|
||||
fSuspendSyncLevel == 0
|
||||
|| cursorTouched);
|
||||
doInSoftware = false;
|
||||
} else if (d->GetPattern() == B_SOLID_LOW
|
||||
&& d->GetDrawingMode() == B_OP_COPY) {
|
||||
r.IntersectWith(fPainter->ClippingRegion());
|
||||
fGraphicsCard->FillRegion(r, d->LowColor());
|
||||
fGraphicsCard->FillRegion(r, d->LowColor(),
|
||||
fSuspendSyncLevel == 0
|
||||
|| cursorTouched);
|
||||
doInSoftware = false;
|
||||
}
|
||||
}
|
||||
@@ -768,7 +801,8 @@ DrawingEngine::FillRegion(BRegion& r, const DrawState *d)
|
||||
fGraphicsCard->Invalidate(touched);
|
||||
}
|
||||
|
||||
fGraphicsCard->ShowSoftwareCursor();
|
||||
if (cursorTouched)
|
||||
fGraphicsCard->ShowSoftwareCursor();
|
||||
}
|
||||
|
||||
WriteUnlock();
|
||||
@@ -1270,3 +1304,4 @@ DrawingEngine::_CopyRect(uint8* src, uint32 width, uint32 height,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -66,6 +66,9 @@ public:
|
||||
// will remove any clipping (drawing allowed everywhere)
|
||||
void ConstrainClippingRegion(const BRegion* region);
|
||||
|
||||
void SuspendAutoSync();
|
||||
void Sync();
|
||||
|
||||
// drawing functions
|
||||
void CopyRegion(/*const*/ BRegion* region,
|
||||
int32 xOffset, int32 yOffset);
|
||||
@@ -156,6 +159,7 @@ public:
|
||||
Painter* fPainter;
|
||||
HWInterface* fGraphicsCard;
|
||||
uint32 fAvailableHWAccleration;
|
||||
int32 fSuspendSyncLevel;
|
||||
};
|
||||
|
||||
#endif // DRAWING_ENGINE_H_
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "frame_buffer_support.h"
|
||||
#include "drawing_support.h"
|
||||
|
||||
#include "RenderingBuffer.h"
|
||||
#include "ServerCursor.h"
|
||||
@@ -302,7 +302,7 @@ HWInterface::CopyBackToFront(const BRect& frame)
|
||||
}
|
||||
|
||||
// HideSoftwareCursor
|
||||
void
|
||||
bool
|
||||
HWInterface::HideSoftwareCursor(const BRect& area)
|
||||
{
|
||||
if (fCursorAreaBackup && !fCursorAreaBackup->cursor_hidden) {
|
||||
@@ -312,8 +312,10 @@ HWInterface::HideSoftwareCursor(const BRect& area)
|
||||
fCursorAreaBackup->bottom);
|
||||
if (area.Intersects(backupArea)) {
|
||||
_RestoreCursorArea();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// HideSoftwareCursor
|
||||
@@ -404,10 +406,11 @@ HWInterface::_DrawCursor(BRect area) const
|
||||
*(uint32*)b = *(uint32*)s;
|
||||
// assumes backbuffer alpha = 255
|
||||
// assuming pre-multiplied cursor bitmap
|
||||
uint8 a = 255 - c[3];
|
||||
d[0] = ((b[0] * a) >> 8) + c[0];
|
||||
d[1] = ((b[1] * a) >> 8) + c[1];
|
||||
d[2] = ((b[2] * a) >> 8) + c[2];
|
||||
int a = 255 - c[3];
|
||||
d[0] = ((int)(b[0] * a + 255) >> 8) + c[0];
|
||||
d[1] = ((int)(b[1] * a + 255) >> 8) + c[1];
|
||||
d[2] = ((int)(b[2] * a + 255) >> 8) + c[2];
|
||||
|
||||
s += 4;
|
||||
c += 4;
|
||||
d += 4;
|
||||
@@ -428,9 +431,10 @@ HWInterface::_DrawCursor(BRect area) const
|
||||
// assumes backbuffer alpha = 255
|
||||
// assuming pre-multiplied cursor bitmap
|
||||
uint8 a = 255 - c[3];
|
||||
d[0] = ((s[0] * a) >> 8) + c[0];
|
||||
d[1] = ((s[1] * a) >> 8) + c[1];
|
||||
d[2] = ((s[2] * a) >> 8) + c[2];
|
||||
d[0] = ((s[0] * a + 255) >> 8) + c[0];
|
||||
d[1] = ((s[1] * a + 255) >> 8) + c[1];
|
||||
d[2] = ((s[2] * a + 255) >> 8) + c[2];
|
||||
|
||||
s += 4;
|
||||
c += 4;
|
||||
d += 4;
|
||||
|
||||
@@ -73,9 +73,12 @@ class HWInterface : public MultiLocker {
|
||||
uint32 count,
|
||||
int32 xOffset, int32 yOffset) {}
|
||||
virtual void FillRegion(/*const*/ BRegion& region,
|
||||
const RGBColor& color) {}
|
||||
const RGBColor& color,
|
||||
bool autoSync) {}
|
||||
virtual void InvertRegion(/*const*/ BRegion& region) {}
|
||||
|
||||
virtual void Sync() {}
|
||||
|
||||
// cursor handling (these do their own Read/Write locking)
|
||||
ServerCursor* Cursor() const { return fCursor; }
|
||||
virtual void SetCursor(ServerCursor* cursor);
|
||||
@@ -115,7 +118,7 @@ class HWInterface : public MultiLocker {
|
||||
// ---
|
||||
// NOTE: Investigate locking for these! The client code should already hold a
|
||||
// ReadLock, but maybe these functions should acquire a WriteLock!
|
||||
void HideSoftwareCursor(const BRect& area);
|
||||
bool HideSoftwareCursor(const BRect& area);
|
||||
void HideSoftwareCursor();
|
||||
void ShowSoftwareCursor();
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ StaticLibrary libasdrawing.a :
|
||||
AccelerantBuffer.cpp
|
||||
AccelerantHWInterface.cpp
|
||||
BitmapBuffer.cpp
|
||||
drawing_support.cpp
|
||||
DrawingEngine.cpp
|
||||
MallocBuffer.cpp
|
||||
UpdateQueue.cpp
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <agg_span_image_filter_rgba32.h>
|
||||
#include <agg_span_interpolator_linear.h>
|
||||
|
||||
#include "frame_buffer_support.h"
|
||||
#include "drawing_support.h"
|
||||
|
||||
#include "DrawState.h"
|
||||
|
||||
@@ -210,6 +210,8 @@ Painter::SetDrawState(const DrawState* data, bool updateFont)
|
||||
fLineJoinMode = data->LineJoinMode();
|
||||
fMiterLimit = data->MiterLimit();
|
||||
|
||||
// adopt the color *after* the pattern is set
|
||||
// to set the renderers to the correct color
|
||||
SetHighColor(data->HighColor().GetColor32());
|
||||
SetLowColor(data->LowColor().GetColor32());
|
||||
|
||||
@@ -240,7 +242,7 @@ Painter::SetHighColor(const rgb_color& color)
|
||||
void
|
||||
Painter::SetLowColor(const rgb_color& color)
|
||||
{
|
||||
fPatternHandler->SetLowColor(color);;
|
||||
fPatternHandler->SetLowColor(color);
|
||||
if (*(fPatternHandler->GetR5Pattern()) == B_SOLID_LOW)
|
||||
_SetRendererColor(color);
|
||||
}
|
||||
@@ -1356,12 +1358,8 @@ Painter::_DrawBitmap(const agg::rendering_buffer& srcBuffer, color_space format,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fSubpixelPrecise) {
|
||||
// round off viewRect (in a way avoiding too much distortion)
|
||||
viewRect.OffsetTo(roundf(viewRect.left), roundf(viewRect.top));
|
||||
viewRect.right = roundf(viewRect.right);
|
||||
viewRect.bottom = roundf(viewRect.bottom);
|
||||
}
|
||||
if (!fSubpixelPrecise)
|
||||
align_rect_to_pixels(&viewRect);
|
||||
|
||||
double xScale = (viewRect.Width() + 1) / (bitmapRect.Width() + 1);
|
||||
double yScale = (viewRect.Height() + 1) / (bitmapRect.Height() + 1);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef DRAWING_MODE_H
|
||||
#define DRAWING_MODE_H
|
||||
|
||||
#include "frame_buffer_support.h"
|
||||
#include "drawing_support.h"
|
||||
|
||||
#include "PatternHandler.h"
|
||||
#include "PixelFormat.h"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "drawing_support.h"
|
||||
|
||||
#include <Rect.h>
|
||||
|
||||
void
|
||||
align_rect_to_pixels(BRect* rect)
|
||||
{
|
||||
// round the rect with the least ammount of distortion
|
||||
rect->OffsetTo(roundf(rect->left), roundf(rect->top));
|
||||
rect->right = roundf(rect->right);
|
||||
rect->bottom = roundf(rect->bottom);
|
||||
}
|
||||
|
||||
+3
@@ -138,6 +138,9 @@ blend_line32(uint8* buffer, int32 pixels, uint8 r, uint8 g, uint8 b, uint8 a)
|
||||
gfxcpy32(buffer, tempBuffer, pixels * 4);
|
||||
}
|
||||
|
||||
void
|
||||
align_rect_to_pixels(BRect* rect);
|
||||
|
||||
#endif // SUPPORT_H
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ Server haiku_app_server :
|
||||
AccelerantBuffer.cpp
|
||||
AccelerantHWInterface.cpp
|
||||
BitmapBuffer.cpp
|
||||
drawing_support.cpp
|
||||
DrawingEngine.cpp
|
||||
MallocBuffer.cpp
|
||||
UpdateQueue.cpp
|
||||
@@ -148,6 +149,7 @@ SubInclude HAIKU_TOP src tests servers app copy_bits ;
|
||||
SubInclude HAIKU_TOP src tests servers app cursor_test ;
|
||||
SubInclude HAIKU_TOP src tests servers app desktop_window ;
|
||||
SubInclude HAIKU_TOP src tests servers app event_mask ;
|
||||
SubInclude HAIKU_TOP src tests servers app following ;
|
||||
SubInclude HAIKU_TOP src tests servers app look_and_feel ;
|
||||
SubInclude HAIKU_TOP src tests servers app painter ;
|
||||
SubInclude HAIKU_TOP src tests servers app playground ;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
SubDir HAIKU_TOP src tests servers app following ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
AddSubDirSupportedPlatforms libbe_test ;
|
||||
|
||||
UseHeaders [ FDirName os app ] ;
|
||||
UseHeaders [ FDirName os interface ] ;
|
||||
|
||||
SimpleTest Following :
|
||||
main.cpp
|
||||
: be ;
|
||||
|
||||
if ( $(TARGET_PLATFORM) = libbe_test ) {
|
||||
HaikuInstall install-test-apps : $(HAIKU_APP_TEST_DIR) : Following
|
||||
: tests!apps ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
// main.cpp
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Message.h>
|
||||
#include <Button.h>
|
||||
#include <View.h>
|
||||
#include <Window.h>
|
||||
|
||||
enum {
|
||||
TRACKING_NONE = 0,
|
||||
TRACKING_ALL,
|
||||
TRACKING_RIGHT,
|
||||
TRACKING_BOTTOM,
|
||||
TRACKING_RIGHT_BOTTOM,
|
||||
};
|
||||
|
||||
class TestView : public BView {
|
||||
|
||||
public:
|
||||
TestView(BRect frame, const char* name,
|
||||
uint32 resizeFlags, uint32 flags)
|
||||
: BView(frame, name, resizeFlags, flags),
|
||||
fTracking(TRACKING_NONE),
|
||||
fLastMousePos(0.0, 0.0)
|
||||
{
|
||||
rgb_color color;
|
||||
color.red = rand() / 256;
|
||||
color.green = rand() / 256;
|
||||
color.blue = rand() / 256;
|
||||
color.alpha = 255;
|
||||
SetViewColor(color);
|
||||
SetLowColor(color);
|
||||
}
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void MouseUp(BPoint where);
|
||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage);
|
||||
|
||||
private:
|
||||
uint32 fTracking;
|
||||
|
||||
BPoint fLastMousePos;
|
||||
};
|
||||
|
||||
// Draw
|
||||
void
|
||||
TestView::Draw(BRect updateRect)
|
||||
{
|
||||
// text
|
||||
SetHighColor(0, 0, 0, 255);
|
||||
const char* message = "Click and drag to move this view!";
|
||||
DrawString(message, BPoint(20.0, 30.0));
|
||||
|
||||
BRect r(Bounds());
|
||||
r.right -= 15.0;
|
||||
r.bottom -= 15.0;
|
||||
StrokeLine(r.RightTop(), BPoint(r.right, Bounds().bottom));
|
||||
StrokeLine(r.LeftBottom(), BPoint(Bounds().right, r.bottom));
|
||||
}
|
||||
|
||||
// MouseDown
|
||||
void
|
||||
TestView::MouseDown(BPoint where)
|
||||
{
|
||||
BRect r(Bounds());
|
||||
r.right -= 15.0;
|
||||
r.bottom -= 15.0;
|
||||
if (r.Contains(where))
|
||||
fTracking = TRACKING_ALL;
|
||||
else if (r.bottom < where.y && r.right < where.x)
|
||||
fTracking = TRACKING_RIGHT_BOTTOM;
|
||||
else if (r.bottom < where.y)
|
||||
fTracking = TRACKING_BOTTOM;
|
||||
else if (r.right < where.x)
|
||||
fTracking = TRACKING_RIGHT;
|
||||
|
||||
fLastMousePos = where;
|
||||
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
|
||||
}
|
||||
|
||||
// MouseUp
|
||||
void
|
||||
TestView::MouseUp(BPoint where)
|
||||
{
|
||||
fTracking = TRACKING_NONE;
|
||||
}
|
||||
|
||||
// MouseMoved
|
||||
void
|
||||
TestView::MouseMoved(BPoint where, uint32 transit,
|
||||
const BMessage* dragMessage)
|
||||
{
|
||||
BPoint offset = where - fLastMousePos;
|
||||
switch (fTracking) {
|
||||
case TRACKING_ALL:
|
||||
MoveBy(offset.x, offset.y);
|
||||
// fLastMousePos stays fixed
|
||||
break;
|
||||
case TRACKING_RIGHT:
|
||||
ResizeBy(offset.x, 0.0);
|
||||
fLastMousePos = where;
|
||||
break;
|
||||
case TRACKING_BOTTOM:
|
||||
ResizeBy(0.0, offset.y);
|
||||
fLastMousePos = where;
|
||||
break;
|
||||
case TRACKING_RIGHT_BOTTOM:
|
||||
ResizeBy(offset.x, offset.y);
|
||||
fLastMousePos = where;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// show_window
|
||||
void
|
||||
show_window(BRect frame, const char* name)
|
||||
{
|
||||
BWindow* window = new BWindow(frame, name,
|
||||
B_TITLED_WINDOW,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE);
|
||||
|
||||
BView* view = new TestView(window->Bounds(), "test 1", B_FOLLOW_ALL,
|
||||
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
|
||||
|
||||
window->AddChild(view);
|
||||
|
||||
BRect bounds = view->Bounds();
|
||||
bounds.InsetBy(20, 20);
|
||||
BView* view1 = new TestView(bounds, "test 2", B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM,
|
||||
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
|
||||
view->AddChild(view1);
|
||||
|
||||
bounds = view1->Bounds();
|
||||
bounds.InsetBy(20, 20);
|
||||
BView* view2 = new TestView(bounds, "test 3", B_FOLLOW_NONE,
|
||||
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
|
||||
view1->AddChild(view2);
|
||||
|
||||
|
||||
window->Show();
|
||||
}
|
||||
|
||||
// main
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
BApplication* app = new BApplication("application/x.vnd-Haiku.Following");
|
||||
|
||||
BRect frame(50.0, 50.0, 300.0, 250.0);
|
||||
show_window(frame, "Following Test");
|
||||
|
||||
app->Run();
|
||||
|
||||
delete app;
|
||||
return 0;
|
||||
}
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
../../../../../generated/tests/apps/run_haiku_registrar || exit
|
||||
|
||||
if test -f ../../../../../generated/tests/apps/haiku_app_server; then
|
||||
../../../../../generated/tests/apps/haiku_app_server &
|
||||
else
|
||||
echo "You need to \"TARGET_PLATFORM=r5 jam install-test-apps\" first."
|
||||
fi
|
||||
|
||||
sleep 1s
|
||||
|
||||
if test -f ../../../../../generated/tests/apps/Following; then
|
||||
../../../../../generated/tests/apps/Following
|
||||
else
|
||||
echo "You need to \"TARGET_PLATFORM=r5 jam install-test-apps\" first."
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user