xref: /haiku/src/servers/app/ServerApp.cpp (revision 3216a856947f9746d8c4c1e720ccf3dc5c0ac786)
1 /*
2  * Copyright 2001-2016, 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  *		Jérôme Duval, jerome.duval@free.fr
12  *		Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
13  *		Philippe Saint-Pierre, stpere@gmail.com
14  *		Wim van der Meer, <WPJvanderMeer@gmail.com>
15  *		Joseph Groover <looncraz@looncraz.net>
16  */
17 
18 
19 /*!	\class ServerApp ServerApp.h
20 	\brief Counterpart to BApplication within the app_server
21 */
22 
23 
24 #include "ServerApp.h"
25 
26 #include <new>
27 #include <stdio.h>
28 #include <string.h>
29 #include <syslog.h>
30 
31 #include <AppDefs.h>
32 #include <Autolock.h>
33 #include <Debug.h>
34 #include <List.h>
35 #include <ScrollBar.h>
36 #include <Shape.h>
37 #include <String.h>
38 #include <StackOrHeapArray.h>
39 
40 #include <FontPrivate.h>
41 #include <MessengerPrivate.h>
42 #include <PrivateScreen.h>
43 #include <RosterPrivate.h>
44 #include <ServerProtocol.h>
45 #include <WindowPrivate.h>
46 
47 #include "AppServer.h"
48 #include "BitmapManager.h"
49 #include "CursorManager.h"
50 #include "CursorSet.h"
51 #include "Desktop.h"
52 #include "DecorManager.h"
53 #include "DrawingEngine.h"
54 #include "EventStream.h"
55 #include "FontManager.h"
56 #include "HWInterface.h"
57 #include "InputManager.h"
58 #include "OffscreenServerWindow.h"
59 #include "Screen.h"
60 #include "ServerBitmap.h"
61 #include "ServerConfig.h"
62 #include "ServerCursor.h"
63 #include "ServerPicture.h"
64 #include "ServerTokenSpace.h"
65 #include "ServerWindow.h"
66 #include "SystemPalette.h"
67 #include "Window.h"
68 
69 
70 //#define DEBUG_SERVERAPP
71 #ifdef DEBUG_SERVERAPP
72 #	define STRACE(x) debug_printf x
73 #else
74 #	define STRACE(x) ;
75 #endif
76 
77 //#define DEBUG_SERVERAPP_FONT
78 #ifdef DEBUG_SERVERAPP_FONT
79 #	define FTRACE(x) debug_printf x
80 #else
81 #	define FTRACE(x) ;
82 #endif
83 
84 using std::nothrow;
85 
86 static const uint32 kMsgUpdateShowAllDraggers = '_adg';
87 static const uint32 kMsgAppQuit = 'appQ';
88 
89 
90 ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort,
91 		port_id clientLooperPort, team_id clientTeam,
92 		int32 clientToken, const char* signature)
93 	:
94 	MessageLooper("application"),
95 
96 	fMessagePort(-1),
97 	fClientReplyPort(clientReplyPort),
98 	fDesktop(desktop),
99 	fSignature(signature),
100 	fClientTeam(clientTeam),
101 	fWindowListLock("window list"),
102 	fTemporaryDisplayModeChange(0),
103 	fMapLocker("server app maps"),
104 	fAppCursor(NULL),
105 	fViewCursor(NULL),
106 	fCursorHideLevel(0),
107 	fIsActive(false),
108 	fMemoryAllocator(new (std::nothrow) ClientMemoryAllocator(this))
109 {
110 	if (fSignature == "")
111 		fSignature = "application/no-signature";
112 
113 	char name[B_OS_NAME_LENGTH];
114 	snprintf(name, sizeof(name), "a<%" B_PRId32 ":%s", clientTeam,
115 		SignatureLeaf());
116 
117 	fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name);
118 	if (fMessagePort < B_OK)
119 		return;
120 
121 	fLink.SetSenderPort(fClientReplyPort);
122 	fLink.SetReceiverPort(fMessagePort);
123 	fLink.SetTargetTeam(clientTeam);
124 
125 	// we let the application own the port, so that we get aware when it's gone
126 	if (set_port_owner(fMessagePort, clientTeam) < B_OK) {
127 		delete_port(fMessagePort);
128 		fMessagePort = -1;
129 		return;
130 	}
131 
132 	BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
133 		clientLooperPort, clientToken);
134 
135 	fInitialWorkspace = desktop->CurrentWorkspace();
136 		// TODO: this should probably be retrieved when the app is loaded!
137 
138 	// record the current system wide fonts..
139 	desktop->LockSingleWindow();
140 	DesktopSettings settings(desktop);
141 	settings.GetDefaultPlainFont(fPlainFont);
142 	settings.GetDefaultBoldFont(fBoldFont);
143 	settings.GetDefaultFixedFont(fFixedFont);
144 	desktop->UnlockSingleWindow();
145 
146 	STRACE(("ServerApp %s:\n", Signature()));
147 	STRACE(("\tBApp port: %" B_PRId32 "\n", fClientReplyPort));
148 	STRACE(("\tReceiver port: %" B_PRId32 "\n", fMessagePort));
149 }
150 
151 
152 ServerApp::~ServerApp()
153 {
154 	STRACE(("*ServerApp %s:~ServerApp()\n", Signature()));
155 	ASSERT(fQuitting);
156 
157 	// quit all server windows
158 
159 	fWindowListLock.Lock();
160 	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
161 		ServerWindow* window = fWindowList.ItemAt(i);
162 		window->Quit();
163 	}
164 	fWindowListLock.Unlock();
165 
166 	// wait for the windows to quit
167 	snooze(20000);
168 
169 	fDesktop->RevertScreenModes(fTemporaryDisplayModeChange);
170 
171 	fWindowListLock.Lock();
172 	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
173 		ServerWindow* window = fWindowList.ItemAt(i);
174 
175 		// A window could have been removed in the mean time
176 		// (if those 20 milli seconds from above weren't enough)
177 		if (window == NULL)
178 			continue;
179 
180 		sem_id deathSemaphore = window->DeathSemaphore();
181 		fWindowListLock.Unlock();
182 
183 		// wait 3 seconds for our window to quit - that's quite a long
184 		// time, but killing it might have desastrous effects
185 		if (MessageLooper::WaitForQuit(deathSemaphore, 3000000) != B_OK) {
186 			// This really shouldn't happen, as it shows we're buggy
187 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
188 			syslog(LOG_ERR, "ServerApp %s: ServerWindow doesn't respond!\n",
189 				Signature());
190 #else
191 			debugger("ServerWindow doesn't respond!\n");
192 #endif
193 		}
194 		fWindowListLock.Lock();
195 	}
196 
197 	if (fMemoryAllocator != NULL)
198 		fMemoryAllocator->Detach();
199 	fMapLocker.Lock();
200 
201 	while (!fBitmapMap.empty())
202 		_DeleteBitmap(fBitmapMap.begin()->second);
203 
204 	while (!fPictureMap.empty())
205 		fPictureMap.begin()->second->SetOwner(NULL);
206 
207 	fDesktop->GetCursorManager().DeleteCursors(fClientTeam);
208 	if (fMemoryAllocator != NULL)
209 		fMemoryAllocator->ReleaseReference();
210 
211 	STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature()));
212 }
213 
214 
215 /*!	\brief Checks if the application was initialized correctly
216 */
217 status_t
218 ServerApp::InitCheck()
219 {
220 	if (fMessagePort < B_OK)
221 		return fMessagePort;
222 
223 	if (fClientReplyPort < B_OK)
224 		return fClientReplyPort;
225 
226 	if (fWindowListLock.InitCheck() < B_OK)
227 		return fWindowListLock.InitCheck();
228 
229 	if (fMemoryAllocator == NULL)
230 		return B_NO_MEMORY;
231 
232 	return B_OK;
233 }
234 
235 
236 void
237 ServerApp::Quit()
238 {
239 	Quit(-1);
240 }
241 
242 
243 /*!	\brief This quits the application and deletes it. You're not supposed
244 		to call its destructor directly.
245 
246 	At the point you're calling this method, the application should already
247 	be removed from the application list.
248 */
249 void
250 ServerApp::Quit(sem_id shutdownSemaphore)
251 {
252 	if (fThread < B_OK) {
253 		delete this;
254 		return;
255 	}
256 
257 	// execute application deletion in the message looper thread
258 
259 	fQuitting = true;
260 	PostMessage(kMsgAppQuit);
261 
262 	send_data(fThread, 'QUIT', &shutdownSemaphore, sizeof(sem_id));
263 }
264 
265 
266 /*!	\brief Sets the ServerApp's active status
267 	\param value The new status of the ServerApp.
268 
269 	This changes an internal flag and also sets the current cursor to the one
270 	specified by the application
271 */
272 void
273 ServerApp::Activate(bool value)
274 {
275 	if (fIsActive == value)
276 		return;
277 
278 	fIsActive = value;
279 
280 	if (fIsActive) {
281 		// notify registrar about the active app
282 		BRoster::Private roster;
283 		roster.UpdateActiveApp(ClientTeam());
284 
285 		if (_HasWindowUnderMouse()) {
286 			// Set the cursor to the application cursor, if any
287 			fDesktop->SetCursor(CurrentCursor());
288 		}
289 		fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
290 	}
291 }
292 
293 
294 void
295 ServerApp::SetCurrentCursor(ServerCursor* cursor)
296 {
297 	if (fViewCursor != cursor) {
298 		if (fViewCursor)
299 			fViewCursor->ReleaseReference();
300 
301 		fViewCursor = cursor;
302 
303 		if (fViewCursor)
304 			fViewCursor->AcquireReference();
305 	}
306 
307 	fDesktop->SetCursor(CurrentCursor());
308 }
309 
310 
311 ServerCursor*
312 ServerApp::CurrentCursor() const
313 {
314 	if (fViewCursor != NULL)
315 		return fViewCursor;
316 
317 	return fAppCursor;
318 }
319 
320 
321 bool
322 ServerApp::AddWindow(ServerWindow* window)
323 {
324 	BAutolock locker(fWindowListLock);
325 
326 	return fWindowList.AddItem(window);
327 }
328 
329 
330 void
331 ServerApp::RemoveWindow(ServerWindow* window)
332 {
333 	BAutolock locker(fWindowListLock);
334 
335 	fWindowList.RemoveItem(window);
336 }
337 
338 
339 bool
340 ServerApp::InWorkspace(int32 index) const
341 {
342 	BAutolock locker(fWindowListLock);
343 
344 	// we could cache this, but then we'd have to recompute the cached
345 	// value everytime a window has closed or changed workspaces
346 
347 	// TODO: support initial application workspace!
348 
349 	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
350 		ServerWindow* serverWindow = fWindowList.ItemAt(i);
351 
352 		const Window* window = serverWindow->Window();
353 		if (window == NULL || window->IsOffscreenWindow())
354 			continue;
355 
356 		// only normal and unhidden windows count
357 
358 		if (window->IsNormal() && !window->IsHidden()
359 			&& window->InWorkspace(index))
360 			return true;
361 	}
362 
363 	return false;
364 }
365 
366 
367 uint32
368 ServerApp::Workspaces() const
369 {
370 	uint32 workspaces = 0;
371 
372 	BAutolock locker(fWindowListLock);
373 
374 	// we could cache this, but then we'd have to recompute the cached
375 	// value everytime a window has closed or changed workspaces
376 
377 	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
378 		ServerWindow* serverWindow = fWindowList.ItemAt(i);
379 
380 		const Window* window = serverWindow->Window();
381 		if (window == NULL || window->IsOffscreenWindow())
382 			continue;
383 
384 		// only normal and unhidden windows count
385 
386 		if (window->IsNormal() && !window->IsHidden())
387 			workspaces |= window->Workspaces();
388 	}
389 
390 	// TODO: add initial application workspace!
391 	return workspaces;
392 }
393 
394 
395 /*!	\brief Acquires a reference of the desired bitmap, if available.
396 	\param token ID token of the bitmap to find
397 	\return The bitmap having that ID or NULL if not found
398 */
399 ServerBitmap*
400 ServerApp::GetBitmap(int32 token) const
401 {
402 	if (token < 1)
403 		return NULL;
404 
405 	BAutolock _(fMapLocker);
406 
407 	ServerBitmap* bitmap = _FindBitmap(token);
408 	if (bitmap == NULL)
409 		return NULL;
410 
411 	bitmap->AcquireReference();
412 
413 	return bitmap;
414 }
415 
416 
417 ServerPicture*
418 ServerApp::CreatePicture(const ServerPicture* original)
419 {
420 	ServerPicture* picture;
421 	if (original != NULL)
422 		picture = new(std::nothrow) ServerPicture(*original);
423 	else
424 		picture = new(std::nothrow) ServerPicture();
425 
426 	if (picture != NULL && !picture->SetOwner(this))
427 		picture->ReleaseReference();
428 
429 	return picture;
430 }
431 
432 
433 ServerPicture*
434 ServerApp::GetPicture(int32 token) const
435 {
436 	if (token < 1)
437 		return NULL;
438 
439 	BAutolock _(fMapLocker);
440 
441 	ServerPicture* picture = _FindPicture(token);
442 	if (picture == NULL)
443 		return NULL;
444 
445 	picture->AcquireReference();
446 
447 	return picture;
448 }
449 
450 
451 /*! To be called only by ServerPicture itself.*/
452 bool
453 ServerApp::AddPicture(ServerPicture* picture)
454 {
455 	BAutolock _(fMapLocker);
456 
457 	ASSERT(picture->Owner() == NULL);
458 
459 	try {
460 		fPictureMap.insert(std::make_pair(picture->Token(), picture));
461 	} catch (std::bad_alloc& exception) {
462 		return false;
463 	}
464 
465 	return true;
466 }
467 
468 
469 /*! To be called only by ServerPicture itself.*/
470 void
471 ServerApp::RemovePicture(ServerPicture* picture)
472 {
473 	BAutolock _(fMapLocker);
474 
475 	ASSERT(picture->Owner() == this);
476 
477 	fPictureMap.erase(picture->Token());
478 	picture->ReleaseReference();
479 }
480 
481 
482 /*!	Called from the ClientMemoryAllocator whenever a server area could be
483 	deleted.
484 	A message is then sent to the client telling it that it can delete its
485 	client area, too.
486 */
487 void
488 ServerApp::NotifyDeleteClientArea(area_id serverArea)
489 {
490 	BMessage notify(kMsgDeleteServerMemoryArea);
491 	notify.AddInt32("server area", serverArea);
492 
493 	SendMessageToClient(&notify);
494 }
495 
496 
497 /*!	\brief Send a message to the ServerApp's BApplication
498 	\param message The message to send
499 */
500 void
501 ServerApp::SendMessageToClient(BMessage* message) const
502 {
503 	status_t status = fHandlerMessenger.SendMessage(message, (BHandler*)NULL,
504 		100000);
505 	if (status != B_OK) {
506 		syslog(LOG_ERR, "app %s send to client failed: %s\n", Signature(),
507 			strerror(status));
508 	}
509 }
510 
511 
512 // #pragma mark - private methods
513 
514 
515 void
516 ServerApp::_GetLooperName(char* name, size_t length)
517 {
518 	snprintf(name, length, "a:%" B_PRId32 ":%s", ClientTeam(), SignatureLeaf());
519 }
520 
521 
522 /*!	\brief Handler function for BApplication API messages
523 	\param code Identifier code for the message. Equivalent to BMessage::what
524 	\param buffer Any attachments
525 
526 	Note that the buffer's exact format is determined by the particular message.
527 	All attachments are placed in the buffer via a PortLink, so it will be a
528 	matter of casting and incrementing an index variable to access them.
529 */
530 void
531 ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
532 {
533 	switch (code) {
534 		case AS_REGISTER_INPUT_SERVER:
535 		{
536 			EventStream* stream
537 				= new(std::nothrow) InputServerStream(fHandlerMessenger);
538 			if (stream != NULL
539 				&& (!stream->IsValid() || !gInputManager->AddStream(stream))) {
540 				delete stream;
541 				break;
542 			}
543 
544 			// TODO: this should be done using notifications (so that an
545 			// abandoned stream will get noticed directly)
546 			if (fDesktop->EventDispatcher().InitCheck() != B_OK)
547 				fDesktop->EventDispatcher().SetTo(gInputManager->GetStream());
548 			break;
549 		}
550 
551 		case AS_APP_CRASHED:
552 			// Allow the debugger to show its window: if needed, remove any
553 			// kWindowScreenFeels from the windows of this application
554 			if (fDesktop->LockAllWindows()) {
555 				if (fWindowListLock.Lock()) {
556 					for (int32 i = fWindowList.CountItems(); i-- > 0;) {
557 						ServerWindow* serverWindow = fWindowList.ItemAt(i);
558 
559 						Window* window = serverWindow->Window();
560 						if (window == NULL || window->IsOffscreenWindow())
561 							continue;
562 
563 						if (window->Feel() == kWindowScreenFeel)
564 							fDesktop->SetWindowFeel(window, B_NORMAL_WINDOW_FEEL);
565 					}
566 
567 					fWindowListLock.Unlock();
568 				}
569 				fDesktop->UnlockAllWindows();
570 			}
571 			break;
572 
573 		case AS_DUMP_ALLOCATOR:
574 			fMemoryAllocator->Dump();
575 			break;
576 		case AS_DUMP_BITMAPS:
577 		{
578 			fMapLocker.Lock();
579 
580 			debug_printf("Application %" B_PRId32 ", %s: %d bitmaps:\n",
581 				ClientTeam(), Signature(), (int)fBitmapMap.size());
582 
583 			BitmapMap::const_iterator iterator = fBitmapMap.begin();
584 			for (; iterator != fBitmapMap.end(); iterator++) {
585 				ServerBitmap* bitmap = iterator->second;
586 				debug_printf("  [%" B_PRId32 "] %" B_PRId32 "x%" B_PRId32 ", "
587 					"area %" B_PRId32 ", size %" B_PRId32 "\n",
588 					bitmap->Token(), bitmap->Width(), bitmap->Height(),
589 					bitmap->Area(), bitmap->BitsLength());
590 			}
591 			fMapLocker.Unlock();
592 			break;
593 		}
594 
595 		case AS_CREATE_WINDOW:
596 		case AS_CREATE_OFFSCREEN_WINDOW:
597 		{
598 			port_id clientReplyPort = -1;
599 			status_t status = _CreateWindow(code, link, clientReplyPort);
600 
601 			// if sucessful, ServerWindow::Run() will already have replied
602 			if (status < B_OK) {
603 				// window creation failed, we need to notify the client
604 				BPrivate::LinkSender reply(clientReplyPort);
605 				reply.StartMessage(status);
606 				reply.Flush();
607 			}
608 			break;
609 		}
610 
611 		case AS_GET_WINDOW_LIST:
612 		{
613 			team_id team;
614 			if (link.Read<team_id>(&team) == B_OK)
615 				fDesktop->WriteWindowList(team, fLink.Sender());
616 			break;
617 		}
618 
619 		case AS_GET_WINDOW_INFO:
620 		{
621 			int32 serverToken;
622 			if (link.Read<int32>(&serverToken) == B_OK)
623 				fDesktop->WriteWindowInfo(serverToken, fLink.Sender());
624 			break;
625 		}
626 
627 		case AS_GET_WINDOW_ORDER:
628 		{
629 			int32 workspace;
630 			if (link.Read<int32>(&workspace) == B_OK)
631 				fDesktop->WriteWindowOrder(workspace, fLink.Sender());
632 			break;
633 		}
634 
635 		case AS_GET_APPLICATION_ORDER:
636 		{
637 			int32 workspace;
638 			if (link.Read<int32>(&workspace) == B_OK)
639 				fDesktop->WriteApplicationOrder(workspace, fLink.Sender());
640 			break;
641 		}
642 
643 		case AS_MINIMIZE_TEAM:
644 		{
645 			team_id team;
646 			if (link.Read<team_id>(&team) == B_OK)
647 				fDesktop->MinimizeApplication(team);
648 			break;
649 		}
650 
651 		case AS_BRING_TEAM_TO_FRONT:
652 		{
653 			team_id team;
654 			if (link.Read<team_id>(&team) == B_OK)
655 				fDesktop->BringApplicationToFront(team);
656 			break;
657 		}
658 
659 		case AS_WINDOW_ACTION:
660 		{
661 			int32 token;
662 			int32 action;
663 
664 			link.Read<int32>(&token);
665 			if (link.Read<int32>(&action) != B_OK)
666 				break;
667 
668 			fDesktop->WindowAction(token, action);
669 			break;
670 		}
671 
672 		// Decorator commands
673 
674 		case AS_SET_DECORATOR:
675 		{
676 			// Attached Data:
677 			// path to decorator add-on
678 
679 			BString path;
680 			link.ReadString(path);
681 
682 			status_t error = gDecorManager.SetDecorator(path, fDesktop);
683 
684 			fLink.Attach<status_t>(error);
685 			fLink.Flush();
686 
687 			if (error == B_OK)
688 				fDesktop->BroadcastToAllApps(AS_UPDATE_DECORATOR);
689 			break;
690 		}
691 
692 		case AS_GET_DECORATOR:
693 		{
694 			fLink.StartMessage(B_OK);
695 			fLink.AttachString(gDecorManager.GetCurrentDecorator().String());
696 			fLink.Flush();
697 			break;
698 		}
699 
700 		case AS_SET_CONTROL_LOOK:
701 		{
702 			STRACE(("ServerApp %s: Set ControlLook\n", Signature()));
703 
704 			BString path;
705 			status_t error = B_ERROR;
706 			if (link.ReadString(path) == B_OK) {
707 				LockedDesktopSettings settings(fDesktop);
708 				error = settings.SetControlLook(path.String());
709 			}
710 
711 			fLink.StartMessage(error);
712 			fLink.Flush();
713 			break;
714 		}
715 
716 		case AS_GET_CONTROL_LOOK:
717 		{
718 			STRACE(("ServerApp %s: Get ControlLook\n", Signature()));
719 
720 			if (fDesktop->LockSingleWindow()) {
721 				DesktopSettings settings(fDesktop);
722 
723 				fLink.StartMessage(B_OK);
724 				fLink.AttachString(settings.ControlLook().String());
725 				fDesktop->UnlockSingleWindow();
726 			} else
727 				fLink.StartMessage(B_ERROR);
728 
729 			fLink.Flush();
730 			break;
731 		}
732 
733 		case AS_CREATE_BITMAP:
734 		{
735 			STRACE(("ServerApp %s: Received BBitmap creation request\n",
736 				Signature()));
737 
738 			// Allocate a bitmap for an application
739 
740 			// Attached Data:
741 			// 1) BRect bounds
742 			// 2) color_space space
743 			// 3) int32 bitmap_flags
744 			// 4) int32 bytes_per_row
745 			// 5) int32 screen_id
746 
747 			// Reply Data:
748 			//	1) int32 server token
749 			//	2) area_id id of the area in which the bitmap data resides
750 			//	3) int32 area pointer offset used to calculate fBasePtr
751 
752 			// First, let's attempt to allocate the bitmap
753 			ServerBitmap* bitmap = NULL;
754 			uint8 allocationFlags = kAllocator;
755 
756 			BRect frame;
757 			color_space colorSpace;
758 			uint32 flags;
759 			int32 bytesPerRow;
760 			int32 screenID;
761 
762 			link.Read<BRect>(&frame);
763 			link.Read<color_space>(&colorSpace);
764 			link.Read<uint32>(&flags);
765 			link.Read<int32>(&bytesPerRow);
766 			if (link.Read<int32>(&screenID) == B_OK) {
767 				// TODO: choose the right HWInterface with regards to the
768 				// screenID
769 				bitmap = gBitmapManager->CreateBitmap(fMemoryAllocator,
770 					*fDesktop->HWInterface(), frame, colorSpace, flags,
771 					bytesPerRow, screenID, &allocationFlags);
772 			}
773 
774 			STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n",
775 				Signature(), frame.Width() + 1, frame.Height() + 1));
776 
777 			if (bitmap != NULL && _AddBitmap(bitmap)) {
778 				fLink.StartMessage(B_OK);
779 				fLink.Attach<int32>(bitmap->Token());
780 				fLink.Attach<uint8>(allocationFlags);
781 
782 				fLink.Attach<area_id>(bitmap->Area());
783 				fLink.Attach<int32>(bitmap->AreaOffset());
784 
785 				if ((allocationFlags & kFramebuffer) != 0)
786 					fLink.Attach<int32>(bitmap->BytesPerRow());
787 			} else {
788 				if (bitmap != NULL)
789 					bitmap->ReleaseReference();
790 
791 				fLink.StartMessage(B_NO_MEMORY);
792 			}
793 
794 			fLink.Flush();
795 			break;
796 		}
797 
798 		case AS_DELETE_BITMAP:
799 		{
800 			STRACE(("ServerApp %s: received BBitmap delete request\n",
801 				Signature()));
802 
803 			// Attached Data:
804 			// 1) int32 token
805 			int32 token;
806 			link.Read<int32>(&token);
807 
808 			fMapLocker.Lock();
809 
810 			ServerBitmap* bitmap = _FindBitmap(token);
811 			if (bitmap != NULL) {
812 				STRACE(("ServerApp %s: Deleting Bitmap %" B_PRId32 "\n",
813 					Signature(), token));
814 
815 				_DeleteBitmap(bitmap);
816 			}
817 
818 			fMapLocker.Unlock();
819 			break;
820 		}
821 
822 		case AS_GET_BITMAP_OVERLAY_RESTRICTIONS:
823 		{
824 			overlay_restrictions restrictions;
825 			status_t status = B_ERROR;
826 
827 			int32 token;
828 			if (link.Read<int32>(&token) != B_OK)
829 				break;
830 
831 			ServerBitmap* bitmap = GetBitmap(token);
832 			if (bitmap != NULL) {
833 				STRACE(("ServerApp %s: Get overlay restrictions for bitmap "
834 					"%" B_PRId32 "\n", Signature(), token));
835 
836 				status = fDesktop->HWInterface()->GetOverlayRestrictions(
837 					bitmap->Overlay(), &restrictions);
838 
839 				bitmap->ReleaseReference();
840 			}
841 
842 			fLink.StartMessage(status);
843 			if (status == B_OK)
844 				fLink.Attach(&restrictions, sizeof(overlay_restrictions));
845 
846 			fLink.Flush();
847 			break;
848 		}
849 
850 		case AS_GET_BITMAP_SUPPORT_FLAGS:
851 		{
852 			uint32 colorSpace;
853 			if (link.Read<uint32>(&colorSpace) != B_OK)
854 				break;
855 
856 			bool overlay = fDesktop->HWInterface()->CheckOverlayRestrictions(
857 				64, 64, (color_space)colorSpace);
858 			uint32 flags = overlay ? B_BITMAPS_SUPPORT_OVERLAY : 0;
859 
860 			fLink.StartMessage(B_OK);
861 			fLink.Attach<int32>(flags);
862 			fLink.Flush();
863 			break;
864 		}
865 
866 		case AS_RECONNECT_BITMAP:
867 		{
868 			// First, let's attempt to allocate the bitmap
869 			ServerBitmap* bitmap = NULL;
870 
871 			BRect frame;
872 			color_space colorSpace;
873 			uint32 flags;
874 			int32 bytesPerRow;
875 			int32 screenID;
876 			area_id clientArea;
877 			int32 areaOffset;
878 
879 			link.Read<BRect>(&frame);
880 			link.Read<color_space>(&colorSpace);
881 			link.Read<uint32>(&flags);
882 			link.Read<int32>(&bytesPerRow);
883 			link.Read<int32>(&screenID);
884 			link.Read<int32>(&clientArea);
885 			if (link.Read<int32>(&areaOffset) == B_OK) {
886 				// TODO: choose the right HWInterface with regards to the
887 				// screenID
888 				bitmap = gBitmapManager->CloneFromClient(clientArea, areaOffset,
889 					frame, colorSpace, flags, bytesPerRow);
890 			}
891 
892 			if (bitmap != NULL && _AddBitmap(bitmap)) {
893 				fLink.StartMessage(B_OK);
894 				fLink.Attach<int32>(bitmap->Token());
895 
896 				fLink.Attach<area_id>(bitmap->Area());
897 
898 			} else {
899 				if (bitmap != NULL)
900 					bitmap->ReleaseReference();
901 
902 				fLink.StartMessage(B_NO_MEMORY);
903 			}
904 
905 			fLink.Flush();
906 			break;
907 		}
908 
909 		// Picture ops
910 
911 		case AS_CREATE_PICTURE:
912 		{
913 			// TODO: Maybe rename this to AS_UPLOAD_PICTURE ?
914 			STRACE(("ServerApp %s: Create Picture\n", Signature()));
915 			status_t status = B_NO_MEMORY;
916 
917 			ServerPicture* picture = CreatePicture();
918 			if (picture != NULL) {
919 				int32 subPicturesCount = 0;
920 				link.Read<int32>(&subPicturesCount);
921 				for (int32 i = 0; i < subPicturesCount; i++) {
922 					int32 token = -1;
923 					link.Read<int32>(&token);
924 
925 					BAutolock _(fMapLocker);
926 					if (ServerPicture* subPicture = _FindPicture(token))
927 						picture->NestPicture(subPicture);
928 				}
929 				status = picture->ImportData(link);
930 			}
931 			if (status == B_OK) {
932 				fLink.StartMessage(B_OK);
933 				fLink.Attach<int32>(picture->Token());
934 			} else
935 				fLink.StartMessage(status);
936 
937 			fLink.Flush();
938 			break;
939 		}
940 
941 		case AS_DELETE_PICTURE:
942 		{
943 			STRACE(("ServerApp %s: Delete Picture\n", Signature()));
944 			int32 token;
945 			if (link.Read<int32>(&token) == B_OK) {
946 				BAutolock _(fMapLocker);
947 
948 				ServerPicture* picture = _FindPicture(token);
949 				if (picture != NULL)
950 					picture->SetOwner(NULL);
951 			}
952 			break;
953 		}
954 
955 		case AS_CLONE_PICTURE:
956 		{
957 			STRACE(("ServerApp %s: Clone Picture\n", Signature()));
958 			int32 token;
959 			ServerPicture* original = NULL;
960 			if (link.Read<int32>(&token) == B_OK)
961 				original = GetPicture(token);
962 
963 			if (original != NULL) {
964 				ServerPicture* cloned = CreatePicture(original);
965 				if (cloned != NULL) {
966 					fLink.StartMessage(B_OK);
967 					fLink.Attach<int32>(cloned->Token());
968 				} else
969 					fLink.StartMessage(B_NO_MEMORY);
970 
971 				original->ReleaseReference();
972 			} else
973 				fLink.StartMessage(B_BAD_VALUE);
974 
975 			fLink.Flush();
976 			break;
977 		}
978 
979 		case AS_DOWNLOAD_PICTURE:
980 		{
981 			STRACE(("ServerApp %s: Download Picture\n", Signature()));
982 			int32 token;
983 			link.Read<int32>(&token);
984 			ServerPicture* picture = GetPicture(token);
985 			if (picture != NULL) {
986 				picture->ExportData(fLink);
987 					// ExportData() calls StartMessage() already
988 				picture->ReleaseReference();
989 			} else
990 				fLink.StartMessage(B_ERROR);
991 
992 			fLink.Flush();
993 			break;
994 		}
995 
996 		case AS_CURRENT_WORKSPACE:
997 			STRACE(("ServerApp %s: get current workspace\n", Signature()));
998 
999 			if (fDesktop->LockSingleWindow()) {
1000 				fLink.StartMessage(B_OK);
1001 				fLink.Attach<int32>(fDesktop->CurrentWorkspace());
1002 				fDesktop->UnlockSingleWindow();
1003 			} else
1004 				fLink.StartMessage(B_ERROR);
1005 
1006 			fLink.Flush();
1007 			break;
1008 
1009 		case AS_ACTIVATE_WORKSPACE:
1010 		{
1011 			STRACE(("ServerApp %s: activate workspace\n", Signature()));
1012 
1013 			// TODO: See above
1014 			int32 index;
1015 			link.Read<int32>(&index);
1016 
1017 			bool takeFocusWindowThere;
1018 			link.Read<bool>(&takeFocusWindowThere);
1019 
1020 			fDesktop->SetWorkspace(index, takeFocusWindowThere);
1021 			break;
1022 		}
1023 
1024 		case AS_SET_WORKSPACE_LAYOUT:
1025 		{
1026 			int32 newColumns;
1027 			int32 newRows;
1028 			if (link.Read<int32>(&newColumns) == B_OK
1029 				&& link.Read<int32>(&newRows) == B_OK)
1030 				fDesktop->SetWorkspacesLayout(newColumns, newRows);
1031 			break;
1032 		}
1033 
1034 		case AS_GET_WORKSPACE_LAYOUT:
1035 		{
1036 			if (fDesktop->LockSingleWindow()) {
1037 				DesktopSettings settings(fDesktop);
1038 
1039 				fLink.StartMessage(B_OK);
1040 				fLink.Attach<int32>(settings.WorkspacesColumns());
1041 				fLink.Attach<int32>(settings.WorkspacesRows());
1042 
1043 				fDesktop->UnlockSingleWindow();
1044 			} else
1045 				fLink.StartMessage(B_ERROR);
1046 
1047 			fLink.Flush();
1048 			break;
1049 		}
1050 
1051 		case AS_IDLE_TIME:
1052 			STRACE(("ServerApp %s: idle time\n", Signature()));
1053 
1054 			fLink.StartMessage(B_OK);
1055 			fLink.Attach<bigtime_t>(fDesktop->EventDispatcher().IdleTime());
1056 			fLink.Flush();
1057 			break;
1058 
1059 		case AS_SHOW_CURSOR:
1060 		{
1061 			STRACE(("ServerApp %s: Show Cursor\n", Signature()));
1062 			fCursorHideLevel--;
1063 			if (fCursorHideLevel < 0)
1064 				fCursorHideLevel = 0;
1065 			fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
1066 			break;
1067 		}
1068 
1069 		case AS_HIDE_CURSOR:
1070 		{
1071 			STRACE(("ServerApp %s: Hide Cursor\n", Signature()));
1072 			fCursorHideLevel++;
1073 			fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
1074 			break;
1075 		}
1076 
1077 		case AS_OBSCURE_CURSOR:
1078 		{
1079 			STRACE(("ServerApp %s: Obscure Cursor\n", Signature()));
1080 			fDesktop->HWInterface()->ObscureCursor();
1081 			break;
1082 		}
1083 
1084 		case AS_QUERY_CURSOR_HIDDEN:
1085 		{
1086 			STRACE(("ServerApp %s: Received IsCursorHidden request\n",
1087 				Signature()));
1088 
1089 			fLink.StartMessage(fCursorHideLevel > 0 ? B_OK : B_ERROR);
1090 			fLink.Flush();
1091 			break;
1092 		}
1093 
1094 		case AS_SET_CURSOR:
1095 		{
1096 			STRACE(("ServerApp %s: SetCursor\n", Signature()));
1097 
1098 			// Attached data:
1099 			// 1) bool flag to send a reply
1100 			// 2) int32 token ID of the cursor to set
1101 			// 3) port_id port to receive a reply. Only exists if the sync flag
1102 			//    is true.
1103 			bool sync;
1104 			int32 token;
1105 
1106 			link.Read<bool>(&sync);
1107 			if (link.Read<int32>(&token) != B_OK)
1108 				break;
1109 
1110 			if (!fDesktop->GetCursorManager().Lock())
1111 				break;
1112 
1113 			ServerCursor* oldCursor = fAppCursor;
1114 			fAppCursor = fDesktop->GetCursorManager().FindCursor(token);
1115 			if (fAppCursor != NULL)
1116 				fAppCursor->AcquireReference();
1117 
1118 			if (_HasWindowUnderMouse())
1119 				fDesktop->SetCursor(CurrentCursor());
1120 
1121 			if (oldCursor != NULL)
1122 				oldCursor->ReleaseReference();
1123 
1124 			fDesktop->GetCursorManager().Unlock();
1125 
1126 			if (sync) {
1127 				// The application is expecting a reply
1128 				fLink.StartMessage(B_OK);
1129 				fLink.Flush();
1130 			}
1131 			break;
1132 		}
1133 
1134 		case AS_SET_VIEW_CURSOR:
1135 		{
1136 			STRACE(("ServerApp %s: AS_SET_VIEW_CURSOR:\n", Signature()));
1137 
1138 			ViewSetViewCursorInfo info;
1139 			if (link.Read<ViewSetViewCursorInfo>(&info) != B_OK)
1140 				break;
1141 
1142 			if (fDesktop->GetCursorManager().Lock()) {
1143 				ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(
1144 					info.cursorToken);
1145 				// If we found a cursor, make sure it doesn't go away. If we
1146 				// get a NULL cursor, it probably means we are supposed to use
1147 				// the system default cursor.
1148 				if (cursor != NULL)
1149 					cursor->AcquireReference();
1150 
1151 				fDesktop->GetCursorManager().Unlock();
1152 
1153 				// We need to acquire the write lock here, since we cannot
1154 				// afford that the window thread to which the view belongs
1155 				// is running and messing with that same view.
1156 				fDesktop->LockAllWindows();
1157 
1158 				// Find the corresponding view by the given token. It's ok
1159 				// if this view does not exist anymore, since it may have
1160 				// already be deleted in the window thread before this
1161 				// message got here.
1162 				View* view;
1163 				if (fViewTokens.GetToken(info.viewToken, B_HANDLER_TOKEN,
1164 					(void**)&view) == B_OK) {
1165 					// Set the cursor on the view.
1166 					view->SetCursor(cursor);
1167 
1168 					// The cursor might need to be updated now.
1169 					Window* window = view->Window();
1170 					if (window != NULL && window->IsFocus()) {
1171 						if (fDesktop->ViewUnderMouse(window) == view->Token())
1172 							SetCurrentCursor(cursor);
1173 					}
1174 				}
1175 
1176 				fDesktop->UnlockAllWindows();
1177 
1178 				// Release the temporary reference.
1179 				if (cursor != NULL)
1180 					cursor->ReleaseReference();
1181 			}
1182 
1183 			if (info.sync) {
1184 				// sync the client (it can now delete the cursor)
1185 				fLink.StartMessage(B_OK);
1186 				fLink.Flush();
1187 			}
1188 			break;
1189 		}
1190 
1191 		case AS_CREATE_CURSOR:
1192 		{
1193 			STRACE(("ServerApp %s: Create Cursor\n", Signature()));
1194 
1195 			// Attached data:
1196 			// 1) 68 bytes of fAppCursor data
1197 			// 2) port_id reply port
1198 
1199 			status_t status = B_ERROR;
1200 			uint8 cursorData[68];
1201 			ServerCursor* cursor = NULL;
1202 
1203 //			if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
1204 //				cursor = new (nothrow) ServerCursor(cursorData);
1205 //				if (cursor == NULL)
1206 //					status = B_NO_MEMORY;
1207 //			}
1208 //
1209 //			if (cursor != NULL) {
1210 //				cursor->SetOwningTeam(fClientTeam);
1211 //				fDesktop->GetCursorManager().AddCursor(cursor);
1212 //
1213 //				// Synchronous message - BApplication is waiting on the cursor's ID
1214 //				fLink.StartMessage(B_OK);
1215 //				fLink.Attach<int32>(cursor->Token());
1216 //			} else
1217 //				fLink.StartMessage(status);
1218 
1219 			if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
1220 				cursor = fDesktop->GetCursorManager().CreateCursor(fClientTeam,
1221 					cursorData);
1222 				if (cursor == NULL)
1223 					status = B_NO_MEMORY;
1224 			}
1225 
1226 			if (cursor != NULL) {
1227 				// Synchronous message - BApplication is waiting on the
1228 				// cursor's ID
1229 				fLink.StartMessage(B_OK);
1230 				fLink.Attach<int32>(cursor->Token());
1231 			} else
1232 				fLink.StartMessage(status);
1233 
1234 			fLink.Flush();
1235 			break;
1236 		}
1237 
1238 		case AS_CREATE_CURSOR_BITMAP:
1239 		{
1240 			STRACE(("ServerApp %s: Create Cursor bitmap\n", Signature()));
1241 
1242 			status_t status = B_ERROR;
1243 
1244 			int32 size = 0;
1245 			BRect cursorRect;
1246 			color_space colorspace = B_RGBA32;
1247 			BPoint hotspot;
1248 			ServerCursor* cursor = NULL;
1249 
1250 			if (link.Read<int32>(&size) == B_OK
1251 				&& link.Read<BRect>(&cursorRect) == B_OK
1252 				&& link.Read<color_space>(&colorspace) == B_OK
1253 				&& link.Read<BPoint>(&hotspot) == B_OK
1254 				&& size > 0) {
1255 
1256 				BStackOrHeapArray<uint8, 256> byteArray(size);
1257 				if (!byteArray.IsValid()) {
1258 					status = B_NO_MEMORY;
1259 				} else if (link.Read(byteArray, size) == B_OK) {
1260 					cursor = fDesktop->GetCursorManager().CreateCursor(
1261 						fClientTeam, cursorRect, colorspace, 0, hotspot);
1262 					if (cursor == NULL)
1263 						status = B_NO_MEMORY;
1264 					else
1265 						memcpy(cursor->Bits(), byteArray, size);
1266 				}
1267 			}
1268 
1269 			if (cursor != NULL) {
1270 				// Synchronous message - BApplication is waiting on the
1271 				// cursor's ID
1272 				fLink.StartMessage(B_OK);
1273 				fLink.Attach<int32>(cursor->Token());
1274 			} else
1275 				fLink.StartMessage(status);
1276 
1277 			fLink.Flush();
1278 			break;
1279 		}
1280 
1281 		case AS_REFERENCE_CURSOR:
1282 		{
1283 			STRACE(("ServerApp %s: Reference BCursor\n", Signature()));
1284 
1285 			// Attached data:
1286 			// 1) int32 token ID of the cursor to reference
1287 
1288 			int32 token;
1289 			if (link.Read<int32>(&token) != B_OK)
1290 				break;
1291 
1292 			if (!fDesktop->GetCursorManager().Lock())
1293 				break;
1294 
1295 			ServerCursor* cursor
1296 				= fDesktop->GetCursorManager().FindCursor(token);
1297 			if (cursor != NULL)
1298 				cursor->AcquireReference();
1299 
1300 			fDesktop->GetCursorManager().Unlock();
1301 
1302 			break;
1303 		}
1304 
1305 		case AS_DELETE_CURSOR:
1306 		{
1307 			STRACE(("ServerApp %s: Delete BCursor\n", Signature()));
1308 
1309 			// Attached data:
1310 			// 1) int32 token ID of the cursor to delete
1311 
1312 			int32 token;
1313 			if (link.Read<int32>(&token) != B_OK)
1314 				break;
1315 
1316 			if (!fDesktop->GetCursorManager().Lock())
1317 				break;
1318 
1319 			ServerCursor* cursor
1320 				= fDesktop->GetCursorManager().FindCursor(token);
1321 			if (cursor != NULL)
1322 				cursor->ReleaseReference();
1323 
1324 			fDesktop->GetCursorManager().Unlock();
1325 
1326 			break;
1327 		}
1328 
1329 		case AS_GET_CURSOR_POSITION:
1330 		{
1331 			STRACE(("ServerApp %s: Get Cursor position\n", Signature()));
1332 
1333 			// Returns
1334 			// 1) BPoint mouse location
1335 			// 2) int32 button state
1336 
1337 			BPoint where;
1338 			int32 buttons;
1339 			fDesktop->GetLastMouseState(&where, &buttons);
1340 			fLink.StartMessage(B_OK);
1341 			fLink.Attach<BPoint>(where);
1342 			fLink.Attach<int32>(buttons);
1343 			fLink.Flush();
1344 			break;
1345 		}
1346 
1347 		case AS_GET_CURSOR_BITMAP:
1348 		{
1349 			STRACE(("ServerApp %s: Get Cursor bitmap\n", Signature()));
1350 
1351 			// Returns
1352 			// 1) uint32 number of data bytes of the bitmap
1353 			// 2) uint32 cursor width in number of pixels
1354 			// 3) uint32 cursor height in number of pixels
1355 			// 4) BPoint cursor hot spot
1356 			// 5) cursor bitmap data
1357 
1358 			ServerCursorReference cursorRef = fDesktop->Cursor();
1359 			ServerCursor* cursor = cursorRef.Get();
1360 			if (cursor != NULL) {
1361 				uint32 size = cursor->BitsLength();
1362 				fLink.StartMessage(B_OK);
1363 				fLink.Attach<uint32>(size);
1364 				fLink.Attach<uint32>(cursor->Width());
1365 				fLink.Attach<uint32>(cursor->Height());
1366 				fLink.Attach<color_space>(cursor->ColorSpace());
1367 				fLink.Attach<BPoint>(cursor->GetHotSpot());
1368 				fLink.Attach(cursor->Bits(), size);
1369 			} else
1370 				fLink.StartMessage(B_ERROR);
1371 
1372 			fLink.Flush();
1373 
1374 			break;
1375 		}
1376 
1377 		case AS_GET_SCROLLBAR_INFO:
1378 		{
1379 			STRACE(("ServerApp %s: Get ScrollBar info\n", Signature()));
1380 
1381 			if (fDesktop->LockSingleWindow()) {
1382 				scroll_bar_info info;
1383 				DesktopSettings settings(fDesktop);
1384 				settings.GetScrollBarInfo(info);
1385 
1386 				fLink.StartMessage(B_OK);
1387 				fLink.Attach<scroll_bar_info>(info);
1388 				fDesktop->UnlockSingleWindow();
1389 			} else
1390 				fLink.StartMessage(B_ERROR);
1391 
1392 			fLink.Flush();
1393 			break;
1394 		}
1395 
1396 		case AS_SET_SCROLLBAR_INFO:
1397 		{
1398 			STRACE(("ServerApp %s: Set ScrollBar info\n", Signature()));
1399 
1400 			// Attached Data:
1401 			// 1) scroll_bar_info scroll bar info structure
1402 
1403 			scroll_bar_info info;
1404 			if (link.Read<scroll_bar_info>(&info) == B_OK) {
1405 				LockedDesktopSettings settings(fDesktop);
1406 				settings.SetScrollBarInfo(info);
1407 			}
1408 
1409 			fLink.StartMessage(B_OK);
1410 			fLink.Flush();
1411 			break;
1412 		}
1413 
1414 		case AS_GET_MENU_INFO:
1415 		{
1416 			STRACE(("ServerApp %s: Get menu info\n", Signature()));
1417 			if (fDesktop->LockSingleWindow()) {
1418 				menu_info info;
1419 				DesktopSettings settings(fDesktop);
1420 				settings.GetMenuInfo(info);
1421 
1422 				fLink.StartMessage(B_OK);
1423 				fLink.Attach<menu_info>(info);
1424 
1425 				fDesktop->UnlockSingleWindow();
1426 			} else
1427 				fLink.StartMessage(B_ERROR);
1428 
1429 			fLink.Flush();
1430 			break;
1431 		}
1432 
1433 		case AS_SET_MENU_INFO:
1434 		{
1435 			STRACE(("ServerApp %s: Set menu info\n", Signature()));
1436 			menu_info info;
1437 			if (link.Read<menu_info>(&info) == B_OK) {
1438 				LockedDesktopSettings settings(fDesktop);
1439 				settings.SetMenuInfo(info);
1440 					// TODO: SetMenuInfo() should do some validity check, so
1441 					//	that the answer we're giving can actually be useful
1442 			}
1443 
1444 			fLink.StartMessage(B_OK);
1445 			fLink.Flush();
1446 			break;
1447 		}
1448 
1449 		case AS_SET_MOUSE_MODE:
1450 		{
1451 			STRACE(("ServerApp %s: Set Mouse Focus mode\n",
1452 				Signature()));
1453 
1454 			// Attached Data:
1455 			// 1) enum mode_mouse mouse focus mode
1456 
1457 			mode_mouse mouseMode;
1458 			if (link.Read<mode_mouse>(&mouseMode) == B_OK) {
1459 				LockedDesktopSettings settings(fDesktop);
1460 				settings.SetMouseMode(mouseMode);
1461 			}
1462 			break;
1463 		}
1464 
1465 		case AS_GET_MOUSE_MODE:
1466 		{
1467 			STRACE(("ServerApp %s: Get Mouse Focus mode\n",
1468 				Signature()));
1469 
1470 			if (fDesktop->LockSingleWindow()) {
1471 				DesktopSettings settings(fDesktop);
1472 
1473 				fLink.StartMessage(B_OK);
1474 				fLink.Attach<mode_mouse>(settings.MouseMode());
1475 
1476 				fDesktop->UnlockSingleWindow();
1477 			} else
1478 				fLink.StartMessage(B_ERROR);
1479 
1480 			fLink.Flush();
1481 			break;
1482 		}
1483 
1484 		case AS_SET_FOCUS_FOLLOWS_MOUSE_MODE:
1485 		{
1486 			STRACE(("ServerApp %s: Set Focus Follows Mouse mode\n", Signature()));
1487 
1488 			// Attached Data:
1489 			// 1) enum mode_focus_follows_mouse FFM mouse mode
1490 
1491 			mode_focus_follows_mouse focusFollowsMousMode;
1492 			if (link.Read<mode_focus_follows_mouse>(&focusFollowsMousMode) == B_OK) {
1493 				LockedDesktopSettings settings(fDesktop);
1494 				settings.SetFocusFollowsMouseMode(focusFollowsMousMode);
1495 			}
1496 			break;
1497 		}
1498 
1499 		case AS_GET_FOCUS_FOLLOWS_MOUSE_MODE:
1500 		{
1501 			STRACE(("ServerApp %s: Get Focus Follows Mouse mode\n", Signature()));
1502 
1503 			if (fDesktop->LockSingleWindow()) {
1504 				DesktopSettings settings(fDesktop);
1505 
1506 				fLink.StartMessage(B_OK);
1507 				fLink.Attach<mode_focus_follows_mouse>(
1508 					settings.FocusFollowsMouseMode());
1509 
1510 				fDesktop->UnlockSingleWindow();
1511 			} else
1512 				fLink.StartMessage(B_ERROR);
1513 
1514 			fLink.Flush();
1515 			break;
1516 		}
1517 
1518 		case AS_SET_ACCEPT_FIRST_CLICK:
1519 		{
1520 			STRACE(("ServerApp %s: Set Accept First Click\n", Signature()));
1521 
1522 			// Attached Data:
1523 			// 1) bool accept_first_click
1524 
1525 			bool acceptFirstClick;
1526 			if (link.Read<bool>(&acceptFirstClick) == B_OK) {
1527 				LockedDesktopSettings settings(fDesktop);
1528 				settings.SetAcceptFirstClick(acceptFirstClick);
1529 			}
1530 			break;
1531 		}
1532 
1533 		case AS_GET_ACCEPT_FIRST_CLICK:
1534 		{
1535 			STRACE(("ServerApp %s: Get Accept First Click\n", Signature()));
1536 
1537 			if (fDesktop->LockSingleWindow()) {
1538 				DesktopSettings settings(fDesktop);
1539 
1540 				fLink.StartMessage(B_OK);
1541 				fLink.Attach<bool>(settings.AcceptFirstClick());
1542 
1543 				fDesktop->UnlockSingleWindow();
1544 			} else
1545 				fLink.StartMessage(B_ERROR);
1546 
1547 			fLink.Flush();
1548 			break;
1549 		}
1550 
1551 		case AS_GET_SHOW_ALL_DRAGGERS:
1552 		{
1553 			STRACE(("ServerApp %s: Get Show All Draggers\n", Signature()));
1554 
1555 			if (fDesktop->LockSingleWindow()) {
1556 				DesktopSettings settings(fDesktop);
1557 
1558 				fLink.StartMessage(B_OK);
1559 				fLink.Attach<bool>(settings.ShowAllDraggers());
1560 
1561 				fDesktop->UnlockSingleWindow();
1562 			} else
1563 				fLink.StartMessage(B_ERROR);
1564 
1565 			fLink.Flush();
1566 			break;
1567 		}
1568 
1569 		case AS_SET_SHOW_ALL_DRAGGERS:
1570 		{
1571 			STRACE(("ServerApp %s: Set Show All Draggers\n", Signature()));
1572 
1573 			bool changed = false;
1574 			bool show;
1575 			if (link.Read<bool>(&show) == B_OK) {
1576 				LockedDesktopSettings settings(fDesktop);
1577 				if (show != settings.ShowAllDraggers()) {
1578 					settings.SetShowAllDraggers(show);
1579 					changed = true;
1580 				}
1581 			}
1582 
1583 			if (changed)
1584 				fDesktop->BroadcastToAllApps(kMsgUpdateShowAllDraggers);
1585 			break;
1586 		}
1587 
1588 		case kMsgUpdateShowAllDraggers:
1589 		{
1590 			bool show = false;
1591 			if (fDesktop->LockSingleWindow()) {
1592 				DesktopSettings settings(fDesktop);
1593 				show = settings.ShowAllDraggers();
1594 				fDesktop->UnlockSingleWindow();
1595 			}
1596 			BMessage update(_SHOW_DRAG_HANDLES_);
1597 			update.AddBool("show", show);
1598 
1599 			SendMessageToClient(&update);
1600 			break;
1601 		}
1602 
1603 		/* font messages */
1604 
1605 		case AS_SET_SYSTEM_FONT:
1606 		{
1607 			FTRACE(("ServerApp %s: AS_SET_SYSTEM_FONT\n", Signature()));
1608 			// gets:
1609 			//	1) string - font type ("plain", ...)
1610 			//	2) string - family
1611 			//	3) string - style
1612 			//	4) float - size
1613 
1614 			char type[B_OS_NAME_LENGTH];
1615 			font_family familyName;
1616 			font_style styleName;
1617 			float size;
1618 
1619 			if (link.ReadString(type, sizeof(type)) == B_OK
1620 				&& link.ReadString(familyName, sizeof(familyName)) == B_OK
1621 				&& link.ReadString(styleName, sizeof(styleName)) == B_OK
1622 				&& link.Read<float>(&size) == B_OK) {
1623 				gFontManager->Lock();
1624 
1625 				FontStyle* style
1626 					= gFontManager->GetStyle(familyName, styleName);
1627 				if (style != NULL) {
1628 					ServerFont font(*style, size);
1629 					gFontManager->Unlock();
1630 						// We must not have locked the font manager when
1631 						// locking the desktop (through LockedDesktopSettings
1632 						// below)
1633 
1634 					LockedDesktopSettings settings(fDesktop);
1635 
1636 					// TODO: Should we also update our internal copies now?
1637 					if (strcmp(type, "plain") == 0)
1638 						settings.SetDefaultPlainFont(font);
1639 					else if (strcmp(type, "bold") == 0)
1640 						settings.SetDefaultBoldFont(font);
1641 					else if (strcmp(type, "fixed") == 0)
1642 						settings.SetDefaultFixedFont(font);
1643 				} else
1644 					gFontManager->Unlock();
1645 			}
1646 			break;
1647 		}
1648 
1649 		case AS_GET_SYSTEM_DEFAULT_FONT:
1650 		{
1651 			// input:
1652 			//	1) string - font type ("plain", ...)
1653 
1654 			ServerFont font;
1655 
1656 			char type[B_OS_NAME_LENGTH];
1657 			status_t status = link.ReadString(type, sizeof(type));
1658 			if (status == B_OK) {
1659 				if (!strcmp(type, "plain")) {
1660 					font = *gFontManager->DefaultPlainFont();
1661 				} else if (!strcmp(type, "bold")) {
1662 					font = *gFontManager->DefaultBoldFont();
1663 				} else if (!strcmp(type, "fixed")) {
1664 					font = *gFontManager->DefaultFixedFont();
1665 				} else
1666 					status = B_BAD_VALUE;
1667 			}
1668 
1669 			if (status == B_OK) {
1670 				// returns:
1671 				//	1) string - family
1672 				//	2) string - style
1673 				//	3) float - size
1674 
1675 				fLink.StartMessage(B_OK);
1676 				fLink.AttachString(font.Family());
1677 				fLink.AttachString(font.Style());
1678 				fLink.Attach<float>(font.Size());
1679 			} else
1680 				fLink.StartMessage(status);
1681 
1682 			fLink.Flush();
1683 			break;
1684 		}
1685 
1686 		case AS_GET_SYSTEM_FONTS:
1687 		{
1688 			FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature()));
1689 			// Returns:
1690 			// 1) uint16 - family ID
1691 			// 2) uint16 - style ID
1692 			// 3) float - size in points
1693 			// 4) uint16 - face flags
1694 			// 5) uint32 - font flags
1695 
1696 			if (!fDesktop->LockSingleWindow()) {
1697 				fLink.StartMessage(B_OK);
1698 				fLink.Flush();
1699 				break;
1700 			}
1701 
1702 			// The client is requesting the system fonts, this
1703 			// could happend either at application start up, or
1704 			// because the client is resyncing with the global
1705 			// fonts. So we record the current system wide fonts
1706 			// into our own copies at this point.
1707 			DesktopSettings settings(fDesktop);
1708 
1709 			settings.GetDefaultPlainFont(fPlainFont);
1710 			settings.GetDefaultBoldFont(fBoldFont);
1711 			settings.GetDefaultFixedFont(fFixedFont);
1712 
1713 			fLink.StartMessage(B_OK);
1714 
1715 			for (int32 i = 0; i < 3; i++) {
1716 				ServerFont* font = NULL;
1717 				switch (i) {
1718 					case 0:
1719 						font = &fPlainFont;
1720 						fLink.AttachString("plain");
1721 						break;
1722 
1723 					case 1:
1724 						font = &fBoldFont;
1725 						fLink.AttachString("bold");
1726 						break;
1727 
1728 					case 2:
1729 						font = &fFixedFont;
1730 						fLink.AttachString("fixed");
1731 						break;
1732 				}
1733 
1734 				fLink.Attach<uint16>(font->FamilyID());
1735 				fLink.Attach<uint16>(font->StyleID());
1736 				fLink.Attach<float>(font->Size());
1737 				fLink.Attach<uint16>(font->Face());
1738 				fLink.Attach<uint32>(font->Flags());
1739 			}
1740 
1741 			fDesktop->UnlockSingleWindow();
1742 			fLink.Flush();
1743 			break;
1744 		}
1745 
1746 		case AS_GET_FONT_LIST_REVISION:
1747 		{
1748 			STRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature()));
1749 
1750 			fLink.StartMessage(B_OK);
1751 			fLink.Attach<int32>(
1752 				gFontManager->CheckRevision(fDesktop->UserID()));
1753 			fLink.Flush();
1754 			break;
1755 		}
1756 
1757 		case AS_GET_FAMILY_AND_STYLES:
1758 		{
1759 			FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature()));
1760 
1761 			// Attached Data:
1762 			// 1) int32 the index of the font family to get
1763 
1764 			// Returns:
1765 			// 1) string - name of family
1766 			// 2) uint32 - flags of font family (B_IS_FIXED || B_HAS_TUNED_FONT)
1767 			// 3) count of styles in that family
1768 			// For each style:
1769 			//		1) string - name of style
1770 			//		2) uint16 - face of style
1771 			//		3) uint32 - flags of style
1772 
1773 			int32 index;
1774 			link.Read<int32>(&index);
1775 
1776 			gFontManager->Lock();
1777 
1778 			FontFamily* family = gFontManager->FamilyAt(index);
1779 			if (family) {
1780 				fLink.StartMessage(B_OK);
1781 				fLink.AttachString(family->Name());
1782 				fLink.Attach<uint32>(family->Flags());
1783 
1784 				int32 count = family->CountStyles();
1785 				fLink.Attach<int32>(count);
1786 
1787 				for (int32 i = 0; i < count; i++) {
1788 					FontStyle* style = family->StyleAt(i);
1789 
1790 					fLink.AttachString(style->Name());
1791 					fLink.Attach<uint16>(style->Face());
1792 					fLink.Attach<uint32>(style->Flags());
1793 				}
1794 			} else
1795 				fLink.StartMessage(B_BAD_VALUE);
1796 
1797 			gFontManager->Unlock();
1798 			fLink.Flush();
1799 			break;
1800 		}
1801 
1802 		case AS_GET_FAMILY_AND_STYLE:
1803 		{
1804 			FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE\n", Signature()));
1805 
1806 			// Attached Data:
1807 			// 1) uint16 - family ID
1808 			// 2) uint16 - style ID
1809 
1810 			// Returns:
1811 			// 1) font_family The name of the font family
1812 			// 2) font_style - name of the style
1813 
1814 			uint16 familyID, styleID;
1815 			link.Read<uint16>(&familyID);
1816 			link.Read<uint16>(&styleID);
1817 
1818 			gFontManager->Lock();
1819 
1820 			FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID);
1821 			if (fontStyle != NULL) {
1822 				fLink.StartMessage(B_OK);
1823 				fLink.AttachString(fontStyle->Family()->Name());
1824 				fLink.AttachString(fontStyle->Name());
1825 			} else
1826 				fLink.StartMessage(B_BAD_VALUE);
1827 
1828 			fLink.Flush();
1829 			gFontManager->Unlock();
1830 			break;
1831 		}
1832 
1833 		case AS_GET_FAMILY_AND_STYLE_IDS:
1834 		{
1835 			FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLE_IDS\n",
1836 				Signature()));
1837 
1838 			// Attached Data:
1839 			// 1) font_family - name of font family to use
1840 			// 2) font_style - name of style in family
1841 			// 3) family ID - only used if 1) is empty
1842 			// 4) style ID - only used if 2) is empty
1843 			// 5) face - the font's current face
1844 
1845 			// Returns:
1846 			// 1) uint16 - family ID
1847 			// 2) uint16 - style ID
1848 			// 3) uint16 - face
1849 
1850 			font_family family;
1851 			font_style style;
1852 			uint16 familyID, styleID;
1853 			uint16 face;
1854 			if (link.ReadString(family, sizeof(font_family)) == B_OK
1855 				&& link.ReadString(style, sizeof(font_style)) == B_OK
1856 				&& link.Read<uint16>(&familyID) == B_OK
1857 				&& link.Read<uint16>(&styleID) == B_OK
1858 				&& link.Read<uint16>(&face) == B_OK) {
1859 				// get the font and return IDs and face
1860 				gFontManager->Lock();
1861 
1862 				FontStyle *fontStyle = gFontManager->GetStyle(family, style,
1863 					familyID, styleID, face);
1864 
1865 				if (fontStyle != NULL) {
1866 					fLink.StartMessage(B_OK);
1867 					fLink.Attach<uint16>(fontStyle->Family()->ID());
1868 					fLink.Attach<uint16>(fontStyle->ID());
1869 
1870 					// we try to keep the font face close to what we got
1871 					face = fontStyle->PreservedFace(face);
1872 
1873 					fLink.Attach<uint16>(face);
1874 				} else
1875 					fLink.StartMessage(B_NAME_NOT_FOUND);
1876 
1877 				gFontManager->Unlock();
1878 			} else
1879 				fLink.StartMessage(B_BAD_VALUE);
1880 
1881 			fLink.Flush();
1882 			break;
1883 		}
1884 
1885 		case AS_GET_FONT_FILE_FORMAT:
1886 		{
1887 			FTRACE(("ServerApp %s: AS_GET_FONT_FILE_FORMAT\n", Signature()));
1888 
1889 			// Attached Data:
1890 			// 1) uint16 - family ID
1891 			// 2) uint16 - style ID
1892 
1893 			// Returns:
1894 			// 1) uint16 font_file_format of font
1895 
1896 			int32 familyID, styleID;
1897 			link.Read<int32>(&familyID);
1898 			link.Read<int32>(&styleID);
1899 
1900 			gFontManager->Lock();
1901 
1902 			FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID);
1903 			if (fontStyle) {
1904 				fLink.StartMessage(B_OK);
1905 				fLink.Attach<uint16>((uint16)fontStyle->FileFormat());
1906 			} else
1907 				fLink.StartMessage(B_BAD_VALUE);
1908 
1909 			gFontManager->Unlock();
1910 			fLink.Flush();
1911 			break;
1912 		}
1913 
1914 		case AS_GET_STRING_WIDTHS:
1915 		{
1916 			FTRACE(("ServerApp %s: AS_GET_STRING_WIDTHS\n", Signature()));
1917 
1918 			// Attached Data:
1919 			// 1) uint16 ID of family
1920 			// 2) uint16 ID of style
1921 			// 3) float point size of font
1922 			// 4) uint8 spacing to use
1923 			// 5) int32 numStrings
1924 			// 6) int32 string length to measure (numStrings times)
1925 			// 7) string String to measure (numStrings times)
1926 
1927 			// Returns:
1928 			// 1) float - width of the string in pixels (numStrings times)
1929 
1930 			uint16 family, style;
1931 			float size;
1932 			uint8 spacing;
1933 
1934 			link.Read<uint16>(&family);
1935 			link.Read<uint16>(&style);
1936 			link.Read<float>(&size);
1937 			link.Read<uint8>(&spacing);
1938 			int32 numStrings;
1939 			if (link.Read<int32>(&numStrings) != B_OK) {
1940 				// this results in a B_BAD_VALUE return
1941 				numStrings = 0;
1942 				size = 0.0f;
1943 			}
1944 
1945 			BStackOrHeapArray<float, 64> widthArray(numStrings);
1946 			BStackOrHeapArray<int32, 64> lengthArray(numStrings);
1947 			BStackOrHeapArray<char*, 64> stringArray(numStrings);
1948 			if (!widthArray.IsValid() || !lengthArray.IsValid()
1949 				|| !stringArray.IsValid()) {
1950 				fLink.StartMessage(B_NO_MEMORY);
1951 				fLink.Flush();
1952 				break;
1953 			}
1954 
1955 			for (int32 i = 0; i < numStrings; i++) {
1956 				// This version of ReadString allocates the strings, we free
1957 				// them below
1958 				link.ReadString(&stringArray[i], (size_t *)&lengthArray[i]);
1959 			}
1960 
1961 			ServerFont font;
1962 
1963 			if (font.SetFamilyAndStyle(family, style) == B_OK && size > 0) {
1964 				font.SetSize(size);
1965 				font.SetSpacing(spacing);
1966 
1967 				for (int32 i = 0; i < numStrings; i++) {
1968 					if (!stringArray[i] || lengthArray[i] <= 0)
1969 						widthArray[i] = 0.0;
1970 					else {
1971 						widthArray[i] = font.StringWidth(stringArray[i],
1972 							lengthArray[i]);
1973 					}
1974 				}
1975 
1976 				fLink.StartMessage(B_OK);
1977 				fLink.Attach(widthArray, numStrings * sizeof(float));
1978 			} else
1979 				fLink.StartMessage(B_BAD_VALUE);
1980 
1981 			fLink.Flush();
1982 
1983 			for (int32 i = 0; i < numStrings; i++)
1984 				free(stringArray[i]);
1985 			break;
1986 		}
1987 
1988 		case AS_GET_FONT_BOUNDING_BOX:
1989 		{
1990 			FTRACE(("ServerApp %s: AS_GET_BOUNDING_BOX unimplemented\n",
1991 				Signature()));
1992 
1993 			// Attached Data:
1994 			// 1) uint16 - family ID
1995 			// 2) uint16 - style ID
1996 
1997 			// Returns:
1998 			// 1) BRect - box holding entire font
1999 
2000 			// ToDo: implement me!
2001 			fLink.StartMessage(B_ERROR);
2002 			fLink.Flush();
2003 			break;
2004 		}
2005 
2006 		case AS_GET_TUNED_COUNT:
2007 		{
2008 			FTRACE(("ServerApp %s: AS_GET_TUNED_COUNT\n", Signature()));
2009 
2010 			// Attached Data:
2011 			// 1) uint16 - family ID
2012 			// 2) uint16 - style ID
2013 
2014 			// Returns:
2015 			// 1) int32 - number of font strikes available
2016 
2017 			uint16 familyID, styleID;
2018 			link.Read<uint16>(&familyID);
2019 			link.Read<uint16>(&styleID);
2020 
2021 			gFontManager->Lock();
2022 
2023 			FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID);
2024 			if (fontStyle != NULL) {
2025 				fLink.StartMessage(B_OK);
2026 				fLink.Attach<int32>(fontStyle->TunedCount());
2027 			} else
2028 				fLink.StartMessage(B_BAD_VALUE);
2029 
2030 			gFontManager->Unlock();
2031 			fLink.Flush();
2032 			break;
2033 		}
2034 
2035 		case AS_GET_TUNED_INFO:
2036 		{
2037 			FTRACE(("ServerApp %s: AS_GET_TUNED_INFO unimplmemented\n",
2038 				Signature()));
2039 
2040 			// Attached Data:
2041 			// 1) uint16 - family ID
2042 			// 2) uint16 - style ID
2043 			// 3) uint32 - index of the particular font strike
2044 
2045 			// Returns:
2046 			// 1) tuned_font_info - info on the strike specified
2047 			// ToDo: implement me!
2048 
2049 			fLink.StartMessage(B_ERROR);
2050 			fLink.Flush();
2051 			break;
2052 		}
2053 
2054 		case AS_GET_EXTRA_FONT_FLAGS:
2055 		{
2056 			FTRACE(("ServerApp %s: AS_GET_EXTRA_FONT_FLAGS\n",
2057 				Signature()));
2058 
2059 			// Attached Data:
2060 			// 1) uint16 - family ID
2061 			// 2) uint16 - style ID
2062 
2063 			// Returns:
2064 			// 1) uint32 - extra font flags
2065 
2066 			uint16 familyID, styleID;
2067 			link.Read<uint16>(&familyID);
2068 			link.Read<uint16>(&styleID);
2069 
2070 			gFontManager->Lock();
2071 
2072 			FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID);
2073 			if (fontStyle != NULL) {
2074 				fLink.StartMessage(B_OK);
2075 				fLink.Attach<uint32>(fontStyle->Flags());
2076 			} else
2077 				fLink.StartMessage(B_BAD_VALUE);
2078 
2079 			gFontManager->Unlock();
2080 			fLink.Flush();
2081 			break;
2082 		}
2083 
2084 		case AS_GET_FONT_HEIGHT:
2085 		{
2086 			FTRACE(("ServerApp %s: AS_GET_FONT_HEIGHT\n", Signature()));
2087 
2088 			// Attached Data:
2089 			// 1) uint16 family ID
2090 			// 2) uint16 style ID
2091 			// 3) float size
2092 
2093 			uint16 familyID, styleID;
2094 			float size;
2095 			link.Read<uint16>(&familyID);
2096 			link.Read<uint16>(&styleID);
2097 			link.Read<float>(&size);
2098 
2099 			gFontManager->Lock();
2100 
2101 			FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID);
2102 			if (fontStyle != NULL) {
2103 				font_height height;
2104 				fontStyle->GetHeight(size, height);
2105 
2106 				fLink.StartMessage(B_OK);
2107 				fLink.Attach<font_height>(height);
2108 			} else
2109 				fLink.StartMessage(B_BAD_VALUE);
2110 
2111 			gFontManager->Unlock();
2112 			fLink.Flush();
2113 			break;
2114 		}
2115 
2116 		case AS_GET_UNICODE_BLOCKS:
2117 		{
2118 			FTRACE(("ServerApp %s: AS_GET_UNICODE_BLOCKS\n", Signature()));
2119 
2120 			// Attached Data:
2121 			// 1) uint16 family ID
2122 			// 2) uint16 style ID
2123 
2124 			// Returns:
2125 			// 1) unicode_block - bitfield of Unicode blocks in font
2126 
2127 			uint16 familyID, styleID;
2128 			link.Read<uint16>(&familyID);
2129 			link.Read<uint16>(&styleID);
2130 
2131 			ServerFont font;
2132 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2133 			if (status == B_OK) {
2134 				unicode_block blocksForFont;
2135 				font.GetUnicodeBlocks(blocksForFont);
2136 
2137 				fLink.StartMessage(B_OK);
2138 				fLink.Attach<unicode_block>(blocksForFont);
2139 			} else
2140 				fLink.StartMessage(status);
2141 
2142 			fLink.Flush();
2143 			break;
2144 		}
2145 
2146 		case AS_GET_HAS_UNICODE_BLOCK:
2147 		{
2148 			FTRACE(("ServerApp %s: AS_INCLUDES_UNICODE_BLOCK\n", Signature()));
2149 
2150 			// Attached Data:
2151 			// 1) uint16 family ID
2152 			// 2) uint16 style ID
2153 			// 3) uint32 start of unicode block
2154 			// 4) uint32 end of unicode block
2155 
2156 			// Returns:
2157 			// 1) bool - whether or not font includes specified block range
2158 
2159 			uint16 familyID, styleID;
2160 			uint32 start, end;
2161 			link.Read<uint16>(&familyID);
2162 			link.Read<uint16>(&styleID);
2163 			link.Read<uint32>(&start);
2164 			link.Read<uint32>(&end);
2165 
2166 			ServerFont font;
2167 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2168 			if (status == B_OK) {
2169 				bool hasBlock;
2170 
2171 				status = font.IncludesUnicodeBlock(start, end, hasBlock);
2172 				fLink.StartMessage(status);
2173 				fLink.Attach<bool>(hasBlock);
2174 			} else
2175 				fLink.StartMessage(status);
2176 
2177 			fLink.Flush();
2178 			break;
2179 		}
2180 
2181 		case AS_GET_GLYPH_SHAPES:
2182 		{
2183 			FTRACE(("ServerApp %s: AS_GET_GLYPH_SHAPES\n", Signature()));
2184 
2185 			// Attached Data:
2186 			// 1) uint16 - family ID
2187 			// 2) uint16 - style ID
2188 			// 3) float - point size
2189 			// 4) float - shear
2190 			// 5) float - rotation
2191 			// 6) float - false bold width
2192 			// 6) uint32 - flags
2193 			// 7) int32 - numChars
2194 			// 8) int32 - numBytes
2195 			// 8) char - chars (numBytes times)
2196 
2197 			// Returns:
2198 			// 1) BShape - glyph shape
2199 			// numChars times
2200 
2201 			uint16 familyID, styleID;
2202 			uint32 flags;
2203 			float size, shear, rotation, falseBoldWidth;
2204 
2205 			link.Read<uint16>(&familyID);
2206 			link.Read<uint16>(&styleID);
2207 			link.Read<float>(&size);
2208 			link.Read<float>(&shear);
2209 			link.Read<float>(&rotation);
2210 			link.Read<float>(&falseBoldWidth);
2211 			link.Read<uint32>(&flags);
2212 
2213 			int32 numChars, numBytes;
2214 			link.Read<int32>(&numChars);
2215 			link.Read<int32>(&numBytes);
2216 
2217 			BStackOrHeapArray<char, 256> charArray(numBytes);
2218 			BStackOrHeapArray<BShape*, 64> shapes(numChars);
2219 			if (!charArray.IsValid() || !shapes.IsValid()) {
2220 				fLink.StartMessage(B_NO_MEMORY);
2221 				fLink.Flush();
2222 				break;
2223 			}
2224 
2225 			link.Read(charArray, numBytes);
2226 
2227 			ServerFont font;
2228 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2229 			if (status == B_OK) {
2230 				font.SetSize(size);
2231 				font.SetShear(shear);
2232 				font.SetRotation(rotation);
2233 				font.SetFalseBoldWidth(falseBoldWidth);
2234 				font.SetFlags(flags);
2235 
2236 				status = font.GetGlyphShapes(charArray, numChars, shapes);
2237 				if (status == B_OK) {
2238 					fLink.StartMessage(B_OK);
2239 					for (int32 i = 0; i < numChars; i++) {
2240 						fLink.AttachShape(*shapes[i]);
2241 						delete shapes[i];
2242 					}
2243 				}
2244 			}
2245 
2246 			if (status != B_OK)
2247 				fLink.StartMessage(status);
2248 
2249 			fLink.Flush();
2250 			break;
2251 		}
2252 
2253 		case AS_GET_HAS_GLYPHS:
2254 		{
2255 			FTRACE(("ServerApp %s: AS_GET_HAS_GLYPHS\n", Signature()));
2256 
2257 			// Attached Data:
2258 			// 1) uint16 - family ID
2259 			// 2) uint16 - style ID
2260 			// 3) int32 - numChars
2261 			// 4) int32 - numBytes
2262 			// 5) char - the char buffer with size numBytes
2263 
2264 			uint16 familyID, styleID;
2265 			link.Read<uint16>(&familyID);
2266 			link.Read<uint16>(&styleID);
2267 
2268 			int32 numChars, numBytes;
2269 			link.Read<int32>(&numChars);
2270 			link.Read<int32>(&numBytes);
2271 
2272 			BStackOrHeapArray<char, 256> charArray(numBytes);
2273 			BStackOrHeapArray<bool, 256> hasArray(numChars);
2274 			if (!charArray.IsValid() || !hasArray.IsValid()) {
2275 				fLink.StartMessage(B_NO_MEMORY);
2276 				fLink.Flush();
2277 				break;
2278 			}
2279 
2280 			link.Read(charArray, numBytes);
2281 
2282 			ServerFont font;
2283 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2284 			if (status == B_OK) {
2285 				status = font.GetHasGlyphs(charArray, numBytes, numChars,
2286 					hasArray);
2287 				if (status == B_OK) {
2288 					fLink.StartMessage(B_OK);
2289 					fLink.Attach(hasArray, numChars * sizeof(bool));
2290 				}
2291 			}
2292 
2293 			if (status != B_OK)
2294 				fLink.StartMessage(status);
2295 
2296 			fLink.Flush();
2297 			break;
2298 		}
2299 
2300 		case AS_GET_EDGES:
2301 		{
2302 			FTRACE(("ServerApp %s: AS_GET_EDGES\n", Signature()));
2303 
2304 			// Attached Data:
2305 			// 1) uint16 - family ID
2306 			// 2) uint16 - style ID
2307 			// 3) int32 - numChars
2308 			// 4) int32 - numBytes
2309 			// 5) char - the char buffer with size numBytes
2310 
2311 			uint16 familyID, styleID;
2312 			link.Read<uint16>(&familyID);
2313 			link.Read<uint16>(&styleID);
2314 
2315 			int32 numChars;
2316 			link.Read<int32>(&numChars);
2317 
2318 			uint32 numBytes;
2319 			link.Read<uint32>(&numBytes);
2320 
2321 			BStackOrHeapArray<char, 256> charArray(numBytes);
2322 			BStackOrHeapArray<edge_info, 64> edgeArray(numChars);
2323 			if (!charArray.IsValid() || !edgeArray.IsValid()) {
2324 				fLink.StartMessage(B_NO_MEMORY);
2325 				fLink.Flush();
2326 				break;
2327 			}
2328 
2329 			link.Read(charArray, numBytes);
2330 
2331 			ServerFont font;
2332 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2333 			if (status == B_OK) {
2334 				status = font.GetEdges(charArray, numBytes, numChars,
2335 					edgeArray);
2336 				if (status == B_OK) {
2337 					fLink.StartMessage(B_OK);
2338 					fLink.Attach(edgeArray, numChars * sizeof(edge_info));
2339 				}
2340 			}
2341 
2342 			if (status != B_OK)
2343 				fLink.StartMessage(status);
2344 
2345 			fLink.Flush();
2346 			break;
2347 		}
2348 
2349 		case AS_GET_ESCAPEMENTS:
2350 		{
2351 			FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS\n", Signature()));
2352 
2353 			// Attached Data:
2354 			// 1) uint16 - family ID
2355 			// 2) uint16 - style ID
2356 			// 3) float - point size
2357 			// 4) uint8 - spacing
2358 			// 5) float - rotation
2359 			// 6) uint32 - flags
2360 			// 7) int32 - numChars
2361 			// 8) char - char     -\       both
2362 			// 9) BPoint - offset -/ (numChars times)
2363 
2364 			// Returns:
2365 			// 1) BPoint - escapement
2366 			// numChars times
2367 
2368 			uint16 familyID, styleID;
2369 			uint32 flags;
2370 			float size, rotation;
2371 			uint8 spacing;
2372 
2373 			link.Read<uint16>(&familyID);
2374 			link.Read<uint16>(&styleID);
2375 			link.Read<float>(&size);
2376 			link.Read<uint8>(&spacing);
2377 			link.Read<float>(&rotation);
2378 			link.Read<uint32>(&flags);
2379 
2380 			escapement_delta delta;
2381 			link.Read<float>(&delta.nonspace);
2382 			link.Read<float>(&delta.space);
2383 
2384 			bool wantsOffsets;
2385 			link.Read<bool>(&wantsOffsets);
2386 
2387 			int32 numChars;
2388 			link.Read<int32>(&numChars);
2389 
2390 			uint32 numBytes;
2391 			link.Read<uint32>(&numBytes);
2392 
2393 			BStackOrHeapArray<char, 256> charArray(numBytes);
2394 			BStackOrHeapArray<BPoint, 64> escapements(numChars);
2395 			BPoint* offsets = NULL;
2396 			if (wantsOffsets)
2397 				offsets = new(std::nothrow) BPoint[numChars];
2398 
2399 			if (!charArray.IsValid() || !escapements.IsValid()
2400 				|| (offsets == NULL && wantsOffsets)) {
2401 				delete[] offsets;
2402 				fLink.StartMessage(B_NO_MEMORY);
2403 				fLink.Flush();
2404 				break;
2405 			}
2406 
2407 			link.Read(charArray, numBytes);
2408 
2409 			ServerFont font;
2410 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2411 			if (status == B_OK) {
2412 				font.SetSize(size);
2413 				font.SetSpacing(spacing);
2414 				font.SetRotation(rotation);
2415 				font.SetFlags(flags);
2416 
2417 				status = font.GetEscapements(charArray, numBytes, numChars,
2418 					delta, escapements, offsets);
2419 
2420 				if (status == B_OK) {
2421 					fLink.StartMessage(B_OK);
2422 					for (int32 i = 0; i < numChars; i++)
2423 						fLink.Attach<BPoint>(escapements[i]);
2424 
2425 					if (wantsOffsets) {
2426 						for (int32 i = 0; i < numChars; i++)
2427 							fLink.Attach<BPoint>(offsets[i]);
2428 					}
2429 				}
2430 			}
2431 
2432 			if (status != B_OK)
2433 				fLink.StartMessage(status);
2434 
2435 			delete[] offsets;
2436 			fLink.Flush();
2437 			break;
2438 		}
2439 
2440 		case AS_GET_ESCAPEMENTS_AS_FLOATS:
2441 		{
2442 			FTRACE(("ServerApp %s: AS_GET_ESCAPEMENTS_AS_FLOATS\n", Signature()));
2443 
2444 			// Attached Data:
2445 			// 1) uint16 - family ID
2446 			// 2) uint16 - style ID
2447 			// 3) float - point size
2448 			// 4) uint8 - spacing
2449 			// 5) float - rotation
2450 			// 6) uint32 - flags
2451 			// 7) float - additional "nonspace" delta
2452 			// 8) float - additional "space" delta
2453 			// 9) int32 - numChars
2454 			// 10) int32 - numBytes
2455 			// 11) char - the char buffer with size numBytes
2456 
2457 			// Returns:
2458 			// 1) float - escapement buffer with numChar entries
2459 
2460 			uint16 familyID, styleID;
2461 			uint32 flags;
2462 			float size, rotation;
2463 			uint8 spacing;
2464 
2465 			link.Read<uint16>(&familyID);
2466 			link.Read<uint16>(&styleID);
2467 			link.Read<float>(&size);
2468 			link.Read<uint8>(&spacing);
2469 			link.Read<float>(&rotation);
2470 			link.Read<uint32>(&flags);
2471 
2472 			escapement_delta delta;
2473 			link.Read<float>(&delta.nonspace);
2474 			link.Read<float>(&delta.space);
2475 
2476 			int32 numChars;
2477 			link.Read<int32>(&numChars);
2478 
2479 			uint32 numBytes;
2480 			link.Read<uint32>(&numBytes);
2481 
2482 			BStackOrHeapArray<char, 256> charArray(numBytes);
2483 			BStackOrHeapArray<float, 64> escapements(numChars);
2484 			if (!charArray.IsValid() || !escapements.IsValid()) {
2485 				fLink.StartMessage(B_NO_MEMORY);
2486 				fLink.Flush();
2487 				break;
2488 			}
2489 
2490 			link.Read(charArray, numBytes);
2491 
2492 			// figure out escapements
2493 
2494 			ServerFont font;
2495 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2496 			if (status == B_OK) {
2497 				font.SetSize(size);
2498 				font.SetSpacing(spacing);
2499 				font.SetRotation(rotation);
2500 				font.SetFlags(flags);
2501 
2502 				status = font.GetEscapements(charArray, numBytes, numChars,
2503 					delta, escapements);
2504 
2505 				if (status == B_OK) {
2506 					fLink.StartMessage(B_OK);
2507 					fLink.Attach(escapements, numChars * sizeof(float));
2508 				}
2509 			}
2510 
2511 			if (status != B_OK)
2512 				fLink.StartMessage(status);
2513 
2514 			fLink.Flush();
2515 			break;
2516 		}
2517 
2518 		case AS_GET_BOUNDINGBOXES_CHARS:
2519 		case AS_GET_BOUNDINGBOXES_STRING:
2520 		{
2521 			FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_CHARS\n", Signature()));
2522 
2523 			// Attached Data:
2524 			// 1) uint16 - family ID
2525 			// 2) uint16 - style ID
2526 			// 3) float - point size
2527 			// 4) float - rotation
2528 			// 5) float - shear
2529 			// 6) float - false bold width
2530 			// 7) uint8 - spacing
2531 			// 8) uint32 - flags
2532 			// 9) font_metric_mode - mode
2533 			// 10) bool - string escapement
2534 			// 11) escapement_delta - additional delta
2535 			// 12) int32 - numChars
2536 			// 13) int32 - numBytes
2537 			// 14) char - the char buffer with size numBytes
2538 
2539 			// Returns:
2540 			// 1) BRect - rects with numChar entries
2541 
2542 			uint16 familyID, styleID;
2543 			uint32 flags;
2544 			float size, rotation, shear, falseBoldWidth;
2545 			uint8 spacing;
2546 			font_metric_mode mode;
2547 			bool stringEscapement;
2548 
2549 			link.Read<uint16>(&familyID);
2550 			link.Read<uint16>(&styleID);
2551 			link.Read<float>(&size);
2552 			link.Read<float>(&rotation);
2553 			link.Read<float>(&shear);
2554 			link.Read<float>(&falseBoldWidth);
2555 			link.Read<uint8>(&spacing);
2556 			link.Read<uint32>(&flags);
2557 			link.Read<font_metric_mode>(&mode);
2558 			link.Read<bool>(&stringEscapement);
2559 
2560 			escapement_delta delta;
2561 			link.Read<escapement_delta>(&delta);
2562 
2563 			int32 numChars;
2564 			link.Read<int32>(&numChars);
2565 
2566 			uint32 numBytes;
2567 			link.Read<uint32>(&numBytes);
2568 
2569 			BStackOrHeapArray<char, 256> charArray(numBytes);
2570 			BStackOrHeapArray<BRect, 64> rectArray(numChars);
2571 			if (!charArray.IsValid() || !rectArray.IsValid()) {
2572 				fLink.StartMessage(B_NO_MEMORY);
2573 				fLink.Flush();
2574 				break;
2575 			}
2576 
2577 			link.Read(charArray, numBytes);
2578 
2579 			// figure out escapements
2580 
2581 			ServerFont font;
2582 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2583 			if (status == B_OK) {
2584 				font.SetSize(size);
2585 				font.SetRotation(rotation);
2586 				font.SetShear(shear);
2587 				font.SetFalseBoldWidth(falseBoldWidth);
2588 				font.SetSpacing(spacing);
2589 				font.SetFlags(flags);
2590 
2591 				// TODO: implement for real
2592 				status = font.GetBoundingBoxes(charArray, numBytes,
2593 					numChars, rectArray, stringEscapement, mode, delta,
2594 					code == AS_GET_BOUNDINGBOXES_STRING);
2595 				if (status == B_OK) {
2596 					fLink.StartMessage(B_OK);
2597 					for (int32 i = 0; i < numChars; i++)
2598 						fLink.Attach<BRect>(rectArray[i]);
2599 				}
2600 			}
2601 
2602 			if (status != B_OK)
2603 				fLink.StartMessage(status);
2604 
2605 			fLink.Flush();
2606 			break;
2607 		}
2608 
2609 		case AS_GET_BOUNDINGBOXES_STRINGS:
2610 		{
2611 			FTRACE(("ServerApp %s: AS_GET_BOUNDINGBOXES_STRINGS\n",
2612 				Signature()));
2613 
2614 			// Attached Data:
2615 			// 1) uint16 - family ID
2616 			// 2) uint16 - style ID
2617 			// 3) float - point size
2618 			// 4) float - rotation
2619 			// 5) float - shear
2620 			// 6) float - false bold width
2621 			// 7) uint8 - spacing
2622 			// 8) uint32 - flags
2623 			// 9) font_metric_mode - mode
2624 			// 10) int32 numStrings
2625 			// 11) escapement_delta - additional delta (numStrings times)
2626 			// 12) int32 string length to measure (numStrings times)
2627 			// 13) string - string (numStrings times)
2628 
2629 			// Returns:
2630 			// 1) BRect - rects with numStrings entries
2631 
2632 			uint16 familyID, styleID;
2633 			uint32 flags;
2634 			float ptsize, rotation, shear, falseBoldWidth;
2635 			uint8 spacing;
2636 			font_metric_mode mode;
2637 
2638 			link.Read<uint16>(&familyID);
2639 			link.Read<uint16>(&styleID);
2640 			link.Read<float>(&ptsize);
2641 			link.Read<float>(&rotation);
2642 			link.Read<float>(&shear);
2643 			link.Read<float>(&falseBoldWidth);
2644 			link.Read<uint8>(&spacing);
2645 			link.Read<uint32>(&flags);
2646 			link.Read<font_metric_mode>(&mode);
2647 
2648 			int32 numStrings;
2649 			link.Read<int32>(&numStrings);
2650 
2651 			BStackOrHeapArray<escapement_delta, 64> deltaArray(numStrings);
2652 			BStackOrHeapArray<char*, 64> stringArray(numStrings);
2653 			BStackOrHeapArray<size_t, 64> lengthArray(numStrings);
2654 			BStackOrHeapArray<BRect, 64> rectArray(numStrings);
2655 			if (!deltaArray.IsValid() || !stringArray.IsValid()
2656 				|| !lengthArray.IsValid() || !rectArray.IsValid()) {
2657 				fLink.StartMessage(B_NO_MEMORY);
2658 				fLink.Flush();
2659 				break;
2660 			}
2661 
2662 			for (int32 i = 0; i < numStrings; i++) {
2663 				// This version of ReadString allocates the strings, we free
2664 				// them below
2665 				link.ReadString(&stringArray[i], &lengthArray[i]);
2666 				link.Read<escapement_delta>(&deltaArray[i]);
2667 			}
2668 
2669 			ServerFont font;
2670 			status_t status = font.SetFamilyAndStyle(familyID, styleID);
2671 			if (status == B_OK) {
2672 				font.SetSize(ptsize);
2673 				font.SetRotation(rotation);
2674 				font.SetShear(shear);
2675 				font.SetFalseBoldWidth(falseBoldWidth);
2676 				font.SetSpacing(spacing);
2677 				font.SetFlags(flags);
2678 
2679 				status = font.GetBoundingBoxesForStrings(stringArray,
2680 					lengthArray, numStrings, rectArray, mode, deltaArray);
2681 				if (status == B_OK) {
2682 					fLink.StartMessage(B_OK);
2683 					fLink.Attach(rectArray, numStrings * sizeof(BRect));
2684 				}
2685 			}
2686 
2687 			for (int32 i = 0; i < numStrings; i++)
2688 				free(stringArray[i]);
2689 
2690 			if (status != B_OK)
2691 				fLink.StartMessage(status);
2692 
2693 			fLink.Flush();
2694 			break;
2695 		}
2696 
2697 		// Screen commands
2698 
2699 		case AS_VALID_SCREEN_ID:
2700 		{
2701 			// Attached data
2702 			// 1) int32 screen
2703 
2704 			int32 id;
2705 			if (link.Read<int32>(&id) == B_OK
2706 				&& id == B_MAIN_SCREEN_ID.id)
2707 				fLink.StartMessage(B_OK);
2708 			else
2709 				fLink.StartMessage(B_ERROR);
2710 
2711 			fLink.Flush();
2712 			break;
2713 		}
2714 
2715 		case AS_GET_NEXT_SCREEN_ID:
2716 		{
2717 			// Attached data
2718 			// 1) int32 screen
2719 
2720 			int32 id;
2721 			link.Read<int32>(&id);
2722 
2723 			// TODO: for now, just say we're the last one
2724 			fLink.StartMessage(B_ENTRY_NOT_FOUND);
2725 			fLink.Flush();
2726 			break;
2727 		}
2728 
2729 		case AS_GET_SCREEN_ID_FROM_WINDOW:
2730 		{
2731 			status_t status = B_BAD_VALUE;
2732 
2733 			// Attached data
2734 			// 1) int32 - window client token
2735 
2736 			int32 clientToken;
2737 			if (link.Read<int32>(&clientToken) != B_OK)
2738 				status = B_BAD_DATA;
2739 			else {
2740 				BAutolock locker(fWindowListLock);
2741 
2742 				for (int32 i = fWindowList.CountItems(); i-- > 0;) {
2743 					ServerWindow* serverWindow = fWindowList.ItemAt(i);
2744 
2745 					if (serverWindow->ClientToken() == clientToken) {
2746 						AutoReadLocker _(fDesktop->ScreenLocker());
2747 
2748 						// found it!
2749 						Window* window = serverWindow->Window();
2750 						const Screen* screen = NULL;
2751 						if (window != NULL)
2752 							screen = window->Screen();
2753 
2754 						if (screen == NULL) {
2755 							// The window hasn't been added to the desktop yet,
2756 							// or it's an offscreen window
2757 							break;
2758 						}
2759 
2760 						fLink.StartMessage(B_OK);
2761 						fLink.Attach<int32>(screen->ID());
2762 						status = B_OK;
2763 						break;
2764 					}
2765 				}
2766 			}
2767 
2768 			if (status != B_OK)
2769 				fLink.StartMessage(status);
2770 			fLink.Flush();
2771 			break;
2772 		}
2773 
2774 		case AS_SCREEN_GET_MODE:
2775 		{
2776 			STRACE(("ServerApp %s: AS_SCREEN_GET_MODE\n", Signature()));
2777 
2778 			// Attached data
2779 			// 1) int32 screen
2780 			// 2) uint32 workspace index
2781 
2782 			int32 id;
2783 			link.Read<int32>(&id);
2784 			uint32 workspace;
2785 			link.Read<uint32>(&workspace);
2786 
2787 			display_mode mode;
2788 			status_t status = fDesktop->GetScreenMode(workspace, id, mode);
2789 
2790 			fLink.StartMessage(status);
2791 			if (status == B_OK)
2792 				fLink.Attach<display_mode>(mode);
2793 			fLink.Flush();
2794 			break;
2795 		}
2796 
2797 		case AS_SCREEN_SET_MODE:
2798 		{
2799 			STRACE(("ServerApp %s: AS_SCREEN_SET_MODE\n", Signature()));
2800 
2801 			// Attached data
2802 			// 1) int32 screen
2803 			// 2) workspace index
2804 			// 3) display_mode to set
2805 			// 4) 'makeDefault' boolean
2806 
2807 			int32 id;
2808 			link.Read<int32>(&id);
2809 			uint32 workspace;
2810 			link.Read<uint32>(&workspace);
2811 
2812 			display_mode mode;
2813 			link.Read<display_mode>(&mode);
2814 
2815 			bool makeDefault = false;
2816 			status_t status = link.Read<bool>(&makeDefault);
2817 
2818 			if (status == B_OK) {
2819 				status = fDesktop->SetScreenMode(workspace, id, mode,
2820 					makeDefault);
2821 			}
2822 			if (status == B_OK) {
2823 				if (workspace == (uint32)B_CURRENT_WORKSPACE_INDEX
2824 					&& fDesktop->LockSingleWindow()) {
2825 					workspace = fDesktop->CurrentWorkspace();
2826 					fDesktop->UnlockSingleWindow();
2827 				}
2828 
2829 				if (!makeDefault) {
2830 					// Memorize the screen change, so that it can be reverted
2831 					// later
2832 					fTemporaryDisplayModeChange |= 1 << workspace;
2833 				} else
2834 					fTemporaryDisplayModeChange &= ~(1 << workspace);
2835 			}
2836 
2837 			fLink.StartMessage(status);
2838 			fLink.Flush();
2839 			break;
2840 		}
2841 
2842 		case AS_PROPOSE_MODE:
2843 		{
2844 			STRACE(("ServerApp %s: AS_PROPOSE_MODE\n", Signature()));
2845 			int32 id;
2846 			link.Read<int32>(&id);
2847 
2848 			display_mode target, low, high;
2849 			link.Read<display_mode>(&target);
2850 			link.Read<display_mode>(&low);
2851 			link.Read<display_mode>(&high);
2852 			status_t status = fDesktop->HWInterface()->ProposeMode(&target,
2853 				&low, &high);
2854 
2855 			// ProposeMode() returns B_BAD_VALUE to hint that the candidate is
2856 			// not within the given limits (but is supported)
2857 			if (status == B_OK || status == B_BAD_VALUE) {
2858 				fLink.StartMessage(B_OK);
2859 				fLink.Attach<display_mode>(target);
2860 				fLink.Attach<bool>(status == B_OK);
2861 			} else
2862 				fLink.StartMessage(status);
2863 
2864 			fLink.Flush();
2865 			break;
2866 		}
2867 
2868 		case AS_GET_MODE_LIST:
2869 		{
2870 			int32 id;
2871 			link.Read<int32>(&id);
2872 			// TODO: use this screen id
2873 
2874 			display_mode* modeList;
2875 			uint32 count;
2876 			status_t status = fDesktop->HWInterface()->GetModeList(&modeList,
2877 				&count);
2878 			if (status == B_OK) {
2879 				fLink.StartMessage(B_OK);
2880 				fLink.Attach<uint32>(count);
2881 				fLink.Attach(modeList, sizeof(display_mode) * count);
2882 
2883 				delete[] modeList;
2884 			} else
2885 				fLink.StartMessage(status);
2886 
2887 			fLink.Flush();
2888 			break;
2889 		}
2890 
2891 		case AS_GET_SCREEN_FRAME:
2892 		{
2893 			STRACE(("ServerApp %s: AS_GET_SCREEN_FRAME\n", Signature()));
2894 
2895 			// Attached data
2896 			// 1) int32 screen
2897 			// 2) uint32 workspace index
2898 
2899 			int32 id;
2900 			link.Read<int32>(&id);
2901 			uint32 workspace;
2902 			link.Read<uint32>(&workspace);
2903 
2904 			BRect frame;
2905 			status_t status = fDesktop->GetScreenFrame(workspace, id, frame);
2906 
2907 			fLink.StartMessage(status);
2908 			if (status == B_OK)
2909 				fLink.Attach<BRect>(frame);
2910 
2911 			fLink.Flush();
2912 			break;
2913 		}
2914 
2915 		case AS_SCREEN_GET_COLORMAP:
2916 		{
2917 			STRACE(("ServerApp %s: AS_SCREEN_GET_COLORMAP\n", Signature()));
2918 
2919 			int32 id;
2920 			link.Read<int32>(&id);
2921 
2922 			const color_map* colorMap = SystemColorMap();
2923 			if (colorMap != NULL) {
2924 				fLink.StartMessage(B_OK);
2925 				fLink.Attach<color_map>(*colorMap);
2926 			} else
2927 				fLink.StartMessage(B_ERROR);
2928 
2929 			fLink.Flush();
2930 			break;
2931 		}
2932 
2933 		case AS_GET_DESKTOP_COLOR:
2934 		{
2935 			STRACE(("ServerApp %s: get desktop color\n", Signature()));
2936 
2937 			uint32 index;
2938 			link.Read<uint32>(&index);
2939 
2940 			fLink.StartMessage(B_OK);
2941 			fDesktop->LockSingleWindow();
2942 
2943 			// we're nice to our children (and also take the default case
2944 			// into account which asks for the current workspace)
2945 			if (index >= (uint32)kMaxWorkspaces)
2946 				index = fDesktop->CurrentWorkspace();
2947 
2948 			Workspace workspace(*fDesktop, index, true);
2949 			fLink.Attach<rgb_color>(workspace.Color());
2950 
2951 			fDesktop->UnlockSingleWindow();
2952 			fLink.Flush();
2953 			break;
2954 		}
2955 
2956 		case AS_SET_DESKTOP_COLOR:
2957 		{
2958 			STRACE(("ServerApp %s: set desktop color\n", Signature()));
2959 
2960 			rgb_color color;
2961 			uint32 index;
2962 			bool makeDefault;
2963 
2964 			link.Read<rgb_color>(&color);
2965 			link.Read<uint32>(&index);
2966 			if (link.Read<bool>(&makeDefault) != B_OK)
2967 				break;
2968 
2969 			fDesktop->LockAllWindows();
2970 
2971 			// we're nice to our children (and also take the default case
2972 			// into account which asks for the current workspace)
2973 			if (index >= (uint32)kMaxWorkspaces)
2974 				index = fDesktop->CurrentWorkspace();
2975 
2976 			Workspace workspace(*fDesktop, index);
2977 			workspace.SetColor(color, makeDefault);
2978 
2979 			fDesktop->UnlockAllWindows();
2980 			break;
2981 		}
2982 
2983 		case AS_GET_ACCELERANT_INFO:
2984 		{
2985 			STRACE(("ServerApp %s: get accelerant info\n", Signature()));
2986 
2987 			// We aren't using the screen_id for now...
2988 			int32 id;
2989 			link.Read<int32>(&id);
2990 
2991 			accelerant_device_info accelerantInfo;
2992 			// TODO: I wonder if there should be a "desktop" lock...
2993 			status_t status
2994 				= fDesktop->HWInterface()->GetDeviceInfo(&accelerantInfo);
2995 			if (status == B_OK) {
2996 				fLink.StartMessage(B_OK);
2997 				fLink.Attach<accelerant_device_info>(accelerantInfo);
2998 			} else
2999 				fLink.StartMessage(status);
3000 
3001 			fLink.Flush();
3002 			break;
3003 		}
3004 
3005 		case AS_GET_MONITOR_INFO:
3006 		{
3007 			STRACE(("ServerApp %s: get monitor info\n", Signature()));
3008 
3009 			// We aren't using the screen_id for now...
3010 			int32 id;
3011 			link.Read<int32>(&id);
3012 
3013 			monitor_info info;
3014 			// TODO: I wonder if there should be a "desktop" lock...
3015 			status_t status = fDesktop->HWInterface()->GetMonitorInfo(&info);
3016 			if (status == B_OK) {
3017 				fLink.StartMessage(B_OK);
3018 				fLink.Attach<monitor_info>(info);
3019 			} else
3020 				fLink.StartMessage(status);
3021 
3022 			fLink.Flush();
3023 			break;
3024 		}
3025 
3026 		case AS_GET_FRAME_BUFFER_CONFIG:
3027 		{
3028 			STRACE(("ServerApp %s: get frame buffer config\n", Signature()));
3029 
3030 			// We aren't using the screen_id for now...
3031 			int32 id;
3032 			link.Read<int32>(&id);
3033 
3034 			frame_buffer_config config;
3035 			// TODO: I wonder if there should be a "desktop" lock...
3036 			status_t status = fDesktop->HWInterface()->GetFrameBufferConfig(config);
3037 			if (status == B_OK) {
3038 				fLink.StartMessage(B_OK);
3039 				fLink.Attach<frame_buffer_config>(config);
3040 			} else
3041 				fLink.StartMessage(status);
3042 
3043 			fLink.Flush();
3044 			break;
3045 		}
3046 
3047 		case AS_GET_RETRACE_SEMAPHORE:
3048 		{
3049 			STRACE(("ServerApp %s: get retrace semaphore\n", Signature()));
3050 
3051 			// We aren't using the screen_id for now...
3052 			int32 id;
3053 			link.Read<int32>(&id);
3054 
3055 			fLink.StartMessage(B_OK);
3056 			fLink.Attach<sem_id>(fDesktop->HWInterface()->RetraceSemaphore());
3057 			fLink.Flush();
3058 			break;
3059 		}
3060 
3061 		case AS_GET_TIMING_CONSTRAINTS:
3062 		{
3063 			STRACE(("ServerApp %s: get timing constraints\n", Signature()));
3064 
3065 			// We aren't using the screen_id for now...
3066 			int32 id;
3067 			link.Read<int32>(&id);
3068 
3069 			display_timing_constraints constraints;
3070 			status_t status = fDesktop->HWInterface()->GetTimingConstraints(
3071 				&constraints);
3072 			if (status == B_OK) {
3073 				fLink.StartMessage(B_OK);
3074 				fLink.Attach<display_timing_constraints>(constraints);
3075 			} else
3076 				fLink.StartMessage(status);
3077 
3078 			fLink.Flush();
3079 			break;
3080 		}
3081 
3082 		case AS_GET_PIXEL_CLOCK_LIMITS:
3083 		{
3084 			STRACE(("ServerApp %s: get pixel clock limits\n", Signature()));
3085 			// We aren't using the screen_id for now...
3086 			int32 id;
3087 			link.Read<int32>(&id);
3088 			display_mode mode;
3089 			link.Read<display_mode>(&mode);
3090 
3091 			uint32 low, high;
3092 			status_t status = fDesktop->HWInterface()->GetPixelClockLimits(&mode,
3093 				&low, &high);
3094 			if (status == B_OK) {
3095 				fLink.StartMessage(B_OK);
3096 				fLink.Attach<uint32>(low);
3097 				fLink.Attach<uint32>(high);
3098 			} else
3099 				fLink.StartMessage(status);
3100 
3101 			fLink.Flush();
3102 			break;
3103 		}
3104 
3105 		case AS_SET_DPMS:
3106 		{
3107 			STRACE(("ServerApp %s: AS_SET_DPMS\n", Signature()));
3108 			int32 id;
3109 			link.Read<int32>(&id);
3110 
3111 			uint32 mode;
3112 			link.Read<uint32>(&mode);
3113 
3114 			status_t status = fDesktop->HWInterface()->SetDPMSMode(mode);
3115 			fLink.StartMessage(status);
3116 
3117 			fLink.Flush();
3118 			break;
3119 		}
3120 
3121 		case AS_GET_DPMS_STATE:
3122 		{
3123 			STRACE(("ServerApp %s: AS_GET_DPMS_STATE\n", Signature()));
3124 
3125 			int32 id;
3126 			link.Read<int32>(&id);
3127 
3128 			uint32 state = fDesktop->HWInterface()->DPMSMode();
3129 			fLink.StartMessage(B_OK);
3130 			fLink.Attach<uint32>(state);
3131 			fLink.Flush();
3132 			break;
3133 		}
3134 
3135 		case AS_GET_DPMS_CAPABILITIES:
3136 		{
3137 			STRACE(("ServerApp %s: AS_GET_DPMS_CAPABILITIES\n", Signature()));
3138 			int32 id;
3139 			link.Read<int32>(&id);
3140 
3141 			uint32 capabilities = fDesktop->HWInterface()->DPMSCapabilities();
3142 			fLink.StartMessage(B_OK);
3143 			fLink.Attach<uint32>(capabilities);
3144 			fLink.Flush();
3145 			break;
3146 		}
3147 
3148 		case AS_SCREEN_SET_BRIGHTNESS:
3149 		{
3150 			STRACE(("ServerApp %s: AS_SCREEN_SET_BRIGHTNESS\n", Signature()));
3151 			int32 id;
3152 			link.Read<int32>(&id);
3153 
3154 			float brightness;
3155 			link.Read<float>(&brightness);
3156 
3157 			status_t status = fDesktop->SetBrightness(id, brightness);
3158 			fLink.StartMessage(status);
3159 
3160 			fLink.Flush();
3161 			break;
3162 		}
3163 
3164 		case AS_SCREEN_GET_BRIGHTNESS:
3165 		{
3166 			STRACE(("ServerApp %s: AS_SCREEN_GET_BRIGHTNESS\n", Signature()));
3167 			int32 id;
3168 			link.Read<int32>(&id);
3169 
3170 			float brightness;
3171 			status_t result = fDesktop->HWInterface()->GetBrightness(&brightness);
3172 			fLink.StartMessage(result);
3173 			if (result == B_OK)
3174 				fLink.Attach<float>(brightness);
3175 			fLink.Flush();
3176 			break;
3177 		}
3178 
3179 		case AS_READ_BITMAP:
3180 		{
3181 			STRACE(("ServerApp %s: AS_READ_BITMAP\n", Signature()));
3182 			int32 token;
3183 			link.Read<int32>(&token);
3184 
3185 			bool drawCursor = true;
3186 			link.Read<bool>(&drawCursor);
3187 
3188 			BRect bounds;
3189 			link.Read<BRect>(&bounds);
3190 
3191 			bool success = false;
3192 
3193 			ServerBitmap* bitmap = GetBitmap(token);
3194 			if (bitmap != NULL) {
3195 				if (fDesktop->GetDrawingEngine()->LockExclusiveAccess()) {
3196 					success = fDesktop->GetDrawingEngine()->ReadBitmap(bitmap,
3197 						drawCursor, bounds) == B_OK;
3198 					fDesktop->GetDrawingEngine()->UnlockExclusiveAccess();
3199 				}
3200 				bitmap->ReleaseReference();
3201 			}
3202 
3203 			if (success)
3204 				fLink.StartMessage(B_OK);
3205 			else
3206 				fLink.StartMessage(B_BAD_VALUE);
3207 
3208 			fLink.Flush();
3209 			break;
3210 		}
3211 
3212 		case AS_GET_ACCELERANT_PATH:
3213 		{
3214 			int32 id;
3215 			fLink.Read<int32>(&id);
3216 
3217 			BString path;
3218 			status_t status = fDesktop->HWInterface()->GetAccelerantPath(path);
3219 			fLink.StartMessage(status);
3220 			if (status == B_OK)
3221 				fLink.AttachString(path.String());
3222 
3223 			fLink.Flush();
3224 			break;
3225 		}
3226 
3227 		case AS_GET_DRIVER_PATH:
3228 		{
3229 			int32 id;
3230 			fLink.Read<int32>(&id);
3231 
3232 			BString path;
3233 			status_t status = fDesktop->HWInterface()->GetDriverPath(path);
3234 			fLink.StartMessage(status);
3235 			if (status == B_OK)
3236 				fLink.AttachString(path.String());
3237 
3238 			fLink.Flush();
3239 			break;
3240 		}
3241 
3242 		// BWindowScreen communication
3243 
3244 		case AS_DIRECT_SCREEN_LOCK:
3245 		{
3246 			bool lock;
3247 			link.Read<bool>(&lock);
3248 
3249 			status_t status;
3250 			if (lock)
3251 				status = fDesktop->LockDirectScreen(ClientTeam());
3252 			else
3253 				status = fDesktop->UnlockDirectScreen(ClientTeam());
3254 
3255 			fLink.StartMessage(status);
3256 			fLink.Flush();
3257 			break;
3258 		}
3259 
3260 		// Hinting and aliasing
3261 
3262 		case AS_SET_SUBPIXEL_ANTIALIASING:
3263 		{
3264 			bool subpix;
3265 			if (link.Read<bool>(&subpix) == B_OK) {
3266 				LockedDesktopSettings settings(fDesktop);
3267 				settings.SetSubpixelAntialiasing(subpix);
3268 			}
3269 			fDesktop->Redraw();
3270 			break;
3271 		}
3272 
3273 		case AS_GET_SUBPIXEL_ANTIALIASING:
3274 		{
3275 			DesktopSettings settings(fDesktop);
3276 			fLink.StartMessage(B_OK);
3277 			fLink.Attach<bool>(settings.SubpixelAntialiasing());
3278 			fLink.Flush();
3279 			break;
3280 		}
3281 
3282 		case AS_SET_HINTING:
3283 		{
3284 			uint8 hinting;
3285 			if (link.Read<uint8>(&hinting) == B_OK && hinting < 3) {
3286 				LockedDesktopSettings settings(fDesktop);
3287 				if (hinting != settings.Hinting()) {
3288 					settings.SetHinting(hinting);
3289 					fDesktop->Redraw();
3290 				}
3291 			}
3292 			break;
3293 		}
3294 
3295 		case AS_GET_HINTING:
3296 		{
3297 			DesktopSettings settings(fDesktop);
3298 			fLink.StartMessage(B_OK);
3299 			fLink.Attach<uint8>(settings.Hinting());
3300 			fLink.Flush();
3301 			break;
3302 		}
3303 
3304 		case AS_SET_SUBPIXEL_AVERAGE_WEIGHT:
3305 		{
3306 			uint8 averageWeight;
3307 			if (link.Read<uint8>(&averageWeight) == B_OK) {
3308 				LockedDesktopSettings settings(fDesktop);
3309 				settings.SetSubpixelAverageWeight(averageWeight);
3310 			}
3311 			fDesktop->Redraw();
3312 			break;
3313 		}
3314 
3315 		case AS_GET_SUBPIXEL_AVERAGE_WEIGHT:
3316 		{
3317 			DesktopSettings settings(fDesktop);
3318 			fLink.StartMessage(B_OK);
3319 			fLink.Attach<uint8>(settings.SubpixelAverageWeight());
3320 			fLink.Flush();
3321 			break;
3322 		}
3323 
3324 		case AS_SET_SUBPIXEL_ORDERING:
3325 		{
3326 			bool subpixelOrdering;
3327 			if (link.Read<bool>(&subpixelOrdering) == B_OK) {
3328 				LockedDesktopSettings settings(fDesktop);
3329 				settings.SetSubpixelOrderingRegular(subpixelOrdering);
3330 			}
3331 			fDesktop->Redraw();
3332 			break;
3333 		}
3334 
3335 		case AS_GET_SUBPIXEL_ORDERING:
3336 		{
3337 			DesktopSettings settings(fDesktop);
3338 			fLink.StartMessage(B_OK);
3339 			fLink.Attach<bool>(settings.IsSubpixelOrderingRegular());
3340 			fLink.Flush();
3341 			break;
3342 		}
3343 
3344 		default:
3345 			printf("ServerApp %s received unhandled message code %" B_PRId32
3346 				"\n", Signature(), code);
3347 
3348 			if (link.NeedsReply()) {
3349 				// the client is now blocking and waiting for a reply!
3350 				fLink.StartMessage(B_ERROR);
3351 				fLink.Flush();
3352 			} else
3353 				puts("message doesn't need a reply!");
3354 			break;
3355 	}
3356 }
3357 
3358 
3359 /*!	\brief The thread function ServerApps use to monitor messages
3360 */
3361 void
3362 ServerApp::_MessageLooper()
3363 {
3364 	// Message-dispatching loop for the ServerApp
3365 
3366 	// get our own team ID
3367 	thread_info threadInfo;
3368 	get_thread_info(fThread, &threadInfo);
3369 
3370 	// First let's tell the client how to talk with us.
3371 	fLink.StartMessage(B_OK);
3372 	fLink.Attach<port_id>(fMessagePort);
3373 	fLink.Attach<area_id>(fDesktop->SharedReadOnlyArea());
3374 	fLink.Attach<team_id>(threadInfo.team);
3375 	fLink.Flush();
3376 
3377 	BPrivate::LinkReceiver &receiver = fLink.Receiver();
3378 
3379 	int32 code;
3380 	status_t err = B_OK;
3381 
3382 	while (!fQuitting) {
3383 		STRACE(("info: ServerApp::_MessageLooper() listening on port %" B_PRId32
3384 			".\n", fMessagePort));
3385 
3386 		err = receiver.GetNextMessage(code);
3387 		if (err != B_OK || code == B_QUIT_REQUESTED) {
3388 			STRACE(("ServerApp: application seems to be gone...\n"));
3389 
3390 			// Tell desktop to quit us
3391 			BPrivate::LinkSender link(fDesktop->MessagePort());
3392 			link.StartMessage(AS_DELETE_APP);
3393 			link.Attach<thread_id>(Thread());
3394 			link.Flush();
3395 			break;
3396 		}
3397 
3398 		switch (code) {
3399 			case kMsgAppQuit:
3400 				// we receive this from our destructor on quit
3401 				fQuitting = true;
3402 				break;
3403 
3404 			case AS_QUIT_APP:
3405 			{
3406 				// This message is received only when the app_server is asked
3407 				// to shut down in test/debug mode. Of course, if we are testing
3408 				// while using AccelerantDriver, we do NOT want to shut down
3409 				// client applications. The server can be quit in this fashion
3410 				// through the driver's interface, such as closing the
3411 				// ViewDriver's window.
3412 
3413 				STRACE(("ServerApp %s:Server shutdown notification received\n",
3414 					Signature()));
3415 
3416 				// If we are using the real, accelerated version of the
3417 				// DrawingEngine, we do NOT want the user to be able shut down
3418 				// the server. The results would NOT be pretty
3419 #if TEST_MODE
3420 				BMessage pleaseQuit(B_QUIT_REQUESTED);
3421 				SendMessageToClient(&pleaseQuit);
3422 #endif
3423 				break;
3424 			}
3425 
3426 			default:
3427 				STRACE(("ServerApp %s: Got a Message to dispatch\n",
3428 					Signature()));
3429 				_DispatchMessage(code, receiver);
3430 				break;
3431 		}
3432 	}
3433 
3434 	// Quit() will send us a message; we're handling the exiting procedure
3435 	thread_id sender;
3436 	sem_id shutdownSemaphore;
3437 	receive_data(&sender, &shutdownSemaphore, sizeof(sem_id));
3438 
3439 	delete this;
3440 
3441 	if (shutdownSemaphore >= B_OK)
3442 		release_sem(shutdownSemaphore);
3443 }
3444 
3445 
3446 status_t
3447 ServerApp::_CreateWindow(int32 code, BPrivate::LinkReceiver& link,
3448 	port_id& clientReplyPort)
3449 {
3450 	// Attached data:
3451 	// 1) int32 bitmap token (only for AS_CREATE_OFFSCREEN_WINDOW)
3452 	// 2) BRect window frame
3453 	// 3) uint32 window look
3454 	// 4) uint32 window feel
3455 	// 5) uint32 window flags
3456 	// 6) uint32 workspace index
3457 	// 7) int32 BHandler token of the window
3458 	// 8) port_id window's reply port
3459 	// 9) port_id window's looper port
3460 	// 10) const char * title
3461 
3462 	BRect frame;
3463 	int32 bitmapToken;
3464 	uint32 look;
3465 	uint32 feel;
3466 	uint32 flags;
3467 	uint32 workspaces;
3468 	int32 token;
3469 	port_id looperPort;
3470 	char* title;
3471 
3472 	if (code == AS_CREATE_OFFSCREEN_WINDOW)
3473 		link.Read<int32>(&bitmapToken);
3474 
3475 	link.Read<BRect>(&frame);
3476 	link.Read<uint32>(&look);
3477 	link.Read<uint32>(&feel);
3478 	link.Read<uint32>(&flags);
3479 	link.Read<uint32>(&workspaces);
3480 	link.Read<int32>(&token);
3481 	link.Read<port_id>(&clientReplyPort);
3482 	link.Read<port_id>(&looperPort);
3483 	if (link.ReadString(&title) != B_OK)
3484 		return B_ERROR;
3485 
3486 	if (!frame.IsValid()) {
3487 		// make sure we pass a valid rectangle to ServerWindow
3488 		frame.right = frame.left + 1;
3489 		frame.bottom = frame.top + 1;
3490 	}
3491 
3492 	status_t status = B_NO_MEMORY;
3493 	ServerWindow *window = NULL;
3494 
3495 	if (code == AS_CREATE_OFFSCREEN_WINDOW) {
3496 		ServerBitmap* bitmap = GetBitmap(bitmapToken);
3497 
3498 		if (bitmap != NULL) {
3499 			window = new (nothrow) OffscreenServerWindow(title, this,
3500 				clientReplyPort, looperPort, token, bitmap);
3501 		} else
3502 			status = B_ERROR;
3503 	} else {
3504 		window = new (nothrow) ServerWindow(title, this, clientReplyPort,
3505 			looperPort, token);
3506 		STRACE(("\nServerApp %s: New Window %s (%g:%g, %g:%g)\n",
3507 			Signature(), title, frame.left, frame.top,
3508 			frame.right, frame.bottom));
3509 	}
3510 
3511 	free(title);
3512 
3513 	// NOTE: the reply to the client is handled in ServerWindow::Run()
3514 	if (window != NULL) {
3515 		status = window->Init(frame, (window_look)look, (window_feel)feel,
3516 			flags, workspaces);
3517 		if (status == B_OK) {
3518 			status = window->Run();
3519 			if (status != B_OK) {
3520 				syslog(LOG_ERR, "ServerApp::_CreateWindow() - failed to run "
3521 					"the window thread\n");
3522 			}
3523 		}
3524 
3525 		if (status != B_OK)
3526 			delete window;
3527 	}
3528 
3529 	return status;
3530 }
3531 
3532 
3533 bool
3534 ServerApp::_HasWindowUnderMouse()
3535 {
3536 	BAutolock locker(fWindowListLock);
3537 
3538 	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
3539 		ServerWindow* serverWindow = fWindowList.ItemAt(i);
3540 
3541 		if (fDesktop->ViewUnderMouse(serverWindow->Window()) != B_NULL_TOKEN)
3542 			return true;
3543 	}
3544 
3545 	return false;
3546 }
3547 
3548 
3549 bool
3550 ServerApp::_AddBitmap(ServerBitmap* bitmap)
3551 {
3552 	BAutolock _(fMapLocker);
3553 
3554 	try {
3555 		fBitmapMap.insert(std::make_pair(bitmap->Token(), bitmap));
3556 	} catch (std::bad_alloc& exception) {
3557 		return false;
3558 	}
3559 
3560 	bitmap->SetOwner(this);
3561 	return true;
3562 }
3563 
3564 
3565 void
3566 ServerApp::_DeleteBitmap(ServerBitmap* bitmap)
3567 {
3568 	ASSERT(fMapLocker.IsLocked());
3569 
3570 	gBitmapManager->BitmapRemoved(bitmap);
3571 	fBitmapMap.erase(bitmap->Token());
3572 
3573 	bitmap->ReleaseReference();
3574 }
3575 
3576 
3577 ServerBitmap*
3578 ServerApp::_FindBitmap(int32 token) const
3579 {
3580 	ASSERT(fMapLocker.IsLocked());
3581 
3582 	BitmapMap::const_iterator iterator = fBitmapMap.find(token);
3583 	if (iterator == fBitmapMap.end())
3584 		return NULL;
3585 
3586 	return iterator->second;
3587 }
3588 
3589 
3590 ServerPicture*
3591 ServerApp::_FindPicture(int32 token) const
3592 {
3593 	ASSERT(fMapLocker.IsLocked());
3594 
3595 	PictureMap::const_iterator iterator = fPictureMap.find(token);
3596 	if (iterator == fPictureMap.end())
3597 		return NULL;
3598 
3599 	return iterator->second;
3600 }
3601