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