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.
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.
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 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).
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:
int32xVal
,yVal
; ...event
->AddInt32
( "x",xVal
);event
->AddInt32
( "y",yVal
);
Drawing tablets or other pointing devices that provide absolute locations
add the x and y entries as B_FLOAT_TYPEs
:
floatxVal
,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.
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:
floatxVal
,yVal
; ...event
->AddFloat
( "x",xVal
);event
->AddFloat
( "y",yVal
);event
->AddFloat
( "be:tablet_x",xVal
);event
->AddFloat
( "be:tablet_y",yVal
);
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):
floatpressure
; ...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.
floattilt_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.
int32erase_mode
; ...event
->AddInt32
( "be:tablet_eraser",erase_mode
);
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".
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.
To create a new input device, you must:
create a subclass of
BInputServerDevice
implement the
instantiate_input_device()
C function to create an instance of your
BInputServerDevice
subclass
compile the class and the function as an add-on
install the add-on in one of the input device directories
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.
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
.
You can install your input devices in the latter two
directories—i.e. those under B_COMMON_ADDONS_DIRECTORY
, and
B_USER_ADDONS_DIRECTORY
.
The B_BEOS_ADDONS_DIRECTORY
is reserved for add-ons that are supplied
by the BeOS.