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