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(¢er); 835991547efSStephan Aßmus ConvertToScreen(¢er); 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(¢er); 845991547efSStephan Aßmus ConvertToScreen(¢er); 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(¢er); 857991547efSStephan Aßmus ConvertToScreen(¢er); 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(¢er); 866991547efSStephan Aßmus ConvertToScreen(¢er); 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(®ion); 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