Application.cpp revision dd10337f
1dd10337fSAxel Dörfler/*
2dd10337fSAxel Dörfler * Copyright 2001-2005, Haiku.
3dd10337fSAxel Dörfler * Distributed under the terms of the MIT License.
4dd10337fSAxel Dörfler *
5dd10337fSAxel Dörfler * Authors:
6dd10337fSAxel Dörfler *		Erik Jaesler (erik@cgsoftware.com)
7dd10337fSAxel Dörfler */
8dd10337fSAxel Dörfler
9dd10337fSAxel Dörfler
1073a2b29fSIngo Weinhold#include <new>
11c7f20c70SIngo Weinhold#include <stdio.h>
12ca8ed922SStefano Ceccherini#include <stdlib.h>
1373a2b29fSIngo Weinhold#include <string.h>
1452a38012Sejakowatz
1553b9eef8SStefano Ceccherini#include <Alert.h>
1673a2b29fSIngo Weinhold#include <AppFileInfo.h>
1752a38012Sejakowatz#include <Application.h>
188a526591SIngo Weinhold#include <AppMisc.h>
19af34fbf1SAxel Dörfler#include <MessageRunner.h>
20c7f20c70SIngo Weinhold#include <Cursor.h>
21a8fc5954SStefano Ceccherini#include <Debug.h>
2273a2b29fSIngo Weinhold#include <Entry.h>
2373a2b29fSIngo Weinhold#include <File.h>
24c7f20c70SIngo Weinhold#include <Locker.h>
2573a2b29fSIngo Weinhold#include <Path.h>
26b1698c8eSejakowatz#include <PropertyInfo.h>
27c7f20c70SIngo Weinhold#include <RegistrarDefs.h>
286cd5d5b1SStefano Ceccherini#include <Resources.h>
29c7f20c70SIngo Weinhold#include <Roster.h>
302ed834e3SIngo Weinhold#include <RosterPrivate.h>
31ebbcbbcaSejakowatz#include <Window.h>
3252a38012Sejakowatz
3341f6b937SDarkWyrm#include <AppServerLink.h>
34ebbcbbcaSejakowatz#include <LooperList.h>
3586832512SStefano Ceccherini#include <MenuWindow.h>
36ebbcbbcaSejakowatz#include <ObjectLocker.h>
37591d280eSDarkWyrm#include <PortLink.h>
3841f6b937SDarkWyrm#include <ServerProtocol.h>
396542ca9bSStefano Ceccherini
4072f5d860SAxel Dörflerusing namespace BPrivate;
4152a38012Sejakowatz
4252a38012Sejakowatz// Globals ---------------------------------------------------------------------
43af34fbf1SAxel DörflerBApplication *be_app = NULL;
44af34fbf1SAxel DörflerBMessenger be_app_messenger;
4552a38012Sejakowatz
46beabca50SAxel DörflerBResources *BApplication::_app_resources = NULL;
47beabca50SAxel DörflerBLocker BApplication::_app_resources_lock("_app_resources_lock");
4852a38012Sejakowatz
4941f6b937SDarkWyrm
50dd10337fSAxel Dörflerstatic property_info sPropertyInfo[] = {
51ebbcbbcaSejakowatz	{
52ebbcbbcaSejakowatz		"Window",
53beabca50SAxel Dörfler		{},
54beabca50SAxel Dörfler		{B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER},
55beabca50SAxel Dörfler		NULL, 0,
56beabca50SAxel Dörfler		{},
57beabca50SAxel Dörfler		{},
58beabca50SAxel Dörfler		{}
59ebbcbbcaSejakowatz	},
60ebbcbbcaSejakowatz	{
61ebbcbbcaSejakowatz		"Window",
62beabca50SAxel Dörfler		{},
63beabca50SAxel Dörfler		{B_NAME_SPECIFIER},
64beabca50SAxel Dörfler		NULL, 1,
65beabca50SAxel Dörfler		{},
66beabca50SAxel Dörfler		{},
67beabca50SAxel Dörfler		{}
68ebbcbbcaSejakowatz	},
69ebbcbbcaSejakowatz	{
70ebbcbbcaSejakowatz		"Looper",
71beabca50SAxel Dörfler		{},
72beabca50SAxel Dörfler		{B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER},
73beabca50SAxel Dörfler		NULL, 2,
74beabca50SAxel Dörfler		{},
75beabca50SAxel Dörfler		{},
76beabca50SAxel Dörfler		{}
77ebbcbbcaSejakowatz	},
78ebbcbbcaSejakowatz	{
79ebbcbbcaSejakowatz		"Looper",
80beabca50SAxel Dörfler		{},
81beabca50SAxel Dörfler		{B_ID_SPECIFIER},
82beabca50SAxel Dörfler		NULL, 3,
83beabca50SAxel Dörfler		{},
84beabca50SAxel Dörfler		{},
85beabca50SAxel Dörfler		{}
86ebbcbbcaSejakowatz	},
87ebbcbbcaSejakowatz	{
88ebbcbbcaSejakowatz		"Looper",
89beabca50SAxel Dörfler		{},
90beabca50SAxel Dörfler		{B_NAME_SPECIFIER},
91beabca50SAxel Dörfler		NULL, 4,
92beabca50SAxel Dörfler		{},
93beabca50SAxel Dörfler		{},
94beabca50SAxel Dörfler		{}
95ebbcbbcaSejakowatz	},
96ebbcbbcaSejakowatz	{
97ebbcbbcaSejakowatz		"Name",
98beabca50SAxel Dörfler		{B_GET_PROPERTY},
99beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
100beabca50SAxel Dörfler		NULL, 5,
101beabca50SAxel Dörfler		{B_STRING_TYPE},
102beabca50SAxel Dörfler		{},
103beabca50SAxel Dörfler		{}
104ebbcbbcaSejakowatz	},
105ebbcbbcaSejakowatz	{
106ebbcbbcaSejakowatz		"Window",
107beabca50SAxel Dörfler		{B_COUNT_PROPERTIES},
108beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
109beabca50SAxel Dörfler		NULL, 5,
110beabca50SAxel Dörfler		{B_INT32_TYPE},
111beabca50SAxel Dörfler		{},
112beabca50SAxel Dörfler		{}
113ebbcbbcaSejakowatz	},
114ebbcbbcaSejakowatz	{
115ebbcbbcaSejakowatz		"Loopers",
116beabca50SAxel Dörfler		{B_GET_PROPERTY},
117beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
118beabca50SAxel Dörfler		NULL, 5,
119beabca50SAxel Dörfler		{B_MESSENGER_TYPE},
120beabca50SAxel Dörfler		{},
121beabca50SAxel Dörfler		{}
122ebbcbbcaSejakowatz	},
123ebbcbbcaSejakowatz	{
124ebbcbbcaSejakowatz		"Windows",
125beabca50SAxel Dörfler		{B_GET_PROPERTY},
126beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
127beabca50SAxel Dörfler		NULL, 5,
128beabca50SAxel Dörfler		{B_MESSENGER_TYPE},
129beabca50SAxel Dörfler		{},
130beabca50SAxel Dörfler		{}
131ebbcbbcaSejakowatz	},
132ebbcbbcaSejakowatz	{
133ebbcbbcaSejakowatz		"Looper",
134beabca50SAxel Dörfler		{B_COUNT_PROPERTIES},
135beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
136beabca50SAxel Dörfler		NULL, 5,
137beabca50SAxel Dörfler		{B_INT32_TYPE},
138beabca50SAxel Dörfler		{},
139beabca50SAxel Dörfler		{}
140ebbcbbcaSejakowatz	},
141ebbcbbcaSejakowatz	{}
1422284462cSejakowatz};
1432284462cSejakowatz
14473a2b29fSIngo Weinhold// argc/argv
14573a2b29fSIngo Weinholdextern const int __libc_argc;
14673a2b29fSIngo Weinholdextern const char * const *__libc_argv;
14752a38012Sejakowatz
148c7f20c70SIngo Weinhold
149c7f20c70SIngo Weinhold// debugging
15001225b39SIngo Weinhold//#define DBG(x) x
15101225b39SIngo Weinhold#define DBG(x)
152c7f20c70SIngo Weinhold#define OUT	printf
153c7f20c70SIngo Weinhold
154c7f20c70SIngo Weinhold
15573a2b29fSIngo Weinhold// prototypes of helper functions
15673a2b29fSIngo Weinholdstatic const char* looper_name_for(const char *signature);
1579986313cSIngo Weinholdstatic status_t check_app_signature(const char *signature);
158bee72328SAxel Dörflerstatic void fill_argv_message(BMessage &message);
159c7f20c70SIngo Weinhold
160beabca50SAxel Dörfler
161beabca50SAxel DörflerBApplication::BApplication(const char *signature)
162af34fbf1SAxel Dörfler	: BLooper(looper_name_for(signature))
16352a38012Sejakowatz{
164c7f20c70SIngo Weinhold	InitData(signature, NULL);
16552a38012Sejakowatz}
166beabca50SAxel Dörfler
167beabca50SAxel Dörfler
168af34fbf1SAxel DörflerBApplication::BApplication(const char *signature, status_t *_error)
169af34fbf1SAxel Dörfler	: BLooper(looper_name_for(signature))
17052a38012Sejakowatz{
171af34fbf1SAxel Dörfler	InitData(signature, _error);
17252a38012Sejakowatz}
173beabca50SAxel Dörfler
174beabca50SAxel Dörfler
175c18d8429SAxel DörflerBApplication::BApplication(BMessage *data)
176c18d8429SAxel Dörfler	// Note: BeOS calls the private BLooper(int32, port_id, const char *)
177c18d8429SAxel Dörfler	// constructor here, test if it's needed
178c18d8429SAxel Dörfler	: BLooper(looper_name_for(NULL))
179c18d8429SAxel Dörfler{
180c18d8429SAxel Dörfler	const char *signature = NULL;
181c18d8429SAxel Dörfler	data->FindString("mime_sig", &signature);
182c18d8429SAxel Dörfler
183c18d8429SAxel Dörfler	InitData(signature, NULL);
184c18d8429SAxel Dörfler
185c18d8429SAxel Dörfler	bigtime_t pulseRate;
186c18d8429SAxel Dörfler	if (data->FindInt64("_pulse", &pulseRate) == B_OK)
187c18d8429SAxel Dörfler		SetPulseRate(pulseRate);
188c18d8429SAxel Dörfler
189c18d8429SAxel Dörfler}
190c18d8429SAxel Dörfler
191c18d8429SAxel Dörfler
192c18d8429SAxel DörflerBApplication::BApplication(uint32 signature)
193c18d8429SAxel Dörfler{
194c18d8429SAxel Dörfler}
195c18d8429SAxel Dörfler
196c18d8429SAxel Dörfler
197c18d8429SAxel DörflerBApplication::BApplication(const BApplication &rhs)
198c18d8429SAxel Dörfler{
199c18d8429SAxel Dörfler}
200c18d8429SAxel Dörfler
201c18d8429SAxel Dörfler
20252a38012SejakowatzBApplication::~BApplication()
20352a38012Sejakowatz{
20472f5d860SAxel Dörfler	Lock();
205f28a6f70SAdi Oanca
20672f5d860SAxel Dörfler	// tell all loopers(usually windows) to quit. Also, wait for them.
20772f5d860SAxel Dörfler	quit_all_windows(true);
208f28a6f70SAdi Oanca
209dc3ebdecSAdi Oanca	// unregister from the roster
210dc3ebdecSAdi Oanca	BRoster::Private().RemoveApp(Team());
211dc3ebdecSAdi Oanca
212044be4e2SIngo Weinhold#ifndef RUN_WITHOUT_APP_SERVER
2133ceb31b9SDarkWyrm	// tell app_server we're quitting...
214dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
2153ceb31b9SDarkWyrm	link.StartMessage(B_QUIT_REQUESTED);
216f28a6f70SAdi Oanca	link.Flush();
217044be4e2SIngo Weinhold#endif	// RUN_WITHOUT_APP_SERVER
218f28a6f70SAdi Oanca
219dd10337fSAxel Dörfler	delete_port(fServerLink->SenderPort());
220dd10337fSAxel Dörfler	delete_port(fServerLink->ReceiverPort());
221dd10337fSAxel Dörfler	delete fServerLink;
22272f5d860SAxel Dörfler
22372f5d860SAxel Dörfler	// uninitialize be_app, the be_app_messenger is invalidated automatically
2248a526591SIngo Weinhold	be_app = NULL;
22552a38012Sejakowatz}
226beabca50SAxel Dörfler
227beabca50SAxel Dörfler
228c18d8429SAxel DörflerBApplication &
229c18d8429SAxel DörflerBApplication::operator=(const BApplication &rhs)
23052a38012Sejakowatz{
231c18d8429SAxel Dörfler	return *this;
232c18d8429SAxel Dörfler}
233beabca50SAxel Dörfler
23441f6b937SDarkWyrm
235c18d8429SAxel Dörflervoid
236c18d8429SAxel DörflerBApplication::InitData(const char *signature, status_t *_error)
237c18d8429SAxel Dörfler{
238dd10337fSAxel Dörfler	DBG(OUT("BApplication::InitData(`%s', %p)\n", signature, _error));
239c18d8429SAxel Dörfler	// check whether there exists already an application
240c18d8429SAxel Dörfler	if (be_app)
241c18d8429SAxel Dörfler		debugger("2 BApplication objects were created. Only one is allowed.");
242c18d8429SAxel Dörfler
243dd10337fSAxel Dörfler	fServerLink = new BPrivate::PortLink(-1, -1);
244c18d8429SAxel Dörfler	fServerHeap = NULL;
245c18d8429SAxel Dörfler	fInitialWorkspace = 0;
246c18d8429SAxel Dörfler	fDraggedMessage = NULL;
247c18d8429SAxel Dörfler	fReadyToRunCalled = false;
248c18d8429SAxel Dörfler
249c18d8429SAxel Dörfler	// initially, there is no pulse
250c18d8429SAxel Dörfler	fPulseRunner = NULL;
251c18d8429SAxel Dörfler	fPulseRate = 0;
252c18d8429SAxel Dörfler
253c18d8429SAxel Dörfler	// check signature
254c18d8429SAxel Dörfler	fInitError = check_app_signature(signature);
255c18d8429SAxel Dörfler	fAppName = signature;
256c18d8429SAxel Dörfler
257c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_REGISTRAR
258c18d8429SAxel Dörfler	bool isRegistrar = signature
259c18d8429SAxel Dörfler		&& !strcasecmp(signature, kRegistrarSignature);
260c18d8429SAxel Dörfler	// get team and thread
261c18d8429SAxel Dörfler	team_id team = Team();
262c18d8429SAxel Dörfler	thread_id thread = BPrivate::main_thread_for(team);
263c18d8429SAxel Dörfler#endif
264c18d8429SAxel Dörfler
265c18d8429SAxel Dörfler	// get app executable ref
266c18d8429SAxel Dörfler	entry_ref ref;
26784de162bSIngo Weinhold	if (fInitError == B_OK) {
268c18d8429SAxel Dörfler		fInitError = BPrivate::get_app_ref(&ref);
26984de162bSIngo Weinhold		if (fInitError != B_OK) {
27084de162bSIngo Weinhold			DBG(OUT("BApplication::InitData(): Failed to get app ref: %s\n",
27184de162bSIngo Weinhold				strerror(fInitError)));
27284de162bSIngo Weinhold		}
27384de162bSIngo Weinhold	}
274c18d8429SAxel Dörfler
275c18d8429SAxel Dörfler	// get the BAppFileInfo and extract the information we need
276c18d8429SAxel Dörfler	uint32 appFlags = B_REG_DEFAULT_APP_FLAGS;
277c18d8429SAxel Dörfler	if (fInitError == B_OK) {
278c18d8429SAxel Dörfler		BAppFileInfo fileInfo;
279c18d8429SAxel Dörfler		BFile file(&ref, B_READ_ONLY);
280c18d8429SAxel Dörfler		fInitError = fileInfo.SetTo(&file);
281c18d8429SAxel Dörfler		if (fInitError == B_OK) {
282c18d8429SAxel Dörfler			fileInfo.GetAppFlags(&appFlags);
283ca8ed922SStefano Ceccherini			char appFileSignature[B_MIME_TYPE_LENGTH];
284c18d8429SAxel Dörfler			// compare the file signature and the supplied signature
285c18d8429SAxel Dörfler			if (fileInfo.GetSignature(appFileSignature) == B_OK
286c18d8429SAxel Dörfler				&& strcasecmp(appFileSignature, signature) != 0) {
287c18d8429SAxel Dörfler				printf("Signature in rsrc doesn't match constructor arg. (%s, %s)\n",
288c18d8429SAxel Dörfler					signature, appFileSignature);
289c18d8429SAxel Dörfler			}
29084de162bSIngo Weinhold		} else {
29184de162bSIngo Weinhold			DBG(OUT("BApplication::InitData(): Failed to get info from: "
29284de162bSIngo Weinhold				"BAppFileInfo: %s\n", strerror(fInitError)));
293c18d8429SAxel Dörfler		}
294c18d8429SAxel Dörfler	}
295c18d8429SAxel Dörfler
296c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_REGISTRAR
297c18d8429SAxel Dörfler	// check whether be_roster is valid
298c18d8429SAxel Dörfler	if (fInitError == B_OK && !isRegistrar
299c18d8429SAxel Dörfler		&& !BRoster::Private().IsMessengerValid(false)) {
300c18d8429SAxel Dörfler		printf("FATAL: be_roster is not valid. Is the registrar running?\n");
301c18d8429SAxel Dörfler		fInitError = B_NO_INIT;
302c18d8429SAxel Dörfler	}
303c18d8429SAxel Dörfler
304c18d8429SAxel Dörfler	// check whether or not we are pre-registered
305c18d8429SAxel Dörfler	bool preRegistered = false;
306c18d8429SAxel Dörfler	app_info appInfo;
307c18d8429SAxel Dörfler	if (fInitError == B_OK && !isRegistrar) {
308c18d8429SAxel Dörfler		preRegistered = BRoster::Private().IsAppPreRegistered(&ref, team,
309c18d8429SAxel Dörfler							&appInfo);
310c18d8429SAxel Dörfler	}
311c18d8429SAxel Dörfler	if (preRegistered) {
312c18d8429SAxel Dörfler		// we are pre-registered => the app info has been filled in
313c18d8429SAxel Dörfler		// Check whether we need to replace the looper port with a port
314c18d8429SAxel Dörfler		// created by the roster.
315c18d8429SAxel Dörfler		if (appInfo.port >= 0 && appInfo.port != fMsgPort) {
316c18d8429SAxel Dörfler			delete_port(fMsgPort);
317c18d8429SAxel Dörfler			fMsgPort = appInfo.port;
318c18d8429SAxel Dörfler		} else
319c18d8429SAxel Dörfler			appInfo.port = fMsgPort;
320c18d8429SAxel Dörfler		// check the signature and correct it, if necessary
321c18d8429SAxel Dörfler		if (strcasecmp(appInfo.signature, fAppName))
322c18d8429SAxel Dörfler			BRoster::Private().SetSignature(team, fAppName);
323c18d8429SAxel Dörfler		// complete the registration
324c18d8429SAxel Dörfler		fInitError = BRoster::Private().CompleteRegistration(team, thread,
325c18d8429SAxel Dörfler						appInfo.port);
326c18d8429SAxel Dörfler	} else if (fInitError == B_OK) {
327c18d8429SAxel Dörfler		// not pre-registered -- try to register the application
328c18d8429SAxel Dörfler		team_id otherTeam = -1;
329c18d8429SAxel Dörfler		// the registrar must not register
330c18d8429SAxel Dörfler		if (!isRegistrar) {
331c18d8429SAxel Dörfler			fInitError = BRoster::Private().AddApplication(signature, &ref,
332c18d8429SAxel Dörfler				appFlags, team, thread, fMsgPort, true, NULL, &otherTeam);
33384de162bSIngo Weinhold			if (fInitError != B_OK) {
33484de162bSIngo Weinhold				DBG(OUT("BApplication::InitData(): Failed to add app: %s\n",
33584de162bSIngo Weinhold					strerror(fInitError)));
33684de162bSIngo Weinhold			}
337c18d8429SAxel Dörfler		}
338c18d8429SAxel Dörfler		if (fInitError == B_ALREADY_RUNNING) {
339c18d8429SAxel Dörfler			// An instance is already running and we asked for
340c18d8429SAxel Dörfler			// single/exclusive launch. Send our argv to the running app.
341c18d8429SAxel Dörfler			// Do that only, if the app is NOT B_ARGV_ONLY.
342c18d8429SAxel Dörfler			if (otherTeam >= 0 && __libc_argc > 1) {
343c18d8429SAxel Dörfler				app_info otherAppInfo;
344c18d8429SAxel Dörfler				if (be_roster->GetRunningAppInfo(otherTeam, &otherAppInfo) == B_OK
345c18d8429SAxel Dörfler					&& !(otherAppInfo.flags & B_ARGV_ONLY)) {
346c18d8429SAxel Dörfler					// create an B_ARGV_RECEIVED message
347c18d8429SAxel Dörfler					BMessage argvMessage(B_ARGV_RECEIVED);
348bee72328SAxel Dörfler					fill_argv_message(argvMessage);
349c18d8429SAxel Dörfler
350c18d8429SAxel Dörfler					// replace the first argv string with the path of the
351c18d8429SAxel Dörfler					// other application
352c18d8429SAxel Dörfler					BPath path;
353c18d8429SAxel Dörfler					if (path.SetTo(&otherAppInfo.ref) == B_OK)
354c18d8429SAxel Dörfler						argvMessage.ReplaceString("argv", 0, path.Path());
355c18d8429SAxel Dörfler
356c18d8429SAxel Dörfler					// send the message
357c18d8429SAxel Dörfler					BMessenger(NULL, otherTeam).SendMessage(&argvMessage);
358c18d8429SAxel Dörfler				}
359c18d8429SAxel Dörfler			}
360c18d8429SAxel Dörfler		} else if (fInitError == B_OK) {
361c18d8429SAxel Dörfler			// the registrations was successful
362c18d8429SAxel Dörfler			// Create a B_ARGV_RECEIVED message and send it to ourselves.
363c18d8429SAxel Dörfler			// Do that even, if we are B_ARGV_ONLY.
364c18d8429SAxel Dörfler			// TODO: When BLooper::AddMessage() is done, use that instead of
365c18d8429SAxel Dörfler			// PostMessage().
366c18d8429SAxel Dörfler
367c18d8429SAxel Dörfler			DBG(OUT("info: BApplication sucessfully registered.\n"));
368c18d8429SAxel Dörfler
369c18d8429SAxel Dörfler			if (__libc_argc > 1) {
370c18d8429SAxel Dörfler				BMessage argvMessage(B_ARGV_RECEIVED);
371bee72328SAxel Dörfler				fill_argv_message(argvMessage);
372c18d8429SAxel Dörfler				PostMessage(&argvMessage, this);
373c18d8429SAxel Dörfler			}
374c18d8429SAxel Dörfler			// send a B_READY_TO_RUN message as well
375c18d8429SAxel Dörfler			PostMessage(B_READY_TO_RUN, this);
376c18d8429SAxel Dörfler		} else if (fInitError > B_ERRORS_END) {
377c18d8429SAxel Dörfler			// Registrar internal errors shouldn't fall into the user's hands.
378c18d8429SAxel Dörfler			fInitError = B_ERROR;
379c18d8429SAxel Dörfler		}
380c18d8429SAxel Dörfler	}
3814e51dee8SDarkWyrm#else
3824e51dee8SDarkWyrm	// We need to have ReadyToRun called even when we're not using the registrar
3834e51dee8SDarkWyrm	PostMessage(B_READY_TO_RUN, this);
3844e51dee8SDarkWyrm#endif	// ifndef RUN_WITHOUT_REGISTRAR
385c18d8429SAxel Dörfler
386c18d8429SAxel Dörfler	// TODO: Not completely sure about the order, but this should be close.
387c18d8429SAxel Dörfler
388c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_APP_SERVER
389c18d8429SAxel Dörfler	// An app_server connection is necessary for a lot of stuff, so get that first.
390c18d8429SAxel Dörfler	if (fInitError == B_OK)
391c18d8429SAxel Dörfler		connect_to_app_server();
392c18d8429SAxel Dörfler	if (fInitError == B_OK)
393c18d8429SAxel Dörfler		setup_server_heaps();
394c18d8429SAxel Dörfler#endif	// RUN_WITHOUT_APP_SERVER
395c18d8429SAxel Dörfler
396c18d8429SAxel Dörfler	// init be_app and be_app_messenger
397c18d8429SAxel Dörfler	if (fInitError == B_OK) {
398c18d8429SAxel Dörfler		be_app = this;
399c18d8429SAxel Dörfler		be_app_messenger = BMessenger(NULL, this);
400c18d8429SAxel Dörfler	}
401dd10337fSAxel Dörfler
402c18d8429SAxel Dörfler	// set the BHandler's name
403c18d8429SAxel Dörfler	if (fInitError == B_OK)
404c18d8429SAxel Dörfler		SetName(ref.name);
405c18d8429SAxel Dörfler	// create meta MIME
406c18d8429SAxel Dörfler	if (fInitError == B_OK) {
407c18d8429SAxel Dörfler		BPath path;
408c18d8429SAxel Dörfler		if (path.SetTo(&ref) == B_OK)
409c18d8429SAxel Dörfler			create_app_meta_mime(path.Path(), false, true, false);
410c18d8429SAxel Dörfler	}
411c18d8429SAxel Dörfler
412c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_APP_SERVER
4137475dcdfSStefano Ceccherini	// Initialize the IK after we have set be_app because of a construction of a
414dd10337fSAxel Dörfler	// AppServerLink (which depends on be_app) nested inside the call to get_menu_info.
4157475dcdfSStefano Ceccherini	if (fInitError == B_OK)
4167475dcdfSStefano Ceccherini		fInitError = _init_interface_kit_();
417c18d8429SAxel Dörfler	// create global system cursors
418c18d8429SAxel Dörfler	// ToDo: these could have a predefined server token to safe the communication!
419c18d8429SAxel Dörfler	B_CURSOR_SYSTEM_DEFAULT = new BCursor(B_HAND_CURSOR);
420c18d8429SAxel Dörfler	B_CURSOR_I_BEAM = new BCursor(B_I_BEAM_CURSOR);
4212c458b6dSStefano Ceccherini
4222c458b6dSStefano Ceccherini	fInitialWorkspace = current_workspace();
423c18d8429SAxel Dörfler#endif	// RUN_WITHOUT_APP_SERVER
42441f6b937SDarkWyrm
425c18d8429SAxel Dörfler	// Return the error or exit, if there was an error and no error variable
426c18d8429SAxel Dörfler	// has been supplied.
42784de162bSIngo Weinhold	if (_error) {
428c18d8429SAxel Dörfler		*_error = fInitError;
42984de162bSIngo Weinhold	} else if (fInitError != B_OK) {
43084de162bSIngo Weinhold		DBG(OUT("BApplication::InitData() failed: %s\n", strerror(fInitError)));
431c18d8429SAxel Dörfler		exit(0);
43284de162bSIngo Weinhold	}
43384de162bSIngo WeinholdDBG(OUT("BApplication::InitData() done\n"));
43452a38012Sejakowatz}
435beabca50SAxel Dörfler
436beabca50SAxel Dörfler
437beabca50SAxel DörflerBArchivable *
438beabca50SAxel DörflerBApplication::Instantiate(BMessage *data)
43952a38012Sejakowatz{
4405dccfc19SStefano Ceccherini	if (validate_instantiation(data, "BApplication"))
4415dccfc19SStefano Ceccherini		return new BApplication(data);
442beabca50SAxel Dörfler
4435dccfc19SStefano Ceccherini	return NULL;
44452a38012Sejakowatz}
445beabca50SAxel Dörfler
446beabca50SAxel Dörfler
44741f6b937SDarkWyrmstatus_t
448beabca50SAxel DörflerBApplication::Archive(BMessage *data, bool deep) const
44952a38012Sejakowatz{
45041f6b937SDarkWyrm	status_t status = BLooper::Archive(data, deep);
45141f6b937SDarkWyrm	if (status < B_OK)
45241f6b937SDarkWyrm		return status;
45341f6b937SDarkWyrm
45441f6b937SDarkWyrm	app_info info;
45541f6b937SDarkWyrm	status = GetAppInfo(&info);
45641f6b937SDarkWyrm	if (status < B_OK)
45741f6b937SDarkWyrm		return status;
45841f6b937SDarkWyrm
45941f6b937SDarkWyrm	status = data->AddString("mime_sig", info.signature);
46041f6b937SDarkWyrm	if (status < B_OK)
46141f6b937SDarkWyrm		return status;
46241f6b937SDarkWyrm
463beabca50SAxel Dörfler	return data->AddInt64("_pulse", fPulseRate);
46452a38012Sejakowatz}
465beabca50SAxel Dörfler
466beabca50SAxel Dörfler
467beabca50SAxel Dörflerstatus_t
468beabca50SAxel DörflerBApplication::InitCheck() const
46952a38012Sejakowatz{
47052a38012Sejakowatz	return fInitError;
47152a38012Sejakowatz}
472beabca50SAxel Dörfler
473beabca50SAxel Dörfler
474beabca50SAxel Dörflerthread_id
475beabca50SAxel DörflerBApplication::Run()
47652a38012Sejakowatz{
47772f5d860SAxel Dörfler	if (fInitError != B_OK)
47872f5d860SAxel Dörfler		return fInitError;
47972f5d860SAxel Dörfler
480c7f20c70SIngo Weinhold	AssertLocked();
481c7f20c70SIngo Weinhold
4826cd5d5b1SStefano Ceccherini	if (fRunCalled)
4836cd5d5b1SStefano Ceccherini		debugger("BApplication::Run was already called. Can only be called once.");
484c7f20c70SIngo Weinhold
4859986313cSIngo Weinhold	// Note: We need a local variable too (for the return value), since
4869986313cSIngo Weinhold	// fTaskID is cleared by Quit().
48772f5d860SAxel Dörfler// ToDo: actually, it's not clobbered there?!
4889986313cSIngo Weinhold	thread_id thread = fTaskID = find_thread(NULL);
489c7f20c70SIngo Weinhold
490c7f20c70SIngo Weinhold	fRunCalled = true;
491c7f20c70SIngo Weinhold
492c7f20c70SIngo Weinhold	run_task();
493c7f20c70SIngo Weinhold
49472f5d860SAxel Dörfler	delete fPulseRunner;
4959986313cSIngo Weinhold	return thread;
49652a38012Sejakowatz}
497beabca50SAxel Dörfler
498beabca50SAxel Dörfler
499beabca50SAxel Dörflervoid
500beabca50SAxel DörflerBApplication::Quit()
50152a38012Sejakowatz{
50298207f6fSIngo Weinhold	bool unlock = false;
503c7f20c70SIngo Weinhold	if (!IsLocked()) {
504beabca50SAxel Dörfler		const char *name = Name();
505c7f20c70SIngo Weinhold		if (!name)
506c7f20c70SIngo Weinhold			name = "no-name";
50798207f6fSIngo Weinhold		printf("ERROR - you must Lock the application object before calling "
50898207f6fSIngo Weinhold			   "Quit(), team=%ld, looper=%s\n", Team(), name);
50998207f6fSIngo Weinhold		unlock = true;
51098207f6fSIngo Weinhold		if (!Lock())
51198207f6fSIngo Weinhold			return;
512c7f20c70SIngo Weinhold	}
513c7f20c70SIngo Weinhold	// Delete the object, if not running only.
51498207f6fSIngo Weinhold	if (!fRunCalled) {
515c7f20c70SIngo Weinhold		delete this;
51698207f6fSIngo Weinhold	} else if (find_thread(NULL) != fTaskID) {
51772f5d860SAxel Dörfler// ToDo: why shouldn't we set fTerminating to true directly in this case?
51898207f6fSIngo Weinhold		// We are not the looper thread.
51998207f6fSIngo Weinhold		// We push a _QUIT_ into the queue.
52098207f6fSIngo Weinhold		// TODO: When BLooper::AddMessage() is done, use that instead of
52198207f6fSIngo Weinhold		// PostMessage()??? This would overtake messages that are still at
52298207f6fSIngo Weinhold		// the port.
52398207f6fSIngo Weinhold		// NOTE: We must not unlock here -- otherwise we had to re-lock, which
52498207f6fSIngo Weinhold		// may not work. This is bad, since, if the port is full, it
52598207f6fSIngo Weinhold		// won't get emptier, as the looper thread needs to lock the object
52698207f6fSIngo Weinhold		// before dispatching messages.
52798207f6fSIngo Weinhold		while (PostMessage(_QUIT_, this) == B_WOULD_BLOCK)
52898207f6fSIngo Weinhold			snooze(10000);
52998207f6fSIngo Weinhold	} else {
53098207f6fSIngo Weinhold		// We are the looper thread.
53198207f6fSIngo Weinhold		// Just set fTerminating to true which makes us fall through the
53298207f6fSIngo Weinhold		// message dispatching loop and return from Run().
53398207f6fSIngo Weinhold		fTerminating = true;
53498207f6fSIngo Weinhold	}
53598207f6fSIngo Weinhold	// If we had to lock the object, unlock now.
53698207f6fSIngo Weinhold	if (unlock)
53798207f6fSIngo Weinhold		Unlock();
53852a38012Sejakowatz}
539beabca50SAxel Dörfler
540beabca50SAxel Dörfler
541beabca50SAxel Dörflerbool
542beabca50SAxel DörflerBApplication::QuitRequested()
54352a38012Sejakowatz{
54472f5d860SAxel Dörfler	return quit_all_windows(false);
545f6dc8f8dSStefano Ceccherini}
546beabca50SAxel Dörfler
547beabca50SAxel Dörfler
548beabca50SAxel Dörflervoid
549beabca50SAxel DörflerBApplication::Pulse()
55052a38012Sejakowatz{
551c18d8429SAxel Dörfler	// supposed to be implemented by subclasses
55252a38012Sejakowatz}
553beabca50SAxel Dörfler
554beabca50SAxel Dörfler
555beabca50SAxel Dörflervoid
556beabca50SAxel DörflerBApplication::ReadyToRun()
55752a38012Sejakowatz{
558c18d8429SAxel Dörfler	// supposed to be implemented by subclasses
55952a38012Sejakowatz}
560beabca50SAxel Dörfler
561beabca50SAxel Dörfler
562833a5922SStefano Ceccherinivoid
563833a5922SStefano CeccheriniBApplication::MessageReceived(BMessage *message)
56452a38012Sejakowatz{
565833a5922SStefano Ceccherini	switch (message->what) {
5665dccfc19SStefano Ceccherini		case B_COUNT_PROPERTIES:
5675dccfc19SStefano Ceccherini		case B_GET_PROPERTY:
5685dccfc19SStefano Ceccherini		case B_SET_PROPERTY:
569bd6c2601SStefano Ceccherini		{
570bd6c2601SStefano Ceccherini			int32 index;
571bd6c2601SStefano Ceccherini			BMessage specifier;
572bd6c2601SStefano Ceccherini			int32 what;
573bd6c2601SStefano Ceccherini			const char *property = NULL;
574bd6c2601SStefano Ceccherini			bool scriptHandled = false;
575bd6c2601SStefano Ceccherini			if (message->GetCurrentSpecifier(&index, &specifier, &what, &property) == B_OK) {
576bd6c2601SStefano Ceccherini				if (ScriptReceived(message, index, &specifier, what, property))
577bd6c2601SStefano Ceccherini					scriptHandled = true;
578bd6c2601SStefano Ceccherini			}
579bd6c2601SStefano Ceccherini			if (!scriptHandled)
580bd6c2601SStefano Ceccherini				BLooper::MessageReceived(message);
5815dccfc19SStefano Ceccherini			break;
582bd6c2601SStefano Ceccherini		}
583beabca50SAxel Dörfler
584833a5922SStefano Ceccherini		// Bebook says: B_SILENT_RELAUNCH
585833a5922SStefano Ceccherini		// Sent to a single-launch application when it's activated by being launched
586833a5922SStefano Ceccherini		// (for example, if the user double-clicks its icon in Tracker).
587833a5922SStefano Ceccherini		case B_SILENT_RELAUNCH:
588833a5922SStefano Ceccherini			be_roster->ActivateApp(Team());
589833a5922SStefano Ceccherini			// supposed to fall through
5905dccfc19SStefano Ceccherini		default:
591833a5922SStefano Ceccherini			BLooper::MessageReceived(message);
5925dccfc19SStefano Ceccherini			break;
5935dccfc19SStefano Ceccherini	}
59452a38012Sejakowatz}
595beabca50SAxel Dörfler
596beabca50SAxel Dörfler
597beabca50SAxel Dörflervoid
598beabca50SAxel DörflerBApplication::ArgvReceived(int32 argc, char **argv)
59952a38012Sejakowatz{
600beabca50SAxel Dörfler	// supposed to be implemented by subclasses
60152a38012Sejakowatz}
602beabca50SAxel Dörfler
603beabca50SAxel Dörfler
604beabca50SAxel Dörflervoid
605beabca50SAxel DörflerBApplication::AppActivated(bool active)
60652a38012Sejakowatz{
607beabca50SAxel Dörfler	// supposed to be implemented by subclasses
60852a38012Sejakowatz}
609beabca50SAxel Dörfler
610beabca50SAxel Dörfler
611beabca50SAxel Dörflervoid
612beabca50SAxel DörflerBApplication::RefsReceived(BMessage *message)
61352a38012Sejakowatz{
614beabca50SAxel Dörfler	// supposed to be implemented by subclasses
61552a38012Sejakowatz}
616beabca50SAxel Dörfler
617beabca50SAxel Dörfler
618beabca50SAxel Dörflervoid
619beabca50SAxel DörflerBApplication::AboutRequested()
62052a38012Sejakowatz{
62153b9eef8SStefano Ceccherini	thread_info info;
62253b9eef8SStefano Ceccherini	if (get_thread_info(Thread(), &info) == B_OK) {
62353b9eef8SStefano Ceccherini		BAlert *alert = new BAlert("_about_", info.name, "OK");
62453b9eef8SStefano Ceccherini		alert->Go(NULL);
62553b9eef8SStefano Ceccherini	}
62652a38012Sejakowatz}
627beabca50SAxel Dörfler
628beabca50SAxel Dörfler
629beabca50SAxel DörflerBHandler *
630beabca50SAxel DörflerBApplication::ResolveSpecifier(BMessage *msg, int32 index,
631beabca50SAxel Dörfler	BMessage *specifier, int32 form, const char *property)
63252a38012Sejakowatz{
633beabca50SAxel Dörfler	// ToDo: implement ResolveSpecifier()!
634beabca50SAxel Dörfler	return NULL;
63552a38012Sejakowatz}
636beabca50SAxel Dörfler
637beabca50SAxel Dörfler
638beabca50SAxel Dörflervoid
639beabca50SAxel DörflerBApplication::ShowCursor()
64052a38012Sejakowatz{
641dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
6423ceb31b9SDarkWyrm	link.StartMessage(AS_SHOW_CURSOR);
6433ceb31b9SDarkWyrm	link.Flush();
64452a38012Sejakowatz}
645beabca50SAxel Dörfler
646beabca50SAxel Dörfler
647beabca50SAxel Dörflervoid
648beabca50SAxel DörflerBApplication::HideCursor()
64952a38012Sejakowatz{
650dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
6513ceb31b9SDarkWyrm	link.StartMessage(AS_HIDE_CURSOR);
6523ceb31b9SDarkWyrm	link.Flush();
65352a38012Sejakowatz}
654beabca50SAxel Dörfler
655beabca50SAxel Dörfler
656beabca50SAxel Dörflervoid
657beabca50SAxel DörflerBApplication::ObscureCursor()
65852a38012Sejakowatz{
659dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
6603ceb31b9SDarkWyrm	link.StartMessage(AS_OBSCURE_CURSOR);
6613ceb31b9SDarkWyrm	link.Flush();
66252a38012Sejakowatz}
663beabca50SAxel Dörfler
664beabca50SAxel Dörfler
665beabca50SAxel Dörflerbool
666beabca50SAxel DörflerBApplication::IsCursorHidden() const
66752a38012Sejakowatz{
668dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
6693ceb31b9SDarkWyrm	int32 code = SERVER_FALSE;
6703ceb31b9SDarkWyrm	link.StartMessage(AS_QUERY_CURSOR_HIDDEN);
671dd10337fSAxel Dörfler	link.FlushWithReply(code);
672beabca50SAxel Dörfler
673beabca50SAxel Dörfler	return code == SERVER_TRUE;
67452a38012Sejakowatz}
675beabca50SAxel Dörfler
676beabca50SAxel Dörfler
677beabca50SAxel Dörflervoid
678beabca50SAxel DörflerBApplication::SetCursor(const void *cursor)
67952a38012Sejakowatz{
68052a38012Sejakowatz	// BeBook sez: If you want to call SetCursor() without forcing an immediate
68152a38012Sejakowatz	//				sync of the Application Server, you have to use a BCursor.
68252a38012Sejakowatz	// By deductive reasoning, this function forces a sync. =)
68352a38012Sejakowatz	BCursor Cursor(cursor);
68452a38012Sejakowatz	SetCursor(&Cursor, true);
68552a38012Sejakowatz}
686beabca50SAxel Dörfler
687beabca50SAxel Dörfler
688beabca50SAxel Dörflervoid
689beabca50SAxel DörflerBApplication::SetCursor(const BCursor *cursor, bool sync)
69052a38012Sejakowatz{
691dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
692beabca50SAxel Dörfler	int32 code = SERVER_FALSE;
693beabca50SAxel Dörfler
6943ceb31b9SDarkWyrm	link.StartMessage(AS_SET_CURSOR_BCURSOR);
69545799af7SDarkWyrm	link.Attach<bool>(sync);
69645799af7SDarkWyrm	link.Attach<int32>(cursor->m_serverToken);
697beabca50SAxel Dörfler	if (sync)
698dd10337fSAxel Dörfler		link.FlushWithReply(code);
69945799af7SDarkWyrm	else
70045799af7SDarkWyrm		link.Flush();
70152a38012Sejakowatz}
702beabca50SAxel Dörfler
703beabca50SAxel Dörfler
704beabca50SAxel Dörflerint32
705beabca50SAxel DörflerBApplication::CountWindows() const
70652a38012Sejakowatz{
70752a38012Sejakowatz	// BeBook sez: The windows list includes all windows explicitely created by
70852a38012Sejakowatz	//				the app ... but excludes private windows create by Be
70952a38012Sejakowatz	//				classes.
71052a38012Sejakowatz	// I'm taking this to include private menu windows, thus the incl_menus
71152a38012Sejakowatz	// param is false.
71252a38012Sejakowatz	return count_windows(false);
71352a38012Sejakowatz}
714beabca50SAxel Dörfler
715beabca50SAxel Dörfler
716beabca50SAxel DörflerBWindow *
717beabca50SAxel DörflerBApplication::WindowAt(int32 index) const
71852a38012Sejakowatz{
71952a38012Sejakowatz	// BeBook sez: The windows list includes all windows explicitely created by
72052a38012Sejakowatz	//				the app ... but excludes private windows create by Be
72152a38012Sejakowatz	//				classes.
72252a38012Sejakowatz	// I'm taking this to include private menu windows, thus the incl_menus
72352a38012Sejakowatz	// param is false.
72452a38012Sejakowatz	return window_at(index, false);
72552a38012Sejakowatz}
726beabca50SAxel Dörfler
727beabca50SAxel Dörfler
728beabca50SAxel Dörflerint32
729beabca50SAxel DörflerBApplication::CountLoopers() const
73052a38012Sejakowatz{
731ebbcbbcaSejakowatz	BObjectLocker<BLooperList> ListLock(gLooperList);
732ebbcbbcaSejakowatz	if (ListLock.IsLocked())
733ebbcbbcaSejakowatz		return gLooperList.CountLoopers();
734ebbcbbcaSejakowatz
735beabca50SAxel Dörfler	// Some bad, non-specific thing has happened
736beabca50SAxel Dörfler	return B_ERROR;
73752a38012Sejakowatz}
738beabca50SAxel Dörfler
739beabca50SAxel Dörfler
740beabca50SAxel DörflerBLooper *
741beabca50SAxel DörflerBApplication::LooperAt(int32 index) const
74252a38012Sejakowatz{
743ca8ed922SStefano Ceccherini	BLooper *looper = NULL;
744ca8ed922SStefano Ceccherini	BObjectLocker<BLooperList> listLock(gLooperList);
745ca8ed922SStefano Ceccherini	if (listLock.IsLocked())
746ca8ed922SStefano Ceccherini		looper = gLooperList.LooperAt(index);
747ebbcbbcaSejakowatz
748ca8ed922SStefano Ceccherini	return looper;
74952a38012Sejakowatz}
750beabca50SAxel Dörfler
751beabca50SAxel Dörfler
752beabca50SAxel Dörflerbool
753beabca50SAxel DörflerBApplication::IsLaunching() const
75452a38012Sejakowatz{
75552a38012Sejakowatz	return !fReadyToRunCalled;
75652a38012Sejakowatz}
757beabca50SAxel Dörfler
758beabca50SAxel Dörfler
759beabca50SAxel Dörflerstatus_t
760beabca50SAxel DörflerBApplication::GetAppInfo(app_info *info) const
76152a38012Sejakowatz{
76252a38012Sejakowatz	return be_roster->GetRunningAppInfo(be_app->Team(), info);
76352a38012Sejakowatz}
764beabca50SAxel Dörfler
765beabca50SAxel Dörfler
766beabca50SAxel DörflerBResources *
767beabca50SAxel DörflerBApplication::AppResources()
76852a38012Sejakowatz{
7696cd5d5b1SStefano Ceccherini	if (!_app_resources_lock.Lock())
7706cd5d5b1SStefano Ceccherini		return NULL;
771beabca50SAxel Dörfler
7726cd5d5b1SStefano Ceccherini	// BApplication caches its resources, so check
7736cd5d5b1SStefano Ceccherini	// if it already happened.
7746cd5d5b1SStefano Ceccherini	if (_app_resources != NULL) {
7756cd5d5b1SStefano Ceccherini		_app_resources_lock.Unlock();
7766cd5d5b1SStefano Ceccherini		return _app_resources;
7776cd5d5b1SStefano Ceccherini	}
778beabca50SAxel Dörfler
7795dccfc19SStefano Ceccherini	entry_ref ref;
7805dccfc19SStefano Ceccherini	bool found = false;
781beabca50SAxel Dörfler
7826cd5d5b1SStefano Ceccherini	// App is already running. Get its entry ref with
7835dccfc19SStefano Ceccherini	// GetRunningAppInfo()
7846cd5d5b1SStefano Ceccherini	app_info appInfo;
7856cd5d5b1SStefano Ceccherini	if (be_app && be_roster->GetRunningAppInfo(be_app->Team(), &appInfo) == B_OK) {
7866cd5d5b1SStefano Ceccherini		ref = appInfo.ref;
7876cd5d5b1SStefano Ceccherini		found = true;
788beabca50SAxel Dörfler	} else {
7896cd5d5b1SStefano Ceccherini		// Run() hasn't been called yet
7906cd5d5b1SStefano Ceccherini		found = BPrivate::get_app_ref(&ref) == B_OK;
791beabca50SAxel Dörfler	}
792beabca50SAxel Dörfler
7936cd5d5b1SStefano Ceccherini	if (found) {
7946cd5d5b1SStefano Ceccherini		BFile file(&ref, B_READ_ONLY);
7956cd5d5b1SStefano Ceccherini		if (file.InitCheck() == B_OK) {
7966cd5d5b1SStefano Ceccherini			BResources *resources = new BResources();
7975dccfc19SStefano Ceccherini			if (resources->SetTo(&file, false) < B_OK)
7986cd5d5b1SStefano Ceccherini				delete resources;
7995dccfc19SStefano Ceccherini			else
8006cd5d5b1SStefano Ceccherini				_app_resources = resources;
8016cd5d5b1SStefano Ceccherini		}
8026cd5d5b1SStefano Ceccherini	}
803beabca50SAxel Dörfler
8046cd5d5b1SStefano Ceccherini	_app_resources_lock.Unlock();
805beabca50SAxel Dörfler
8066cd5d5b1SStefano Ceccherini	return _app_resources;
80752a38012Sejakowatz}
808bae6988eSAxel Dörfler
809bae6988eSAxel Dörfler
810f19d9d3bSStefano Ceccherinivoid
811bae6988eSAxel DörflerBApplication::DispatchMessage(BMessage *message, BHandler *handler)
81273a2b29fSIngo Weinhold{
813bae6988eSAxel Dörfler	if (handler != this) {
814bae6988eSAxel Dörfler		// it's not ours to dispatch
815bae6988eSAxel Dörfler		BLooper::DispatchMessage(message, handler);
816bae6988eSAxel Dörfler		return;
817bae6988eSAxel Dörfler	}
818bae6988eSAxel Dörfler
81973a2b29fSIngo Weinhold	switch (message->what) {
82073a2b29fSIngo Weinhold		case B_ARGV_RECEIVED:
821f19d9d3bSStefano Ceccherini			do_argv(message);
82273a2b29fSIngo Weinhold			break;
8235dccfc19SStefano Ceccherini
82473a2b29fSIngo Weinhold		case B_REFS_RECEIVED:
825bae6988eSAxel Dörfler		{
826bae6988eSAxel Dörfler			// this adds the refs that are part of this message to the recent
827bae6988eSAxel Dörfler			// lists, but only folders and documents are handled here
828bae6988eSAxel Dörfler			entry_ref ref;
829bae6988eSAxel Dörfler			int32 i = 0;
830bae6988eSAxel Dörfler			while (message->FindRef("refs", i++, &ref) == B_OK) {
831bae6988eSAxel Dörfler				BEntry entry(&ref, true);
832bae6988eSAxel Dörfler				if (entry.InitCheck() != B_OK)
833bae6988eSAxel Dörfler					continue;
834bae6988eSAxel Dörfler
835bae6988eSAxel Dörfler				if (entry.IsDirectory())
836bae6988eSAxel Dörfler					BRoster().AddToRecentFolders(&ref);
837bae6988eSAxel Dörfler				else {
838bae6988eSAxel Dörfler					// filter out applications, we only want to have documents
839bae6988eSAxel Dörfler					// in the recent files list
840bae6988eSAxel Dörfler					BNode node(&entry);
841bae6988eSAxel Dörfler					BNodeInfo info(&node);
842bae6988eSAxel Dörfler
843bae6988eSAxel Dörfler					char mimeType[B_MIME_TYPE_LENGTH];
844bae6988eSAxel Dörfler					if (info.GetType(mimeType) != B_OK
845bae6988eSAxel Dörfler						|| strcasecmp(mimeType, B_APP_MIME_TYPE))
846bae6988eSAxel Dörfler						BRoster().AddToRecentDocuments(&ref);
847bae6988eSAxel Dörfler				}
848bae6988eSAxel Dörfler			}
849bae6988eSAxel Dörfler
85073a2b29fSIngo Weinhold			RefsReceived(message);
85173a2b29fSIngo Weinhold			break;
852bae6988eSAxel Dörfler		}
8535dccfc19SStefano Ceccherini
85473a2b29fSIngo Weinhold		case B_READY_TO_RUN:
855ca8ed922SStefano Ceccherini			if (!fReadyToRunCalled) {
856bae6988eSAxel Dörfler				ReadyToRun();
857ca8ed922SStefano Ceccherini				fReadyToRunCalled = true;
858ca8ed922SStefano Ceccherini			}
85973a2b29fSIngo Weinhold			break;
860bae6988eSAxel Dörfler
8615dccfc19SStefano Ceccherini		case B_ABOUT_REQUESTED:
8625dccfc19SStefano Ceccherini			AboutRequested();
8635dccfc19SStefano Ceccherini			break;
864bae6988eSAxel Dörfler
865e372dc78SAxel Dörfler		case B_QUIT_REQUESTED:
8661a2f24bbSIngo Weinhold			DBG(message->PrintToStream());
867e372dc78SAxel Dörfler			if (QuitRequested())
868e372dc78SAxel Dörfler				Quit();
869e372dc78SAxel Dörfler			break;
870e372dc78SAxel Dörfler
871bae6988eSAxel Dörfler		case B_PULSE:
872bae6988eSAxel Dörfler			Pulse();
873bae6988eSAxel Dörfler			break;
874f8411ab1SStefano Ceccherini
875bae6988eSAxel Dörfler		case B_APP_ACTIVATED:
876f8411ab1SStefano Ceccherini		{
877f8411ab1SStefano Ceccherini			bool active = false;
878f8411ab1SStefano Ceccherini			message->FindBool("active", &active);
879f8411ab1SStefano Ceccherini			AppActivated(active);
880f8411ab1SStefano Ceccherini			break;
881f8411ab1SStefano Ceccherini		}
882f8411ab1SStefano Ceccherini
883f8411ab1SStefano Ceccherini		case _SHOW_DRAG_HANDLES_:
884f8411ab1SStefano Ceccherini		{
885f8411ab1SStefano Ceccherini			bool visible = false;
886f8411ab1SStefano Ceccherini			message->FindBool("visible", &visible);
887f8411ab1SStefano Ceccherini			// TODO: Call the registrar or whoever is responsible for this
888f8411ab1SStefano Ceccherini			break;
889f8411ab1SStefano Ceccherini		}
890f8411ab1SStefano Ceccherini
891f8411ab1SStefano Ceccherini		// TODO: Handle these as well
892ca8ed922SStefano Ceccherini		// These two are handled by BTextView classes, so
893ca8ed922SStefano Ceccherini		// BApplication probably forwards these messages to them.
894ca8ed922SStefano Ceccherini		case _DISPOSE_DRAG_:
895ca8ed922SStefano Ceccherini		case _PING_:
896bae6988eSAxel Dörfler			puts("not yet handled message:");
8971a2f24bbSIngo Weinhold			DBG(message->PrintToStream());
898bae6988eSAxel Dörfler			break;
899ca8ed922SStefano Ceccherini
900