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