xref: /haiku/src/servers/app/ServerWindow.cpp (revision 652d5f6347ae220645c66f1ab1f3ef691f8b7dc3)
1 /*
2  * Copyright 2001-2019, 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 <stefano.ceccherini@gmail.com>
10  *		Axel Dörfler <axeld@pinc-software.de>
11  *		Artur Wyszynski <harakash@gmail.com>
12  *		Philippe Saint-Pierre <stpere@gmail.com>
13  *		Brecht Machiels <brecht@mos6581.org>
14  *		Julian Harnath <julian.harnath@rwth-aachen.de>
15  *		Joseph Groover <looncraz@looncraz.net>
16  */
17 
18 
19 /*!	\class ServerWindow
20 
21 	The ServerWindow class handles all BWindow messaging; it forwards all
22 	BWindow requests to the corresponding app_server classes, that is Desktop,
23 	Window, and View.
24 	Furthermore, it also sends app_server requests/notices to its BWindow. There
25 	is one ServerWindow per BWindow.
26 */
27 
28 
29 #include "ServerWindow.h"
30 
31 #include <syslog.h>
32 #include <new>
33 
34 #include <AppDefs.h>
35 #include <Autolock.h>
36 #include <Debug.h>
37 #include <DirectWindow.h>
38 #include <TokenSpace.h>
39 #include <View.h>
40 #include <GradientLinear.h>
41 #include <GradientRadial.h>
42 #include <GradientRadialFocus.h>
43 #include <GradientDiamond.h>
44 #include <GradientConic.h>
45 
46 #include <MessagePrivate.h>
47 #include <PortLink.h>
48 #include <ShapePrivate.h>
49 #include <ServerProtocolStructs.h>
50 #include <StackOrHeapArray.h>
51 #include <ViewPrivate.h>
52 #include <WindowInfo.h>
53 #include <WindowPrivate.h>
54 
55 #include "clipping.h"
56 #include "utf8_functions.h"
57 
58 #include "AlphaMask.h"
59 #include "AppServer.h"
60 #include "AutoDeleter.h"
61 #include "BBitmapBuffer.h"
62 #include "BitmapManager.h"
63 #include "Desktop.h"
64 #include "DirectWindowInfo.h"
65 #include "DrawingEngine.h"
66 #include "DrawState.h"
67 #include "HWInterface.h"
68 #include "Layer.h"
69 #include "Overlay.h"
70 #include "ProfileMessageSupport.h"
71 #include "RenderingBuffer.h"
72 #include "ServerApp.h"
73 #include "ServerBitmap.h"
74 #include "ServerPicture.h"
75 #include "ServerProtocol.h"
76 #include "Window.h"
77 #include "WorkspacesView.h"
78 
79 
80 using std::nothrow;
81 
82 
83 //#define TRACE_SERVER_WINDOW
84 #ifdef TRACE_SERVER_WINDOW
85 #	include <stdio.h>
86 #	define STRACE(x) debug_printf x
87 #else
88 #	define STRACE(x) ;
89 #endif
90 
91 //#define TRACE_SERVER_WINDOW_MESSAGES
92 #ifdef TRACE_SERVER_WINDOW_MESSAGES
93 #	include <stdio.h>
94 static const char* kDrawingModeMap[] = {
95 	"B_OP_COPY",
96 	"B_OP_OVER",
97 	"B_OP_ERASE",
98 	"B_OP_INVERT",
99 	"B_OP_ADD",
100 	"B_OP_SUBTRACT",
101 	"B_OP_BLEND",
102 	"B_OP_MIN",
103 	"B_OP_MAX",
104 	"B_OP_SELECT",
105 	"B_OP_ALPHA",
106 
107 	"fix kDrawingModeMap",
108 	"fix kDrawingModeMap",
109 	"fix kDrawingModeMap",
110 	"fix kDrawingModeMap",
111 	"fix kDrawingModeMap",
112 };
113 #	define DTRACE(x) debug_printf x
114 #else
115 #	define DTRACE(x) ;
116 #endif
117 
118 //#define TRACE_SERVER_GRADIENTS
119 #ifdef TRACE_SERVER_GRADIENTS
120 #	include <OS.h>
121 #	define GTRACE(x) debug_printf x
122 #else
123 #	define GTRACE(x) ;
124 #endif
125 
126 //#define PROFILE_MESSAGE_LOOP
127 #ifdef PROFILE_MESSAGE_LOOP
128 struct profile { int32 code; int32 count; bigtime_t time; };
129 static profile sMessageProfile[AS_LAST_CODE];
130 static profile sRedrawProcessingTime;
131 //static profile sNextMessageTime;
132 #endif
133 
134 
135 //	#pragma mark -
136 
137 
138 #ifdef PROFILE_MESSAGE_LOOP
139 static int
140 compare_message_profiles(const void* _a, const void* _b)
141 {
142 	profile* a = (profile*)*(void**)_a;
143 	profile* b = (profile*)*(void**)_b;
144 	if (a->time < b->time)
145 		return 1;
146 	if (a->time > b->time)
147 		return -1;
148 	return 0;
149 }
150 #endif
151 
152 
153 //	#pragma mark -
154 
155 
156 /*!	Sets up the basic BWindow counterpart - you have to call Init() before
157 	you can actually use it, though.
158 */
159 ServerWindow::ServerWindow(const char* title, ServerApp* app,
160 		port_id clientPort, port_id looperPort, int32 clientToken)
161 	:
162 	MessageLooper(title && *title ? title : "Unnamed Window"),
163 	fTitle(NULL),
164 	fDesktop(app->GetDesktop()),
165 	fServerApp(app),
166 	fWindowAddedToDesktop(false),
167 
168 	fClientTeam(app->ClientTeam()),
169 
170 	fMessagePort(-1),
171 	fClientReplyPort(clientPort),
172 	fClientLooperPort(looperPort),
173 
174 	fClientToken(clientToken),
175 
176 	fCurrentView(NULL),
177 	fCurrentDrawingRegion(),
178 	fCurrentDrawingRegionValid(false),
179 
180 	fIsDirectlyAccessing(false)
181 {
182 	STRACE(("ServerWindow(%s)::ServerWindow()\n", title));
183 
184 	SetTitle(title);
185 	fServerToken = BPrivate::gDefaultTokens.NewToken(B_SERVER_TOKEN, this);
186 
187 	BMessenger::Private(fFocusMessenger).SetTo(fClientTeam,
188 		looperPort, B_PREFERRED_TOKEN);
189 	BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
190 		looperPort, clientToken);
191 
192 	fEventTarget.SetTo(fFocusMessenger);
193 
194 	fDeathSemaphore = create_sem(0, "window death");
195 }
196 
197 
198 /*! Tears down all connections the main app_server objects, and deletes some
199 	internals.
200 */
201 ServerWindow::~ServerWindow()
202 {
203 	STRACE(("ServerWindow(%s@%p):~ServerWindow()\n", fTitle, this));
204 
205 	if (!fWindow->IsOffscreenWindow()) {
206 		fWindowAddedToDesktop = false;
207 		fDesktop->RemoveWindow(fWindow.Get());
208 	}
209 
210 	if (App() != NULL) {
211 		App()->RemoveWindow(this);
212 		fServerApp = NULL;
213 	}
214 
215 	fWindow.Unset(); // TODO: is it really needed?
216 
217 	free(fTitle);
218 	delete_port(fMessagePort);
219 
220 	BPrivate::gDefaultTokens.RemoveToken(fServerToken);
221 
222 	fDirectWindowInfo.Unset(); // TODO: is it really needed?
223 	STRACE(("ServerWindow(%p) will exit NOW\n", this));
224 
225 	delete_sem(fDeathSemaphore);
226 
227 #ifdef PROFILE_MESSAGE_LOOP
228 	BList profiles;
229 	for (int32 i = 0; i < AS_LAST_CODE; i++) {
230 		if (sMessageProfile[i].count == 0)
231 			continue;
232 		sMessageProfile[i].code = i;
233 		profiles.AddItem(&sMessageProfile[i]);
234 	}
235 
236 	profiles.SortItems(compare_message_profiles);
237 
238 	int32 count = profiles.CountItems();
239 	for (int32 i = 0; i < count; i++) {
240 		profile* p = (profile*)profiles.ItemAtFast(i);
241 		printf("[%s] called %" B_PRId32 " times, %g secs (%" B_PRId64 " usecs "
242 			"per call)\n", string_for_message_code(p->code), p->count, p->time / 1000000.0,
243 			p->time / p->count);
244 	}
245 	if (sRedrawProcessingTime.count > 0) {
246 		printf("average redraw processing time: %g secs, count: %" B_PRId32 " "
247 			"(%" B_PRId64 " usecs per call)\n",
248 			sRedrawProcessingTime.time / 1000000.0, sRedrawProcessingTime.count,
249 			sRedrawProcessingTime.time / sRedrawProcessingTime.count);
250 	}
251 //	if (sNextMessageTime.count > 0) {
252 //		printf("average NextMessage() time: %g secs, count: %ld (%lld usecs per call)\n",
253 //			sNextMessageTime.time / 1000000.0, sNextMessageTime.count,
254 //			sNextMessageTime.time / sNextMessageTime.count);
255 //	}
256 #endif
257 }
258 
259 
260 status_t
261 ServerWindow::Init(BRect frame, window_look look, window_feel feel,
262 	uint32 flags, uint32 workspace)
263 {
264 	if (!App()->AddWindow(this)) {
265 		fServerApp = NULL;
266 		return B_NO_MEMORY;
267 	}
268 
269 	if (fTitle == NULL)
270 		return B_NO_MEMORY;
271 
272 	// fMessagePort is the port to which the app sends messages for the server
273 	fMessagePort = create_port(100, fTitle);
274 	if (fMessagePort < B_OK)
275 		return fMessagePort;
276 
277 	fLink.SetSenderPort(fClientReplyPort);
278 	fLink.SetReceiverPort(fMessagePort);
279 
280 	// We cannot call MakeWindow in the constructor, since it
281 	// is a virtual function!
282 	fWindow.SetTo(MakeWindow(frame, fTitle, look, feel, flags, workspace));
283 	if (!fWindow.IsSet() || fWindow->InitCheck() != B_OK) {
284 		fWindow.Unset();
285 		return B_NO_MEMORY;
286 	}
287 
288 	if (!fWindow->IsOffscreenWindow()) {
289 		fDesktop->AddWindow(fWindow.Get());
290 		fWindowAddedToDesktop = true;
291 	}
292 
293 	return B_OK;
294 }
295 
296 
297 /*!	Returns the ServerWindow's Window, if it exists and has been
298 	added to the Desktop already.
299 	In other words, you cannot assume this method will always give you
300 	a valid pointer.
301 */
302 Window*
303 ServerWindow::Window() const
304 {
305 	if (!fWindowAddedToDesktop)
306 		return NULL;
307 
308 	return fWindow.Get();
309 }
310 
311 
312 void
313 ServerWindow::_PrepareQuit()
314 {
315 	if (fThread == find_thread(NULL)) {
316 		// make sure we're hidden
317 		fDesktop->LockSingleWindow();
318 		_Hide();
319 		fDesktop->UnlockSingleWindow();
320 	} else if (fThread >= B_OK)
321 		PostMessage(AS_INTERNAL_HIDE_WINDOW);
322 }
323 
324 
325 void
326 ServerWindow::_GetLooperName(char* name, size_t length)
327 {
328 	const char *title = Title();
329 	if (title == NULL || !title[0])
330 		title = "Unnamed Window";
331 
332 	snprintf(name, length, "w:%" B_PRId32 ":%s", ClientTeam(), title);
333 }
334 
335 
336 /*! Shows the window's Window.
337 */
338 void
339 ServerWindow::_Show()
340 {
341 	// NOTE: if you do something else, other than sending a port message, PLEASE lock
342 	STRACE(("ServerWindow %s: _Show\n", Title()));
343 
344 	if (fQuitting || fWindow->IsMinimized() || !fWindow->IsHidden()
345 		|| fWindow->IsOffscreenWindow() || fWindow->TopView() == NULL)
346 		return;
347 
348 	// TODO: Maybe we need to dispatch a message to the desktop to show/hide us
349 	// instead of doing it from this thread.
350 	fDesktop->UnlockSingleWindow();
351 	fDesktop->ShowWindow(fWindow.Get());
352 	if (fDirectWindowInfo.IsSet() && fDirectWindowInfo->IsFullScreen())
353 		_ResizeToFullScreen();
354 
355 	fDesktop->LockSingleWindow();
356 }
357 
358 
359 /*! Hides the window's Window. You need to have all windows locked when
360 	calling this function.
361 */
362 void
363 ServerWindow::_Hide()
364 {
365 	STRACE(("ServerWindow %s: _Hide\n", Title()));
366 
367 	if (fWindow->IsHidden() || fWindow->IsOffscreenWindow())
368 		return;
369 
370 	fDesktop->UnlockSingleWindow();
371 	fDesktop->HideWindow(fWindow.Get());
372 	fDesktop->LockSingleWindow();
373 }
374 
375 
376 void
377 ServerWindow::RequestRedraw()
378 {
379 	PostMessage(AS_REDRAW, 0);
380 		// we don't care if this fails - it's only a notification, and if
381 		// it fails, there are obviously enough messages in the queue
382 		// already
383 
384 	atomic_add(&fRedrawRequested, 1);
385 }
386 
387 
388 void
389 ServerWindow::SetTitle(const char* newTitle)
390 {
391 	char* oldTitle = fTitle;
392 
393 	if (newTitle == NULL)
394 		newTitle = "";
395 
396 	fTitle = strdup(newTitle);
397 	if (fTitle == NULL) {
398 		// out of memory condition
399 		fTitle = oldTitle;
400 		return;
401 	}
402 
403 	free(oldTitle);
404 
405 	if (Thread() >= B_OK) {
406 		char name[B_OS_NAME_LENGTH];
407 		_GetLooperName(name, sizeof(name));
408 		rename_thread(Thread(), name);
409 	}
410 
411 	if (fWindow.IsSet())
412 		fDesktop->SetWindowTitle(fWindow.Get(), newTitle);
413 }
414 
415 
416 //! Requests that the ServerWindow's BWindow quit
417 void
418 ServerWindow::NotifyQuitRequested()
419 {
420 	// NOTE: if you do something else, other than sending a port message,
421 	// PLEASE lock
422 	STRACE(("ServerWindow %s: Quit\n", fTitle));
423 
424 	BMessage msg(B_QUIT_REQUESTED);
425 	SendMessageToClient(&msg);
426 }
427 
428 
429 void
430 ServerWindow::NotifyMinimize(bool minimize)
431 {
432 	if (fWindow->Feel() != B_NORMAL_WINDOW_FEEL)
433 		return;
434 
435 	// The client is responsible for the actual minimization
436 
437 	BMessage msg(B_MINIMIZE);
438 	msg.AddInt64("when", real_time_clock_usecs());
439 	msg.AddBool("minimize", minimize);
440 
441 	SendMessageToClient(&msg);
442 }
443 
444 
445 //! Sends a message to the client to perform a Zoom
446 void
447 ServerWindow::NotifyZoom()
448 {
449 	// NOTE: if you do something else, other than sending a port message,
450 	// PLEASE lock
451 	BMessage msg(B_ZOOM);
452 	SendMessageToClient(&msg);
453 }
454 
455 
456 void
457 ServerWindow::GetInfo(window_info& info)
458 {
459 	info.team = ClientTeam();
460 	info.server_token = ServerToken();
461 
462 	info.thread = Thread();
463 	info.client_token = ClientToken();
464 	info.client_port = fClientLooperPort;
465 	info.workspaces = fWindow->Workspaces();
466 
467 	// logic taken from Switcher comments and experiments
468 	if (fWindow->IsHidden())
469 		info.layer = 0;
470 	else if (fWindow->IsVisible()) {
471 		if (fWindow->Feel() == kDesktopWindowFeel)
472 			info.layer = 2;
473 		else if (fWindow->IsFloating() || fWindow->IsModal())
474 			info.layer = 4;
475 		else
476 			info.layer = 3;
477 	} else
478 		info.layer = 1;
479 
480 	info.feel = fWindow->Feel();
481 	info.flags = fWindow->Flags();
482 	info.window_left = (int)floor(fWindow->Frame().left);
483 	info.window_top = (int)floor(fWindow->Frame().top);
484 	info.window_right = (int)floor(fWindow->Frame().right);
485 	info.window_bottom = (int)floor(fWindow->Frame().bottom);
486 
487 	info.show_hide_level = fWindow->ShowLevel();
488 	info.is_mini = fWindow->IsMinimized();
489 }
490 
491 
492 void
493 ServerWindow::ResyncDrawState()
494 {
495 	_UpdateDrawState(fCurrentView);
496 }
497 
498 
499 View*
500 ServerWindow::_CreateView(BPrivate::LinkReceiver& link, View** _parent)
501 {
502 	// NOTE: no need to check for a lock. This is a private method.
503 
504 	int32 token;
505 	BRect frame;
506 	uint32 resizeMask;
507 	uint32 eventMask;
508 	uint32 eventOptions;
509 	uint32 flags;
510 	bool hidden;
511 	int32 parentToken;
512 	char* name = NULL;
513 	rgb_color viewColor;
514 	BPoint scrollingOffset;
515 
516 	link.Read<int32>(&token);
517 	link.ReadString(&name);
518 	link.Read<BRect>(&frame);
519 	link.Read<BPoint>(&scrollingOffset);
520 	link.Read<uint32>(&resizeMask);
521 	link.Read<uint32>(&eventMask);
522 	link.Read<uint32>(&eventOptions);
523 	link.Read<uint32>(&flags);
524 	link.Read<bool>(&hidden);
525 	link.Read<rgb_color>(&viewColor);
526 	link.Read<int32>(&parentToken);
527 
528 	STRACE(("ServerWindow(%s)::_CreateView()-> view %s, token %" B_PRId32 "\n",
529 		fTitle, name, token));
530 
531 	View* newView;
532 
533 	if ((flags & kWorkspacesViewFlag) != 0) {
534 		newView = new (nothrow) WorkspacesView(frame, scrollingOffset, name,
535 			token, resizeMask, flags);
536 	} else {
537 		newView = new (nothrow) View(frame, scrollingOffset, name, token,
538 			resizeMask, flags);
539 	}
540 
541 	free(name);
542 
543 	if (newView == NULL)
544 		return NULL;
545 
546 	if (newView->InitCheck() != B_OK) {
547 		delete newView;
548 		return NULL;
549 	}
550 
551 	// there is no way of setting this, other than manually :-)
552 	newView->SetViewColor(viewColor);
553 	newView->SetHidden(hidden);
554 	newView->SetEventMask(eventMask, eventOptions);
555 
556 	if (eventMask != 0 || eventOptions != 0) {
557 //		fDesktop->UnlockSingleWindow();
558 //		fDesktop->LockAllWindows();
559 fDesktop->UnlockAllWindows();
560 		// TODO: possible deadlock
561 		fDesktop->EventDispatcher().AddListener(EventTarget(),
562 			newView->Token(), eventMask, eventOptions);
563 fDesktop->LockAllWindows();
564 //		fDesktop->UnlockAllWindows();
565 //		fDesktop->LockSingleWindow();
566 	}
567 
568 	// Initialize the view with the current application plain font.
569 	// NOTE: This might be out of sync with the global app_server plain
570 	// font, but that is so on purpose! The client needs to resync itself
571 	// with the app_server fonts upon notification, but if we just use
572 	// the current font here, the be_plain_font on the client may still
573 	// hold old values. So this needs to be an update initiated by the
574 	// client application.
575 	newView->CurrentState()->SetFont(App()->PlainFont());
576 
577 	if (_parent) {
578 		View *parent;
579 		if (App()->ViewTokens().GetToken(parentToken, B_HANDLER_TOKEN,
580 				(void**)&parent) != B_OK
581 			|| parent->Window()->ServerWindow() != this) {
582 			debug_printf("View token not found!\n");
583 			parent = NULL;
584 		}
585 
586 		*_parent = parent;
587 	}
588 
589 	return newView;
590 }
591 
592 
593 /*!	Dispatches all window messages, and those view messages that
594 	don't need a valid fCurrentView (ie. view creation).
595 */
596 void
597 ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
598 {
599 	switch (code) {
600 		case AS_SHOW_OR_HIDE_WINDOW:
601 		{
602 			int32 showLevel;
603 			if (link.Read<int32>(&showLevel) == B_OK) {
604 				DTRACE(("ServerWindow %s: Message AS_SHOW_OR_HIDE_WINDOW, "
605 					"show level: %" B_PRId32 "\n", Title(), showLevel));
606 
607 				fWindow->SetShowLevel(showLevel);
608 				if (showLevel <= 0)
609 					_Show();
610 				else
611 					_Hide();
612 			}
613 			break;
614 		}
615 		// Only for internal use within this class
616 		case AS_INTERNAL_HIDE_WINDOW:
617 			_Hide();
618 			break;
619 		case AS_MINIMIZE_WINDOW:
620 		{
621 			bool minimize;
622 			if (link.Read<bool>(&minimize) == B_OK) {
623 				DTRACE(("ServerWindow %s: Message AS_MINIMIZE_WINDOW, "
624 					"minimize: %d\n", Title(), minimize));
625 
626 				fDesktop->UnlockSingleWindow();
627 				fDesktop->MinimizeWindow(fWindow.Get(), minimize);
628 				fDesktop->LockSingleWindow();
629 			}
630 			break;
631 		}
632 
633 		case AS_ACTIVATE_WINDOW:
634 		{
635 			bool activate = true;
636 			if (link.Read<bool>(&activate) != B_OK)
637 				break;
638 
639 			DTRACE(("ServerWindow %s: Message AS_ACTIVATE_WINDOW: activate: "
640 				"%d\n", Title(), activate));
641 
642 			fDesktop->UnlockSingleWindow();
643 
644 			if (activate)
645 				fDesktop->SelectWindow(fWindow.Get());
646 			else
647 				fDesktop->SendWindowBehind(fWindow.Get(), NULL);
648 
649 			fDesktop->LockSingleWindow();
650 			break;
651 		}
652 		case AS_SEND_BEHIND:
653 		{
654 			// Has the all-window lock
655 			int32 token;
656 			team_id teamID;
657 			status_t status = B_ERROR;
658 
659 			link.Read<int32>(&token);
660 			if (link.Read<team_id>(&teamID) == B_OK) {
661 				::Window* behindOf = fDesktop->FindWindowByClientToken(token,
662 					teamID);
663 
664 				DTRACE(("ServerWindow %s: Message AS_SEND_BEHIND %s\n",
665 					Title(), behindOf != NULL ? behindOf->Title() : "NULL"));
666 
667 				if (behindOf != NULL || token == -1) {
668 					fDesktop->SendWindowBehind(fWindow.Get(), behindOf);
669 					status = B_OK;
670 				} else
671 					status = B_NAME_NOT_FOUND;
672 			}
673 
674 			fLink.StartMessage(status);
675 			fLink.Flush();
676 			break;
677 		}
678 
679 		case B_QUIT_REQUESTED:
680 			DTRACE(("ServerWindow %s received quit request\n", Title()));
681 			NotifyQuitRequested();
682 			break;
683 
684 		case AS_ENABLE_UPDATES:
685 			DTRACE(("ServerWindow %s: Message AS_ENABLE_UPDATES\n", Title()));
686 			fWindow->EnableUpdateRequests();
687 			break;
688 
689 		case AS_DISABLE_UPDATES:
690 			DTRACE(("ServerWindow %s: Message AS_DISABLE_UPDATES\n", Title()));
691 			fWindow->DisableUpdateRequests();
692 			break;
693 
694 		case AS_NEEDS_UPDATE:
695 			DTRACE(("ServerWindow %s: Message AS_NEEDS_UPDATE: %d\n",
696 				Title(), fWindow->NeedsUpdate()));
697 			if (fWindow->NeedsUpdate())
698 				fLink.StartMessage(B_OK);
699 			else
700 				fLink.StartMessage(B_ERROR);
701 			fLink.Flush();
702 			break;
703 
704 		case AS_SET_WINDOW_TITLE:
705 		{
706 			char* newTitle;
707 			if (link.ReadString(&newTitle) == B_OK) {
708 				DTRACE(("ServerWindow %s: Message AS_SET_WINDOW_TITLE: %s\n",
709 					Title(), newTitle));
710 
711 				SetTitle(newTitle);
712 				free(newTitle);
713 			}
714 			break;
715 		}
716 
717 		case AS_ADD_TO_SUBSET:
718 		{
719 			// Has the all-window lock
720 			DTRACE(("ServerWindow %s: Message AS_ADD_TO_SUBSET\n", Title()));
721 			status_t status = B_ERROR;
722 
723 			int32 token;
724 			if (link.Read<int32>(&token) == B_OK) {
725 				::Window* window = fDesktop->FindWindowByClientToken(token,
726 					App()->ClientTeam());
727 				if (window == NULL || window->Feel() != B_NORMAL_WINDOW_FEEL) {
728 					status = B_BAD_VALUE;
729 				} else {
730 					status = fDesktop->AddWindowToSubset(fWindow.Get(), window)
731 						? B_OK : B_NO_MEMORY;
732 				}
733 			}
734 
735 			fLink.StartMessage(status);
736 			fLink.Flush();
737 			break;
738 		}
739 		case AS_REMOVE_FROM_SUBSET:
740 		{
741 			// Has the all-window lock
742 			DTRACE(("ServerWindow %s: Message AS_REM_FROM_SUBSET\n", Title()));
743 			status_t status = B_ERROR;
744 
745 			int32 token;
746 			if (link.Read<int32>(&token) == B_OK) {
747 				::Window* window = fDesktop->FindWindowByClientToken(token,
748 					App()->ClientTeam());
749 				if (window != NULL) {
750 					fDesktop->RemoveWindowFromSubset(fWindow.Get(), window);
751 					status = B_OK;
752 				} else
753 					status = B_BAD_VALUE;
754 			}
755 
756 			fLink.StartMessage(status);
757 			fLink.Flush();
758 			break;
759 		}
760 
761 		case AS_SET_LOOK:
762 		{
763 			// Has the all-window look
764 			DTRACE(("ServerWindow %s: Message AS_SET_LOOK\n", Title()));
765 
766 			status_t status = B_ERROR;
767 			int32 look;
768 			if (link.Read<int32>(&look) == B_OK) {
769 				// test if look is valid
770 				status = Window::IsValidLook((window_look)look)
771 					? B_OK : B_BAD_VALUE;
772 			}
773 
774 			if (status == B_OK && !fWindow->IsOffscreenWindow())
775 				fDesktop->SetWindowLook(fWindow.Get(), (window_look)look);
776 
777 			fLink.StartMessage(status);
778 			fLink.Flush();
779 			break;
780 		}
781 		case AS_SET_FEEL:
782 		{
783 			// Has the all-window look
784 			DTRACE(("ServerWindow %s: Message AS_SET_FEEL\n", Title()));
785 
786 			status_t status = B_ERROR;
787 			int32 feel;
788 			if (link.Read<int32>(&feel) == B_OK) {
789 				// test if feel is valid
790 				status = Window::IsValidFeel((window_feel)feel)
791 					? B_OK : B_BAD_VALUE;
792 			}
793 
794 			if (status == B_OK && !fWindow->IsOffscreenWindow())
795 				fDesktop->SetWindowFeel(fWindow.Get(), (window_feel)feel);
796 
797 			fLink.StartMessage(status);
798 			fLink.Flush();
799 			break;
800 		}
801 		case AS_SET_FLAGS:
802 		{
803 			// Has the all-window look
804 			DTRACE(("ServerWindow %s: Message AS_SET_FLAGS\n", Title()));
805 
806 			status_t status = B_ERROR;
807 			uint32 flags;
808 			if (link.Read<uint32>(&flags) == B_OK) {
809 				// test if flags are valid
810 				status = (flags & ~Window::ValidWindowFlags()) == 0
811 					? B_OK : B_BAD_VALUE;
812 			}
813 
814 			if (status == B_OK && !fWindow->IsOffscreenWindow())
815 				fDesktop->SetWindowFlags(fWindow.Get(), flags);
816 
817 			fLink.StartMessage(status);
818 			fLink.Flush();
819 			break;
820 		}
821 #if 0
822 		case AS_SET_ALIGNMENT:
823 		{
824 			// TODO: Implement AS_SET_ALIGNMENT
825 			DTRACE(("ServerWindow %s: Message Set_Alignment unimplemented\n",
826 				Title()));
827 			break;
828 		}
829 		case AS_GET_ALIGNMENT:
830 		{
831 			// TODO: Implement AS_GET_ALIGNMENT
832 			DTRACE(("ServerWindow %s: Message Get_Alignment unimplemented\n",
833 				Title()));
834 			break;
835 		}
836 #endif
837 		case AS_IS_FRONT_WINDOW:
838 		{
839 			bool isFront = fDesktop->FrontWindow() == fWindow.Get();
840 			DTRACE(("ServerWindow %s: Message AS_IS_FRONT_WINDOW: %d\n",
841 				Title(), isFront));
842 			fLink.StartMessage(isFront ? B_OK : B_ERROR);
843 			fLink.Flush();
844 			break;
845 		}
846 
847 		case AS_GET_WORKSPACES:
848 		{
849 			DTRACE(("ServerWindow %s: Message AS_GET_WORKSPACES\n", Title()));
850 			fLink.StartMessage(B_OK);
851 			fLink.Attach<uint32>(fWindow->Workspaces());
852 			fLink.Flush();
853 			break;
854 		}
855 		case AS_SET_WORKSPACES:
856 		{
857 			// Has the all-window lock (but would actually not need to lock at
858 			// all)
859 			uint32 newWorkspaces;
860 			if (link.Read<uint32>(&newWorkspaces) != B_OK)
861 				break;
862 
863 			DTRACE(("ServerWindow %s: Message AS_SET_WORKSPACES %" B_PRIx32 "\n",
864 				Title(), newWorkspaces));
865 
866 			fDesktop->SetWindowWorkspaces(fWindow.Get(), newWorkspaces);
867 			break;
868 		}
869 		case AS_WINDOW_RESIZE:
870 		{
871 			// Has the all-window look
872 			float xResizeTo;
873 			float yResizeTo;
874 			link.Read<float>(&xResizeTo);
875 			if (link.Read<float>(&yResizeTo) != B_OK)
876 				break;
877 
878 			DTRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n",
879 				Title(), xResizeTo, yResizeTo));
880 
881 			// comment this code for the time being, as some apps rely
882 			// on the programmatically resize behavior during user resize
883 //			if (fWindow->IsResizing()) {
884 				// While the user resizes the window, we ignore
885 				// pragmatically set window bounds
886 //				fLink.StartMessage(B_BUSY);
887 //			} else {
888 				fDesktop->ResizeWindowBy(fWindow.Get(),
889 					xResizeTo - fWindow->Frame().Width(),
890 					yResizeTo - fWindow->Frame().Height());
891 				fLink.StartMessage(B_OK);
892 //			}
893 			fLink.Flush();
894 			break;
895 		}
896 		case AS_WINDOW_MOVE:
897 		{
898 			// Has the all-window look
899 			float xMoveTo;
900 			float yMoveTo;
901 			link.Read<float>(&xMoveTo);
902 			if (link.Read<float>(&yMoveTo) != B_OK)
903 				break;
904 
905 			DTRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n",
906 				Title(), xMoveTo, yMoveTo));
907 
908 			if (fWindow->IsDragging()) {
909 				// While the user moves the window, we ignore
910 				// pragmatically set window positions
911 				fLink.StartMessage(B_BUSY);
912 			} else {
913 				fDesktop->MoveWindowBy(fWindow.Get(),
914 					xMoveTo - fWindow->Frame().left,
915 					yMoveTo - fWindow->Frame().top);
916 				fLink.StartMessage(B_OK);
917 			}
918 			fLink.Flush();
919 			break;
920 		}
921 		case AS_SET_SIZE_LIMITS:
922 		{
923 			// Has the all-window look
924 
925 			// Attached Data:
926 			// 1) float minimum width
927 			// 2) float maximum width
928 			// 3) float minimum height
929 			// 4) float maximum height
930 
931 			// TODO: for now, move the client to int32 as well!
932 			int32 minWidth, maxWidth, minHeight, maxHeight;
933 			float value;
934 			link.Read<float>(&value);	minWidth = (int32)value;
935 			link.Read<float>(&value);	maxWidth = (int32)value;
936 			link.Read<float>(&value);	minHeight = (int32)value;
937 			link.Read<float>(&value);	maxHeight = (int32)value;
938 /*
939 			link.Read<int32>(&minWidth);
940 			link.Read<int32>(&maxWidth);
941 			link.Read<int32>(&minHeight);
942 			link.Read<int32>(&maxHeight);
943 */
944 			DTRACE(("ServerWindow %s: Message AS_SET_SIZE_LIMITS: "
945 				"x: %" B_PRId32 "-%" B_PRId32 ", y: %" B_PRId32 "-%" B_PRId32
946 				"\n", Title(), minWidth, maxWidth, minHeight, maxHeight));
947 
948 			fWindow->SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight);
949 
950 			// and now, sync the client to the limits that we were able to enforce
951 			fWindow->GetSizeLimits(&minWidth, &maxWidth,
952 				&minHeight, &maxHeight);
953 
954 			fLink.StartMessage(B_OK);
955 			fLink.Attach<BRect>(fWindow->Frame());
956 			fLink.Attach<float>((float)minWidth);
957 			fLink.Attach<float>((float)maxWidth);
958 			fLink.Attach<float>((float)minHeight);
959 			fLink.Attach<float>((float)maxHeight);
960 
961 			fLink.Flush();
962 
963 			fDesktop->NotifySizeLimitsChanged(fWindow.Get(), minWidth, maxWidth,
964 				minHeight, maxHeight);
965 			break;
966 		}
967 
968 		case AS_SET_DECORATOR_SETTINGS:
969 		{
970 			// Has the all-window look
971 			DTRACE(("ServerWindow %s: Message AS_SET_DECORATOR_SETTINGS\n",
972 				Title()));
973 
974 			int32 size;
975 			if (fWindow.IsSet() && link.Read<int32>(&size) == B_OK) {
976 				char buffer[size];
977 				if (link.Read(buffer, size) == B_OK) {
978 					BMessage settings;
979 					if (settings.Unflatten(buffer) == B_OK)
980 						fDesktop->SetWindowDecoratorSettings(
981 							fWindow.Get(), settings);
982 				}
983 			}
984 			break;
985 		}
986 
987 		case AS_GET_DECORATOR_SETTINGS:
988 		{
989 			DTRACE(("ServerWindow %s: Message AS_GET_DECORATOR_SETTINGS\n",
990 				Title()));
991 
992 			bool success = false;
993 
994 			BMessage settings;
995 			if (fWindow->GetDecoratorSettings(&settings)) {
996 				int32 size = settings.FlattenedSize();
997 				char buffer[size];
998 				if (settings.Flatten(buffer, size) == B_OK) {
999 					success = true;
1000 					fLink.StartMessage(B_OK);
1001 					fLink.Attach<int32>(size);
1002 					fLink.Attach(buffer, size);
1003 				}
1004 			}
1005 
1006 			if (!success)
1007 				fLink.StartMessage(B_ERROR);
1008 
1009 			fLink.Flush();
1010 			break;
1011 		}
1012 
1013 		case AS_SYSTEM_FONT_CHANGED:
1014 		{
1015 			// Has the all-window look
1016 			fDesktop->FontsChanged(fWindow.Get());
1017 			break;
1018 		}
1019 
1020 		// Forward to client
1021 		case B_FONTS_UPDATED:
1022 		{
1023 			// TODO: would knowing which font was changed be useful?
1024 			BMessage message(code);
1025 			SendMessageToClient(&message);
1026 			break;
1027 		}
1028 
1029 		case AS_REDRAW:
1030 			// Nothing to do here - the redraws are actually handled by looking
1031 			// at the fRedrawRequested member variable in _MessageLooper().
1032 			break;
1033 
1034 		case AS_SYNC:
1035 			DTRACE(("ServerWindow %s: Message AS_SYNC\n", Title()));
1036 			// the synchronisation works by the fact that the client
1037 			// window is waiting for this reply, after having received it,
1038 			// client and server queues are in sync (earlier, the client
1039 			// may have pushed drawing commands at the server and now it
1040 			// knows they have all been carried out)
1041 			fLink.StartMessage(B_OK);
1042 			fLink.Flush();
1043 			break;
1044 
1045 		case AS_BEGIN_UPDATE:
1046 			DTRACE(("ServerWindow %s: Message AS_BEGIN_UPDATE\n", Title()));
1047 			fWindow->BeginUpdate(fLink);
1048 			break;
1049 
1050 		case AS_END_UPDATE:
1051 			DTRACE(("ServerWindow %s: Message AS_END_UPDATE\n", Title()));
1052 			fWindow->EndUpdate();
1053 			break;
1054 
1055 		case AS_GET_MOUSE:
1056 		{
1057 			// Has the all-window look
1058 			DTRACE(("ServerWindow %s: Message AS_GET_MOUSE\n", fTitle));
1059 
1060 			// Returns
1061 			// 1) BPoint mouse location
1062 			// 2) int32 button state
1063 
1064 			BPoint where;
1065 			int32 buttons;
1066 			fDesktop->GetLastMouseState(&where, &buttons);
1067 
1068 			fLink.StartMessage(B_OK);
1069 			fLink.Attach<BPoint>(where);
1070 			fLink.Attach<int32>(buttons);
1071 			fLink.Flush();
1072 			break;
1073 		}
1074 
1075 		// BDirectWindow communication
1076 
1077 		case AS_DIRECT_WINDOW_GET_SYNC_DATA:
1078 		{
1079 			status_t status = _EnableDirectWindowMode();
1080 
1081 			fLink.StartMessage(status);
1082 			if (status == B_OK) {
1083 				struct direct_window_sync_data syncData;
1084 				fDirectWindowInfo->GetSyncData(syncData);
1085 
1086 				fLink.Attach(&syncData, sizeof(syncData));
1087 			}
1088 
1089 			fLink.Flush();
1090 			break;
1091 		}
1092 		case AS_DIRECT_WINDOW_SET_FULLSCREEN:
1093 		{
1094 			// Has the all-window look
1095 			bool enable;
1096 			link.Read<bool>(&enable);
1097 
1098 			status_t status = B_OK;
1099 			if (fDirectWindowInfo.IsSet())
1100 				_DirectWindowSetFullScreen(enable);
1101 			else
1102 				status = B_BAD_TYPE;
1103 
1104 			fLink.StartMessage(status);
1105 			fLink.Flush();
1106 			break;
1107 		}
1108 
1109 		// View creation and destruction (don't need a valid fCurrentView)
1110 
1111 		case AS_SET_CURRENT_VIEW:
1112 		{
1113 			int32 token;
1114 			if (link.Read<int32>(&token) != B_OK)
1115 				break;
1116 
1117 			View *current;
1118 			if (App()->ViewTokens().GetToken(token, B_HANDLER_TOKEN,
1119 					(void**)&current) != B_OK
1120 				|| current->Window()->ServerWindow() != this) {
1121 				// TODO: if this happens, we probably want to kill the app and
1122 				// clean up
1123 				debug_printf("ServerWindow %s: Message "
1124 					"\n\n\nAS_SET_CURRENT_VIEW: view not found, token %"
1125 					B_PRId32 "\n", fTitle, token);
1126 				current = NULL;
1127 			} else {
1128 				DTRACE(("\n\n\nServerWindow %s: Message AS_SET_CURRENT_VIEW: %s, "
1129 					"token %" B_PRId32 "\n", fTitle, current->Name(), token));
1130 				_SetCurrentView(current);
1131 			}
1132 			break;
1133 		}
1134 
1135 		case AS_VIEW_CREATE_ROOT:
1136 		{
1137 			DTRACE(("ServerWindow %s: Message AS_VIEW_CREATE_ROOT\n", fTitle));
1138 
1139 			// Start receiving top_view data -- pass NULL as the parent view.
1140 			// This should be the *only* place where this happens.
1141 			if (fCurrentView != NULL) {
1142 				debug_printf("ServerWindow %s: Message "
1143 					"AS_VIEW_CREATE_ROOT: fCurrentView already set!!\n",
1144 					fTitle);
1145 				break;
1146 			}
1147 
1148 			_SetCurrentView(_CreateView(link, NULL));
1149 			fWindow->SetTopView(fCurrentView);
1150 			break;
1151 		}
1152 
1153 		case AS_VIEW_CREATE:
1154 		{
1155 			DTRACE(("ServerWindow %s: Message AS_VIEW_CREATE: View name: "
1156 				"%s\n", fTitle, fCurrentView->Name()));
1157 
1158 			View* parent = NULL;
1159 			View* newView = _CreateView(link, &parent);
1160 			if (parent != NULL && newView != NULL)
1161 				parent->AddChild(newView);
1162 			else {
1163 				delete newView;
1164 				debug_printf("ServerWindow %s: Message AS_VIEW_CREATE: "
1165 					"parent or newView NULL!!\n", fTitle);
1166 			}
1167 			break;
1168 		}
1169 
1170 		case AS_TALK_TO_DESKTOP_LISTENER:
1171 		{
1172 			if (fDesktop->MessageForListener(fWindow.Get(), fLink.Receiver(),
1173 				fLink.Sender()))
1174 				break;
1175 			// unhandled message at least send an error if needed
1176 			if (link.NeedsReply()) {
1177 				fLink.StartMessage(B_ERROR);
1178 				fLink.Flush();
1179 			}
1180 			break;
1181 		}
1182 
1183 		default:
1184 			if (fCurrentView == NULL) {
1185 				debug_printf("ServerWindow %s received unexpected code - "
1186 					"message '%s' before top_view attached.\n",
1187 					Title(), string_for_message_code(code));
1188 				if (link.NeedsReply()) {
1189 					fLink.StartMessage(B_ERROR);
1190 					fLink.Flush();
1191 				}
1192 				return;
1193 			}
1194 
1195 			_DispatchViewMessage(code, link);
1196 			break;
1197 	}
1198 }
1199 
1200 
1201 /*!
1202 	Dispatches all view messages that need a valid fCurrentView.
1203 */
1204 void
1205 ServerWindow::_DispatchViewMessage(int32 code,
1206 	BPrivate::LinkReceiver &link)
1207 {
1208 	if (_DispatchPictureMessage(code, link))
1209 		return;
1210 
1211 	switch (code) {
1212 		case AS_VIEW_SCROLL:
1213 		{
1214 			float dh;
1215 			float dv;
1216 			link.Read<float>(&dh);
1217 			if (link.Read<float>(&dv) != B_OK)
1218 				break;
1219 
1220 			DTRACE(("ServerWindow %s: Message AS_VIEW_SCROLL: View name: "
1221 				"%s, %.1f x %.1f\n", fTitle, fCurrentView->Name(), dh, dv));
1222 			fWindow->ScrollViewBy(fCurrentView, dh, dv);
1223 			break;
1224 		}
1225 		case AS_VIEW_COPY_BITS:
1226 		{
1227 			BRect src;
1228 			BRect dst;
1229 
1230 			link.Read<BRect>(&src);
1231 			if (link.Read<BRect>(&dst) != B_OK)
1232 				break;
1233 
1234 			DTRACE(("ServerWindow %s: Message AS_VIEW_COPY_BITS: View name: "
1235 				"%s, BRect(%.1f, %.1f, %.1f, %.1f) -> "
1236 				"BRect(%.1f, %.1f, %.1f, %.1f)\n", fTitle,
1237 				fCurrentView->Name(), src.left, src.top, src.right, src.bottom,
1238 				dst.left, dst.top, dst.right, dst.bottom));
1239 
1240 			BRegion contentRegion;
1241 			// TODO: avoid copy operation maybe?
1242 			fWindow->GetContentRegion(&contentRegion);
1243 			fCurrentView->CopyBits(src, dst, contentRegion);
1244 			break;
1245 		}
1246 		case AS_VIEW_DELETE:
1247 		{
1248 			// Received when a view is detached from a window
1249 
1250 			int32 token;
1251 			if (link.Read<int32>(&token) != B_OK)
1252 				break;
1253 
1254 			View *view;
1255 			if (App()->ViewTokens().GetToken(token, B_HANDLER_TOKEN,
1256 					(void**)&view) == B_OK
1257 				&& view->Window()->ServerWindow() == this) {
1258 				View* parent = view->Parent();
1259 
1260 				DTRACE(("ServerWindow %s: AS_VIEW_DELETE view: %p, "
1261 					"parent: %p\n", fTitle, view, parent));
1262 
1263 				if (parent != NULL) {
1264 					parent->RemoveChild(view);
1265 
1266 					if (view->EventMask() != 0) {
1267 						// TODO: possible deadlock (event dispatcher already
1268 						// locked itself, waits for Desktop write lock, but
1269 						// we have it, now we are trying to lock the event
1270 						// dispatcher -> deadlock)
1271 fDesktop->UnlockSingleWindow();
1272 						fDesktop->EventDispatcher().RemoveListener(
1273 							EventTarget(), token);
1274 fDesktop->LockSingleWindow();
1275 					}
1276 
1277 					if (fCurrentView == view || fCurrentView->HasParent(view))
1278 						_SetCurrentView(parent);
1279 
1280 					delete view;
1281 				} // else we don't delete the root view
1282 			}
1283 			break;
1284 		}
1285 		case AS_VIEW_SET_STATE:
1286 		{
1287 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_STATE: "
1288 				"View name: %s\n", fTitle, fCurrentView->Name()));
1289 
1290 			fCurrentView->CurrentState()->ReadFromLink(link);
1291 			// TODO: When is this used?!?
1292 			fCurrentView->RebuildClipping(true);
1293 			_UpdateDrawState(fCurrentView);
1294 
1295 			break;
1296 		}
1297 		case AS_VIEW_SET_FONT_STATE:
1298 		{
1299 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FONT_STATE: "
1300 				"View name: %s\n", fTitle, fCurrentView->Name()));
1301 
1302 			fCurrentView->CurrentState()->ReadFontFromLink(link);
1303 			fWindow->GetDrawingEngine()->SetFont(
1304 				fCurrentView->CurrentState());
1305 			break;
1306 		}
1307 		case AS_VIEW_GET_STATE:
1308 		{
1309 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_STATE: "
1310 				"View name: %s\n", fTitle, fCurrentView->Name()));
1311 
1312 			fLink.StartMessage(B_OK);
1313 
1314 			// attach state data
1315 			fCurrentView->CurrentState()->WriteToLink(fLink.Sender());
1316 			fLink.Flush();
1317 			break;
1318 		}
1319 		case AS_VIEW_SET_EVENT_MASK:
1320 		{
1321 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_EVENT_MASK: "
1322 				"View name: %s\n", fTitle, fCurrentView->Name()));
1323 			uint32 eventMask, options;
1324 
1325 			link.Read<uint32>(&eventMask);
1326 			if (link.Read<uint32>(&options) == B_OK) {
1327 				fCurrentView->SetEventMask(eventMask, options);
1328 
1329 fDesktop->UnlockSingleWindow();
1330 				// TODO: possible deadlock!
1331 				if (eventMask != 0 || options != 0) {
1332 					fDesktop->EventDispatcher().AddListener(EventTarget(),
1333 						fCurrentView->Token(), eventMask, options);
1334 				} else {
1335 					fDesktop->EventDispatcher().RemoveListener(EventTarget(),
1336 						fCurrentView->Token());
1337 				}
1338 fDesktop->LockSingleWindow();
1339 			}
1340 			break;
1341 		}
1342 		case AS_VIEW_SET_MOUSE_EVENT_MASK:
1343 		{
1344 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_MOUSE_EVENT_MASK: "
1345 				"View name: %s\n", fTitle, fCurrentView->Name()));
1346 			uint32 eventMask, options;
1347 
1348 			link.Read<uint32>(&eventMask);
1349 			if (link.Read<uint32>(&options) == B_OK) {
1350 fDesktop->UnlockSingleWindow();
1351 				// TODO: possible deadlock
1352 				if (eventMask != 0 || options != 0) {
1353 					if (options & B_LOCK_WINDOW_FOCUS)
1354 						fDesktop->SetFocusLocked(fWindow.Get());
1355 					fDesktop->EventDispatcher().AddTemporaryListener(EventTarget(),
1356 						fCurrentView->Token(), eventMask, options);
1357 				} else {
1358 					fDesktop->EventDispatcher().RemoveTemporaryListener(EventTarget(),
1359 						fCurrentView->Token());
1360 				}
1361 fDesktop->LockSingleWindow();
1362 			}
1363 
1364 			// TODO: support B_LOCK_WINDOW_FOCUS option in Desktop
1365 			break;
1366 		}
1367 		case AS_VIEW_MOVE_TO:
1368 		{
1369 			float x, y;
1370 			link.Read<float>(&x);
1371 			if (link.Read<float>(&y) != B_OK)
1372 				break;
1373 
1374 			DTRACE(("ServerWindow %s: Message AS_VIEW_MOVE_TO: View name: "
1375 				"%s, x: %.1f, y: %.1f\n", fTitle, fCurrentView->Name(), x, y));
1376 
1377 			float offsetX = x - fCurrentView->Frame().left;
1378 			float offsetY = y - fCurrentView->Frame().top;
1379 
1380 			BRegion dirty;
1381 			fCurrentView->MoveBy(offsetX, offsetY, &dirty);
1382 
1383 			// TODO: think about how to avoid this hack:
1384 			// the parent clipping needs to be updated, it is not
1385 			// done in MoveBy() since it would cause
1386 			// too much computations when children are resized because
1387 			// follow modes
1388 			if (View* parent = fCurrentView->Parent())
1389 				parent->RebuildClipping(false);
1390 
1391 			fWindow->MarkContentDirty(dirty);
1392 			break;
1393 		}
1394 		case AS_VIEW_RESIZE_TO:
1395 		{
1396 			float newWidth, newHeight;
1397 			link.Read<float>(&newWidth);
1398 			if (link.Read<float>(&newHeight) != B_OK)
1399 				break;
1400 
1401 			DTRACE(("ServerWindow %s: Message AS_VIEW_RESIZE_TO: View name: "
1402 				"%s, width: %.1f, height: %.1f\n", fTitle,
1403 				fCurrentView->Name(), newWidth, newHeight));
1404 
1405 			float deltaWidth = newWidth - fCurrentView->Frame().Width();
1406 			float deltaHeight = newHeight - fCurrentView->Frame().Height();
1407 
1408 			BRegion dirty;
1409 			fCurrentView->ResizeBy(deltaWidth, deltaHeight, &dirty);
1410 
1411 			// TODO: see above
1412 			if (View* parent = fCurrentView->Parent())
1413 				parent->RebuildClipping(false);
1414 
1415 			fWindow->MarkContentDirty(dirty);
1416 			break;
1417 		}
1418 		case AS_VIEW_GET_COORD:
1419 		{
1420 			// our offset in the parent -> will be originX and originY
1421 			// in BView
1422 			BPoint parentOffset = fCurrentView->Frame().LeftTop();
1423 
1424 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_COORD: "
1425 				"View: %s -> x: %.1f, y: %.1f\n", Title(),
1426 				fCurrentView->Name(), parentOffset.x, parentOffset.y));
1427 
1428 			fLink.StartMessage(B_OK);
1429 			fLink.Attach<BPoint>(parentOffset);
1430 			fLink.Attach<BRect>(fCurrentView->Bounds());
1431 			fLink.Flush();
1432 			break;
1433 		}
1434 		case AS_VIEW_SET_ORIGIN:
1435 		{
1436 			float x, y;
1437 			link.Read<float>(&x);
1438 			if (link.Read<float>(&y) != B_OK)
1439 				break;
1440 
1441 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_ORIGIN: "
1442 				"View: %s -> x: %.1f, y: %.1f\n", Title(),
1443 				fCurrentView->Name(), x, y));
1444 
1445 			fCurrentView->SetDrawingOrigin(BPoint(x, y));
1446 			_UpdateDrawState(fCurrentView);
1447 			break;
1448 		}
1449 		case AS_VIEW_GET_ORIGIN:
1450 		{
1451 			BPoint drawingOrigin = fCurrentView->DrawingOrigin();
1452 
1453 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_ORIGIN: "
1454 				"View: %s -> x: %.1f, y: %.1f\n", Title(),
1455 				fCurrentView->Name(), drawingOrigin.x, drawingOrigin.y));
1456 
1457 			fLink.StartMessage(B_OK);
1458 			fLink.Attach<BPoint>(drawingOrigin);
1459 			fLink.Flush();
1460 			break;
1461 		}
1462 		case AS_VIEW_RESIZE_MODE:
1463 		{
1464 			uint32 resizeMode;
1465 			if (link.Read<uint32>(&resizeMode) != B_OK)
1466 				break;
1467 
1468 			DTRACE(("ServerWindow %s: Message AS_VIEW_RESIZE_MODE: "
1469 				"View: %s -> %" B_PRId32 "\n", Title(), fCurrentView->Name(),
1470 				resizeMode));
1471 
1472 			fCurrentView->SetResizeMode(resizeMode);
1473 			break;
1474 		}
1475 		case AS_VIEW_SET_FLAGS:
1476 		{
1477 			uint32 flags;
1478 			link.Read<uint32>(&flags);
1479 
1480 			// The views clipping changes when the B_DRAW_ON_CHILDREN flag is
1481 			// toggled.
1482 			bool updateClipping = (flags & B_DRAW_ON_CHILDREN)
1483 				^ (fCurrentView->Flags() & B_DRAW_ON_CHILDREN);
1484 
1485 			fCurrentView->SetFlags(flags);
1486 			_UpdateDrawState(fCurrentView);
1487 
1488 			if (updateClipping) {
1489 				fCurrentView->RebuildClipping(false);
1490 				fCurrentDrawingRegionValid = false;
1491 			}
1492 
1493 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FLAGS: "
1494 				"View: %s -> flags: %" B_PRIu32 "\n", Title(),
1495 				fCurrentView->Name(), flags));
1496 			break;
1497 		}
1498 		case AS_VIEW_HIDE:
1499 			DTRACE(("ServerWindow %s: Message AS_VIEW_HIDE: View: %s\n",
1500 				Title(), fCurrentView->Name()));
1501 			fCurrentView->SetHidden(true);
1502 			break;
1503 
1504 		case AS_VIEW_SHOW:
1505 			DTRACE(("ServerWindow %s: Message AS_VIEW_SHOW: View: %s\n",
1506 				Title(), fCurrentView->Name()));
1507 			fCurrentView->SetHidden(false);
1508 			break;
1509 
1510 		case AS_VIEW_SET_LINE_MODE:
1511 		{
1512 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_LINE_MODE: "
1513 				"View: %s\n", Title(), fCurrentView->Name()));
1514 			ViewSetLineModeInfo info;
1515 			if (link.Read<ViewSetLineModeInfo>(&info) != B_OK)
1516 				break;
1517 
1518 			fCurrentView->CurrentState()->SetLineCapMode(info.lineCap);
1519 			fCurrentView->CurrentState()->SetLineJoinMode(info.lineJoin);
1520 			fCurrentView->CurrentState()->SetMiterLimit(info.miterLimit);
1521 
1522 			fWindow->GetDrawingEngine()->SetStrokeMode(info.lineCap,
1523 				info.lineJoin, info.miterLimit);
1524 
1525 			break;
1526 		}
1527 		case AS_VIEW_GET_LINE_MODE:
1528 		{
1529 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_LINE_MODE: "
1530 				"View: %s\n", Title(), fCurrentView->Name()));
1531 			ViewSetLineModeInfo info;
1532 			info.lineJoin = fCurrentView->CurrentState()->LineJoinMode();
1533 			info.lineCap = fCurrentView->CurrentState()->LineCapMode();
1534 			info.miterLimit = fCurrentView->CurrentState()->MiterLimit();
1535 
1536 			fLink.StartMessage(B_OK);
1537 			fLink.Attach<ViewSetLineModeInfo>(info);
1538 			fLink.Flush();
1539 
1540 			break;
1541 		}
1542 		case AS_VIEW_SET_FILL_RULE:
1543 		{
1544 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_FILL_RULE: "
1545 				"View: %s\n", Title(), fCurrentView->Name()));
1546 			int32 fillRule;
1547 			if (link.Read<int32>(&fillRule) != B_OK)
1548 				break;
1549 
1550 			fCurrentView->CurrentState()->SetFillRule(fillRule);
1551 			fWindow->GetDrawingEngine()->SetFillRule(fillRule);
1552 
1553 			break;
1554 		}
1555 		case AS_VIEW_GET_FILL_RULE:
1556 		{
1557 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_FILL_RULE: "
1558 				"View: %s\n", Title(), fCurrentView->Name()));
1559 			int32 fillRule = fCurrentView->CurrentState()->FillRule();
1560 
1561 			fLink.StartMessage(B_OK);
1562 			fLink.Attach<int32>(fillRule);
1563 			fLink.Flush();
1564 
1565 			break;
1566 		}
1567 		case AS_VIEW_PUSH_STATE:
1568 		{
1569 			DTRACE(("ServerWindow %s: Message AS_VIEW_PUSH_STATE: View: "
1570 				"%s\n", Title(), fCurrentView->Name()));
1571 
1572 			fCurrentView->PushState();
1573 			// TODO: is this necessary?
1574 //			_UpdateDrawState(fCurrentView);
1575 			break;
1576 		}
1577 		case AS_VIEW_POP_STATE:
1578 		{
1579 			DTRACE(("ServerWindow %s: Message AS_VIEW_POP_STATE: View: %s\n",
1580 				Title(), fCurrentView->Name()));
1581 
1582 			fCurrentView->PopState();
1583 			_UpdateDrawState(fCurrentView);
1584 			break;
1585 		}
1586 		case AS_VIEW_SET_SCALE:
1587 		{
1588 			float scale;
1589 			if (link.Read<float>(&scale) != B_OK)
1590 				break;
1591 
1592 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_SCALE: "
1593 				"View: %s -> scale: %.2f\n", Title(), fCurrentView->Name(),
1594 				scale));
1595 
1596 			fCurrentView->SetScale(scale);
1597 			_UpdateDrawState(fCurrentView);
1598 			break;
1599 		}
1600 		case AS_VIEW_GET_SCALE:
1601 		{
1602 			float scale = fCurrentView->CurrentState()->Scale();
1603 
1604 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_SCALE: "
1605 				"View: %s -> scale: %.2f\n",
1606 				Title(), fCurrentView->Name(), scale));
1607 
1608 			fLink.StartMessage(B_OK);
1609 			fLink.Attach<float>(scale);
1610 			fLink.Flush();
1611 			break;
1612 		}
1613 		case AS_VIEW_SET_TRANSFORM:
1614 		{
1615 			BAffineTransform transform;
1616 			if (link.Read<BAffineTransform>(&transform) != B_OK)
1617 				break;
1618 
1619 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_TRANSFORM: "
1620 				"View: %s -> transform: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
1621 				Title(), fCurrentView->Name(), transform.sx, transform.shy,
1622 				transform.shx, transform.sy, transform.tx, transform.ty));
1623 
1624 			fCurrentView->CurrentState()->SetTransform(transform);
1625 			_UpdateDrawState(fCurrentView);
1626 			break;
1627 		}
1628 		case AS_VIEW_GET_TRANSFORM:
1629 		{
1630 			BAffineTransform transform
1631 				= fCurrentView->CurrentState()->Transform();
1632 
1633 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_TRANSFORM: "
1634 				"View: %s -> transform: %.2f, %.2f, %.2f, %.2f, %.2f, %.2f\n",
1635 				Title(), fCurrentView->Name(), transform.sx, transform.shy,
1636 				transform.shx, transform.sy, transform.tx, transform.ty));
1637 
1638 			fLink.StartMessage(B_OK);
1639 			fLink.Attach<BAffineTransform>(transform);
1640 			fLink.Flush();
1641 			break;
1642 		}
1643 		case AS_VIEW_GET_PARENT_COMPOSITE:
1644 		{
1645 			DrawState* state = fCurrentView->CurrentState()->PreviousState();
1646 
1647 			fLink.StartMessage(B_OK);
1648 			if (state != NULL) {
1649 				fLink.Attach<BAffineTransform>(state->CombinedTransform());
1650 				fLink.Attach<float>(state->CombinedScale());
1651 				fLink.Attach<BPoint>(state->CombinedOrigin());
1652 			} else {
1653 				fLink.Attach<BAffineTransform>(BAffineTransform());
1654 				fLink.Attach<float>(1.0f);
1655 				fLink.Attach<BPoint>(B_ORIGIN);
1656 			}
1657 			fLink.Flush();
1658 			break;
1659 		}
1660 		case AS_VIEW_AFFINE_TRANSLATE:
1661 		{
1662 			double x, y;
1663 			link.Read<double>(&x);
1664 			link.Read<double>(&y);
1665 			BAffineTransform current =
1666 				fCurrentView->CurrentState()->Transform();
1667 			current.PreTranslateBy(x, y);
1668 			fCurrentView->CurrentState()->SetTransform(current);
1669 			_UpdateDrawState(fCurrentView);
1670 			break;
1671 		}
1672 
1673 		case AS_VIEW_AFFINE_SCALE:
1674 		{
1675 			double x, y;
1676 			link.Read<double>(&x);
1677 			link.Read<double>(&y);
1678 			BAffineTransform current =
1679 				fCurrentView->CurrentState()->Transform();
1680 			current.PreScaleBy(x, y);
1681 			fCurrentView->CurrentState()->SetTransform(current);
1682 			_UpdateDrawState(fCurrentView);
1683 			break;
1684 		}
1685 
1686 		case AS_VIEW_AFFINE_ROTATE:
1687 		{
1688 			double angleRadians;
1689 			link.Read<double>(&angleRadians);
1690 			BAffineTransform current =
1691 				fCurrentView->CurrentState()->Transform();
1692 			current.PreRotateBy(angleRadians);
1693 			fCurrentView->CurrentState()->SetTransform(current);
1694 			_UpdateDrawState(fCurrentView);
1695 			break;
1696 		}
1697 
1698 		case AS_VIEW_SET_PEN_LOC:
1699 		{
1700 			BPoint location;
1701 			if (link.Read<BPoint>(&location) != B_OK)
1702 				break;
1703 
1704 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PEN_LOC: "
1705 				"View: %s -> BPoint(%.1f, %.1f)\n", Title(),
1706 				fCurrentView->Name(), location.x, location.y));
1707 
1708 			fCurrentView->CurrentState()->SetPenLocation(location);
1709 			break;
1710 		}
1711 		case AS_VIEW_GET_PEN_LOC:
1712 		{
1713 			BPoint location = fCurrentView->CurrentState()->PenLocation();
1714 
1715 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_PEN_LOC: "
1716 				"View: %s -> BPoint(%.1f, %.1f)\n", Title(),
1717 				fCurrentView->Name(), location.x, location.y));
1718 
1719 			fLink.StartMessage(B_OK);
1720 			fLink.Attach<BPoint>(location);
1721 			fLink.Flush();
1722 
1723 			break;
1724 		}
1725 		case AS_VIEW_SET_PEN_SIZE:
1726 		{
1727 			float penSize;
1728 			if (link.Read<float>(&penSize) != B_OK)
1729 				break;
1730 
1731 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PEN_SIZE: "
1732 				"View: %s -> %.1f\n", Title(), fCurrentView->Name(), penSize));
1733 
1734 			fCurrentView->CurrentState()->SetPenSize(penSize);
1735 			fWindow->GetDrawingEngine()->SetPenSize(
1736 				fCurrentView->CurrentState()->PenSize());
1737 			break;
1738 		}
1739 		case AS_VIEW_GET_PEN_SIZE:
1740 		{
1741 			float penSize = fCurrentView->CurrentState()->UnscaledPenSize();
1742 
1743 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_PEN_SIZE: "
1744 				"View: %s -> %.1f\n", Title(), fCurrentView->Name(), penSize));
1745 
1746 			fLink.StartMessage(B_OK);
1747 			fLink.Attach<float>(penSize);
1748 			fLink.Flush();
1749 
1750 			break;
1751 		}
1752 		case AS_VIEW_SET_VIEW_COLOR:
1753 		{
1754 			rgb_color color;
1755 			if (link.Read(&color, sizeof(rgb_color)) != B_OK)
1756 				break;
1757 
1758 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_VIEW_COLOR: "
1759 				"View: %s -> rgb_color(%d, %d, %d, %d)\n", Title(),
1760 				fCurrentView->Name(), color.red, color.green, color.blue,
1761 				color.alpha));
1762 
1763 			fCurrentView->SetViewColor(color);
1764 			break;
1765 		}
1766 		case AS_VIEW_GET_VIEW_COLOR:
1767 		{
1768 			rgb_color color = fCurrentView->ViewColor();
1769 
1770 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_VIEW_COLOR: "
1771 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1772 				Title(), fCurrentView->Name(), color.red, color.green,
1773 				color.blue, color.alpha));
1774 
1775 			fLink.StartMessage(B_OK);
1776 			fLink.Attach<rgb_color>(color);
1777 			fLink.Flush();
1778 			break;
1779 		}
1780 		case AS_VIEW_SET_HIGH_COLOR:
1781 		{
1782 			rgb_color color;
1783 			if (link.Read(&color, sizeof(rgb_color)) != B_OK)
1784 				break;
1785 
1786 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_HIGH_COLOR: "
1787 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1788 				Title(), fCurrentView->Name(), color.red, color.green,
1789 				color.blue, color.alpha));
1790 
1791 			fCurrentView->CurrentState()->SetHighColor(color);
1792 			fWindow->GetDrawingEngine()->SetHighColor(color);
1793 			break;
1794 		}
1795 
1796 		case AS_VIEW_SET_HIGH_UI_COLOR:
1797 		{
1798 			color_which which = B_NO_COLOR;
1799 			float tint = B_NO_TINT;
1800 
1801 			if (link.Read<color_which>(&which) != B_OK
1802 				|| link.Read<float>(&tint) != B_OK )
1803 				break;
1804 
1805 			fCurrentView->CurrentState()->SetHighUIColor(which, tint);
1806 
1807 			// TODO: should we do more color_which validity checking?
1808 			if (which != B_NO_COLOR) {
1809 				DesktopSettings settings(fDesktop);
1810 				rgb_color color = tint_color(settings.UIColor(which), tint);
1811 
1812 				fCurrentView->CurrentState()->SetHighColor(color);
1813 				fWindow->GetDrawingEngine()->SetHighColor(color);
1814 			}
1815 			break;
1816 		}
1817 		case AS_VIEW_SET_LOW_UI_COLOR:
1818 		{
1819 			color_which which = B_NO_COLOR;
1820 			float tint = B_NO_TINT;
1821 
1822 			if (link.Read<color_which>(&which) != B_OK
1823 				|| link.Read<float>(&tint) != B_OK )
1824 				break;
1825 
1826 			fCurrentView->CurrentState()->SetLowUIColor(which, tint);
1827 
1828 			// TODO: should we do more color_which validity checking?
1829 			if (which != B_NO_COLOR) {
1830 				DesktopSettings settings(fDesktop);
1831 				rgb_color color = tint_color(settings.UIColor(which), tint);
1832 
1833 				fCurrentView->CurrentState()->SetLowColor(color);
1834 				fWindow->GetDrawingEngine()->SetLowColor(color);
1835 			}
1836 			break;
1837 		}
1838 		case AS_VIEW_SET_VIEW_UI_COLOR:
1839 		{
1840 			color_which which = B_NO_COLOR;
1841 			float tint = B_NO_TINT;
1842 
1843 			if (link.Read<color_which>(&which) != B_OK
1844 				|| link.Read<float>(&tint) != B_OK )
1845 				break;
1846 
1847 			// TODO: should we do more color_which validity checking?
1848 			fCurrentView->SetViewUIColor(which, tint);
1849 			break;
1850 		}
1851 		case AS_VIEW_GET_HIGH_UI_COLOR:
1852 		{
1853 			float tint;
1854 			color_which which = fCurrentView->CurrentState()->HighUIColor(&tint);
1855 			rgb_color color = fCurrentView->CurrentState()->HighColor();
1856 
1857 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_HIGH_UI_COLOR: "
1858 				"View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1859 				" %i, %i)\n", Title(), fCurrentView->Name(), which, tint,
1860 				color.red, color.green, color.blue, color.alpha));
1861 
1862 			fLink.StartMessage(B_OK);
1863 			fLink.Attach<color_which>(which);
1864 			fLink.Attach<float>(tint);
1865 			fLink.Attach<rgb_color>(color);
1866 			fLink.Flush();
1867 			break;
1868 		}
1869 		case AS_VIEW_GET_LOW_UI_COLOR:
1870 		{
1871 			float tint;
1872 			color_which which = fCurrentView->CurrentState()->LowUIColor(&tint);
1873 			rgb_color color = fCurrentView->CurrentState()->LowColor();
1874 
1875 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_LOW_UI_COLOR: "
1876 				"View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1877 				" %i, %i)\n", Title(), fCurrentView->Name(), which, tint,
1878 				color.red, color.green, color.blue, color.alpha));
1879 
1880 			fLink.StartMessage(B_OK);
1881 			fLink.Attach<color_which>(which);
1882 			fLink.Attach<float>(tint);
1883 			fLink.Attach<rgb_color>(color);
1884 			fLink.Flush();
1885 			break;
1886 		}
1887 		case AS_VIEW_GET_VIEW_UI_COLOR:
1888 		{
1889 			float tint;
1890 			color_which which = fCurrentView->ViewUIColor(&tint);
1891 			rgb_color color = fCurrentView->ViewColor();
1892 
1893 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_VIEW_UI_COLOR: "
1894 				"View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1895 				" %i, %i)\n", Title(), fCurrentView->Name(), which, tint,
1896 				color.red, color.green, color.blue, color.alpha));
1897 
1898 			fLink.StartMessage(B_OK);
1899 			fLink.Attach<color_which>(which);
1900 			fLink.Attach<float>(tint);
1901 			fLink.Attach<rgb_color>(color);
1902 			fLink.Flush();
1903 			break;
1904 		}
1905 		case AS_VIEW_GET_HIGH_COLOR:
1906 		{
1907 			rgb_color color = fCurrentView->CurrentState()->HighColor();
1908 
1909 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_HIGH_COLOR: "
1910 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1911 				Title(), fCurrentView->Name(), color.red, color.green,
1912 				color.blue, color.alpha));
1913 
1914 			fLink.StartMessage(B_OK);
1915 			fLink.Attach<rgb_color>(color);
1916 			fLink.Flush();
1917 			break;
1918 		}
1919 		case AS_VIEW_SET_LOW_COLOR:
1920 		{
1921 			rgb_color color;
1922 			if (link.Read(&color, sizeof(rgb_color)) != B_OK)
1923 				break;
1924 
1925 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_LOW_COLOR: "
1926 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1927 				Title(), fCurrentView->Name(), color.red, color.green,
1928 				color.blue, color.alpha));
1929 
1930 			fCurrentView->CurrentState()->SetLowColor(color);
1931 			fWindow->GetDrawingEngine()->SetLowColor(color);
1932 			break;
1933 		}
1934 		case AS_VIEW_GET_LOW_COLOR:
1935 		{
1936 			rgb_color color = fCurrentView->CurrentState()->LowColor();
1937 
1938 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_LOW_COLOR: "
1939 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1940 				Title(), fCurrentView->Name(), color.red, color.green,
1941 				color.blue, color.alpha));
1942 
1943 			fLink.StartMessage(B_OK);
1944 			fLink.Attach<rgb_color>(color);
1945 			fLink.Flush();
1946 			break;
1947 		}
1948 		case AS_VIEW_SET_PATTERN:
1949 		{
1950 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PATTERN: "
1951 				"View: %s\n", fTitle, fCurrentView->Name()));
1952 
1953 			pattern pat;
1954 			if (link.Read(&pat, sizeof(pattern)) != B_OK)
1955 				break;
1956 
1957 			fCurrentView->CurrentState()->SetPattern(Pattern(pat));
1958 			fWindow->GetDrawingEngine()->SetPattern(pat);
1959 			break;
1960 		}
1961 
1962 		case AS_VIEW_SET_BLENDING_MODE:
1963 		{
1964 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_BLEND_MODE: "
1965 				"View: %s\n", Title(), fCurrentView->Name()));
1966 
1967 			ViewBlendingModeInfo info;
1968 			if (link.Read<ViewBlendingModeInfo>(&info) != B_OK)
1969 				break;
1970 
1971 			fCurrentView->CurrentState()->SetBlendingMode(
1972 				info.sourceAlpha, info.alphaFunction);
1973 			fWindow->GetDrawingEngine()->SetBlendingMode(
1974 				info.sourceAlpha, info.alphaFunction);
1975 			break;
1976 		}
1977 		case AS_VIEW_GET_BLENDING_MODE:
1978 		{
1979 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_BLEND_MODE: "
1980 				"View: %s\n", Title(), fCurrentView->Name()));
1981 
1982 			ViewBlendingModeInfo info;
1983 			info.sourceAlpha = fCurrentView->CurrentState()->AlphaSrcMode();
1984 			info.alphaFunction = fCurrentView->CurrentState()->AlphaFncMode();
1985 
1986 			fLink.StartMessage(B_OK);
1987 			fLink.Attach<ViewBlendingModeInfo>(info);
1988 			fLink.Flush();
1989 
1990 			break;
1991 		}
1992 		case AS_VIEW_SET_DRAWING_MODE:
1993 		{
1994 			int8 drawingMode;
1995 			if (link.Read<int8>(&drawingMode) != B_OK)
1996 				break;
1997 
1998 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_DRAW_MODE: "
1999 				"View: %s -> %s\n", Title(), fCurrentView->Name(),
2000 				kDrawingModeMap[drawingMode]));
2001 
2002 			fCurrentView->CurrentState()->SetDrawingMode(
2003 				(drawing_mode)drawingMode);
2004 			fWindow->GetDrawingEngine()->SetDrawingMode(
2005 				(drawing_mode)drawingMode);
2006 			break;
2007 		}
2008 		case AS_VIEW_GET_DRAWING_MODE:
2009 		{
2010 			int8 drawingMode
2011 				= (int8)(fCurrentView->CurrentState()->GetDrawingMode());
2012 
2013 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_DRAW_MODE: "
2014 				"View: %s -> %s\n", Title(), fCurrentView->Name(),
2015 				kDrawingModeMap[drawingMode]));
2016 
2017 			fLink.StartMessage(B_OK);
2018 			fLink.Attach<int8>(drawingMode);
2019 			fLink.Flush();
2020 
2021 			break;
2022 		}
2023 		case AS_VIEW_SET_VIEW_BITMAP:
2024 		{
2025 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_VIEW_BITMAP: "
2026 				"View: %s\n", Title(), fCurrentView->Name()));
2027 
2028 			int32 bitmapToken, resizingMode, options;
2029 			BRect srcRect, dstRect;
2030 
2031 			link.Read<int32>(&bitmapToken);
2032 			link.Read<BRect>(&srcRect);
2033 			link.Read<BRect>(&dstRect);
2034 			link.Read<int32>(&resizingMode);
2035 			status_t status = link.Read<int32>(&options);
2036 
2037 			rgb_color colorKey = {0};
2038 
2039 			if (status == B_OK) {
2040 				BReference<ServerBitmap> bitmap(fServerApp->GetBitmap(bitmapToken), true);
2041 				if (bitmapToken == -1 || bitmap != NULL) {
2042 					bool wasOverlay = fCurrentView->ViewBitmap() != NULL
2043 						&& fCurrentView->ViewBitmap()->Overlay() != NULL;
2044 
2045 					fCurrentView->SetViewBitmap(bitmap, srcRect, dstRect,
2046 						resizingMode, options);
2047 
2048 					// TODO: if we revert the view color overlay handling
2049 					//	in View::Draw() to the BeOS version, we never
2050 					//	need to invalidate the view for overlays.
2051 
2052 					// Invalidate view - but only if this is a non-overlay
2053 					// switch
2054 					if (bitmap == NULL || bitmap->Overlay() == NULL
2055 						|| !wasOverlay) {
2056 						BRegion dirty((BRect)fCurrentView->Bounds());
2057 						fWindow->InvalidateView(fCurrentView, dirty);
2058 					}
2059 
2060 					if (bitmap != NULL && bitmap->Overlay() != NULL) {
2061 						bitmap->Overlay()->SetFlags(options);
2062 						colorKey = bitmap->Overlay()->Color();
2063 					}
2064 				} else
2065 					status = B_BAD_VALUE;
2066 			}
2067 
2068 			fLink.StartMessage(status);
2069 			if (status == B_OK && (options & AS_REQUEST_COLOR_KEY) != 0) {
2070 				// Attach color key for the overlay bitmap
2071 				fLink.Attach<rgb_color>(colorKey);
2072 			}
2073 
2074 			fLink.Flush();
2075 			break;
2076 		}
2077 		case AS_VIEW_PRINT_ALIASING:
2078 		{
2079 			DTRACE(("ServerWindow %s: Message AS_VIEW_PRINT_ALIASING: "
2080 				"View: %s\n", Title(), fCurrentView->Name()));
2081 
2082 			bool fontAliasing;
2083 			if (link.Read<bool>(&fontAliasing) == B_OK) {
2084 				fCurrentView->CurrentState()->SetForceFontAliasing(fontAliasing);
2085 				_UpdateDrawState(fCurrentView);
2086 			}
2087 			break;
2088 		}
2089 		case AS_VIEW_CLIP_TO_PICTURE:
2090 		{
2091 			DTRACE(("ServerWindow %s: Message AS_VIEW_CLIP_TO_PICTURE: "
2092 				"View: %s\n", Title(), fCurrentView->Name()));
2093 
2094 			int32 pictureToken;
2095 			BPoint where;
2096 			bool inverse = false;
2097 
2098 			link.Read<int32>(&pictureToken);
2099 			if (pictureToken < 0) {
2100 				fCurrentView->SetAlphaMask(NULL);
2101 				_UpdateDrawState(fCurrentView);
2102 				break;
2103 			}
2104 
2105 			link.Read<BPoint>(&where);
2106 			if (link.Read<bool>(&inverse) != B_OK)
2107 				break;
2108 
2109 			BReference<ServerPicture> picture(fServerApp->GetPicture(pictureToken), true);
2110 			if (picture == NULL)
2111 				break;
2112 
2113 			BReference<AlphaMask> const mask(new(std::nothrow) PictureAlphaMask(
2114 				fCurrentView->GetAlphaMask(), picture,
2115 				*fCurrentView->CurrentState(), where, inverse), true);
2116 			fCurrentView->SetAlphaMask(mask);
2117 
2118 			_UpdateDrawState(fCurrentView);
2119 			break;
2120 		}
2121 
2122 		case AS_VIEW_GET_CLIP_REGION:
2123 		{
2124 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_CLIP_REGION: "
2125 				"View: %s\n", Title(), fCurrentView->Name()));
2126 
2127 			// if this view is hidden, it has no visible region
2128 			fLink.StartMessage(B_OK);
2129 			if (!fWindow->IsVisible() || !fCurrentView->IsVisible()) {
2130 				BRegion empty;
2131 				fLink.AttachRegion(empty);
2132 			} else {
2133 				_UpdateCurrentDrawingRegion();
2134 				BRegion region(fCurrentDrawingRegion);
2135 				fCurrentView->ScreenToLocalTransform().Apply(&region);
2136 				fLink.AttachRegion(region);
2137 			}
2138 			fLink.Flush();
2139 
2140 			break;
2141 		}
2142 		case AS_VIEW_SET_CLIP_REGION:
2143 		{
2144 			int32 rectCount;
2145 			status_t status = link.Read<int32>(&rectCount);
2146 				// a negative count means no
2147 				// region for the current draw state,
2148 				// but an *empty* region is actually valid!
2149 				// even if it means no drawing is allowed
2150 
2151 			if (status < B_OK)
2152 				break;
2153 
2154 			if (rectCount >= 0) {
2155 				// we are supposed to set the clipping region
2156 				BRegion region;
2157 				if (rectCount > 0 && link.ReadRegion(&region) < B_OK)
2158 					break;
2159 
2160 				DTRACE(("ServerWindow %s: Message AS_VIEW_SET_CLIP_REGION: "
2161 					"View: %s -> rect count: %" B_PRId32 ", frame = "
2162 					"BRect(%.1f, %.1f, %.1f, %.1f)\n",
2163 					Title(), fCurrentView->Name(), rectCount,
2164 					region.Frame().left, region.Frame().top,
2165 					region.Frame().right, region.Frame().bottom));
2166 
2167 				fCurrentView->SetUserClipping(&region);
2168 			} else {
2169 				// we are supposed to unset the clipping region
2170 				// passing NULL sets this states region to that
2171 				// of the previous state
2172 
2173 				DTRACE(("ServerWindow %s: Message AS_VIEW_SET_CLIP_REGION: "
2174 					"View: %s -> unset\n", Title(), fCurrentView->Name()));
2175 
2176 				fCurrentView->SetUserClipping(NULL);
2177 			}
2178 			fCurrentDrawingRegionValid = false;
2179 
2180 			break;
2181 		}
2182 
2183 		case AS_VIEW_CLIP_TO_RECT:
2184 		{
2185 			bool inverse;
2186 			BRect rect;
2187 
2188 			link.Read<bool>(&inverse);
2189 			link.Read<BRect>(&rect);
2190 
2191 			bool needDrawStateUpdate = fCurrentView->ClipToRect(
2192 				rect, inverse);
2193 			fCurrentDrawingRegionValid = false;
2194 
2195 			if (needDrawStateUpdate)
2196 				_UpdateDrawState(fCurrentView);
2197 
2198 			_UpdateCurrentDrawingRegion();
2199 
2200 			BRegion region(fCurrentDrawingRegion);
2201 			fCurrentView->ScreenToLocalTransform().Apply(&region);
2202 
2203 			break;
2204 		}
2205 
2206 		case AS_VIEW_CLIP_TO_SHAPE:
2207 		{
2208 			bool inverse;
2209 			link.Read<bool>(&inverse);
2210 
2211 			shape_data shape;
2212 			link.Read<int32>(&shape.opCount);
2213 			link.Read<int32>(&shape.ptCount);
2214 			shape.opSize = shape.opCount * sizeof(uint32);
2215 			shape.ptSize = shape.ptCount * sizeof(BPoint);
2216 			shape.opList = new(nothrow) uint32[shape.opCount];
2217 			shape.ptList = new(nothrow) BPoint[shape.ptCount];
2218 			if (link.Read(shape.opList, shape.opSize) >= B_OK
2219 				&& link.Read(shape.ptList, shape.ptSize) >= B_OK) {
2220 				fCurrentView->ClipToShape(&shape, inverse);
2221 				_UpdateDrawState(fCurrentView);
2222 			}
2223 
2224 			delete[] shape.opList;
2225 			delete[] shape.ptList;
2226 			break;
2227 		}
2228 
2229 		case AS_VIEW_INVALIDATE_RECT:
2230 		{
2231 			// NOTE: looks like this call is NOT affected by origin and scale
2232 			// on R5 so this implementation is "correct"
2233 			BRect invalidRect;
2234 			if (link.Read<BRect>(&invalidRect) == B_OK) {
2235 				DTRACE(("ServerWindow %s: Message AS_VIEW_INVALIDATE_RECT: "
2236 					"View: %s -> BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2237 					fCurrentView->Name(), invalidRect.left, invalidRect.top,
2238 					invalidRect.right, invalidRect.bottom));
2239 
2240 				View* view = NULL;
2241 				if (link.Read<View*>(&view) != B_OK)
2242 					view = fCurrentView;
2243 
2244 				// make sure the view is still available!
2245 				if (view != fCurrentView
2246 					&& !fWindow->TopView()->HasView(view))
2247 					break;
2248 
2249 				BRegion dirty(invalidRect);
2250 				fWindow->InvalidateView(view, dirty);
2251 			}
2252 			break;
2253 		}
2254 
2255 		case AS_VIEW_DELAYED_INVALIDATE_RECT:
2256 		{
2257 			bigtime_t time = 0;
2258 			BRect invalidRect;
2259 			if (link.Read<bigtime_t>(&time) == B_OK
2260 				&& link.Read<BRect>(&invalidRect) == B_OK) {
2261 				DTRACE(("ServerWindow %s: Message "
2262 					"AS_VIEW_DELAYED_INVALIDATE_RECT: "
2263 					"View: %s -> BRect(%.1f, %.1f, %.1f, %.1f) at time %llu\n",
2264 					Title(), fCurrentView->Name(), invalidRect.left,
2265 					invalidRect.top, invalidRect.right, invalidRect.bottom,
2266 					time));
2267 
2268 				DelayedMessage delayed(AS_VIEW_INVALIDATE_RECT, time, true);
2269 				delayed.AddTarget(MessagePort());
2270 				delayed.SetMerge(DM_MERGE_DUPLICATES);
2271 
2272 				if (delayed.Attach<BRect>(invalidRect) == B_OK
2273 						&& delayed.Attach<View*>(fCurrentView) == B_OK)
2274 					delayed.Flush();
2275 			}
2276 			break;
2277 		}
2278 
2279 		case AS_VIEW_INVALIDATE_REGION:
2280 		{
2281 			// NOTE: looks like this call is NOT affected by origin and scale
2282 			// on R5 so this implementation is "correct"
2283 			BRegion region;
2284 			if (link.ReadRegion(&region) < B_OK)
2285 				break;
2286 
2287 			DTRACE(("ServerWindow %s: Message AS_VIEW_INVALIDATE_REGION: "
2288 					"View: %s -> rect count: %" B_PRId32 ", frame: BRect(%.1f, "
2289 					"%.1f, %.1f, %.1f)\n", Title(),
2290 					fCurrentView->Name(), region.CountRects(),
2291 					region.Frame().left, region.Frame().top,
2292 					region.Frame().right, region.Frame().bottom));
2293 
2294 			fWindow->InvalidateView(fCurrentView, region);
2295 			break;
2296 		}
2297 
2298 		case AS_VIEW_DRAG_IMAGE:
2299 		{
2300 			// TODO: flesh out AS_VIEW_DRAG_IMAGE
2301 			DTRACE(("ServerWindow %s: Message AS_DRAG_IMAGE\n", Title()));
2302 
2303 			int32 bitmapToken;
2304 			drawing_mode dragMode;
2305 			BPoint offset;
2306 			int32 bufferSize;
2307 
2308 			link.Read<int32>(&bitmapToken);
2309 			link.Read<int32>((int32*)&dragMode);
2310 			link.Read<BPoint>(&offset);
2311 			link.Read<int32>(&bufferSize);
2312 
2313 			if (bufferSize > 0) {
2314 				char* buffer = new (nothrow) char[bufferSize];
2315 				BMessage dragMessage;
2316 				if (link.Read(buffer, bufferSize) == B_OK
2317 					&& dragMessage.Unflatten(buffer) == B_OK) {
2318 						BReference<ServerBitmap> bitmap(
2319 							fServerApp->GetBitmap(bitmapToken), true);
2320 						// TODO: possible deadlock
2321 fDesktop->UnlockSingleWindow();
2322 						fDesktop->EventDispatcher().SetDragMessage(dragMessage,
2323 							bitmap, offset);
2324 fDesktop->LockSingleWindow();
2325 				}
2326 				delete[] buffer;
2327 			}
2328 			// sync the client (it can now delete the bitmap)
2329 			fLink.StartMessage(B_OK);
2330 			fLink.Flush();
2331 
2332 			break;
2333 		}
2334 		case AS_VIEW_DRAG_RECT:
2335 		{
2336 			// TODO: flesh out AS_VIEW_DRAG_RECT
2337 			DTRACE(("ServerWindow %s: Message AS_DRAG_RECT\n", Title()));
2338 
2339 			BRect dragRect;
2340 			BPoint offset;
2341 			int32 bufferSize;
2342 
2343 			link.Read<BRect>(&dragRect);
2344 			link.Read<BPoint>(&offset);
2345 			link.Read<int32>(&bufferSize);
2346 
2347 			if (bufferSize > 0) {
2348 				char* buffer = new (nothrow) char[bufferSize];
2349 				BMessage dragMessage;
2350 				if (link.Read(buffer, bufferSize) == B_OK
2351 					&& dragMessage.Unflatten(buffer) == B_OK) {
2352 						// TODO: possible deadlock
2353 fDesktop->UnlockSingleWindow();
2354 						fDesktop->EventDispatcher().SetDragMessage(dragMessage,
2355 							NULL /* should be dragRect */, offset);
2356 fDesktop->LockSingleWindow();
2357 				}
2358 				delete[] buffer;
2359 			}
2360 			break;
2361 		}
2362 
2363 		case AS_VIEW_BEGIN_RECT_TRACK:
2364 		{
2365 			DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_RECT_TRACK\n",
2366 				Title()));
2367 			BRect dragRect;
2368 			uint32 style;
2369 
2370 			link.Read<BRect>(&dragRect);
2371 			link.Read<uint32>(&style);
2372 
2373 			// TODO: implement rect tracking (used sometimes for selecting
2374 			// a group of things, also sometimes used to appear to drag
2375 			// something, but without real drag message)
2376 			break;
2377 		}
2378 		case AS_VIEW_END_RECT_TRACK:
2379 		{
2380 			DTRACE(("ServerWindow %s: Message AS_VIEW_END_RECT_TRACK\n",
2381 				Title()));
2382 			// TODO: implement rect tracking
2383 			break;
2384 		}
2385 
2386 		case AS_VIEW_BEGIN_PICTURE:
2387 		{
2388 			DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_PICTURE\n",
2389 				Title()));
2390 			BReference<ServerPicture> picture(App()->CreatePicture(), true);
2391 			if (picture != NULL) {
2392 				picture->SyncState(fCurrentView);
2393 				fCurrentView->SetPicture(picture);
2394 			}
2395 			break;
2396 		}
2397 
2398 		case AS_VIEW_APPEND_TO_PICTURE:
2399 		{
2400 			DTRACE(("ServerWindow %s: Message AS_VIEW_APPEND_TO_PICTURE\n",
2401 				Title()));
2402 
2403 			int32 token;
2404 			link.Read<int32>(&token);
2405 
2406 			BReference<ServerPicture> picture(App()->GetPicture(token), true);
2407 			if (picture != NULL)
2408 				picture->SyncState(fCurrentView);
2409 
2410 			fCurrentView->SetPicture(picture);
2411 
2412 			break;
2413 		}
2414 
2415 		case AS_VIEW_END_PICTURE:
2416 		{
2417 			DTRACE(("ServerWindow %s: Message AS_VIEW_END_PICTURE\n",
2418 				Title()));
2419 
2420 			ServerPicture* picture = fCurrentView->Picture();
2421 			if (picture != NULL) {
2422 				fCurrentView->SetPicture(NULL);
2423 				fLink.StartMessage(B_OK);
2424 				fLink.Attach<int32>(picture->Token());
2425 			} else
2426 				fLink.StartMessage(B_ERROR);
2427 
2428 			fLink.Flush();
2429 			break;
2430 		}
2431 
2432 		case AS_VIEW_BEGIN_LAYER:
2433 		{
2434 			DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_LAYER\n",
2435 				Title()));
2436 
2437 			uint8 opacity;
2438 			link.Read<uint8>(&opacity);
2439 
2440 			Layer* layer = new(std::nothrow) Layer(opacity);
2441 			if (layer == NULL)
2442 				break;
2443 
2444 			if (opacity != 255) {
2445 				fCurrentView->CurrentState()->SetDrawingMode(B_OP_ALPHA);
2446 				fCurrentView->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA,
2447 					B_ALPHA_COMPOSITE);
2448 				fCurrentView->CurrentState()->SetDrawingModeLocked(true);
2449 			}
2450 
2451 			fCurrentView->SetPicture(layer);
2452 			break;
2453 		}
2454 
2455 		default:
2456 			// The drawing code handles allocation failures using exceptions;
2457 			// so we need to account for that here.
2458 			try {
2459 				_DispatchViewDrawingMessage(code, link);
2460 			} catch (std::bad_alloc&) {
2461 				// Cancel any message we were in the middle of sending.
2462 				fLink.CancelMessage();
2463 
2464 				if (link.NeedsReply()) {
2465 					// As done in _DispatchViewDrawingMessage, send just a
2466 					// single status_t as the reply.
2467 					fLink.StartMessage(B_NO_MEMORY);
2468 					fLink.Flush();
2469 				}
2470 			}
2471 			break;
2472 	}
2473 }
2474 
2475 
2476 /*!	Dispatches all view drawing messages.
2477 	The desktop clipping must be read locked when entering this method.
2478 	Requires a valid fCurrentView.
2479 */
2480 void
2481 ServerWindow::_DispatchViewDrawingMessage(int32 code,
2482 	BPrivate::LinkReceiver &link)
2483 {
2484 	if (!fCurrentView->IsVisible() || !fWindow->IsVisible()) {
2485 		if (link.NeedsReply()) {
2486 			debug_printf("ServerWindow::DispatchViewDrawingMessage() got "
2487 				"message %" B_PRId32 " that needs a reply!\n", code);
2488 			// the client is now blocking and waiting for a reply!
2489 			fLink.StartMessage(B_ERROR);
2490 			fLink.Flush();
2491 		}
2492 		return;
2493 	}
2494 
2495 	DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
2496 	if (!drawingEngine) {
2497 		// ?!?
2498 		debug_printf("ServerWindow %s: no drawing engine!!\n", Title());
2499 		if (link.NeedsReply()) {
2500 			// the client is now blocking and waiting for a reply!
2501 			fLink.StartMessage(B_ERROR);
2502 			fLink.Flush();
2503 		}
2504 		return;
2505 	}
2506 
2507 	_UpdateCurrentDrawingRegion();
2508 	if (fCurrentDrawingRegion.CountRects() <= 0 && code != AS_VIEW_END_LAYER) {
2509 			// If the command is AS_VIEW_END_LAYER, then we continue even if
2510 			// the clipping region is empty. The layer itself might set a valid
2511 			// clipping while its contents are drawn, and even if it doesn't,
2512 			// we must still play back its picture so that we don't leak
2513 			// nested layer instances.
2514 
2515 		DTRACE(("ServerWindow %s: _DispatchViewDrawingMessage(): View: %s, "
2516 			"INVALID CLIPPING!\n", Title(), fCurrentView->Name()));
2517 		if (link.NeedsReply()) {
2518 			// the client is now blocking and waiting for a reply!
2519 			fLink.StartMessage(B_ERROR);
2520 			fLink.Flush();
2521 		}
2522 		return;
2523 	}
2524 
2525 	drawingEngine->LockParallelAccess();
2526 	// NOTE: the region is not copied, Painter keeps a pointer,
2527 	// that's why you need to use the clipping only for as long
2528 	// as you have it locked
2529 	drawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion);
2530 
2531 	switch (code) {
2532 		case AS_STROKE_LINE:
2533 		{
2534 			ViewStrokeLineInfo info;
2535 			if (link.Read<ViewStrokeLineInfo>(&info) != B_OK)
2536 				break;
2537 
2538 			DTRACE(("ServerWindow %s: Message AS_STROKE_LINE: View: %s -> "
2539 				"BPoint(%.1f, %.1f) - BPoint(%.1f, %.1f)\n", Title(),
2540 					fCurrentView->Name(),
2541 					info.startPoint.x, info.startPoint.y,
2542 					info.endPoint.x, info.endPoint.y));
2543 
2544 			BPoint penPos = info.endPoint;
2545 			const SimpleTransform transform =
2546 				fCurrentView->PenToScreenTransform();
2547 			transform.Apply(&info.startPoint);
2548 			transform.Apply(&info.endPoint);
2549 			drawingEngine->StrokeLine(info.startPoint, info.endPoint);
2550 
2551 			// We update the pen here because many DrawingEngine calls which
2552 			// do not update the pen position actually call StrokeLine
2553 
2554 			// TODO: Decide where to put this, for example, it cannot be done
2555 			// for DrawString(), also there needs to be a decision, if the pen
2556 			// location is in View coordinates (I think it should be) or in
2557 			// screen coordinates.
2558 			fCurrentView->CurrentState()->SetPenLocation(penPos);
2559 			break;
2560 		}
2561 		case AS_VIEW_INVERT_RECT:
2562 		{
2563 			BRect rect;
2564 			if (link.Read<BRect>(&rect) != B_OK)
2565 				break;
2566 
2567 			DTRACE(("ServerWindow %s: Message AS_INVERT_RECT: View: %s -> "
2568 				"BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2569 				fCurrentView->Name(), rect.left, rect.top, rect.right,
2570 				rect.bottom));
2571 
2572 			fCurrentView->PenToScreenTransform().Apply(&rect);
2573 			drawingEngine->InvertRect(rect);
2574 			break;
2575 		}
2576 		case AS_STROKE_RECT:
2577 		{
2578 			BRect rect;
2579 			if (link.Read<BRect>(&rect) != B_OK)
2580 				break;
2581 
2582 			DTRACE(("ServerWindow %s: Message AS_STROKE_RECT: View: %s -> "
2583 				"BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2584 				fCurrentView->Name(), rect.left, rect.top, rect.right,
2585 				rect.bottom));
2586 
2587 			fCurrentView->PenToScreenTransform().Apply(&rect);
2588 			drawingEngine->StrokeRect(rect);
2589 			break;
2590 		}
2591 		case AS_FILL_RECT:
2592 		{
2593 			BRect rect;
2594 			if (link.Read<BRect>(&rect) != B_OK)
2595 				break;
2596 
2597 			DTRACE(("ServerWindow %s: Message AS_FILL_RECT: View: %s -> "
2598 				"BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2599 				fCurrentView->Name(), rect.left, rect.top, rect.right,
2600 				rect.bottom));
2601 
2602 			fCurrentView->PenToScreenTransform().Apply(&rect);
2603 			drawingEngine->FillRect(rect);
2604 			break;
2605 		}
2606 		case AS_FILL_RECT_GRADIENT:
2607 		{
2608 			BRect rect;
2609 			link.Read<BRect>(&rect);
2610 			BGradient* gradient;
2611 			if (link.ReadGradient(&gradient) != B_OK)
2612 				break;
2613 
2614 			GTRACE(("ServerWindow %s: Message AS_FILL_RECT_GRADIENT: View: %s "
2615 				"-> BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2616 				fCurrentView->Name(), rect.left, rect.top, rect.right,
2617 				rect.bottom));
2618 
2619 			const SimpleTransform transform =
2620 				fCurrentView->PenToScreenTransform();
2621 			transform.Apply(&rect);
2622 			transform.Apply(gradient);
2623 			drawingEngine->FillRect(rect, *gradient);
2624 			delete gradient;
2625 			break;
2626 		}
2627 		case AS_VIEW_DRAW_BITMAP:
2628 		{
2629 			ViewDrawBitmapInfo info;
2630 			if (link.Read<ViewDrawBitmapInfo>(&info) != B_OK)
2631 				break;
2632 
2633 #if 0
2634 			if (strcmp(fServerApp->SignatureLeaf(), "x-vnd.videolan-vlc") == 0)
2635 				info.options |= B_FILTER_BITMAP_BILINEAR;
2636 #endif
2637 
2638 			BReference<ServerBitmap> bitmap(fServerApp->GetBitmap(info.bitmapToken), true);
2639 			if (bitmap != NULL) {
2640 				DTRACE(("ServerWindow %s: Message AS_VIEW_DRAW_BITMAP: "
2641 					"View: %s, bitmap: %" B_PRId32 " (size %" B_PRId32 " x "
2642 					"%" B_PRId32 "), BRect(%.1f, %.1f, %.1f, %.1f) -> "
2643 					"BRect(%.1f, %.1f, %.1f, %.1f)\n",
2644 					fTitle, fCurrentView->Name(), info.bitmapToken,
2645 					bitmap->Width(), bitmap->Height(),
2646 					info.bitmapRect.left, info.bitmapRect.top,
2647 					info.bitmapRect.right, info.bitmapRect.bottom,
2648 					info.viewRect.left, info.viewRect.top,
2649 					info.viewRect.right, info.viewRect.bottom));
2650 
2651 				fCurrentView->PenToScreenTransform().Apply(&info.viewRect);
2652 
2653 // TODO: Unbreak...
2654 //				if ((info.options & B_WAIT_FOR_RETRACE) != 0)
2655 //					fDesktop->HWInterface()->WaitForRetrace(20000);
2656 
2657 				drawingEngine->DrawBitmap(bitmap, info.bitmapRect,
2658 					info.viewRect, info.options);
2659 			}
2660 			break;
2661 		}
2662 		case AS_STROKE_ARC:
2663 		case AS_FILL_ARC:
2664 		{
2665 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ARC\n", Title()));
2666 
2667 			float angle, span;
2668 			BRect r;
2669 
2670 			link.Read<BRect>(&r);
2671 			link.Read<float>(&angle);
2672 			if (link.Read<float>(&span) != B_OK)
2673 				break;
2674 
2675 			fCurrentView->PenToScreenTransform().Apply(&r);
2676 			drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC);
2677 			break;
2678 		}
2679 		case AS_FILL_ARC_GRADIENT:
2680 		{
2681 			GTRACE(("ServerWindow %s: Message AS_FILL_ARC_GRADIENT\n",
2682 				Title()));
2683 
2684 			float angle, span;
2685 			BRect r;
2686 			link.Read<BRect>(&r);
2687 			link.Read<float>(&angle);
2688 			link.Read<float>(&span);
2689 			BGradient* gradient;
2690 			if (link.ReadGradient(&gradient) != B_OK)
2691 				break;
2692 			const SimpleTransform transform =
2693 				fCurrentView->PenToScreenTransform();
2694 			transform.Apply(&r);
2695 			transform.Apply(gradient);
2696 			drawingEngine->FillArc(r, angle, span, *gradient);
2697 			delete gradient;
2698 			break;
2699 		}
2700 		case AS_STROKE_BEZIER:
2701 		case AS_FILL_BEZIER:
2702 		{
2703 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n",
2704 				Title()));
2705 
2706 			const SimpleTransform transform =
2707 				fCurrentView->PenToScreenTransform();
2708 			BPoint pts[4];
2709 			status_t status;
2710 			for (int32 i = 0; i < 4; i++) {
2711 				status = link.Read<BPoint>(&(pts[i]));
2712 				transform.Apply(&pts[i]);
2713 			}
2714 			if (status != B_OK)
2715 				break;
2716 
2717 			drawingEngine->DrawBezier(pts, code == AS_FILL_BEZIER);
2718 			break;
2719 		}
2720 		case AS_FILL_BEZIER_GRADIENT:
2721 		{
2722 			GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n",
2723 				Title()));
2724 
2725 			const SimpleTransform transform =
2726 				fCurrentView->PenToScreenTransform();
2727 			BPoint pts[4];
2728 			for (int32 i = 0; i < 4; i++) {
2729 				link.Read<BPoint>(&(pts[i]));
2730 				transform.Apply(&pts[i]);
2731 			}
2732 			BGradient* gradient;
2733 			if (link.ReadGradient(&gradient) != B_OK)
2734 				break;
2735 			transform.Apply(gradient);
2736 			drawingEngine->FillBezier(pts, *gradient);
2737 			delete gradient;
2738 			break;
2739 		}
2740 		case AS_STROKE_ELLIPSE:
2741 		case AS_FILL_ELLIPSE:
2742 		{
2743 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ELLIPSE\n",
2744 				Title()));
2745 
2746 			BRect rect;
2747 			if (link.Read<BRect>(&rect) != B_OK)
2748 				break;
2749 
2750 			fCurrentView->PenToScreenTransform().Apply(&rect);
2751 			drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE);
2752 			break;
2753 		}
2754 		case AS_FILL_ELLIPSE_GRADIENT:
2755 		{
2756 			GTRACE(("ServerWindow %s: Message AS_FILL_ELLIPSE_GRADIENT\n",
2757 				Title()));
2758 
2759 			BRect rect;
2760 			link.Read<BRect>(&rect);
2761 			BGradient* gradient;
2762 			if (link.ReadGradient(&gradient) != B_OK)
2763 				break;
2764 			const SimpleTransform transform =
2765 				fCurrentView->PenToScreenTransform();
2766 			transform.Apply(&rect);
2767 			transform.Apply(gradient);
2768 			drawingEngine->FillEllipse(rect, *gradient);
2769 			delete gradient;
2770 			break;
2771 		}
2772 		case AS_STROKE_ROUNDRECT:
2773 		case AS_FILL_ROUNDRECT:
2774 		{
2775 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ROUNDRECT\n",
2776 				Title()));
2777 
2778 			BRect rect;
2779 			float xRadius;
2780 			float yRadius;
2781 			link.Read<BRect>(&rect);
2782 			link.Read<float>(&xRadius);
2783 			if (link.Read<float>(&yRadius) != B_OK)
2784 				break;
2785 
2786 			fCurrentView->PenToScreenTransform().Apply(&rect);
2787 			float scale = fCurrentView->CurrentState()->CombinedScale();
2788 			drawingEngine->DrawRoundRect(rect, xRadius * scale, yRadius * scale,
2789 				code == AS_FILL_ROUNDRECT);
2790 			break;
2791 		}
2792 		case AS_FILL_ROUNDRECT_GRADIENT:
2793 		{
2794 			GTRACE(("ServerWindow %s: Message AS_FILL_ROUNDRECT_GRADIENT\n",
2795 				Title()));
2796 
2797 			BRect rect;
2798 			float xrad,yrad;
2799 			link.Read<BRect>(&rect);
2800 			link.Read<float>(&xrad);
2801 			link.Read<float>(&yrad);
2802 			BGradient* gradient;
2803 			if (link.ReadGradient(&gradient) != B_OK)
2804 				break;
2805 			const SimpleTransform transform =
2806 				fCurrentView->PenToScreenTransform();
2807 			transform.Apply(&rect);
2808 			transform.Apply(gradient);
2809 			drawingEngine->FillRoundRect(rect, xrad, yrad, *gradient);
2810 			delete gradient;
2811 			break;
2812 		}
2813 		case AS_STROKE_TRIANGLE:
2814 		case AS_FILL_TRIANGLE:
2815 		{
2816 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n",
2817 				Title()));
2818 
2819 			const SimpleTransform transform =
2820 				fCurrentView->PenToScreenTransform();
2821 			BPoint pts[3];
2822 			BRect rect;
2823 
2824 			for (int32 i = 0; i < 3; i++) {
2825 				link.Read<BPoint>(&(pts[i]));
2826 				transform.Apply(&pts[i]);
2827 			}
2828 
2829 			if (link.Read<BRect>(&rect) != B_OK)
2830 				break;
2831 
2832 			transform.Apply(&rect);
2833 			drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE);
2834 			break;
2835 		}
2836 		case AS_FILL_TRIANGLE_GRADIENT:
2837 		{
2838 			DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n",
2839 				Title()));
2840 
2841 			const SimpleTransform transform =
2842 				fCurrentView->PenToScreenTransform();
2843 			BPoint pts[3];
2844 			BRect rect;
2845 			for (int32 i = 0; i < 3; i++) {
2846 				link.Read<BPoint>(&(pts[i]));
2847 				transform.Apply(&pts[i]);
2848 			}
2849 			link.Read<BRect>(&rect);
2850 			BGradient* gradient;
2851 			if (link.ReadGradient(&gradient) != B_OK)
2852 				break;
2853 			transform.Apply(&rect);
2854 			transform.Apply(gradient);
2855 			drawingEngine->FillTriangle(pts, rect, *gradient);
2856 			delete gradient;
2857 			break;
2858 		}
2859 		case AS_STROKE_POLYGON:
2860 		case AS_FILL_POLYGON:
2861 		{
2862 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_POLYGON\n",
2863 				Title()));
2864 
2865 			BRect polyFrame;
2866 			bool isClosed = true;
2867 			int32 pointCount;
2868 
2869 			link.Read<BRect>(&polyFrame);
2870 			if (code == AS_STROKE_POLYGON)
2871 				link.Read<bool>(&isClosed);
2872 			link.Read<int32>(&pointCount);
2873 
2874 			const SimpleTransform transform =
2875 				fCurrentView->PenToScreenTransform();
2876 			BPoint* pointList = new(nothrow) BPoint[pointCount];
2877 			if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
2878 				for (int32 i = 0; i < pointCount; i++)
2879 					transform.Apply(&pointList[i]);
2880 				transform.Apply(&polyFrame);
2881 
2882 				drawingEngine->DrawPolygon(pointList, pointCount, polyFrame,
2883 					code == AS_FILL_POLYGON, isClosed && pointCount > 2);
2884 			}
2885 			delete[] pointList;
2886 			break;
2887 		}
2888 		case AS_FILL_POLYGON_GRADIENT:
2889 		{
2890 			DTRACE(("ServerWindow %s: Message AS_FILL_POLYGON_GRADIENT\n",
2891 				Title()));
2892 
2893 			BRect polyFrame;
2894 			bool isClosed = true;
2895 			int32 pointCount;
2896 			link.Read<BRect>(&polyFrame);
2897 			link.Read<int32>(&pointCount);
2898 
2899 			const SimpleTransform transform =
2900 				fCurrentView->PenToScreenTransform();
2901 			BPoint* pointList = new(nothrow) BPoint[pointCount];
2902 			BGradient* gradient;
2903 			if (link.Read(pointList, pointCount * sizeof(BPoint)) == B_OK
2904 				&& link.ReadGradient(&gradient) == B_OK) {
2905 				for (int32 i = 0; i < pointCount; i++)
2906 					transform.Apply(&pointList[i]);
2907 				transform.Apply(&polyFrame);
2908 				transform.Apply(gradient);
2909 
2910 				drawingEngine->FillPolygon(pointList, pointCount,
2911 					polyFrame, *gradient, isClosed && pointCount > 2);
2912 				delete gradient;
2913 			}
2914 			delete[] pointList;
2915 			break;
2916 		}
2917 		case AS_STROKE_SHAPE:
2918 		case AS_FILL_SHAPE:
2919 		{
2920 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_SHAPE\n",
2921 				Title()));
2922 
2923 			BRect shapeFrame;
2924 			int32 opCount;
2925 			int32 ptCount;
2926 
2927 			link.Read<BRect>(&shapeFrame);
2928 			link.Read<int32>(&opCount);
2929 			link.Read<int32>(&ptCount);
2930 
2931 			uint32* opList = new(nothrow) uint32[opCount];
2932 			BPoint* ptList = new(nothrow) BPoint[ptCount];
2933 			if (link.Read(opList, opCount * sizeof(uint32)) >= B_OK &&
2934 				link.Read(ptList, ptCount * sizeof(BPoint)) >= B_OK) {
2935 
2936 				// this might seem a bit weird, but under R5, the shapes
2937 				// are always offset by the current pen location
2938 				BPoint screenOffset
2939 					= fCurrentView->CurrentState()->PenLocation();
2940 				shapeFrame.OffsetBy(screenOffset);
2941 
2942 				const SimpleTransform transform =
2943 					fCurrentView->PenToScreenTransform();
2944 				transform.Apply(&screenOffset);
2945 				transform.Apply(&shapeFrame);
2946 
2947 				drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount,
2948 					ptList, code == AS_FILL_SHAPE, screenOffset,
2949 					fCurrentView->Scale());
2950 			}
2951 
2952 			delete[] opList;
2953 			delete[] ptList;
2954 			break;
2955 		}
2956 		case AS_FILL_SHAPE_GRADIENT:
2957 		{
2958 			DTRACE(("ServerWindow %s: Message AS_FILL_SHAPE_GRADIENT\n",
2959 				Title()));
2960 
2961 			BRect shapeFrame;
2962 			int32 opCount;
2963 			int32 ptCount;
2964 
2965 			link.Read<BRect>(&shapeFrame);
2966 			link.Read<int32>(&opCount);
2967 			link.Read<int32>(&ptCount);
2968 
2969 			uint32* opList = new(nothrow) uint32[opCount];
2970 			BPoint* ptList = new(nothrow) BPoint[ptCount];
2971 			BGradient* gradient;
2972 			if (link.Read(opList, opCount * sizeof(uint32)) == B_OK
2973 				&& link.Read(ptList, ptCount * sizeof(BPoint)) == B_OK
2974 				&& link.ReadGradient(&gradient) == B_OK) {
2975 
2976 				// this might seem a bit weird, but under R5, the shapes
2977 				// are always offset by the current pen location
2978 				BPoint screenOffset
2979 					= fCurrentView->CurrentState()->PenLocation();
2980 				shapeFrame.OffsetBy(screenOffset);
2981 
2982 				const SimpleTransform transform =
2983 					fCurrentView->PenToScreenTransform();
2984 				transform.Apply(&screenOffset);
2985 				transform.Apply(&shapeFrame);
2986 				transform.Apply(gradient);
2987 				drawingEngine->FillShape(shapeFrame, opCount, opList,
2988 					ptCount, ptList, *gradient, screenOffset,
2989 					fCurrentView->Scale());
2990 				delete gradient;
2991 			}
2992 
2993 			delete[] opList;
2994 			delete[] ptList;
2995 			break;
2996 		}
2997 		case AS_FILL_REGION:
2998 		{
2999 			DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title()));
3000 
3001 			BRegion region;
3002 			if (link.ReadRegion(&region) < B_OK)
3003 				break;
3004 
3005 			fCurrentView->PenToScreenTransform().Apply(&region);
3006 			drawingEngine->FillRegion(region);
3007 
3008 			break;
3009 		}
3010 		case AS_FILL_REGION_GRADIENT:
3011 		{
3012 			DTRACE(("ServerWindow %s: Message AS_FILL_REGION_GRADIENT\n",
3013 				Title()));
3014 
3015 			BRegion region;
3016 			link.ReadRegion(&region);
3017 
3018 			BGradient* gradient;
3019 			if (link.ReadGradient(&gradient) != B_OK)
3020 				break;
3021 
3022 			const SimpleTransform transform =
3023 				fCurrentView->PenToScreenTransform();
3024 			transform.Apply(&region);
3025 			transform.Apply(gradient);
3026 			drawingEngine->FillRegion(region, *gradient);
3027 			delete gradient;
3028 			break;
3029 		}
3030 		case AS_STROKE_LINEARRAY:
3031 		{
3032 			DTRACE(("ServerWindow %s: Message AS_STROKE_LINEARRAY\n",
3033 				Title()));
3034 
3035 			// Attached Data:
3036 			// 1) int32 Number of lines in the array
3037 			// 2) LineArrayData
3038 
3039 			int32 lineCount;
3040 			if (link.Read<int32>(&lineCount) != B_OK || lineCount <= 0)
3041 				break;
3042 
3043 			// To speed things up, try to use a stack allocation and only
3044 			// fall back to the heap if there are enough lines...
3045 			ViewLineArrayInfo* lineData;
3046 			const int32 kStackBufferLineDataCount = 64;
3047 			ViewLineArrayInfo lineDataStackBuffer[kStackBufferLineDataCount];
3048 			if (lineCount > kStackBufferLineDataCount) {
3049 				lineData = new(std::nothrow) ViewLineArrayInfo[lineCount];
3050 				if (lineData == NULL)
3051 					break;
3052 			} else
3053 				lineData = lineDataStackBuffer;
3054 
3055 			// Read them all in one go
3056 			size_t dataSize = lineCount * sizeof(ViewLineArrayInfo);
3057 			if (link.Read(lineData, dataSize) != B_OK) {
3058 				if (lineData != lineDataStackBuffer)
3059 					delete[] lineData;
3060 				break;
3061 			}
3062 
3063 			// Convert to screen coords and draw
3064 			const SimpleTransform transform =
3065 				fCurrentView->PenToScreenTransform();
3066 			for (int32 i = 0; i < lineCount; i++) {
3067 				transform.Apply(&lineData[i].startPoint);
3068 				transform.Apply(&lineData[i].endPoint);
3069 			}
3070 			drawingEngine->StrokeLineArray(lineCount, lineData);
3071 
3072 			if (lineData != lineDataStackBuffer)
3073 				delete[] lineData;
3074 			break;
3075 		}
3076 		case AS_DRAW_STRING:
3077 		case AS_DRAW_STRING_WITH_DELTA:
3078 		{
3079 			ViewDrawStringInfo info;
3080 			if (link.Read<ViewDrawStringInfo>(&info) != B_OK
3081 				|| info.stringLength <= 0) {
3082 				break;
3083 			}
3084 
3085 			// NOTE: Careful, the + 1 is for termination!
3086 			BStackOrHeapArray<char, 4096> string(
3087 				(info.stringLength + 1 + 63) / 64 * 64);
3088 			if (!string.IsValid())
3089 				break;
3090 
3091 			escapement_delta* delta = NULL;
3092 			if (code == AS_DRAW_STRING_WITH_DELTA) {
3093 				// In this case, info.delta will contain valid values.
3094 				delta = &info.delta;
3095 			}
3096 
3097 			if (link.Read(string, info.stringLength) != B_OK)
3098 				break;
3099 
3100 			// Terminate the string, if nothing else, it's important
3101 			// for the DTRACE call below...
3102 			string[info.stringLength] = '\0';
3103 
3104 			DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View: %s "
3105 				"-> %s\n", Title(), fCurrentView->Name(), string));
3106 
3107 			fCurrentView->PenToScreenTransform().Apply(&info.location);
3108 			BPoint penLocation = drawingEngine->DrawString(string,
3109 				info.stringLength, info.location, delta);
3110 
3111 			fCurrentView->ScreenToPenTransform().Apply(&penLocation);
3112 			fCurrentView->CurrentState()->SetPenLocation(penLocation);
3113 
3114 			break;
3115 		}
3116 		case AS_DRAW_STRING_WITH_OFFSETS:
3117 		{
3118 			int32 stringLength;
3119 			if (link.Read<int32>(&stringLength) != B_OK || stringLength <= 0)
3120 				break;
3121 
3122 			int32 glyphCount;
3123 			if (link.Read<int32>(&glyphCount) != B_OK || glyphCount <= 0)
3124 				break;
3125 
3126 			// NOTE: Careful, the + 1 is for termination!
3127 			BStackOrHeapArray<char, 512> string(
3128 				(stringLength + 1 + 63) / 64 * 64);
3129 			BStackOrHeapArray<BPoint, 512> locations(glyphCount);
3130 			if (!string.IsValid() || !locations.IsValid())
3131 				break;
3132 
3133 			if (link.Read(string, stringLength) != B_OK)
3134 				break;
3135 			// Count UTF8 glyphs and make sure we have enough locations
3136 			if ((int32)UTF8CountChars(string, stringLength) > glyphCount)
3137 				break;
3138 			if (link.Read(locations, glyphCount * sizeof(BPoint)) != B_OK)
3139 				break;
3140 			// Terminate the string, if nothing else, it's important
3141 			// for the DTRACE call below...
3142 			string[stringLength] = '\0';
3143 
3144 			DTRACE(("ServerWindow %s: Message AS_DRAW_STRING_WITH_OFFSETS, View: %s "
3145 				"-> %s\n", Title(), fCurrentView->Name(), string));
3146 
3147 			const SimpleTransform transform =
3148 				fCurrentView->PenToScreenTransform();
3149 			for (int32 i = 0; i < glyphCount; i++)
3150 				transform.Apply(&locations[i]);
3151 
3152 			BPoint penLocation = drawingEngine->DrawString(string,
3153 				stringLength, locations);
3154 
3155 			fCurrentView->ScreenToPenTransform().Apply(&penLocation);
3156 			fCurrentView->CurrentState()->SetPenLocation(penLocation);
3157 
3158 			break;
3159 		}
3160 
3161 		case AS_VIEW_DRAW_PICTURE:
3162 		{
3163 			int32 token;
3164 			link.Read<int32>(&token);
3165 
3166 			BPoint where;
3167 			if (link.Read<BPoint>(&where) == B_OK) {
3168 				BReference<ServerPicture> picture(App()->GetPicture(token), true);
3169 				if (picture != NULL) {
3170 					// Setting the drawing origin outside of the
3171 					// state makes sure that everything the picture
3172 					// does is relative to the global picture offset.
3173 					fCurrentView->PushState();
3174 					fCurrentView->SetDrawingOrigin(where);
3175 
3176 					fCurrentView->PushState();
3177 					picture->Play(fCurrentView);
3178 					fCurrentView->PopState();
3179 
3180 					fCurrentView->PopState();
3181 				}
3182 			}
3183 			break;
3184 		}
3185 
3186 		case AS_VIEW_END_LAYER:
3187 		{
3188 			DTRACE(("ServerWindow %s: Message AS_VIEW_END_LAYER\n",
3189 				Title()));
3190 
3191 			fCurrentView->BlendAllLayers();
3192 			fCurrentView->SetPicture(NULL);
3193 			fCurrentView->CurrentState()->SetDrawingModeLocked(false);
3194 			break;
3195 		}
3196 
3197 		default:
3198 			debug_printf("ServerWindow %s received unexpected code: %s\n",
3199 				Title(), string_for_message_code(code));
3200 
3201 			if (link.NeedsReply()) {
3202 				// the client is now blocking and waiting for a reply!
3203 				fLink.StartMessage(B_ERROR);
3204 				fLink.Flush();
3205 			}
3206 			break;
3207 	}
3208 
3209 	drawingEngine->UnlockParallelAccess();
3210 }
3211 
3212 
3213 bool
3214 ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link)
3215 {
3216 	ServerPicture* picture = fCurrentView->Picture();
3217 	if (picture == NULL)
3218 		return false;
3219 
3220 	switch (code) {
3221 		case AS_VIEW_SET_ORIGIN:
3222 		{
3223 			float x, y;
3224 			link.Read<float>(&x);
3225 			link.Read<float>(&y);
3226 
3227 			fCurrentView->SetDrawingOrigin(BPoint(x, y));
3228 			picture->WriteSetOrigin(BPoint(x, y));
3229 			break;
3230 		}
3231 
3232 		case AS_VIEW_INVERT_RECT:
3233 		{
3234 			BRect rect;
3235 			link.Read<BRect>(&rect);
3236 			picture->WriteInvertRect(rect);
3237 			break;
3238 		}
3239 
3240 		case AS_VIEW_PUSH_STATE:
3241 		{
3242 			fCurrentView->PushState();
3243 			picture->WritePushState();
3244 			break;
3245 		}
3246 
3247 		case AS_VIEW_POP_STATE:
3248 		{
3249 			fCurrentView->PopState();
3250 			picture->WritePopState();
3251 			break;
3252 		}
3253 
3254 		case AS_VIEW_SET_DRAWING_MODE:
3255 		{
3256 			int8 drawingMode;
3257 			link.Read<int8>(&drawingMode);
3258 
3259 			picture->WriteSetDrawingMode((drawing_mode)drawingMode);
3260 
3261 			fCurrentView->CurrentState()->SetDrawingMode(
3262 				(drawing_mode)drawingMode);
3263 			fWindow->GetDrawingEngine()->SetDrawingMode(
3264 				(drawing_mode)drawingMode);
3265 			break;
3266 		}
3267 
3268 		case AS_VIEW_SET_PEN_LOC:
3269 		{
3270 			BPoint location;
3271 			link.Read<BPoint>(&location);
3272 			picture->WriteSetPenLocation(location);
3273 
3274 			fCurrentView->CurrentState()->SetPenLocation(location);
3275 			break;
3276 		}
3277 
3278 		case AS_VIEW_SET_PEN_SIZE:
3279 		{
3280 			float penSize;
3281 			link.Read<float>(&penSize);
3282 			picture->WriteSetPenSize(penSize);
3283 
3284 			fCurrentView->CurrentState()->SetPenSize(penSize);
3285 			fWindow->GetDrawingEngine()->SetPenSize(
3286 				fCurrentView->CurrentState()->PenSize());
3287 			break;
3288 		}
3289 
3290 		case AS_VIEW_SET_LINE_MODE:
3291 		{
3292 
3293 			ViewSetLineModeInfo info;
3294 			link.Read<ViewSetLineModeInfo>(&info);
3295 
3296 			picture->WriteSetLineMode(info.lineCap, info.lineJoin,
3297 				info.miterLimit);
3298 
3299 			fCurrentView->CurrentState()->SetLineCapMode(info.lineCap);
3300 			fCurrentView->CurrentState()->SetLineJoinMode(info.lineJoin);
3301 			fCurrentView->CurrentState()->SetMiterLimit(info.miterLimit);
3302 
3303 			fWindow->GetDrawingEngine()->SetStrokeMode(info.lineCap,
3304 				info.lineJoin, info.miterLimit);
3305 			break;
3306 		}
3307 		case AS_VIEW_SET_FILL_RULE:
3308 		{
3309 			int32 fillRule;
3310 			if (link.Read<int32>(&fillRule) != B_OK)
3311 				break;
3312 
3313 			picture->WriteSetFillRule(fillRule);
3314 
3315 			fCurrentView->CurrentState()->SetFillRule(fillRule);
3316 			fWindow->GetDrawingEngine()->SetFillRule(fillRule);
3317 
3318 			break;
3319 		}
3320 		case AS_VIEW_SET_SCALE:
3321 		{
3322 			float scale;
3323 			if (link.Read<float>(&scale) != B_OK)
3324 				break;
3325 
3326 			picture->WriteSetScale(scale);
3327 
3328 			fCurrentView->SetScale(scale);
3329 			_UpdateDrawState(fCurrentView);
3330 			break;
3331 		}
3332 		case AS_VIEW_SET_TRANSFORM:
3333 		{
3334 			BAffineTransform transform;
3335 			if (link.Read<BAffineTransform>(&transform) != B_OK)
3336 				break;
3337 
3338 			picture->WriteSetTransform(transform);
3339 
3340 			fCurrentView->CurrentState()->SetTransform(transform);
3341 			_UpdateDrawState(fCurrentView);
3342 			break;
3343 		}
3344 
3345 		case AS_VIEW_AFFINE_TRANSLATE:
3346 		{
3347 			double x, y;
3348 			link.Read<double>(&x);
3349 			link.Read<double>(&y);
3350 
3351 			picture->WriteTranslateBy(x, y);
3352 
3353 			BAffineTransform current =
3354 				fCurrentView->CurrentState()->Transform();
3355 			current.PreTranslateBy(x, y);
3356 			fCurrentView->CurrentState()->SetTransform(current);
3357 			_UpdateDrawState(fCurrentView);
3358 			break;
3359 		}
3360 
3361 		case AS_VIEW_AFFINE_SCALE:
3362 		{
3363 			double x, y;
3364 			link.Read<double>(&x);
3365 			link.Read<double>(&y);
3366 
3367 			picture->WriteScaleBy(x, y);
3368 
3369 			BAffineTransform current =
3370 				fCurrentView->CurrentState()->Transform();
3371 			current.PreScaleBy(x, y);
3372 			fCurrentView->CurrentState()->SetTransform(current);
3373 			_UpdateDrawState(fCurrentView);
3374 			break;
3375 		}
3376 
3377 		case AS_VIEW_AFFINE_ROTATE:
3378 		{
3379 			double angleRadians;
3380 			link.Read<double>(&angleRadians);
3381 
3382 			picture->WriteRotateBy(angleRadians);
3383 
3384 			BAffineTransform current =
3385 				fCurrentView->CurrentState()->Transform();
3386 			current.PreRotateBy(angleRadians);
3387 			fCurrentView->CurrentState()->SetTransform(current);
3388 			_UpdateDrawState(fCurrentView);
3389 			break;
3390 		}
3391 
3392 
3393 		case AS_VIEW_SET_PATTERN:
3394 		{
3395 			pattern pat;
3396 			link.Read(&pat, sizeof(pattern));
3397 			picture->WriteSetPattern(pat);
3398 			break;
3399 		}
3400 
3401 		case AS_VIEW_SET_FONT_STATE:
3402 		{
3403 			uint16 mask = fCurrentView->CurrentState()->ReadFontFromLink(link);
3404 			fWindow->GetDrawingEngine()->SetFont(
3405 				fCurrentView->CurrentState());
3406 
3407 			picture->WriteFontState(fCurrentView->CurrentState()->Font(), mask);
3408 			break;
3409 		}
3410 
3411 		case AS_FILL_RECT:
3412 		case AS_STROKE_RECT:
3413 		{
3414 			BRect rect;
3415 			link.Read<BRect>(&rect);
3416 
3417 			picture->WriteDrawRect(rect, code == AS_FILL_RECT);
3418 			break;
3419 		}
3420 
3421 		case AS_FILL_REGION:
3422 		{
3423 			// There is no B_PIC_FILL_REGION op, we have to
3424 			// implement it using B_PIC_FILL_RECT
3425 			BRegion region;
3426 			if (link.ReadRegion(&region) < B_OK)
3427 				break;
3428 			for (int32 i = 0; i < region.CountRects(); i++)
3429 				picture->WriteDrawRect(region.RectAt(i), true);
3430 			break;
3431 		}
3432 
3433 		case AS_STROKE_ROUNDRECT:
3434 		case AS_FILL_ROUNDRECT:
3435 		{
3436 			BRect rect;
3437 			link.Read<BRect>(&rect);
3438 
3439 			BPoint radii;
3440 			link.Read<float>(&radii.x);
3441 			link.Read<float>(&radii.y);
3442 
3443 			picture->WriteDrawRoundRect(rect, radii, code == AS_FILL_ROUNDRECT);
3444 			break;
3445 		}
3446 
3447 		case AS_STROKE_ELLIPSE:
3448 		case AS_FILL_ELLIPSE:
3449 		{
3450 			BRect rect;
3451 			link.Read<BRect>(&rect);
3452 			picture->WriteDrawEllipse(rect, code == AS_FILL_ELLIPSE);
3453 			break;
3454 		}
3455 
3456 		case AS_STROKE_ARC:
3457 		case AS_FILL_ARC:
3458 		{
3459 			BRect rect;
3460 			link.Read<BRect>(&rect);
3461 			float startTheta, arcTheta;
3462 			link.Read<float>(&startTheta);
3463 			link.Read<float>(&arcTheta);
3464 
3465 			BPoint radii((rect.Width() + 1) / 2, (rect.Height() + 1) / 2);
3466 			BPoint center = rect.LeftTop() + radii;
3467 
3468 			picture->WriteDrawArc(center, radii, startTheta, arcTheta,
3469 				code == AS_FILL_ARC);
3470 			break;
3471 		}
3472 
3473 		case AS_STROKE_TRIANGLE:
3474 		case AS_FILL_TRIANGLE:
3475 		{
3476 			// There is no B_PIC_FILL/STROKE_TRIANGLE op,
3477 			// we implement it using B_PIC_FILL/STROKE_POLYGON
3478 			BPoint points[3];
3479 
3480 			for (int32 i = 0; i < 3; i++) {
3481 				link.Read<BPoint>(&(points[i]));
3482 			}
3483 
3484 			BRect rect;
3485 			link.Read<BRect>(&rect);
3486 
3487 			picture->WriteDrawPolygon(3, points,
3488 					true, code == AS_FILL_TRIANGLE);
3489 			break;
3490 		}
3491 		case AS_STROKE_POLYGON:
3492 		case AS_FILL_POLYGON:
3493 		{
3494 			BRect polyFrame;
3495 			bool isClosed = true;
3496 			int32 pointCount;
3497 			const bool fill = (code == AS_FILL_POLYGON);
3498 
3499 			link.Read<BRect>(&polyFrame);
3500 			if (code == AS_STROKE_POLYGON)
3501 				link.Read<bool>(&isClosed);
3502 			link.Read<int32>(&pointCount);
3503 
3504 			BPoint* pointList = new(nothrow) BPoint[pointCount];
3505 			if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
3506 				picture->WriteDrawPolygon(pointCount, pointList,
3507 					isClosed && pointCount > 2, fill);
3508 			}
3509 			delete[] pointList;
3510 			break;
3511 		}
3512 
3513 		case AS_STROKE_BEZIER:
3514 		case AS_FILL_BEZIER:
3515 		{
3516 			BPoint points[4];
3517 			for (int32 i = 0; i < 4; i++) {
3518 				link.Read<BPoint>(&(points[i]));
3519 			}
3520 			picture->WriteDrawBezier(points, code == AS_FILL_BEZIER);
3521 			break;
3522 		}
3523 
3524 		//case AS_STROKE_RECT_GRADIENT:
3525 		case AS_FILL_RECT_GRADIENT:
3526 		{
3527 			BRect rect;
3528 			link.Read<BRect>(&rect);
3529 			BGradient* gradient;
3530 			if (link.ReadGradient(&gradient) != B_OK)
3531 				break;
3532 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3533 
3534 			picture->WriteDrawRectGradient(rect, *gradient, code == AS_FILL_RECT_GRADIENT);
3535 			break;
3536 		}
3537 
3538 		//case AS_STROKE_ARC_GRADIENT:
3539 		case AS_FILL_ARC_GRADIENT:
3540 		{
3541 			BRect rect;
3542 			link.Read<BRect>(&rect);
3543 			float startTheta, arcTheta;
3544 			link.Read<float>(&startTheta);
3545 			link.Read<float>(&arcTheta);
3546 			BGradient* gradient;
3547 			if (link.ReadGradient(&gradient) != B_OK)
3548 				break;
3549 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3550 
3551 			BPoint radii((rect.Width() + 1) / 2, (rect.Height() + 1) / 2);
3552 			BPoint center = rect.LeftTop() + radii;
3553 
3554 			picture->WriteDrawArcGradient(center, radii, startTheta, arcTheta, *gradient,
3555 				code == AS_FILL_ARC_GRADIENT);
3556 			break;
3557 		}
3558 
3559 		//case AS_STROKE_BEZIER_GRADIENT:
3560 		case AS_FILL_BEZIER_GRADIENT:
3561 		{
3562 			BPoint points[4];
3563 			for (int32 i = 0; i < 4; i++) {
3564 				link.Read<BPoint>(&(points[i]));
3565 			}
3566 			BGradient* gradient;
3567 			if (link.ReadGradient(&gradient) != B_OK)
3568 				break;
3569 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3570 
3571 			picture->WriteDrawBezierGradient(points, *gradient, code == AS_FILL_BEZIER_GRADIENT);
3572 			break;
3573 		}
3574 
3575 		//case AS_STROKE_ELLIPSE_GRADIENT:
3576 		case AS_FILL_ELLIPSE_GRADIENT:
3577 		{
3578 			BRect rect;
3579 			link.Read<BRect>(&rect);
3580 			BGradient* gradient;
3581 			if (link.ReadGradient(&gradient) != B_OK)
3582 				break;
3583 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3584 
3585 			picture->WriteDrawEllipseGradient(rect, *gradient, code == AS_FILL_ELLIPSE_GRADIENT);
3586 			break;
3587 		}
3588 
3589 		//case AS_STROKE_ROUNDRECT_GRADIENT:
3590 		case AS_FILL_ROUNDRECT_GRADIENT:
3591 		{
3592 			BRect rect;
3593 			link.Read<BRect>(&rect);
3594 
3595 			BPoint radii;
3596 			link.Read<float>(&radii.x);
3597 			link.Read<float>(&radii.y);
3598 			BGradient* gradient;
3599 			if (link.ReadGradient(&gradient) != B_OK)
3600 				break;
3601 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3602 
3603 			picture->WriteDrawRoundRectGradient(rect, radii, *gradient, code == AS_FILL_ROUNDRECT_GRADIENT);
3604 			break;
3605 		}
3606 
3607 		//case AS_STROKE_TRIANGLE_GRADIENT:
3608 		case AS_FILL_TRIANGLE_GRADIENT:
3609 		{
3610 			// There is no B_PIC_FILL/STROKE_TRIANGLE op,
3611 			// we implement it using B_PIC_FILL/STROKE_POLYGON
3612 			BPoint points[3];
3613 
3614 			for (int32 i = 0; i < 3; i++) {
3615 				link.Read<BPoint>(&(points[i]));
3616 			}
3617 
3618 			BRect rect;
3619 			link.Read<BRect>(&rect);
3620 			BGradient* gradient;
3621 			if (link.ReadGradient(&gradient) != B_OK)
3622 				break;
3623 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3624 
3625 			picture->WriteDrawPolygonGradient(3, points,
3626 					true, *gradient, code == AS_FILL_TRIANGLE_GRADIENT);
3627 			break;
3628 		}
3629 
3630 		//case AS_STROKE_POLYGON_GRADIENT:
3631 		case AS_FILL_POLYGON_GRADIENT:
3632 		{
3633 			BRect polyFrame;
3634 			bool isClosed = true;
3635 			int32 pointCount;
3636 			const bool fill = (code == AS_FILL_POLYGON_GRADIENT);
3637 
3638 			link.Read<BRect>(&polyFrame);
3639 			if (code == AS_STROKE_POLYGON)
3640 				link.Read<bool>(&isClosed);
3641 			link.Read<int32>(&pointCount);
3642 
3643 			ArrayDeleter<BPoint> pointList(new(nothrow) BPoint[pointCount]);
3644 			if (link.Read(pointList.Get(), pointCount * sizeof(BPoint)) != B_OK)
3645 				break;
3646 
3647 			BGradient* gradient;
3648 			if (link.ReadGradient(&gradient) != B_OK)
3649 				break;
3650 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3651 
3652 			picture->WriteDrawPolygonGradient(pointCount, pointList.Get(),
3653 				isClosed && pointCount > 2, *gradient, fill);
3654 			break;
3655 		}
3656 
3657 		//case AS_STROKE_SHAPE_GRADIENT:
3658 		case AS_FILL_SHAPE_GRADIENT:
3659 		{
3660 			BRect shapeFrame;
3661 			int32 opCount;
3662 			int32 ptCount;
3663 
3664 			link.Read<BRect>(&shapeFrame);
3665 			link.Read<int32>(&opCount);
3666 			link.Read<int32>(&ptCount);
3667 
3668 			ArrayDeleter<uint32> opList(new(std::nothrow) uint32[opCount]);
3669 			ArrayDeleter<BPoint> ptList(new(std::nothrow) BPoint[ptCount]);
3670 			if (!opList.IsSet() || !ptList.IsSet()
3671 				|| link.Read(opList.Get(), opCount * sizeof(uint32)) != B_OK
3672 				|| link.Read(ptList.Get(), ptCount * sizeof(BPoint)) != B_OK)
3673 				break;
3674 
3675 			BGradient* gradient;
3676 			if (link.ReadGradient(&gradient) != B_OK)
3677 				break;
3678 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3679 
3680 			// This might seem a bit weird, but under BeOS, the shapes
3681 			// are always offset by the current pen location
3682 			BPoint penLocation
3683 				= fCurrentView->CurrentState()->PenLocation();
3684 			for (int32 i = 0; i < ptCount; i++) {
3685 				ptList.Get()[i] += penLocation;
3686 			}
3687 			const bool fill = (code == AS_FILL_SHAPE_GRADIENT);
3688 			picture->WriteDrawShapeGradient(opCount, opList.Get(), ptCount, ptList.Get(), *gradient, fill);
3689 
3690 			break;
3691 		}
3692 
3693 		case AS_FILL_REGION_GRADIENT:
3694 		{
3695 			// There is no B_PIC_FILL_REGION op, we have to
3696 			// implement it using B_PIC_FILL_RECT
3697 			BRegion region;
3698 			if (link.ReadRegion(&region) < B_OK)
3699 				break;
3700 
3701 			BGradient* gradient;
3702 			if (link.ReadGradient(&gradient) != B_OK)
3703 				break;
3704 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3705 
3706 			for (int32 i = 0; i < region.CountRects(); i++)
3707 				picture->WriteDrawRectGradient(region.RectAt(i), *gradient, true);
3708 			break;
3709 		}
3710 
3711 		case AS_STROKE_LINE:
3712 		{
3713 			ViewStrokeLineInfo info;
3714 			link.Read<ViewStrokeLineInfo>(&info);
3715 
3716 			picture->WriteStrokeLine(info.startPoint, info.endPoint);
3717 
3718 			BPoint penPos = info.endPoint;
3719 			const SimpleTransform transform =
3720 				fCurrentView->PenToScreenTransform();
3721 			transform.Apply(&info.endPoint);
3722 			fCurrentView->CurrentState()->SetPenLocation(penPos);
3723 			break;
3724 		}
3725 
3726 		case AS_STROKE_LINEARRAY:
3727 		{
3728 			int32 lineCount;
3729 			if (link.Read<int32>(&lineCount) != B_OK || lineCount <= 0)
3730 				break;
3731 
3732 			// To speed things up, try to use a stack allocation and only
3733 			// fall back to the heap if there are enough lines...
3734 			ViewLineArrayInfo* lineData;
3735 			const int32 kStackBufferLineDataCount = 64;
3736 			ViewLineArrayInfo lineDataStackBuffer[kStackBufferLineDataCount];
3737 			if (lineCount > kStackBufferLineDataCount) {
3738 				lineData = new(std::nothrow) ViewLineArrayInfo[lineCount];
3739 				if (lineData == NULL)
3740 					break;
3741 			} else
3742 				lineData = lineDataStackBuffer;
3743 
3744 			// Read them all in one go
3745 			size_t dataSize = lineCount * sizeof(ViewLineArrayInfo);
3746 			if (link.Read(lineData, dataSize) != B_OK) {
3747 				if (lineData != lineDataStackBuffer)
3748 					delete[] lineData;
3749 				break;
3750 			}
3751 
3752 			picture->WritePushState();
3753 
3754 			for (int32 i = 0; i < lineCount; i++) {
3755 				picture->WriteSetHighColor(lineData[i].color);
3756 				picture->WriteStrokeLine(lineData[i].startPoint,
3757 					lineData[i].endPoint);
3758 			}
3759 
3760 			picture->WritePopState();
3761 
3762 			if (lineData != lineDataStackBuffer)
3763 				delete[] lineData;
3764 			break;
3765 		}
3766 
3767 		case AS_VIEW_SET_LOW_COLOR:
3768 		case AS_VIEW_SET_HIGH_COLOR:
3769 		{
3770 			rgb_color color;
3771 			link.Read(&color, sizeof(rgb_color));
3772 
3773 			if (code == AS_VIEW_SET_HIGH_COLOR) {
3774 				picture->WriteSetHighColor(color);
3775 				fCurrentView->CurrentState()->SetHighColor(color);
3776 				fWindow->GetDrawingEngine()->SetHighColor(color);
3777 			} else {
3778 				picture->WriteSetLowColor(color);
3779 				fCurrentView->CurrentState()->SetLowColor(color);
3780 				fWindow->GetDrawingEngine()->SetLowColor(color);
3781 			}
3782 		}	break;
3783 
3784 		case AS_DRAW_STRING:
3785 		case AS_DRAW_STRING_WITH_DELTA:
3786 		{
3787 			ViewDrawStringInfo info;
3788 			if (link.Read<ViewDrawStringInfo>(&info) != B_OK)
3789 				break;
3790 
3791 			char* string = (char*)malloc(info.stringLength + 1);
3792 			if (string == NULL)
3793 				break;
3794 
3795 			if (code != AS_DRAW_STRING_WITH_DELTA) {
3796 				// In this case, info.delta will NOT contain valid values.
3797 				info.delta = (escapement_delta){ 0, 0 };
3798 			}
3799 
3800 			if (link.Read(string, info.stringLength) != B_OK) {
3801 				free(string);
3802 				break;
3803 			}
3804 			// Terminate the string
3805 			string[info.stringLength] = '\0';
3806 
3807 			picture->WriteDrawString(info.location, string, info.stringLength,
3808 				info.delta);
3809 
3810 			// We need to update the pen location
3811 			fCurrentView->PenToScreenTransform().Apply(&info.location);
3812 			DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
3813 			if (drawingEngine->LockParallelAccess()) {
3814 				BPoint penLocation = drawingEngine->DrawStringDry(
3815 					string, info.stringLength, info.location, &info.delta);
3816 
3817 				fCurrentView->ScreenToPenTransform().Apply(&penLocation);
3818 				fCurrentView->CurrentState()->SetPenLocation(penLocation);
3819 
3820 				drawingEngine->UnlockParallelAccess();
3821 			}
3822 
3823 			free(string);
3824 			break;
3825 		}
3826 
3827 		case AS_DRAW_STRING_WITH_OFFSETS:
3828 		{
3829 			int32 stringLength;
3830 			if (link.Read<int32>(&stringLength) != B_OK || stringLength <= 0)
3831 				break;
3832 
3833 			int32 glyphCount;
3834 			if (link.Read<int32>(&glyphCount) != B_OK || glyphCount <= 0)
3835 				break;
3836 
3837 			// NOTE: Careful, the + 1 is for termination!
3838 			BStackOrHeapArray<char, 512> string(
3839 				(stringLength + 1 + 63) / 64 * 64);
3840 			BStackOrHeapArray<BPoint, 512> locations(glyphCount);
3841 			if (!string.IsValid() || !locations.IsValid())
3842 				break;
3843 
3844 			if (link.Read(string, stringLength) != B_OK)
3845 				break;
3846 			// Count UTF8 glyphs and make sure we have enough locations
3847 			if ((int32)UTF8CountChars(string, stringLength) > glyphCount)
3848 				break;
3849 			if (link.Read(locations, glyphCount * sizeof(BPoint)) != B_OK)
3850 				break;
3851 			// Terminate the string
3852 			string[stringLength] = '\0';
3853 
3854 			const SimpleTransform transform =
3855 				fCurrentView->PenToScreenTransform();
3856 			for (int32 i = 0; i < glyphCount; i++)
3857 				transform.Apply(&locations[i]);
3858 
3859 			picture->WriteDrawString(string, stringLength, locations,
3860 				glyphCount);
3861 
3862 			DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
3863 			if (drawingEngine->LockParallelAccess()) {
3864 				// Update pen location
3865 				BPoint penLocation = drawingEngine->DrawStringDry(
3866 					string, stringLength, locations);
3867 
3868 				fCurrentView->ScreenToPenTransform().Apply(&penLocation);
3869 				fCurrentView->CurrentState()->SetPenLocation(penLocation);
3870 
3871 				drawingEngine->UnlockParallelAccess();
3872 			}
3873 
3874 			break;
3875 		}
3876 
3877 		case AS_STROKE_SHAPE:
3878 		case AS_FILL_SHAPE:
3879 		{
3880 			BRect shapeFrame;
3881 			int32 opCount;
3882 			int32 ptCount;
3883 
3884 			link.Read<BRect>(&shapeFrame);
3885 			link.Read<int32>(&opCount);
3886 			link.Read<int32>(&ptCount);
3887 
3888 			BStackOrHeapArray<uint32, 512> opList(opCount);
3889 			BStackOrHeapArray<BPoint, 512> ptList(ptCount);
3890 			if (!opList.IsValid() || !ptList.IsValid()
3891 				|| link.Read(opList, opCount * sizeof(uint32)) < B_OK
3892 				|| link.Read(ptList, ptCount * sizeof(BPoint)) < B_OK) {
3893 				break;
3894 			}
3895 			picture->WriteDrawShape(opCount, opList, ptCount,
3896 				ptList, code == AS_FILL_SHAPE);
3897 
3898 			break;
3899 		}
3900 
3901 		case AS_VIEW_DRAW_BITMAP:
3902 		{
3903 			ViewDrawBitmapInfo info;
3904 			link.Read<ViewDrawBitmapInfo>(&info);
3905 
3906 			BReference<ServerBitmap> bitmap(App()->GetBitmap(info.bitmapToken), true);
3907 			if (bitmap == NULL)
3908 				break;
3909 
3910 			picture->WriteDrawBitmap(info.bitmapRect, info.viewRect,
3911 				bitmap->Width(), bitmap->Height(), bitmap->BytesPerRow(),
3912 				bitmap->ColorSpace(), info.options, bitmap->Bits(),
3913 				bitmap->BitsLength());
3914 
3915 			break;
3916 		}
3917 
3918 		case AS_VIEW_DRAW_PICTURE:
3919 		{
3920 			int32 token;
3921 			link.Read<int32>(&token);
3922 
3923 			BPoint where;
3924 			if (link.Read<BPoint>(&where) == B_OK) {
3925 				BReference<ServerPicture> pictureToDraw(App()->GetPicture(token), true);
3926 				if (pictureToDraw != NULL) {
3927 					// We need to make a copy of the picture, since it can
3928 					// change after it has been drawn
3929 					BReference<ServerPicture> copy(App()->CreatePicture(pictureToDraw), true);
3930 					picture->NestPicture(copy);
3931 					picture->WriteDrawPicture(where, copy->Token());
3932 				}
3933 			}
3934 			break;
3935 		}
3936 
3937 		case AS_VIEW_SET_CLIP_REGION:
3938 		{
3939 			int32 rectCount;
3940 			status_t status = link.Read<int32>(&rectCount);
3941 				// a negative count means no
3942 				// region for the current draw state,
3943 				// but an *empty* region is actually valid!
3944 				// even if it means no drawing is allowed
3945 
3946 			if (status < B_OK)
3947 				break;
3948 
3949 			if (rectCount >= 0) {
3950 				// we are supposed to set the clipping region
3951 				BRegion region;
3952 				if (rectCount > 0 && link.ReadRegion(&region) < B_OK)
3953 					break;
3954 				picture->WriteSetClipping(region);
3955 			} else {
3956 				// we are supposed to clear the clipping region
3957 				picture->WriteClearClipping();
3958 			}
3959 			break;
3960 		}
3961 
3962 		case AS_VIEW_CLIP_TO_PICTURE:
3963 		{
3964 			int32 pictureToken;
3965 			BPoint where;
3966 			bool inverse = false;
3967 
3968 			link.Read<int32>(&pictureToken);
3969 			if (pictureToken < 0)
3970 				break;
3971 
3972 			link.Read<BPoint>(&where);
3973 			if (link.Read<bool>(&inverse) != B_OK)
3974 				break;
3975 
3976 			BReference<ServerPicture> pictureToClip(fServerApp->GetPicture(pictureToken), true);
3977 			if (pictureToClip != NULL) {
3978 				// We need to make a copy of the picture, since it can
3979 				// change after it has been drawn
3980 				BReference<ServerPicture> copy(App()->CreatePicture(pictureToClip), true);
3981 				picture->NestPicture(copy);
3982 				picture->WriteClipToPicture(copy->Token(), where, inverse);
3983 			}
3984 			break;
3985 		}
3986 
3987 		case AS_VIEW_CLIP_TO_RECT:
3988 		{
3989 			bool inverse;
3990 			BRect rect;
3991 			link.Read<bool>(&inverse);
3992 			link.Read<BRect>(&rect);
3993 			picture->WriteClipToRect(rect, inverse);
3994 
3995 			break;
3996 		}
3997 
3998 		case AS_VIEW_CLIP_TO_SHAPE:
3999 		{
4000 			bool inverse;
4001 			link.Read<bool>(&inverse);
4002 
4003 			shape_data shape;
4004 			link.Read<int32>(&shape.opCount);
4005 			link.Read<int32>(&shape.ptCount);
4006 			shape.opSize = shape.opCount * sizeof(uint32);
4007 			shape.ptSize = shape.ptCount * sizeof(BPoint);
4008 			shape.opList = new(nothrow) uint32[shape.opCount];
4009 			shape.ptList = new(nothrow) BPoint[shape.ptCount];
4010 			if (link.Read(shape.opList, shape.opSize) >= B_OK
4011 				&& link.Read(shape.ptList, shape.ptSize) >= B_OK) {
4012 				picture->WriteClipToShape(shape.opCount, shape.opList,
4013 					shape.ptCount, shape.ptList, inverse);
4014 			}
4015 
4016 			delete[] shape.opList;
4017 			delete[] shape.ptList;
4018 			break;
4019 		}
4020 
4021 		case AS_VIEW_BEGIN_PICTURE:
4022 		{
4023 			BReference <ServerPicture> newPicture(App()->CreatePicture(), true);
4024 			if (newPicture != NULL) {
4025 				newPicture->PushPicture(picture);
4026 				newPicture->SyncState(fCurrentView);
4027 				fCurrentView->SetPicture(newPicture);
4028 			}
4029 			break;
4030 		}
4031 
4032 		case AS_VIEW_APPEND_TO_PICTURE:
4033 		{
4034 			int32 token;
4035 			link.Read<int32>(&token);
4036 
4037 			BReference<ServerPicture> appendPicture(App()->GetPicture(token), true);
4038 			if (appendPicture != NULL) {
4039 				//picture->SyncState(fCurrentView);
4040 				appendPicture->AppendPicture(picture);
4041 			}
4042 
4043 			fCurrentView->SetPicture(appendPicture);
4044 
4045 			break;
4046 		}
4047 
4048 		case AS_VIEW_END_PICTURE:
4049 		{
4050 			BReference<ServerPicture> poppedPicture(picture->PopPicture(), true);
4051 			fCurrentView->SetPicture(poppedPicture);
4052 
4053 			fLink.StartMessage(B_OK);
4054 			fLink.Attach<int32>(picture->Token());
4055 			fLink.Flush();
4056 			return true;
4057 		}
4058 
4059 		case AS_VIEW_BEGIN_LAYER:
4060 		{
4061 			uint8 opacity;
4062 			link.Read<uint8>(&opacity);
4063 
4064 			Layer* layer = dynamic_cast<Layer*>(picture);
4065 			if (layer == NULL)
4066 				break;
4067 
4068 			Layer* nextLayer = new(std::nothrow) Layer(opacity);
4069 			if (nextLayer == NULL)
4070 				break;
4071 
4072 			if (opacity != 255) {
4073 				fCurrentView->CurrentState()->SetDrawingMode(B_OP_ALPHA);
4074 				fCurrentView->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA,
4075 					B_ALPHA_COMPOSITE);
4076 				fCurrentView->CurrentState()->SetDrawingModeLocked(true);
4077 			}
4078 
4079 			nextLayer->PushLayer(layer);
4080 			fCurrentView->SetPicture(nextLayer);
4081 			break;
4082 		}
4083 
4084 		case AS_VIEW_END_LAYER:
4085 		{
4086 			Layer* layer = dynamic_cast<Layer*>(picture);
4087 			if (layer == NULL)
4088 				break;
4089 
4090 			BReference<Layer> previousLayer(layer->PopLayer(), true);
4091 			if (previousLayer == NULL) {
4092 				// End last layer
4093 				return false;
4094 			}
4095 			fCurrentView->SetPicture(previousLayer);
4096 
4097 			previousLayer->WriteBlendLayer(layer);
4098 			break;
4099 		}
4100 
4101 /*
4102 		case AS_VIEW_SET_BLENDING_MODE:
4103 		{
4104 			ViewBlendingModeInfo info;
4105 			link.Read<ViewBlendingModeInfo>(&info);
4106 
4107 			picture->BeginOp(B_PIC_SET_BLENDING_MODE);
4108 			picture->AddInt16((int16)info.sourceAlpha);
4109 			picture->AddInt16((int16)info.alphaFunction);
4110 			picture->EndOp();
4111 
4112 			fCurrentView->CurrentState()->SetBlendingMode(info.sourceAlpha,
4113 				info.alphaFunction);
4114 			fWindow->GetDrawingEngine()->SetBlendingMode(info.sourceAlpha,
4115 				info.alphaFunction);
4116 			break;
4117 		}*/
4118 		default:
4119 			return false;
4120 	}
4121 
4122 	if (link.NeedsReply()) {
4123 		fLink.StartMessage(B_ERROR);
4124 		fLink.Flush();
4125 	}
4126 	return true;
4127 }
4128 
4129 
4130 /*!	\brief Message-dispatching loop for the ServerWindow
4131 
4132 	Watches the ServerWindow's message port and dispatches as necessary
4133 */
4134 void
4135 ServerWindow::_MessageLooper()
4136 {
4137 	// Send a reply to our window - it is expecting fMessagePort
4138 	// port and some other info.
4139 
4140 	fLink.StartMessage(B_OK);
4141 	fLink.Attach<port_id>(fMessagePort);
4142 
4143 	int32 minWidth, maxWidth, minHeight, maxHeight;
4144 	fWindow->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
4145 
4146 	fLink.Attach<BRect>(fWindow->Frame());
4147 	fLink.Attach<float>((float)minWidth);
4148 	fLink.Attach<float>((float)maxWidth);
4149 	fLink.Attach<float>((float)minHeight);
4150 	fLink.Attach<float>((float)maxHeight);
4151 	fLink.Flush();
4152 
4153 	BPrivate::LinkReceiver& receiver = fLink.Receiver();
4154 	bool quitLoop = false;
4155 
4156 	while (!quitLoop) {
4157 		//STRACE(("info: ServerWindow::MonitorWin listening on port %ld.\n",
4158 		//	fMessagePort));
4159 
4160 		int32 code;
4161 		status_t status = receiver.GetNextMessage(code);
4162 		if (status != B_OK) {
4163 			// that shouldn't happen, it's our port
4164 			printf("Someone deleted our message port!\n");
4165 
4166 			// try to let our client die happily
4167 			NotifyQuitRequested();
4168 			break;
4169 		}
4170 
4171 #ifdef PROFILE_MESSAGE_LOOP
4172 		bigtime_t start = system_time();
4173 #endif
4174 
4175 		Lock();
4176 
4177 #ifdef PROFILE_MESSAGE_LOOP
4178 		bigtime_t diff = system_time() - start;
4179 		if (diff > 10000) {
4180 			printf("ServerWindow %s: lock acquisition took %" B_PRId64 " usecs\n",
4181 				Title(), diff);
4182 		}
4183 #endif
4184 
4185 		int32 messagesProcessed = 0;
4186 		bigtime_t processingStart = system_time();
4187 		bool lockedDesktopSingleWindow = false;
4188 
4189 		while (true) {
4190 			if (code == AS_DELETE_WINDOW || code == kMsgQuitLooper) {
4191 				// this means the client has been killed
4192 				DTRACE(("ServerWindow %s received 'AS_DELETE_WINDOW' message "
4193 					"code\n", Title()));
4194 
4195 				if (code == AS_DELETE_WINDOW) {
4196 					fLink.StartMessage(B_OK);
4197 					fLink.Flush();
4198 				}
4199 
4200 				if (lockedDesktopSingleWindow)
4201 					fDesktop->UnlockSingleWindow();
4202 
4203 				quitLoop = true;
4204 
4205 				// ServerWindow's destructor takes care of pulling this object
4206 				// off the desktop.
4207 				ASSERT(fWindow->IsHidden());
4208 				break;
4209 			}
4210 
4211 			// Acquire the appropriate lock
4212 			bool needsAllWindowsLocked = _MessageNeedsAllWindowsLocked(code);
4213 			if (needsAllWindowsLocked) {
4214 				// We may already still hold the read-lock from the previous
4215 				// inner-loop iteration.
4216 				if (lockedDesktopSingleWindow) {
4217 					fDesktop->UnlockSingleWindow();
4218 					lockedDesktopSingleWindow = false;
4219 				}
4220 				fDesktop->LockAllWindows();
4221 			} else {
4222 				// We never keep the write-lock across inner-loop iterations,
4223 				// so there is nothing else to do besides read-locking unless
4224 				// we already have the read-lock from the previous iteration.
4225 				if (!lockedDesktopSingleWindow) {
4226 					fDesktop->LockSingleWindow();
4227 					lockedDesktopSingleWindow = true;
4228 				}
4229 			}
4230 
4231 			if (atomic_and(&fRedrawRequested, 0) != 0) {
4232 #ifdef PROFILE_MESSAGE_LOOP
4233 				bigtime_t redrawStart = system_time();
4234 #endif
4235 				fWindow->RedrawDirtyRegion();
4236 #ifdef PROFILE_MESSAGE_LOOP
4237 				diff = system_time() - redrawStart;
4238 				atomic_add(&sRedrawProcessingTime.count, 1);
4239 # ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
4240 				atomic_add64(&sRedrawProcessingTime.time, diff);
4241 # else
4242 				sRedrawProcessingTime.time += diff;
4243 # endif
4244 #endif
4245 			}
4246 
4247 #ifdef PROFILE_MESSAGE_LOOP
4248 			bigtime_t dispatchStart = system_time();
4249 #endif
4250 			_DispatchMessage(code, receiver);
4251 
4252 #ifdef PROFILE_MESSAGE_LOOP
4253 			if (code >= 0 && code < AS_LAST_CODE) {
4254 				diff = system_time() - dispatchStart;
4255 				atomic_add(&sMessageProfile[code].count, 1);
4256 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
4257 				atomic_add64(&sMessageProfile[code].time, diff);
4258 #else
4259 				sMessageProfile[code].time += diff;
4260 #endif
4261 				if (diff > 10000) {
4262 					printf("ServerWindow %s: message %" B_PRId32 " took %"
4263 						B_PRId64 " usecs\n", Title(), code, diff);
4264 				}
4265 			}
4266 #endif
4267 
4268 			if (needsAllWindowsLocked)
4269 				fDesktop->UnlockAllWindows();
4270 
4271 			// Only process up to 70 waiting messages at once (we have the
4272 			// Desktop locked), but don't hold the lock longer than 10 ms
4273 			if (!receiver.HasMessages() || ++messagesProcessed > 70
4274 				|| system_time() - processingStart > 10000) {
4275 				if (lockedDesktopSingleWindow)
4276 					fDesktop->UnlockSingleWindow();
4277 				break;
4278 			}
4279 
4280 			// next message
4281 			status_t status = receiver.GetNextMessage(code);
4282 			if (status != B_OK) {
4283 				// that shouldn't happen, it's our port
4284 				printf("Someone deleted our message port!\n");
4285 				if (lockedDesktopSingleWindow)
4286 					fDesktop->UnlockSingleWindow();
4287 
4288 				// try to let our client die happily
4289 				NotifyQuitRequested();
4290 				break;
4291 			}
4292 		}
4293 
4294 		Unlock();
4295 	}
4296 
4297 	// We were asked to quit the message loop - either on request or because of
4298 	// an error.
4299 	Quit();
4300 		// does not return
4301 }
4302 
4303 
4304 void
4305 ServerWindow::ScreenChanged(const BMessage* message)
4306 {
4307 	SendMessageToClient(message);
4308 
4309 	if (fDirectWindowInfo.IsSet() && fDirectWindowInfo->IsFullScreen())
4310 		_ResizeToFullScreen();
4311 }
4312 
4313 
4314 status_t
4315 ServerWindow::SendMessageToClient(const BMessage* msg, int32 target) const
4316 {
4317 	if (target == B_NULL_TOKEN)
4318 		target = fClientToken;
4319 
4320 	BMessenger reply;
4321 	BMessage::Private messagePrivate((BMessage*)msg);
4322 	return messagePrivate.SendMessage(fClientLooperPort, fClientTeam, target,
4323 		0, false, reply);
4324 }
4325 
4326 
4327 Window*
4328 ServerWindow::MakeWindow(BRect frame, const char* name,
4329 	window_look look, window_feel feel, uint32 flags, uint32 workspace)
4330 {
4331 	// The non-offscreen ServerWindow uses the DrawingEngine instance from
4332 	// the desktop.
4333 	return new(std::nothrow) ::Window(frame, name, look, feel, flags,
4334 		workspace, this, fDesktop->HWInterface()->CreateDrawingEngine());
4335 }
4336 
4337 
4338 void
4339 ServerWindow::HandleDirectConnection(int32 bufferState, int32 driverState)
4340 {
4341 	ASSERT_MULTI_LOCKED(fDesktop->WindowLocker());
4342 
4343 	if (!fDirectWindowInfo.IsSet())
4344 		return;
4345 
4346 	STRACE(("HandleDirectConnection(bufferState = %" B_PRId32 ", driverState = "
4347 		"%" B_PRId32 ")\n", bufferState, driverState));
4348 
4349 	status_t status = fDirectWindowInfo->SetState(
4350 		(direct_buffer_state)bufferState, (direct_driver_state)driverState,
4351 		fDesktop->HWInterface()->FrontBuffer(), fWindow->Frame(),
4352 		fWindow->VisibleContentRegion());
4353 
4354 	if (status != B_OK) {
4355 		char errorString[256];
4356 		snprintf(errorString, sizeof(errorString),
4357 			"%s killed for a problem in DirectConnected(): %s",
4358 			App()->Signature(), strerror(status));
4359 		syslog(LOG_ERR, errorString);
4360 
4361 		// The client application didn't release the semaphore
4362 		// within the given timeout. Or something else went wrong.
4363 		// Deleting this member should make it crash.
4364 		fDirectWindowInfo.Unset();
4365 	} else if ((bufferState & B_DIRECT_MODE_MASK) == B_DIRECT_START)
4366 		fIsDirectlyAccessing = true;
4367 	else if ((bufferState & B_DIRECT_MODE_MASK) == B_DIRECT_STOP)
4368 		fIsDirectlyAccessing = false;
4369 }
4370 
4371 
4372 void
4373 ServerWindow::_SetCurrentView(View* view)
4374 {
4375 	if (fCurrentView == view)
4376 		return;
4377 
4378 	fCurrentView = view;
4379 	fCurrentDrawingRegionValid = false;
4380 	_UpdateDrawState(fCurrentView);
4381 
4382 #if 0
4383 #if DELAYED_BACKGROUND_CLEARING
4384 	if (fCurrentView && fCurrentView->IsBackgroundDirty()
4385 		&& fWindow->InUpdate()) {
4386 		DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
4387 		if (drawingEngine->LockParallelAccess()) {
4388 			fWindow->GetEffectiveDrawingRegion(fCurrentView,
4389 				fCurrentDrawingRegion);
4390 			fCurrentDrawingRegionValid = true;
4391 			BRegion dirty(fCurrentDrawingRegion);
4392 
4393 			BRegion content;
4394 			fWindow->GetContentRegion(&content);
4395 
4396 			fCurrentView->Draw(drawingEngine, &dirty, &content, false);
4397 
4398 			drawingEngine->UnlockParallelAccess();
4399 		}
4400 	}
4401 #endif
4402 #endif // 0
4403 }
4404 
4405 
4406 void
4407 ServerWindow::_UpdateDrawState(View* view)
4408 {
4409 	// switch the drawing state
4410 	// TODO: is it possible to scroll a view while it
4411 	// is being drawn? probably not... otherwise the
4412 	// "offsets" passed below would need to be updated again
4413 	DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
4414 	if (view != NULL && drawingEngine != NULL) {
4415 		BPoint leftTop(0, 0);
4416 		if (view->GetAlphaMask() != NULL) {
4417 			view->LocalToScreenTransform().Apply(&leftTop);
4418 			view->GetAlphaMask()->SetCanvasGeometry(leftTop, view->Bounds());
4419 			leftTop = BPoint(0, 0);
4420 		}
4421 		view->PenToScreenTransform().Apply(&leftTop);
4422 		drawingEngine->SetDrawState(view->CurrentState(), leftTop.x, leftTop.y);
4423 	}
4424 }
4425 
4426 
4427 void
4428 ServerWindow::_UpdateCurrentDrawingRegion()
4429 {
4430 	if (!fCurrentDrawingRegionValid
4431 		|| fWindow->DrawingRegionChanged(fCurrentView)) {
4432 		fWindow->GetEffectiveDrawingRegion(fCurrentView, fCurrentDrawingRegion);
4433 		fCurrentDrawingRegionValid = true;
4434 	}
4435 }
4436 
4437 
4438 bool
4439 ServerWindow::_MessageNeedsAllWindowsLocked(uint32 code) const
4440 {
4441 	switch (code) {
4442 		case AS_SET_WINDOW_TITLE:
4443 		case AS_ADD_TO_SUBSET:
4444 		case AS_REMOVE_FROM_SUBSET:
4445 		case AS_VIEW_CREATE_ROOT:
4446 		case AS_VIEW_CREATE:
4447 		case AS_SEND_BEHIND:
4448 		case AS_SET_LOOK:
4449 		case AS_SET_FEEL:
4450 		case AS_SET_FLAGS:
4451 		case AS_SET_WORKSPACES:
4452 		case AS_WINDOW_MOVE:
4453 		case AS_WINDOW_RESIZE:
4454 		case AS_SET_SIZE_LIMITS:
4455 		case AS_SYSTEM_FONT_CHANGED:
4456 		case AS_SET_DECORATOR_SETTINGS:
4457 		case AS_GET_MOUSE:
4458 		case AS_DIRECT_WINDOW_SET_FULLSCREEN:
4459 //		case AS_VIEW_SET_EVENT_MASK:
4460 //		case AS_VIEW_SET_MOUSE_EVENT_MASK:
4461 		case AS_TALK_TO_DESKTOP_LISTENER:
4462 			return true;
4463 		default:
4464 			return false;
4465 	}
4466 }
4467 
4468 
4469 void
4470 ServerWindow::_ResizeToFullScreen()
4471 {
4472 	BRect screenFrame;
4473 
4474 	{
4475 		AutoReadLocker _(fDesktop->ScreenLocker());
4476 		const Screen* screen = fWindow->Screen();
4477 		if (screen == NULL)
4478 			return;
4479 
4480 		screenFrame = fWindow->Screen()->Frame();
4481 	}
4482 
4483 	fDesktop->MoveWindowBy(fWindow.Get(),
4484 		screenFrame.left - fWindow->Frame().left,
4485 		screenFrame.top - fWindow->Frame().top);
4486 	fDesktop->ResizeWindowBy(fWindow.Get(),
4487 		screenFrame.Width() - fWindow->Frame().Width(),
4488 		screenFrame.Height() - fWindow->Frame().Height());
4489 }
4490 
4491 
4492 status_t
4493 ServerWindow::_EnableDirectWindowMode()
4494 {
4495 	if (fDirectWindowInfo.IsSet()) {
4496 		// already in direct window mode
4497 		return B_ERROR;
4498 	}
4499 
4500 	if (fDesktop->HWInterface()->FrontBuffer() == NULL) {
4501 		// direct window mode not supported
4502 		return B_UNSUPPORTED;
4503 	}
4504 
4505 	fDirectWindowInfo.SetTo(new(std::nothrow) DirectWindowInfo);
4506 	if (!fDirectWindowInfo.IsSet())
4507 		return B_NO_MEMORY;
4508 
4509 	status_t status = fDirectWindowInfo->InitCheck();
4510 	if (status != B_OK) {
4511 		fDirectWindowInfo.Unset();
4512 
4513 		return status;
4514 	}
4515 
4516 	return B_OK;
4517 }
4518 
4519 
4520 void
4521 ServerWindow::_DirectWindowSetFullScreen(bool enable)
4522 {
4523 	window_feel feel = kWindowScreenFeel;
4524 
4525 	if (enable) {
4526 		fDesktop->HWInterface()->SetCursorVisible(false);
4527 
4528 		fDirectWindowInfo->EnableFullScreen(fWindow->Frame(), fWindow->Feel());
4529 		_ResizeToFullScreen();
4530 	} else {
4531 		const BRect& originalFrame = fDirectWindowInfo->OriginalFrame();
4532 
4533 		fDirectWindowInfo->DisableFullScreen();
4534 
4535 		// Resize window back to its original size
4536 		fDesktop->MoveWindowBy(fWindow.Get(),
4537 			originalFrame.left - fWindow->Frame().left,
4538 			originalFrame.top - fWindow->Frame().top);
4539 		fDesktop->ResizeWindowBy(fWindow.Get(),
4540 			originalFrame.Width() - fWindow->Frame().Width(),
4541 			originalFrame.Height() - fWindow->Frame().Height());
4542 
4543 		fDesktop->HWInterface()->SetCursorVisible(true);
4544 	}
4545 
4546 	fDesktop->SetWindowFeel(fWindow.Get(), feel);
4547 }
4548