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(®ion);
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