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