xref: /haiku/src/servers/app/ServerWindow.cpp (revision 020cbad9d40235a2c50a81a42d69912a5ff8fbc4)
1 /*
2  * Copyright 2001-2007, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Adrian Oanca <adioanca@gmail.com>
8  *		Stephan Aßmus <superstippi@gmx.de>
9  *		Stefano Ceccherini (burton666@libero.it)
10  *		Axel Dörfler, axeld@pinc-software.de
11  */
12 
13 /*!
14 	\class ServerWindow
15 	\brief Shadow BWindow class
16 
17 	A ServerWindow handles all the intraserver tasks required of it by its BWindow. There are
18 	too many tasks to list as being done by them, but they include handling View transactions,
19 	coordinating and linking a window's WindowLayer half with its messaging half, dispatching
20 	mouse and key events from the server to its window, and other such things.
21 */
22 
23 
24 #include "ServerWindow.h"
25 
26 #include "AppServer.h"
27 #include "DebugInfoManager.h"
28 #include "Desktop.h"
29 #include "DrawingEngine.h"
30 #include "HWInterface.h"
31 #include "Overlay.h"
32 #include "ProfileMessageSupport.h"
33 #include "RAMLinkMsgReader.h"
34 #include "RenderingBuffer.h"
35 #include "ServerApp.h"
36 #include "ServerBitmap.h"
37 #include "ServerPicture.h"
38 #include "ServerProtocol.h"
39 #include "WindowLayer.h"
40 #include "WorkspacesLayer.h"
41 
42 #include "clipping.h"
43 
44 #include <DirectWindowPrivate.h>
45 #include <MessagePrivate.h>
46 #include <PortLink.h>
47 #include <WindowInfo.h>
48 #include <WindowPrivate.h>
49 
50 #include <AppDefs.h>
51 #include <Autolock.h>
52 #include <DirectWindow.h>
53 #include <TokenSpace.h>
54 #include <View.h>
55 
56 #include <new>
57 
58 using std::nothrow;
59 
60 //#define TRACE_SERVER_WINDOW
61 //#define TRACE_SERVER_WINDOW_MESSAGES
62 //#define PROFILE_MESSAGE_LOOP
63 
64 
65 #ifdef TRACE_SERVER_WINDOW
66 #	include <stdio.h>
67 #	define STRACE(x) printf x
68 #else
69 #	define STRACE(x) ;
70 #endif
71 
72 #ifdef TRACE_SERVER_WINDOW_MESSAGES
73 #	include <stdio.h>
74 #	define DTRACE(x) printf x
75 #else
76 #	define DTRACE(x) ;
77 #endif
78 
79 #ifdef PROFILE_MESSAGE_LOOP
80 struct profile { int32 code; int32 count; bigtime_t time; };
81 static profile sMessageProfile[AS_LAST_CODE];
82 static profile sRedrawProcessingTime;
83 //static profile sNextMessageTime;
84 #endif
85 
86 
87 struct direct_window_data {
88 	direct_window_data();
89 	~direct_window_data();
90 
91 	status_t InitCheck() const;
92 
93 	sem_id	sem;
94 	sem_id	sem_ack;
95 	area_id	area;
96 	bool	started;
97 	int	next_buffer_state;
98 	direct_buffer_info *buffer_info;
99 };
100 
101 
102 direct_window_data::direct_window_data()
103 	:
104 	sem(-1),
105 	sem_ack(-1),
106 	area(-1),
107 	started(false),
108 	next_buffer_state(0),
109 	buffer_info(NULL)
110 {
111 	area = create_area("direct area", (void **)&buffer_info,
112 		B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_WRITE);
113 
114 	sem = create_sem(0, "direct sem");
115 	sem_ack = create_sem(0, "direct sem ack");
116 }
117 
118 
119 direct_window_data::~direct_window_data()
120 {
121 	// this should make the client die in case it's still running
122 	buffer_info->bits = NULL;
123 	buffer_info->bytes_per_row = 0;
124 
125 	delete_area(area);
126 	delete_sem(sem);
127 	delete_sem(sem_ack);
128 }
129 
130 
131 status_t
132 direct_window_data::InitCheck() const
133 {
134 	if (area < B_OK)
135 		return area;
136 	if (sem < B_OK)
137 		return sem;
138 	if (sem_ack < B_OK)
139 		return sem_ack;
140 
141 	return B_OK;
142 }
143 
144 
145 //	#pragma mark -
146 
147 
148 /*!
149 	Sets up the basic BWindow counterpart - you have to call Init() before
150 	you can actually use it, though.
151 */
152 ServerWindow::ServerWindow(const char *title, ServerApp *app,
153 	port_id clientPort, port_id looperPort, int32 clientToken)
154 	: MessageLooper(title && *title ? title : "Unnamed Window"),
155 	fTitle(NULL),
156 	fDesktop(app->GetDesktop()),
157 	fServerApp(app),
158 	fWindowLayer(NULL),
159 	fWindowAddedToDesktop(false),
160 
161 	fClientTeam(app->ClientTeam()),
162 
163 	fMessagePort(-1),
164 	fClientReplyPort(clientPort),
165 	fClientLooperPort(looperPort),
166 
167 	fClientToken(clientToken),
168 
169 	fCurrentLayer(NULL),
170 	fCurrentDrawingRegion(),
171 	fCurrentDrawingRegionValid(false),
172 
173 	fDirectWindowData(NULL)
174 {
175 	STRACE(("ServerWindow(%s)::ServerWindow()\n", title));
176 
177 	SetTitle(title);
178 	fServerToken = BPrivate::gDefaultTokens.NewToken(B_SERVER_TOKEN, this);
179 
180 	BMessenger::Private(fFocusMessenger).SetTo(fClientTeam,
181 		looperPort, B_PREFERRED_TOKEN);
182 	BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
183 		looperPort, clientToken);
184 
185 	fEventTarget.SetTo(fFocusMessenger);
186 
187 	fDeathSemaphore = create_sem(0, "window death");
188 }
189 
190 #ifdef PROFILE_MESSAGE_LOOP
191 static int
192 compare_message_profiles(const void* _a, const void* _b)
193 {
194 	profile* a = (profile*)*(void**)_a;
195 	profile* b = (profile*)*(void**)_b;
196 	if (a->time < b->time)
197 		return 1;
198 	if (a->time > b->time)
199 		return -1;
200 	return 0;
201 }
202 #endif
203 
204 
205 //! Tears down all connections the main app_server objects, and deletes some internals.
206 ServerWindow::~ServerWindow()
207 {
208 	STRACE(("ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this));
209 
210 	if (!fWindowLayer->IsOffscreenWindow()) {
211 		fWindowAddedToDesktop = false;
212 		fDesktop->RemoveWindow(fWindowLayer);
213 	}
214 
215 	if (App() != NULL)
216 		App()->RemoveWindow(this);
217 
218 	delete fWindowLayer;
219 
220 	free(fTitle);
221 	delete_port(fMessagePort);
222 
223 	BPrivate::gDefaultTokens.RemoveToken(fServerToken);
224 
225 	delete fDirectWindowData;
226 	STRACE(("ServerWindow(%p) will exit NOW\n", this));
227 
228 	delete_sem(fDeathSemaphore);
229 
230 #ifdef PROFILE_MESSAGE_LOOP
231 	BList profiles;
232 	for (int32 i = 0; i < AS_LAST_CODE; i++) {
233 		if (sMessageProfile[i].count == 0)
234 			continue;
235 		sMessageProfile[i].code = i;
236 		profiles.AddItem(&sMessageProfile[i]);
237 	}
238 
239 	profiles.SortItems(compare_message_profiles);
240 
241 	BString codeName;
242 	int32 count = profiles.CountItems();
243 	for (int32 i = 0; i < count; i++) {
244 		profile* p = (profile*)profiles.ItemAtFast(i);
245 		string_for_message_code(p->code, codeName);
246 		printf("[%s] called %ld times, %g secs (%Ld usecs per call)\n",
247 			codeName.String(), p->count, p->time / 1000000.0,
248 			p->time / p->count);
249 	}
250 	if (sRedrawProcessingTime.count > 0) {
251 		printf("average redraw processing time: %g secs, count: %ld (%lld usecs per call)\n",
252 			sRedrawProcessingTime.time / 1000000.0, sRedrawProcessingTime.count,
253 			sRedrawProcessingTime.time / sRedrawProcessingTime.count);
254 	}
255 //	if (sNextMessageTime.count > 0) {
256 //		printf("average NextMessage() time: %g secs, count: %ld (%lld usecs per call)\n",
257 //			sNextMessageTime.time / 1000000.0, sNextMessageTime.count,
258 //			sNextMessageTime.time / sNextMessageTime.count);
259 //	}
260 #endif
261 }
262 
263 
264 status_t
265 ServerWindow::Init(BRect frame, window_look look, window_feel feel,
266 	uint32 flags, uint32 workspace)
267 {
268 	if (!App()->AddWindow(this)) {
269 		fServerApp = NULL;
270 		return B_NO_MEMORY;
271 	}
272 
273 	if (fTitle == NULL)
274 		return B_NO_MEMORY;
275 
276 	// fMessagePort is the port to which the app sends messages for the server
277 	fMessagePort = create_port(100, fTitle);
278 	if (fMessagePort < B_OK)
279 		return fMessagePort;
280 
281 	fLink.SetSenderPort(fClientReplyPort);
282 	fLink.SetReceiverPort(fMessagePort);
283 
284 	// We cannot call MakeWindowLayer in the constructor, since it
285 	// is a virtual function!
286 	fWindowLayer = MakeWindowLayer(frame, fTitle, look, feel, flags, workspace);
287 	if (!fWindowLayer)
288 		return B_NO_MEMORY;
289 
290 	if (!fWindowLayer->IsOffscreenWindow()) {
291 		fDesktop->AddWindow(fWindowLayer);
292 		fWindowAddedToDesktop = true;
293 	}
294 
295 	return B_OK;
296 }
297 
298 
299 bool
300 ServerWindow::Run()
301 {
302 	if (!MessageLooper::Run())
303 		return false;
304 
305 	// Send a reply to our window - it is expecting fMessagePort
306 	// port and some other info
307 
308 	fLink.StartMessage(B_OK);
309 	fLink.Attach<port_id>(fMessagePort);
310 
311 	int32 minWidth, maxWidth, minHeight, maxHeight;
312 	fWindowLayer->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
313 
314 	fLink.Attach<BRect>(fWindowLayer->Frame());
315 	fLink.Attach<float>((float)minWidth);
316 	fLink.Attach<float>((float)maxWidth);
317 	fLink.Attach<float>((float)minHeight);
318 	fLink.Attach<float>((float)maxHeight);
319 	fLink.Flush();
320 
321 	return true;
322 }
323 
324 
325 void
326 ServerWindow::_PrepareQuit()
327 {
328 	if (fThread == find_thread(NULL)) {
329 		// make sure we're hidden
330 		fDesktop->LockSingleWindow();
331 		_Hide();
332 		fDesktop->UnlockSingleWindow();
333 	} else if (fThread >= B_OK)
334 		PostMessage(AS_HIDE_WINDOW);
335 }
336 
337 
338 void
339 ServerWindow::_GetLooperName(char* name, size_t length)
340 {
341 	const char *title = Title();
342 	if (title == NULL || !title[0])
343 		title = "Unnamed Window";
344 
345 	snprintf(name, length, "w:%ld:%s", ClientTeam(), title);
346 }
347 
348 
349 //! Forces the window layer to update its decorator
350 void
351 ServerWindow::ReplaceDecorator()
352 {
353 	if (!IsLocked())
354 		debugger("you must lock a ServerWindow object before calling ::ReplaceDecorator()\n");
355 
356 	STRACE(("ServerWindow %s: Replace Decorator\n", fTitle));
357 	//fWindowLayer->UpdateDecorator();
358 }
359 
360 
361 //! Shows the window's WindowLayer
362 void
363 ServerWindow::_Show()
364 {
365 	// NOTE: if you do something else, other than sending a port message, PLEASE lock
366 	STRACE(("ServerWindow %s: _Show\n", Title()));
367 
368 	if (fQuitting || !fWindowLayer->IsHidden() || fWindowLayer->IsOffscreenWindow())
369 		return;
370 
371 	// TODO: Maybe we need to dispatch a message to the desktop to show/hide us
372 	// instead of doing it from this thread.
373 	fDesktop->UnlockSingleWindow();
374 	fDesktop->ShowWindow(fWindowLayer);
375 	fDesktop->LockSingleWindow();
376 
377 	if (fDirectWindowData != NULL)
378 		HandleDirectConnection(B_DIRECT_START | B_BUFFER_RESET);
379 }
380 
381 
382 //! Hides the window's WindowLayer
383 void
384 ServerWindow::_Hide()
385 {
386 	// NOTE: if you do something else, other than sending a port message, PLEASE lock
387 	STRACE(("ServerWindow %s: _Hide\n", Title()));
388 
389 	if (fWindowLayer->IsHidden() || fWindowLayer->IsOffscreenWindow())
390 		return;
391 
392 	if (fDirectWindowData != NULL)
393 		HandleDirectConnection(B_DIRECT_STOP);
394 
395 	fDesktop->UnlockSingleWindow();
396 	fDesktop->HideWindow(fWindowLayer);
397 	fDesktop->LockSingleWindow();
398 }
399 
400 
401 void
402 ServerWindow::RequestRedraw()
403 {
404 	PostMessage(AS_REDRAW, 0);
405 		// we don't care if this fails - it's only a notification, and if
406 		// it fails, there are obviously enough messages in the queue
407 		// already
408 
409 	atomic_add(&fRedrawRequested, 1);
410 }
411 
412 
413 void
414 ServerWindow::SetTitle(const char* newTitle)
415 {
416 	char* oldTitle = fTitle;
417 
418 	if (newTitle == NULL)
419 		newTitle = "";
420 
421 	fTitle = strdup(newTitle);
422 	if (fTitle == NULL) {
423 		// out of memory condition
424 		fTitle = oldTitle;
425 		return;
426 	}
427 
428 	free(oldTitle);
429 
430 	if (Thread() >= B_OK) {
431 		char name[B_OS_NAME_LENGTH];
432 		_GetLooperName(name, sizeof(name));
433 		rename_thread(Thread(), name);
434 	}
435 
436 	if (fWindowLayer != NULL) {
437 //fDesktop->UnlockSingleWindow();
438 		fDesktop->SetWindowTitle(fWindowLayer, newTitle);
439 //fDesktop->LockSingleWindow();
440 	}
441 }
442 
443 
444 //! Requests that the ServerWindow's BWindow quit
445 void
446 ServerWindow::NotifyQuitRequested()
447 {
448 	// NOTE: if you do something else, other than sending a port message,
449 	// PLEASE lock
450 	STRACE(("ServerWindow %s: Quit\n", fTitle));
451 
452 	BMessage msg(B_QUIT_REQUESTED);
453 	SendMessageToClient(&msg);
454 }
455 
456 
457 void
458 ServerWindow::NotifyMinimize(bool minimize)
459 {
460 	if (fWindowLayer->Feel() != B_NORMAL_WINDOW_FEEL)
461 		return;
462 
463 	// The client is responsible for the actual minimization
464 
465 	BMessage msg(B_MINIMIZE);
466 	msg.AddInt64("when", real_time_clock_usecs());
467 	msg.AddBool("minimize", minimize);
468 
469 	SendMessageToClient(&msg);
470 }
471 
472 
473 //! Sends a message to the client to perform a Zoom
474 void
475 ServerWindow::NotifyZoom()
476 {
477 	// NOTE: if you do something else, other than sending a port message,
478 	// PLEASE lock
479 	BMessage msg(B_ZOOM);
480 	SendMessageToClient(&msg);
481 }
482 
483 
484 void
485 ServerWindow::GetInfo(window_info& info)
486 {
487 	info.team = ClientTeam();
488 	info.server_token = ServerToken();
489 
490 	info.thread = Thread();
491 	info.client_token = ClientToken();
492 	info.client_port = fClientLooperPort;
493 	info.workspaces = fWindowLayer->Workspaces();
494 
495 	info.layer = 0; // ToDo: what is this???
496 	info.feel = fWindowLayer->Feel();
497 	info.flags = fWindowLayer->Flags();
498 	info.window_left = (int)floor(fWindowLayer->Frame().left);
499 	info.window_top = (int)floor(fWindowLayer->Frame().top);
500 	info.window_right = (int)floor(fWindowLayer->Frame().right);
501 	info.window_bottom = (int)floor(fWindowLayer->Frame().bottom);
502 
503 	info.show_hide_level = fWindowLayer->IsHidden() ? 1 : 0; // ???
504 	info.is_mini = fWindowLayer->IsMinimized();
505 }
506 
507 
508 void
509 ServerWindow::ResyncDrawState()
510 {
511 	_UpdateDrawState(fCurrentLayer);
512 }
513 
514 
515 /*!
516 	Returns the ServerWindow's WindowLayer, if it exists and has been
517 	added to the Desktop already.
518 	In other words, you cannot assume this method will always give you
519 	a valid pointer.
520 */
521 WindowLayer*
522 ServerWindow::Window() const
523 {
524 	// TODO: ensure desktop is locked!
525 	if (!fWindowAddedToDesktop)
526 		return NULL;
527 
528 	return fWindowLayer;
529 }
530 
531 
532 ViewLayer*
533 ServerWindow::_CreateLayerTree(BPrivate::LinkReceiver &link, ViewLayer **_parent)
534 {
535 	// NOTE: no need to check for a lock. This is a private method.
536 
537 	int32 token;
538 	BRect frame;
539 	uint32 resizeMask;
540 	uint32 eventMask;
541 	uint32 eventOptions;
542 	uint32 flags;
543 	bool hidden;
544 	int32 parentToken;
545 	char* name = NULL;
546 	rgb_color viewColor;
547 	BPoint scrollingOffset;
548 
549 	link.Read<int32>(&token);
550 	link.ReadString(&name);
551 	link.Read<BRect>(&frame);
552 	link.Read<BPoint>(&scrollingOffset);
553 	link.Read<uint32>(&resizeMask);
554 	link.Read<uint32>(&eventMask);
555 	link.Read<uint32>(&eventOptions);
556 	link.Read<uint32>(&flags);
557 	link.Read<bool>(&hidden);
558 	link.Read<rgb_color>(&viewColor);
559 	link.Read<int32>(&parentToken);
560 
561 	STRACE(("ServerWindow(%s)::_CreateLayerTree()-> layer %s, token %ld\n",
562 		fTitle, name, token));
563 
564 	ViewLayer* newLayer;
565 
566 	if (link.Code() == AS_LAYER_CREATE_ROOT
567 		&& (fWindowLayer->Flags() & kWorkspacesWindowFlag) != 0) {
568 		// this is a workspaces window!
569 		newLayer = new (nothrow) WorkspacesLayer(frame, scrollingOffset, name,
570 			token, resizeMask, flags);
571 	} else {
572 		newLayer = new (nothrow) ViewLayer(frame, scrollingOffset, name, token,
573 			resizeMask, flags);
574 	}
575 
576 	free(name);
577 
578 	if (newLayer == NULL)
579 		return NULL;
580 
581 	// there is no way of setting this, other than manually :-)
582 	newLayer->SetViewColor(viewColor);
583 	newLayer->SetHidden(hidden);
584 	newLayer->SetEventMask(eventMask, eventOptions);
585 
586 	if (eventMask != 0 || eventOptions != 0) {
587 //		fDesktop->UnlockSingleWindow();
588 //		fDesktop->LockAllWindows();
589 fDesktop->UnlockAllWindows();
590 		// TODO: possible deadlock
591 		fDesktop->EventDispatcher().AddListener(EventTarget(),
592 			newLayer->Token(), eventMask, eventOptions);
593 fDesktop->LockAllWindows();
594 //		fDesktop->UnlockAllWindows();
595 //		fDesktop->LockSingleWindow();
596 	}
597 
598 	// TODO: default fonts should be created and stored in the Application
599 	DesktopSettings settings(fDesktop);
600 	ServerFont font;
601 	settings.GetDefaultPlainFont(font);
602 	newLayer->CurrentState()->SetFont(font);
603 
604 	if (_parent) {
605 		ViewLayer *parent;
606 		if (App()->ViewTokens().GetToken(parentToken, B_HANDLER_TOKEN,
607 				(void**)&parent) != B_OK
608 			|| parent->Window()->ServerWindow() != this) {
609 			CRITICAL("View token not found!\n");
610 			parent = NULL;
611 		}
612 
613 		*_parent = parent;
614 	}
615 
616 	return newLayer;
617 }
618 
619 
620 /*!
621 	Dispatches all window messages, and those view messages that
622 	don't need a valid fCurrentLayer (ie. layer creation).
623 */
624 void
625 ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
626 {
627 	switch (code) {
628 		case AS_SHOW_WINDOW:
629 			STRACE(("ServerWindow %s: Message AS_SHOW_WINDOW\n", Title()));
630 			_Show();
631 			break;
632 
633 		case AS_HIDE_WINDOW:
634 			STRACE(("ServerWindow %s: Message AS_HIDE_WINDOW\n", Title()));
635 			_Hide();
636 			break;
637 
638 		case AS_MINIMIZE_WINDOW:
639 		{
640 			DTRACE(("ServerWindow %s: Message AS_MINIMIZE_WINDOW\n", Title()));
641 			int32 showLevel;
642 			bool minimize;
643 
644 			link.Read<bool>(&minimize);
645 			if (link.Read<int32>(&showLevel) == B_OK) {
646 				if (showLevel <= 0) {
647 					// window is currently hidden - ignore the minimize request
648 					break;
649 				}
650 
651 				if (minimize && !fWindowLayer->IsHidden())
652 					_Hide();
653 				else if (!minimize && fWindowLayer->IsHidden())
654 					_Show();
655 
656 				fWindowLayer->SetMinimized(minimize);
657 			}
658 			break;
659 		}
660 
661 		case AS_ACTIVATE_WINDOW:
662 		{
663 			DTRACE(("ServerWindow %s: Message AS_ACTIVATE_WINDOW: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
664 			bool activate = true;
665 
666 			link.Read<bool>(&activate);
667 
668 //fDesktop->UnlockSingleWindow();
669 			if (activate)
670 				fDesktop->ActivateWindow(fWindowLayer);
671 			else
672 				fDesktop->SendWindowBehind(fWindowLayer, NULL);
673 //fDesktop->LockSingleWindow();
674 			break;
675 		}
676 		case AS_SEND_BEHIND:
677 		{
678 			STRACE(("ServerWindow %s: Message AS_SEND_BEHIND\n", Title()));
679 			int32 token;
680 			team_id teamID;
681 			status_t status;
682 
683 			link.Read<int32>(&token);
684 			link.Read<team_id>(&teamID);
685 
686 			WindowLayer *behindOf;
687 			if ((behindOf = fDesktop->FindWindowLayerByClientToken(token, teamID)) != NULL) {
688 //fDesktop->UnlockSingleWindow();
689 // TODO: there is a big race condition when we unlock here (window could be gone by now)!
690 				fDesktop->SendWindowBehind(fWindowLayer, behindOf);
691 //fDesktop->LockSingleWindow();
692 				status = B_OK;
693 			} else
694 				status = B_NAME_NOT_FOUND;
695 
696 			fLink.StartMessage(status);
697 			fLink.Flush();
698 			break;
699 		}
700 
701 		case B_QUIT_REQUESTED:
702 			STRACE(("ServerWindow %s received quit request\n", Title()));
703 			NotifyQuitRequested();
704 			break;
705 
706 		case AS_ENABLE_UPDATES:
707 		{
708 			STRACE(("ServerWindow %s: Message AS_ENABLE_UPDATES unimplemented\n",
709 				Title()));
710 // TODO: AS_ENABLE_UPDATES
711 			//fWindowLayer->EnableUpdateRequests();
712 			break;
713 		}
714 		case AS_DISABLE_UPDATES:
715 		{
716 			STRACE(("ServerWindow %s: Message AS_DISABLE_UPDATES unimplemented\n",
717 				Title()));
718 // TODO: AS_DISABLE_UPDATES
719 			//fWindowLayer->DisableUpdateRequests();
720 			break;
721 		}
722 		case AS_NEEDS_UPDATE:
723 		{
724 			STRACE(("ServerWindow %s: Message AS_NEEDS_UPDATE\n", Title()));
725 			if (fWindowLayer->NeedsUpdate())
726 				fLink.StartMessage(B_OK);
727 			else
728 				fLink.StartMessage(B_ERROR);
729 			fLink.Flush();
730 			break;
731 		}
732 		case AS_SET_WINDOW_TITLE:
733 		{
734 			char* newTitle;
735 			if (link.ReadString(&newTitle) == B_OK) {
736 				SetTitle(newTitle);
737 				free(newTitle);
738 			}
739 			break;
740 		}
741 
742 		case AS_ADD_TO_SUBSET:
743 		{
744 			STRACE(("ServerWindow %s: Message AS_ADD_TO_SUBSET\n", Title()));
745 			status_t status = B_ERROR;
746 
747 			int32 token;
748 			if (link.Read<int32>(&token) == B_OK) {
749 				WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken(
750 					token, App()->ClientTeam());
751 				if (windowLayer == NULL
752 					|| windowLayer->Feel() != B_NORMAL_WINDOW_FEEL) {
753 					status = B_BAD_VALUE;
754 				} else {
755 //fDesktop->UnlockSingleWindow();
756 // TODO: there is a big race condition when we unlock here (window could be gone by now)!
757 					status = fDesktop->AddWindowToSubset(fWindowLayer, windowLayer)
758 						? B_OK : B_NO_MEMORY;
759 //fDesktop->LockSingleWindow();
760 				}
761 			}
762 
763 			fLink.StartMessage(status);
764 			fLink.Flush();
765 			break;
766 		}
767 		case AS_REMOVE_FROM_SUBSET:
768 		{
769 			STRACE(("ServerWindow %s: Message AS_REM_FROM_SUBSET\n", Title()));
770 			status_t status = B_ERROR;
771 
772 			int32 token;
773 			if (link.Read<int32>(&token) == B_OK) {
774 				WindowLayer* windowLayer = fDesktop->FindWindowLayerByClientToken(
775 					token, App()->ClientTeam());
776 				if (windowLayer != NULL) {
777 //fDesktop->UnlockSingleWindow();
778 // TODO: there is a big race condition when we unlock here (window could be gone by now)!
779 					fDesktop->RemoveWindowFromSubset(fWindowLayer, windowLayer);
780 //fDesktop->LockSingleWindow();
781 					status = B_OK;
782 				} else
783 					status = B_BAD_VALUE;
784 			}
785 
786 			fLink.StartMessage(status);
787 			fLink.Flush();
788 			break;
789 		}
790 
791 		case AS_SET_LOOK:
792 		{
793 			STRACE(("ServerWindow %s: Message AS_SET_LOOK\n", Title()));
794 
795 			status_t status = B_ERROR;
796 			int32 look;
797 			if (link.Read<int32>(&look) == B_OK) {
798 				// test if look is valid
799 				status = WindowLayer::IsValidLook((window_look)look)
800 					? B_OK : B_BAD_VALUE;
801 			}
802 
803 			if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
804 //fDesktop->UnlockSingleWindow();
805 				fDesktop->SetWindowLook(fWindowLayer, (window_look)look);
806 //fDesktop->LockSingleWindow();
807 			}
808 
809 			fLink.StartMessage(status);
810 			fLink.Flush();
811 			break;
812 		}
813 		case AS_SET_FEEL:
814 		{
815 			STRACE(("ServerWindow %s: Message AS_SET_FEEL\n", Title()));
816 
817 			status_t status = B_ERROR;
818 			int32 feel;
819 			if (link.Read<int32>(&feel) == B_OK) {
820 				// test if feel is valid
821 				status = WindowLayer::IsValidFeel((window_feel)feel)
822 					? B_OK : B_BAD_VALUE;
823 			}
824 
825 			if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
826 //fDesktop->UnlockSingleWindow();
827 				fDesktop->SetWindowFeel(fWindowLayer, (window_feel)feel);
828 //fDesktop->LockSingleWindow();
829 			}
830 
831 			fLink.StartMessage(status);
832 			fLink.Flush();
833 			break;
834 		}
835 		case AS_SET_FLAGS:
836 		{
837 			STRACE(("ServerWindow %s: Message AS_SET_FLAGS\n", Title()));
838 
839 			status_t status = B_ERROR;
840 			uint32 flags;
841 			if (link.Read<uint32>(&flags) == B_OK) {
842 				// test if flags are valid
843 				status = (flags & ~WindowLayer::ValidWindowFlags()) == 0
844 					? B_OK : B_BAD_VALUE;
845 			}
846 
847 			if (status == B_OK && !fWindowLayer->IsOffscreenWindow()) {
848 //fDesktop->UnlockSingleWindow();
849 				fDesktop->SetWindowFlags(fWindowLayer, flags);
850 //fDesktop->LockSingleWindow();
851 			}
852 
853 			fLink.StartMessage(status);
854 			fLink.Flush();
855 			break;
856 		}
857 #if 0
858 		case AS_SET_ALIGNMENT:
859 		{
860 			// TODO: Implement AS_SET_ALIGNMENT
861 			STRACE(("ServerWindow %s: Message Set_Alignment unimplemented\n", Title()));
862 			break;
863 		}
864 		case AS_GET_ALIGNMENT:
865 		{
866 			// TODO: Implement AS_GET_ALIGNMENT
867 			STRACE(("ServerWindow %s: Message Get_Alignment unimplemented\n", Title()));
868 			break;
869 		}
870 #endif
871 		case AS_IS_FRONT_WINDOW:
872 			fLink.StartMessage(fDesktop->FrontWindow() == fWindowLayer ? B_OK : B_ERROR);
873 			fLink.Flush();
874 			break;
875 
876 		case AS_GET_WORKSPACES:
877 		{
878 			STRACE(("ServerWindow %s: Message AS_GET_WORKSPACES\n", Title()));
879 			fLink.StartMessage(B_OK);
880 			fLink.Attach<uint32>(fWindowLayer->Workspaces());
881 			fLink.Flush();
882 			break;
883 		}
884 		case AS_SET_WORKSPACES:
885 		{
886 			uint32 newWorkspaces;
887 			if (link.Read<uint32>(&newWorkspaces) != B_OK)
888 				break;
889 
890 			STRACE(("ServerWindow %s: Message AS_SET_WORKSPACES %lx\n",
891 				Title(), newWorkspaces));
892 
893 //fDesktop->UnlockSingleWindow();
894 			fDesktop->SetWindowWorkspaces(fWindowLayer, newWorkspaces);
895 //fDesktop->LockSingleWindow();
896 			break;
897 		}
898 		case AS_WINDOW_RESIZE:
899 		{
900 			float xResizeBy;
901 			float yResizeBy;
902 			link.Read<float>(&xResizeBy);
903 			if (link.Read<float>(&yResizeBy) != B_OK)
904 				break;
905 
906 			STRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n",
907 				Title(), xResizeBy, yResizeBy));
908 
909 			if (fWindowLayer->IsResizing()) {
910 				// While the user resizes the window, we ignore
911 				// pragmatically set window bounds
912 				fLink.StartMessage(B_BUSY);
913 			} else {
914 //fDesktop->UnlockSingleWindow();
915 				fDesktop->ResizeWindowBy(fWindowLayer, xResizeBy, yResizeBy);
916 //fDesktop->LockSingleWindow();
917 				fLink.StartMessage(B_OK);
918 			}
919 			fLink.Flush();
920 			break;
921 		}
922 		case AS_WINDOW_MOVE:
923 		{
924 			float xMoveBy;
925 			float yMoveBy;
926 			link.Read<float>(&xMoveBy);
927 			if (link.Read<float>(&yMoveBy) != B_OK)
928 				break;
929 
930 			STRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n",
931 				Title(), xMoveBy, yMoveBy));
932 
933 			if (fWindowLayer->IsDragging()) {
934 				// While the user moves the window, we ignore
935 				// pragmatically set window positions
936 				fLink.StartMessage(B_BUSY);
937 			} else {
938 //fDesktop->UnlockSingleWindow();
939 				fDesktop->MoveWindowBy(fWindowLayer, xMoveBy, yMoveBy);
940 //fDesktop->LockSingleWindow();
941 				fLink.StartMessage(B_OK);
942 			}
943 			fLink.Flush();
944 			break;
945 		}
946 		case AS_SET_SIZE_LIMITS:
947 		{
948 			// Attached Data:
949 			// 1) float minimum width
950 			// 2) float maximum width
951 			// 3) float minimum height
952 			// 4) float maximum height
953 
954 			// TODO: for now, move the client to int32 as well!
955 			int32 minWidth, maxWidth, minHeight, maxHeight;
956 			float value;
957 			link.Read<float>(&value);	minWidth = (int32)value;
958 			link.Read<float>(&value);	maxWidth = (int32)value;
959 			link.Read<float>(&value);	minHeight = (int32)value;
960 			link.Read<float>(&value);	maxHeight = (int32)value;
961 /*
962 			link.Read<int32>(&minWidth);
963 			link.Read<int32>(&maxWidth);
964 			link.Read<int32>(&minHeight);
965 			link.Read<int32>(&maxHeight);
966 */
967 //fDesktop->UnlockSingleWindow();
968 
969 			if (fDesktop->LockAllWindows()) {
970 				fWindowLayer->SetSizeLimits(minWidth, maxWidth,
971 					minHeight, maxHeight);
972 				fDesktop->UnlockAllWindows();
973 			}
974 
975 //fDesktop->LockSingleWindow();
976 
977 			// and now, sync the client to the limits that we were able to enforce
978 			fWindowLayer->GetSizeLimits(&minWidth, &maxWidth,
979 				&minHeight, &maxHeight);
980 
981 			fLink.StartMessage(B_OK);
982 			fLink.Attach<BRect>(fWindowLayer->Frame());
983 			fLink.Attach<float>((float)minWidth);
984 			fLink.Attach<float>((float)maxWidth);
985 			fLink.Attach<float>((float)minHeight);
986 			fLink.Attach<float>((float)maxHeight);
987 
988 			fLink.Flush();
989 			break;
990 		}
991 
992 		case AS_SET_DECORATOR_SETTINGS:
993 		{
994 			STRACE(("ServerWindow %s: Message AS_SET_DECORATOR_SETTINGS\n"));
995 
996 			int32 size;
997 			if (fWindowLayer && link.Read<int32>(&size) == B_OK) {
998 				char buffer[size];
999 				if (link.Read(buffer, size) == B_OK) {
1000 					BMessage settings;
1001 					if (settings.Unflatten(buffer) == B_OK) {
1002 //fDesktop->UnlockSingleWindow();
1003 						fDesktop->SetWindowDecoratorSettings(fWindowLayer, settings);
1004 //fDesktop->LockSingleWindow();
1005 					}
1006 				}
1007 			}
1008 			break;
1009 		}
1010 
1011 		case AS_GET_DECORATOR_SETTINGS:
1012 		{
1013 			STRACE(("ServerWindow %s: Message AS_GET_DECORATOR_SETTINGS\n"));
1014 
1015 			bool success = false;
1016 
1017 			BMessage settings;
1018 			if (fWindowLayer->GetDecoratorSettings(&settings)) {
1019 				int32 size = settings.FlattenedSize();
1020 				char buffer[size];
1021 				if (settings.Flatten(buffer, size) == B_OK) {
1022 					success = true;
1023 					fLink.StartMessage(B_OK);
1024 					fLink.Attach<int32>(size);
1025 					fLink.Attach(buffer, size);
1026 				}
1027 			}
1028 
1029 			if (!success)
1030 				fLink.StartMessage(B_ERROR);
1031 
1032 			fLink.Flush();
1033 			break;
1034 		}
1035 
1036 		case AS_REDRAW:
1037 			// Nothing to do here - the redraws are actually handled by looking
1038 			// at the fRedrawRequested member variable in _MessageLooper().
1039 			break;
1040 
1041 		case AS_SYNC:
1042 			// the synchronisation works by the fact that the client
1043 			// window is waiting for this reply, after having received it,
1044 			// client and server queues are in sync (earlier, the client
1045 			// may have pushed drawing commands at the server and now it
1046 			// knows they have all been carried out)
1047 			fLink.StartMessage(B_OK);
1048 			fLink.Flush();
1049 			break;
1050 
1051 		case AS_BEGIN_UPDATE:
1052 			DTRACE(("ServerWindowo %s: AS_BEGIN_UPDATE\n", Title()));
1053 			fWindowLayer->BeginUpdate(fLink);
1054 			break;
1055 
1056 		case AS_END_UPDATE:
1057 			DTRACE(("ServerWindowo %s: AS_END_UPDATE\n", Title()));
1058 			fWindowLayer->EndUpdate();
1059 			break;
1060 
1061 		case AS_GET_MOUSE:
1062 		{
1063 			DTRACE(("ServerWindow %s: Message AS_GET_MOUSE\n", fTitle));
1064 
1065 //fDesktop->UnlockSingleWindow();
1066 			// Returns
1067 			// 1) BPoint mouse location
1068 			// 2) int32 button state
1069 
1070 			BPoint where;
1071 			int32 buttons;
1072 			fDesktop->GetLastMouseState(&where, &buttons);
1073 //fDesktop->LockSingleWindow();
1074 
1075 			fLink.StartMessage(B_OK);
1076 			fLink.Attach<BPoint>(where);
1077 			fLink.Attach<int32>(buttons);
1078 			fLink.Flush();
1079 			break;
1080 		}
1081 
1082 		// BDirectWindow communication
1083 
1084 		case AS_DIRECT_WINDOW_GET_SYNC_DATA:
1085 		{
1086 			status_t status = _EnableDirectWindowMode();
1087 
1088 			fLink.StartMessage(status);
1089 			if (status == B_OK) {
1090 				struct direct_window_sync_data syncData = {
1091 					fDirectWindowData->area,
1092 					fDirectWindowData->sem,
1093 					fDirectWindowData->sem_ack
1094 				};
1095 
1096 				fLink.Attach(&syncData, sizeof(syncData));
1097 			}
1098 
1099 			fLink.Flush();
1100 			break;
1101 		}
1102 		case AS_DIRECT_WINDOW_SET_FULLSCREEN:
1103 		{
1104 			// TODO: maybe there is more to do than this?
1105 			bool enable;
1106 			link.Read<bool>(&enable);
1107 
1108 			status_t status = B_OK;
1109 			if (!fWindowLayer->IsOffscreenWindow()) {
1110 //fDesktop->UnlockSingleWindow();
1111 				fDesktop->SetWindowFeel(fWindowLayer,
1112 					enable ? kWindowScreenFeel : B_NORMAL_WINDOW_FEEL);
1113 //fDesktop->LockSingleWindow();
1114 			} else
1115 				status = B_BAD_TYPE;
1116 
1117 			fLink.StartMessage(status);
1118 			fLink.Flush();
1119 			break;
1120 		}
1121 
1122 		// View creation and destruction (don't need a valid fCurrentLayer)
1123 
1124 		case AS_SET_CURRENT_LAYER:
1125 		{
1126 			int32 token;
1127 			if (link.Read<int32>(&token) != B_OK)
1128 				break;
1129 
1130 			ViewLayer *current;
1131 			if (App()->ViewTokens().GetToken(token, B_HANDLER_TOKEN,
1132 					(void**)&current) != B_OK
1133 				|| current->Window()->ServerWindow() != this) {
1134 				// ToDo: if this happens, we probably want to kill the app and clean up
1135 				fprintf(stderr, "ServerWindow %s: Message AS_SET_CURRENT_LAYER: layer not found, token %ld\n", fTitle, token);
1136 				current = NULL;
1137 			} else {
1138 				DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token));
1139 				_SetCurrentLayer(current);
1140 			}
1141 			break;
1142 		}
1143 
1144 		case AS_LAYER_CREATE_ROOT:
1145 		{
1146 			STRACE(("ServerWindow %s: Message AS_LAYER_CREATE_ROOT\n", fTitle));
1147 
1148 			// Start receiving top_view data -- pass NULL as the parent view.
1149 			// This should be the *only* place where this happens.
1150 			if (fCurrentLayer != NULL) {
1151 				fprintf(stderr, "ServerWindow %s: Message AS_LAYER_CREATE_ROOT: fCurrentLayer already set!!\n", fTitle);
1152 				break;
1153 			}
1154 
1155 			_SetCurrentLayer(_CreateLayerTree(link, NULL));
1156 			fWindowLayer->SetTopLayer(fCurrentLayer);
1157 			break;
1158 		}
1159 
1160 		case AS_LAYER_CREATE:
1161 		{
1162 			STRACE(("ServerWindow %s: Message AS_LAYER_CREATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
1163 
1164 			ViewLayer* parent = NULL;
1165 			ViewLayer* newLayer = _CreateLayerTree(link, &parent);
1166 			if (parent != NULL && newLayer != NULL)
1167 				parent->AddChild(newLayer);
1168 			else
1169 				fprintf(stderr, "ServerWindow %s: Message AS_LAYER_CREATE: parent or newLayer NULL!!\n", fTitle);
1170 			break;
1171 		}
1172 
1173 		default:
1174 			// TODO: when creating a ViewLayer, check for yet non-existing ViewLayer::InitCheck()
1175 			// and take appropriate actions, then checking for fCurrentLayer->CurrentState()
1176 			// is unnecessary
1177 			if (fCurrentLayer == NULL || fCurrentLayer->CurrentState() == NULL) {
1178 				BString codeName;
1179 				string_for_message_code(code, codeName);
1180 				printf("ServerWindow %s received unexpected code - "
1181 					"message '%s' before top_view attached.\n",
1182 					Title(), codeName.String());
1183 				if (link.NeedsReply()) {
1184 					fLink.StartMessage(B_ERROR);
1185 					fLink.Flush();
1186 				}
1187 				return;
1188 			}
1189 
1190 			_DispatchViewMessage(code, link);
1191 			break;
1192 	}
1193 }
1194 
1195 
1196 /*!
1197 	Dispatches all view messages that need a valid fCurrentLayer.
1198 */
1199 void
1200 ServerWindow::_DispatchViewMessage(int32 code,
1201 	BPrivate::LinkReceiver &link)
1202 {
1203 	if (_DispatchPictureMessage(code, link))
1204 		return;
1205 
1206 	switch (code) {
1207 		case AS_LAYER_SCROLL:
1208 		{
1209 			DTRACE(("ServerWindow %s: Message AS_LAYER_SCROLL: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
1210 			float dh;
1211 			float dv;
1212 
1213 			link.Read<float>(&dh);
1214 			link.Read<float>(&dv);
1215 			fWindowLayer->ScrollViewBy(fCurrentLayer, dh, dv);
1216 			break;
1217 		}
1218 		case AS_LAYER_COPY_BITS:
1219 		{
1220 			BRect src;
1221 			BRect dst;
1222 
1223 			link.Read<BRect>(&src);
1224 			link.Read<BRect>(&dst);
1225 
1226 			BRegion contentRegion;
1227 			// TODO: avoid copy operation maybe?
1228 			fWindowLayer->GetContentRegion(&contentRegion);
1229 			fCurrentLayer->CopyBits(src, dst, contentRegion);
1230 			break;
1231 		}
1232 		case AS_LAYER_DELETE:
1233 		{
1234 			// Received when a view is detached from a window
1235 
1236 			int32 token;
1237 			if (link.Read<int32>(&token) != B_OK)
1238 				break;
1239 
1240 			ViewLayer *view;
1241 			if (App()->ViewTokens().GetToken(token, B_HANDLER_TOKEN,
1242 					(void**)&view) == B_OK
1243 				&& view->Window()->ServerWindow() == this) {
1244 				ViewLayer* parent = view->Parent();
1245 
1246 				STRACE(("ServerWindow %s: AS_LAYER_DELETE view: %p, parent: %p\n",
1247 					fTitle, view, parent));
1248 
1249 				if (parent != NULL) {
1250 					parent->RemoveChild(view);
1251 
1252 					if (view->EventMask() != 0) {
1253 						// TODO: possible deadlock (event dispatcher already
1254 						// locked itself, waits for Desktop write lock, but
1255 						// we have it, now we are trying to lock the event
1256 						// dispatcher -> deadlock)
1257 fDesktop->UnlockSingleWindow();
1258 						fDesktop->EventDispatcher().RemoveListener(
1259 							EventTarget(), token);
1260 fDesktop->LockSingleWindow();
1261 					}
1262 					if (fCurrentLayer == view)
1263 						_SetCurrentLayer(parent);
1264 					delete view;
1265 				} // else we don't delete the root view
1266 			}
1267 			break;
1268 		}
1269 		case AS_LAYER_SET_STATE:
1270 		{
1271 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_STATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
1272 
1273 			fCurrentLayer->CurrentState()->ReadFromLink(link);
1274 			// TODO: When is this used?!?
1275 			fCurrentLayer->RebuildClipping(true);
1276 			_UpdateDrawState(fCurrentLayer);
1277 
1278 			break;
1279 		}
1280 		case AS_LAYER_SET_FONT_STATE:
1281 		{
1282 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_FONT_STATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
1283 			fCurrentLayer->CurrentState()->ReadFontFromLink(link);
1284 			fWindowLayer->GetDrawingEngine()->SetFont(
1285 				fCurrentLayer->CurrentState());
1286 			break;
1287 		}
1288 		case AS_LAYER_GET_STATE:
1289 		{
1290 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_STATE: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
1291 
1292 			fLink.StartMessage(B_OK);
1293 
1294 			// attach state data
1295 			fCurrentLayer->CurrentState()->WriteToLink(fLink.Sender());
1296 			fLink.Flush();
1297 			break;
1298 		}
1299 		case AS_LAYER_SET_EVENT_MASK:
1300 		{
1301 			STRACE(("ServerWindow %s: Message AS_LAYER_SET_EVENT_MASK: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
1302 			uint32 eventMask, options;
1303 
1304 			link.Read<uint32>(&eventMask);
1305 			if (link.Read<uint32>(&options) == B_OK) {
1306 				fCurrentLayer->SetEventMask(eventMask, options);
1307 
1308 fDesktop->UnlockSingleWindow();
1309 				// TODO: possible deadlock!
1310 				if (eventMask != 0 || options != 0) {
1311 					fDesktop->EventDispatcher().AddListener(EventTarget(),
1312 						fCurrentLayer->Token(), eventMask, options);
1313 				} else {
1314 					fDesktop->EventDispatcher().RemoveListener(EventTarget(),
1315 						fCurrentLayer->Token());
1316 				}
1317 fDesktop->LockSingleWindow();
1318 			}
1319 			break;
1320 		}
1321 		case AS_LAYER_SET_MOUSE_EVENT_MASK:
1322 		{
1323 			STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
1324 			uint32 eventMask, options;
1325 
1326 			link.Read<uint32>(&eventMask);
1327 			if (link.Read<uint32>(&options) == B_OK) {
1328 fDesktop->UnlockSingleWindow();
1329 				// TODO: possible deadlock
1330 				if (eventMask != 0 || options != 0) {
1331 					fDesktop->EventDispatcher().AddTemporaryListener(EventTarget(),
1332 						fCurrentLayer->Token(), eventMask, options);
1333 				} else {
1334 					fDesktop->EventDispatcher().RemoveTemporaryListener(EventTarget(),
1335 						fCurrentLayer->Token());
1336 				}
1337 fDesktop->LockSingleWindow();
1338 			}
1339 
1340 			// TODO: support B_LOCK_WINDOW_FOCUS option in Desktop
1341 			break;
1342 		}
1343 		case AS_LAYER_MOVE_TO:
1344 		{
1345 			STRACE(("ServerWindow %s: Message AS_LAYER_MOVE_TO: ViewLayer name: %s\n",
1346 				fTitle, fCurrentLayer->Name()));
1347 
1348 			float x, y;
1349 			link.Read<float>(&x);
1350 			link.Read<float>(&y);
1351 
1352 			float offsetX = x - fCurrentLayer->Frame().left;
1353 			float offsetY = y - fCurrentLayer->Frame().top;
1354 
1355 			BRegion dirty;
1356 			fCurrentLayer->MoveBy(offsetX, offsetY, &dirty);
1357 
1358 			// TODO: think about how to avoid this hack:
1359 			// the parent clipping needs to be updated, it is not
1360 			// done in MoveBy() since it would cause
1361 			// too much computations when children are resized because
1362 			// follow modes
1363 			if (ViewLayer* parent = fCurrentLayer->Parent())
1364 				parent->RebuildClipping(false);
1365 
1366 			fWindowLayer->MarkContentDirty(dirty);
1367 			break;
1368 		}
1369 		case AS_LAYER_RESIZE_TO:
1370 		{
1371 			STRACE(("ServerWindow %s: Message AS_LAYER_RESIZE_TO: ViewLayer name: %s\n",
1372 				fTitle, fCurrentLayer->Name()));
1373 
1374 			float newWidth, newHeight;
1375 			link.Read<float>(&newWidth);
1376 			link.Read<float>(&newHeight);
1377 
1378 			float deltaWidth = newWidth - fCurrentLayer->Frame().Width();
1379 			float deltaHeight = newHeight - fCurrentLayer->Frame().Height();
1380 
1381 			BRegion dirty;
1382 			fCurrentLayer->ResizeBy(deltaWidth, deltaHeight, &dirty);
1383 
1384 			// TODO: see above
1385 			if (ViewLayer* parent = fCurrentLayer->Parent())
1386 				parent->RebuildClipping(false);
1387 
1388 			fWindowLayer->MarkContentDirty(dirty);
1389 			break;
1390 		}
1391 		case AS_LAYER_GET_COORD:
1392 		{
1393 			STRACE(("ServerWindow %s: Message AS_LAYER_GET_COORD: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1394 			fLink.StartMessage(B_OK);
1395 			// our offset in the parent -> will be originX and originY in BView
1396 			BPoint parentOffset = fCurrentLayer->Frame().LeftTop();
1397 			fLink.Attach<BPoint>(parentOffset);
1398 			fLink.Attach<BRect>(fCurrentLayer->Bounds());
1399 			fLink.Flush();
1400 			break;
1401 		}
1402 		case AS_LAYER_SET_ORIGIN:
1403 		{
1404 			STRACE(("ServerWindow %s: Message AS_LAYER_SET_ORIGIN: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1405 
1406 			float x, y;
1407 			link.Read<float>(&x);
1408 			link.Read<float>(&y);
1409 
1410 			fCurrentLayer->SetDrawingOrigin(BPoint(x, y));
1411 			_UpdateDrawState(fCurrentLayer);
1412 			break;
1413 		}
1414 		case AS_LAYER_GET_ORIGIN:
1415 		{
1416 			STRACE(("ServerWindow %s: Message AS_LAYER_GET_ORIGIN: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1417 			fLink.StartMessage(B_OK);
1418 			fLink.Attach<BPoint>(fCurrentLayer->DrawingOrigin());
1419 			fLink.Flush();
1420 			break;
1421 		}
1422 		case AS_LAYER_RESIZE_MODE:
1423 		{
1424 			STRACE(("ServerWindow %s: Message AS_LAYER_RESIZE_MODE: ViewLayer: %s\n",
1425 				Title(), fCurrentLayer->Name()));
1426 
1427 			uint32 resizeMode;
1428 			if (link.Read<uint32>(&resizeMode) == B_OK)
1429 				fCurrentLayer->SetResizeMode(resizeMode);
1430 			break;
1431 		}
1432 		case AS_LAYER_SET_CURSOR:
1433 		{
1434 			DTRACE(("ServerWindow %s: Message AS_LAYER_CURSOR: ViewLayer: %s\n", Title(),
1435 				fCurrentLayer->Name()));
1436 
1437 			int32 token;
1438 			bool sync;
1439 			link.Read<int32>(&token);
1440 			if (link.Read<bool>(&sync) != B_OK)
1441 				break;
1442 
1443 			if (!fDesktop->GetCursorManager().Lock())
1444 				break;
1445 
1446 			ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
1447 			fCurrentLayer->SetCursor(cursor);
1448 
1449 			fDesktop->GetCursorManager().Unlock();
1450 
1451 			if (fWindowLayer->IsFocus()) {
1452 				// The cursor might need to be updated now
1453 				if (fDesktop->ViewUnderMouse(fWindowLayer) == fCurrentLayer->Token())
1454 					fServerApp->SetCurrentCursor(cursor);
1455 			}
1456 			if (sync) {
1457 				// sync the client (it can now delete the cursor)
1458 				fLink.StartMessage(B_OK);
1459 				fLink.Flush();
1460 			}
1461 
1462 			break;
1463 		}
1464 		case AS_LAYER_SET_FLAGS:
1465 		{
1466 			uint32 flags;
1467 			link.Read<uint32>(&flags);
1468 			fCurrentLayer->SetFlags(flags);
1469 			_UpdateDrawState(fCurrentLayer);
1470 
1471 			STRACE(("ServerWindow %s: Message AS_LAYER_SET_FLAGS: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1472 			break;
1473 		}
1474 		case AS_LAYER_HIDE:
1475 		{
1476 			STRACE(("ServerWindow %s: Message AS_LAYER_HIDE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1477 			fCurrentLayer->SetHidden(true);
1478 			break;
1479 		}
1480 		case AS_LAYER_SHOW:
1481 		{
1482 			STRACE(("ServerWindow %s: Message AS_LAYER_SHOW: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1483 			fCurrentLayer->SetHidden(false);
1484 			break;
1485 		}
1486 		case AS_LAYER_SET_LINE_MODE:
1487 		{
1488 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_LINE_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1489 			int8 lineCap, lineJoin;
1490 			float miterLimit;
1491 
1492 			link.Read<int8>(&lineCap);
1493 			link.Read<int8>(&lineJoin);
1494 			link.Read<float>(&miterLimit);
1495 
1496 			fCurrentLayer->CurrentState()->SetLineCapMode((cap_mode)lineCap);
1497 			fCurrentLayer->CurrentState()->SetLineJoinMode((join_mode)lineJoin);
1498 			fCurrentLayer->CurrentState()->SetMiterLimit(miterLimit);
1499 
1500 			fWindowLayer->GetDrawingEngine()->SetStrokeMode((cap_mode)lineCap,
1501 				(join_mode)lineJoin, miterLimit);
1502 //			_UpdateDrawState(fCurrentLayer);
1503 
1504 			break;
1505 		}
1506 		case AS_LAYER_GET_LINE_MODE:
1507 		{
1508 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_LINE_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1509 			fLink.StartMessage(B_OK);
1510 			fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->LineCapMode()));
1511 			fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->LineJoinMode()));
1512 			fLink.Attach<float>(fCurrentLayer->CurrentState()->MiterLimit());
1513 			fLink.Flush();
1514 
1515 			break;
1516 		}
1517 		case AS_LAYER_PUSH_STATE:
1518 		{
1519 			DTRACE(("ServerWindow %s: Message AS_LAYER_PUSH_STATE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1520 
1521 			fCurrentLayer->PushState();
1522 			// TODO: is this necessary?
1523 			_UpdateDrawState(fCurrentLayer);
1524 			break;
1525 		}
1526 		case AS_LAYER_POP_STATE:
1527 		{
1528 			DTRACE(("ServerWindow %s: Message AS_LAYER_POP_STATE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1529 
1530 			fCurrentLayer->PopState();
1531 			_UpdateDrawState(fCurrentLayer);
1532 			break;
1533 		}
1534 		case AS_LAYER_SET_SCALE:
1535 		{
1536 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_SCALE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1537 			float scale;
1538 			link.Read<float>(&scale);
1539 
1540 			fCurrentLayer->SetScale(scale);
1541 			_UpdateDrawState(fCurrentLayer);
1542 			break;
1543 		}
1544 		case AS_LAYER_GET_SCALE:
1545 		{
1546 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_SCALE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1547 
1548 			fLink.StartMessage(B_OK);
1549 			fLink.Attach<float>(fCurrentLayer->CurrentState()->Scale());
1550 			fLink.Flush();
1551 			break;
1552 		}
1553 		case AS_LAYER_SET_PEN_LOC:
1554 		{
1555 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_LOC: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1556 			float x, y;
1557 
1558 			link.Read<float>(&x);
1559 			link.Read<float>(&y);
1560 
1561 			fCurrentLayer->CurrentState()->SetPenLocation(BPoint(x, y));
1562 			break;
1563 		}
1564 		case AS_LAYER_GET_PEN_LOC:
1565 		{
1566 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_PEN_LOC: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1567 			fLink.StartMessage(B_OK);
1568 			fLink.Attach<BPoint>(fCurrentLayer->CurrentState()->PenLocation());
1569 			fLink.Flush();
1570 
1571 			break;
1572 		}
1573 		case AS_LAYER_SET_PEN_SIZE:
1574 		{
1575 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_SIZE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1576 			float penSize;
1577 			link.Read<float>(&penSize);
1578 
1579 			fCurrentLayer->CurrentState()->SetPenSize(penSize);
1580 			fWindowLayer->GetDrawingEngine()->SetPenSize(
1581 				fCurrentLayer->CurrentState()->PenSize());
1582 			break;
1583 		}
1584 		case AS_LAYER_GET_PEN_SIZE:
1585 		{
1586 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_PEN_SIZE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1587 			fLink.StartMessage(B_OK);
1588 			fLink.Attach<float>(
1589 				fCurrentLayer->CurrentState()->UnscaledPenSize());
1590 			fLink.Flush();
1591 
1592 			break;
1593 		}
1594 		case AS_LAYER_SET_VIEW_COLOR:
1595 		{
1596 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_VIEW_COLOR: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1597 			rgb_color c;
1598 
1599 			link.Read(&c, sizeof(rgb_color));
1600 
1601 			fCurrentLayer->SetViewColor(c);
1602 			break;
1603 		}
1604 
1605 		case AS_LAYER_GET_HIGH_COLOR:
1606 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_HIGH_COLOR: ViewLayer: %s\n",
1607 				Title(), fCurrentLayer->Name()));
1608 
1609 			fLink.StartMessage(B_OK);
1610 			fLink.Attach<rgb_color>(fCurrentLayer->CurrentState()->HighColor());
1611 			fLink.Flush();
1612 			break;
1613 
1614 		case AS_LAYER_GET_LOW_COLOR:
1615 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_LOW_COLOR: ViewLayer: %s\n",
1616 				Title(), fCurrentLayer->Name()));
1617 
1618 			fLink.StartMessage(B_OK);
1619 			fLink.Attach<rgb_color>(fCurrentLayer->CurrentState()->LowColor());
1620 			fLink.Flush();
1621 			break;
1622 
1623 		case AS_LAYER_GET_VIEW_COLOR:
1624 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_VIEW_COLOR: ViewLayer: %s\n",
1625 				Title(), fCurrentLayer->Name()));
1626 
1627 			fLink.StartMessage(B_OK);
1628 			fLink.Attach<rgb_color>(fCurrentLayer->ViewColor());
1629 			fLink.Flush();
1630 			break;
1631 
1632 		case AS_LAYER_SET_BLENDING_MODE:
1633 		{
1634 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_BLEND_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1635 			int8 srcAlpha, alphaFunc;
1636 
1637 			link.Read<int8>(&srcAlpha);
1638 			link.Read<int8>(&alphaFunc);
1639 
1640 			fCurrentLayer->CurrentState()->SetBlendingMode((source_alpha)srcAlpha,
1641 				(alpha_function)alphaFunc);
1642 			//_UpdateDrawState(fCurrentLayer);
1643 			fWindowLayer->GetDrawingEngine()->SetBlendingMode((source_alpha)srcAlpha,
1644 				(alpha_function)alphaFunc);
1645 			break;
1646 		}
1647 		case AS_LAYER_GET_BLENDING_MODE:
1648 		{
1649 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_BLEND_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1650 			fLink.StartMessage(B_OK);
1651 			fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->AlphaSrcMode()));
1652 			fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->AlphaFncMode()));
1653 			fLink.Flush();
1654 
1655 			break;
1656 		}
1657 		case AS_LAYER_SET_DRAWING_MODE:
1658 		{
1659 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_DRAW_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1660 			int8 drawingMode;
1661 
1662 			link.Read<int8>(&drawingMode);
1663 
1664 			fCurrentLayer->CurrentState()->SetDrawingMode((drawing_mode)drawingMode);
1665 			//_UpdateDrawState(fCurrentLayer);
1666 			fWindowLayer->GetDrawingEngine()->SetDrawingMode((drawing_mode)drawingMode);
1667 			break;
1668 		}
1669 		case AS_LAYER_GET_DRAWING_MODE:
1670 		{
1671 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_DRAW_MODE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1672 			fLink.StartMessage(B_OK);
1673 			fLink.Attach<int8>((int8)(fCurrentLayer->CurrentState()->GetDrawingMode()));
1674 			fLink.Flush();
1675 
1676 			break;
1677 		}
1678 		case AS_LAYER_SET_VIEW_BITMAP:
1679 		{
1680 			int32 bitmapToken, resizingMode, options;
1681 			BRect srcRect, dstRect;
1682 
1683 			link.Read<int32>(&bitmapToken);
1684 			link.Read<BRect>(&srcRect);
1685 			link.Read<BRect>(&dstRect);
1686 			link.Read<int32>(&resizingMode);
1687 			status_t status = link.Read<int32>(&options);
1688 
1689 			rgb_color colorKey = {0};
1690 
1691 			if (status == B_OK) {
1692 				ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken);
1693 				if (bitmapToken == -1 || bitmap != NULL) {
1694 					bool wasOverlay = fCurrentLayer->ViewBitmap() != NULL
1695 						&& fCurrentLayer->ViewBitmap()->Overlay() != NULL;
1696 
1697 					// TODO: this is a race condition: the bitmap could have been
1698 					//	deleted in the mean time!!
1699 					fCurrentLayer->SetViewBitmap(bitmap, srcRect, dstRect,
1700 						resizingMode, options);
1701 
1702 					// TODO: if we revert the view color overlay handling
1703 					//	in ViewLayer::Draw() to the R5 version, we never
1704 					//	need to invalidate the view for overlays.
1705 
1706 					// invalidate view - but only if this is a non-overlay switch
1707 					if (bitmap == NULL || bitmap->Overlay() == NULL || !wasOverlay) {
1708 						BRegion dirty((BRect)fCurrentLayer->Bounds());
1709 						fWindowLayer->InvalidateView(fCurrentLayer, dirty);
1710 					}
1711 
1712 					if (bitmap != NULL && bitmap->Overlay() != NULL) {
1713 						bitmap->Overlay()->SetFlags(options);
1714 						colorKey = bitmap->Overlay()->Color();
1715 					}
1716 				} else
1717 					status = B_BAD_VALUE;
1718 			}
1719 
1720 			fLink.StartMessage(status);
1721 			if (status == B_OK && (options & AS_REQUEST_COLOR_KEY) != 0) {
1722 				// Attach color key for the overlay bitmap
1723 				fLink.Attach<rgb_color>(colorKey);
1724 			}
1725 
1726 			fLink.Flush();
1727 			break;
1728 		}
1729 		case AS_LAYER_PRINT_ALIASING:
1730 		{
1731 			DTRACE(("ServerWindow %s: Message AS_LAYER_PRINT_ALIASING: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1732 			bool fontAliasing;
1733 			if (link.Read<bool>(&fontAliasing) == B_OK) {
1734 				fCurrentLayer->CurrentState()->SetForceFontAliasing(fontAliasing);
1735 				_UpdateDrawState(fCurrentLayer);
1736 			}
1737 			break;
1738 		}
1739 		case AS_LAYER_CLIP_TO_PICTURE:
1740 		{
1741 			DTRACE(("ServerWindow %s: Message AS_LAYER_CLIP_TO_PICTURE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1742 			// TODO: you are not allowed to use ViewLayer regions here!!!
1743 
1744 			int32 pictureToken;
1745 			BPoint where;
1746 			bool inverse = false;
1747 
1748 			link.Read<int32>(&pictureToken);
1749 			link.Read<BPoint>(&where);
1750 			link.Read<bool>(&inverse);
1751 
1752 			// search for a picture with the specified token.
1753 			ServerPicture *picture = fServerApp->FindPicture(pictureToken);
1754 			// TODO: Increase that picture's reference count.(~ allocate a picture)
1755 			if (picture == NULL)
1756 				break;
1757 
1758 			BRegion region;
1759 			// TODO: I think we also need the BView's token
1760 			// I think PictureToRegion would fit better into the ViewLayer class (?)
1761 			if (PictureToRegion(picture, region, inverse, where) < B_OK)
1762 				break;
1763 
1764 			fCurrentLayer->SetUserClipping(&region);
1765 
1766 // TODO: reenable AS_LAYER_CLIP_TO_PICTURE
1767 #if 0
1768 			if (rootLayer && !(fCurrentLayer->IsHidden()) && !fWindowLayer->InUpdate()) {
1769 				BRegion invalidRegion;
1770 				fCurrentLayer->GetOnScreenRegion(invalidRegion);
1771 
1772 				// TODO: this is broken! a smaller area may be invalidated!
1773 
1774 				fCurrentLayer->fParent->MarkForRebuild(invalidRegion);
1775 				fCurrentLayer->fParent->TriggerRebuild();
1776 				rootLayer->MarkForRedraw(invalidRegion);
1777 				rootLayer->TriggerRedraw();
1778 			}
1779 #endif
1780 			break;
1781 		}
1782 
1783 		case AS_LAYER_GET_CLIP_REGION:
1784 		{
1785 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_CLIP_REGION: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1786 
1787 			// if this ViewLayer is hidden, it is clear that its visible region is void.
1788 			fLink.StartMessage(B_OK);
1789 			if (fCurrentLayer->IsHidden()) {
1790 				BRegion empty;
1791 				fLink.AttachRegion(empty);
1792 			} else {
1793 				BRegion drawingRegion = fCurrentLayer->LocalClipping();
1794 				fLink.AttachRegion(drawingRegion);
1795 			}
1796 			fLink.Flush();
1797 
1798 			break;
1799 		}
1800 		case AS_LAYER_SET_CLIP_REGION:
1801 		{
1802 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1803 
1804 			int32 rectCount;
1805 			status_t status = link.Read<int32>(&rectCount);
1806 				// a negative count means no
1807 				// region for the current draw state,
1808 				// but an *empty* region is actually valid!
1809 				// even if it means no drawing is allowed
1810 
1811 			if (status < B_OK)
1812 				break;
1813 
1814 			if (rectCount >= 0) {
1815 				// we are supposed to set the clipping region
1816 				BRegion region;
1817 				if (rectCount > 0 && link.ReadRegion(&region) < B_OK)
1818 					break;
1819 				fCurrentLayer->SetUserClipping(&region);
1820 			} else {
1821 				// we are supposed to unset the clipping region
1822 				// passing NULL sets this states region to that
1823 				// of the previous state
1824 				fCurrentLayer->SetUserClipping(NULL);
1825 			}
1826 
1827 			break;
1828 		}
1829 
1830 		case AS_LAYER_INVALIDATE_RECT:
1831 		{
1832 			DTRACE(("ServerWindow %s: Message AS_LAYER_INVALIDATE_RECT: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1833 
1834 			// NOTE: looks like this call is NOT affected by origin and scale on R5
1835 			// so this implementation is "correct"
1836 			BRect invalidRect;
1837 			if (link.Read<BRect>(&invalidRect) == B_OK) {
1838 				BRegion dirty(invalidRect);
1839 				fWindowLayer->InvalidateView(fCurrentLayer, dirty);
1840 			}
1841 			break;
1842 		}
1843 		case AS_LAYER_INVALIDATE_REGION:
1844 		{
1845 			DTRACE(("ServerWindow %s: Message AS_LAYER_INVALIDATE_RECT: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1846 
1847 			// NOTE: looks like this call is NOT affected by origin and scale on R5
1848 			// so this implementation is "correct"
1849 			BRegion region;
1850 			if (link.ReadRegion(&region) < B_OK)
1851 				break;
1852 
1853 			fWindowLayer->InvalidateView(fCurrentLayer, region);
1854 			break;
1855 		}
1856 
1857 		case AS_LAYER_SET_HIGH_COLOR:
1858 		{
1859 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_HIGH_COLOR: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1860 
1861 			rgb_color c;
1862 			link.Read(&c, sizeof(rgb_color));
1863 
1864 			fCurrentLayer->CurrentState()->SetHighColor(c);
1865 			fWindowLayer->GetDrawingEngine()->SetHighColor(c);
1866 			break;
1867 		}
1868 		case AS_LAYER_SET_LOW_COLOR:
1869 		{
1870 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_LOW_COLOR: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
1871 
1872 			rgb_color c;
1873 			link.Read(&c, sizeof(rgb_color));
1874 
1875 			fCurrentLayer->CurrentState()->SetLowColor(c);
1876 			fWindowLayer->GetDrawingEngine()->SetLowColor(c);
1877 			break;
1878 		}
1879 		case AS_LAYER_SET_PATTERN:
1880 		{
1881 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PATTERN: ViewLayer: %s\n", fTitle, fCurrentLayer->Name()));
1882 
1883 			pattern pat;
1884 			link.Read(&pat, sizeof(pattern));
1885 
1886 			fCurrentLayer->CurrentState()->SetPattern(Pattern(pat));
1887 			fWindowLayer->GetDrawingEngine()->SetPattern(pat);
1888 			break;
1889 		}
1890 		case AS_LAYER_DRAG_IMAGE:
1891 		{
1892 			// TODO: flesh out AS_LAYER_DRAG_IMAGE
1893 			STRACE(("ServerWindow %s: Message AS_DRAG_IMAGE\n", Title()));
1894 
1895 			int32 bitmapToken;
1896 			drawing_mode dragMode;
1897 			BPoint offset;
1898 			int32 bufferSize;
1899 
1900 			link.Read<int32>(&bitmapToken);
1901 			link.Read<int32>((int32*)&dragMode);
1902 			link.Read<BPoint>(&offset);
1903 			link.Read<int32>(&bufferSize);
1904 
1905 			if (bufferSize > 0) {
1906 				char* buffer = new (nothrow) char[bufferSize];
1907 				BMessage dragMessage;
1908 				if (link.Read(buffer, bufferSize) == B_OK
1909 					&& dragMessage.Unflatten(buffer) == B_OK) {
1910 						ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken);
1911 						// TODO: possible deadlock
1912 fDesktop->UnlockSingleWindow();
1913 						fDesktop->EventDispatcher().SetDragMessage(dragMessage,
1914 							bitmap, offset);
1915 fDesktop->LockSingleWindow();
1916 				}
1917 				delete[] buffer;
1918 			}
1919 			// sync the client (it can now delete the bitmap)
1920 			fLink.StartMessage(B_OK);
1921 			fLink.Flush();
1922 
1923 			break;
1924 		}
1925 		case AS_LAYER_DRAG_RECT:
1926 		{
1927 			// TODO: flesh out AS_LAYER_DRAG_RECT
1928 			STRACE(("ServerWindow %s: Message AS_DRAG_RECT\n", Title()));
1929 
1930 			BRect dragRect;
1931 			BPoint offset;
1932 			int32 bufferSize;
1933 
1934 			link.Read<BRect>(&dragRect);
1935 			link.Read<BPoint>(&offset);
1936 			link.Read<int32>(&bufferSize);
1937 
1938 			if (bufferSize > 0) {
1939 				char* buffer = new (nothrow) char[bufferSize];
1940 				BMessage dragMessage;
1941 				if (link.Read(buffer, bufferSize) == B_OK
1942 					&& dragMessage.Unflatten(buffer) == B_OK) {
1943 						// TODO: possible deadlock
1944 fDesktop->UnlockSingleWindow();
1945 						fDesktop->EventDispatcher().SetDragMessage(dragMessage,
1946 							NULL /* should be dragRect */, offset);
1947 fDesktop->LockSingleWindow();
1948 				}
1949 				delete[] buffer;
1950 			}
1951 
1952 			break;
1953 		}
1954 
1955 		case AS_LAYER_BEGIN_RECT_TRACK:
1956 		{
1957 			DTRACE(("ServerWindow %s: Message AS_LAYER_BEGIN_RECT_TRACK\n", Title()));
1958 			BRect dragRect;
1959 			uint32 style;
1960 
1961 			link.Read<BRect>(&dragRect);
1962 			link.Read<uint32>(&style);
1963 
1964 			// TODO: implement rect tracking (used sometimes for selecting
1965 			// a group of things, also sometimes used to appear to drag something,
1966 			// but without real drag message)
1967 			break;
1968 		}
1969 		case AS_LAYER_END_RECT_TRACK:
1970 		{
1971 			DTRACE(("ServerWindow %s: Message AS_LAYER_END_RECT_TRACK\n", Title()));
1972 			// TODO: implement rect tracking
1973 			break;
1974 		}
1975 
1976 		case AS_LAYER_BEGIN_PICTURE:
1977 		{
1978 			DTRACE(("ServerWindow %s: Message AS_LAYER_BEGIN_PICTURE\n", Title()));
1979 			ServerPicture *picture = App()->CreatePicture();
1980 			picture->SyncState(fCurrentLayer);
1981 			fCurrentLayer->SetPicture(picture);
1982 			break;
1983 		}
1984 
1985 		case AS_LAYER_APPEND_TO_PICTURE:
1986 		{
1987 			DTRACE(("ServerWindow %s: Message AS_LAYER_APPEND_TO_PICTURE\n", Title()));
1988 
1989 			int32 pictureToken;
1990 			link.Read<int32>(&pictureToken);
1991 			ServerPicture *picture = App()->FindPicture(pictureToken);
1992 			if (picture)
1993 				picture->SyncState(fCurrentLayer);
1994 			fCurrentLayer->SetPicture(picture);
1995 				// we don't care if it's NULL
1996 			break;
1997 		}
1998 
1999 		case AS_LAYER_END_PICTURE:
2000 		{
2001 			DTRACE(("ServerWindow %s: Message AS_LAYER_END_PICTURE\n", Title()));
2002 
2003 			ServerPicture *picture = fCurrentLayer->Picture();
2004 			if (picture != NULL) {
2005 				fCurrentLayer->SetPicture(NULL);
2006 				fLink.StartMessage(B_OK);
2007 				fLink.Attach<int32>(picture->Token());
2008 			} else
2009 				fLink.StartMessage(B_ERROR);
2010 
2011 			fLink.Flush();
2012 			break;
2013 		}
2014 
2015 		default:
2016 			_DispatchViewDrawingMessage(code, link);
2017 			break;
2018 	}
2019 }
2020 
2021 
2022 /*!
2023 	Dispatches all view drawing messages.
2024 	The desktop clipping must be read locked when entering this method.
2025 	Requires a valid fCurrentLayer.
2026 */
2027 void
2028 ServerWindow::_DispatchViewDrawingMessage(int32 code, BPrivate::LinkReceiver &link)
2029 {
2030 	if (!fCurrentLayer->IsVisible() || !fWindowLayer->IsVisible()) {
2031 		if (link.NeedsReply()) {
2032 			printf("ServerWindow::DispatchViewDrawingMessage() got message %ld that needs a reply!\n", code);
2033 			// the client is now blocking and waiting for a reply!
2034 			fLink.StartMessage(B_ERROR);
2035 			fLink.Flush();
2036 		}
2037 		return;
2038 	}
2039 
2040 	DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine();
2041 	if (!drawingEngine) {
2042 		// ?!?
2043 		DTRACE(("ServerWindow %s: no drawing engine!!\n", Title()));
2044 		if (link.NeedsReply()) {
2045 			// the client is now blocking and waiting for a reply!
2046 			fLink.StartMessage(B_ERROR);
2047 			fLink.Flush();
2048 		}
2049 		return;
2050 	}
2051 
2052 	if (!fCurrentDrawingRegionValid || fWindowLayer->DrawingRegionChanged(fCurrentLayer)) {
2053 		fWindowLayer->GetEffectiveDrawingRegion(fCurrentLayer, fCurrentDrawingRegion);
2054 		fCurrentDrawingRegionValid = true;
2055 	}
2056 
2057 	if (fCurrentDrawingRegion.CountRects() <= 0) {
2058 		if (link.NeedsReply()) {
2059 			// the client is now blocking and waiting for a reply!
2060 			fLink.StartMessage(B_ERROR);
2061 			fLink.Flush();
2062 		}
2063 		return;
2064 	}
2065 
2066 	drawingEngine->LockParallelAccess();
2067 	// NOTE: the region is not copied, Painter keeps a pointer,
2068 	// that's why you need to use the clipping only for as long
2069 	// as you have it locked
2070 	drawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion);
2071 
2072 	switch (code) {
2073 		case AS_STROKE_LINE:
2074 		{
2075 			DTRACE(("ServerWindow %s: Message AS_STROKE_LINE\n", Title()));
2076 
2077 			float x1, y1, x2, y2;
2078 
2079 			link.Read<float>(&x1);
2080 			link.Read<float>(&y1);
2081 			link.Read<float>(&x2);
2082 			link.Read<float>(&y2);
2083 
2084 			BPoint p1(x1, y1);
2085 			BPoint p2(x2, y2);
2086 			BPoint penPos = p2;
2087 			fCurrentLayer->ConvertToScreenForDrawing(&p1);
2088 			fCurrentLayer->ConvertToScreenForDrawing(&p2);
2089 			drawingEngine->StrokeLine(p1, p2);
2090 
2091 			// We update the pen here because many DrawingEngine calls which do not update the
2092 			// pen position actually call StrokeLine
2093 
2094 			// TODO: Decide where to put this, for example, it cannot be done
2095 			// for DrawString(), also there needs to be a decision, if penlocation
2096 			// is in View coordinates (I think it should be) or in screen coordinates.
2097 			fCurrentLayer->CurrentState()->SetPenLocation(penPos);
2098 			break;
2099 		}
2100 		case AS_LAYER_INVERT_RECT:
2101 		{
2102 			DTRACE(("ServerWindow %s: Message AS_INVERT_RECT\n", Title()));
2103 
2104 			BRect rect;
2105 			link.Read<BRect>(&rect);
2106 
2107 			fCurrentLayer->ConvertToScreenForDrawing(&rect);
2108 			drawingEngine->InvertRect(rect);
2109 			break;
2110 		}
2111 		case AS_STROKE_RECT:
2112 		{
2113 			DTRACE(("ServerWindow %s: Message AS_STROKE_RECT\n", Title()));
2114 
2115 			BRect rect;
2116 			link.Read<BRect>(&rect);
2117 
2118 			fCurrentLayer->ConvertToScreenForDrawing(&rect);
2119 			drawingEngine->StrokeRect(rect);
2120 			break;
2121 		}
2122 		case AS_FILL_RECT:
2123 		{
2124 			DTRACE(("ServerWindow %s: Message AS_FILL_RECT\n", Title()));
2125 
2126 			BRect rect;
2127 			link.Read<BRect>(&rect);
2128 
2129 			fCurrentLayer->ConvertToScreenForDrawing(&rect);
2130 			drawingEngine->FillRect(rect);
2131 			break;
2132 		}
2133 		case AS_LAYER_DRAW_BITMAP:
2134 		{
2135 			DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP: ViewLayer name: %s\n", fTitle, fCurrentLayer->Name()));
2136 			int32 bitmapToken;
2137 			BRect srcRect, dstRect;
2138 
2139 			link.Read<int32>(&bitmapToken);
2140 			link.Read<BRect>(&dstRect);
2141 			link.Read<BRect>(&srcRect);
2142 
2143 			ServerBitmap* bitmap = fServerApp->FindBitmap(bitmapToken);
2144 			if (bitmap) {
2145 				fCurrentLayer->ConvertToScreenForDrawing(&dstRect);
2146 
2147 				drawingEngine->DrawBitmap(bitmap, srcRect, dstRect);
2148 			}
2149 
2150 			break;
2151 		}
2152 		case AS_STROKE_ARC:
2153 		case AS_FILL_ARC:
2154 		{
2155 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ARC\n", Title()));
2156 
2157 			float angle, span;
2158 			BRect r;
2159 
2160 			link.Read<BRect>(&r);
2161 			link.Read<float>(&angle);
2162 			link.Read<float>(&span);
2163 
2164 			fCurrentLayer->ConvertToScreenForDrawing(&r);
2165 			drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC);
2166 			break;
2167 		}
2168 		case AS_STROKE_BEZIER:
2169 		case AS_FILL_BEZIER:
2170 		{
2171 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n", Title()));
2172 
2173 			BPoint pts[4];
2174 			for (int32 i = 0; i < 4; i++) {
2175 				link.Read<BPoint>(&(pts[i]));
2176 				fCurrentLayer->ConvertToScreenForDrawing(&pts[i]);
2177 			}
2178 
2179 			drawingEngine->DrawBezier(pts, code == AS_FILL_BEZIER);
2180 			break;
2181 		}
2182 		case AS_STROKE_ELLIPSE:
2183 		case AS_FILL_ELLIPSE:
2184 		{
2185 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ELLIPSE\n", Title()));
2186 
2187 			BRect rect;
2188 			link.Read<BRect>(&rect);
2189 
2190 			fCurrentLayer->ConvertToScreenForDrawing(&rect);
2191 			drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE);
2192 			break;
2193 		}
2194 		case AS_STROKE_ROUNDRECT:
2195 		case AS_FILL_ROUNDRECT:
2196 		{
2197 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ROUNDRECT\n", Title()));
2198 
2199 			BRect rect;
2200 			float xrad,yrad;
2201 			link.Read<BRect>(&rect);
2202 			link.Read<float>(&xrad);
2203 			link.Read<float>(&yrad);
2204 
2205 			fCurrentLayer->ConvertToScreenForDrawing(&rect);
2206 			drawingEngine->DrawRoundRect(rect, xrad, yrad, code == AS_FILL_ROUNDRECT);
2207 			break;
2208 		}
2209 		case AS_STROKE_TRIANGLE:
2210 		case AS_FILL_TRIANGLE:
2211 		{
2212 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n", Title()));
2213 
2214  			BPoint pts[3];
2215 			BRect rect;
2216 
2217  			for (int32 i = 0; i < 3; i++) {
2218 				link.Read<BPoint>(&(pts[i]));
2219 				fCurrentLayer->ConvertToScreenForDrawing(&pts[i]);
2220  			}
2221 
2222 			link.Read<BRect>(&rect);
2223 
2224 			fCurrentLayer->ConvertToScreenForDrawing(&rect);
2225 			drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE);
2226 			break;
2227 		}
2228 		case AS_STROKE_POLYGON:
2229 		case AS_FILL_POLYGON:
2230 		{
2231 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_POLYGON\n", Title()));
2232 
2233 			BRect polyFrame;
2234 			bool isClosed = true;
2235 			int32 pointCount;
2236 
2237 			link.Read<BRect>(&polyFrame);
2238 			if (code == AS_STROKE_POLYGON)
2239 				link.Read<bool>(&isClosed);
2240 			link.Read<int32>(&pointCount);
2241 
2242 			BPoint* pointList = new(nothrow) BPoint[pointCount];
2243 			if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
2244 				for (int32 i = 0; i < pointCount; i++)
2245 					fCurrentLayer->ConvertToScreenForDrawing(&pointList[i]);
2246 				fCurrentLayer->ConvertToScreenForDrawing(&polyFrame);
2247 
2248 				drawingEngine->DrawPolygon(pointList, pointCount, polyFrame,
2249 					code == AS_FILL_POLYGON, isClosed && pointCount > 2);
2250 			}
2251 			delete[] pointList;
2252 			break;
2253 		}
2254 		case AS_STROKE_SHAPE:
2255 		case AS_FILL_SHAPE:
2256 		{
2257 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_SHAPE\n", Title()));
2258 
2259 			BRect shapeFrame;
2260 			int32 opCount;
2261 			int32 ptCount;
2262 
2263 			link.Read<BRect>(&shapeFrame);
2264 			link.Read<int32>(&opCount);
2265 			link.Read<int32>(&ptCount);
2266 
2267 			uint32* opList = new(nothrow) uint32[opCount];
2268 			BPoint* ptList = new(nothrow) BPoint[ptCount];
2269 			if (link.Read(opList, opCount * sizeof(uint32)) >= B_OK &&
2270 				link.Read(ptList, ptCount * sizeof(BPoint)) >= B_OK) {
2271 
2272 				// this might seem a bit weird, but under R5, the shapes
2273 				// are always offset by the current pen location
2274 				BPoint penLocation = fCurrentLayer->CurrentState()->PenLocation();
2275 				for (int32 i = 0; i < ptCount; i++) {
2276 					ptList[i] += penLocation;
2277 					fCurrentLayer->ConvertToScreenForDrawing(&ptList[i]);
2278 				}
2279 
2280 				drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount, ptList,
2281 					code == AS_FILL_SHAPE);
2282 			}
2283 
2284 			delete[] opList;
2285 			delete[] ptList;
2286 			break;
2287 		}
2288 		case AS_FILL_REGION:
2289 		{
2290 			DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title()));
2291 
2292 			BRegion region;
2293 			if (link.ReadRegion(&region) < B_OK)
2294 				break;
2295 
2296 			fCurrentLayer->ConvertToScreenForDrawing(&region);
2297 			drawingEngine->FillRegion(region);
2298 
2299 			break;
2300 		}
2301 		case AS_STROKE_LINEARRAY:
2302 		{
2303 			DTRACE(("ServerWindow %s: Message AS_STROKE_LINEARRAY\n", Title()));
2304 
2305 			// Attached Data:
2306 			// 1) int32 Number of lines in the array
2307 			// 2) LineArrayData
2308 
2309 			int32 lineCount;
2310 
2311 			link.Read<int32>(&lineCount);
2312 			if (lineCount > 0) {
2313 				LineArrayData lineData[lineCount];
2314 
2315 				for (int32 i = 0; i < lineCount; i++) {
2316 					LineArrayData* index = &lineData[i];
2317 
2318 					link.Read<float>(&(index->pt1.x));
2319 					link.Read<float>(&(index->pt1.y));
2320 					link.Read<float>(&(index->pt2.x));
2321 					link.Read<float>(&(index->pt2.y));
2322 					link.Read<rgb_color>(&(index->color));
2323 
2324 					fCurrentLayer->ConvertToScreenForDrawing(&index->pt1);
2325 					fCurrentLayer->ConvertToScreenForDrawing(&index->pt2);
2326 				}
2327 				drawingEngine->StrokeLineArray(lineCount, lineData);
2328 			}
2329 			break;
2330 		}
2331 		case AS_DRAW_STRING:
2332 		case AS_DRAW_STRING_WITH_DELTA:
2333 		{
2334 			DTRACE(("ServerWindow %s: Message AS_DRAW_STRING\n", Title()));
2335 			char* string;
2336 			int32 length;
2337 			BPoint location;
2338 			escapement_delta _delta;
2339 			escapement_delta* delta = NULL;
2340 
2341 			link.Read<int32>(&length);
2342 			link.Read<BPoint>(&location);
2343 			if (code == AS_DRAW_STRING_WITH_DELTA) {
2344 				link.Read<escapement_delta>(&_delta);
2345 				if (_delta.nonspace != 0.0 || _delta.space != 0.0)
2346 					delta = &_delta;
2347 			}
2348 			link.ReadString(&string);
2349 
2350 
2351 			fCurrentLayer->ConvertToScreenForDrawing(&location);
2352 			BPoint penLocation = drawingEngine->DrawString(string, length,
2353 				location, delta);
2354 
2355 			fCurrentLayer->ConvertFromScreenForDrawing(&penLocation);
2356 			fCurrentLayer->CurrentState()->SetPenLocation(penLocation);
2357 
2358 			free(string);
2359 			break;
2360 		}
2361 
2362 		case AS_LAYER_DRAW_PICTURE:
2363 		{
2364 			int32 token;
2365 			if (link.Read<int32>(&token) == B_OK) {
2366 				BPoint where;
2367 				link.Read<BPoint>(&where);
2368 
2369 				ServerPicture *picture = App()->FindPicture(token);
2370 				if (picture != NULL) {
2371 					fCurrentLayer->CurrentState()->SetOrigin(where);
2372 					picture->Play(fCurrentLayer);
2373 				}
2374 			}
2375 			break;
2376 		}
2377 
2378 		default:
2379 			BString codeString;
2380 			string_for_message_code(code, codeString);
2381 			printf("ServerWindow %s received unexpected code: %s\n",
2382 				Title(), codeString.String());
2383 
2384 			if (link.NeedsReply()) {
2385 				// the client is now blocking and waiting for a reply!
2386 				fLink.StartMessage(B_ERROR);
2387 				fLink.Flush();
2388 			}
2389 			break;
2390 	}
2391 
2392 	drawingEngine->UnlockParallelAccess();
2393 }
2394 
2395 
2396 bool
2397 ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver &link)
2398 {
2399 	ServerPicture *picture = fCurrentLayer->Picture();
2400 	if (picture == NULL)
2401 		return false;
2402 
2403 	switch (code) {
2404 		case AS_LAYER_SET_ORIGIN:
2405 		{
2406 			float x, y;
2407 			link.Read<float>(&x);
2408 			link.Read<float>(&y);
2409 
2410 			picture->WriteSetOrigin(BPoint(x, y));
2411 			break;
2412 		}
2413 
2414 		case AS_LAYER_INVERT_RECT:
2415 		{
2416 			BRect rect;
2417 			link.Read<BRect>(&rect);
2418 			picture->WriteInvertRect(rect);
2419 
2420 			break;
2421 		}
2422 
2423 		case AS_LAYER_PUSH_STATE:
2424 		{
2425 			picture->WritePushState();
2426 			break;
2427 		}
2428 
2429 		case AS_LAYER_POP_STATE:
2430 		{
2431 			picture->WritePopState();
2432 			break;
2433 		}
2434 
2435 		case AS_LAYER_SET_DRAWING_MODE:
2436 		{
2437 			int8 drawingMode;
2438 			link.Read<int8>(&drawingMode);
2439 
2440 			picture->WriteSetDrawingMode((drawing_mode)drawingMode);
2441 			break;
2442 		}
2443 
2444 		case AS_LAYER_SET_PEN_LOC:
2445 		{
2446 			float x, y;
2447 			link.Read<float>(&x);
2448 			link.Read<float>(&y);
2449 			picture->WriteSetPenLocation(BPoint(x, y));
2450 			break;
2451 		}
2452 		case AS_LAYER_SET_PEN_SIZE:
2453 		{
2454 			float penSize;
2455 			link.Read<float>(&penSize);
2456 			picture->WriteSetPenSize(penSize);
2457 			break;
2458 		}
2459 
2460 		case AS_LAYER_SET_LINE_MODE:
2461 		{
2462 			int8 lineCap, lineJoin;
2463 			float miterLimit;
2464 
2465 			link.Read<int8>(&lineCap);
2466 			link.Read<int8>(&lineJoin);
2467 			link.Read<float>(&miterLimit);
2468 
2469 			picture->WriteSetLineMode((cap_mode)lineCap, (join_mode)lineJoin, miterLimit);
2470 
2471 			break;
2472 		}
2473 		case AS_LAYER_SET_SCALE:
2474 		{
2475 			float scale;
2476 			link.Read<float>(&scale);
2477 			picture->WriteSetScale(scale);
2478 			break;
2479 		}
2480 
2481 		case AS_LAYER_SET_PATTERN:
2482 		{
2483 			pattern pat;
2484 			link.Read(&pat, sizeof(pattern));
2485 			picture->WriteSetPattern(pat);
2486 			break;
2487 		}
2488 
2489 		case AS_LAYER_SET_FONT_STATE:
2490 		{
2491 			picture->SetFontFromLink(link);
2492 			break;
2493 		}
2494 
2495 		case AS_FILL_RECT:
2496 		case AS_STROKE_RECT:
2497 		{
2498 			BRect rect;
2499 			link.Read<BRect>(&rect);
2500 
2501 			picture->WriteDrawRect(rect, code == AS_FILL_RECT);
2502 			break;
2503 		}
2504 
2505 		case AS_FILL_REGION:
2506 		{
2507 			// There is no B_PIC_FILL_REGION op, we have to
2508 			// implement it using B_PIC_FILL_RECT
2509 			BRegion region;
2510 			if (link.ReadRegion(&region) < B_OK)
2511 				break;
2512 			for (int32 i = 0; i < region.CountRects(); i++)
2513 				picture->WriteDrawRect(region.RectAt(i), true);
2514 			break;
2515 		}
2516 
2517 		case AS_STROKE_ROUNDRECT:
2518 		case AS_FILL_ROUNDRECT:
2519 		{
2520 			BRect rect;
2521 			link.Read<BRect>(&rect);
2522 
2523 			BPoint radii;
2524 			link.Read<float>(&radii.x);
2525 			link.Read<float>(&radii.y);
2526 
2527 			picture->WriteDrawRoundRect(rect, radii, code == AS_FILL_ROUNDRECT);
2528 			break;
2529 		}
2530 
2531 		case AS_STROKE_ELLIPSE:
2532 		case AS_FILL_ELLIPSE:
2533 		{
2534 			BRect rect;
2535 			link.Read<BRect>(&rect);
2536 			picture->WriteDrawEllipse(rect, code == AS_FILL_ELLIPSE);
2537 			break;
2538 		}
2539 
2540 		case AS_STROKE_ARC:
2541 		case AS_FILL_ARC:
2542 		{
2543 			BRect rect;
2544 			link.Read<BRect>(&rect);
2545 			float startTheta, arcTheta;
2546 			link.Read<float>(&startTheta);
2547 			link.Read<float>(&arcTheta);
2548 
2549 			BPoint radii((rect.Width() + 1) / 2, (rect.Height() + 1) / 2);
2550 			BPoint center = rect.LeftTop() + radii;
2551 
2552 			picture->WriteDrawArc(center, radii, startTheta, arcTheta, code == AS_FILL_ARC);
2553 			break;
2554 		}
2555 
2556 		case AS_STROKE_TRIANGLE:
2557 		case AS_FILL_TRIANGLE:
2558 		{
2559 			// There is no B_PIC_FILL/STROKE_TRIANGLE op,
2560 			// we implement it using B_PIC_FILL/STROKE_POLYGON
2561 			BPoint points[3];
2562 
2563 			for (int32 i = 0; i < 3; i++) {
2564 				link.Read<BPoint>(&(points[i]));
2565 			}
2566 
2567 			BRect rect;
2568 			link.Read<BRect>(&rect);
2569 
2570 			picture->WriteDrawPolygon(3, points,
2571 					true, code == AS_FILL_TRIANGLE);
2572 			break;
2573 		}
2574 		case AS_STROKE_POLYGON:
2575 		case AS_FILL_POLYGON:
2576 		{
2577 			BRect polyFrame;
2578 			bool isClosed = true;
2579 			int32 pointCount;
2580 			const bool fill = (code == AS_FILL_POLYGON);
2581 
2582 			link.Read<BRect>(&polyFrame);
2583 			if (code == AS_STROKE_POLYGON)
2584 				link.Read<bool>(&isClosed);
2585 			link.Read<int32>(&pointCount);
2586 
2587 			BPoint* pointList = new(nothrow) BPoint[pointCount];
2588 			if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
2589 				picture->WriteDrawPolygon(pointCount, pointList,
2590 					isClosed && pointCount > 2, fill);
2591 			}
2592 			delete[] pointList;
2593 			break;
2594 		}
2595 
2596 		case AS_STROKE_BEZIER:
2597 		case AS_FILL_BEZIER:
2598 		{
2599 			BPoint points[4];
2600 			for (int32 i = 0; i < 4; i++) {
2601 				link.Read<BPoint>(&(points[i]));
2602 			}
2603 			picture->WriteDrawBezier(points, code == AS_FILL_BEZIER);
2604 			break;
2605 		}
2606 
2607 		case AS_STROKE_LINE:
2608 		{
2609 			float x1, y1, x2, y2;
2610 
2611 			link.Read<float>(&x1);
2612 			link.Read<float>(&y1);
2613 			link.Read<float>(&x2);
2614 			link.Read<float>(&y2);
2615 
2616 			picture->WriteStrokeLine(BPoint(x1, y1), BPoint(x2, y2));
2617 			break;
2618 		}
2619 
2620 		case AS_STROKE_LINEARRAY:
2621 		{
2622 			int32 lineCount;
2623 			link.Read<int32>(&lineCount);
2624 			if (lineCount <= 0)
2625 				break;
2626 
2627 			picture->WritePushState();
2628 
2629 			for (int32 i = 0; i < lineCount; i++) {
2630 				float x1, y1, x2, y2;
2631 				link.Read<float>(&x1);
2632 				link.Read<float>(&y1);
2633 				link.Read<float>(&x2);
2634 				link.Read<float>(&y2);
2635 
2636 				rgb_color color;
2637 				link.Read<rgb_color>(&color);
2638 
2639 				picture->WriteSetHighColor(color);
2640 				picture->WriteStrokeLine(BPoint(x1, y1), BPoint(x2, y2));
2641 			}
2642 
2643 			picture->WritePopState();
2644 			break;
2645 		}
2646 
2647 		case AS_LAYER_SET_LOW_COLOR:
2648 		case AS_LAYER_SET_HIGH_COLOR:
2649 		{
2650 			rgb_color color;
2651 			link.Read(&color, sizeof(rgb_color));
2652 
2653 			if (code == AS_LAYER_SET_HIGH_COLOR)
2654 				picture->WriteSetHighColor(color);
2655 			else
2656 				picture->WriteSetLowColor(color);
2657 			break;
2658 		}
2659 
2660 		case AS_DRAW_STRING:
2661 		case AS_DRAW_STRING_WITH_DELTA:
2662 		{
2663 			char* string = NULL;
2664 			int32 length;
2665 			BPoint location;
2666 
2667 			link.Read<int32>(&length);
2668 			link.Read<BPoint>(&location);
2669 			escapement_delta delta = { 0, 0 };
2670 			if (code == AS_DRAW_STRING_WITH_DELTA)
2671 				link.Read<escapement_delta>(&delta);
2672 			link.ReadString(&string);
2673 
2674 			picture->WriteDrawString(location, string, length, delta);
2675 
2676 			free(string);
2677 			break;
2678 		}
2679 
2680 		case AS_STROKE_SHAPE:
2681 		case AS_FILL_SHAPE:
2682 		{
2683 			BRect shapeFrame;
2684 			int32 opCount;
2685 			int32 ptCount;
2686 
2687 			link.Read<BRect>(&shapeFrame);
2688 			link.Read<int32>(&opCount);
2689 			link.Read<int32>(&ptCount);
2690 
2691 			uint32 *opList = new(nothrow) uint32[opCount];
2692 			BPoint *ptList = new(nothrow) BPoint[ptCount];
2693 			if (opList != NULL && ptList != NULL
2694 				&& link.Read(opList, opCount * sizeof(uint32)) >= B_OK
2695 				&& link.Read(ptList, ptCount * sizeof(BPoint)) >= B_OK) {
2696 
2697 				// This might seem a bit weird, but under R5, the shapes
2698 				// are always offset by the current pen location
2699 				BPoint penLocation = fCurrentLayer->CurrentState()->PenLocation();
2700 				for (int32 i = 0; i < ptCount; i++) {
2701 					ptList[i] += penLocation;
2702 				}
2703 				const bool fill = (code == AS_FILL_SHAPE);
2704 				picture->WriteDrawShape(opCount, opList, ptCount, ptList, fill);
2705 			}
2706 			delete[] opList;
2707 			delete[] ptList;
2708 
2709 			break;
2710 		}
2711 
2712 		case AS_LAYER_DRAW_BITMAP:
2713 		{
2714 			int32 token;
2715 			link.Read<int32>(&token);
2716 
2717 			BRect destRect;
2718 			link.Read<BRect>(&destRect);
2719 
2720 			BRect sourceRect;
2721 			link.Read<BRect>(&sourceRect);
2722 
2723 			ServerBitmap *bitmap = App()->FindBitmap(token);
2724 			if (bitmap == NULL)
2725 				break;
2726 
2727 			picture->WriteDrawBitmap(sourceRect, destRect, bitmap->Width(), bitmap->Height(),
2728 						bitmap->BytesPerRow(), bitmap->ColorSpace(), /*bitmap->Flags()*/0,
2729 						bitmap->Bits(), bitmap->BitsLength());
2730 
2731 			break;
2732 		}
2733 
2734 		case AS_LAYER_DRAW_PICTURE:
2735 		{
2736 			int32 token;
2737 			if (link.Read<int32>(&token) == B_OK) {
2738 				BPoint where;
2739 				link.Read<BPoint>(&where);
2740 
2741 				ServerPicture *pictureToDraw = App()->FindPicture(token);
2742 				if (picture != NULL) {
2743 					// We need to make a copy of the picture, since it can change
2744 					// after it has been drawn
2745 					ServerPicture *copy = App()->CreatePicture(pictureToDraw);
2746 					picture->NestPicture(copy);
2747 					picture->WriteDrawPicture(where, copy->Token());
2748 				}
2749 			}
2750 			break;
2751 		}
2752 
2753 		case AS_LAYER_SET_CLIP_REGION:
2754 		{
2755 			int32 rectCount;
2756 			status_t status = link.Read<int32>(&rectCount);
2757 				// a negative count means no
2758 				// region for the current draw state,
2759 				// but an *empty* region is actually valid!
2760 				// even if it means no drawing is allowed
2761 
2762 			if (status < B_OK)
2763 				break;
2764 
2765 			if (rectCount >= 0) {
2766 				// we are supposed to set the clipping region
2767 				BRegion region;
2768 				if (rectCount > 0 && link.ReadRegion(&region) < B_OK)
2769 					break;
2770 				picture->WriteSetClipping(region);
2771 			} else {
2772 				// we are supposed to clear the clipping region
2773 				picture->WriteClearClipping();
2774 			}
2775 
2776 			break;
2777 		}
2778 		case AS_LAYER_BEGIN_PICTURE:
2779 		{
2780 			ServerPicture *newPicture = App()->CreatePicture();
2781 			newPicture->Usurp(picture);
2782 			newPicture->SyncState(fCurrentLayer);
2783 			fCurrentLayer->SetPicture(newPicture);
2784 
2785 			break;
2786 		}
2787 
2788 		case AS_LAYER_APPEND_TO_PICTURE:
2789 		{
2790 			int32 pictureToken;
2791 			link.Read<int32>(&pictureToken);
2792 			ServerPicture *appendPicture = App()->FindPicture(pictureToken);
2793 			if (appendPicture) {
2794 				//picture->SyncState(fCurrentLayer);
2795 				appendPicture->Usurp(picture);
2796 			}
2797 			fCurrentLayer->SetPicture(appendPicture);
2798 				// we don't care if it's NULL
2799 			break;
2800 		}
2801 
2802 		case AS_LAYER_END_PICTURE:
2803 		{
2804 			ServerPicture *steppedDown = picture->StepDown();
2805 			fCurrentLayer->SetPicture(steppedDown);
2806 			fLink.StartMessage(B_OK);
2807 			fLink.Attach<int32>(picture->Token());
2808 			fLink.Flush();
2809 			return true;
2810 		}
2811 /*
2812 		case AS_LAYER_SET_BLENDING_MODE:
2813 		{
2814 			int8 srcAlpha, alphaFunc;
2815 
2816 			link.Read<int8>(&srcAlpha);
2817 			link.Read<int8>(&alphaFunc);
2818 
2819 			picture->BeginOp(B_PIC_SET_BLENDING_MODE);
2820 			picture->AddInt16((int16)srcAlpha);
2821 			picture->AddInt16((int16)alphaFunc);
2822 			picture->EndOp();
2823 
2824 			break;
2825 		}*/
2826 		default:
2827 			return false;
2828 	}
2829 
2830 	if (link.NeedsReply()) {
2831 		fLink.StartMessage(B_ERROR);
2832 		fLink.Flush();
2833 	}
2834 	return true;
2835 }
2836 
2837 
2838 /*!
2839 	\brief Message-dispatching loop for the ServerWindow
2840 
2841 	Watches the ServerWindow's message port and dispatches as necessary
2842 */
2843 void
2844 ServerWindow::_MessageLooper()
2845 {
2846 	BPrivate::LinkReceiver& receiver = fLink.Receiver();
2847 	bool quitLoop = false;
2848 
2849 	while (!quitLoop) {
2850 		//STRACE(("info: ServerWindow::MonitorWin listening on port %ld.\n",
2851 		//	fMessagePort));
2852 
2853 		int32 code;
2854 		status_t status = receiver.GetNextMessage(code);
2855 		if (status < B_OK) {
2856 			// that shouldn't happen, it's our port
2857 			printf("Someone deleted our message port!\n");
2858 
2859 			// try to let our client die happily
2860 			NotifyQuitRequested();
2861 			break;
2862 		}
2863 
2864 #ifdef PROFILE_MESSAGE_LOOP
2865 		bigtime_t start = system_time();
2866 #endif
2867 
2868 		Lock();
2869 
2870 #ifdef PROFILE_MESSAGE_LOOP
2871 		bigtime_t diff = system_time() - start;
2872 		if (diff > 10000)
2873 			printf("ServerWindow %s: lock acquisition took %Ld usecs\n", Title(), diff);
2874 #endif
2875 
2876 		int32 messagesProcessed = 0;
2877 		bool lockedDesktop = false;
2878 		bool needsAllWindowsLocked = false;
2879 
2880 		while (true) {
2881 			if (code == AS_DELETE_WINDOW || code == kMsgQuitLooper) {
2882 				// this means the client has been killed
2883 				STRACE(("ServerWindow %s received 'AS_DELETE_WINDOW' message code\n",
2884 					Title()));
2885 
2886 				if (code == AS_DELETE_WINDOW) {
2887 					fLink.StartMessage(B_OK);
2888 					fLink.Flush();
2889 				}
2890 
2891 				if (lockedDesktop)
2892 					fDesktop->UnlockSingleWindow();
2893 
2894 				quitLoop = true;
2895 
2896 				// ServerWindow's destructor takes care of pulling this object off the desktop.
2897 				if (!fWindowLayer->IsHidden())
2898 					CRITICAL("ServerWindow: a window must be hidden before it's deleted\n");
2899 
2900 				break;
2901 			}
2902 
2903 			needsAllWindowsLocked = _MessageNeedsAllWindowsLocked(code);
2904 
2905 			if (!lockedDesktop && !needsAllWindowsLocked) {
2906 				// only lock it once
2907 				fDesktop->LockSingleWindow();
2908 				lockedDesktop = true;
2909 			} else if (lockedDesktop && !needsAllWindowsLocked) {
2910 				// nothing to do
2911 			} else if (needsAllWindowsLocked) {
2912 				if (lockedDesktop) {
2913 					// unlock single before locking all
2914 					fDesktop->UnlockSingleWindow();
2915 					lockedDesktop = false;
2916 				}
2917 				fDesktop->LockAllWindows();
2918 			}
2919 
2920 			if (atomic_and(&fRedrawRequested, 0) != 0) {
2921 #ifdef PROFILE_MESSAGE_LOOP
2922 				bigtime_t redrawStart = system_time();
2923 #endif
2924 				fWindowLayer->RedrawDirtyRegion();
2925 #ifdef PROFILE_MESSAGE_LOOP
2926 				diff = system_time() - redrawStart;
2927 				atomic_add(&sRedrawProcessingTime.count, 1);
2928 # ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
2929 				atomic_add64(&sRedrawProcessingTime.time, diff);
2930 # else
2931 				sRedrawProcessingTime.time += diff;
2932 # endif
2933 #endif
2934 			}
2935 
2936 
2937 #ifdef PROFILE_MESSAGE_LOOP
2938 			bigtime_t dispatchStart = system_time();
2939 #endif
2940 			_DispatchMessage(code, receiver);
2941 
2942 #ifdef PROFILE_MESSAGE_LOOP
2943 			if (code >= 0 && code < AS_LAST_CODE) {
2944 				diff = system_time() - dispatchStart;
2945 				atomic_add(&sMessageProfile[code].count, 1);
2946 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
2947 				atomic_add64(&sMessageProfile[code].time, diff);
2948 #else
2949 				sMessageProfile[code].time += diff;
2950 #endif
2951 				if (diff > 10000)
2952 					printf("ServerWindow %s: message %ld took %Ld usecs\n", Title(), code, diff);
2953 			}
2954 #endif
2955 
2956 			if (needsAllWindowsLocked)
2957 				fDesktop->UnlockAllWindows();
2958 
2959 			// only process up to 70 waiting messages at once (we have the Desktop locked)
2960 			if (!receiver.HasMessages() || ++messagesProcessed > 70) {
2961 				if (lockedDesktop)
2962 					fDesktop->UnlockSingleWindow();
2963 				break;
2964 			}
2965 
2966 			// next message
2967 			status_t status = receiver.GetNextMessage(code);
2968 			if (status < B_OK) {
2969 				// that shouldn't happen, it's our port
2970 				printf("Someone deleted our message port!\n");
2971 				if (lockedDesktop)
2972 					fDesktop->UnlockSingleWindow();
2973 
2974 				// try to let our client die happily
2975 				NotifyQuitRequested();
2976 				break;
2977 			}
2978 		}
2979 
2980 		Unlock();
2981 	}
2982 
2983 	// we were asked to quit the message loop - either on request or because of an error
2984 	Quit();
2985 		// does not return
2986 }
2987 
2988 
2989 status_t
2990 ServerWindow::SendMessageToClient(const BMessage* msg, int32 target) const
2991 {
2992 	if (target == B_NULL_TOKEN)
2993 		target = fClientToken;
2994 
2995 	BMessenger reply;
2996 	BMessage::Private messagePrivate((BMessage *)msg);
2997 	return messagePrivate.SendMessage(fClientLooperPort, fClientTeam, target,
2998 		0, false, reply);
2999 }
3000 
3001 
3002 WindowLayer*
3003 ServerWindow::MakeWindowLayer(BRect frame, const char* name,
3004 	window_look look, window_feel feel, uint32 flags, uint32 workspace)
3005 {
3006 	// The non-offscreen ServerWindow uses the DrawingEngine instance from the desktop.
3007 	return new (nothrow) WindowLayer(frame, name, look, feel, flags,
3008 //		workspace, this, fDesktop->GetDrawingEngine());
3009 		workspace, this, new DrawingEngine(fDesktop->HWInterface()));
3010 }
3011 
3012 
3013 status_t
3014 ServerWindow::_EnableDirectWindowMode()
3015 {
3016 	if (fDirectWindowData != NULL) {
3017 		// already in direct window mode
3018 		return B_ERROR;
3019 	}
3020 
3021 	fDirectWindowData = new (nothrow) direct_window_data;
3022 	if (fDirectWindowData == NULL)
3023 		return B_NO_MEMORY;
3024 
3025 	status_t status = fDirectWindowData->InitCheck();
3026 	if (status < B_OK) {
3027 		delete fDirectWindowData;
3028 		fDirectWindowData = NULL;
3029 
3030 		return status;
3031 	}
3032 
3033 	return B_OK;
3034 }
3035 
3036 
3037 void
3038 ServerWindow::HandleDirectConnection(int32 bufferState, int32 driverState)
3039 {
3040 	STRACE(("HandleDirectConnection(bufferState = %ld, driverState = %ld)\n",
3041 		bufferState, driverState));
3042 
3043 	if (fDirectWindowData == NULL
3044 		|| (!fDirectWindowData->started
3045 			&& (bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_START))
3046 		return;
3047 
3048 	// If the direct connection is stopped, only continue if a start notification is received.
3049 	// But save the "reason" of the call (B_BUFFER_RESIZED, B_CLIPPING_MODIFIED, etc)
3050 	if ((fDirectWindowData->buffer_info->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_STOP
3051 		&& (bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_START) {
3052 		fDirectWindowData->next_buffer_state |= bufferState & ~B_DIRECT_MODE_MASK;
3053 		return;
3054 	}
3055 
3056 	fDirectWindowData->started = true;
3057 
3058 	fDirectWindowData->buffer_info->buffer_state =
3059 		(direct_buffer_state)(bufferState | fDirectWindowData->next_buffer_state);
3060 	fDirectWindowData->next_buffer_state = 0;
3061 
3062 	if (driverState != -1)
3063 		fDirectWindowData->buffer_info->driver_state = (direct_driver_state)driverState;
3064 
3065 	if ((bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) {
3066 		// TODO: Locking ?
3067 		RenderingBuffer *buffer = fDesktop->HWInterface()->FrontBuffer();
3068 		fDirectWindowData->buffer_info->bits = buffer->Bits();
3069 		fDirectWindowData->buffer_info->pci_bits = NULL; // TODO
3070 		fDirectWindowData->buffer_info->bytes_per_row = buffer->BytesPerRow();
3071 		switch (buffer->ColorSpace()) {
3072 			case B_RGB32:
3073 			case B_RGBA32:
3074 			case B_RGB32_BIG:
3075 			case B_RGBA32_BIG:
3076 				fDirectWindowData->buffer_info->bits_per_pixel = 32;
3077 				break;
3078 			case B_RGB24:
3079 			case B_RGB24_BIG:
3080 				fDirectWindowData->buffer_info->bits_per_pixel = 24;
3081 				break;
3082 			case B_RGB16:
3083 			case B_RGB16_BIG:
3084 			case B_RGB15:
3085 			case B_RGB15_BIG:
3086 				fDirectWindowData->buffer_info->bits_per_pixel = 16;
3087 				break;
3088 			case B_CMAP8:
3089 				fDirectWindowData->buffer_info->bits_per_pixel = 8;
3090 				break;
3091 			default:
3092 				fprintf(stderr, "unkown colorspace in HandleDirectConnection()!\n");
3093 				fDirectWindowData->buffer_info->bits_per_pixel = 0;
3094 				break;
3095 		}
3096 		fDirectWindowData->buffer_info->pixel_format = buffer->ColorSpace();
3097 		fDirectWindowData->buffer_info->layout = B_BUFFER_NONINTERLEAVED;
3098 		fDirectWindowData->buffer_info->orientation = B_BUFFER_TOP_TO_BOTTOM; // TODO
3099 		fDirectWindowData->buffer_info->window_bounds = to_clipping_rect(fWindowLayer->Frame());
3100 
3101 		// TODO: Review this
3102 		const int32 kMaxClipRectsCount = (B_PAGE_SIZE - sizeof(direct_buffer_info))
3103 			/ sizeof(clipping_rect);
3104 
3105 		// We just want the region inside the window, border excluded.
3106 		BRegion clipRegion = fWindowLayer->VisibleContentRegion();
3107 
3108 		fDirectWindowData->buffer_info->clip_list_count = min_c(clipRegion.CountRects(),
3109 			kMaxClipRectsCount);
3110 		fDirectWindowData->buffer_info->clip_bounds = clipRegion.FrameInt();
3111 
3112 		for (uint32 i = 0; i < fDirectWindowData->buffer_info->clip_list_count; i++)
3113 			fDirectWindowData->buffer_info->clip_list[i] = clipRegion.RectAtInt(i);
3114 	}
3115 
3116 	// Releasing this sem causes the client to call BDirectWindow::DirectConnected()
3117 	release_sem(fDirectWindowData->sem);
3118 
3119 	// TODO: Waiting half a second in the ServerWindow thread is not a problem,
3120 	// but since we are called from the Desktop's thread too, very bad things could happen.
3121 	// Find some way to call this method only within ServerWindow's thread (messaging ?)
3122 	status_t status;
3123 	do {
3124 		// TODO: The timeout is 3000000 usecs (3 seconds) on beos.
3125 		// Test, but I think half a second is enough.
3126 		status = acquire_sem_etc(fDirectWindowData->sem_ack, 1, B_TIMEOUT, 500000);
3127 	} while (status == B_INTERRUPTED);
3128 
3129 	if (status < B_OK) {
3130 		// The client application didn't release the semaphore
3131 		// within the given timeout. Or something else went wrong.
3132 		// Deleting this member should make it crash.
3133 		delete fDirectWindowData;
3134 		fDirectWindowData = NULL;
3135 	}
3136 }
3137 
3138 
3139 void
3140 ServerWindow::_SetCurrentLayer(ViewLayer* layer)
3141 {
3142 	if (fCurrentLayer == layer)
3143 		return;
3144 
3145 	fCurrentLayer = layer;
3146 	fCurrentDrawingRegionValid = false;
3147 	_UpdateDrawState(fCurrentLayer);
3148 
3149 #if 0
3150 #if DELAYED_BACKGROUND_CLEARING
3151 	if (fCurrentLayer && fCurrentLayer->IsBackgroundDirty()
3152 		&& fWindowLayer->InUpdate()) {
3153 		DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine();
3154 		if (drawingEngine->LockParallelAccess()) {
3155 
3156 			fWindowLayer->GetEffectiveDrawingRegion(fCurrentLayer, fCurrentDrawingRegion);
3157 			fCurrentDrawingRegionValid = true;
3158 			BRegion dirty(fCurrentDrawingRegion);
3159 
3160 			BRegion content;
3161 			fWindowLayer->GetContentRegion(&content);
3162 
3163 			fCurrentLayer->Draw(drawingEngine, &dirty, &content, false);
3164 
3165 			drawingEngine->UnlockParallelAccess();
3166 		}
3167 	}
3168 #endif
3169 #endif // 0
3170 }
3171 
3172 
3173 void
3174 ServerWindow::_UpdateDrawState(ViewLayer* layer)
3175 {
3176 	// switch the drawing state
3177 	// TODO: is it possible to scroll a view while it
3178 	// is being drawn? probably not... otherwise the
3179 	// "offsets" passed below would need to be updated again
3180 	DrawingEngine* drawingEngine = fWindowLayer->GetDrawingEngine();
3181 	if (layer && drawingEngine) {
3182 		BPoint p(0, 0);
3183 		layer->ConvertToScreenForDrawing(&p);
3184 		drawingEngine->SetDrawState(layer->CurrentState(), p.x, p.y);
3185 	}
3186 }
3187 
3188 
3189 bool
3190 ServerWindow::_MessageNeedsAllWindowsLocked(uint32 code) const
3191 {
3192 	switch (code) {
3193 		case AS_ACTIVATE_WINDOW:
3194 		case AS_SET_WINDOW_TITLE:
3195 		case AS_ADD_TO_SUBSET:
3196 		case AS_REMOVE_FROM_SUBSET:
3197 		case AS_LAYER_CREATE_ROOT:
3198 		case AS_LAYER_CREATE:
3199 		case AS_SEND_BEHIND:
3200 		case AS_SET_LOOK:
3201 		case AS_SET_FEEL:
3202 		case AS_SET_FLAGS:
3203 		case AS_SET_WORKSPACES:
3204 		case AS_WINDOW_MOVE:
3205 		case AS_WINDOW_RESIZE:
3206 		case AS_SET_SIZE_LIMITS:
3207 		case AS_SET_DECORATOR_SETTINGS:
3208 		case AS_GET_MOUSE:
3209 		case AS_DIRECT_WINDOW_SET_FULLSCREEN:
3210 //		case AS_LAYER_SET_EVENT_MASK:
3211 //		case AS_LAYER_SET_MOUSE_EVENT_MASK:
3212 			return true;
3213 		default:
3214 			return false;
3215 	}
3216 }
3217 
3218 
3219 status_t
3220 ServerWindow::PictureToRegion(ServerPicture *picture, BRegion &region,
3221 	bool inverse, BPoint where)
3222 {
3223 	fprintf(stderr, "ServerWindow::PictureToRegion() not implemented\n");
3224 	region.MakeEmpty();
3225 	return B_ERROR;
3226 }
3227