xref: /haiku/src/servers/app/View.cpp (revision b5ba4badb3098efc0ef2fb32cf8347823379dd75)
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>
137f9368caSlooncraz  *		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
resize_frame(IntRect & frame,uint32 resizingMode,int32 x,int32 y)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 
View(IntRect frame,IntPoint scrollingOffset,const char * name,int32 token,uint32 resizeMode,uint32 flags)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 }),
947f9368caSlooncraz 	fWhichViewColor(B_NO_COLOR),
957f9368caSlooncraz 	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 {
129779ab335SX512 	if (fDrawState.IsSet())
130953d895eSAxel Dörfler 		fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
131953d895eSAxel Dörfler }
132953d895eSAxel Dörfler 
133953d895eSAxel Dörfler 
~View()134953d895eSAxel Dörfler View::~View()
135953d895eSAxel Dörfler {
136953d895eSAxel Dörfler 	// iterate over children and delete each one
137437b1927SAxel Dörfler 	View* view = fFirstChild;
138437b1927SAxel Dörfler 	while (view) {
139437b1927SAxel Dörfler 		View* toast = view;
140437b1927SAxel Dörfler 		view = view->fNextSibling;
141953d895eSAxel Dörfler 		delete toast;
142953d895eSAxel Dörfler 	}
143953d895eSAxel Dörfler }
144953d895eSAxel Dörfler 
145953d895eSAxel Dörfler 
146953d895eSAxel Dörfler IntRect
Bounds() const147953d895eSAxel Dörfler View::Bounds() const
148953d895eSAxel Dörfler {
149953d895eSAxel Dörfler 	IntRect bounds(fScrollingOffset.x, fScrollingOffset.y,
150953d895eSAxel Dörfler 		fScrollingOffset.x + fFrame.Width(),
151953d895eSAxel Dörfler 		fScrollingOffset.y + fFrame.Height());
152953d895eSAxel Dörfler 	return bounds;
153953d895eSAxel Dörfler }
154953d895eSAxel Dörfler 
155953d895eSAxel Dörfler 
156953d895eSAxel Dörfler void
ConvertToVisibleInTopView(IntRect * bounds) const157953d895eSAxel Dörfler View::ConvertToVisibleInTopView(IntRect* bounds) const
158953d895eSAxel Dörfler {
159953d895eSAxel Dörfler 	*bounds = *bounds & Bounds();
160953d895eSAxel Dörfler 	// NOTE: this step is necessary even if we don't have a parent!
1616f2a446eSJulian Harnath 	bounds->OffsetBy(fFrame.left - fScrollingOffset.x,
1626f2a446eSJulian Harnath 		fFrame.top - fScrollingOffset.y);
163953d895eSAxel Dörfler 
164953d895eSAxel Dörfler 	if (fParent)
165953d895eSAxel Dörfler 		fParent->ConvertToVisibleInTopView(bounds);
166953d895eSAxel Dörfler }
167953d895eSAxel Dörfler 
168953d895eSAxel Dörfler 
169953d895eSAxel Dörfler void
AttachedToWindow(::Window * window)170953d895eSAxel Dörfler View::AttachedToWindow(::Window* window)
171953d895eSAxel Dörfler {
172953d895eSAxel Dörfler 	fWindow = window;
173953d895eSAxel Dörfler 
174953d895eSAxel Dörfler 	// an ugly hack to detect the desktop background
175437b1927SAxel Dörfler 	if (window->Feel() == kDesktopWindowFeel && Parent() == TopView())
176953d895eSAxel Dörfler 		fIsDesktopBackground = true;
177953d895eSAxel Dörfler 
178953d895eSAxel Dörfler 	// insert view into local token space
179953d895eSAxel Dörfler 	if (fWindow != NULL) {
180953d895eSAxel Dörfler 		fWindow->ServerWindow()->App()->ViewTokens().SetToken(fToken,
181953d895eSAxel Dörfler 			B_HANDLER_TOKEN, this);
182953d895eSAxel Dörfler 	}
183953d895eSAxel Dörfler 
184953d895eSAxel Dörfler 	// attach child views as well
185953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
186953d895eSAxel Dörfler 		child->AttachedToWindow(window);
187953d895eSAxel Dörfler }
188953d895eSAxel Dörfler 
189953d895eSAxel Dörfler 
190953d895eSAxel Dörfler void
DetachedFromWindow()191953d895eSAxel Dörfler View::DetachedFromWindow()
192953d895eSAxel Dörfler {
193953d895eSAxel Dörfler 	// remove view from local token space
194edb62548SMichael Lotz 	if (fWindow != NULL && fWindow->ServerWindow()->App() != NULL)
195953d895eSAxel Dörfler 		fWindow->ServerWindow()->App()->ViewTokens().RemoveToken(fToken);
196953d895eSAxel Dörfler 
197953d895eSAxel Dörfler 	fWindow = NULL;
198953d895eSAxel Dörfler 	// detach child views as well
199953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
200953d895eSAxel Dörfler 		child->DetachedFromWindow();
201953d895eSAxel Dörfler }
202953d895eSAxel Dörfler 
203953d895eSAxel Dörfler 
204953d895eSAxel Dörfler // #pragma mark -
205953d895eSAxel Dörfler 
206953d895eSAxel Dörfler 
207e1a30115SAdrien Destugues DrawingEngine*
GetDrawingEngine() const208e1a30115SAdrien Destugues View::GetDrawingEngine() const
209e1a30115SAdrien Destugues {
210e1a30115SAdrien Destugues 	return Window()->GetDrawingEngine();
211e1a30115SAdrien Destugues }
212e1a30115SAdrien Destugues 
213e1a30115SAdrien Destugues 
214e1a30115SAdrien Destugues ServerPicture*
GetPicture(int32 token) const215e1a30115SAdrien Destugues View::GetPicture(int32 token) const
216e1a30115SAdrien Destugues {
217e1a30115SAdrien Destugues 	return Window()->ServerWindow()->App()->GetPicture(token);
218e1a30115SAdrien Destugues }
219e1a30115SAdrien Destugues 
220e1a30115SAdrien Destugues 
221e1a30115SAdrien Destugues void
ResyncDrawState()222e1a30115SAdrien Destugues View::ResyncDrawState()
223e1a30115SAdrien Destugues {
224e1a30115SAdrien Destugues 	return Window()->ServerWindow()->ResyncDrawState();
225e1a30115SAdrien Destugues }
226e1a30115SAdrien Destugues 
227e1a30115SAdrien Destugues 
228e1a30115SAdrien Destugues void
UpdateCurrentDrawingRegion()229e1a30115SAdrien Destugues View::UpdateCurrentDrawingRegion()
230e1a30115SAdrien Destugues {
231e1a30115SAdrien Destugues 	return Window()->ServerWindow()->UpdateCurrentDrawingRegion();
232e1a30115SAdrien Destugues }
233e1a30115SAdrien Destugues 
234e1a30115SAdrien Destugues 
235953d895eSAxel Dörfler void
AddChild(View * view)236437b1927SAxel Dörfler View::AddChild(View* view)
237953d895eSAxel Dörfler {
238437b1927SAxel Dörfler 	if (view->fParent) {
239953d895eSAxel Dörfler 		printf("View::AddChild() - View already has a parent\n");
240953d895eSAxel Dörfler 		return;
241953d895eSAxel Dörfler 	}
242953d895eSAxel Dörfler 
243437b1927SAxel Dörfler 	view->fParent = this;
244953d895eSAxel Dörfler 
245953d895eSAxel Dörfler 	if (!fLastChild) {
246953d895eSAxel Dörfler 		// no children yet
247437b1927SAxel Dörfler 		fFirstChild = view;
248953d895eSAxel Dörfler 	} else {
249437b1927SAxel Dörfler 		// append view to formerly last child
250437b1927SAxel Dörfler 		fLastChild->fNextSibling = view;
251437b1927SAxel Dörfler 		view->fPreviousSibling = fLastChild;
252953d895eSAxel Dörfler 	}
253437b1927SAxel Dörfler 	fLastChild = view;
254953d895eSAxel Dörfler 
255437b1927SAxel Dörfler 	view->UpdateVisibleDeep(fVisible);
256953d895eSAxel Dörfler 
257437b1927SAxel Dörfler 	if (view->IsVisible())
258953d895eSAxel Dörfler 		RebuildClipping(false);
259953d895eSAxel Dörfler 
260953d895eSAxel Dörfler 	if (fWindow) {
261437b1927SAxel Dörfler 		view->AttachedToWindow(fWindow);
262953d895eSAxel Dörfler 
263437b1927SAxel Dörfler 		if (view->IsVisible()) {
264953d895eSAxel Dörfler 			// trigger redraw
265437b1927SAxel Dörfler 			IntRect clippedFrame = view->Frame();
266953d895eSAxel Dörfler 			ConvertToVisibleInTopView(&clippedFrame);
2670d312feaSAugustin Cavalier 
2680d312feaSAugustin Cavalier 			BRegion dirty;
2690d312feaSAugustin Cavalier 			dirty.Set((clipping_rect)clippedFrame);
2700d312feaSAugustin Cavalier 			fWindow->MarkContentDirtyAsync(dirty);
271953d895eSAxel Dörfler 		}
272953d895eSAxel Dörfler 	}
273953d895eSAxel Dörfler }
274953d895eSAxel Dörfler 
275953d895eSAxel Dörfler 
276953d895eSAxel Dörfler bool
RemoveChild(View * view)277437b1927SAxel Dörfler View::RemoveChild(View* view)
278953d895eSAxel Dörfler {
2793e8d3c5fSMichael Lotz 	if (view == NULL || view->fParent != this) {
280953d895eSAxel Dörfler 		printf("View::RemoveChild(%p - %s) - View is not child of "
281437b1927SAxel Dörfler 			"this (%p) view!\n", view, view ? view->Name() : NULL, this);
282953d895eSAxel Dörfler 		return false;
283953d895eSAxel Dörfler 	}
284953d895eSAxel Dörfler 
285437b1927SAxel Dörfler 	view->fParent = NULL;
286953d895eSAxel Dörfler 
287437b1927SAxel Dörfler 	if (fLastChild == view)
288437b1927SAxel Dörfler 		fLastChild = view->fPreviousSibling;
289437b1927SAxel Dörfler 		// view->fNextSibling would be NULL
290953d895eSAxel Dörfler 
291437b1927SAxel Dörfler 	if (fFirstChild == view )
292437b1927SAxel Dörfler 		fFirstChild = view->fNextSibling;
293437b1927SAxel Dörfler 		// view->fPreviousSibling would be NULL
294953d895eSAxel Dörfler 
295437b1927SAxel Dörfler 	// connect child before and after view
296437b1927SAxel Dörfler 	if (view->fPreviousSibling)
297437b1927SAxel Dörfler 		view->fPreviousSibling->fNextSibling = view->fNextSibling;
298953d895eSAxel Dörfler 
299437b1927SAxel Dörfler 	if (view->fNextSibling)
300437b1927SAxel Dörfler 		view->fNextSibling->fPreviousSibling = view->fPreviousSibling;
301953d895eSAxel Dörfler 
302437b1927SAxel Dörfler 	// view has no siblings anymore
303437b1927SAxel Dörfler 	view->fPreviousSibling = NULL;
304437b1927SAxel Dörfler 	view->fNextSibling = NULL;
305953d895eSAxel Dörfler 
306437b1927SAxel Dörfler 	if (view->IsVisible()) {
307437b1927SAxel Dörfler 		Overlay* overlay = view->_Overlay();
308953d895eSAxel Dörfler 		if (overlay != NULL)
309953d895eSAxel Dörfler 			overlay->Hide();
310953d895eSAxel Dörfler 
311953d895eSAxel Dörfler 		RebuildClipping(false);
312953d895eSAxel Dörfler 	}
313953d895eSAxel Dörfler 
314953d895eSAxel Dörfler 	if (fWindow) {
315437b1927SAxel Dörfler 		view->DetachedFromWindow();
316953d895eSAxel Dörfler 
317437b1927SAxel Dörfler 		if (fVisible && view->IsVisible()) {
318953d895eSAxel Dörfler 			// trigger redraw
319437b1927SAxel Dörfler 			IntRect clippedFrame = view->Frame();
320953d895eSAxel Dörfler 			ConvertToVisibleInTopView(&clippedFrame);
3210d312feaSAugustin Cavalier 
3220d312feaSAugustin Cavalier 			BRegion dirty;
3230d312feaSAugustin Cavalier 			dirty.Set((clipping_rect)clippedFrame);
3240d312feaSAugustin Cavalier 			fWindow->MarkContentDirtyAsync(dirty);
325953d895eSAxel Dörfler 		}
326953d895eSAxel Dörfler 	}
327953d895eSAxel Dörfler 
328953d895eSAxel Dörfler 	return true;
329953d895eSAxel Dörfler }
330953d895eSAxel Dörfler 
331953d895eSAxel Dörfler 
332953d895eSAxel Dörfler View*
TopView()333437b1927SAxel Dörfler View::TopView()
334953d895eSAxel Dörfler {
335953d895eSAxel Dörfler 	// returns the top level view of the hirarchy,
336953d895eSAxel Dörfler 	// it doesn't have to be the top level of a window
337953d895eSAxel Dörfler 
338953d895eSAxel Dörfler 	if (fParent)
339437b1927SAxel Dörfler 		return fParent->TopView();
340953d895eSAxel Dörfler 
341953d895eSAxel Dörfler 	return this;
342953d895eSAxel Dörfler }
343953d895eSAxel Dörfler 
344953d895eSAxel Dörfler 
345953d895eSAxel Dörfler uint32
CountChildren(bool deep) const346953d895eSAxel Dörfler View::CountChildren(bool deep) const
347953d895eSAxel Dörfler {
348953d895eSAxel Dörfler 	uint32 count = 0;
349953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
350953d895eSAxel Dörfler 		count++;
351953d895eSAxel Dörfler 		if (deep) {
352953d895eSAxel Dörfler 			count += child->CountChildren(deep);
353953d895eSAxel Dörfler 		}
354953d895eSAxel Dörfler 	}
355953d895eSAxel Dörfler 	return count;
356953d895eSAxel Dörfler }
357953d895eSAxel Dörfler 
358953d895eSAxel Dörfler 
359953d895eSAxel Dörfler void
CollectTokensForChildren(BList * tokenMap) const360953d895eSAxel Dörfler View::CollectTokensForChildren(BList* tokenMap) const
361953d895eSAxel Dörfler {
362953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
363953d895eSAxel Dörfler 		tokenMap->AddItem((void*)child);
364953d895eSAxel Dörfler 		child->CollectTokensForChildren(tokenMap);
365953d895eSAxel Dörfler 	}
366953d895eSAxel Dörfler }
367953d895eSAxel Dörfler 
368953d895eSAxel Dörfler 
369953d895eSAxel Dörfler #if 0
370953d895eSAxel Dörfler bool
371953d895eSAxel Dörfler View::MarkAt(DrawingEngine* engine, const BPoint& where, int32 level)
372953d895eSAxel Dörfler {
373953d895eSAxel Dörfler 	BRect rect(fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
374953d895eSAxel Dörfler 
375953d895eSAxel Dörfler 	if (Parent() != NULL) {
376953d895eSAxel Dörfler 		Parent()->ConvertToScreen(&rect);
377953d895eSAxel Dörfler 		if (!rect.Contains(where))
378953d895eSAxel Dörfler 			return false;
379953d895eSAxel Dörfler 
380953d895eSAxel Dörfler 		engine->StrokeRect(rect, (rgb_color){level * 30, level * 30, level * 30});
381953d895eSAxel Dörfler 	}
382953d895eSAxel Dörfler 
383953d895eSAxel Dörfler 
384953d895eSAxel Dörfler 	bool found = false;
385953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
386953d895eSAxel Dörfler 		found |= child->MarkAt(engine, where, level + 1);
387953d895eSAxel Dörfler 	}
388953d895eSAxel Dörfler 
389953d895eSAxel Dörfler 	if (!found) {
390953d895eSAxel Dörfler 		rgb_color color = {0};
391953d895eSAxel Dörfler 		switch (level % 2) {
392953d895eSAxel Dörfler 			case 0: color.green = rand() % 256; break;
393953d895eSAxel Dörfler 			case 1: color.blue = rand() % 256; break;
394953d895eSAxel Dörfler 		}
395953d895eSAxel Dörfler 
396953d895eSAxel Dörfler 		rect.InsetBy(1, 1);
397953d895eSAxel Dörfler 		//engine->FillRegion(fLocalClipping, (rgb_color){255, 255, 0, 10});
398953d895eSAxel Dörfler 		engine->StrokeRect(rect, color);
399953d895eSAxel Dörfler 		rect.InsetBy(1, 1);
400953d895eSAxel Dörfler 		engine->StrokeRect(rect, color);
401953d895eSAxel Dörfler 	}
402953d895eSAxel Dörfler 
403953d895eSAxel Dörfler 	return true;
404953d895eSAxel Dörfler }
405953d895eSAxel Dörfler #endif
406953d895eSAxel Dörfler 
407953d895eSAxel Dörfler 
408953d895eSAxel Dörfler void
FindViews(uint32 flags,BObjectList<View> & list,int32 & left)409953d895eSAxel Dörfler View::FindViews(uint32 flags, BObjectList<View>& list, int32& left)
410953d895eSAxel Dörfler {
411953d895eSAxel Dörfler 	if ((Flags() & flags) == flags) {
412953d895eSAxel Dörfler 		list.AddItem(this);
413953d895eSAxel Dörfler 		left--;
414953d895eSAxel Dörfler 		return;
415953d895eSAxel Dörfler 	}
416953d895eSAxel Dörfler 
417953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
418953d895eSAxel Dörfler 		child->FindViews(flags, list, left);
419953d895eSAxel Dörfler 		if (left == 0)
420953d895eSAxel Dörfler 			break;
421953d895eSAxel Dörfler 	}
422953d895eSAxel Dörfler }
423953d895eSAxel Dörfler 
424953d895eSAxel Dörfler 
4257f9368caSlooncraz bool
HasView(View * view)4267f9368caSlooncraz View::HasView(View* view)
4277f9368caSlooncraz {
4287f9368caSlooncraz 	if (view == this)
4297f9368caSlooncraz 		return true;
4307f9368caSlooncraz 
4317f9368caSlooncraz 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
4327f9368caSlooncraz 		if (child->HasView(view))
4337f9368caSlooncraz 			return true;
4347f9368caSlooncraz 	}
4357f9368caSlooncraz 
4367f9368caSlooncraz 	return false;
4377f9368caSlooncraz }
4387f9368caSlooncraz 
4397f9368caSlooncraz 
440953d895eSAxel Dörfler View*
ViewAt(const BPoint & where)441953d895eSAxel Dörfler View::ViewAt(const BPoint& where)
442953d895eSAxel Dörfler {
443953d895eSAxel Dörfler 	if (!fVisible)
444953d895eSAxel Dörfler 		return NULL;
445953d895eSAxel Dörfler 
446953d895eSAxel Dörfler 	IntRect frame = Frame();
447953d895eSAxel Dörfler 	if (Parent() != NULL)
4486f2a446eSJulian Harnath 		Parent()->LocalToScreenTransform().Apply(&frame);
449953d895eSAxel Dörfler 
450953d895eSAxel Dörfler 	if (!frame.Contains(where))
451953d895eSAxel Dörfler 		return NULL;
452953d895eSAxel Dörfler 
453953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
454437b1927SAxel Dörfler 		View* view = child->ViewAt(where);
455437b1927SAxel Dörfler 		if (view != NULL)
456437b1927SAxel Dörfler 			return view;
457953d895eSAxel Dörfler 	}
458953d895eSAxel Dörfler 
459953d895eSAxel Dörfler 	return this;
460953d895eSAxel Dörfler }
461953d895eSAxel Dörfler 
462953d895eSAxel Dörfler 
463953d895eSAxel Dörfler // #pragma mark -
464953d895eSAxel Dörfler 
465953d895eSAxel Dörfler 
466953d895eSAxel Dörfler void
SetName(const char * string)467953d895eSAxel Dörfler View::SetName(const char* string)
468953d895eSAxel Dörfler {
469953d895eSAxel Dörfler 	fName.SetTo(string);
470953d895eSAxel Dörfler }
471953d895eSAxel Dörfler 
472953d895eSAxel Dörfler 
473953d895eSAxel Dörfler void
SetFlags(uint32 flags)474953d895eSAxel Dörfler View::SetFlags(uint32 flags)
475953d895eSAxel Dörfler {
47647102c07SX512 	uint32 oldFlags = fFlags;
477953d895eSAxel Dörfler 	fFlags = flags;
47847102c07SX512 
47947102c07SX512 	// Child view with B_TRANSPARENT_BACKGROUND flag change clipping of
48047102c07SX512 	// parent view.
48147102c07SX512 	if (fParent != NULL
48247102c07SX512 		&& IsVisible()
48347102c07SX512 		&& (((oldFlags & B_TRANSPARENT_BACKGROUND) != 0)
48447102c07SX512 			!= ((fFlags & B_TRANSPARENT_BACKGROUND) != 0))) {
48547102c07SX512 		fParent->RebuildClipping(false);
48647102c07SX512 	}
48747102c07SX512 
488953d895eSAxel Dörfler 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
489953d895eSAxel Dörfler }
490953d895eSAxel Dörfler 
491953d895eSAxel Dörfler 
492953d895eSAxel Dörfler void
SetViewBitmap(ServerBitmap * bitmap,IntRect sourceRect,IntRect destRect,int32 resizingMode,int32 options)493953d895eSAxel Dörfler View::SetViewBitmap(ServerBitmap* bitmap, IntRect sourceRect,
494953d895eSAxel Dörfler 	IntRect destRect, int32 resizingMode, int32 options)
495953d895eSAxel Dörfler {
496953d895eSAxel Dörfler 	if (fViewBitmap != NULL) {
497953d895eSAxel Dörfler 		Overlay* overlay = _Overlay();
498953d895eSAxel Dörfler 
499953d895eSAxel Dörfler 		if (bitmap != NULL) {
500953d895eSAxel Dörfler 			// take over overlay token from current overlay (if it has any)
501953d895eSAxel Dörfler 			Overlay* newOverlay = bitmap->Overlay();
502953d895eSAxel Dörfler 
503953d895eSAxel Dörfler 			if (overlay != NULL && newOverlay != NULL)
504953d895eSAxel Dörfler 				newOverlay->TakeOverToken(overlay);
505953d895eSAxel Dörfler 		} else if (overlay != NULL)
506953d895eSAxel Dörfler 			overlay->Hide();
507953d895eSAxel Dörfler 	}
508953d895eSAxel Dörfler 
50960d30785SX512 	fViewBitmap.SetTo(bitmap, false);
510953d895eSAxel Dörfler 	fBitmapSource = sourceRect;
511953d895eSAxel Dörfler 	fBitmapDestination = destRect;
512953d895eSAxel Dörfler 	fBitmapResizingMode = resizingMode;
513953d895eSAxel Dörfler 	fBitmapOptions = options;
514953d895eSAxel Dörfler 
515953d895eSAxel Dörfler 	_UpdateOverlayView();
516953d895eSAxel Dörfler }
517953d895eSAxel Dörfler 
518953d895eSAxel Dörfler 
519953d895eSAxel Dörfler ::Overlay*
_Overlay() const520953d895eSAxel Dörfler View::_Overlay() const
521953d895eSAxel Dörfler {
522953d895eSAxel Dörfler 	if (fViewBitmap == NULL)
523953d895eSAxel Dörfler 		return NULL;
524953d895eSAxel Dörfler 
525953d895eSAxel Dörfler 	return fViewBitmap->Overlay();
526953d895eSAxel Dörfler }
527953d895eSAxel Dörfler 
528953d895eSAxel Dörfler 
529953d895eSAxel Dörfler void
_UpdateOverlayView() const530953d895eSAxel Dörfler View::_UpdateOverlayView() const
531953d895eSAxel Dörfler {
532953d895eSAxel Dörfler 	Overlay* overlay = _Overlay();
533953d895eSAxel Dörfler 	if (overlay == NULL)
534953d895eSAxel Dörfler 		return;
535953d895eSAxel Dörfler 
536953d895eSAxel Dörfler 	IntRect destination = fBitmapDestination;
5376f2a446eSJulian Harnath 	LocalToScreenTransform().Apply(&destination);
538953d895eSAxel Dörfler 
539953d895eSAxel Dörfler 	overlay->Configure(fBitmapSource, destination);
540953d895eSAxel Dörfler }
541953d895eSAxel Dörfler 
542953d895eSAxel Dörfler 
543953d895eSAxel Dörfler /*!
544953d895eSAxel Dörfler 	This method is called whenever the window is resized or moved - would
545953d895eSAxel Dörfler 	be nice to have a better solution for this, though.
546953d895eSAxel Dörfler */
547953d895eSAxel Dörfler void
UpdateOverlay()548953d895eSAxel Dörfler View::UpdateOverlay()
549953d895eSAxel Dörfler {
550953d895eSAxel Dörfler 	if (!IsVisible())
551953d895eSAxel Dörfler 		return;
552953d895eSAxel Dörfler 
553953d895eSAxel Dörfler 	if (_Overlay() != NULL) {
554953d895eSAxel Dörfler 		_UpdateOverlayView();
555953d895eSAxel Dörfler 	} else {
556953d895eSAxel Dörfler 		// recursively ask children of this view
557953d895eSAxel Dörfler 
558953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
559953d895eSAxel Dörfler 			child->UpdateOverlay();
560953d895eSAxel Dörfler 		}
561953d895eSAxel Dörfler 	}
562953d895eSAxel Dörfler }
563953d895eSAxel Dörfler 
564953d895eSAxel Dörfler 
565953d895eSAxel Dörfler // #pragma mark -
566953d895eSAxel Dörfler 
567953d895eSAxel Dörfler 
568953d895eSAxel Dörfler void
_LocalToScreenTransform(SimpleTransform & transform) const5696f2a446eSJulian Harnath View::_LocalToScreenTransform(SimpleTransform& transform) const
570953d895eSAxel Dörfler {
5716f2a446eSJulian Harnath 	const View* view = this;
5726f2a446eSJulian Harnath 	int32 offsetX = 0;
5736f2a446eSJulian Harnath 	int32 offsetY = 0;
5746f2a446eSJulian Harnath 	do {
5756f2a446eSJulian Harnath 		offsetX += view->fFrame.left - view->fScrollingOffset.x;
5766f2a446eSJulian Harnath 		offsetY += view->fFrame.top  - view->fScrollingOffset.y;
5776f2a446eSJulian Harnath 		view = view->fParent;
5786f2a446eSJulian Harnath 	} while (view != NULL);
5796f2a446eSJulian Harnath 
5806f2a446eSJulian Harnath 	transform.AddOffset(offsetX, offsetY);
581953d895eSAxel Dörfler }
582953d895eSAxel Dörfler 
583953d895eSAxel Dörfler 
584953d895eSAxel Dörfler void
_ScreenToLocalTransform(SimpleTransform & transform) const5856f2a446eSJulian Harnath View::_ScreenToLocalTransform(SimpleTransform& transform) const
586953d895eSAxel Dörfler {
5876f2a446eSJulian Harnath 	const View* view = this;
5886f2a446eSJulian Harnath 	int32 offsetX = 0;
5896f2a446eSJulian Harnath 	int32 offsetY = 0;
5906f2a446eSJulian Harnath 	do {
5916f2a446eSJulian Harnath 		offsetX += view->fScrollingOffset.x - view->fFrame.left;
5926f2a446eSJulian Harnath 		offsetY += view->fScrollingOffset.y - view->fFrame.top;
5936f2a446eSJulian Harnath 		view = view->fParent;
5946f2a446eSJulian Harnath 	} while (view != NULL);
595953d895eSAxel Dörfler 
5966f2a446eSJulian Harnath 	transform.AddOffset(offsetX, offsetY);
597953d895eSAxel Dörfler }
598953d895eSAxel Dörfler 
599953d895eSAxel Dörfler 
600953d895eSAxel Dörfler // #pragma mark -
601953d895eSAxel Dörfler 
602953d895eSAxel Dörfler 
603953d895eSAxel Dörfler void
MoveBy(int32 x,int32 y,BRegion * dirtyRegion)604953d895eSAxel Dörfler View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
605953d895eSAxel Dörfler {
606953d895eSAxel Dörfler 	if (x == 0 && y == 0)
607953d895eSAxel Dörfler 		return;
608953d895eSAxel Dörfler 
609953d895eSAxel Dörfler 	fFrame.OffsetBy(x, y);
610953d895eSAxel Dörfler 
611953d895eSAxel Dörfler 	// to move on screen, we must not be hidden and we must have a parent
612953d895eSAxel Dörfler 	if (fVisible && fParent && dirtyRegion) {
613953d895eSAxel Dörfler #if 1
614953d895eSAxel Dörfler // based on redraw on new location
615953d895eSAxel Dörfler 		// the place were we are now visible
616953d895eSAxel Dörfler 		IntRect newVisibleBounds(Bounds());
617953d895eSAxel Dörfler 		// we can use the frame of the old
618953d895eSAxel Dörfler 		// local clipping to see which parts need invalidation
619953d895eSAxel Dörfler 		IntRect oldVisibleBounds(newVisibleBounds);
620953d895eSAxel Dörfler 		oldVisibleBounds.OffsetBy(-x, -y);
6216f2a446eSJulian Harnath 		LocalToScreenTransform().Apply(&oldVisibleBounds);
622953d895eSAxel Dörfler 
623953d895eSAxel Dörfler 		ConvertToVisibleInTopView(&newVisibleBounds);
624953d895eSAxel Dörfler 
625953d895eSAxel Dörfler 		dirtyRegion->Include((clipping_rect)oldVisibleBounds);
626953d895eSAxel Dörfler 		// newVisibleBounds already is in screen coords
627953d895eSAxel Dörfler 		dirtyRegion->Include((clipping_rect)newVisibleBounds);
628953d895eSAxel Dörfler #else
629953d895eSAxel Dörfler // blitting version, invalidates
630953d895eSAxel Dörfler // old contents
631953d895eSAxel Dörfler 		IntRect oldVisibleBounds(Bounds());
632953d895eSAxel Dörfler 		IntRect newVisibleBounds(oldVisibleBounds);
633953d895eSAxel Dörfler 		oldVisibleBounds.OffsetBy(-x, -y);
6346f2a446eSJulian Harnath 		LocalToScreenTransform().Apply(&oldVisibleBounds);
635953d895eSAxel Dörfler 
636953d895eSAxel Dörfler 		// NOTE: using ConvertToVisibleInTopView()
637953d895eSAxel Dörfler 		// instead of ConvertToScreen()! see below
638953d895eSAxel Dörfler 		ConvertToVisibleInTopView(&newVisibleBounds);
639953d895eSAxel Dörfler 
640953d895eSAxel Dörfler 		newVisibleBounds.OffsetBy(-x, -y);
641953d895eSAxel Dörfler 
642953d895eSAxel Dörfler 		// clipping oldVisibleBounds to newVisibleBounds
643953d895eSAxel Dörfler 		// makes sure we don't copy parts hidden under
644953d895eSAxel Dörfler 		// parent views
645953d895eSAxel Dörfler 		BRegion* region = fWindow->GetRegion();
646953d895eSAxel Dörfler 		if (region) {
647953d895eSAxel Dörfler 			region->Set(oldVisibleBounds & newVisibleBounds);
648953d895eSAxel Dörfler 			fWindow->CopyContents(region, x, y);
649953d895eSAxel Dörfler 
650953d895eSAxel Dörfler 			region->Set(oldVisibleBounds);
651953d895eSAxel Dörfler 			newVisibleBounds.OffsetBy(x, y);
652953d895eSAxel Dörfler 			region->Exclude((clipping_rect)newVisibleBounds);
653953d895eSAxel Dörfler 			dirtyRegion->Include(dirty);
654953d895eSAxel Dörfler 
655953d895eSAxel Dörfler 			fWindow->RecycleRegion(region);
656953d895eSAxel Dörfler 		}
657953d895eSAxel Dörfler 
658953d895eSAxel Dörfler #endif
659953d895eSAxel Dörfler 	}
660953d895eSAxel Dörfler 
661953d895eSAxel Dörfler 	if (!fParent) {
662953d895eSAxel Dörfler 		// the top view's screen clipping does not change,
663953d895eSAxel Dörfler 		// because no parts are clipped away from parent
664953d895eSAxel Dörfler 		// views
665953d895eSAxel Dörfler 		_MoveScreenClipping(x, y, true);
666953d895eSAxel Dörfler 	} else {
667953d895eSAxel Dörfler 		// parts might have been revealed from underneath
668953d895eSAxel Dörfler 		// the parent, or might now be hidden underneath
669953d895eSAxel Dörfler 		// the parent, this is taken care of when building
670953d895eSAxel Dörfler 		// the screen clipping
671953d895eSAxel Dörfler 		InvalidateScreenClipping();
672953d895eSAxel Dörfler 	}
673953d895eSAxel Dörfler }
674953d895eSAxel Dörfler 
675953d895eSAxel Dörfler 
676953d895eSAxel Dörfler void
ResizeBy(int32 x,int32 y,BRegion * dirtyRegion)677953d895eSAxel Dörfler View::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
678953d895eSAxel Dörfler {
679953d895eSAxel Dörfler 	if (x == 0 && y == 0)
680953d895eSAxel Dörfler 		return;
681953d895eSAxel Dörfler 
682953d895eSAxel Dörfler 	fFrame.right += x;
683953d895eSAxel Dörfler 	fFrame.bottom += y;
684953d895eSAxel Dörfler 
685953d895eSAxel Dörfler 	if (fVisible && dirtyRegion) {
686953d895eSAxel Dörfler 		IntRect oldBounds(Bounds());
687953d895eSAxel Dörfler 		oldBounds.right -= x;
688953d895eSAxel Dörfler 		oldBounds.bottom -= y;
689953d895eSAxel Dörfler 
690953d895eSAxel Dörfler 		BRegion* dirty = fWindow->GetRegion();
691953d895eSAxel Dörfler 		if (!dirty)
692953d895eSAxel Dörfler 			return;
693953d895eSAxel Dörfler 
694953d895eSAxel Dörfler 		dirty->Set((clipping_rect)Bounds());
695953d895eSAxel Dörfler 		dirty->Include((clipping_rect)oldBounds);
696953d895eSAxel Dörfler 
697953d895eSAxel Dörfler 		if (!(fFlags & B_FULL_UPDATE_ON_RESIZE)) {
698953d895eSAxel Dörfler 			// the dirty region is just the difference of
699953d895eSAxel Dörfler 			// old and new bounds
700953d895eSAxel Dörfler 			dirty->Exclude((clipping_rect)(oldBounds & Bounds()));
701953d895eSAxel Dörfler 		}
702953d895eSAxel Dörfler 
703953d895eSAxel Dörfler 		InvalidateScreenClipping();
704953d895eSAxel Dörfler 
705953d895eSAxel Dörfler 		if (dirty->CountRects() > 0) {
706953d895eSAxel Dörfler 			if ((fFlags & B_DRAW_ON_CHILDREN) == 0) {
707953d895eSAxel Dörfler 				// exclude children, they are expected to
708953d895eSAxel Dörfler 				// include their own dirty regions in ParentResized()
709953d895eSAxel Dörfler 				for (View* child = FirstChild(); child;
710953d895eSAxel Dörfler 						child = child->NextSibling()) {
7116ab29b93SX512 					if (!child->IsVisible()
71247102c07SX512 						|| (child->fFlags & B_TRANSPARENT_BACKGROUND) != 0) {
713953d895eSAxel Dörfler 						continue;
7146ab29b93SX512 					}
715953d895eSAxel Dörfler 					IntRect previousChildVisible(
716953d895eSAxel Dörfler 						child->Frame() & oldBounds & Bounds());
717953d895eSAxel Dörfler 					if (dirty->Frame().Intersects(previousChildVisible)) {
718953d895eSAxel Dörfler 						dirty->Exclude((clipping_rect)previousChildVisible);
719953d895eSAxel Dörfler 					}
720953d895eSAxel Dörfler 				}
721953d895eSAxel Dörfler 			}
722953d895eSAxel Dörfler 
7236f2a446eSJulian Harnath 			LocalToScreenTransform().Apply(dirty);
724953d895eSAxel Dörfler 			dirtyRegion->Include(dirty);
725953d895eSAxel Dörfler 		}
726953d895eSAxel Dörfler 		fWindow->RecycleRegion(dirty);
727953d895eSAxel Dörfler 	}
728953d895eSAxel Dörfler 
729953d895eSAxel Dörfler 	// layout the children
730953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
731953d895eSAxel Dörfler 		child->ParentResized(x, y, dirtyRegion);
732953d895eSAxel Dörfler 
733953d895eSAxel Dörfler 	// view bitmap
73495e95feeSMichael Lotz 	if (fViewBitmap != NULL)
735953d895eSAxel Dörfler 		resize_frame(fBitmapDestination, fBitmapResizingMode, x, y);
736953d895eSAxel Dörfler 
737953d895eSAxel Dörfler 	// at this point, children are at their new locations,
738953d895eSAxel Dörfler 	// so we can rebuild the clipping
739953d895eSAxel Dörfler 	// TODO: when the implementation of Hide() and Show() is
740953d895eSAxel Dörfler 	// complete, see if this should be avoided
741953d895eSAxel Dörfler 	RebuildClipping(false);
742953d895eSAxel Dörfler }
743953d895eSAxel Dörfler 
744953d895eSAxel Dörfler 
745953d895eSAxel Dörfler void
ParentResized(int32 x,int32 y,BRegion * dirtyRegion)746953d895eSAxel Dörfler View::ParentResized(int32 x, int32 y, BRegion* dirtyRegion)
747953d895eSAxel Dörfler {
748953d895eSAxel Dörfler 	IntRect newFrame = fFrame;
749953d895eSAxel Dörfler 	resize_frame(newFrame, fResizeMode & 0x0000ffff, x, y);
750953d895eSAxel Dörfler 
751953d895eSAxel Dörfler 	if (newFrame != fFrame) {
752953d895eSAxel Dörfler 		// careful, MoveBy will change fFrame
753953d895eSAxel Dörfler 		int32 widthDiff = (int32)(newFrame.Width() - fFrame.Width());
754953d895eSAxel Dörfler 		int32 heightDiff = (int32)(newFrame.Height() - fFrame.Height());
755953d895eSAxel Dörfler 
756953d895eSAxel Dörfler 		MoveBy(newFrame.left - fFrame.left,
757953d895eSAxel Dörfler 			newFrame.top - fFrame.top, dirtyRegion);
758953d895eSAxel Dörfler 
759953d895eSAxel Dörfler 		ResizeBy(widthDiff, heightDiff, dirtyRegion);
760953d895eSAxel Dörfler 	} else {
761953d895eSAxel Dörfler 		// TODO: this covers the fact that our screen clipping might change
762953d895eSAxel Dörfler 		// when the parent changes its size, even though our frame stays
763953d895eSAxel Dörfler 		// the same - there might be a way to test for this, but axeld doesn't
764953d895eSAxel Dörfler 		// know, stippi should look into this when he's back :)
765953d895eSAxel Dörfler 		InvalidateScreenClipping();
766953d895eSAxel Dörfler 	}
767953d895eSAxel Dörfler }
768953d895eSAxel Dörfler 
769953d895eSAxel Dörfler 
770953d895eSAxel Dörfler void
ScrollBy(int32 x,int32 y,BRegion * dirtyRegion)771953d895eSAxel Dörfler View::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
772953d895eSAxel Dörfler {
773953d895eSAxel Dörfler 	if (!fVisible || !fWindow) {
774953d895eSAxel Dörfler 		fScrollingOffset.x += x;
775953d895eSAxel Dörfler 		fScrollingOffset.y += y;
776953d895eSAxel Dörfler 		return;
777953d895eSAxel Dörfler 	}
778953d895eSAxel Dörfler 
779953d895eSAxel Dörfler 	// blitting version, invalidates
780953d895eSAxel Dörfler 	// old contents
781953d895eSAxel Dörfler 
782953d895eSAxel Dörfler 	// remember old bounds for tracking dirty region
783953d895eSAxel Dörfler 	IntRect oldBounds(Bounds());
784953d895eSAxel Dörfler 
785953d895eSAxel Dörfler 	// NOTE: using ConvertToVisibleInTopView()
786953d895eSAxel Dörfler 	// instead of ConvertToScreen(), this makes
787953d895eSAxel Dörfler 	// sure we don't try to move or invalidate an
788953d895eSAxel Dörfler 	// area hidden underneath the parent view
789953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&oldBounds);
790953d895eSAxel Dörfler 
791953d895eSAxel Dörfler 	// find the area of the view that can be scrolled,
792953d895eSAxel Dörfler 	// contents are shifted in the opposite direction from scrolling
793953d895eSAxel Dörfler 	IntRect stillVisibleBounds(oldBounds);
794953d895eSAxel Dörfler 	stillVisibleBounds.OffsetBy(x, y);
795953d895eSAxel Dörfler 	stillVisibleBounds = stillVisibleBounds & oldBounds;
796953d895eSAxel Dörfler 
797953d895eSAxel Dörfler 	fScrollingOffset.x += x;
798953d895eSAxel Dörfler 	fScrollingOffset.y += y;
799953d895eSAxel Dörfler 
800953d895eSAxel Dörfler 	// do the blit, this will make sure
801953d895eSAxel Dörfler 	// that other more complex dirty regions
802953d895eSAxel Dörfler 	// are taken care of
803953d895eSAxel Dörfler 	BRegion* copyRegion = fWindow->GetRegion();
804953d895eSAxel Dörfler 	if (!copyRegion)
805953d895eSAxel Dörfler 		return;
806953d895eSAxel Dörfler 	copyRegion->Set((clipping_rect)stillVisibleBounds);
807953d895eSAxel Dörfler 	fWindow->CopyContents(copyRegion, -x, -y);
808953d895eSAxel Dörfler 
809953d895eSAxel Dörfler 	// find the dirty region as far as we are
810953d895eSAxel Dörfler 	// concerned
811953d895eSAxel Dörfler 	BRegion* dirty = copyRegion;
812953d895eSAxel Dörfler 		// reuse copyRegion and call it dirty
813953d895eSAxel Dörfler 
814953d895eSAxel Dörfler 	dirty->Set((clipping_rect)oldBounds);
815953d895eSAxel Dörfler 	stillVisibleBounds.OffsetBy(-x, -y);
816953d895eSAxel Dörfler 	dirty->Exclude((clipping_rect)stillVisibleBounds);
817953d895eSAxel Dörfler 	dirtyRegion->Include(dirty);
818953d895eSAxel Dörfler 
819953d895eSAxel Dörfler 	fWindow->RecycleRegion(dirty);
820953d895eSAxel Dörfler 
821953d895eSAxel Dörfler 	// the screen clipping of this view and it's
822953d895eSAxel Dörfler 	// childs is no longer valid
823953d895eSAxel Dörfler 	InvalidateScreenClipping();
824953d895eSAxel Dörfler 	RebuildClipping(false);
825953d895eSAxel Dörfler }
826953d895eSAxel Dörfler 
827953d895eSAxel Dörfler 
828953d895eSAxel Dörfler void
CopyBits(IntRect src,IntRect dst,BRegion & windowContentClipping)829953d895eSAxel Dörfler View::CopyBits(IntRect src, IntRect dst, BRegion& windowContentClipping)
830953d895eSAxel Dörfler {
831953d895eSAxel Dörfler 	if (!fVisible || !fWindow)
832953d895eSAxel Dörfler 		return;
833953d895eSAxel Dörfler 
8341cde68c5SJulian Harnath 	// TODO: figure out what to do when we have a transform which is not
8351cde68c5SJulian Harnath 	// a dilation
8361cde68c5SJulian Harnath 	BAffineTransform transform = CurrentState()->CombinedTransform();
8371cde68c5SJulian Harnath 	if (!transform.IsIdentity() && transform.IsDilation()) {
8381cde68c5SJulian Harnath 		BPoint points[4] = { src.LeftTop(), src.RightBottom(),
8391cde68c5SJulian Harnath 							 dst.LeftTop(), dst.RightBottom() };
8401cde68c5SJulian Harnath 		transform.Apply(&points[0], 4);
8411cde68c5SJulian Harnath 		src.Set(points[0].x, points[0].y, points[1].x, points[1].y);
8421cde68c5SJulian Harnath 		dst.Set(points[2].x, points[2].y, points[3].x, points[3].y);
8431cde68c5SJulian Harnath 	}
8441cde68c5SJulian Harnath 
845953d895eSAxel Dörfler 	// TODO: confirm that in R5 this call is affected by origin and scale
846953d895eSAxel Dörfler 
847953d895eSAxel Dörfler 	// blitting version
848953d895eSAxel Dörfler 
849953d895eSAxel Dörfler 	int32 xOffset = dst.left - src.left;
850953d895eSAxel Dörfler 	int32 yOffset = dst.top - src.top;
851953d895eSAxel Dörfler 
852953d895eSAxel Dörfler 	// figure out which part can be blittet
853953d895eSAxel Dörfler 	IntRect visibleSrc(src);
854953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&visibleSrc);
855953d895eSAxel Dörfler 
856953d895eSAxel Dörfler 	IntRect visibleSrcAtDest(src);
857953d895eSAxel Dörfler 	visibleSrcAtDest.OffsetBy(xOffset, yOffset);
858953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&visibleSrcAtDest);
859953d895eSAxel Dörfler 
860953d895eSAxel Dörfler 	// clip src to visible at dest
861953d895eSAxel Dörfler 	visibleSrcAtDest.OffsetBy(-xOffset, -yOffset);
862953d895eSAxel Dörfler 	visibleSrc = visibleSrc & visibleSrcAtDest;
863953d895eSAxel Dörfler 
864953d895eSAxel Dörfler 	// do the blit, this will make sure
865953d895eSAxel Dörfler 	// that other more complex dirty regions
866953d895eSAxel Dörfler 	// are taken care of
867953d895eSAxel Dörfler 	BRegion* copyRegion = fWindow->GetRegion();
868953d895eSAxel Dörfler 	if (!copyRegion)
869953d895eSAxel Dörfler 		return;
870953d895eSAxel Dörfler 
871953d895eSAxel Dörfler 	// move src rect to destination here for efficiency reasons
872953d895eSAxel Dörfler 	visibleSrc.OffsetBy(xOffset, yOffset);
873953d895eSAxel Dörfler 
874f0c3c996SMichael Lotz 	// we need to interstect the copyRegion two times, onces
875953d895eSAxel Dörfler 	// at the source and once at the destination (here done
876953d895eSAxel Dörfler 	// the other way arround but it doesn't matter)
877953d895eSAxel Dörfler 	// the reason for this is that we are not supposed to visually
878953d895eSAxel Dörfler 	// copy children in the source rect and neither to copy onto
879953d895eSAxel Dörfler 	// children in the destination rect...
880953d895eSAxel Dörfler 	copyRegion->Set((clipping_rect)visibleSrc);
881ea2bcbf4SMichael Lotz 	BRegion *screenAndUserClipping
882ea2bcbf4SMichael Lotz 		= &ScreenAndUserClipping(&windowContentClipping);
883ea2bcbf4SMichael Lotz 	copyRegion->IntersectWith(screenAndUserClipping);
884953d895eSAxel Dörfler 	copyRegion->OffsetBy(-xOffset, -yOffset);
885ea2bcbf4SMichael Lotz 	copyRegion->IntersectWith(screenAndUserClipping);
886953d895eSAxel Dörfler 
887953d895eSAxel Dörfler 	// do the actual blit
888953d895eSAxel Dörfler 	fWindow->CopyContents(copyRegion, xOffset, yOffset);
889953d895eSAxel Dörfler 
890953d895eSAxel Dörfler 	// find the dirty region as far as we are concerned
891953d895eSAxel Dörfler 	IntRect dirtyDst(dst);
892953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&dirtyDst);
893953d895eSAxel Dörfler 
894953d895eSAxel Dörfler 	BRegion* dirty = fWindow->GetRegion();
895953d895eSAxel Dörfler 	if (!dirty) {
896953d895eSAxel Dörfler 		fWindow->RecycleRegion(copyRegion);
897953d895eSAxel Dörfler 		return;
898953d895eSAxel Dörfler 	}
899953d895eSAxel Dörfler 
900953d895eSAxel Dörfler 	// offset copyRegion to destination again
901953d895eSAxel Dörfler 	copyRegion->OffsetBy(xOffset, yOffset);
902953d895eSAxel Dörfler 	// start with destination given by user
903953d895eSAxel Dörfler 	dirty->Set((clipping_rect)dirtyDst);
904953d895eSAxel Dörfler 	// exclude the part that we could copy
905953d895eSAxel Dörfler 	dirty->Exclude(copyRegion);
906953d895eSAxel Dörfler 
907ea2bcbf4SMichael Lotz 	dirty->IntersectWith(screenAndUserClipping);
908*b5ba4badSX512 	fWindow->MarkContentDirty(*dirty, *dirty);
909953d895eSAxel Dörfler 
910953d895eSAxel Dörfler 	fWindow->RecycleRegion(dirty);
911953d895eSAxel Dörfler 	fWindow->RecycleRegion(copyRegion);
912953d895eSAxel Dörfler }
913953d895eSAxel Dörfler 
914953d895eSAxel Dörfler 
915953d895eSAxel Dörfler // #pragma mark -
916953d895eSAxel Dörfler 
917953d895eSAxel Dörfler 
918953d895eSAxel Dörfler void
ColorUpdated(color_which which,rgb_color color)9197f9368caSlooncraz View::ColorUpdated(color_which which, rgb_color color)
9207f9368caSlooncraz {
9217f9368caSlooncraz 	float tint = B_NO_TINT;
9227f9368caSlooncraz 
9237f9368caSlooncraz 	if (fWhichViewColor == which)
9247f9368caSlooncraz 		SetViewColor(tint_color(color, fWhichViewColorTint));
9257f9368caSlooncraz 
9267f9368caSlooncraz 	if (CurrentState()->HighUIColor(&tint) == which)
9277f9368caSlooncraz 		CurrentState()->SetHighColor(tint_color(color, tint));
9287f9368caSlooncraz 
9297f9368caSlooncraz 	if (CurrentState()->LowUIColor(&tint) == which)
9307f9368caSlooncraz 		CurrentState()->SetLowColor(tint_color(color, tint));
9317f9368caSlooncraz 
9327f9368caSlooncraz 	for (View* child = FirstChild(); child != NULL;
9337f9368caSlooncraz 			child = child->NextSibling()) {
9347f9368caSlooncraz 
9357f9368caSlooncraz 		child->ColorUpdated(which, color);
9367f9368caSlooncraz 	}
9377f9368caSlooncraz }
9387f9368caSlooncraz 
9397f9368caSlooncraz 
9407f9368caSlooncraz void
SetViewUIColor(color_which which,float tint)9417f9368caSlooncraz View::SetViewUIColor(color_which which, float tint)
9427f9368caSlooncraz {
9437f9368caSlooncraz 	if (which != B_NO_COLOR) {
9447f9368caSlooncraz 		DesktopSettings settings(fWindow->Desktop());
9457f9368caSlooncraz 		SetViewColor(tint_color(settings.UIColor(which), tint));
9467f9368caSlooncraz 	}
9477f9368caSlooncraz 
9487f9368caSlooncraz 	fWhichViewColor = which;
9497f9368caSlooncraz 	fWhichViewColorTint = tint;
9507f9368caSlooncraz }
9517f9368caSlooncraz 
9527f9368caSlooncraz 
9537f9368caSlooncraz color_which
ViewUIColor(float * tint)9547f9368caSlooncraz View::ViewUIColor(float* tint)
9557f9368caSlooncraz {
9567f9368caSlooncraz 	if (tint != NULL)
9577f9368caSlooncraz 		*tint = fWhichViewColorTint;
9587f9368caSlooncraz 
9597f9368caSlooncraz 	return fWhichViewColor;
9607f9368caSlooncraz }
9617f9368caSlooncraz 
9627f9368caSlooncraz 
9637f9368caSlooncraz // #pragma mark -
9647f9368caSlooncraz 
9657f9368caSlooncraz 
9667f9368caSlooncraz void
PushState()967953d895eSAxel Dörfler View::PushState()
968953d895eSAxel Dörfler {
96960d30785SX512 	DrawState* previousState = fDrawState.Detach();
97060d30785SX512 	DrawState* newState = previousState->PushState();
97160d30785SX512 	if (newState == NULL)
97260d30785SX512 		newState = previousState;
97360d30785SX512 
97460d30785SX512 	fDrawState.SetTo(newState);
975e1a30115SAdrien Destugues 	// In BeAPI, B_SUBPIXEL_PRECISE is a view flag, and not affected by the
976e1a30115SAdrien Destugues 	// view state. Our implementation moves it to the draw state, but let's
977e1a30115SAdrien Destugues 	// be compatible with the API here and make it survive accross state
978e1a30115SAdrien Destugues 	// changes.
979953d895eSAxel Dörfler 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
980953d895eSAxel Dörfler }
981953d895eSAxel Dörfler 
982953d895eSAxel Dörfler 
983953d895eSAxel Dörfler void
PopState()984953d895eSAxel Dörfler View::PopState()
985953d895eSAxel Dörfler {
986953d895eSAxel Dörfler 	if (fDrawState->PreviousState() == NULL) {
987953d895eSAxel Dörfler 		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), "
988953d895eSAxel Dörfler 			"but there is NO state on stack!\n", Name());
989953d895eSAxel Dörfler 		return;
990953d895eSAxel Dörfler 	}
991953d895eSAxel Dörfler 
9922e44cfceSStephan Aßmus 	bool rebuildClipping = fDrawState->HasAdditionalClipping();
993953d895eSAxel Dörfler 
99460d30785SX512 	fDrawState.SetTo(fDrawState->PopState());
995953d895eSAxel Dörfler 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
996953d895eSAxel Dörfler 
997953d895eSAxel Dörfler 	// rebuild clipping
998953d895eSAxel Dörfler 	// (the clipping from the popped state is not effective anymore)
999953d895eSAxel Dörfler 	if (rebuildClipping)
1000953d895eSAxel Dörfler 		RebuildClipping(false);
1001953d895eSAxel Dörfler }
1002953d895eSAxel Dörfler 
1003953d895eSAxel Dörfler 
1004e1a30115SAdrien Destugues // #pragma mark -
1005e1a30115SAdrien Destugues 
1006e1a30115SAdrien Destugues 
1007953d895eSAxel Dörfler void
SetEventMask(uint32 eventMask,uint32 options)1008953d895eSAxel Dörfler View::SetEventMask(uint32 eventMask, uint32 options)
1009953d895eSAxel Dörfler {
1010953d895eSAxel Dörfler 	fEventMask = eventMask;
1011953d895eSAxel Dörfler 	fEventOptions = options;
1012953d895eSAxel Dörfler }
1013953d895eSAxel Dörfler 
1014953d895eSAxel Dörfler 
1015953d895eSAxel Dörfler void
SetCursor(ServerCursor * cursor)1016953d895eSAxel Dörfler View::SetCursor(ServerCursor* cursor)
1017953d895eSAxel Dörfler {
1018953d895eSAxel Dörfler 	if (cursor == fCursor)
1019953d895eSAxel Dörfler 		return;
1020953d895eSAxel Dörfler 
102160d30785SX512 	fCursor.SetTo(cursor, false);
1022953d895eSAxel Dörfler }
1023953d895eSAxel Dörfler 
1024953d895eSAxel Dörfler 
1025953d895eSAxel Dörfler void
SetPicture(ServerPicture * picture)1026953d895eSAxel Dörfler View::SetPicture(ServerPicture* picture)
1027953d895eSAxel Dörfler {
102885a7877fSAxel Dörfler 	if (picture == fPicture)
102985a7877fSAxel Dörfler 		return;
103085a7877fSAxel Dörfler 
103160d30785SX512 	fPicture.SetTo(picture, false);
1032953d895eSAxel Dörfler }
1033953d895eSAxel Dörfler 
1034953d895eSAxel Dörfler 
1035953d895eSAxel Dörfler void
BlendAllLayers()1036551438b9SJulian Harnath View::BlendAllLayers()
1037551438b9SJulian Harnath {
1038551438b9SJulian Harnath 	if (fPicture == NULL)
1039551438b9SJulian Harnath 		return;
104060d30785SX512 	Layer* layer = dynamic_cast<Layer*>(fPicture.Get());
1041551438b9SJulian Harnath 	if (layer == NULL)
1042551438b9SJulian Harnath 		return;
1043551438b9SJulian Harnath 	BlendLayer(layer);
1044551438b9SJulian Harnath }
1045551438b9SJulian Harnath 
1046551438b9SJulian Harnath 
1047551438b9SJulian Harnath void
Draw(DrawingEngine * drawingEngine,const BRegion * effectiveClipping,const BRegion * windowContentClipping,bool deep)1048*b5ba4badSX512 View::Draw(DrawingEngine* drawingEngine, const BRegion* effectiveClipping,
1049*b5ba4badSX512 	const BRegion* windowContentClipping, bool deep)
1050953d895eSAxel Dörfler {
1051953d895eSAxel Dörfler 	if (!fVisible) {
1052953d895eSAxel Dörfler 		// child views cannot be visible either
1053953d895eSAxel Dörfler 		return;
1054953d895eSAxel Dörfler 	}
1055953d895eSAxel Dörfler 
1056953d895eSAxel Dörfler 	if (fViewBitmap != NULL || fViewColor != B_TRANSPARENT_COLOR) {
1057953d895eSAxel Dörfler 		// we can only draw within our own area
105855a88f0cSStephan Aßmus 		BRegion* redraw;
105955a88f0cSStephan Aßmus 		if ((fFlags & B_DRAW_ON_CHILDREN) != 0) {
106055a88f0cSStephan Aßmus 			// The client may actually want to prevent the background to
106155a88f0cSStephan Aßmus 			// be painted outside the user clipping.
106255a88f0cSStephan Aßmus 			redraw = fWindow->GetRegion(
106355a88f0cSStephan Aßmus 				ScreenAndUserClipping(windowContentClipping));
106455a88f0cSStephan Aßmus 		} else {
106555a88f0cSStephan Aßmus 			// Ignore user clipping as in BeOS for painting the background.
106655a88f0cSStephan Aßmus 			redraw = fWindow->GetRegion(
1067f0c3c996SMichael Lotz 				_ScreenClipping(windowContentClipping));
106855a88f0cSStephan Aßmus 		}
1069953d895eSAxel Dörfler 		if (!redraw)
1070953d895eSAxel Dörfler 			return;
1071953d895eSAxel Dörfler 		// add the current clipping
1072953d895eSAxel Dörfler 		redraw->IntersectWith(effectiveClipping);
1073953d895eSAxel Dörfler 
1074953d895eSAxel Dörfler 		Overlay* overlayCookie = _Overlay();
1075953d895eSAxel Dörfler 
1076953d895eSAxel Dörfler 		if (fViewBitmap != NULL && overlayCookie == NULL) {
1077953d895eSAxel Dörfler 			// draw view bitmap
1078953d895eSAxel Dörfler 			// TODO: support other options!
1079953d895eSAxel Dörfler 			BRect rect = fBitmapDestination;
10806f2a446eSJulian Harnath 			PenToScreenTransform().Apply(&rect);
1081953d895eSAxel Dörfler 
1082953d895eSAxel Dörfler 			align_rect_to_pixels(&rect);
1083953d895eSAxel Dörfler 
1084953d895eSAxel Dörfler 			if (fBitmapOptions & B_TILE_BITMAP_Y) {
1085953d895eSAxel Dörfler 				// move rect up as much as needed
1086953d895eSAxel Dörfler 				while (rect.top > redraw->Frame().top)
1087953d895eSAxel Dörfler 					rect.OffsetBy(0.0, -(rect.Height() + 1));
1088953d895eSAxel Dörfler 			}
1089953d895eSAxel Dörfler 			if (fBitmapOptions & B_TILE_BITMAP_X) {
1090953d895eSAxel Dörfler 				// move rect left as much as needed
1091953d895eSAxel Dörfler 				while (rect.left > redraw->Frame().left)
1092953d895eSAxel Dörfler 					rect.OffsetBy(-(rect.Width() + 1), 0.0);
1093953d895eSAxel Dörfler 			}
1094953d895eSAxel Dörfler 
1095953d895eSAxel Dörfler // XXX: locking removed because the Window keeps the engine locked
1096953d895eSAxel Dörfler // because it keeps track of syncing right now
1097953d895eSAxel Dörfler 
1098953d895eSAxel Dörfler 			// lock the drawing engine for as long as we need the clipping
1099953d895eSAxel Dörfler 			// to be valid
1100953d895eSAxel Dörfler 			if (rect.IsValid()/* && drawingEngine->Lock()*/) {
1101953d895eSAxel Dörfler 				drawingEngine->ConstrainClippingRegion(redraw);
1102953d895eSAxel Dörfler 
11032b4f382aSStephan Aßmus 				drawing_mode oldMode;
11042b4f382aSStephan Aßmus 				drawingEngine->SetDrawingMode(B_OP_COPY, oldMode);
11052b4f382aSStephan Aßmus 
1106953d895eSAxel Dörfler 				if (fBitmapOptions & B_TILE_BITMAP) {
1107953d895eSAxel Dörfler 					// tile across entire view
1108953d895eSAxel Dörfler 
1109953d895eSAxel Dörfler 					float start = rect.left;
1110953d895eSAxel Dörfler 					while (rect.top < redraw->Frame().bottom) {
1111953d895eSAxel Dörfler 						while (rect.left < redraw->Frame().right) {
1112953d895eSAxel Dörfler 							drawingEngine->DrawBitmap(fViewBitmap,
11137eed63a1SStephan Aßmus 								fBitmapSource, rect, fBitmapOptions);
1114953d895eSAxel Dörfler 							rect.OffsetBy(rect.Width() + 1, 0.0);
1115953d895eSAxel Dörfler 						}
1116953d895eSAxel Dörfler 						rect.OffsetBy(start - rect.left, rect.Height() + 1);
1117953d895eSAxel Dörfler 					}
1118953d895eSAxel Dörfler 					// nothing left to be drawn
1119953d895eSAxel Dörfler 					redraw->MakeEmpty();
1120953d895eSAxel Dörfler 				} else if (fBitmapOptions & B_TILE_BITMAP_X) {
1121953d895eSAxel Dörfler 					// tile in x direction
1122953d895eSAxel Dörfler 
1123953d895eSAxel Dörfler 					while (rect.left < redraw->Frame().right) {
1124953d895eSAxel Dörfler 						drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
11257eed63a1SStephan Aßmus 							rect, fBitmapOptions);
1126953d895eSAxel Dörfler 						rect.OffsetBy(rect.Width() + 1, 0.0);
1127953d895eSAxel Dörfler 					}
1128953d895eSAxel Dörfler 					// remove horizontal stripe from clipping
1129953d895eSAxel Dörfler 					rect.left = redraw->Frame().left;
1130953d895eSAxel Dörfler 					rect.right = redraw->Frame().right;
1131953d895eSAxel Dörfler 					redraw->Exclude(rect);
1132953d895eSAxel Dörfler 				} else if (fBitmapOptions & B_TILE_BITMAP_Y) {
1133953d895eSAxel Dörfler 					// tile in y direction
1134953d895eSAxel Dörfler 
1135953d895eSAxel Dörfler 					while (rect.top < redraw->Frame().bottom) {
1136953d895eSAxel Dörfler 						drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
11377eed63a1SStephan Aßmus 							rect, fBitmapOptions);
1138953d895eSAxel Dörfler 						rect.OffsetBy(0.0, rect.Height() + 1);
1139953d895eSAxel Dörfler 					}
1140953d895eSAxel Dörfler 					// remove vertical stripe from clipping
1141953d895eSAxel Dörfler 					rect.top = redraw->Frame().top;
1142953d895eSAxel Dörfler 					rect.bottom = redraw->Frame().bottom;
1143953d895eSAxel Dörfler 					redraw->Exclude(rect);
1144953d895eSAxel Dörfler 				} else {
1145953d895eSAxel Dörfler 					// no tiling at all
1146953d895eSAxel Dörfler 
1147953d895eSAxel Dörfler 					drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
11487eed63a1SStephan Aßmus 						rect, fBitmapOptions);
1149953d895eSAxel Dörfler 					redraw->Exclude(rect);
1150953d895eSAxel Dörfler 				}
1151953d895eSAxel Dörfler 
11522b4f382aSStephan Aßmus 				drawingEngine->SetDrawingMode(oldMode);
11532b4f382aSStephan Aßmus 
1154953d895eSAxel Dörfler 				// NOTE: It is ok not to reset the clipping, that
1155953d895eSAxel Dörfler 				// would only waste time
1156953d895eSAxel Dörfler //				drawingEngine->Unlock();
1157953d895eSAxel Dörfler 			}
1158953d895eSAxel Dörfler 
1159953d895eSAxel Dörfler 		}
1160953d895eSAxel Dörfler 
1161953d895eSAxel Dörfler 		if (fViewColor != B_TRANSPARENT_COLOR) {
1162953d895eSAxel Dörfler 			// fill visible region with view color,
1163953d895eSAxel Dörfler 			// this version of FillRegion ignores any
1164953d895eSAxel Dörfler 			// clipping, that's why "redraw" needs to
1165953d895eSAxel Dörfler 			// be correct
1166953d895eSAxel Dörfler // see #634
1167953d895eSAxel Dörfler //			if (redraw->Frame().left < 0 || redraw->Frame().top < 0) {
1168953d895eSAxel Dörfler //				char message[1024];
1169953d895eSAxel Dörfler //				BRect c = effectiveClipping->Frame();
1170953d895eSAxel Dörfler //				BRect w = windowContentClipping->Frame();
1171953d895eSAxel Dörfler //				BRect r = redraw->Frame();
1172953d895eSAxel Dörfler //				sprintf(message, "invalid background: current clipping: (%d, %d)->(%d, %d), "
1173953d895eSAxel Dörfler //					"window content: (%d, %d)->(%d, %d), redraw: (%d, %d)->(%d, %d)",
1174953d895eSAxel Dörfler //					(int)c.left, (int)c.top, (int)c.right, (int)c.bottom,
1175953d895eSAxel Dörfler //					(int)w.left, (int)w.top, (int)w.right, (int)w.bottom,
1176953d895eSAxel Dörfler //					(int)r.left, (int)r.top, (int)r.right, (int)r.bottom);
1177953d895eSAxel Dörfler //				debugger(message);
1178953d895eSAxel Dörfler //			}
1179953d895eSAxel Dörfler 
1180953d895eSAxel Dörfler 			drawingEngine->FillRegion(*redraw, overlayCookie != NULL
1181953d895eSAxel Dörfler 				? overlayCookie->Color() : fViewColor);
1182953d895eSAxel Dörfler 		}
1183953d895eSAxel Dörfler 
1184953d895eSAxel Dörfler 		fWindow->RecycleRegion(redraw);
1185953d895eSAxel Dörfler 	}
1186953d895eSAxel Dörfler 
1187953d895eSAxel Dörfler 	fBackgroundDirty = false;
1188953d895eSAxel Dörfler 
1189953d895eSAxel Dörfler 	// let children draw
1190953d895eSAxel Dörfler 	if (deep) {
1191953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
1192953d895eSAxel Dörfler 			child->Draw(drawingEngine, effectiveClipping,
1193953d895eSAxel Dörfler 				windowContentClipping, deep);
1194953d895eSAxel Dörfler 		}
1195953d895eSAxel Dörfler 	}
1196953d895eSAxel Dörfler }
1197953d895eSAxel Dörfler 
1198953d895eSAxel Dörfler 
1199953d895eSAxel Dörfler // #pragma mark -
1200953d895eSAxel Dörfler 
1201953d895eSAxel Dörfler 
1202953d895eSAxel Dörfler void
MouseDown(BMessage * message,BPoint where)1203953d895eSAxel Dörfler View::MouseDown(BMessage* message, BPoint where)
1204953d895eSAxel Dörfler {
1205953d895eSAxel Dörfler 	// empty hook method
1206953d895eSAxel Dörfler }
1207953d895eSAxel Dörfler 
1208953d895eSAxel Dörfler 
1209953d895eSAxel Dörfler void
MouseUp(BMessage * message,BPoint where)1210953d895eSAxel Dörfler View::MouseUp(BMessage* message, BPoint where)
1211953d895eSAxel Dörfler {
1212953d895eSAxel Dörfler 	// empty hook method
1213953d895eSAxel Dörfler }
1214953d895eSAxel Dörfler 
1215953d895eSAxel Dörfler 
1216953d895eSAxel Dörfler void
MouseMoved(BMessage * message,BPoint where)1217953d895eSAxel Dörfler View::MouseMoved(BMessage* message, BPoint where)
1218953d895eSAxel Dörfler {
1219953d895eSAxel Dörfler 	// empty hook method
1220953d895eSAxel Dörfler }
1221953d895eSAxel Dörfler 
1222953d895eSAxel Dörfler 
1223953d895eSAxel Dörfler // #pragma mark -
1224953d895eSAxel Dörfler 
1225953d895eSAxel Dörfler 
1226953d895eSAxel Dörfler void
SetHidden(bool hidden)1227953d895eSAxel Dörfler View::SetHidden(bool hidden)
1228953d895eSAxel Dörfler {
1229953d895eSAxel Dörfler 	if (fHidden != hidden) {
1230953d895eSAxel Dörfler 		fHidden = hidden;
1231953d895eSAxel Dörfler 
1232953d895eSAxel Dörfler 		// recurse into children and update their visible flag
1233953d895eSAxel Dörfler 		bool oldVisible = fVisible;
1234953d895eSAxel Dörfler 		UpdateVisibleDeep(fParent ? fParent->IsVisible() : !fHidden);
1235953d895eSAxel Dörfler 		if (oldVisible != fVisible) {
1236953d895eSAxel Dörfler 			// Include or exclude us from the parent area, and update the
1237953d895eSAxel Dörfler 			// children's clipping as well when the view will be visible
1238953d895eSAxel Dörfler 			if (fParent)
1239953d895eSAxel Dörfler 				fParent->RebuildClipping(fVisible);
1240953d895eSAxel Dörfler 			else
1241953d895eSAxel Dörfler 				RebuildClipping(fVisible);
1242953d895eSAxel Dörfler 
1243953d895eSAxel Dörfler 			if (fWindow) {
1244953d895eSAxel Dörfler 				// trigger a redraw
1245953d895eSAxel Dörfler 				IntRect clippedBounds = Bounds();
1246953d895eSAxel Dörfler 				ConvertToVisibleInTopView(&clippedBounds);
12470d312feaSAugustin Cavalier 
1248*b5ba4badSX512 				BRegion dirty, expose;
12490d312feaSAugustin Cavalier 				dirty.Set((clipping_rect)clippedBounds);
1250*b5ba4badSX512 				fWindow->MarkContentDirty(dirty, expose);
1251953d895eSAxel Dörfler 			}
1252953d895eSAxel Dörfler 		}
1253953d895eSAxel Dörfler 	}
1254953d895eSAxel Dörfler }
1255953d895eSAxel Dörfler 
1256953d895eSAxel Dörfler 
1257953d895eSAxel Dörfler bool
IsHidden() const1258953d895eSAxel Dörfler View::IsHidden() const
1259953d895eSAxel Dörfler {
1260953d895eSAxel Dörfler 	return fHidden;
1261953d895eSAxel Dörfler }
1262953d895eSAxel Dörfler 
1263953d895eSAxel Dörfler 
1264953d895eSAxel Dörfler void
UpdateVisibleDeep(bool parentVisible)1265953d895eSAxel Dörfler View::UpdateVisibleDeep(bool parentVisible)
1266953d895eSAxel Dörfler {
1267953d895eSAxel Dörfler 	bool wasVisible = fVisible;
1268953d895eSAxel Dörfler 
1269953d895eSAxel Dörfler 	fVisible = parentVisible && !fHidden;
1270953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
1271953d895eSAxel Dörfler 		child->UpdateVisibleDeep(fVisible);
1272953d895eSAxel Dörfler 
1273953d895eSAxel Dörfler 	// overlay handling
1274953d895eSAxel Dörfler 
1275953d895eSAxel Dörfler 	Overlay* overlay = _Overlay();
1276953d895eSAxel Dörfler 	if (overlay == NULL)
1277953d895eSAxel Dörfler 		return;
1278953d895eSAxel Dörfler 
1279953d895eSAxel Dörfler 	if (fVisible && !wasVisible)
1280953d895eSAxel Dörfler 		_UpdateOverlayView();
1281953d895eSAxel Dörfler 	else if (!fVisible && wasVisible)
1282953d895eSAxel Dörfler 		overlay->Hide();
1283953d895eSAxel Dörfler }
1284953d895eSAxel Dörfler 
1285953d895eSAxel Dörfler 
1286953d895eSAxel Dörfler // #pragma mark -
1287953d895eSAxel Dörfler 
1288953d895eSAxel Dörfler 
1289953d895eSAxel Dörfler void
MarkBackgroundDirty()1290953d895eSAxel Dörfler View::MarkBackgroundDirty()
1291953d895eSAxel Dörfler {
1292953d895eSAxel Dörfler 	if (fBackgroundDirty)
1293953d895eSAxel Dörfler 		return;
1294953d895eSAxel Dörfler 	fBackgroundDirty = true;
1295953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
1296953d895eSAxel Dörfler 		child->MarkBackgroundDirty();
1297953d895eSAxel Dörfler }
1298953d895eSAxel Dörfler 
1299953d895eSAxel Dörfler 
1300953d895eSAxel Dörfler void
AddTokensForViewsInRegion(BPrivate::PortLink & link,BRegion & region,BRegion * windowContentClipping)1301437b1927SAxel Dörfler View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region,
1302953d895eSAxel Dörfler 	BRegion* windowContentClipping)
1303953d895eSAxel Dörfler {
1304953d895eSAxel Dörfler 	if (!fVisible)
1305953d895eSAxel Dörfler 		return;
1306953d895eSAxel Dörfler 
1307581e6786SStephan Aßmus 	{
1308581e6786SStephan Aßmus 		// NOTE: use scope in order to reduce stack space requirements
1309581e6786SStephan Aßmus 
1310581e6786SStephan Aßmus 		// This check will prevent descending the view hierarchy
1311581e6786SStephan Aßmus 		// any further than necessary
1312953d895eSAxel Dörfler 		IntRect screenBounds(Bounds());
13136f2a446eSJulian Harnath 		LocalToScreenTransform().Apply(&screenBounds);
1314953d895eSAxel Dörfler 		if (!region.Intersects((clipping_rect)screenBounds))
1315953d895eSAxel Dörfler 			return;
1316953d895eSAxel Dörfler 
1317581e6786SStephan Aßmus 		// Unfortunately, we intersecting another region, but otherwise
1318581e6786SStephan Aßmus 		// we couldn't provide the exact update rect to the client
1319581e6786SStephan Aßmus 		BRegion localDirty = _ScreenClipping(windowContentClipping);
1320581e6786SStephan Aßmus 		localDirty.IntersectWith(&region);
1321581e6786SStephan Aßmus 		if (localDirty.CountRects() > 0) {
1322953d895eSAxel Dörfler 			link.Attach<int32>(fToken);
1323581e6786SStephan Aßmus 			link.Attach<BRect>(localDirty.Frame());
1324953d895eSAxel Dörfler 		}
1325953d895eSAxel Dörfler 	}
1326953d895eSAxel Dörfler 
1327581e6786SStephan Aßmus 	for (View* child = FirstChild(); child; child = child->NextSibling())
1328581e6786SStephan Aßmus 		child->AddTokensForViewsInRegion(link, region, windowContentClipping);
1329581e6786SStephan Aßmus }
1330581e6786SStephan Aßmus 
1331953d895eSAxel Dörfler 
1332953d895eSAxel Dörfler void
PrintToStream() const1333953d895eSAxel Dörfler View::PrintToStream() const
1334953d895eSAxel Dörfler {
1335953d895eSAxel Dörfler 	printf("View:          %s\n", Name());
13363fed1a15SAlex Smith 	printf("  fToken:           %" B_PRId32 "\n", fToken);
13373fed1a15SAlex Smith 	printf("  fFrame:           IntRect(%" B_PRId32 ", %" B_PRId32 ", %" B_PRId32 ", %" B_PRId32 ")\n",
13383fed1a15SAlex Smith 		fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
13393fed1a15SAlex Smith 	printf("  fScrollingOffset: IntPoint(%" B_PRId32 ", %" B_PRId32 ")\n",
13403fed1a15SAlex Smith 		fScrollingOffset.x, fScrollingOffset.y);
1341953d895eSAxel Dörfler 	printf("  fHidden:          %d\n", fHidden);
1342953d895eSAxel Dörfler 	printf("  fVisible:         %d\n", fVisible);
1343953d895eSAxel Dörfler 	printf("  fWindow:          %p\n", fWindow);
1344953d895eSAxel Dörfler 	printf("  fParent:          %p\n", fParent);
1345953d895eSAxel Dörfler 	printf("  fLocalClipping:\n");
1346953d895eSAxel Dörfler 	fLocalClipping.PrintToStream();
1347953d895eSAxel Dörfler 	printf("  fScreenClipping:\n");
1348953d895eSAxel Dörfler 	fScreenClipping.PrintToStream();
1349953d895eSAxel Dörfler 	printf("  valid:            %d\n", fScreenClippingValid);
1350f0c3c996SMichael Lotz 
1351f0c3c996SMichael Lotz 	printf("  fUserClipping:\n");
1352779ab335SX512 	if (fUserClipping.IsSet())
1353f0c3c996SMichael Lotz 		fUserClipping->PrintToStream();
1354f0c3c996SMichael Lotz 	else
1355f0c3c996SMichael Lotz 		printf("  none\n");
1356f0c3c996SMichael Lotz 
1357f0c3c996SMichael Lotz 	printf("  fScreenAndUserClipping:\n");
1358779ab335SX512 	if (fScreenAndUserClipping.IsSet())
1359f0c3c996SMichael Lotz 		fScreenAndUserClipping->PrintToStream();
1360f0c3c996SMichael Lotz 	else
1361f0c3c996SMichael Lotz 		printf("  invalid\n");
1362f0c3c996SMichael Lotz 
1363953d895eSAxel Dörfler 	printf("  state:\n");
136479ef179cSStephan Aßmus 	printf("    user clipping:  %d\n", fDrawState->HasClipping());
136579ef179cSStephan Aßmus 	BPoint origin = fDrawState->CombinedOrigin();
136679ef179cSStephan Aßmus 	printf("    origin:         BPoint(%.1f, %.1f)\n", origin.x, origin.y);
136779ef179cSStephan Aßmus 	printf("    scale:          %.2f\n", fDrawState->CombinedScale());
1368953d895eSAxel Dörfler 	printf("\n");
1369953d895eSAxel Dörfler }
1370953d895eSAxel Dörfler 
1371953d895eSAxel Dörfler 
1372953d895eSAxel Dörfler void
RebuildClipping(bool deep)1373953d895eSAxel Dörfler View::RebuildClipping(bool deep)
1374953d895eSAxel Dörfler {
1375953d895eSAxel Dörfler 	// the clipping spans over the bounds area
1376953d895eSAxel Dörfler 	fLocalClipping.Set((clipping_rect)Bounds());
1377953d895eSAxel Dörfler 
1378953d895eSAxel Dörfler 	if (View* child = FirstChild()) {
1379953d895eSAxel Dörfler 		// if this view does not draw over children,
1380953d895eSAxel Dörfler 		// exclude all children from the clipping
1381953d895eSAxel Dörfler 		if ((fFlags & B_DRAW_ON_CHILDREN) == 0) {
1382953d895eSAxel Dörfler 			BRegion* childrenRegion = fWindow->GetRegion();
1383953d895eSAxel Dörfler 			if (!childrenRegion)
1384953d895eSAxel Dörfler 				return;
1385953d895eSAxel Dörfler 
1386953d895eSAxel Dörfler 			for (; child; child = child->NextSibling()) {
13876ab29b93SX512 				if (child->IsVisible()
138847102c07SX512 					&& (child->fFlags & B_TRANSPARENT_BACKGROUND) == 0) {
1389953d895eSAxel Dörfler 					childrenRegion->Include((clipping_rect)child->Frame());
1390953d895eSAxel Dörfler 				}
13916ab29b93SX512 			}
1392953d895eSAxel Dörfler 
1393953d895eSAxel Dörfler 			fLocalClipping.Exclude(childrenRegion);
1394953d895eSAxel Dörfler 			fWindow->RecycleRegion(childrenRegion);
1395953d895eSAxel Dörfler 		}
1396953d895eSAxel Dörfler 		// if the operation is "deep", make children rebuild their
1397953d895eSAxel Dörfler 		// clipping too
1398953d895eSAxel Dörfler 		if (deep) {
1399953d895eSAxel Dörfler 			for (child = FirstChild(); child; child = child->NextSibling())
1400953d895eSAxel Dörfler 				child->RebuildClipping(true);
1401953d895eSAxel Dörfler 		}
1402953d895eSAxel Dörfler 	}
1403953d895eSAxel Dörfler 
1404953d895eSAxel Dörfler 	// add the user clipping in case there is one
140579ef179cSStephan Aßmus 	if (fDrawState->HasClipping()) {
1406953d895eSAxel Dörfler 		// NOTE: in case the user sets a user defined clipping region,
1407953d895eSAxel Dörfler 		// rebuilding the clipping is a bit more expensive because there
1408953d895eSAxel Dörfler 		// is no separate "drawing region"... on the other
1409953d895eSAxel Dörfler 		// hand, views for which this feature is actually used will
1410953d895eSAxel Dörfler 		// probably not have any children, so it is not that expensive
1411953d895eSAxel Dörfler 		// after all
1412779ab335SX512 		if (!fUserClipping.IsSet()) {
141360d30785SX512 			fUserClipping.SetTo(new (nothrow) BRegion);
1414779ab335SX512 			if (!fUserClipping.IsSet())
1415953d895eSAxel Dörfler 				return;
1416953d895eSAxel Dörfler 		}
1417953d895eSAxel Dörfler 
141860d30785SX512 		fDrawState->GetCombinedClippingRegion(fUserClipping.Get());
1419f0c3c996SMichael Lotz 	} else {
142060d30785SX512 		fUserClipping.SetTo(NULL);
1421f0c3c996SMichael Lotz 	}
1422f0c3c996SMichael Lotz 
142360d30785SX512 	fScreenAndUserClipping.SetTo(NULL);
1424953d895eSAxel Dörfler 	fScreenClippingValid = false;
1425953d895eSAxel Dörfler }
1426953d895eSAxel Dörfler 
1427953d895eSAxel Dörfler 
1428953d895eSAxel Dörfler BRegion&
ScreenAndUserClipping(const BRegion * windowContentClipping,bool force) const1429*b5ba4badSX512 View::ScreenAndUserClipping(const BRegion* windowContentClipping, bool force) const
1430953d895eSAxel Dörfler {
1431f0c3c996SMichael Lotz 	// no user clipping - return screen clipping directly
1432779ab335SX512 	if (!fUserClipping.IsSet())
1433f0c3c996SMichael Lotz 		return _ScreenClipping(windowContentClipping, force);
1434953d895eSAxel Dörfler 
1435f0c3c996SMichael Lotz 	// combined screen and user clipping already valid
1436779ab335SX512 	if (fScreenAndUserClipping.IsSet())
143760d30785SX512 		return *fScreenAndUserClipping.Get();
1438953d895eSAxel Dörfler 
1439f0c3c996SMichael Lotz 	// build a new combined user and screen clipping
144060d30785SX512 	fScreenAndUserClipping.SetTo(new (nothrow) BRegion(*fUserClipping.Get()));
1441779ab335SX512 	if (!fScreenAndUserClipping.IsSet())
1442953d895eSAxel Dörfler 		return fScreenClipping;
1443f0c3c996SMichael Lotz 
144460d30785SX512 	LocalToScreenTransform().Apply(fScreenAndUserClipping.Get());
1445f0c3c996SMichael Lotz 	fScreenAndUserClipping->IntersectWith(
1446f0c3c996SMichael Lotz 		&_ScreenClipping(windowContentClipping, force));
144760d30785SX512 	return *fScreenAndUserClipping.Get();
1448953d895eSAxel Dörfler }
1449953d895eSAxel Dörfler 
1450953d895eSAxel Dörfler 
1451953d895eSAxel Dörfler void
InvalidateScreenClipping()1452953d895eSAxel Dörfler View::InvalidateScreenClipping()
1453953d895eSAxel Dörfler {
1454953d895eSAxel Dörfler // TODO: appearantly, we are calling ScreenClipping() on
1455953d895eSAxel Dörfler // views who's parents don't have a valid screen clipping yet,
1456953d895eSAxel Dörfler // this messes up the logic that for any given view with
1457953d895eSAxel Dörfler // fScreenClippingValid == false, all children have
1458953d895eSAxel Dörfler // fScreenClippingValid == false too. If this could be made the
1459953d895eSAxel Dörfler // case, we could save some performance here with the commented
1460953d895eSAxel Dörfler // out check, since InvalidateScreenClipping() might be called
1461953d895eSAxel Dörfler // frequently.
1462953d895eSAxel Dörfler // TODO: investigate, if InvalidateScreenClipping() could be
1463953d895eSAxel Dörfler // called in "deep" and "non-deep" mode, ie. see if there are
1464953d895eSAxel Dörfler // any cases where the children would still have valid screen
1465953d895eSAxel Dörfler // clipping, even though the parent's screen clipping becomes
1466953d895eSAxel Dörfler // invalid.
1467953d895eSAxel Dörfler //	if (!fScreenClippingValid)
1468953d895eSAxel Dörfler //		return;
1469953d895eSAxel Dörfler 
147060d30785SX512 	fScreenAndUserClipping.SetTo(NULL);
1471953d895eSAxel Dörfler 	fScreenClippingValid = false;
1472953d895eSAxel Dörfler 	// invalidate the childrens screen clipping as well
1473953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
1474953d895eSAxel Dörfler 		child->InvalidateScreenClipping();
1475953d895eSAxel Dörfler 	}
1476953d895eSAxel Dörfler }
1477953d895eSAxel Dörfler 
1478953d895eSAxel Dörfler 
1479f0c3c996SMichael Lotz BRegion&
_ScreenClipping(const BRegion * windowContentClipping,bool force) const1480*b5ba4badSX512 View::_ScreenClipping(const BRegion* windowContentClipping, bool force) const
1481f0c3c996SMichael Lotz {
1482f0c3c996SMichael Lotz 	if (!fScreenClippingValid || force) {
1483f0c3c996SMichael Lotz 		fScreenClipping = fLocalClipping;
14846f2a446eSJulian Harnath 		LocalToScreenTransform().Apply(&fScreenClipping);
1485f0c3c996SMichael Lotz 
1486f0c3c996SMichael Lotz 		// see if parts of our bounds are hidden underneath
1487f0c3c996SMichael Lotz 		// the parent, the local clipping does not account for this
1488f0c3c996SMichael Lotz 		IntRect clippedBounds = Bounds();
1489f0c3c996SMichael Lotz 		ConvertToVisibleInTopView(&clippedBounds);
1490f0c3c996SMichael Lotz 		if (clippedBounds.Width() < fScreenClipping.Frame().Width()
1491f0c3c996SMichael Lotz 			|| clippedBounds.Height() < fScreenClipping.Frame().Height()) {
14920d312feaSAugustin Cavalier 			BRegion temp;
14930d312feaSAugustin Cavalier 			temp.Set((clipping_rect)clippedBounds);
14940d312feaSAugustin Cavalier 			fScreenClipping.IntersectWith(&temp);
1495f0c3c996SMichael Lotz 		}
1496f0c3c996SMichael Lotz 
1497f0c3c996SMichael Lotz 		fScreenClipping.IntersectWith(windowContentClipping);
1498f0c3c996SMichael Lotz 		fScreenClippingValid = true;
1499f0c3c996SMichael Lotz 	}
1500f0c3c996SMichael Lotz 
1501f0c3c996SMichael Lotz 	return fScreenClipping;
1502f0c3c996SMichael Lotz }
1503f0c3c996SMichael Lotz 
1504f0c3c996SMichael Lotz 
1505953d895eSAxel Dörfler void
_MoveScreenClipping(int32 x,int32 y,bool deep)1506953d895eSAxel Dörfler View::_MoveScreenClipping(int32 x, int32 y, bool deep)
1507953d895eSAxel Dörfler {
1508f0c3c996SMichael Lotz 	if (fScreenClippingValid) {
1509953d895eSAxel Dörfler 		fScreenClipping.OffsetBy(x, y);
151060d30785SX512 		fScreenAndUserClipping.SetTo(NULL);
1511f0c3c996SMichael Lotz 	}
1512953d895eSAxel Dörfler 
1513953d895eSAxel Dörfler 	if (deep) {
1514953d895eSAxel Dörfler 		// move the childrens screen clipping as well
1515953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
1516953d895eSAxel Dörfler 			child->_MoveScreenClipping(x, y, deep);
1517953d895eSAxel Dörfler 		}
1518953d895eSAxel Dörfler 	}
1519953d895eSAxel Dörfler }
1520953d895eSAxel Dörfler 
1521