xref: /haiku/src/servers/app/ServerWindow.cpp (revision 372b901dfeada686207d00bbcce456f748bbda12)
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_AFFINE_TRANSLATE:
1644 		{
1645 			double x, y;
1646 			link.Read<double>(&x);
1647 			link.Read<double>(&y);
1648 			BAffineTransform current =
1649 				fCurrentView->CurrentState()->Transform();
1650 			current.PreTranslateBy(x, y);
1651 			fCurrentView->CurrentState()->SetTransform(current);
1652 			_UpdateDrawState(fCurrentView);
1653 			break;
1654 		}
1655 
1656 		case AS_VIEW_AFFINE_SCALE:
1657 		{
1658 			double x, y;
1659 			link.Read<double>(&x);
1660 			link.Read<double>(&y);
1661 			BAffineTransform current =
1662 				fCurrentView->CurrentState()->Transform();
1663 			current.PreScaleBy(x, y);
1664 			fCurrentView->CurrentState()->SetTransform(current);
1665 			_UpdateDrawState(fCurrentView);
1666 			break;
1667 		}
1668 
1669 		case AS_VIEW_AFFINE_ROTATE:
1670 		{
1671 			double angleRadians;
1672 			link.Read<double>(&angleRadians);
1673 			BAffineTransform current =
1674 				fCurrentView->CurrentState()->Transform();
1675 			current.PreRotateBy(angleRadians);
1676 			fCurrentView->CurrentState()->SetTransform(current);
1677 			_UpdateDrawState(fCurrentView);
1678 			break;
1679 		}
1680 
1681 		case AS_VIEW_SET_PEN_LOC:
1682 		{
1683 			BPoint location;
1684 			if (link.Read<BPoint>(&location) != B_OK)
1685 				break;
1686 
1687 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PEN_LOC: "
1688 				"View: %s -> BPoint(%.1f, %.1f)\n", Title(),
1689 				fCurrentView->Name(), location.x, location.y));
1690 
1691 			fCurrentView->CurrentState()->SetPenLocation(location);
1692 			break;
1693 		}
1694 		case AS_VIEW_GET_PEN_LOC:
1695 		{
1696 			BPoint location = fCurrentView->CurrentState()->PenLocation();
1697 
1698 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_PEN_LOC: "
1699 				"View: %s -> BPoint(%.1f, %.1f)\n", Title(),
1700 				fCurrentView->Name(), location.x, location.y));
1701 
1702 			fLink.StartMessage(B_OK);
1703 			fLink.Attach<BPoint>(location);
1704 			fLink.Flush();
1705 
1706 			break;
1707 		}
1708 		case AS_VIEW_SET_PEN_SIZE:
1709 		{
1710 			float penSize;
1711 			if (link.Read<float>(&penSize) != B_OK)
1712 				break;
1713 
1714 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PEN_SIZE: "
1715 				"View: %s -> %.1f\n", Title(), fCurrentView->Name(), penSize));
1716 
1717 			fCurrentView->CurrentState()->SetPenSize(penSize);
1718 			fWindow->GetDrawingEngine()->SetPenSize(
1719 				fCurrentView->CurrentState()->PenSize());
1720 			break;
1721 		}
1722 		case AS_VIEW_GET_PEN_SIZE:
1723 		{
1724 			float penSize = fCurrentView->CurrentState()->UnscaledPenSize();
1725 
1726 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_PEN_SIZE: "
1727 				"View: %s -> %.1f\n", Title(), fCurrentView->Name(), penSize));
1728 
1729 			fLink.StartMessage(B_OK);
1730 			fLink.Attach<float>(penSize);
1731 			fLink.Flush();
1732 
1733 			break;
1734 		}
1735 		case AS_VIEW_SET_VIEW_COLOR:
1736 		{
1737 			rgb_color color;
1738 			if (link.Read(&color, sizeof(rgb_color)) != B_OK)
1739 				break;
1740 
1741 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_VIEW_COLOR: "
1742 				"View: %s -> rgb_color(%d, %d, %d, %d)\n", Title(),
1743 				fCurrentView->Name(), color.red, color.green, color.blue,
1744 				color.alpha));
1745 
1746 			fCurrentView->SetViewColor(color);
1747 			break;
1748 		}
1749 		case AS_VIEW_GET_VIEW_COLOR:
1750 		{
1751 			rgb_color color = fCurrentView->ViewColor();
1752 
1753 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_VIEW_COLOR: "
1754 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1755 				Title(), fCurrentView->Name(), color.red, color.green,
1756 				color.blue, color.alpha));
1757 
1758 			fLink.StartMessage(B_OK);
1759 			fLink.Attach<rgb_color>(color);
1760 			fLink.Flush();
1761 			break;
1762 		}
1763 		case AS_VIEW_SET_HIGH_COLOR:
1764 		{
1765 			rgb_color color;
1766 			if (link.Read(&color, sizeof(rgb_color)) != B_OK)
1767 				break;
1768 
1769 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_HIGH_COLOR: "
1770 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1771 				Title(), fCurrentView->Name(), color.red, color.green,
1772 				color.blue, color.alpha));
1773 
1774 			fCurrentView->CurrentState()->SetHighColor(color);
1775 			fWindow->GetDrawingEngine()->SetHighColor(color);
1776 			break;
1777 		}
1778 
1779 		case AS_VIEW_SET_HIGH_UI_COLOR:
1780 		{
1781 			color_which which = B_NO_COLOR;
1782 			float tint = B_NO_TINT;
1783 
1784 			if (link.Read<color_which>(&which) != B_OK
1785 				|| link.Read<float>(&tint) != B_OK )
1786 				break;
1787 
1788 			fCurrentView->CurrentState()->SetHighUIColor(which, tint);
1789 
1790 			// TODO: should we do more color_which validity checking?
1791 			if (which != B_NO_COLOR) {
1792 				DesktopSettings settings(fDesktop);
1793 				rgb_color color = tint_color(settings.UIColor(which), tint);
1794 
1795 				fCurrentView->CurrentState()->SetHighColor(color);
1796 				fWindow->GetDrawingEngine()->SetHighColor(color);
1797 			}
1798 			break;
1799 		}
1800 		case AS_VIEW_SET_LOW_UI_COLOR:
1801 		{
1802 			color_which which = B_NO_COLOR;
1803 			float tint = B_NO_TINT;
1804 
1805 			if (link.Read<color_which>(&which) != B_OK
1806 				|| link.Read<float>(&tint) != B_OK )
1807 				break;
1808 
1809 			fCurrentView->CurrentState()->SetLowUIColor(which, tint);
1810 
1811 			// TODO: should we do more color_which validity checking?
1812 			if (which != B_NO_COLOR) {
1813 				DesktopSettings settings(fDesktop);
1814 				rgb_color color = tint_color(settings.UIColor(which), tint);
1815 
1816 				fCurrentView->CurrentState()->SetLowColor(color);
1817 				fWindow->GetDrawingEngine()->SetLowColor(color);
1818 			}
1819 			break;
1820 		}
1821 		case AS_VIEW_SET_VIEW_UI_COLOR:
1822 		{
1823 			color_which which = B_NO_COLOR;
1824 			float tint = B_NO_TINT;
1825 
1826 			if (link.Read<color_which>(&which) != B_OK
1827 				|| link.Read<float>(&tint) != B_OK )
1828 				break;
1829 
1830 			// TODO: should we do more color_which validity checking?
1831 			fCurrentView->SetViewUIColor(which, tint);
1832 			break;
1833 		}
1834 		case AS_VIEW_GET_HIGH_UI_COLOR:
1835 		{
1836 			float tint;
1837 			color_which which = fCurrentView->CurrentState()->HighUIColor(&tint);
1838 			rgb_color color = fCurrentView->CurrentState()->HighColor();
1839 
1840 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_HIGH_UI_COLOR: "
1841 				"View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1842 				" %i, %i)\n", Title(), fCurrentView->Name(), which, tint,
1843 				color.red, color.green, color.blue, color.alpha));
1844 
1845 			fLink.StartMessage(B_OK);
1846 			fLink.Attach<color_which>(which);
1847 			fLink.Attach<float>(tint);
1848 			fLink.Attach<rgb_color>(color);
1849 			fLink.Flush();
1850 			break;
1851 		}
1852 		case AS_VIEW_GET_LOW_UI_COLOR:
1853 		{
1854 			float tint;
1855 			color_which which = fCurrentView->CurrentState()->LowUIColor(&tint);
1856 			rgb_color color = fCurrentView->CurrentState()->LowColor();
1857 
1858 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_LOW_UI_COLOR: "
1859 				"View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1860 				" %i, %i)\n", Title(), fCurrentView->Name(), which, tint,
1861 				color.red, color.green, color.blue, color.alpha));
1862 
1863 			fLink.StartMessage(B_OK);
1864 			fLink.Attach<color_which>(which);
1865 			fLink.Attach<float>(tint);
1866 			fLink.Attach<rgb_color>(color);
1867 			fLink.Flush();
1868 			break;
1869 		}
1870 		case AS_VIEW_GET_VIEW_UI_COLOR:
1871 		{
1872 			float tint;
1873 			color_which which = fCurrentView->ViewUIColor(&tint);
1874 			rgb_color color = fCurrentView->ViewColor();
1875 
1876 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_VIEW_UI_COLOR: "
1877 				"View: %s -> color_which(%i) tint(%.3f) - rgb_color(%i, %i,"
1878 				" %i, %i)\n", Title(), fCurrentView->Name(), which, tint,
1879 				color.red, color.green, color.blue, color.alpha));
1880 
1881 			fLink.StartMessage(B_OK);
1882 			fLink.Attach<color_which>(which);
1883 			fLink.Attach<float>(tint);
1884 			fLink.Attach<rgb_color>(color);
1885 			fLink.Flush();
1886 			break;
1887 		}
1888 		case AS_VIEW_GET_HIGH_COLOR:
1889 		{
1890 			rgb_color color = fCurrentView->CurrentState()->HighColor();
1891 
1892 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_HIGH_COLOR: "
1893 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1894 				Title(), fCurrentView->Name(), color.red, color.green,
1895 				color.blue, color.alpha));
1896 
1897 			fLink.StartMessage(B_OK);
1898 			fLink.Attach<rgb_color>(color);
1899 			fLink.Flush();
1900 			break;
1901 		}
1902 		case AS_VIEW_SET_LOW_COLOR:
1903 		{
1904 			rgb_color color;
1905 			if (link.Read(&color, sizeof(rgb_color)) != B_OK)
1906 				break;
1907 
1908 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_LOW_COLOR: "
1909 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1910 				Title(), fCurrentView->Name(), color.red, color.green,
1911 				color.blue, color.alpha));
1912 
1913 			fCurrentView->CurrentState()->SetLowColor(color);
1914 			fWindow->GetDrawingEngine()->SetLowColor(color);
1915 			break;
1916 		}
1917 		case AS_VIEW_GET_LOW_COLOR:
1918 		{
1919 			rgb_color color = fCurrentView->CurrentState()->LowColor();
1920 
1921 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_LOW_COLOR: "
1922 				"View: %s -> rgb_color(%d, %d, %d, %d)\n",
1923 				Title(), fCurrentView->Name(), color.red, color.green,
1924 				color.blue, color.alpha));
1925 
1926 			fLink.StartMessage(B_OK);
1927 			fLink.Attach<rgb_color>(color);
1928 			fLink.Flush();
1929 			break;
1930 		}
1931 		case AS_VIEW_SET_PATTERN:
1932 		{
1933 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_PATTERN: "
1934 				"View: %s\n", fTitle, fCurrentView->Name()));
1935 
1936 			pattern pat;
1937 			if (link.Read(&pat, sizeof(pattern)) != B_OK)
1938 				break;
1939 
1940 			fCurrentView->CurrentState()->SetPattern(Pattern(pat));
1941 			fWindow->GetDrawingEngine()->SetPattern(pat);
1942 			break;
1943 		}
1944 
1945 		case AS_VIEW_SET_BLENDING_MODE:
1946 		{
1947 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_BLEND_MODE: "
1948 				"View: %s\n", Title(), fCurrentView->Name()));
1949 
1950 			ViewBlendingModeInfo info;
1951 			if (link.Read<ViewBlendingModeInfo>(&info) != B_OK)
1952 				break;
1953 
1954 			fCurrentView->CurrentState()->SetBlendingMode(
1955 				info.sourceAlpha, info.alphaFunction);
1956 			fWindow->GetDrawingEngine()->SetBlendingMode(
1957 				info.sourceAlpha, info.alphaFunction);
1958 			break;
1959 		}
1960 		case AS_VIEW_GET_BLENDING_MODE:
1961 		{
1962 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_BLEND_MODE: "
1963 				"View: %s\n", Title(), fCurrentView->Name()));
1964 
1965 			ViewBlendingModeInfo info;
1966 			info.sourceAlpha = fCurrentView->CurrentState()->AlphaSrcMode();
1967 			info.alphaFunction = fCurrentView->CurrentState()->AlphaFncMode();
1968 
1969 			fLink.StartMessage(B_OK);
1970 			fLink.Attach<ViewBlendingModeInfo>(info);
1971 			fLink.Flush();
1972 
1973 			break;
1974 		}
1975 		case AS_VIEW_SET_DRAWING_MODE:
1976 		{
1977 			int8 drawingMode;
1978 			if (link.Read<int8>(&drawingMode) != B_OK)
1979 				break;
1980 
1981 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_DRAW_MODE: "
1982 				"View: %s -> %s\n", Title(), fCurrentView->Name(),
1983 				kDrawingModeMap[drawingMode]));
1984 
1985 			fCurrentView->CurrentState()->SetDrawingMode(
1986 				(drawing_mode)drawingMode);
1987 			fWindow->GetDrawingEngine()->SetDrawingMode(
1988 				(drawing_mode)drawingMode);
1989 			break;
1990 		}
1991 		case AS_VIEW_GET_DRAWING_MODE:
1992 		{
1993 			int8 drawingMode
1994 				= (int8)(fCurrentView->CurrentState()->GetDrawingMode());
1995 
1996 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_DRAW_MODE: "
1997 				"View: %s -> %s\n", Title(), fCurrentView->Name(),
1998 				kDrawingModeMap[drawingMode]));
1999 
2000 			fLink.StartMessage(B_OK);
2001 			fLink.Attach<int8>(drawingMode);
2002 			fLink.Flush();
2003 
2004 			break;
2005 		}
2006 		case AS_VIEW_SET_VIEW_BITMAP:
2007 		{
2008 			DTRACE(("ServerWindow %s: Message AS_VIEW_SET_VIEW_BITMAP: "
2009 				"View: %s\n", Title(), fCurrentView->Name()));
2010 
2011 			int32 bitmapToken, resizingMode, options;
2012 			BRect srcRect, dstRect;
2013 
2014 			link.Read<int32>(&bitmapToken);
2015 			link.Read<BRect>(&srcRect);
2016 			link.Read<BRect>(&dstRect);
2017 			link.Read<int32>(&resizingMode);
2018 			status_t status = link.Read<int32>(&options);
2019 
2020 			rgb_color colorKey = {0};
2021 
2022 			if (status == B_OK) {
2023 				BReference<ServerBitmap> bitmap(fServerApp->GetBitmap(bitmapToken), true);
2024 				if (bitmapToken == -1 || bitmap != NULL) {
2025 					bool wasOverlay = fCurrentView->ViewBitmap() != NULL
2026 						&& fCurrentView->ViewBitmap()->Overlay() != NULL;
2027 
2028 					fCurrentView->SetViewBitmap(bitmap, srcRect, dstRect,
2029 						resizingMode, options);
2030 
2031 					// TODO: if we revert the view color overlay handling
2032 					//	in View::Draw() to the BeOS version, we never
2033 					//	need to invalidate the view for overlays.
2034 
2035 					// Invalidate view - but only if this is a non-overlay
2036 					// switch
2037 					if (bitmap == NULL || bitmap->Overlay() == NULL
2038 						|| !wasOverlay) {
2039 						BRegion dirty((BRect)fCurrentView->Bounds());
2040 						fWindow->InvalidateView(fCurrentView, dirty);
2041 					}
2042 
2043 					if (bitmap != NULL && bitmap->Overlay() != NULL) {
2044 						bitmap->Overlay()->SetFlags(options);
2045 						colorKey = bitmap->Overlay()->Color();
2046 					}
2047 				} else
2048 					status = B_BAD_VALUE;
2049 			}
2050 
2051 			fLink.StartMessage(status);
2052 			if (status == B_OK && (options & AS_REQUEST_COLOR_KEY) != 0) {
2053 				// Attach color key for the overlay bitmap
2054 				fLink.Attach<rgb_color>(colorKey);
2055 			}
2056 
2057 			fLink.Flush();
2058 			break;
2059 		}
2060 		case AS_VIEW_PRINT_ALIASING:
2061 		{
2062 			DTRACE(("ServerWindow %s: Message AS_VIEW_PRINT_ALIASING: "
2063 				"View: %s\n", Title(), fCurrentView->Name()));
2064 
2065 			bool fontAliasing;
2066 			if (link.Read<bool>(&fontAliasing) == B_OK) {
2067 				fCurrentView->CurrentState()->SetForceFontAliasing(fontAliasing);
2068 				_UpdateDrawState(fCurrentView);
2069 			}
2070 			break;
2071 		}
2072 		case AS_VIEW_CLIP_TO_PICTURE:
2073 		{
2074 			DTRACE(("ServerWindow %s: Message AS_VIEW_CLIP_TO_PICTURE: "
2075 				"View: %s\n", Title(), fCurrentView->Name()));
2076 
2077 			int32 pictureToken;
2078 			BPoint where;
2079 			bool inverse = false;
2080 
2081 			link.Read<int32>(&pictureToken);
2082 			if (pictureToken < 0) {
2083 				fCurrentView->SetAlphaMask(NULL);
2084 				_UpdateDrawState(fCurrentView);
2085 				break;
2086 			}
2087 
2088 			link.Read<BPoint>(&where);
2089 			if (link.Read<bool>(&inverse) != B_OK)
2090 				break;
2091 
2092 			BReference<ServerPicture> picture(fServerApp->GetPicture(pictureToken), true);
2093 			if (picture == NULL)
2094 				break;
2095 
2096 			BReference<AlphaMask> const mask(new(std::nothrow) PictureAlphaMask(
2097 				fCurrentView->GetAlphaMask(), picture,
2098 				*fCurrentView->CurrentState(), where, inverse), true);
2099 			fCurrentView->SetAlphaMask(mask);
2100 
2101 			_UpdateDrawState(fCurrentView);
2102 			break;
2103 		}
2104 
2105 		case AS_VIEW_GET_CLIP_REGION:
2106 		{
2107 			DTRACE(("ServerWindow %s: Message AS_VIEW_GET_CLIP_REGION: "
2108 				"View: %s\n", Title(), fCurrentView->Name()));
2109 
2110 			// if this view is hidden, it has no visible region
2111 			fLink.StartMessage(B_OK);
2112 			if (!fWindow->IsVisible() || !fCurrentView->IsVisible()) {
2113 				BRegion empty;
2114 				fLink.AttachRegion(empty);
2115 			} else {
2116 				_UpdateCurrentDrawingRegion();
2117 				BRegion region(fCurrentDrawingRegion);
2118 				fCurrentView->ScreenToLocalTransform().Apply(&region);
2119 				fLink.AttachRegion(region);
2120 			}
2121 			fLink.Flush();
2122 
2123 			break;
2124 		}
2125 		case AS_VIEW_SET_CLIP_REGION:
2126 		{
2127 			int32 rectCount;
2128 			status_t status = link.Read<int32>(&rectCount);
2129 				// a negative count means no
2130 				// region for the current draw state,
2131 				// but an *empty* region is actually valid!
2132 				// even if it means no drawing is allowed
2133 
2134 			if (status < B_OK)
2135 				break;
2136 
2137 			if (rectCount >= 0) {
2138 				// we are supposed to set the clipping region
2139 				BRegion region;
2140 				if (rectCount > 0 && link.ReadRegion(&region) < B_OK)
2141 					break;
2142 
2143 				DTRACE(("ServerWindow %s: Message AS_VIEW_SET_CLIP_REGION: "
2144 					"View: %s -> rect count: %" B_PRId32 ", frame = "
2145 					"BRect(%.1f, %.1f, %.1f, %.1f)\n",
2146 					Title(), fCurrentView->Name(), rectCount,
2147 					region.Frame().left, region.Frame().top,
2148 					region.Frame().right, region.Frame().bottom));
2149 
2150 				fCurrentView->SetUserClipping(&region);
2151 			} else {
2152 				// we are supposed to unset the clipping region
2153 				// passing NULL sets this states region to that
2154 				// of the previous state
2155 
2156 				DTRACE(("ServerWindow %s: Message AS_VIEW_SET_CLIP_REGION: "
2157 					"View: %s -> unset\n", Title(), fCurrentView->Name()));
2158 
2159 				fCurrentView->SetUserClipping(NULL);
2160 			}
2161 			fCurrentDrawingRegionValid = false;
2162 
2163 			break;
2164 		}
2165 
2166 		case AS_VIEW_CLIP_TO_RECT:
2167 		{
2168 			bool inverse;
2169 			BRect rect;
2170 
2171 			link.Read<bool>(&inverse);
2172 			link.Read<BRect>(&rect);
2173 
2174 			bool needDrawStateUpdate = fCurrentView->ClipToRect(
2175 				rect, inverse);
2176 			fCurrentDrawingRegionValid = false;
2177 
2178 			if (needDrawStateUpdate)
2179 				_UpdateDrawState(fCurrentView);
2180 
2181 			_UpdateCurrentDrawingRegion();
2182 
2183 			BRegion region(fCurrentDrawingRegion);
2184 			fCurrentView->ScreenToLocalTransform().Apply(&region);
2185 
2186 			break;
2187 		}
2188 
2189 		case AS_VIEW_CLIP_TO_SHAPE:
2190 		{
2191 			bool inverse;
2192 			link.Read<bool>(&inverse);
2193 
2194 			shape_data shape;
2195 			link.Read<int32>(&shape.opCount);
2196 			link.Read<int32>(&shape.ptCount);
2197 			shape.opSize = shape.opCount * sizeof(uint32);
2198 			shape.ptSize = shape.ptCount * sizeof(BPoint);
2199 			shape.opList = new(nothrow) uint32[shape.opCount];
2200 			shape.ptList = new(nothrow) BPoint[shape.ptCount];
2201 			if (link.Read(shape.opList, shape.opSize) >= B_OK
2202 				&& link.Read(shape.ptList, shape.ptSize) >= B_OK) {
2203 				fCurrentView->ClipToShape(&shape, inverse);
2204 				_UpdateDrawState(fCurrentView);
2205 			}
2206 
2207 			delete[] shape.opList;
2208 			delete[] shape.ptList;
2209 			break;
2210 		}
2211 
2212 		case AS_VIEW_INVALIDATE_RECT:
2213 		{
2214 			// NOTE: looks like this call is NOT affected by origin and scale
2215 			// on R5 so this implementation is "correct"
2216 			BRect invalidRect;
2217 			if (link.Read<BRect>(&invalidRect) == B_OK) {
2218 				DTRACE(("ServerWindow %s: Message AS_VIEW_INVALIDATE_RECT: "
2219 					"View: %s -> BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2220 					fCurrentView->Name(), invalidRect.left, invalidRect.top,
2221 					invalidRect.right, invalidRect.bottom));
2222 
2223 				View* view = NULL;
2224 				if (link.Read<View*>(&view) != B_OK)
2225 					view = fCurrentView;
2226 
2227 				// make sure the view is still available!
2228 				if (view != fCurrentView
2229 					&& !fWindow->TopView()->HasView(view))
2230 					break;
2231 
2232 				BRegion dirty(invalidRect);
2233 				fWindow->InvalidateView(view, dirty);
2234 			}
2235 			break;
2236 		}
2237 
2238 		case AS_VIEW_DELAYED_INVALIDATE_RECT:
2239 		{
2240 			bigtime_t time = 0;
2241 			BRect invalidRect;
2242 			if (link.Read<bigtime_t>(&time) == B_OK
2243 				&& link.Read<BRect>(&invalidRect) == B_OK) {
2244 				DTRACE(("ServerWindow %s: Message "
2245 					"AS_VIEW_DELAYED_INVALIDATE_RECT: "
2246 					"View: %s -> BRect(%.1f, %.1f, %.1f, %.1f) at time %llu\n",
2247 					Title(), fCurrentView->Name(), invalidRect.left,
2248 					invalidRect.top, invalidRect.right, invalidRect.bottom,
2249 					time));
2250 
2251 				DelayedMessage delayed(AS_VIEW_INVALIDATE_RECT, time, true);
2252 				delayed.AddTarget(MessagePort());
2253 				delayed.SetMerge(DM_MERGE_DUPLICATES);
2254 
2255 				if (delayed.Attach<BRect>(invalidRect) == B_OK
2256 						&& delayed.Attach<View*>(fCurrentView) == B_OK)
2257 					delayed.Flush();
2258 			}
2259 			break;
2260 		}
2261 
2262 		case AS_VIEW_INVALIDATE_REGION:
2263 		{
2264 			// NOTE: looks like this call is NOT affected by origin and scale
2265 			// on R5 so this implementation is "correct"
2266 			BRegion region;
2267 			if (link.ReadRegion(&region) < B_OK)
2268 				break;
2269 
2270 			DTRACE(("ServerWindow %s: Message AS_VIEW_INVALIDATE_REGION: "
2271 					"View: %s -> rect count: %" B_PRId32 ", frame: BRect(%.1f, "
2272 					"%.1f, %.1f, %.1f)\n", Title(),
2273 					fCurrentView->Name(), region.CountRects(),
2274 					region.Frame().left, region.Frame().top,
2275 					region.Frame().right, region.Frame().bottom));
2276 
2277 			fWindow->InvalidateView(fCurrentView, region);
2278 			break;
2279 		}
2280 
2281 		case AS_VIEW_DRAG_IMAGE:
2282 		{
2283 			// TODO: flesh out AS_VIEW_DRAG_IMAGE
2284 			DTRACE(("ServerWindow %s: Message AS_DRAG_IMAGE\n", Title()));
2285 
2286 			int32 bitmapToken;
2287 			drawing_mode dragMode;
2288 			BPoint offset;
2289 			int32 bufferSize;
2290 
2291 			link.Read<int32>(&bitmapToken);
2292 			link.Read<int32>((int32*)&dragMode);
2293 			link.Read<BPoint>(&offset);
2294 			link.Read<int32>(&bufferSize);
2295 
2296 			if (bufferSize > 0) {
2297 				char* buffer = new (nothrow) char[bufferSize];
2298 				BMessage dragMessage;
2299 				if (link.Read(buffer, bufferSize) == B_OK
2300 					&& dragMessage.Unflatten(buffer) == B_OK) {
2301 						BReference<ServerBitmap> bitmap(
2302 							fServerApp->GetBitmap(bitmapToken), true);
2303 						// TODO: possible deadlock
2304 fDesktop->UnlockSingleWindow();
2305 						fDesktop->EventDispatcher().SetDragMessage(dragMessage,
2306 							bitmap, offset);
2307 fDesktop->LockSingleWindow();
2308 				}
2309 				delete[] buffer;
2310 			}
2311 			// sync the client (it can now delete the bitmap)
2312 			fLink.StartMessage(B_OK);
2313 			fLink.Flush();
2314 
2315 			break;
2316 		}
2317 		case AS_VIEW_DRAG_RECT:
2318 		{
2319 			// TODO: flesh out AS_VIEW_DRAG_RECT
2320 			DTRACE(("ServerWindow %s: Message AS_DRAG_RECT\n", Title()));
2321 
2322 			BRect dragRect;
2323 			BPoint offset;
2324 			int32 bufferSize;
2325 
2326 			link.Read<BRect>(&dragRect);
2327 			link.Read<BPoint>(&offset);
2328 			link.Read<int32>(&bufferSize);
2329 
2330 			if (bufferSize > 0) {
2331 				char* buffer = new (nothrow) char[bufferSize];
2332 				BMessage dragMessage;
2333 				if (link.Read(buffer, bufferSize) == B_OK
2334 					&& dragMessage.Unflatten(buffer) == B_OK) {
2335 						// TODO: possible deadlock
2336 fDesktop->UnlockSingleWindow();
2337 						fDesktop->EventDispatcher().SetDragMessage(dragMessage,
2338 							NULL /* should be dragRect */, offset);
2339 fDesktop->LockSingleWindow();
2340 				}
2341 				delete[] buffer;
2342 			}
2343 			break;
2344 		}
2345 
2346 		case AS_VIEW_BEGIN_RECT_TRACK:
2347 		{
2348 			DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_RECT_TRACK\n",
2349 				Title()));
2350 			BRect dragRect;
2351 			uint32 style;
2352 
2353 			link.Read<BRect>(&dragRect);
2354 			link.Read<uint32>(&style);
2355 
2356 			// TODO: implement rect tracking (used sometimes for selecting
2357 			// a group of things, also sometimes used to appear to drag
2358 			// something, but without real drag message)
2359 			break;
2360 		}
2361 		case AS_VIEW_END_RECT_TRACK:
2362 		{
2363 			DTRACE(("ServerWindow %s: Message AS_VIEW_END_RECT_TRACK\n",
2364 				Title()));
2365 			// TODO: implement rect tracking
2366 			break;
2367 		}
2368 
2369 		case AS_VIEW_BEGIN_PICTURE:
2370 		{
2371 			DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_PICTURE\n",
2372 				Title()));
2373 			BReference<ServerPicture> picture(App()->CreatePicture(), true);
2374 			if (picture != NULL) {
2375 				picture->SyncState(fCurrentView);
2376 				fCurrentView->SetPicture(picture);
2377 			}
2378 			break;
2379 		}
2380 
2381 		case AS_VIEW_APPEND_TO_PICTURE:
2382 		{
2383 			DTRACE(("ServerWindow %s: Message AS_VIEW_APPEND_TO_PICTURE\n",
2384 				Title()));
2385 
2386 			int32 token;
2387 			link.Read<int32>(&token);
2388 
2389 			BReference<ServerPicture> picture(App()->GetPicture(token), true);
2390 			if (picture != NULL)
2391 				picture->SyncState(fCurrentView);
2392 
2393 			fCurrentView->SetPicture(picture);
2394 
2395 			break;
2396 		}
2397 
2398 		case AS_VIEW_END_PICTURE:
2399 		{
2400 			DTRACE(("ServerWindow %s: Message AS_VIEW_END_PICTURE\n",
2401 				Title()));
2402 
2403 			ServerPicture* picture = fCurrentView->Picture();
2404 			if (picture != NULL) {
2405 				fCurrentView->SetPicture(NULL);
2406 				fLink.StartMessage(B_OK);
2407 				fLink.Attach<int32>(picture->Token());
2408 			} else
2409 				fLink.StartMessage(B_ERROR);
2410 
2411 			fLink.Flush();
2412 			break;
2413 		}
2414 
2415 		case AS_VIEW_BEGIN_LAYER:
2416 		{
2417 			DTRACE(("ServerWindow %s: Message AS_VIEW_BEGIN_LAYER\n",
2418 				Title()));
2419 
2420 			uint8 opacity;
2421 			link.Read<uint8>(&opacity);
2422 
2423 			Layer* layer = new(std::nothrow) Layer(opacity);
2424 			if (layer == NULL)
2425 				break;
2426 
2427 			if (opacity != 255) {
2428 				fCurrentView->CurrentState()->SetDrawingMode(B_OP_ALPHA);
2429 				fCurrentView->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA,
2430 					B_ALPHA_COMPOSITE);
2431 				fCurrentView->CurrentState()->SetDrawingModeLocked(true);
2432 			}
2433 
2434 			fCurrentView->SetPicture(layer);
2435 			break;
2436 		}
2437 
2438 		default:
2439 			// The drawing code handles allocation failures using exceptions;
2440 			// so we need to account for that here.
2441 			try {
2442 				_DispatchViewDrawingMessage(code, link);
2443 			} catch (std::bad_alloc&) {
2444 				// Cancel any message we were in the middle of sending.
2445 				fLink.CancelMessage();
2446 
2447 				if (link.NeedsReply()) {
2448 					// As done in _DispatchViewDrawingMessage, send just a
2449 					// single status_t as the reply.
2450 					fLink.StartMessage(B_NO_MEMORY);
2451 					fLink.Flush();
2452 				}
2453 			}
2454 			break;
2455 	}
2456 }
2457 
2458 
2459 /*!	Dispatches all view drawing messages.
2460 	The desktop clipping must be read locked when entering this method.
2461 	Requires a valid fCurrentView.
2462 */
2463 void
2464 ServerWindow::_DispatchViewDrawingMessage(int32 code,
2465 	BPrivate::LinkReceiver &link)
2466 {
2467 	if (!fCurrentView->IsVisible() || !fWindow->IsVisible()) {
2468 		if (link.NeedsReply()) {
2469 			debug_printf("ServerWindow::DispatchViewDrawingMessage() got "
2470 				"message %" B_PRId32 " that needs a reply!\n", code);
2471 			// the client is now blocking and waiting for a reply!
2472 			fLink.StartMessage(B_ERROR);
2473 			fLink.Flush();
2474 		}
2475 		return;
2476 	}
2477 
2478 	DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
2479 	if (!drawingEngine) {
2480 		// ?!?
2481 		debug_printf("ServerWindow %s: no drawing engine!!\n", Title());
2482 		if (link.NeedsReply()) {
2483 			// the client is now blocking and waiting for a reply!
2484 			fLink.StartMessage(B_ERROR);
2485 			fLink.Flush();
2486 		}
2487 		return;
2488 	}
2489 
2490 	_UpdateCurrentDrawingRegion();
2491 	if (fCurrentDrawingRegion.CountRects() <= 0 && code != AS_VIEW_END_LAYER) {
2492 			// If the command is AS_VIEW_END_LAYER, then we continue even if
2493 			// the clipping region is empty. The layer itself might set a valid
2494 			// clipping while its contents are drawn, and even if it doesn't,
2495 			// we must still play back its picture so that we don't leak
2496 			// nested layer instances.
2497 
2498 		DTRACE(("ServerWindow %s: _DispatchViewDrawingMessage(): View: %s, "
2499 			"INVALID CLIPPING!\n", Title(), fCurrentView->Name()));
2500 		if (link.NeedsReply()) {
2501 			// the client is now blocking and waiting for a reply!
2502 			fLink.StartMessage(B_ERROR);
2503 			fLink.Flush();
2504 		}
2505 		return;
2506 	}
2507 
2508 	drawingEngine->LockParallelAccess();
2509 	// NOTE: the region is not copied, Painter keeps a pointer,
2510 	// that's why you need to use the clipping only for as long
2511 	// as you have it locked
2512 	drawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion);
2513 
2514 	switch (code) {
2515 		case AS_STROKE_LINE:
2516 		{
2517 			ViewStrokeLineInfo info;
2518 			if (link.Read<ViewStrokeLineInfo>(&info) != B_OK)
2519 				break;
2520 
2521 			DTRACE(("ServerWindow %s: Message AS_STROKE_LINE: View: %s -> "
2522 				"BPoint(%.1f, %.1f) - BPoint(%.1f, %.1f)\n", Title(),
2523 					fCurrentView->Name(),
2524 					info.startPoint.x, info.startPoint.y,
2525 					info.endPoint.x, info.endPoint.y));
2526 
2527 			BPoint penPos = info.endPoint;
2528 			const SimpleTransform transform =
2529 				fCurrentView->PenToScreenTransform();
2530 			transform.Apply(&info.startPoint);
2531 			transform.Apply(&info.endPoint);
2532 			drawingEngine->StrokeLine(info.startPoint, info.endPoint);
2533 
2534 			// We update the pen here because many DrawingEngine calls which
2535 			// do not update the pen position actually call StrokeLine
2536 
2537 			// TODO: Decide where to put this, for example, it cannot be done
2538 			// for DrawString(), also there needs to be a decision, if the pen
2539 			// location is in View coordinates (I think it should be) or in
2540 			// screen coordinates.
2541 			fCurrentView->CurrentState()->SetPenLocation(penPos);
2542 			break;
2543 		}
2544 		case AS_VIEW_INVERT_RECT:
2545 		{
2546 			BRect rect;
2547 			if (link.Read<BRect>(&rect) != B_OK)
2548 				break;
2549 
2550 			DTRACE(("ServerWindow %s: Message AS_INVERT_RECT: View: %s -> "
2551 				"BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2552 				fCurrentView->Name(), rect.left, rect.top, rect.right,
2553 				rect.bottom));
2554 
2555 			fCurrentView->PenToScreenTransform().Apply(&rect);
2556 			drawingEngine->InvertRect(rect);
2557 			break;
2558 		}
2559 		case AS_STROKE_RECT:
2560 		{
2561 			BRect rect;
2562 			if (link.Read<BRect>(&rect) != B_OK)
2563 				break;
2564 
2565 			DTRACE(("ServerWindow %s: Message AS_STROKE_RECT: View: %s -> "
2566 				"BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2567 				fCurrentView->Name(), rect.left, rect.top, rect.right,
2568 				rect.bottom));
2569 
2570 			fCurrentView->PenToScreenTransform().Apply(&rect);
2571 			drawingEngine->StrokeRect(rect);
2572 			break;
2573 		}
2574 		case AS_FILL_RECT:
2575 		{
2576 			BRect rect;
2577 			if (link.Read<BRect>(&rect) != B_OK)
2578 				break;
2579 
2580 			DTRACE(("ServerWindow %s: Message AS_FILL_RECT: View: %s -> "
2581 				"BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2582 				fCurrentView->Name(), rect.left, rect.top, rect.right,
2583 				rect.bottom));
2584 
2585 			fCurrentView->PenToScreenTransform().Apply(&rect);
2586 			drawingEngine->FillRect(rect);
2587 			break;
2588 		}
2589 		case AS_FILL_RECT_GRADIENT:
2590 		{
2591 			BRect rect;
2592 			link.Read<BRect>(&rect);
2593 			BGradient* gradient;
2594 			if (link.ReadGradient(&gradient) != B_OK)
2595 				break;
2596 
2597 			GTRACE(("ServerWindow %s: Message AS_FILL_RECT_GRADIENT: View: %s "
2598 				"-> BRect(%.1f, %.1f, %.1f, %.1f)\n", Title(),
2599 				fCurrentView->Name(), rect.left, rect.top, rect.right,
2600 				rect.bottom));
2601 
2602 			const SimpleTransform transform =
2603 				fCurrentView->PenToScreenTransform();
2604 			transform.Apply(&rect);
2605 			transform.Apply(gradient);
2606 			drawingEngine->FillRect(rect, *gradient);
2607 			delete gradient;
2608 			break;
2609 		}
2610 		case AS_VIEW_DRAW_BITMAP:
2611 		{
2612 			ViewDrawBitmapInfo info;
2613 			if (link.Read<ViewDrawBitmapInfo>(&info) != B_OK)
2614 				break;
2615 
2616 #if 0
2617 			if (strcmp(fServerApp->SignatureLeaf(), "x-vnd.videolan-vlc") == 0)
2618 				info.options |= B_FILTER_BITMAP_BILINEAR;
2619 #endif
2620 
2621 			BReference<ServerBitmap> bitmap(fServerApp->GetBitmap(info.bitmapToken), true);
2622 			if (bitmap != NULL) {
2623 				DTRACE(("ServerWindow %s: Message AS_VIEW_DRAW_BITMAP: "
2624 					"View: %s, bitmap: %" B_PRId32 " (size %" B_PRId32 " x "
2625 					"%" B_PRId32 "), BRect(%.1f, %.1f, %.1f, %.1f) -> "
2626 					"BRect(%.1f, %.1f, %.1f, %.1f)\n",
2627 					fTitle, fCurrentView->Name(), info.bitmapToken,
2628 					bitmap->Width(), bitmap->Height(),
2629 					info.bitmapRect.left, info.bitmapRect.top,
2630 					info.bitmapRect.right, info.bitmapRect.bottom,
2631 					info.viewRect.left, info.viewRect.top,
2632 					info.viewRect.right, info.viewRect.bottom));
2633 
2634 				fCurrentView->PenToScreenTransform().Apply(&info.viewRect);
2635 
2636 // TODO: Unbreak...
2637 //				if ((info.options & B_WAIT_FOR_RETRACE) != 0)
2638 //					fDesktop->HWInterface()->WaitForRetrace(20000);
2639 
2640 				drawingEngine->DrawBitmap(bitmap, info.bitmapRect,
2641 					info.viewRect, info.options);
2642 			}
2643 			break;
2644 		}
2645 		case AS_STROKE_ARC:
2646 		case AS_FILL_ARC:
2647 		{
2648 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ARC\n", Title()));
2649 
2650 			float angle, span;
2651 			BRect r;
2652 
2653 			link.Read<BRect>(&r);
2654 			link.Read<float>(&angle);
2655 			if (link.Read<float>(&span) != B_OK)
2656 				break;
2657 
2658 			fCurrentView->PenToScreenTransform().Apply(&r);
2659 			drawingEngine->DrawArc(r, angle, span, code == AS_FILL_ARC);
2660 			break;
2661 		}
2662 		case AS_FILL_ARC_GRADIENT:
2663 		{
2664 			GTRACE(("ServerWindow %s: Message AS_FILL_ARC_GRADIENT\n",
2665 				Title()));
2666 
2667 			float angle, span;
2668 			BRect r;
2669 			link.Read<BRect>(&r);
2670 			link.Read<float>(&angle);
2671 			link.Read<float>(&span);
2672 			BGradient* gradient;
2673 			if (link.ReadGradient(&gradient) != B_OK)
2674 				break;
2675 			const SimpleTransform transform =
2676 				fCurrentView->PenToScreenTransform();
2677 			transform.Apply(&r);
2678 			transform.Apply(gradient);
2679 			drawingEngine->FillArc(r, angle, span, *gradient);
2680 			delete gradient;
2681 			break;
2682 		}
2683 		case AS_STROKE_BEZIER:
2684 		case AS_FILL_BEZIER:
2685 		{
2686 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_BEZIER\n",
2687 				Title()));
2688 
2689 			const SimpleTransform transform =
2690 				fCurrentView->PenToScreenTransform();
2691 			BPoint pts[4];
2692 			status_t status;
2693 			for (int32 i = 0; i < 4; i++) {
2694 				status = link.Read<BPoint>(&(pts[i]));
2695 				transform.Apply(&pts[i]);
2696 			}
2697 			if (status != B_OK)
2698 				break;
2699 
2700 			drawingEngine->DrawBezier(pts, code == AS_FILL_BEZIER);
2701 			break;
2702 		}
2703 		case AS_FILL_BEZIER_GRADIENT:
2704 		{
2705 			GTRACE(("ServerWindow %s: Message AS_FILL_BEZIER_GRADIENT\n",
2706 				Title()));
2707 
2708 			const SimpleTransform transform =
2709 				fCurrentView->PenToScreenTransform();
2710 			BPoint pts[4];
2711 			for (int32 i = 0; i < 4; i++) {
2712 				link.Read<BPoint>(&(pts[i]));
2713 				transform.Apply(&pts[i]);
2714 			}
2715 			BGradient* gradient;
2716 			if (link.ReadGradient(&gradient) != B_OK)
2717 				break;
2718 			transform.Apply(gradient);
2719 			drawingEngine->FillBezier(pts, *gradient);
2720 			delete gradient;
2721 			break;
2722 		}
2723 		case AS_STROKE_ELLIPSE:
2724 		case AS_FILL_ELLIPSE:
2725 		{
2726 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ELLIPSE\n",
2727 				Title()));
2728 
2729 			BRect rect;
2730 			if (link.Read<BRect>(&rect) != B_OK)
2731 				break;
2732 
2733 			fCurrentView->PenToScreenTransform().Apply(&rect);
2734 			drawingEngine->DrawEllipse(rect, code == AS_FILL_ELLIPSE);
2735 			break;
2736 		}
2737 		case AS_FILL_ELLIPSE_GRADIENT:
2738 		{
2739 			GTRACE(("ServerWindow %s: Message AS_FILL_ELLIPSE_GRADIENT\n",
2740 				Title()));
2741 
2742 			BRect rect;
2743 			link.Read<BRect>(&rect);
2744 			BGradient* gradient;
2745 			if (link.ReadGradient(&gradient) != B_OK)
2746 				break;
2747 			const SimpleTransform transform =
2748 				fCurrentView->PenToScreenTransform();
2749 			transform.Apply(&rect);
2750 			transform.Apply(gradient);
2751 			drawingEngine->FillEllipse(rect, *gradient);
2752 			delete gradient;
2753 			break;
2754 		}
2755 		case AS_STROKE_ROUNDRECT:
2756 		case AS_FILL_ROUNDRECT:
2757 		{
2758 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_ROUNDRECT\n",
2759 				Title()));
2760 
2761 			BRect rect;
2762 			float xRadius;
2763 			float yRadius;
2764 			link.Read<BRect>(&rect);
2765 			link.Read<float>(&xRadius);
2766 			if (link.Read<float>(&yRadius) != B_OK)
2767 				break;
2768 
2769 			fCurrentView->PenToScreenTransform().Apply(&rect);
2770 			float scale = fCurrentView->CurrentState()->CombinedScale();
2771 			drawingEngine->DrawRoundRect(rect, xRadius * scale, yRadius * scale,
2772 				code == AS_FILL_ROUNDRECT);
2773 			break;
2774 		}
2775 		case AS_FILL_ROUNDRECT_GRADIENT:
2776 		{
2777 			GTRACE(("ServerWindow %s: Message AS_FILL_ROUNDRECT_GRADIENT\n",
2778 				Title()));
2779 
2780 			BRect rect;
2781 			float xrad,yrad;
2782 			link.Read<BRect>(&rect);
2783 			link.Read<float>(&xrad);
2784 			link.Read<float>(&yrad);
2785 			BGradient* gradient;
2786 			if (link.ReadGradient(&gradient) != B_OK)
2787 				break;
2788 			const SimpleTransform transform =
2789 				fCurrentView->PenToScreenTransform();
2790 			transform.Apply(&rect);
2791 			transform.Apply(gradient);
2792 			drawingEngine->FillRoundRect(rect, xrad, yrad, *gradient);
2793 			delete gradient;
2794 			break;
2795 		}
2796 		case AS_STROKE_TRIANGLE:
2797 		case AS_FILL_TRIANGLE:
2798 		{
2799 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_TRIANGLE\n",
2800 				Title()));
2801 
2802 			const SimpleTransform transform =
2803 				fCurrentView->PenToScreenTransform();
2804 			BPoint pts[3];
2805 			BRect rect;
2806 
2807 			for (int32 i = 0; i < 3; i++) {
2808 				link.Read<BPoint>(&(pts[i]));
2809 				transform.Apply(&pts[i]);
2810 			}
2811 
2812 			if (link.Read<BRect>(&rect) != B_OK)
2813 				break;
2814 
2815 			transform.Apply(&rect);
2816 			drawingEngine->DrawTriangle(pts, rect, code == AS_FILL_TRIANGLE);
2817 			break;
2818 		}
2819 		case AS_FILL_TRIANGLE_GRADIENT:
2820 		{
2821 			DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE_GRADIENT\n",
2822 				Title()));
2823 
2824 			const SimpleTransform transform =
2825 				fCurrentView->PenToScreenTransform();
2826 			BPoint pts[3];
2827 			BRect rect;
2828 			for (int32 i = 0; i < 3; i++) {
2829 				link.Read<BPoint>(&(pts[i]));
2830 				transform.Apply(&pts[i]);
2831 			}
2832 			link.Read<BRect>(&rect);
2833 			BGradient* gradient;
2834 			if (link.ReadGradient(&gradient) != B_OK)
2835 				break;
2836 			transform.Apply(&rect);
2837 			transform.Apply(gradient);
2838 			drawingEngine->FillTriangle(pts, rect, *gradient);
2839 			delete gradient;
2840 			break;
2841 		}
2842 		case AS_STROKE_POLYGON:
2843 		case AS_FILL_POLYGON:
2844 		{
2845 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_POLYGON\n",
2846 				Title()));
2847 
2848 			BRect polyFrame;
2849 			bool isClosed = true;
2850 			int32 pointCount;
2851 
2852 			link.Read<BRect>(&polyFrame);
2853 			if (code == AS_STROKE_POLYGON)
2854 				link.Read<bool>(&isClosed);
2855 			link.Read<int32>(&pointCount);
2856 
2857 			const SimpleTransform transform =
2858 				fCurrentView->PenToScreenTransform();
2859 			BPoint* pointList = new(nothrow) BPoint[pointCount];
2860 			if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
2861 				for (int32 i = 0; i < pointCount; i++)
2862 					transform.Apply(&pointList[i]);
2863 				transform.Apply(&polyFrame);
2864 
2865 				drawingEngine->DrawPolygon(pointList, pointCount, polyFrame,
2866 					code == AS_FILL_POLYGON, isClosed && pointCount > 2);
2867 			}
2868 			delete[] pointList;
2869 			break;
2870 		}
2871 		case AS_FILL_POLYGON_GRADIENT:
2872 		{
2873 			DTRACE(("ServerWindow %s: Message AS_FILL_POLYGON_GRADIENT\n",
2874 				Title()));
2875 
2876 			BRect polyFrame;
2877 			bool isClosed = true;
2878 			int32 pointCount;
2879 			link.Read<BRect>(&polyFrame);
2880 			link.Read<int32>(&pointCount);
2881 
2882 			const SimpleTransform transform =
2883 				fCurrentView->PenToScreenTransform();
2884 			BPoint* pointList = new(nothrow) BPoint[pointCount];
2885 			BGradient* gradient;
2886 			if (link.Read(pointList, pointCount * sizeof(BPoint)) == B_OK
2887 				&& link.ReadGradient(&gradient) == B_OK) {
2888 				for (int32 i = 0; i < pointCount; i++)
2889 					transform.Apply(&pointList[i]);
2890 				transform.Apply(&polyFrame);
2891 				transform.Apply(gradient);
2892 
2893 				drawingEngine->FillPolygon(pointList, pointCount,
2894 					polyFrame, *gradient, isClosed && pointCount > 2);
2895 				delete gradient;
2896 			}
2897 			delete[] pointList;
2898 			break;
2899 		}
2900 		case AS_STROKE_SHAPE:
2901 		case AS_FILL_SHAPE:
2902 		{
2903 			DTRACE(("ServerWindow %s: Message AS_STROKE/FILL_SHAPE\n",
2904 				Title()));
2905 
2906 			BRect shapeFrame;
2907 			int32 opCount;
2908 			int32 ptCount;
2909 
2910 			link.Read<BRect>(&shapeFrame);
2911 			link.Read<int32>(&opCount);
2912 			link.Read<int32>(&ptCount);
2913 
2914 			uint32* opList = new(nothrow) uint32[opCount];
2915 			BPoint* ptList = new(nothrow) BPoint[ptCount];
2916 			if (link.Read(opList, opCount * sizeof(uint32)) >= B_OK &&
2917 				link.Read(ptList, ptCount * sizeof(BPoint)) >= B_OK) {
2918 
2919 				// this might seem a bit weird, but under R5, the shapes
2920 				// are always offset by the current pen location
2921 				BPoint screenOffset
2922 					= fCurrentView->CurrentState()->PenLocation();
2923 				shapeFrame.OffsetBy(screenOffset);
2924 
2925 				const SimpleTransform transform =
2926 					fCurrentView->PenToScreenTransform();
2927 				transform.Apply(&screenOffset);
2928 				transform.Apply(&shapeFrame);
2929 
2930 				drawingEngine->DrawShape(shapeFrame, opCount, opList, ptCount,
2931 					ptList, code == AS_FILL_SHAPE, screenOffset,
2932 					fCurrentView->Scale());
2933 			}
2934 
2935 			delete[] opList;
2936 			delete[] ptList;
2937 			break;
2938 		}
2939 		case AS_FILL_SHAPE_GRADIENT:
2940 		{
2941 			DTRACE(("ServerWindow %s: Message AS_FILL_SHAPE_GRADIENT\n",
2942 				Title()));
2943 
2944 			BRect shapeFrame;
2945 			int32 opCount;
2946 			int32 ptCount;
2947 
2948 			link.Read<BRect>(&shapeFrame);
2949 			link.Read<int32>(&opCount);
2950 			link.Read<int32>(&ptCount);
2951 
2952 			uint32* opList = new(nothrow) uint32[opCount];
2953 			BPoint* ptList = new(nothrow) BPoint[ptCount];
2954 			BGradient* gradient;
2955 			if (link.Read(opList, opCount * sizeof(uint32)) == B_OK
2956 				&& link.Read(ptList, ptCount * sizeof(BPoint)) == B_OK
2957 				&& link.ReadGradient(&gradient) == B_OK) {
2958 
2959 				// this might seem a bit weird, but under R5, the shapes
2960 				// are always offset by the current pen location
2961 				BPoint screenOffset
2962 					= fCurrentView->CurrentState()->PenLocation();
2963 				shapeFrame.OffsetBy(screenOffset);
2964 
2965 				const SimpleTransform transform =
2966 					fCurrentView->PenToScreenTransform();
2967 				transform.Apply(&screenOffset);
2968 				transform.Apply(&shapeFrame);
2969 				transform.Apply(gradient);
2970 				drawingEngine->FillShape(shapeFrame, opCount, opList,
2971 					ptCount, ptList, *gradient, screenOffset,
2972 					fCurrentView->Scale());
2973 				delete gradient;
2974 			}
2975 
2976 			delete[] opList;
2977 			delete[] ptList;
2978 			break;
2979 		}
2980 		case AS_FILL_REGION:
2981 		{
2982 			DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title()));
2983 
2984 			BRegion region;
2985 			if (link.ReadRegion(&region) < B_OK)
2986 				break;
2987 
2988 			fCurrentView->PenToScreenTransform().Apply(&region);
2989 			drawingEngine->FillRegion(region);
2990 
2991 			break;
2992 		}
2993 		case AS_FILL_REGION_GRADIENT:
2994 		{
2995 			DTRACE(("ServerWindow %s: Message AS_FILL_REGION_GRADIENT\n",
2996 				Title()));
2997 
2998 			BRegion region;
2999 			link.ReadRegion(&region);
3000 
3001 			BGradient* gradient;
3002 			if (link.ReadGradient(&gradient) != B_OK)
3003 				break;
3004 
3005 			const SimpleTransform transform =
3006 				fCurrentView->PenToScreenTransform();
3007 			transform.Apply(&region);
3008 			transform.Apply(gradient);
3009 			drawingEngine->FillRegion(region, *gradient);
3010 			delete gradient;
3011 			break;
3012 		}
3013 		case AS_STROKE_LINEARRAY:
3014 		{
3015 			DTRACE(("ServerWindow %s: Message AS_STROKE_LINEARRAY\n",
3016 				Title()));
3017 
3018 			// Attached Data:
3019 			// 1) int32 Number of lines in the array
3020 			// 2) LineArrayData
3021 
3022 			int32 lineCount;
3023 			if (link.Read<int32>(&lineCount) != B_OK || lineCount <= 0)
3024 				break;
3025 
3026 			// To speed things up, try to use a stack allocation and only
3027 			// fall back to the heap if there are enough lines...
3028 			ViewLineArrayInfo* lineData;
3029 			const int32 kStackBufferLineDataCount = 64;
3030 			ViewLineArrayInfo lineDataStackBuffer[kStackBufferLineDataCount];
3031 			if (lineCount > kStackBufferLineDataCount) {
3032 				lineData = new(std::nothrow) ViewLineArrayInfo[lineCount];
3033 				if (lineData == NULL)
3034 					break;
3035 			} else
3036 				lineData = lineDataStackBuffer;
3037 
3038 			// Read them all in one go
3039 			size_t dataSize = lineCount * sizeof(ViewLineArrayInfo);
3040 			if (link.Read(lineData, dataSize) != B_OK) {
3041 				if (lineData != lineDataStackBuffer)
3042 					delete[] lineData;
3043 				break;
3044 			}
3045 
3046 			// Convert to screen coords and draw
3047 			const SimpleTransform transform =
3048 				fCurrentView->PenToScreenTransform();
3049 			for (int32 i = 0; i < lineCount; i++) {
3050 				transform.Apply(&lineData[i].startPoint);
3051 				transform.Apply(&lineData[i].endPoint);
3052 			}
3053 			drawingEngine->StrokeLineArray(lineCount, lineData);
3054 
3055 			if (lineData != lineDataStackBuffer)
3056 				delete[] lineData;
3057 			break;
3058 		}
3059 		case AS_DRAW_STRING:
3060 		case AS_DRAW_STRING_WITH_DELTA:
3061 		{
3062 			ViewDrawStringInfo info;
3063 			if (link.Read<ViewDrawStringInfo>(&info) != B_OK
3064 				|| info.stringLength <= 0) {
3065 				break;
3066 			}
3067 
3068 			// NOTE: Careful, the + 1 is for termination!
3069 			BStackOrHeapArray<char, 4096> string(
3070 				(info.stringLength + 1 + 63) / 64 * 64);
3071 			if (!string.IsValid())
3072 				break;
3073 
3074 			escapement_delta* delta = NULL;
3075 			if (code == AS_DRAW_STRING_WITH_DELTA) {
3076 				// In this case, info.delta will contain valid values.
3077 				delta = &info.delta;
3078 			}
3079 
3080 			if (link.Read(string, info.stringLength) != B_OK)
3081 				break;
3082 
3083 			// Terminate the string, if nothing else, it's important
3084 			// for the DTRACE call below...
3085 			string[info.stringLength] = '\0';
3086 
3087 			DTRACE(("ServerWindow %s: Message AS_DRAW_STRING, View: %s "
3088 				"-> %s\n", Title(), fCurrentView->Name(), string));
3089 
3090 			fCurrentView->PenToScreenTransform().Apply(&info.location);
3091 			BPoint penLocation = drawingEngine->DrawString(string,
3092 				info.stringLength, info.location, delta);
3093 
3094 			fCurrentView->ScreenToPenTransform().Apply(&penLocation);
3095 			fCurrentView->CurrentState()->SetPenLocation(penLocation);
3096 
3097 			break;
3098 		}
3099 		case AS_DRAW_STRING_WITH_OFFSETS:
3100 		{
3101 			int32 stringLength;
3102 			if (link.Read<int32>(&stringLength) != B_OK || stringLength <= 0)
3103 				break;
3104 
3105 			int32 glyphCount;
3106 			if (link.Read<int32>(&glyphCount) != B_OK || glyphCount <= 0)
3107 				break;
3108 
3109 			// NOTE: Careful, the + 1 is for termination!
3110 			BStackOrHeapArray<char, 512> string(
3111 				(stringLength + 1 + 63) / 64 * 64);
3112 			BStackOrHeapArray<BPoint, 512> locations(glyphCount);
3113 			if (!string.IsValid() || !locations.IsValid())
3114 				break;
3115 
3116 			if (link.Read(string, stringLength) != B_OK)
3117 				break;
3118 			// Count UTF8 glyphs and make sure we have enough locations
3119 			if ((int32)UTF8CountChars(string, stringLength) > glyphCount)
3120 				break;
3121 			if (link.Read(locations, glyphCount * sizeof(BPoint)) != B_OK)
3122 				break;
3123 			// Terminate the string, if nothing else, it's important
3124 			// for the DTRACE call below...
3125 			string[stringLength] = '\0';
3126 
3127 			DTRACE(("ServerWindow %s: Message AS_DRAW_STRING_WITH_OFFSETS, View: %s "
3128 				"-> %s\n", Title(), fCurrentView->Name(), string));
3129 
3130 			const SimpleTransform transform =
3131 				fCurrentView->PenToScreenTransform();
3132 			for (int32 i = 0; i < glyphCount; i++)
3133 				transform.Apply(&locations[i]);
3134 
3135 			BPoint penLocation = drawingEngine->DrawString(string,
3136 				stringLength, locations);
3137 
3138 			fCurrentView->ScreenToPenTransform().Apply(&penLocation);
3139 			fCurrentView->CurrentState()->SetPenLocation(penLocation);
3140 
3141 			break;
3142 		}
3143 
3144 		case AS_VIEW_DRAW_PICTURE:
3145 		{
3146 			int32 token;
3147 			link.Read<int32>(&token);
3148 
3149 			BPoint where;
3150 			if (link.Read<BPoint>(&where) == B_OK) {
3151 				BReference<ServerPicture> picture(App()->GetPicture(token), true);
3152 				if (picture != NULL) {
3153 					// Setting the drawing origin outside of the
3154 					// state makes sure that everything the picture
3155 					// does is relative to the global picture offset.
3156 					fCurrentView->PushState();
3157 					fCurrentView->SetDrawingOrigin(where);
3158 
3159 					fCurrentView->PushState();
3160 					picture->Play(fCurrentView);
3161 					fCurrentView->PopState();
3162 
3163 					fCurrentView->PopState();
3164 				}
3165 			}
3166 			break;
3167 		}
3168 
3169 		case AS_VIEW_END_LAYER:
3170 		{
3171 			DTRACE(("ServerWindow %s: Message AS_VIEW_END_LAYER\n",
3172 				Title()));
3173 
3174 			fCurrentView->BlendAllLayers();
3175 			fCurrentView->SetPicture(NULL);
3176 			fCurrentView->CurrentState()->SetDrawingModeLocked(false);
3177 			break;
3178 		}
3179 
3180 		default:
3181 			debug_printf("ServerWindow %s received unexpected code: %s\n",
3182 				Title(), string_for_message_code(code));
3183 
3184 			if (link.NeedsReply()) {
3185 				// the client is now blocking and waiting for a reply!
3186 				fLink.StartMessage(B_ERROR);
3187 				fLink.Flush();
3188 			}
3189 			break;
3190 	}
3191 
3192 	drawingEngine->UnlockParallelAccess();
3193 }
3194 
3195 
3196 bool
3197 ServerWindow::_DispatchPictureMessage(int32 code, BPrivate::LinkReceiver& link)
3198 {
3199 	ServerPicture* picture = fCurrentView->Picture();
3200 	if (picture == NULL)
3201 		return false;
3202 
3203 	switch (code) {
3204 		case AS_VIEW_SET_ORIGIN:
3205 		{
3206 			float x, y;
3207 			link.Read<float>(&x);
3208 			link.Read<float>(&y);
3209 
3210 			fCurrentView->SetDrawingOrigin(BPoint(x, y));
3211 			picture->WriteSetOrigin(BPoint(x, y));
3212 			break;
3213 		}
3214 
3215 		case AS_VIEW_INVERT_RECT:
3216 		{
3217 			BRect rect;
3218 			link.Read<BRect>(&rect);
3219 			picture->WriteInvertRect(rect);
3220 			break;
3221 		}
3222 
3223 		case AS_VIEW_PUSH_STATE:
3224 		{
3225 			fCurrentView->PushState();
3226 			picture->WritePushState();
3227 			break;
3228 		}
3229 
3230 		case AS_VIEW_POP_STATE:
3231 		{
3232 			fCurrentView->PopState();
3233 			picture->WritePopState();
3234 			break;
3235 		}
3236 
3237 		case AS_VIEW_SET_DRAWING_MODE:
3238 		{
3239 			int8 drawingMode;
3240 			link.Read<int8>(&drawingMode);
3241 
3242 			picture->WriteSetDrawingMode((drawing_mode)drawingMode);
3243 
3244 			fCurrentView->CurrentState()->SetDrawingMode(
3245 				(drawing_mode)drawingMode);
3246 			fWindow->GetDrawingEngine()->SetDrawingMode(
3247 				(drawing_mode)drawingMode);
3248 			break;
3249 		}
3250 
3251 		case AS_VIEW_SET_PEN_LOC:
3252 		{
3253 			BPoint location;
3254 			link.Read<BPoint>(&location);
3255 			picture->WriteSetPenLocation(location);
3256 
3257 			fCurrentView->CurrentState()->SetPenLocation(location);
3258 			break;
3259 		}
3260 
3261 		case AS_VIEW_SET_PEN_SIZE:
3262 		{
3263 			float penSize;
3264 			link.Read<float>(&penSize);
3265 			picture->WriteSetPenSize(penSize);
3266 
3267 			fCurrentView->CurrentState()->SetPenSize(penSize);
3268 			fWindow->GetDrawingEngine()->SetPenSize(
3269 				fCurrentView->CurrentState()->PenSize());
3270 			break;
3271 		}
3272 
3273 		case AS_VIEW_SET_LINE_MODE:
3274 		{
3275 
3276 			ViewSetLineModeInfo info;
3277 			link.Read<ViewSetLineModeInfo>(&info);
3278 
3279 			picture->WriteSetLineMode(info.lineCap, info.lineJoin,
3280 				info.miterLimit);
3281 
3282 			fCurrentView->CurrentState()->SetLineCapMode(info.lineCap);
3283 			fCurrentView->CurrentState()->SetLineJoinMode(info.lineJoin);
3284 			fCurrentView->CurrentState()->SetMiterLimit(info.miterLimit);
3285 
3286 			fWindow->GetDrawingEngine()->SetStrokeMode(info.lineCap,
3287 				info.lineJoin, info.miterLimit);
3288 			break;
3289 		}
3290 		case AS_VIEW_SET_FILL_RULE:
3291 		{
3292 			int32 fillRule;
3293 			if (link.Read<int32>(&fillRule) != B_OK)
3294 				break;
3295 
3296 			picture->WriteSetFillRule(fillRule);
3297 
3298 			fCurrentView->CurrentState()->SetFillRule(fillRule);
3299 			fWindow->GetDrawingEngine()->SetFillRule(fillRule);
3300 
3301 			break;
3302 		}
3303 		case AS_VIEW_SET_SCALE:
3304 		{
3305 			float scale;
3306 			if (link.Read<float>(&scale) != B_OK)
3307 				break;
3308 
3309 			picture->WriteSetScale(scale);
3310 
3311 			fCurrentView->SetScale(scale);
3312 			_UpdateDrawState(fCurrentView);
3313 			break;
3314 		}
3315 		case AS_VIEW_SET_TRANSFORM:
3316 		{
3317 			BAffineTransform transform;
3318 			if (link.Read<BAffineTransform>(&transform) != B_OK)
3319 				break;
3320 
3321 			picture->WriteSetTransform(transform);
3322 
3323 			fCurrentView->CurrentState()->SetTransform(transform);
3324 			_UpdateDrawState(fCurrentView);
3325 			break;
3326 		}
3327 
3328 		case AS_VIEW_AFFINE_TRANSLATE:
3329 		{
3330 			double x, y;
3331 			link.Read<double>(&x);
3332 			link.Read<double>(&y);
3333 
3334 			picture->WriteTranslateBy(x, y);
3335 
3336 			BAffineTransform current =
3337 				fCurrentView->CurrentState()->Transform();
3338 			current.PreTranslateBy(x, y);
3339 			fCurrentView->CurrentState()->SetTransform(current);
3340 			_UpdateDrawState(fCurrentView);
3341 			break;
3342 		}
3343 
3344 		case AS_VIEW_AFFINE_SCALE:
3345 		{
3346 			double x, y;
3347 			link.Read<double>(&x);
3348 			link.Read<double>(&y);
3349 
3350 			picture->WriteScaleBy(x, y);
3351 
3352 			BAffineTransform current =
3353 				fCurrentView->CurrentState()->Transform();
3354 			current.PreScaleBy(x, y);
3355 			fCurrentView->CurrentState()->SetTransform(current);
3356 			_UpdateDrawState(fCurrentView);
3357 			break;
3358 		}
3359 
3360 		case AS_VIEW_AFFINE_ROTATE:
3361 		{
3362 			double angleRadians;
3363 			link.Read<double>(&angleRadians);
3364 
3365 			picture->WriteRotateBy(angleRadians);
3366 
3367 			BAffineTransform current =
3368 				fCurrentView->CurrentState()->Transform();
3369 			current.PreRotateBy(angleRadians);
3370 			fCurrentView->CurrentState()->SetTransform(current);
3371 			_UpdateDrawState(fCurrentView);
3372 			break;
3373 		}
3374 
3375 
3376 		case AS_VIEW_SET_PATTERN:
3377 		{
3378 			pattern pat;
3379 			link.Read(&pat, sizeof(pattern));
3380 			picture->WriteSetPattern(pat);
3381 			break;
3382 		}
3383 
3384 		case AS_VIEW_SET_FONT_STATE:
3385 		{
3386 			uint16 mask = fCurrentView->CurrentState()->ReadFontFromLink(link);
3387 			fWindow->GetDrawingEngine()->SetFont(
3388 				fCurrentView->CurrentState());
3389 
3390 			picture->WriteFontState(fCurrentView->CurrentState()->Font(), mask);
3391 			break;
3392 		}
3393 
3394 		case AS_FILL_RECT:
3395 		case AS_STROKE_RECT:
3396 		{
3397 			BRect rect;
3398 			link.Read<BRect>(&rect);
3399 
3400 			picture->WriteDrawRect(rect, code == AS_FILL_RECT);
3401 			break;
3402 		}
3403 
3404 		case AS_FILL_REGION:
3405 		{
3406 			// There is no B_PIC_FILL_REGION op, we have to
3407 			// implement it using B_PIC_FILL_RECT
3408 			BRegion region;
3409 			if (link.ReadRegion(&region) < B_OK)
3410 				break;
3411 			for (int32 i = 0; i < region.CountRects(); i++)
3412 				picture->WriteDrawRect(region.RectAt(i), true);
3413 			break;
3414 		}
3415 
3416 		case AS_STROKE_ROUNDRECT:
3417 		case AS_FILL_ROUNDRECT:
3418 		{
3419 			BRect rect;
3420 			link.Read<BRect>(&rect);
3421 
3422 			BPoint radii;
3423 			link.Read<float>(&radii.x);
3424 			link.Read<float>(&radii.y);
3425 
3426 			picture->WriteDrawRoundRect(rect, radii, code == AS_FILL_ROUNDRECT);
3427 			break;
3428 		}
3429 
3430 		case AS_STROKE_ELLIPSE:
3431 		case AS_FILL_ELLIPSE:
3432 		{
3433 			BRect rect;
3434 			link.Read<BRect>(&rect);
3435 			picture->WriteDrawEllipse(rect, code == AS_FILL_ELLIPSE);
3436 			break;
3437 		}
3438 
3439 		case AS_STROKE_ARC:
3440 		case AS_FILL_ARC:
3441 		{
3442 			BRect rect;
3443 			link.Read<BRect>(&rect);
3444 			float startTheta, arcTheta;
3445 			link.Read<float>(&startTheta);
3446 			link.Read<float>(&arcTheta);
3447 
3448 			BPoint radii((rect.Width() + 1) / 2, (rect.Height() + 1) / 2);
3449 			BPoint center = rect.LeftTop() + radii;
3450 
3451 			picture->WriteDrawArc(center, radii, startTheta, arcTheta,
3452 				code == AS_FILL_ARC);
3453 			break;
3454 		}
3455 
3456 		case AS_STROKE_TRIANGLE:
3457 		case AS_FILL_TRIANGLE:
3458 		{
3459 			// There is no B_PIC_FILL/STROKE_TRIANGLE op,
3460 			// we implement it using B_PIC_FILL/STROKE_POLYGON
3461 			BPoint points[3];
3462 
3463 			for (int32 i = 0; i < 3; i++) {
3464 				link.Read<BPoint>(&(points[i]));
3465 			}
3466 
3467 			BRect rect;
3468 			link.Read<BRect>(&rect);
3469 
3470 			picture->WriteDrawPolygon(3, points,
3471 					true, code == AS_FILL_TRIANGLE);
3472 			break;
3473 		}
3474 		case AS_STROKE_POLYGON:
3475 		case AS_FILL_POLYGON:
3476 		{
3477 			BRect polyFrame;
3478 			bool isClosed = true;
3479 			int32 pointCount;
3480 			const bool fill = (code == AS_FILL_POLYGON);
3481 
3482 			link.Read<BRect>(&polyFrame);
3483 			if (code == AS_STROKE_POLYGON)
3484 				link.Read<bool>(&isClosed);
3485 			link.Read<int32>(&pointCount);
3486 
3487 			BPoint* pointList = new(nothrow) BPoint[pointCount];
3488 			if (link.Read(pointList, pointCount * sizeof(BPoint)) >= B_OK) {
3489 				picture->WriteDrawPolygon(pointCount, pointList,
3490 					isClosed && pointCount > 2, fill);
3491 			}
3492 			delete[] pointList;
3493 			break;
3494 		}
3495 
3496 		case AS_STROKE_BEZIER:
3497 		case AS_FILL_BEZIER:
3498 		{
3499 			BPoint points[4];
3500 			for (int32 i = 0; i < 4; i++) {
3501 				link.Read<BPoint>(&(points[i]));
3502 			}
3503 			picture->WriteDrawBezier(points, code == AS_FILL_BEZIER);
3504 			break;
3505 		}
3506 
3507 		//case AS_STROKE_RECT_GRADIENT:
3508 		case AS_FILL_RECT_GRADIENT:
3509 		{
3510 			BRect rect;
3511 			link.Read<BRect>(&rect);
3512 			BGradient* gradient;
3513 			if (link.ReadGradient(&gradient) != B_OK)
3514 				break;
3515 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3516 
3517 			picture->WriteDrawRectGradient(rect, *gradient, code == AS_FILL_RECT_GRADIENT);
3518 			break;
3519 		}
3520 
3521 		//case AS_STROKE_ARC_GRADIENT:
3522 		case AS_FILL_ARC_GRADIENT:
3523 		{
3524 			BRect rect;
3525 			link.Read<BRect>(&rect);
3526 			float startTheta, arcTheta;
3527 			link.Read<float>(&startTheta);
3528 			link.Read<float>(&arcTheta);
3529 			BGradient* gradient;
3530 			if (link.ReadGradient(&gradient) != B_OK)
3531 				break;
3532 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3533 
3534 			BPoint radii((rect.Width() + 1) / 2, (rect.Height() + 1) / 2);
3535 			BPoint center = rect.LeftTop() + radii;
3536 
3537 			picture->WriteDrawArcGradient(center, radii, startTheta, arcTheta, *gradient,
3538 				code == AS_FILL_ARC_GRADIENT);
3539 			break;
3540 		}
3541 
3542 		//case AS_STROKE_BEZIER_GRADIENT:
3543 		case AS_FILL_BEZIER_GRADIENT:
3544 		{
3545 			BPoint points[4];
3546 			for (int32 i = 0; i < 4; i++) {
3547 				link.Read<BPoint>(&(points[i]));
3548 			}
3549 			BGradient* gradient;
3550 			if (link.ReadGradient(&gradient) != B_OK)
3551 				break;
3552 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3553 
3554 			picture->WriteDrawBezierGradient(points, *gradient, code == AS_FILL_BEZIER_GRADIENT);
3555 			break;
3556 		}
3557 
3558 		//case AS_STROKE_ELLIPSE_GRADIENT:
3559 		case AS_FILL_ELLIPSE_GRADIENT:
3560 		{
3561 			BRect rect;
3562 			link.Read<BRect>(&rect);
3563 			BGradient* gradient;
3564 			if (link.ReadGradient(&gradient) != B_OK)
3565 				break;
3566 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3567 
3568 			picture->WriteDrawEllipseGradient(rect, *gradient, code == AS_FILL_ELLIPSE_GRADIENT);
3569 			break;
3570 		}
3571 
3572 		//case AS_STROKE_ROUNDRECT_GRADIENT:
3573 		case AS_FILL_ROUNDRECT_GRADIENT:
3574 		{
3575 			BRect rect;
3576 			link.Read<BRect>(&rect);
3577 
3578 			BPoint radii;
3579 			link.Read<float>(&radii.x);
3580 			link.Read<float>(&radii.y);
3581 			BGradient* gradient;
3582 			if (link.ReadGradient(&gradient) != B_OK)
3583 				break;
3584 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3585 
3586 			picture->WriteDrawRoundRectGradient(rect, radii, *gradient, code == AS_FILL_ROUNDRECT_GRADIENT);
3587 			break;
3588 		}
3589 
3590 		//case AS_STROKE_TRIANGLE_GRADIENT:
3591 		case AS_FILL_TRIANGLE_GRADIENT:
3592 		{
3593 			// There is no B_PIC_FILL/STROKE_TRIANGLE op,
3594 			// we implement it using B_PIC_FILL/STROKE_POLYGON
3595 			BPoint points[3];
3596 
3597 			for (int32 i = 0; i < 3; i++) {
3598 				link.Read<BPoint>(&(points[i]));
3599 			}
3600 
3601 			BRect rect;
3602 			link.Read<BRect>(&rect);
3603 			BGradient* gradient;
3604 			if (link.ReadGradient(&gradient) != B_OK)
3605 				break;
3606 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3607 
3608 			picture->WriteDrawPolygonGradient(3, points,
3609 					true, *gradient, code == AS_FILL_TRIANGLE_GRADIENT);
3610 			break;
3611 		}
3612 
3613 		//case AS_STROKE_POLYGON_GRADIENT:
3614 		case AS_FILL_POLYGON_GRADIENT:
3615 		{
3616 			BRect polyFrame;
3617 			bool isClosed = true;
3618 			int32 pointCount;
3619 			const bool fill = (code == AS_FILL_POLYGON_GRADIENT);
3620 
3621 			link.Read<BRect>(&polyFrame);
3622 			if (code == AS_STROKE_POLYGON)
3623 				link.Read<bool>(&isClosed);
3624 			link.Read<int32>(&pointCount);
3625 
3626 			ArrayDeleter<BPoint> pointList(new(nothrow) BPoint[pointCount]);
3627 			if (link.Read(pointList.Get(), pointCount * sizeof(BPoint)) != B_OK)
3628 				break;
3629 
3630 			BGradient* gradient;
3631 			if (link.ReadGradient(&gradient) != B_OK)
3632 				break;
3633 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3634 
3635 			picture->WriteDrawPolygonGradient(pointCount, pointList.Get(),
3636 				isClosed && pointCount > 2, *gradient, fill);
3637 			break;
3638 		}
3639 
3640 		//case AS_STROKE_SHAPE_GRADIENT:
3641 		case AS_FILL_SHAPE_GRADIENT:
3642 		{
3643 			BRect shapeFrame;
3644 			int32 opCount;
3645 			int32 ptCount;
3646 
3647 			link.Read<BRect>(&shapeFrame);
3648 			link.Read<int32>(&opCount);
3649 			link.Read<int32>(&ptCount);
3650 
3651 			ArrayDeleter<uint32> opList(new(std::nothrow) uint32[opCount]);
3652 			ArrayDeleter<BPoint> ptList(new(std::nothrow) BPoint[ptCount]);
3653 			if (!opList.IsSet() || !ptList.IsSet()
3654 				|| link.Read(opList.Get(), opCount * sizeof(uint32)) != B_OK
3655 				|| link.Read(ptList.Get(), ptCount * sizeof(BPoint)) != B_OK)
3656 				break;
3657 
3658 			BGradient* gradient;
3659 			if (link.ReadGradient(&gradient) != B_OK)
3660 				break;
3661 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3662 
3663 			// This might seem a bit weird, but under BeOS, the shapes
3664 			// are always offset by the current pen location
3665 			BPoint penLocation
3666 				= fCurrentView->CurrentState()->PenLocation();
3667 			for (int32 i = 0; i < ptCount; i++) {
3668 				ptList.Get()[i] += penLocation;
3669 			}
3670 			const bool fill = (code == AS_FILL_SHAPE_GRADIENT);
3671 			picture->WriteDrawShapeGradient(opCount, opList.Get(), ptCount, ptList.Get(), *gradient, fill);
3672 
3673 			break;
3674 		}
3675 
3676 		case AS_FILL_REGION_GRADIENT:
3677 		{
3678 			// There is no B_PIC_FILL_REGION op, we have to
3679 			// implement it using B_PIC_FILL_RECT
3680 			BRegion region;
3681 			if (link.ReadRegion(&region) < B_OK)
3682 				break;
3683 
3684 			BGradient* gradient;
3685 			if (link.ReadGradient(&gradient) != B_OK)
3686 				break;
3687 			ObjectDeleter<BGradient> gradientDeleter(gradient);
3688 
3689 			for (int32 i = 0; i < region.CountRects(); i++)
3690 				picture->WriteDrawRectGradient(region.RectAt(i), *gradient, true);
3691 			break;
3692 		}
3693 
3694 		case AS_STROKE_LINE:
3695 		{
3696 			ViewStrokeLineInfo info;
3697 			link.Read<ViewStrokeLineInfo>(&info);
3698 
3699 			picture->WriteStrokeLine(info.startPoint, info.endPoint);
3700 
3701 			BPoint penPos = info.endPoint;
3702 			const SimpleTransform transform =
3703 				fCurrentView->PenToScreenTransform();
3704 			transform.Apply(&info.endPoint);
3705 			fCurrentView->CurrentState()->SetPenLocation(penPos);
3706 			break;
3707 		}
3708 
3709 		case AS_STROKE_LINEARRAY:
3710 		{
3711 			int32 lineCount;
3712 			if (link.Read<int32>(&lineCount) != B_OK || lineCount <= 0)
3713 				break;
3714 
3715 			// To speed things up, try to use a stack allocation and only
3716 			// fall back to the heap if there are enough lines...
3717 			ViewLineArrayInfo* lineData;
3718 			const int32 kStackBufferLineDataCount = 64;
3719 			ViewLineArrayInfo lineDataStackBuffer[kStackBufferLineDataCount];
3720 			if (lineCount > kStackBufferLineDataCount) {
3721 				lineData = new(std::nothrow) ViewLineArrayInfo[lineCount];
3722 				if (lineData == NULL)
3723 					break;
3724 			} else
3725 				lineData = lineDataStackBuffer;
3726 
3727 			// Read them all in one go
3728 			size_t dataSize = lineCount * sizeof(ViewLineArrayInfo);
3729 			if (link.Read(lineData, dataSize) != B_OK) {
3730 				if (lineData != lineDataStackBuffer)
3731 					delete[] lineData;
3732 				break;
3733 			}
3734 
3735 			picture->WritePushState();
3736 
3737 			for (int32 i = 0; i < lineCount; i++) {
3738 				picture->WriteSetHighColor(lineData[i].color);
3739 				picture->WriteStrokeLine(lineData[i].startPoint,
3740 					lineData[i].endPoint);
3741 			}
3742 
3743 			picture->WritePopState();
3744 
3745 			if (lineData != lineDataStackBuffer)
3746 				delete[] lineData;
3747 			break;
3748 		}
3749 
3750 		case AS_VIEW_SET_LOW_COLOR:
3751 		case AS_VIEW_SET_HIGH_COLOR:
3752 		{
3753 			rgb_color color;
3754 			link.Read(&color, sizeof(rgb_color));
3755 
3756 			if (code == AS_VIEW_SET_HIGH_COLOR) {
3757 				picture->WriteSetHighColor(color);
3758 				fCurrentView->CurrentState()->SetHighColor(color);
3759 				fWindow->GetDrawingEngine()->SetHighColor(color);
3760 			} else {
3761 				picture->WriteSetLowColor(color);
3762 				fCurrentView->CurrentState()->SetLowColor(color);
3763 				fWindow->GetDrawingEngine()->SetLowColor(color);
3764 			}
3765 		}	break;
3766 
3767 		case AS_DRAW_STRING:
3768 		case AS_DRAW_STRING_WITH_DELTA:
3769 		{
3770 			ViewDrawStringInfo info;
3771 			if (link.Read<ViewDrawStringInfo>(&info) != B_OK)
3772 				break;
3773 
3774 			char* string = (char*)malloc(info.stringLength + 1);
3775 			if (string == NULL)
3776 				break;
3777 
3778 			if (code != AS_DRAW_STRING_WITH_DELTA) {
3779 				// In this case, info.delta will NOT contain valid values.
3780 				info.delta = (escapement_delta){ 0, 0 };
3781 			}
3782 
3783 			if (link.Read(string, info.stringLength) != B_OK) {
3784 				free(string);
3785 				break;
3786 			}
3787 			// Terminate the string
3788 			string[info.stringLength] = '\0';
3789 
3790 			picture->WriteDrawString(info.location, string, info.stringLength,
3791 				info.delta);
3792 
3793 			// We need to update the pen location
3794 			fCurrentView->PenToScreenTransform().Apply(&info.location);
3795 			DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
3796 			if (drawingEngine->LockParallelAccess()) {
3797 				BPoint penLocation = drawingEngine->DrawStringDry(
3798 					string, info.stringLength, info.location, &info.delta);
3799 
3800 				fCurrentView->ScreenToPenTransform().Apply(&penLocation);
3801 				fCurrentView->CurrentState()->SetPenLocation(penLocation);
3802 
3803 				drawingEngine->UnlockParallelAccess();
3804 			}
3805 
3806 			free(string);
3807 			break;
3808 		}
3809 
3810 		case AS_DRAW_STRING_WITH_OFFSETS:
3811 		{
3812 			int32 stringLength;
3813 			if (link.Read<int32>(&stringLength) != B_OK || stringLength <= 0)
3814 				break;
3815 
3816 			int32 glyphCount;
3817 			if (link.Read<int32>(&glyphCount) != B_OK || glyphCount <= 0)
3818 				break;
3819 
3820 			// NOTE: Careful, the + 1 is for termination!
3821 			BStackOrHeapArray<char, 512> string(
3822 				(stringLength + 1 + 63) / 64 * 64);
3823 			BStackOrHeapArray<BPoint, 512> locations(glyphCount);
3824 			if (!string.IsValid() || !locations.IsValid())
3825 				break;
3826 
3827 			if (link.Read(string, stringLength) != B_OK)
3828 				break;
3829 			// Count UTF8 glyphs and make sure we have enough locations
3830 			if ((int32)UTF8CountChars(string, stringLength) > glyphCount)
3831 				break;
3832 			if (link.Read(locations, glyphCount * sizeof(BPoint)) != B_OK)
3833 				break;
3834 			// Terminate the string
3835 			string[stringLength] = '\0';
3836 
3837 			const SimpleTransform transform =
3838 				fCurrentView->PenToScreenTransform();
3839 			for (int32 i = 0; i < glyphCount; i++)
3840 				transform.Apply(&locations[i]);
3841 
3842 			picture->WriteDrawString(string, stringLength, locations,
3843 				glyphCount);
3844 
3845 			DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
3846 			if (drawingEngine->LockParallelAccess()) {
3847 				// Update pen location
3848 				BPoint penLocation = drawingEngine->DrawStringDry(
3849 					string, stringLength, locations);
3850 
3851 				fCurrentView->ScreenToPenTransform().Apply(&penLocation);
3852 				fCurrentView->CurrentState()->SetPenLocation(penLocation);
3853 
3854 				drawingEngine->UnlockParallelAccess();
3855 			}
3856 
3857 			break;
3858 		}
3859 
3860 		case AS_STROKE_SHAPE:
3861 		case AS_FILL_SHAPE:
3862 		{
3863 			BRect shapeFrame;
3864 			int32 opCount;
3865 			int32 ptCount;
3866 
3867 			link.Read<BRect>(&shapeFrame);
3868 			link.Read<int32>(&opCount);
3869 			link.Read<int32>(&ptCount);
3870 
3871 			BStackOrHeapArray<uint32, 512> opList(opCount);
3872 			BStackOrHeapArray<BPoint, 512> ptList(ptCount);
3873 			if (!opList.IsValid() || !ptList.IsValid()
3874 				|| link.Read(opList, opCount * sizeof(uint32)) < B_OK
3875 				|| link.Read(ptList, ptCount * sizeof(BPoint)) < B_OK) {
3876 				break;
3877 			}
3878 			picture->WriteDrawShape(opCount, opList, ptCount,
3879 				ptList, code == AS_FILL_SHAPE);
3880 
3881 			break;
3882 		}
3883 
3884 		case AS_VIEW_DRAW_BITMAP:
3885 		{
3886 			ViewDrawBitmapInfo info;
3887 			link.Read<ViewDrawBitmapInfo>(&info);
3888 
3889 			BReference<ServerBitmap> bitmap(App()->GetBitmap(info.bitmapToken), true);
3890 			if (bitmap == NULL)
3891 				break;
3892 
3893 			picture->WriteDrawBitmap(info.bitmapRect, info.viewRect,
3894 				bitmap->Width(), bitmap->Height(), bitmap->BytesPerRow(),
3895 				bitmap->ColorSpace(), info.options, bitmap->Bits(),
3896 				bitmap->BitsLength());
3897 
3898 			break;
3899 		}
3900 
3901 		case AS_VIEW_DRAW_PICTURE:
3902 		{
3903 			int32 token;
3904 			link.Read<int32>(&token);
3905 
3906 			BPoint where;
3907 			if (link.Read<BPoint>(&where) == B_OK) {
3908 				BReference<ServerPicture> pictureToDraw(App()->GetPicture(token), true);
3909 				if (pictureToDraw != NULL) {
3910 					// We need to make a copy of the picture, since it can
3911 					// change after it has been drawn
3912 					BReference<ServerPicture> copy(App()->CreatePicture(pictureToDraw), true);
3913 					picture->NestPicture(copy);
3914 					picture->WriteDrawPicture(where, copy->Token());
3915 				}
3916 			}
3917 			break;
3918 		}
3919 
3920 		case AS_VIEW_SET_CLIP_REGION:
3921 		{
3922 			int32 rectCount;
3923 			status_t status = link.Read<int32>(&rectCount);
3924 				// a negative count means no
3925 				// region for the current draw state,
3926 				// but an *empty* region is actually valid!
3927 				// even if it means no drawing is allowed
3928 
3929 			if (status < B_OK)
3930 				break;
3931 
3932 			if (rectCount >= 0) {
3933 				// we are supposed to set the clipping region
3934 				BRegion region;
3935 				if (rectCount > 0 && link.ReadRegion(&region) < B_OK)
3936 					break;
3937 				picture->WriteSetClipping(region);
3938 			} else {
3939 				// we are supposed to clear the clipping region
3940 				picture->WriteClearClipping();
3941 			}
3942 			break;
3943 		}
3944 
3945 		case AS_VIEW_CLIP_TO_PICTURE:
3946 		{
3947 			int32 pictureToken;
3948 			BPoint where;
3949 			bool inverse = false;
3950 
3951 			link.Read<int32>(&pictureToken);
3952 			if (pictureToken < 0)
3953 				break;
3954 
3955 			link.Read<BPoint>(&where);
3956 			if (link.Read<bool>(&inverse) != B_OK)
3957 				break;
3958 
3959 			BReference<ServerPicture> pictureToClip(fServerApp->GetPicture(pictureToken), true);
3960 			if (pictureToClip != NULL) {
3961 				// We need to make a copy of the picture, since it can
3962 				// change after it has been drawn
3963 				BReference<ServerPicture> copy(App()->CreatePicture(pictureToClip), true);
3964 				picture->NestPicture(copy);
3965 				picture->WriteClipToPicture(copy->Token(), where, inverse);
3966 			}
3967 			break;
3968 		}
3969 
3970 		case AS_VIEW_CLIP_TO_RECT:
3971 		{
3972 			bool inverse;
3973 			BRect rect;
3974 			link.Read<bool>(&inverse);
3975 			link.Read<BRect>(&rect);
3976 			picture->WriteClipToRect(rect, inverse);
3977 
3978 			break;
3979 		}
3980 
3981 		case AS_VIEW_CLIP_TO_SHAPE:
3982 		{
3983 			bool inverse;
3984 			link.Read<bool>(&inverse);
3985 
3986 			shape_data shape;
3987 			link.Read<int32>(&shape.opCount);
3988 			link.Read<int32>(&shape.ptCount);
3989 			shape.opSize = shape.opCount * sizeof(uint32);
3990 			shape.ptSize = shape.ptCount * sizeof(BPoint);
3991 			shape.opList = new(nothrow) uint32[shape.opCount];
3992 			shape.ptList = new(nothrow) BPoint[shape.ptCount];
3993 			if (link.Read(shape.opList, shape.opSize) >= B_OK
3994 				&& link.Read(shape.ptList, shape.ptSize) >= B_OK) {
3995 				picture->WriteClipToShape(shape.opCount, shape.opList,
3996 					shape.ptCount, shape.ptList, inverse);
3997 			}
3998 
3999 			delete[] shape.opList;
4000 			delete[] shape.ptList;
4001 			break;
4002 		}
4003 
4004 		case AS_VIEW_BEGIN_PICTURE:
4005 		{
4006 			BReference <ServerPicture> newPicture(App()->CreatePicture(), true);
4007 			if (newPicture != NULL) {
4008 				newPicture->PushPicture(picture);
4009 				newPicture->SyncState(fCurrentView);
4010 				fCurrentView->SetPicture(newPicture);
4011 			}
4012 			break;
4013 		}
4014 
4015 		case AS_VIEW_APPEND_TO_PICTURE:
4016 		{
4017 			int32 token;
4018 			link.Read<int32>(&token);
4019 
4020 			BReference<ServerPicture> appendPicture(App()->GetPicture(token), true);
4021 			if (appendPicture != NULL) {
4022 				//picture->SyncState(fCurrentView);
4023 				appendPicture->AppendPicture(picture);
4024 			}
4025 
4026 			fCurrentView->SetPicture(appendPicture);
4027 
4028 			break;
4029 		}
4030 
4031 		case AS_VIEW_END_PICTURE:
4032 		{
4033 			BReference<ServerPicture> poppedPicture(picture->PopPicture(), true);
4034 			fCurrentView->SetPicture(poppedPicture);
4035 
4036 			fLink.StartMessage(B_OK);
4037 			fLink.Attach<int32>(picture->Token());
4038 			fLink.Flush();
4039 			return true;
4040 		}
4041 
4042 		case AS_VIEW_BEGIN_LAYER:
4043 		{
4044 			uint8 opacity;
4045 			link.Read<uint8>(&opacity);
4046 
4047 			Layer* layer = dynamic_cast<Layer*>(picture);
4048 			if (layer == NULL)
4049 				break;
4050 
4051 			Layer* nextLayer = new(std::nothrow) Layer(opacity);
4052 			if (nextLayer == NULL)
4053 				break;
4054 
4055 			if (opacity != 255) {
4056 				fCurrentView->CurrentState()->SetDrawingMode(B_OP_ALPHA);
4057 				fCurrentView->CurrentState()->SetBlendingMode(B_PIXEL_ALPHA,
4058 					B_ALPHA_COMPOSITE);
4059 				fCurrentView->CurrentState()->SetDrawingModeLocked(true);
4060 			}
4061 
4062 			nextLayer->PushLayer(layer);
4063 			fCurrentView->SetPicture(nextLayer);
4064 			break;
4065 		}
4066 
4067 		case AS_VIEW_END_LAYER:
4068 		{
4069 			Layer* layer = dynamic_cast<Layer*>(picture);
4070 			if (layer == NULL)
4071 				break;
4072 
4073 			BReference<Layer> previousLayer(layer->PopLayer(), true);
4074 			if (previousLayer == NULL) {
4075 				// End last layer
4076 				return false;
4077 			}
4078 			fCurrentView->SetPicture(previousLayer);
4079 
4080 			previousLayer->WriteBlendLayer(layer);
4081 			break;
4082 		}
4083 
4084 /*
4085 		case AS_VIEW_SET_BLENDING_MODE:
4086 		{
4087 			ViewBlendingModeInfo info;
4088 			link.Read<ViewBlendingModeInfo>(&info);
4089 
4090 			picture->BeginOp(B_PIC_SET_BLENDING_MODE);
4091 			picture->AddInt16((int16)info.sourceAlpha);
4092 			picture->AddInt16((int16)info.alphaFunction);
4093 			picture->EndOp();
4094 
4095 			fCurrentView->CurrentState()->SetBlendingMode(info.sourceAlpha,
4096 				info.alphaFunction);
4097 			fWindow->GetDrawingEngine()->SetBlendingMode(info.sourceAlpha,
4098 				info.alphaFunction);
4099 			break;
4100 		}*/
4101 		default:
4102 			return false;
4103 	}
4104 
4105 	if (link.NeedsReply()) {
4106 		fLink.StartMessage(B_ERROR);
4107 		fLink.Flush();
4108 	}
4109 	return true;
4110 }
4111 
4112 
4113 /*!	\brief Message-dispatching loop for the ServerWindow
4114 
4115 	Watches the ServerWindow's message port and dispatches as necessary
4116 */
4117 void
4118 ServerWindow::_MessageLooper()
4119 {
4120 	// Send a reply to our window - it is expecting fMessagePort
4121 	// port and some other info.
4122 
4123 	fLink.StartMessage(B_OK);
4124 	fLink.Attach<port_id>(fMessagePort);
4125 
4126 	int32 minWidth, maxWidth, minHeight, maxHeight;
4127 	fWindow->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
4128 
4129 	fLink.Attach<BRect>(fWindow->Frame());
4130 	fLink.Attach<float>((float)minWidth);
4131 	fLink.Attach<float>((float)maxWidth);
4132 	fLink.Attach<float>((float)minHeight);
4133 	fLink.Attach<float>((float)maxHeight);
4134 	fLink.Flush();
4135 
4136 	BPrivate::LinkReceiver& receiver = fLink.Receiver();
4137 	bool quitLoop = false;
4138 
4139 	while (!quitLoop) {
4140 		//STRACE(("info: ServerWindow::MonitorWin listening on port %ld.\n",
4141 		//	fMessagePort));
4142 
4143 		int32 code;
4144 		status_t status = receiver.GetNextMessage(code);
4145 		if (status != B_OK) {
4146 			// that shouldn't happen, it's our port
4147 			printf("Someone deleted our message port!\n");
4148 
4149 			// try to let our client die happily
4150 			NotifyQuitRequested();
4151 			break;
4152 		}
4153 
4154 #ifdef PROFILE_MESSAGE_LOOP
4155 		bigtime_t start = system_time();
4156 #endif
4157 
4158 		Lock();
4159 
4160 #ifdef PROFILE_MESSAGE_LOOP
4161 		bigtime_t diff = system_time() - start;
4162 		if (diff > 10000) {
4163 			printf("ServerWindow %s: lock acquisition took %" B_PRId64 " usecs\n",
4164 				Title(), diff);
4165 		}
4166 #endif
4167 
4168 		int32 messagesProcessed = 0;
4169 		bigtime_t processingStart = system_time();
4170 		bool lockedDesktopSingleWindow = false;
4171 
4172 		while (true) {
4173 			if (code == AS_DELETE_WINDOW || code == kMsgQuitLooper) {
4174 				// this means the client has been killed
4175 				DTRACE(("ServerWindow %s received 'AS_DELETE_WINDOW' message "
4176 					"code\n", Title()));
4177 
4178 				if (code == AS_DELETE_WINDOW) {
4179 					fLink.StartMessage(B_OK);
4180 					fLink.Flush();
4181 				}
4182 
4183 				if (lockedDesktopSingleWindow)
4184 					fDesktop->UnlockSingleWindow();
4185 
4186 				quitLoop = true;
4187 
4188 				// ServerWindow's destructor takes care of pulling this object
4189 				// off the desktop.
4190 				ASSERT(fWindow->IsHidden());
4191 				break;
4192 			}
4193 
4194 			// Acquire the appropriate lock
4195 			bool needsAllWindowsLocked = _MessageNeedsAllWindowsLocked(code);
4196 			if (needsAllWindowsLocked) {
4197 				// We may already still hold the read-lock from the previous
4198 				// inner-loop iteration.
4199 				if (lockedDesktopSingleWindow) {
4200 					fDesktop->UnlockSingleWindow();
4201 					lockedDesktopSingleWindow = false;
4202 				}
4203 				fDesktop->LockAllWindows();
4204 			} else {
4205 				// We never keep the write-lock across inner-loop iterations,
4206 				// so there is nothing else to do besides read-locking unless
4207 				// we already have the read-lock from the previous iteration.
4208 				if (!lockedDesktopSingleWindow) {
4209 					fDesktop->LockSingleWindow();
4210 					lockedDesktopSingleWindow = true;
4211 				}
4212 			}
4213 
4214 			if (atomic_and(&fRedrawRequested, 0) != 0) {
4215 #ifdef PROFILE_MESSAGE_LOOP
4216 				bigtime_t redrawStart = system_time();
4217 #endif
4218 				fWindow->RedrawDirtyRegion();
4219 #ifdef PROFILE_MESSAGE_LOOP
4220 				diff = system_time() - redrawStart;
4221 				atomic_add(&sRedrawProcessingTime.count, 1);
4222 # ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
4223 				atomic_add64(&sRedrawProcessingTime.time, diff);
4224 # else
4225 				sRedrawProcessingTime.time += diff;
4226 # endif
4227 #endif
4228 			}
4229 
4230 #ifdef PROFILE_MESSAGE_LOOP
4231 			bigtime_t dispatchStart = system_time();
4232 #endif
4233 			_DispatchMessage(code, receiver);
4234 
4235 #ifdef PROFILE_MESSAGE_LOOP
4236 			if (code >= 0 && code < AS_LAST_CODE) {
4237 				diff = system_time() - dispatchStart;
4238 				atomic_add(&sMessageProfile[code].count, 1);
4239 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
4240 				atomic_add64(&sMessageProfile[code].time, diff);
4241 #else
4242 				sMessageProfile[code].time += diff;
4243 #endif
4244 				if (diff > 10000) {
4245 					printf("ServerWindow %s: message %" B_PRId32 " took %"
4246 						B_PRId64 " usecs\n", Title(), code, diff);
4247 				}
4248 			}
4249 #endif
4250 
4251 			if (needsAllWindowsLocked)
4252 				fDesktop->UnlockAllWindows();
4253 
4254 			// Only process up to 70 waiting messages at once (we have the
4255 			// Desktop locked), but don't hold the lock longer than 10 ms
4256 			if (!receiver.HasMessages() || ++messagesProcessed > 70
4257 				|| system_time() - processingStart > 10000) {
4258 				if (lockedDesktopSingleWindow)
4259 					fDesktop->UnlockSingleWindow();
4260 				break;
4261 			}
4262 
4263 			// next message
4264 			status_t status = receiver.GetNextMessage(code);
4265 			if (status != B_OK) {
4266 				// that shouldn't happen, it's our port
4267 				printf("Someone deleted our message port!\n");
4268 				if (lockedDesktopSingleWindow)
4269 					fDesktop->UnlockSingleWindow();
4270 
4271 				// try to let our client die happily
4272 				NotifyQuitRequested();
4273 				break;
4274 			}
4275 		}
4276 
4277 		Unlock();
4278 	}
4279 
4280 	// We were asked to quit the message loop - either on request or because of
4281 	// an error.
4282 	Quit();
4283 		// does not return
4284 }
4285 
4286 
4287 void
4288 ServerWindow::ScreenChanged(const BMessage* message)
4289 {
4290 	SendMessageToClient(message);
4291 
4292 	if (fDirectWindowInfo.IsSet() && fDirectWindowInfo->IsFullScreen())
4293 		_ResizeToFullScreen();
4294 }
4295 
4296 
4297 status_t
4298 ServerWindow::SendMessageToClient(const BMessage* msg, int32 target) const
4299 {
4300 	if (target == B_NULL_TOKEN)
4301 		target = fClientToken;
4302 
4303 	BMessenger reply;
4304 	BMessage::Private messagePrivate((BMessage*)msg);
4305 	return messagePrivate.SendMessage(fClientLooperPort, fClientTeam, target,
4306 		0, false, reply);
4307 }
4308 
4309 
4310 Window*
4311 ServerWindow::MakeWindow(BRect frame, const char* name,
4312 	window_look look, window_feel feel, uint32 flags, uint32 workspace)
4313 {
4314 	// The non-offscreen ServerWindow uses the DrawingEngine instance from
4315 	// the desktop.
4316 	return new(std::nothrow) ::Window(frame, name, look, feel, flags,
4317 		workspace, this, fDesktop->HWInterface()->CreateDrawingEngine());
4318 }
4319 
4320 
4321 void
4322 ServerWindow::HandleDirectConnection(int32 bufferState, int32 driverState)
4323 {
4324 	ASSERT_MULTI_LOCKED(fDesktop->WindowLocker());
4325 
4326 	if (!fDirectWindowInfo.IsSet())
4327 		return;
4328 
4329 	STRACE(("HandleDirectConnection(bufferState = %" B_PRId32 ", driverState = "
4330 		"%" B_PRId32 ")\n", bufferState, driverState));
4331 
4332 	status_t status = fDirectWindowInfo->SetState(
4333 		(direct_buffer_state)bufferState, (direct_driver_state)driverState,
4334 		fDesktop->HWInterface()->FrontBuffer(), fWindow->Frame(),
4335 		fWindow->VisibleContentRegion());
4336 
4337 	if (status != B_OK) {
4338 		char errorString[256];
4339 		snprintf(errorString, sizeof(errorString),
4340 			"%s killed for a problem in DirectConnected(): %s",
4341 			App()->Signature(), strerror(status));
4342 		syslog(LOG_ERR, errorString);
4343 
4344 		// The client application didn't release the semaphore
4345 		// within the given timeout. Or something else went wrong.
4346 		// Deleting this member should make it crash.
4347 		fDirectWindowInfo.Unset();
4348 	} else if ((bufferState & B_DIRECT_MODE_MASK) == B_DIRECT_START)
4349 		fIsDirectlyAccessing = true;
4350 	else if ((bufferState & B_DIRECT_MODE_MASK) == B_DIRECT_STOP)
4351 		fIsDirectlyAccessing = false;
4352 }
4353 
4354 
4355 void
4356 ServerWindow::_SetCurrentView(View* view)
4357 {
4358 	if (fCurrentView == view)
4359 		return;
4360 
4361 	fCurrentView = view;
4362 	fCurrentDrawingRegionValid = false;
4363 	_UpdateDrawState(fCurrentView);
4364 
4365 #if 0
4366 #if DELAYED_BACKGROUND_CLEARING
4367 	if (fCurrentView && fCurrentView->IsBackgroundDirty()
4368 		&& fWindow->InUpdate()) {
4369 		DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
4370 		if (drawingEngine->LockParallelAccess()) {
4371 			fWindow->GetEffectiveDrawingRegion(fCurrentView,
4372 				fCurrentDrawingRegion);
4373 			fCurrentDrawingRegionValid = true;
4374 			BRegion dirty(fCurrentDrawingRegion);
4375 
4376 			BRegion content;
4377 			fWindow->GetContentRegion(&content);
4378 
4379 			fCurrentView->Draw(drawingEngine, &dirty, &content, false);
4380 
4381 			drawingEngine->UnlockParallelAccess();
4382 		}
4383 	}
4384 #endif
4385 #endif // 0
4386 }
4387 
4388 
4389 void
4390 ServerWindow::_UpdateDrawState(View* view)
4391 {
4392 	// switch the drawing state
4393 	// TODO: is it possible to scroll a view while it
4394 	// is being drawn? probably not... otherwise the
4395 	// "offsets" passed below would need to be updated again
4396 	DrawingEngine* drawingEngine = fWindow->GetDrawingEngine();
4397 	if (view != NULL && drawingEngine != NULL) {
4398 		BPoint leftTop(0, 0);
4399 		if (view->GetAlphaMask() != NULL) {
4400 			view->LocalToScreenTransform().Apply(&leftTop);
4401 			view->GetAlphaMask()->SetCanvasGeometry(leftTop, view->Bounds());
4402 			leftTop = BPoint(0, 0);
4403 		}
4404 		view->PenToScreenTransform().Apply(&leftTop);
4405 		drawingEngine->SetDrawState(view->CurrentState(), leftTop.x, leftTop.y);
4406 	}
4407 }
4408 
4409 
4410 void
4411 ServerWindow::_UpdateCurrentDrawingRegion()
4412 {
4413 	if (!fCurrentDrawingRegionValid
4414 		|| fWindow->DrawingRegionChanged(fCurrentView)) {
4415 		fWindow->GetEffectiveDrawingRegion(fCurrentView, fCurrentDrawingRegion);
4416 		fCurrentDrawingRegionValid = true;
4417 	}
4418 }
4419 
4420 
4421 bool
4422 ServerWindow::_MessageNeedsAllWindowsLocked(uint32 code) const
4423 {
4424 	switch (code) {
4425 		case AS_SET_WINDOW_TITLE:
4426 		case AS_ADD_TO_SUBSET:
4427 		case AS_REMOVE_FROM_SUBSET:
4428 		case AS_VIEW_CREATE_ROOT:
4429 		case AS_VIEW_CREATE:
4430 		case AS_SEND_BEHIND:
4431 		case AS_SET_LOOK:
4432 		case AS_SET_FEEL:
4433 		case AS_SET_FLAGS:
4434 		case AS_SET_WORKSPACES:
4435 		case AS_WINDOW_MOVE:
4436 		case AS_WINDOW_RESIZE:
4437 		case AS_SET_SIZE_LIMITS:
4438 		case AS_SYSTEM_FONT_CHANGED:
4439 		case AS_SET_DECORATOR_SETTINGS:
4440 		case AS_GET_MOUSE:
4441 		case AS_DIRECT_WINDOW_SET_FULLSCREEN:
4442 //		case AS_VIEW_SET_EVENT_MASK:
4443 //		case AS_VIEW_SET_MOUSE_EVENT_MASK:
4444 		case AS_TALK_TO_DESKTOP_LISTENER:
4445 			return true;
4446 		default:
4447 			return false;
4448 	}
4449 }
4450 
4451 
4452 void
4453 ServerWindow::_ResizeToFullScreen()
4454 {
4455 	BRect screenFrame;
4456 
4457 	{
4458 		AutoReadLocker _(fDesktop->ScreenLocker());
4459 		const Screen* screen = fWindow->Screen();
4460 		if (screen == NULL)
4461 			return;
4462 
4463 		screenFrame = fWindow->Screen()->Frame();
4464 	}
4465 
4466 	fDesktop->MoveWindowBy(fWindow.Get(),
4467 		screenFrame.left - fWindow->Frame().left,
4468 		screenFrame.top - fWindow->Frame().top);
4469 	fDesktop->ResizeWindowBy(fWindow.Get(),
4470 		screenFrame.Width() - fWindow->Frame().Width(),
4471 		screenFrame.Height() - fWindow->Frame().Height());
4472 }
4473 
4474 
4475 status_t
4476 ServerWindow::_EnableDirectWindowMode()
4477 {
4478 	if (fDirectWindowInfo.IsSet()) {
4479 		// already in direct window mode
4480 		return B_ERROR;
4481 	}
4482 
4483 	if (fDesktop->HWInterface()->FrontBuffer() == NULL) {
4484 		// direct window mode not supported
4485 		return B_UNSUPPORTED;
4486 	}
4487 
4488 	fDirectWindowInfo.SetTo(new(std::nothrow) DirectWindowInfo);
4489 	if (!fDirectWindowInfo.IsSet())
4490 		return B_NO_MEMORY;
4491 
4492 	status_t status = fDirectWindowInfo->InitCheck();
4493 	if (status != B_OK) {
4494 		fDirectWindowInfo.Unset();
4495 
4496 		return status;
4497 	}
4498 
4499 	return B_OK;
4500 }
4501 
4502 
4503 void
4504 ServerWindow::_DirectWindowSetFullScreen(bool enable)
4505 {
4506 	window_feel feel = kWindowScreenFeel;
4507 
4508 	if (enable) {
4509 		fDesktop->HWInterface()->SetCursorVisible(false);
4510 
4511 		fDirectWindowInfo->EnableFullScreen(fWindow->Frame(), fWindow->Feel());
4512 		_ResizeToFullScreen();
4513 	} else {
4514 		const BRect& originalFrame = fDirectWindowInfo->OriginalFrame();
4515 
4516 		fDirectWindowInfo->DisableFullScreen();
4517 
4518 		// Resize window back to its original size
4519 		fDesktop->MoveWindowBy(fWindow.Get(),
4520 			originalFrame.left - fWindow->Frame().left,
4521 			originalFrame.top - fWindow->Frame().top);
4522 		fDesktop->ResizeWindowBy(fWindow.Get(),
4523 			originalFrame.Width() - fWindow->Frame().Width(),
4524 			originalFrame.Height() - fWindow->Frame().Height());
4525 
4526 		fDesktop->HWInterface()->SetCursorVisible(true);
4527 	}
4528 
4529 	fDesktop->SetWindowFeel(fWindow.Get(), feel);
4530 }
4531