The Application Kit: BApplication

The Application Kit Table of Contents | The Application Kit Index

# BApplication

Derived from: BLooper > BHandler > BArchivable

Declared in: be/app/Application.h

Library: libbe.so

###### Summary

The BApplication class defines an object that represents your application, creates a connection to the App Server, and runs your app's main message loop. An app can only create one BApplication object; the system automatically set the global `be_app` object to point to the BApplication object you create.

A BApplication object's most pervasive task is to handle messages that are sent to your app, a subject that's described in detail below. But message handling aside, you can also use your BApplication object to...

- Control the cursor. BApplication defines functions that hide and show the cursor, and set the cursor's image. See `SetCursor()`.

- Access the window list. You can iterate through the windows that your application has created with `WindowAt()`.

- Get information about your application. Your app's signature, executable location, and launch flags can be retrieved through `GetAppInfo()`. Additional information—icons, version strings, recognized file types—can be retrieved by creating an BAppFileInfo object based on your app's executable file. BAppFileInfo is defined in the Storage Kit.

  ### be_app and Subclassing BApplication

  Because of its importance, the BApplication object that you create is automatically assigned to the global `be_app` variable. Anytime you need to refer to your BApplication object—from anywhere in your code—you can use `be_app` instead.

  Unless you're creating a very simple application, you should subclass BApplication. But be aware that the `be_app` variable is typed as (BApplication *). You'll have to cast `be_app` when you call a function that's declared by your subclass:

         ((MyApp *)be_app)->MyAppFunction();

  ### Constructing the Object and Running the Message Loop

  As with all BLoopers, to use a BApplication you construct the object and then tell it to start its message loop by calling the `Run()` function. However, unlike other loopers, BApplication's `Run()` doesn't return until the application is told to quit. And after `Run()` returns, you delete the object—it isn't deleted for you.

  Typically, you create your BApplication object in your `main()` function—it's usually the first object you create. The barest outline of a typical `main()` function looks something like this:

         #include <Application.h>

         main()1
         {
            2new BApplication("application/x-vnd.your-app-sig")3;

            /* Further initialization goes here -- read settings, set globals, etc. */

            be_app->Run()4;

            /* Clean up -- write settings, etc. */

            delete be_app;
         }

  1 The `main()` function doesn't declare argc and argv parameters (used for passing along command line arguments). If the user passes command line arguments to your app, they'll show up in the `ArgvReceived()` hook function.

  2 Why no pointer assignment? The constructor automatically assigns the object to `be_app`, so you don't have to assign it yourself.

  3 The string passed to the constructor sets the application's signature. This is a precautionary measure—it's better to add the signature as a resource than to define it here (a resource signature overrides the constructor signature). Use the `FileTypes` app to set the signature as a resource.

  4 As explained in the BLooper class, `Run()` is almost always called from the same thread in which you construct the BApplication object. (More accurately, the constructor locks the object, and `Run()` unlocks it. Since locks are scoped to threads, the easiest thing to do is to construct and `Run()` in the same thread.)

  ### Application Messages

  After you tell your BApplication to run, its message loop begins to receive messages. In general, the messages are handled in the expected fashion: They show up in BApplication's `MessageReceived()` function (or that of a designated BHandler; for more on how messages are dispatched to handlers, see <x>).

  But BApplication also recognizes a set of application messages that it handles by invoking corresponding hook functions. The hook functions are invoked by `DispatchMessage()` so the application messages never show up in `MessageReceived()`.

  Overriding the hook functions that correspond to the application messages is an important part of the implementation of a BApplication subclass.

  In the table below, the application messages (identified by their command constants) are listed in roughly the order your BApplication can expect to receive them.

  Command Constant | Hook function | Description
  --- | --- | ---
  `B_ARGV_RECEIVED` | `ArgvReceived()` | Command line arguments are delivered through this message.
  `B_REFS_RECEIVED` | `RefsReceived()` | Files (entry_refs) that are dropped on your app's icon, or that are double-clicked to launch your app are delivered through this message.
  `B_READY_TO_RUN` | `ReadyToRun()` | Invoked from within `Run()`, the application has finished configuring itself and is ready to go. If you haven't already created and displayed an initial window, you should do so here.
  `B_APP_ACTIVATED` | `AppActivated()` | The application has just become the active application, or has relinquished that status.
  `B_PULSE` | `Pulse()` | If requested, pulse messages are sent at regular intervals by the system.
  `B_ABOUT_REQUESTED` | `AboutRequested()` | The user wants to see the app's About... box.

  The protocols for the application messages are described <x>.

  For more information on the details of when and why the hook functions are invoked, see the individual function descriptions.

  A BApplication can also receive the `B_QUIT_REQUESTED` looper message. As explained in BLooper, `B_QUIT_REQUESTED` causes `Quit()` to be called, contingent on the value returned by the `QuitRequested()` hook function. However, BApplication's implementation of `Quit()` is different from BLooper's version. Don't miss it.

  ### Other Topics

  - Locking. As a BLooper, a BApplication mustt be locked before calling certain protected functions. The BApplication locking mechanism is inherited without modification from BLooper.

  - FileTypes settings. The BApplication object represents your application at run-time. However, some of the characteristics of your app—whether it can be launched more than once, the file types it can open, its icon—are not run-time decisions.

  ## Hook Functions

  `AboutRequested()`

  AppActivated()

  ArgvReceived()

  Pulse()

  ReadyToRun()

  RefsReceived()

  ## Constructor and Destructor

  ### BApplication()

  `BApplication(`const char *signature`)`
  `BApplication(`const char *signature, status_t *error`)`
  `BApplication(` BMessage *archive`)`

  The constructor creates a new object, locks it, sets the global variable `be_app` to point to it, and establishes a connection to the Application Server. From this point on, your app can receive messages, although it won't start processing them until you call `Run()`. You can also begin creating and displaying BWindow objects—even before you call `Run()`.

  The signature constructors assign the argument as the app's application signature. The argument is ignored if a signature is already specified in a resource or attribute of the application's executable (serious apps should always set the signature as both an attribute and a resource). The signature is a MIME type string that must have the supertype "application". For more information on application signatures and how to set them, see <x>.

  If you specify error, a pointer to a status_t, any error that occurs while constructing the BApplication will be returned in that variable. Alternately, you can call `InitCheck()` to check the results. If an error is returned by the constructor, you shouldn't call `Run()`.

  The archive constructor is an implementation detail; see the BArchivable class.

  ### ~BApplication()

  virtual`~BApplication() `

  Closes and deletes the application's BWindows (and the BViews they contain), and severs the application's connection to the Application Server.

  Never delete a BApplication object while it's running—wait until `Run()` returns. To stop a BApplication (and so cause `Run()` to return), send it a `B_QUIT_REQUESTED` message:

         be_app->PostMessage(B_QUIT_REQUESTED);

  ## Static Functions

  ### AppResources()

  `static` `BResources` *`AppResources(`void`) `

  Returns a BResources object that's configured from your application's executable file. You may read the data in the BResources object, but you're not allowed to write it; see the BResources class for details. The BResources object belongs to the BApplication class and mustn't be freed.

  You needn't have a `be_app` object to invoke this function.

  ### Instantiate() see BArchivable::Instantiate()

  ## Member Functions

  ### AboutRequested()

  virtual void `AboutRequested(`void`) `

  Hook function that's invoked when the BApplication receives a `B_ABOUT_REQUESTED` message, undoubtedly because the user clicked an About... menu item. You should implement the function to put a window on-screen that provides the user with information about the application (version number, license restrictions, authors' names, etc).

  ### AppActivated()

  virtual void `AppActivated(`bool active`) `

  Hook function that's invoked when the application receives a `B_APP_ACTIVATED` message. The message is sent when the app gains or loses active application status. The active flag tells you which way the wind blows: `true` means your app is now active; `false` means it isn't.

  The user can activate an app by clicking on or unhiding one of its windows; you can activate an app programmatically by calling `BWindow::Activate()` or `BRoster::ActivateApp()`. (With regard to the latter: This function is called only if the app has an "activatable" window—i.e. a non-modal, non-floating window).

  During launch, this function is called after `ReadyToRun()` (provided the app is displaying an activatable window).

  "be_app"

  ### Archive() , see

  ### ArgvReceived()

  virtual void `ArgvReceived(`int32 argc, char **argv`) `

  Hook function that's invoked when the application receives a `B_ARGV_RECEIVED` message. The message is sent if command line arguments are used in launching the app from the shell, or if argv/argc values are passed to `BRoster::Launch()`.

  | This function isn't called if there were no command line arguments, or if `BRoster::Launch()` was called without argv/argc values.

  When the app is launched from the shell, `ArgvReceived()`'s arguments are identical to the traditional `main()` arguments: The number of command line arguments is passed as argc; the arguments themselves are passed as an array of strings in argv. The first argv string identifes the executable file; the other strings are the command line arguments proper. For example, this...

         $ MyApp file1 file2

  ...produces the argv array {"./MyApp", "file1", "file2"}.

  `BRoster::Launch()` forwards its argv and argc arguments, but adds the executable name to the front of the argv array and increments the argc value.

  Normally, the `B_ARGV_RECEIVED` message (if sent at all) is sent once, just before `B_READY_TO_RUN` is sent. However, if the user tries to re-launch (from the command line and with arguments) an already-running app that's set to `B_EXCLUSIVE_LAUNCH` or `B_SINGLE_LAUNCH`, the re-launch will generate a `B_ARGV_RECEIVED` message that's sent to the already-running image. Thus, for such apps, the `B_ARGV_RECEIVED` message can show up at any time.

  ### CountWindows() see WindowAt()

  ### DispatchMessage() see BLooper::DispatchMessage()

  ### GetAppInfo()

  status_t `GetAppInfo(`app_info *theInfo`)` const

  Returns information about the application. This is a cover for

         be_roster–>GetRunningAppInfo(be_app->Team(), theInfo);

  See `BRoster::GetAppInfo()` for more information.

  ### HideCursor() see SetCursor()

  ### IsCursorHidden() see SetCursor()

  ### IsLaunching()

  bool `IsLaunching(`void`)` const

  Returns `true` if the app is still launching. An app is considered to be in its launching phase until `ReadyToRun()` returns. Invoked from within `ReadyToRun()`, `IsLaunching()` returns `true`.

  ### MessageReceived() see BHandler::MessageReceived()

  ### ObscureCursor() see SetCursor()

  ### Pulse() , SetPulseRate()

  virtual void `Pulse(`void`) `
  void `SetPulseRate(`bigtime_t rate`) `

  `Pulse()` is a hook function that's called when the app receives a `B_PULSE` message. The message is sent once every rate microseconds, as set in `SetPulseRate()`. The first `Pulse()` message is sent after `ReadyToRun()` returns. If the pulse rate is 0 (the default), the `B_PULSE` messages aren't sent.

  You can implement `Pulse()` to do whatever you want (the default version does nothing), but don't try to use it for precision timing: The pulse granularity is no better than 100,000 microseconds.

  Keep in mind that `Pulse()` executes in the app's message loop thread along with all other message handling functions. Your app won't receive any `Pulse()` invocations while it's waiting for some other handler function (including `MessageReceived()`) to finish. In the meantime, `B_PULSE` messages will be stacking up in the message queue; when the loop becomes "unblocked", you'll see a burst of `Pulse()` invocations.

  ### Quit() see Run()

  ### QuitRequested()

  virtual bool `QuitRequested(`void`) `

  Hook function that's invoked when the app receives a `B_QUIT_REQUESTED` message. As described in the BLooper class (which declares this function), the request to quit is confirmed if `QuitRequested()` returns `true`, and denied if it returns `false`.

  In its implementation, BApplication sends `BWindow::QuitRequested()` to each of its BWindow objects. If they all agree to quit, the windows are all destroyed (through `BWindow::Quit()`) and this `QuitRequested()` returns `true`. But if any BWindow refuses to quit, that window and all surviving windows are saved, and this `QuitRequested()` returns `false`.

  Augment this function as you will, but be sure to call the BApplication version in your implementation.

  ### ReadyToRun()

  virtual void `ReadyToRun(`void`) `

  Hook function that's called when the app receives a `B_READY_TO_RUN` message. The message is sent automatically during the `Run()` function, and is sent after the initial `B_REFS_RECEIVED` and `B_ARGV_RECEIVED` messages (if any) have been handled. This is the only application message that every running app is guaranteed to receive.

  What you do with `ReadyToRun()` is up to you—if your app hasn't put up a window by the time this function is called, you'll probably want to do it here. The default version of `ReadyToRun()` is empty.

  ### RefsReceived()

  virtual void `RefsReceived(` BMessage *message`) `

  Hook function that's called when the app receives a `B_REFS_RECEIVED` message. The message is sent when the user drops a file (or files) on your app's icon, or double clicks a file that's handled by your app. The message can arrive either at launch time, or while your app is already running—use `IsLaunching()` to tell which.

  message contains a single field named "refs" that contains one or more `entry_ref` (`B_REF_TYPE`) items—one for each file that was dropped or double-clicked. Do with them what you will; the default implementation is empty. Typically, you would use the refs to create BEntry or BFile objects.

  "Scripting Suites and Properties"

  ### ResolveSpecifier() , see

  ### Run() , Quit()

  virtual thread_id `Run(`void`) `
  virtual void `Quit(`void`) `

  These functions, inherited from BLooper, are different enough from their parent versions to warrant description:

  - `Run()` doesn't spawn a new thread—it runs the message loop in the thread that it's called from, and doesn't return until the message loop stops.

  - `Quit()` doesn't kill the looper thread—it tells the thread to finish processing the message queue (disallowing new messages) at which point `Run()` will be able to return. After so instructing the thread, `Quit()` returns—it doesn't wait for the message queue to empty.

  - Also, `Quit()` doesn't delete the BApplication object. It's up to you to delete it after `Run()` returns. (However, `Quit()` does delete the object if it's called before the message loop starts—i.e. before `Run()` is called.)

  ### SetCursor() , HideCursor() , ShowCursor() , ObscureCursor() , IsCursorHidden()

  ``

  void `SetCursor(`const void *cursor`) `
  void `SetCursor(`const BCursor *cursor, bool sync = true`) `
  void `HideCursor(`void`) `
  void `ShowCursor(`void`) `
  void `ObscureCursor(`void`) `
  bool `IsCursorHidden(`void`)` const

  Cursor functions:

  - `SetCursor()` sets the cursor image that's used when this is the active application. You can pass one of the Be-defined cursor constants (`B_HAND_CURSOR` and `B_I_BEAM_CURSOR`) or create your own cursor image. The cursor data format is described below.

  - You can also call `SetCursor()` passing a BCursor object; specifying sync as `true` forces the Application Server to immediately resynchronize, thereby ensuring that the cursor change takes place immediately. The default BCursors are `B_CURSOR_SYSTEM_DEFAULT` for the hand cursor and `B_CURSOR_I_BEAM` for the I-beam text editing cursor.

  - `HideCursor()` removes the cursor from the screen.

  - `ShowCursor()` restores it.

  - `ObscureCursor()` hides the cursor until the user moves the mouse.

  - `IsCursorHidden()` returns `true` if the cursor is hidden (but not obscured), and `false` if not.

  The cursor data format is described in the "Cursor Data Format" section under BCursor.

  ### ShowCursor() see SetCursor()

  ### WindowAt() , CountWindows()

  BWindow *`WindowAt(`int32 index`)` const
  int32 `CountWindows(`void`)` const

  `WindowAt()` returns the index'th BWindow object in the application's window list. If index is out of range, the function returns `NULL`.

  `CountWindows()` returns the number of windows in the window list.

  - The windows list includes all windows explicitly created by the app—whether they're normal, floating, or modal, and whether or not they're actually displayed—but excludes private windows created by Be classes.

  - The order of windows in the list has no signficance.

  - Locking the BApplication object doesn't lock the window list. If you need coordinated access to the list, you'll have to provide your own locking mechanism that protects these functions and all BWindow construction and deletion.

  ## Global Variables

  ### be_app

  `BApplication *``be_app`;

  `be_app` is the global variable that represents your BApplication object. You can refer to `be_app` anywhere you need a reference to the BApplication object that you created. If you want to call a function that's declared by your BApplication subclass, you have to cast be_app to your subclass:

         ((MyApp *)be_app)->MyAppFunction();

  ### be_app_messenger

  `BMessenger *``be_app_messenger`;

  `be_app_messenger` is a global BMessenger that targets your `be_app` object. It's created in the BApplication constructor.

  ## Archived Fields

  Field | Type code | Meaning
  --- | --- | ---
  "mime_sig" | `B_STRING_TYPE` | Application signature.

  ## Scripting Suites and Properties

  ### "Name"

  Command | Specifier | Meaning
  --- | --- | ---
  `B_GET_PROPERTY` | `B_DIRECT_SPECIFIER` | Gets the name of the application's main thread.

  ### "Window"

  Command | Specifiers | Meaning
  --- | --- | ---
  `B_COUNT_PROPERTIES` | `B_DIRECT_SPECIFIER` | Returns CountWindows().
  Not applicable. | `B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER` | The message is forwarded to the specified BWindow.

  The Application Kit Table of Contents | The Application Kit Index

  The Be Book,
  ...in lovely HTML...
  for BeOS Release 5.

  Copyright © 2000 Be, Inc. All rights reserved..