1bd28b3c7SAxel Dörfler/*
2f744935bSAxel Dörfler * Copyright 2001-2016, Haiku.
3bd28b3c7SAxel Dörfler * Distributed under the terms of the MIT License.
4bd28b3c7SAxel Dörfler *
5bd28b3c7SAxel Dörfler * Authors:
6bd28b3c7SAxel Dörfler *		DarkWyrm <bpmagic@columbus.rr.com>
7bd28b3c7SAxel Dörfler *		Adrian Oanca <adioanca@cotty.iren.ro>
8bd28b3c7SAxel Dörfler *		Stephan A��mus <superstippi@gmx.de>
9bd28b3c7SAxel Dörfler *		Stefano Ceccherini (burton666@libero.it)
10bd28b3c7SAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
11959a5a68SAxel Dörfler *		J��r��me Duval, jerome.duval@free.fr
12b09e2f6fSStephan Aßmus *		Andrej Spielmann, <andrej.spielmann@seh.ox.ac.uk>
13fc235d55SStephan Aßmus *		Philippe Saint-Pierre, stpere@gmail.com
141c73ffa1SStephan Aßmus *		Wim van der Meer, <WPJvanderMeer@gmail.com>
157f9368caSlooncraz *		Joseph Groover <looncraz@looncraz.net>
16bd28b3c7SAxel Dörfler */
17bd28b3c7SAxel Dörfler
186c364068SAxel Dörfler
196c364068SAxel Dörfler/*!	\class ServerApp ServerApp.h
20770c05d6SAxel Dörfler	\brief Counterpart to BApplication within the app_server
21770c05d6SAxel Dörfler*/
22b5436616SAxel Dörfler
236c364068SAxel Dörfler
246c364068SAxel Dörfler#include "ServerApp.h"
256c364068SAxel Dörfler
266c364068SAxel Dörfler#include <new>
276c364068SAxel Dörfler#include <stdio.h>
286c364068SAxel Dörfler#include <string.h>
296c364068SAxel Dörfler#include <syslog.h>
306c364068SAxel Dörfler
316c364068SAxel Dörfler#include <AppDefs.h>
326c364068SAxel Dörfler#include <Autolock.h>
336c364068SAxel Dörfler#include <Debug.h>
346c364068SAxel Dörfler#include <List.h>
356c364068SAxel Dörfler#include <ScrollBar.h>
366c364068SAxel Dörfler#include <Shape.h>
376c364068SAxel Dörfler#include <String.h>
38f4c2f7ebSJonathan Schleifer#include <StackOrHeapArray.h>
396c364068SAxel Dörfler
406c364068SAxel Dörfler#include <FontPrivate.h>
416c364068SAxel Dörfler#include <MessengerPrivate.h>
425e3f4c41SAxel Dörfler#include <PrivateScreen.h>
436c364068SAxel Dörfler#include <RosterPrivate.h>
446c364068SAxel Dörfler#include <ServerProtocol.h>
456c364068SAxel Dörfler#include <WindowPrivate.h>
466c364068SAxel Dörfler
4743c4c1eeSDarkWyrm#include "AppServer.h"
483dcb3b07SStephan Aßmus#include "BitmapManager.h"
490934499cSDarkWyrm#include "CursorManager.h"
5022137825SMichael Lotz#include "CursorSet.h"
5134a81c2fSDarkWyrm#include "Desktop.h"
523dcb3b07SStephan Aßmus#include "DecorManager.h"
536ed89418SStephan Aßmus#include "DrawingEngine.h"
54f7598223SAxel Dörfler#include "EventStream.h"
55bdd34c02SAxel Dörfler#include "FontManager.h"
563dcb3b07SStephan Aßmus#include "HWInterface.h"
57f7598223SAxel Dörfler#include "InputManager.h"
58359c905cSStephan Aßmus#include "OffscreenServerWindow.h"
59953d895eSAxel Dörfler#include "Screen.h"
600934499cSDarkWyrm#include "ServerBitmap.h"
610934499cSDarkWyrm#include "ServerConfig.h"
623dcb3b07SStephan Aßmus#include "ServerCursor.h"
633dcb3b07SStephan Aßmus#include "ServerPicture.h"
64be05d56cSAxel Dörfler#include "ServerTokenSpace.h"
653dcb3b07SStephan Aßmus#include "ServerWindow.h"
667475dcdfSStefano Ceccherini#include "SystemPalette.h"
67953d895eSAxel Dörfler#include "Window.h"
687b919e9aSDarkWyrm
6916ed1e1dSAxel Dörfler
7016ed1e1dSAxel Dörfler//#define DEBUG_SERVERAPP
713ecfa8e1SAdi Oanca#ifdef DEBUG_SERVERAPP
72a4de7fa0SAxel Dörfler#	define STRACE(x) debug_printf x
733ecfa8e1SAdi Oanca#else
743ecfa8e1SAdi Oanca#	define STRACE(x) ;
753ecfa8e1SAdi Oanca#endif
760934499cSDarkWyrm
77e438905aSAdi Oanca//#define DEBUG_SERVERAPP_FONT
780d9d87e7SDarkWyrm#ifdef DEBUG_SERVERAPP_FONT
79a4de7fa0SAxel Dörfler#	define FTRACE(x) debug_printf x
800d9d87e7SDarkWyrm#else
810d9d87e7SDarkWyrm#	define FTRACE(x) ;
820d9d87e7SDarkWyrm#endif
830d9d87e7SDarkWyrm
8463ea9a28SIngo Weinholdusing std::nothrow;
85fcb006dcSAxel Dörfler
86cf2aeb20SAxel Dörflerstatic const uint32 kMsgUpdateShowAllDraggers = '_adg';
87fcb006dcSAxel Dörflerstatic const uint32 kMsgAppQuit = 'appQ';
88fcb006dcSAxel Dörfler
89fcb006dcSAxel Dörfler
90770c05d6SAxel DörflerServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort,
914c0269b9SAxel Dörfler		port_id clientLooperPort, team_id clientTeam,
924c0269b9SAxel Dörfler		int32 clientToken, const char* signature)
936c364068SAxel Dörfler	:
946c364068SAxel Dörfler	MessageLooper("application"),
954c0269b9SAxel Dörfler
96fcb006dcSAxel Dörfler	fMessagePort(-1),
9789ab121eSAxel Dörfler	fClientReplyPort(clientReplyPort),
98770c05d6SAxel Dörfler	fDesktop(desktop),
99bd28b3c7SAxel Dörfler	fSignature(signature),
100fcb006dcSAxel Dörfler	fClientTeam(clientTeam),
101a38e46a0SAxel Dörfler	fWindowListLock("window list"),
1025e3f4c41SAxel Dörfler	fTemporaryDisplayModeChange(0),
10385a7877fSAxel Dörfler	fMapLocker("server app maps"),
104bd28b3c7SAxel Dörfler	fAppCursor(NULL),
1059ce4e5b4SAxel Dörfler	fViewCursor(NULL),
106df190823SStephan Aßmus	fCursorHideLevel(0),
107bd28b3c7SAxel Dörfler	fIsActive(false),
108f744935bSAxel Dörfler	fMemoryAllocator(new (std::nothrow) ClientMemoryAllocator(this))
1090934499cSDarkWyrm{
11080581303SStefano Ceccherini	if (fSignature == "")
111fcb006dcSAxel Dörfler		fSignature = "application/no-signature";
112fcb006dcSAxel Dörfler
113a38e46a0SAxel Dörfler	char name[B_OS_NAME_LENGTH];
1143fed1a15SAlex Smith	snprintf(name, sizeof(name), "a<%" B_PRId32 ":%s", clientTeam,
1153fed1a15SAlex Smith		SignatureLeaf());
116fcb006dcSAxel Dörfler
117a38e46a0SAxel Dörfler	fMessagePort = create_port(DEFAULT_MONITOR_PORT_SIZE, name);
118fcb006dcSAxel Dörfler	if (fMessagePort < B_OK)
119fcb006dcSAxel Dörfler		return;
120fcb006dcSAxel Dörfler
121fcb006dcSAxel Dörfler	fLink.SetSenderPort(fClientReplyPort);
122fcb006dcSAxel Dörfler	fLink.SetReceiverPort(fMessagePort);
123b13b0b0fSIthamar R. Adema	fLink.SetTargetTeam(clientTeam);
124fcb006dcSAxel Dörfler
125fcb006dcSAxel Dörfler	// we let the application own the port, so that we get aware when it's gone
126fcb006dcSAxel Dörfler	if (set_port_owner(fMessagePort, clientTeam) < B_OK) {
127fcb006dcSAxel Dörfler		delete_port(fMessagePort);
128fcb006dcSAxel Dörfler		fMessagePort = -1;
129fcb006dcSAxel Dörfler		return;
130fcb006dcSAxel Dörfler	}
131d7c08b7dSAxel Dörfler
1324ceb1e51SAxel Dörfler	BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
1334ceb1e51SAxel Dörfler		clientLooperPort, clientToken);
134f7598223SAxel Dörfler
135843bc3cdSAxel Dörfler	fInitialWorkspace = desktop->CurrentWorkspace();
136843bc3cdSAxel Dörfler		// TODO: this should probably be retrieved when the app is loaded!
137843bc3cdSAxel Dörfler
138fc235d55SStephan Aßmus	// record the current system wide fonts..
139fc235d55SStephan Aßmus	desktop->LockSingleWindow();
140fc235d55SStephan Aßmus	DesktopSettings settings(desktop);
141fc235d55SStephan Aßmus	settings.GetDefaultPlainFont(fPlainFont);
142fc235d55SStephan Aßmus	settings.GetDefaultBoldFont(fBoldFont);
143fc235d55SStephan Aßmus	settings.GetDefaultFixedFont(fFixedFont);
144fc235d55SStephan Aßmus	desktop->UnlockSingleWindow();
145fc235d55SStephan Aßmus
1461e1b96cdSAxel Dörfler	STRACE(("ServerApp %s:\n", Signature()));
1473fed1a15SAlex Smith	STRACE(("\tBApp port: %" B_PRId32 "\n", fClientReplyPort));
1483fed1a15SAlex Smith	STRACE(("\tReceiver port: %" B_PRId32 "\n", fMessagePort));
1490934499cSDarkWyrm}
1500934499cSDarkWyrm
15180581303SStefano Ceccherini
1524c0269b9SAxel DörflerServerApp::~ServerApp()
1530934499cSDarkWyrm{
1541e1b96cdSAxel Dörfler	STRACE(("*ServerApp %s:~ServerApp()\n", Signature()));
155437b1927SAxel Dörfler	ASSERT(fQuitting);
156fcb006dcSAxel Dörfler
1571b53e8afSAxel Dörfler	// quit all server windows
1581b53e8afSAxel Dörfler
15967e79bf4SAxel Dörfler	fWindowListLock.Lock();
1601b53e8afSAxel Dörfler	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
161d9525baaSAxel Dörfler		ServerWindow* window = fWindowList.ItemAt(i);
1621b53e8afSAxel Dörfler		window->Quit();
1631b53e8afSAxel Dörfler	}
1641b53e8afSAxel Dörfler	fWindowListLock.Unlock();
1651b53e8afSAxel Dörfler
1661b53e8afSAxel Dörfler	// wait for the windows to quit
16767e79bf4SAxel Dörfler	snooze(20000);
16867e79bf4SAxel Dörfler
1698bca36b1SAxel Dörfler	fDesktop->RevertScreenModes(fTemporaryDisplayModeChange);
1708bca36b1SAxel Dörfler
17167e79bf4SAxel Dörfler	fWindowListLock.Lock();
17267e79bf4SAxel Dörfler	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
17355fd3336SAxel Dörfler		ServerWindow* window = fWindowList.ItemAt(i);
17455fd3336SAxel Dörfler
1756c364068SAxel Dörfler		// A window could have been removed in the mean time
1766c364068SAxel Dörfler		// (if those 20 milli seconds from above weren't enough)
17755fd3336SAxel Dörfler		if (window == NULL)
17855fd3336SAxel Dörfler			continue;
17955fd3336SAxel Dörfler
18055fd3336SAxel Dörfler		sem_id deathSemaphore = window->DeathSemaphore();
1811b53e8afSAxel Dörfler		fWindowListLock.Unlock();
1821b53e8afSAxel Dörfler
18367e79bf4SAxel Dörfler		// wait 3 seconds for our window to quit - that's quite a long
18467e79bf4SAxel Dörfler		// time, but killing it might have desastrous effects
18567e79bf4SAxel Dörfler		if (MessageLooper::WaitForQuit(deathSemaphore, 3000000) != B_OK) {
18667e79bf4SAxel Dörfler			// This really shouldn't happen, as it shows we're buggy
187ff3abf4dSAxel Dörfler#ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST
1881eed15a2SAxel Dörfler			syslog(LOG_ERR, "ServerApp %s: ServerWindow doesn't respond!\n",
18967e79bf4SAxel Dörfler				Signature());
190359c905cSStephan Aßmus#else
1911eed15a2SAxel Dörfler			debugger("ServerWindow doesn't respond!\n");
192359c905cSStephan Aßmus#endif
19367e79bf4SAxel Dörfler		}
19467e79bf4SAxel Dörfler		fWindowListLock.Lock();
1951b53e8afSAxel Dörfler	}
1961b53e8afSAxel Dörfler
197f744935bSAxel Dörfler	if (fMemoryAllocator != NULL)
198f744935bSAxel Dörfler		fMemoryAllocator->Detach();
19985a7877fSAxel Dörfler	fMapLocker.Lock();
20085a7877fSAxel Dörfler
20187e7b978SAxel Dörfler	while (!fBitmapMap.empty())
20287e7b978SAxel Dörfler		_DeleteBitmap(fBitmapMap.begin()->second);
20385a7877fSAxel Dörfler
20487e7b978SAxel Dörfler	while (!fPictureMap.empty())
2054177bfe6SStephan Aßmus		fPictureMap.begin()->second->SetOwner(NULL);
206bff387f1SDarkWyrm
207aa1f5437SAxel Dörfler	fDesktop->GetCursorManager().DeleteCursors(fClientTeam);
208f744935bSAxel Dörfler	if (fMemoryAllocator != NULL)
209f744935bSAxel Dörfler		fMemoryAllocator->ReleaseReference();
210158c4633SAdi Oanca
2110ec4af22SAxel Dörfler	STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature()));
2120934499cSDarkWyrm}
2130934499cSDarkWyrm
214fcb006dcSAxel Dörfler
2156c364068SAxel Dörfler/*!	\brief Checks if the application was initialized correctly
216fcb006dcSAxel Dörfler*/
217fcb006dcSAxel Dörflerstatus_t
218fcb006dcSAxel DörflerServerApp::InitCheck()
219fcb006dcSAxel Dörfler{
220fcb006dcSAxel Dörfler	if (fMessagePort < B_OK)
221fcb006dcSAxel Dörfler		return fMessagePort;
222fcb006dcSAxel Dörfler
223fcb006dcSAxel Dörfler	if (fClientReplyPort < B_OK)
224fcb006dcSAxel Dörfler		return fClientReplyPort;
225fcb006dcSAxel Dörfler
226565155afSAugustin Cavalier	if (fWindowListLock.InitCheck() < B_OK)
227565155afSAugustin Cavalier		return fWindowListLock.InitCheck();
228fcb006dcSAxel Dörfler
229f744935bSAxel Dörfler	if (fMemoryAllocator == NULL)
230f744935bSAxel Dörfler		return B_NO_MEMORY;
231f744935bSAxel Dörfler
232fcb006dcSAxel Dörfler	return B_OK;
233fcb006dcSAxel Dörfler}
234fcb006dcSAxel Dörfler
235fcb006dcSAxel Dörfler
236e4c638f6SStefano Ceccherinivoid
237e4c638f6SStefano CeccheriniServerApp::Quit()
238e4c638f6SStefano Ceccherini{
239e4c638f6SStefano Ceccherini	Quit(-1);
240e4c638f6SStefano Ceccherini}
241e4c638f6SStefano Ceccherini
242e4c638f6SStefano Ceccherini
2436c364068SAxel Dörfler/*!	\brief This quits the application and deletes it. You're not supposed
244fcb006dcSAxel Dörfler		to call its destructor directly.
245fcb006dcSAxel Dörfler
246fcb006dcSAxel Dörfler	At the point you're calling this method, the application should already
247fcb006dcSAxel Dörfler	be removed from the application list.
248fcb006dcSAxel Dörfler*/
249fcb006dcSAxel Dörflervoid
2503870c9f1SAxel DörflerServerApp::Quit(sem_id shutdownSemaphore)
251fcb006dcSAxel Dörfler{
252fcb006dcSAxel Dörfler	if (fThread < B_OK) {
253fcb006dcSAxel Dörfler		delete this;
254fcb006dcSAxel Dörfler		return;
255fcb006dcSAxel Dörfler	}
256fcb006dcSAxel Dörfler
257fcb006dcSAxel Dörfler	// execute application deletion in the message looper thread
258fcb006dcSAxel Dörfler
259fcb006dcSAxel Dörfler	fQuitting = true;
260ce1639b2SAxel Dörfler	PostMessage(kMsgAppQuit);
261fcb006dcSAxel Dörfler
2623870c9f1SAxel Dörfler	send_data(fThread, 'QUIT', &shutdownSemaphore, sizeof(sem_id));
263fcb006dcSAxel Dörfler}
264fcb006dcSAxel Dörfler
265fcb006dcSAxel Dörfler
2666c364068SAxel Dörfler/*!	\brief Sets the ServerApp's active status
26746ec4904SDarkWyrm	\param value The new status of the ServerApp.
2689dbce7a4SAxel Dörfler
269345d8c9fSAxel Dörfler	This changes an internal flag and also sets the current cursor to the one
270345d8c9fSAxel Dörfler	specified by the application
27146ec4904SDarkWyrm*/
27280581303SStefano Ceccherinivoid
27380581303SStefano CeccheriniServerApp::Activate(bool value)
27446ec4904SDarkWyrm{
275b073091aSStephan Aßmus	if (fIsActive == value)
276b073091aSStephan Aßmus		return;
277b073091aSStephan Aßmus
27880581303SStefano Ceccherini	fIsActive = value;
279b073091aSStephan Aßmus
2809ce4e5b4SAxel Dörfler	if (fIsActive) {
281e30afed4SAxel Dörfler		// notify registrar about the active app
282e30afed4SAxel Dörfler		BRoster::Private roster;
283e30afed4SAxel Dörfler		roster.UpdateActiveApp(ClientTeam());
284e30afed4SAxel Dörfler
28587b1f40cSAxel Dörfler		if (_HasWindowUnderMouse()) {
28687b1f40cSAxel Dörfler			// Set the cursor to the application cursor, if any
28787b1f40cSAxel Dörfler			fDesktop->SetCursor(CurrentCursor());
28887b1f40cSAxel Dörfler		}
2899ce4e5b4SAxel Dörfler		fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
2909ce4e5b4SAxel Dörfler	}
29146ec4904SDarkWyrm}
2928380e999SStefano Ceccherini
2938380e999SStefano Ceccherini
29480581303SStefano Ceccherinivoid
2959ce4e5b4SAxel DörflerServerApp::SetCurrentCursor(ServerCursor* cursor)
29646ec4904SDarkWyrm{
29787e7b978SAxel Dörfler	if (fViewCursor != cursor) {
29887e7b978SAxel Dörfler		if (fViewCursor)
29987e7b978SAxel Dörfler			fViewCursor->ReleaseReference();
30019e179caSStephan Aßmus
30187e7b978SAxel Dörfler		fViewCursor = cursor;
30219e179caSStephan Aßmus
30387e7b978SAxel Dörfler		if (fViewCursor)
30487e7b978SAxel Dörfler			fViewCursor->AcquireReference();
30587e7b978SAxel Dörfler	}
30619e179caSStephan Aßmus
3079ce4e5b4SAxel Dörfler	fDesktop->SetCursor(CurrentCursor());
3089ce4e5b4SAxel Dörfler}
3099ce4e5b4SAxel Dörfler
3109ce4e5b4SAxel Dörfler
3119ce4e5b4SAxel DörflerServerCursor*
3129ce4e5b4SAxel DörflerServerApp::CurrentCursor() const
3139ce4e5b4SAxel Dörfler{
3149ce4e5b4SAxel Dörfler	if (fViewCursor != NULL)
3159ce4e5b4SAxel Dörfler		return fViewCursor;
3169ce4e5b4SAxel Dörfler
3179ce4e5b4SAxel Dörfler	return fAppCursor;
31846ec4904SDarkWyrm}
31946ec4904SDarkWyrm
3208380e999SStefano Ceccherini
32185a7877fSAxel Dörflerbool
32285a7877fSAxel DörflerServerApp::AddWindow(ServerWindow* window)
32385a7877fSAxel Dörfler{
32485a7877fSAxel Dörfler	BAutolock locker(fWindowListLock);
32585a7877fSAxel Dörfler
32685a7877fSAxel Dörfler	return fWindowList.AddItem(window);
32785a7877fSAxel Dörfler}
32885a7877fSAxel Dörfler
32985a7877fSAxel Dörfler
33089ab121eSAxel Dörflervoid
33185a7877fSAxel DörflerServerApp::RemoveWindow(ServerWindow* window)
332fcb006dcSAxel Dörfler{
33385a7877fSAxel Dörfler	BAutolock locker(fWindowListLock);
33485a7877fSAxel Dörfler
33585a7877fSAxel Dörfler	fWindowList.RemoveItem(window);
336fcb006dcSAxel Dörfler}
337fcb006dcSAxel Dörfler
338fcb006dcSAxel Dörfler
33985a7877fSAxel Dörflerbool
34085a7877fSAxel DörflerServerApp::InWorkspace(int32 index) const
34185a7877fSAxel Dörfler{
34285a7877fSAxel Dörfler	BAutolock locker(fWindowListLock);
34385a7877fSAxel Dörfler
34485a7877fSAxel Dörfler	// we could cache this, but then we'd have to recompute the cached
34585a7877fSAxel Dörfler	// value everytime a window has closed or changed workspaces
34685a7877fSAxel Dörfler
34785a7877fSAxel Dörfler	// TODO: support initial application workspace!
34885a7877fSAxel Dörfler
34985a7877fSAxel Dörfler	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
35085a7877fSAxel Dörfler		ServerWindow* serverWindow = fWindowList.ItemAt(i);
35185a7877fSAxel Dörfler
35285a7877fSAxel Dörfler		const Window* window = serverWindow->Window();
35385a7877fSAxel Dörfler		if (window == NULL || window->IsOffscreenWindow())
35485a7877fSAxel Dörfler			continue;
35585a7877fSAxel Dörfler
35685a7877fSAxel Dörfler		// only normal and unhidden windows count
35785a7877fSAxel Dörfler
35885a7877fSAxel Dörfler		if (window->IsNormal() && !window->IsHidden()
35985a7877fSAxel Dörfler			&& window->InWorkspace(index))
36085a7877fSAxel Dörfler			return true;
36185a7877fSAxel Dörfler	}
36285a7877fSAxel Dörfler
36385a7877fSAxel Dörfler	return false;
36485a7877fSAxel Dörfler}
36585a7877fSAxel Dörfler
36685a7877fSAxel Dörfler
36785a7877fSAxel Dörfleruint32
36885a7877fSAxel DörflerServerApp::Workspaces() const
36985a7877fSAxel Dörfler{
37085a7877fSAxel Dörfler	uint32 workspaces = 0;
37185a7877fSAxel Dörfler
37285a7877fSAxel Dörfler	BAutolock locker(fWindowListLock);
37385a7877fSAxel Dörfler
37485a7877fSAxel Dörfler	// we could cache this, but then we'd have to recompute the cached
37585a7877fSAxel Dörfler	// value everytime a window has closed or changed workspaces
37685a7877fSAxel Dörfler
37785a7877fSAxel Dörfler	for (int32 i = fWindowList.CountItems(); i-- > 0;) {
37885a7877fSAxel Dörfler		ServerWindow* serverWindow = fWindowList.ItemAt(i);
37985a7877fSAxel Dörfler
38085a7877fSAxel Dörfler		const Window* window = serverWindow->Window();
38185a7877fSAxel Dörfler		if (window == NULL || window->IsOffscreenWindow())
38285a7877fSAxel Dörfler			continue;
38385a7877fSAxel Dörfler
38485a7877fSAxel Dörfler		// only normal and unhidden windows count
38585a7877fSAxel Dörfler
38685a7877fSAxel Dörfler		if (window->IsNormal() && !window->IsHidden())
38785a7877fSAxel Dörfler			workspaces |= window->Workspaces();
38885a7877fSAxel Dörfler	}
38985a7877fSAxel Dörfler
39085a7877fSAxel Dörfler	// TODO: add initial application workspace!
39185a7877fSAxel Dörfler	return workspaces;
39285a7877fSAxel Dörfler}
39385a7877fSAxel Dörfler
39485a7877fSAxel Dörfler
39585a7877fSAxel Dörfler/*!	\brief Acquires a reference of the desired bitmap, if available.
39685a7877fSAxel Dörfler	\param token ID token of the bitmap to find
39785a7877fSAxel Dörfler	\return The bitmap having that ID or NULL if not found
398fcb006dcSAxel Dörfler*/
39985a7877fSAxel DörflerServerBitmap*
40085a7877fSAxel DörflerServerApp::GetBitmap(int32 token) const
40185a7877fSAxel Dörfler{
40285a7877fSAxel Dörfler	if (token < 1)
40385a7877fSAxel Dörfler		return NULL;
40485a7877fSAxel Dörfler
40585a7877fSAxel Dörfler	BAutolock _(fMapLocker);
40685a7877fSAxel Dörfler
40785a7877fSAxel Dörfler	ServerBitmap* bitmap = _FindBitmap(token);
40885a7877fSAxel Dörfler	if (bitmap == NULL)
40985a7877fSAxel Dörfler		return NULL;
41085a7877fSAxel Dörfler
4114b0459b2SAxel Dörfler	bitmap->AcquireReference();
41285a7877fSAxel Dörfler
41385a7877fSAxel Dörfler	return bitmap;
41485a7877fSAxel Dörfler}
41585a7877fSAxel Dörfler
41685a7877fSAxel Dörfler
41785a7877fSAxel DörflerServerPicture*
41885a7877fSAxel DörflerServerApp::CreatePicture(const ServerPicture* original)
41985a7877fSAxel Dörfler{
42085a7877fSAxel Dörfler	ServerPicture* picture;
42185a7877fSAxel Dörfler	if (original != NULL)
42285a7877fSAxel Dörfler		picture = new(std::nothrow) ServerPicture(*original);
42385a7877fSAxel Dörfler	else
42485a7877fSAxel Dörfler		picture = new(std::nothrow) ServerPicture();
425bd28b3c7SAxel Dörfler
42685a7877fSAxel Dörfler	if (picture != NULL && !picture->SetOwner(this))
42785a7877fSAxel Dörfler		picture->ReleaseReference();
428bd28b3c7SAxel Dörfler
42985a7877fSAxel Dörfler	return picture;
43085a7877fSAxel Dörfler}
4316c364068SAxel Dörfler
432d7c08b7dSAxel Dörfler
43385a7877fSAxel DörflerServerPicture*
43485a7877fSAxel DörflerServerApp::GetPicture(int32 token) const
43585a7877fSAxel Dörfler{
43685a7877fSAxel Dörfler	if (token < 1)
43785a7877fSAxel Dörfler		return NULL;
438e42a5b26SDarkWyrm
43985a7877fSAxel Dörfler	BAutolock _(fMapLocker);
440fcb006dcSAxel Dörfler
44185a7877fSAxel Dörfler	ServerPicture* picture = _FindPicture(token);
44285a7877fSAxel Dörfler	if (picture == NULL)
44385a7877fSAxel Dörfler		return NULL;
444fcb006dcSAxel Dörfler
44585a7877fSAxel Dörfler	picture->AcquireReference();
446247a9343SDarkWyrm
44785a7877fSAxel Dörfler	return picture;
44885a7877fSAxel Dörfler}
449bd28b3c7SAxel Dörfler
45085a7877fSAxel Dörfler
4514177bfe6SStephan Aßmus/*! To be called only by ServerPicture itself.*/
45285a7877fSAxel Dörflerbool
45387e7b978SAxel DörflerServerApp::AddPicture(ServerPicture* picture)
45485a7877fSAxel Dörfler{
45585a7877fSAxel Dörfler	BAutolock _(fMapLocker);
45685a7877fSAxel Dörfler
4574177bfe6SStephan Aßmus	ASSERT(picture->Owner() == NULL);
4584177bfe6SStephan Aßmus
45985a7877fSAxel Dörfler	try {
46085a7877fSAxel Dörfler		fPictureMap.insert(std::make_pair(picture->Token(), picture));
46185a7877fSAxel Dörfler	} catch (std::bad_alloc& exception) {
46285a7877fSAxel Dörfler		return false;
463bd28b3c7SAxel Dörfler	}
464247a9343SDarkWyrm
46585a7877fSAxel Dörfler	return true;
46685a7877fSAxel Dörfler}
467fcb006dcSAxel Dörfler
4683870c9f1SAxel Dörfler
4694177bfe6SStephan Aßmus/*! To be called only by ServerPicture itself.*/
47085a7877fSAxel Dörflervoid
47187e7b978SAxel DörflerServerApp::RemovePicture(ServerPicture* picture)
47285a7877fSAxel Dörfler{
47385a7877fSAxel Dörfler	BAutolock _(fMapLocker);
47487e7b978SAxel Dörfler
4754177bfe6SStephan Aßmus	ASSERT(picture->Owner() == this);
4764177bfe6SStephan Aßmus
47785a7877fSAxel Dörfler	fPictureMap.erase(picture->Token());
47887e7b978SAxel Dörfler	picture->ReleaseReference();
47985a7877fSAxel Dörfler}
48085a7877fSAxel Dörfler
48185a7877fSAxel Dörfler
48235d6e0feSAdrien Destugues/*!	Called from the ClientMemoryAllocator whenever a server area could be
48335d6e0feSAdrien Destugues	deleted.
48435d6e0feSAdrien Destugues	A message is then sent to the client telling it that it can delete its
48535d6e0feSAdrien Destugues	client area, too.
48635d6e0feSAdrien Destugues*/
48735d6e0feSAdrien Destuguesvoid
48835d6e0feSAdrien DestuguesServerApp::NotifyDeleteClientArea(area_id serverArea)
48935d6e0feSAdrien Destugues{
49035d6e0feSAdrien Destugues	BMessage notify(kMsgDeleteServerMemoryArea);
49135d6e0feSAdrien Destugues	notify.AddInt32("server area", serverArea);
49235d6e0feSAdrien Destugues
49335d6e0feSAdrien Destugues	SendMessageToClient(&notify);
49435d6e0feSAdrien Destugues}
49535d6e0feSAdrien Destugues
49635d6e0feSAdrien Destugues
49735d6e0feSAdrien Destugues/*!	\brief Send a message to the ServerApp's BApplication
49835d6e0feSAdrien Destugues	\param message The message to send
49935d6e0feSAdrien Destugues*/
50035d6e0feSAdrien Destuguesvoid
50135d6e0feSAdrien DestuguesServerApp::SendMessageToClient(BMessage* message) const
50235d6e0feSAdrien Destugues{
50335d6e0feSAdrien Destugues	status_t status = fHandlerMessenger.SendMessage(message, (BHandler*)NULL,
50435d6e0feSAdrien Destugues		100000);
50535d6e0feSAdrien Destugues	if (status != B_OK) {
50635d6e0feSAdrien Destugues		syslog(LOG_ERR, "app %s send to client failed: %s\n", Signature(),
50735d6e0feSAdrien Destugues			strerror(status));
50835d6e0feSAdrien Destugues	}
50935d6e0feSAdrien Destugues}
51035d6e0feSAdrien Destugues
51135d6e0feSAdrien Destugues
51285a7877fSAxel Dörfler// #pragma mark - private methods
51385a7877fSAxel Dörfler
514