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