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			void				ColorsChanged(BRegion* updateRegion);
247
248			void				SetLook(window_look look,
249									BRegion* updateRegion);
250			void				SetFeel(window_feel feel);
251			void				SetFlags(uint32 flags, BRegion* updateRegion);
252
253			window_look			Look() const { return fLook; }
254			window_feel			Feel() const { return fFeel; }
255			uint32				Flags() const { return fFlags; }
256
257			// window manager stuff
258			uint32				Workspaces() const { return fWorkspaces; }
259			void				SetWorkspaces(uint32 workspaces)
260									{ fWorkspaces = workspaces; }
261			bool				InWorkspace(int32 index) const;
262
263			bool				SupportsFront();
264
265			bool				IsModal() const;
266			bool				IsFloating() const;
267			bool				IsNormal() const;
268
269			bool				HasModal() const;
270
271			Window*				Frontmost(Window* first = NULL,
272									int32 workspace = -1);
273			Window*				Backmost(Window* first = NULL,
274									int32 workspace = -1);
275
276			bool				AddToSubset(Window* window);
277			void				RemoveFromSubset(Window* window);
278			bool				HasInSubset(const Window* window) const;
279			bool				SameSubset(Window* window);
280			uint32				SubsetWorkspaces() const;
281			bool				InSubsetWorkspace(int32 index) const;
282
283			bool				HasWorkspacesViews() const
284									{ return fWorkspacesViewCount != 0; }
285			void				AddWorkspacesView()
286									{ fWorkspacesViewCount++; }
287			void				RemoveWorkspacesView()
288									{ fWorkspacesViewCount--; }
289			void				FindWorkspacesViews(
290									BObjectList<WorkspacesView>& list) const;
291
292	static	bool				IsValidLook(window_look look);
293	static	bool				IsValidFeel(window_feel feel);
294	static	bool				IsModalFeel(window_feel feel);
295	static	bool				IsFloatingFeel(window_feel feel);
296
297	static	uint32				ValidWindowFlags();
298	static	uint32				ValidWindowFlags(window_feel feel);
299
300			// Window stack methods.
301			WindowStack*		GetWindowStack();
302
303			bool				DetachFromWindowStack(
304									bool ownStackNeeded = true);
305			bool				AddWindowToStack(Window* window);
306			Window*				StackedWindowAt(const BPoint& where);
307			Window*				TopLayerStackWindow();
308
309			int32				PositionInStack() const;
310			bool				MoveToTopStackLayer();
311			bool				MoveToStackPosition(int32 index,
312									bool isMoving);
313protected:
314			void				_ShiftPartOfRegion(BRegion* region,
315									BRegion* regionToShift, int32 xOffset,
316									int32 yOffset);
317
318			// different types of drawing
319			void				_TriggerContentRedraw(BRegion& dirty);
320			void				_DrawBorder();
321
322			// handling update sessions
323			void				_TransferToUpdateSession(
324									BRegion* contentDirtyRegion);
325			void				_SendUpdateMessage();
326
327			void				_UpdateContentRegion();
328
329			void				_ObeySizeLimits();
330			void				_PropagatePosition();
331
332			BString				fTitle;
333			// TODO: no fp rects anywhere
334			BRect				fFrame;
335			const ::Screen*		fScreen;
336
337			window_anchor		fAnchor[kListCount];
338
339			// the visible region is only recalculated from the
340			// Desktop thread, when using it, Desktop::ReadLockClipping()
341			// has to be called
342
343			BRegion				fVisibleRegion;
344			BRegion				fVisibleContentRegion;
345			// our part of the "global" dirty region
346			// it is calculated from the desktop thread,
347			// but we can write to it when we read locked
348			// the clipping, since it is local and the desktop
349			// thread is blocked
350			BRegion				fDirtyRegion;
351			uint32				fDirtyCause;
352
353			// caching local regions
354			BRegion				fContentRegion;
355			BRegion				fEffectiveDrawingRegion;
356
357			bool				fVisibleContentRegionValid : 1;
358			bool				fContentRegionValid : 1;
359			bool				fEffectiveDrawingRegionValid : 1;
360
361			::RegionPool		fRegionPool;
362
363			BObjectList<Window> fSubsets;
364
365			WindowBehaviour*	fWindowBehaviour;
366			View*				fTopView;
367			::ServerWindow*		fWindow;
368			DrawingEngine*		fDrawingEngine;
369			::Desktop*			fDesktop;
370
371			// The synchronization, which client drawing commands
372			// belong to the redraw of which dirty region is handled
373			// through an UpdateSession. When the client has
374			// been informed that it should redraw stuff, then
375			// this is the current update session. All new
376			// redraw requests from the Desktop will go
377			// into the pending update session.
378	class UpdateSession {
379	public:
380									UpdateSession();
381		virtual						~UpdateSession();
382
383				void				Include(BRegion* additionalDirty);
384				void				Exclude(BRegion* dirtyInNextSession);
385
386		inline	BRegion&			DirtyRegion()
387										{ return fDirtyRegion; }
388
389				void				MoveBy(int32 x, int32 y);
390
391				void				SetUsed(bool used);
392		inline	bool				IsUsed() const
393										{ return fInUse; }
394
395				void				AddCause(uint8 cause);
396		inline	bool				IsExpose() const
397										{ return fCause & UPDATE_EXPOSE; }
398		inline	bool				IsRequest() const
399										{ return fCause & UPDATE_REQUEST; }
400
401	private:
402				BRegion				fDirtyRegion;
403				bool				fInUse;
404				uint8				fCause;
405	};
406
407			UpdateSession		fUpdateSessions[2];
408			UpdateSession*		fCurrentUpdateSession;
409			UpdateSession*		fPendingUpdateSession;
410			// these two flags are supposed to ensure a sane
411			// and consistent update session
412			bool				fUpdateRequested : 1;
413			bool				fInUpdate : 1;
414			bool				fUpdatesEnabled : 1;
415
416			bool				fHidden : 1;
417			int32				fShowLevel;
418			bool				fMinimized : 1;
419			bool				fIsFocus : 1;
420
421			window_look			fLook;
422			window_feel			fFeel;
423			uint32				fOriginalFlags;
424			uint32				fFlags;
425			uint32				fWorkspaces;
426			int32				fCurrentWorkspace;
427
428			int32				fMinWidth;
429			int32				fMaxWidth;
430			int32				fMinHeight;
431			int32				fMaxHeight;
432
433			int32				fWorkspacesViewCount;
434
435		friend class DecorManager;
436
437private:
438			WindowStack*		_InitWindowStack();
439
440			BReference<WindowStack>		fCurrentStack;
441};
442
443
444#endif // WINDOW_H
445