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
28class Window;
29
30
31typedef	BObjectList<Window>	StackWindows;
32
33
34class WindowStack : public BReferenceable {
35public:
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);
55private:
56			::Decorator*		fDecorator;
57
58			StackWindows		fWindowList;
59			StackWindows		fWindowLayerOrder;
60};
61
62
63namespace BPrivate {
64	class PortLink;
65};
66
67class ClickTarget;
68class ClientLooper;
69class Decorator;
70class Desktop;
71class DrawingEngine;
72class EventDispatcher;
73class Screen;
74class WindowBehaviour;
75class WorkspacesView;
76
77// TODO: move this into a proper place
78#define AS_REDRAW 'rdrw'
79
80enum {
81	UPDATE_REQUEST		= 0x01,
82	UPDATE_EXPOSE		= 0x02,
83};
84
85
86class Window {
87public:
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				SetShowLevel(int32 showLevel);
214	inline	int32				ShowLevel() const { return fShowLevel; }
215
216			void				SetMinimized(bool minimized);
217	inline	bool				IsMinimized() const { return fMinimized; }
218
219			void				SetCurrentWorkspace(int32 index)
220									{ fCurrentWorkspace = index; }
221			int32				CurrentWorkspace() const
222									{ return fCurrentWorkspace; }
223			bool				IsVisible() const;
224
225			bool				IsDragging() const;
226			bool				IsResizing() const;
227
228			void				SetSizeLimits(int32 minWidth, int32 maxWidth,
229									int32 minHeight, int32 maxHeight);
230
231			void				GetSizeLimits(int32* minWidth, int32* maxWidth,
232									int32* minHeight, int32* maxHeight) const;
233
234								// 0.0 -> left .... 1.0 -> right
235			bool				SetTabLocation(float location, bool isShifting,
236									BRegion& dirty);
237			float				TabLocation() const;
238
239			bool				SetDecoratorSettings(const BMessage& settings,
240													 BRegion& dirty);
241			bool				GetDecoratorSettings(BMessage* settings);
242
243			void				HighlightDecorator(bool active);
244
245			void				FontsChanged(BRegion* updateRegion);
246
247			void				SetLook(window_look look,
248									BRegion* updateRegion);
249			void				SetFeel(window_feel feel);
250			void				SetFlags(uint32 flags, BRegion* updateRegion);
251
252			window_look			Look() const { return fLook; }
253			window_feel			Feel() const { return fFeel; }
254			uint32				Flags() const { return fFlags; }
255
256			// window manager stuff
257			uint32				Workspaces() const { return fWorkspaces; }
258			void				SetWorkspaces(uint32 workspaces)
259									{ fWorkspaces = workspaces; }
260			bool				InWorkspace(int32 index) const;
261
262			bool				SupportsFront();
263
264			bool				IsModal() const;
265			bool				IsFloating() const;
266			bool				IsNormal() const;
267
268			bool				HasModal() const;
269
270			Window*				Frontmost(Window* first = NULL,
271									int32 workspace = -1);
272			Window*				Backmost(Window* first = NULL,
273									int32 workspace = -1);
274
275			bool				AddToSubset(Window* window);
276			void				RemoveFromSubset(Window* window);
277			bool				HasInSubset(const Window* window) const;
278			bool				SameSubset(Window* window);
279			uint32				SubsetWorkspaces() const;
280			bool				InSubsetWorkspace(int32 index) const;
281
282			bool				HasWorkspacesViews() const
283									{ return fWorkspacesViewCount != 0; }
284			void				AddWorkspacesView()
285									{ fWorkspacesViewCount++; }
286			void				RemoveWorkspacesView()
287									{ fWorkspacesViewCount--; }
288			void				FindWorkspacesViews(
289									BObjectList<WorkspacesView>& list) const;
290
291	static	bool				IsValidLook(window_look look);
292	static	bool				IsValidFeel(window_feel feel);
293	static	bool				IsModalFeel(window_feel feel);
294	static	bool				IsFloatingFeel(window_feel feel);
295
296	static	uint32				ValidWindowFlags();
297	static	uint32				ValidWindowFlags(window_feel feel);
298
299			// Window stack methods.
300			WindowStack*		GetWindowStack();
301
302			bool				DetachFromWindowStack(
303									bool ownStackNeeded = true);
304			bool				AddWindowToStack(Window* window);
305			Window*				StackedWindowAt(const BPoint& where);
306			Window*				TopLayerStackWindow();
307
308			int32				PositionInStack() const;
309			bool				MoveToTopStackLayer();
310			bool				MoveToStackPosition(int32 index,
311									bool isMoving);
312protected:
313			void				_ShiftPartOfRegion(BRegion* region,
314									BRegion* regionToShift, int32 xOffset,
315									int32 yOffset);
316
317			// different types of drawing
318			void				_TriggerContentRedraw(BRegion& dirty);
319			void				_DrawBorder();
320
321			// handling update sessions
322			void				_TransferToUpdateSession(
323									BRegion* contentDirtyRegion);
324			void				_SendUpdateMessage();
325
326			void				_UpdateContentRegion();
327
328			void				_ObeySizeLimits();
329			void				_PropagatePosition();
330
331			BString				fTitle;
332			// TODO: no fp rects anywhere
333			BRect				fFrame;
334			const ::Screen*		fScreen;
335
336			window_anchor		fAnchor[kListCount];
337
338			// the visible region is only recalculated from the
339			// Desktop thread, when using it, Desktop::ReadLockClipping()
340			// has to be called
341
342			BRegion				fVisibleRegion;
343			BRegion				fVisibleContentRegion;
344			// our part of the "global" dirty region
345			// it is calculated from the desktop thread,
346			// but we can write to it when we read locked
347			// the clipping, since it is local and the desktop
348			// thread is blocked
349			BRegion				fDirtyRegion;
350			uint32				fDirtyCause;
351
352			// caching local regions
353			BRegion				fContentRegion;
354			BRegion				fEffectiveDrawingRegion;
355
356			bool				fVisibleContentRegionValid : 1;
357			bool				fContentRegionValid : 1;
358			bool				fEffectiveDrawingRegionValid : 1;
359
360			::RegionPool		fRegionPool;
361
362			BObjectList<Window> fSubsets;
363
364			WindowBehaviour*	fWindowBehaviour;
365			View*				fTopView;
366			::ServerWindow*		fWindow;
367			DrawingEngine*		fDrawingEngine;
368			::Desktop*			fDesktop;
369
370			// The synchronization, which client drawing commands
371			// belong to the redraw of which dirty region is handled
372			// through an UpdateSession. When the client has
373			// been informed that it should redraw stuff, then
374			// this is the current update session. All new
375			// redraw requests from the Desktop will go
376			// into the pending update session.
377	class UpdateSession {
378	public:
379									UpdateSession();
380		virtual						~UpdateSession();
381
382				void				Include(BRegion* additionalDirty);
383				void				Exclude(BRegion* dirtyInNextSession);
384
385		inline	BRegion&			DirtyRegion()
386										{ return fDirtyRegion; }
387
388				void				MoveBy(int32 x, int32 y);
389
390				void				SetUsed(bool used);
391		inline	bool				IsUsed() const
392										{ return fInUse; }
393
394				void				AddCause(uint8 cause);
395		inline	bool				IsExpose() const
396										{ return fCause & UPDATE_EXPOSE; }
397		inline	bool				IsRequest() const
398										{ return fCause & UPDATE_REQUEST; }
399
400	private:
401				BRegion				fDirtyRegion;
402				bool				fInUse;
403				uint8				fCause;
404	};
405
406			UpdateSession		fUpdateSessions[2];
407			UpdateSession*		fCurrentUpdateSession;
408			UpdateSession*		fPendingUpdateSession;
409			// these two flags are supposed to ensure a sane
410			// and consistent update session
411			bool				fUpdateRequested : 1;
412			bool				fInUpdate : 1;
413			bool				fUpdatesEnabled : 1;
414
415			bool				fHidden : 1;
416			int32				fShowLevel;
417			bool				fMinimized : 1;
418			bool				fIsFocus : 1;
419
420			window_look			fLook;
421			window_feel			fFeel;
422			uint32				fOriginalFlags;
423			uint32				fFlags;
424			uint32				fWorkspaces;
425			int32				fCurrentWorkspace;
426
427			int32				fMinWidth;
428			int32				fMaxWidth;
429			int32				fMinHeight;
430			int32				fMaxHeight;
431
432			int32				fWorkspacesViewCount;
433
434		friend class DecorManager;
435
436private:
437			WindowStack*		_InitWindowStack();
438
439			BReference<WindowStack>		fCurrentStack;
440};
441
442
443#endif // WINDOW_H
444