From 123406799ff074ff1367777f8751d935cfa95f47 Mon Sep 17 00:00:00 2001 From: CodeforEvolution Date: Wed, 3 Mar 2021 21:58:48 -0600 Subject: [PATCH] input_server: Properly implement watch_input_devices() & add documentation Allow for multiple programs to watch for changes in the state of input devices connected to the system. Previously only one program at a time could watch input devices. While this functionality was not implemented in BeOS R5, it was at least documented in the BeBook. Also added some API documentation where necessary for the function and related constants. Change-Id: Icd927998cffcab212bb63bcf10c64c620e9da9a2 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3872 Reviewed-by: Adrien Destugues --- docs/user/interface/Input.dox | 58 +++++++++++++++++------- src/servers/input/AddOnManager.cpp | 73 ++++++++++++++++++++++++++---- src/servers/input/AddOnManager.h | 4 +- src/servers/input/InputServer.cpp | 18 +++++++- 4 files changed, 126 insertions(+), 27 deletions(-) diff --git a/docs/user/interface/Input.dox b/docs/user/interface/Input.dox index 4ebd51c27e..9cc5e06839 100644 --- a/docs/user/interface/Input.dox +++ b/docs/user/interface/Input.dox @@ -199,8 +199,8 @@ /*! \enum input_device_type - \ingroup - \brief Undocumented enum. + \ingroup interface + \brief Device types that the Input Server can recognize. \since Haiku R1 */ @@ -208,7 +208,10 @@ /*! \var input_device_type B_POINTING_DEVICE - \brief Undocumented enum value. + \brief Pointing devices like mice, drawing tablets, touch screens, etc. + + These devices generate \c B_MOUSE_MOVED, \c B_MOUSE_UP, and \c B_MOUSE_DOWN + messages. \since Haiku R1 */ @@ -216,7 +219,10 @@ /*! \var input_device_type B_KEYBOARD_DEVICE - \brief Undocumented enum value. + \brief Key-based input devices like a keyboard, number pad, etc. + + These devices generate \c B_KEY_DOWN, \c B_UNMAPPED_KEY_DOWN, \c B_KEY_UP, + \c B_UNMAPPED_KEY_UP, and \c B_MODIFIERS_CHANGED messages. \since Haiku R1 */ @@ -224,7 +230,7 @@ /*! \var input_device_type B_UNDEFINED_DEVICE - \brief Undocumented enum value. + \brief An undefined/unknown type of input device. \since Haiku R1 */ @@ -232,8 +238,12 @@ /*! \enum input_device_notification - \ingroup - \brief Undocumented enum. + \ingroup interface + \brief Constants for the \c be:opcode field of a \c B_INPUT_DEVICES_CHANGED + message. + + These message constants reflect changes in the state of input devices that + the Input Server is aware of. \since Haiku R1 */ @@ -241,7 +251,7 @@ /*! \var input_device_notification B_INPUT_DEVICE_ADDED - \brief Undocumented enum value. + \brief An input device was added to the system. \since Haiku R1 */ @@ -249,7 +259,7 @@ /*! \var input_device_notification B_INPUT_DEVICE_STARTED - \brief Undocumented enum value. + \brief An input device was started. \since Haiku R1 */ @@ -257,7 +267,7 @@ /*! \var input_device_notification B_INPUT_DEVICE_STOPPED - \brief Undocumented enum value. + \brief An input device was stopped. \since Haiku R1 */ @@ -265,7 +275,7 @@ /*! \var input_device_notification B_INPUT_DEVICE_REMOVED - \brief Undocumented enum value. + \brief An input device was removed from the system. \since Haiku R1 */ @@ -299,13 +309,29 @@ /*! \fn status_t watch_input_devices(BMessenger target, bool start) - \brief Undocumented function + \brief Start/stop watching input devices for state changes. - \param target Undocumented - \param start Undocumented + Informs the Input Server that \a target would like to start/stop receiving + \c B_INPUT_DEVICES_CHANGED messages, reflecting the state of input devices + the Input Server is aware of. - \return Undocumented - \retval Undocumented + The \c B_INPUT_DEVICES_CHANGED message contains: + - \c be:opcode An \c input_device_notifcation constant that identifies + which event occured. + - \c be:device_name A string containing the device's name. + - \c be:device_type An \c input_device_type constant representing the + device's type. + + \param target Where the device state change messages should or should not be + sent. + \param start Whether \a target should start/stop receiving device state + change messages. + + \return A status code. + \retval B_OK Watching has successfully been started or stopped. + \retval B_BAD_VALUE \a target never started watching for device state + changes, though a request was made to stop watching for changes. + \retval Other errors depending on the state of the Input Server. \since Haiku R1 */ diff --git a/src/servers/input/AddOnManager.cpp b/src/servers/input/AddOnManager.cpp index 3627bc9294..61c288df9b 100644 --- a/src/servers/input/AddOnManager.cpp +++ b/src/servers/input/AddOnManager.cpp @@ -755,11 +755,25 @@ AddOnManager::_HandleFindDevices(BMessage* message, BMessage* reply) status_t AddOnManager::_HandleWatchDevices(BMessage* message, BMessage* reply) { - // TODO handle multiple watchers at the same time - if (message->FindBool("start")) - message->FindMessenger("target", &fWatcherMessenger); - else - fWatcherMessenger = BMessenger(); + BMessenger watcherMessenger; + if (message->FindMessenger("target", &watcherMessenger) != B_OK) + return B_ERROR; + + bool startWatching; + if (message->FindBool("start", &startWatching) != B_OK) + return B_ERROR; + + if (fWatcherMessengerList.find(watcherMessenger) + == fWatcherMessengerList.end()) { + if (startWatching) + fWatcherMessengerList.insert(watcherMessenger); + else + return B_BAD_VALUE; + } else { + if (!startWatching) + fWatcherMessengerList.erase(watcherMessenger); + } + return B_OK; } @@ -767,9 +781,52 @@ AddOnManager::_HandleWatchDevices(BMessage* message, BMessage* reply) status_t AddOnManager::_HandleNotifyDevice(BMessage* message, BMessage* reply) { - // TODO handle multiple watchers at the same time - status_t result = fWatcherMessenger.SendMessage(message); - syslog(LOG_NOTICE, "Notify of added/removed device (%s)", strerror(result)); + if (!message->HasBool("added") && !message->HasBool("started")) + return B_BAD_VALUE; + + syslog(LOG_NOTICE, "Notify of added/removed/started/stopped device"); + + BMessage changeMessage(B_INPUT_DEVICES_CHANGED); + + bool deviceAdded; + if (message->FindBool("added", &deviceAdded) == B_OK) { + if (deviceAdded) + changeMessage.AddInt32("be:opcode", B_INPUT_DEVICE_ADDED); + else + changeMessage.AddInt32("be:opcode", B_INPUT_DEVICE_REMOVED); + } + + bool deviceStarted; + if (message->FindBool("started", &deviceStarted) == B_OK) { + if (deviceStarted) + changeMessage.AddInt32("be:opcode", B_INPUT_DEVICE_STARTED); + else + changeMessage.AddInt32("be:opcode", B_INPUT_DEVICE_STOPPED); + } + + BString deviceName; + if (message->FindString("name", &deviceName) != B_OK) + return B_BAD_VALUE; + + changeMessage.AddString("be:device_name", deviceName); + + input_device_type deviceType = B_UNDEFINED_DEVICE; + if (message->FindInt32("type", deviceType) != B_OK) + return B_BAD_VALUE; + + changeMessage.AddInt32("be:device_type", deviceType); + + std::set::iterator it = fWatcherMessengerList.begin(); + while (it != fWatcherMessengerList.end()) { + const BMessenger& currentMessenger = *it; + + status_t result = currentMessenger.SendMessage(&changeMessage); + + if (result != B_OK && !currentMessenger.IsValid()) + fWatcherMessengerList.erase(it++); + else + it++; + } return B_OK; } diff --git a/src/servers/input/AddOnManager.h b/src/servers/input/AddOnManager.h index 9600dd147b..ec7ef4a140 100644 --- a/src/servers/input/AddOnManager.h +++ b/src/servers/input/AddOnManager.h @@ -21,6 +21,8 @@ #include #include +#include + #include "PathList.h" @@ -125,7 +127,7 @@ private: PathList fDevicePaths; MonitorHandler* fHandler; - BMessenger fWatcherMessenger; + std::set fWatcherMessengerList; bool fSafeMode; }; diff --git a/src/servers/input/InputServer.cpp b/src/servers/input/InputServer.cpp index 60c443d44c..6013cac81f 100644 --- a/src/servers/input/InputServer.cpp +++ b/src/servers/input/InputServer.cpp @@ -1250,7 +1250,8 @@ InputServer::UnregisterDevices(BInputServerDevice& serverDevice, if (fInputDeviceList.RemoveItem(j)) { BMessage message(IS_NOTIFY_DEVICE); message.AddBool("added", false); - message.AddString("name", device->name); + message.AddString("name", item->Name()); + message.AddInt32("type", item->Type()); fAddOnManager->PostMessage(&message); delete item; } @@ -1313,7 +1314,8 @@ debug_printf("InputServer::RegisterDevices() device_ref already exists: %s\n", d item->Start(); BMessage message(IS_NOTIFY_DEVICE); message.AddBool("added", true); - message.AddString("name", device->name); + message.AddString("name", item->Name()); + message.AddInt32("type", item->Type()); fAddOnManager->PostMessage(&message); } else { delete item; @@ -1352,6 +1354,12 @@ InputServer::StartStopDevices(const char* name, input_device_type type, else item->Stop(); + BMessage message(IS_NOTIFY_DEVICE); + message.AddBool("started", doStart); + message.AddString("name", item->Name()); + message.AddInt32("type", item->Type()); + fAddOnManager->PostMessage(&message); + if (name) return B_OK; } @@ -1386,6 +1394,12 @@ InputServer::StartStopDevices(BInputServerDevice& serverDevice, bool doStart) item->Start(); else item->Stop(); + + BMessage message(IS_NOTIFY_DEVICE); + message.AddBool("started", doStart); + message.AddString("name", item->Name()); + message.AddInt32("type", item->Type()); + fAddOnManager->PostMessage(&message); } return B_OK;