xref: /haiku/src/servers/app/ServerWindow.cpp (revision 0b2dbe7d46ee888392907c60131b7f7652314175)
1 /*
2  * Copyright 2001-2005, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Adrian Oanca <adioanca@cotty.iren.ro>
8  *		Stephan Aßmus <superstippi@gmx.de>
9  *		Stefano Ceccherini (burton666@libero.it)
10  *		Axel Dörfler, axeld@pinc-software.de
11  */
12 
13 #include <AppDefs.h>
14 #include <GraphicsDefs.h>
15 #include <Message.h>
16 #include <PortLink.h>
17 #include <Rect.h>
18 #include <View.h>
19 #include <ViewAux.h>
20 #include <Autolock.h>
21 
22 #include "AppServer.h"
23 #include "BGet++.h"
24 #include "DebugInfoManager.h"
25 #include "Desktop.h"
26 #include "DisplayDriver.h"
27 #include "HWInterface.h"
28 #include "Layer.h"
29 #include "MessagePrivate.h"
30 #include "RAMLinkMsgReader.h"
31 #include "RootLayer.h"
32 #include "ServerApp.h"
33 #include "ServerBitmap.h"
34 #include "ServerPicture.h"
35 #include "ServerProtocol.h"
36 #include "TokenHandler.h"
37 #include "Utils.h"
38 #include "WinBorder.h"
39 #include "Workspace.h"
40 
41 #include "ServerWindow.h"
42 
43 //#define DEBUG_SERVERWINDOW
44 //#define DEBUG_SERVERWINDOW_GRAPHICS
45 
46 
47 #ifdef DEBUG_SERVERWINDOW
48 #	include <stdio.h>
49 #	define STRACE(x) printf x
50 #else
51 #	define STRACE(x) ;
52 #endif
53 
54 #ifdef DEBUG_SERVERWINDOW_GRAPHICS
55 #	include <stdio.h>
56 #	define DTRACE(x) printf x
57 #else
58 #	define DTRACE(x) ;
59 #endif
60 
61 
62 static const uint32 kMsgWindowQuit = 'winQ';
63 
64 
65 /*!
66 	\brief Constructor
67 
68 	Does a lot of stuff to set up for the window - new decorator, new winborder, spawn a
69 	monitor thread.
70 */
71 ServerWindow::ServerWindow(const char *title, ServerApp *app,
72 	port_id clientPort, port_id looperPort, int32 handlerID,
73 	BRect frame, uint32 look, uint32 feel, uint32 flags, uint32 workspace)
74 	: BLocker(title && *title ? title : "Unnamed Window"),
75 	fTitle(title),
76 	fServerApp(app),
77 	fWinBorder(NULL),
78 	fClientTeam(app->ClientTeam()),
79 	fMessagePort(-1),
80 	fClientReplyPort(clientPort),
81 	fClientLooperPort(looperPort),
82 	fQuitting(false),
83 	fClientViewsWithInvalidCoords(B_VIEW_RESIZED),
84 	fHandlerToken(handlerID),
85 	fCurrentLayer(NULL)
86 {
87 	STRACE(("ServerWindow(%s)::ServerWindow()\n", title));
88 
89 	if (fTitle == NULL)
90 		fTitle = strdup("Unnamed Window");
91 	if (fTitle == NULL)
92 		return;
93 
94 	// fMessagePort is the port to which the app sends messages for the server
95 	fMessagePort = create_port(100, fTitle);
96 	if (fMessagePort < B_OK)
97 		return;
98 
99 	fLink.SetSenderPort(fClientReplyPort);
100 	fLink.SetReceiverPort(fMessagePort);
101 
102 	char name[60];
103 	snprintf(name, sizeof(name), "%ld: %s", fClientTeam, fTitle);
104 
105 	fWinBorder = new WinBorder(frame, name, look, feel, flags,
106 		workspace, this, gDesktop->GetDisplayDriver());
107 
108 	STRACE(("ServerWindow %s Created\n", fTitle));
109 }
110 
111 
112 //!Tears down all connections the main app_server objects, and deletes some internals.
113 ServerWindow::~ServerWindow()
114 {
115 	STRACE(("*ServerWindow (%s):~ServerWindow()\n", fTitle));
116 
117 	delete fWinBorder;
118 	free(const_cast<char *>(fTitle));
119 
120 	STRACE(("#ServerWindow(%s) will exit NOW\n", fTitle));
121 }
122 
123 
124 status_t
125 ServerWindow::InitCheck()
126 {
127 	if (fTitle == NULL || fWinBorder == NULL)
128 		return B_NO_MEMORY;
129 
130 	if (fMessagePort < B_OK)
131 		return fMessagePort;
132 
133 	return B_OK;
134 }
135 
136 
137 bool
138 ServerWindow::Run()
139 {
140 	BAutolock locker(this);
141 
142 	// Spawn our message-monitoring thread
143 	fThread = spawn_thread(_message_thread, fTitle, B_NORMAL_PRIORITY, this);
144 	if (fThread < B_OK)
145 		return false;
146 
147 	if (resume_thread(fThread) != B_OK) {
148 		kill_thread(fThread);
149 		fThread = -1;
150 		return false;
151 	}
152 
153 	// Send a reply to our window - it is expecting fMessagePort
154 	// port and some other info
155 
156 	fLink.StartMessage(SERVER_TRUE);
157 	fLink.Attach<port_id>(fMessagePort);
158 
159 	float minWidth, maxWidth, minHeight, maxHeight;
160 	fWinBorder->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
161 
162 	fLink.Attach<BRect>(fWinBorder->Frame());
163 	fLink.Attach<float>(minWidth);
164 	fLink.Attach<float>(maxWidth);
165 	fLink.Attach<float>(minHeight);
166 	fLink.Attach<float>(maxHeight);
167 	fLink.Flush();
168 
169 	return true;
170 }
171 
172 
173 void
174 ServerWindow::Quit()
175 {
176 	fQuitting = true;
177 
178 	if (fThread < B_OK) {
179 		delete this;
180 		return;
181 	}
182 
183 	if (fThread == find_thread(NULL)) {
184 		App()->RemoveWindow(this);
185 
186 		delete this;
187 		exit_thread(0);
188 	} else {
189 		PostMessage(AS_HIDE_WINDOW);
190 		PostMessage(kMsgWindowQuit);
191 	}
192 }
193 
194 
195 /*!
196 	\brief Send a message to the ServerWindow with no attachments
197 	\param code ID code of the message to post
198 */
199 void
200 ServerWindow::PostMessage(int32 code)
201 {
202 	BPrivate::LinkSender link(fMessagePort);
203 	link.StartMessage(code);
204 	link.Flush();
205 }
206 
207 
208 //! Forces the window border to update its decorator
209 void
210 ServerWindow::ReplaceDecorator()
211 {
212 	if (!IsLocked())
213 		debugger("you must lock a ServerWindow object before calling ::ReplaceDecorator()\n");
214 
215 	STRACE(("ServerWindow %s: Replace Decorator\n", fTitle));
216 	fWinBorder->UpdateDecorator();
217 }
218 
219 //! Shows the window's WinBorder
220 void
221 ServerWindow::Show()
222 {
223 	// NOTE: if you do something else, other than sending a port message, PLEASE lock
224 	STRACE(("ServerWindow %s: Show\n", Title()));
225 
226 	if (fQuitting || !fWinBorder->IsHidden())
227 		return;
228 
229 	fWinBorder->GetRootLayer()->ShowWinBorder(fWinBorder);
230 }
231 
232 //! Hides the window's WinBorder
233 void
234 ServerWindow::Hide()
235 {
236 	// NOTE: if you do something else, other than sending a port message, PLEASE lock
237 	STRACE(("ServerWindow %s: Hide\n", Title()));
238 
239 	if (fWinBorder->IsHidden())
240 		return;
241 
242 	fWinBorder->GetRootLayer()->HideWinBorder(fWinBorder);
243 }
244 
245 
246 //! Requests that the ServerWindow's BWindow quit
247 void
248 ServerWindow::NotifyQuitRequested()
249 {
250 	// NOTE: if you do something else, other than sending a port message, PLEASE lock
251 	STRACE(("ServerWindow %s: Quit\n", fTitle));
252 
253 	BMessage msg(B_QUIT_REQUESTED);
254 	SendMessageToClient(&msg);
255 }
256 
257 
258 void
259 ServerWindow::NotifyMinimize(bool minimize)
260 {
261 	// NOTE: if you do something else, other than sending a port message, PLEASE lock
262 	// This function doesn't need much -- check to make sure that we should and
263 	// send the message to the client. According to the BeBook, the BWindow hook function
264 	// does all the heavy lifting for us. :)
265 	bool sendMessages = false;
266 
267 	if (minimize) {
268 		if (!fWinBorder->IsHidden()) {
269 			Hide();
270 			sendMessages = true;
271 		}
272 	} else {
273 		if (fWinBorder->IsHidden()) {
274 			Show();
275 			sendMessages = true;
276 		}
277 	}
278 
279 	if (sendMessages) {
280 		BMessage msg(B_MINIMIZE);
281 		msg.AddInt64("when", real_time_clock_usecs());
282 		msg.AddBool("minimize", minimize);
283 
284 		SendMessageToClient(&msg);
285 	}
286 }
287 
288 //! Sends a message to the client to perform a Zoom
289 void
290 ServerWindow::NotifyZoom()
291 {
292 	// NOTE: if you do something else, other than sending a port message, PLEASE lock
293 	BMessage msg(B_ZOOM);
294 	SendMessageToClient(&msg);
295 }
296 
297 /*!
298 	\brief Notifies window of a change in screen resolution
299 	\param frame Size of the new resolution
300 	\param color_space Color space of the new screen mode
301 */
302 void
303 ServerWindow::NotifyScreenModeChanged(const BRect frame, const color_space colorSpace)
304 {
305 	STRACE(("ServerWindow %s: ScreenModeChanged\n", fTitle));
306 
307 	BMessage msg(B_SCREEN_CHANGED);
308 	msg.AddRect("frame", frame);
309 	msg.AddInt32("mode", (int32)colorSpace);
310 
311 	SendMessageToClient(&msg);
312 }
313 
314 /*!
315 	\brief Sets the font state for a layer
316 	\param layer The layer to set the font
317 */
318 inline void
319 ServerWindow::SetLayerFontState(Layer *layer, BPrivate::LinkReceiver &link)
320 {
321 	STRACE(("ServerWindow %s: SetLayerFontStateMessage for layer %s\n",
322 			fTitle, layer->Name()));
323 	// NOTE: no need to check for a lock. This is a private method.
324 
325 	layer->fLayerData->ReadFontFromLink(link);
326 }
327 
328 
329 inline void
330 ServerWindow::SetLayerState(Layer *layer, BPrivate::LinkReceiver &link)
331 {
332 	STRACE(("ServerWindow %s: SetLayerState for layer %s\n", Title(),
333 			 layer->Name()));
334 	// NOTE: no need to check for a lock. This is a private method.
335 
336 	layer->fLayerData->ReadFromLink(link);
337 	// TODO: Rebuild clipping here?
338 }
339 
340 
341 inline Layer*
342 ServerWindow::CreateLayerTree(BPrivate::LinkReceiver &link, Layer **_parent)
343 {
344 	// NOTE: no need to check for a lock. This is a private method.
345 
346 	int32 token;
347 	BRect frame;
348 	uint32 resizeMask;
349 	uint32 eventMask;
350 	uint32 eventOptions;
351 	uint32 flags;
352 	bool hidden;
353 	int32 parentToken;
354 	char *name = NULL;
355 	rgb_color viewColor;
356 
357 	link.Read<int32>(&token);
358 	link.ReadString(&name);
359 	link.Read<BRect>(&frame);
360 	link.Read<uint32>(&resizeMask);
361 	link.Read<uint32>(&eventMask);
362 	link.Read<uint32>(&eventOptions);
363 	link.Read<uint32>(&flags);
364 	link.Read<bool>(&hidden);
365 	link.Read<rgb_color>(&viewColor);
366 	link.Read<int32>(&parentToken);
367 
368 	STRACE(("ServerWindow(%s)::CreateLayerTree()-> layer %s, token %ld\n",
369 		fTitle, name, token));
370 
371 	Layer *newLayer = new Layer(frame, name, token, resizeMask,
372 			flags, gDesktop->GetDisplayDriver());
373 
374 	free(name);
375 
376 	// there is no way of setting this, other than manually :-)
377 	newLayer->fViewColor = viewColor;
378 	newLayer->fHidden = hidden;
379 	newLayer->fEventMask = eventMask;
380 	newLayer->fEventOptions = eventOptions;
381 	newLayer->fOwner = fWinBorder;
382 
383 	if (_parent) {
384 		Layer *parent = fWinBorder->FindLayer(parentToken);
385 		if (parent == NULL)
386 			CRITICAL("View token not found!\n");
387 
388 		*_parent = parent;
389 	}
390 
391 	return newLayer;
392 }
393 
394 
395 void
396 ServerWindow::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
397 {
398 	if (fCurrentLayer == NULL && code != AS_LAYER_CREATE_ROOT && code != AS_LAYER_CREATE) {
399 		printf("ServerWindow %s received unexpected code - message offset %ld before top_view attached.\n", Title(), code - SERVER_TRUE);
400 		return;
401 	}
402 
403 	RootLayer *myRootLayer = fWinBorder->GetRootLayer();
404 	myRootLayer->Lock();
405 
406 	switch (code) {
407 		//--------- BView Messages -----------------
408 		case AS_LAYER_SCROLL:
409 		{
410 			DTRACE(("ServerWindow %s: Message AS_LAYER_SCROLL: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
411 			float dh;
412 			float dv;
413 
414 			link.Read<float>(&dh);
415 			link.Read<float>(&dv);
416 #ifndef NEW_CLIPPING
417 			// scroll visually by using the CopyBits() implementation
418 			// this will also take care of invalidating previously invisible
419 			// areas (areas scrolled into view)
420 			BRect src = fCurrentLayer->Bounds();
421 			BRect dst = src;
422 			// NOTE: if we scroll down, the contents are moved *up*
423 			dst.OffsetBy(-dh, -dv);
424 
425 			// TODO: Are origin and scale handled in this conversion?
426 			src = fCurrentLayer->ConvertToTop(src);
427 			dst = fCurrentLayer->ConvertToTop(dst);
428 
429 			int32 xOffset = (int32)(dst.left - src.left);
430 			int32 yOffset = (int32)(dst.top - src.top);
431 
432 			// this little detail is where it differs from CopyBits()
433 			// -> it will invalidate areas previously out of screen
434 			dst = dst | src;
435 
436 			fCurrentLayer->fLayerData->OffsetOrigin(BPoint(dh, dv));
437 
438 			fCurrentLayer->CopyBits(src, dst, xOffset, yOffset);
439 #else
440 			fCurrentLayer->ScrollBy(dh, dv);
441 #endif
442 
443 			break;
444 		}
445 		case AS_LAYER_COPY_BITS:
446 		{
447 			BRect src;
448 			BRect dst;
449 
450 			link.Read<BRect>(&src);
451 			link.Read<BRect>(&dst);
452 
453 			// TODO: Are origin and scale handled in this conversion?
454 			src = fCurrentLayer->ConvertToTop(src);
455 			dst = fCurrentLayer->ConvertToTop(dst);
456 
457 			int32 xOffset = (int32)(dst.left - src.left);
458 			int32 yOffset = (int32)(dst.top - src.top);
459 
460 			fCurrentLayer->CopyBits(src, dst, xOffset, yOffset);
461 
462 			break;
463 		}
464 		case AS_SET_CURRENT_LAYER:
465 		{
466 			int32 token;
467 
468 			link.Read<int32>(&token);
469 
470 myRootLayer->Lock();
471 			Layer *current = fWinBorder->FindLayer(token);
472 myRootLayer->Unlock();
473 			if (current) {
474 				DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: %s, token %ld\n", fTitle, current->Name(), token));
475 			} else {
476 				DTRACE(("ServerWindow %s: Message AS_SET_CURRENT_LAYER: layer not found, token %ld\n", fTitle, token));
477 			}
478 
479 			if (current)
480 				fCurrentLayer = current;
481 			else // hope this NEVER happens! :-)
482 				CRITICAL("Server PANIC: window cannot find Layer with ID\n");
483 			// ToDo: if this happens, we probably want to kill the app and clean up
484 			break;
485 		}
486 
487 		case AS_LAYER_CREATE_ROOT:
488 		{
489 			STRACE(("ServerWindow %s: Message AS_LAYER_CREATE_ROOT\n", fTitle));
490 
491 			// Start receiving top_view data -- pass NULL as the parent view.
492 			// This should be the *only* place where this happens.
493 			if (fCurrentLayer != NULL)
494 				break;
495 
496 myRootLayer->Lock();
497 			fWinBorder->fTopLayer = CreateLayerTree(link, NULL);
498 			fWinBorder->fTopLayer->SetAsTopLayer(true);
499 			fCurrentLayer = fWinBorder->fTopLayer;
500 
501 			// connect decorator and top layer.
502 			fWinBorder->AddChild(fWinBorder->fTopLayer, NULL);
503 myRootLayer->Unlock();
504 			break;
505 		}
506 
507 		case AS_LAYER_CREATE:
508 		{
509 			STRACE(("ServerWindow %s: Message AS_LAYER_CREATE: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
510 
511 			Layer* parent = NULL;
512 			Layer* newLayer = CreateLayerTree(link, &parent);
513 myRootLayer->Lock();
514 			if (parent != NULL)
515 				parent->AddChild(newLayer, this);
516 
517 			if (!newLayer->IsHidden() && parent)
518 #ifndef NEW_CLIPPING
519 				myRootLayer->GoInvalidate(newLayer, newLayer->fFull);
520 #else
521 			{
522 				BRegion invalidRegion;
523 				newLayer->GetWantedRegion(invalidRegion);
524 				myRootLayer->GoInvalidate(newLayer, invalidRegion);
525 			}
526 #endif
527 
528 myRootLayer->Unlock();
529 			break;
530 		}
531 		case AS_LAYER_DELETE:
532 		{
533 			// Received when a view is detached from a window. This is definitely
534 			// the less taxing operation - we call PruneTree() on the removed
535 			// layer, detach the layer itself, delete it, and invalidate the
536 			// area assuming that the view was visible when removed
537 
538 			STRACE(("ServerWindow %s: AS_LAYER_DELETE(self)...\n", fTitle));
539 myRootLayer->Lock();
540 			Layer *parent = fCurrentLayer->fParent;
541 			BRegion *invalidRegion = NULL;
542 
543 			if (!fCurrentLayer->IsHidden() && parent) {
544 #ifndef NEW_CLIPPING
545 				if (fCurrentLayer->fFullVisible.CountRects() > 0)
546 					invalidRegion = new BRegion(fCurrentLayer->fFullVisible);
547 #else
548 				if (fCurrentLayer->FullVisible().Frame().IsValid())
549 					invalidRegion = new BRegion(fCurrentLayer->FullVisible());
550 #endif
551 			}
552 
553 			// here we remove current layer from list.
554 			fCurrentLayer->RemoveSelf();
555 			fCurrentLayer->PruneTree();
556 
557 			if (invalidRegion) {
558 				myRootLayer->GoInvalidate(parent, *invalidRegion);
559 				delete invalidRegion;
560 			}
561 myRootLayer->Unlock();
562 
563 			#ifdef DEBUG_SERVERWINDOW
564 			parent->PrintTree();
565 			#endif
566 			STRACE(("DONE: ServerWindow %s: Message AS_DELETE_LAYER: Parent: %s Layer: %s\n", fTitle, parent->Name(), fCurrentLayer->Name()));
567 
568 			delete fCurrentLayer;
569 
570 			fCurrentLayer = parent;
571 			break;
572 		}
573 		case AS_LAYER_SET_STATE:
574 		{
575 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_STATE: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
576 //			SetLayerState(fCurrentLayer);
577 			SetLayerState(fCurrentLayer, link);
578 			// TODO: should this be moved into SetLayerState?
579 			// If it _always_ needs to be done afterwards, then yes!
580 #ifndef NEW_CLIPPING
581 			fCurrentLayer->RebuildFullRegion();
582 #endif
583 			break;
584 		}
585 		case AS_LAYER_SET_FONT_STATE:
586 		{
587 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_FONT_STATE: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
588 //			SetLayerFontState(fCurrentLayer);
589 			SetLayerFontState(fCurrentLayer, link);
590 #ifndef NEW_CLIPPING
591 			fCurrentLayer->RebuildFullRegion();
592 #endif
593 			break;
594 		}
595 		case AS_LAYER_GET_STATE:
596 		{
597 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_STATE: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
598 
599 			fLink.StartMessage(SERVER_TRUE);
600 
601 			// attach state data
602 			fCurrentLayer->fLayerData->WriteToLink(fLink.Sender());
603 			fLink.Flush();
604 			break;
605 		}
606 		case AS_LAYER_SET_MOUSE_EVENT_MASK:
607 		{
608 			STRACE(("ServerWindow %s: Message AS_LAYER_SET_MOUSE_EVENT_MASK: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
609 
610 			uint32		mask;
611 			uint32		options;
612 
613 			link.Read<uint32>(&mask);
614 			link.Read<uint32>(&options);
615 
616 			myRootLayer->SetEventMaskLayer(fCurrentLayer, mask, options);
617 			break;
618 		}
619 		case AS_LAYER_MOVE_TO:
620 		{
621 			STRACE(("ServerWindow %s: Message AS_LAYER_MOVE_TO: Layer name: %s\n",
622 				fTitle, fCurrentLayer->Name()));
623 
624 			float x, y;
625 			link.Read<float>(&x);
626 			link.Read<float>(&y);
627 
628 			float offsetX = x - fCurrentLayer->fFrame.left;
629 			float offsetY = y - fCurrentLayer->fFrame.top;
630 
631 			fCurrentLayer->MoveBy(offsetX, offsetY);
632 			break;
633 		}
634 		case AS_LAYER_RESIZE_TO:
635 		{
636 			STRACE(("ServerWindow %s: Message AS_LAYER_RESIZE_TO: Layer name: %s\n",
637 				fTitle, fCurrentLayer->Name()));
638 
639 			float newWidth, newHeight;
640 			link.Read<float>(&newWidth);
641 			link.Read<float>(&newHeight);
642 
643 			// TODO: If fCurrentLayer is a window, check for minimum size allowed.
644 			// Need WinBorder::GetSizeLimits
645 			float deltaWidth = newWidth - fCurrentLayer->fFrame.Width();
646 			float deltaHeight = newHeight - fCurrentLayer->fFrame.Height();
647 
648 			fCurrentLayer->ResizeBy(deltaWidth, deltaHeight);
649 			break;
650 		}
651 		case AS_LAYER_GET_COORD:
652 		{
653 			STRACE(("ServerWindow %s: Message AS_LAYER_GET_COORD: Layer: %s\n", Title(), fCurrentLayer->Name()));
654 			fLink.StartMessage(SERVER_TRUE);
655 			// our offset in the parent -> will be originX and originY in BView
656 			fLink.Attach<float>(fCurrentLayer->fFrame.left);
657 			fLink.Attach<float>(fCurrentLayer->fFrame.top);
658 			// convert frame to bounds
659 			fLink.Attach<BRect>(fCurrentLayer->fFrame.OffsetToCopy(fCurrentLayer->BoundsOrigin()));
660 			fLink.Flush();
661 			break;
662 		}
663 		case AS_LAYER_SET_ORIGIN:
664 		{
665 			STRACE(("ServerWindow %s: Message AS_LAYER_SET_ORIGIN: Layer: %s\n", Title(), fCurrentLayer->Name()));
666 			float x, y;
667 
668 			link.Read<float>(&x);
669 			link.Read<float>(&y);
670 
671 			fCurrentLayer->fLayerData->SetOrigin(BPoint(x, y));
672 			break;
673 		}
674 		case AS_LAYER_GET_ORIGIN:
675 		{
676 			STRACE(("ServerWindow %s: Message AS_LAYER_GET_ORIGIN: Layer: %s\n", Title(), fCurrentLayer->Name()));
677 			fLink.StartMessage(SERVER_TRUE);
678 			fLink.Attach<BPoint>(fCurrentLayer->fLayerData->Origin());
679 			fLink.Flush();
680 			break;
681 		}
682 		case AS_LAYER_RESIZE_MODE:
683 		{
684 			STRACE(("ServerWindow %s: Message AS_LAYER_RESIZE_MODE: Layer: %s\n", Title(), fCurrentLayer->Name()));
685 			link.Read<uint32>(&(fCurrentLayer->fResizeMode));
686 			break;
687 		}
688 		case AS_LAYER_CURSOR:
689 		{
690 			DTRACE(("ServerWindow %s: Message AS_LAYER_CURSOR: Layer: %s - NOT IMPLEMENTED\n", Title(), fCurrentLayer->Name()));
691 			int32 token;
692 
693 			link.Read<int32>(&token);
694 
695 			// TODO: implement; I think each Layer should have a member pointing
696 			// to this requested cursor.
697 
698 			break;
699 		}
700 		case AS_LAYER_SET_FLAGS:
701 		{
702 			link.Read<uint32>(&(fCurrentLayer->fFlags));
703 
704 			STRACE(("ServerWindow %s: Message AS_LAYER_SET_FLAGS: Layer: %s\n", Title(), fCurrentLayer->Name()));
705 			break;
706 		}
707 		case AS_LAYER_HIDE:
708 		{
709 			STRACE(("ServerWindow %s: Message AS_LAYER_HIDE: Layer: %s\n", Title(), fCurrentLayer->Name()));
710 			fCurrentLayer->Hide();
711 			break;
712 		}
713 		case AS_LAYER_SHOW:
714 		{
715 			STRACE(("ServerWindow %s: Message AS_LAYER_SHOW: Layer: %s\n", Title(), fCurrentLayer->Name()));
716 			fCurrentLayer->Show();
717 			break;
718 		}
719 		case AS_LAYER_SET_LINE_MODE:
720 		{
721 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_LINE_MODE: Layer: %s\n", Title(), fCurrentLayer->Name()));
722 			int8 lineCap, lineJoin;
723 			float miterLimit;
724 
725 			// TODO: Look into locking scheme relating to Layers and modifying redraw-related members
726 
727 			link.Read<int8>(&lineCap);
728 			link.Read<int8>(&lineJoin);
729 			link.Read<float>(&miterLimit);
730 
731 			fCurrentLayer->fLayerData->SetLineCapMode((cap_mode)lineCap);
732 			fCurrentLayer->fLayerData->SetLineJoinMode((join_mode)lineJoin);
733 			fCurrentLayer->fLayerData->SetMiterLimit(miterLimit);
734 
735 			break;
736 		}
737 		case AS_LAYER_GET_LINE_MODE:
738 		{
739 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_LINE_MODE: Layer: %s\n", Title(), fCurrentLayer->Name()));
740 			fLink.StartMessage(SERVER_TRUE);
741 			fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->LineCapMode()));
742 			fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->LineJoinMode()));
743 			fLink.Attach<float>(fCurrentLayer->fLayerData->MiterLimit());
744 			fLink.Flush();
745 
746 			break;
747 		}
748 		case AS_LAYER_PUSH_STATE:
749 		{
750 			DTRACE(("ServerWindow %s: Message AS_LAYER_PUSH_STATE: Layer: %s\n", Title(), fCurrentLayer->Name()));
751 
752 			fCurrentLayer->PushState();
753 #ifndef NEW_CLIPPING
754 			fCurrentLayer->RebuildFullRegion();
755 #endif
756 			break;
757 		}
758 		case AS_LAYER_POP_STATE:
759 		{
760 			DTRACE(("ServerWindow %s: Message AS_LAYER_POP_STATE: Layer: %s\n", Title(), fCurrentLayer->Name()));
761 
762 			fCurrentLayer->PopState();
763 #ifndef NEW_CLIPPING
764 			fCurrentLayer->RebuildFullRegion();
765 #endif
766 			break;
767 		}
768 		case AS_LAYER_SET_SCALE:
769 		{
770 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_SCALE: Layer: %s\n", Title(), fCurrentLayer->Name()));
771 			float scale;
772 			link.Read<float>(&scale);
773 			// TODO: The BeBook says, if you call SetScale() it will be
774 			// multiplied with the scale from all previous states on the stack
775 			fCurrentLayer->fLayerData->SetScale(scale);
776 			break;
777 		}
778 		case AS_LAYER_GET_SCALE:
779 		{
780 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_SCALE: Layer: %s\n", Title(), fCurrentLayer->Name()));
781 			LayerData		*ld = fCurrentLayer->fLayerData;
782 
783 			// TODO: And here, we're taking that into account, but not above
784 			// -> refactor put scale into Layer, or better yet, when the
785 			// state stack is within Layer, PushState() should multiply
786 			// by the previous last states scale. Would fix the problem above too.
787 			float			scale = ld->Scale();
788 
789 			while ((ld = ld->prevState))
790 				scale *= ld->Scale();
791 
792 			fLink.StartMessage(SERVER_TRUE);
793 			fLink.Attach<float>(scale);
794 			fLink.Flush();
795 
796 			break;
797 		}
798 		case AS_LAYER_SET_PEN_LOC:
799 		{
800 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_LOC: Layer: %s\n", Title(), fCurrentLayer->Name()));
801 			float		x, y;
802 
803 			link.Read<float>(&x);
804 			link.Read<float>(&y);
805 
806 			fCurrentLayer->fLayerData->SetPenLocation(BPoint(x, y));
807 
808 			break;
809 		}
810 		case AS_LAYER_GET_PEN_LOC:
811 		{
812 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_PEN_LOC: Layer: %s\n", Title(), fCurrentLayer->Name()));
813 			fLink.StartMessage(SERVER_TRUE);
814 			fLink.Attach<BPoint>(fCurrentLayer->fLayerData->PenLocation());
815 			fLink.Flush();
816 
817 			break;
818 		}
819 		case AS_LAYER_SET_PEN_SIZE:
820 		{
821 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PEN_SIZE: Layer: %s\n", Title(), fCurrentLayer->Name()));
822 			float penSize;
823 			link.Read<float>(&penSize);
824 			fCurrentLayer->fLayerData->SetPenSize(penSize);
825 
826 			break;
827 		}
828 		case AS_LAYER_GET_PEN_SIZE:
829 		{
830 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_PEN_SIZE: Layer: %s\n", Title(), fCurrentLayer->Name()));
831 			fLink.StartMessage(SERVER_TRUE);
832 			fLink.Attach<float>(fCurrentLayer->fLayerData->PenSize());
833 			fLink.Flush();
834 
835 			break;
836 		}
837 		case AS_LAYER_SET_VIEW_COLOR:
838 		{
839 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_VIEW_COLOR: Layer: %s\n", Title(), fCurrentLayer->Name()));
840 			rgb_color c;
841 
842 			link.Read(&c, sizeof(rgb_color));
843 myRootLayer->Lock();
844 			fCurrentLayer->SetViewColor(RGBColor(c));
845 
846 #ifndef NEW_CLIPPING
847 			myRootLayer->GoRedraw(fCurrentLayer, fCurrentLayer->fVisible);
848 #else
849 			myRootLayer->GoRedraw(fCurrentLayer, fCurrentLayer->VisibleRegion());
850 #endif
851 myRootLayer->Unlock();
852 			break;
853 		}
854 
855 		case AS_LAYER_GET_HIGH_COLOR:
856 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_HIGH_COLOR: Layer: %s\n",
857 				Title(), fCurrentLayer->Name()));
858 
859 			fLink.StartMessage(SERVER_TRUE);
860 			fLink.Attach<rgb_color>(fCurrentLayer->fLayerData->HighColor().GetColor32());
861 			fLink.Flush();
862 			break;
863 
864 		case AS_LAYER_GET_LOW_COLOR:
865 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_LOW_COLOR: Layer: %s\n",
866 				Title(), fCurrentLayer->Name()));
867 
868 			fLink.StartMessage(SERVER_TRUE);
869 			fLink.Attach<rgb_color>(fCurrentLayer->fLayerData->LowColor().GetColor32());
870 			fLink.Flush();
871 			break;
872 
873 		case AS_LAYER_GET_VIEW_COLOR:
874 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_VIEW_COLOR: Layer: %s\n",
875 				Title(), fCurrentLayer->Name()));
876 
877 			fLink.StartMessage(SERVER_TRUE);
878 			fLink.Attach<rgb_color>(fCurrentLayer->ViewColor().GetColor32());
879 			fLink.Flush();
880 			break;
881 
882 		case AS_LAYER_SET_BLEND_MODE:
883 		{
884 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_BLEND_MODE: Layer: %s\n", Title(), fCurrentLayer->Name()));
885 			int8 srcAlpha, alphaFunc;
886 
887 			link.Read<int8>(&srcAlpha);
888 			link.Read<int8>(&alphaFunc);
889 
890 			fCurrentLayer->fLayerData->SetBlendingMode((source_alpha)srcAlpha,
891 											(alpha_function)alphaFunc);
892 
893 			break;
894 		}
895 		case AS_LAYER_GET_BLEND_MODE:
896 		{
897 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_BLEND_MODE: Layer: %s\n", Title(), fCurrentLayer->Name()));
898 			fLink.StartMessage(SERVER_TRUE);
899 			fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->AlphaSrcMode()));
900 			fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->AlphaFncMode()));
901 			fLink.Flush();
902 
903 			break;
904 		}
905 		case AS_LAYER_SET_DRAW_MODE:
906 		{
907 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_DRAW_MODE: Layer: %s\n", Title(), fCurrentLayer->Name()));
908 			int8 drawingMode;
909 
910 			link.Read<int8>(&drawingMode);
911 
912 			fCurrentLayer->fLayerData->SetDrawingMode((drawing_mode)drawingMode);
913 
914 			break;
915 		}
916 		case AS_LAYER_GET_DRAW_MODE:
917 		{
918 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_DRAW_MODE: Layer: %s\n", Title(), fCurrentLayer->Name()));
919 			fLink.StartMessage(SERVER_TRUE);
920 			fLink.Attach<int8>((int8)(fCurrentLayer->fLayerData->GetDrawingMode()));
921 			fLink.Flush();
922 
923 			break;
924 		}
925 		case AS_LAYER_PRINT_ALIASING:
926 		{
927 			DTRACE(("ServerWindow %s: Message AS_LAYER_PRINT_ALIASING: Layer: %s\n", Title(), fCurrentLayer->Name()));
928 			bool fontAliasing;
929 			link.Read<bool>(&fontAliasing);
930 			fCurrentLayer->fLayerData->SetFontAntiAliasing(!fontAliasing);
931 
932 			break;
933 		}
934 		case AS_LAYER_CLIP_TO_PICTURE:
935 		{
936 			DTRACE(("ServerWindow %s: Message AS_LAYER_CLIP_TO_PICTURE: Layer: %s\n", Title(), fCurrentLayer->Name()));
937 		// TODO: you are not allowed to use Layer regions here!!!
938 		// If there is no other way, then first lock RootLayer object first.
939 
940 			int32 pictureToken;
941 			BPoint where;
942 			bool inverse = false;
943 
944 			link.Read<int32>(&pictureToken);
945 			link.Read<BPoint>(&where);
946 			link.Read<bool>(&inverse);
947 
948 			// search for a picture with the specified token.
949 			ServerPicture *picture = fServerApp->FindPicture(pictureToken);
950 			// TODO: Increase that picture's reference count.(~ allocate a picture)
951 			if (picture == NULL)
952 				break;
953 
954 			BRegion region;
955 			// TODO: I think we also need the BView's token
956 			// I think PictureToRegion would fit better into the Layer class (?)
957 			if (PictureToRegion(picture, region, inverse, where) < B_OK)
958 				break;
959 
960 			fCurrentLayer->fLayerData->SetClippingRegion(region);
961 
962 #ifndef NEW_CLIPPING
963 			fCurrentLayer->RebuildFullRegion();
964 #endif
965 			if (!(fCurrentLayer->IsHidden()) && !fWinBorder->InUpdate())
966 #ifndef NEW_CLIPPING
967 				myRootLayer->GoInvalidate(fCurrentLayer, fCurrentLayer->fFull);
968 #else
969 			{
970 				BRegion invalidRegion;
971 				fCurrentLayer->GetWantedRegion(invalidRegion);
972 				myRootLayer->GoInvalidate(fCurrentLayer, invalidRegion);
973 			}
974 #endif
975 
976 			break;
977 		}
978 
979 		case AS_LAYER_GET_CLIP_REGION:
980 		{
981 			DTRACE(("ServerWindow %s: Message AS_LAYER_GET_CLIP_REGION: Layer: %s\n", Title(), fCurrentLayer->Name()));
982 
983 			// if this Layer is hidden, it is clear that its visible region is void.
984 			if (fCurrentLayer->IsHidden())
985 			{
986 				fLink.StartMessage(SERVER_TRUE);
987 				fLink.Attach<int32>(0L);
988 				fLink.Flush();
989 			}
990 			else
991 			{
992 				// TODO: Watch out for the coordinate system in AS_LAYER_GET_CLIP_REGION
993 				BRegion reg;
994 				LayerData *ld;
995 				int32 noOfRects;
996 
997 				ld = fCurrentLayer->fLayerData;
998 				if (ld->ClippingRegion())
999 					reg.IntersectWith(ld->ClippingRegion());
1000 
1001 				// TODO: This could also be done more reliably in the Layer,
1002 				// when the State stack is implemented there. There should be
1003 				// DrawData::fCulmulatedClippingRegion...
1004 				// TODO: the DrawData clipping region should be in local view coords.
1005 				while ((ld = ld->prevState)) {
1006 					if (ld->ClippingRegion())
1007 						reg.IntersectWith(ld->ClippingRegion());
1008 				}
1009 
1010 				noOfRects = reg.CountRects();
1011 				fLink.StartMessage(SERVER_TRUE);
1012 				fLink.Attach<int32>(noOfRects);
1013 
1014 				for(int i = 0; i < noOfRects; i++)
1015 					fLink.Attach<BRect>(reg.RectAt(i));
1016 			}
1017 			break;
1018 		}
1019 		case AS_LAYER_SET_CLIP_REGION:
1020 		{
1021 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_CLIP_REGION: Layer: %s\n", Title(), fCurrentLayer->Name()));
1022 
1023 			// TODO: Watch out for the coordinate system in AS_LAYER_SET_CLIP_REGION
1024 			int32 noOfRects;
1025 			BRect r;
1026 
1027 			link.Read<int32>(&noOfRects);
1028 
1029 			BRegion region;
1030 			for (int i = 0; i < noOfRects; i++) {
1031 				link.Read<BRect>(&r);
1032 				region.Include(r);
1033 			}
1034 			fCurrentLayer->fLayerData->SetClippingRegion(region);
1035 
1036 #ifndef NEW_CLIPPING
1037 			fCurrentLayer->RebuildFullRegion();
1038 			if (!(fCurrentLayer->IsHidden()) && !fWinBorder->InUpdate())
1039 				myRootLayer->GoInvalidate(fCurrentLayer, fCurrentLayer->fFull);
1040 #else
1041 			if (!(fCurrentLayer->IsHidden()) && !fWinBorder->InUpdate())
1042 				myRootLayer->GoInvalidate(fCurrentLayer, fCurrentLayer->Frame());
1043 #endif
1044 
1045 			break;
1046 		}
1047 		case AS_LAYER_INVAL_RECT:
1048 		{
1049 			DTRACE(("ServerWindow %s: Message AS_LAYER_INVAL_RECT: Layer: %s\n", Title(), fCurrentLayer->Name()));
1050 
1051 			// TODO: handle transformation (origin and scale) prior to converting to top
1052 			BRect		invalRect;
1053 
1054 			link.Read<BRect>(&invalRect);
1055 			BRect converted(fCurrentLayer->ConvertToTop(invalRect.LeftTop()),
1056 							fCurrentLayer->ConvertToTop(invalRect.RightBottom()));
1057 			BRegion invalidRegion(converted);
1058 //			invalidRegion.IntersectWith(&fCurrentLayer->fVisible);
1059 
1060 			myRootLayer->GoRedraw(fWinBorder, invalidRegion);
1061 //			myRootLayer->RequestDraw(invalidRegion, fWinBorder);
1062 			break;
1063 		}
1064 		case AS_LAYER_INVAL_REGION:
1065 		{
1066 			DTRACE(("ServerWindow %s: Message AS_LAYER_INVAL_RECT: Layer: %s\n", Title(), fCurrentLayer->Name()));
1067 
1068 			// TODO: handle transformation (origin and scale) prior to converting to top
1069 			// TODO: Handle conversion to top
1070 			BRegion invalReg;
1071 			int32 noOfRects;
1072 			BRect rect;
1073 
1074 			link.Read<int32>(&noOfRects);
1075 
1076 			for(int i = 0; i < noOfRects; i++)
1077 			{
1078 				link.Read<BRect>(&rect);
1079 				invalReg.Include(rect);
1080 			}
1081 
1082 			myRootLayer->GoRedraw(fCurrentLayer, invalReg);
1083 
1084 			break;
1085 		}
1086 		case AS_BEGIN_UPDATE:
1087 		{
1088 			DTRACE(("ServerWindowo %s: AS_BEGIN_UPDATE\n", Title()));
1089 			fWinBorder->GetRootLayer()->Lock();
1090 			fWinBorder->UpdateStart();
1091 			fWinBorder->GetRootLayer()->Unlock();
1092 			break;
1093 		}
1094 		case AS_END_UPDATE:
1095 		{
1096 			DTRACE(("ServerWindowo %s: AS_END_UPDATE\n", Title()));
1097 			fWinBorder->GetRootLayer()->Lock();
1098 			fWinBorder->UpdateEnd();
1099 			fWinBorder->GetRootLayer()->Unlock();
1100 			break;
1101 		}
1102 
1103 		// ********** END: BView Messages ***********
1104 
1105 		// ********* BWindow Messages ***********
1106 		case AS_LAYER_DELETE_ROOT:
1107 		{
1108 			// Received when a window deletes its internal top view
1109 
1110 			// TODO: Implement AS_LAYER_DELETE_ROOT
1111 			STRACE(("ServerWindow %s: Message Delete_Layer_Root unimplemented\n", Title()));
1112 			break;
1113 		}
1114 		case AS_SHOW_WINDOW:
1115 		{
1116 			STRACE(("ServerWindow %s: Message AS_SHOW_WINDOW\n", Title()));
1117 			Show();
1118 			break;
1119 		}
1120 		case AS_HIDE_WINDOW:
1121 		{
1122 			STRACE(("ServerWindow %s: Message AS_HIDE_WINDOW\n", Title()));
1123 			Hide();
1124 			break;
1125 		}
1126 		case AS_SEND_BEHIND:
1127 		{
1128 			// TODO: Implement AS_SEND_BEHIND
1129 			STRACE(("ServerWindow %s: Message  Send_Behind unimplemented\n", Title()));
1130 			break;
1131 		}
1132 		case AS_ENABLE_UPDATES:
1133 		{
1134 			// TODO: Implement AS_ENABLE_UPDATES
1135 			STRACE(("ServerWindow %s: Message Enable_Updates unimplemented\n", Title()));
1136 			break;
1137 		}
1138 		case AS_DISABLE_UPDATES:
1139 		{
1140 			// TODO: Implement AS_DISABLE_UPDATES
1141 			STRACE(("ServerWindow %s: Message Disable_Updates unimplemented\n", Title()));
1142 			break;
1143 		}
1144 		case AS_NEEDS_UPDATE:
1145 		{
1146 			// TODO: Implement AS_NEEDS_UPDATE
1147 			STRACE(("ServerWindow %s: Message Needs_Update unimplemented\n", Title()));
1148 			break;
1149 		}
1150 		case AS_WINDOW_TITLE:
1151 		{
1152 			// TODO: Implement AS_WINDOW_TITLE
1153 			STRACE(("ServerWindow %s: Message Set_Title unimplemented\n", Title()));
1154 			break;
1155 		}
1156 		case AS_ADD_TO_SUBSET:
1157 		{
1158 			STRACE(("ServerWindow %s: Message AS_ADD_TO_SUBSET\n", Title()));
1159 			WinBorder *wb;
1160 			int32 mainToken;
1161 			team_id	teamID;
1162 
1163 			link.Read<int32>(&mainToken);
1164 			link.Read(&teamID, sizeof(team_id));
1165 
1166 			wb = gDesktop->FindWinBorderByServerWindowTokenAndTeamID(mainToken, teamID);
1167 			if (wb) {
1168 				fLink.StartMessage(SERVER_TRUE);
1169 				fLink.Flush();
1170 
1171 				// ToDo: this is a pretty expensive and complicated way to send a message...
1172 				BPrivate::PortLink msg(-1, -1);
1173 				msg.StartMessage(AS_ROOTLAYER_ADD_TO_SUBSET);
1174 				msg.Attach<WinBorder*>(fWinBorder);
1175 				msg.Attach<WinBorder*>(wb);
1176 				fWinBorder->GetRootLayer()->EnqueueMessage(msg);
1177 			} else {
1178 				fLink.StartMessage(SERVER_FALSE);
1179 				fLink.Flush();
1180 			}
1181 			break;
1182 		}
1183 		case AS_REM_FROM_SUBSET:
1184 		{
1185 			STRACE(("ServerWindow %s: Message AS_REM_FROM_SUBSET\n", Title()));
1186 			WinBorder *wb;
1187 			int32 mainToken;
1188 			team_id teamID;
1189 
1190 			link.Read<int32>(&mainToken);
1191 			link.Read(&teamID, sizeof(team_id));
1192 
1193 			wb = gDesktop->FindWinBorderByServerWindowTokenAndTeamID(mainToken, teamID);
1194 			if (wb) {
1195 				fLink.StartMessage(SERVER_TRUE);
1196 				fLink.Flush();
1197 
1198 				BPrivate::PortLink msg(-1, -1);
1199 				msg.StartMessage(AS_ROOTLAYER_REMOVE_FROM_SUBSET);
1200 				msg.Attach<WinBorder*>(fWinBorder);
1201 				msg.Attach<WinBorder*>(wb);
1202 				fWinBorder->GetRootLayer()->EnqueueMessage(msg);
1203 			} else {
1204 				fLink.StartMessage(SERVER_FALSE);
1205 				fLink.Flush();
1206 			}
1207 			break;
1208 		}
1209 		case AS_SET_LOOK:
1210 		{
1211 			// TODO: Implement AS_SET_LOOK
1212 			STRACE(("ServerWindow %s: Message Set_Look unimplemented\n", Title()));
1213 			break;
1214 		}
1215 		case AS_SET_FLAGS:
1216 		{
1217 			// TODO: Implement AS_SET_FLAGS
1218 			STRACE(("ServerWindow %s: Message Set_Flags unimplemented\n", Title()));
1219 			break;
1220 		}
1221 		case AS_SET_FEEL:
1222 		{
1223 			STRACE(("ServerWindow %s: Message AS_SET_FEEL\n", Title()));
1224 			int32 newFeel;
1225 			link.Read<int32>(&newFeel);
1226 			myRootLayer->GoChangeWinBorderFeel(fWinBorder, newFeel);
1227 			break;
1228 		}
1229 		case AS_SET_ALIGNMENT:
1230 		{
1231 			// TODO: Implement AS_SET_ALIGNMENT
1232 			STRACE(("ServerWindow %s: Message Set_Alignment unimplemented\n", Title()));
1233 			break;
1234 		}
1235 		case AS_GET_ALIGNMENT:
1236 		{
1237 			// TODO: Implement AS_GET_ALIGNMENT
1238 			STRACE(("ServerWindow %s: Message Get_Alignment unimplemented\n", Title()));
1239 			break;
1240 		}
1241 		case AS_GET_WORKSPACES:
1242 		{
1243 			STRACE(("ServerWindow %s: Message Get_Workspaces unimplemented\n", Title()));
1244 			fLink.StartMessage(SERVER_TRUE);
1245 			fLink.Attach<uint32>(fWinBorder->Workspaces());
1246 			fLink.Flush();
1247 			break;
1248 		}
1249 		case AS_SET_WORKSPACES:
1250 		{
1251 			// TODO: Implement AS_SET_WORKSPACES
1252 			STRACE(("ServerWindow %s: Message Set_Workspaces unimplemented\n", Title()));
1253 			uint32 newWorkspaces;
1254 			link.Read<uint32>(&newWorkspaces);
1255 
1256 			BPrivate::PortLink msg(-1, -1);
1257 			msg.StartMessage(AS_ROOTLAYER_WINBORDER_SET_WORKSPACES);
1258 			msg.Attach<WinBorder*>(fWinBorder);
1259 			msg.Attach<uint32>(fWinBorder->Workspaces());
1260 			msg.Attach<uint32>(newWorkspaces);
1261 			fWinBorder->GetRootLayer()->EnqueueMessage(msg);
1262 			break;
1263 		}
1264 		case AS_WINDOW_RESIZE:
1265 		{
1266 			float xResizeBy;
1267 			float yResizeBy;
1268 
1269 			link.Read<float>(&xResizeBy);
1270 			link.Read<float>(&yResizeBy);
1271 
1272 			STRACE(("ServerWindow %s: Message AS_WINDOW_RESIZE %.1f, %.1f\n", Title(), xResizeBy, yResizeBy));
1273 
1274 			fWinBorder->ResizeBy(xResizeBy, yResizeBy);
1275 
1276 			break;
1277 		}
1278 		case AS_WINDOW_MOVE:
1279 		{
1280 			float xMoveBy;
1281 			float yMoveBy;
1282 
1283 			link.Read<float>(&xMoveBy);
1284 			link.Read<float>(&yMoveBy);
1285 
1286 			STRACE(("ServerWindow %s: Message AS_WINDOW_MOVE: %.1f, %.1f\n", Title(), xMoveBy, yMoveBy));
1287 
1288 			fWinBorder->MoveBy(xMoveBy, yMoveBy);
1289 
1290 			break;
1291 		}
1292 		case AS_SET_SIZE_LIMITS:
1293 		{
1294 			// Attached Data:
1295 			// 1) float minimum width
1296 			// 2) float maximum width
1297 			// 3) float minimum height
1298 			// 4) float maximum height
1299 
1300 			float minWidth;
1301 			float maxWidth;
1302 			float minHeight;
1303 			float maxHeight;
1304 
1305 			link.Read<float>(&minWidth);
1306 			link.Read<float>(&maxWidth);
1307 			link.Read<float>(&minHeight);
1308 			link.Read<float>(&maxHeight);
1309 
1310 			fWinBorder->SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight);
1311 
1312 			// and now, sync the client to the limits that we were able to enforce
1313 			fWinBorder->GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
1314 
1315 			fLink.StartMessage(SERVER_TRUE);
1316 			fLink.Attach<float>(minWidth);
1317 			fLink.Attach<float>(maxWidth);
1318 			fLink.Attach<float>(minHeight);
1319 			fLink.Attach<float>(maxHeight);
1320 
1321 			fLink.Flush();
1322 
1323 			break;
1324 		}
1325 		case B_MINIMIZE:
1326 		{
1327 			// TODO: Implement B_MINIMIZE
1328 			STRACE(("ServerWindow %s: Message Minimize unimplemented\n", Title()));
1329 			break;
1330 		}
1331 		case B_WINDOW_ACTIVATED:
1332 		{
1333 			// TODO: Implement B_WINDOW_ACTIVATED
1334 			STRACE(("ServerWindow %s: Message Window_Activated unimplemented\n", Title()));
1335 			break;
1336 		}
1337 		case B_ZOOM:
1338 		{
1339 			// TODO: Implement B_ZOOM
1340 			STRACE(("ServerWindow %s: Message Zoom unimplemented\n", Title()));
1341 			break;
1342 		}
1343 		// Some BView drawing messages, but which don't need clipping
1344 		case AS_LAYER_SET_HIGH_COLOR:
1345 		{
1346 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_HIGH_COLOR: Layer: %s\n", Title(), fCurrentLayer->Name()));
1347 			rgb_color c;
1348 
1349 			link.Read(&c, sizeof(rgb_color));
1350 
1351 			fCurrentLayer->fLayerData->SetHighColor(RGBColor(c));
1352 
1353 			break;
1354 		}
1355 		case AS_LAYER_SET_LOW_COLOR:
1356 		{
1357 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_LOW_COLOR: Layer: %s\n", Title(), fCurrentLayer->Name()));
1358 			rgb_color c;
1359 
1360 			link.Read(&c, sizeof(rgb_color));
1361 
1362 			fCurrentLayer->fLayerData->SetLowColor(RGBColor(c));
1363 
1364 			break;
1365 		}
1366 		case AS_LAYER_SET_PATTERN:
1367 		{
1368 			DTRACE(("ServerWindow %s: Message AS_LAYER_SET_PATTERN: Layer: %s\n", fTitle, fCurrentLayer->Name()));
1369 			pattern pat;
1370 
1371 			link.Read(&pat, sizeof(pattern));
1372 
1373 			fCurrentLayer->fLayerData->SetPattern(Pattern(pat));
1374 
1375 			break;
1376 		}
1377 		case AS_MOVEPENTO:
1378 		{
1379 			DTRACE(("ServerWindow %s: Message AS_MOVEPENTO\n", Title()));
1380 
1381 			float x,y;
1382 
1383 			link.Read<float>(&x);
1384 			link.Read<float>(&y);
1385 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1386 				fCurrentLayer->fLayerData->SetPenLocation(BPoint(x, y));
1387 
1388 			break;
1389 		}
1390 		case AS_SETPENSIZE:
1391 		{
1392 			DTRACE(("ServerWindow %s: Message AS_SETPENSIZE\n", Title()));
1393 			float size;
1394 
1395 			link.Read<float>(&size);
1396 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1397 				fCurrentLayer->fLayerData->SetPenSize(size);
1398 
1399 			break;
1400 		}
1401 		case AS_SET_FONT:
1402 		{
1403 			DTRACE(("ServerWindow %s: Message AS_SET_FONT\n", Title()));
1404 			// TODO: Implement AS_SET_FONT?
1405 			// Confusing!! But it works already!
1406 			break;
1407 		}
1408 		case AS_SET_FONT_SIZE:
1409 		{
1410 			DTRACE(("ServerWindow %s: Message AS_SET_FONT_SIZE\n", Title()));
1411 			// TODO: Implement AS_SET_FONT_SIZE?
1412 			break;
1413 		}
1414 		case AS_AREA_MESSAGE:
1415 		{
1416 			STRACE(("ServerWindow %s: Message AS_AREA_MESSAGE\n", Title()));
1417 			// This occurs in only one kind of case: a message is too big to send over a port. This
1418 			// is really an edge case, so this shouldn't happen *too* often
1419 
1420 			// Attached Data:
1421 			// 1) area_id id of an area already owned by the server containing the message
1422 			// 2) size_t offset of the pointer in the area
1423 			// 3) size_t size of the message
1424 
1425 			area_id area;
1426 			size_t offset;
1427 			size_t msgsize;
1428 			area_info ai;
1429 			int8 *msgpointer;
1430 
1431 			link.Read<area_id>(&area);
1432 			link.Read<size_t>(&offset);
1433 			link.Read<size_t>(&msgsize);
1434 
1435 			// Part sanity check, part get base pointer :)
1436 			if(get_area_info(area,&ai)!=B_OK)
1437 				break;
1438 
1439 			msgpointer = (int8*)ai.address + offset;
1440 
1441 			RAMLinkMsgReader mlink(msgpointer);
1442 			_DispatchMessage(mlink.Code(), mlink);
1443 
1444 			// This is a very special case in the sense that when ServerMemIO is used for this
1445 			// purpose, it will be set to NOT automatically free the memory which it had
1446 			// requested. This is the server's job once the message has been dispatched.
1447 			fServerApp->AppAreaPool()->ReleaseBuffer(msgpointer);
1448 			break;
1449 		}
1450 		case AS_SYNC:
1451 		{
1452 			// TODO: AS_SYNC is a no-op for now, just to get things working
1453 			fLink.StartMessage(SERVER_TRUE);
1454 			fLink.Flush();
1455 			break;
1456 		}
1457 		case AS_LAYER_DRAG_IMAGE:
1458 		{
1459 			// TODO: Implement AS_LAYER_DRAG_IMAGE
1460 			STRACE(("ServerWindow %s: Message AS_DRAG_IMAGE unimplemented\n", Title()));
1461 			DTRACE(("ServerWindow %s: Message AS_DRAG_IMAGE unimplemented\n", Title()));
1462 			break;
1463 		}
1464 		case AS_LAYER_DRAG_RECT:
1465 		{
1466 			// TODO: Implement AS_LAYER_DRAG_RECT
1467 			STRACE(("ServerWindow %s: Message AS_DRAG_RECT unimplemented\n", Title()));
1468 			DTRACE(("ServerWindow %s: Message AS_DRAG_RECT unimplemented\n", Title()));
1469 			break;
1470 		}
1471 		case AS_LAYER_GET_MOUSE_COORDS:
1472 		{
1473 			DTRACE(("ServerWindow %s: Message AS_GET_MOUSE_COORDS\n", fTitle));
1474 
1475 			fLink.StartMessage(SERVER_TRUE);
1476 
1477 			// Returns
1478 			// 1) BPoint mouse location
1479 			// 2) int32 button state
1480 
1481 			fLink.Attach<BPoint>(gDesktop->GetHWInterface()->GetCursorPosition());
1482 			fLink.Attach<int32>(gDesktop->ActiveRootLayer()->Buttons());
1483 
1484 			fLink.Flush();
1485 			break;
1486 		}
1487 
1488 		default:
1489 			_DispatchGraphicsMessage(code, link);
1490 			break;
1491 	}
1492 
1493 	myRootLayer->Unlock();
1494 }
1495 
1496 		// -------------------- Graphics messages ----------------------------------
1497 
1498 inline
1499 void
1500 ServerWindow::_DispatchGraphicsMessage(int32 code, BPrivate::LinkReceiver &link)
1501 {
1502 	fWinBorder->GetRootLayer()->Lock();
1503 #ifndef NEW_CLIPPING
1504 	BRegion rreg(fCurrentLayer->fVisible);
1505 #else
1506 	BRegion rreg(fCurrentLayer->fVisible2);
1507 #endif
1508 
1509 	if (fWinBorder->InUpdate())
1510 		rreg.IntersectWith(&fWinBorder->RegionToBeUpdated());
1511 
1512 	gDesktop->GetDisplayDriver()->ConstrainClippingRegion(&rreg);
1513 //	rgb_color  rrr = fCurrentLayer->fLayerData->viewcolor.GetColor32();
1514 //	RGBColor c(rand()%255,rand()%255,rand()%255);
1515 //	gDesktop->GetDisplayDriver()->FillRect(BRect(0,0,639,479), c);
1516 
1517 	switch (code) {
1518 		case AS_STROKE_LINE:
1519 		{
1520 			DTRACE(("ServerWindow %s: Message AS_STROKE_LINE\n", Title()));
1521 
1522 			float x1, y1, x2, y2;
1523 
1524 			link.Read<float>(&x1);
1525 			link.Read<float>(&y1);
1526 			link.Read<float>(&x2);
1527 			link.Read<float>(&y2);
1528 
1529 			if (fCurrentLayer && fCurrentLayer->fLayerData) {
1530 				BPoint p1(x1,y1);
1531 				BPoint p2(x2,y2);
1532 				gDesktop->GetDisplayDriver()->StrokeLine(fCurrentLayer->ConvertToTop(p1),
1533 														fCurrentLayer->ConvertToTop(p2),
1534 														fCurrentLayer->fLayerData);
1535 
1536 				// We update the pen here because many DisplayDriver calls which do not update the
1537 				// pen position actually call StrokeLine
1538 
1539 				// TODO: Decide where to put this, for example, it cannot be done
1540 				// for DrawString(), also there needs to be a decision, if penlocation
1541 				// is in View coordinates (I think it should be) or in screen coordinates.
1542 				fCurrentLayer->fLayerData->SetPenLocation(p2);
1543 			}
1544 			break;
1545 		}
1546 		case AS_LAYER_INVERT_RECT:
1547 		{
1548 			DTRACE(("ServerWindow %s: Message AS_INVERT_RECT\n", Title()));
1549 
1550 			BRect rect;
1551 			link.Read<BRect>(&rect);
1552 
1553 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1554 				gDesktop->GetDisplayDriver()->InvertRect(fCurrentLayer->ConvertToTop(rect));
1555 			break;
1556 		}
1557 		case AS_STROKE_RECT:
1558 		{
1559 			DTRACE(("ServerWindow %s: Message AS_STROKE_RECT\n", Title()));
1560 
1561 			float left, top, right, bottom;
1562 			link.Read<float>(&left);
1563 			link.Read<float>(&top);
1564 			link.Read<float>(&right);
1565 			link.Read<float>(&bottom);
1566 			BRect rect(left,top,right,bottom);
1567 
1568 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1569 				gDesktop->GetDisplayDriver()->StrokeRect(fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData);
1570 			break;
1571 		}
1572 		case AS_FILL_RECT:
1573 		{
1574 			DTRACE(("ServerWindow %s: Message AS_FILL_RECT\n", Title()));
1575 
1576 			BRect rect;
1577 			link.Read<BRect>(&rect);
1578 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1579 				gDesktop->GetDisplayDriver()->FillRect(fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData);
1580 			break;
1581 		}
1582 		case AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT:
1583 		{
1584 			DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
1585 			int32		bitmapToken;
1586 			BPoint 		point;
1587 
1588 			link.Read<int32>(&bitmapToken);
1589 			link.Read<BPoint>(&point);
1590 
1591 			ServerBitmap* sbmp = fServerApp->FindBitmap(bitmapToken);
1592 			if (sbmp) {
1593 				BRect src = sbmp->Bounds();
1594 				BRect dst = src.OffsetToCopy(point);
1595 				dst = fCurrentLayer->ConvertToTop(dst);
1596 
1597 				fCurrentLayer->GetDisplayDriver()->DrawBitmap(sbmp, src, dst, fCurrentLayer->fLayerData);
1598 			}
1599 
1600 			// TODO: Adi -- shouldn't AS_LAYER_DRAW_BITMAP_SYNC_AT_POINT sync with the client?
1601 			break;
1602 		}
1603 		case AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT:
1604 		{
1605 			DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP_ASYNC_AT_POINT: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
1606 			int32		bitmapToken;
1607 			BPoint 		point;
1608 
1609 			link.Read<int32>(&bitmapToken);
1610 			link.Read<BPoint>(&point);
1611 
1612 			ServerBitmap* sbmp = fServerApp->FindBitmap(bitmapToken);
1613 			if (sbmp) {
1614 				BRect src = sbmp->Bounds();
1615 				BRect dst = src.OffsetToCopy(point);
1616 				dst = fCurrentLayer->ConvertToTop(dst);
1617 
1618 				fCurrentLayer->GetDisplayDriver()->DrawBitmap(sbmp, src, dst, fCurrentLayer->fLayerData);
1619 			}
1620 			break;
1621 		}
1622 		case AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT:
1623 		{
1624 			DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
1625 			int32 bitmapToken;
1626 			BRect srcRect, dstRect;
1627 
1628 			link.Read<int32>(&bitmapToken);
1629 			link.Read<BRect>(&dstRect);
1630 			link.Read<BRect>(&srcRect);
1631 
1632 			ServerBitmap* sbmp = fServerApp->FindBitmap(bitmapToken);
1633 			if (sbmp) {
1634 				dstRect = fCurrentLayer->ConvertToTop(dstRect);
1635 
1636 				fCurrentLayer->GetDisplayDriver()->DrawBitmap(sbmp, srcRect, dstRect, fCurrentLayer->fLayerData);
1637 			}
1638 
1639 			// TODO: Adi -- shouldn't AS_LAYER_DRAW_BITMAP_SYNC_IN_RECT sync with the client?
1640 			break;
1641 		}
1642 		case AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT:
1643 		{
1644 			DTRACE(("ServerWindow %s: Message AS_LAYER_DRAW_BITMAP_ASYNC_IN_RECT: Layer name: %s\n", fTitle, fCurrentLayer->Name()));
1645 			int32 bitmapToken;
1646 			BRect srcRect, dstRect;
1647 
1648 			link.Read<int32>(&bitmapToken);
1649 			link.Read<BRect>(&dstRect);
1650 			link.Read<BRect>(&srcRect);
1651 
1652 			ServerBitmap* sbmp = fServerApp->FindBitmap(bitmapToken);
1653 			if (sbmp) {
1654 				dstRect = fCurrentLayer->ConvertToTop(dstRect);
1655 
1656 				fCurrentLayer->GetDisplayDriver()->DrawBitmap(sbmp, srcRect, dstRect, fCurrentLayer->fLayerData);
1657 			}
1658 			break;
1659 		}
1660 		case AS_STROKE_ARC:
1661 		{
1662 			DTRACE(("ServerWindow %s: Message AS_STROKE_ARC\n", Title()));
1663 
1664 			float angle, span;
1665 			BRect r;
1666 
1667 			link.Read<BRect>(&r);
1668 			link.Read<float>(&angle);
1669 			link.Read<float>(&span);
1670 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1671 				gDesktop->GetDisplayDriver()->StrokeArc(fCurrentLayer->ConvertToTop(r),angle,span, fCurrentLayer->fLayerData);
1672 			break;
1673 		}
1674 		case AS_FILL_ARC:
1675 		{
1676 			DTRACE(("ServerWindow %s: Message AS_FILL_ARC\n", Title()));
1677 
1678 			float angle, span;
1679 			BRect r;
1680 
1681 			link.Read<BRect>(&r);
1682 			link.Read<float>(&angle);
1683 			link.Read<float>(&span);
1684 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1685 				gDesktop->GetDisplayDriver()->FillArc(fCurrentLayer->ConvertToTop(r),angle,span, fCurrentLayer->fLayerData);
1686 			break;
1687 		}
1688 		case AS_STROKE_BEZIER:
1689 		{
1690 			DTRACE(("ServerWindow %s: Message AS_STROKE_BEZIER\n", Title()));
1691 
1692 			BPoint *pts;
1693 			int i;
1694 			pts = new BPoint[4];
1695 
1696 			for (i=0; i<4; i++)
1697 				link.Read<BPoint>(&(pts[i]));
1698 
1699 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1700 			{
1701 				for (i=0; i<4; i++)
1702 					pts[i]=fCurrentLayer->ConvertToTop(pts[i]);
1703 
1704 				gDesktop->GetDisplayDriver()->StrokeBezier(pts, fCurrentLayer->fLayerData);
1705 			}
1706 			delete [] pts;
1707 			break;
1708 		}
1709 		case AS_FILL_BEZIER:
1710 		{
1711 			DTRACE(("ServerWindow %s: Message AS_FILL_BEZIER\n", Title()));
1712 
1713 			BPoint *pts;
1714 			int i;
1715 			pts = new BPoint[4];
1716 
1717 			for (i=0; i<4; i++)
1718 				link.Read<BPoint>(&(pts[i]));
1719 
1720 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1721 			{
1722 				for (i=0; i<4; i++)
1723 					pts[i]=fCurrentLayer->ConvertToTop(pts[i]);
1724 
1725 				gDesktop->GetDisplayDriver()->FillBezier(pts, fCurrentLayer->fLayerData);
1726 			}
1727 			delete [] pts;
1728 			break;
1729 		}
1730 		case AS_STROKE_ELLIPSE:
1731 		{
1732 			DTRACE(("ServerWindow %s: Message AS_STROKE_ELLIPSE\n", Title()));
1733 
1734 			BRect rect;
1735 			link.Read<BRect>(&rect);
1736 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1737 				gDesktop->GetDisplayDriver()->StrokeEllipse(fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData);
1738 			break;
1739 		}
1740 		case AS_FILL_ELLIPSE:
1741 		{
1742 			DTRACE(("ServerWindow %s: Message AS_FILL_ELLIPSE\n", Title()));
1743 
1744 			BRect rect;
1745 			link.Read<BRect>(&rect);
1746 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1747 				gDesktop->GetDisplayDriver()->FillEllipse(fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData);
1748 			break;
1749 		}
1750 		case AS_STROKE_ROUNDRECT:
1751 		{
1752 			DTRACE(("ServerWindow %s: Message AS_STROKE_ROUNDRECT\n", Title()));
1753 
1754 			BRect rect;
1755 			float xrad,yrad;
1756 			link.Read<BRect>(&rect);
1757 			link.Read<float>(&xrad);
1758 			link.Read<float>(&yrad);
1759 
1760 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1761 				gDesktop->GetDisplayDriver()->StrokeRoundRect(fCurrentLayer->ConvertToTop(rect),xrad,yrad, fCurrentLayer->fLayerData);
1762 			break;
1763 		}
1764 		case AS_FILL_ROUNDRECT:
1765 		{
1766 			DTRACE(("ServerWindow %s: Message AS_FILL_ROUNDRECT\n", Title()));
1767 
1768 			BRect rect;
1769 			float xrad,yrad;
1770 			link.Read<BRect>(&rect);
1771 			link.Read<float>(&xrad);
1772 			link.Read<float>(&yrad);
1773 
1774 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1775 				gDesktop->GetDisplayDriver()->FillRoundRect(fCurrentLayer->ConvertToTop(rect),xrad,yrad, fCurrentLayer->fLayerData);
1776 			break;
1777 		}
1778 		case AS_STROKE_TRIANGLE:
1779 		{
1780 			DTRACE(("ServerWindow %s: Message AS_STROKE_TRIANGLE\n", Title()));
1781 
1782 			BPoint pts[3];
1783 			BRect rect;
1784 
1785 			for (int i=0; i<3; i++)
1786 				link.Read<BPoint>(&(pts[i]));
1787 
1788 			link.Read<BRect>(&rect);
1789 
1790 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1791 			{
1792 				for(int i=0;i<3;i++)
1793 					pts[i]=fCurrentLayer->ConvertToTop(pts[i]);
1794 
1795 				gDesktop->GetDisplayDriver()->StrokeTriangle(pts, fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData);
1796 			}
1797 			break;
1798 		}
1799 		case AS_FILL_TRIANGLE:
1800 		{
1801 			DTRACE(("ServerWindow %s: Message AS_FILL_TRIANGLE\n", Title()));
1802 
1803 			BPoint pts[3];
1804 			BRect rect;
1805 
1806 			for (int i=0; i<3; i++)
1807 				link.Read<BPoint>(&(pts[i]));
1808 
1809 			link.Read<BRect>(&rect);
1810 
1811 			if (fCurrentLayer && fCurrentLayer->fLayerData)
1812 			{
1813 				for(int i=0;i<3;i++)
1814 					pts[i]=fCurrentLayer->ConvertToTop(pts[i]);
1815 
1816 				gDesktop->GetDisplayDriver()->FillTriangle(pts, fCurrentLayer->ConvertToTop(rect), fCurrentLayer->fLayerData);
1817 			}
1818 			break;
1819 		}
1820 // TODO: get rid of all this code duplication!!
1821 		case AS_STROKE_POLYGON:
1822 		{
1823 			DTRACE(("ServerWindow %s: Message AS_STROKE_POLYGON\n", Title()));
1824 
1825 			BRect polyframe;
1826 			bool isclosed;
1827 			int32 pointcount;
1828 			BPoint *pointlist;
1829 
1830 			link.Read<BRect>(&polyframe);
1831 			link.Read<bool>(&isclosed);
1832 			link.Read<int32>(&pointcount);
1833 
1834 			pointlist=new BPoint[pointcount];
1835 
1836 			link.Read(pointlist, sizeof(BPoint)*pointcount);
1837 
1838 			for(int32 i=0; i<pointcount; i++)
1839 				pointlist[i]=fCurrentLayer->ConvertToTop(pointlist[i]);
1840 
1841 			gDesktop->GetDisplayDriver()->StrokePolygon(pointlist,pointcount,polyframe,
1842 					fCurrentLayer->fLayerData,isclosed);
1843 
1844 			delete [] pointlist;
1845 			break;
1846 		}
1847 		case AS_FILL_POLYGON:
1848 		{
1849 			DTRACE(("ServerWindow %s: Message AS_FILL_POLYGON\n", Title()));
1850 
1851 			BRect polyframe;
1852 			int32 pointcount;
1853 			BPoint *pointlist;
1854 
1855 			link.Read<BRect>(&polyframe);
1856 			link.Read<int32>(&pointcount);
1857 
1858 			pointlist=new BPoint[pointcount];
1859 
1860 			link.Read(pointlist, sizeof(BPoint)*pointcount);
1861 
1862 			for(int32 i=0; i<pointcount; i++)
1863 				pointlist[i]=fCurrentLayer->ConvertToTop(pointlist[i]);
1864 
1865 			gDesktop->GetDisplayDriver()->FillPolygon(pointlist,pointcount,polyframe, fCurrentLayer->fLayerData);
1866 
1867 			delete [] pointlist;
1868 
1869 			break;
1870 		}
1871 		case AS_STROKE_SHAPE:
1872 		{
1873 			DTRACE(("ServerWindow %s: Message AS_STROKE_SHAPE\n", Title()));
1874 
1875 			BRect shaperect;
1876 			int32 opcount;
1877 			int32 ptcount;
1878 			int32 *oplist;
1879 			BPoint *ptlist;
1880 
1881 			link.Read<BRect>(&shaperect);
1882 			link.Read<int32>(&opcount);
1883 			link.Read<int32>(&ptcount);
1884 
1885 			oplist=new int32[opcount];
1886 			ptlist=new BPoint[ptcount];
1887 
1888 			link.Read(oplist,sizeof(int32)*opcount);
1889 			link.Read(ptlist,sizeof(BPoint)*ptcount);
1890 
1891 			for(int32 i=0; i<ptcount; i++)
1892 				ptlist[i]=fCurrentLayer->ConvertToTop(ptlist[i]);
1893 
1894 			gDesktop->GetDisplayDriver()->StrokeShape(shaperect, opcount, oplist, ptcount, ptlist, fCurrentLayer->fLayerData);
1895 			delete oplist;
1896 			delete ptlist;
1897 
1898 			break;
1899 		}
1900 		case AS_FILL_SHAPE:
1901 		{
1902 			DTRACE(("ServerWindow %s: Message AS_FILL_SHAPE\n", Title()));
1903 
1904 			BRect shaperect;
1905 			int32 opcount;
1906 			int32 ptcount;
1907 			int32 *oplist;
1908 			BPoint *ptlist;
1909 
1910 			link.Read<BRect>(&shaperect);
1911 			link.Read<int32>(&opcount);
1912 			link.Read<int32>(&ptcount);
1913 
1914 			oplist=new int32[opcount];
1915 			ptlist=new BPoint[ptcount];
1916 
1917 			link.Read(oplist,sizeof(int32)*opcount);
1918 			link.Read(ptlist,sizeof(BPoint)*ptcount);
1919 
1920 			for(int32 i=0; i<ptcount; i++)
1921 				ptlist[i]=fCurrentLayer->ConvertToTop(ptlist[i]);
1922 
1923 			gDesktop->GetDisplayDriver()->FillShape(shaperect, opcount, oplist, ptcount, ptlist, fCurrentLayer->fLayerData);
1924 
1925 			delete oplist;
1926 			delete ptlist;
1927 
1928 			break;
1929 		}
1930 		case AS_FILL_REGION:
1931 		{
1932 			DTRACE(("ServerWindow %s: Message AS_FILL_REGION\n", Title()));
1933 
1934 			int32 count;
1935 			link.Read<int32>(&count);
1936 
1937 			BRect *rects = new BRect[count];
1938 			if (link.Read(rects, sizeof(BRect) * count) != B_OK) {
1939 				delete[] rects;
1940 				break;
1941 			}
1942 
1943 			// Between the client-side conversion to BRects from clipping_rects to the overhead
1944 			// in repeatedly calling FillRect(), this is definitely in need of optimization. At
1945 			// least it works for now. :)
1946 			for (int32 i = 0; i < count; i++) {
1947 				gDesktop->GetDisplayDriver()->FillRect(fCurrentLayer->ConvertToTop(rects[i]),
1948 					fCurrentLayer->fLayerData);
1949 			}
1950 
1951 			delete[] rects;
1952 
1953 			// TODO: create support for clipping_rect usage for faster BRegion display.
1954 			// Tweaks to DisplayDriver are necessary along with conversion routines in Layer
1955 			break;
1956 		}
1957 		case AS_STROKE_LINEARRAY:
1958 		{
1959 			DTRACE(("ServerWindow %s: Message AS_STROKE_LINEARRAY\n", Title()));
1960 
1961 			// Attached Data:
1962 			// 1) int32 Number of lines in the array
1963 			// 2) array of struct _array_data_ objects, as defined in ViewAux.h
1964 
1965 			int32 linecount;
1966 
1967 			link.Read<int32>(&linecount);
1968 			if(linecount>0)
1969 			{
1970 				LineArrayData linedata[linecount], *index;
1971 
1972 				for(int32 i=0; i<linecount; i++)
1973 				{
1974 					index=&linedata[i];
1975 
1976 					link.Read<float>(&(index->pt1.x));
1977 					link.Read<float>(&(index->pt1.y));
1978 					link.Read<float>(&(index->pt2.x));
1979 					link.Read<float>(&(index->pt2.y));
1980 					link.Read<rgb_color>(&(index->color));
1981 
1982 					index->pt1=fCurrentLayer->ConvertToTop(index->pt1);
1983 					index->pt2=fCurrentLayer->ConvertToTop(index->pt2);
1984 				}
1985 				gDesktop->GetDisplayDriver()->StrokeLineArray(linecount,linedata,fCurrentLayer->fLayerData);
1986 			}
1987 			break;
1988 		}
1989 		case AS_DRAW_STRING:
1990 		{
1991 			DTRACE(("ServerWindow %s: Message AS_DRAW_STRING\n", Title()));
1992 			char *string;
1993 			int32 length;
1994 			BPoint location;
1995 			escapement_delta delta;
1996 
1997 			link.Read<int32>(&length);
1998 			link.Read<BPoint>(&location);
1999 			link.Read<escapement_delta>(&delta);
2000 			link.ReadString(&string);
2001 
2002 			if (fCurrentLayer && fCurrentLayer->fLayerData)
2003 				gDesktop->GetDisplayDriver()->DrawString(string, length,
2004 														fCurrentLayer->ConvertToTop(location),
2005 														fCurrentLayer->fLayerData);
2006 
2007 			free(string);
2008 			break;
2009 		}
2010 		default:
2011 		{
2012 			printf("ServerWindow %s received unexpected code - message offset %ld\n", Title(), code - SERVER_TRUE);
2013 			break;
2014 		}
2015 	}
2016 
2017 	gDesktop->GetDisplayDriver()->ConstrainClippingRegion(NULL);
2018 	fWinBorder->GetRootLayer()->Unlock();
2019 }
2020 
2021 /*!
2022 	\brief Message-dispatching loop starter
2023 	\param data The thread's ServerWindow
2024 */
2025 int32
2026 ServerWindow::_message_thread(void *_window)
2027 {
2028 	ServerWindow *window = (ServerWindow *)_window;
2029 
2030 	window->_MessageLooper();
2031 	return 0;
2032 }
2033 
2034 
2035 /*!
2036 	\brief Message-dispatching loop for the ServerWindow
2037 
2038 	Watches the ServerWindow's message port and dispatches as necessary
2039 */
2040 void
2041 ServerWindow::_MessageLooper()
2042 {
2043 	BPrivate::LinkReceiver& receiver = fLink.Receiver();
2044 
2045 	bool quitting = false;
2046 	int32 code;
2047 	status_t err = B_OK;
2048 
2049 	while (!quitting) {
2050 		STRACE(("info: ServerWindow::MonitorWin listening on port %ld.\n",
2051 			fMessagePort));
2052 
2053 		err = receiver.GetNextMessage(code);
2054 		if (err < B_OK) {
2055 			// that shouldn't happen, it's our port
2056 			// ToDo: do something about it, anyway!
2057 			return;
2058 		}
2059 
2060 		Lock();
2061 
2062 		switch (code) {
2063 			case AS_DELETE_WINDOW:
2064 			case kMsgWindowQuit:
2065 			{
2066 				// this means the client has been killed
2067 				STRACE(("ServerWindow %s received 'AS_DELETE_WINDOW' message code\n",
2068 					Title()));
2069 
2070 				// ToDo: what's this?
2071 				//RootLayer *rootLayer = fWinBorder->GetRootLayer();
2072 
2073 				// we are preparing to delete a ServerWindow, RootLayer should be aware
2074 				// of that and stop for a moment.
2075 				// also we must wait a bit for the associated WinBorder to become hidden
2076 				//while(1) {
2077 				//	myRootLayer->Lock();
2078 				//	if (IsHidden())
2079 				//		break;
2080 				//	else
2081 				//		rootLayer->Unlock();
2082 				//}
2083 
2084 				// ServerWindow's destructor takes care of pulling this object off the desktop.
2085 				if (!fWinBorder->IsHidden())
2086 					CRITICAL("ServerWindow: a window must be hidden before it's deleted\n");
2087 
2088 				Quit();
2089 					// does not return
2090 				break;
2091 			}
2092 			case B_QUIT_REQUESTED:
2093 				STRACE(("ServerWindow %s received quit request\n", Title()));
2094 				NotifyQuitRequested();
2095 				break;
2096 
2097 			default:
2098 				_DispatchMessage(code, receiver);
2099 				break;
2100 		}
2101 
2102 		Unlock();
2103 	}
2104 }
2105 
2106 void
2107 ServerWindow::SendMessageToClient(const BMessage* msg, int32 target, bool usePreferred) const
2108 {
2109 	ssize_t size = msg->FlattenedSize();
2110 	char* buffer = new char[size];
2111 
2112 	if (msg->Flatten(buffer, size) == B_OK) {
2113 		status_t ret = BMessage::Private::SendFlattenedMessage(buffer, size,
2114 							fClientLooperPort, target, usePreferred, 100000);
2115 		if (ret < B_OK)
2116 			fprintf(stderr, "ServerWindow::SendMessageToClient(): %s\n", strerror(ret));
2117 	} else
2118 		printf("PANIC: ServerWindow %s: can't flatten message in 'SendMessageToClient()'\n", fTitle);
2119 
2120 	delete[] buffer;
2121 }
2122 
2123 
2124 status_t
2125 ServerWindow::PictureToRegion(ServerPicture *picture, BRegion &region,
2126 							bool inverse, BPoint where)
2127 {
2128 	fprintf(stderr, "ServerWindow::PictureToRegion() not implemented\n");
2129 	region.MakeEmpty();
2130 	return B_ERROR;
2131 }
2132