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