Application.cpp revision c4f7df69
1dd10337fSAxel Dörfler/*
2cfc3fa87SAxel Dörfler * Copyright 2001-2008, 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)
799e2816cSJérôme Duval * 		Jerome Duval
8c01f349eSAxel Dörfler *		Axel D��rfler, axeld@pinc-software.de
9dd10337fSAxel Dörfler */
10dd10337fSAxel Dörfler
11dd10337fSAxel Dörfler
12cfc3fa87SAxel Dörfler#include <Application.h>
13cfc3fa87SAxel Dörfler
14cfc3fa87SAxel Dörfler#include <new>
15cfc3fa87SAxel Dörfler#include <stdio.h>
16cfc3fa87SAxel Dörfler#include <stdlib.h>
17cfc3fa87SAxel Dörfler#include <string.h>
18cfc3fa87SAxel Dörfler#include <unistd.h>
1952a38012Sejakowatz
2053b9eef8SStefano Ceccherini#include <Alert.h>
2173a2b29fSIngo Weinhold#include <AppFileInfo.h>
22c7f20c70SIngo Weinhold#include <Cursor.h>
23a8fc5954SStefano Ceccherini#include <Debug.h>
2473a2b29fSIngo Weinhold#include <Entry.h>
2573a2b29fSIngo Weinhold#include <File.h>
26c7f20c70SIngo Weinhold#include <Locker.h>
27cfc3fa87SAxel Dörfler#include <MessageRunner.h>
2873a2b29fSIngo Weinhold#include <Path.h>
29b1698c8eSejakowatz#include <PropertyInfo.h>
30c7f20c70SIngo Weinhold#include <RegistrarDefs.h>
316cd5d5b1SStefano Ceccherini#include <Resources.h>
32c7f20c70SIngo Weinhold#include <Roster.h>
33ebbcbbcaSejakowatz#include <Window.h>
3452a38012Sejakowatz
35cfc3fa87SAxel Dörfler#include <AppMisc.h>
36cfc3fa87SAxel Dörfler#include <AppServerLink.h>
37cfc3fa87SAxel Dörfler#include <AutoLocker.h>
38cfc3fa87SAxel Dörfler#include <DraggerPrivate.h>
39cfc3fa87SAxel Dörfler#include <LooperList.h>
40cfc3fa87SAxel Dörfler#include <MenuWindow.h>
41cfc3fa87SAxel Dörfler#include <PortLink.h>
42cfc3fa87SAxel Dörfler#include <RosterPrivate.h>
43cfc3fa87SAxel Dörfler#include <ServerMemoryAllocator.h>
44cfc3fa87SAxel Dörfler#include <ServerProtocol.h>
456542ca9bSStefano Ceccherini
4672f5d860SAxel Dörflerusing namespace BPrivate;
4752a38012Sejakowatz
48cfc3fa87SAxel Dörfler
49af34fbf1SAxel DörflerBApplication *be_app = NULL;
50af34fbf1SAxel DörflerBMessenger be_app_messenger;
5152a38012Sejakowatz
5217adbf1fSStefano CeccheriniBResources *BApplication::sAppResources = NULL;
5317adbf1fSStefano CeccheriniBLocker BApplication::sAppResourcesLock("_app_resources_lock");
5452a38012Sejakowatz
5541f6b937SDarkWyrm
5637d8f330SAxel Dörflerenum {
5737d8f330SAxel Dörfler	kWindowByIndex,
5837d8f330SAxel Dörfler	kWindowByName,
5937d8f330SAxel Dörfler	kLooperByIndex,
6037d8f330SAxel Dörfler	kLooperByID,
6137d8f330SAxel Dörfler	kLooperByName,
6237d8f330SAxel Dörfler	kApplication
6337d8f330SAxel Dörfler};
6437d8f330SAxel Dörfler
65dd10337fSAxel Dörflerstatic property_info sPropertyInfo[] = {
66ebbcbbcaSejakowatz	{
67ebbcbbcaSejakowatz		"Window",
68beabca50SAxel Dörfler		{},
69beabca50SAxel Dörfler		{B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER},
7037d8f330SAxel Dörfler		NULL, kWindowByIndex,
71beabca50SAxel Dörfler		{},
72beabca50SAxel Dörfler		{},
73beabca50SAxel Dörfler		{}
74ebbcbbcaSejakowatz	},
75ebbcbbcaSejakowatz	{
76ebbcbbcaSejakowatz		"Window",
77beabca50SAxel Dörfler		{},
78beabca50SAxel Dörfler		{B_NAME_SPECIFIER},
7937d8f330SAxel Dörfler		NULL, kWindowByName,
80beabca50SAxel Dörfler		{},
81beabca50SAxel Dörfler		{},
82beabca50SAxel Dörfler		{}
83ebbcbbcaSejakowatz	},
84ebbcbbcaSejakowatz	{
85ebbcbbcaSejakowatz		"Looper",
86beabca50SAxel Dörfler		{},
87beabca50SAxel Dörfler		{B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER},
8837d8f330SAxel Dörfler		NULL, kLooperByIndex,
89beabca50SAxel Dörfler		{},
90beabca50SAxel Dörfler		{},
91beabca50SAxel Dörfler		{}
92ebbcbbcaSejakowatz	},
93ebbcbbcaSejakowatz	{
94ebbcbbcaSejakowatz		"Looper",
95beabca50SAxel Dörfler		{},
96beabca50SAxel Dörfler		{B_ID_SPECIFIER},
9737d8f330SAxel Dörfler		NULL, kLooperByID,
98beabca50SAxel Dörfler		{},
99beabca50SAxel Dörfler		{},
100beabca50SAxel Dörfler		{}
101ebbcbbcaSejakowatz	},
102ebbcbbcaSejakowatz	{
103ebbcbbcaSejakowatz		"Looper",
104beabca50SAxel Dörfler		{},
105beabca50SAxel Dörfler		{B_NAME_SPECIFIER},
10637d8f330SAxel Dörfler		NULL, kLooperByName,
107beabca50SAxel Dörfler		{},
108beabca50SAxel Dörfler		{},
109beabca50SAxel Dörfler		{}
110ebbcbbcaSejakowatz	},
111ebbcbbcaSejakowatz	{
112ebbcbbcaSejakowatz		"Name",
113beabca50SAxel Dörfler		{B_GET_PROPERTY},
114beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
11537d8f330SAxel Dörfler		NULL, kApplication,
116beabca50SAxel Dörfler		{B_STRING_TYPE},
117beabca50SAxel Dörfler		{},
118beabca50SAxel Dörfler		{}
119ebbcbbcaSejakowatz	},
120ebbcbbcaSejakowatz	{
121ebbcbbcaSejakowatz		"Window",
122beabca50SAxel Dörfler		{B_COUNT_PROPERTIES},
123beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
12437d8f330SAxel Dörfler		NULL, kApplication,
125beabca50SAxel Dörfler		{B_INT32_TYPE},
126beabca50SAxel Dörfler		{},
127beabca50SAxel Dörfler		{}
128ebbcbbcaSejakowatz	},
129ebbcbbcaSejakowatz	{
130ebbcbbcaSejakowatz		"Loopers",
131beabca50SAxel Dörfler		{B_GET_PROPERTY},
132beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
13337d8f330SAxel Dörfler		NULL, kApplication,
134beabca50SAxel Dörfler		{B_MESSENGER_TYPE},
135beabca50SAxel Dörfler		{},
136beabca50SAxel Dörfler		{}
137ebbcbbcaSejakowatz	},
138ebbcbbcaSejakowatz	{
139ebbcbbcaSejakowatz		"Windows",
140beabca50SAxel Dörfler		{B_GET_PROPERTY},
141beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
14237d8f330SAxel Dörfler		NULL, kApplication,
143beabca50SAxel Dörfler		{B_MESSENGER_TYPE},
144beabca50SAxel Dörfler		{},
145beabca50SAxel Dörfler		{}
146ebbcbbcaSejakowatz	},
147ebbcbbcaSejakowatz	{
148ebbcbbcaSejakowatz		"Looper",
149beabca50SAxel Dörfler		{B_COUNT_PROPERTIES},
150beabca50SAxel Dörfler		{B_DIRECT_SPECIFIER},
15137d8f330SAxel Dörfler		NULL, kApplication,
152beabca50SAxel Dörfler		{B_INT32_TYPE},
153beabca50SAxel Dörfler		{},
154beabca50SAxel Dörfler		{}
155ebbcbbcaSejakowatz	},
156ebbcbbcaSejakowatz	{}
1572284462cSejakowatz};
1582284462cSejakowatz
15973a2b29fSIngo Weinhold// argc/argv
16073a2b29fSIngo Weinholdextern const int __libc_argc;
16173a2b29fSIngo Weinholdextern const char * const *__libc_argv;
16252a38012Sejakowatz
163c7f20c70SIngo Weinhold
164c7f20c70SIngo Weinhold// debugging
16501225b39SIngo Weinhold//#define DBG(x) x
16601225b39SIngo Weinhold#define DBG(x)
167c7f20c70SIngo Weinhold#define OUT	printf
168c7f20c70SIngo Weinhold
169c7f20c70SIngo Weinhold
17073a2b29fSIngo Weinhold// prototypes of helper functions
17173a2b29fSIngo Weinholdstatic const char* looper_name_for(const char *signature);
1729986313cSIngo Weinholdstatic status_t check_app_signature(const char *signature);
173bee72328SAxel Dörflerstatic void fill_argv_message(BMessage &message);
174c7f20c70SIngo Weinhold
175beabca50SAxel Dörfler
176beabca50SAxel DörflerBApplication::BApplication(const char *signature)
177af34fbf1SAxel Dörfler	: BLooper(looper_name_for(signature))
17852a38012Sejakowatz{
1799a44fdc9SAxel Dörfler	_InitData(signature, true, NULL);
18052a38012Sejakowatz}
181beabca50SAxel Dörfler
182beabca50SAxel Dörfler
183af34fbf1SAxel DörflerBApplication::BApplication(const char *signature, status_t *_error)
184af34fbf1SAxel Dörfler	: BLooper(looper_name_for(signature))
18552a38012Sejakowatz{
1869a44fdc9SAxel Dörfler	_InitData(signature, true, _error);
187c8e7f53eSIngo Weinhold}
188c8e7f53eSIngo Weinhold
189c8e7f53eSIngo Weinhold
190c8e7f53eSIngo WeinholdBApplication::BApplication(const char *signature, bool initGUI,
191c8e7f53eSIngo Weinhold		status_t *_error)
192c8e7f53eSIngo Weinhold	: BLooper(looper_name_for(signature))
193c8e7f53eSIngo Weinhold{
1949a44fdc9SAxel Dörfler	_InitData(signature, initGUI, _error);
19552a38012Sejakowatz}
196beabca50SAxel Dörfler
197beabca50SAxel Dörfler
198c18d8429SAxel DörflerBApplication::BApplication(BMessage *data)
199c18d8429SAxel Dörfler	// Note: BeOS calls the private BLooper(int32, port_id, const char *)
200c18d8429SAxel Dörfler	// constructor here, test if it's needed
201c18d8429SAxel Dörfler	: BLooper(looper_name_for(NULL))
202c18d8429SAxel Dörfler{
203c18d8429SAxel Dörfler	const char *signature = NULL;
204c18d8429SAxel Dörfler	data->FindString("mime_sig", &signature);
205c18d8429SAxel Dörfler
2069a44fdc9SAxel Dörfler	_InitData(signature, true, NULL);
207c18d8429SAxel Dörfler
208c18d8429SAxel Dörfler	bigtime_t pulseRate;
209c18d8429SAxel Dörfler	if (data->FindInt64("_pulse", &pulseRate) == B_OK)
210c18d8429SAxel Dörfler		SetPulseRate(pulseRate);
211c18d8429SAxel Dörfler}
212c18d8429SAxel Dörfler
213c18d8429SAxel Dörfler
214c18d8429SAxel DörflerBApplication::BApplication(uint32 signature)
215c18d8429SAxel Dörfler{
216c18d8429SAxel Dörfler}
217c18d8429SAxel Dörfler
218c18d8429SAxel Dörfler
219c18d8429SAxel DörflerBApplication::BApplication(const BApplication &rhs)
220c18d8429SAxel Dörfler{
221c18d8429SAxel Dörfler}
222c18d8429SAxel Dörfler
223c18d8429SAxel Dörfler
22452a38012SejakowatzBApplication::~BApplication()
22552a38012Sejakowatz{
22672f5d860SAxel Dörfler	Lock();
227f28a6f70SAdi Oanca
22872f5d860SAxel Dörfler	// tell all loopers(usually windows) to quit. Also, wait for them.
2299a44fdc9SAxel Dörfler	_QuitAllWindows(true);
230f28a6f70SAdi Oanca
231dc3ebdecSAdi Oanca	// unregister from the roster
232dc3ebdecSAdi Oanca	BRoster::Private().RemoveApp(Team());
233dc3ebdecSAdi Oanca
234044be4e2SIngo Weinhold#ifndef RUN_WITHOUT_APP_SERVER
2353ceb31b9SDarkWyrm	// tell app_server we're quitting...
236c4f7df69SStefano Ceccherini	if (be_app) {
237c4f7df69SStefano Ceccherini		// be_app can be NULL here if the application fails to initialize
238c4f7df69SStefano Ceccherini		// correctly. For example, if it's already running and it's set to
239c4f7df69SStefano Ceccherini		// exclusive launch.
240c4f7df69SStefano Ceccherini		BPrivate::AppServerLink link;
241c4f7df69SStefano Ceccherini		link.StartMessage(B_QUIT_REQUESTED);
242c4f7df69SStefano Ceccherini		link.Flush();
243c4f7df69SStefano Ceccherini	}
244dd10337fSAxel Dörfler	delete_port(fServerLink->SenderPort());
245dd10337fSAxel Dörfler	delete_port(fServerLink->ReceiverPort());
246dd10337fSAxel Dörfler	delete fServerLink;
247a60ea282SIngo Weinhold#endif	// RUN_WITHOUT_APP_SERVER
24872f5d860SAxel Dörfler
249c7c61938SAxel Dörfler	delete fServerAllocator;
250c7c61938SAxel Dörfler
25172f5d860SAxel Dörfler	// uninitialize be_app, the be_app_messenger is invalidated automatically
2528a526591SIngo Weinhold	be_app = NULL;
25352a38012Sejakowatz}
254beabca50SAxel Dörfler
255beabca50SAxel Dörfler
256c18d8429SAxel DörflerBApplication &
257c18d8429SAxel DörflerBApplication::operator=(const BApplication &rhs)
25852a38012Sejakowatz{
259c18d8429SAxel Dörfler	return *this;
260c18d8429SAxel Dörfler}
261beabca50SAxel Dörfler
26241f6b937SDarkWyrm
263c18d8429SAxel Dörflervoid
2649a44fdc9SAxel DörflerBApplication::_InitData(const char *signature, bool initGUI, status_t *_error)
265c18d8429SAxel Dörfler{
266dd10337fSAxel Dörfler	DBG(OUT("BApplication::InitData(`%s', %p)\n", signature, _error));
267c18d8429SAxel Dörfler	// check whether there exists already an application
268c18d8429SAxel Dörfler	if (be_app)
269c18d8429SAxel Dörfler		debugger("2 BApplication objects were created. Only one is allowed.");
270c18d8429SAxel Dörfler
271dd10337fSAxel Dörfler	fServerLink = new BPrivate::PortLink(-1, -1);
2729a44fdc9SAxel Dörfler	fServerAllocator = NULL;
273c18d8429SAxel Dörfler	fInitialWorkspace = 0;
2749a44fdc9SAxel Dörfler	//fDraggedMessage = NULL;
275c18d8429SAxel Dörfler	fReadyToRunCalled = false;
276c18d8429SAxel Dörfler
277c18d8429SAxel Dörfler	// initially, there is no pulse
278c18d8429SAxel Dörfler	fPulseRunner = NULL;
279c18d8429SAxel Dörfler	fPulseRate = 0;
280c18d8429SAxel Dörfler
281c18d8429SAxel Dörfler	// check signature
282c18d8429SAxel Dörfler	fInitError = check_app_signature(signature);
283c18d8429SAxel Dörfler	fAppName = signature;
284c18d8429SAxel Dörfler
285c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_REGISTRAR
286c18d8429SAxel Dörfler	bool isRegistrar = signature
287c18d8429SAxel Dörfler		&& !strcasecmp(signature, kRegistrarSignature);
288c18d8429SAxel Dörfler	// get team and thread
289c18d8429SAxel Dörfler	team_id team = Team();
290c18d8429SAxel Dörfler	thread_id thread = BPrivate::main_thread_for(team);
291c18d8429SAxel Dörfler#endif
292c18d8429SAxel Dörfler
293c18d8429SAxel Dörfler	// get app executable ref
294c18d8429SAxel Dörfler	entry_ref ref;
29584de162bSIngo Weinhold	if (fInitError == B_OK) {
296c18d8429SAxel Dörfler		fInitError = BPrivate::get_app_ref(&ref);
29784de162bSIngo Weinhold		if (fInitError != B_OK) {
29884de162bSIngo Weinhold			DBG(OUT("BApplication::InitData(): Failed to get app ref: %s\n",
29984de162bSIngo Weinhold				strerror(fInitError)));
30084de162bSIngo Weinhold		}
30184de162bSIngo Weinhold	}
302c18d8429SAxel Dörfler
303c18d8429SAxel Dörfler	// get the BAppFileInfo and extract the information we need
304c18d8429SAxel Dörfler	uint32 appFlags = B_REG_DEFAULT_APP_FLAGS;
305c18d8429SAxel Dörfler	if (fInitError == B_OK) {
306c18d8429SAxel Dörfler		BAppFileInfo fileInfo;
307c18d8429SAxel Dörfler		BFile file(&ref, B_READ_ONLY);
308c18d8429SAxel Dörfler		fInitError = fileInfo.SetTo(&file);
309c18d8429SAxel Dörfler		if (fInitError == B_OK) {
310c18d8429SAxel Dörfler			fileInfo.GetAppFlags(&appFlags);
311ca8ed922SStefano Ceccherini			char appFileSignature[B_MIME_TYPE_LENGTH];
312c18d8429SAxel Dörfler			// compare the file signature and the supplied signature
313c18d8429SAxel Dörfler			if (fileInfo.GetSignature(appFileSignature) == B_OK
314c18d8429SAxel Dörfler				&& strcasecmp(appFileSignature, signature) != 0) {
315c18d8429SAxel Dörfler				printf("Signature in rsrc doesn't match constructor arg. (%s, %s)\n",
316c18d8429SAxel Dörfler					signature, appFileSignature);
317c18d8429SAxel Dörfler			}
31884de162bSIngo Weinhold		} else {
31984de162bSIngo Weinhold			DBG(OUT("BApplication::InitData(): Failed to get info from: "
32084de162bSIngo Weinhold				"BAppFileInfo: %s\n", strerror(fInitError)));
321c18d8429SAxel Dörfler		}
322c18d8429SAxel Dörfler	}
323c18d8429SAxel Dörfler
324c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_REGISTRAR
325c18d8429SAxel Dörfler	// check whether be_roster is valid
326c18d8429SAxel Dörfler	if (fInitError == B_OK && !isRegistrar
327c18d8429SAxel Dörfler		&& !BRoster::Private().IsMessengerValid(false)) {
328c18d8429SAxel Dörfler		printf("FATAL: be_roster is not valid. Is the registrar running?\n");
329c18d8429SAxel Dörfler		fInitError = B_NO_INIT;
330c18d8429SAxel Dörfler	}
331c18d8429SAxel Dörfler
332c18d8429SAxel Dörfler	// check whether or not we are pre-registered
333c18d8429SAxel Dörfler	bool preRegistered = false;
334c18d8429SAxel Dörfler	app_info appInfo;
335c18d8429SAxel Dörfler	if (fInitError == B_OK && !isRegistrar) {
3366bfd06d1SIngo Weinhold		if (BRoster::Private().IsAppRegistered(&ref, team, 0, &preRegistered,
3376bfd06d1SIngo Weinhold				&appInfo) != B_OK) {
3386bfd06d1SIngo Weinhold			preRegistered = false;
3396bfd06d1SIngo Weinhold		}
340c18d8429SAxel Dörfler	}
341c18d8429SAxel Dörfler	if (preRegistered) {
342c18d8429SAxel Dörfler		// we are pre-registered => the app info has been filled in
343c18d8429SAxel Dörfler		// Check whether we need to replace the looper port with a port
344c18d8429SAxel Dörfler		// created by the roster.
345c18d8429SAxel Dörfler		if (appInfo.port >= 0 && appInfo.port != fMsgPort) {
346c18d8429SAxel Dörfler			delete_port(fMsgPort);
347c18d8429SAxel Dörfler			fMsgPort = appInfo.port;
348c18d8429SAxel Dörfler		} else
349c18d8429SAxel Dörfler			appInfo.port = fMsgPort;
350c4dde2f7SAxel Dörfler		// check the signature and correct it, if necessary, also the case
351c4dde2f7SAxel Dörfler		if (strcmp(appInfo.signature, fAppName))
352c18d8429SAxel Dörfler			BRoster::Private().SetSignature(team, fAppName);
353c18d8429SAxel Dörfler		// complete the registration
354c18d8429SAxel Dörfler		fInitError = BRoster::Private().CompleteRegistration(team, thread,
355c18d8429SAxel Dörfler						appInfo.port);
356c18d8429SAxel Dörfler	} else if (fInitError == B_OK) {
357c18d8429SAxel Dörfler		// not pre-registered -- try to register the application
358c18d8429SAxel Dörfler		team_id otherTeam = -1;
359c18d8429SAxel Dörfler		// the registrar must not register
360c18d8429SAxel Dörfler		if (!isRegistrar) {
361c18d8429SAxel Dörfler			fInitError = BRoster::Private().AddApplication(signature, &ref,
362c18d8429SAxel Dörfler				appFlags, team, thread, fMsgPort, true, NULL, &otherTeam);
36384de162bSIngo Weinhold			if (fInitError != B_OK) {
36484de162bSIngo Weinhold				DBG(OUT("BApplication::InitData(): Failed to add app: %s\n",
36584de162bSIngo Weinhold					strerror(fInitError)));
36684de162bSIngo Weinhold			}
367c18d8429SAxel Dörfler		}
368c18d8429SAxel Dörfler		if (fInitError == B_ALREADY_RUNNING) {
369c18d8429SAxel Dörfler			// An instance is already running and we asked for
370c18d8429SAxel Dörfler			// single/exclusive launch. Send our argv to the running app.
371c18d8429SAxel Dörfler			// Do that only, if the app is NOT B_ARGV_ONLY.
372aa389c6bSAxel Dörfler			if (otherTeam >= 0) {
373aa389c6bSAxel Dörfler				BMessenger otherApp(NULL, otherTeam);
374c18d8429SAxel Dörfler				app_info otherAppInfo;
375aa389c6bSAxel Dörfler				if (__libc_argc > 1
376aa389c6bSAxel Dörfler					&& be_roster->GetRunningAppInfo(otherTeam, &otherAppInfo) == B_OK
377c18d8429SAxel Dörfler					&& !(otherAppInfo.flags & B_ARGV_ONLY)) {
378c18d8429SAxel Dörfler					// create an B_ARGV_RECEIVED message
379c18d8429SAxel Dörfler					BMessage argvMessage(B_ARGV_RECEIVED);
380bee72328SAxel Dörfler					fill_argv_message(argvMessage);
381c18d8429SAxel Dörfler
382c18d8429SAxel Dörfler					// replace the first argv string with the path of the
383c18d8429SAxel Dörfler					// other application
384c18d8429SAxel Dörfler					BPath path;
385c18d8429SAxel Dörfler					if (path.SetTo(&otherAppInfo.ref) == B_OK)
386c18d8429SAxel Dörfler						argvMessage.ReplaceString("argv", 0, path.Path());
387c18d8429SAxel Dörfler
388c18d8429SAxel Dörfler					// send the message
389aa389c6bSAxel Dörfler					otherApp.SendMessage(&argvMessage);
390aa389c6bSAxel Dörfler				} else
391aa389c6bSAxel Dörfler					otherApp.SendMessage(B_SILENT_RELAUNCH);
392c18d8429SAxel Dörfler			}
393c18d8429SAxel Dörfler		} else if (fInitError == B_OK) {
394c18d8429SAxel Dörfler			// the registrations was successful
395c18d8429SAxel Dörfler			// Create a B_ARGV_RECEIVED message and send it to ourselves.
396c18d8429SAxel Dörfler			// Do that even, if we are B_ARGV_ONLY.
397c18d8429SAxel Dörfler			// TODO: When BLooper::AddMessage() is done, use that instead of
398c18d8429SAxel Dörfler			// PostMessage().
399c18d8429SAxel Dörfler
400c18d8429SAxel Dörfler			DBG(OUT("info: BApplication sucessfully registered.\n"));
401c18d8429SAxel Dörfler
402c18d8429SAxel Dörfler			if (__libc_argc > 1) {
403c18d8429SAxel Dörfler				BMessage argvMessage(B_ARGV_RECEIVED);
404bee72328SAxel Dörfler				fill_argv_message(argvMessage);
405c18d8429SAxel Dörfler				PostMessage(&argvMessage, this);
406c18d8429SAxel Dörfler			}
407c18d8429SAxel Dörfler			// send a B_READY_TO_RUN message as well
408c18d8429SAxel Dörfler			PostMessage(B_READY_TO_RUN, this);
409c18d8429SAxel Dörfler		} else if (fInitError > B_ERRORS_END) {
410c18d8429SAxel Dörfler			// Registrar internal errors shouldn't fall into the user's hands.
411c18d8429SAxel Dörfler			fInitError = B_ERROR;
412c18d8429SAxel Dörfler		}
413c18d8429SAxel Dörfler	}
4144e51dee8SDarkWyrm#else
4154e51dee8SDarkWyrm	// We need to have ReadyToRun called even when we're not using the registrar
4164e51dee8SDarkWyrm	PostMessage(B_READY_TO_RUN, this);
4174e51dee8SDarkWyrm#endif	// ifndef RUN_WITHOUT_REGISTRAR
418c18d8429SAxel Dörfler
419c18d8429SAxel Dörfler	if (fInitError == B_OK) {
420aa389c6bSAxel Dörfler		// TODO: Not completely sure about the order, but this should be close.
421aa389c6bSAxel Dörfler
422aa389c6bSAxel Dörfler		// init be_app and be_app_messenger
423c18d8429SAxel Dörfler		be_app = this;
424c18d8429SAxel Dörfler		be_app_messenger = BMessenger(NULL, this);
425dd10337fSAxel Dörfler
426aa389c6bSAxel Dörfler		// set the BHandler's name
427c18d8429SAxel Dörfler		SetName(ref.name);
428c8e7f53eSIngo Weinhold
429aa389c6bSAxel Dörfler		// create meta MIME
430c18d8429SAxel Dörfler		BPath path;
431c18d8429SAxel Dörfler		if (path.SetTo(&ref) == B_OK)
432c18d8429SAxel Dörfler			create_app_meta_mime(path.Path(), false, true, false);
433c18d8429SAxel Dörfler
434c18d8429SAxel Dörfler#ifndef RUN_WITHOUT_APP_SERVER
435aa389c6bSAxel Dörfler		// app server connection and IK initialization
436aa389c6bSAxel Dörfler		if (initGUI)
437aa389c6bSAxel Dörfler			fInitError = _InitGUIContext();
438c18d8429SAxel Dörfler#endif	// RUN_WITHOUT_APP_SERVER
439aa389c6bSAxel Dörfler	}
44041f6b937SDarkWyrm
441c18d8429SAxel Dörfler	// Return the error or exit, if there was an error and no error variable
442c18d8429SAxel Dörfler	// has been supplied.
44384de162bSIngo Weinhold	if (_error) {
444c18d8429SAxel Dörfler		*_error = fInitError;
44584de162bSIngo Weinhold	} else if (fInitError != B_OK) {
44684de162bSIngo Weinhold		DBG(OUT("BApplication::InitData() failed: %s\n", strerror(fInitError)));
447c18d8429SAxel Dörfler		exit(0);
44884de162bSIngo Weinhold	}
44984de162bSIngo WeinholdDBG(OUT("BApplication::InitData() done\n"));
45052a38012Sejakowatz}
451beabca50SAxel Dörfler
452beabca50SAxel Dörfler
453beabca50SAxel DörflerBArchivable *
454beabca50SAxel DörflerBApplication::Instantiate(BMessage *data)
45552a38012Sejakowatz{
4565dccfc19SStefano Ceccherini	if (validate_instantiation(data, "BApplication"))
4575dccfc19SStefano Ceccherini		return new BApplication(data);
458beabca50SAxel Dörfler
4595dccfc19SStefano Ceccherini	return NULL;
46052a38012Sejakowatz}
461beabca50SAxel Dörfler
462beabca50SAxel Dörfler
46341f6b937SDarkWyrmstatus_t
464beabca50SAxel DörflerBApplication::Archive(BMessage *data, bool deep) const
46552a38012Sejakowatz{
46641f6b937SDarkWyrm	status_t status = BLooper::Archive(data, deep);
46741f6b937SDarkWyrm	if (status < B_OK)
46841f6b937SDarkWyrm		return status;
46941f6b937SDarkWyrm
47041f6b937SDarkWyrm	app_info info;
47141f6b937SDarkWyrm	status = GetAppInfo(&info);
47241f6b937SDarkWyrm	if (status < B_OK)
47341f6b937SDarkWyrm		return status;
47441f6b937SDarkWyrm
47541f6b937SDarkWyrm	status = data->AddString("mime_sig", info.signature);
47641f6b937SDarkWyrm	if (status < B_OK)
47741f6b937SDarkWyrm		return status;
47841f6b937SDarkWyrm
479beabca50SAxel Dörfler	return data->AddInt64("_pulse", fPulseRate);
48052a38012Sejakowatz}
481beabca50SAxel Dörfler
482beabca50SAxel Dörfler
483beabca50SAxel Dörflerstatus_t
484beabca50SAxel DörflerBApplication::InitCheck() const
48552a38012Sejakowatz{
48652a38012Sejakowatz	return fInitError;
48752a38012Sejakowatz}
488beabca50SAxel Dörfler
489beabca50SAxel Dörfler
490beabca50SAxel Dörflerthread_id
491beabca50SAxel DörflerBApplication::Run()
49252a38012Sejakowatz{
49372f5d860SAxel Dörfler	if (fInitError != B_OK)
49472f5d860SAxel Dörfler		return fInitError;
49572f5d860SAxel Dörfler
496c7f20c70SIngo Weinhold	AssertLocked();
497c7f20c70SIngo Weinhold
4986cd5d5b1SStefano Ceccherini	if (fRunCalled)
4996cd5d5b1SStefano Ceccherini		debugger("BApplication::Run was already called. Can only be called once.");
500c7f20c70SIngo Weinhold
501c01f349eSAxel Dörfler	fThread = find_thread(NULL);
502c7f20c70SIngo Weinhold	fRunCalled = true;
503c7f20c70SIngo Weinhold
5043cace414SAxel Dörfler	task_looper();
505c7f20c70SIngo Weinhold
50672f5d860SAxel Dörfler	delete fPulseRunner;
507c01f349eSAxel Dörfler	return fThread;
50852a38012Sejakowatz}
509beabca50SAxel Dörfler
510beabca50SAxel Dörfler
511beabca50SAxel Dörflervoid
512beabca50SAxel DörflerBApplication::Quit()
51352a38012Sejakowatz{
51498207f6fSIngo Weinhold	bool unlock = false;
515c7f20c70SIngo Weinhold	if (!IsLocked()) {
516beabca50SAxel Dörfler		const char *name = Name();
517c7f20c70SIngo Weinhold		if (!name)
518c7f20c70SIngo Weinhold			name = "no-name";
51998207f6fSIngo Weinhold		printf("ERROR - you must Lock the application object before calling "
52098207f6fSIngo Weinhold			   "Quit(), team=%ld, looper=%s\n", Team(), name);
52198207f6fSIngo Weinhold		unlock = true;
52298207f6fSIngo Weinhold		if (!Lock())
52398207f6fSIngo Weinhold			return;
524c7f20c70SIngo Weinhold	}
525c7f20c70SIngo Weinhold	// Delete the object, if not running only.
52698207f6fSIngo Weinhold	if (!fRunCalled) {
527c7f20c70SIngo Weinhold		delete this;
528c01f349eSAxel Dörfler	} else if (find_thread(NULL) != fThread) {
52972f5d860SAxel Dörfler// ToDo: why shouldn't we set fTerminating to true directly in this case?
53098207f6fSIngo Weinhold		// We are not the looper thread.
53198207f6fSIngo Weinhold		// We push a _QUIT_ into the queue.
53298207f6fSIngo Weinhold		// TODO: When BLooper::AddMessage() is done, use that instead of
53398207f6fSIngo Weinhold		// PostMessage()??? This would overtake messages that are still at
53498207f6fSIngo Weinhold		// the port.
53598207f6fSIngo Weinhold		// NOTE: We must not unlock here -- otherwise we had to re-lock, which
53698207f6fSIngo Weinhold		// may not work. This is bad, since, if the port is full, it
53798207f6fSIngo Weinhold		// won't get emptier, as the looper thread needs to lock the object
53898207f6fSIngo Weinhold		// before dispatching messages.
53998207f6fSIngo Weinhold		while (PostMessage(_QUIT_, this) == B_WOULD_BLOCK)
54098207f6fSIngo Weinhold			snooze(10000);
54198207f6fSIngo Weinhold	} else {
54298207f6fSIngo Weinhold		// We are the looper thread.
54398207f6fSIngo Weinhold		// Just set fTerminating to true which makes us fall through the
54498207f6fSIngo Weinhold		// message dispatching loop and return from Run().
54598207f6fSIngo Weinhold		fTerminating = true;
54698207f6fSIngo Weinhold	}
54798207f6fSIngo Weinhold	// If we had to lock the object, unlock now.
54898207f6fSIngo Weinhold	if (unlock)
54998207f6fSIngo Weinhold		Unlock();
55052a38012Sejakowatz}
551beabca50SAxel Dörfler
552beabca50SAxel Dörfler
553beabca50SAxel Dörflerbool
554beabca50SAxel DörflerBApplication::QuitRequested()
55552a38012Sejakowatz{
5569a44fdc9SAxel Dörfler	return _QuitAllWindows(false);
557f6dc8f8dSStefano Ceccherini}
558beabca50SAxel Dörfler
559beabca50SAxel Dörfler
560beabca50SAxel Dörflervoid
561beabca50SAxel DörflerBApplication::Pulse()
56252a38012Sejakowatz{
563c18d8429SAxel Dörfler	// supposed to be implemented by subclasses
56452a38012Sejakowatz}
565beabca50SAxel Dörfler
566beabca50SAxel Dörfler
567beabca50SAxel Dörflervoid
568beabca50SAxel DörflerBApplication::ReadyToRun()
56952a38012Sejakowatz{
570c18d8429SAxel Dörfler	// supposed to be implemented by subclasses
57152a38012Sejakowatz}
572beabca50SAxel Dörfler
573beabca50SAxel Dörfler
574833a5922SStefano Ceccherinivoid
575833a5922SStefano CeccheriniBApplication::MessageReceived(BMessage *message)
57652a38012Sejakowatz{
577833a5922SStefano Ceccherini	switch (message->what) {
5785dccfc19SStefano Ceccherini		case B_COUNT_PROPERTIES:
5795dccfc19SStefano Ceccherini		case B_GET_PROPERTY:
5805dccfc19SStefano Ceccherini		case B_SET_PROPERTY:
581bd6c2601SStefano Ceccherini		{
582bd6c2601SStefano Ceccherini			int32 index;
583bd6c2601SStefano Ceccherini			BMessage specifier;
584bd6c2601SStefano Ceccherini			int32 what;
585bd6c2601SStefano Ceccherini			const char *property = NULL;
5863106b9ecSStefano Ceccherini			if (message->GetCurrentSpecifier(&index, &specifier, &what, &property) < B_OK
58717adbf1fSStefano Ceccherini				|| !ScriptReceived(message, index, &specifier, what, property))
588bd6c2601SStefano Ceccherini				BLooper::MessageReceived(message);
5895dccfc19SStefano Ceccherini			break;
590bd6c2601SStefano Ceccherini		}
591beabca50SAxel Dörfler
592833a5922SStefano Ceccherini		case B_SILENT_RELAUNCH:
593aa389c6bSAxel Dörfler			// Sent to a B_SINGLE_LAUNCH application when it's launched again
594aa389c6bSAxel Dörfler			// (see _InitData())
595833a5922SStefano Ceccherini			be_roster->ActivateApp(Team());
596aa389c6bSAxel Dörfler			break;
597aa389c6bSAxel Dörfler
5985dccfc19SStefano Ceccherini		default:
599833a5922SStefano Ceccherini			BLooper::MessageReceived(message);
6005dccfc19SStefano Ceccherini			break;
6015dccfc19SStefano Ceccherini	}
60252a38012Sejakowatz}
603beabca50SAxel Dörfler
604beabca50SAxel Dörfler
605beabca50SAxel Dörflervoid
606beabca50SAxel DörflerBApplication::ArgvReceived(int32 argc, char **argv)
60752a38012Sejakowatz{
608beabca50SAxel Dörfler	// supposed to be implemented by subclasses
60952a38012Sejakowatz}
610beabca50SAxel Dörfler
611beabca50SAxel Dörfler
612beabca50SAxel Dörflervoid
613beabca50SAxel DörflerBApplication::AppActivated(bool active)
61452a38012Sejakowatz{
615beabca50SAxel Dörfler	// supposed to be implemented by subclasses
61652a38012Sejakowatz}
617beabca50SAxel Dörfler
618beabca50SAxel Dörfler
619beabca50SAxel Dörflervoid
620beabca50SAxel DörflerBApplication::RefsReceived(BMessage *message)
62152a38012Sejakowatz{
622beabca50SAxel Dörfler	// supposed to be implemented by subclasses
62352a38012Sejakowatz}
624beabca50SAxel Dörfler
625beabca50SAxel Dörfler
626beabca50SAxel Dörflervoid
627beabca50SAxel DörflerBApplication::AboutRequested()
62852a38012Sejakowatz{
62953b9eef8SStefano Ceccherini	thread_info info;
63053b9eef8SStefano Ceccherini	if (get_thread_info(Thread(), &info) == B_OK) {
63153b9eef8SStefano Ceccherini		BAlert *alert = new BAlert("_about_", info.name, "OK");
63253b9eef8SStefano Ceccherini		alert->Go(NULL);
63353b9eef8SStefano Ceccherini	}
63452a38012Sejakowatz}
635beabca50SAxel Dörfler
636beabca50SAxel Dörfler
637beabca50SAxel DörflerBHandler *
6381f8172a4SJérôme DuvalBApplication::ResolveSpecifier(BMessage *message, int32 index,
63937d8f330SAxel Dörfler	BMessage *specifier, int32 what, const char *property)
64052a38012Sejakowatz{
6411f8172a4SJérôme Duval	BPropertyInfo propInfo(sPropertyInfo);
642e91315aaSJérôme Duval	status_t err = B_OK;
643e91315aaSJérôme Duval	uint32 data;
64437d8f330SAxel Dörfler
64537d8f330SAxel Dörfler	if (propInfo.FindMatch(message, 0, specifier, what, property, &data) >= 0) {
646e91315aaSJérôme Duval		switch (data) {
64737d8f330SAxel Dörfler			case kWindowByIndex:
64837d8f330SAxel Dörfler			{
64937d8f330SAxel Dörfler				int32 index;
65037d8f330SAxel Dörfler				err = specifier->FindInt32("index", &index);
651e91315aaSJérôme Duval				if (err != B_OK)
652e91315aaSJérôme Duval					break;
65337d8f330SAxel Dörfler
654e91315aaSJérôme Duval				if (what == B_REVERSE_INDEX_SPECIFIER)
65537d8f330SAxel Dörfler					index = CountWindows() - index;
65637d8f330SAxel Dörfler
65737d8f330SAxel Dörfler				BWindow *window = WindowAt(index);
65837d8f330SAxel Dörfler				if (window != NULL) {
659e91315aaSJérôme Duval					message->PopSpecifier();
66037d8f330SAxel Dörfler					BMessenger(window).SendMessage(message);
66137d8f330SAxel Dörfler				} else
66237d8f330SAxel Dörfler					err = B_BAD_INDEX;
663e91315aaSJérôme Duval				break;
664e91315aaSJérôme Duval			}
66537d8f330SAxel Dörfler
66637d8f330SAxel Dörfler			case kWindowByName:
66737d8f330SAxel Dörfler			{
668e91315aaSJérôme Duval				const char *name;
669e91315aaSJérôme Duval				err = specifier->FindString("name", &name);
670e91315aaSJérôme Duval				if (err != B_OK)
671e91315aaSJérôme Duval					break;
67237d8f330SAxel Dörfler
67337d8f330SAxel Dörfler				for (int32 i = 0;; i++) {
67437d8f330SAxel Dörfler					BWindow *window = WindowAt(i);
67537d8f330SAxel Dörfler					if (window == NULL) {
67637d8f330SAxel Dörfler						err = B_NAME_NOT_FOUND;
67737d8f330SAxel Dörfler						break;
67837d8f330SAxel Dörfler					}
67937d8f330SAxel Dörfler					if (window->Title() != NULL && !strcmp(window->Title(), name)) {
68037d8f330SAxel Dörfler						message->PopSpecifier();
68137d8f330SAxel Dörfler						BMessenger(window).SendMessage(message);
68237d8f330SAxel Dörfler						break;
683e91315aaSJérôme Duval					}
684e91315aaSJérôme Duval				}
685e91315aaSJérôme Duval				break;
686e91315aaSJérôme Duval			}
68737d8f330SAxel Dörfler
68837d8f330SAxel Dörfler			case kLooperByIndex:
68937d8f330SAxel Dörfler			{
69037d8f330SAxel Dörfler				int32 index;
69137d8f330SAxel Dörfler				err = specifier->FindInt32("index", &index);
692e91315aaSJérôme Duval				if (err != B_OK)
693e91315aaSJérôme Duval					break;
69437d8f330SAxel Dörfler
695e91315aaSJérôme Duval				if (what == B_REVERSE_INDEX_SPECIFIER)
69637d8f330SAxel Dörfler					index = CountLoopers() - index;
69737d8f330SAxel Dörfler
69837d8f330SAxel Dörfler				BLooper *looper = LooperAt(index);
69937d8f330SAxel Dörfler				if (looper != NULL) {
700e91315aaSJérôme Duval					message->PopSpecifier();
701e91315aaSJérôme Duval					BMessenger(looper).SendMessage(message);
70237d8f330SAxel Dörfler				} else
70337d8f330SAxel Dörfler					err = B_BAD_INDEX;
704e91315aaSJérôme Duval				break;
705e91315aaSJérôme Duval			}
70637d8f330SAxel Dörfler
70737d8f330SAxel Dörfler			case kLooperByID:
70837d8f330SAxel Dörfler				// TODO: implement getting looper by ID!
709e91315aaSJérôme Duval				break;
71037d8f330SAxel Dörfler
71137d8f330SAxel Dörfler			case kLooperByName:
71237d8f330SAxel Dörfler			{
713e91315aaSJérôme Duval				const char *name;
714e91315aaSJérôme Duval				err = specifier->FindString("name", &name);
715e91315aaSJérôme Duval				if (err != B_OK)
716e91315aaSJérôme Duval					break;
71737d8f330SAxel Dörfler
71837d8f330SAxel Dörfler				for (int32 i = 0;; i++) {
719e91315aaSJérôme Duval					BLooper *looper = LooperAt(i);
72037d8f330SAxel Dörfler					if (looper == NULL) {
72137d8f330SAxel Dörfler						err = B_NAME_NOT_FOUND;
72237d8f330SAxel Dörfler						break;
72337d8f330SAxel Dörfler					}
72437d8f330SAxel Dörfler					if (looper->Name() != NULL && !strcmp(looper->Name(), name)) {
725e91315aaSJérôme Duval						message->PopSpecifier();
726e91315aaSJérôme Duval						BMessenger(looper).SendMessage(message);
72737d8f330SAxel Dörfler						break;
728e91315aaSJérôme Duval					}
729e91315aaSJérôme Duval				}
730e91315aaSJérôme Duval				break;
731e91315aaSJérôme Duval			}
73237d8f330SAxel Dörfler
73337d8f330SAxel Dörfler			case kApplication:
734e91315aaSJérôme Duval				return this;
735e91315aaSJérôme Duval		}
736e91315aaSJérôme Duval	} else {
73737d8f330SAxel Dörfler		return BLooper::ResolveSpecifier(message, index, specifier, what,
73837d8f330SAxel Dörfler			property);
739e91315aaSJérôme Duval	}
7401f8172a4SJérôme Duval
74137d8f330SAxel Dörfler	if (err != B_OK) {
74237d8f330SAxel Dörfler		BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
74337d8f330SAxel Dörfler		reply.AddInt32("error", err);
74437d8f330SAxel Dörfler		reply.AddString("message", strerror(err));
74537d8f330SAxel Dörfler		message->SendReply(&reply);
74637d8f330SAxel Dörfler	}
7471f8172a4SJérôme Duval
748e91315aaSJérôme Duval	return NULL;
749e91315aaSJérôme Duval
75052a38012Sejakowatz}
751beabca50SAxel Dörfler
752beabca50SAxel Dörfler
753beabca50SAxel Dörflervoid
754beabca50SAxel DörflerBApplication::ShowCursor()
75552a38012Sejakowatz{
756dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
7573ceb31b9SDarkWyrm	link.StartMessage(AS_SHOW_CURSOR);
7583ceb31b9SDarkWyrm	link.Flush();
75952a38012Sejakowatz}
760beabca50SAxel Dörfler
761beabca50SAxel Dörfler
762beabca50SAxel Dörflervoid
763beabca50SAxel DörflerBApplication::HideCursor()
76452a38012Sejakowatz{
765dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
7663ceb31b9SDarkWyrm	link.StartMessage(AS_HIDE_CURSOR);
7673ceb31b9SDarkWyrm	link.Flush();
76852a38012Sejakowatz}
769beabca50SAxel Dörfler
770beabca50SAxel Dörfler
771beabca50SAxel Dörflervoid
772beabca50SAxel DörflerBApplication::ObscureCursor()
77352a38012Sejakowatz{
774dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
7753ceb31b9SDarkWyrm	link.StartMessage(AS_OBSCURE_CURSOR);
7763ceb31b9SDarkWyrm	link.Flush();
77752a38012Sejakowatz}
778beabca50SAxel Dörfler
779beabca50SAxel Dörfler
780beabca50SAxel Dörflerbool
781beabca50SAxel DörflerBApplication::IsCursorHidden() const
78252a38012Sejakowatz{
783dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
7846d5488e1SAxel Dörfler	int32 status = B_ERROR;
7853ceb31b9SDarkWyrm	link.StartMessage(AS_QUERY_CURSOR_HIDDEN);
7866d5488e1SAxel Dörfler	link.FlushWithReply(status);
787beabca50SAxel Dörfler
7886d5488e1SAxel Dörfler	return status == B_OK;
78952a38012Sejakowatz}
790beabca50SAxel Dörfler
791beabca50SAxel Dörfler
792beabca50SAxel Dörflervoid
793aa1f5437SAxel DörflerBApplication::SetCursor(const void *cursorData)
79452a38012Sejakowatz{
795aa1f5437SAxel Dörfler	BCursor cursor(cursorData);
796aa1f5437SAxel Dörfler	SetCursor(&cursor, true);
797aa1f5437SAxel Dörfler		// forces the cursor to be sync'ed
79852a38012Sejakowatz}
799beabca50SAxel Dörfler
800beabca50SAxel Dörfler
801beabca50SAxel Dörflervoid
802beabca50SAxel DörflerBApplication::SetCursor(const BCursor *cursor, bool sync)
80352a38012Sejakowatz{
804dd10337fSAxel Dörfler	BPrivate::AppServerLink link;
805aa1f5437SAxel Dörfler	link.StartMessage(AS_SET_CURSOR);
80645799af7SDarkWyrm	link.Attach<bool>(sync);
807aa1f5437SAxel Dörfler	link.Attach<int32>(cursor->fServerToken);
808aa1f5437SAxel Dörfler
809aa1f5437SAxel Dörfler	if (sync) {
810aa1f5437SAxel Dörfler		int32 code;
811dd10337fSAxel Dörfler		link.FlushWithReply(code);
812aa1f5437SAxel Dörfler	} else
81345799af7SDarkWyrm		link.Flush();
81452a38012Sejakowatz}
815beabca50SAxel Dörfler
816beabca50SAxel Dörfler
817beabca50SAxel Dörflerint32
818beabca50SAxel DörflerBApplication::CountWindows() const
81952a38012Sejakowatz{
8209a44fdc9SAxel Dörfler	return _CountWindows(false);
821aa1f5437SAxel Dörfler		// we're ignoring menu windows
82252a38012Sejakowatz}
823beabca50SAxel Dörfler
824beabca50SAxel Dörfler
825beabca50SAxel DörflerBWindow *
826beabca50SAxel DörflerBApplication::WindowAt(int32 index) const
82752a38012Sejakowatz{
8289a44fdc9SAxel Dörfler	return _WindowAt(index, false);
829aa1f5437SAxel Dörfler		// we're ignoring menu windows
83052a38012Sejakowatz}
831beabca50SAxel Dörfler
832beabca50SAxel Dörfler
833beabca50SAxel Dörflerint32
834beabca50SAxel DörflerBApplication::CountLoopers() const
83552a38012Sejakowatz{
8362b2ec438SIngo Weinhold	AutoLocker<BLooperList> ListLock(gLooperList);
837ebbcbbcaSejakowatz	if (ListLock.IsLocked())
838ebbcbbcaSejakowatz		return gLooperList.CountLoopers();
839ebbcbbcaSejakowatz
840beabca50SAxel Dörfler	// Some bad, non-specific thing has happened
841beabca50SAxel Dörfler	return B_ERROR;
84252a38012Sejakowatz}
843