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