2005-12-08 15:41:19 +03:00
|
|
|
/*
|
2007-03-02 02:17:40 +03:00
|
|
|
* Copyright (c) 2001-2007, Haiku, Inc.
|
2005-12-08 15:41:19 +03:00
|
|
|
* Distributed under the terms of the MIT license.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* DarkWyrm <bpmagic@columbus.rr.com>
|
|
|
|
* Adi Oanca <adioanca@gmail.com>
|
2006-02-02 23:19:29 +03:00
|
|
|
* Axel Dörfler, axeld@pinc-software.de
|
2005-12-08 15:41:19 +03:00
|
|
|
* Stephan Aßmus <superstippi@gmx.de>
|
2007-03-02 02:17:40 +03:00
|
|
|
* Marcus Overhagen <marcus@overhagen.de>
|
2005-12-08 15:41:19 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "ViewLayer.h"
|
|
|
|
|
2005-12-29 19:46:02 +03:00
|
|
|
#include "BitmapManager.h"
|
2005-12-08 15:41:19 +03:00
|
|
|
#include "Desktop.h"
|
|
|
|
#include "DrawingEngine.h"
|
2006-04-23 19:45:35 +04:00
|
|
|
#include "Overlay.h"
|
2005-12-08 15:41:19 +03:00
|
|
|
#include "ServerApp.h"
|
2005-12-29 19:46:02 +03:00
|
|
|
#include "ServerBitmap.h"
|
2006-02-26 21:15:31 +03:00
|
|
|
#include "ServerCursor.h"
|
2006-01-03 13:30:08 +03:00
|
|
|
#include "ServerPicture.h"
|
2005-12-08 15:41:19 +03:00
|
|
|
#include "ServerWindow.h"
|
|
|
|
#include "WindowLayer.h"
|
|
|
|
|
2006-04-19 18:12:57 +04:00
|
|
|
#include "drawing_support.h"
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
#include <List.h>
|
ServerFont:
* fixed weird pointer conversion in SetStyle()
* fixed a potential mix up in operator=() in case the
other ServerFont has fStyle == NULL
ServerWindow:
* the WindowLayer fTopLayer cannot be deleted by
client request, just for safety reasons
* the link is flushed if there is no drawing engine,
but this case is theoretical only
* deleting the ServerWindow object syncs with the
client, so that when BBitmaps are deleted, they
can be sure there are no pending messages (which
would be executed in a nother thread)
* there is no timeout anymore when sending messages
to the client, which made absolutely no sense
AGGTextRenderer:
* renamed fFontManager to fFontCache, because that's
what it really is
* fLastFamilyAndStyle defaulted to the system plain
font and therefor that font was never loaded when
the font never changed meanwhile
DrawingMode:
* I'm not quite sure but I think there was the
potential of a division by zero, at least I
had crashes with "divide error"
HWInterface:
* fix update when the cursor shape changed in
double buffered mode
ViewLayer:
* since the top layer is never really deleted
before its time has come, it is not necessary
to set it to NULL in the ViewLayer destructor
ViewLayer/WindowLayer:
* added a function to collect the view tokens
that are affected by an update session
EventDispatcher:
* use the importance of the message for the timeout
in _SendMessage()
* drop mouse moved events in the server if we're
lagging behind more than 5 ms (Axel, maybe review)
View:
* there were some problems with the locking
of the BWindow looper in RemoveSelf(), since
this is called from the window destructor,
also of BWindows from BBitmaps, which have
never been run (this might need review), at
least I seem to have solved the crashing
problems introduced by actually deleting the
view hirarchy in the BWindow destructor
* fixed _Draw() for being used non-recursively,
temporarily disabled DrawAfterChildren, which
didn't work yet anyways (because views cannot
draw over children in the server yet)
Window:
* small cleanup when deleting shortcuts
* sync with the server when having send
AS_DELETE_WINDOW (see ServerWindow above)
* fixed locking in Begin/EndViewTransaction()
* removed folding of _UPDATE_ messages, since
there is only one ever in the queue
* set the fInTransaction flag during an update,
I plan to use this in BView later to
flush the link when drawing outside of an
update
* BView::_Draw() is now called by view token,
this gives the next leap forward in speed,
the overhead because of drawing clean views
was considerable
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15878 a95241bf-73f2-0310-859d-f6bbb57e9c96
2006-01-09 01:04:52 +03:00
|
|
|
#include <Message.h>
|
2006-02-06 13:28:30 +03:00
|
|
|
#include <PortLink.h>
|
2005-12-08 15:41:19 +03:00
|
|
|
#include <View.h> // for resize modes
|
2006-02-13 16:43:30 +03:00
|
|
|
#include <WindowPrivate.h>
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2005-12-10 23:16:41 +03:00
|
|
|
#include <new>
|
|
|
|
|
|
|
|
using std::nothrow;
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2006-04-04 05:51:16 +04:00
|
|
|
|
2006-04-23 18:28:48 +04:00
|
|
|
void
|
2006-11-29 06:20:07 +03:00
|
|
|
resize_frame(IntRect& frame, uint32 resizingMode, int32 x, int32 y)
|
2006-04-23 18:28:48 +04:00
|
|
|
{
|
|
|
|
// follow with left side
|
|
|
|
if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8)
|
|
|
|
frame.left += x;
|
|
|
|
else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8)
|
|
|
|
frame.left += x / 2;
|
|
|
|
|
|
|
|
// follow with right side
|
|
|
|
if ((resizingMode & 0x000FU) == _VIEW_RIGHT_)
|
|
|
|
frame.right += x;
|
|
|
|
else if ((resizingMode & 0x000FU) == _VIEW_CENTER_)
|
|
|
|
frame.right += x / 2;
|
|
|
|
|
|
|
|
// follow with top side
|
|
|
|
if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12)
|
|
|
|
frame.top += y;
|
|
|
|
else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12)
|
|
|
|
frame.top += y / 2;
|
|
|
|
|
|
|
|
// follow with bottom side
|
|
|
|
if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4)
|
|
|
|
frame.bottom += y;
|
|
|
|
else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4)
|
|
|
|
frame.bottom += y / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
ViewLayer::ViewLayer(IntRect frame, IntPoint scrollingOffset, const char* name,
|
2005-12-08 15:41:19 +03:00
|
|
|
int32 token, uint32 resizeMode, uint32 flags)
|
|
|
|
:
|
|
|
|
fName(name),
|
|
|
|
fToken(token),
|
|
|
|
|
|
|
|
fFrame(frame),
|
2006-04-04 05:51:16 +04:00
|
|
|
fScrollingOffset(scrollingOffset),
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2007-08-17 16:56:20 +04:00
|
|
|
fViewColor((rgb_color){ 255, 255, 255, 255 }),
|
2005-12-08 15:41:19 +03:00
|
|
|
fDrawState(new (nothrow) DrawState),
|
2005-12-29 19:46:02 +03:00
|
|
|
fViewBitmap(NULL),
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
fResizeMode(resizeMode),
|
|
|
|
fFlags(flags),
|
|
|
|
|
|
|
|
// ViewLayers start visible by default
|
|
|
|
fHidden(false),
|
|
|
|
fVisible(true),
|
2005-12-21 01:31:42 +03:00
|
|
|
fBackgroundDirty(true),
|
2006-02-13 16:43:30 +03:00
|
|
|
fIsDesktopBackground(false),
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
fEventMask(0),
|
|
|
|
fEventOptions(0),
|
|
|
|
|
|
|
|
fWindow(NULL),
|
|
|
|
fParent(NULL),
|
|
|
|
|
|
|
|
fFirstChild(NULL),
|
|
|
|
fPreviousSibling(NULL),
|
|
|
|
fNextSibling(NULL),
|
|
|
|
fLastChild(NULL),
|
2006-02-02 23:19:29 +03:00
|
|
|
|
|
|
|
fCursor(NULL),
|
2006-01-03 13:30:08 +03:00
|
|
|
fPicture(NULL),
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2007-07-19 21:06:28 +04:00
|
|
|
fLocalClipping((BRect)Bounds()),
|
2005-12-08 15:41:19 +03:00
|
|
|
fScreenClipping(),
|
|
|
|
fScreenClippingValid(false)
|
|
|
|
{
|
2005-12-21 14:22:48 +03:00
|
|
|
if (fDrawState)
|
|
|
|
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
ViewLayer::~ViewLayer()
|
|
|
|
{
|
2005-12-29 20:40:18 +03:00
|
|
|
if (fViewBitmap != NULL)
|
|
|
|
gBitmapManager->DeleteBitmap(fViewBitmap);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
delete fDrawState;
|
|
|
|
|
ServerFont:
* fixed weird pointer conversion in SetStyle()
* fixed a potential mix up in operator=() in case the
other ServerFont has fStyle == NULL
ServerWindow:
* the WindowLayer fTopLayer cannot be deleted by
client request, just for safety reasons
* the link is flushed if there is no drawing engine,
but this case is theoretical only
* deleting the ServerWindow object syncs with the
client, so that when BBitmaps are deleted, they
can be sure there are no pending messages (which
would be executed in a nother thread)
* there is no timeout anymore when sending messages
to the client, which made absolutely no sense
AGGTextRenderer:
* renamed fFontManager to fFontCache, because that's
what it really is
* fLastFamilyAndStyle defaulted to the system plain
font and therefor that font was never loaded when
the font never changed meanwhile
DrawingMode:
* I'm not quite sure but I think there was the
potential of a division by zero, at least I
had crashes with "divide error"
HWInterface:
* fix update when the cursor shape changed in
double buffered mode
ViewLayer:
* since the top layer is never really deleted
before its time has come, it is not necessary
to set it to NULL in the ViewLayer destructor
ViewLayer/WindowLayer:
* added a function to collect the view tokens
that are affected by an update session
EventDispatcher:
* use the importance of the message for the timeout
in _SendMessage()
* drop mouse moved events in the server if we're
lagging behind more than 5 ms (Axel, maybe review)
View:
* there were some problems with the locking
of the BWindow looper in RemoveSelf(), since
this is called from the window destructor,
also of BWindows from BBitmaps, which have
never been run (this might need review), at
least I seem to have solved the crashing
problems introduced by actually deleting the
view hirarchy in the BWindow destructor
* fixed _Draw() for being used non-recursively,
temporarily disabled DrawAfterChildren, which
didn't work yet anyways (because views cannot
draw over children in the server yet)
Window:
* small cleanup when deleting shortcuts
* sync with the server when having send
AS_DELETE_WINDOW (see ServerWindow above)
* fixed locking in Begin/EndViewTransaction()
* removed folding of _UPDATE_ messages, since
there is only one ever in the queue
* set the fInTransaction flag during an update,
I plan to use this in BView later to
flush the link when drawing outside of an
update
* BView::_Draw() is now called by view token,
this gives the next leap forward in speed,
the overhead because of drawing clean views
was considerable
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15878 a95241bf-73f2-0310-859d-f6bbb57e9c96
2006-01-09 01:04:52 +03:00
|
|
|
// if (fWindow && this == fWindow->TopLayer())
|
|
|
|
// fWindow->SetTopLayer(NULL);
|
2006-01-03 13:30:08 +03:00
|
|
|
|
2006-02-26 21:15:31 +03:00
|
|
|
if (fCursor)
|
|
|
|
fCursor->Release();
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// iterate over children and delete each one
|
|
|
|
ViewLayer* layer = fFirstChild;
|
|
|
|
while (layer) {
|
|
|
|
ViewLayer* toast = layer;
|
|
|
|
layer = layer->fNextSibling;
|
|
|
|
delete toast;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect
|
2005-12-08 15:41:19 +03:00
|
|
|
ViewLayer::Bounds() const
|
|
|
|
{
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect bounds(fScrollingOffset.x, fScrollingOffset.y,
|
|
|
|
fScrollingOffset.x + fFrame.Width(),
|
|
|
|
fScrollingOffset.y + fFrame.Height());
|
2005-12-08 15:41:19 +03:00
|
|
|
return bounds;
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
2006-11-29 06:20:07 +03:00
|
|
|
ViewLayer::ConvertToVisibleInTopView(IntRect* bounds) const
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
|
|
|
*bounds = *bounds & Bounds();
|
|
|
|
// NOTE: this step is necessary even if we don't have a parent!
|
|
|
|
ConvertToParent(bounds);
|
|
|
|
|
|
|
|
if (fParent)
|
|
|
|
fParent->ConvertToVisibleInTopView(bounds);
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::AttachedToWindow(WindowLayer* window)
|
|
|
|
{
|
|
|
|
fWindow = window;
|
|
|
|
|
2006-02-13 16:43:30 +03:00
|
|
|
// an ugly hack to detect the desktop background
|
|
|
|
if (window->Feel() == kDesktopWindowFeel && Parent() == TopLayer())
|
|
|
|
fIsDesktopBackground = true;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// insert view into local token space
|
|
|
|
if (fWindow != NULL)
|
|
|
|
fWindow->ServerWindow()->App()->ViewTokens().SetToken(fToken, B_HANDLER_TOKEN, this);
|
|
|
|
|
|
|
|
// attach child views as well
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
|
|
|
|
child->AttachedToWindow(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::DetachedFromWindow()
|
|
|
|
{
|
|
|
|
// remove view from local token space
|
|
|
|
if (fWindow != NULL)
|
|
|
|
fWindow->ServerWindow()->App()->ViewTokens().RemoveToken(fToken);
|
|
|
|
|
|
|
|
fWindow = NULL;
|
|
|
|
// detach child views as well
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
|
|
|
|
child->DetachedFromWindow();
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::AddChild(ViewLayer* layer)
|
|
|
|
{
|
|
|
|
if (layer->fParent) {
|
|
|
|
printf("ViewLayer::AddChild() - ViewLayer already has a parent\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
layer->fParent = this;
|
|
|
|
|
|
|
|
if (!fLastChild) {
|
|
|
|
// no children yet
|
|
|
|
fFirstChild = layer;
|
|
|
|
} else {
|
|
|
|
// append layer to formerly last child
|
|
|
|
fLastChild->fNextSibling = layer;
|
|
|
|
layer->fPreviousSibling = fLastChild;
|
|
|
|
}
|
|
|
|
fLastChild = layer;
|
|
|
|
|
2006-02-06 22:31:02 +03:00
|
|
|
layer->UpdateVisibleDeep(fVisible);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (layer->IsVisible())
|
|
|
|
RebuildClipping(false);
|
|
|
|
|
|
|
|
if (fWindow) {
|
|
|
|
layer->AttachedToWindow(fWindow);
|
|
|
|
|
2006-08-24 18:09:15 +04:00
|
|
|
if (layer->IsVisible()) {
|
|
|
|
// trigger redraw
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect clippedFrame = layer->Frame();
|
2006-08-24 18:09:15 +04:00
|
|
|
ConvertToVisibleInTopView(&clippedFrame);
|
|
|
|
BRegion* dirty = fWindow->GetRegion();
|
|
|
|
if (dirty) {
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Set((clipping_rect)clippedFrame);
|
2006-08-24 18:09:15 +04:00
|
|
|
fWindow->MarkContentDirtyAsync(*dirty);
|
|
|
|
fWindow->RecycleRegion(dirty);
|
|
|
|
}
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
ViewLayer::RemoveChild(ViewLayer* layer)
|
|
|
|
{
|
|
|
|
if (layer->fParent != this) {
|
|
|
|
printf("ViewLayer::RemoveChild(%p - %s) - ViewLayer is not child of this (%p) layer!\n", layer, layer ? layer->Name() : NULL, this);
|
|
|
|
return false;
|
|
|
|
}
|
2006-05-19 12:42:46 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
layer->fParent = NULL;
|
2006-05-19 12:42:46 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fLastChild == layer)
|
|
|
|
fLastChild = layer->fPreviousSibling;
|
|
|
|
// layer->fNextSibling would be NULL
|
2006-05-19 12:42:46 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (fFirstChild == layer )
|
|
|
|
fFirstChild = layer->fNextSibling;
|
|
|
|
// layer->fPreviousSibling would be NULL
|
|
|
|
|
|
|
|
// connect child before and after layer
|
|
|
|
if (layer->fPreviousSibling)
|
|
|
|
layer->fPreviousSibling->fNextSibling = layer->fNextSibling;
|
2006-05-19 12:42:46 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
if (layer->fNextSibling)
|
|
|
|
layer->fNextSibling->fPreviousSibling = layer->fPreviousSibling;
|
|
|
|
|
|
|
|
// layer has no siblings anymore
|
|
|
|
layer->fPreviousSibling = NULL;
|
|
|
|
layer->fNextSibling = NULL;
|
|
|
|
|
2006-04-23 19:45:35 +04:00
|
|
|
if (layer->IsVisible()) {
|
2007-07-18 21:01:34 +04:00
|
|
|
Overlay* overlay = layer->_Overlay();
|
2006-04-23 19:45:35 +04:00
|
|
|
if (overlay != NULL)
|
|
|
|
overlay->Hide();
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
RebuildClipping(false);
|
2006-04-23 19:45:35 +04:00
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
if (fWindow) {
|
|
|
|
layer->DetachedFromWindow();
|
|
|
|
|
2006-08-24 18:09:15 +04:00
|
|
|
if (fVisible && layer->IsVisible()) {
|
|
|
|
// trigger redraw
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect clippedFrame = layer->Frame();
|
2006-08-24 18:09:15 +04:00
|
|
|
ConvertToVisibleInTopView(&clippedFrame);
|
|
|
|
BRegion* dirty = fWindow->GetRegion();
|
|
|
|
if (dirty) {
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Set((clipping_rect)clippedFrame);
|
2006-08-24 18:09:15 +04:00
|
|
|
fWindow->MarkContentDirtyAsync(*dirty);
|
|
|
|
fWindow->RecycleRegion(dirty);
|
|
|
|
}
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ViewLayer*
|
|
|
|
ViewLayer::TopLayer()
|
|
|
|
{
|
|
|
|
// returns the top level view of the hirarchy,
|
|
|
|
// it doesn't have to be the top level of a window
|
|
|
|
|
|
|
|
if (fParent)
|
|
|
|
return fParent->TopLayer();
|
|
|
|
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
uint32
|
|
|
|
ViewLayer::CountChildren(bool deep) const
|
|
|
|
{
|
|
|
|
uint32 count = 0;
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
|
|
|
count++;
|
|
|
|
if (deep) {
|
|
|
|
count += child->CountChildren(deep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::CollectTokensForChildren(BList* tokenMap) const
|
|
|
|
{
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
|
|
|
tokenMap->AddItem((void*)child);
|
|
|
|
child->CollectTokensForChildren(tokenMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
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 = child->NextSibling()) {
|
|
|
|
ViewLayer* layer = child->ViewAt(where, windowContentClipping);
|
|
|
|
if (layer)
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::SetName(const char* string)
|
|
|
|
{
|
|
|
|
fName.SetTo(string);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::SetFlags(uint32 flags)
|
|
|
|
{
|
|
|
|
fFlags = flags;
|
|
|
|
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::SetDrawingOrigin(BPoint origin)
|
|
|
|
{
|
|
|
|
fDrawState->SetOrigin(origin);
|
|
|
|
|
|
|
|
// rebuild clipping
|
|
|
|
if (fDrawState->ClippingRegion())
|
|
|
|
RebuildClipping(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BPoint
|
|
|
|
ViewLayer::DrawingOrigin() const
|
|
|
|
{
|
|
|
|
BPoint origin(fDrawState->Origin());
|
|
|
|
float scale = Scale();
|
|
|
|
|
|
|
|
origin.x *= scale;
|
|
|
|
origin.y *= scale;
|
|
|
|
|
|
|
|
return origin;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::SetScale(float scale)
|
|
|
|
{
|
|
|
|
fDrawState->SetScale(scale);
|
|
|
|
|
|
|
|
// rebuild clipping
|
|
|
|
if (fDrawState->ClippingRegion())
|
|
|
|
RebuildClipping(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float
|
|
|
|
ViewLayer::Scale() const
|
|
|
|
{
|
|
|
|
return CurrentState()->Scale();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-03-08 21:57:44 +03:00
|
|
|
ViewLayer::SetUserClipping(const BRegion* region)
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
|
|
|
fDrawState->SetClippingRegion(region);
|
|
|
|
|
2005-12-30 22:56:42 +03:00
|
|
|
// rebuild clipping (for just this view)
|
2005-12-08 15:41:19 +03:00
|
|
|
RebuildClipping(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-29 19:46:02 +03:00
|
|
|
void
|
2006-11-29 06:20:07 +03:00
|
|
|
ViewLayer::SetViewBitmap(ServerBitmap* bitmap, IntRect sourceRect,
|
|
|
|
IntRect destRect, int32 resizingMode, int32 options)
|
2005-12-29 19:46:02 +03:00
|
|
|
{
|
2006-04-23 18:28:48 +04:00
|
|
|
if (fViewBitmap != NULL) {
|
2006-05-03 01:22:56 +04:00
|
|
|
Overlay* overlay = _Overlay();
|
|
|
|
|
2006-04-23 18:28:48 +04:00
|
|
|
if (bitmap != NULL) {
|
|
|
|
// take over overlay token from current overlay (if it has any)
|
2006-04-23 19:45:35 +04:00
|
|
|
Overlay* newOverlay = bitmap->Overlay();
|
2006-04-23 18:28:48 +04:00
|
|
|
|
2006-05-03 01:22:56 +04:00
|
|
|
if (overlay != NULL && newOverlay != NULL)
|
|
|
|
newOverlay->TakeOverToken(overlay);
|
|
|
|
} else if (overlay != NULL)
|
|
|
|
overlay->Hide();
|
2006-04-23 18:28:48 +04:00
|
|
|
|
2005-12-29 19:46:02 +03:00
|
|
|
gBitmapManager->DeleteBitmap(fViewBitmap);
|
2006-04-23 18:28:48 +04:00
|
|
|
}
|
2005-12-29 19:46:02 +03:00
|
|
|
|
|
|
|
// the caller is allowed to delete the bitmap after setting the background
|
|
|
|
if (bitmap != NULL)
|
|
|
|
bitmap->Acquire();
|
|
|
|
|
2005-12-30 22:56:42 +03:00
|
|
|
fViewBitmap = bitmap;
|
2005-12-29 19:46:02 +03:00
|
|
|
fBitmapSource = sourceRect;
|
|
|
|
fBitmapDestination = destRect;
|
|
|
|
fBitmapResizingMode = resizingMode;
|
|
|
|
fBitmapOptions = options;
|
2005-12-30 22:56:42 +03:00
|
|
|
|
2006-04-23 18:28:48 +04:00
|
|
|
_UpdateOverlayView();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-23 19:45:35 +04:00
|
|
|
::Overlay*
|
2006-04-23 18:28:48 +04:00
|
|
|
ViewLayer::_Overlay() const
|
|
|
|
{
|
|
|
|
if (fViewBitmap == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2006-04-23 19:45:35 +04:00
|
|
|
return fViewBitmap->Overlay();
|
2006-04-23 18:28:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::_UpdateOverlayView() const
|
|
|
|
{
|
2006-04-23 19:45:35 +04:00
|
|
|
Overlay* overlay = _Overlay();
|
2006-04-23 18:28:48 +04:00
|
|
|
if (overlay == NULL)
|
|
|
|
return;
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect destination = fBitmapDestination;
|
2006-04-23 18:28:48 +04:00
|
|
|
ConvertToScreen(&destination);
|
|
|
|
|
2006-05-19 12:42:46 +04:00
|
|
|
overlay->Configure(fBitmapSource, destination);
|
2005-12-29 19:46:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-16 23:12:01 +04:00
|
|
|
/*!
|
|
|
|
This method is called whenever the window is resized or moved - would
|
|
|
|
be nice to have a better solution for this, though.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ViewLayer::UpdateOverlay()
|
|
|
|
{
|
2006-05-17 16:46:56 +04:00
|
|
|
if (!IsVisible())
|
|
|
|
return;
|
|
|
|
|
2006-05-16 23:12:01 +04:00
|
|
|
if (_Overlay() != NULL) {
|
|
|
|
_UpdateOverlayView();
|
|
|
|
} else {
|
|
|
|
// recursively ask children of this view
|
|
|
|
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
|
|
|
child->UpdateOverlay();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ConvertToParent(BPoint* point) const
|
|
|
|
{
|
|
|
|
// remove scrolling offset and convert to parent coordinate space
|
|
|
|
point->x += fFrame.left - fScrollingOffset.x;
|
|
|
|
point->y += fFrame.top - fScrollingOffset.y;
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ConvertToParent(IntPoint* point) const
|
|
|
|
{
|
|
|
|
// remove scrolling offset and convert to parent coordinate space
|
|
|
|
point->x += fFrame.left - fScrollingOffset.x;
|
|
|
|
point->y += fFrame.top - fScrollingOffset.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ConvertToParent(IntRect* rect) const
|
|
|
|
{
|
|
|
|
// remove scrolling offset and convert to parent coordinate space
|
|
|
|
rect->OffsetBy(fFrame.left - fScrollingOffset.x,
|
|
|
|
fFrame.top - fScrollingOffset.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromParent(BPoint* point) const
|
|
|
|
{
|
2006-11-29 06:20:07 +03:00
|
|
|
// convert from parent coordinate space amd add scrolling offset
|
|
|
|
point->x += fScrollingOffset.x - fFrame.left;
|
|
|
|
point->y += fScrollingOffset.y - fFrame.top;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromParent(IntPoint* point) const
|
|
|
|
{
|
|
|
|
// convert from parent coordinate space amd add scrolling offset
|
2005-12-08 15:41:19 +03:00
|
|
|
point->x += fScrollingOffset.x - fFrame.left;
|
|
|
|
point->y += fScrollingOffset.y - fFrame.top;
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromParent(BRect* rect) const
|
|
|
|
{
|
2006-11-29 06:20:07 +03:00
|
|
|
// convert from parent coordinate space amd add scrolling offset
|
|
|
|
rect->OffsetBy(fScrollingOffset.x - fFrame.left,
|
|
|
|
fScrollingOffset.y - fFrame.top);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromParent(IntRect* rect) const
|
|
|
|
{
|
|
|
|
// convert from parent coordinate space amd add scrolling offset
|
2005-12-08 15:41:19 +03:00
|
|
|
rect->OffsetBy(fScrollingOffset.x - fFrame.left,
|
|
|
|
fScrollingOffset.y - fFrame.top);
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromParent(BRegion* region) const
|
|
|
|
{
|
2006-11-29 06:20:07 +03:00
|
|
|
// convert from parent coordinate space amd add scrolling offset
|
2005-12-08 15:41:19 +03:00
|
|
|
region->OffsetBy(fScrollingOffset.x - fFrame.left,
|
|
|
|
fScrollingOffset.y - fFrame.top);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! converts a point from local to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreen(BPoint* pt) const
|
|
|
|
{
|
|
|
|
ConvertToParent(pt);
|
|
|
|
|
|
|
|
if (fParent)
|
|
|
|
fParent->ConvertToScreen(pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
//! converts a point from local to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreen(IntPoint* pt) const
|
|
|
|
{
|
|
|
|
ConvertToParent(pt);
|
|
|
|
|
|
|
|
if (fParent)
|
|
|
|
fParent->ConvertToScreen(pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
//! converts a rect from local to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreen(BRect* rect) const
|
|
|
|
{
|
2006-02-06 22:31:02 +03:00
|
|
|
BPoint offset(0.0, 0.0);
|
|
|
|
ConvertToScreen(&offset);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2006-02-06 22:31:02 +03:00
|
|
|
rect->OffsetBy(offset);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
//! converts a rect from local to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreen(IntRect* rect) const
|
|
|
|
{
|
|
|
|
BPoint offset(0.0, 0.0);
|
|
|
|
ConvertToScreen(&offset);
|
|
|
|
|
|
|
|
rect->OffsetBy(offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
//! converts a region from local to screen coordinate system
|
|
|
|
void
|
2006-02-06 22:31:02 +03:00
|
|
|
ViewLayer::ConvertToScreen(BRegion* region) const
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
2006-02-06 22:31:02 +03:00
|
|
|
BPoint offset(0.0, 0.0);
|
|
|
|
ConvertToScreen(&offset);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2007-03-02 02:17:40 +03:00
|
|
|
region->OffsetBy((int)offset.x, (int)offset.y);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! converts a point from screen to local coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromScreen(BPoint* pt) const
|
|
|
|
{
|
|
|
|
ConvertFromParent(pt);
|
|
|
|
|
|
|
|
if (fParent)
|
|
|
|
fParent->ConvertFromScreen(pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
//! converts a point from screen to local coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromScreen(IntPoint* pt) const
|
|
|
|
{
|
|
|
|
ConvertFromParent(pt);
|
|
|
|
|
|
|
|
if (fParent)
|
|
|
|
fParent->ConvertFromScreen(pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
//! converts a rect from screen to local coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromScreen(BRect* rect) const
|
|
|
|
{
|
2006-02-06 22:31:02 +03:00
|
|
|
BPoint offset(0.0, 0.0);
|
|
|
|
ConvertFromScreen(&offset);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2006-02-06 22:31:02 +03:00
|
|
|
rect->OffsetBy(offset.x, offset.y);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
//! converts a rect from screen to local coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromScreen(IntRect* rect) const
|
|
|
|
{
|
|
|
|
BPoint offset(0.0, 0.0);
|
|
|
|
ConvertFromScreen(&offset);
|
|
|
|
|
2007-03-02 02:17:40 +03:00
|
|
|
rect->OffsetBy((int)offset.x, (int)offset.y);
|
2006-11-29 06:20:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
//! converts a region from screen to local coordinate system
|
|
|
|
void
|
2006-02-06 22:31:02 +03:00
|
|
|
ViewLayer::ConvertFromScreen(BRegion* region) const
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
2006-02-06 22:31:02 +03:00
|
|
|
BPoint offset(0.0, 0.0);
|
|
|
|
ConvertFromScreen(&offset);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2007-03-02 02:17:40 +03:00
|
|
|
region->OffsetBy((int)offset.x, (int)offset.y);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! converts a point from local *drawing* to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreenForDrawing(BPoint* point) const
|
|
|
|
{
|
|
|
|
fDrawState->Transform(point);
|
|
|
|
// NOTE: from here on, don't use the
|
|
|
|
// "*ForDrawing()" versions of the parent!
|
|
|
|
ConvertToScreen(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! converts a rect from local *drawing* to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreenForDrawing(BRect* rect) const
|
|
|
|
{
|
|
|
|
fDrawState->Transform(rect);
|
|
|
|
// NOTE: from here on, don't use the
|
|
|
|
// "*ForDrawing()" versions of the parent!
|
|
|
|
ConvertToScreen(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! converts a region from local *drawing* to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreenForDrawing(BRegion* region) const
|
|
|
|
{
|
|
|
|
fDrawState->Transform(region);
|
|
|
|
// NOTE: from here on, don't use the
|
|
|
|
// "*ForDrawing()" versions of the parent!
|
|
|
|
ConvertToScreen(region);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-02 02:17:40 +03:00
|
|
|
//! converts points from local *drawing* to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num) const
|
|
|
|
{
|
|
|
|
// TODO: optimize this, it should be smarter
|
|
|
|
while (num--) {
|
|
|
|
*dst = *src;
|
|
|
|
fDrawState->Transform(dst);
|
|
|
|
// NOTE: from here on, don't use the
|
|
|
|
// "*ForDrawing()" versions of the parent!
|
|
|
|
ConvertToScreen(dst);
|
|
|
|
src++;
|
|
|
|
dst++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! converts rects from local *drawing* to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num) const
|
|
|
|
{
|
|
|
|
// TODO: optimize this, it should be smarter
|
|
|
|
while (num--) {
|
|
|
|
*dst = *src;
|
|
|
|
fDrawState->Transform(dst);
|
|
|
|
// NOTE: from here on, don't use the
|
|
|
|
// "*ForDrawing()" versions of the parent!
|
|
|
|
ConvertToScreen(dst);
|
|
|
|
src++;
|
|
|
|
dst++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! converts regions from local *drawing* to screen coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertToScreenForDrawing(BRegion* dst, const BRegion* src, int32 num) const
|
|
|
|
{
|
|
|
|
// TODO: optimize this, it should be smarter
|
|
|
|
while (num--) {
|
|
|
|
*dst = *src;
|
|
|
|
fDrawState->Transform(dst);
|
|
|
|
// NOTE: from here on, don't use the
|
|
|
|
// "*ForDrawing()" versions of the parent!
|
|
|
|
ConvertToScreen(dst);
|
|
|
|
src++;
|
|
|
|
dst++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
//! converts a point from screen to local coordinate system
|
|
|
|
void
|
|
|
|
ViewLayer::ConvertFromScreenForDrawing(BPoint* point) const
|
|
|
|
{
|
|
|
|
ConvertFromScreen(point);
|
|
|
|
fDrawState->InverseTransform(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|
|
|
{
|
|
|
|
if (x == 0 && y == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fFrame.OffsetBy(x, y);
|
|
|
|
|
|
|
|
// to move on screen, we must not be hidden and we must have a parent
|
|
|
|
if (fVisible && fParent && dirtyRegion) {
|
2006-02-09 15:42:08 +03:00
|
|
|
#if 1
|
2005-12-08 15:41:19 +03:00
|
|
|
// based on redraw on new location
|
|
|
|
// the place were we are now visible
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect newVisibleBounds(Bounds());
|
2005-12-08 15:41:19 +03:00
|
|
|
// we can use the frame of the old
|
|
|
|
// local clipping to see which parts need invalidation
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect oldVisibleBounds(newVisibleBounds);
|
2005-12-08 15:41:19 +03:00
|
|
|
oldVisibleBounds.OffsetBy(-x, -y);
|
|
|
|
ConvertToScreen(&oldVisibleBounds);
|
|
|
|
|
|
|
|
ConvertToVisibleInTopView(&newVisibleBounds);
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
dirtyRegion->Include((clipping_rect)oldVisibleBounds);
|
2005-12-08 15:41:19 +03:00
|
|
|
// newVisibleBounds already is in screen coords
|
2006-11-29 06:20:07 +03:00
|
|
|
dirtyRegion->Include((clipping_rect)newVisibleBounds);
|
2005-12-08 15:41:19 +03:00
|
|
|
#else
|
|
|
|
// blitting version, invalidates
|
|
|
|
// old contents
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect oldVisibleBounds(Bounds());
|
|
|
|
IntRect newVisibleBounds(oldVisibleBounds);
|
2005-12-08 15:41:19 +03:00
|
|
|
oldVisibleBounds.OffsetBy(-x, -y);
|
|
|
|
ConvertToScreen(&oldVisibleBounds);
|
|
|
|
|
|
|
|
// NOTE: using ConvertToVisibleInTopView()
|
|
|
|
// instead of ConvertToScreen()! see below
|
|
|
|
ConvertToVisibleInTopView(&newVisibleBounds);
|
|
|
|
|
|
|
|
newVisibleBounds.OffsetBy(-x, -y);
|
|
|
|
|
|
|
|
// clipping oldVisibleBounds to newVisibleBounds
|
|
|
|
// makes sure we don't copy parts hidden under
|
|
|
|
// parent views
|
2006-04-07 23:14:25 +04:00
|
|
|
BRegion* region = fWindow->GetRegion();
|
|
|
|
if (region) {
|
|
|
|
region->Set(oldVisibleBounds & newVisibleBounds);
|
|
|
|
fWindow->CopyContents(region, x, y);
|
|
|
|
|
|
|
|
region->Set(oldVisibleBounds);
|
|
|
|
newVisibleBounds.OffsetBy(x, y);
|
2006-11-29 06:20:07 +03:00
|
|
|
region->Exclude((clipping_rect)newVisibleBounds);
|
2006-04-07 23:14:25 +04:00
|
|
|
dirtyRegion->Include(dirty);
|
|
|
|
|
|
|
|
fWindow->RecycleRegion(region);
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fParent) {
|
|
|
|
// the top view's screen clipping does not change,
|
|
|
|
// because no parts are clipped away from parent
|
|
|
|
// views
|
|
|
|
_MoveScreenClipping(x, y, true);
|
|
|
|
} else {
|
|
|
|
// parts might have been revealed from underneath
|
|
|
|
// the parent, or might now be hidden underneath
|
|
|
|
// the parent, this is taken care of when building
|
|
|
|
// the screen clipping
|
2006-11-29 06:20:07 +03:00
|
|
|
InvalidateScreenClipping();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|
|
|
{
|
|
|
|
if (x == 0 && y == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fFrame.right += x;
|
|
|
|
fFrame.bottom += y;
|
|
|
|
|
|
|
|
if (fVisible && dirtyRegion) {
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect oldBounds(Bounds());
|
2005-12-08 15:41:19 +03:00
|
|
|
oldBounds.right -= x;
|
|
|
|
oldBounds.bottom -= y;
|
|
|
|
|
2006-04-07 23:14:25 +04:00
|
|
|
BRegion* dirty = fWindow->GetRegion();
|
|
|
|
if (!dirty)
|
|
|
|
return;
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Set((clipping_rect)Bounds());
|
|
|
|
dirty->Include((clipping_rect)oldBounds);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
if (!(fFlags & B_FULL_UPDATE_ON_RESIZE)) {
|
|
|
|
// the dirty region is just the difference of
|
|
|
|
// old and new bounds
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Exclude((clipping_rect)(oldBounds & Bounds()));
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
InvalidateScreenClipping();
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2006-04-07 23:14:25 +04:00
|
|
|
if (dirty->CountRects() > 0) {
|
2005-12-08 15:41:19 +03:00
|
|
|
// exclude children, they are expected to
|
|
|
|
// include their own dirty regions in ParentResized()
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
|
|
|
if (child->IsVisible()) {
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect previousChildVisible(child->Frame() & oldBounds & Bounds());
|
2006-04-07 23:14:25 +04:00
|
|
|
if (dirty->Frame().Intersects(previousChildVisible)) {
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Exclude((clipping_rect)previousChildVisible);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-07 23:14:25 +04:00
|
|
|
ConvertToScreen(dirty);
|
|
|
|
dirtyRegion->Include(dirty);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
2006-04-07 23:14:25 +04:00
|
|
|
fWindow->RecycleRegion(dirty);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// layout the children
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
|
|
|
|
child->ParentResized(x, y, dirtyRegion);
|
|
|
|
|
2006-04-23 18:28:48 +04:00
|
|
|
// view bitmap
|
|
|
|
|
|
|
|
resize_frame(fBitmapDestination, fBitmapResizingMode, x, y);
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// at this point, children are at their new locations,
|
|
|
|
// so we can rebuild the clipping
|
|
|
|
// TODO: when the implementation of Hide() and Show() is
|
|
|
|
// complete, see if this should be avoided
|
|
|
|
RebuildClipping(false);
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ParentResized(int32 x, int32 y, BRegion* dirtyRegion)
|
|
|
|
{
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect newFrame = fFrame;
|
2006-04-23 18:28:48 +04:00
|
|
|
resize_frame(newFrame, fResizeMode & 0x0000ffff, x, y);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
if (newFrame != fFrame) {
|
|
|
|
// careful, MoveBy will change fFrame
|
|
|
|
int32 widthDiff = (int32)(newFrame.Width() - fFrame.Width());
|
|
|
|
int32 heightDiff = (int32)(newFrame.Height() - fFrame.Height());
|
|
|
|
|
|
|
|
MoveBy(newFrame.left - fFrame.left,
|
|
|
|
newFrame.top - fFrame.top, dirtyRegion);
|
|
|
|
|
|
|
|
ResizeBy(widthDiff, heightDiff, dirtyRegion);
|
2007-01-04 15:28:31 +03:00
|
|
|
} else {
|
|
|
|
// TODO: this covers the fact that our screen clipping might change
|
|
|
|
// when the parent changes its size, even though our frame stays
|
|
|
|
// the same - there might be a way to test for this, but axeld doesn't
|
|
|
|
// know, stippi should look into this when he's back :)
|
|
|
|
InvalidateScreenClipping();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|
|
|
{
|
2007-04-19 23:36:36 +04:00
|
|
|
if (!fVisible || !fWindow) {
|
|
|
|
fScrollingOffset.x += x;
|
|
|
|
fScrollingOffset.y += y;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// blitting version, invalidates
|
|
|
|
// old contents
|
|
|
|
|
|
|
|
// remember old bounds for tracking dirty region
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect oldBounds(Bounds());
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
// NOTE: using ConvertToVisibleInTopView()
|
|
|
|
// instead of ConvertToScreen(), this makes
|
|
|
|
// sure we don't try to move or invalidate an
|
|
|
|
// area hidden underneath the parent view
|
|
|
|
ConvertToVisibleInTopView(&oldBounds);
|
2006-11-29 12:27:23 +03:00
|
|
|
|
|
|
|
// find the area of the view that can be scrolled,
|
|
|
|
// contents are shifted in the opposite direction from scrolling
|
|
|
|
IntRect stillVisibleBounds(oldBounds);
|
|
|
|
stillVisibleBounds.OffsetBy(x, y);
|
|
|
|
stillVisibleBounds = stillVisibleBounds & oldBounds;
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
fScrollingOffset.x += x;
|
|
|
|
fScrollingOffset.y += y;
|
|
|
|
|
|
|
|
// do the blit, this will make sure
|
|
|
|
// that other more complex dirty regions
|
|
|
|
// are taken care of
|
2006-04-19 18:12:57 +04:00
|
|
|
BRegion* copyRegion = fWindow->GetRegion();
|
|
|
|
if (!copyRegion)
|
|
|
|
return;
|
2006-11-29 06:20:07 +03:00
|
|
|
copyRegion->Set((clipping_rect)stillVisibleBounds);
|
2006-04-19 18:12:57 +04:00
|
|
|
fWindow->CopyContents(copyRegion, -x, -y);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
// find the dirty region as far as we are
|
|
|
|
// concerned
|
2006-04-19 18:12:57 +04:00
|
|
|
BRegion* dirty = copyRegion;
|
|
|
|
// reuse copyRegion and call it dirty
|
2006-04-07 23:14:25 +04:00
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Set((clipping_rect)oldBounds);
|
2005-12-08 15:41:19 +03:00
|
|
|
stillVisibleBounds.OffsetBy(-x, -y);
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Exclude((clipping_rect)stillVisibleBounds);
|
2006-04-07 23:14:25 +04:00
|
|
|
dirtyRegion->Include(dirty);
|
|
|
|
|
|
|
|
fWindow->RecycleRegion(dirty);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
// the screen clipping of this view and it's
|
|
|
|
// childs is no longer valid
|
2006-11-29 06:20:07 +03:00
|
|
|
InvalidateScreenClipping();
|
2005-12-08 15:41:19 +03:00
|
|
|
RebuildClipping(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-11-29 06:20:07 +03:00
|
|
|
ViewLayer::CopyBits(IntRect src, IntRect dst, BRegion& windowContentClipping)
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
|
|
|
if (!fVisible || !fWindow)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// TODO: confirm that in R5 this call is affected by origin and scale
|
|
|
|
|
|
|
|
// blitting version
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
int32 xOffset = dst.left - src.left;
|
|
|
|
int32 yOffset = dst.top - src.top;
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
// figure out which part can be blittet
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect visibleSrc(src);
|
2005-12-08 15:41:19 +03:00
|
|
|
ConvertToVisibleInTopView(&visibleSrc);
|
|
|
|
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect visibleSrcAtDest(src);
|
2005-12-08 15:41:19 +03:00
|
|
|
visibleSrcAtDest.OffsetBy(xOffset, yOffset);
|
|
|
|
ConvertToVisibleInTopView(&visibleSrcAtDest);
|
|
|
|
|
|
|
|
// clip src to visible at dest
|
|
|
|
visibleSrcAtDest.OffsetBy(-xOffset, -yOffset);
|
|
|
|
visibleSrc = visibleSrc & visibleSrcAtDest;
|
|
|
|
|
|
|
|
// do the blit, this will make sure
|
|
|
|
// that other more complex dirty regions
|
|
|
|
// are taken care of
|
2006-04-19 18:12:57 +04:00
|
|
|
BRegion* copyRegion = fWindow->GetRegion();
|
|
|
|
if (!copyRegion)
|
|
|
|
return;
|
|
|
|
|
2006-04-29 22:19:54 +04:00
|
|
|
// move src rect to destination here for efficiency reasons
|
|
|
|
visibleSrc.OffsetBy(xOffset, yOffset);
|
|
|
|
|
|
|
|
// we need to interstect the copyRegion too times, onces
|
|
|
|
// at the source and once at the destination (here done
|
|
|
|
// the other way arround but it doesn't matter)
|
|
|
|
// the reason for this is that we are not supposed to visually
|
|
|
|
// copy children in the source rect and neither to copy onto
|
|
|
|
// children in the destination rect...
|
2006-11-29 06:20:07 +03:00
|
|
|
copyRegion->Set((clipping_rect)visibleSrc);
|
2006-04-19 18:12:57 +04:00
|
|
|
copyRegion->IntersectWith(&ScreenClipping(&windowContentClipping));
|
2006-04-29 22:19:54 +04:00
|
|
|
// note that fScreenClipping is used directly from hereon
|
|
|
|
// because it is now up to date
|
|
|
|
|
|
|
|
copyRegion->OffsetBy(-xOffset, -yOffset);
|
|
|
|
copyRegion->IntersectWith(&fScreenClipping);
|
|
|
|
|
|
|
|
// do the actual blit
|
2006-04-19 18:12:57 +04:00
|
|
|
fWindow->CopyContents(copyRegion, xOffset, yOffset);
|
2005-12-08 15:41:19 +03:00
|
|
|
|
|
|
|
// find the dirty region as far as we are concerned
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect dirtyDst(dst);
|
2005-12-08 15:41:19 +03:00
|
|
|
ConvertToVisibleInTopView(&dirtyDst);
|
|
|
|
|
2006-04-29 22:19:54 +04:00
|
|
|
BRegion* dirty = fWindow->GetRegion();
|
|
|
|
if (!dirty) {
|
|
|
|
fWindow->RecycleRegion(copyRegion);
|
|
|
|
return;
|
|
|
|
}
|
2006-04-07 23:14:25 +04:00
|
|
|
|
2006-04-29 22:19:54 +04:00
|
|
|
// offset copyRegion to destination again
|
|
|
|
copyRegion->OffsetBy(xOffset, yOffset);
|
|
|
|
// start with destination given by user
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Set((clipping_rect)dirtyDst);
|
2005-12-08 15:41:19 +03:00
|
|
|
// exclude the part that we could copy
|
2006-04-29 22:19:54 +04:00
|
|
|
dirty->Exclude(copyRegion);
|
|
|
|
|
|
|
|
dirty->IntersectWith(&fScreenClipping);
|
2006-04-07 23:14:25 +04:00
|
|
|
fWindow->MarkContentDirty(*dirty);
|
|
|
|
|
|
|
|
fWindow->RecycleRegion(dirty);
|
2006-04-29 22:19:54 +04:00
|
|
|
fWindow->RecycleRegion(copyRegion);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::PushState()
|
|
|
|
{
|
|
|
|
fDrawState = fDrawState->PushState();
|
|
|
|
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::PopState()
|
|
|
|
{
|
|
|
|
if (fDrawState->PreviousState() == NULL) {
|
|
|
|
fprintf(stderr, "WARNING: User called BView(%s)::PopState(), "
|
|
|
|
"but there is NO state on stack!\n", Name());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool rebuildClipping = fDrawState->ClippingRegion() != NULL;
|
|
|
|
|
|
|
|
fDrawState = fDrawState->PopState();
|
|
|
|
fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
|
|
|
|
|
|
|
|
// rebuild clipping
|
|
|
|
// (the clipping from the popped state is not effective anymore)
|
|
|
|
if (rebuildClipping)
|
|
|
|
RebuildClipping(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::SetEventMask(uint32 eventMask, uint32 options)
|
|
|
|
{
|
|
|
|
fEventMask = eventMask;
|
|
|
|
fEventOptions = options;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-02 23:19:29 +03:00
|
|
|
void
|
|
|
|
ViewLayer::SetCursor(ServerCursor *cursor)
|
|
|
|
{
|
2006-02-26 21:15:31 +03:00
|
|
|
if (cursor != fCursor) {
|
|
|
|
if (fCursor)
|
|
|
|
fCursor->Release();
|
|
|
|
|
|
|
|
fCursor = cursor;
|
|
|
|
|
|
|
|
if (fCursor) {
|
|
|
|
fCursor->Acquire();
|
|
|
|
fCursor->SetPendingViewCursor(false);
|
|
|
|
}
|
|
|
|
}
|
2006-02-02 23:19:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-01-03 13:30:08 +03:00
|
|
|
void
|
|
|
|
ViewLayer::SetPicture(ServerPicture *picture)
|
|
|
|
{
|
|
|
|
fPicture = picture;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ServerPicture *
|
|
|
|
ViewLayer::Picture() const
|
|
|
|
{
|
|
|
|
return fPicture;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
|
|
|
|
BRegion* windowContentClipping, bool deep)
|
|
|
|
{
|
2006-02-13 16:43:30 +03:00
|
|
|
if (!fVisible) {
|
|
|
|
// child views cannot be visible either
|
2006-01-03 13:19:20 +03:00
|
|
|
return;
|
2006-02-13 16:43:30 +03:00
|
|
|
}
|
2006-01-03 13:19:20 +03:00
|
|
|
|
2007-08-17 16:56:20 +04:00
|
|
|
if (fViewBitmap != NULL || fViewColor != B_TRANSPARENT_COLOR) {
|
2005-12-29 22:30:48 +03:00
|
|
|
// we can only draw within our own area
|
2006-04-19 18:12:57 +04:00
|
|
|
BRegion* redraw = fWindow->GetRegion(ScreenClipping(windowContentClipping));
|
|
|
|
if (!redraw)
|
|
|
|
return;
|
2005-12-29 22:30:48 +03:00
|
|
|
// add the current clipping
|
2006-04-19 18:12:57 +04:00
|
|
|
redraw->IntersectWith(effectiveClipping);
|
2006-02-13 16:43:30 +03:00
|
|
|
|
2006-04-23 19:45:35 +04:00
|
|
|
Overlay* overlayCookie = _Overlay();
|
2006-04-22 20:41:12 +04:00
|
|
|
|
|
|
|
if (fViewBitmap != NULL && overlayCookie == NULL) {
|
2005-12-29 22:30:48 +03:00
|
|
|
// draw view bitmap
|
|
|
|
// TODO: support other options!
|
|
|
|
BRect rect = fBitmapDestination;
|
|
|
|
ConvertToScreenForDrawing(&rect);
|
2006-02-13 16:43:30 +03:00
|
|
|
|
2006-04-19 18:12:57 +04:00
|
|
|
align_rect_to_pixels(&rect);
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2005-12-29 22:30:48 +03:00
|
|
|
// lock the drawing engine for as long as we need the clipping
|
|
|
|
// to be valid
|
2006-04-19 18:12:57 +04:00
|
|
|
if (rect.IsValid()/* && drawingEngine->Lock()*/) {
|
|
|
|
drawingEngine->ConstrainClippingRegion(redraw);
|
2005-12-29 22:30:48 +03:00
|
|
|
|
2006-04-19 18:12:57 +04:00
|
|
|
if (fBitmapOptions & B_TILE_BITMAP) {
|
|
|
|
// tile across entire view
|
2006-04-22 20:41:12 +04:00
|
|
|
|
2006-04-19 18:12:57 +04:00
|
|
|
float start = rect.left;
|
|
|
|
while (rect.top < redraw->Frame().bottom) {
|
|
|
|
while (rect.left < redraw->Frame().right) {
|
* completed my changes to DrawState handling, the current DrawingState
of the active ViewLayer is now always mirrored in the Painter instance
of a ServerWindow, so that it doesn't need to be synced on every drawing
command, this was previously incomplete for font handling
* removed the DrawState parameter from all the DrawingEngine functions
* adjusted ServerWindow and ServerPicture accordingly
* made sure that string related functions used by non-drawing related
parts (ServerApp, Decorator) don't interfere with the current drawing
state
* moved AS_SYNC handling from _DispatchViewMessage to _DispatchMessage,
it is actually a window message and doesn't require fCurrentLayer to
be valid
* fixed bug #1300, fCurrentLayer was not updated when a ViewLayer was
deleted by client request which happened to be fCurrentLayer (I am now
handling it so that the parent becomes the current layer, could be
wrong)
* AGGTextRenderer is no longer using it's own scanline, which should save
a few bytes RAM, the Painter already had such an object
* StringWidth() in AGGTextRenderer is now taking the escapement_delta into
account
* Painter::StrokeLine() doesn't need to check the clipping as much, since
that is already done in DrawingEngine
* if a ServerWindow message is not handled because fCurrentLayer is NULL,
a reply is sent in case the messages needs it (client window could
freeze otherwise, waiting for the reply for ever)
* removed unused AS_SET_FONT and AS_SET_FONT_SIZE
* added automatic RGBColor -> rgb_color conversion to RGBColor.h
* minor cleanup for 80 char/line limit
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21685 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-22 23:48:27 +04:00
|
|
|
drawingEngine->DrawBitmap(fViewBitmap,
|
|
|
|
fBitmapSource, rect);
|
2006-04-19 18:12:57 +04:00
|
|
|
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
|
2006-04-22 20:41:12 +04:00
|
|
|
|
2006-04-19 18:12:57 +04:00
|
|
|
while (rect.left < redraw->Frame().right) {
|
|
|
|
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
|
* completed my changes to DrawState handling, the current DrawingState
of the active ViewLayer is now always mirrored in the Painter instance
of a ServerWindow, so that it doesn't need to be synced on every drawing
command, this was previously incomplete for font handling
* removed the DrawState parameter from all the DrawingEngine functions
* adjusted ServerWindow and ServerPicture accordingly
* made sure that string related functions used by non-drawing related
parts (ServerApp, Decorator) don't interfere with the current drawing
state
* moved AS_SYNC handling from _DispatchViewMessage to _DispatchMessage,
it is actually a window message and doesn't require fCurrentLayer to
be valid
* fixed bug #1300, fCurrentLayer was not updated when a ViewLayer was
deleted by client request which happened to be fCurrentLayer (I am now
handling it so that the parent becomes the current layer, could be
wrong)
* AGGTextRenderer is no longer using it's own scanline, which should save
a few bytes RAM, the Painter already had such an object
* StringWidth() in AGGTextRenderer is now taking the escapement_delta into
account
* Painter::StrokeLine() doesn't need to check the clipping as much, since
that is already done in DrawingEngine
* if a ServerWindow message is not handled because fCurrentLayer is NULL,
a reply is sent in case the messages needs it (client window could
freeze otherwise, waiting for the reply for ever)
* removed unused AS_SET_FONT and AS_SET_FONT_SIZE
* added automatic RGBColor -> rgb_color conversion to RGBColor.h
* minor cleanup for 80 char/line limit
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21685 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-22 23:48:27 +04:00
|
|
|
rect);
|
2006-04-19 18:12:57 +04:00
|
|
|
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
|
2006-04-22 20:41:12 +04:00
|
|
|
|
2006-04-19 18:12:57 +04:00
|
|
|
while (rect.top < redraw->Frame().bottom) {
|
|
|
|
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
|
* completed my changes to DrawState handling, the current DrawingState
of the active ViewLayer is now always mirrored in the Painter instance
of a ServerWindow, so that it doesn't need to be synced on every drawing
command, this was previously incomplete for font handling
* removed the DrawState parameter from all the DrawingEngine functions
* adjusted ServerWindow and ServerPicture accordingly
* made sure that string related functions used by non-drawing related
parts (ServerApp, Decorator) don't interfere with the current drawing
state
* moved AS_SYNC handling from _DispatchViewMessage to _DispatchMessage,
it is actually a window message and doesn't require fCurrentLayer to
be valid
* fixed bug #1300, fCurrentLayer was not updated when a ViewLayer was
deleted by client request which happened to be fCurrentLayer (I am now
handling it so that the parent becomes the current layer, could be
wrong)
* AGGTextRenderer is no longer using it's own scanline, which should save
a few bytes RAM, the Painter already had such an object
* StringWidth() in AGGTextRenderer is now taking the escapement_delta into
account
* Painter::StrokeLine() doesn't need to check the clipping as much, since
that is already done in DrawingEngine
* if a ServerWindow message is not handled because fCurrentLayer is NULL,
a reply is sent in case the messages needs it (client window could
freeze otherwise, waiting for the reply for ever)
* removed unused AS_SET_FONT and AS_SET_FONT_SIZE
* added automatic RGBColor -> rgb_color conversion to RGBColor.h
* minor cleanup for 80 char/line limit
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21685 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-22 23:48:27 +04:00
|
|
|
rect);
|
2006-04-19 18:12:57 +04:00
|
|
|
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
|
2006-04-22 20:41:12 +04:00
|
|
|
|
2006-04-19 18:12:57 +04:00
|
|
|
drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
|
* completed my changes to DrawState handling, the current DrawingState
of the active ViewLayer is now always mirrored in the Painter instance
of a ServerWindow, so that it doesn't need to be synced on every drawing
command, this was previously incomplete for font handling
* removed the DrawState parameter from all the DrawingEngine functions
* adjusted ServerWindow and ServerPicture accordingly
* made sure that string related functions used by non-drawing related
parts (ServerApp, Decorator) don't interfere with the current drawing
state
* moved AS_SYNC handling from _DispatchViewMessage to _DispatchMessage,
it is actually a window message and doesn't require fCurrentLayer to
be valid
* fixed bug #1300, fCurrentLayer was not updated when a ViewLayer was
deleted by client request which happened to be fCurrentLayer (I am now
handling it so that the parent becomes the current layer, could be
wrong)
* AGGTextRenderer is no longer using it's own scanline, which should save
a few bytes RAM, the Painter already had such an object
* StringWidth() in AGGTextRenderer is now taking the escapement_delta into
account
* Painter::StrokeLine() doesn't need to check the clipping as much, since
that is already done in DrawingEngine
* if a ServerWindow message is not handled because fCurrentLayer is NULL,
a reply is sent in case the messages needs it (client window could
freeze otherwise, waiting for the reply for ever)
* removed unused AS_SET_FONT and AS_SET_FONT_SIZE
* added automatic RGBColor -> rgb_color conversion to RGBColor.h
* minor cleanup for 80 char/line limit
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21685 a95241bf-73f2-0310-859d-f6bbb57e9c96
2007-07-22 23:48:27 +04:00
|
|
|
rect);
|
2006-04-19 18:12:57 +04:00
|
|
|
redraw->Exclude(rect);
|
|
|
|
}
|
|
|
|
|
2005-12-29 22:30:48 +03:00
|
|
|
// NOTE: It is ok not to reset the clipping, that
|
|
|
|
// would only waste time
|
2006-04-19 18:12:57 +04:00
|
|
|
// drawingEngine->Unlock();
|
2005-12-29 22:30:48 +03:00
|
|
|
}
|
2006-02-13 16:43:30 +03:00
|
|
|
|
2005-12-29 22:30:48 +03:00
|
|
|
}
|
2006-02-13 16:43:30 +03:00
|
|
|
|
2007-08-17 16:56:20 +04:00
|
|
|
if (fViewColor != B_TRANSPARENT_COLOR) {
|
2005-12-29 22:30:48 +03:00
|
|
|
// fill visible region with view color,
|
|
|
|
// this version of FillRegion ignores any
|
|
|
|
// clipping, that's why "redraw" needs to
|
|
|
|
// be correct
|
2007-10-25 22:20:03 +04:00
|
|
|
// see #634
|
|
|
|
// if (redraw->Frame().left < 0 || redraw->Frame().top < 0) {
|
|
|
|
// char message[1024];
|
|
|
|
// BRect c = effectiveClipping->Frame();
|
|
|
|
// BRect w = windowContentClipping->Frame();
|
|
|
|
// BRect r = redraw->Frame();
|
|
|
|
// sprintf(message, "invalid background: current clipping: (%d, %d)->(%d, %d), "
|
|
|
|
// "window content: (%d, %d)->(%d, %d), redraw: (%d, %d)->(%d, %d)",
|
|
|
|
// (int)c.left, (int)c.top, (int)c.right, (int)c.bottom,
|
|
|
|
// (int)w.left, (int)w.top, (int)w.right, (int)w.bottom,
|
|
|
|
// (int)r.left, (int)r.top, (int)r.right, (int)r.bottom);
|
|
|
|
// debugger(message);
|
|
|
|
// }
|
|
|
|
|
2006-04-23 18:28:48 +04:00
|
|
|
drawingEngine->FillRegion(*redraw, overlayCookie != NULL
|
|
|
|
? overlayCookie->Color() : fViewColor);
|
2005-12-29 22:30:48 +03:00
|
|
|
}
|
2006-04-19 18:12:57 +04:00
|
|
|
|
|
|
|
fWindow->RecycleRegion(redraw);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
2005-12-21 01:31:42 +03:00
|
|
|
fBackgroundDirty = false;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// let children draw
|
|
|
|
if (deep) {
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
|
|
|
child->Draw(drawingEngine, effectiveClipping,
|
|
|
|
windowContentClipping, deep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-02 18:09:11 +04:00
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2006-03-14 01:05:49 +03:00
|
|
|
void
|
|
|
|
ViewLayer::MouseDown(BMessage* message, BPoint where)
|
|
|
|
{
|
2006-05-22 14:05:17 +04:00
|
|
|
// empty hook method
|
2006-03-14 01:05:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::MouseUp(BMessage* message, BPoint where)
|
|
|
|
{
|
2006-05-22 14:05:17 +04:00
|
|
|
// empty hook method
|
2006-03-14 01:05:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::MouseMoved(BMessage* message, BPoint where)
|
|
|
|
{
|
2006-05-22 14:05:17 +04:00
|
|
|
// empty hook method
|
2006-03-14 01:05:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ViewLayer::SetHidden(bool hidden)
|
|
|
|
{
|
|
|
|
if (fHidden != hidden) {
|
|
|
|
fHidden = hidden;
|
|
|
|
|
|
|
|
// recurse into children and update their visible flag
|
2006-05-22 14:05:17 +04:00
|
|
|
bool oldVisible = fVisible;
|
|
|
|
UpdateVisibleDeep(fParent ? fParent->IsVisible() : !fHidden);
|
|
|
|
if (oldVisible != fVisible) {
|
|
|
|
// Include or exclude us from the parent area, and update the
|
|
|
|
// children's clipping as well when the view will be visible
|
|
|
|
if (fParent)
|
|
|
|
fParent->RebuildClipping(fVisible);
|
|
|
|
else
|
|
|
|
RebuildClipping(fVisible);
|
|
|
|
|
|
|
|
if (fWindow) {
|
|
|
|
// trigger a redraw
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect clippedBounds = Bounds();
|
2006-05-22 14:05:17 +04:00
|
|
|
ConvertToVisibleInTopView(&clippedBounds);
|
|
|
|
BRegion* dirty = fWindow->GetRegion();
|
|
|
|
if (!dirty)
|
|
|
|
return;
|
2006-11-29 06:20:07 +03:00
|
|
|
dirty->Set((clipping_rect)clippedBounds);
|
2006-05-22 14:05:17 +04:00
|
|
|
fWindow->MarkContentDirty(*dirty);
|
|
|
|
fWindow->RecycleRegion(dirty);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
bool
|
|
|
|
ViewLayer::IsHidden() const
|
|
|
|
{
|
|
|
|
return fHidden;
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::UpdateVisibleDeep(bool parentVisible)
|
|
|
|
{
|
2006-05-19 12:42:46 +04:00
|
|
|
bool wasVisible = fVisible;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fVisible = parentVisible && !fHidden;
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
|
|
|
|
child->UpdateVisibleDeep(fVisible);
|
2006-04-23 18:28:48 +04:00
|
|
|
|
|
|
|
// overlay handling
|
|
|
|
|
2006-04-23 19:45:35 +04:00
|
|
|
Overlay* overlay = _Overlay();
|
2006-04-23 18:28:48 +04:00
|
|
|
if (overlay == NULL)
|
|
|
|
return;
|
|
|
|
|
2006-05-19 12:42:46 +04:00
|
|
|
if (fVisible && !wasVisible)
|
2006-05-17 16:46:56 +04:00
|
|
|
_UpdateOverlayView();
|
2006-05-19 12:42:46 +04:00
|
|
|
else if (!fVisible && wasVisible)
|
2006-04-23 18:28:48 +04:00
|
|
|
overlay->Hide();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
|
|
|
|
|
2005-12-21 01:31:42 +03:00
|
|
|
void
|
|
|
|
ViewLayer::MarkBackgroundDirty()
|
|
|
|
{
|
2006-11-29 06:20:07 +03:00
|
|
|
if (fBackgroundDirty)
|
|
|
|
return;
|
2005-12-21 01:31:42 +03:00
|
|
|
fBackgroundDirty = true;
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
|
|
|
|
child->MarkBackgroundDirty();
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
ServerFont:
* fixed weird pointer conversion in SetStyle()
* fixed a potential mix up in operator=() in case the
other ServerFont has fStyle == NULL
ServerWindow:
* the WindowLayer fTopLayer cannot be deleted by
client request, just for safety reasons
* the link is flushed if there is no drawing engine,
but this case is theoretical only
* deleting the ServerWindow object syncs with the
client, so that when BBitmaps are deleted, they
can be sure there are no pending messages (which
would be executed in a nother thread)
* there is no timeout anymore when sending messages
to the client, which made absolutely no sense
AGGTextRenderer:
* renamed fFontManager to fFontCache, because that's
what it really is
* fLastFamilyAndStyle defaulted to the system plain
font and therefor that font was never loaded when
the font never changed meanwhile
DrawingMode:
* I'm not quite sure but I think there was the
potential of a division by zero, at least I
had crashes with "divide error"
HWInterface:
* fix update when the cursor shape changed in
double buffered mode
ViewLayer:
* since the top layer is never really deleted
before its time has come, it is not necessary
to set it to NULL in the ViewLayer destructor
ViewLayer/WindowLayer:
* added a function to collect the view tokens
that are affected by an update session
EventDispatcher:
* use the importance of the message for the timeout
in _SendMessage()
* drop mouse moved events in the server if we're
lagging behind more than 5 ms (Axel, maybe review)
View:
* there were some problems with the locking
of the BWindow looper in RemoveSelf(), since
this is called from the window destructor,
also of BWindows from BBitmaps, which have
never been run (this might need review), at
least I seem to have solved the crashing
problems introduced by actually deleting the
view hirarchy in the BWindow destructor
* fixed _Draw() for being used non-recursively,
temporarily disabled DrawAfterChildren, which
didn't work yet anyways (because views cannot
draw over children in the server yet)
Window:
* small cleanup when deleting shortcuts
* sync with the server when having send
AS_DELETE_WINDOW (see ServerWindow above)
* fixed locking in Begin/EndViewTransaction()
* removed folding of _UPDATE_ messages, since
there is only one ever in the queue
* set the fInTransaction flag during an update,
I plan to use this in BView later to
flush the link when drawing outside of an
update
* BView::_Draw() is now called by view token,
this gives the next leap forward in speed,
the overhead because of drawing clean views
was considerable
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15878 a95241bf-73f2-0310-859d-f6bbb57e9c96
2006-01-09 01:04:52 +03:00
|
|
|
void
|
|
|
|
ViewLayer::AddTokensForLayersInRegion(BMessage* message,
|
|
|
|
BRegion& region,
|
|
|
|
BRegion* windowContentClipping)
|
|
|
|
{
|
2006-02-06 22:31:02 +03:00
|
|
|
if (!fVisible)
|
|
|
|
return;
|
|
|
|
|
ServerFont:
* fixed weird pointer conversion in SetStyle()
* fixed a potential mix up in operator=() in case the
other ServerFont has fStyle == NULL
ServerWindow:
* the WindowLayer fTopLayer cannot be deleted by
client request, just for safety reasons
* the link is flushed if there is no drawing engine,
but this case is theoretical only
* deleting the ServerWindow object syncs with the
client, so that when BBitmaps are deleted, they
can be sure there are no pending messages (which
would be executed in a nother thread)
* there is no timeout anymore when sending messages
to the client, which made absolutely no sense
AGGTextRenderer:
* renamed fFontManager to fFontCache, because that's
what it really is
* fLastFamilyAndStyle defaulted to the system plain
font and therefor that font was never loaded when
the font never changed meanwhile
DrawingMode:
* I'm not quite sure but I think there was the
potential of a division by zero, at least I
had crashes with "divide error"
HWInterface:
* fix update when the cursor shape changed in
double buffered mode
ViewLayer:
* since the top layer is never really deleted
before its time has come, it is not necessary
to set it to NULL in the ViewLayer destructor
ViewLayer/WindowLayer:
* added a function to collect the view tokens
that are affected by an update session
EventDispatcher:
* use the importance of the message for the timeout
in _SendMessage()
* drop mouse moved events in the server if we're
lagging behind more than 5 ms (Axel, maybe review)
View:
* there were some problems with the locking
of the BWindow looper in RemoveSelf(), since
this is called from the window destructor,
also of BWindows from BBitmaps, which have
never been run (this might need review), at
least I seem to have solved the crashing
problems introduced by actually deleting the
view hirarchy in the BWindow destructor
* fixed _Draw() for being used non-recursively,
temporarily disabled DrawAfterChildren, which
didn't work yet anyways (because views cannot
draw over children in the server yet)
Window:
* small cleanup when deleting shortcuts
* sync with the server when having send
AS_DELETE_WINDOW (see ServerWindow above)
* fixed locking in Begin/EndViewTransaction()
* removed folding of _UPDATE_ messages, since
there is only one ever in the queue
* set the fInTransaction flag during an update,
I plan to use this in BView later to
flush the link when drawing outside of an
update
* BView::_Draw() is now called by view token,
this gives the next leap forward in speed,
the overhead because of drawing clean views
was considerable
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15878 a95241bf-73f2-0310-859d-f6bbb57e9c96
2006-01-09 01:04:52 +03:00
|
|
|
if (region.Intersects(ScreenClipping(windowContentClipping).Frame()))
|
|
|
|
message->AddInt32("_token", fToken);
|
|
|
|
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
|
|
|
|
child->AddTokensForLayersInRegion(message, region,
|
|
|
|
windowContentClipping);
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2006-02-06 13:28:30 +03:00
|
|
|
void
|
|
|
|
ViewLayer::AddTokensForLayersInRegion(BPrivate::PortLink& link,
|
|
|
|
BRegion& region,
|
|
|
|
BRegion* windowContentClipping)
|
|
|
|
{
|
2006-02-06 22:31:02 +03:00
|
|
|
if (!fVisible)
|
|
|
|
return;
|
|
|
|
|
2006-12-05 01:25:17 +03:00
|
|
|
IntRect screenBounds(Bounds());
|
|
|
|
ConvertToScreen(&screenBounds);
|
|
|
|
if (!region.Intersects((clipping_rect)screenBounds))
|
|
|
|
return;
|
|
|
|
|
2007-04-19 23:36:36 +04:00
|
|
|
if (region.Intersects(ScreenClipping(windowContentClipping).Frame()))
|
|
|
|
link.Attach<int32>(fToken);
|
2006-02-06 13:28:30 +03:00
|
|
|
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling())
|
|
|
|
child->AddTokensForLayersInRegion(link, region,
|
|
|
|
windowContentClipping);
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::PrintToStream() const
|
|
|
|
{
|
|
|
|
printf("ViewLayer: %s\n", Name());
|
|
|
|
printf(" fToken: %ld\n", fToken);
|
2006-11-29 06:20:07 +03:00
|
|
|
printf(" fFrame: IntRect(%ld, %ld, %ld, %ld)\n", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
|
|
|
|
printf(" fScrollingOffset: IntPoint(%ld, %ld)\n", fScrollingOffset.x, fScrollingOffset.y);
|
2005-12-08 15:41:19 +03:00
|
|
|
printf(" fHidden: %d\n", fHidden);
|
|
|
|
printf(" fVisible: %d\n", fVisible);
|
|
|
|
printf(" fWindow: %p\n", fWindow);
|
|
|
|
printf(" fParent: %p\n", fParent);
|
|
|
|
printf(" fLocalClipping:\n");
|
|
|
|
fLocalClipping.PrintToStream();
|
|
|
|
printf(" fScreenClipping:\n");
|
|
|
|
fScreenClipping.PrintToStream();
|
|
|
|
printf(" valid: %d\n", fScreenClippingValid);
|
|
|
|
printf(" state:\n");
|
|
|
|
printf(" user clipping: %p\n", fDrawState->ClippingRegion());
|
|
|
|
printf(" origin: BPoint(%.1f, %.1f)\n", fDrawState->Origin().x, fDrawState->Origin().y);
|
|
|
|
printf(" scale: %.2f\n", fDrawState->Scale());
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::RebuildClipping(bool deep)
|
|
|
|
{
|
|
|
|
// the clipping spans over the bounds area
|
2006-11-29 06:20:07 +03:00
|
|
|
fLocalClipping.Set((clipping_rect)Bounds());
|
2005-12-08 15:41:19 +03:00
|
|
|
|
2007-07-18 16:59:05 +04:00
|
|
|
if (ViewLayer* child = FirstChild()) {
|
|
|
|
BRegion* childrenRegion = fWindow->GetRegion();
|
|
|
|
if (!childrenRegion)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// exclude all children from the clipping
|
|
|
|
for (; child; child = child->NextSibling()) {
|
|
|
|
if (child->IsVisible())
|
|
|
|
childrenRegion->Include((clipping_rect)child->Frame());
|
|
|
|
|
|
|
|
if (deep)
|
|
|
|
child->RebuildClipping(deep);
|
|
|
|
}
|
|
|
|
|
|
|
|
fLocalClipping.Exclude(childrenRegion);
|
|
|
|
fWindow->RecycleRegion(childrenRegion);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// add the user clipping in case there is one
|
|
|
|
if (const BRegion* userClipping = fDrawState->ClippingRegion()) {
|
|
|
|
// NOTE: in case the user sets a user defined clipping region,
|
|
|
|
// rebuilding the clipping is a bit more expensive because there
|
|
|
|
// is no separate "drawing region"... on the other
|
|
|
|
// hand, views for which this feature is actually used will
|
|
|
|
// probably not have any children, so it is not that expensive
|
|
|
|
// after all
|
2006-04-19 18:12:57 +04:00
|
|
|
BRegion* screenUserClipping = fWindow->GetRegion(*userClipping);
|
|
|
|
if (!screenUserClipping)
|
|
|
|
return;
|
|
|
|
fDrawState->Transform(screenUserClipping);
|
|
|
|
fLocalClipping.IntersectWith(screenUserClipping);
|
|
|
|
fWindow->RecycleRegion(screenUserClipping);
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fScreenClippingValid = false;
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
BRegion&
|
|
|
|
ViewLayer::ScreenClipping(BRegion* windowContentClipping, bool force) const
|
|
|
|
{
|
|
|
|
if (!fScreenClippingValid || force) {
|
|
|
|
fScreenClipping = fLocalClipping;
|
|
|
|
ConvertToScreen(&fScreenClipping);
|
|
|
|
|
|
|
|
// see if we parts of our bounds are hidden underneath
|
|
|
|
// the parent, the local clipping does not account for this
|
2006-11-29 06:20:07 +03:00
|
|
|
IntRect clippedBounds = Bounds();
|
2005-12-08 15:41:19 +03:00
|
|
|
ConvertToVisibleInTopView(&clippedBounds);
|
|
|
|
if (clippedBounds.Width() < fScreenClipping.Frame().Width() ||
|
|
|
|
clippedBounds.Height() < fScreenClipping.Frame().Height()) {
|
2006-04-19 18:12:57 +04:00
|
|
|
BRegion* temp = fWindow->GetRegion();
|
|
|
|
if (temp) {
|
2006-11-29 06:20:07 +03:00
|
|
|
temp->Set((clipping_rect)clippedBounds);
|
2006-04-19 18:12:57 +04:00
|
|
|
fScreenClipping.IntersectWith(temp);
|
|
|
|
fWindow->RecycleRegion(temp);
|
|
|
|
}
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fScreenClipping.IntersectWith(windowContentClipping);
|
|
|
|
fScreenClippingValid = true;
|
|
|
|
}
|
|
|
|
//printf("###ViewLayer(%s)::ScreenClipping():\n", Name());
|
|
|
|
//fScreenClipping.PrintToStream();
|
|
|
|
return fScreenClipping;
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
2006-11-29 06:20:07 +03:00
|
|
|
ViewLayer::InvalidateScreenClipping()
|
2005-12-08 15:41:19 +03:00
|
|
|
{
|
2006-11-29 06:20:07 +03:00
|
|
|
if (!fScreenClippingValid)
|
|
|
|
return;
|
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
fScreenClippingValid = false;
|
2006-11-29 06:20:07 +03:00
|
|
|
// invalidate the childrens screen clipping as well
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
|
|
|
child->InvalidateScreenClipping();
|
2005-12-08 15:41:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-22 14:05:17 +04:00
|
|
|
|
2005-12-08 15:41:19 +03:00
|
|
|
void
|
|
|
|
ViewLayer::_MoveScreenClipping(int32 x, int32 y, bool deep)
|
|
|
|
{
|
|
|
|
if (fScreenClippingValid)
|
|
|
|
fScreenClipping.OffsetBy(x, y);
|
|
|
|
|
|
|
|
if (deep) {
|
|
|
|
// move the childrens screen clipping as well
|
|
|
|
for (ViewLayer* child = FirstChild(); child; child = child->NextSibling()) {
|
|
|
|
child->_MoveScreenClipping(x, y, deep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|