BInputServerDevice

BInputServerDevice is a base class for input devices; these are instances of BInputServerDevice subclasses that generate input events. In most cases, an input device corresponds to a device driver that handles a specific brand or model of hardware (mouse, keyboard, tablet, etc.), but it doesn't have to: an input device can get events from the Net, or generate them algorithmically, for example. Also, a single BInputServerDevice can handle more than one device driver.

BInputServerDevice objects are created and deleted by the Input Server only—you never create or delete these objects themselves.


Starting and Sending Messages

For each device that your object registers, it gets a Start() function call. This is the Input Server's way of telling your object that it can begin generating input events (for the designated device). So far, all of this—from the add-on load to the Start() call—happens within a single Input Server thread (for all input devices). When your Start() function is called, you should spawn a thread so your object can generate events without blocking the Server. Events are generated and sent through the EnqueueMessage() function.


Device Types and Control Messages

The Input Server knows about two types of devices: keyboards, and pointing devices (mice, tablets, etc). When you register your object's devices (through RegisterDevices()) you have to indicate the device type. The Input Server uses the device type to predicate the input device control messages it sends to the devices. These messages, delivered in Control() calls, tell a device that there's been a change downstream that applies specifically to that type of device. For example, when the user changes the mouse speed, each pointing device receives a B_MOUSE_SPEED_CHANGED notification.

The Be-defined control messages are predicated on device type only.

If your BInputServerDevice object manages a device other than a pointer or a keyboard, you tell the Input Server that the device is undefined. In this case, the Input Server won't send your device any device-specific messages; to send your device a message you (or an application that knows about your device) have to use a BInputServerDevice object.

Pointing Devices

Pointing devices such as mice, trackballs, drawing tablets, etc. generate B_MOUSE_MOVED messages (which trigger a BView's MouseMoved() function) featuring a where field representing the cursor's location in view co-ordinates. Unfortunately, your BInputServerDevice doesn't know anything about views; that's the App Server's job. You'll still need to add this information to the B_MOUSE_MOVED messages generated by your BInputServerDevice, and the App Server will adjust it to view co-ordinates for you.

When generating a B_MOUSE_MOVED message, you add x and y fields in one of two ways:

  • an offset relative to the cursor's previous position (B_INT32_TYPE values)

  • an absolute position expressed in the range 0.0 to 1.0 (B_FLOAT_TYPE values)

Mice always use relative locations; tablets can use either (though they usually provide absolute values).

Relative Locations

All mice (and some drawing tablets) express the pointer location relative to its previous position. If your pointing device is operating in relative co-ordinate mode, you add x and y entries as B_INT32_TYPE values in device-defined units. The App Server interprets these units as pixels, so you may need to scale your output:

int32 xVal, yVal;
...
event->AddInt32( "x", xVal );
event->AddInt32( "y", yVal );

Absolute Locations

Drawing tablets or other pointing devices that provide absolute locations add the x and y entries as B_FLOAT_TYPEs:

float xVal, yVal;
...
event->AddFloat( "x", xVal );
event->AddFloat( "y", yVal );

These values must be in the range [0.0 to 1.0]. The app_server scales them to the screen's co-ordinate system so (0.0, 0.0) is the left-top, and (1.0, 1.0) is the right-bottom of the screen. This lets the pointing device work with any screen resolution, automatically.

Now where?

When the Application Server receives one of these B_MOUSE_MOVED messages, it converts the x and y values into absolute values in the target view's co-ordinate system, and then throws away the x and y entries in the message. Because of this, and the fact that some applications might want more accurate positional information from tablets, fill in the be:tablet_x and be:tablet_y fields as well:

float xVal, yVal;
...
event->AddFloat( "x", xVal );
event->AddFloat( "y", yVal );
event->AddFloat( "be:tablet_x", xVal );
event->AddFloat( "be:tablet_y", yVal );

Other Useful Information

Pressure information is stored in the be:tablet_pressure field, as a float in the range [0.0 to 1.0] (minimum pressure to maximum pressure):

float pressure;
...
event->AddFloat( "be:tablet_pressure", pressure );

If the tablet supports tilt information, store it in be:tablet_tilt_x and be:tablet_tilt_y, scaling the information to the range [0.0 to 1.0]. A tilt of (-1.0, -1.0) tilts to the left-top, (1.0, 1.0) tilts to the right-bottom, and (0.0, 0.0) is no tilt.

float tilt_x, tilt_y;
...
event->AddFloat( "be:tablet_tilt_x", tilt_x );
event->AddFloat( "be:tablet_tilt_y", tilt_y );

Tablets with pens that support an eraser store the eraser's state in the be:tablet_eraser field. A value of 1 means the pen is reversed (i.e. the eraser is on), and 0 means it should behave normally.

int32 erase_mode;
...
event->AddInt32( "be:tablet_eraser", erase_mode );

Device State

The Control() protocol is designed to accommodate queries (in addition to commands). Currently, however, the Input Server maintains the keyboard and pointing device state and answers these queries itself; it doesn't forward any of the Be-defined query messages. For example, when an application asks for the current mouse speed setting (through get_mouse_speed()), the query gets no further than the Input Server itself—it doesn't get passed as a control message to a pointing device.

If you're designing a BInputServerDevice that manages a keyboard or pointing device, you must keep in mind that your device is not responsible for its "Be-defined" state. The elements of the state—mouse speed, key map, etc.—correspond to the control messages listed in "Input Device Control Messages".


Dynamic Devices

As hardware devices are attached and detached from the computer, you can add and remove items from your BInputServerDevice's list of registered devices (by calling RegisterDevice() / UnregisterDevice()). But your object has to first notice that a physical device has been added or removed. It does this by placing a node monitor on the device directory (/dev). As a convenience—and to help conserve resources—the BInputServerDevice class provides the Start/StopMonitoringDevices() functions which install and remove node monitors for you.


Creating and Registering

To create a new input device, you must:

At boot time, the Input Server loads the add-ons it finds in the input device directories. For each add-on it loads, the Server invokes instantiate_input_device() to get a pointer to the add-on's BInputServerDevice object. After constructing the object, the Server calls InitCheck() to give the add-on a chance to bail out if the constructor failed. If the add-on wants to continue, it calls RegisterDevices() (from within InitCheck()) to tell the Server which physical or virtual devices it handles.


Installing an Input Device

The input server looks for input devices in the input_server/devices subdirectories of B_BEOS_ADDONS_DIRECTORY, B_COMMON_ADDONS_DIRECTORY, and B_USER_ADDONS_DIRECTORY.

Creative Commons License
Legal Notice
This work is licensed under a Creative Commons Attribution-Non commercial-No Derivative Works 3.0 License.