App Server Interface Specification v0.3
Purpose:
The app_server provides services to the OpenBeOS by managing processes, filtering and dispatching input from the Input Server to the appropriate applications, and managing all graphics-related tasks.
Tasks:
The tasks performed by the app_server are grouped in relation to its purpose.
Receives and redirects (dispatches) messages from the input server
Responds to messages from apps
Receives and consolidates requests from BView, BWindow, BBitmap, and others to draw stuff (draw bitmap, etc)
Utilizes ports to communicate with child processes
Handles drag & drop messaging
Manages the system clipboard
Loads and Kills processes
Detects absence of Input Server and restarts when not running
Aids in system shutdown
Dynamically loads accelerant portion of graphics driver
Creates a connection with BBitmaps requiring a child view
Draws the blue desktop screen
Provides workspace support
Provides functionality to the BeAPI for drawing primitives, such as rectangles, ellipses, and beziers
Provides a means for BViews to draw on BBitmaps
Manages window behavior with respect to redraw (move to front, minimize, etc)
Returns a frame buffer to direct-access classes
Caches fonts for screen and printer use
Draws text and provides other font API support for the BeAPI classes
Table of Contents
Graphics:
I. Desktop Initialization
II. Window management
A. ServerApp
B. ServerWindow
C. Layer
D. WindowBorder
E. Decorator
III. Screen updates
IV. Cursor management
V. Display Drivers
Process Management:
I. BApplication execution
II. Non-BApplication execution
III. Killing/Exiting applications
IV. System Shutdown
Input Processing:
I. Input Server messages
II. Mouse
III. Keyboard
Messaging:
I. Inter-Application messaging
II. Drag-and-drop
III. Methods
Graphics:
I. Desktop Initialization
II. Window management
III. Screen updates
IV. Cursor management
I. Desktop Initialization
The graphics hardware is abstracted from the rest of the app_server. When started, the server creates the desktop, which is little more than a collection of workspaces. The desktop actually creates a DisplayDriver and then calls the driver's method Inititialize() before calling a few high-level routines for setup. Below is the process by which the HWDriver class, which is used to access the primary graphics card in the system, followed by the steps taken to set up the desktop.
Load Accelerant
The app_server looks in three paths when scanning for an accelerant:
/fd/beos/system/add-ons/app_server
/boot/home/config/add-ons/app_server
/boot/beos/system/add-ons/app_server
When the app_server searches a path, it simply prints to the debug stream on the serial port a message akin "Attempting to load accelerant so-and-so" when loading the accelerant. Following this, it is loads the accelerant via load_add_on(), obtains the hook function control_graphics_card is via get_image_symbol, and control_graphics_card(OPEN_GRAPHICS_CARD) is called. If this returns an error, the image is unloaded after a control_graphics_card(CLOSE_GRAPHICS_CARD) is called and the server spits out a message like "So-and-so is not an acceptable driver" to the serial port. Assuming that the OPEN call succeeds, the app_server serial prints "Using so-and-so as accelerant." Hook functions are then acquired through control_graphics_card(B_GET_GRAPHICS_CARD_HOOKS). At this point, it is a good idea to have a palette generated for 8-bit mode (just in case we're going to use it), so the server generates the system palette. The palette on the graphics card is then set through many calls to control_graphics_card(B_SET_INDEXED_COLOR).
Set up workspaces
Workspace preferences are read in from disk. If they exist, they are used; otherwise the default of 3 workspace, each with the settings 640x480x256@59.9Hz, is used. Each workspace is initialized to the proper information (preferences or default). Additionally, all settings are checked and possibly "clipped" by information gained through the driver class. With the desktop having been given the proper settings, the default workspace, 0, is activated.
Display
Provided that everything has gone well so far, the screen is filled to the user-set workspace color or RGB(51,102,160) Also, the global clipboard is created, which is nothing more than a BClipboard object. The Input Server will notify the app_server of its existence, at which point the cursor will be set to B_HAND_CURSOR and shown on the screen.
II. Window management
Window management is a complicated issue, requiring the cooperation of a number of different types of elements. Each BApplication, BWindow, and BView has a counterpart in the app_server which has a role to play. These objects are Decorators, ServerApps, ServerWindows, Layers, and WindowBorders.
A. ServerApps
ServerApp objects are created when a BApplication notifies the app_server of its presence. In acknowledging the BApplication's existence, the server creates a ServerApp which will handle future server-app communications and notifies the BApplication of the port to which it must send future messages.
ServerApps are each an independent thread which has a function similar to that of a BLooper, but with additional tasks. When a BWindow is created, it spawns a ServerWindow object to handle the new window. The same applies to when a window is destroyed. Cursor commands and all other BApplication functions which require server interaction are also handled. B_QUIT_REQUESTED messages are received and passed along to the main thread in order for the ServerApp object to be destroyed. The server's Picasso thread also utilizes ServerApp::PingTarget in order to determine whether the counterpart BApplication is still alive and running.
B. ServerWindows
ServerWindow objects' purpose is to take care of the needs of BWindows. This includes all calls which require a trip to the server, such as BView graphics calls and sending messages to invoke hook functions within a window.
C. Layers
Layers are shadowed BViews and are used to handle much BView functionality and also determine invalid screen regions. Hierarchal functions, such as AddChild, are mirrored. Invalid regions are tracked and generate Draw requests which are sent to the application for a specific BView to update its part of the screen.
D. WindowBorders
WindowBorders are a special kind of Layer with no BView counterpart, designed to handle window management issues, such as click tests, resize and move events, and ensuring that its decorator updates the screen appropriately.
F. Decorators
Decorators are addons which are intended to do one thing: draw the window frame. The Decorator API and development information is described in the Decorator Development Reference. They are essentially the means by which WindowBorders draw to the screen.
G. How It All Works
The app_server is one large, complex beast because of all the tasks it performs. It also utilizes the various objects to accomplish them. Input messages are received from the Input Server and all messages not specific to the server (such as Ctrl-Alt-Shift-Backspace) are passed to the active application, if any. Mouse clicks are passed to the ServerWindow class for hit testing. These hit tests can result in window tabs and buttons being clicked, or mouse click messages being passed to a specific view in a window.
These input messages which are passed to a running application will sometimes cause things to happen inside it, such as button presses, window closings/openings, etc. which will cause messages to be sent to the server. These messages are sent either from a BWindow to a ServerWindow or a BApplication to a ServerApp. When such messages are sent, then the corresponding app_server object performs an appropriate action.
III. Screen Updates
Screen updates are done entirely through the BView class or some subclass thereof, hereafter referred to as a view. A view's drawing commands will cause its window to store draw command messages in a message packet. At some point Flush() will be called and the command packet will be sent to the window's ServerWindow object inside the server.
The ServerWindow will receive the packet, check to ensure that its size is correct, and begin retrieving each command from the packet and dispatching it, taking the appropriate actions. Actual drawing commands, such as StrokeRect, will involve the ServerWindow object calling the appropriate command in the graphics module for the Layer corresponding to the view which sent the command.
IV. Cursor Management
The app_server handles all messiness to do with the cursor. The cursor commands which are members of the BApplication class will send a message to its ServerApp, which will then call the DisplayDriver's appropriate function. The DisplayDriver used will actually handle the drawing of the cursor and whether or not to do so at any given time.
OpenBeOS R1 will also include the advent of an extension of the API: SetCursor(BBitmap *), which will accept a BBitmap of color space RGB(A)32, RGBA16, CMAP8, GRAY8, or GRAY1. Thus, color cursors and cursors which are not 16x16 are now supported.
V. Display Drivers
Unlike the BeOS R5 app_server, OpenBeOS' server will have a special feature: a modular graphics driver access class. The class is not actually the graphics driver, but, rather, a generalized interface which is implemented to interact with various destinations for graphics output. This allows the server to draw to a BWindow/BView combination, a BDirectWindow, or the actual frame buffer of a particular graphics card. All that the rest of the server needs to do is call whichever graphics function that is needed.
Process Management:
I. BApplication execution
II. Non-BApplication execution
III. Killing/Exiting applications
IV. System Shutdown
I. BApplication execution
Applications will come in two types: those which communicate with the app_server and take advantage of its services, and those which do not. To access the app_server, an application must be derived from BApplication.
When a BApplication (referred to hereafter as a BApp) is executed, the app constructor creates its BLooper message port with the name AppLooperPort. This port's id, by means of BLooper, registers its port_id with the app_server so that the two can communicate with each other most easily.
When the app_server receives notification that an app has been created, the server creates an AppMonitor (with accompanying thread) in its own team to handle messages sent to it and sends a reply with the port_id of the AppMonitor, to which all future messages are sent. These AppMonitor objects are stored in a global BList created for the storage of such things.
II. non-BApplication execution
Other applications do not communicate with the app_server. These applications have no access to app services and do not generally pass BMessages. This includes, but is not limited to, UNIX apps. The app_server ignores such applications except when asked to kill them.
While, technically, these are not limited to being non-GUI applications, in practice these applications are command-line-only, for the application would be required to (1) render the app_server unable to access video hardware and (2) reinvent existing graphics code to load and use accelerants and draw onto the video buffer. This is extremely bad style and programming practice, not to mention more work than it is worth except in one case: the OpenBeOS app_server can coexist with the BeOS R5 app_server with some degree of peace because it can utilize extra video cards which the BeOS app_server does not use.
III. Killing/Exiting Applications
While the input server handles the Team Monitor window, the app_server actually takes care of shutting down teams, peacefully or not. Exiting an app is done simply by sending a B_QUIT_REQUESTED message to particular app. Killing an app is done via kill_team, but all the messy details are handled by the kernel itself through this call. When the user requests a team die via the Team Monitor, the Input Server sends a message to the app_server to kill the team, attaching the team_id. The app_server responds by happily nuking the respective team and notifies the registrar of its forcible removal from the roster.
IV. System Shutdown
Although the server maintains an internal list of running GUI applications, when a request to shut down the system is received by the app_server, it will pass the request on to the registrar, which will, in turn, increment its way through the app roster and request each app quit. When each quit request is sent, a timer is started and after timeout, the registrar will ask the server to kill the particular team and continue iterating through the application list.
Input Processing:
I. Input Server messages
II. Mouse
III. Keyboard
I. Input Server messages
The Input Server collects information about keyboard and mouse events and forwards them to the app_server via messages. They are sent to port specifically for such messages, and the port is monitored by a thread whose task is to monitor, process, and dispatch them to the appropriate recipients. The Input Server is a regular BApplication, and unlike other applications, it requests a port to which it can send input messages.
II. Mouse
Mouse events consist of button changes, mouse movements, and the mouse wheel. The message will consist of the time of the event and attachments appropriate for each message listed below:
B_MOUSE_DOWN
when
location of the cursor
button number
modifiers
clicks
B_MOUSE_UP
time
buttons' status // not implemented for R5 but included for future expansion
location of the cursor
modifiers
B_MOUSE_MOVED
time
location of the cursor
buttons' status
B_MOUSE_WHEEL_CHANGED
time
location of the cursor
transit - in or out
x delta
y delta
III. Keyboard
Keyboard events consist of notification when a key is pressed or released. Any keypress or release will evoke a message, regardless of whether or not the key is mapped. The message will consist of the appropriate code and attachments listed below:
B_KEY_DOWN
time
key code
repeat count
modifiers
states
UTF-8 code
string generated
modifier-independent ASCII code
B_KEY_UP
time
key code
modifiers
states
UTF-8 code
string generated
modifier-independent ASCII code
B_UNMAPPED_KEY_DOWN
time
key code
modifiers
states
B_UNMAPPED_KEY_UP
time
key code
modifiers
states
B_MODIFIERS_CHANGED // sent when a modifier key changes
time
modifier states
previous modifier states
states
Nearly all keypresses received by the app_server are passed onto the appropriate application. Control-Tab, when held, is sent to the Deskbar for app switching. Command+F?? is intercepted and a workspace is switched. Left Control + Alt + Delete is not even intercepted by the app_server. The Input Server receives it and shows the Team Monitor window.
Messaging:
I. Inter-Application messaging
II. Drag-and-drop
III. Methods
I. Inter-Application Messaging
The details of messaging are depicted under Process Management::BApplication.
II. Drag-and-drop
III. Methods
Messaging with the app_server is not done using BMessages because of the overhead required to send them costs time and speed. Instead, ports are utilized indirectly by means of the PortLink class, which simply makes attaching data to a port message easier, but requires very little overhead.