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