xref: /haiku/src/servers/app/Window.h (revision 4c07199d8201fcf267e90be0d24b76799d03cea6)
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 
45 	const	StackWindows&		WindowList() const { return fWindowList; }
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 
96 			BRect				Frame() const { return fFrame; }
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 
103 			::Desktop*			Desktop() const { return fDesktop; }
104 			::Decorator*		Decorator() const;
105 			::ServerWindow*		ServerWindow() const { return fWindow; }
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!
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);
137 			View*				TopView() const { return fTopView.Get(); }
138 			View*				ViewAt(const BPoint& where);
139 
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);
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();
168 			bool				InUpdate() const
169 									{ return fInUpdate; }
170 
171 			bool				NeedsUpdate() const
172 									{ return fUpdateRequested; }
173 
174 			DrawingEngine*		GetDrawingEngine() const
175 									{ return fDrawingEngine.Get(); }
176 
177 			// managing a region pool
178 			::RegionPool*		RegionPool()
179 									{ return &fRegionPool; }
180 	inline	BRegion*			GetRegion()
181 									{ return fRegionPool.GetRegion(); }
182 	inline	BRegion*			GetRegion(const BRegion& copy)
183 									{ return fRegionPool.GetRegion(copy); }
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);
213 			bool				IsFocus() const { return fIsFocus; }
214 
215 			void				SetHidden(bool hidden);
216 	inline	bool				IsHidden() const { return fHidden; }
217 
218 			void				SetShowLevel(int32 showLevel);
219 	inline	int32				ShowLevel() const { return fShowLevel; }
220 
221 			void				SetMinimized(bool minimized);
222 	inline	bool				IsMinimized() const { return fMinimized; }
223 
224 			void				SetCurrentWorkspace(int32 index)
225 									{ fCurrentWorkspace = index; }
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 
258 			window_look			Look() const { return fLook; }
259 			window_feel			Feel() const { return fFeel; }
260 			uint32				Flags() const { return fFlags; }
261 
262 			// window manager stuff
263 			uint32				Workspaces() const { return fWorkspaces; }
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 
288 			bool				HasWorkspacesViews() const
289 									{ return fWorkspacesViewCount != 0; }
290 			void				AddWorkspacesView()
291 									{ fWorkspacesViewCount++; }
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 
399 		inline	BRegion&			DirtyRegion()
400 										{ return fDirtyRegion; }
401 
402 				void				MoveBy(int32 x, int32 y);
403 
404 				void				SetUsed(bool used);
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