xref: /haiku/src/servers/app/View.cpp (revision 2e44cfce6671cbb0a5a1658fbb197899def3c73b)
1953d895eSAxel Dörfler /*
2953d895eSAxel Dörfler  * Copyright (c) 2001-2008, 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>
11953d895eSAxel Dörfler  */
12953d895eSAxel Dörfler 
13953d895eSAxel Dörfler 
14953d895eSAxel Dörfler #include "View.h"
15953d895eSAxel Dörfler 
16953d895eSAxel Dörfler #include "BitmapManager.h"
17953d895eSAxel Dörfler #include "Desktop.h"
18953d895eSAxel Dörfler #include "DrawingEngine.h"
19953d895eSAxel Dörfler #include "Overlay.h"
20953d895eSAxel Dörfler #include "ServerApp.h"
21953d895eSAxel Dörfler #include "ServerBitmap.h"
22953d895eSAxel Dörfler #include "ServerCursor.h"
23953d895eSAxel Dörfler #include "ServerPicture.h"
24953d895eSAxel Dörfler #include "ServerWindow.h"
25953d895eSAxel Dörfler #include "Window.h"
26953d895eSAxel Dörfler 
27953d895eSAxel Dörfler #include "drawing_support.h"
28953d895eSAxel Dörfler 
29953d895eSAxel Dörfler #include <List.h>
30953d895eSAxel Dörfler #include <Message.h>
31953d895eSAxel Dörfler #include <PortLink.h>
32953d895eSAxel Dörfler #include <View.h> // for resize modes
33953d895eSAxel Dörfler #include <WindowPrivate.h>
34953d895eSAxel Dörfler 
35991547efSStephan Aßmus #include <GradientLinear.h>
36991547efSStephan Aßmus #include <GradientRadial.h>
37991547efSStephan Aßmus #include <GradientRadialFocus.h>
38991547efSStephan Aßmus #include <GradientDiamond.h>
39991547efSStephan Aßmus #include <GradientConic.h>
40991547efSStephan Aßmus 
41953d895eSAxel Dörfler #include <stdio.h>
42953d895eSAxel Dörfler 
43953d895eSAxel Dörfler #include <new>
44953d895eSAxel Dörfler 
45953d895eSAxel Dörfler using std::nothrow;
46953d895eSAxel Dörfler 
47953d895eSAxel Dörfler 
48953d895eSAxel Dörfler void
49953d895eSAxel Dörfler resize_frame(IntRect& frame, uint32 resizingMode, int32 x, int32 y)
50953d895eSAxel Dörfler {
51953d895eSAxel Dörfler 	// follow with left side
52953d895eSAxel Dörfler 	if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8)
53953d895eSAxel Dörfler 		frame.left += x;
54953d895eSAxel Dörfler 	else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8)
55953d895eSAxel Dörfler 		frame.left += x / 2;
56953d895eSAxel Dörfler 
57953d895eSAxel Dörfler 	// follow with right side
58953d895eSAxel Dörfler 	if ((resizingMode & 0x000FU) == _VIEW_RIGHT_)
59953d895eSAxel Dörfler 		frame.right += x;
60953d895eSAxel Dörfler 	else if ((resizingMode & 0x000FU) == _VIEW_CENTER_)
61953d895eSAxel Dörfler 		frame.right += x / 2;
62953d895eSAxel Dörfler 
63953d895eSAxel Dörfler 	// follow with top side
64953d895eSAxel Dörfler 	if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12)
65953d895eSAxel Dörfler 		frame.top += y;
66953d895eSAxel Dörfler 	else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12)
67953d895eSAxel Dörfler 		frame.top += y / 2;
68953d895eSAxel Dörfler 
69953d895eSAxel Dörfler 	// follow with bottom side
70953d895eSAxel Dörfler 	if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4)
71953d895eSAxel Dörfler 		frame.bottom += y;
72953d895eSAxel Dörfler 	else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4)
73953d895eSAxel Dörfler 		frame.bottom += y / 2;
74953d895eSAxel Dörfler }
75953d895eSAxel Dörfler 
76953d895eSAxel Dörfler 
77953d895eSAxel Dörfler //	#pragma mark -
78953d895eSAxel Dörfler 
79953d895eSAxel Dörfler 
80953d895eSAxel Dörfler View::View(IntRect frame, IntPoint scrollingOffset, const char* name,
81953d895eSAxel Dörfler 		int32 token, uint32 resizeMode, uint32 flags)
82953d895eSAxel Dörfler 	:
83953d895eSAxel Dörfler 	fName(name),
84953d895eSAxel Dörfler 	fToken(token),
85953d895eSAxel Dörfler 
86953d895eSAxel Dörfler 	fFrame(frame),
87953d895eSAxel Dörfler 	fScrollingOffset(scrollingOffset),
88953d895eSAxel Dörfler 
89953d895eSAxel Dörfler 	fViewColor((rgb_color){ 255, 255, 255, 255 }),
90953d895eSAxel Dörfler 	fDrawState(new (nothrow) DrawState),
91953d895eSAxel Dörfler 	fViewBitmap(NULL),
92953d895eSAxel Dörfler 
93953d895eSAxel Dörfler 	fResizeMode(resizeMode),
94953d895eSAxel Dörfler 	fFlags(flags),
95953d895eSAxel Dörfler 
96437b1927SAxel Dörfler 	// Views start visible by default
97953d895eSAxel Dörfler 	fHidden(false),
98953d895eSAxel Dörfler 	fVisible(true),
99953d895eSAxel Dörfler 	fBackgroundDirty(true),
100953d895eSAxel Dörfler 	fIsDesktopBackground(false),
101953d895eSAxel Dörfler 
102953d895eSAxel Dörfler 	fEventMask(0),
103953d895eSAxel Dörfler 	fEventOptions(0),
104953d895eSAxel Dörfler 
105953d895eSAxel Dörfler 	fWindow(NULL),
106953d895eSAxel Dörfler 	fParent(NULL),
107953d895eSAxel Dörfler 
108953d895eSAxel Dörfler 	fFirstChild(NULL),
109953d895eSAxel Dörfler 	fPreviousSibling(NULL),
110953d895eSAxel Dörfler 	fNextSibling(NULL),
111953d895eSAxel Dörfler 	fLastChild(NULL),
112953d895eSAxel Dörfler 
113953d895eSAxel Dörfler 	fCursor(NULL),
114953d895eSAxel Dörfler 	fPicture(NULL),
115953d895eSAxel Dörfler 
116953d895eSAxel Dörfler 	fLocalClipping((BRect)Bounds()),
117953d895eSAxel Dörfler 	fScreenClipping(),
118f0c3c996SMichael Lotz 	fScreenClippingValid(false),
119f0c3c996SMichael Lotz 	fUserClipping(NULL),
120f0c3c996SMichael Lotz 	fScreenAndUserClipping(NULL)
121953d895eSAxel Dörfler {
122953d895eSAxel Dörfler 	if (fDrawState)
123953d895eSAxel Dörfler 		fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
124953d895eSAxel Dörfler }
125953d895eSAxel Dörfler 
126953d895eSAxel Dörfler 
127953d895eSAxel Dörfler View::~View()
128953d895eSAxel Dörfler {
129953d895eSAxel Dörfler 	if (fViewBitmap != NULL)
130953d895eSAxel Dörfler 		gBitmapManager->DeleteBitmap(fViewBitmap);
131953d895eSAxel Dörfler 
132ea2bcbf4SMichael Lotz 	delete fScreenAndUserClipping;
133ea2bcbf4SMichael Lotz 	delete fUserClipping;
134953d895eSAxel Dörfler 	delete fDrawState;
135953d895eSAxel Dörfler 
136437b1927SAxel Dörfler //	if (fWindow && this == fWindow->TopView())
137437b1927SAxel Dörfler //		fWindow->SetTopView(NULL);
138953d895eSAxel Dörfler 
139953d895eSAxel Dörfler 	if (fCursor)
140953d895eSAxel Dörfler 		fCursor->Release();
141953d895eSAxel Dörfler 
142953d895eSAxel Dörfler 	// iterate over children and delete each one
143437b1927SAxel Dörfler 	View* view = fFirstChild;
144437b1927SAxel Dörfler 	while (view) {
145437b1927SAxel Dörfler 		View* toast = view;
146437b1927SAxel Dörfler 		view = view->fNextSibling;
147953d895eSAxel Dörfler 		delete toast;
148953d895eSAxel Dörfler 	}
149953d895eSAxel Dörfler }
150953d895eSAxel Dörfler 
151953d895eSAxel Dörfler 
152953d895eSAxel Dörfler IntRect
153953d895eSAxel Dörfler View::Bounds() const
154953d895eSAxel Dörfler {
155953d895eSAxel Dörfler 	IntRect bounds(fScrollingOffset.x, fScrollingOffset.y,
156953d895eSAxel Dörfler 		fScrollingOffset.x + fFrame.Width(),
157953d895eSAxel Dörfler 		fScrollingOffset.y + fFrame.Height());
158953d895eSAxel Dörfler 	return bounds;
159953d895eSAxel Dörfler }
160953d895eSAxel Dörfler 
161953d895eSAxel Dörfler 
162953d895eSAxel Dörfler void
163953d895eSAxel Dörfler View::ConvertToVisibleInTopView(IntRect* bounds) const
164953d895eSAxel Dörfler {
165953d895eSAxel Dörfler 	*bounds = *bounds & Bounds();
166953d895eSAxel Dörfler 	// NOTE: this step is necessary even if we don't have a parent!
167953d895eSAxel Dörfler 	ConvertToParent(bounds);
168953d895eSAxel Dörfler 
169953d895eSAxel Dörfler 	if (fParent)
170953d895eSAxel Dörfler 		fParent->ConvertToVisibleInTopView(bounds);
171953d895eSAxel Dörfler }
172953d895eSAxel Dörfler 
173953d895eSAxel Dörfler 
174953d895eSAxel Dörfler void
175953d895eSAxel Dörfler View::AttachedToWindow(::Window* window)
176953d895eSAxel Dörfler {
177953d895eSAxel Dörfler 	fWindow = window;
178953d895eSAxel Dörfler 
179953d895eSAxel Dörfler 	// an ugly hack to detect the desktop background
180437b1927SAxel Dörfler 	if (window->Feel() == kDesktopWindowFeel && Parent() == TopView())
181953d895eSAxel Dörfler 		fIsDesktopBackground = true;
182953d895eSAxel Dörfler 
183953d895eSAxel Dörfler 	// insert view into local token space
184953d895eSAxel Dörfler 	if (fWindow != NULL) {
185953d895eSAxel Dörfler 		fWindow->ServerWindow()->App()->ViewTokens().SetToken(fToken,
186953d895eSAxel Dörfler 			B_HANDLER_TOKEN, this);
187953d895eSAxel Dörfler 	}
188953d895eSAxel Dörfler 
189953d895eSAxel Dörfler 	// attach child views as well
190953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
191953d895eSAxel Dörfler 		child->AttachedToWindow(window);
192953d895eSAxel Dörfler }
193953d895eSAxel Dörfler 
194953d895eSAxel Dörfler 
195953d895eSAxel Dörfler void
196953d895eSAxel Dörfler View::DetachedFromWindow()
197953d895eSAxel Dörfler {
198953d895eSAxel Dörfler 	// remove view from local token space
199953d895eSAxel Dörfler 	if (fWindow != NULL)
200953d895eSAxel Dörfler 		fWindow->ServerWindow()->App()->ViewTokens().RemoveToken(fToken);
201953d895eSAxel Dörfler 
202953d895eSAxel Dörfler 	fWindow = NULL;
203953d895eSAxel Dörfler 	// detach child views as well
204953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
205953d895eSAxel Dörfler 		child->DetachedFromWindow();
206953d895eSAxel Dörfler }
207953d895eSAxel Dörfler 
208953d895eSAxel Dörfler 
209953d895eSAxel Dörfler // #pragma mark -
210953d895eSAxel Dörfler 
211953d895eSAxel Dörfler 
212953d895eSAxel Dörfler void
213437b1927SAxel Dörfler View::AddChild(View* view)
214953d895eSAxel Dörfler {
215437b1927SAxel Dörfler 	if (view->fParent) {
216953d895eSAxel Dörfler 		printf("View::AddChild() - View already has a parent\n");
217953d895eSAxel Dörfler 		return;
218953d895eSAxel Dörfler 	}
219953d895eSAxel Dörfler 
220437b1927SAxel Dörfler 	view->fParent = this;
221953d895eSAxel Dörfler 
222953d895eSAxel Dörfler 	if (!fLastChild) {
223953d895eSAxel Dörfler 		// no children yet
224437b1927SAxel Dörfler 		fFirstChild = view;
225953d895eSAxel Dörfler 	} else {
226437b1927SAxel Dörfler 		// append view to formerly last child
227437b1927SAxel Dörfler 		fLastChild->fNextSibling = view;
228437b1927SAxel Dörfler 		view->fPreviousSibling = fLastChild;
229953d895eSAxel Dörfler 	}
230437b1927SAxel Dörfler 	fLastChild = view;
231953d895eSAxel Dörfler 
232437b1927SAxel Dörfler 	view->UpdateVisibleDeep(fVisible);
233953d895eSAxel Dörfler 
234437b1927SAxel Dörfler 	if (view->IsVisible())
235953d895eSAxel Dörfler 		RebuildClipping(false);
236953d895eSAxel Dörfler 
237953d895eSAxel Dörfler 	if (fWindow) {
238437b1927SAxel Dörfler 		view->AttachedToWindow(fWindow);
239953d895eSAxel Dörfler 
240437b1927SAxel Dörfler 		if (view->IsVisible()) {
241953d895eSAxel Dörfler 			// trigger redraw
242437b1927SAxel Dörfler 			IntRect clippedFrame = view->Frame();
243953d895eSAxel Dörfler 			ConvertToVisibleInTopView(&clippedFrame);
244953d895eSAxel Dörfler 			BRegion* dirty = fWindow->GetRegion();
245953d895eSAxel Dörfler 			if (dirty) {
246953d895eSAxel Dörfler 				dirty->Set((clipping_rect)clippedFrame);
247953d895eSAxel Dörfler 				fWindow->MarkContentDirtyAsync(*dirty);
248953d895eSAxel Dörfler 				fWindow->RecycleRegion(dirty);
249953d895eSAxel Dörfler 			}
250953d895eSAxel Dörfler 		}
251953d895eSAxel Dörfler 	}
252953d895eSAxel Dörfler }
253953d895eSAxel Dörfler 
254953d895eSAxel Dörfler 
255953d895eSAxel Dörfler bool
256437b1927SAxel Dörfler View::RemoveChild(View* view)
257953d895eSAxel Dörfler {
2583e8d3c5fSMichael Lotz 	if (view == NULL || view->fParent != this) {
259953d895eSAxel Dörfler 		printf("View::RemoveChild(%p - %s) - View is not child of "
260437b1927SAxel Dörfler 			"this (%p) view!\n", view, view ? view->Name() : NULL, this);
261953d895eSAxel Dörfler 		return false;
262953d895eSAxel Dörfler 	}
263953d895eSAxel Dörfler 
264437b1927SAxel Dörfler 	view->fParent = NULL;
265953d895eSAxel Dörfler 
266437b1927SAxel Dörfler 	if (fLastChild == view)
267437b1927SAxel Dörfler 		fLastChild = view->fPreviousSibling;
268437b1927SAxel Dörfler 		// view->fNextSibling would be NULL
269953d895eSAxel Dörfler 
270437b1927SAxel Dörfler 	if (fFirstChild == view )
271437b1927SAxel Dörfler 		fFirstChild = view->fNextSibling;
272437b1927SAxel Dörfler 		// view->fPreviousSibling would be NULL
273953d895eSAxel Dörfler 
274437b1927SAxel Dörfler 	// connect child before and after view
275437b1927SAxel Dörfler 	if (view->fPreviousSibling)
276437b1927SAxel Dörfler 		view->fPreviousSibling->fNextSibling = view->fNextSibling;
277953d895eSAxel Dörfler 
278437b1927SAxel Dörfler 	if (view->fNextSibling)
279437b1927SAxel Dörfler 		view->fNextSibling->fPreviousSibling = view->fPreviousSibling;
280953d895eSAxel Dörfler 
281437b1927SAxel Dörfler 	// view has no siblings anymore
282437b1927SAxel Dörfler 	view->fPreviousSibling = NULL;
283437b1927SAxel Dörfler 	view->fNextSibling = NULL;
284953d895eSAxel Dörfler 
285437b1927SAxel Dörfler 	if (view->IsVisible()) {
286437b1927SAxel Dörfler 		Overlay* overlay = view->_Overlay();
287953d895eSAxel Dörfler 		if (overlay != NULL)
288953d895eSAxel Dörfler 			overlay->Hide();
289953d895eSAxel Dörfler 
290953d895eSAxel Dörfler 		RebuildClipping(false);
291953d895eSAxel Dörfler 	}
292953d895eSAxel Dörfler 
293953d895eSAxel Dörfler 	if (fWindow) {
294437b1927SAxel Dörfler 		view->DetachedFromWindow();
295953d895eSAxel Dörfler 
296437b1927SAxel Dörfler 		if (fVisible && view->IsVisible()) {
297953d895eSAxel Dörfler 			// trigger redraw
298437b1927SAxel Dörfler 			IntRect clippedFrame = view->Frame();
299953d895eSAxel Dörfler 			ConvertToVisibleInTopView(&clippedFrame);
300953d895eSAxel Dörfler 			BRegion* dirty = fWindow->GetRegion();
301953d895eSAxel Dörfler 			if (dirty) {
302953d895eSAxel Dörfler 				dirty->Set((clipping_rect)clippedFrame);
303953d895eSAxel Dörfler 				fWindow->MarkContentDirtyAsync(*dirty);
304953d895eSAxel Dörfler 				fWindow->RecycleRegion(dirty);
305953d895eSAxel Dörfler 			}
306953d895eSAxel Dörfler 		}
307953d895eSAxel Dörfler 	}
308953d895eSAxel Dörfler 
309953d895eSAxel Dörfler 	return true;
310953d895eSAxel Dörfler }
311953d895eSAxel Dörfler 
312953d895eSAxel Dörfler 
313953d895eSAxel Dörfler View*
314437b1927SAxel Dörfler View::TopView()
315953d895eSAxel Dörfler {
316953d895eSAxel Dörfler 	// returns the top level view of the hirarchy,
317953d895eSAxel Dörfler 	// it doesn't have to be the top level of a window
318953d895eSAxel Dörfler 
319953d895eSAxel Dörfler 	if (fParent)
320437b1927SAxel Dörfler 		return fParent->TopView();
321953d895eSAxel Dörfler 
322953d895eSAxel Dörfler 	return this;
323953d895eSAxel Dörfler }
324953d895eSAxel Dörfler 
325953d895eSAxel Dörfler 
326953d895eSAxel Dörfler uint32
327953d895eSAxel Dörfler View::CountChildren(bool deep) const
328953d895eSAxel Dörfler {
329953d895eSAxel Dörfler 	uint32 count = 0;
330953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
331953d895eSAxel Dörfler 		count++;
332953d895eSAxel Dörfler 		if (deep) {
333953d895eSAxel Dörfler 			count += child->CountChildren(deep);
334953d895eSAxel Dörfler 		}
335953d895eSAxel Dörfler 	}
336953d895eSAxel Dörfler 	return count;
337953d895eSAxel Dörfler }
338953d895eSAxel Dörfler 
339953d895eSAxel Dörfler 
340953d895eSAxel Dörfler void
341953d895eSAxel Dörfler View::CollectTokensForChildren(BList* tokenMap) const
342953d895eSAxel Dörfler {
343953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
344953d895eSAxel Dörfler 		tokenMap->AddItem((void*)child);
345953d895eSAxel Dörfler 		child->CollectTokensForChildren(tokenMap);
346953d895eSAxel Dörfler 	}
347953d895eSAxel Dörfler }
348953d895eSAxel Dörfler 
349953d895eSAxel Dörfler 
350953d895eSAxel Dörfler #if 0
351953d895eSAxel Dörfler bool
352953d895eSAxel Dörfler View::MarkAt(DrawingEngine* engine, const BPoint& where, int32 level)
353953d895eSAxel Dörfler {
354953d895eSAxel Dörfler 	BRect rect(fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
355953d895eSAxel Dörfler 
356953d895eSAxel Dörfler 	if (Parent() != NULL) {
357953d895eSAxel Dörfler 		Parent()->ConvertToScreen(&rect);
358953d895eSAxel Dörfler 		if (!rect.Contains(where))
359953d895eSAxel Dörfler 			return false;
360953d895eSAxel Dörfler 
361953d895eSAxel Dörfler 		engine->StrokeRect(rect, (rgb_color){level * 30, level * 30, level * 30});
362953d895eSAxel Dörfler 	}
363953d895eSAxel Dörfler 
364953d895eSAxel Dörfler 
365953d895eSAxel Dörfler 	bool found = false;
366953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
367953d895eSAxel Dörfler 		found |= child->MarkAt(engine, where, level + 1);
368953d895eSAxel Dörfler 	}
369953d895eSAxel Dörfler 
370953d895eSAxel Dörfler 	if (!found) {
371953d895eSAxel Dörfler 		rgb_color color = {0};
372953d895eSAxel Dörfler 		switch (level % 2) {
373953d895eSAxel Dörfler 			case 0: color.green = rand() % 256; break;
374953d895eSAxel Dörfler 			case 1: color.blue = rand() % 256; break;
375953d895eSAxel Dörfler 		}
376953d895eSAxel Dörfler 
377953d895eSAxel Dörfler 		rect.InsetBy(1, 1);
378953d895eSAxel Dörfler 		//engine->FillRegion(fLocalClipping, (rgb_color){255, 255, 0, 10});
379953d895eSAxel Dörfler 		engine->StrokeRect(rect, color);
380953d895eSAxel Dörfler 		rect.InsetBy(1, 1);
381953d895eSAxel Dörfler 		engine->StrokeRect(rect, color);
382953d895eSAxel Dörfler 	}
383953d895eSAxel Dörfler 
384953d895eSAxel Dörfler 	return true;
385953d895eSAxel Dörfler }
386953d895eSAxel Dörfler #endif
387953d895eSAxel Dörfler 
388953d895eSAxel Dörfler 
389953d895eSAxel Dörfler void
390953d895eSAxel Dörfler View::FindViews(uint32 flags, BObjectList<View>& list, int32& left)
391953d895eSAxel Dörfler {
392953d895eSAxel Dörfler 	if ((Flags() & flags) == flags) {
393953d895eSAxel Dörfler 		list.AddItem(this);
394953d895eSAxel Dörfler 		left--;
395953d895eSAxel Dörfler 		return;
396953d895eSAxel Dörfler 	}
397953d895eSAxel Dörfler 
398953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
399953d895eSAxel Dörfler 		child->FindViews(flags, list, left);
400953d895eSAxel Dörfler 		if (left == 0)
401953d895eSAxel Dörfler 			break;
402953d895eSAxel Dörfler 	}
403953d895eSAxel Dörfler }
404953d895eSAxel Dörfler 
405953d895eSAxel Dörfler 
406953d895eSAxel Dörfler View*
407953d895eSAxel Dörfler View::ViewAt(const BPoint& where)
408953d895eSAxel Dörfler {
409953d895eSAxel Dörfler 	if (!fVisible)
410953d895eSAxel Dörfler 		return NULL;
411953d895eSAxel Dörfler 
412953d895eSAxel Dörfler 	IntRect frame = Frame();
413953d895eSAxel Dörfler 	if (Parent() != NULL)
414953d895eSAxel Dörfler 		Parent()->ConvertToScreen(&frame);
415953d895eSAxel Dörfler 
416953d895eSAxel Dörfler 	if (!frame.Contains(where))
417953d895eSAxel Dörfler 		return NULL;
418953d895eSAxel Dörfler 
419953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
420437b1927SAxel Dörfler 		View* view = child->ViewAt(where);
421437b1927SAxel Dörfler 		if (view != NULL)
422437b1927SAxel Dörfler 			return view;
423953d895eSAxel Dörfler 	}
424953d895eSAxel Dörfler 
425953d895eSAxel Dörfler 	return this;
426953d895eSAxel Dörfler }
427953d895eSAxel Dörfler 
428953d895eSAxel Dörfler 
429953d895eSAxel Dörfler // #pragma mark -
430953d895eSAxel Dörfler 
431953d895eSAxel Dörfler 
432953d895eSAxel Dörfler void
433953d895eSAxel Dörfler View::SetName(const char* string)
434953d895eSAxel Dörfler {
435953d895eSAxel Dörfler 	fName.SetTo(string);
436953d895eSAxel Dörfler }
437953d895eSAxel Dörfler 
438953d895eSAxel Dörfler 
439953d895eSAxel Dörfler void
440953d895eSAxel Dörfler View::SetFlags(uint32 flags)
441953d895eSAxel Dörfler {
442953d895eSAxel Dörfler 	fFlags = flags;
443953d895eSAxel Dörfler 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
444953d895eSAxel Dörfler }
445953d895eSAxel Dörfler 
446953d895eSAxel Dörfler 
447953d895eSAxel Dörfler void
448953d895eSAxel Dörfler View::SetDrawingOrigin(BPoint origin)
449953d895eSAxel Dörfler {
450953d895eSAxel Dörfler 	fDrawState->SetOrigin(origin);
451953d895eSAxel Dörfler 
452953d895eSAxel Dörfler 	// rebuild clipping
45379ef179cSStephan Aßmus 	if (fDrawState->HasClipping())
454953d895eSAxel Dörfler 		RebuildClipping(false);
455953d895eSAxel Dörfler }
456953d895eSAxel Dörfler 
457953d895eSAxel Dörfler 
458953d895eSAxel Dörfler BPoint
459953d895eSAxel Dörfler View::DrawingOrigin() const
460953d895eSAxel Dörfler {
461953d895eSAxel Dörfler 	BPoint origin(fDrawState->Origin());
462953d895eSAxel Dörfler 	float scale = Scale();
463953d895eSAxel Dörfler 
464953d895eSAxel Dörfler 	origin.x *= scale;
465953d895eSAxel Dörfler 	origin.y *= scale;
466953d895eSAxel Dörfler 
467953d895eSAxel Dörfler 	return origin;
468953d895eSAxel Dörfler }
469953d895eSAxel Dörfler 
470953d895eSAxel Dörfler 
471953d895eSAxel Dörfler void
472953d895eSAxel Dörfler View::SetScale(float scale)
473953d895eSAxel Dörfler {
474953d895eSAxel Dörfler 	fDrawState->SetScale(scale);
475953d895eSAxel Dörfler 
476953d895eSAxel Dörfler 	// rebuild clipping
47779ef179cSStephan Aßmus 	if (fDrawState->HasClipping())
478953d895eSAxel Dörfler 		RebuildClipping(false);
479953d895eSAxel Dörfler }
480953d895eSAxel Dörfler 
481953d895eSAxel Dörfler 
482953d895eSAxel Dörfler float
483953d895eSAxel Dörfler View::Scale() const
484953d895eSAxel Dörfler {
485953d895eSAxel Dörfler 	return CurrentState()->Scale();
486953d895eSAxel Dörfler }
487953d895eSAxel Dörfler 
488953d895eSAxel Dörfler 
489953d895eSAxel Dörfler void
490953d895eSAxel Dörfler View::SetUserClipping(const BRegion* region)
491953d895eSAxel Dörfler {
492953d895eSAxel Dörfler 	fDrawState->SetClippingRegion(region);
493953d895eSAxel Dörfler 
494953d895eSAxel Dörfler 	// rebuild clipping (for just this view)
495953d895eSAxel Dörfler 	RebuildClipping(false);
496953d895eSAxel Dörfler }
497953d895eSAxel Dörfler 
498953d895eSAxel Dörfler 
499953d895eSAxel Dörfler void
500953d895eSAxel Dörfler View::SetViewBitmap(ServerBitmap* bitmap, IntRect sourceRect,
501953d895eSAxel Dörfler 	IntRect destRect, int32 resizingMode, int32 options)
502953d895eSAxel Dörfler {
503953d895eSAxel Dörfler 	if (fViewBitmap != NULL) {
504953d895eSAxel Dörfler 		Overlay* overlay = _Overlay();
505953d895eSAxel Dörfler 
506953d895eSAxel Dörfler 		if (bitmap != NULL) {
507953d895eSAxel Dörfler 			// take over overlay token from current overlay (if it has any)
508953d895eSAxel Dörfler 			Overlay* newOverlay = bitmap->Overlay();
509953d895eSAxel Dörfler 
510953d895eSAxel Dörfler 			if (overlay != NULL && newOverlay != NULL)
511953d895eSAxel Dörfler 				newOverlay->TakeOverToken(overlay);
512953d895eSAxel Dörfler 		} else if (overlay != NULL)
513953d895eSAxel Dörfler 			overlay->Hide();
514953d895eSAxel Dörfler 
515953d895eSAxel Dörfler 		gBitmapManager->DeleteBitmap(fViewBitmap);
516953d895eSAxel Dörfler 	}
517953d895eSAxel Dörfler 
518953d895eSAxel Dörfler 	// the caller is allowed to delete the bitmap after setting the background
519953d895eSAxel Dörfler 	if (bitmap != NULL)
520953d895eSAxel Dörfler 		bitmap->Acquire();
521953d895eSAxel Dörfler 
522953d895eSAxel Dörfler 	fViewBitmap = bitmap;
523953d895eSAxel Dörfler 	fBitmapSource = sourceRect;
524953d895eSAxel Dörfler 	fBitmapDestination = destRect;
525953d895eSAxel Dörfler 	fBitmapResizingMode = resizingMode;
526953d895eSAxel Dörfler 	fBitmapOptions = options;
527953d895eSAxel Dörfler 
528953d895eSAxel Dörfler 	_UpdateOverlayView();
529953d895eSAxel Dörfler }
530953d895eSAxel Dörfler 
531953d895eSAxel Dörfler 
532953d895eSAxel Dörfler ::Overlay*
533953d895eSAxel Dörfler View::_Overlay() const
534953d895eSAxel Dörfler {
535953d895eSAxel Dörfler 	if (fViewBitmap == NULL)
536953d895eSAxel Dörfler 		return NULL;
537953d895eSAxel Dörfler 
538953d895eSAxel Dörfler 	return fViewBitmap->Overlay();
539953d895eSAxel Dörfler }
540953d895eSAxel Dörfler 
541953d895eSAxel Dörfler 
542953d895eSAxel Dörfler void
543953d895eSAxel Dörfler View::_UpdateOverlayView() const
544953d895eSAxel Dörfler {
545953d895eSAxel Dörfler 	Overlay* overlay = _Overlay();
546953d895eSAxel Dörfler 	if (overlay == NULL)
547953d895eSAxel Dörfler 		return;
548953d895eSAxel Dörfler 
549953d895eSAxel Dörfler 	IntRect destination = fBitmapDestination;
550953d895eSAxel Dörfler 	ConvertToScreen(&destination);
551953d895eSAxel Dörfler 
552953d895eSAxel Dörfler 	overlay->Configure(fBitmapSource, destination);
553953d895eSAxel Dörfler }
554953d895eSAxel Dörfler 
555953d895eSAxel Dörfler 
556953d895eSAxel Dörfler /*!
557953d895eSAxel Dörfler 	This method is called whenever the window is resized or moved - would
558953d895eSAxel Dörfler 	be nice to have a better solution for this, though.
559953d895eSAxel Dörfler */
560953d895eSAxel Dörfler void
561953d895eSAxel Dörfler View::UpdateOverlay()
562953d895eSAxel Dörfler {
563953d895eSAxel Dörfler 	if (!IsVisible())
564953d895eSAxel Dörfler 		return;
565953d895eSAxel Dörfler 
566953d895eSAxel Dörfler 	if (_Overlay() != NULL) {
567953d895eSAxel Dörfler 		_UpdateOverlayView();
568953d895eSAxel Dörfler 	} else {
569953d895eSAxel Dörfler 		// recursively ask children of this view
570953d895eSAxel Dörfler 
571953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
572953d895eSAxel Dörfler 			child->UpdateOverlay();
573953d895eSAxel Dörfler 		}
574953d895eSAxel Dörfler 	}
575953d895eSAxel Dörfler }
576953d895eSAxel Dörfler 
577953d895eSAxel Dörfler 
578953d895eSAxel Dörfler // #pragma mark -
579953d895eSAxel Dörfler 
580953d895eSAxel Dörfler 
581953d895eSAxel Dörfler void
582953d895eSAxel Dörfler View::ConvertToParent(BPoint* point) const
583953d895eSAxel Dörfler {
584953d895eSAxel Dörfler 	// remove scrolling offset and convert to parent coordinate space
585953d895eSAxel Dörfler 	point->x += fFrame.left - fScrollingOffset.x;
586953d895eSAxel Dörfler 	point->y += fFrame.top - fScrollingOffset.y;
587953d895eSAxel Dörfler }
588953d895eSAxel Dörfler 
589953d895eSAxel Dörfler 
590953d895eSAxel Dörfler void
591953d895eSAxel Dörfler View::ConvertToParent(IntPoint* point) const
592953d895eSAxel Dörfler {
593953d895eSAxel Dörfler 	// remove scrolling offset and convert to parent coordinate space
594953d895eSAxel Dörfler 	point->x += fFrame.left - fScrollingOffset.x;
595953d895eSAxel Dörfler 	point->y += fFrame.top - fScrollingOffset.y;
596953d895eSAxel Dörfler }
597953d895eSAxel Dörfler 
598953d895eSAxel Dörfler 
599953d895eSAxel Dörfler void
600953d895eSAxel Dörfler View::ConvertToParent(BRect* rect) const
601953d895eSAxel Dörfler {
602953d895eSAxel Dörfler 	// remove scrolling offset and convert to parent coordinate space
603953d895eSAxel Dörfler 	rect->OffsetBy(fFrame.left - fScrollingOffset.x,
604953d895eSAxel Dörfler 		fFrame.top - fScrollingOffset.y);
605953d895eSAxel Dörfler }
606953d895eSAxel Dörfler 
607953d895eSAxel Dörfler 
608953d895eSAxel Dörfler void
609953d895eSAxel Dörfler View::ConvertToParent(IntRect* rect) const
610953d895eSAxel Dörfler {
611953d895eSAxel Dörfler 	// remove scrolling offset and convert to parent coordinate space
612953d895eSAxel Dörfler 	rect->OffsetBy(fFrame.left - fScrollingOffset.x,
613953d895eSAxel Dörfler 		fFrame.top - fScrollingOffset.y);
614953d895eSAxel Dörfler }
615953d895eSAxel Dörfler 
616953d895eSAxel Dörfler 
617953d895eSAxel Dörfler void
618953d895eSAxel Dörfler View::ConvertToParent(BRegion* region) const
619953d895eSAxel Dörfler {
620953d895eSAxel Dörfler 	// remove scrolling offset and convert to parent coordinate space
621953d895eSAxel Dörfler 	region->OffsetBy(fFrame.left - fScrollingOffset.x,
622953d895eSAxel Dörfler 		fFrame.top - fScrollingOffset.y);
623953d895eSAxel Dörfler }
624953d895eSAxel Dörfler 
625953d895eSAxel Dörfler 
626953d895eSAxel Dörfler void
627953d895eSAxel Dörfler View::ConvertFromParent(BPoint* point) const
628953d895eSAxel Dörfler {
629953d895eSAxel Dörfler 	// convert from parent coordinate space amd add scrolling offset
630953d895eSAxel Dörfler 	point->x += fScrollingOffset.x - fFrame.left;
631953d895eSAxel Dörfler 	point->y += fScrollingOffset.y - fFrame.top;
632953d895eSAxel Dörfler }
633953d895eSAxel Dörfler 
634953d895eSAxel Dörfler 
635953d895eSAxel Dörfler void
636953d895eSAxel Dörfler View::ConvertFromParent(IntPoint* point) const
637953d895eSAxel Dörfler {
638953d895eSAxel Dörfler 	// convert from parent coordinate space amd add scrolling offset
639953d895eSAxel Dörfler 	point->x += fScrollingOffset.x - fFrame.left;
640953d895eSAxel Dörfler 	point->y += fScrollingOffset.y - fFrame.top;
641953d895eSAxel Dörfler }
642953d895eSAxel Dörfler 
643953d895eSAxel Dörfler 
644953d895eSAxel Dörfler void
645953d895eSAxel Dörfler View::ConvertFromParent(BRect* rect) const
646953d895eSAxel Dörfler {
647953d895eSAxel Dörfler 	// convert from parent coordinate space amd add scrolling offset
648953d895eSAxel Dörfler 	rect->OffsetBy(fScrollingOffset.x - fFrame.left,
649953d895eSAxel Dörfler 		fScrollingOffset.y - fFrame.top);
650953d895eSAxel Dörfler }
651953d895eSAxel Dörfler 
652953d895eSAxel Dörfler 
653953d895eSAxel Dörfler void
654953d895eSAxel Dörfler View::ConvertFromParent(IntRect* rect) const
655953d895eSAxel Dörfler {
656953d895eSAxel Dörfler 	// convert from parent coordinate space amd add scrolling offset
657953d895eSAxel Dörfler 	rect->OffsetBy(fScrollingOffset.x - fFrame.left,
658953d895eSAxel Dörfler 		fScrollingOffset.y - fFrame.top);
659953d895eSAxel Dörfler }
660953d895eSAxel Dörfler 
661953d895eSAxel Dörfler 
662953d895eSAxel Dörfler void
663953d895eSAxel Dörfler View::ConvertFromParent(BRegion* region) const
664953d895eSAxel Dörfler {
665953d895eSAxel Dörfler 	// convert from parent coordinate space amd add scrolling offset
666953d895eSAxel Dörfler 	region->OffsetBy(fScrollingOffset.x - fFrame.left,
667953d895eSAxel Dörfler 		fScrollingOffset.y - fFrame.top);
668953d895eSAxel Dörfler }
669953d895eSAxel Dörfler 
670953d895eSAxel Dörfler //! converts a point from local to screen coordinate system
671953d895eSAxel Dörfler void
672953d895eSAxel Dörfler View::ConvertToScreen(BPoint* pt) const
673953d895eSAxel Dörfler {
674953d895eSAxel Dörfler 	ConvertToParent(pt);
675953d895eSAxel Dörfler 
676953d895eSAxel Dörfler 	if (fParent)
677953d895eSAxel Dörfler 		fParent->ConvertToScreen(pt);
678953d895eSAxel Dörfler }
679953d895eSAxel Dörfler 
680953d895eSAxel Dörfler 
681953d895eSAxel Dörfler //! converts a point from local to screen coordinate system
682953d895eSAxel Dörfler void
683953d895eSAxel Dörfler View::ConvertToScreen(IntPoint* pt) const
684953d895eSAxel Dörfler {
685953d895eSAxel Dörfler 	ConvertToParent(pt);
686953d895eSAxel Dörfler 
687953d895eSAxel Dörfler 	if (fParent)
688953d895eSAxel Dörfler 		fParent->ConvertToScreen(pt);
689953d895eSAxel Dörfler }
690953d895eSAxel Dörfler 
691953d895eSAxel Dörfler 
692953d895eSAxel Dörfler //! converts a rect from local to screen coordinate system
693953d895eSAxel Dörfler void
694953d895eSAxel Dörfler View::ConvertToScreen(BRect* rect) const
695953d895eSAxel Dörfler {
696953d895eSAxel Dörfler 	BPoint offset(0.0, 0.0);
697953d895eSAxel Dörfler 	ConvertToScreen(&offset);
698953d895eSAxel Dörfler 
699953d895eSAxel Dörfler 	rect->OffsetBy(offset);
700953d895eSAxel Dörfler }
701953d895eSAxel Dörfler 
702953d895eSAxel Dörfler 
703953d895eSAxel Dörfler //! converts a rect from local to screen coordinate system
704953d895eSAxel Dörfler void
705953d895eSAxel Dörfler View::ConvertToScreen(IntRect* rect) const
706953d895eSAxel Dörfler {
707953d895eSAxel Dörfler 	BPoint offset(0.0, 0.0);
708953d895eSAxel Dörfler 	ConvertToScreen(&offset);
709953d895eSAxel Dörfler 
710953d895eSAxel Dörfler 	rect->OffsetBy(offset);
711953d895eSAxel Dörfler }
712953d895eSAxel Dörfler 
713953d895eSAxel Dörfler 
714953d895eSAxel Dörfler //! converts a region from local to screen coordinate system
715953d895eSAxel Dörfler void
716953d895eSAxel Dörfler View::ConvertToScreen(BRegion* region) const
717953d895eSAxel Dörfler {
718953d895eSAxel Dörfler 	BPoint offset(0.0, 0.0);
719953d895eSAxel Dörfler 	ConvertToScreen(&offset);
720953d895eSAxel Dörfler 
721953d895eSAxel Dörfler 	region->OffsetBy((int)offset.x, (int)offset.y);
722953d895eSAxel Dörfler }
723953d895eSAxel Dörfler 
724953d895eSAxel Dörfler 
725953d895eSAxel Dörfler //! converts a point from screen to local coordinate system
726953d895eSAxel Dörfler void
727953d895eSAxel Dörfler View::ConvertFromScreen(BPoint* pt) const
728953d895eSAxel Dörfler {
729953d895eSAxel Dörfler 	ConvertFromParent(pt);
730953d895eSAxel Dörfler 
731953d895eSAxel Dörfler 	if (fParent)
732953d895eSAxel Dörfler 		fParent->ConvertFromScreen(pt);
733953d895eSAxel Dörfler }
734953d895eSAxel Dörfler 
735953d895eSAxel Dörfler 
736953d895eSAxel Dörfler //! converts a point from screen to local coordinate system
737953d895eSAxel Dörfler void
738953d895eSAxel Dörfler View::ConvertFromScreen(IntPoint* pt) const
739953d895eSAxel Dörfler {
740953d895eSAxel Dörfler 	ConvertFromParent(pt);
741953d895eSAxel Dörfler 
742953d895eSAxel Dörfler 	if (fParent)
743953d895eSAxel Dörfler 		fParent->ConvertFromScreen(pt);
744953d895eSAxel Dörfler }
745953d895eSAxel Dörfler 
746953d895eSAxel Dörfler 
747953d895eSAxel Dörfler //! converts a rect from screen to local coordinate system
748953d895eSAxel Dörfler void
749953d895eSAxel Dörfler View::ConvertFromScreen(BRect* rect) const
750953d895eSAxel Dörfler {
751953d895eSAxel Dörfler 	BPoint offset(0.0, 0.0);
752953d895eSAxel Dörfler 	ConvertFromScreen(&offset);
753953d895eSAxel Dörfler 
754953d895eSAxel Dörfler 	rect->OffsetBy(offset.x, offset.y);
755953d895eSAxel Dörfler }
756953d895eSAxel Dörfler 
757953d895eSAxel Dörfler 
758953d895eSAxel Dörfler //! converts a rect from screen to local coordinate system
759953d895eSAxel Dörfler void
760953d895eSAxel Dörfler View::ConvertFromScreen(IntRect* rect) const
761953d895eSAxel Dörfler {
762953d895eSAxel Dörfler 	BPoint offset(0.0, 0.0);
763953d895eSAxel Dörfler 	ConvertFromScreen(&offset);
764953d895eSAxel Dörfler 
765953d895eSAxel Dörfler 	rect->OffsetBy((int)offset.x, (int)offset.y);
766953d895eSAxel Dörfler }
767953d895eSAxel Dörfler 
768953d895eSAxel Dörfler 
769953d895eSAxel Dörfler //! converts a region from screen to local coordinate system
770953d895eSAxel Dörfler void
771953d895eSAxel Dörfler View::ConvertFromScreen(BRegion* region) const
772953d895eSAxel Dörfler {
773953d895eSAxel Dörfler 	BPoint offset(0.0, 0.0);
774953d895eSAxel Dörfler 	ConvertFromScreen(&offset);
775953d895eSAxel Dörfler 
776953d895eSAxel Dörfler 	region->OffsetBy((int)offset.x, (int)offset.y);
777953d895eSAxel Dörfler }
778953d895eSAxel Dörfler 
779953d895eSAxel Dörfler 
780953d895eSAxel Dörfler //! converts a point from local *drawing* to screen coordinate system
781953d895eSAxel Dörfler void
782953d895eSAxel Dörfler View::ConvertToScreenForDrawing(BPoint* point) const
783953d895eSAxel Dörfler {
784953d895eSAxel Dörfler 	fDrawState->Transform(point);
785953d895eSAxel Dörfler 	// NOTE: from here on, don't use the
786953d895eSAxel Dörfler 	// "*ForDrawing()" versions of the parent!
787953d895eSAxel Dörfler 	ConvertToScreen(point);
788953d895eSAxel Dörfler }
789953d895eSAxel Dörfler 
790953d895eSAxel Dörfler 
791953d895eSAxel Dörfler //! converts a rect from local *drawing* to screen coordinate system
792953d895eSAxel Dörfler void
793953d895eSAxel Dörfler View::ConvertToScreenForDrawing(BRect* rect) const
794953d895eSAxel Dörfler {
795953d895eSAxel Dörfler 	fDrawState->Transform(rect);
796953d895eSAxel Dörfler 	// NOTE: from here on, don't use the
797953d895eSAxel Dörfler 	// "*ForDrawing()" versions of the parent!
798953d895eSAxel Dörfler 	ConvertToScreen(rect);
799953d895eSAxel Dörfler }
800953d895eSAxel Dörfler 
801953d895eSAxel Dörfler 
802953d895eSAxel Dörfler //! converts a region from local *drawing* to screen coordinate system
803953d895eSAxel Dörfler void
804953d895eSAxel Dörfler View::ConvertToScreenForDrawing(BRegion* region) const
805953d895eSAxel Dörfler {
806953d895eSAxel Dörfler 	fDrawState->Transform(region);
807953d895eSAxel Dörfler 	// NOTE: from here on, don't use the
808953d895eSAxel Dörfler 	// "*ForDrawing()" versions of the parent!
809953d895eSAxel Dörfler 	ConvertToScreen(region);
810953d895eSAxel Dörfler }
811953d895eSAxel Dörfler 
812953d895eSAxel Dörfler 
813991547efSStephan Aßmus //! converts a gradient from local *drawing* to screen coordinate system
814991547efSStephan Aßmus void
815991547efSStephan Aßmus View::ConvertToScreenForDrawing(BGradient* gradient) const
816991547efSStephan Aßmus {
81764eb49fdSStephan Aßmus 	switch(gradient->GetType()) {
81852de6dceSStephan Aßmus 		case BGradient::TYPE_LINEAR: {
819991547efSStephan Aßmus 			BGradientLinear* linear = (BGradientLinear*) gradient;
820991547efSStephan Aßmus 			BPoint start = linear->Start();
821991547efSStephan Aßmus 			BPoint end = linear->End();
822991547efSStephan Aßmus 			fDrawState->Transform(&start);
823991547efSStephan Aßmus 			ConvertToScreen(&start);
824991547efSStephan Aßmus 			fDrawState->Transform(&end);
825991547efSStephan Aßmus 			ConvertToScreen(&end);
826991547efSStephan Aßmus 			linear->SetStart(start);
827991547efSStephan Aßmus 			linear->SetEnd(end);
82864eb49fdSStephan Aßmus 			linear->SortColorStopsByOffset();
829991547efSStephan Aßmus 			break;
830991547efSStephan Aßmus 		}
83152de6dceSStephan Aßmus 		case BGradient::TYPE_RADIAL: {
832991547efSStephan Aßmus 			BGradientRadial* radial = (BGradientRadial*) gradient;
833991547efSStephan Aßmus 			BPoint center = radial->Center();
834991547efSStephan Aßmus 			fDrawState->Transform(&center);
835991547efSStephan Aßmus 			ConvertToScreen(&center);
836991547efSStephan Aßmus 			radial->SetCenter(center);
83764eb49fdSStephan Aßmus 			radial->SortColorStopsByOffset();
838991547efSStephan Aßmus 			break;
839991547efSStephan Aßmus 		}
84052de6dceSStephan Aßmus 		case BGradient::TYPE_RADIAL_FOCUS: {
841991547efSStephan Aßmus 			BGradientRadialFocus* radialFocus = (BGradientRadialFocus*) gradient;
842991547efSStephan Aßmus 			BPoint center = radialFocus->Center();
843991547efSStephan Aßmus 			BPoint focal = radialFocus->Focal();
844991547efSStephan Aßmus 			fDrawState->Transform(&center);
845991547efSStephan Aßmus 			ConvertToScreen(&center);
846991547efSStephan Aßmus 			fDrawState->Transform(&focal);
847991547efSStephan Aßmus 			ConvertToScreen(&focal);
848991547efSStephan Aßmus 			radialFocus->SetCenter(center);
849991547efSStephan Aßmus 			radialFocus->SetFocal(focal);
85064eb49fdSStephan Aßmus 			radialFocus->SortColorStopsByOffset();
851991547efSStephan Aßmus 			break;
852991547efSStephan Aßmus 		}
85352de6dceSStephan Aßmus 		case BGradient::TYPE_DIAMOND: {
854991547efSStephan Aßmus 			BGradientDiamond* diamond = (BGradientDiamond*) gradient;
855991547efSStephan Aßmus 			BPoint center = diamond->Center();
856991547efSStephan Aßmus 			fDrawState->Transform(&center);
857991547efSStephan Aßmus 			ConvertToScreen(&center);
858991547efSStephan Aßmus 			diamond->SetCenter(center);
85964eb49fdSStephan Aßmus 			diamond->SortColorStopsByOffset();
860991547efSStephan Aßmus 			break;
861991547efSStephan Aßmus 		}
86252de6dceSStephan Aßmus 		case BGradient::TYPE_CONIC: {
863991547efSStephan Aßmus 			BGradientConic* conic = (BGradientConic*) gradient;
864991547efSStephan Aßmus 			BPoint center = conic->Center();
865991547efSStephan Aßmus 			fDrawState->Transform(&center);
866991547efSStephan Aßmus 			ConvertToScreen(&center);
867991547efSStephan Aßmus 			conic->SetCenter(center);
86864eb49fdSStephan Aßmus 			conic->SortColorStopsByOffset();
869991547efSStephan Aßmus 			break;
870991547efSStephan Aßmus 		}
87152de6dceSStephan Aßmus 		case BGradient::TYPE_NONE: {
872991547efSStephan Aßmus 			break;
873991547efSStephan Aßmus 		}
874991547efSStephan Aßmus 	}
875991547efSStephan Aßmus }
876991547efSStephan Aßmus 
877991547efSStephan Aßmus 
878953d895eSAxel Dörfler //! converts points from local *drawing* to screen coordinate system
879953d895eSAxel Dörfler void
880953d895eSAxel Dörfler View::ConvertToScreenForDrawing(BPoint* dst, const BPoint* src, int32 num) const
881953d895eSAxel Dörfler {
882953d895eSAxel Dörfler 	// TODO: optimize this, it should be smarter
883953d895eSAxel Dörfler 	while (num--) {
884953d895eSAxel Dörfler 		*dst = *src;
885953d895eSAxel Dörfler 		fDrawState->Transform(dst);
886953d895eSAxel Dörfler 		// NOTE: from here on, don't use the
887953d895eSAxel Dörfler 		// "*ForDrawing()" versions of the parent!
888953d895eSAxel Dörfler 		ConvertToScreen(dst);
889953d895eSAxel Dörfler 		src++;
890953d895eSAxel Dörfler 		dst++;
891953d895eSAxel Dörfler 	}
892953d895eSAxel Dörfler }
893953d895eSAxel Dörfler 
894953d895eSAxel Dörfler 
895953d895eSAxel Dörfler //! converts rects from local *drawing* to screen coordinate system
896953d895eSAxel Dörfler void
897953d895eSAxel Dörfler View::ConvertToScreenForDrawing(BRect* dst, const BRect* src, int32 num) const
898953d895eSAxel Dörfler {
899953d895eSAxel Dörfler 	// TODO: optimize this, it should be smarter
900953d895eSAxel Dörfler 	while (num--) {
901953d895eSAxel Dörfler 		*dst = *src;
902953d895eSAxel Dörfler 		fDrawState->Transform(dst);
903953d895eSAxel Dörfler 		// NOTE: from here on, don't use the
904953d895eSAxel Dörfler 		// "*ForDrawing()" versions of the parent!
905953d895eSAxel Dörfler 		ConvertToScreen(dst);
906953d895eSAxel Dörfler 		src++;
907953d895eSAxel Dörfler 		dst++;
908953d895eSAxel Dörfler 	}
909953d895eSAxel Dörfler }
910953d895eSAxel Dörfler 
911953d895eSAxel Dörfler 
912953d895eSAxel Dörfler //! converts regions from local *drawing* to screen coordinate system
913953d895eSAxel Dörfler void
914953d895eSAxel Dörfler View::ConvertToScreenForDrawing(BRegion* dst, const BRegion* src, int32 num) const
915953d895eSAxel Dörfler {
916953d895eSAxel Dörfler 	// TODO: optimize this, it should be smarter
917953d895eSAxel Dörfler 	while (num--) {
918953d895eSAxel Dörfler 		*dst = *src;
919953d895eSAxel Dörfler 		fDrawState->Transform(dst);
920953d895eSAxel Dörfler 		// NOTE: from here on, don't use the
921953d895eSAxel Dörfler 		// "*ForDrawing()" versions of the parent!
922953d895eSAxel Dörfler 		ConvertToScreen(dst);
923953d895eSAxel Dörfler 		src++;
924953d895eSAxel Dörfler 		dst++;
925953d895eSAxel Dörfler 	}
926953d895eSAxel Dörfler }
927953d895eSAxel Dörfler 
928953d895eSAxel Dörfler 
929953d895eSAxel Dörfler //! converts a point from screen to local coordinate system
930953d895eSAxel Dörfler void
931953d895eSAxel Dörfler View::ConvertFromScreenForDrawing(BPoint* point) const
932953d895eSAxel Dörfler {
933953d895eSAxel Dörfler 	ConvertFromScreen(point);
934953d895eSAxel Dörfler 	fDrawState->InverseTransform(point);
935953d895eSAxel Dörfler }
936953d895eSAxel Dörfler 
937953d895eSAxel Dörfler 
938953d895eSAxel Dörfler // #pragma mark -
939953d895eSAxel Dörfler 
940953d895eSAxel Dörfler 
941953d895eSAxel Dörfler void
942953d895eSAxel Dörfler View::MoveBy(int32 x, int32 y, BRegion* dirtyRegion)
943953d895eSAxel Dörfler {
944953d895eSAxel Dörfler 	if (x == 0 && y == 0)
945953d895eSAxel Dörfler 		return;
946953d895eSAxel Dörfler 
947953d895eSAxel Dörfler 	fFrame.OffsetBy(x, y);
948953d895eSAxel Dörfler 
949953d895eSAxel Dörfler 	// to move on screen, we must not be hidden and we must have a parent
950953d895eSAxel Dörfler 	if (fVisible && fParent && dirtyRegion) {
951953d895eSAxel Dörfler #if 1
952953d895eSAxel Dörfler // based on redraw on new location
953953d895eSAxel Dörfler 		// the place were we are now visible
954953d895eSAxel Dörfler 		IntRect newVisibleBounds(Bounds());
955953d895eSAxel Dörfler 		// we can use the frame of the old
956953d895eSAxel Dörfler 		// local clipping to see which parts need invalidation
957953d895eSAxel Dörfler 		IntRect oldVisibleBounds(newVisibleBounds);
958953d895eSAxel Dörfler 		oldVisibleBounds.OffsetBy(-x, -y);
959953d895eSAxel Dörfler 		ConvertToScreen(&oldVisibleBounds);
960953d895eSAxel Dörfler 
961953d895eSAxel Dörfler 		ConvertToVisibleInTopView(&newVisibleBounds);
962953d895eSAxel Dörfler 
963953d895eSAxel Dörfler 		dirtyRegion->Include((clipping_rect)oldVisibleBounds);
964953d895eSAxel Dörfler 		// newVisibleBounds already is in screen coords
965953d895eSAxel Dörfler 		dirtyRegion->Include((clipping_rect)newVisibleBounds);
966953d895eSAxel Dörfler #else
967953d895eSAxel Dörfler // blitting version, invalidates
968953d895eSAxel Dörfler // old contents
969953d895eSAxel Dörfler 		IntRect oldVisibleBounds(Bounds());
970953d895eSAxel Dörfler 		IntRect newVisibleBounds(oldVisibleBounds);
971953d895eSAxel Dörfler 		oldVisibleBounds.OffsetBy(-x, -y);
972953d895eSAxel Dörfler 		ConvertToScreen(&oldVisibleBounds);
973953d895eSAxel Dörfler 
974953d895eSAxel Dörfler 		// NOTE: using ConvertToVisibleInTopView()
975953d895eSAxel Dörfler 		// instead of ConvertToScreen()! see below
976953d895eSAxel Dörfler 		ConvertToVisibleInTopView(&newVisibleBounds);
977953d895eSAxel Dörfler 
978953d895eSAxel Dörfler 		newVisibleBounds.OffsetBy(-x, -y);
979953d895eSAxel Dörfler 
980953d895eSAxel Dörfler 		// clipping oldVisibleBounds to newVisibleBounds
981953d895eSAxel Dörfler 		// makes sure we don't copy parts hidden under
982953d895eSAxel Dörfler 		// parent views
983953d895eSAxel Dörfler 		BRegion* region = fWindow->GetRegion();
984953d895eSAxel Dörfler 		if (region) {
985953d895eSAxel Dörfler 			region->Set(oldVisibleBounds & newVisibleBounds);
986953d895eSAxel Dörfler 			fWindow->CopyContents(region, x, y);
987953d895eSAxel Dörfler 
988953d895eSAxel Dörfler 			region->Set(oldVisibleBounds);
989953d895eSAxel Dörfler 			newVisibleBounds.OffsetBy(x, y);
990953d895eSAxel Dörfler 			region->Exclude((clipping_rect)newVisibleBounds);
991953d895eSAxel Dörfler 			dirtyRegion->Include(dirty);
992953d895eSAxel Dörfler 
993953d895eSAxel Dörfler 			fWindow->RecycleRegion(region);
994953d895eSAxel Dörfler 		}
995953d895eSAxel Dörfler 
996953d895eSAxel Dörfler #endif
997953d895eSAxel Dörfler 	}
998953d895eSAxel Dörfler 
999953d895eSAxel Dörfler 	if (!fParent) {
1000953d895eSAxel Dörfler 		// the top view's screen clipping does not change,
1001953d895eSAxel Dörfler 		// because no parts are clipped away from parent
1002953d895eSAxel Dörfler 		// views
1003953d895eSAxel Dörfler 		_MoveScreenClipping(x, y, true);
1004953d895eSAxel Dörfler 	} else {
1005953d895eSAxel Dörfler 		// parts might have been revealed from underneath
1006953d895eSAxel Dörfler 		// the parent, or might now be hidden underneath
1007953d895eSAxel Dörfler 		// the parent, this is taken care of when building
1008953d895eSAxel Dörfler 		// the screen clipping
1009953d895eSAxel Dörfler 		InvalidateScreenClipping();
1010953d895eSAxel Dörfler 	}
1011953d895eSAxel Dörfler }
1012953d895eSAxel Dörfler 
1013953d895eSAxel Dörfler 
1014953d895eSAxel Dörfler void
1015953d895eSAxel Dörfler View::ResizeBy(int32 x, int32 y, BRegion* dirtyRegion)
1016953d895eSAxel Dörfler {
1017953d895eSAxel Dörfler 	if (x == 0 && y == 0)
1018953d895eSAxel Dörfler 		return;
1019953d895eSAxel Dörfler 
1020953d895eSAxel Dörfler 	fFrame.right += x;
1021953d895eSAxel Dörfler 	fFrame.bottom += y;
1022953d895eSAxel Dörfler 
1023953d895eSAxel Dörfler 	if (fVisible && dirtyRegion) {
1024953d895eSAxel Dörfler 		IntRect oldBounds(Bounds());
1025953d895eSAxel Dörfler 		oldBounds.right -= x;
1026953d895eSAxel Dörfler 		oldBounds.bottom -= y;
1027953d895eSAxel Dörfler 
1028953d895eSAxel Dörfler 		BRegion* dirty = fWindow->GetRegion();
1029953d895eSAxel Dörfler 		if (!dirty)
1030953d895eSAxel Dörfler 			return;
1031953d895eSAxel Dörfler 
1032953d895eSAxel Dörfler 		dirty->Set((clipping_rect)Bounds());
1033953d895eSAxel Dörfler 		dirty->Include((clipping_rect)oldBounds);
1034953d895eSAxel Dörfler 
1035953d895eSAxel Dörfler 		if (!(fFlags & B_FULL_UPDATE_ON_RESIZE)) {
1036953d895eSAxel Dörfler 			// the dirty region is just the difference of
1037953d895eSAxel Dörfler 			// old and new bounds
1038953d895eSAxel Dörfler 			dirty->Exclude((clipping_rect)(oldBounds & Bounds()));
1039953d895eSAxel Dörfler 		}
1040953d895eSAxel Dörfler 
1041953d895eSAxel Dörfler 		InvalidateScreenClipping();
1042953d895eSAxel Dörfler 
1043953d895eSAxel Dörfler 		if (dirty->CountRects() > 0) {
1044953d895eSAxel Dörfler 			if ((fFlags & B_DRAW_ON_CHILDREN) == 0) {
1045953d895eSAxel Dörfler 				// exclude children, they are expected to
1046953d895eSAxel Dörfler 				// include their own dirty regions in ParentResized()
1047953d895eSAxel Dörfler 				for (View* child = FirstChild(); child;
1048953d895eSAxel Dörfler 						child = child->NextSibling()) {
1049953d895eSAxel Dörfler 					if (!child->IsVisible())
1050953d895eSAxel Dörfler 						continue;
1051953d895eSAxel Dörfler 					IntRect previousChildVisible(
1052953d895eSAxel Dörfler 						child->Frame() & oldBounds & Bounds());
1053953d895eSAxel Dörfler 					if (dirty->Frame().Intersects(previousChildVisible)) {
1054953d895eSAxel Dörfler 						dirty->Exclude((clipping_rect)previousChildVisible);
1055953d895eSAxel Dörfler 					}
1056953d895eSAxel Dörfler 				}
1057953d895eSAxel Dörfler 			}
1058953d895eSAxel Dörfler 
1059953d895eSAxel Dörfler 			ConvertToScreen(dirty);
1060953d895eSAxel Dörfler 			dirtyRegion->Include(dirty);
1061953d895eSAxel Dörfler 		}
1062953d895eSAxel Dörfler 		fWindow->RecycleRegion(dirty);
1063953d895eSAxel Dörfler 	}
1064953d895eSAxel Dörfler 
1065953d895eSAxel Dörfler 	// layout the children
1066953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
1067953d895eSAxel Dörfler 		child->ParentResized(x, y, dirtyRegion);
1068953d895eSAxel Dörfler 
1069953d895eSAxel Dörfler 	// view bitmap
1070953d895eSAxel Dörfler 
1071953d895eSAxel Dörfler 	resize_frame(fBitmapDestination, fBitmapResizingMode, x, y);
1072953d895eSAxel Dörfler 
1073953d895eSAxel Dörfler 	// at this point, children are at their new locations,
1074953d895eSAxel Dörfler 	// so we can rebuild the clipping
1075953d895eSAxel Dörfler 	// TODO: when the implementation of Hide() and Show() is
1076953d895eSAxel Dörfler 	// complete, see if this should be avoided
1077953d895eSAxel Dörfler 	RebuildClipping(false);
1078953d895eSAxel Dörfler }
1079953d895eSAxel Dörfler 
1080953d895eSAxel Dörfler 
1081953d895eSAxel Dörfler void
1082953d895eSAxel Dörfler View::ParentResized(int32 x, int32 y, BRegion* dirtyRegion)
1083953d895eSAxel Dörfler {
1084953d895eSAxel Dörfler 	IntRect newFrame = fFrame;
1085953d895eSAxel Dörfler 	resize_frame(newFrame, fResizeMode & 0x0000ffff, x, y);
1086953d895eSAxel Dörfler 
1087953d895eSAxel Dörfler 	if (newFrame != fFrame) {
1088953d895eSAxel Dörfler 		// careful, MoveBy will change fFrame
1089953d895eSAxel Dörfler 		int32 widthDiff = (int32)(newFrame.Width() - fFrame.Width());
1090953d895eSAxel Dörfler 		int32 heightDiff = (int32)(newFrame.Height() - fFrame.Height());
1091953d895eSAxel Dörfler 
1092953d895eSAxel Dörfler 		MoveBy(newFrame.left - fFrame.left,
1093953d895eSAxel Dörfler 			newFrame.top - fFrame.top, dirtyRegion);
1094953d895eSAxel Dörfler 
1095953d895eSAxel Dörfler 		ResizeBy(widthDiff, heightDiff, dirtyRegion);
1096953d895eSAxel Dörfler 	} else {
1097953d895eSAxel Dörfler 		// TODO: this covers the fact that our screen clipping might change
1098953d895eSAxel Dörfler 		// when the parent changes its size, even though our frame stays
1099953d895eSAxel Dörfler 		// the same - there might be a way to test for this, but axeld doesn't
1100953d895eSAxel Dörfler 		// know, stippi should look into this when he's back :)
1101953d895eSAxel Dörfler 		InvalidateScreenClipping();
1102953d895eSAxel Dörfler 	}
1103953d895eSAxel Dörfler }
1104953d895eSAxel Dörfler 
1105953d895eSAxel Dörfler 
1106953d895eSAxel Dörfler void
1107953d895eSAxel Dörfler View::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
1108953d895eSAxel Dörfler {
1109953d895eSAxel Dörfler 	if (!fVisible || !fWindow) {
1110953d895eSAxel Dörfler 		fScrollingOffset.x += x;
1111953d895eSAxel Dörfler 		fScrollingOffset.y += y;
1112953d895eSAxel Dörfler 		return;
1113953d895eSAxel Dörfler 	}
1114953d895eSAxel Dörfler 
1115953d895eSAxel Dörfler 	// blitting version, invalidates
1116953d895eSAxel Dörfler 	// old contents
1117953d895eSAxel Dörfler 
1118953d895eSAxel Dörfler 	// remember old bounds for tracking dirty region
1119953d895eSAxel Dörfler 	IntRect oldBounds(Bounds());
1120953d895eSAxel Dörfler 
1121953d895eSAxel Dörfler 	// NOTE: using ConvertToVisibleInTopView()
1122953d895eSAxel Dörfler 	// instead of ConvertToScreen(), this makes
1123953d895eSAxel Dörfler 	// sure we don't try to move or invalidate an
1124953d895eSAxel Dörfler 	// area hidden underneath the parent view
1125953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&oldBounds);
1126953d895eSAxel Dörfler 
1127953d895eSAxel Dörfler 	// find the area of the view that can be scrolled,
1128953d895eSAxel Dörfler 	// contents are shifted in the opposite direction from scrolling
1129953d895eSAxel Dörfler 	IntRect stillVisibleBounds(oldBounds);
1130953d895eSAxel Dörfler 	stillVisibleBounds.OffsetBy(x, y);
1131953d895eSAxel Dörfler 	stillVisibleBounds = stillVisibleBounds & oldBounds;
1132953d895eSAxel Dörfler 
1133953d895eSAxel Dörfler 	fScrollingOffset.x += x;
1134953d895eSAxel Dörfler 	fScrollingOffset.y += y;
1135953d895eSAxel Dörfler 
1136953d895eSAxel Dörfler 	// do the blit, this will make sure
1137953d895eSAxel Dörfler 	// that other more complex dirty regions
1138953d895eSAxel Dörfler 	// are taken care of
1139953d895eSAxel Dörfler 	BRegion* copyRegion = fWindow->GetRegion();
1140953d895eSAxel Dörfler 	if (!copyRegion)
1141953d895eSAxel Dörfler 		return;
1142953d895eSAxel Dörfler 	copyRegion->Set((clipping_rect)stillVisibleBounds);
1143953d895eSAxel Dörfler 	fWindow->CopyContents(copyRegion, -x, -y);
1144953d895eSAxel Dörfler 
1145953d895eSAxel Dörfler 	// find the dirty region as far as we are
1146953d895eSAxel Dörfler 	// concerned
1147953d895eSAxel Dörfler 	BRegion* dirty = copyRegion;
1148953d895eSAxel Dörfler 		// reuse copyRegion and call it dirty
1149953d895eSAxel Dörfler 
1150953d895eSAxel Dörfler 	dirty->Set((clipping_rect)oldBounds);
1151953d895eSAxel Dörfler 	stillVisibleBounds.OffsetBy(-x, -y);
1152953d895eSAxel Dörfler 	dirty->Exclude((clipping_rect)stillVisibleBounds);
1153953d895eSAxel Dörfler 	dirtyRegion->Include(dirty);
1154953d895eSAxel Dörfler 
1155953d895eSAxel Dörfler 	fWindow->RecycleRegion(dirty);
1156953d895eSAxel Dörfler 
1157953d895eSAxel Dörfler 	// the screen clipping of this view and it's
1158953d895eSAxel Dörfler 	// childs is no longer valid
1159953d895eSAxel Dörfler 	InvalidateScreenClipping();
1160953d895eSAxel Dörfler 	RebuildClipping(false);
1161953d895eSAxel Dörfler }
1162953d895eSAxel Dörfler 
1163953d895eSAxel Dörfler 
1164953d895eSAxel Dörfler void
1165953d895eSAxel Dörfler View::CopyBits(IntRect src, IntRect dst, BRegion& windowContentClipping)
1166953d895eSAxel Dörfler {
1167953d895eSAxel Dörfler 	if (!fVisible || !fWindow)
1168953d895eSAxel Dörfler 		return;
1169953d895eSAxel Dörfler 
1170953d895eSAxel Dörfler 	// TODO: confirm that in R5 this call is affected by origin and scale
1171953d895eSAxel Dörfler 
1172953d895eSAxel Dörfler 	// blitting version
1173953d895eSAxel Dörfler 
1174953d895eSAxel Dörfler 	int32 xOffset = dst.left - src.left;
1175953d895eSAxel Dörfler 	int32 yOffset = dst.top - src.top;
1176953d895eSAxel Dörfler 
1177953d895eSAxel Dörfler 	// figure out which part can be blittet
1178953d895eSAxel Dörfler 	IntRect visibleSrc(src);
1179953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&visibleSrc);
1180953d895eSAxel Dörfler 
1181953d895eSAxel Dörfler 	IntRect visibleSrcAtDest(src);
1182953d895eSAxel Dörfler 	visibleSrcAtDest.OffsetBy(xOffset, yOffset);
1183953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&visibleSrcAtDest);
1184953d895eSAxel Dörfler 
1185953d895eSAxel Dörfler 	// clip src to visible at dest
1186953d895eSAxel Dörfler 	visibleSrcAtDest.OffsetBy(-xOffset, -yOffset);
1187953d895eSAxel Dörfler 	visibleSrc = visibleSrc & visibleSrcAtDest;
1188953d895eSAxel Dörfler 
1189953d895eSAxel Dörfler 	// do the blit, this will make sure
1190953d895eSAxel Dörfler 	// that other more complex dirty regions
1191953d895eSAxel Dörfler 	// are taken care of
1192953d895eSAxel Dörfler 	BRegion* copyRegion = fWindow->GetRegion();
1193953d895eSAxel Dörfler 	if (!copyRegion)
1194953d895eSAxel Dörfler 		return;
1195953d895eSAxel Dörfler 
1196953d895eSAxel Dörfler 	// move src rect to destination here for efficiency reasons
1197953d895eSAxel Dörfler 	visibleSrc.OffsetBy(xOffset, yOffset);
1198953d895eSAxel Dörfler 
1199f0c3c996SMichael Lotz 	// we need to interstect the copyRegion two times, onces
1200953d895eSAxel Dörfler 	// at the source and once at the destination (here done
1201953d895eSAxel Dörfler 	// the other way arround but it doesn't matter)
1202953d895eSAxel Dörfler 	// the reason for this is that we are not supposed to visually
1203953d895eSAxel Dörfler 	// copy children in the source rect and neither to copy onto
1204953d895eSAxel Dörfler 	// children in the destination rect...
1205953d895eSAxel Dörfler 	copyRegion->Set((clipping_rect)visibleSrc);
1206ea2bcbf4SMichael Lotz 	BRegion *screenAndUserClipping
1207ea2bcbf4SMichael Lotz 		= &ScreenAndUserClipping(&windowContentClipping);
1208ea2bcbf4SMichael Lotz 	copyRegion->IntersectWith(screenAndUserClipping);
1209953d895eSAxel Dörfler 	copyRegion->OffsetBy(-xOffset, -yOffset);
1210ea2bcbf4SMichael Lotz 	copyRegion->IntersectWith(screenAndUserClipping);
1211953d895eSAxel Dörfler 
1212953d895eSAxel Dörfler 	// do the actual blit
1213953d895eSAxel Dörfler 	fWindow->CopyContents(copyRegion, xOffset, yOffset);
1214953d895eSAxel Dörfler 
1215953d895eSAxel Dörfler 	// find the dirty region as far as we are concerned
1216953d895eSAxel Dörfler 	IntRect dirtyDst(dst);
1217953d895eSAxel Dörfler 	ConvertToVisibleInTopView(&dirtyDst);
1218953d895eSAxel Dörfler 
1219953d895eSAxel Dörfler 	BRegion* dirty = fWindow->GetRegion();
1220953d895eSAxel Dörfler 	if (!dirty) {
1221953d895eSAxel Dörfler 		fWindow->RecycleRegion(copyRegion);
1222953d895eSAxel Dörfler 		return;
1223953d895eSAxel Dörfler 	}
1224953d895eSAxel Dörfler 
1225953d895eSAxel Dörfler 	// offset copyRegion to destination again
1226953d895eSAxel Dörfler 	copyRegion->OffsetBy(xOffset, yOffset);
1227953d895eSAxel Dörfler 	// start with destination given by user
1228953d895eSAxel Dörfler 	dirty->Set((clipping_rect)dirtyDst);
1229953d895eSAxel Dörfler 	// exclude the part that we could copy
1230953d895eSAxel Dörfler 	dirty->Exclude(copyRegion);
1231953d895eSAxel Dörfler 
1232ea2bcbf4SMichael Lotz 	dirty->IntersectWith(screenAndUserClipping);
1233953d895eSAxel Dörfler 	fWindow->MarkContentDirty(*dirty);
1234953d895eSAxel Dörfler 
1235953d895eSAxel Dörfler 	fWindow->RecycleRegion(dirty);
1236953d895eSAxel Dörfler 	fWindow->RecycleRegion(copyRegion);
1237953d895eSAxel Dörfler }
1238953d895eSAxel Dörfler 
1239953d895eSAxel Dörfler 
1240953d895eSAxel Dörfler // #pragma mark -
1241953d895eSAxel Dörfler 
1242953d895eSAxel Dörfler 
1243953d895eSAxel Dörfler void
1244953d895eSAxel Dörfler View::PushState()
1245953d895eSAxel Dörfler {
124679ef179cSStephan Aßmus 	DrawState* newState = fDrawState->PushState();
124779ef179cSStephan Aßmus 	if (newState) {
124879ef179cSStephan Aßmus 		fDrawState = newState;
1249953d895eSAxel Dörfler 		fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
1250953d895eSAxel Dörfler 	}
125179ef179cSStephan Aßmus }
1252953d895eSAxel Dörfler 
1253953d895eSAxel Dörfler 
1254953d895eSAxel Dörfler void
1255953d895eSAxel Dörfler View::PopState()
1256953d895eSAxel Dörfler {
1257953d895eSAxel Dörfler 	if (fDrawState->PreviousState() == NULL) {
1258953d895eSAxel Dörfler 		fprintf(stderr, "WARNING: User called BView(%s)::PopState(), "
1259953d895eSAxel Dörfler 			"but there is NO state on stack!\n", Name());
1260953d895eSAxel Dörfler 		return;
1261953d895eSAxel Dörfler 	}
1262953d895eSAxel Dörfler 
1263*2e44cfceSStephan Aßmus 	bool rebuildClipping = fDrawState->HasAdditionalClipping();
1264953d895eSAxel Dörfler 
1265953d895eSAxel Dörfler 	fDrawState = fDrawState->PopState();
1266953d895eSAxel Dörfler 	fDrawState->SetSubPixelPrecise(fFlags & B_SUBPIXEL_PRECISE);
1267953d895eSAxel Dörfler 
1268953d895eSAxel Dörfler 	// rebuild clipping
1269953d895eSAxel Dörfler 	// (the clipping from the popped state is not effective anymore)
1270953d895eSAxel Dörfler 	if (rebuildClipping)
1271953d895eSAxel Dörfler 		RebuildClipping(false);
1272953d895eSAxel Dörfler }
1273953d895eSAxel Dörfler 
1274953d895eSAxel Dörfler 
1275953d895eSAxel Dörfler void
1276953d895eSAxel Dörfler View::SetEventMask(uint32 eventMask, uint32 options)
1277953d895eSAxel Dörfler {
1278953d895eSAxel Dörfler 	fEventMask = eventMask;
1279953d895eSAxel Dörfler 	fEventOptions = options;
1280953d895eSAxel Dörfler }
1281953d895eSAxel Dörfler 
1282953d895eSAxel Dörfler 
1283953d895eSAxel Dörfler void
1284953d895eSAxel Dörfler View::SetCursor(ServerCursor *cursor)
1285953d895eSAxel Dörfler {
1286953d895eSAxel Dörfler 	if (cursor == fCursor)
1287953d895eSAxel Dörfler 		return;
1288953d895eSAxel Dörfler 
1289953d895eSAxel Dörfler 	if (fCursor)
1290953d895eSAxel Dörfler 		fCursor->Release();
1291953d895eSAxel Dörfler 
1292953d895eSAxel Dörfler 	fCursor = cursor;
1293953d895eSAxel Dörfler 
1294953d895eSAxel Dörfler 	if (fCursor) {
1295953d895eSAxel Dörfler 		fCursor->Acquire();
1296953d895eSAxel Dörfler 		fCursor->SetPendingViewCursor(false);
1297953d895eSAxel Dörfler 	}
1298953d895eSAxel Dörfler }
1299953d895eSAxel Dörfler 
1300953d895eSAxel Dörfler 
1301953d895eSAxel Dörfler void
1302953d895eSAxel Dörfler View::SetPicture(ServerPicture *picture)
1303953d895eSAxel Dörfler {
1304953d895eSAxel Dörfler 	fPicture = picture;
1305953d895eSAxel Dörfler }
1306953d895eSAxel Dörfler 
1307953d895eSAxel Dörfler 
1308953d895eSAxel Dörfler void
1309953d895eSAxel Dörfler View::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping,
1310953d895eSAxel Dörfler 	BRegion* windowContentClipping, bool deep)
1311953d895eSAxel Dörfler {
1312953d895eSAxel Dörfler 	if (!fVisible) {
1313953d895eSAxel Dörfler 		// child views cannot be visible either
1314953d895eSAxel Dörfler 		return;
1315953d895eSAxel Dörfler 	}
1316953d895eSAxel Dörfler 
1317953d895eSAxel Dörfler 	if (fViewBitmap != NULL || fViewColor != B_TRANSPARENT_COLOR) {
1318953d895eSAxel Dörfler 		// we can only draw within our own area
1319f0c3c996SMichael Lotz 		BRegion* redraw = fWindow->GetRegion(
1320f0c3c996SMichael Lotz 			_ScreenClipping(windowContentClipping));
1321953d895eSAxel Dörfler 		if (!redraw)
1322953d895eSAxel Dörfler 			return;
1323953d895eSAxel Dörfler 		// add the current clipping
1324953d895eSAxel Dörfler 		redraw->IntersectWith(effectiveClipping);
1325953d895eSAxel Dörfler 
1326953d895eSAxel Dörfler 		Overlay* overlayCookie = _Overlay();
1327953d895eSAxel Dörfler 
1328953d895eSAxel Dörfler 		if (fViewBitmap != NULL && overlayCookie == NULL) {
1329953d895eSAxel Dörfler 			// draw view bitmap
1330953d895eSAxel Dörfler 			// TODO: support other options!
1331953d895eSAxel Dörfler 			BRect rect = fBitmapDestination;
1332953d895eSAxel Dörfler 			ConvertToScreenForDrawing(&rect);
1333953d895eSAxel Dörfler 
1334953d895eSAxel Dörfler 			align_rect_to_pixels(&rect);
1335953d895eSAxel Dörfler 
1336953d895eSAxel Dörfler 			if (fBitmapOptions & B_TILE_BITMAP_Y) {
1337953d895eSAxel Dörfler 				// move rect up as much as needed
1338953d895eSAxel Dörfler 				while (rect.top > redraw->Frame().top)
1339953d895eSAxel Dörfler 					rect.OffsetBy(0.0, -(rect.Height() + 1));
1340953d895eSAxel Dörfler 			}
1341953d895eSAxel Dörfler 			if (fBitmapOptions & B_TILE_BITMAP_X) {
1342953d895eSAxel Dörfler 				// move rect left as much as needed
1343953d895eSAxel Dörfler 				while (rect.left > redraw->Frame().left)
1344953d895eSAxel Dörfler 					rect.OffsetBy(-(rect.Width() + 1), 0.0);
1345953d895eSAxel Dörfler 			}
1346953d895eSAxel Dörfler 
1347953d895eSAxel Dörfler // XXX: locking removed because the Window keeps the engine locked
1348953d895eSAxel Dörfler // because it keeps track of syncing right now
1349953d895eSAxel Dörfler 
1350953d895eSAxel Dörfler 			// lock the drawing engine for as long as we need the clipping
1351953d895eSAxel Dörfler 			// to be valid
1352953d895eSAxel Dörfler 			if (rect.IsValid()/* && drawingEngine->Lock()*/) {
1353953d895eSAxel Dörfler 				drawingEngine->ConstrainClippingRegion(redraw);
1354953d895eSAxel Dörfler 
13552b4f382aSStephan Aßmus 				drawing_mode oldMode;
13562b4f382aSStephan Aßmus 				drawingEngine->SetDrawingMode(B_OP_COPY, oldMode);
13572b4f382aSStephan Aßmus 
1358953d895eSAxel Dörfler 				if (fBitmapOptions & B_TILE_BITMAP) {
1359953d895eSAxel Dörfler 					// tile across entire view
1360953d895eSAxel Dörfler 
1361953d895eSAxel Dörfler 					float start = rect.left;
1362953d895eSAxel Dörfler 					while (rect.top < redraw->Frame().bottom) {
1363953d895eSAxel Dörfler 						while (rect.left < redraw->Frame().right) {
1364953d895eSAxel Dörfler 							drawingEngine->DrawBitmap(fViewBitmap,
13657eed63a1SStephan Aßmus 								fBitmapSource, rect, fBitmapOptions);
1366953d895eSAxel Dörfler 							rect.OffsetBy(rect.Width() + 1, 0.0);
1367953d895eSAxel Dörfler 						}
1368953d895eSAxel Dörfler 						rect.OffsetBy(start - rect.left, rect.Height() + 1);
1369953d895eSAxel Dörfler 					}
1370953d895eSAxel Dörfler 					// nothing left to be drawn
1371953d895eSAxel Dörfler 					redraw->MakeEmpty();
1372953d895eSAxel Dörfler 				} else if (fBitmapOptions & B_TILE_BITMAP_X) {
1373953d895eSAxel Dörfler 					// tile in x direction
1374953d895eSAxel Dörfler 
1375953d895eSAxel Dörfler 					while (rect.left < redraw->Frame().right) {
1376953d895eSAxel Dörfler 						drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
13777eed63a1SStephan Aßmus 							rect, fBitmapOptions);
1378953d895eSAxel Dörfler 						rect.OffsetBy(rect.Width() + 1, 0.0);
1379953d895eSAxel Dörfler 					}
1380953d895eSAxel Dörfler 					// remove horizontal stripe from clipping
1381953d895eSAxel Dörfler 					rect.left = redraw->Frame().left;
1382953d895eSAxel Dörfler 					rect.right = redraw->Frame().right;
1383953d895eSAxel Dörfler 					redraw->Exclude(rect);
1384953d895eSAxel Dörfler 				} else if (fBitmapOptions & B_TILE_BITMAP_Y) {
1385953d895eSAxel Dörfler 					// tile in y direction
1386953d895eSAxel Dörfler 
1387953d895eSAxel Dörfler 					while (rect.top < redraw->Frame().bottom) {
1388953d895eSAxel Dörfler 						drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
13897eed63a1SStephan Aßmus 							rect, fBitmapOptions);
1390953d895eSAxel Dörfler 						rect.OffsetBy(0.0, rect.Height() + 1);
1391953d895eSAxel Dörfler 					}
1392953d895eSAxel Dörfler 					// remove vertical stripe from clipping
1393953d895eSAxel Dörfler 					rect.top = redraw->Frame().top;
1394953d895eSAxel Dörfler 					rect.bottom = redraw->Frame().bottom;
1395953d895eSAxel Dörfler 					redraw->Exclude(rect);
1396953d895eSAxel Dörfler 				} else {
1397953d895eSAxel Dörfler 					// no tiling at all
1398953d895eSAxel Dörfler 
1399953d895eSAxel Dörfler 					drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource,
14007eed63a1SStephan Aßmus 						rect, fBitmapOptions);
1401953d895eSAxel Dörfler 					redraw->Exclude(rect);
1402953d895eSAxel Dörfler 				}
1403953d895eSAxel Dörfler 
14042b4f382aSStephan Aßmus 				drawingEngine->SetDrawingMode(oldMode);
14052b4f382aSStephan Aßmus 
1406953d895eSAxel Dörfler 				// NOTE: It is ok not to reset the clipping, that
1407953d895eSAxel Dörfler 				// would only waste time
1408953d895eSAxel Dörfler //				drawingEngine->Unlock();
1409953d895eSAxel Dörfler 			}
1410953d895eSAxel Dörfler 
1411953d895eSAxel Dörfler 		}
1412953d895eSAxel Dörfler 
1413953d895eSAxel Dörfler 		if (fViewColor != B_TRANSPARENT_COLOR) {
1414953d895eSAxel Dörfler 			// fill visible region with view color,
1415953d895eSAxel Dörfler 			// this version of FillRegion ignores any
1416953d895eSAxel Dörfler 			// clipping, that's why "redraw" needs to
1417953d895eSAxel Dörfler 			// be correct
1418953d895eSAxel Dörfler // see #634
1419953d895eSAxel Dörfler //			if (redraw->Frame().left < 0 || redraw->Frame().top < 0) {
1420953d895eSAxel Dörfler //				char message[1024];
1421953d895eSAxel Dörfler //				BRect c = effectiveClipping->Frame();
1422953d895eSAxel Dörfler //				BRect w = windowContentClipping->Frame();
1423953d895eSAxel Dörfler //				BRect r = redraw->Frame();
1424953d895eSAxel Dörfler //				sprintf(message, "invalid background: current clipping: (%d, %d)->(%d, %d), "
1425953d895eSAxel Dörfler //					"window content: (%d, %d)->(%d, %d), redraw: (%d, %d)->(%d, %d)",
1426953d895eSAxel Dörfler //					(int)c.left, (int)c.top, (int)c.right, (int)c.bottom,
1427953d895eSAxel Dörfler //					(int)w.left, (int)w.top, (int)w.right, (int)w.bottom,
1428953d895eSAxel Dörfler //					(int)r.left, (int)r.top, (int)r.right, (int)r.bottom);
1429953d895eSAxel Dörfler //				debugger(message);
1430953d895eSAxel Dörfler //			}
1431953d895eSAxel Dörfler 
1432953d895eSAxel Dörfler 			drawingEngine->FillRegion(*redraw, overlayCookie != NULL
1433953d895eSAxel Dörfler 				? overlayCookie->Color() : fViewColor);
1434953d895eSAxel Dörfler 		}
1435953d895eSAxel Dörfler 
1436953d895eSAxel Dörfler 		fWindow->RecycleRegion(redraw);
1437953d895eSAxel Dörfler 	}
1438953d895eSAxel Dörfler 
1439953d895eSAxel Dörfler 	fBackgroundDirty = false;
1440953d895eSAxel Dörfler 
1441953d895eSAxel Dörfler 	// let children draw
1442953d895eSAxel Dörfler 	if (deep) {
1443953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
1444953d895eSAxel Dörfler 			child->Draw(drawingEngine, effectiveClipping,
1445953d895eSAxel Dörfler 				windowContentClipping, deep);
1446953d895eSAxel Dörfler 		}
1447953d895eSAxel Dörfler 	}
1448953d895eSAxel Dörfler }
1449953d895eSAxel Dörfler 
1450953d895eSAxel Dörfler 
1451953d895eSAxel Dörfler // #pragma mark -
1452953d895eSAxel Dörfler 
1453953d895eSAxel Dörfler 
1454953d895eSAxel Dörfler void
1455953d895eSAxel Dörfler View::MouseDown(BMessage* message, BPoint where)
1456953d895eSAxel Dörfler {
1457953d895eSAxel Dörfler 	// empty hook method
1458953d895eSAxel Dörfler }
1459953d895eSAxel Dörfler 
1460953d895eSAxel Dörfler 
1461953d895eSAxel Dörfler void
1462953d895eSAxel Dörfler View::MouseUp(BMessage* message, BPoint where)
1463953d895eSAxel Dörfler {
1464953d895eSAxel Dörfler 	// empty hook method
1465953d895eSAxel Dörfler }
1466953d895eSAxel Dörfler 
1467953d895eSAxel Dörfler 
1468953d895eSAxel Dörfler void
1469953d895eSAxel Dörfler View::MouseMoved(BMessage* message, BPoint where)
1470953d895eSAxel Dörfler {
1471953d895eSAxel Dörfler 	// empty hook method
1472953d895eSAxel Dörfler }
1473953d895eSAxel Dörfler 
1474953d895eSAxel Dörfler 
1475953d895eSAxel Dörfler // #pragma mark -
1476953d895eSAxel Dörfler 
1477953d895eSAxel Dörfler 
1478953d895eSAxel Dörfler void
1479953d895eSAxel Dörfler View::SetHidden(bool hidden)
1480953d895eSAxel Dörfler {
1481953d895eSAxel Dörfler 	if (fHidden != hidden) {
1482953d895eSAxel Dörfler 		fHidden = hidden;
1483953d895eSAxel Dörfler 
1484953d895eSAxel Dörfler 		// recurse into children and update their visible flag
1485953d895eSAxel Dörfler 		bool oldVisible = fVisible;
1486953d895eSAxel Dörfler 		UpdateVisibleDeep(fParent ? fParent->IsVisible() : !fHidden);
1487953d895eSAxel Dörfler 		if (oldVisible != fVisible) {
1488953d895eSAxel Dörfler 			// Include or exclude us from the parent area, and update the
1489953d895eSAxel Dörfler 			// children's clipping as well when the view will be visible
1490953d895eSAxel Dörfler 			if (fParent)
1491953d895eSAxel Dörfler 				fParent->RebuildClipping(fVisible);
1492953d895eSAxel Dörfler 			else
1493953d895eSAxel Dörfler 				RebuildClipping(fVisible);
1494953d895eSAxel Dörfler 
1495953d895eSAxel Dörfler 			if (fWindow) {
1496953d895eSAxel Dörfler 				// trigger a redraw
1497953d895eSAxel Dörfler 				IntRect clippedBounds = Bounds();
1498953d895eSAxel Dörfler 				ConvertToVisibleInTopView(&clippedBounds);
1499953d895eSAxel Dörfler 				BRegion* dirty = fWindow->GetRegion();
1500953d895eSAxel Dörfler 				if (!dirty)
1501953d895eSAxel Dörfler 					return;
1502953d895eSAxel Dörfler 				dirty->Set((clipping_rect)clippedBounds);
1503953d895eSAxel Dörfler 				fWindow->MarkContentDirty(*dirty);
1504953d895eSAxel Dörfler 				fWindow->RecycleRegion(dirty);
1505953d895eSAxel Dörfler 			}
1506953d895eSAxel Dörfler 		}
1507953d895eSAxel Dörfler 	}
1508953d895eSAxel Dörfler }
1509953d895eSAxel Dörfler 
1510953d895eSAxel Dörfler 
1511953d895eSAxel Dörfler bool
1512953d895eSAxel Dörfler View::IsHidden() const
1513953d895eSAxel Dörfler {
1514953d895eSAxel Dörfler 	return fHidden;
1515953d895eSAxel Dörfler }
1516953d895eSAxel Dörfler 
1517953d895eSAxel Dörfler 
1518953d895eSAxel Dörfler void
1519953d895eSAxel Dörfler View::UpdateVisibleDeep(bool parentVisible)
1520953d895eSAxel Dörfler {
1521953d895eSAxel Dörfler 	bool wasVisible = fVisible;
1522953d895eSAxel Dörfler 
1523953d895eSAxel Dörfler 	fVisible = parentVisible && !fHidden;
1524953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
1525953d895eSAxel Dörfler 		child->UpdateVisibleDeep(fVisible);
1526953d895eSAxel Dörfler 
1527953d895eSAxel Dörfler 	// overlay handling
1528953d895eSAxel Dörfler 
1529953d895eSAxel Dörfler 	Overlay* overlay = _Overlay();
1530953d895eSAxel Dörfler 	if (overlay == NULL)
1531953d895eSAxel Dörfler 		return;
1532953d895eSAxel Dörfler 
1533953d895eSAxel Dörfler 	if (fVisible && !wasVisible)
1534953d895eSAxel Dörfler 		_UpdateOverlayView();
1535953d895eSAxel Dörfler 	else if (!fVisible && wasVisible)
1536953d895eSAxel Dörfler 		overlay->Hide();
1537953d895eSAxel Dörfler }
1538953d895eSAxel Dörfler 
1539953d895eSAxel Dörfler 
1540953d895eSAxel Dörfler // #pragma mark -
1541953d895eSAxel Dörfler 
1542953d895eSAxel Dörfler 
1543953d895eSAxel Dörfler void
1544953d895eSAxel Dörfler View::MarkBackgroundDirty()
1545953d895eSAxel Dörfler {
1546953d895eSAxel Dörfler 	if (fBackgroundDirty)
1547953d895eSAxel Dörfler 		return;
1548953d895eSAxel Dörfler 	fBackgroundDirty = true;
1549953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling())
1550953d895eSAxel Dörfler 		child->MarkBackgroundDirty();
1551953d895eSAxel Dörfler }
1552953d895eSAxel Dörfler 
1553953d895eSAxel Dörfler 
1554953d895eSAxel Dörfler void
1555437b1927SAxel Dörfler View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region,
1556953d895eSAxel Dörfler 	BRegion* windowContentClipping)
1557953d895eSAxel Dörfler {
1558953d895eSAxel Dörfler 	if (!fVisible)
1559953d895eSAxel Dörfler 		return;
1560953d895eSAxel Dörfler 
1561581e6786SStephan Aßmus 	{
1562581e6786SStephan Aßmus 		// NOTE: use scope in order to reduce stack space requirements
1563581e6786SStephan Aßmus 
1564581e6786SStephan Aßmus 		// This check will prevent descending the view hierarchy
1565581e6786SStephan Aßmus 		// any further than necessary
1566953d895eSAxel Dörfler 		IntRect screenBounds(Bounds());
1567953d895eSAxel Dörfler 		ConvertToScreen(&screenBounds);
1568953d895eSAxel Dörfler 		if (!region.Intersects((clipping_rect)screenBounds))
1569953d895eSAxel Dörfler 			return;
1570953d895eSAxel Dörfler 
1571581e6786SStephan Aßmus 		// Unfortunately, we intersecting another region, but otherwise
1572581e6786SStephan Aßmus 		// we couldn't provide the exact update rect to the client
1573581e6786SStephan Aßmus 		BRegion localDirty = _ScreenClipping(windowContentClipping);
1574581e6786SStephan Aßmus 		localDirty.IntersectWith(&region);
1575581e6786SStephan Aßmus 		if (localDirty.CountRects() > 0) {
1576953d895eSAxel Dörfler 			link.Attach<int32>(fToken);
1577581e6786SStephan Aßmus 			link.Attach<BRect>(localDirty.Frame());
1578953d895eSAxel Dörfler 		}
1579953d895eSAxel Dörfler 	}
1580953d895eSAxel Dörfler 
1581581e6786SStephan Aßmus 	for (View* child = FirstChild(); child; child = child->NextSibling())
1582581e6786SStephan Aßmus 		child->AddTokensForViewsInRegion(link, region, windowContentClipping);
1583581e6786SStephan Aßmus }
1584581e6786SStephan Aßmus 
1585953d895eSAxel Dörfler 
1586953d895eSAxel Dörfler void
1587953d895eSAxel Dörfler View::PrintToStream() const
1588953d895eSAxel Dörfler {
1589953d895eSAxel Dörfler 	printf("View:          %s\n", Name());
1590953d895eSAxel Dörfler 	printf("  fToken:           %ld\n", fToken);
1591953d895eSAxel Dörfler 	printf("  fFrame:           IntRect(%ld, %ld, %ld, %ld)\n", fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);
1592953d895eSAxel Dörfler 	printf("  fScrollingOffset: IntPoint(%ld, %ld)\n", fScrollingOffset.x, fScrollingOffset.y);
1593953d895eSAxel Dörfler 	printf("  fHidden:          %d\n", fHidden);
1594953d895eSAxel Dörfler 	printf("  fVisible:         %d\n", fVisible);
1595953d895eSAxel Dörfler 	printf("  fWindow:          %p\n", fWindow);
1596953d895eSAxel Dörfler 	printf("  fParent:          %p\n", fParent);
1597953d895eSAxel Dörfler 	printf("  fLocalClipping:\n");
1598953d895eSAxel Dörfler 	fLocalClipping.PrintToStream();
1599953d895eSAxel Dörfler 	printf("  fScreenClipping:\n");
1600953d895eSAxel Dörfler 	fScreenClipping.PrintToStream();
1601953d895eSAxel Dörfler 	printf("  valid:            %d\n", fScreenClippingValid);
1602f0c3c996SMichael Lotz 
1603f0c3c996SMichael Lotz 	printf("  fUserClipping:\n");
1604f0c3c996SMichael Lotz 	if (fUserClipping != NULL)
1605f0c3c996SMichael Lotz 		fUserClipping->PrintToStream();
1606f0c3c996SMichael Lotz 	else
1607f0c3c996SMichael Lotz 		printf("  none\n");
1608f0c3c996SMichael Lotz 
1609f0c3c996SMichael Lotz 	printf("  fScreenAndUserClipping:\n");
1610f0c3c996SMichael Lotz 	if (fScreenAndUserClipping != NULL)
1611f0c3c996SMichael Lotz 		fScreenAndUserClipping->PrintToStream();
1612f0c3c996SMichael Lotz 	else
1613f0c3c996SMichael Lotz 		printf("  invalid\n");
1614f0c3c996SMichael Lotz 
1615953d895eSAxel Dörfler 	printf("  state:\n");
161679ef179cSStephan Aßmus 	printf("    user clipping:  %d\n", fDrawState->HasClipping());
161779ef179cSStephan Aßmus 	BPoint origin = fDrawState->CombinedOrigin();
161879ef179cSStephan Aßmus 	printf("    origin:         BPoint(%.1f, %.1f)\n", origin.x, origin.y);
161979ef179cSStephan Aßmus 	printf("    scale:          %.2f\n", fDrawState->CombinedScale());
1620953d895eSAxel Dörfler 	printf("\n");
1621953d895eSAxel Dörfler }
1622953d895eSAxel Dörfler 
1623953d895eSAxel Dörfler 
1624953d895eSAxel Dörfler void
1625953d895eSAxel Dörfler View::RebuildClipping(bool deep)
1626953d895eSAxel Dörfler {
1627953d895eSAxel Dörfler 	// the clipping spans over the bounds area
1628953d895eSAxel Dörfler 	fLocalClipping.Set((clipping_rect)Bounds());
1629953d895eSAxel Dörfler 
1630953d895eSAxel Dörfler 	if (View* child = FirstChild()) {
1631953d895eSAxel Dörfler 		// if this view does not draw over children,
1632953d895eSAxel Dörfler 		// exclude all children from the clipping
1633953d895eSAxel Dörfler 		if ((fFlags & B_DRAW_ON_CHILDREN) == 0) {
1634953d895eSAxel Dörfler 			BRegion* childrenRegion = fWindow->GetRegion();
1635953d895eSAxel Dörfler 			if (!childrenRegion)
1636953d895eSAxel Dörfler 				return;
1637953d895eSAxel Dörfler 
1638953d895eSAxel Dörfler 			for (; child; child = child->NextSibling()) {
1639953d895eSAxel Dörfler 				if (child->IsVisible())
1640953d895eSAxel Dörfler 					childrenRegion->Include((clipping_rect)child->Frame());
1641953d895eSAxel Dörfler 			}
1642953d895eSAxel Dörfler 
1643953d895eSAxel Dörfler 			fLocalClipping.Exclude(childrenRegion);
1644953d895eSAxel Dörfler 			fWindow->RecycleRegion(childrenRegion);
1645953d895eSAxel Dörfler 		}
1646953d895eSAxel Dörfler 		// if the operation is "deep", make children rebuild their
1647953d895eSAxel Dörfler 		// clipping too
1648953d895eSAxel Dörfler 		if (deep) {
1649953d895eSAxel Dörfler 			for (child = FirstChild(); child; child = child->NextSibling())
1650953d895eSAxel Dörfler 				child->RebuildClipping(true);
1651953d895eSAxel Dörfler 		}
1652953d895eSAxel Dörfler 	}
1653953d895eSAxel Dörfler 
1654953d895eSAxel Dörfler 	// add the user clipping in case there is one
165579ef179cSStephan Aßmus 	if (fDrawState->HasClipping()) {
1656953d895eSAxel Dörfler 		// NOTE: in case the user sets a user defined clipping region,
1657953d895eSAxel Dörfler 		// rebuilding the clipping is a bit more expensive because there
1658953d895eSAxel Dörfler 		// is no separate "drawing region"... on the other
1659953d895eSAxel Dörfler 		// hand, views for which this feature is actually used will
1660953d895eSAxel Dörfler 		// probably not have any children, so it is not that expensive
1661953d895eSAxel Dörfler 		// after all
1662f0c3c996SMichael Lotz 		if (fUserClipping == NULL) {
1663f0c3c996SMichael Lotz 			fUserClipping = new (nothrow) BRegion;
1664f0c3c996SMichael Lotz 			if (fUserClipping == NULL)
1665953d895eSAxel Dörfler 				return;
1666953d895eSAxel Dörfler 		}
1667953d895eSAxel Dörfler 
1668f0c3c996SMichael Lotz 		fDrawState->GetCombinedClippingRegion(fUserClipping);
1669f0c3c996SMichael Lotz 	} else {
1670f0c3c996SMichael Lotz 		delete fUserClipping;
1671f0c3c996SMichael Lotz 		fUserClipping = NULL;
1672f0c3c996SMichael Lotz 	}
1673f0c3c996SMichael Lotz 
1674f0c3c996SMichael Lotz 	delete fScreenAndUserClipping;
1675f0c3c996SMichael Lotz 	fScreenAndUserClipping = NULL;
1676953d895eSAxel Dörfler 	fScreenClippingValid = false;
1677953d895eSAxel Dörfler }
1678953d895eSAxel Dörfler 
1679953d895eSAxel Dörfler 
1680953d895eSAxel Dörfler BRegion&
1681f0c3c996SMichael Lotz View::ScreenAndUserClipping(BRegion* windowContentClipping, bool force) const
1682953d895eSAxel Dörfler {
1683f0c3c996SMichael Lotz 	// no user clipping - return screen clipping directly
1684f0c3c996SMichael Lotz 	if (fUserClipping == NULL)
1685f0c3c996SMichael Lotz 		return _ScreenClipping(windowContentClipping, force);
1686953d895eSAxel Dörfler 
1687f0c3c996SMichael Lotz 	// combined screen and user clipping already valid
1688f0c3c996SMichael Lotz 	if (fScreenAndUserClipping != NULL)
1689f0c3c996SMichael Lotz 		return *fScreenAndUserClipping;
1690953d895eSAxel Dörfler 
1691f0c3c996SMichael Lotz 	// build a new combined user and screen clipping
1692f0c3c996SMichael Lotz 	fScreenAndUserClipping = new (nothrow) BRegion(*fUserClipping);
1693f0c3c996SMichael Lotz 	if (fScreenAndUserClipping == NULL)
1694953d895eSAxel Dörfler 		return fScreenClipping;
1695f0c3c996SMichael Lotz 
1696f0c3c996SMichael Lotz 	ConvertToScreen(fScreenAndUserClipping);
1697f0c3c996SMichael Lotz 	fScreenAndUserClipping->IntersectWith(
1698f0c3c996SMichael Lotz 		&_ScreenClipping(windowContentClipping, force));
1699f0c3c996SMichael Lotz 	return *fScreenAndUserClipping;
1700953d895eSAxel Dörfler }
1701953d895eSAxel Dörfler 
1702953d895eSAxel Dörfler 
1703953d895eSAxel Dörfler void
1704953d895eSAxel Dörfler View::InvalidateScreenClipping()
1705953d895eSAxel Dörfler {
1706953d895eSAxel Dörfler // TODO: appearantly, we are calling ScreenClipping() on
1707953d895eSAxel Dörfler // views who's parents don't have a valid screen clipping yet,
1708953d895eSAxel Dörfler // this messes up the logic that for any given view with
1709953d895eSAxel Dörfler // fScreenClippingValid == false, all children have
1710953d895eSAxel Dörfler // fScreenClippingValid == false too. If this could be made the
1711953d895eSAxel Dörfler // case, we could save some performance here with the commented
1712953d895eSAxel Dörfler // out check, since InvalidateScreenClipping() might be called
1713953d895eSAxel Dörfler // frequently.
1714953d895eSAxel Dörfler // TODO: investigate, if InvalidateScreenClipping() could be
1715953d895eSAxel Dörfler // called in "deep" and "non-deep" mode, ie. see if there are
1716953d895eSAxel Dörfler // any cases where the children would still have valid screen
1717953d895eSAxel Dörfler // clipping, even though the parent's screen clipping becomes
1718953d895eSAxel Dörfler // invalid.
1719953d895eSAxel Dörfler //	if (!fScreenClippingValid)
1720953d895eSAxel Dörfler //		return;
1721953d895eSAxel Dörfler 
1722f0c3c996SMichael Lotz 	delete fScreenAndUserClipping;
1723f0c3c996SMichael Lotz 	fScreenAndUserClipping = NULL;
1724953d895eSAxel Dörfler 	fScreenClippingValid = false;
1725953d895eSAxel Dörfler 	// invalidate the childrens screen clipping as well
1726953d895eSAxel Dörfler 	for (View* child = FirstChild(); child; child = child->NextSibling()) {
1727953d895eSAxel Dörfler 		child->InvalidateScreenClipping();
1728953d895eSAxel Dörfler 	}
1729953d895eSAxel Dörfler }
1730953d895eSAxel Dörfler 
1731953d895eSAxel Dörfler 
1732f0c3c996SMichael Lotz BRegion&
1733f0c3c996SMichael Lotz View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
1734f0c3c996SMichael Lotz {
1735f0c3c996SMichael Lotz 	if (!fScreenClippingValid || force) {
1736f0c3c996SMichael Lotz 		fScreenClipping = fLocalClipping;
1737f0c3c996SMichael Lotz 		ConvertToScreen(&fScreenClipping);
1738f0c3c996SMichael Lotz 
1739f0c3c996SMichael Lotz 		// see if parts of our bounds are hidden underneath
1740f0c3c996SMichael Lotz 		// the parent, the local clipping does not account for this
1741f0c3c996SMichael Lotz 		IntRect clippedBounds = Bounds();
1742f0c3c996SMichael Lotz 		ConvertToVisibleInTopView(&clippedBounds);
1743f0c3c996SMichael Lotz 		if (clippedBounds.Width() < fScreenClipping.Frame().Width()
1744f0c3c996SMichael Lotz 			|| clippedBounds.Height() < fScreenClipping.Frame().Height()) {
1745f0c3c996SMichael Lotz 			BRegion* temp = fWindow->GetRegion();
1746f0c3c996SMichael Lotz 			if (temp) {
1747f0c3c996SMichael Lotz 				temp->Set((clipping_rect)clippedBounds);
1748f0c3c996SMichael Lotz 				fScreenClipping.IntersectWith(temp);
1749f0c3c996SMichael Lotz 				fWindow->RecycleRegion(temp);
1750f0c3c996SMichael Lotz 			}
1751f0c3c996SMichael Lotz 		}
1752f0c3c996SMichael Lotz 
1753f0c3c996SMichael Lotz 		fScreenClipping.IntersectWith(windowContentClipping);
1754f0c3c996SMichael Lotz 		fScreenClippingValid = true;
1755f0c3c996SMichael Lotz 	}
1756f0c3c996SMichael Lotz 
1757f0c3c996SMichael Lotz 	return fScreenClipping;
1758f0c3c996SMichael Lotz }
1759f0c3c996SMichael Lotz 
1760f0c3c996SMichael Lotz 
1761953d895eSAxel Dörfler void
1762953d895eSAxel Dörfler View::_MoveScreenClipping(int32 x, int32 y, bool deep)
1763953d895eSAxel Dörfler {
1764f0c3c996SMichael Lotz 	if (fScreenClippingValid) {
1765953d895eSAxel Dörfler 		fScreenClipping.OffsetBy(x, y);
1766f0c3c996SMichael Lotz 		delete fScreenAndUserClipping;
1767f0c3c996SMichael Lotz 		fScreenAndUserClipping = NULL;
1768f0c3c996SMichael Lotz 	}
1769953d895eSAxel Dörfler 
1770953d895eSAxel Dörfler 	if (deep) {
1771953d895eSAxel Dörfler 		// move the childrens screen clipping as well
1772953d895eSAxel Dörfler 		for (View* child = FirstChild(); child; child = child->NextSibling()) {
1773953d895eSAxel Dörfler 			child->_MoveScreenClipping(x, y, deep);
1774953d895eSAxel Dörfler 		}
1775953d895eSAxel Dörfler 	}
1776953d895eSAxel Dörfler }
1777953d895eSAxel Dörfler 
1778