1dd10337fSAxel Dörfler/*
230238c04SAxel Dörfler * Copyright 2001-2015 Haiku, inc. All rights reserved.
3dd10337fSAxel Dörfler * Distributed under the terms of the MIT License.
4dd10337fSAxel Dörfler *
5dd10337fSAxel Dörfler * Authors:
6c01f349eSAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
7be902ac4SJohn Scipione *		Jerome Duval
8be902ac4SJohn Scipione *		Erik Jaesler, erik@cgsoftware.com
9dd10337fSAxel Dörfler */
10dd10337fSAxel Dörfler
11dd10337fSAxel Dörfler
12cfc3fa87SAxel Dörfler#include <Application.h>
13cfc3fa87SAxel Dörfler
14cfc3fa87SAxel Dörfler#include <new>
15879f9a09SIngo Weinhold#include <pthread.h>
16cfc3fa87SAxel Dörfler#include <stdio.h>
17cfc3fa87SAxel Dörfler#include <stdlib.h>
18cfc3fa87SAxel Dörfler#include <string.h>
193aeed660SJérôme Duval#include <strings.h>
20cfc3fa87SAxel Dörfler#include <unistd.h>
2152a38012Sejakowatz
2253b9eef8SStefano Ceccherini#include <Alert.h>
2373a2b29fSIngo Weinhold#include <AppFileInfo.h>
24c7f20c70SIngo Weinhold#include <Cursor.h>
25a8fc5954SStefano Ceccherini#include <Debug.h>
2673a2b29fSIngo Weinhold#include <Entry.h>
2773a2b29fSIngo Weinhold#include <File.h>
28c7f20c70SIngo Weinhold#include <Locker.h>
29cfc3fa87SAxel Dörfler#include <MessageRunner.h>
306c40fc5dSczeidler#include <ObjectList.h>
3173a2b29fSIngo Weinhold#include <Path.h>
32b1698c8eSejakowatz#include <PropertyInfo.h>
33c7f20c70SIngo Weinhold#include <RegistrarDefs.h>
346cd5d5b1SStefano Ceccherini#include <Resources.h>
35c7f20c70SIngo Weinhold#include <Roster.h>
36ebbcbbcaSejakowatz#include <Window.h>
3752a38012Sejakowatz
38cfc3fa87SAxel Dörfler#include <AppMisc.h>
39cfc3fa87SAxel Dörfler#include <AppServerLink.h>
40cfc3fa87SAxel Dörfler#include <AutoLocker.h>
416c40fc5dSczeidler#include <BitmapPrivate.h>
42cfc3fa87SAxel Dörfler#include <DraggerPrivate.h>
431480e5daSAxel Dörfler#include <LaunchDaemonDefs.h>
441480e5daSAxel Dörfler#include <LaunchRoster.h>
45cfc3fa87SAxel Dörfler#include <LooperList.h>
46cfc3fa87SAxel Dörfler#include <MenuWindow.h>
476c40fc5dSczeidler#include <PicturePrivate.h>
48cfc3fa87SAxel Dörfler#include <PortLink.h>
49cfc3fa87SAxel Dörfler#include <RosterPrivate.h>
50cfc3fa87SAxel Dörfler#include <ServerMemoryAllocator.h>
51cfc3fa87SAxel Dörfler#include <ServerProtocol.h>
526542ca9bSStefano Ceccherini
53879f9a09SIngo Weinhold
5472f5d860SAxel Dörflerusing namespace BPrivate;
5552a38012Sejakowatz
56cfc3fa87SAxel Dörfler
570690387cSAxel Dörflerstatic const char* kDefaultLooperName = "AppLooperPort";
580690387cSAxel Dörfler
59be902ac4SJohn ScipioneBApplication* be_app = NULL;
60af34fbf1SAxel DörflerBMessenger be_app_messenger;
6152a38012Sejakowatz
62879f9a09SIngo Weinholdpthread_once_t sAppResourcesInitOnce = PTHREAD_ONCE_INIT;
63be902ac4SJohn ScipioneBResources* BApplication::sAppResources = NULL;
6405962bb1SDario CasalinuovoBObjectList<BLooper> sOnQuitLooperList;
6552a38012Sejakowatz
6641f6b937SDarkWyrm
6737d8f330SAxel Dörflerenum {
6837d8f330SAxel Dörfler	kWindowByIndex,
6937d8f330SAxel Dörfler	kWindowByName,
7037d8f330SAxel Dörfler	kLooperByIndex,
7137d8f330SAxel Dörfler	kLooperByID,
7237d8f330SAxel Dörfler	kLooperByName,
7337d8f330SAxel Dörfler	kApplication
7437d8f330SAxel Dörfler};
7537d8f330SAxel Dörfler
76be902ac4SJohn Scipione
77dd10337fSAxel Dörflerstatic property_info sPropertyInfo[] = {
78ebbcbbcaSejakowatz	{
79ebbcbbcaSejakowatz		"Window",
80beabca50SAxel Dörfler		{},
81beabca50SAxel Dörfler		{B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER},
8237d8f330SAxel Dörfler		NULL, kWindowByIndex,
83beabca50SAxel Dörfler		{},
84beabca50SAxel Dörfler		{},
85beabca50SAxel Dörfler		{}
86ebbcbbcaSejakowatz	},
87ebbcbbcaSejakowatz	{
88ebbcbbcaSejakowatz		"Window",
89beabca50SAxel Dörfler		{},
90beabca50SAxel Dörfler		{B_NAME_SPECIFIER},
9137d8f330SAxel Dörfler		NULL, kWindowByName,
92beabca50SAxel Dörfler		{},
93beabca50SAxel Dörfler		{},
94beabca50SAxel Dörfler		{}
95ebbcbbcaSejakowatz	},
96ebbcbbcaSejakowatz	{
97ebbcbbcaSejakowatz		"Looper",
98beabca50SAxel Dörfler		{},
99beabca50SAxel Dörfler		{B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER},
10037d8f330SAxel Dörfler		NULL, kLooperByIndex,
101beabca50SAxel Dörfler		{},
102beabca50SAxel Dörfler		{},
103beabca50SAxel Dörfler		{}
104ebbcbbcaSejakowatz	},
105ebbcbbcaSejakowatz	{
106ebbcbbcaSejakowatz		"Looper",
107beabca50SAxel Dörfler		{},
108beabca50SAxel Dörfler		{B_ID_SPECIFIER},
10937d8f330SAxel Dörfler		NULL, kLooperByID,
110beabca50SAxel Dörfler		{},
111beabca50SAxel Dörfler		{},
112beabca50SAxel Dörfler		{}
113ebbcbbcaSejakowatz	},
114ebbcbbcaSejakowatz	{
115ebbcbbcaSejakowatz		"Looper",
116beabca50SAxel Dörfler		{},
117beabca50SAxel Dörfler		{B_NAME_SPECIFIER},
11837d8f330SAxel Dörfler		NULL, kLooperByName,
119beabca50SAxel Dörfler		{},
120beabca50SAxel Dörfler		{},
121beabca50SAxel Dörfler		{}
122ebbcbbcaSejakowatz	},
123ebbcbbcaSejakowatz	{
124ebbcbbcaSejakowatz		"Name",
125beabca50SAxel Dörfler		{B_GET_PROPERTY},
126beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
12737d8f330SAxel Dörfler		NULL, kApplication,
128beabca50SAxel Dörfler		{B_STRING_TYPE},
129beabca50SAxel Dörfler		{},
130beabca50SAxel Dörfler		{}
131ebbcbbcaSejakowatz	},
132ebbcbbcaSejakowatz	{
133ebbcbbcaSejakowatz		"Window",
134beabca50SAxel Dörfler		{B_COUNT_PROPERTIES},
135beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
13637d8f330SAxel Dörfler		NULL, kApplication,
137beabca50SAxel Dörfler		{B_INT32_TYPE},
138beabca50SAxel Dörfler		{},
139beabca50SAxel Dörfler		{}
140ebbcbbcaSejakowatz	},
141ebbcbbcaSejakowatz	{
142ebbcbbcaSejakowatz		"Loopers",
143beabca50SAxel Dörfler		{B_GET_PROPERTY},
144beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
14537d8f330SAxel Dörfler		NULL, kApplication,
146beabca50SAxel Dörfler		{B_MESSENGER_TYPE},
147beabca50SAxel Dörfler		{},
148beabca50SAxel Dörfler		{}
149ebbcbbcaSejakowatz	},
150ebbcbbcaSejakowatz	{
151ebbcbbcaSejakowatz		"Windows",
152beabca50SAxel Dörfler		{B_GET_PROPERTY},
153beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
15437d8f330SAxel Dörfler		NULL, kApplication,
155beabca50SAxel Dörfler		{B_MESSENGER_TYPE},
156beabca50SAxel Dörfler		{},
157beabca50SAxel Dörfler		{}
158ebbcbbcaSejakowatz	},
159ebbcbbcaSejakowatz	{
160ebbcbbcaSejakowatz		"Looper",
161beabca50SAxel Dörfler		{B_COUNT_PROPERTIES},
162beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
16337d8f330SAxel Dörfler		NULL, kApplication,
164beabca50SAxel Dörfler		{B_INT32_TYPE},
165beabca50SAxel Dörfler		{},
166beabca50SAxel Dörfler		{}
167ebbcbbcaSejakowatz	},
16816af9b4cSHumdinger
16916af9b4cSHumdinger	{ 0 }
1702284462cSejakowatz};
1712284462cSejakowatz
172be902ac4SJohn Scipione
17373a2b29fSIngo Weinhold// argc/argv
17473a2b29fSIngo Weinholdextern const int __libc_argc;
175be902ac4SJohn Scipioneextern const char* const *__libc_argv;
17652a38012Sejakowatz
177c7f20c70SIngo Weinhold
178c7f20c70SIngo Weinhold// debugging
17901225b39SIngo Weinhold//#define DBG(x) x
18001225b39SIngo Weinhold#define DBG(x)
181c7f20c70SIngo Weinhold#define OUT	printf
182c7f20c70SIngo Weinhold
183c7f20c70SIngo Weinhold
184be902ac4SJohn Scipione//	#pragma mark - static helper functions
185be902ac4SJohn Scipione
186be902ac4SJohn Scipione
187be902ac4SJohn Scipione/*!
188be902ac4SJohn Scipione	\brief Checks whether the supplied string is a valid application signature.
189be902ac4SJohn Scipione
190be902ac4SJohn Scipione	An error message is printed, if the string is no valid app signature.
191be902ac4SJohn Scipione
192be902ac4SJohn Scipione	\param signature The string to be checked.
193be902ac4SJohn Scipione
194be902ac4SJohn Scipione	\return A status code.
195be902ac4SJohn Scipione	\retval B_OK \a signature is a valid app signature.
196be902ac4SJohn Scipione	\retval B_BAD_VALUE \a signature is \c NULL or no valid app signature.
197be902ac4SJohn Scipione*/
198be902ac4SJohn Scipionestatic status_t
199be902ac4SJohn Scipionecheck_app_signature(const char* signature)
200be902ac4SJohn Scipione{
201be902ac4SJohn Scipione	bool isValid = false;
202be902ac4SJohn Scipione	BMimeType type(signature);
203be902ac4SJohn Scipione
204be902ac4SJohn Scipione	if (type.IsValid() && !type.IsSupertypeOnly()
205be902ac4SJohn Scipione		&& BMimeType("application").Contains(&type)) {
206be902ac4SJohn Scipione		isValid = true;
207be902ac4SJohn Scipione	}
208be902ac4SJohn Scipione
209be902ac4SJohn Scipione	if (!isValid) {
210be902ac4SJohn Scipione		printf("bad signature (%s), must begin with \"application/\" and "
211be902ac4SJohn Scipione			   "can't conflict with existing registered mime types inside "
212be902ac4SJohn Scipione			   "the \"application\" media type.\n", signature);
213be902ac4SJohn Scipione	}
214be902ac4SJohn Scipione
215be902ac4SJohn Scipione	return (isValid ? B_OK : B_BAD_VALUE);
216be902ac4SJohn Scipione}
217be902ac4SJohn Scipione
218be902ac4SJohn Scipione
219fc5dbdc9SJonathan Schleifer#ifndef RUN_WITHOUT_REGISTRAR
220be902ac4SJohn Scipione// Fills the passed BMessage with B_ARGV_RECEIVED infos.
221be902ac4SJohn Scipionestatic void
222be902ac4SJohn Scipionefill_argv_message(BMessage &message)
223be902ac4SJohn Scipione{
224be902ac4SJohn Scipione	message.what = B_ARGV_RECEIVED;
225be902ac4SJohn Scipione
226be902ac4SJohn Scipione	int32 argc = __libc_argc;
227be902ac4SJohn Scipione	const char* const *argv = __libc_argv;
228be902ac4SJohn Scipione
229be902ac4SJohn Scipione	// add argc
230be902ac4SJohn Scipione	message.AddInt32("argc", argc);
231be902ac4SJohn Scipione
232be902ac4SJohn Scipione	// add argv
233be902ac4SJohn Scipione	for (int32 i = 0; i < argc; i++) {
234be902ac4SJohn Scipione		if (argv[i] != NULL)
235be902ac4SJohn Scipione			message.AddString("argv", argv[i]);
236be902ac4SJohn Scipione	}
237be902ac4SJohn Scipione
238be902ac4SJohn Scipione	// add current working directory
239be902ac4SJohn Scipione	char cwd[B_PATH_NAME_LENGTH];
240be902ac4SJohn Scipione	if (getcwd(cwd, B_PATH_NAME_LENGTH))
241be902ac4SJohn Scipione		message.AddString("cwd", cwd);
242be902ac4SJohn Scipione}
243fc5dbdc9SJonathan Schleifer#endif
244c7f20c70SIngo Weinhold
245beabca50SAxel Dörfler
246be902ac4SJohn Scipione//	#pragma mark - BApplication
247be902ac4SJohn Scipione
248be902ac4SJohn Scipione
249be902ac4SJohn ScipioneBApplication::BApplication(const char* signature)
250be902ac4SJohn Scipione	:
2510690387cSAxel Dörfler	BLooper(kDefaultLooperName)
25252a38012Sejakowatz{
2539a44fdc9SAxel Dörfler	_InitData(signature, true, NULL);
25452a38012Sejakowatz}
255beabca50SAxel Dörfler
256beabca50SAxel Dörfler
257be902ac4SJohn ScipioneBApplication::BApplication(const char* signature, status_t* _error)
258be902ac4SJohn Scipione	:
2590690387cSAxel Dörfler	BLooper(kDefaultLooperName)
26052a38012Sejakowatz{
2619a44fdc9SAxel Dörfler	_InitData(signature, true, _error);
262c8e7f53eSIngo Weinhold}
263c8e7f53eSIngo Weinhold
264c8e7f53eSIngo Weinhold
2650690387cSAxel DörflerBApplication::BApplication(const char* signature, const char* looperName,
2661480e5daSAxel Dörfler	port_id port, bool initGUI, status_t* _error)
267be902ac4SJohn Scipione	:
2681480e5daSAxel Dörfler	BLooper(B_NORMAL_PRIORITY + 1, port < 0 ? _GetPort(signature) : port,
2691480e5daSAxel Dörfler		looperName != NULL ? looperName : kDefaultLooperName)
270c8e7f53eSIngo Weinhold{
2719a44fdc9SAxel Dörfler	_InitData(signature, initGUI, _error);
272798ad3dbSAxel Dörfler	if (port < 0)
273798ad3dbSAxel Dörfler		fOwnsPort = false;
27452a38012Sejakowatz}
275beabca50SAxel Dörfler
276beabca50SAxel Dörfler
277be902ac4SJohn ScipioneBApplication::BApplication(BMessage* data)
278be902ac4SJohn Scipione	// Note: BeOS calls the private BLooper(int32, port_id, const char*)
279c18d8429SAxel Dörfler	// constructor here, test if it's needed
280be902ac4SJohn Scipione	:
2810690387cSAxel Dörfler	BLooper(kDefaultLooperName)
282c18d8429SAxel Dörfler{
283be902ac4SJohn Scipione	const char* signature = NULL;
284c18d8429SAxel Dörfler	data->FindString("mime_sig", &signature);
285c18d8429SAxel Dörfler
2869a44fdc9SAxel Dörfler	_InitData(signature, true, NULL);
287c18d8429SAxel Dörfler
288c18d8429SAxel Dörfler	bigtime_t pulseRate;
289c18d8429SAxel Dörfler	if (data->FindInt64("_pulse", &pulseRate) == B_OK)
290c18d8429SAxel Dörfler		SetPulseRate(pulseRate);
291c18d8429SAxel Dörfler}
292c18d8429SAxel Dörfler
293c18d8429SAxel Dörfler
294ebb0db62SAugustin Cavalier#ifdef _BEOS_R5_COMPATIBLE_
295c18d8429SAxel DörflerBApplication::BApplication(uint32 signature)
296c18d8429SAxel Dörfler{
297c18d8429SAxel Dörfler}
298c18d8429SAxel Dörfler
299c18d8429SAxel Dörfler
300c18d8429SAxel DörflerBApplication::BApplication(const BApplication &rhs)
301c18d8429SAxel Dörfler{
302c18d8429SAxel Dörfler}
303c18d8429SAxel Dörfler
304c18d8429SAxel Dörfler
305ebb0db62SAugustin CavalierBApplication&
306ebb0db62SAugustin CavalierBApplication::operator=(const BApplication &rhs)
307ebb0db62SAugustin Cavalier{
308ebb0db62SAugustin Cavalier	return *this;
309ebb0db62SAugustin Cavalier}
310ebb0db62SAugustin Cavalier#endif
311ebb0db62SAugustin Cavalier
312ebb0db62SAugustin Cavalier
31352a38012SejakowatzBApplication::~BApplication()
31452a38012Sejakowatz{
31572f5d860SAxel Dörfler	Lock();
316f28a6f70SAdi Oanca
31772f5d860SAxel Dörfler	// tell all loopers(usually windows) to quit. Also, wait for them.
3189a44fdc9SAxel Dörfler	_QuitAllWindows(true);
319f28a6f70SAdi Oanca
32005962bb1SDario Casalinuovo	// quit registered loopers
32105962bb1SDario Casalinuovo	for (int32 i = 0; i < sOnQuitLooperList.CountItems(); i++) {
32205962bb1SDario Casalinuovo		BLooper* looper = sOnQuitLooperList.ItemAt(i);
32305962bb1SDario Casalinuovo		if (looper->Lock())
32405962bb1SDario Casalinuovo			looper->Quit();
32505962bb1SDario Casalinuovo	}
32605962bb1SDario Casalinuovo
327dc3ebdecSAdi Oanca	// unregister from the roster
328dc3ebdecSAdi Oanca	BRoster::Private().RemoveApp(Team());
329dc3ebdecSAdi Oanca
330044be4e2SIngo Weinhold#ifndef RUN_WITHOUT_APP_SERVER
3313ceb31b9SDarkWyrm	// tell app_server we're quitting...
332c4f7df69SStefano Ceccherini	if (be_app) {
333c4f7df69SStefano Ceccherini		// be_app can be NULL here if the application fails to initialize
334c4f7df69SStefano Ceccherini		// correctly. For example, if it's already running and it's set to
335c4f7df69SStefano Ceccherini		// exclusive launch.
336c4f7df69SStefano Ceccherini		BPrivate::AppServerLink link;
337c4f7df69SStefano Ceccherini		link.StartMessage(B_QUIT_REQUESTED);
338c4f7df69SStefano Ceccherini		link.Flush();
339c4f7df69SStefano Ceccherini	}
340dd10337fSAxel Dörfler	delete_port(fServerLink->SenderPort());
341dd10337fSAxel Dörfler	delete_port(fServerLink->ReceiverPort());
342dd10337fSAxel Dörfler	delete fServerLink;
343a60ea282SIngo Weinhold#endif	// RUN_WITHOUT_APP_SERVER
34472f5d860SAxel Dörfler
345c7c61938SAxel Dörfler	delete fServerAllocator;
346c7c61938SAxel Dörfler
34772f5d860SAxel Dörfler	// uninitialize be_app, the be_app_messenger is invalidated automatically
3488a526591SIngo Weinhold	be_app = NULL;
34952a38012Sejakowatz}
350beabca50SAxel Dörfler
351beabca50SAxel Dörfler
352c18d8429SAxel Dörflervoid
353be902ac4SJohn ScipioneBApplication::_InitData(const char* signature, bool initGUI, status_t* _error)
354c18d8429SAxel Dörfler{
355dd10337fSAxel Dörfler	DBG(OUT("BApplication::InitData(`%s', %p)\n", signature, _error));
356c18d8429SAxel Dörfler	// check whether there exists already an application
357239f8573SAxel Dörfler	if (be_app != NULL)
358c18d8429SAxel Dörfler		debugger("2 BApplication objects were created. Only one is allowed.");
359c18d8429SAxel Dörfler
360dd10337fSAxel Dörfler	fServerLink = new BPrivate::PortLink(-1, -1);
3619a44fdc9SAxel Dörfler	fServerAllocator = NULL;
362239f8573SAxel Dörfler	fServerReadOnlyMemory = NULL;
363c18d8429SAxel Dörfler	fInitialWorkspace = 0;
3649a44fdc9SAxel Dörfler	//fDraggedMessage = NULL;
365c18d8429SAxel Dörfler	fReadyToRunCalled = false;
366c18d8429SAxel Dörfler
367c18d8429SAxel Dörfler	// initially, there is no pulse
368c18d8429SAxel Dörfler	fPulseRunner = NULL;
369c18d8429SAxel Dörfler	fPulseRate = 0;
370c18d8429SAxel Dörfler
371c18d8429SAxel Dörfler	// check signature
372c18d8429SAxel Dörfler	fInitError = check_app_signature(signature);
373c18d8429SAxel Dörfler	fAppName = signature;
374c18d8429SAxel Dörfler
375c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_REGISTRAR
3761480e5daSAxel Dörfler	bool registerApp = signature == NULL
377bea38cb7SAxel Dörfler		|| (strcasecmp(signature, B_REGISTRAR_SIGNATURE) != 0
3781480e5daSAxel Dörfler			&& strcasecmp(signature, kLaunchDaemonSignature) != 0);
379c18d8429SAxel Dörfler	// get team and thread
380c18d8429SAxel Dörfler	team_id team = Team();
381c18d8429SAxel Dörfler	thread_id thread = BPrivate::main_thread_for(team);
382c18d8429SAxel Dörfler#endif
383c18d8429SAxel Dörfler
384c18d8429SAxel Dörfler	// get app executable ref
385c18d8429SAxel Dörfler	entry_ref ref;
38684de162bSIngo Weinhold	if (fInitError == B_OK) {
387c18d8429SAxel Dörfler		fInitError = BPrivate::get_app_ref(&ref);
38884de162bSIngo Weinhold		if (fInitError != B_OK) {
38984de162bSIngo Weinhold			DBG(OUT("BApplication::InitData(): Failed to get app ref: %s\n",
39084de162bSIngo Weinhold				strerror(fInitError)));
39184de162bSIngo Weinhold		}
39284de162bSIngo Weinhold	}
393c18d8429SAxel Dörfler
394c18d8429SAxel Dörfler	// get the BAppFileInfo and extract the information we need
395c18d8429SAxel Dörfler	uint32 appFlags = B_REG_DEFAULT_APP_FLAGS;
396c18d8429SAxel Dörfler	if (fInitError == B_OK) {
397c18d8429SAxel Dörfler		BAppFileInfo fileInfo;
398c18d8429SAxel Dörfler		BFile file(&ref, B_READ_ONLY);
399c18d8429SAxel Dörfler		fInitError = fileInfo.SetTo(&file);
400c18d8429SAxel Dörfler		if (fInitError == B_OK) {
401c18d8429SAxel Dörfler			fileInfo.GetAppFlags(&appFlags);
402ca8ed922SStefano Ceccherini			char appFileSignature[B_MIME_TYPE_LENGTH];
403c18d8429SAxel Dörfler			// compare the file signature and the supplied signature
404c18d8429SAxel Dörfler			if (fileInfo.GetSignature(appFileSignature) == B_OK
405c18d8429SAxel Dörfler				&& strcasecmp(appFileSignature, signature) != 0) {
406c18d8429SAxel Dörfler				printf("Signature in rsrc doesn't match constructor arg. (%s, %s)\n",
407c18d8429SAxel Dörfler					signature, appFileSignature);
408c18d8429SAxel Dörfler			}
40984de162bSIngo Weinhold		} else {
41084de162bSIngo Weinhold			DBG(OUT("BApplication::InitData(): Failed to get info from: "
41184de162bSIngo Weinhold				"BAppFileInfo: %s\n", strerror(fInitError)));
412c18d8429SAxel Dörfler		}
413c18d8429SAxel Dörfler	}
414c18d8429SAxel Dörfler
415c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_REGISTRAR
416c18d8429SAxel Dörfler	// check whether be_roster is valid
4171480e5daSAxel Dörfler	if (fInitError == B_OK && registerApp
418c18d8429SAxel Dörfler		&& !BRoster::Private().IsMessengerValid(false)) {
419c18d8429SAxel Dörfler		printf("FATAL: be_roster is not valid. Is the registrar running?\n");
420c18d8429SAxel Dörfler		fInitError = B_NO_INIT;
421c18d8429SAxel Dörfler	}
422c18d8429SAxel Dörfler
423c18d8429SAxel Dörfler	// check whether or not we are pre-registered
424c18d8429SAxel Dörfler	bool preRegistered = false;
425c18d8429SAxel Dörfler	app_info appInfo;
4261480e5daSAxel Dörfler	if (fInitError == B_OK && registerApp) {
4276bfd06d1SIngo Weinhold		if (BRoster::Private().IsAppRegistered(&ref, team, 0, &preRegistered,
4286bfd06d1SIngo Weinhold				&appInfo) != B_OK) {
4296bfd06d1SIngo Weinhold			preRegistered = false;
4306bfd06d1SIngo Weinhold		}
431c18d8429SAxel Dörfler	}
432c18d8429SAxel Dörfler	if (preRegistered) {
433c18d8429SAxel Dörfler		// we are pre-registered => the app info has been filled in
434c18d8429SAxel Dörfler		// Check whether we need to replace the looper port with a port
435c18d8429SAxel Dörfler		// created by the roster.
436c18d8429SAxel Dörfler		if (appInfo.port >= 0 && appInfo.port != fMsgPort) {
437c18d8429SAxel Dörfler			delete_port(fMsgPort);
438c18d8429SAxel Dörfler			fMsgPort = appInfo.port;
439c18d8429SAxel Dörfler		} else
440c18d8429SAxel Dörfler			appInfo.port = fMsgPort;
441c4dde2f7SAxel Dörfler		// check the signature and correct it, if necessary, also the case
442c4dde2f7SAxel Dörfler		if (strcmp(appInfo.signature, fAppName))
443c18d8429SAxel Dörfler			BRoster::Private().SetSignature(team, fAppName);
444c18d8429SAxel Dörfler		// complete the registration
445c18d8429SAxel Dörfler		fInitError = BRoster::Private().CompleteRegistration(team, thread,
446c18d8429SAxel Dörfler						appInfo.port);
447c18d8429SAxel Dörfler	} else if (fInitError == B_OK) {
448c18d8429SAxel Dörfler		// not pre-registered -- try to register the application
449c18d8429SAxel Dörfler		team_id otherTeam = -1;
4501480e5daSAxel Dörfler		if (registerApp) {
451c18d8429SAxel Dörfler			fInitError = BRoster::Private().AddApplication(signature, &ref,
452c18d8429SAxel Dörfler				appFlags, team, thread, fMsgPort, true, NULL, &otherTeam);
45384de162bSIngo Weinhold			if (fInitError != B_OK) {
45484de162bSIngo Weinhold				DBG(OUT("BApplication::InitData(): Failed to add app: %s\n",
45584de162bSIngo Weinhold					strerror(fInitError)));
45684de162bSIngo Weinhold			}
457c18d8429SAxel Dörfler		}
458c18d8429SAxel Dörfler		if (fInitError == B_ALREADY_RUNNING) {
459c18d8429SAxel Dörfler			// An instance is already running and we asked for
460c18d8429SAxel Dörfler			// single/exclusive launch. Send our argv to the running app.
461c18d8429SAxel Dörfler			// Do that only, if the app is NOT B_ARGV_ONLY.
462aa389c6bSAxel Dörfler			if (otherTeam >= 0) {
463aa389c6bSAxel Dörfler				BMessenger otherApp(NULL, otherTeam);
464c18d8429SAxel Dörfler				app_info otherAppInfo;
4659b3be140SMichael Lotz				bool argvOnly = be_roster->GetRunningAppInfo(otherTeam,
4669b3be140SMichael Lotz						&otherAppInfo) == B_OK
4679b3be140SMichael Lotz					&& (otherAppInfo.flags & B_ARGV_ONLY) != 0;
4689b3be140SMichael Lotz
4699b3be140SMichael Lotz				if (__libc_argc > 1 && !argvOnly) {
470c18d8429SAxel Dörfler					// create an B_ARGV_RECEIVED message
471c18d8429SAxel Dörfler					BMessage argvMessage(B_ARGV_RECEIVED);
472bee72328SAxel Dörfler					fill_argv_message(argvMessage);
473c18d8429SAxel Dörfler
474c18d8429SAxel Dörfler					// replace the first argv string with the path of the
475c18d8429SAxel Dörfler					// other application
476c18d8429SAxel Dörfler					BPath path;
477c18d8429SAxel Dörfler					if (path.SetTo(&otherAppInfo.ref) == B_OK)
478c18d8429SAxel Dörfler						argvMessage.ReplaceString("argv", 0, path.Path());
479c18d8429SAxel Dörfler
480c18d8429SAxel Dörfler					// send the message
481aa389c6bSAxel Dörfler					otherApp.SendMessage(&argvMessage);
4829b3be140SMichael Lotz				} else if (!argvOnly)
483aa389c6bSAxel Dörfler					otherApp.SendMessage(B_SILENT_RELAUNCH);
484c18d8429SAxel Dörfler			}
485c18d8429SAxel Dörfler		} else if (fInitError == B_OK) {
486c18d8429SAxel Dörfler			// the registrations was successful
487c18d8429SAxel Dörfler			// Create a B_ARGV_RECEIVED message and send it to ourselves.
488c18d8429SAxel Dörfler			// Do that even, if we are B_ARGV_ONLY.
489c18d8429SAxel Dörfler			// TODO: When BLooper::AddMessage() is done, use that instead of
490c18d8429SAxel Dörfler			// PostMessage().
491c18d8429SAxel Dörfler
4921b6bc267SAlexander von Gluck IV			DBG(OUT("info: BApplication successfully registered.\n"));
493c18d8429SAxel Dörfler
494c18d8429SAxel Dörfler			if (__libc_argc > 1) {
495c18d8429SAxel Dörfler				BMessage argvMessage(B_ARGV_RECEIVED);
496bee72328SAxel Dörfler				fill_argv_message(argvMessage);
497c18d8429SAxel Dörfler				PostMessage(&argvMessage, this);
498c18d8429SAxel Dörfler			}
499c18d8429SAxel Dörfler			// send a B_READY_TO_RUN message as well
500c18d8429SAxel Dörfler			PostMessage(B_READY_TO_RUN, this);
501c18d8429SAxel Dörfler		} else if (fInitError > B_ERRORS_END) {
502c18d8429SAxel Dörfler			// Registrar internal errors shouldn't fall into the user's hands.
503c18d8429SAxel Dörfler			fInitError = B_ERROR;
504c18d8429SAxel Dörfler		}
505c18d8429SAxel Dörfler	}
5064e51dee8SDarkWyrm#else
5074e51dee8SDarkWyrm	// We need to have ReadyToRun called even when we're not using the registrar
5084e51dee8SDarkWyrm	PostMessage(B_READY_TO_RUN, this);
5094e51dee8SDarkWyrm#endif	// ifndef RUN_WITHOUT_REGISTRAR
510c18d8429SAxel Dörfler
511c18d8429SAxel Dörfler	if (fInitError == B_OK) {
512aa389c6bSAxel Dörfler		// TODO: Not completely sure about the order, but this should be close.
513aa389c6bSAxel Dörfler
514aa389c6bSAxel Dörfler		// init be_app and be_app_messenger
515c18d8429SAxel Dörfler		be_app = this;
516c18d8429SAxel Dörfler		be_app_messenger = BMessenger(NULL, this);
517dd10337fSAxel Dörfler
518aa389c6bSAxel Dörfler		// set the BHandler's name
519c18d8429SAxel Dörfler		SetName(ref.name);
520c8e7f53eSIngo Weinhold
521aa389c6bSAxel Dörfler		// create meta MIME
522c18d8429SAxel Dörfler		BPath path;
5233667f6efSMichael Lotz		if (registerApp && path.SetTo(&ref) == B_OK)
524c18d8429SAxel Dörfler			create_app_meta_mime(path.Path(), false, true, false);
525c18d8429SAxel Dörfler
526c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_APP_SERVER
527aa389c6bSAxel Dörfler		// app server connection and IK initialization
528aa389c6bSAxel Dörfler		if (initGUI)
529aa389c6bSAxel Dörfler			fInitError = _InitGUIContext();
530c18d8429SAxel Dörfler#endif	// RUN_WITHOUT_APP_SERVER
531aa389c6bSAxel Dörfler	}
53241f6b937SDarkWyrm
533c18d8429SAxel Dörfler	// Return the error or exit, if there was an error and no error variable
534c18d8429SAxel Dörfler	// has been supplied.
535d482c7caSAxel Dörfler	if (_error != NULL) {
536c18d8429SAxel Dörfler		*_error = fInitError;
53784de162bSIngo Weinhold	} else if (fInitError != B_OK) {
53884de162bSIngo Weinhold		DBG(OUT("BApplication::InitData() failed: %s\n", strerror(fInitError)));
539c18d8429SAxel Dörfler		exit(0);
54084de162bSIngo Weinhold	}
54184de162bSIngo WeinholdDBG(OUT("BApplication::InitData() done\n"));
54252a38012Sejakowatz}
543beabca50SAxel Dörfler
544beabca50SAxel Dörfler
5451480e5daSAxel Dörflerport_id
5461480e5daSAxel DörflerBApplication::_GetPort(const char* signature)
5471480e5daSAxel Dörfler{
54843aec2c7SAxel Dörfler	return BLaunchRoster().GetPort(signature, NULL);
5491480e5daSAxel Dörfler}
5501480e5daSAxel Dörfler
5511480e5daSAxel Dörfler
552be902ac4SJohn ScipioneBArchivable*
553be902ac4SJohn ScipioneBApplication::Instantiate(BMessage* data)
55452a38012Sejakowatz{
5555dccfc19SStefano Ceccherini	if (validate_instantiation(data, "BApplication"))
5565dccfc19SStefano Ceccherini		return new BApplication(data);
557beabca50SAxel Dörfler
558a02979bbSKarsten Heimrich	return NULL;
55952a38012Sejakowatz}
560beabca50SAxel Dörfler
561beabca50SAxel Dörfler
56241f6b937SDarkWyrmstatus_t
563be902ac4SJohn ScipioneBApplication::Archive(BMessage* data, bool deep) const
56452a38012Sejakowatz{
56541f6b937SDarkWyrm	status_t status = BLooper::Archive(data, deep);
56641f6b937SDarkWyrm	if (status < B_OK)
56741f6b937SDarkWyrm		return status;
56841f6b937SDarkWyrm
56941f6b937SDarkWyrm	app_info info;
57041f6b937SDarkWyrm	status = GetAppInfo(&info);
57141f6b937SDarkWyrm	if (status < B_OK)
57241f6b937SDarkWyrm		return status;
57341f6b937SDarkWyrm
57441f6b937SDarkWyrm	status = data->AddString("mime_sig", info.signature);
57541f6b937SDarkWyrm	if (status < B_OK)
57641f6b937SDarkWyrm		return status;
57741f6b937SDarkWyrm
578beabca50SAxel Dörfler	return data->AddInt64("_pulse", fPulseRate);
57952a38012Sejakowatz}
580beabca50SAxel Dörfler
581beabca50SAxel Dörfler
582beabca50SAxel Dörflerstatus_t
583beabca50SAxel DörflerBApplication::InitCheck() const
58452a38012Sejakowatz{
58552a38012Sejakowatz	return fInitError;
58652a38012Sejakowatz}
587beabca50SAxel Dörfler
588beabca50SAxel Dörfler
589beabca50SAxel Dörflerthread_id
590beabca50SAxel DörflerBApplication::Run()
59152a38012Sejakowatz{
59272f5d860SAxel Dörfler	if (fInitError != B_OK)
59372f5d860SAxel Dörfler		return fInitError;
59472f5d860SAxel Dörfler
595151343ebSAdrien Destugues	Loop();
596c7f20c70SIngo Weinhold
59772f5d860SAxel Dörfler	delete fPulseRunner;
598c01f349eSAxel Dörfler	return fThread;
59952a38012Sejakowatz}
600beabca50SAxel Dörfler
601beabca50SAxel Dörfler
602beabca50SAxel Dörflervoid
603beabca50SAxel DörflerBApplication::Quit()
60452a38012Sejakowatz{
60598207f6fSIngo Weinhold	bool unlock = false;
606c7f20c70SIngo Weinhold	if (!IsLocked()) {
607be902ac4SJohn Scipione		const char* name = Name();
608be902ac4SJohn Scipione		if (name == NULL)
609c7f20c70SIngo Weinhold			name = "no-name";
610be902ac4SJohn Scipione
61198207f6fSIngo Weinhold		printf("ERROR - you must Lock the application object before calling "
6129be774b5SAlex Smith			   "Quit(), team=%" B_PRId32 ", looper=%s\n", Team(), name);
61398207f6fSIngo Weinhold		unlock = true;
61498207f6fSIngo Weinhold		if (!Lock())
61598207f6fSIngo Weinhold			return;
616c7f20c70SIngo Weinhold	}
617c7f20c70SIngo Weinhold	// Delete the object, if not running only.
61898207f6fSIngo Weinhold	if (!fRunCalled) {
619c7f20c70SIngo Weinhold		delete this;
620c01f349eSAxel Dörfler	} else if (find_thread(NULL) != fThread) {
62172f5d860SAxel Dörfler// ToDo: why shouldn't we set fTerminating to true directly in this case?
62298207f6fSIngo Weinhold		// We are not the looper thread.
62398207f6fSIngo Weinhold		// We push a _QUIT_ into the queue.
62498207f6fSIngo Weinhold		// TODO: When BLooper::AddMessage() is done, use that instead of
62598207f6fSIngo Weinhold		// PostMessage()??? This would overtake messages that are still at
62698207f6fSIngo Weinhold		// the port.
62798207f6fSIngo Weinhold		// NOTE: We must not unlock here -- otherwise we had to re-lock, which
62898207f6fSIngo Weinhold		// may not work. This is bad, since, if the port is full, it
62998207f6fSIngo Weinhold		// won't get emptier, as the looper thread needs to lock the object
63098207f6fSIngo Weinhold		// before dispatching messages.
63198207f6fSIngo Weinhold		while (PostMessage(_QUIT_, this) == B_WOULD_BLOCK)
63298207f6fSIngo Weinhold			snooze(10000);
63398207f6fSIngo Weinhold	} else {
63498207f6fSIngo Weinhold		// We are the looper thread.
63598207f6fSIngo Weinhold		// Just set fTerminating to true which makes us fall through the
63698207f6fSIngo Weinhold		// message dispatching loop and return from Run().
63798207f6fSIngo Weinhold		fTerminating = true;
63898207f6fSIngo Weinhold	}
639be902ac4SJohn Scipione
64098207f6fSIngo Weinhold	// If we had to lock the object, unlock now.
64198207f6fSIngo Weinhold	if (unlock)
64298207f6fSIngo Weinhold		Unlock();
64352a38012Sejakowatz}
644beabca50SAxel Dörfler
645beabca50SAxel Dörfler
646beabca50SAxel Dörflerbool
647beabca50SAxel DörflerBApplication::QuitRequested()
64852a38012Sejakowatz{
6499a44fdc9SAxel Dörfler	return _QuitAllWindows(false);
650f6dc8f8dSStefano Ceccherini}
651beabca50SAxel Dörfler
652beabca50SAxel Dörfler
653beabca50SAxel Dörflervoid
654beabca50SAxel DörflerBApplication::Pulse()
65552a38012Sejakowatz{
656c18d8429SAxel Dörfler	// supposed to be implemented by subclasses
65752a38012Sejakowatz}
658beabca50SAxel Dörfler
659beabca50SAxel Dörfler
660beabca50SAxel Dörflervoid
661beabca50SAxel DörflerBApplication::ReadyToRun()
66252a38012Sejakowatz{
663c18d8429SAxel Dörfler	// supposed to be implemented by subclasses
66452a38012Sejakowatz}
665beabca50SAxel Dörfler
666beabca50SAxel Dörfler
667833a5922SStefano Ceccherinivoid
668be902ac4SJohn ScipioneBApplication::MessageReceived(BMessage* message)
66952a38012Sejakowatz{
670833a5922SStefano Ceccherini	switch (message->what) {
6715dccfc19SStefano Ceccherini		case B_COUNT_PROPERTIES:
6725dccfc19SStefano Ceccherini		case B_GET_PROPERTY:
6735dccfc19SStefano Ceccherini		case B_SET_PROPERTY:
674bd6c2601SStefano Ceccherini		{
675bd6c2601SStefano Ceccherini			int32 index;
676bd6c2601SStefano Ceccherini			BMessage specifier;
677bd6c2601SStefano Ceccherini			int32 what;
678be902ac4SJohn Scipione			const char* property = NULL;
679be902ac4SJohn Scipione			if (message->GetCurrentSpecifier(&index, &specifier, &what,
680be902ac4SJohn Scipione					&property) < B_OK
681be902ac4SJohn Scipione				|| !ScriptReceived(message, index, &specifier, what,
682be902ac4SJohn Scipione					property)) {
683bd6c2601SStefano Ceccherini				BLooper::MessageReceived(message);
684be902ac4SJohn Scipione			}
6855dccfc19SStefano Ceccherini			break;
686bd6c2601SStefano Ceccherini		}
687beabca50SAxel Dörfler
688833a5922SStefano Ceccherini		case B_SILENT_RELAUNCH:
689aa389c6bSAxel Dörfler			// Sent to a B_SINGLE_LAUNCH application when it's launched again
690aa389c6bSAxel Dörfler			// (see _InitData())
691833a5922SStefano Ceccherini			be_roster->ActivateApp(Team());
692aa389c6bSAxel Dörfler			break;
693aa389c6bSAxel Dörfler
6946c40fc5dSczeidler		case kMsgAppServerRestarted:
6956c40fc5dSczeidler			_ReconnectToServer();
6966c40fc5dSczeidler			break;
6978e2140faSAxel Dörfler
6988e2140faSAxel Dörfler		case kMsgDeleteServerMemoryArea:
6998e2140faSAxel Dörfler		{
7008e2140faSAxel Dörfler			int32 serverArea;
7018e2140faSAxel Dörfler			if (message->FindInt32("server area", &serverArea) == B_OK) {
7028e2140faSAxel Dörfler				// The link is not used, but we currently borrow its lock
7038e2140faSAxel Dörfler				BPrivate::AppServerLink link;
7048e2140faSAxel Dörfler				fServerAllocator->RemoveArea(serverArea);
7058e2140faSAxel Dörfler			}
7068e2140faSAxel Dörfler			break;
7076c40fc5dSczeidler		}
7086c40fc5dSczeidler
7095dccfc19SStefano Ceccherini		default:
710833a5922SStefano Ceccherini			BLooper::MessageReceived(message);
7115dccfc19SStefano Ceccherini	}
71252a38012Sejakowatz}
713beabca50SAxel Dörfler
714beabca50SAxel Dörfler
715beabca50SAxel Dörflervoid
716be902ac4SJohn ScipioneBApplication::ArgvReceived(int32 argc, char** argv)
71752a38012Sejakowatz{
718beabca50SAxel Dörfler	// supposed to be implemented by subclasses
71952a38012Sejakowatz}
720beabca50SAxel Dörfler
721beabca50SAxel Dörfler
722beabca50SAxel Dörflervoid
723beabca50SAxel DörflerBApplication::AppActivated(bool active)
72452a38012Sejakowatz{
725beabca50SAxel Dörfler	// supposed to be implemented by subclasses
72652a38012Sejakowatz}
727beabca50SAxel Dörfler
728beabca50SAxel Dörfler
729beabca50SAxel Dörflervoid
730be902ac4SJohn ScipioneBApplication::RefsReceived(BMessage* message)
73152a38012Sejakowatz{
732beabca50SAxel Dörfler	// supposed to be implemented by subclasses
73352a38012Sejakowatz}
734beabca50SAxel Dörfler
735beabca50SAxel Dörfler
736beabca50SAxel Dörflervoid
737beabca50SAxel DörflerBApplication::AboutRequested()
73852a38012Sejakowatz{
739c254f99cSAdrien Destugues	// supposed to be implemented by subclasses
74052a38012Sejakowatz}
741beabca50SAxel Dörfler
742beabca50SAxel Dörfler
743be902ac4SJohn ScipioneBHandler*
744be902ac4SJohn ScipioneBApplication::ResolveSpecifier(BMessage* message, int32 index,
745be902ac4SJohn Scipione	BMessage* specifier, int32 what, const char* property)
74652a38012Sejakowatz{
7471f8172a4SJérôme Duval	BPropertyInfo propInfo(sPropertyInfo);
748e91315aaSJérôme Duval	status_t err = B_OK;
749e91315aaSJérôme Duval	uint32 data;
75037d8f330SAxel Dörfler
75137d8f330SAxel Dörfler	if (propInfo.FindMatch(message, 0, specifier, what, property, &data) >= 0) {
752e91315aaSJérôme Duval		switch (data) {
75337d8f330SAxel Dörfler			case kWindowByIndex:
75437d8f330SAxel Dörfler			{
75537d8f330SAxel Dörfler				int32 index;
75637d8f330SAxel Dörfler				err = specifier->FindInt32("index", &index);
757e91315aaSJérôme Duval				if (err != B_OK)
758e91315aaSJérôme Duval					break;
75937d8f330SAxel Dörfler
760e91315aaSJérôme Duval				if (what == B_REVERSE_INDEX_SPECIFIER)
76137d8f330SAxel Dörfler					index = CountWindows() - index;
76237d8f330SAxel Dörfler
763be902ac4SJohn Scipione				BWindow* window = WindowAt(index);
76437d8f330SAxel Dörfler				if (window != NULL) {
765e91315aaSJérôme Duval					message->PopSpecifier();
76637d8f330SAxel Dörfler					BMessenger(window).SendMessage(message);
76737d8f330SAxel Dörfler				} else
76837d8f330SAxel Dörfler					err = B_BAD_INDEX;
769e91315aaSJérôme Duval				break;
770e91315aaSJérôme Duval			}
77137d8f330SAxel Dörfler
77237d8f330SAxel Dörfler			case kWindowByName:
77337d8f330SAxel Dörfler			{
774be902ac4SJohn Scipione				const char* name;
775e91315aaSJérôme Duval				err = specifier->FindString("name", &name);
776e91315aaSJérôme Duval				if (err != B_OK)
777e91315aaSJérôme Duval					break;
77837d8f330SAxel Dörfler
77937d8f330SAxel Dörfler				for (int32 i = 0;; i++) {
780be902ac4SJohn Scipione					BWindow* window = WindowAt(i);
78137d8f330SAxel Dörfler					if (window == NULL) {
78237d8f330SAxel Dörfler						err = B_NAME_NOT_FOUND;
78337d8f330SAxel Dörfler						break;
78437d8f330SAxel Dörfler					}
785be902ac4SJohn Scipione					if (window->Title() != NULL && !strcmp(window->Title(),
786be902ac4SJohn Scipione							name)) {
78737d8f330SAxel Dörfler						message->PopSpecifier();
78837d8f330SAxel Dörfler						BMessenger(window).SendMessage(message);
78937d8f330SAxel Dörfler						break;
790e91315aaSJérôme Duval					}
791e91315aaSJérôme Duval				}
792e91315aaSJérôme Duval				break;
793e91315aaSJérôme Duval			}
79437d8f330SAxel Dörfler
79537d8f330SAxel Dörfler			case kLooperByIndex:
79637d8f330SAxel Dörfler			{
79737d8f330SAxel Dörfler				int32 index;
79837d8f330SAxel Dörfler				err = specifier->FindInt32("index", &