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;