1 /* 2 * Copyright 2001-2020, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * DarkWyrm, bpmagic@columbus.rr.com 7 * Adi Oanca, adioanca@gmail.com 8 * Stephan Aßmus, superstippi@gmx.de 9 * Axel Dörfler, axeld@pinc-software.de 10 * Brecht Machiels, brecht@mos6581.org 11 * Clemens Zeidler, haiku@clemens-zeidler.de 12 * Tri-Edge AI 13 * Jacob Secunda, secundja@gmail.com 14 */ 15 #ifndef WINDOW_H 16 #define WINDOW_H 17 18 19 #include "RegionPool.h" 20 #include "ServerWindow.h" 21 #include "View.h" 22 #include "WindowList.h" 23 24 #include <AutoDeleter.h> 25 #include <ObjectList.h> 26 #include <Referenceable.h> 27 #include <Region.h> 28 #include <String.h> 29 30 31 class Window; 32 33 34 typedef BObjectList<Window> StackWindows; 35 36 37 class WindowStack : public BReferenceable { 38 public: 39 WindowStack(::Decorator* decorator); 40 ~WindowStack(); 41 42 void SetDecorator(::Decorator* decorator); 43 ::Decorator* Decorator(); 44 WindowList()45 const StackWindows& WindowList() const { return fWindowList; } LayerOrder()46 const StackWindows& LayerOrder() const { return fWindowLayerOrder; } 47 48 Window* TopLayerWindow() const; 49 50 int32 CountWindows(); 51 Window* WindowAt(int32 index); 52 bool AddWindow(Window* window, 53 int32 position = -1); 54 bool RemoveWindow(Window* window); 55 56 bool MoveToTopLayer(Window* window); 57 bool Move(int32 from, int32 to); 58 private: 59 ObjectDeleter< ::Decorator> 60 fDecorator; 61 62 StackWindows fWindowList; 63 StackWindows fWindowLayerOrder; 64 }; 65 66 67 namespace BPrivate { 68 class PortLink; 69 }; 70 71 class ClickTarget; 72 class ClientLooper; 73 class Decorator; 74 class Desktop; 75 class DrawingEngine; 76 class EventDispatcher; 77 class Screen; 78 class WindowBehaviour; 79 class WorkspacesView; 80 81 // TODO: move this into a proper place 82 #define AS_REDRAW 'rdrw' 83 84 85 class Window { 86 public: 87 Window(const BRect& frame, const char *name, 88 window_look look, window_feel feel, 89 uint32 flags, uint32 workspaces, 90 ::ServerWindow* window, 91 DrawingEngine* drawingEngine); 92 virtual ~Window(); 93 94 status_t InitCheck() const; 95 Frame()96 BRect Frame() const { return fFrame; } Title()97 const char* Title() const { return fTitle.String(); } 98 99 window_anchor& Anchor(int32 index); 100 Window* NextWindow(int32 index) const; 101 Window* PreviousWindow(int32 index) const; 102 Desktop()103 ::Desktop* Desktop() const { return fDesktop; } 104 ::Decorator* Decorator() const; ServerWindow()105 ::ServerWindow* ServerWindow() const { return fWindow; } EventTarget()106 ::EventTarget& EventTarget() const 107 { return fWindow->EventTarget(); } 108 109 bool ReloadDecor(); 110 111 void SetScreen(const ::Screen* screen); 112 const ::Screen* Screen() const; 113 114 // setting and getting the "hard" clipping, you need to have 115 // WriteLock()ed the clipping! 116 void SetClipping(BRegion* stillAvailableOnScreen); 117 // you need to have ReadLock()ed the clipping! VisibleRegion()118 inline BRegion& VisibleRegion() { return fVisibleRegion; } 119 BRegion& VisibleContentRegion(); 120 121 // TODO: not protected by a lock, but noone should need this anyways 122 // make private? when used inside Window, it has the ReadLock() 123 void GetFullRegion(BRegion* region); 124 void GetBorderRegion(BRegion* region); 125 void GetContentRegion(BRegion* region); 126 127 void MoveBy(int32 x, int32 y, bool moveStack = true); 128 void ResizeBy(int32 x, int32 y, 129 BRegion* dirtyRegion, 130 bool resizeStack = true); 131 void SetOutlinesDelta(BPoint delta, 132 BRegion* dirtyRegion); 133 134 void ScrollViewBy(View* view, int32 dx, int32 dy); 135 136 void SetTopView(View* topView); TopView()137 View* TopView() const { return fTopView.Get(); } 138 View* ViewAt(const BPoint& where); 139 IsOffscreenWindow()140 virtual bool IsOffscreenWindow() const { return false; } 141 142 void GetEffectiveDrawingRegion(View* view, 143 BRegion& region); 144 bool DrawingRegionChanged(View* view) const; 145 146 // generic version, used by the Desktop 147 void ProcessDirtyRegion(const BRegion& dirtyRegion, 148 const BRegion& exposeRegion); ProcessDirtyRegion(const BRegion & exposeRegion)149 void ProcessDirtyRegion(const BRegion& exposeRegion) 150 { ProcessDirtyRegion(exposeRegion, exposeRegion); } 151 void RedrawDirtyRegion(); 152 153 // can be used from inside classes that don't 154 // need to know about Desktop (first version uses Desktop) 155 void MarkDirty(BRegion& regionOnScreen); 156 // these versions do not use the Desktop 157 void MarkContentDirty(BRegion& dirtyRegion, 158 BRegion& exposeRegion); 159 void MarkContentDirtyAsync(BRegion& dirtyRegion); 160 // shortcut for invalidating just one view 161 void InvalidateView(View* view, BRegion& viewRegion); 162 163 void DisableUpdateRequests(); 164 void EnableUpdateRequests(); 165 166 void BeginUpdate(BPrivate::PortLink& link); 167 void EndUpdate(); InUpdate()168 bool InUpdate() const 169 { return fInUpdate; } 170 NeedsUpdate()171 bool NeedsUpdate() const 172 { return fUpdateRequested; } 173 GetDrawingEngine()174 DrawingEngine* GetDrawingEngine() const 175 { return fDrawingEngine.Get(); } 176 177 // managing a region pool RegionPool()178 ::RegionPool* RegionPool() 179 { return &fRegionPool; } GetRegion()180 inline BRegion* GetRegion() 181 { return fRegionPool.GetRegion(); } GetRegion(const BRegion & copy)182 inline BRegion* GetRegion(const BRegion& copy) 183 { return fRegionPool.GetRegion(copy); } RecycleRegion(BRegion * region)184 inline void RecycleRegion(BRegion* region) 185 { fRegionPool.Recycle(region); } 186 187 void CopyContents(BRegion* region, 188 int32 xOffset, int32 yOffset); 189 190 void MouseDown(BMessage* message, BPoint where, 191 const ClickTarget& lastClickTarget, 192 int32& clickCount, 193 ClickTarget& _clickTarget); 194 void MouseUp(BMessage* message, BPoint where, 195 int32* _viewToken); 196 void MouseMoved(BMessage* message, BPoint where, 197 int32* _viewToken, bool isLatestMouseMoved, 198 bool isFake); 199 200 void ModifiersChanged(int32 modifiers); 201 202 // some hooks to inform the client window 203 // TODO: move this to ServerWindow maybe? 204 void WorkspaceActivated(int32 index, bool active); 205 void WorkspacesChanged(uint32 oldWorkspaces, 206 uint32 newWorkspaces); 207 void Activated(bool active); 208 209 // changing some properties 210 void SetTitle(const char* name, BRegion& dirty); 211 212 void SetFocus(bool focus); IsFocus()213 bool IsFocus() const { return fIsFocus; } 214 215 void SetHidden(bool hidden); IsHidden()216 inline bool IsHidden() const { return fHidden; } 217 218 void SetShowLevel(int32 showLevel); ShowLevel()219 inline int32 ShowLevel() const { return fShowLevel; } 220 221 void SetMinimized(bool minimized); IsMinimized()222 inline bool IsMinimized() const { return fMinimized; } 223 SetCurrentWorkspace(int32 index)224 void SetCurrentWorkspace(int32 index) 225 { fCurrentWorkspace = index; } CurrentWorkspace()226 int32 CurrentWorkspace() const 227 { return fCurrentWorkspace; } 228 bool IsVisible() const; 229 230 bool IsDragging() const; 231 bool IsResizing() const; 232 233 void SetSizeLimits(int32 minWidth, int32 maxWidth, 234 int32 minHeight, int32 maxHeight); 235 236 void GetSizeLimits(int32* minWidth, int32* maxWidth, 237 int32* minHeight, int32* maxHeight) const; 238 239 // 0.0 -> left .... 1.0 -> right 240 bool SetTabLocation(float location, bool isShifting, 241 BRegion& dirty); 242 float TabLocation() const; 243 244 bool SetDecoratorSettings(const BMessage& settings, 245 BRegion& dirty); 246 bool GetDecoratorSettings(BMessage* settings); 247 248 void HighlightDecorator(bool active); 249 250 void FontsChanged(BRegion* updateRegion); 251 void ColorsChanged(BRegion* updateRegion); 252 253 void SetLook(window_look look, 254 BRegion* updateRegion); 255 void SetFeel(window_feel feel); 256 void SetFlags(uint32 flags, BRegion* updateRegion); 257 Look()258 window_look Look() const { return fLook; } Feel()259 window_feel Feel() const { return fFeel; } Flags()260 uint32 Flags() const { return fFlags; } 261 262 // window manager stuff Workspaces()263 uint32 Workspaces() const { return fWorkspaces; } SetWorkspaces(uint32 workspaces)264 void SetWorkspaces(uint32 workspaces) 265 { fWorkspaces = workspaces; } 266 bool InWorkspace(int32 index) const; 267 268 bool SupportsFront(); 269 270 bool IsModal() const; 271 bool IsFloating() const; 272 bool IsNormal() const; 273 274 bool HasModal() const; 275 276 Window* Frontmost(Window* first = NULL, 277 int32 workspace = -1); 278 Window* Backmost(Window* first = NULL, 279 int32 workspace = -1); 280 281 bool AddToSubset(Window* window); 282 void RemoveFromSubset(Window* window); 283 bool HasInSubset(const Window* window) const; 284 bool SameSubset(Window* window); 285 uint32 SubsetWorkspaces() const; 286 bool InSubsetWorkspace(int32 index) const; 287 HasWorkspacesViews()288 bool HasWorkspacesViews() const 289 { return fWorkspacesViewCount != 0; } AddWorkspacesView()290 void AddWorkspacesView() 291 { fWorkspacesViewCount++; } RemoveWorkspacesView()292 void RemoveWorkspacesView() 293 { fWorkspacesViewCount--; } 294 void FindWorkspacesViews( 295 BObjectList<WorkspacesView>& list) const; 296 297 static bool IsValidLook(window_look look); 298 static bool IsValidFeel(window_feel feel); 299 static bool IsModalFeel(window_feel feel); 300 static bool IsFloatingFeel(window_feel feel); 301 302 static uint32 ValidWindowFlags(); 303 static uint32 ValidWindowFlags(window_feel feel); 304 305 // Window stack methods. 306 WindowStack* GetWindowStack(); 307 308 bool DetachFromWindowStack( 309 bool ownStackNeeded = true); 310 bool AddWindowToStack(Window* window); 311 Window* StackedWindowAt(const BPoint& where); 312 Window* TopLayerStackWindow(); 313 314 int32 PositionInStack() const; 315 bool MoveToTopStackLayer(); 316 bool MoveToStackPosition(int32 index, 317 bool isMoving); 318 protected: 319 void _ShiftPartOfRegion(BRegion* region, 320 BRegion* regionToShift, int32 xOffset, 321 int32 yOffset); 322 323 // different types of drawing 324 void _TriggerContentRedraw(BRegion& dirty, 325 const BRegion& expose = BRegion()); 326 void _DrawBorder(); 327 328 // handling update sessions 329 void _TransferToUpdateSession( 330 BRegion* contentDirtyRegion); 331 void _SendUpdateMessage(); 332 333 void _UpdateContentRegion(); 334 335 void _ObeySizeLimits(); 336 void _PropagatePosition(); 337 338 BString fTitle; 339 // TODO: no fp rects anywhere 340 BRect fFrame; 341 const ::Screen* fScreen; 342 343 window_anchor fAnchor[kListCount]; 344 345 // the visible region is only recalculated from the 346 // Desktop thread, when using it, Desktop::ReadLockClipping() 347 // has to be called 348 349 BRegion fVisibleRegion; 350 BRegion fVisibleContentRegion; 351 352 // Our part of the "global" dirty region (what needs to be redrawn). 353 // It is calculated from the desktop thread, but we can write to it when we read locked 354 // the clipping, since it is local and the desktop thread is blocked. 355 BRegion fDirtyRegion; 356 357 // Subset of the dirty region that is newly exposed. While the dirty region is merely 358 // showing out of date data on screen, this subset of it is showing remains of other 359 // windows. To avoid glitches, it must be set to a reasonable state as fast as possible, 360 // without waiting for a roundtrip to the window's Draw() methods. So it will be filled 361 // using background color and view bitmap, which can all be done without leaving 362 // app_server. 363 BRegion fExposeRegion; 364 365 // caching local regions 366 BRegion fContentRegion; 367 BRegion fEffectiveDrawingRegion; 368 369 bool fVisibleContentRegionValid : 1; 370 bool fContentRegionValid : 1; 371 bool fEffectiveDrawingRegionValid : 1; 372 373 ::RegionPool fRegionPool; 374 375 BObjectList<Window> fSubsets; 376 377 ObjectDeleter<WindowBehaviour> 378 fWindowBehaviour; 379 ObjectDeleter<View> fTopView; 380 ::ServerWindow* fWindow; 381 ObjectDeleter<DrawingEngine> 382 fDrawingEngine; 383 ::Desktop* fDesktop; 384 385 // The synchronization, which client drawing commands 386 // belong to the redraw of which dirty region is handled 387 // through an UpdateSession. When the client has 388 // been informed that it should redraw stuff, then 389 // this is the current update session. All new 390 // redraw requests from the Desktop will go 391 // into the pending update session. 392 class UpdateSession { 393 public: 394 UpdateSession(); 395 396 void Include(BRegion* additionalDirty); 397 void Exclude(BRegion* dirtyInNextSession); 398 DirtyRegion()399 inline BRegion& DirtyRegion() 400 { return fDirtyRegion; } 401 402 void MoveBy(int32 x, int32 y); 403 404 void SetUsed(bool used); IsUsed()405 inline bool IsUsed() const 406 { return fInUse; } 407 408 private: 409 BRegion fDirtyRegion; 410 bool fInUse; 411 }; 412 413 UpdateSession fUpdateSessions[2]; 414 UpdateSession* fCurrentUpdateSession; 415 UpdateSession* fPendingUpdateSession; 416 // these two flags are supposed to ensure a sane 417 // and consistent update session 418 bool fUpdateRequested : 1; 419 bool fInUpdate : 1; 420 bool fUpdatesEnabled : 1; 421 422 bool fHidden : 1; 423 int32 fShowLevel; 424 bool fMinimized : 1; 425 bool fIsFocus : 1; 426 427 window_look fLook; 428 window_feel fFeel; 429 uint32 fOriginalFlags; 430 uint32 fFlags; 431 uint32 fWorkspaces; 432 int32 fCurrentWorkspace; 433 434 int32 fMinWidth; 435 int32 fMaxWidth; 436 int32 fMinHeight; 437 int32 fMaxHeight; 438 439 int32 fWorkspacesViewCount; 440 441 friend class DecorManager; 442 443 private: 444 WindowStack* _InitWindowStack(); 445 446 BReference<WindowStack> fCurrentStack; 447 }; 448 449 450 #endif // WINDOW_H 451