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