Determining Input Devices in Linux*

Submit New Article

Last Modified On :   April 22, 2009 5:13 PM PDT
Rate
 


Preface


The Intel Mobile Internet Device (MID) platform provides a full internet experience in a pocket-sized form factor. Combining Moblin-based operating systems with the Intel® Atom™ processor, MIDs are able to run any application that has been built for the x86 architecture, including Adobe* Flash 10 and Adobe* AIR 1.5. While the features of the devices that are and will be on the market vary depending on OEM and target market, there are several features that the devices share in common: small form factor, emphasis on internet connectivity rather than extensive storage, and alternate input methods.

Although there are ultra-mobile computing devices in the market that run Microsoft Windows* XP or Windows Vista and that are built on the same hardware platform as those running a Moblin-based operating systems such as Midinux* or Ubuntu* Mobile Edition, this series of whitepapers focuses entirely on the Moblin-based MIDs. For information on how to retrieve this information from Windows operating systems, please consult that platform’s documentation, or see the Intel Mobile Platform SDK.

The functionality described in this paper is also provided via the Platform Awareness Service, a light-weight, D-Bus initiated platform information provider. However, because the final software stack for each Moblin device is influenced heavily by the OEM and Service Providers, this service may not be pre-installed on some Moblin-based devices. We have therefore written these whitepapers in order to simplify access to this information on platforms that do not have this service installed.

For further information on how to use D-Bus to retrieve information from the Platform Awareness Service, please refer to the Platform Awareness Service documentation.

Introduction


One of the more distinguishing differences between a desktop machine and a mobile device is the way in which data can be input. Most desktop machines are equipped with a keyboard, a mouse, and perhaps other input devices. For a mobile device the choices are not always as obvious, and at times are not even available. The user of these machines, however, expects to be able to input information into the machine, and the software used must be aware of the options for input that are available on the system.

The purpose of this paper is to demonstrate one way of retrieving input device information from Moblin-based Linux platforms.

How to get Input Device Information in Linux


While there is a fair amount of information available, we focus on three main pieces of information in order to keep things small and simple:

  • The existence of a physical keyboard
  • The existence of a physical pointing device
  • Whether the existence of either device changes

Using HAL


The Linux Hardware Abstraction Layer (HAL>) can retrieve information about the hardware that makes up a computer system. HAL can be queried through the command line using commands like hal-device, hal-find-by-property, hal-find-by-capability, and hal-get-property . One can get the same information inside of an application by using D-BUS. The HAL 0.5.10 Specification lists information that is available through HAL. Therefore, for our purposes here, we will illustrate the use of the D-BUS interface to query the HAL and locate the available input devices, and once located determine which input device is relevant to a particular query. This is done by means of the FindDeviceByCapability directive to return a list of devices that have various input capabilities, namely keyboard and mouse. We will also illustrate a method for detecting when input devices are added or removed.

Creating the List of Input Devices


In order to obtain a list of input devices, two functions are used to query the HAL for available devices. isPhysicalKeyboardPresent() collects information about the keyboards that are connected to the system. isPhysicalPointerPresent() collects information about the mouse devices that are connected to the system. Each function has the same parameters:

  • MIDPlatformSvc *obj – Contains a pointer to the system bus through which the HAL is queried
  • gboolean *Present – Returns TRUE if the device is present, FALSE if no device is present
  • GError **error – Used to report the absence of the device being queried
Each function performs basically the same algorithm: connect to the HAL and request a list of devices using the FindDeviceByCapability directive to look for input.keyboard and input.mouse capability, and then, if appropriate, add the device to the collection of available input devices. The list returned by this query to the HAL is a collection of User Interface Devices (UDI) that each have the capability requested. Each UDI in this list is then examined to ensure that only the appropriate set of capabilities is present in the device, meaning that keyboards do not also have mouse capability, and that mouse devices do not also have keyboard or keys capability. This is done by again calling the HAL to determine if the opposite capability is also present in the UDI. When it is determined that only the desired capability is present in the UDI, a call to adjustinputdevicenames() is then made to track the particular UDI along with its discovered capability. Details of this function are located below. Once the device list has been created, it is used to track devices as they are connected or disconnected from the system.

A listing of isPhysicalKeyboardPresent() is now presented:

gboolean isPhysicalKeyboardPresent(MIDPlatformSvc *obj, gboolean *keyboardPresent, GError **error)
{
DBusGConnection *sysBus;
DBusGProxy *proxy;
char **kbdList = NULL,**mouseList = NULL;
char **kbd_ptr,**mouse_ptr,**mousename;
int i = 0,len = 0;

// Initialize the System DBus connection
sysBus = obj->systemBus;

// Connect a proxy to the Hal Manager interface
proxy = dbus_g_proxy_new_for_name(sysBus,"org.freedesktop.Hal",
"/org/freedesktop/Hal/Manager","org.freedesktop.Hal.Manager" );

dbus_g_proxy_call(proxy, "FindDeviceByCapability", error, //Find Keyboard via HAL
G_TYPE_STRING, "input.keyboard", G_TYPE_INVALID, // param #1
G_TYPE_STRV, &kbdList, G_TYPE_INVALID); // ret val

if (kbdList)
len = g_strv_length(kbdList);
if (len == 0) { // no keyboard found
*keyboardPresent = FALSE; // Function Fail
g_set_error (error, // set an error
INPUT_DEVICE_NP, // error domain
1, // error code
"No Keyboard devices were found.\n"); // error message
return TRUE;
}
gboolean haskbd = FALSE,hasmouse;
for (kbd_ptr = kbdList; *kbd_ptr; kbd_ptr++,i++) // iterate through the list of
{ // keyboard devices, checking each udi to for mouse capability
hasmouse = FALSE;
DBusGProxy *kbdProxy = dbus_g_proxy_new_for_name(sysBus, //Open proxy for
"org.freedesktop.Hal",*kbd_ptr,"org.freedesktop.Hal.Device" );//Keyboard UDI
dbus_g_proxy_call(kbdProxy, "GetPropertyStringList", error, // Checking caps
G_TYPE_STRING, "info.capabilities", G_TYPE_INVALID,
G_TYPE_STRV, &mouseList, G_TYPE_INVALID);
len = g_strv_length(mouseList);
for (mouse_ptr = mouseList;*mouse_ptr && !hasmouse;mouse_ptr++)
{
if (!strcmp(*mouse_ptr,"input.mouse"))
hasmouse = TRUE;
}
if (!hasmouse)
{
haskbd = TRUE;
adjustinputdevicenames(obj,*kbd_ptr,ADDIT,KEYBOARD);
}
if (len)
g_strfreev(mouseList);
g_object_unref (kbdProxy);
}
g_strfreev(kbdList);
g_object_unref (proxy);

*keyboardPresent = haskbd;
return TRUE;
}


An additional check is made when working with mouse devices. It has been determined that a mouse emulation UDI is sent by DBUS when a keyboard is connected to or disconnected from the system. It does have input.mouse capabilities only, but, as an emulation, is not connected to a physical device. Thus, when searching mouse devices for keys or keyboard capabilities, an additional call to the HAL is made using the GetPropertyString directive to discover the info.product elements of the UDI. If the property name is not “Macintosh mouse button emulation”, then we proceed with checking to see if keys or keyboard capabilities are also present in the UDI. A listing of isPhysicalPointerPresent() is now presented:

gboolean isPhysicalPointerPresent(MIDPlatformSvc *obj, gboolean *pointerPresent, GError **error)
{
DBusGConnection *sysBus;
DBusGProxy *proxy;
char **kbdList = NULL,**mouseList = NULL;
char **mouse_ptr,**kbd_ptr,*mouseproduct;
int i = 0,len = 0;

// Initialize the System DBus connection
sysBus = obj->systemBus;

// Connect a proxy to the Hal Manager interface
proxy = dbus_g_proxy_new_for_name(sysBus,"org.freedesktop.Hal",
"/org/freedesktop/Hal/Manager","org.freedesktop.Hal.Manager" );

dbus_g_proxy_call(proxy, "FindDeviceByCapability", error, //Find Mouse via HAL
G_TYPE_STRING, "input.mouse", G_TYPE_INVALID, // param #1
G_TYPE_STRV, &mouseList, G_TYPE_INVALID); // ret val

if (mouseList)
len = g_strv_length(mouseList);
if (len == 0) { // no keyboard found
*pointerPresent = FALSE; // Function fails
g_set_error (error, // set an error
INPUT_DEVICE_NP, // error domain
1, // error code
"No Mouse devices were found.\n"); // error message
return TRUE;
}
gboolean hasmouse = FALSE,haskeyboard; // No solely mouse capability is assumed

for (i=0,mouse_ptr = mouseList; *mouse_ptr && !hasmouse; mouse_ptr++,i++)
// iterate through the list of mouse devices, checking each udi for keyboard capability
{
haskeyboard = FALSE;
DBusGProxy *mouseProxy = dbus_g_proxy_new_for_name(sysBus,"org.freedesktop.Hal",
*mouse_ptr,"org.freedesktop.Hal.Device" ); //Open Proxy for Mouse UDI
dbus_g_proxy_call(mouseProxy, "GetPropertyString", error, // Checking caps.
G_TYPE_STRING, "info.product", G_TYPE_INVALID,
G_TYPE_STRING, &mouseproduct, G_TYPE_INVALID);
if (strcmp(mouseproduct,"Macintosh mouse button emulation")) // if mouse
{ // device is not Macintosh mouse button emulation continue
dbus_g_proxy_call(mouseProxy, "GetPropertyStringList", error,
G_TYPE_STRING, "info.capabilities", G_TYPE_INVALID,
G_TYPE_STRV, &kbdList, G_TYPE_INVALID);
len = g_strv_length(kbdList);
for (kbd_ptr = kbdList; *kbd_ptr && !haskeyboard; kbd_ptr++) //check to
{ // see if device has any "Keyboard" capability as well; if so,
// device is not solely a mouse device
if (!strncmp(*kbd_ptr,"input.key",9)) //check for input.key*,
// if any exist we have keyboard capability, not just mouse
haskeyboard = TRUE;
}
if (!haskeyboard) //set mouse capability with respect to keyboard:
// if no keyboard we have mouse; if keyboard we
{ // don't have mouse only
hasmouse = TRUE;
adjustinputdevicenames(obj,*mouse_ptr,ADDIT,MOUSE);
}
if (len)
g_strfreev(kbdList); //free elements as appropriate
}
free(mouseproduct);
g_object_unref (mouseProxy); //free proxy
}
g_strfreev (mouseList);
g_object_unref (proxy);
*pointerPresent = hasmouse;
return TRUE;
}


Collecting the Available Input Devices


As information regarding the input devices is discovered, and as it can change any time a device is connected to or disconnected from the system, a method for tracking available devices becomes necessary. Each UDI has a unique name and is generally connected to a unique function, in our case either for mouse support or keyboard support. The function adjustinputdevicesnames() was written to track these changes as they occur. The parameters are as follows:

  • MIDPlatformSvc *obj – Contains a pointer to the system bus used when advising users of changes in the availability of devices
  • char *name – Contains the name of the UDI being tracked
  • int action – Indicates to the function the operation to perform. Options here are ADDIT, REMOVEIT, CLEANUP, INITIALIZE, NOACTION
  • int role – Indicates the role of this particular UDI. Options here are KEYBOARD or MOUSE.
The purpose of this function is to collect and track the information regarding the various UDI’s that are discovered by the system, and to track when changes dictate that an advisory should be sent to interested parties regarding the state of input devices on the system. In tracking the UDI’s, once they are entered in the list of devices, the name remains in the list. This is because each device is assigned the same name, and when disconnected or connected will be the same as the previous use. A listing of adjustinputdevicename() and associated data is now presented:

#define ADDIT              1
#define REMOVEIT 2
#define CLEANUP 3
#define KEYBOARD 4
#define MOUSE 5
#define NOACTION 6
#define INITIALIZE 7

#define TBLSIZE 20

typedef struct
{ char *name;
int active;
int role;
} DEVICE_INFO;

static void adjustinputdevicenames(MIDPlatformSvc *obj,char *name,int action,int role)
{
static DEVICE_INFO inpdevs[TBLSIZE]; // static variables will keep state
int i;
static int devcount = 0,mousecount = 0, keyboardcount = 0;
static gboolean firstpass = TRUE;
gboolean present = FALSE;

if (action == ADDIT) // operation is to add UDI to tracking mechanism
{
gboolean adjcount = FALSE;

for (i = 0; i < devcount && !present; i++)
if (!strcmp(name,inpdevs[i].name) && inpdevs[i].role == role)
{ // check to see if UDI name and role already exist and is yes
adjcount = !inpdevs[i].active; // determine previous state
inpdevs[i].active = TRUE; // set as active
present = TRUE; // set as present
}
if (!present) // UDI is not present so it is added
{
inpdevs[devcount].name = strdup(name); // keep UDI name
inpdevs[devcount].active = TRUE; // set as active
inpdevs[devcount].role = role; // store its role
devcount++; // increase device count
adjcount = TRUE; // indicate adjustment necessary
}
if (adjcount)
{ //if adjustments are necessary, make them based on role of UDI
if (role == KEYBOARD)
{ // if keyboard has not been present and now is then
if (!firstpass && !keyboardcount) // alert users of change
keyboardPresentChanged(obj,TRUE,NULL);
keyboardcount++; // adjust keyboard count
}
else if (role == MOUSE)
{ // if mouse has not been present and now is then
if (!firstpass && !mousecount) // alert users of change
pointerPresentChanged(obj,TRUE,NULL);
mousecount++; // adjust mouse count
}
firstpass = FALSE; // set controlling variable to FALSE
}
}
else if (action == REMOVEIT) // operation is to remove UDI as active
{
for (i = 0; i < devcount; i++) // for each UDI that is tracked
{ // if UDI is being queried and is active
if (!strcmp(name,inpdevs[i].name) && inpdevs[i].active)
{
inpdevs[i].active = FALSE; // set as inactive
if (inpdevs[i].role == KEYBOARD)
{ // if role is keyboard decrement refence count
keyboardcount--; // and if now no keyboards are
if (!firstpass && keyboardcount < 1) // present
keyboardPresentChanged(obj,FALSE,NULL);
} // alert users of change
else if (inpdevs[i].role == MOUSE)
{ // if role is mouse, decrement reference count
mousecount--; // and is now no mouse is present
if (!firstpass && mousecount < 1) // alert users
pointerPresentChanged(obj,FALSE,NULL);
} //of change
}
}
firstpass = FALSE;
}
else if (action == CLEANUP) // operation is to cleanup information
{
for (i = 0; i < devcount; i++)
{
free(inpdevs[i].name); // release memory allocated for name
inpdevs[i].name = NULL;
inpdevs[i].active = FALSE; // set active and role to zero state
inpdevs[i].role = 0;
}
devcount = 0; // set counters all to zero
keyboardcount = 0;
mousecount = 0;

firstpass = TRUE; // set to initial state
}
else if (action == INITIALIZE && firstpass) // operation is to initialize
{
for (i = 0; i < TBLSIZE; i++)
{
inpdevs[i].name = NULL; // set a known state for all
inpdevs[i].active = FALSE; // elements
inpdevs[i].role = 0;
}
}
}


Tracking Changes in Available Input Devices


Input devices can change at almost any time. The DBUS provides signaling capabilities are sent when a connection or disconnection of a device occurs on the system. We have taken advantage of this capability to monitor the changes to input devices by subscribing to the DeviceAdded and DeviceRemoved signals. This method provides a mechanism whereby a callback function can be specified to handle these two signals. The function beginInputEventThread(), which is invoked by the Mobile Internet Device platform architecture to initialize the input events, is the function in which we provide hooks into the signaling system to be able to monitor changes to input events. Its parameter is a MIDPlatformSvc object containing system bus information used throughout the input device module. A listing of this function is now presented:

void beginInputEventThread(MIDPlatformSvc *obj)
{
DBusGConnection *sysBus = obj->systemBus; // Initialize the System DBus connection
DBusGProxy *proxy;
gboolean kpresent,mpresent;
GError *error = NULL;

adjustinputdevicenames(obj,NULL,INITIALIZE,NOACTION); //initialize keyboard/mouse data
isPhysicalPointerPresent(obj,&mpresent,&error); //Make first check of mouse
isPhysicalKeyboardPresent(obj,&kpresent,&error); //Make first check of keyboards
// Connect a proxy to the Hal Manager interface
proxy = dbus_g_proxy_new_for_name(sysBus, // Retrieve proxy to HAL manager
"org.freedesktop.Hal",
"/org/freedesktop/Hal/Manager",
"org.freedesktop.Hal.Manager" );
dbus_g_proxy_add_signal(proxy,"DeviceAdded",G_TYPE_STRING,G_TYPE_INVALID);
dbus_g_proxy_connect_signal(proxy,"DeviceAdded",G_CALLBACK(checkAddedDevice),
(void *)obj,NULL); // add and connect to DeviceAdded signal
// with callbackfunction checkAddedDevice()
dbus_g_proxy_add_signal(proxy,"DeviceRemoved",G_TYPE_STRING,G_TYPE_INVALID);
dbus_g_proxy_connect_signal(proxy,"DeviceRemoved",G_CALLBACK(checkRemovedDevice),
(void *)obj,NULL); // add and connect to DeviceRemoved signal
return; // with callback function checkRemovedDevice
}


As noted in the function above, two functions, checkAddedDevice() and checkRemoveDevice() are denoted as the callback functions that are called when the aforementioned signals are sent. They will make calls to appropriate functions that will monitor and track the changes to devices as they occur. The callback checkRemovedDevice() function makes use of adjustinputdevicenames() that we have already discussed. Its parameters are:

  • DBusGProxy *proxy – a DBus proxy pointer stored when the callback function was declared and registered with the connect signal call
  • gchar* device_udi – the name of the UDI which has been removed
  • gpointer userData – a pointer to user defined data associated with the connect signal call

A listing of this function is now presented:

void checkRemovedDevice(DBusGProxy *proxy, gchar *device_udi, gpointer userData)
{
adjustinputdevicenames((MIDPlatformSvc *)userData,device_udi,REMOVEIT,NOACTION);
return;
}


It should be noted that the call to adjustinputdevicenames() in this function denotes that we are removing a device from active service in our data elements.

The callback checkAddedDevice() function makes use of the function examineUDI(), which is discussed below. Its parameters are:

  • DBusGProxy *proxy – a DBus proxy pointer stored when the callback function was declared and registered with the connect signal call
  • gchar* device_udi – the name of the UDI which has been removed
  • gpointer userData – a pointer to user defined data associated with the connect signal call

A listing of this function is now presented:

void checkAddedDevice(DBusGProxy *proxy, gchar *device_udi, gpointer userData)
{
examineUDI(proxy,device_udi,(MIDPlatformSvc *)userData);
return;
}


Identifying an added input device requires a slightly different approach than removing an input device. Since a device added to the system could belong to a variety of functionality, a means to determine if the device added is an input device had to be created. As we are only interested in input devices, the function examineUDI() is used to make this determination. This function uses the HAL to determine the capability of the device being examined, and only adds a device if it has keyboard or mouse capability. The parameters are:

  • DBusGProxy *proxy – a DBus proxy pointer stored when the callback function was declared and registered with the connect signal call
  • gchar* device_udi – the name of the UDI which has been removed
  • MIDPlatformSvc *obj – a pointer to user defined data associated with the connect signal call
This function, after determining that the added device is an input device, makes use of adjustinputdevicenames() to track the new device. A listing of this function is now presented:

static void examineUDI (DBusGProxy *proxy, gchar *device_udi,MIDPlatformSvc *obj)
{
char **devicecaps = NULL,**list1 = NULL,**list2 = NULL;
GError **error = NULL;
int len = -1;

DBusGProxy *capProxy = dbus_g_proxy_new_for_name(obj->systemBus,
"org.freedesktop.Hal",device_udi,
"org.freedesktop.Hal.Device"); //Open Proxy for supplied UDI
dbus_g_proxy_call(capProxy,"GetPropertyStringList", // Checking for device capability
error,G_TYPE_STRING, "info.capabilities", G_TYPE_INVALID,
G_TYPE_STRV, &devicecaps, G_TYPE_INVALID);
if (devicecaps)
{
len = g_strv_length(devicecaps);
for (list1 = devicecaps;*list1;list1++)
{
if (!strncmp(*list1,"input.key",9)) // Is any key type capability present
{
gboolean haskbd = FALSE;
list2 = list1; // check remaining through second pointer
for (;*list2 && !haskbd;list2++) // check for keyboard
if (!strcmp(*list2,"input.keyboard"))
haskbd = TRUE;
if (haskbd) // if there is a keyboard make sure mouse is missing
{
gboolean hasmouse = FALSE;
list1++;//begin mouse search one beyond where key was found
if (list1)
for (;*list1 && !hasmouse;list1++)
if (!strcmp(*list1,"input.mouse"))
hasmouse = TRUE;
if (!hasmouse) // if no mouse present add UDI to kbd list
adjustinputdevicenames(obj,device_udi,ADDIT,
KEYBOARD);
}
break; //end for loop search
}
else if (!strcmp(*list1,"input.mouse")) // is mouse the capability
{
gboolean haskey = FALSE;
list1++;
if (list1) // make sure not “key” capability is present
for (;*list1 && !haskey;list1++)
if (!strncmp(*list1,"input.key",9))
haskey = TRUE;
if (!haskey) // if no key, then add UDI to mouse list
adjustinputdevicenames(obj,device_udi,ADDIT,MOUSE);
break; //end 'for' loop search
}
}
}
g_object_unref (capProxy);
}


Notification of Changes in Available Input Devices


As mentioned above, when changes in input devices occurs the user is notified of these changes through an alert through the DBUS signaling service. These alerts are made via the functions keyboardPresentChanged() and pointerPresentChanged. Both functions have identical parameters:

  • MIDPlatformSvc *obj – Contains a pointer to the system bus to which the alert is issued
  • Gboolean isPresent – indicates the current data of the devices
  • GError *error = an error reporting element
Both functions operate the same way by calling g_signal_emit() to pass the specific alert defined for each function. The listing of both functions is now presented:

gboolean keyboardPresentChanged(MIDPlatformSvc*obj, gboolean isPresent, GError *error)
{
if (error == NULL) //GQuark stuff #define SIG_PHYSICAL_KEYBOARD_PRESENT_ID
{ //"physical_keyboard_present_changed": whether the physical keyboard is present
g_signal_emit(obj,g_inputSignals[SIG_PHYSICAL_KEYBOARD_PRESENT_ID].signalId,
0,isPresent);
}
return TRUE;
}


gboolean pointerPresentChanged(MIDPlatformSvc*obj, gboolean isPresent, GError *error)
{
if (error == NULL) //GQuark stuff #define SIG_PHYSICAL_POINTER_PRESENT_ID
{ //"physical_mouse_present_changed": whether the physical mouse is present
g_signal_emit(obj,g_inputSignals[SIG_PHYSICAL_POINTER_PRESENT_ID].signalId,
0,isPresent);
}
return TRUE;
}


Cleaning Up Information Regarding Available Input Devices


As must always occur, we must be careful to cleanup the memory and other resources we have used during the process of tracking input devices. The Intel® Mobile Internet Device platform provides a mechanism for all components to release all resources used during the process of managing the device. For input devices, this is done through a call tofinalizeInputObject(). Its one parameter, MIDPlatformSvc *obj, contains the system bus information we have used through out. A list of the function is now presented:

void finalizeInputObject(MIDPlatformSvc *obj)
{
DBusGConnection *sysBus = obj->systemBus; // Initialize the System DBus connection
DBusGProxy *proxy;
gboolean present;
GError *error = NULL;

adjustinputdevicenames(obj,NULL,CLEANUP,NOACTION); //cleanup the tracking table
// Connect a proxy to the Hal Manager interface
proxy = dbus_g_proxy_new_for_name(sysBus,"org.freedesktop.Hal",
"/org/freedesktop/Hal/Manager","org.freedesktop.Hal.Manager" );
dbus_g_proxy_disconnect_signal(proxy,"DeviceAdded",G_CALLBACK(checkAddedDevice),
(void *)obj); // disconnect from DeviceAdded signal
dbus_g_proxy_disconnect_signal(proxy,"DeviceRemoved",G_CALLBACK(checkRemovedDevice),
(void *)obj); // disconnect from DeviceRemoved signal
return;
}


Unsupported Input Devices


There are two input devices that are current not supported to the extent of keyboards and the mouse. They are the TouchScreen and the On-Screen keyboard. There are hooks in the input code that returns a fixed state for these devices, but any changes to them is not reported at this time. Future revisions will surely have support for these devices if support in the OS can be found. A listing of the three functions that returned a fixed state is now presented:

gboolean isTouchScreen(MIDPlatformSvc *obj, gboolean *isTouchScreen, GError **error)
{
*isTouchScreen = TRUE;
return TRUE;
}

gboolean isOnScreenKeyboardVisible(MIDPlatformSvc *obj, gboolean *visible, GError **error)
{
*visible = FALSE;
return TRUE;
}

gboolean onScreenKeyboardChanged(MIDPlatformSvc* obj)
{
gboolean visible;
GError* error = NULL;
dbg("Simulating a OnScreenKeyboardChanged Event.");
isOnScreenKeyboardVisible(obj, &visible, &error);
if (error == NULL)
{
g_signal_emit ( obj,
g_inputSignals[SIG_ON_SCREEN_KEYBOARD_CHANGED_ID].signalId ,
0, //GQuark stuff
//the parameters; in this case, whether or not the
//keyboard is visible
);
}//GQuark stuff #define SIG_PHYSICAL_KEYBOARD_PRESENT_ID "on_screen_keyboard_changed"
return TRUE;
}


Writing Input Device Aware Applications


The ability to determine input devices is very important to an application. When events occur that change that ability, it is important that the application is aware of these changes. Hopefully this paper covered enough detail to get you started on writing your own input device aware applications for Linux.