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
31class Window;
32
33
34typedef	BObjectList<Window>	StackWindows;
35
36
37class WindowStack : public BReferenceable {
38public:
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);
58private:
59			ObjectDeleter< ::Decorator>
60								fDecorator;
61
62			StackWindows		fWindowList;
63			StackWindows		fWindowLayerOrder;
64};
65
66
67namespace BPrivate {
68	class PortLink;
69};
70
71class ClickTarget;
72class ClientLooper;
73class Decorator;
74class Desktop;
75class DrawingEngine;
76class EventDispatcher;
77class Screen;
78class WindowBehaviour;
79class WorkspacesView;
80
81// TODO: move this into a proper place
82#define AS_REDRAW 'rdrw'
83
84
85class Window {
86public:
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);
318protected:
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
443private:
444			WindowStack*		_InitWindowStack();
445
446			BReference<WindowStack>		fCurrentStack;
447};
448
449
450#endif // WINDOW_H
451