xref: /haiku/src/servers/app/View.cpp (revision 7f9368cae5ff96137d32a60ed2e86795421f8222)
1953d895eSAxel Dörfler /*
2551438b9SJulian Harnath  * Copyright (c) 2001-2015, Haiku, Inc.
3953d895eSAxel Dörfler  * Distributed under the terms of the MIT license.
4953d895eSAxel Dörfler  *
5953d895eSAxel Dörfler  * Authors:
6953d895eSAxel Dörfler  *		DarkWyrm <bpmagic@columbus.rr.com>
7953d895eSAxel Dörfler  *		Adi Oanca <adioanca@gmail.com>
8953d895eSAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
9953d895eSAxel Dörfler  *		Stephan Aßmus <superstippi@gmx.de>
10953d895eSAxel Dörfler  *		Marcus Overhagen <marcus@overhagen.de>
11e1a30115SAdrien Destugues  *		Adrien Destugues <pulkomandy@pulkomandy.tk
12551438b9SJulian Harnath  *		Julian Harnath <julian.harnath@rwth-aachen.de>
13*7f9368caSlooncraz  *		Joseph Groover <looncraz@looncraz.net>
14953d895eSAxel Dörfler  */
15953d895eSAxel Dörfler #include "View.h"
16953d895eSAxel Dörfler 
17bd06a41cSClemens Zeidler #include <new>
18bd06a41cSClemens Zeidler #include <stdio.h>
19bd06a41cSClemens Zeidler 
20f08d5477SAdrien Destugues #include "AlphaMask.h"
21953d895eSAxel Dörfler #include "Desktop.h"
22953d895eSAxel Dörfler #include "DrawingEngine.h"
23bd06a41cSClemens Zeidler #include "DrawState.h"
24551438b9SJulian Harnath #include "Layer.h"
25953d895eSAxel Dörfler #include "Overlay.h"
26953d895eSAxel Dörfler #include "ServerApp.h"
27953d895eSAxel Dörfler #include "ServerBitmap.h"
28953d895eSAxel Dörfler #include "ServerCursor.h"
29953d895eSAxel Dörfler #include "ServerPicture.h"
30953d895eSAxel Dörfler #include "ServerWindow.h"
31953d895eSAxel Dörfler #include "Window.h"
32953d895eSAxel Dörfler 
33551438b9SJulian Harnath #include "BitmapHWInterface.h"
34953d895eSAxel Dörfler #include "drawing_support.h"
35953d895eSAxel Dörfler 
36953d895eSAxel Dörfler #include <List.h>
37953d895eSAxel Dörfler #include <Message.h>
38953d895eSAxel Dörfler #include <PortLink.h>
39953d895eSAxel Dörfler #include <View.h> // for resize modes
40953d895eSAxel Dörfler #include <WindowPrivate.h>
41953d895eSAxel Dörfler 
42991547efSStephan Aßmus #include <GradientLinear.h>
43991547efSStephan Aßmus #include <GradientRadial.h>
44991547efSStephan Aßmus #include <GradientRadialFocus.h>
45991547efSStephan Aßmus #include <GradientDiamond.h>
46991547efSStephan Aßmus #include <GradientConic.h>
47991547efSStephan Aßmus 
48953d895eSAxel Dörfler 
49953d895eSAxel Dörfler using std::nothrow;
50953d895eSAxel Dörfler 
51953d895eSAxel Dörfler 
52953d895eSAxel Dörfler void
53953d895eSAxel Dörfler resize_frame(IntRect& frame, uint32 resizingMode, int32 x, int32 y)
54953d895eSAxel Dörfler {
55953d895eSAxel Dörfler 	// follow with left side
56953d895eSAxel Dörfler 	if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8)
57953d895eSAxel Dörfler 		frame.left += x;
58953d895eSAxel Dörfler 	else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8)
59953d895eSAxel Dörfler 		frame.left += x / 2;
60953d895eSAxel Dörfler 
61953d895eSAxel Dörfler 	// follow with right side
62953d895eSAxel Dörfler 	if ((resizingMode & 0x000FU) == _VIEW_RIGHT_)
63953d895eSAxel Dörfler 		frame.right += x;
64953d895eSAxel Dörfler 	else if ((resizingMode & 0x000FU) == _VIEW_CENTER_)
65953d895eSAxel Dörfler 		frame.right += x / 2;
66953d895eSAxel Dörfler 
67953d895eSAxel Dörfler 	// follow with top side
68953d895eSAxel Dörfler 	if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12)
69953d895eSAxel Dörfler 		frame.top += y;
70953d895eSAxel Dörfler 	else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12)
71953d895eSAxel Dörfler 		frame.top += y / 2;
72953d895eSAxel Dörfler 
73953d895eSAxel Dörfler 	// follow with bottom side
74953d895eSAxel Dörfler 	if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4)
75953d895eSAxel Dörfler 		frame.bottom += y;
76953d895eSAxel Dörfler 	else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4)
77953d895eSAxel Dörfler 		frame.bottom += y / 2;
78953d895eSAxel Dörfler }
79953d895eSAxel Dörfler 
80953d895eSAxel Dörfler 
81953d895eSAxel Dörfler //	#pragma mark -
82953d895eSAxel Dörfler 
83953d895eSAxel Dörfler 
84953d895eSAxel Dörfler View::View(IntRect frame, IntPoint scrollingOffset, const char* name,
85953d895eSAxel Dörfler 		int32 token, uint32 resizeMode, uint32 flags)
86953d895eSAxel Dörfler 	:
87953d895eSAxel Dörfler 	fName(name),
88953d895eSAxel Dörfler 	fToken(token),
89953d895eSAxel Dörfler 
90953d895eSAxel Dörfler 	fFrame(frame),
91953d895eSAxel Dörfler 	fScrollingOffset(scrollingOffset),
92953d895eSAxel Dörfler 
93953d895eSAxel Dörfler 	fViewColor((rgb_color){ 255, 255, 255, 255 }),
94*7f9368caSlooncraz 	fWhichViewColor(B_NO_COLOR),
95*7f9368caSlooncraz 	fWhichViewColorTint(B_NO_TINT),
96953d895eSAxel Dörfler 	fViewBitmap(NULL),
9795e95feeSMichael Lotz 	fBitmapResizingMode(0),
9895e95feeSMichael Lotz 	fBitmapOptions(0),
99953d895eSAxel Dörfler 
100953d895eSAxel Dörfler 	fResizeMode(resizeMode),
101953d895eSAxel Dörfler 	fFlags(flags),
102953d895eSAxel Dörfler 
103437b1927SAxel Dörfler 	// Views start visible by default
104953d895eSAxel Dörfler 	fHidden(false),
105953d895eSAxel Dörfler 	fVisible(true),
106953d895eSAxel Dörfler 	fBackgroundDirty(true),
107953d895eSAxel Dörfler 	fIsDesktopBackground(false),
108953d895eSAxel Dörfler 
109953d895eSAxel Dörfler 	fEventMask(0),
110953d895eSAxel Dörfler 	fEventOptions(0),
111953d895eSAxel Dörfler 
112953d895eSAxel Dörfler 	fWindow(NULL),
113953d895eSAxel Dörfler 	fParent(NULL),
114953d895eSAxel Dörfler 
115953d895eSAxel Dörfler 	fFirstChild(NULL),
116953d895eSAxel Dörfler 	fPreviousSibling(NULL),
117953d895eSAxel Dörfler 	fNextSibling(NULL),
118953d895eSAxel Dörfler 	fLastChild(NULL),
119953d895eSAxel Dörfler 
120953d895eSAxel Dörfler 	fCursor(NULL),
121953d895eSAxel Dörfler 	fPicture(NULL),
122953d895eSAxel Dörfler 
123953d895eSAxel Dörfler 	fLocalClipping((BRect)Bounds()),
124953d895eSAxel Dörfler 	fScreenClipping(),
125f0c3c996SMichael Lotz 	fScreenClippingValid(false),
126f0c3c996SMichael Lotz 	fUserClipping(NULL),
127f0c3c996SMichael Lotz 	fScreenAndUserClipping(NULL)
128953d895eSAxel Dörfler {
129953d895eSAxel Dörfler 	if (fDrawState)
130953d895eSAxel Dörfler 		fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
131953d895eSAxel Dörfler }
132953d895eSAxel Dörfler 
133953d895eSAxel Dörfler 
134953d895eSAxel Dörfler View::~View()
135953d895eSAxel Dörfler {
136953d895eSAxel Dörfler 	if (fViewBitmap != NULL)
1374b0459b2SAxel Dörfler 		fViewBitmap->ReleaseReference();
138953d895eSAxel Dörfler 
139ea2bcbf4SMichael Lotz 	delete fScreenAndUserClipping;
140ea2bcbf4SMichael Lotz 	delete fUserClipping;
141953d895eSAxel Dörfler 	delete fDrawState;
142953d895eSAxel Dörfler 
143437b1927SAxel Dörfler //	if (fWindow && this == fWindow->TopView())
144437b1927SAxel Dörfler //		fWindow->SetTopView(NULL);
145953d895eSAxel Dörfler 
146953d895eSAxel Dörfler 	if (fCursor)
1474b0459b2SAxel Dörfler 		fCursor->ReleaseReference();
148953d895eSAxel Dörfler 
149953d895eSAxel Dörfler 	// iterate over children and delete each one
150437b1927SAxel Dörfler 	View* view = fFirstChild;
151437b1927SAxel Dörfler 	while (view) {
152437b1927SAxel Dörfler 		View* toast = view;
153437b1927SAxel Dörfler 		view = view->fNextSibling;
154953d895eSAxel Dörfler 		delete toast;
155953d895eSAxel Dörfler 	}
156953d895eSAxel Dörfler }
157953d895eSAxel Dörfler 
158953d895eSAxel Dörfler 
159953d895eSAxel Dörfler IntRect
160953d895eSAxel Dörfler View::Bounds() const
161953d895eSAxel Dörfler {
162953d895eSAxel Dörfler 	IntRect bounds(fScrollingOffset.x, fScrollingOffset.y,
163953d895eSAxel Dörfler 		fScrollingOffset.x + fFrame.Width(),
164953d895eSAxel Dörfler 		fScrollingOffset.y + fFrame.Height());
165953d895eSAxel Dörfler 	return bounds;
166953d895eSAxel Dörfler }
167953d895eSAxel Dörfler 
168953d895eSAxel Dörfler 
169953d895eSAxel Dörfler void
170953d895eSAxel Dörfler View::ConvertToVisibleInTopView(IntRect* bounds) const
171953d895eSAxel Dörfler {
172953d895eSAxel Dörfler 	*bounds = *bounds & Bounds();
173953d895eSAxel Dörfler 	// NOTE: this step is necessary even if we don't have a parent!
1746f2a446eSJulian Harnath 	bounds->OffsetBy(fFrame.left - fScrollingOffset.x,
1756f2a446eSJulian Harnath 		fFrame.top - fScrollingOffset.y);
176953d895eSAxel Dörfler 
177953d895eSAxel Dörfler 	if (fParent)
178953d895eSAxel Dörfler 		fParent->ConvertToVisibleInTopView(bounds);
179953d895eSAxel Dörfler }
180953d895eSAxel Dörfler 
181953d895eSAxel Dörfler 
182953d895eSAxel Dörfler void
183953d895eSAxel Dörfler View::AttachedToWindow(::Window* window)
184953d895eSAxel Dörfler {
185953d895eSAxel Dörfler 	fWindow = window;
186953d895eSAxel Dörfler 
187953d895eSAxel Dörfler 	// an ugly hack to detect the desktop background
188437b1927SAxel Dörfler 	if (window->Feel() == kDesktopWindowFeel && Parent() == TopView())
189953d895eSAxel Dörfler 		fIsDesktopBackground = true;
190953d895eSAxel Dörfler 
191953d895eSAxel Dörfler 	// insert view into local token space
192953d895eSAxel Dörfler 	if (fWindow != NULL) {
193953d895eSAxel Dörfler 		fWindow->ServerWindow()->App()->ViewTokens().SetToken(fToken,
194953d895eSAxel Dörfler 			B_HANDLER_TOKEN, this);
195953d895eSAxel Dörfler 	}
196953d895eSAxel Dörfler 
197953d895eSAxel Dörfler 	// attach child views as well
198953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
199953d895eSAxel Dörfler 		child->AttachedToWindow(window);
200953d895eSAxel Dörfler }
201953d895eSAxel Dörfler 
202953d895eSAxel Dörfler 
203953d895eSAxel Dörfler void
204953d895eSAxel Dörfler View::DetachedFromWindow()
205953d895eSAxel Dörfler {
206953d895eSAxel Dörfler 	// remove view from local token space
207edb62548SMichael Lotz 	if (fWindow != NULL && fWindow->ServerWindow()->App() != NULL)
208953d895eSAxel Dörfler 		fWindow->ServerWindow()->App()->ViewTokens().RemoveToken(fToken);
209953d895eSAxel Dörfler 
210953d895eSAxel Dörfler 	fWindow = NULL;
211953d895eSAxel Dörfler 	// detach child views as well
212953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
213953d895eSAxel Dörfler 		child->DetachedFromWindow();
214953d895eSAxel Dörfler }
215953d895eSAxel Dörfler 
216953d895eSAxel Dörfler 
217953d895eSAxel Dörfler // #pragma mark -
218953d895eSAxel Dörfler 
219953d895eSAxel Dörfler 
220e1a30115SAdrien Destugues DrawingEngine*
221e1a30115SAdrien Destugues View::GetDrawingEngine() const
222e1a30115SAdrien Destugues {
223e1a30115SAdrien Destugues 	return Window()->GetDrawingEngine();
224e1a30115SAdrien Destugues }
225e1a30115SAdrien Destugues 
226e1a30115SAdrien Destugues 
227e1a30115SAdrien Destugues ServerPicture*
228e1a30115SAdrien Destugues View::GetPicture(int32 token) const
229e1a30115SAdrien Destugues {
230e1a30115SAdrien Destugues 	return Window()->ServerWindow()->App()->GetPicture(token);
231e1a30115SAdrien Destugues }
232e1a30115SAdrien Destugues 
233e1a30115SAdrien Destugues 
234e1a30115SAdrien Destugues void
235e1a30115SAdrien Destugues View::ResyncDrawState()
236e1a30115SAdrien Destugues {
237e1a30115SAdrien Destugues 	return Window()->ServerWindow()->ResyncDrawState();
238e1a30115SAdrien Destugues }
239e1a30115SAdrien Destugues 
240e1a30115SAdrien Destugues 
241e1a30115SAdrien Destugues void
242e1a30115SAdrien Destugues View::UpdateCurrentDrawingRegion()
243e1a30115SAdrien Destugues {
244e1a30115SAdrien Destugues 	return Window()->ServerWindow()->UpdateCurrentDrawingRegion();
245e1a30115SAdrien Destugues }
246e1a30115SAdrien Destugues 
247e1a30115SAdrien Destugues 
248953d895eSAxel Dörfler void
249437b1927SAxel Dörfler View::AddChild(View* view)
250953d895eSAxel Dörfler {
251437b1927SAxel Dörfler 	if (view->fParent) {
252953d895eSAxel Dörfler 		printf("View::AddChild() - View already has a parent\n");
253953d895eSAxel Dörfler 		return;
254953d895eSAxel Dörfler 	}
255953d895eSAxel Dörfler 
256437b1927SAxel Dörfler 	view->fParent = this;
257953d895eSAxel Dörfler 
258953d895eSAxel Dörfler 	if (!fLastChild) {
259953d895eSAxel Dörfler 		// no children yet
260437b1927SAxel Dörfler 		fFirstChild = view;
261953d895eSAxel Dörfler 	} else {
262437b1927SAxel Dörfler 		// append view to formerly last child
263437b1927SAxel Dörfler 		fLastChild->fNextSibling = view;
264437b1927SAxel Dörfler 		view->fPreviousSibling = fLastChild;
265953d895eSAxel Dörfler 	}
266437b1927SAxel Dörfler 	fLastChild = view;
267953d895eSAxel Dörfler 
268437b1927SAxel Dörfler 	view->UpdateVisibleDeep(fVisible);
269953d895eSAxel Dörfler 
270437b1927SAxel Dörfler 	if (view->IsVisible())
271953d895eSAxel Dörfler 		RebuildClipping(false);
272953d895eSAxel Dörfler 
273953d895eSAxel Dörfler 	if (fWindow) {
274437b1927SAxel Dörfler 		view->AttachedToWindow(fWindow);
275953d895eSAxel Dörfler 
276437b1927SAxel Dörfler 		if (view->IsVisible()) {
277953d895eSAxel Dörfler 			// trigger redraw
278437b1927SAxel Dörfler 			IntRect clippedFrame = view->Frame();
279953d895eSAxel Dörfler 			ConvertToVisibleInTopView(&clippedFrame);
280953d895eSAxel Dörfler 			BRegion* dirty = fWindow->GetRegion();
281953d895eSAxel Dörfler 			if (dirty) {
282953d895eSAxel Dörfler 				dirty->Set((clipping_rect)clippedFrame);
283953d895eSAxel Dörfler 				fWindow->MarkContentDirtyAsync(*dirty);
284953d895eSAxel Dörfler 				fWindow->RecycleRegion(dirty);
285953d895eSAxel Dörfler 			}
286953d895eSAxel Dörfler 		}
287953d895eSAxel Dörfler 	}
288953d895eSAxel Dörfler }
289953d895eSAxel Dörfler 
290953d895eSAxel Dörfler 
291953d895eSAxel Dörfler bool
292437b1927SAxel Dörfler View::RemoveChild(View* view)
293953d895eSAxel Dörfler {
2943e8d3c5fSMichael Lotz 	if (view == NULL || view->fParent != this) {
295953d895eSAxel Dörfler 		printf("View::RemoveChild(%p - %s) - View is not child of "
296437b1927SAxel Dörfler 			"this (%p) view!\n", view, view ? view->Name() : NULL, this);
297953d895eSAxel Dörfler 		return false;
298953d895eSAxel Dörfler 	}
299953d895eSAxel Dörfler 
300437b1927SAxel Dörfler 	view->fParent = NULL;
301953d895eSAxel Dörfler 
302437b1927SAxel Dörfler 	if (fLastChild == view)
303437b1927SAxel Dörfler 		fLastChild = view->fPreviousSibling;
304437b1927SAxel Dörfler 		// view->fNextSibling would be NULL
305953d895eSAxel Dörfler 
306437b1927SAxel Dörfler 	if (fFirstChild == view )
307437b1927SAxel Dörfler 		fFirstChild = view->fNextSibling;
308437b1927SAxel Dörfler 		// view->fPreviousSibling would be NULL
309953d895eSAxel Dörfler 
310437b1927SAxel Dörfler 	// connect child before and after view
311437b1927SAxel Dörfler 	if (view->fPreviousSibling)
312437b1927SAxel Dörfler 		view->fPreviousSibling->fNextSibling = view->fNextSibling;
313953d895eSAxel Dörfler 
314437b1927SAxel Dörfler 	if (view->fNextSibling)
315437b1927SAxel Dörfler 		view->fNextSibling->fPreviousSibling = view->fPreviousSibling;
316953d895eSAxel Dörfler 
317437b1927SAxel Dörfler 	// view has no siblings anymore
318437b1927SAxel Dörfler 	view->fPreviousSibling = NULL;
319437b1927SAxel Dörfler 	view->fNextSibling = NULL;
320953d895eSAxel Dörfler 
321437b1927SAxel Dörfler 	if (view->IsVisible()) {
322437b1927SAxel Dörfler 		Overlay* overlay = view->_Overlay();
323953d895eSAxel Dörfler 		if (overlay != NULL)
324953d895eSAxel Dörfler 			overlay->Hide();
325953d895eSAxel Dörfler 
326953d895eSAxel Dörfler 		RebuildClipping(false);
327953d895eSAxel Dörfler 	}
328953d895eSAxel Dörfler 
329953d895eSAxel Dörfler 	if (fWindow) {
330437b1927SAxel Dörfler 		view->DetachedFromWindow();
331953d895eSAxel Dörfler 
332437b1927SAxel Dörfler 		if (fVisible && view->IsVisible()) {
333953d895eSAxel Dörfler 			// trigger redraw
334437b1927SAxel Dörfler 			IntRect clippedFrame = view->Frame();
335953d895eSAxel Dörfler 			ConvertToVisibleInTopView(&clippedFrame);
336953d895eSAxel Dörfler 			BRegion* dirty = fWindow->GetRegion();
337953d895eSAxel Dörfler 			if (dirty) {
338953d895eSAxel Dörfler 				dirty->Set((clipping_rect)clippedFrame);
339953d895eSAxel Dörfler 				fWindow->MarkContentDirtyAsync(*dirty);
340953d895eSAxel Dörfler 				fWindow->RecycleRegion(dirty);
341953d895eSAxel Dörfler 			}
342953d895eSAxel Dörfler 		}
343953d895eSAxel Dörfler 	}
344953d895eSAxel Dörfler 
345953d895eSAxel Dörfler 	return true;
346953d895eSAxel Dörfler }
347953d895eSAxel Dörfler 
348953d895eSAxel Dörfler 
349953d895eSAxel Dörfler View*
350437b1927SAxel Dörfler View::TopView()
351953d895eSAxel Dörfler {
352953d895eSAxel Dörfler 	// returns the top level view of the hirarchy,
353953d895eSAxel Dörfler 	// it doesn't have to be the top level of a window
354953d895eSAxel Dörfler 
355953d895eSAxel Dörfler 	if (fParent)
356437b1927SAxel Dörfler 		return fParent->TopView();
357953d895eSAxel Dörfler 
358953d895eSAxel Dörfler 	return this;
359953d895eSAxel Dörfler }
360953d895eSAxel Dörfler 
361953d895eSAxel Dörfler 
362953d895eSAxel Dörfler uint32
363953d895eSAxel Dörfler View::CountChildren(bool deep) const
364953d895eSAxel Dörfler {
365953d895eSAxel Dörfler 	uint32 count = 0;
366953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
367953d895eSAxel Dörfler 		count++;
368953d895eSAxel Dörfler 		if (deep) {
369953d895eSAxel Dörfler 			count += child->CountChildren(deep);
370953d895eSAxel Dörfler 		}
371953d895eSAxel Dörfler 	}
372953d895eSAxel Dörfler 	return count;
373953d895eSAxel Dörfler }
374953d895eSAxel Dörfler 
375953d895eSAxel Dörfler 
376953d895eSAxel Dörfler void
377953d895eSAxel Dörfler View::CollectTokensForChildren(BList* tokenMap) const
378953d895eSAxel Dörfler {
379953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
380953d895eSAxel Dörfler 		tokenMap->AddItem((void*)child);
381953d895eSAxel Dörfler 		child->CollectTokensForChildren(tokenMap);
382953d895eSAxel Dörfler 	}
383953d895eSAxel Dörfler }
384953d895eSAxel Dörfler 
385953d895eSAxel Dörfler 
386953d895eSAxel Dörfler #if 0
387953d895eSAxel Dörfler bool
388953d895eSAxel Dörfler View::MarkAt(DrawingEngine* engine, const BPoint& where, int32 level)
389953d895eSAxel Dörfler {
390953d895eSAxel Dörfler 	BRect rect(fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
391953d895eSAxel Dörfler 
392953d895eSAxel Dörfler 	if (Parent() != NULL) {
393953d895eSAxel Dörfler 		Parent()->ConvertToScreen(&rect);
394953d895eSAxel Dörfler 		if (!rect.Contains(where))
395953d895eSAxel Dörfler 			return false;
396953d895eSAxel Dörfler 
397953d895eSAxel Dörfler 		engine->StrokeRect(rect, (rgb_color){level * 30, level * 30, level * 30});
398953d895eSAxel Dörfler 	}
399953d895eSAxel Dörfler 
400953d895eSAxel Dörfler 
401953d895eSAxel Dörfler 	bool found = false;
402953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
403953d895eSAxel Dörfler 		found |= child->MarkAt(engine, where, level + 1);
404953d895eSAxel Dörfler 	}
405953d895eSAxel Dörfler 
406953d895eSAxel Dörfler 	if (!found) {
407953d895eSAxel Dörfler 		rgb_color color = {0};
408953d895eSAxel Dörfler 		switch (level % 2) {
409953d895eSAxel Dörfler 			case 0: color.green = rand() % 256; break;
410953d895eSAxel Dörfler 			case 1: color.blue = rand() % 256; break;
411953d895eSAxel Dörfler 		}
412953d895eSAxel Dörfler 
413953d895eSAxel Dörfler 		rect.InsetBy(1, 1);
414953d895eSAxel Dörfler 		//engine->FillRegion(fLocalClipping, (rgb_color){255, 255, 0, 10});
415953d895eSAxel Dörfler 		engine->StrokeRect(rect, color);
416953d895eSAxel Dörfler 		rect.InsetBy(1, 1);
417953d895eSAxel Dörfler 		engine->StrokeRect(rect, color);
418953d895eSAxel Dörfler 	}
419953d895eSAxel Dörfler 
420953d895eSAxel Dörfler 	return true;
421953d895eSAxel Dörfler }
422953d895eSAxel Dörfler #endif
423953d895eSAxel Dörfler 
424953d895eSAxel Dörfler 
425953d895eSAxel Dörfler void
426953d895eSAxel Dörfler View::FindViews(uint32 flags, BObjectList<View>& list, int32& left)
427953d895eSAxel Dörfler {
428953d895eSAxel Dörfler 	if ((Flags() & flags) == flags) {
429953d895eSAxel Dörfler 		list.AddItem(this);
430953d895eSAxel Dörfler 		left--;
431953d895eSAxel Dörfler 		return;
432953d895eSAxel Dörfler 	}
433953d895eSAxel Dörfler 
434953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
435953d895eSAxel Dörfler 		child->FindViews(flags, list, left);
436953d895eSAxel Dörfler 		if (left == 0)
437953d895eSAxel Dörfler 			break;
438953d895eSAxel Dörfler 	}
439953d895eSAxel Dörfler }
440953d895eSAxel Dörfler 
441953d895eSAxel Dörfler 
442*7f9368caSlooncraz bool
443*7f9368caSlooncraz View::HasView(View* view)
444*7f9368caSlooncraz {
445*7f9368caSlooncraz 	if (view == this)
446*7f9368caSlooncraz 		return true;
447*7f9368caSlooncraz 
448*7f9368caSlooncraz 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
449*7f9368caSlooncraz 		if (child->HasView(view))
450*7f9368caSlooncraz 			return true;
451*7f9368caSlooncraz 	}
452*7f9368caSlooncraz 
453*7f9368caSlooncraz 	return false;
454*7f9368caSlooncraz }
455*7f9368caSlooncraz 
456*7f9368caSlooncraz 
457953d895eSAxel Dörfler View*
458953d895eSAxel Dörfler View::ViewAt(const BPoint& where)
459953d895eSAxel Dörfler {
460953d895eSAxel Dörfler 	if (!fVisible)
461953d895eSAxel Dörfler 		return NULL;
462953d895eSAxel Dörfler 
463953d895eSAxel Dörfler 	IntRect frame = Frame();
464953d895eSAxel Dörfler 	if (Parent() != NULL)
4656f2a446eSJulian Harnath 		Parent()->LocalToScreenTransform().Apply(&frame);
466953d895eSAxel Dörfler 
467953d895eSAxel Dörfler 	if (!frame.Contains(where))
468953d895eSAxel Dörfler 		return NULL;
469953d895eSAxel Dörfler 
470953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
471437b1927SAxel Dörfler 		View* view = child->ViewAt(where);
472437b1927SAxel Dörfler 		if (view != NULL)
473437b1927SAxel Dörfler 			return view;
474953d895eSAxel Dörfler 	}
475953d895eSAxel Dörfler 
476953d895eSAxel Dörfler 	return this;
477953d895eSAxel Dörfler }
478953d895eSAxel Dörfler 
479953d895eSAxel Dörfler 
480953d895eSAxel Dörfler // #pragma mark -
481953d895eSAxel Dörfler 
482953d895eSAxel Dörfler 
483953d895eSAxel Dörfler void
484953d895eSAxel Dörfler View::SetName(const char* string)
485953d895eSAxel Dörfler {
486953d895eSAxel Dörfler 	fName.SetTo(string);
487953d895eSAxel Dörfler }
488953d895eSAxel Dörfler 
489953d895eSAxel Dörfler 
490953d895eSAxel Dörfler void
491953d895eSAxel Dörfler View::SetFlags(uint32 flags)
492953d895eSAxel Dörfler {
493953d895eSAxel Dörfler 	fFlags = flags;
494953d895eSAxel Dörfler 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
495953d895eSAxel Dörfler }
496953d895eSAxel Dörfler 
497953d895eSAxel Dörfler 
498953d895eSAxel Dörfler void
499953d895eSAxel Dörfler View::SetViewBitmap(ServerBitmap* bitmap, IntRect sourceRect,
500953d895eSAxel Dörfler 	IntRect destRect, int32 resizingMode, int32 options)
501953d895eSAxel Dörfler {
502953d895eSAxel Dörfler 	if (fViewBitmap != NULL) {
503953d895eSAxel Dörfler 		Overlay* overlay = _Overlay();
504953d895eSAxel Dörfler 
505953d895eSAxel Dörfler 		if (bitmap != NULL) {
506953d895eSAxel Dörfler 			// take over overlay token from current overlay (if it has any)
507953d895eSAxel Dörfler 			Overlay* newOverlay = bitmap->Overlay();
508953d895eSAxel Dörfler 
509953d895eSAxel Dörfler 			if (overlay != NULL && newOverlay != NULL)
510953d895eSAxel Dörfler 				newOverlay->TakeOverToken(overlay);
511953d895eSAxel Dörfler 		} else if (overlay != NULL)
512953d895eSAxel Dörfler 			overlay->Hide();
513953d895eSAxel Dörfler 
5144b0459b2SAxel Dörfler 		fViewBitmap->ReleaseReference();
515953d895eSAxel Dörfler 	}
516953d895eSAxel Dörfler 
517953d895eSAxel Dörfler 	// the caller is allowed to delete the bitmap after setting the background
518953d895eSAxel Dörfler 	if (bitmap != NULL)
5194b0459b2SAxel Dörfler 		bitmap->AcquireReference();
520953d895eSAxel Dörfler 
521953d895eSAxel Dörfler 	fViewBitmap = bitmap;
522953d895eSAxel Dörfler 	fBitmapSource = sourceRect;
523953d895eSAxel Dörfler 	fBitmapDestination = destRect;
524953d895eSAxel Dörfler 	fBitmapResizingMode = resizingMode;
525953d895eSAxel Dörfler 	fBitmapOptions = options;
526953d895eSAxel Dörfler 
527953d895eSAxel Dörfler 	_UpdateOverlayView();
528953d895eSAxel Dörfler }
529953d895eSAxel Dörfler 
530953d895eSAxel Dörfler 
531953d895eSAxel Dörfler ::Overlay*
532953d895eSAxel Dörfler View::_Overlay() const
533953d895eSAxel Dörfler {
534953d895eSAxel Dörfler 	if (fViewBitmap == NULL)
535953d895eSAxel Dörfler 		return NULL;
536953d895eSAxel Dörfler 
537953d895eSAxel Dörfler 	return fViewBitmap->Overlay();
538953d895eSAxel Dörfler }
539953d895eSAxel Dörfler 
540953d895eSAxel Dörfler 
541953d895eSAxel Dörfler void
542953d895eSAxel Dörfler View::_UpdateOverlayView() const
543953d895eSAxel Dörfler {
544953d895eSAxel Dörfler 	Overlay* overlay = _Overlay();
545953d895eSAxel Dörfler 	if (overlay == NULL)
546953d895eSAxel Dörfler 		return;
547953d895eSAxel Dörfler 
548953d895eSAxel Dörfler 	IntRect destination = fBitmapDestination;
5496f2a446eSJulian Harnath 	LocalToScreenTransform().Apply(&destination);
550953d895eSAxel Dörfler 
551953d895eSAxel Dörfler 	overlay->Configure(fBitmapSource, destination);
552953d895eSAxel Dörfler }
553953d895eSAxel Dörfler 
554953d895eSAxel Dörfler 
555953d895eSAxel Dörfler /*!
556953d895eSAxel Dörfler 	This method is called whenever the window is resized or moved - would
557953d895eSAxel Dörfler 	be nice to have a better solution for this, though.
558953d895eSAxel Dörfler */
559953d895eSAxel Dörfler void
560953d895eSAxel Dörfler View::UpdateOverlay()
561953d895eSAxel Dörfler {
562953d895eSAxel Dörfler 	if (!IsVisible())
563953d895eSAxel Dörfler 		return;
564953d895eSAxel Dörfler 
565953d895eSAxel Dörfler 	if (_Overlay() != NULL) {
566953d895eSAxel Dörfler 		_UpdateOverlayView();
567953d895eSAxel Dörfler 	} else {
568953d895eSAxel Dörfler 		// recursively ask children of this view
569953d895eSAxel Dörfler 
570953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
571953d895eSAxel Dörfler 			child->UpdateOverlay();
572953d895eSAxel Dörfler 		}
573953d895eSAxel Dörfler 	}
574953d895eSAxel Dörfler }
575953d895eSAxel Dörfler 
576953d895eSAxel Dörfler 
577953d895eSAxel Dörfler // #pragma mark -
578953d895eSAxel Dörfler 
579953d895eSAxel Dörfler 
580953d895eSAxel Dörfler void
5816f2a446eSJulian Harnath View::_LocalToScreenTransform(SimpleTransform& transform) const
582953d895eSAxel Dörfler {
5836f2a446eSJulian Harnath 	const View* view = this;
5846f2a446eSJulian Harnath 	int32 offsetX = 0;
5856f2a446eSJulian Harnath 	int32 offsetY = 0;
5866f2a446eSJulian Harnath 	do {
5876f2a446eSJulian Harnath 		offsetX += view->fFrame.left - view->fScrollingOffset.x;
5886f2a446eSJulian Harnath 		offsetY += view->fFrame.top  - view->fScrollingOffset.y;
5896f2a446eSJulian Harnath 		view = view->fParent;
5906f2a446eSJulian Harnath 	} while (view != NULL);
5916f2a446eSJulian Harnath 
5926f2a446eSJulian Harnath 	transform.AddOffset(offsetX, offsetY);
593953d895eSAxel Dörfler }
594953d895eSAxel Dörfler 
595953d895eSAxel Dörfler 
596953d895eSAxel Dörfler void
5976f2a446eSJulian Harnath View::_ScreenToLocalTransform(SimpleTransform& transform) const
598953d895eSAxel Dörfler {
5996f2a446eSJulian Harnath 	const View* view = this;
6006f2a446eSJulian Harnath 	int32 offsetX = 0;
6016f2a446eSJulian Harnath 	int32 offsetY = 0;
6026f2a446eSJulian Harnath 	do {
6036f2a446eSJulian Harnath 		offsetX += view->fScrollingOffset.x - view->fFrame.left;
6046f2a446eSJulian Harnath 		offsetY += view->fScrollingOffset.y - view->fFrame.top;
6056f2a446eSJulian Harnath 		view = view->fParent;
6066f2a446eSJulian Harnath 	} while (view != NULL);
607953d895eSAxel Dörfler 
6086f2a446eSJulian Harnath 	transform.AddOffset(offsetX, offsetY);
609953d895eSAxel Dörfler }
610953d895eSAxel Dörfler 
611953d895eSAxel Dörfler 
612953d895eSAxel Dörfler // #pragma mark -
613953d895eSAxel Dörfler 
614953d895eSAxel Dörfler 
615953d895eSAxel Dörfler void
616953d895eSAxel Dörfler View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
617953d895eSAxel Dörfler {
618953d895eSAxel Dörfler 	if (x == 0 && y == 0)
619953d895eSAxel Dörfler 		return;
620953d895eSAxel Dörfler 
621953d895eSAxel Dörfler 	fFrame.OffsetBy(x, y);
622953d895eSAxel Dörfler 
623953d895eSAxel Dörfler 	// to move on screen, we must not be hidden and we must have a parent
624953d895eSAxel Dörfler 	if (fVisible && fParent && dirtyRegion) {
625953d895eSAxel Dörfler #if 1
626953d895eSAxel Dörfler // based on redraw on new location
627953d895eSAxel Dörfler 		// the place were we are now visible
628953d895eSAxel Dörfler 		IntRect newVisibleBounds(Bounds());
629953d895eSAxel Dörfler 		// we can use the frame of the old
630953d895eSAxel Dörfler 		// local clipping to see which parts need invalidation
631953d895eSAxel Dörfler 		IntRect oldVisibleBounds(newVisibleBounds);
632953d895eSAxel Dörfler 		oldVisibleBounds.OffsetBy(-x, -y);
6336f2a446eSJulian Harnath 		LocalToScreenTransform().Apply(&oldVisibleBounds);
634953d895eSAxel Dörfler 
635953d895eSAxel Dörfler 		ConvertToVisibleInTopView(&newVisibleBounds);
636953d895eSAxel Dörfler 
637953d895eSAxel Dörfler 		dirtyRegion->Include((clipping_rect)oldVisibleBounds);
638953d895eSAxel Dörfler 		// newVisibleBounds already is in screen coords
639953d895eSAxel Dörfler 		dirtyRegion->Include((clipping_rect)newVisibleBounds);
640953d895eSAxel Dörfler #else
641953d895eSAxel Dörfler // blitting version, invalidates
642953d895eSAxel Dörfler // old contents
643953d895eSAxel Dörfler 		IntRect oldVisibleBounds(Bounds());
644953d895eSAxel Dörfler 		IntRect newVisibleBounds(oldVisibleBounds);
645953d895eSAxel Dörfler 		oldVisibleBounds.OffsetBy(-x, -y);
6466f2a446eSJulian Harnath 		LocalToScreenTransform().Apply(&oldVisibleBounds);
647953d895eSAxel Dörfler 
648953d895eSAxel Dörfler 		// NOTE: using ConvertToVisibleInTopView()
649953d895eSAxel Dörfler 		// instead of ConvertToScreen()! see below
650953d895eSAxel Dörfler 		ConvertToVisibleInTopView(&newVisibleBounds);
651953d895eSAxel Dörfler 
652953d895eSAxel Dörfler 		newVisibleBounds.OffsetBy(-x, -y);
653953d895eSAxel Dörfler 
654953d895eSAxel Dörfler 		// clipping oldVisibleBounds to newVisibleBounds
655953d895eSAxel Dörfler 		// makes sure we don't copy parts hidden under
656953d895eSAxel Dörfler 		// parent views
657953d895eSAxel Dörfler 		BRegion* region = fWindow->GetRegion();
658953d895eSAxel Dörfler 		if (region) {
659953d895eSAxel Dörfler 			region->Set(oldVisibleBounds & newVisibleBounds);
660953d895eSAxel Dörfler 			fWindow->CopyContents(region, x, y);
661953d895eSAxel Dörfler 
662953d895eSAxel Dörfler 			region->Set(oldVisibleBounds);
663953d895eSAxel Dörfler 			newVisibleBounds.OffsetBy(x, y);
664953d895eSAxel Dörfler 			region->Exclude((clipping_rect)newVisibleBounds);
665953d895eSAxel Dörfler 			dirtyRegion->Include(dirty);
666953d895eSAxel Dörfler 
667953d895eSAxel Dörfler 			fWindow->RecycleRegion(region);
668953d895eSAxel Dörfler 		}
669953d895eSAxel Dörfler 
670953d895eSAxel Dörfler #endif
671953d895eSAxel Dörfler 	}
672953d895eSAxel Dörfler 
673953d895eSAxel Dörfler 	if (!fParent) {
674953d895eSAxel Dörfler 		// the top view's screen clipping does not change,
675953d895eSAxel Dörfler 		// because no parts are clipped away from parent
676953d895eSAxel Dörfler 		// views
677953d895eSAxel Dörfler 		_MoveScreenClipping(x, y, true);
678953d895eSAxel Dörfler 	} else {
679953d895eSAxel Dörfler 		// parts might have been revealed from underneath
680953d895eSAxel Dörfler 		// the parent, or might now be hidden underneath
681953d895eSAxel Dörfler 		// the parent, this is taken care of when building
682953d895eSAxel Dörfler 		// the screen clipping
683953d895eSAxel Dörfler 		InvalidateScreenClipping();
684953d895eSAxel Dörfler 	}
685953d895eSAxel Dörfler }
686953d895eSAxel Dörfler 
687953d895eSAxel Dörfler 
688953d895eSAxel Dörfler void
689953d895eSAxel Dörfler View::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
690953d895eSAxel Dörfler {
691953d895eSAxel Dörfler 	if (x == 0 && y == 0)
692953d895eSAxel Dörfler 		return;
693953d895eSAxel Dörfler 
694953d895eSAxel Dörfler 	fFrame.right += x;
695953d895eSAxel Dörfler 	fFrame.bottom += y;
696953d895eSAxel Dörfler 
697953d895eSAxel Dörfler 	if (fVisible && dirtyRegion) {
698953d895eSAxel Dörfler 		IntRect oldBounds(Bounds());
699953d895eSAxel Dörfler 		oldBounds.right -= x;
700953d895eSAxel Dörfler 		oldBounds.bottom -= y;
701953d895eSAxel Dörfler 
702953d895eSAxel Dörfler 		BRegion* dirty = fWindow->GetRegion();
703953d895eSAxel Dörfler 		if (!dirty)
704953d895eSAxel Dörfler 			return;
705953d895eSAxel Dörfler 
706953d895eSAxel Dörfler 		dirty->Set((clipping_rect)Bounds());
707953d895eSAxel Dörfler 		dirty->Include((clipping_rect)oldBounds);
708953d895eSAxel Dörfler 
709953d895eSAxel Dörfler 		if (!(fFlags & B_FULL_UPDATE_ON_RESIZE)) {
710953d895eSAxel Dörfler 			// the dirty region is just the difference of
711953d895eSAxel Dörfler 			// old and new bounds
712953d895eSAxel Dörfler 			dirty->Exclude((clipping_rect)(oldBounds & Bounds()));
713953d895eSAxel Dörfler 		}
714953d895eSAxel Dörfler 
715953d895eSAxel Dörfler 		InvalidateScreenClipping();
716953d895eSAxel Dörfler 
717953d895eSAxel Dörfler 		if (dirty->CountRects() > 0) {
718953d895eSAxel Dörfler 			if ((fFlags & B_DRAW_ON_CHILDREN) == 0) {
719953d895eSAxel Dörfler 				// exclude children, they are expected to
720953d895eSAxel Dörfler 				// include their own dirty regions in ParentResized()
721953d895eSAxel Dörfler 				for (View* child = FirstChild(); child;
722953d895eSAxel Dörfler 						child = child->NextSibling()) {
723953d895eSAxel Dörfler 					if (!child->IsVisible())
724953d895eSAxel Dörfler 						continue;
725953d895eSAxel Dörfler 					IntRect previousChildVisible(
726953d895eSAxel Dörfler 						child->Frame() & oldBounds & Bounds());
727953d895eSAxel Dörfler 					if (dirty->Frame().Intersects(previousChildVisible)) {
728953d895eSAxel Dörfler 						dirty->Exclude((clipping_rect)previousChildVisible);
729953d895eSAxel Dörfler 					}
730953d895eSAxel Dörfler 				}
731953d895eSAxel Dörfler 			}
732953d895eSAxel Dörfler 
7336f2a446eSJulian Harnath 			LocalToScreenTransform().Apply(dirty);
734953d895eSAxel Dörfler 			dirtyRegion->Include(dirty);
735953d895eSAxel Dörfler 		}
736953d895eSAxel Dörfler 		fWindow->RecycleRegion(dirty);
737953d895eSAxel Dörfler 	}
738953d895eSAxel Dörfler 
739953d895eSAxel Dörfler 	// layout the children
740953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
741953d895eSAxel Dörfler 		child->ParentResized(x, y, dirtyRegion);
742953d895eSAxel Dörfler 
743953d895eSAxel Dörfler 	// view bitmap
74495e95feeSMichael Lotz 	if (fViewBitmap != NULL)
745953d895eSAxel Dörfler 		resize_frame(fBitmapDestination, fBitmapResizingMode, x, y);
746953d895eSAxel Dörfler 
747953d895eSAxel Dörfler 	// at this point, children are at their new locations,
748953d895eSAxel Dörfler 	// so we can rebuild the clipping
749953d895eSAxel Dörfler 	// TODO: when the implementation of Hide() and Show() is
750953d895eSAxel Dörfler 	// complete, see if this should be avoided
751953d895eSAxel Dörfler 	RebuildClipping(false);
752953d895eSAxel Dörfler }
753953d895eSAxel Dörfler 
754953d895eSAxel Dörfler 
755953d895eSAxel Dörfler void
756953d895eSAxel Dörfler View::ParentResized(int32 x, int32 y, BRegion* dirtyRegion)
757953d895eSAxel Dörfler {
758953d895eSAxel Dörfler 	IntRect newFrame = fFrame;
759953d895eSAxel Dörfler 	resize_frame(newFrame, fResizeMode & 0x0000ffff, x, y);
760953d895eSAxel Dörfler 
761953d895eSAxel Dörfler 	if (newFrame != fFrame) {
762953d895eSAxel Dörfler 		// careful, MoveBy will change fFrame
763953d895eSAxel Dörfler 		int32 widthDiff = (int32)(newFrame.Width() - fFrame.Width());
764953d895eSAxel Dörfler 		int32 heightDiff = (int32)(newFrame.Height() - fFrame.Height());
765953d895eSAxel Dörfler 
766953d895eSAxel Dörfler 		MoveBy(newFrame.left - fFrame.left,
767953d895eSAxel Dörfler 			newFrame.top - fFrame.top, dirtyRegion);
768953d895eSAxel Dörfler 
769953d895eSAxel Dörfler 		ResizeBy(widthDiff, heightDiff, dirtyRegion);
770953d895eSAxel Dörfler 	} else {
771953d895eSAxel Dörfler 		// TODO: this covers the fact that our screen clipping might change
772953d895eSAxel Dörfler 		// when the parent changes its size, even though our frame stays
773953d895eSAxel Dörfler 		// the same - there might be a way to test for this, but axeld doesn't
774953d895eSAxel Dörfler 		// know, stippi should look into this when he's back :)
775953d895eSAxel Dörfler 		InvalidateScreenClipping();
776953d895eSAxel Dörfler 	}
777953d895eSAxel Dörfler }
778953d895eSAxel Dörfler 
779953d895eSAxel Dörfler 
780953d895eSAxel Dörfler void
781953d895eSAxel Dörfler View::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
782953d895eSAxel Dörfler {
783953d895eSAxel Dörfler 	if (!fVisible || !fWindow) {
784953d895eSAxel Dörfler 		fScrollingOffset.x += x;
785953d895eSAxel Dörfler 		fScrollingOffset.y += y;
786953d895eSAxel Dörfler 		return;
787953d895eSAxel Dörfler 	}
788953d895eSAxel Dörfler 
789953d895eSAxel Dörfler 	// blitting version, invalidates
790953d895eSAxel Dörfler 	// old contents
791953d895eSAxel Dörfler 
792953d895eSAxel Dörfler 	// remember old bounds for tracking dirty region
793953d895eSAxel Dörfler 	IntRect oldBounds(Bounds());
794953d895eSAxel Dörfler 
795953d895eSAxel Dörfler 	// NOTE: using ConvertToVisibleInTopView()
796953d895eSAxel Dörfler 	// instead of ConvertToScreen(), this makes
797953d895eSAxel Dörfler 	// sure we don't try to move or invalidate an
798953d895eSAxel Dörfler 	// area hidden underneath the parent view
799953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&oldBounds);
800953d895eSAxel Dörfler 
801953d895eSAxel Dörfler 	// find the area of the view that can be scrolled,
802953d895eSAxel Dörfler 	// contents are shifted in the opposite direction from scrolling
803953d895eSAxel Dörfler 	IntRect stillVisibleBounds(oldBounds);
804953d895eSAxel Dörfler 	stillVisibleBounds.OffsetBy(x, y);
805953d895eSAxel Dörfler 	stillVisibleBounds = stillVisibleBounds & oldBounds;
806953d895eSAxel Dörfler 
807953d895eSAxel Dörfler 	fScrollingOffset.x += x;
808953d895eSAxel Dörfler 	fScrollingOffset.y += y;
809953d895eSAxel Dörfler 
810953d895eSAxel Dörfler 	// do the blit, this will make sure
811953d895eSAxel Dörfler 	// that other more complex dirty regions
812953d895eSAxel Dörfler 	// are taken care of
813953d895eSAxel Dörfler 	BRegion* copyRegion = fWindow->GetRegion();
814953d895eSAxel Dörfler 	if (!copyRegion)
815953d895eSAxel Dörfler 		return;
816953d895eSAxel Dörfler 	copyRegion->Set((clipping_rect)stillVisibleBounds);
817953d895eSAxel Dörfler 	fWindow->CopyContents(copyRegion, -x, -y);
818953d895eSAxel Dörfler 
819953d895eSAxel Dörfler 	// find the dirty region as far as we are
820953d895eSAxel Dörfler 	// concerned
821953d895eSAxel Dörfler 	BRegion* dirty = copyRegion;
822953d895eSAxel Dörfler 		// reuse copyRegion and call it dirty
823953d895eSAxel Dörfler 
824953d895eSAxel Dörfler 	dirty->Set((clipping_rect)oldBounds);
825953d895eSAxel Dörfler 	stillVisibleBounds.OffsetBy(-x, -y);
826953d895eSAxel Dörfler 	dirty->Exclude((clipping_rect)stillVisibleBounds);
827953d895eSAxel Dörfler 	dirtyRegion->Include(dirty);
828953d895eSAxel Dörfler 
829953d895eSAxel Dörfler 	fWindow->RecycleRegion(dirty);
830953d895eSAxel Dörfler 
831953d895eSAxel Dörfler 	// the screen clipping of this view and it's
832953d895eSAxel Dörfler 	// childs is no longer valid
833953d895eSAxel Dörfler 	InvalidateScreenClipping();
834953d895eSAxel Dörfler 	RebuildClipping(false);
835953d895eSAxel Dörfler }
836953d895eSAxel Dörfler 
837953d895eSAxel Dörfler 
838953d895eSAxel Dörfler void
839953d895eSAxel Dörfler View::CopyBits(IntRect src, IntRect dst, BRegion& windowContentClipping)
840953d895eSAxel Dörfler {
841953d895eSAxel Dörfler 	if (!fVisible || !fWindow)
842953d895eSAxel Dörfler 		return;
843953d895eSAxel Dörfler 
8441cde68c5SJulian Harnath 	// TODO: figure out what to do when we have a transform which is not
8451cde68c5SJulian Harnath 	// a dilation
8461cde68c5SJulian Harnath 	BAffineTransform transform = CurrentState()->CombinedTransform();
8471cde68c5SJulian Harnath 	if (!transform.IsIdentity() && transform.IsDilation()) {
8481cde68c5SJulian Harnath 		BPoint points[4] = { src.LeftTop(), src.RightBottom(),
8491cde68c5SJulian Harnath 							 dst.LeftTop(), dst.RightBottom() };
8501cde68c5SJulian Harnath 		transform.Apply(&points[0], 4);
8511cde68c5SJulian Harnath 		src.Set(points[0].x, points[0].y, points[1].x, points[1].y);
8521cde68c5SJulian Harnath 		dst.Set(points[2].x, points[2].y, points[3].x, points[3].y);
8531cde68c5SJulian Harnath 	}
8541cde68c5SJulian Harnath 
855953d895eSAxel Dörfler 	// TODO: confirm that in R5 this call is affected by origin and scale
856953d895eSAxel Dörfler 
857953d895eSAxel Dörfler 	// blitting version
858953d895eSAxel Dörfler 
859953d895eSAxel Dörfler 	int32 xOffset = dst.left - src.left;
860953d895eSAxel Dörfler 	int32 yOffset = dst.top - src.top;
861953d895eSAxel Dörfler 
862953d895eSAxel Dörfler 	// figure out which part can be blittet
863953d895eSAxel Dörfler 	IntRect visibleSrc(src);
864953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&visibleSrc);
865953d895eSAxel Dörfler 
866953d895eSAxel Dörfler 	IntRect visibleSrcAtDest(src);
867953d895eSAxel Dörfler 	visibleSrcAtDest.OffsetBy(xOffset, yOffset);
868953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&visibleSrcAtDest);
869953d895eSAxel Dörfler 
870953d895eSAxel Dörfler 	// clip src to visible at dest
871953d895eSAxel Dörfler 	visibleSrcAtDest.OffsetBy(-xOffset, -yOffset);
872953d895eSAxel Dörfler 	visibleSrc = visibleSrc & visibleSrcAtDest;
873953d895eSAxel Dörfler 
874953d895eSAxel Dörfler 	// do the blit, this will make sure
875953d895eSAxel Dörfler 	// that other more complex dirty regions
876953d895eSAxel Dörfler 	// are taken care of
877953d895eSAxel Dörfler 	BRegion* copyRegion = fWindow->GetRegion();
878953d895eSAxel Dörfler 	if (!copyRegion)
879953d895eSAxel Dörfler 		return;
880953d895eSAxel Dörfler 
881953d895eSAxel Dörfler 	// move src rect to destination here for efficiency reasons
882953d895eSAxel Dörfler 	visibleSrc.OffsetBy(xOffset, yOffset);
883953d895eSAxel Dörfler 
884f0c3c996SMichael Lotz 	// we need to interstect the copyRegion two times, onces
885953d895eSAxel Dörfler 	// at the source and once at the destination (here done
886953d895eSAxel Dörfler 	// the other way arround but it doesn't matter)
887953d895eSAxel Dörfler 	// the reason for this is that we are not supposed to visually
888953d895eSAxel Dörfler 	// copy children in the source rect and neither to copy onto
889953d895eSAxel Dörfler 	// children in the destination rect...
890953d895eSAxel Dörfler 	copyRegion->Set((clipping_rect)visibleSrc);
891ea2bcbf4SMichael Lotz 	BRegion *screenAndUserClipping
892ea2bcbf4SMichael Lotz 		= &ScreenAndUserClipping(&windowContentClipping);
893ea2bcbf4SMichael Lotz 	copyRegion->IntersectWith(screenAndUserClipping);
894953d895eSAxel Dörfler 	copyRegion->OffsetBy(-xOffset, -yOffset);
895ea2bcbf4SMichael Lotz 	copyRegion->IntersectWith(screenAndUserClipping);
896953d895eSAxel Dörfler 
897953d895eSAxel Dörfler 	// do the actual blit
898953d895eSAxel Dörfler 	fWindow->CopyContents(copyRegion, xOffset, yOffset);
899953d895eSAxel Dörfler 
900953d895eSAxel Dörfler 	// find the dirty region as far as we are concerned
901953d895eSAxel Dörfler 	IntRect dirtyDst(dst);
902953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&dirtyDst);
903953d895eSAxel Dörfler 
904953d895eSAxel Dörfler 	BRegion* dirty = fWindow->GetRegion();
905953d895eSAxel Dörfler 	if (!dirty) {
906953d895eSAxel Dörfler 		fWindow->RecycleRegion(copyRegion);
907953d895eSAxel Dörfler 		return;
908953d895eSAxel Dörfler 	}
909953d895eSAxel Dörfler 
910953d895eSAxel Dörfler 	// offset copyRegion to destination again
911953d895eSAxel Dörfler 	copyRegion->OffsetBy(xOffset, yOffset);
912953d895eSAxel Dörfler 	// start with destination given by user
913953d895eSAxel Dörfler 	dirty->Set((clipping_rect)dirtyDst);
914953d895eSAxel Dörfler 	// exclude the part that we could copy
915953d895eSAxel Dörfler 	dirty->Exclude(copyRegion);
916953d895eSAxel Dörfler 
917ea2bcbf4SMichael Lotz 	dirty->IntersectWith(screenAndUserClipping);
918953d895eSAxel Dörfler 	fWindow->MarkContentDirty(*dirty);
919953d895eSAxel Dörfler 
920953d895eSAxel Dörfler 	fWindow->RecycleRegion(dirty);
921953d895eSAxel Dörfler 	fWindow->RecycleRegion(copyRegion);
922953d895eSAxel Dörfler }
923953d895eSAxel Dörfler 
924953d895eSAxel Dörfler 
925953d895eSAxel Dörfler // #pragma mark -
926953d895eSAxel Dörfler 
927953d895eSAxel Dörfler 
928953d895eSAxel Dörfler void
929*7f9368caSlooncraz View::ColorUpdated(color_which which, rgb_color color)
930*7f9368caSlooncraz {
931*7f9368caSlooncraz 	float tint = B_NO_TINT;
932*7f9368caSlooncraz 
933*7f9368caSlooncraz 	if (fWhichViewColor == which)
934*7f9368caSlooncraz 		SetViewColor(tint_color(color, fWhichViewColorTint));
935*7f9368caSlooncraz 
936*7f9368caSlooncraz 	if (CurrentState()->HighUIColor(&tint) == which)
937*7f9368caSlooncraz 		CurrentState()->SetHighColor(tint_color(color, tint));
938*7f9368caSlooncraz 
939*7f9368caSlooncraz 	if (CurrentState()->LowUIColor(&tint) == which)
940*7f9368caSlooncraz 		CurrentState()->SetLowColor(tint_color(color, tint));
941*7f9368caSlooncraz 
942*7f9368caSlooncraz 	for (View* child = FirstChild(); child != NULL;
943*7f9368caSlooncraz 			child = child->NextSibling()) {
944*7f9368caSlooncraz 
945*7f9368caSlooncraz 		child->ColorUpdated(which, color);
946*7f9368caSlooncraz 	}
947*7f9368caSlooncraz }
948*7f9368caSlooncraz 
949*7f9368caSlooncraz 
950*7f9368caSlooncraz void
951*7f9368caSlooncraz View::SetViewUIColor(color_which which, float tint)
952*7f9368caSlooncraz {
953*7f9368caSlooncraz 	if (which != B_NO_COLOR) {
954*7f9368caSlooncraz 		DesktopSettings settings(fWindow->Desktop());
955*7f9368caSlooncraz 		SetViewColor(tint_color(settings.UIColor(which), tint));
956*7f9368caSlooncraz 	}
957*7f9368caSlooncraz 
958*7f9368caSlooncraz 	fWhichViewColor = which;
959*7f9368caSlooncraz 	fWhichViewColorTint = tint;
960*7f9368caSlooncraz }
961*7f9368caSlooncraz 
962*7f9368caSlooncraz 
963*7f9368caSlooncraz color_which
964*7f9368caSlooncraz View::ViewUIColor(float* tint)
965*7f9368caSlooncraz {
966*7f9368caSlooncraz 	if (tint != NULL)
967*7f9368caSlooncraz 		*tint = fWhichViewColorTint;
968*7f9368caSlooncraz 
969*7f9368caSlooncraz 	return fWhichViewColor;
970*7f9368caSlooncraz }
971*7f9368caSlooncraz 
972*7f9368caSlooncraz 
973*7f9368caSlooncraz // #pragma mark -
974*7f9368caSlooncraz 
975*7f9368caSlooncraz 
976*7f9368caSlooncraz void
977953d895eSAxel Dörfler View::PushState()
978953d895eSAxel Dörfler {
97979ef179cSStephan Aßmus 	DrawState* newState = fDrawState->PushState();
98079ef179cSStephan Aßmus 	if (newState) {
98179ef179cSStephan Aßmus 		fDrawState = newState;
982e1a30115SAdrien Destugues 		// In BeAPI, B_SUBPIXEL_PRECISE is a view flag, and not affected by the
983e1a30115SAdrien Destugues 		// view state. Our implementation moves it to the draw state, but let's
984e1a30115SAdrien Destugues 		// be compatible with the API here and make it survive accross state
985e1a30115SAdrien Destugues 		// changes.
986953d895eSAxel Dörfler 		fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
987953d895eSAxel Dörfler 	}
98879ef179cSStephan Aßmus }
989953d895eSAxel Dörfler 
990953d895eSAxel Dörfler 
991953d895eSAxel Dörfler void
992953d895eSAxel Dörfler View::PopState()
993953d895eSAxel Dörfler {
994953d895eSAxel Dörfler 	if (fDrawState->PreviousState() == NULL) {
995953d895eSAxel Dörfler 		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), "
996953d895eSAxel Dörfler 			"but there is NO state on stack!\n", Name());
997953d895eSAxel Dörfler 		return;
998953d895eSAxel Dörfler 	}
999953d895eSAxel Dörfler 
10002e44cfceSStephan Aßmus 	bool rebuildClipping = fDrawState->HasAdditionalClipping();
1001953d895eSAxel Dörfler 
1002953d895eSAxel Dörfler 	fDrawState = fDrawState->PopState();
1003953d895eSAxel Dörfler 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
1004953d895eSAxel Dörfler 
1005953d895eSAxel Dörfler 	// rebuild clipping
1006953d895eSAxel Dörfler 	// (the clipping from the popped state is not effective anymore)
1007953d895eSAxel Dörfler 	if (rebuildClipping)
1008953d895eSAxel Dörfler 		RebuildClipping(false);
1009953d895eSAxel Dörfler }
1010953d895eSAxel Dörfler 
1011953d895eSAxel Dörfler 
1012e1a30115SAdrien Destugues // #pragma mark -
1013e1a30115SAdrien Destugues 
1014e1a30115SAdrien Destugues 
1015953d895eSAxel Dörfler void
1016953d895eSAxel Dörfler View::SetEventMask(uint32 eventMask, uint32 options)
1017953d895eSAxel Dörfler {
1018953d895eSAxel Dörfler 	fEventMask = eventMask;
1019953d895eSAxel Dörfler 	fEventOptions = options;
1020953d895eSAxel Dörfler }
1021953d895eSAxel Dörfler 
1022953d895eSAxel Dörfler 
1023953d895eSAxel Dörfler void
1024953d895eSAxel Dörfler View::SetCursor(ServerCursor* cursor)
1025953d895eSAxel Dörfler {
1026953d895eSAxel Dörfler 	if (cursor == fCursor)
1027953d895eSAxel Dörfler 		return;
1028953d895eSAxel Dörfler 
1029953d895eSAxel Dörfler 	if (fCursor)
10304b0459b2SAxel Dörfler 		fCursor->ReleaseReference();
1031953d895eSAxel Dörfler 
1032953d895eSAxel Dörfler 	fCursor = cursor;
1033953d895eSAxel Dörfler 
103419e179caSStephan Aßmus 	if (fCursor)
10354b0459b2SAxel Dörfler 		fCursor->AcquireReference();
1036953d895eSAxel Dörfler }
1037953d895eSAxel Dörfler 
1038953d895eSAxel Dörfler 
1039953d895eSAxel Dörfler void
1040953d895eSAxel Dörfler View::SetPicture(ServerPicture* picture)
1041953d895eSAxel Dörfler {
104285a7877fSAxel Dörfler 	if (picture == fPicture)
104385a7877fSAxel Dörfler 		return;
104485a7877fSAxel Dörfler 
104585a7877fSAxel Dörfler 	if (fPicture != NULL)
104685a7877fSAxel Dörfler 		fPicture->ReleaseReference();
104785a7877fSAxel Dörfler 
1048953d895eSAxel Dörfler 	fPicture = picture;
104985a7877fSAxel Dörfler 
105085a7877fSAxel Dörfler 	if (fPicture != NULL)
105185a7877fSAxel Dörfler 		fPicture->AcquireReference();
1052953d895eSAxel Dörfler }
1053953d895eSAxel Dörfler 
1054953d895eSAxel Dörfler 
1055953d895eSAxel Dörfler void
1056551438b9SJulian Harnath View::BlendAllLayers()
1057551438b9SJulian Harnath {
1058551438b9SJulian Harnath 	if (fPicture == NULL)
1059551438b9SJulian Harnath 		return;
1060551438b9SJulian Harnath 	Layer* layer = dynamic_cast<Layer*>(fPicture);
1061551438b9SJulian Harnath 	if (layer == NULL)
1062551438b9SJulian Harnath 		return;
1063551438b9SJulian Harnath 	BlendLayer(layer);
1064551438b9SJulian Harnath }
1065551438b9SJulian Harnath 
1066551438b9SJulian Harnath 
1067551438b9SJulian Harnath void
1068953d895eSAxel Dörfler View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
1069953d895eSAxel Dörfler 	BRegion* windowContentClipping, bool deep)
1070953d895eSAxel Dörfler {
1071953d895eSAxel Dörfler 	if (!fVisible) {
1072953d895eSAxel Dörfler 		// child views cannot be visible either
1073953d895eSAxel Dörfler 		return;
1074953d895eSAxel Dörfler 	}
1075953d895eSAxel Dörfler 
1076953d895eSAxel Dörfler 	if (fViewBitmap != NULL || fViewColor != B_TRANSPARENT_COLOR) {
1077953d895eSAxel Dörfler 		// we can only draw within our own area
107855a88f0cSStephan Aßmus 		BRegion* redraw;
107955a88f0cSStephan Aßmus 		if ((fFlags & B_DRAW_ON_CHILDREN) != 0) {
108055a88f0cSStephan Aßmus 			// The client may actually want to prevent the background to
108155a88f0cSStephan Aßmus 			// be painted outside the user clipping.
108255a88f0cSStephan Aßmus 			redraw = fWindow->GetRegion(
108355a88f0cSStephan Aßmus 				ScreenAndUserClipping(windowContentClipping));
108455a88f0cSStephan Aßmus 		} else {
108555a88f0cSStephan Aßmus 			// Ignore user clipping as in BeOS for painting the background.
108655a88f0cSStephan Aßmus 			redraw = fWindow->GetRegion(
1087f0c3c996SMichael Lotz 				_ScreenClipping(windowContentClipping));
108855a88f0cSStephan Aßmus 		}
1089953d895eSAxel Dörfler 		if (!redraw)
1090953d895eSAxel Dörfler 			return;
1091953d895eSAxel Dörfler 		// add the current clipping
1092953d895eSAxel Dörfler 		redraw->IntersectWith(effectiveClipping);
1093953d895eSAxel Dörfler 
1094953d895eSAxel Dörfler 		Overlay* overlayCookie = _Overlay();
1095953d895eSAxel Dörfler 
1096953d895eSAxel Dörfler 		if (fViewBitmap != NULL && overlayCookie == NULL) {
1097953d895eSAxel Dörfler 			// draw view bitmap
1098953d895eSAxel Dörfler 			// TODO: support other options!
1099953d895eSAxel Dörfler 			BRect rect = fBitmapDestination;
11006f2a446eSJulian Harnath 			PenToScreenTransform().Apply(&rect);
1101953d895eSAxel Dörfler 
1102953d895eSAxel Dörfler 			align_rect_to_pixels(&rect);
1103953d895eSAxel Dörfler 
1104953d895eSAxel Dörfler 			if (fBitmapOptions & B_TILE_BITMAP_Y) {
1105953d895eSAxel Dörfler 				// move rect up as much as needed
1106953d895eSAxel Dörfler 				while (rect.top > redraw->Frame().top)
1107953d895eSAxel Dörfler 					rect.OffsetBy(0.0, -(rect.Height() + 1));
1108953d895eSAxel Dörfler 			}
1109953d895eSAxel Dörfler 			if (fBitmapOptions & B_TILE_BITMAP_X) {
1110953d895eSAxel Dörfler 				// move rect left as much as needed
1111953d895eSAxel Dörfler 				while (rect.left > redraw->Frame().left)
1112953d895eSAxel Dörfler 					rect.OffsetBy(-(rect.Width() + 1), 0.0);
1113953d895eSAxel Dörfler 			}
1114953d895eSAxel Dörfler 
1115953d895eSAxel Dörfler // XXX: locking removed because the Window keeps the engine locked
1116953d895eSAxel Dörfler // because it keeps track of syncing right now
1117953d895eSAxel Dörfler 
1118953d895eSAxel Dörfler 			// lock the drawing engine for as long as we need the clipping
1119953d895eSAxel Dörfler 			// to be valid
1120953d895eSAxel Dörfler 			if (rect.IsValid()/* && drawingEngine->Lock()*/) {
1121953d895eSAxel Dörfler 				drawingEngine->ConstrainClippingRegion(redraw);
1122953d895eSAxel Dörfler 
11232b4f382aSStephan Aßmus 				drawing_mode oldMode;
11242b4f382aSStephan Aßmus 				drawingEngine->SetDrawingMode(B_OP_COPY, oldMode);
11252b4f382aSStephan Aßmus 
1126953d895eSAxel Dörfler 				if (fBitmapOptions & B_TILE_BITMAP) {
1127953d895eSAxel Dörfler 					// tile across entire view
1128953d895eSAxel Dörfler 
1129953d895eSAxel Dörfler 					float start = rect.left;
1130953d895eSAxel Dörfler 					while (rect.top < redraw->Frame().bottom) {
1131953d895eSAxel Dörfler 						while (rect.left < redraw->Frame().right) {
1132953d895eSAxel Dörfler 							drawingEngine->DrawBitmap(fViewBitmap,
11337eed63a1SStephan Aßmus 								fBitmapSource, rect, fBitmapOptions);
1134953d895eSAxel Dörfler 							rect.OffsetBy(rect.Width() + 1, 0.0);
1135953d895eSAxel Dörfler 						}
1136953d895eSAxel Dörfler 						rect.OffsetBy(start - rect.left, rect.Height() + 1);
1137953d895eSAxel Dörfler 					}
1138953d895eSAxel Dörfler 					// nothing left to be drawn
1139953d895eSAxel Dörfler 					redraw->MakeEmpty();
1140953d895eSAxel Dörfler 				} else if (fBitmapOptions & B_TILE_BITMAP_X) {
1141953d895eSAxel Dörfler 					// tile in x direction
1142953d895eSAxel Dörfler 
1143953d895eSAxel Dörfler 					while (rect.left < redraw->Frame().right) {
1144953d895eSAxel Dörfler 						drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
11457eed63a1SStephan Aßmus 							rect, fBitmapOptions);
1146953d895eSAxel Dörfler 						rect.OffsetBy(rect.Width() + 1, 0.0);
1147953d895eSAxel Dörfler 					}
1148953d895eSAxel Dörfler 					// remove horizontal stripe from clipping
1149953d895eSAxel Dörfler 					rect.left = redraw->Frame().left;
1150953d895eSAxel Dörfler 					rect.right = redraw->Frame().right;
1151953d895eSAxel Dörfler 					redraw->Exclude(rect);
1152953d895eSAxel Dörfler 				} else if (fBitmapOptions & B_TILE_BITMAP_Y) {
1153953d895eSAxel Dörfler 					// tile in y direction
1154953d895eSAxel Dörfler 
1155953d895eSAxel Dörfler 					while (rect.top < redraw->Frame().bottom) {
1156953d895eSAxel Dörfler 						drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
11577eed63a1SStephan Aßmus 							rect, fBitmapOptions);
1158953d895eSAxel Dörfler 						rect.OffsetBy(0.0, rect.Height() + 1);
1159953d895eSAxel Dörfler 					}
1160953d895eSAxel Dörfler 					// remove vertical stripe from clipping
1161953d895eSAxel Dörfler 					rect.top = redraw->Frame().top;
1162953d895eSAxel Dörfler 					rect.bottom = redraw->Frame().bottom;
1163953d895eSAxel Dörfler 					redraw->Exclude(rect);
1164953d895eSAxel Dörfler 				} else {
1165953d895eSAxel Dörfler 					// no tiling at all
1166953d895eSAxel Dörfler 
1167953d895eSAxel Dörfler 					drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
11687eed63a1SStephan Aßmus 						rect, fBitmapOptions);
1169953d895eSAxel Dörfler 					redraw->Exclude(rect);
1170953d895eSAxel Dörfler 				}
1171953d895eSAxel Dörfler 
11722b4f382aSStephan Aßmus 				drawingEngine->SetDrawingMode(oldMode);
11732b4f382aSStephan Aßmus 
1174953d895eSAxel Dörfler 				// NOTE: It is ok not to reset the clipping, that
1175953d895eSAxel Dörfler 				// would only waste time
1176953d895eSAxel Dörfler //				drawingEngine->Unlock();
1177953d895eSAxel Dörfler 			}
1178953d895eSAxel Dörfler 
1179953d895eSAxel Dörfler 		}
1180953d895eSAxel Dörfler 
1181953d895eSAxel Dörfler 		if (fViewColor != B_TRANSPARENT_COLOR) {
1182953d895eSAxel Dörfler 			// fill visible region with view color,
1183953d895eSAxel Dörfler 			// this version of FillRegion ignores any
1184953d895eSAxel Dörfler 			// clipping, that's why "redraw" needs to
1185953d895eSAxel Dörfler 			// be correct
1186953d895eSAxel Dörfler // see #634
1187953d895eSAxel Dörfler //			if (redraw->Frame().left < 0 || redraw->Frame().top < 0) {
1188953d895eSAxel Dörfler //				char message[1024];
1189953d895eSAxel Dörfler //				BRect c = effectiveClipping->Frame();
1190953d895eSAxel Dörfler //				BRect w = windowContentClipping->Frame();
1191953d895eSAxel Dörfler //				BRect r = redraw->Frame();
1192953d895eSAxel Dörfler //				sprintf(message, "invalid background: current clipping: (%d, %d)->(%d, %d), "
1193953d895eSAxel Dörfler //					"window content: (%d, %d)->(%d, %d), redraw: (%d, %d)->(%d, %d)",
1194953d895eSAxel Dörfler //					(int)c.left, (int)c.top, (int)c.right, (int)c.bottom,
1195953d895eSAxel Dörfler //					(int)w.left, (int)w.top, (int)w.right, (int)w.bottom,
1196953d895eSAxel Dörfler //					(int)r.left, (int)r.top, (int)r.right, (int)r.bottom);
1197953d895eSAxel Dörfler //				debugger(message);
1198953d895eSAxel Dörfler //			}
1199953d895eSAxel Dörfler 
1200953d895eSAxel Dörfler 			drawingEngine->FillRegion(*redraw, overlayCookie != NULL
1201953d895eSAxel Dörfler 				? overlayCookie->Color() : fViewColor);
1202953d895eSAxel Dörfler 		}
1203953d895eSAxel Dörfler 
1204953d895eSAxel Dörfler 		fWindow->RecycleRegion(redraw);
1205953d895eSAxel Dörfler 	}
1206953d895eSAxel Dörfler 
1207953d895eSAxel Dörfler 	fBackgroundDirty = false;
1208953d895eSAxel Dörfler 
1209953d895eSAxel Dörfler 	// let children draw
1210953d895eSAxel Dörfler 	if (deep) {
1211953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
1212953d895eSAxel Dörfler 			child->Draw(drawingEngine, effectiveClipping,
1213953d895eSAxel Dörfler 				windowContentClipping, deep);
1214953d895eSAxel Dörfler 		}
1215953d895eSAxel Dörfler 	}
1216953d895eSAxel Dörfler }
1217953d895eSAxel Dörfler 
1218953d895eSAxel Dörfler 
1219953d895eSAxel Dörfler // #pragma mark -
1220953d895eSAxel Dörfler 
1221953d895eSAxel Dörfler 
1222953d895eSAxel Dörfler void
1223953d895eSAxel Dörfler View::MouseDown(BMessage* message, BPoint where)
1224953d895eSAxel Dörfler {
1225953d895eSAxel Dörfler 	// empty hook method
1226953d895eSAxel Dörfler }
1227953d895eSAxel Dörfler 
1228953d895eSAxel Dörfler 
1229953d895eSAxel Dörfler void
1230953d895eSAxel Dörfler View::MouseUp(BMessage* message, BPoint where)
1231953d895eSAxel Dörfler {
1232953d895eSAxel Dörfler 	// empty hook method
1233953d895eSAxel Dörfler }
1234953d895eSAxel Dörfler 
1235953d895eSAxel Dörfler 
1236953d895eSAxel Dörfler void
1237953d895eSAxel Dörfler View::MouseMoved(BMessage* message, BPoint where)
1238953d895eSAxel Dörfler {
1239953d895eSAxel Dörfler 	// empty hook method
1240953d895eSAxel Dörfler }
1241953d895eSAxel Dörfler 
1242953d895eSAxel Dörfler 
1243953d895eSAxel Dörfler // #pragma mark -
1244953d895eSAxel Dörfler 
1245953d895eSAxel Dörfler 
1246953d895eSAxel Dörfler void
1247953d895eSAxel Dörfler View::SetHidden(bool hidden)
1248953d895eSAxel Dörfler {
1249953d895eSAxel Dörfler 	if (fHidden != hidden) {
1250953d895eSAxel Dörfler 		fHidden = hidden;
1251953d895eSAxel Dörfler 
1252953d895eSAxel Dörfler 		// recurse into children and update their visible flag
1253953d895eSAxel Dörfler 		bool oldVisible = fVisible;
1254953d895eSAxel Dörfler 		UpdateVisibleDeep(fParent ? fParent->IsVisible() : !fHidden);
1255953d895eSAxel Dörfler 		if (oldVisible != fVisible) {
1256953d895eSAxel Dörfler 			// Include or exclude us from the parent area, and update the
1257953d895eSAxel Dörfler 			// children's clipping as well when the view will be visible
1258953d895eSAxel Dörfler 			if (fParent)
1259953d895eSAxel Dörfler 				fParent->RebuildClipping(fVisible);
1260953d895eSAxel Dörfler 			else
1261953d895eSAxel Dörfler 				RebuildClipping(fVisible);
1262953d895eSAxel Dörfler 
1263953d895eSAxel Dörfler 			if (fWindow) {
1264953d895eSAxel Dörfler 				// trigger a redraw
1265953d895eSAxel Dörfler 				IntRect clippedBounds = Bounds();
1266953d895eSAxel Dörfler 				ConvertToVisibleInTopView(&clippedBounds);
1267953d895eSAxel Dörfler 				BRegion* dirty = fWindow->GetRegion();
1268953d895eSAxel Dörfler 				if (!dirty)
1269953d895eSAxel Dörfler 					return;
1270953d895eSAxel Dörfler 				dirty->Set((clipping_rect)clippedBounds);
1271953d895eSAxel Dörfler 				fWindow->MarkContentDirty(*dirty);
1272953d895eSAxel Dörfler 				fWindow->RecycleRegion(dirty);
1273953d895eSAxel Dörfler 			}
1274953d895eSAxel Dörfler 		}
1275953d895eSAxel Dörfler 	}
1276953d895eSAxel Dörfler }
1277953d895eSAxel Dörfler 
1278953d895eSAxel Dörfler 
1279953d895eSAxel Dörfler bool
1280953d895eSAxel Dörfler View::IsHidden() const
1281953d895eSAxel Dörfler {
1282953d895eSAxel Dörfler 	return fHidden;
1283953d895eSAxel Dörfler }
1284953d895eSAxel Dörfler 
1285953d895eSAxel Dörfler 
1286953d895eSAxel Dörfler void
1287953d895eSAxel Dörfler View::UpdateVisibleDeep(bool parentVisible)
1288953d895eSAxel Dörfler {
1289953d895eSAxel Dörfler 	bool wasVisible = fVisible;
1290953d895eSAxel Dörfler 
1291953d895eSAxel Dörfler 	fVisible = parentVisible && !fHidden;
1292953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
1293953d895eSAxel Dörfler 		child->UpdateVisibleDeep(fVisible);
1294953d895eSAxel Dörfler 
1295953d895eSAxel Dörfler 	// overlay handling
1296953d895eSAxel Dörfler 
1297953d895eSAxel Dörfler 	Overlay* overlay = _Overlay();
1298953d895eSAxel Dörfler 	if (overlay == NULL)
1299953d895eSAxel Dörfler 		return;
1300953d895eSAxel Dörfler 
1301953d895eSAxel Dörfler 	if (fVisible && !wasVisible)
1302953d895eSAxel Dörfler 		_UpdateOverlayView();
1303953d895eSAxel Dörfler 	else if (!fVisible && wasVisible)
1304953d895eSAxel Dörfler 		overlay->Hide();
1305953d895eSAxel Dörfler }
1306953d895eSAxel Dörfler 
1307953d895eSAxel Dörfler 
1308953d895eSAxel Dörfler // #pragma mark -
1309953d895eSAxel Dörfler 
1310953d895eSAxel Dörfler 
1311953d895eSAxel Dörfler void
1312953d895eSAxel Dörfler View::MarkBackgroundDirty()
1313953d895eSAxel Dörfler {
1314953d895eSAxel Dörfler 	if (fBackgroundDirty)
1315953d895eSAxel Dörfler 		return;
1316953d895eSAxel Dörfler 	fBackgroundDirty = true;
1317953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
1318953d895eSAxel Dörfler 		child->MarkBackgroundDirty();
1319953d895eSAxel Dörfler }
1320953d895eSAxel Dörfler 
1321953d895eSAxel Dörfler 
1322953d895eSAxel Dörfler void
1323437b1927SAxel Dörfler View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region,
1324953d895eSAxel Dörfler 	BRegion* windowContentClipping)
1325953d895eSAxel Dörfler {
1326953d895eSAxel Dörfler 	if (!fVisible)
1327953d895eSAxel Dörfler 		return;
1328953d895eSAxel Dörfler 
1329581e6786SStephan Aßmus 	{
1330581e6786SStephan Aßmus 		// NOTE: use scope in order to reduce stack space requirements
1331581e6786SStephan Aßmus 
1332581e6786SStephan Aßmus 		// This check will prevent descending the view hierarchy
1333581e6786SStephan Aßmus 		// any further than necessary
1334953d895eSAxel Dörfler 		IntRect screenBounds(Bounds());
13356f2a446eSJulian Harnath 		LocalToScreenTransform().Apply(&screenBounds);
1336953d895eSAxel Dörfler 		if (!region.Intersects((clipping_rect)screenBounds))
1337953d895eSAxel Dörfler 			return;
1338953d895eSAxel Dörfler 
1339581e6786SStephan Aßmus 		// Unfortunately, we intersecting another region, but otherwise
1340581e6786SStephan Aßmus 		// we couldn't provide the exact update rect to the client
1341581e6786SStephan Aßmus 		BRegion localDirty = _ScreenClipping(windowContentClipping);
1342581e6786SStephan Aßmus 		localDirty.IntersectWith(&region);
1343581e6786SStephan Aßmus 		if (localDirty.CountRects() > 0) {
1344953d895eSAxel Dörfler 			link.Attach<int32>(fToken);
1345581e6786SStephan Aßmus 			link.Attach<BRect>(localDirty.Frame());
1346953d895eSAxel Dörfler 		}
1347953d895eSAxel Dörfler 	}
1348953d895eSAxel Dörfler 
1349581e6786SStephan Aßmus 	for (View* child = FirstChild(); child; child = child->NextSibling())
1350581e6786SStephan Aßmus 		child->AddTokensForViewsInRegion(link, region, windowContentClipping);
1351581e6786SStephan Aßmus }
1352581e6786SStephan Aßmus 
1353953d895eSAxel Dörfler 
1354953d895eSAxel Dörfler void
1355953d895eSAxel Dörfler View::PrintToStream() const
1356953d895eSAxel Dörfler {
1357953d895eSAxel Dörfler 	printf("View:          %s\n", Name());
13583fed1a15SAlex Smith 	printf("  fToken:           %" B_PRId32 "\n", fToken);
13593fed1a15SAlex Smith 	printf("  fFrame:           IntRect(%" B_PRId32 ", %" B_PRId32 ", %" B_PRId32 ", %" B_PRId32 ")\n",
13603fed1a15SAlex Smith 		fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
13613fed1a15SAlex Smith 	printf("  fScrollingOffset: IntPoint(%" B_PRId32 ", %" B_PRId32 ")\n",
13623fed1a15SAlex Smith 		fScrollingOffset.x, fScrollingOffset.y);
1363953d895eSAxel Dörfler 	printf("  fHidden:          %d\n", fHidden);
1364953d895eSAxel Dörfler 	printf("  fVisible:         %d\n", fVisible);
1365953d895eSAxel Dörfler 	printf("  fWindow:          %p\n", fWindow);
1366953d895eSAxel Dörfler 	printf("  fParent:          %p\n", fParent);
1367953d895eSAxel Dörfler 	printf("  fLocalClipping:\n");
1368953d895eSAxel Dörfler 	fLocalClipping.PrintToStream();
1369953d895eSAxel Dörfler 	printf("  fScreenClipping:\n");
1370953d895eSAxel Dörfler 	fScreenClipping.PrintToStream();
1371953d895eSAxel Dörfler 	printf("  valid:            %d\n", fScreenClippingValid);
1372f0c3c996SMichael Lotz 
1373f0c3c996SMichael Lotz 	printf("  fUserClipping:\n");
1374f0c3c996SMichael Lotz 	if (fUserClipping != NULL)
1375f0c3c996SMichael Lotz 		fUserClipping->PrintToStream();
1376f0c3c996SMichael Lotz 	else
1377f0c3c996SMichael Lotz 		printf("  none\n");
1378f0c3c996SMichael Lotz 
1379f0c3c996SMichael Lotz 	printf("  fScreenAndUserClipping:\n");
1380f0c3c996SMichael Lotz 	if (fScreenAndUserClipping != NULL)
1381f0c3c996SMichael Lotz 		fScreenAndUserClipping->PrintToStream();
1382f0c3c996SMichael Lotz 	else
1383f0c3c996SMichael Lotz 		printf("  invalid\n");
1384f0c3c996SMichael Lotz 
1385953d895eSAxel Dörfler 	printf("  state:\n");
138679ef179cSStephan Aßmus 	printf("    user clipping:  %d\n", fDrawState->HasClipping());
138779ef179cSStephan Aßmus 	BPoint origin = fDrawState->CombinedOrigin();
138879ef179cSStephan Aßmus 	printf("    origin:         BPoint(%.1f, %.1f)\n", origin.x, origin.y);
138979ef179cSStephan Aßmus 	printf("    scale:          %.2f\n", fDrawState->CombinedScale());
1390953d895eSAxel Dörfler 	printf("\n");
1391953d895eSAxel Dörfler }
1392953d895eSAxel Dörfler 
1393953d895eSAxel Dörfler 
1394953d895eSAxel Dörfler void
1395953d895eSAxel Dörfler View::RebuildClipping(bool deep)
1396953d895eSAxel Dörfler {
1397953d895eSAxel Dörfler 	// the clipping spans over the bounds area
1398953d895eSAxel Dörfler 	fLocalClipping.Set((clipping_rect)Bounds());
1399953d895eSAxel Dörfler 
1400953d895eSAxel Dörfler 	if (View* child = FirstChild()) {
1401953d895eSAxel Dörfler 		// if this view does not draw over children,
1402953d895eSAxel Dörfler 		// exclude all children from the clipping
1403953d895eSAxel Dörfler 		if ((fFlags & B_DRAW_ON_CHILDREN) == 0) {
1404953d895eSAxel Dörfler 			BRegion* childrenRegion = fWindow->GetRegion();
1405953d895eSAxel Dörfler 			if (!childrenRegion)
1406953d895eSAxel Dörfler 				return;
1407953d895eSAxel Dörfler 
1408953d895eSAxel Dörfler 			for (; child; child = child->NextSibling()) {
1409953d895eSAxel Dörfler 				if (child->IsVisible())
1410953d895eSAxel Dörfler 					childrenRegion->Include((clipping_rect)child->Frame());
1411953d895eSAxel Dörfler 			}
1412953d895eSAxel Dörfler 
1413953d895eSAxel Dörfler 			fLocalClipping.Exclude(childrenRegion);
1414953d895eSAxel Dörfler 			fWindow->RecycleRegion(childrenRegion);
1415953d895eSAxel Dörfler 		}
1416953d895eSAxel Dörfler 		// if the operation is "deep", make children rebuild their
1417953d895eSAxel Dörfler 		// clipping too
1418953d895eSAxel Dörfler 		if (deep) {
1419953d895eSAxel Dörfler 			for (child = FirstChild(); child; child = child->NextSibling())
1420953d895eSAxel Dörfler 				child->RebuildClipping(true);
1421953d895eSAxel Dörfler 		}
1422953d895eSAxel Dörfler 	}
1423953d895eSAxel Dörfler 
1424953d895eSAxel Dörfler 	// add the user clipping in case there is one
142579ef179cSStephan Aßmus 	if (fDrawState->HasClipping()) {
1426953d895eSAxel Dörfler 		// NOTE: in case the user sets a user defined clipping region,
1427953d895eSAxel Dörfler 		// rebuilding the clipping is a bit more expensive because there
1428953d895eSAxel Dörfler 		// is no separate "drawing region"... on the other
1429953d895eSAxel Dörfler 		// hand, views for which this feature is actually used will
1430953d895eSAxel Dörfler 		// probably not have any children, so it is not that expensive
1431953d895eSAxel Dörfler 		// after all
1432f0c3c996SMichael Lotz 		if (fUserClipping == NULL) {
1433f0c3c996SMichael Lotz 			fUserClipping = new (nothrow) BRegion;
1434f0c3c996SMichael Lotz 			if (fUserClipping == NULL)
1435953d895eSAxel Dörfler 				return;
1436953d895eSAxel Dörfler 		}
1437953d895eSAxel Dörfler 
1438f0c3c996SMichael Lotz 		fDrawState->GetCombinedClippingRegion(fUserClipping);
1439f0c3c996SMichael Lotz 	} else {
1440f0c3c996SMichael Lotz 		delete fUserClipping;
1441f0c3c996SMichael Lotz 		fUserClipping = NULL;
1442f0c3c996SMichael Lotz 	}
1443f0c3c996SMichael Lotz 
1444f0c3c996SMichael Lotz 	delete fScreenAndUserClipping;
1445f0c3c996SMichael Lotz 	fScreenAndUserClipping = NULL;
1446953d895eSAxel Dörfler 	fScreenClippingValid = false;
1447953d895eSAxel Dörfler }
1448953d895eSAxel Dörfler 
1449953d895eSAxel Dörfler 
1450953d895eSAxel Dörfler BRegion&
1451f0c3c996SMichael Lotz View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const
1452953d895eSAxel Dörfler {
1453f0c3c996SMichael Lotz 	// no user clipping - return screen clipping directly
1454f0c3c996SMichael Lotz 	if (fUserClipping == NULL)
1455f0c3c996SMichael Lotz 		return _ScreenClipping(windowContentClipping, force);
1456953d895eSAxel Dörfler 
1457f0c3c996SMichael Lotz 	// combined screen and user clipping already valid
1458f0c3c996SMichael Lotz 	if (fScreenAndUserClipping != NULL)
1459f0c3c996SMichael Lotz 		return *fScreenAndUserClipping;
1460953d895eSAxel Dörfler 
1461f0c3c996SMichael Lotz 	// build a new combined user and screen clipping
1462f0c3c996SMichael Lotz 	fScreenAndUserClipping = new (nothrow) BRegion(*fUserClipping);
1463f0c3c996SMichael Lotz 	if (fScreenAndUserClipping == NULL)
1464953d895eSAxel Dörfler 		return fScreenClipping;
1465f0c3c996SMichael Lotz 
14666f2a446eSJulian Harnath 	LocalToScreenTransform().Apply(fScreenAndUserClipping);
1467f0c3c996SMichael Lotz 	fScreenAndUserClipping->IntersectWith(
1468f0c3c996SMichael Lotz 		&_ScreenClipping(windowContentClipping, force));
1469f0c3c996SMichael Lotz 	return *fScreenAndUserClipping;
1470953d895eSAxel Dörfler }
1471953d895eSAxel Dörfler 
1472953d895eSAxel Dörfler 
1473953d895eSAxel Dörfler void
1474953d895eSAxel Dörfler View::InvalidateScreenClipping()
1475953d895eSAxel Dörfler {
1476953d895eSAxel Dörfler // TODO: appearantly, we are calling ScreenClipping() on
1477953d895eSAxel Dörfler // views who's parents don't have a valid screen clipping yet,
1478953d895eSAxel Dörfler // this messes up the logic that for any given view with
1479953d895eSAxel Dörfler // fScreenClippingValid == false, all children have
1480953d895eSAxel Dörfler // fScreenClippingValid == false too. If this could be made the
1481953d895eSAxel Dörfler // case, we could save some performance here with the commented
1482953d895eSAxel Dörfler // out check, since InvalidateScreenClipping() might be called
1483953d895eSAxel Dörfler // frequently.
1484953d895eSAxel Dörfler // TODO: investigate, if InvalidateScreenClipping() could be
1485953d895eSAxel Dörfler // called in "deep" and "non-deep" mode, ie. see if there are
1486953d895eSAxel Dörfler // any cases where the children would still have valid screen
1487953d895eSAxel Dörfler // clipping, even though the parent's screen clipping becomes
1488953d895eSAxel Dörfler // invalid.
1489953d895eSAxel Dörfler //	if (!fScreenClippingValid)
1490953d895eSAxel Dörfler //		return;
1491953d895eSAxel Dörfler 
1492f0c3c996SMichael Lotz 	delete fScreenAndUserClipping;
1493f0c3c996SMichael Lotz 	fScreenAndUserClipping = NULL;
1494953d895eSAxel Dörfler 	fScreenClippingValid = false;
1495953d895eSAxel Dörfler 	// invalidate the childrens screen clipping as well
1496953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
1497953d895eSAxel Dörfler 		child->InvalidateScreenClipping();
1498953d895eSAxel Dörfler 	}
1499953d895eSAxel Dörfler }
1500953d895eSAxel Dörfler 
1501953d895eSAxel Dörfler 
1502f0c3c996SMichael Lotz BRegion&
1503f0c3c996SMichael Lotz View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
1504f0c3c996SMichael Lotz {
1505f0c3c996SMichael Lotz 	if (!fScreenClippingValid || force) {
1506f0c3c996SMichael Lotz 		fScreenClipping = fLocalClipping;
15076f2a446eSJulian Harnath 		LocalToScreenTransform().Apply(&fScreenClipping);
1508f0c3c996SMichael Lotz 
1509f0c3c996SMichael Lotz 		// see if parts of our bounds are hidden underneath
1510f0c3c996SMichael Lotz 		// the parent, the local clipping does not account for this
1511f0c3c996SMichael Lotz 		IntRect clippedBounds = Bounds();
1512f0c3c996SMichael Lotz 		ConvertToVisibleInTopView(&clippedBounds);
1513f0c3c996SMichael Lotz 		if (clippedBounds.Width() < fScreenClipping.Frame().Width()
1514f0c3c996SMichael Lotz 			|| clippedBounds.Height() < fScreenClipping.Frame().Height()) {
1515f0c3c996SMichael Lotz 			BRegion* temp = fWindow->GetRegion();
1516f0c3c996SMichael Lotz 			if (temp) {
1517f0c3c996SMichael Lotz 				temp->Set((clipping_rect)clippedBounds);
1518f0c3c996SMichael Lotz 				fScreenClipping.IntersectWith(temp);
1519f0c3c996SMichael Lotz 				fWindow->RecycleRegion(temp);
1520f0c3c996SMichael Lotz 			}
1521f0c3c996SMichael Lotz 		}
1522f0c3c996SMichael Lotz 
1523f0c3c996SMichael Lotz 		fScreenClipping.IntersectWith(windowContentClipping);
1524f0c3c996SMichael Lotz 		fScreenClippingValid = true;
1525f0c3c996SMichael Lotz 	}
1526f0c3c996SMichael Lotz 
1527f0c3c996SMichael Lotz 	return fScreenClipping;
1528f0c3c996SMichael Lotz }
1529f0c3c996SMichael Lotz 
1530f0c3c996SMichael Lotz 
1531953d895eSAxel Dörfler void
1532953d895eSAxel Dörfler View::_MoveScreenClipping(int32 x, int32 y, bool deep)
1533953d895eSAxel Dörfler {
1534f0c3c996SMichael Lotz 	if (fScreenClippingValid) {
1535953d895eSAxel Dörfler 		fScreenClipping.OffsetBy(x, y);
1536f0c3c996SMichael Lotz 		delete fScreenAndUserClipping;
1537f0c3c996SMichael Lotz 		fScreenAndUserClipping = NULL;
1538f0c3c996SMichael Lotz 	}
1539953d895eSAxel Dörfler 
1540953d895eSAxel Dörfler 	if (deep) {
1541953d895eSAxel Dörfler 		// move the childrens screen clipping as well
1542953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
1543953d895eSAxel Dörfler 			child->_MoveScreenClipping(x, y, deep);
1544953d895eSAxel Dörfler 		}
1545953d895eSAxel Dörfler 	}
1546953d895eSAxel Dörfler }
1547953d895eSAxel Dörfler 
1548