Files
haiku-beta6/src/kits/app/Application.cpp
T
DarkWyrm 45799af7b5 Tweaked all messaging classes to comply with new message protocol policies
AppServerLink no longer inherits from BSession
Modified client files which talk to the server to sync with changes in messaging classes


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4942 a95241bf-73f2-0310-859d-f6bbb57e9c96
2003-10-04 19:08:06 +00:00

1011 lines
29 KiB
C++

//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: Application.cpp
// Author: Erik Jaesler ([email protected])
// Description: BApplication class is the center of the application
// universe. The global be_app and be_app_messenger
// variables are defined here as well.
//------------------------------------------------------------------------------
// Standard Includes -----------------------------------------------------------
#include <new>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// System Includes -------------------------------------------------------------
#include <AppFileInfo.h>
#include <Application.h>
#include <AppMisc.h>
#include <Cursor.h>
#include <Entry.h>
#include <File.h>
#include <Locker.h>
#include <Path.h>
#include <PropertyInfo.h>
#include <RegistrarDefs.h>
#include <Roster.h>
#include <RosterPrivate.h>
#include <Window.h>
// Project Includes ------------------------------------------------------------
#include <LooperList.h>
#include <ObjectLocker.h>
#include <AppServerLink.h>
#include <ServerProtocol.h>
#include <PortLink.h>
#include <PortMessage.h>
// Local Includes --------------------------------------------------------------
// Local Defines ---------------------------------------------------------------
// Uncomment this to run without the registrar - used only for app_server development!
//#define RUN_WITHOUT_REGISTRAR
// Globals ---------------------------------------------------------------------
BApplication* be_app = NULL;
BMessenger be_app_messenger;
BResources* BApplication::_app_resources = NULL;
BLocker BApplication::_app_resources_lock("_app_resources_lock");
property_info gApplicationPropInfo[] =
{
{
"Window",
{},
{B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER},
NULL, 0,
{},
{},
{}
},
{
"Window",
{},
{B_NAME_SPECIFIER},
NULL, 1,
{},
{},
{}
},
{
"Looper",
{},
{B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER},
NULL, 2,
{},
{},
{}
},
{
"Looper",
{},
{B_ID_SPECIFIER},
NULL, 3,
{},
{},
{}
},
{
"Looper",
{},
{B_NAME_SPECIFIER},
NULL, 4,
{},
{},
{}
},
{
"Name",
{B_GET_PROPERTY},
{B_DIRECT_SPECIFIER},
NULL, 5,
{B_STRING_TYPE},
{},
{}
},
{
"Window",
{B_COUNT_PROPERTIES},
{B_DIRECT_SPECIFIER},
NULL, 5,
{B_INT32_TYPE},
{},
{}
},
{
"Loopers",
{B_GET_PROPERTY},
{B_DIRECT_SPECIFIER},
NULL, 5,
{B_MESSENGER_TYPE},
{},
{}
},
{
"Windows",
{B_GET_PROPERTY},
{B_DIRECT_SPECIFIER},
NULL, 5,
{B_MESSENGER_TYPE},
{},
{}
},
{
"Looper",
{B_COUNT_PROPERTIES},
{B_DIRECT_SPECIFIER},
NULL, 5,
{B_INT32_TYPE},
{},
{}
},
{}
};
// argc/argv
extern const int __libc_argc;
extern const char * const *__libc_argv;
class BMenuWindow : public BWindow
{
};
//------------------------------------------------------------------------------
// debugging
//#define DBG(x) x
#define DBG(x)
#define OUT printf
enum {
NOT_IMPLEMENTED = B_ERROR,
};
// prototypes of helper functions
static const char* looper_name_for(const char *signature);
static status_t check_app_signature(const char *signature);
//------------------------------------------------------------------------------
BApplication::BApplication(const char* signature)
: BLooper(looper_name_for(signature)),
fAppName(NULL),
fServerFrom(-1),
fServerTo(-1),
fServerHeap(NULL),
fPulseRate(500000),
fInitialWorkspace(0),
fDraggedMessage(NULL),
fPulseRunner(NULL),
fInitError(B_NO_INIT),
fReadyToRunCalled(false)
{
InitData(signature, NULL);
}
//------------------------------------------------------------------------------
BApplication::BApplication(const char* signature, status_t* error)
: BLooper(looper_name_for(signature)),
fAppName(NULL),
fServerFrom(-1),
fServerTo(-1),
fServerHeap(NULL),
fPulseRate(500000),
fInitialWorkspace(0),
fDraggedMessage(NULL),
fPulseRunner(NULL),
fInitError(B_NO_INIT),
fReadyToRunCalled(false)
{
InitData(signature, error);
}
//------------------------------------------------------------------------------
BApplication::~BApplication()
{
// unregister from the roster
BRoster::Private().RemoveApp(Team());
// uninitialize be_app and be_app_messenger
be_app = NULL;
// R5 doesn't uninitialize be_app_messenger.
// be_app_messenger = BMessenger();
}
//------------------------------------------------------------------------------
BApplication::BApplication(BMessage* data)
: BLooper(looper_name_for(NULL)),
fAppName(NULL),
fServerFrom(-1),
fServerTo(-1),
fServerHeap(NULL),
fPulseRate(500000),
fInitialWorkspace(0),
fDraggedMessage(NULL),
fPulseRunner(NULL),
fInitError(B_NO_INIT),
fReadyToRunCalled(false)
{
}
//------------------------------------------------------------------------------
BArchivable* BApplication::Instantiate(BMessage* data)
{
if (!validate_instantiation(data, "BApplication"))
{
return NULL;
}
return new BApplication(data);
}
//------------------------------------------------------------------------------
status_t BApplication::Archive(BMessage* data, bool deep) const
{
return NOT_IMPLEMENTED;
}
//------------------------------------------------------------------------------
status_t BApplication::InitCheck() const
{
return fInitError;
}
//------------------------------------------------------------------------------
thread_id BApplication::Run()
{
AssertLocked();
if (fRunCalled)
{
// Not allowed to call Run() more than once
// TODO: test
// find out what message is actually here
debugger("");
}
// Note: We need a local variable too (for the return value), since
// fTaskID is cleared by Quit().
thread_id thread = fTaskID = find_thread(NULL);
if (fMsgPort == B_NO_MORE_PORTS || fMsgPort == B_BAD_VALUE)
{
return fMsgPort;
}
fRunCalled = true;
run_task();
return thread;
}
//------------------------------------------------------------------------------
void BApplication::Quit()
{
bool unlock = false;
if (!IsLocked()) {
const char* name = Name();
if (!name)
name = "no-name";
printf("ERROR - you must Lock the application object before calling "
"Quit(), team=%ld, looper=%s\n", Team(), name);
unlock = true;
if (!Lock())
return;
}
// Delete the object, if not running only.
if (!fRunCalled) {
delete this;
} else if (find_thread(NULL) != fTaskID) {
// We are not the looper thread.
// We push a _QUIT_ into the queue.
// TODO: When BLooper::AddMessage() is done, use that instead of
// PostMessage()??? This would overtake messages that are still at
// the port.
// NOTE: We must not unlock here -- otherwise we had to re-lock, which
// may not work. This is bad, since, if the port is full, it
// won't get emptier, as the looper thread needs to lock the object
// before dispatching messages.
while (PostMessage(_QUIT_, this) == B_WOULD_BLOCK)
snooze(10000);
} else {
// We are the looper thread.
// Just set fTerminating to true which makes us fall through the
// message dispatching loop and return from Run().
fTerminating = true;
}
// If we had to lock the object, unlock now.
if (unlock)
Unlock();
}
//------------------------------------------------------------------------------
bool BApplication::QuitRequested()
{
// No windows -- nothing to do.
return BLooper::QuitRequested();
}
//------------------------------------------------------------------------------
void BApplication::Pulse()
{
}
//------------------------------------------------------------------------------
void BApplication::ReadyToRun()
{
}
//------------------------------------------------------------------------------
void BApplication::MessageReceived(BMessage* msg)
{
BLooper::MessageReceived(msg);
}
//------------------------------------------------------------------------------
void BApplication::ArgvReceived(int32 argc, char** argv)
{
}
//------------------------------------------------------------------------------
void BApplication::AppActivated(bool active)
{
}
//------------------------------------------------------------------------------
void BApplication::RefsReceived(BMessage* a_message)
{
}
//------------------------------------------------------------------------------
void BApplication::AboutRequested()
{
}
//------------------------------------------------------------------------------
BHandler* BApplication::ResolveSpecifier(BMessage* msg, int32 index,
BMessage* specifier, int32 form,
const char* property)
{
return NULL; // not implemented
}
//------------------------------------------------------------------------------
void BApplication::ShowCursor()
{
// Because we're just sending an opcode, we can skip the BSession and fake the protocol
int32 foo=AS_SHOW_CURSOR;
write_port(fServerTo,AS_SHOW_CURSOR,&foo,sizeof(int32));
}
//------------------------------------------------------------------------------
void BApplication::HideCursor()
{
// Because we're just sending an opcode, we can skip the BSession and fake the protocol
int32 foo=AS_HIDE_CURSOR;
write_port(fServerTo,AS_HIDE_CURSOR,&foo,sizeof(int32));
}
//------------------------------------------------------------------------------
void BApplication::ObscureCursor()
{
// Because we're just sending an opcode, we can skip the BSession and fake the protocol
int32 foo=AS_OBSCURE_CURSOR;
write_port(fServerTo,AS_OBSCURE_CURSOR,&foo,sizeof(int32));
}
//------------------------------------------------------------------------------
bool BApplication::IsCursorHidden() const
{
PortMessage msg;
BPrivate::BAppServerLink link;
link.SetOpCode(AS_QUERY_CURSOR_HIDDEN);
link.FlushWithReply(&msg);
return (msg.Code()==SERVER_TRUE)?true:false;
}
//------------------------------------------------------------------------------
void BApplication::SetCursor(const void* cursor)
{
// BeBook sez: If you want to call SetCursor() without forcing an immediate
// sync of the Application Server, you have to use a BCursor.
// By deductive reasoning, this function forces a sync. =)
BCursor Cursor(cursor);
SetCursor(&Cursor, true);
}
//------------------------------------------------------------------------------
void BApplication::SetCursor(const BCursor* cursor, bool sync)
{
BPrivate::BAppServerLink link;
PortMessage msg;
link.SetOpCode(AS_SET_CURSOR_BCURSOR);
link.Attach<bool>(sync);
link.Attach<int32>(cursor->m_serverToken);
if(sync)
link.FlushWithReply(&msg);
else
link.Flush();
}
//------------------------------------------------------------------------------
int32 BApplication::CountWindows() const
{
// BeBook sez: The windows list includes all windows explicitely created by
// the app ... but excludes private windows create by Be
// classes.
// I'm taking this to include private menu windows, thus the incl_menus
// param is false.
return count_windows(false);
}
//------------------------------------------------------------------------------
BWindow* BApplication::WindowAt(int32 index) const
{
// BeBook sez: The windows list includes all windows explicitely created by
// the app ... but excludes private windows create by Be
// classes.
// I'm taking this to include private menu windows, thus the incl_menus
// param is false.
return window_at(index, false);
}
//------------------------------------------------------------------------------
int32 BApplication::CountLoopers() const
{
using namespace BPrivate;
BObjectLocker<BLooperList> ListLock(gLooperList);
if (ListLock.IsLocked())
{
return gLooperList.CountLoopers();
}
return B_ERROR; // Some bad, non-specific thing has happened
}
//------------------------------------------------------------------------------
BLooper* BApplication::LooperAt(int32 index) const
{
using namespace BPrivate;
BLooper* Looper = NULL;
BObjectLocker<BLooperList> ListLock(gLooperList);
if (ListLock.IsLocked())
{
Looper = gLooperList.LooperAt(index);
}
return Looper;
}
//------------------------------------------------------------------------------
bool BApplication::IsLaunching() const
{
return !fReadyToRunCalled;
}
//------------------------------------------------------------------------------
status_t BApplication::GetAppInfo(app_info* info) const
{
return be_roster->GetRunningAppInfo(be_app->Team(), info);
}
//------------------------------------------------------------------------------
BResources* BApplication::AppResources()
{
return NULL; // not implemented
}
//------------------------------------------------------------------------------
void BApplication::DispatchMessage(BMessage* message, BHandler* handler)
{
switch (message->what) {
case B_ARGV_RECEIVED:
{
// build the argv vector
status_t error = B_OK;
int32 argc;
char **argv = NULL;
if (message->FindInt32("argc", &argc) == B_OK && argc > 0) {
argv = new char*[argc];
for (int32 i = 0; error == B_OK && i < argc; i++)
argv[i] = NULL;
// copy the arguments
for (int32 i = 0; error == B_OK && i < argc; i++) {
const char *arg = NULL;
error = message->FindString("argv", i, &arg);
if (error == B_OK && arg) {
argv[i] = new(std::nothrow) char[strlen(arg) + 1];
if (argv[i])
strcpy(argv[i], arg);
else
error = B_NO_MEMORY;
}
}
}
// call the hook
if (error == B_OK)
ArgvReceived(argc, argv);
// cleanup
if (argv) {
for (int32 i = 0; i < argc; i++)
delete[] argv[i];
delete[] argv;
}
break;
}
case B_REFS_RECEIVED:
RefsReceived(message);
break;
case B_READY_TO_RUN:
// TODO: Find out, whether to set fReadyToRunCalled before or
// after calling the hook.
ReadyToRun();
fReadyToRunCalled = true;
break;
default:
BLooper::DispatchMessage(message, handler);
break;
}
}
//------------------------------------------------------------------------------
void BApplication::SetPulseRate(bigtime_t rate)
{
fPulseRate = rate;
}
//------------------------------------------------------------------------------
status_t BApplication::GetSupportedSuites(BMessage* data)
{
status_t err = B_OK;
if (!data)
{
err = B_BAD_VALUE;
}
if (!err)
{
err = data->AddString("Suites", "suite/vnd.Be-application");
if (!err)
{
BPropertyInfo PropertyInfo(gApplicationPropInfo);
err = data->AddFlat("message", &PropertyInfo);
if (!err)
{
err = BHandler::GetSupportedSuites(data);
}
}
}
return err;
}
//------------------------------------------------------------------------------
status_t BApplication::Perform(perform_code d, void* arg)
{
return NOT_IMPLEMENTED;
}
//------------------------------------------------------------------------------
BApplication::BApplication(uint32 signature)
{
}
//------------------------------------------------------------------------------
BApplication::BApplication(const BApplication& rhs)
{
}
//------------------------------------------------------------------------------
BApplication& BApplication::operator=(const BApplication& rhs)
{
return *this;
}
//------------------------------------------------------------------------------
void BApplication::_ReservedApplication1()
{
}
//------------------------------------------------------------------------------
void BApplication::_ReservedApplication2()
{
}
//------------------------------------------------------------------------------
void BApplication::_ReservedApplication3()
{
}
//------------------------------------------------------------------------------
void BApplication::_ReservedApplication4()
{
}
//------------------------------------------------------------------------------
void BApplication::_ReservedApplication5()
{
}
//------------------------------------------------------------------------------
void BApplication::_ReservedApplication6()
{
}
//------------------------------------------------------------------------------
void BApplication::_ReservedApplication7()
{
}
//------------------------------------------------------------------------------
void BApplication::_ReservedApplication8()
{
}
//------------------------------------------------------------------------------
bool BApplication::ScriptReceived(BMessage* msg, int32 index, BMessage* specifier, int32 form, const char* property)
{
return false; // not implemented
}
//------------------------------------------------------------------------------
void BApplication::run_task()
{
task_looper();
}
//------------------------------------------------------------------------------
void BApplication::InitData(const char* signature, status_t* error)
{
// check whether there exists already an application
if (be_app)
debugger("2 BApplication objects were created. Only one is allowed.");
// check signature
fInitError = check_app_signature(signature);
fAppName = signature;
bool isRegistrar = (signature && !strcmp(signature, kRegistrarSignature));
// get team and thread
team_id team = Team();
thread_id thread = BPrivate::main_thread_for(team);
// get app executable ref
entry_ref ref;
if (fInitError == B_OK)
fInitError = BPrivate::get_app_ref(&ref);
// get the BAppFileInfo and extract the information we need
uint32 appFlags = B_REG_DEFAULT_APP_FLAGS;
if (fInitError == B_OK) {
BAppFileInfo fileInfo;
BFile file(&ref, B_READ_ONLY);
fInitError = fileInfo.SetTo(&file);
if (fInitError == B_OK) {
fileInfo.GetAppFlags(&appFlags);
char appFileSignature[B_MIME_TYPE_LENGTH + 1];
// compare the file signature and the supplied signature
if (fileInfo.GetSignature(appFileSignature) == B_OK) {
if (strcmp(appFileSignature, signature) != 0) {
printf("Signature in rsrc doesn't match constructor arg. "
"(%s,%s)\n", signature, appFileSignature);
}
}
}
}
#ifndef RUN_WITHOUT_REGISTRAR
// check whether be_roster is valid
if (fInitError == B_OK && !isRegistrar
&& !BRoster::Private().IsMessengerValid(false)) {
printf("FATAL: be_roster is not valid. Is the registrar running?\n");
fInitError = B_NO_INIT;
}
// check whether or not we are pre-registered
bool preRegistered = false;
app_info appInfo;
if (fInitError == B_OK && !isRegistrar) {
preRegistered = BRoster::Private().IsAppPreRegistered(&ref, team,
&appInfo);
}
if (preRegistered) {
// we are pre-registered => the app info has been filled in
// Check whether we need to replace the looper port with a port
// created by the roster.
if (appInfo.port >= 0 && appInfo.port != fMsgPort) {
delete_port(fMsgPort);
fMsgPort = appInfo.port;
} else
appInfo.port = fMsgPort;
// check the signature and correct it, if necessary
if (strcmp(appInfo.signature, fAppName))
BRoster::Private().SetSignature(team, fAppName);
// complete the registration
fInitError = BRoster::Private().CompleteRegistration(team, thread,
appInfo.port);
} else if (fInitError == B_OK) {
// not pre-registered -- try to register the application
team_id otherTeam = -1;
// the registrar must not register
if (!isRegistrar) {
fInitError = BRoster::Private().AddApplication(signature, &ref,
appFlags, team, thread, fMsgPort, true, NULL, &otherTeam);
}
if (fInitError == B_ALREADY_RUNNING) {
// An instance is already running and we asked for
// single/exclusive launch. Send our argv to the running app.
// Do that only, if the app is NOT B_ARGV_ONLY.
if (otherTeam >= 0 && __libc_argc > 1) {
app_info otherAppInfo;
if (be_roster->GetRunningAppInfo(otherTeam, &otherAppInfo)
== B_OK && !(otherAppInfo.flags & B_ARGV_ONLY)) {
// create an B_ARGV_RECEIVED message
BMessage argvMessage(B_ARGV_RECEIVED);
do_argv(&argvMessage);
// replace the first argv string with the path of the
// other application
BPath path;
if (path.SetTo(&otherAppInfo.ref) == B_OK)
argvMessage.ReplaceString("argv", 0, path.Path());
// send the message
BMessenger(NULL, otherTeam).SendMessage(&argvMessage);
}
}
} else if (fInitError == B_OK) {
// the registrations was successful
// Create a B_ARGV_RECEIVED message and send it to ourselves.
// Do that even, if we are B_ARGV_ONLY.
// TODO: When BLooper::AddMessage() is done, use that instead of
// PostMessage().
if (__libc_argc > 1) {
BMessage argvMessage(B_ARGV_RECEIVED);
do_argv(&argvMessage);
PostMessage(&argvMessage, this);
}
// send a B_READY_TO_RUN message as well
PostMessage(B_READY_TO_RUN, this);
} else if (fInitError > B_ERRORS_END) {
// Registrar internal errors shouldn't fall into the user's hands.
fInitError = B_ERROR;
}
}
#endif // ifdef RUN_WITHOUT_REGISTRAR
// Notify app_server that we exist
fServerFrom=find_port(SERVER_PORT_NAME);
if(fServerFrom!=B_NAME_NOT_FOUND)
{
// Create the port so that the app_server knows where to send messages
fServerTo=create_port(100,"a<fServerTo");
if(fServerTo!=B_BAD_VALUE && fServerTo!=B_NO_MORE_PORTS)
{
// AS_CREATE_APP:
// Attach data:
// 1) port_id - receiver port of a regular app
// 2) int32 - handler ID token of the app
// 3) char * - signature of the regular app
PortLink link(fServerFrom);
PortMessage pmsg;
link.SetOpCode(AS_CREATE_APP);
link.Attach<port_id>(fServerTo);
link.Attach<port_id>(_get_object_token_(this));
link.AttachString(signature);
link.FlushWithReply(&pmsg);
// Reply code: AS_CREATE_APP
// Reply data:
// 1) port_id server-side application port (fServerFrom value)
pmsg.Read<port_id>(&fServerFrom);
}
else
fInitError=fServerTo;
}
// init be_app and be_app_messenger
if (fInitError == B_OK) {
be_app = this;
be_app_messenger = BMessenger(NULL, this);
}
// set the BHandler's name
if (fInitError == B_OK)
SetName(ref.name);
// create meta MIME
if (fInitError == B_OK) {
BPath path;
if (path.SetTo(&ref) == B_OK)
create_app_meta_mime(path.Path(), false, true, false);
}
// Return the error or exit, if there was an error and no error variable
// has been supplied.
if (error)
*error = fInitError;
else if (fInitError != B_OK)
exit(0);
}
//------------------------------------------------------------------------------
void BApplication::BeginRectTracking(BRect r, bool trackWhole)
{
BPrivate::BAppServerLink link;
link.Attach<int32>(AS_BEGIN_RECT_TRACKING);
link.Attach<BRect>(r);
link.Attach<int32>(trackWhole);
link.Flush();
}
//------------------------------------------------------------------------------
void BApplication::EndRectTracking()
{
int32 foo=AS_END_RECT_TRACKING;
write_port(fServerTo,AS_END_RECT_TRACKING,&foo,sizeof(int32));
}
//------------------------------------------------------------------------------
void BApplication::get_scs()
{
}
//------------------------------------------------------------------------------
void BApplication::setup_server_heaps()
{
}
//------------------------------------------------------------------------------
void* BApplication::rw_offs_to_ptr(uint32 offset)
{
return NULL; // not implemented
}
//------------------------------------------------------------------------------
void* BApplication::ro_offs_to_ptr(uint32 offset)
{
return NULL; // not implemented
}
//------------------------------------------------------------------------------
void* BApplication::global_ro_offs_to_ptr(uint32 offset)
{
return NULL; // not implemented
}
//------------------------------------------------------------------------------
void BApplication::connect_to_app_server()
{
}
//------------------------------------------------------------------------------
void BApplication::send_drag(BMessage* msg, int32 vs_token, BPoint offset, BRect drag_rect, BHandler* reply_to)
{
}
//------------------------------------------------------------------------------
void BApplication::send_drag(BMessage* msg, int32 vs_token, BPoint offset, int32 bitmap_token, drawing_mode dragMode, BHandler* reply_to)
{
}
//------------------------------------------------------------------------------
void BApplication::write_drag(_BSession_* session, BMessage* a_message)
{
}
//------------------------------------------------------------------------------
bool BApplication::quit_all_windows(bool force)
{
return false; // not implemented
}
//------------------------------------------------------------------------------
bool BApplication::window_quit_loop(bool, bool)
{
return false; // not implemented
}
//------------------------------------------------------------------------------
void BApplication::do_argv(BMessage* message)
{
if (message) {
int32 argc = __libc_argc;
const char * const *argv = __libc_argv;
// add argc
message->AddInt32("argc", argc);
// add argv
for (int32 i = 0; i < argc; i++)
message->AddString("argv", argv[i]);
// add current working directory
char cwd[B_PATH_NAME_LENGTH + 1];
if (getcwd(cwd, B_PATH_NAME_LENGTH + 1))
message->AddString("cwd", cwd);
}
}
//------------------------------------------------------------------------------
uint32 BApplication::InitialWorkspace()
{
return 0; // not implemented
}
//------------------------------------------------------------------------------
int32 BApplication::count_windows(bool incl_menus) const
{
using namespace BPrivate;
// Windows are BLoopers, so we can just check each BLooper to see if it's
// a BWindow (or BMenuWindow)
int32 count = 0;
BObjectLocker<BLooperList> ListLock(gLooperList);
if (ListLock.IsLocked())
{
BLooper* Looper = NULL;
for (int32 i = 0; i < gLooperList.CountLoopers(); ++i)
{
Looper = gLooperList.LooperAt(i);
if (dynamic_cast<BWindow*>(Looper))
{
if (incl_menus || dynamic_cast<BMenuWindow*>(Looper) == NULL)
{
++count;
}
}
}
}
return count;
}
//------------------------------------------------------------------------------
BWindow* BApplication::window_at(uint32 index, bool incl_menus) const
{
using namespace BPrivate;
// Windows are BLoopers, so we can just check each BLooper to see if it's
// a BWindow (or BMenuWindow)
uint32 count = 0;
BWindow* Window = NULL;
BObjectLocker<BLooperList> ListLock(gLooperList);
if (ListLock.IsLocked())
{
BLooper* Looper = NULL;
for (int32 i = 0; i < gLooperList.CountLoopers() && !Window; ++i)
{
Looper = gLooperList.LooperAt(i);
if (dynamic_cast<BWindow*>(Looper))
{
if (incl_menus || dynamic_cast<BMenuWindow*>(Looper) == NULL)
{
if (count == index)
{
Window = dynamic_cast<BWindow*>(Looper);
}
else
{
++count;
}
}
}
}
}
return Window;
}
//------------------------------------------------------------------------------
status_t BApplication::get_window_list(BList* list, bool incl_menus) const
{
return NOT_IMPLEMENTED;
}
//------------------------------------------------------------------------------
int32 BApplication::async_quit_entry(void* data)
{
return 0; // not implemented
}
//------------------------------------------------------------------------------
// check_app_signature
/*! \brief Checks whether the supplied string is a valid application signature.
An error message is printed, if the string is no valid app signature.
\param signature The string to be checked.
\return
- \c B_OK: \a signature is a valid app signature.
- \c B_BAD_VALUE: \a signature is \c NULL or no valid app signature.
*/
static
status_t
check_app_signature(const char *signature)
{
bool isValid = false;
BMimeType type(signature);
if (type.IsValid() && !type.IsSupertypeOnly()
&& BMimeType("application").Contains(&type)) {
isValid = true;
}
if (!isValid) {
printf("bad signature (%s), must begin with \"application/\" and "
"can't conflict with existing registered mime types inside "
"the \"application\" media type.\n", signature);
}
return (isValid ? B_OK : B_BAD_VALUE);
}
// looper_name_for
/*! \brief Returns the looper name for a given signature.
Normally this is "AppLooperPort", but in case of the registrar a
special name.
\return The looper name.
*/
static
const char*
looper_name_for(const char *signature)
{
if (signature && !strcmp(signature, kRegistrarSignature))
return kRosterPortName;
return "AppLooperPort";
}
/*
* $Log $
*
* $Id $
*
*/