1bef1ed93SStephan Aßmus
2bef1ed93SStephan Aßmus#include <stdio.h>
3bef1ed93SStephan Aßmus
4a825e403SStephan Aßmus#include <Application.h>
5bef1ed93SStephan Aßmus#include <Message.h>
6bef1ed93SStephan Aßmus#include <MessageQueue.h>
7bef1ed93SStephan Aßmus#include <Messenger.h>
8bef1ed93SStephan Aßmus#include <Window.h>
9bef1ed93SStephan Aßmus
10bef1ed93SStephan Aßmus#include "DrawingEngine.h"
11e76d86d5SStephan Aßmus#include "DrawView.h"
12bef1ed93SStephan Aßmus#include "WindowLayer.h"
13bef1ed93SStephan Aßmus
14bef1ed93SStephan Aßmus#include "Desktop.h"
15bef1ed93SStephan Aßmus
16bef1ed93SStephan Aßmus// constructor
17e76d86d5SStephan AßmusDesktop::Desktop(DrawView* drawView, DrawingEngine* engine)
18d0e89d53SStephan Aßmus	: BLooper("desktop", B_URGENT_DISPLAY_PRIORITY),
19bef1ed93SStephan Aßmus	  fTracking(false),
20bef1ed93SStephan Aßmus	  fLastMousePos(-1.0, -1.0),
21bef1ed93SStephan Aßmus	  fClickedWindow(NULL),
227943e1a8SStephan Aßmus	  fScrollingView(NULL),
23bef1ed93SStephan Aßmus	  fResizing(false),
24bef1ed93SStephan Aßmus	  fIs2ndButton(false),
25bef1ed93SStephan Aßmus
26bef1ed93SStephan Aßmus	  fClippingLock("clipping lock"),
27bef1ed93SStephan Aßmus	  fBackgroundRegion(),
28bef1ed93SStephan Aßmus
29e76d86d5SStephan Aßmus	  fMasterClipping(),
30e76d86d5SStephan Aßmus	  fXOffset(0),
31e76d86d5SStephan Aßmus	  fYOffset(0),
32e76d86d5SStephan Aßmus
33bef1ed93SStephan Aßmus	  fDrawView(drawView),
34e76d86d5SStephan Aßmus	  fDrawingEngine(engine),
35bef1ed93SStephan Aßmus
360b78f37eSStephan Aßmus	  fWindows(64),
370b78f37eSStephan Aßmus
380b78f37eSStephan Aßmus	  fFocusFollowsMouse(true),
390b78f37eSStephan Aßmus	  fFocusWindow(NULL)
40bef1ed93SStephan Aßmus{
41bef1ed93SStephan Aßmus	fDrawView->SetDesktop(this);
42bef1ed93SStephan Aßmus
43bef1ed93SStephan Aßmus	BRegion stillAvailableOnScreen;
44bef1ed93SStephan Aßmus	_RebuildClippingForAllWindows(&stillAvailableOnScreen);
45bef1ed93SStephan Aßmus	_SetBackground(&stillAvailableOnScreen);
46bef1ed93SStephan Aßmus}
47bef1ed93SStephan Aßmus
48bef1ed93SStephan Aßmus// destructor
49bef1ed93SStephan AßmusDesktop::~Desktop()
50bef1ed93SStephan Aßmus{
51bef1ed93SStephan Aßmus}
52bef1ed93SStephan Aßmus
53bef1ed93SStephan Aßmus// MouseDown
54bef1ed93SStephan Aßmusvoid
558c8275c2SStephan AßmusDesktop::MouseDown(BPoint where, uint32 buttons, int32 clicks)
56bef1ed93SStephan Aßmus{
57bef1ed93SStephan Aßmus	fLastMousePos = where;
58bef1ed93SStephan Aßmus	fClickedWindow = WindowAt(where);
59bef1ed93SStephan Aßmus	fClickTime = system_time();
60bef1ed93SStephan Aßmus	if (buttons == B_PRIMARY_MOUSE_BUTTON) {
61bef1ed93SStephan Aßmus		fTracking = true;
62bef1ed93SStephan Aßmus		if (fClickedWindow) {
637943e1a8SStephan Aßmus			if (modifiers() & B_SHIFT_KEY) {
647943e1a8SStephan Aßmus				fScrollingView = fClickedWindow->ViewAt(where);
657943e1a8SStephan Aßmus			} else if (clicks >= 2) {
668c8275c2SStephan Aßmus				HideWindow(fClickedWindow);
678c8275c2SStephan Aßmus				fClickedWindow = NULL;
688c8275c2SStephan Aßmus			} else {
698c8275c2SStephan Aßmus				BRect frame(fClickedWindow->Frame());
708c8275c2SStephan Aßmus				BRect resizeRect(frame.right - 10, frame.bottom - 10,
718c8275c2SStephan Aßmus								 frame.right + 4, frame.bottom + 4);
728c8275c2SStephan Aßmus				fResizing = resizeRect.Contains(where);
738c8275c2SStephan Aßmus			}
74bef1ed93SStephan Aßmus		}
75bef1ed93SStephan Aßmus	} else if (buttons == B_SECONDARY_MOUSE_BUTTON) {
76bef1ed93SStephan Aßmus		if (fClickedWindow)
77bef1ed93SStephan Aßmus			SendToBack(fClickedWindow);
78bef1ed93SStephan Aßmus
79bef1ed93SStephan Aßmus		fIs2ndButton = true;
80bef1ed93SStephan Aßmus	} else if (buttons == B_TERTIARY_MOUSE_BUTTON) {
81e76d86d5SStephan Aßmus		fDrawView->Invalidate();
82bef1ed93SStephan Aßmus	}
83bef1ed93SStephan Aßmus}
84bef1ed93SStephan Aßmus
85bef1ed93SStephan Aßmus// MouseUp
86bef1ed93SStephan Aßmusvoid
87bef1ed93SStephan AßmusDesktop::MouseUp(BPoint where)
88bef1ed93SStephan Aßmus{
89bef1ed93SStephan Aßmus	if (!fIs2ndButton && system_time() - fClickTime < 250000L && fClickedWindow) {
90bef1ed93SStephan Aßmus		BringToFront(fClickedWindow);
91bef1ed93SStephan Aßmus	}
92bef1ed93SStephan Aßmus	fTracking = false;
93bef1ed93SStephan Aßmus	fIs2ndButton = false;
94bef1ed93SStephan Aßmus	fClickedWindow = NULL;
957943e1a8SStephan Aßmus	fScrollingView = NULL;
96bef1ed93SStephan Aßmus}
97bef1ed93SStephan Aßmus
98bef1ed93SStephan Aßmus// MouseMoved
99bef1ed93SStephan Aßmusvoid
100bef1ed93SStephan AßmusDesktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
101bef1ed93SStephan Aßmus{
1020b78f37eSStephan Aßmus	WindowLayer* window;
1030b78f37eSStephan Aßmus	if (!fTracking && fFocusFollowsMouse && (window = WindowAt(where))) {
1040b78f37eSStephan Aßmus		SetFocusWindow(window);
1050b78f37eSStephan Aßmus	}
106bef1ed93SStephan Aßmus	if (fTracking) {
107bef1ed93SStephan Aßmus		int32 dx = (int32)(where.x - fLastMousePos.x);
108bef1ed93SStephan Aßmus		int32 dy = (int32)(where.y - fLastMousePos.y);
109bef1ed93SStephan Aßmus		fLastMousePos = where;
110bef1ed93SStephan Aßmus
111bef1ed93SStephan Aßmus		if (dx != 0 || dy != 0) {
112bef1ed93SStephan Aßmus			if (fClickedWindow) {
1137943e1a8SStephan Aßmus				if (fScrollingView) {
1147943e1a8SStephan Aßmus					if (LockClipping()) {
1157943e1a8SStephan Aßmus						fClickedWindow->ScrollViewBy(fScrollingView, -dx, -dy);
1167943e1a8SStephan Aßmus						UnlockClipping();
1177943e1a8SStephan Aßmus					}
1187943e1a8SStephan Aßmus				} else if (fResizing) {
119d0e89d53SStephan Aßmus//bigtime_t now = system_time();
120bef1ed93SStephan Aßmus					ResizeWindowBy(fClickedWindow, dx, dy);
121d0e89d53SStephan Aßmus//printf("resizing: %lld\n", system_time() - now);
122bef1ed93SStephan Aßmus				} else {
123bef1ed93SStephan Aßmus					MoveWindowBy(fClickedWindow, dx, dy);
124d0e89d53SStephan Aßmus//printf("moving: %lld\n", system_time() - now);
125bef1ed93SStephan Aßmus				}
126bef1ed93SStephan Aßmus			}
127bef1ed93SStephan Aßmus		}
128bef1ed93SStephan Aßmus	} else if (fIs2ndButton) {
129e76d86d5SStephan Aßmus		fDrawingEngine->StrokeLine(fLastMousePos, where, (rgb_color){ 0, 0, 0, 255 });
130bef1ed93SStephan Aßmus		fLastMousePos = where;
131bef1ed93SStephan Aßmus	}
132bef1ed93SStephan Aßmus}
133bef1ed93SStephan Aßmus
134bef1ed93SStephan Aßmus// MessageReceived
135bef1ed93SStephan Aßmusvoid
136bef1ed93SStephan AßmusDesktop::MessageReceived(BMessage* message)
137bef1ed93SStephan Aßmus{
138bef1ed93SStephan Aßmus	switch (message->what) {
139bef1ed93SStephan Aßmus		case B_MOUSE_DOWN: {
140bef1ed93SStephan Aßmus			BPoint where;
141bef1ed93SStephan Aßmus			uint32 buttons;
1428c8275c2SStephan Aßmus			int32 clicks;
143bef1ed93SStephan Aßmus			if (message->FindPoint("where", &where) >= B_OK &&
1448c8275c2SStephan Aßmus				message->FindInt32("buttons", (int32*)&buttons) >= B_OK &&
1458c8275c2SStephan Aßmus				message->FindInt32("clicks", &clicks) >= B_OK) {
146bef1ed93SStephan Aßmus
147e76d86d5SStephan Aßmus				where.x += fXOffset;
148e76d86d5SStephan Aßmus				where.y += fYOffset;
149e76d86d5SStephan Aßmus
1508c8275c2SStephan Aßmus				MouseDown(where, buttons, clicks);
151bef1ed93SStephan Aßmus			}
152bef1ed93SStephan Aßmus			break;
153bef1ed93SStephan Aßmus		}
154bef1ed93SStephan Aßmus		case B_MOUSE_UP: {
155bef1ed93SStephan Aßmus			BPoint where;
156bef1ed93SStephan Aßmus			if (message->FindPoint("where", &where) >= B_OK) {
157bef1ed93SStephan Aßmus
158e76d86d5SStephan Aßmus				where.x += fXOffset;
159e76d86d5SStephan Aßmus				where.y += fYOffset;
160e76d86d5SStephan Aßmus
161bef1ed93SStephan Aßmus				MouseUp(where);
162bef1ed93SStephan Aßmus			}
163bef1ed93SStephan Aßmus			break;
164bef1ed93SStephan Aßmus		}
165bef1ed93SStephan Aßmus		case B_MOUSE_MOVED: {
166bef1ed93SStephan Aßmus			if (!MessageQueue()->FindMessage(B_MOUSE_MOVED, 0)) {
167bef1ed93SStephan Aßmus				BPoint where;
168bef1ed93SStephan Aßmus				uint32 transit;
169bef1ed93SStephan Aßmus				if (message->FindPoint("where", &where) >= B_OK &&
170bef1ed93SStephan Aßmus					message->FindInt32("be:transit", (int32*)&transit) >= B_OK) {
171e76d86d5SStephan Aßmus
172e76d86d5SStephan Aßmus					where.x += fXOffset;
173e76d86d5SStephan Aßmus					where.y += fYOffset;
174bef1ed93SStephan Aßmus
175bef1ed93SStephan Aßmus					MouseMoved(where, transit, NULL);
176bef1ed93SStephan Aßmus				}
177bef1ed93SStephan Aßmus			}
178bef1ed93SStephan Aßmus			break;
179bef1ed93SStephan Aßmus		}
1804dd89c69SStephan Aßmus
181bef1ed93SStephan Aßmus		case MSG_ADD_WINDOW: {
182bef1ed93SStephan Aßmus			WindowLayer* window;
183bef1ed93SStephan Aßmus			if (message->FindPointer("window", (void**)&window) >= B_OK)
184bef1ed93SStephan Aßmus				AddWindow(window);
185bef1ed93SStephan Aßmus			break;
186bef1ed93SStephan Aßmus		}
1874dd89c69SStephan Aßmus
188a825e403SStephan Aßmus		case MSG_QUIT:
189a825e403SStephan Aßmus			if (LockClipping()) {
190a825e403SStephan Aßmus				int32 count = CountWindows();
191a825e403SStephan Aßmus				for (int32 i = 0; i < count; i++)
192a825e403SStephan Aßmus					WindowAtFast(i)->PostMessage(B_QUIT_REQUESTED);
193a825e403SStephan Aßmus				UnlockClipping();
194a825e403SStephan Aßmus			}
195a825e403SStephan Aßmus			break;
196a825e403SStephan Aßmus
197bef1ed93SStephan Aßmus		default:
198bef1ed93SStephan Aßmus			BLooper::MessageReceived(message);
199bef1ed93SStephan Aßmus	}
200bef1ed93SStephan Aßmus}
201bef1ed93SStephan Aßmus
202c63a78aaSStephan Aßmus// #pragma mark -
203bef1ed93SStephan Aßmus
204e76d86d5SStephan Aßmus// SetMasterClipping
205e76d86d5SStephan Aßmusvoid
206e76d86d5SStephan AßmusDesktop::SetMasterClipping(BRegion* clipping)
207e76d86d5SStephan Aßmus{
208e76d86d5SStephan Aßmus	BRegion update = *clipping;
209e76d86d5SStephan Aßmus	update.Exclude(&fMasterClipping);
210e76d86d5SStephan Aßmus
211e76d86d5SStephan Aßmus	fMasterClipping = *clipping;
212e76d86d5SStephan Aßmus	// since parts of the view might have been exposed,
213e76d86d5SStephan Aßmus	// we need a clipping rebuild
214e76d86d5SStephan Aßmus	BRegion background;
215e76d86d5SStephan Aßmus	_RebuildClippingForAllWindows(&background);
216e76d86d5SStephan Aßmus	_SetBackground(&background);
217e76d86d5SStephan Aßmus
218e76d86d5SStephan Aßmus	fDrawingEngine->FillRegion(&fBackgroundRegion, (rgb_color){ 51, 102, 152, 255 });
219e76d86d5SStephan Aßmus
220e76d86d5SStephan Aßmus	// trigger redrawing windows
221e76d86d5SStephan Aßmus	update.Exclude(&fBackgroundRegion);
222e76d86d5SStephan Aßmus	MarkDirty(&update);
223e76d86d5SStephan Aßmus}
224e76d86d5SStephan Aßmus
225e76d86d5SStephan Aßmus// SetOffset
226e76d86d5SStephan Aßmusvoid
227e76d86d5SStephan AßmusDesktop::SetOffset(int32 x, int32 y)
228e76d86d5SStephan Aßmus{
229e76d86d5SStephan Aßmus	fXOffset = x;
230e76d86d5SStephan Aßmus	fYOffset = y;
231e76d86d5SStephan Aßmus}
232e76d86d5SStephan Aßmus
233e76d86d5SStephan Aßmus// #pragma mark -
234e76d86d5SStephan Aßmus
235bef1ed93SStephan Aßmus// AddWindow
236bef1ed93SStephan Aßmusbool
237bef1ed93SStephan AßmusDesktop::AddWindow(WindowLayer* window)
238bef1ed93SStephan Aßmus{
239bef1ed93SStephan Aßmus	bool success = false;
240bef1ed93SStephan Aßmus	if (fWindows.AddItem((void*)window)) {
241bef1ed93SStephan Aßmus		// rebuild the entire screen clipping and draw the new window
242bef1ed93SStephan Aßmus		if (LockClipping()) {
243bef1ed93SStephan Aßmus			BRegion background;
244bef1ed93SStephan Aßmus			_RebuildClippingForAllWindows(&background);
245bef1ed93SStephan Aßmus			fBackgroundRegion.Exclude(&window->VisibleRegion());
246bef1ed93SStephan Aßmus			MarkDirty(&window->VisibleRegion());
247bef1ed93SStephan Aßmus			_SetBackground(&background);
248bef1ed93SStephan Aßmus
249bef1ed93SStephan Aßmus			UnlockClipping();
250bef1ed93SStephan Aßmus		}
2510b78f37eSStephan Aßmus		SetFocusWindow(window);
2520b78f37eSStephan Aßmus
253bef1ed93SStephan Aßmus		success = true;
254bef1ed93SStephan Aßmus	}
255bef1ed93SStephan Aßmus	return success;
256bef1ed93SStephan Aßmus}
257bef1ed93SStephan Aßmus
258bef1ed93SStephan Aßmus// RemoveWindow
259bef1ed93SStephan Aßmusbool
260bef1ed93SStephan AßmusDesktop::RemoveWindow(WindowLayer* window)
261bef1ed93SStephan Aßmus{
262bef1ed93SStephan Aßmus	bool success = false;
263bef1ed93SStephan Aßmus	if (fWindows.RemoveItem((void*)window)) {
264bef1ed93SStephan Aßmus		// rebuild the entire screen clipping and redraw the exposed windows
265bef1ed93SStephan Aßmus		if (LockClipping()) {
266bef1ed93SStephan Aßmus			BRegion dirty = window->VisibleRegion();
267bef1ed93SStephan Aßmus			BRegion background;
268bef1ed93SStephan Aßmus			_RebuildClippingForAllWindows(&background);
269bef1ed93SStephan Aßmus			MarkDirty(&dirty);
270bef1ed93SStephan Aßmus			_SetBackground(&background);
271bef1ed93SStephan Aßmus
272bef1ed93SStephan Aßmus			UnlockClipping();
273bef1ed93SStephan Aßmus		}
274bef1ed93SStephan Aßmus		success = true;
275bef1ed93SStephan Aßmus	}
276bef1ed93SStephan Aßmus	return success;
277bef1ed93SStephan Aßmus}
278bef1ed93SStephan Aßmus
279bef1ed93SStephan Aßmus// IndexOf
280bef1ed93SStephan Aßmusint32
281bef1ed93SStephan AßmusDesktop::IndexOf(WindowLayer* window) const
282bef1ed93SStephan Aßmus{
283bef1ed93SStephan Aßmus	return fWindows.IndexOf((void*)window);
284bef1ed93SStephan Aßmus}
285bef1ed93SStephan Aßmus
286bef1ed93SStephan Aßmus// CountWindows
287bef1ed93SStephan Aßmusint32
288bef1ed93SStephan AßmusDesktop::CountWindows() const
289bef1ed93SStephan Aßmus{
290bef1ed93SStephan Aßmus	return fWindows.CountItems();
291bef1ed93SStephan Aßmus}
292bef1ed93SStephan Aßmus
293bef1ed93SStephan Aßmus// HasWindow
294bef1ed93SStephan Aßmusbool
295bef1ed93SStephan AßmusDesktop::HasWindow(WindowLayer* window) const
296bef1ed93SStephan Aßmus{
297bef1ed93SStephan Aßmus	return fWindows.HasItem((void*)window);
298bef1ed93SStephan Aßmus}
299bef1ed93SStephan Aßmus
300bef1ed93SStephan Aßmus// WindowAt
301bef1ed93SStephan AßmusWindowLayer*
302bef1ed93SStephan AßmusDesktop::WindowAt(int32 index) const
303bef1ed93SStephan Aßmus{
304bef1ed93SStephan Aßmus	return (WindowLayer*)fWindows.ItemAt(index);
305bef1ed93SStephan Aßmus}
306bef1ed93SStephan Aßmus
307bef1ed93SStephan Aßmus// WindowAtFast
308bef1ed93SStephan AßmusWindowLayer*
309bef1ed93SStephan AßmusDesktop::WindowAtFast(int32 index) const
310bef1ed93SStephan Aßmus{
311bef1ed93SStephan Aßmus	return (WindowLayer*)fWindows.ItemAtFast(index);
312bef1ed93SStephan Aßmus}
313bef1ed93SStephan Aßmus
314bef1ed93SStephan Aßmus// WindowAt
315bef1ed93SStephan AßmusWindowLayer*
316bef1ed93SStephan AßmusDesktop::WindowAt(const BPoint& where) const
317bef1ed93SStephan Aßmus{
318bef1ed93SStephan Aßmus	// NOTE, since the clipping is only changed from this thread,
319bef1ed93SStephan Aßmus	// it is save to use it without locking
320bef1ed93SStephan Aßmus	int32 count = CountWindows();
321bef1ed93SStephan Aßmus	for (int32 i = count - 1; i >= 0; i--) {
322bef1ed93SStephan Aßmus		WindowLayer* window = WindowAtFast(i);
3238c8275c2SStephan Aßmus		if (!window->IsHidden() && window->VisibleRegion().Contains(where))
324bef1ed93SStephan Aßmus			return window;
325bef1ed93SStephan Aßmus	}
326bef1ed93SStephan Aßmus	return NULL;
327bef1ed93SStephan Aßmus}
328bef1ed93SStephan Aßmus
329bef1ed93SStephan Aßmus// TopWindow
330bef1ed93SStephan AßmusWindowLayer*
331bef1ed93SStephan AßmusDesktop::TopWindow() const
332bef1ed93SStephan Aßmus{
333bef1ed93SStephan Aßmus	return (WindowLayer*)fWindows.LastItem();
334bef1ed93SStephan Aßmus}
335bef1ed93SStephan Aßmus
336bef1ed93SStephan Aßmus// BottomWindow
337bef1ed93SStephan AßmusWindowLayer*
338bef1ed93SStephan AßmusDesktop::BottomWindow() const
339bef1ed93SStephan Aßmus{
340bef1ed93SStephan Aßmus	return (WindowLayer*)fWindows.FirstItem();
341bef1ed93SStephan Aßmus}
342bef1ed93SStephan Aßmus
343bef1ed93SStephan Aßmus#pragma mark -
344bef1ed93SStephan Aßmus
345bef1ed93SStephan Aßmus// MoveWindowBy
346bef1ed93SStephan Aßmusvoid
347bef1ed93SStephan AßmusDesktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y)
348bef1ed93SStephan Aßmus{
349748533bbSStephan Aßmus	if (!Lock())
350748533bbSStephan Aßmus		return;
351748533bbSStephan Aßmus
352bef1ed93SStephan Aßmus	if (LockClipping()) {
353bef1ed93SStephan Aßmus		// the dirty region starts with the visible area of the window being moved
354bef1ed93SStephan Aßmus		BRegion newDirtyRegion(window->VisibleRegion());
355bef1ed93SStephan Aßmus
356bef1ed93SStephan Aßmus		window->MoveBy(x, y);
357bef1ed93SStephan Aßmus
358bef1ed93SStephan Aßmus		BRegion background;
359bef1ed93SStephan Aßmus		_RebuildClippingForAllWindows(&background);
360bef1ed93SStephan Aßmus
361bef1ed93SStephan Aßmus		// construct the region that is possible to be blitted
362bef1ed93SStephan Aßmus		// to move the contents of the window
363bef1ed93SStephan Aßmus		BRegion copyRegion(window->VisibleRegion());
364bef1ed93SStephan Aßmus		copyRegion.OffsetBy(-x, -y);
365bef1ed93SStephan Aßmus		copyRegion.IntersectWith(&newDirtyRegion);
366bef1ed93SStephan Aßmus
367bef1ed93SStephan Aßmus		// include the the new visible region of the window being
368bef1ed93SStephan Aßmus		// moved into the dirty region (for now)
369bef1ed93SStephan Aßmus		newDirtyRegion.Include(&window->VisibleRegion());
370bef1ed93SStephan Aßmus
371e76d86d5SStephan Aßmus		fDrawingEngine->CopyRegion(&copyRegion, x, y);
372e76d86d5SStephan Aßmus
373e76d86d5SStephan Aßmus		copyRegion.OffsetBy(x, y);
374e76d86d5SStephan Aßmus		newDirtyRegion.Exclude(&copyRegion);
375bef1ed93SStephan Aßmus
376bef1ed93SStephan Aßmus		MarkDirty(&newDirtyRegion);
377bef1ed93SStephan Aßmus		_SetBackground(&background);
378bef1ed93SStephan Aßmus
379bef1ed93SStephan Aßmus		UnlockClipping();
380bef1ed93SStephan Aßmus	}
381748533bbSStephan Aßmus
382748533bbSStephan Aßmus	Unlock();
383bef1ed93SStephan Aßmus}
384bef1ed93SStephan Aßmus
385bef1ed93SStephan Aßmus// ResizeWindowBy
386bef1ed93SStephan Aßmusvoid
387bef1ed93SStephan AßmusDesktop::ResizeWindowBy(WindowLayer* window, int32 x, int32 y)
388bef1ed93SStephan Aßmus{
389748533bbSStephan Aßmus	if (!Lock())
390748533bbSStephan Aßmus		return;
391748533bbSStephan Aßmus
392bef1ed93SStephan Aßmus	if (LockClipping()) {
393bef1ed93SStephan Aßmus		BRegion newDirtyRegion;
394bef1ed93SStephan Aßmus		BRegion previouslyOccupiedRegion(window->VisibleRegion());
395bef1ed93SStephan Aßmus
396bef1ed93SStephan Aßmus		window->ResizeBy(x, y, &newDirtyRegion);
397bef1ed93SStephan Aßmus
398bef1ed93SStephan Aßmus		BRegion background;
399bef1ed93SStephan Aßmus		_RebuildClippingForAllWindows(&background);
400bef1ed93SStephan Aßmus
401bef1ed93SStephan Aßmus		previouslyOccupiedRegion.Exclude(&window->VisibleRegion());
402bef1ed93SStephan Aßmus
403bef1ed93SStephan Aßmus		newDirtyRegion.IntersectWith(&window->VisibleRegion());
404bef1ed93SStephan Aßmus		newDirtyRegion.Include(&previouslyOccupiedRegion);
405bef1ed93SStephan Aßmus
406bef1ed93SStephan Aßmus		MarkDirty(&newDirtyRegion);
407bef1ed93SStephan Aßmus		_SetBackground(&background);
408bef1ed93SStephan Aßmus
409bef1ed93SStephan Aßmus		UnlockClipping();
410bef1ed93SStephan Aßmus	}
411748533bbSStephan Aßmus
412748533bbSStephan Aßmus	Unlock();
413bef1ed93SStephan Aßmus}
414bef1ed93SStephan Aßmus
4158c8275c2SStephan Aßmus// ShowWindow
4168c8275c2SStephan Aßmusvoid
4178c8275c2SStephan AßmusDesktop::ShowWindow(WindowLayer* window)
4188c8275c2SStephan Aßmus{
4198c8275c2SStephan Aßmus	SetWindowHidden(window, false);
4208c8275c2SStephan Aßmus}
4218c8275c2SStephan Aßmus
4228c8275c2SStephan Aßmus// HideWindow
4238c8275c2SStephan Aßmusvoid
4248c8275c2SStephan AßmusDesktop::HideWindow(WindowLayer* window)
4258c8275c2SStephan Aßmus{
4268c8275c2SStephan Aßmus	SetWindowHidden(window, true);
4278c8275c2SStephan Aßmus}
4288c8275c2SStephan Aßmus
4298c8275c2SStephan Aßmus// SetWindowHidden
4308c8275c2SStephan Aßmusvoid
4318c8275c2SStephan AßmusDesktop::SetWindowHidden(WindowLayer* window, bool hidden)
4328c8275c2SStephan Aßmus{
433e76d86d5SStephan Aßmus	// TODO: if in ffm mode, make sure to switch focus
434e76d86d5SStephan Aßmus	// if appropriate
4358c8275c2SStephan Aßmus	if (LockClipping()) {
4368c8275c2SStephan Aßmus
4378c8275c2SStephan Aßmus		if (window->IsHidden() != hidden) {
4388c8275c2SStephan Aßmus
4398c8275c2SStephan Aßmus			window->SetHidden(hidden);
4408c8275c2SStephan Aßmus
4418c8275c2SStephan Aßmus			BRegion dirty;
4428c8275c2SStephan Aßmus
4438c8275c2SStephan Aßmus			if (hidden) {
4448c8275c2SStephan Aßmus				// after rebuilding the clipping,
4458c8275c2SStephan Aßmus				// this window will not have a visible
4468c8275c2SStephan Aßmus				// region anymore, so we need to remember
4478c8275c2SStephan Aßmus				// it now
4488c8275c2SStephan Aßmus				// (actually that's not true, since
4498c8275c2SStephan Aßmus				// hidden windows are excluded from the
4508c8275c2SStephan Aßmus				// clipping calculation, but anyways)
4518c8275c2SStephan Aßmus				dirty = window->VisibleRegion();
4528c8275c2SStephan Aßmus			}
4538c8275c2SStephan Aßmus
4548c8275c2SStephan Aßmus			BRegion background;
4558c8275c2SStephan Aßmus			_RebuildClippingForAllWindows(&background);
4568c8275c2SStephan Aßmus			_SetBackground(&background);
4578c8275c2SStephan Aßmus
4588c8275c2SStephan Aßmus			if (!hidden) {
4598c8275c2SStephan Aßmus				// everything that is now visible in the
4608c8275c2SStephan Aßmus				// window needs a redraw, but other windows
4618c8275c2SStephan Aßmus				// are not affected, we can call ProcessDirtyRegion()
4628c8275c2SStephan Aßmus				// of the window, and don't have to use MarkDirty()
4638c8275c2SStephan Aßmus				dirty = window->VisibleRegion();
4648c8275c2SStephan Aßmus				window->ProcessDirtyRegion(&dirty);
4658c8275c2SStephan Aßmus			} else {
4668c8275c2SStephan Aßmus				// when the window was hidden, the dirty region
4678c8275c2SStephan Aßmus				// affects other windows
4688c8275c2SStephan Aßmus				MarkDirty(&dirty);
4698c8275c2SStephan Aßmus			}
4708c8275c2SStephan Aßmus		}
4718c8275c2SStephan Aßmus
4728c8275c2SStephan Aßmus		UnlockClipping();
4738c8275c2SStephan Aßmus	}
4748c8275c2SStephan Aßmus}
4758c8275c2SStephan Aßmus
4768c8275c2SStephan Aßmus
477bef1ed93SStephan Aßmus// BringToFront
478bef1ed93SStephan Aßmusvoid
479bef1ed93SStephan AßmusDesktop::BringToFront(WindowLayer* window)
480bef1ed93SStephan Aßmus{
481bef1ed93SStephan Aßmus	if (window == TopWindow())
482bef1ed93SStephan Aßmus		return;
483bef1ed93SStephan Aßmus
484bef1ed93SStephan Aßmus	if (LockClipping()) {
485bef1ed93SStephan Aßmus
486bef1ed93SStephan Aßmus		// we don't need to redraw what is currently
487bef1ed93SStephan Aßmus		// visible of the window
488bef1ed93SStephan Aßmus		BRegion clean(window->VisibleRegion());
489bef1ed93SStephan Aßmus
490bef1ed93SStephan Aßmus		// detach window and re-atach at last position
491bef1ed93SStephan Aßmus		if (fWindows.RemoveItem((void*)window) &&
492bef1ed93SStephan Aßmus			fWindows.AddItem((void*)window)) {
493bef1ed93SStephan Aßmus
494bef1ed93SStephan Aßmus			BRegion dummy;
495bef1ed93SStephan Aßmus			_RebuildClippingForAllWindows(&dummy);
496bef1ed93SStephan Aßmus
497bef1ed93SStephan Aßmus			// redraw what became visible of the window
498bef1ed93SStephan Aßmus			BRegion dirty(window->VisibleRegion());
499bef1ed93SStephan Aßmus			dirty.Exclude(&clean);
500bef1ed93SStephan Aßmus
501bef1ed93SStephan Aßmus			MarkDirty(&dirty);
502bef1ed93SStephan Aßmus		}
503bef1ed93SStephan Aßmus
504bef1ed93SStephan Aßmus		UnlockClipping();
505bef1ed93SStephan Aßmus	}
5060b78f37eSStephan Aßmus
5070b78f37eSStephan Aßmus	if (!fFocusFollowsMouse)
5080b78f37eSStephan Aßmus		SetFocusWindow(TopWindow());
509bef1ed93SStephan Aßmus}
510bef1ed93SStephan Aßmus
511bef1ed93SStephan Aßmus// SendToBack
512bef1ed93SStephan Aßmusvoid
513bef1ed93SStephan AßmusDesktop::SendToBack(WindowLayer* window)
514bef1ed93SStephan Aßmus{
515bef1ed93SStephan Aßmus	if (window == BottomWindow())
516bef1ed93SStephan Aßmus		return;
517bef1ed93SStephan Aßmus
518bef1ed93SStephan Aßmus	if (LockClipping()) {
519bef1ed93SStephan Aßmus
520bef1ed93SStephan Aßmus		// what is currently visible of the window
521bef1ed93SStephan Aßmus		// might be dirty after the window is send to back
522bef1ed93SStephan Aßmus		BRegion dirty(window->VisibleRegion());
523bef1ed93SStephan Aßmus
524bef1ed93SStephan Aßmus		// detach window and re-atach at last position
525bef1ed93SStephan Aßmus		if (fWindows.RemoveItem((void*)window) &&
526bef1ed93SStephan Aßmus			fWindows.AddItem((void*)window, 0)) {
527bef1ed93SStephan Aßmus
528bef1ed93SStephan Aßmus			BRegion dummy;
529bef1ed93SStephan Aßmus			_RebuildClippingForAllWindows(&dummy);
530bef1ed93SStephan Aßmus
531bef1ed93SStephan Aßmus			// redraw what was previously visible of the window
532bef1ed93SStephan Aßmus			BRegion clean(window->VisibleRegion());
533bef1ed93SStephan Aßmus			dirty.Exclude(&clean);
534bef1ed93SStephan Aßmus
535bef1ed93SStephan Aßmus			MarkDirty(&dirty);
536bef1ed93SStephan Aßmus		}
537bef1ed93SStephan Aßmus
538bef1ed93SStephan Aßmus		UnlockClipping();
539bef1ed93SStephan Aßmus	}
5400b78f37eSStephan Aßmus
5410b78f37eSStephan Aßmus	if (!fFocusFollowsMouse)
5420b78f37eSStephan Aßmus		SetFocusWindow(TopWindow());
543bef1ed93SStephan Aßmus}
544bef1ed93SStephan Aßmus
5450b78f37eSStephan Aßmus// SetFocusWindow
5460b78f37eSStephan Aßmusvoid
5470b78f37eSStephan AßmusDesktop::SetFocusWindow(WindowLayer* window)
5480b78f37eSStephan Aßmus{
5490b78f37eSStephan Aßmus	if (fFocusWindow == window)
5500b78f37eSStephan Aßmus		return;
5510b78f37eSStephan Aßmus
552312345bcSStephan Aßmus	if (LockClipping()) {
5530b78f37eSStephan Aßmus
554312345bcSStephan Aßmus		if (fFocusWindow)
555312345bcSStephan Aßmus			fFocusWindow->SetFocus(false);
556312345bcSStephan Aßmus
557312345bcSStephan Aßmus		fFocusWindow = window;
558312345bcSStephan Aßmus
559312345bcSStephan Aßmus		if (fFocusWindow)
560312345bcSStephan Aßmus			fFocusWindow->SetFocus(true);
5610b78f37eSStephan Aßmus
562312345bcSStephan Aßmus		UnlockClipping();
563312345bcSStephan Aßmus	}
5640b78f37eSStephan Aßmus}
5650b78f37eSStephan Aßmus
5660b78f37eSStephan Aßmus
5670b78f37eSStephan Aßmus
568c63a78aaSStephan Aßmus// #pragma mark -
569bef1ed93SStephan Aßmus
570bef1ed93SStephan Aßmus// MarkDirty
571bef1ed93SStephan Aßmusvoid
572bef1ed93SStephan AßmusDesktop::MarkDirty(BRegion* region)
573bef1ed93SStephan Aßmus{
574bef1ed93SStephan Aßmus	if (region->CountRects() == 0)
575bef1ed93SStephan Aßmus		return;
576bef1ed93SStephan Aßmus
577bef1ed93SStephan Aßmus	if (LockClipping()) {
578bef1ed93SStephan Aßmus		// send redraw messages to all windows intersecting the dirty region
579bef1ed93SStephan Aßmus		_TriggerWindowRedrawing(region);
580bef1ed93SStephan Aßmus
581bef1ed93SStephan Aßmus		UnlockClipping();
582bef1ed93SStephan Aßmus	}
583bef1ed93SStephan Aßmus}
584bef1ed93SStephan Aßmus
585a825e403SStephan Aßmus// WindowDied
586