xref: /haiku/src/servers/app/Window.h (revision 45b01eb84189a623981270a02d21c7a8cb93a9e1)
1 /*
2  * Copyright 2001-2009, 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  */
12 #ifndef WINDOW_H
13 #define WINDOW_H
14 
15 
16 #include "Decorator.h"
17 #include "RegionPool.h"
18 #include "ServerWindow.h"
19 #include "View.h"
20 #include "WindowList.h"
21 
22 #include <ObjectList.h>
23 #include <Region.h>
24 #include <String.h>
25 
26 namespace BPrivate {
27 	class PortLink;
28 };
29 
30 class ClientLooper;
31 class Decorator;
32 class Desktop;
33 class DrawingEngine;
34 class EventDispatcher;
35 class Screen;
36 class WorkspacesView;
37 
38 // TODO: move this into a proper place
39 #define AS_REDRAW 'rdrw'
40 
41 enum {
42 	UPDATE_REQUEST		= 0x01,
43 	UPDATE_EXPOSE		= 0x02,
44 };
45 
46 
47 class Window {
48 public:
49 								Window(const BRect& frame, const char *name,
50 									window_look look, window_feel feel,
51 									uint32 flags, uint32 workspaces,
52 									::ServerWindow* window,
53 									DrawingEngine* drawingEngine);
54 	virtual						~Window();
55 
56 			status_t			InitCheck() const;
57 
58 			BRect				Frame() const { return fFrame; }
59 			const char*			Title() const { return fTitle.String(); }
60 
61 			window_anchor&		Anchor(int32 index);
62 			Window*				NextWindow(int32 index) const;
63 			Window*				PreviousWindow(int32 index) const;
64 
65 			::Desktop*			Desktop() const { return fDesktop; }
66 			::Decorator*		Decorator() const { return fDecorator; }
67 			::ServerWindow*		ServerWindow() const { return fWindow; }
68 			::EventTarget&		EventTarget() const
69 									{ return fWindow->EventTarget(); }
70 
71 			void				SetScreen(const ::Screen* screen);
72 			const ::Screen*		Screen() const;
73 
74 			// setting and getting the "hard" clipping, you need to have
75 			// WriteLock()ed the clipping!
76 			void				SetClipping(BRegion* stillAvailableOnScreen);
77 			// you need to have ReadLock()ed the clipping!
78 	inline	BRegion&			VisibleRegion() { return fVisibleRegion; }
79 			BRegion&			VisibleContentRegion();
80 
81 			// TODO: not protected by a lock, but noone should need this anyways
82 			// make private? when used inside Window, it has the ReadLock()
83 			void				GetFullRegion(BRegion* region);
84 			void				GetBorderRegion(BRegion* region);
85 			void				GetContentRegion(BRegion* region);
86 
87 			void				MoveBy(int32 x, int32 y);
88 			void				ResizeBy(int32 x, int32 y,
89 									BRegion* dirtyRegion);
90 
91 			void				ScrollViewBy(View* view, int32 dx, int32 dy);
92 
93 			void				SetTopView(View* topView);
94 			View*				TopView() const { return fTopView; }
95 			View*				ViewAt(const BPoint& where);
96 
97 	virtual	bool				IsOffscreenWindow() const { return false; }
98 
99 			void				GetEffectiveDrawingRegion(View* view,
100 									BRegion& region);
101 			bool				DrawingRegionChanged(View* view) const;
102 
103 			// generic version, used by the Desktop
104 			void				ProcessDirtyRegion(BRegion& regionOnScreen);
105 			void				RedrawDirtyRegion();
106 
107 			// can be used from inside classes that don't
108 			// need to know about Desktop (first version uses Desktop)
109 			void				MarkDirty(BRegion& regionOnScreen);
110 			// these versions do not use the Desktop
111 			void				MarkContentDirty(BRegion& regionOnScreen);
112 			void				MarkContentDirtyAsync(BRegion& regionOnScreen);
113 			// shortcut for invalidating just one view
114 			void				InvalidateView(View* view, BRegion& viewRegion);
115 
116 			void				DisableUpdateRequests();
117 			void				EnableUpdateRequests();
118 
119 			void				BeginUpdate(BPrivate::PortLink& link);
120 			void				EndUpdate();
121 			bool				InUpdate() const
122 									{ return fInUpdate; }
123 
124 			bool				NeedsUpdate() const
125 									{ return fUpdateRequested; }
126 
127 			DrawingEngine*		GetDrawingEngine() const
128 									{ return fDrawingEngine; }
129 
130 			// managing a region pool
131 			::RegionPool*		RegionPool()
132 									{ return &fRegionPool; }
133 	inline	BRegion*			GetRegion()
134 									{ return fRegionPool.GetRegion(); }
135 	inline	BRegion*			GetRegion(const BRegion& copy)
136 									{ return fRegionPool.GetRegion(copy); }
137 	inline	void				RecycleRegion(BRegion* region)
138 									{ fRegionPool.Recycle(region); }
139 
140 			void				CopyContents(BRegion* region,
141 									int32 xOffset, int32 yOffset);
142 
143 			void				MouseDown(BMessage* message, BPoint where,
144 									int32* _viewToken);
145 			void				MouseUp(BMessage* message, BPoint where,
146 									int32* _viewToken);
147 			void				MouseMoved(BMessage* message, BPoint where,
148 									int32* _viewToken, bool isLatestMouseMoved,
149 									bool isFake);
150 
151 			// some hooks to inform the client window
152 			// TODO: move this to ServerWindow maybe?
153 			void				WorkspaceActivated(int32 index, bool active);
154 			void				WorkspacesChanged(uint32 oldWorkspaces,
155 									uint32 newWorkspaces);
156 			void				Activated(bool active);
157 
158 			// changing some properties
159 			void				SetTitle(const char* name, BRegion& dirty);
160 
161 			void				SetFocus(bool focus);
162 			bool				IsFocus() const { return fIsFocus; }
163 
164 			void				SetHidden(bool hidden);
165 	inline	bool				IsHidden() const { return fHidden; }
166 
167 			void				SetMinimized(bool minimized);
168 	inline	bool				IsMinimized() const { return fMinimized; }
169 
170 			void				SetCurrentWorkspace(int32 index)
171 									{ fCurrentWorkspace = index; }
172 			bool				IsVisible() const;
173 
174 			bool				IsDragging() const { return fIsDragging; }
175 			bool				IsResizing() const { return fIsResizing; }
176 
177 			void				SetSizeLimits(int32 minWidth, int32 maxWidth,
178 									int32 minHeight, int32 maxHeight);
179 
180 			void				GetSizeLimits(int32* minWidth, int32* maxWidth,
181 									int32* minHeight, int32* maxHeight) const;
182 
183 								// 0.0 -> left .... 1.0 -> right
184 			bool				SetTabLocation(float location, BRegion& dirty);
185 			float				TabLocation() const;
186 
187 			bool				SetDecoratorSettings(const BMessage& settings,
188 													 BRegion& dirty);
189 			bool				GetDecoratorSettings(BMessage* settings);
190 
191 			void				HighlightDecorator(bool active);
192 
193 			void				FontsChanged(BRegion* updateRegion);
194 
195 			void				SetLook(window_look look,
196 									BRegion* updateRegion);
197 			void				SetFeel(window_feel feel);
198 			void				SetFlags(uint32 flags, BRegion* updateRegion);
199 
200 			window_look			Look() const { return fLook; }
201 			window_feel			Feel() const { return fFeel; }
202 			uint32				Flags() const { return fFlags; }
203 
204 			// window manager stuff
205 			uint32				Workspaces() const { return fWorkspaces; }
206 			void				SetWorkspaces(uint32 workspaces)
207 									{ fWorkspaces = workspaces; }
208 			bool				InWorkspace(int32 index) const;
209 
210 			bool				SupportsFront();
211 
212 			bool				IsModal() const;
213 			bool				IsFloating() const;
214 			bool				IsNormal() const;
215 
216 			bool				HasModal() const;
217 
218 			Window*				Frontmost(Window* first = NULL,
219 									int32 workspace = -1);
220 			Window*				Backmost(Window* first = NULL,
221 									int32 workspace = -1);
222 
223 			bool				AddToSubset(Window* window);
224 			void				RemoveFromSubset(Window* window);
225 			bool				HasInSubset(const Window* window) const;
226 			bool				SameSubset(Window* window);
227 			uint32				SubsetWorkspaces() const;
228 			bool				InSubsetWorkspace(int32 index) const;
229 
230 			bool				HasWorkspacesViews() const
231 									{ return fWorkspacesViewCount != 0; }
232 			void				AddWorkspacesView()
233 									{ fWorkspacesViewCount++; }
234 			void				RemoveWorkspacesView()
235 									{ fWorkspacesViewCount--; }
236 			void				FindWorkspacesViews(
237 									BObjectList<WorkspacesView>& list) const;
238 
239 	static	bool				IsValidLook(window_look look);
240 	static	bool				IsValidFeel(window_feel feel);
241 	static	bool				IsModalFeel(window_feel feel);
242 	static	bool				IsFloatingFeel(window_feel feel);
243 
244 	static	uint32				ValidWindowFlags();
245 	static	uint32				ValidWindowFlags(window_feel feel);
246 
247 protected:
248 			void				_ShiftPartOfRegion(BRegion* region,
249 									BRegion* regionToShift, int32 xOffset,
250 									int32 yOffset);
251 
252 			// different types of drawing
253 			void				_TriggerContentRedraw(BRegion& dirty);
254 			void				_DrawBorder();
255 
256 			// handling update sessions
257 			void				_TransferToUpdateSession(
258 									BRegion* contentDirtyRegion);
259 			void				_SendUpdateMessage();
260 
261 			void				_UpdateContentRegion();
262 
263 			int32				_ExtractButtons(
264 									const BMessage* message) const;
265 			int32				_ExtractModifiers(
266 									const BMessage* message) const;
267 			click_type			_ActionFor(const BMessage* message) const;
268 			click_type			_ActionFor(const BMessage* message,
269 									int32 buttons, int32 modifiers) const;
270 
271 			void				_ObeySizeLimits();
272 			void				_PropagatePosition();
273 
274 			void				_AlterDeltaForSnap(BPoint& delta,
275 									bigtime_t now);
276 
277 			BString				fTitle;
278 			// TODO: no fp rects anywhere
279 			BRect				fFrame;
280 			const ::Screen*		fScreen;
281 
282 			window_anchor		fAnchor[kListCount];
283 
284 			// the visible region is only recalculated from the
285 			// Desktop thread, when using it, Desktop::ReadLockClipping()
286 			// has to be called
287 
288 			BRegion				fVisibleRegion;
289 			BRegion				fVisibleContentRegion;
290 			// our part of the "global" dirty region
291 			// it is calculated from the desktop thread,
292 			// but we can write to it when we read locked
293 			// the clipping, since it is local and the desktop
294 			// thread is blocked
295 			BRegion				fDirtyRegion;
296 			uint32				fDirtyCause;
297 
298 			// caching local regions
299 			BRegion				fBorderRegion;
300 			BRegion				fContentRegion;
301 			BRegion				fEffectiveDrawingRegion;
302 
303 			bool				fVisibleContentRegionValid : 1;
304 			bool				fBorderRegionValid : 1;
305 			bool				fContentRegionValid : 1;
306 			bool				fEffectiveDrawingRegionValid : 1;
307 
308 			::RegionPool		fRegionPool;
309 
310 			BObjectList<Window> fSubsets;
311 
312 // TODO: remove those some day (let the decorator handle that stuff)
313 			bool				fIsClosing : 1;
314 			bool				fIsMinimizing : 1;
315 			bool				fIsZooming : 1;
316 			bool				fIsResizing : 1;
317 			bool				fIsSlidingTab : 1;
318 			bool				fIsDragging : 1;
319 			bool				fActivateOnMouseUp : 1;
320 
321 			::Decorator*		fDecorator;
322 			View*				fTopView;
323 			::ServerWindow*		fWindow;
324 			DrawingEngine*		fDrawingEngine;
325 			::Desktop*			fDesktop;
326 
327 			BPoint				fLastMousePosition;
328 			float				fMouseMoveDistance;
329 			bigtime_t			fLastMoveTime;
330 			bigtime_t			fLastSnapTime;
331 
332 			// The synchronization, which client drawing commands
333 			// belong to the redraw of which dirty region is handled
334 			// through an UpdateSession. When the client has
335 			// been informed that it should redraw stuff, then
336 			// this is the current update session. All new
337 			// redraw requests from the Desktop will go
338 			// into the pending update session.
339 	class UpdateSession {
340 	public:
341 									UpdateSession();
342 		virtual						~UpdateSession();
343 
344 				void				Include(BRegion* additionalDirty);
345 				void				Exclude(BRegion* dirtyInNextSession);
346 
347 		inline	BRegion&			DirtyRegion()
348 										{ return fDirtyRegion; }
349 
350 				void				MoveBy(int32 x, int32 y);
351 
352 				void				SetUsed(bool used);
353 		inline	bool				IsUsed() const
354 										{ return fInUse; }
355 
356 				void				AddCause(uint8 cause);
357 		inline	bool				IsExpose() const
358 										{ return fCause & UPDATE_EXPOSE; }
359 		inline	bool				IsRequest() const
360 										{ return fCause & UPDATE_REQUEST; }
361 
362 	private:
363 				BRegion				fDirtyRegion;
364 				bool				fInUse;
365 				uint8				fCause;
366 	};
367 
368 			BRegion				fDecoratorRegion;
369 
370 			UpdateSession		fUpdateSessions[2];
371 			UpdateSession*		fCurrentUpdateSession;
372 			UpdateSession*		fPendingUpdateSession;
373 			// these two flags are supposed to ensure a sane
374 			// and consistent update session
375 			bool				fUpdateRequested : 1;
376 			bool				fInUpdate : 1;
377 			bool				fUpdatesEnabled : 1;
378 
379 			bool				fHidden : 1;
380 			bool				fMinimized : 1;
381 			bool				fIsFocus : 1;
382 
383 			window_look			fLook;
384 			window_feel			fFeel;
385 			uint32				fOriginalFlags;
386 			uint32				fFlags;
387 			uint32				fWorkspaces;
388 			int32				fCurrentWorkspace;
389 
390 			int32				fMinWidth;
391 			int32				fMaxWidth;
392 			int32				fMinHeight;
393 			int32				fMaxHeight;
394 
395 			int32				fWorkspacesViewCount;
396 };
397 
398 #endif // WINDOW_H
399