diff --git a/headers/os/add-ons/input_server/InputServerDevice.h b/headers/os/add-ons/input_server/InputServerDevice.h index fdf9201de1..1e50180a0f 100644 --- a/headers/os/add-ons/input_server/InputServerDevice.h +++ b/headers/os/add-ons/input_server/InputServerDevice.h @@ -1,46 +1,42 @@ -/****************************************************************************** -/ -/ File: InputServerDevice.h -/ -/ Description: Add-on class for input_server devices. -/ -/ Copyright 1998, Be Incorporated, All Rights Reserved. -/ -******************************************************************************/ - +/* + * Copyright 2008 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ #ifndef _INPUTSERVERDEVICE_H #define _INPUTSERVERDEVICE_H -#include + #include #include +// Register your actual devices using this one - you can subclass +// this to suit your needs struct input_device_ref { - char *name; - input_device_type type; - void *cookie; + char* name; + input_device_type type; // see Input.h + void* cookie; }; - +// BInputServerDevice::Control() codes enum { // B_KEYBOARD_DEVICE notifications - B_KEY_MAP_CHANGED = 1, + B_KEY_MAP_CHANGED = 1, B_KEY_LOCKS_CHANGED, - B_KEY_REPEAT_DELAY_CHANGED, + B_KEY_REPEAT_DELAY_CHANGED, B_KEY_REPEAT_RATE_CHANGED, // B_POINTING_DEVICE notifications - B_MOUSE_TYPE_CHANGED, + B_MOUSE_TYPE_CHANGED, B_MOUSE_MAP_CHANGED, B_MOUSE_SPEED_CHANGED, B_CLICK_SPEED_CHANGED, - B_MOUSE_ACCELERATION_CHANGED + B_MOUSE_ACCELERATION_CHANGED, }; - -class _BDeviceAddOn_; - +namespace BPrivate { + class DeviceAddOn; +} class BInputServerDevice { public: @@ -50,30 +46,28 @@ public: virtual status_t InitCheck(); virtual status_t SystemShuttingDown(); - virtual status_t Start(const char *device, void *cookie); - virtual status_t Stop(const char *device, void *cookie); - virtual status_t Control(const char *device, - void *cookie, - uint32 code, - BMessage *message); + virtual status_t Start(const char* device, void* cookie); + virtual status_t Stop(const char* device, void* cookie); + virtual status_t Control(const char* device, void* cookie, uint32 code, + BMessage* message); - status_t RegisterDevices(input_device_ref **devices); - status_t UnregisterDevices(input_device_ref **devices); + status_t RegisterDevices(input_device_ref** devices); + status_t UnregisterDevices(input_device_ref** devices); - status_t EnqueueMessage(BMessage *message); + status_t EnqueueMessage(BMessage* message); - status_t StartMonitoringDevice(const char *device); - status_t StopMonitoringDevice(const char *device); + status_t StartMonitoringDevice(const char* device); + status_t StopMonitoringDevice(const char* device); + status_t AddDevices(const char* path); private: - _BDeviceAddOn_* fOwner; - virtual void _ReservedInputServerDevice1(); virtual void _ReservedInputServerDevice2(); virtual void _ReservedInputServerDevice3(); virtual void _ReservedInputServerDevice4(); + + BPrivate::DeviceAddOn* fOwner; uint32 _reserved[4]; }; - -#endif +#endif // _INPUTSERVERDEVICE_H diff --git a/src/servers/input/AddOnManager.cpp b/src/servers/input/AddOnManager.cpp index 65cf457be6..e4aa3de25f 100644 --- a/src/servers/input/AddOnManager.cpp +++ b/src/servers/input/AddOnManager.cpp @@ -1,85 +1,128 @@ /* - * Copyright 2004-2005, Haiku, Inc. All rights reserved. + * Copyright 2004-2008, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Marcus Overhagen, Axel Dörfler + * Marcus Overhagen + * Axel Dörfler, axeld@pinc-software.de * Jérôme Duval */ +//! Manager for input_server add-ons (devices, filters, methods) + +#include "AddOnManager.h" + +#include +#include #include #include #include #include #include +#include #include #include #include -#include -#include -#include +#include -#include "AddOnManager.h" #include "InputServer.h" #include "InputServerTypes.h" #include "MethodReplicant.h" -class AddOnManager::InputServerMonitorHandler : public AddOnMonitorHandler { - public: - InputServerMonitorHandler(AddOnManager* manager) - { - fManager = manager; - } +#undef TRACE +//#define TRACE_ADD_ON_MONITOR +#ifdef TRACE_ADD_ON_MONITOR +# define TRACE(x...) debug_printf(x) +# define ERROR(x...) debug_printf(x) +#else +# define TRACE(x...) ; +// TODO: probably better to the syslog +# define ERROR(x...) debug_printf(x) +#endif - virtual void - AddOnCreated(const add_on_entry_info* entryInfo) - { - } - virtual void - AddOnEnabled(const add_on_entry_info* entryInfo) - { - CALLED(); - entry_ref ref; - make_entry_ref(entryInfo->dir_nref.device, entryInfo->dir_nref.node, - entryInfo->name, &ref); - BEntry entry(&ref, false); - fManager->RegisterAddOn(entry); - } - virtual void - AddOnDisabled(const add_on_entry_info* entryInfo) - { - CALLED(); - entry_ref ref; - make_entry_ref(entryInfo->dir_nref.device, entryInfo->dir_nref.node, - entryInfo->name, &ref); - BEntry entry(&ref, false); - fManager->UnregisterAddOn(entry); - } +class AddOnManager::MonitorHandler : public AddOnMonitorHandler { +public: + MonitorHandler(AddOnManager* manager) + { + fManager = manager; + } - virtual void - AddOnRemoved(const add_on_entry_info* entryInfo) - { - } + virtual void AddOnEnabled(const add_on_entry_info* entryInfo) + { + CALLED(); + entry_ref ref; + make_entry_ref(entryInfo->dir_nref.device, entryInfo->dir_nref.node, + entryInfo->name, &ref); + BEntry entry(&ref, false); - private: - AddOnManager* fManager; + fManager->_RegisterAddOn(entry); + } + + virtual void AddOnDisabled(const add_on_entry_info* entryInfo) + { + CALLED(); + entry_ref ref; + make_entry_ref(entryInfo->dir_nref.device, entryInfo->dir_nref.node, + entryInfo->name, &ref); + BEntry entry(&ref, false); + + fManager->_UnregisterAddOn(entry); + } + +private: + AddOnManager* fManager; }; // #pragma mark - +template T* +instantiate_add_on(image_id image, const char* path, const char* type) +{ + T* (*instantiateFunction)(); + + BString functionName = "instantiate_input_"; + functionName += type; + + if (get_image_symbol(image, functionName.String(), B_SYMBOL_TYPE_TEXT, + (void**)&instantiateFunction) < B_OK) { + ERROR("AddOnManager::_RegisterAddOn(): can't find %s() in \"%s\"\n", + functionName.String(), path); + return NULL; + } + + T* addOn = (*instantiateFunction)(); + if (addOn == NULL) { + ERROR("AddOnManager::_RegisterAddOn(): %s() in \"%s\" returned " + "NULL\n", functionName.String(), path); + return NULL; + } + + status_t status = addOn->InitCheck(); + if (status != B_OK) { + ERROR("AddOnManager::_RegisterAddOn(): InitCheck() in \"%s\" " + "returned %s\n", path, strerror(status)); + delete addOn; + return NULL; + } + + return addOn; +} + + +// #pragma mark - + + AddOnManager::AddOnManager(bool safeMode) : BLooper("add-on manager"), - fLock("add-on manager"), fSafeMode(safeMode) { - Run(); } @@ -91,7 +134,7 @@ AddOnManager::~AddOnManager() void AddOnManager::LoadState() { - RegisterAddOns(); + _RegisterAddOns(); } @@ -99,208 +142,25 @@ void AddOnManager::SaveState() { CALLED(); - UnregisterAddOns(); -} - - -status_t -AddOnManager::RegisterAddOn(BEntry& entry) -{ - BPath path(&entry); - - entry_ref ref; - status_t status = entry.GetRef(&ref); - if (status < B_OK) - return status; - - PRINT(("AddOnManager::RegisterAddOn(): trying to load \"%s\"\n", path.Path())); - - image_id addonImage = load_add_on(path.Path()); - - if (addonImage < B_OK) { - PRINT(("load addon %s failed\n", path.Path())); - return addonImage; - } - - BString pathString = path.Path(); - - if (pathString.FindFirst("input_server/devices") > 0) { - BInputServerDevice* (*instantiateFunc)(); - - if (get_image_symbol(addonImage, "instantiate_input_device", - B_SYMBOL_TYPE_TEXT, (void**)&instantiateFunc) < B_OK) { - PRINTERR(("AddOnManager::RegisterAddOn(): can't find instantiate_input_device in \"%s\"\n", - path.Path())); - goto exit_error; - } - - BInputServerDevice* device = (*instantiateFunc)(); - if (device == NULL) { - PRINTERR(("AddOnManager::RegisterAddOn(): instantiate_input_device in \"%s\" returned NULL\n", - path.Path())); - goto exit_error; - } - - status_t status = device->InitCheck(); - if (status != B_OK) { - PRINTERR(("AddOnManager::RegisterAddOn(): BInputServerDevice.InitCheck in \"%s\" returned %s\n", - path.Path(), strerror(status))); - delete device; - goto exit_error; - } - - RegisterDevice(device, ref, addonImage); - } else if (pathString.FindFirst("input_server/filters") > 0) { - BInputServerFilter* (*instantiateFunc)(); - - if (get_image_symbol(addonImage, "instantiate_input_filter", - B_SYMBOL_TYPE_TEXT, (void**)&instantiateFunc) < B_OK) { - PRINTERR(("AddOnManager::RegisterAddOn(): can't find instantiate_input_filter in \"%s\"\n", - path.Path())); - goto exit_error; - } - - BInputServerFilter* filter = (*instantiateFunc)(); - if (filter == NULL) { - PRINTERR(("AddOnManager::RegisterAddOn(): instantiate_input_filter in \"%s\" returned NULL\n", - path.Path())); - goto exit_error; - } - status_t status = filter->InitCheck(); - if (status != B_OK) { - PRINTERR(("AddOnManager::RegisterAddOn(): BInputServerFilter.InitCheck in \"%s\" returned %s\n", - path.Path(), strerror(status))); - delete filter; - goto exit_error; - } - - RegisterFilter(filter, ref, addonImage); - } else if (pathString.FindFirst("input_server/methods") > 0) { - BInputServerMethod* (*instantiateFunc)(); - - if (get_image_symbol(addonImage, "instantiate_input_method", - B_SYMBOL_TYPE_TEXT, (void**)&instantiateFunc) < B_OK) { - PRINTERR(("AddOnManager::RegisterAddOn(): can't find instantiate_input_method in \"%s\"\n", - path.Path())); - goto exit_error; - } - - BInputServerMethod* method = (*instantiateFunc)(); - if (method == NULL) { - PRINTERR(("AddOnManager::RegisterAddOn(): instantiate_input_method in \"%s\" returned NULL\n", - path.Path())); - goto exit_error; - } - status_t status = method->InitCheck(); - if (status != B_OK) { - PRINTERR(("AddOnManager::RegisterAddOn(): BInputServerMethod.InitCheck in \"%s\" returned %s\n", - path.Path(), strerror(status))); - delete method; - goto exit_error; - } - - RegisterMethod(method, ref, addonImage); - } else { - PRINTERR(("AddOnManager::RegisterAddOn(): addon type not found for \"%s\" \n", path.Path())); - goto exit_error; - } - - return B_OK; - -exit_error: - unload_add_on(addonImage); - return status; -} - - -status_t -AddOnManager::UnregisterAddOn(BEntry& entry) -{ - BPath path(&entry); - - entry_ref ref; - status_t status = entry.GetRef(&ref); - if (status < B_OK) - return status; - - PRINT(("AddOnManager::UnregisterAddOn(): trying to unload \"%s\"\n", path.Path())); - - BEntry parent; - entry.GetParent(&parent); - BPath parentPath(&parent); - BString pathString = parentPath.Path(); - - BAutolock locker(fLock); - - if (pathString.FindFirst("input_server/devices") > 0) { - device_info *pinfo; - for (fDeviceList.Rewind(); fDeviceList.GetNext(&pinfo);) { - if (!strcmp(pinfo->ref.name, ref.name)) { - gInputServer->StartStopDevices(*pinfo->device, false); - delete pinfo->device; - if (pinfo->addon_image >= B_OK) - unload_add_on(pinfo->addon_image); - fDeviceList.RemoveCurrent(); - break; - } - } - } else if (pathString.FindFirst("input_server/filters") > 0) { - filter_info *pinfo; - for (fFilterList.Rewind(); fFilterList.GetNext(&pinfo);) { - if (!strcmp(pinfo->ref.name, ref.name)) { - BAutolock lock2(InputServer::gInputFilterListLocker); - InputServer::gInputFilterList.RemoveItem(pinfo->filter); - delete pinfo->filter; - if (pinfo->addon_image >= B_OK) - unload_add_on(pinfo->addon_image); - fFilterList.RemoveCurrent(); - break; - } - } - } else if (pathString.FindFirst("input_server/methods") > 0) { - method_info *pinfo = NULL; - for (fMethodList.Rewind(); fMethodList.GetNext(&pinfo);) { - if (!strcmp(pinfo->ref.name, ref.name)) { - BAutolock lock2(InputServer::gInputMethodListLocker); - InputServer::gInputMethodList.RemoveItem(pinfo->method); - delete pinfo->method; - if (pinfo->addon_image >= B_OK) - unload_add_on(pinfo->addon_image); - fMethodList.RemoveCurrent(); - break; - } - } - - if (fMethodList.CountItems() <= 0) { - // we remove the method replicant - BDeskbar().RemoveItem(REPLICANT_CTL_NAME); - gInputServer->SetMethodReplicant(NULL); - } else if (pinfo != NULL) { - BMessage msg(IS_REMOVE_METHOD); - msg.AddInt32("cookie", (uint32)pinfo->method); - if (gInputServer->MethodReplicant()) - gInputServer->MethodReplicant()->SendMessage(&msg); - } - } - - return B_OK; + _UnregisterAddOns(); } void -AddOnManager::RegisterAddOns() +AddOnManager::_RegisterAddOns() { CALLED(); + BAutolock locker(this); status_t err; - fHandler = new InputServerMonitorHandler(this); + fHandler = new MonitorHandler(this); fAddOnMonitor = new AddOnMonitor(fHandler); #ifndef APPSERVER_TEST_MODE err = fAddOnMonitor->InitCheck(); if (err != B_OK) { - PRINTERR(("AddOnManager::RegisterAddOns(): fAddOnMonitor->InitCheck() returned %s\n", - strerror(err))); + ERROR("AddOnManager::RegisterAddOns(): fAddOnMonitor->InitCheck() " + "returned %s\n", strerror(err)); return; } @@ -332,138 +192,299 @@ AddOnManager::RegisterAddOns() } #else // APPSERVER_TEST_MODE BEntry entry("/boot/home/svnhaiku/trunk/tests/servers/input/view_input_device/input_server/devices/ViewInputDevice"); - RegisterAddOn(entry); + _RegisterAddOn(entry); #endif } void -AddOnManager::UnregisterAddOns() +AddOnManager::_UnregisterAddOns() { + BAutolock locker(this); + BMessenger messenger(fAddOnMonitor); messenger.SendMessage(B_QUIT_REQUESTED); - int32 exit_value; - wait_for_thread(fAddOnMonitor->Thread(), &exit_value); + int32 exitValue; + wait_for_thread(fAddOnMonitor->Thread(), &exitValue); delete fHandler; - BAutolock locker(fLock); + // We have to stop manually the add-ons because the monitor doesn't + // disable them on exit - // we have to stop manually the addons because the monitor doesn't disable them on exit - - { - device_info* info; - for (fDeviceList.Rewind(); fDeviceList.GetNext(&info);) { - gInputServer->StartStopDevices(*info->device, false); - delete info->device; - if (info->addon_image >= B_OK) - unload_add_on(info->addon_image); - fDeviceList.RemoveCurrent(); - } + while (device_info* info = fDeviceList.RemoveItemAt(0)) { + gInputServer->StartStopDevices(*info->add_on, false); + delete info; } - { - filter_info* info; - for (fFilterList.Rewind(); fFilterList.GetNext(&info);) { - delete info->filter; - if (info->addon_image >= B_OK) - unload_add_on(info->addon_image); - fFilterList.RemoveCurrent(); - } + // TODO: what about the filters/methods lists in the input_server? + + while (filter_info* info = fFilterList.RemoveItemAt(0)) { + delete info; } - { - method_info* info; - for (fMethodList.Rewind(); fMethodList.GetNext(&info);) { - delete info->method; - if (info->addon_image >= B_OK) - unload_add_on(info->addon_image); - fMethodList.RemoveCurrent(); - } + while (method_info* info = fMethodList.RemoveItemAt(0)) { + delete info; } } -void -AddOnManager::RegisterDevice(BInputServerDevice* device, const entry_ref& ref, - image_id addonImage) +bool +AddOnManager::_IsDevice(const char* path) const { - BAutolock locker(fLock); + return strstr(path, "input_server/devices") != 0; +} - device_info* info; - for (fDeviceList.Rewind(); fDeviceList.GetNext(&info);) { + +bool +AddOnManager::_IsFilter(const char* path) const +{ + return strstr(path, "input_server/filters") != 0; +} + + +bool +AddOnManager::_IsMethod(const char* path) const +{ + return strstr(path, "input_server/methods") != 0; +} + + +status_t +AddOnManager::_RegisterAddOn(BEntry& entry) +{ + BPath path(&entry); + + entry_ref ref; + status_t status = entry.GetRef(&ref); + if (status < B_OK) + return status; + + TRACE("AddOnManager::RegisterAddOn(): trying to load \"%s\"\n", + path.Path()); + + image_id image = load_add_on(path.Path()); + if (image < B_OK) { + ERROR("load addon %s failed\n", path.Path()); + return image; + } + + status = B_ERROR; + + if (_IsDevice(path.Path())) { + BInputServerDevice* device = instantiate_add_on( + image, path.Path(), "device"); + if (device != NULL) + status = _RegisterDevice(device, ref, image); + } else if (_IsFilter(path.Path())) { + BInputServerFilter* filter = instantiate_add_on( + image, path.Path(), "filter"); + if (filter != NULL) + status = _RegisterFilter(filter, ref, image); + } else if (_IsMethod(path.Path())) { + BInputServerMethod* method = instantiate_add_on( + image, path.Path(), "method"); + if (method != NULL) + status = _RegisterMethod(method, ref, image); + } else { + ERROR("AddOnManager::_RegisterAddOn(): addon type not found for " + "\"%s\" \n", path.Path()); + } + + if (status != B_OK) + unload_add_on(image); + + return status; +} + + +status_t +AddOnManager::_UnregisterAddOn(BEntry& entry) +{ + BPath path(&entry); + + entry_ref ref; + status_t status = entry.GetRef(&ref); + if (status < B_OK) + return status; + + TRACE("AddOnManager::UnregisterAddOn(): trying to unload \"%s\"\n", + path.Path()); + + BAutolock _(this); + + if (_IsDevice(path.Path())) { + for (int32 i = fDeviceList.CountItems(); i-- > 0;) { + device_info* info = fDeviceList.ItemAt(i); + if (!strcmp(info->ref.name, ref.name)) { + gInputServer->StartStopDevices(*info->add_on, false); + delete fDeviceList.RemoveItemAt(i); + break; + } + } + } else if (_IsFilter(path.Path())) { + for (int32 i = fFilterList.CountItems(); i-- > 0;) { + filter_info* info = fFilterList.ItemAt(i); + if (!strcmp(info->ref.name, ref.name)) { + BAutolock locker(InputServer::gInputFilterListLocker); + InputServer::gInputFilterList.RemoveItem(info->add_on); + delete fFilterList.RemoveItemAt(i); + break; + } + } + } else if (_IsMethod(path.Path())) { + BInputServerMethod* method = NULL; + + for (int32 i = fMethodList.CountItems(); i-- > 0;) { + method_info* info = fMethodList.ItemAt(i); + if (!strcmp(info->ref.name, ref.name)) { + BAutolock locker(InputServer::gInputMethodListLocker); + InputServer::gInputMethodList.RemoveItem(info->add_on); + method = info->add_on; + // this will only be used as a cookie, and not referenced + // anymore + delete fMethodList.RemoveItemAt(i); + break; + } + } + + if (fMethodList.CountItems() <= 0) { + // we remove the method replicant + BDeskbar().RemoveItem(REPLICANT_CTL_NAME); + gInputServer->SetMethodReplicant(NULL); + } else if (method != NULL) { + BMessage msg(IS_REMOVE_METHOD); + msg.AddInt32("cookie", (uint32)method); + if (gInputServer->MethodReplicant()) + gInputServer->MethodReplicant()->SendMessage(&msg); + } + } + + return B_OK; +} + + +//! Takes over ownership of the \a device, regardless of success. +status_t +AddOnManager::_RegisterDevice(BInputServerDevice* device, const entry_ref& ref, + image_id addOnImage) +{ + BAutolock locker(this); + + for (int32 i = fDeviceList.CountItems(); i-- > 0;) { + device_info* info = fDeviceList.ItemAt(i); if (!strcmp(info->ref.name, ref.name)) { // we already know this device - return; + delete device; + return B_NAME_IN_USE; } } - PRINT(("AddOnManager::RegisterDevice, name %s\n", ref.name)); + TRACE("AddOnManager::RegisterDevice, name %s\n", ref.name); - device_info newInfo; - newInfo.ref = ref; - newInfo.addon_image = addonImage; - newInfo.device = device; + device_info* info = new(std::nothrow) device_info; + if (info == NULL) { + delete device; + return B_NO_MEMORY; + } - fDeviceList.Insert(newInfo); + info->ref = ref; + info->image = addOnImage; + info->add_on = device; + + if (!fDeviceList.AddItem(info)) { + delete info; + return B_NO_MEMORY; + } + + return B_OK; } -void -AddOnManager::RegisterFilter(BInputServerFilter* filter, const entry_ref& ref, - image_id addonImage) +//! Takes over ownership of the \a filter, regardless of success. +status_t +AddOnManager::_RegisterFilter(BInputServerFilter* filter, const entry_ref& ref, + image_id addOnImage) { - BAutolock locker(fLock); + BAutolock _(this); - filter_info *pinfo; - for (fFilterList.Rewind(); fFilterList.GetNext(&pinfo);) { - if (!strcmp(pinfo->ref.name, ref.name)) { + for (int32 i = fFilterList.CountItems(); i-- > 0;) { + filter_info* info = fFilterList.ItemAt(i); + if (!strcmp(info->ref.name, ref.name)) { // we already know this ref - return; + delete filter; + return B_NAME_IN_USE; } } - PRINT(("%s, name %s\n", __PRETTY_FUNCTION__, ref.name)); + TRACE("%s, name %s\n", __PRETTY_FUNCTION__, ref.name); - filter_info info; - info.ref = ref; - info.addon_image = addonImage; - info.filter = filter; + filter_info* info = new(std::nothrow) filter_info; + if (info == NULL) { + delete filter; + return B_NO_MEMORY; + } - fFilterList.Insert(info); + info->ref = ref; + info->image = addOnImage; + info->add_on = filter; - BAutolock lock2(InputServer::gInputFilterListLocker); - InputServer::gInputFilterList.AddItem(filter); + if (!fFilterList.AddItem(info)) { + delete info; + return B_NO_MEMORY; + } + + BAutolock locker(InputServer::gInputFilterListLocker); + if (!InputServer::gInputFilterList.AddItem(filter)) { + fFilterList.RemoveItem(info); + delete info; + return B_NO_MEMORY; + } + return B_OK; } -void -AddOnManager::RegisterMethod(BInputServerMethod* method, const entry_ref& ref, - image_id addonImage) +//! Takes over ownership of the \a method, regardless of success. +status_t +AddOnManager::_RegisterMethod(BInputServerMethod* method, const entry_ref& ref, + image_id addOnImage) { - BAutolock locker(fLock); + BAutolock _(this); - method_info *pinfo; - for (fMethodList.Rewind(); fMethodList.GetNext(&pinfo);) { - if (!strcmp(pinfo->ref.name, ref.name)) { + for (int32 i = fMethodList.CountItems(); i-- > 0;) { + method_info* info = fMethodList.ItemAt(i); + if (!strcmp(info->ref.name, ref.name)) { // we already know this ref - return; + delete method; + return B_NAME_IN_USE; } } - PRINT(("%s, name %s\n", __PRETTY_FUNCTION__, ref.name)); + TRACE("%s, name %s\n", __PRETTY_FUNCTION__, ref.name); - method_info info; - info.ref = ref; - info.addon_image = addonImage; - info.method = method; + method_info* info = new(std::nothrow) method_info; + if (info == NULL) { + delete method; + return B_NO_MEMORY; + } - fMethodList.Insert(info); + info->ref = ref; + info->image = addOnImage; + info->add_on = method; - BAutolock lock2(InputServer::gInputMethodListLocker); - InputServer::gInputMethodList.AddItem(method); + if (!fMethodList.AddItem(info)) { + delete info; + return B_NO_MEMORY; + } + + BAutolock locker(InputServer::gInputMethodListLocker); + if (!InputServer::gInputMethodList.AddItem(method)) { + fMethodList.RemoveItem(info); + delete info; + return B_NO_MEMORY; + } if (gInputServer->MethodReplicant() == NULL) { - LoadReplicant(); + _LoadReplicant(); if (gInputServer->MethodReplicant()) { _BMethodAddOn_ *addon = InputServer::gKeymapMethod.fOwner; @@ -471,22 +492,24 @@ AddOnManager::RegisterMethod(BInputServerMethod* method, const entry_ref& ref, } } - if (gInputServer->MethodReplicant()) { + if (gInputServer->MethodReplicant() != NULL) { _BMethodAddOn_ *addon = method->fOwner; addon->AddMethod(); } + + return B_OK; } void -AddOnManager::UnloadReplicant() +AddOnManager::_UnloadReplicant() { BDeskbar().RemoveItem(REPLICANT_CTL_NAME); } void -AddOnManager::LoadReplicant() +AddOnManager::_LoadReplicant() { CALLED(); app_info info; @@ -494,7 +517,7 @@ AddOnManager::LoadReplicant() status_t err = BDeskbar().AddItem(&info.ref); if (err != B_OK) { - PRINTERR(("Deskbar refuses to add method replicant: %s\n", strerror(err))); + ERROR("Deskbar refuses to add method replicant: %s\n", strerror(err)); } BMessage request(B_GET_PROPERTY); BMessenger to; @@ -510,21 +533,21 @@ AddOnManager::LoadReplicant() BMessage reply; - if ((to.SendMessage(&request, &reply) == B_OK) - && (reply.FindMessenger("result", &status) == B_OK)) { + if (to.SendMessage(&request, &reply) == B_OK + && reply.FindMessenger("result", &status) == B_OK) { // enum replicant in Status view int32 index = 0; int32 uid; - while ((uid = GetReplicantAt(status, index++)) >= B_OK) { - BMessage rep_info; - if (GetReplicantName(status, uid, &rep_info) != B_OK) + while ((uid = _GetReplicantAt(status, index++)) >= B_OK) { + BMessage replicantInfo; + if (_GetReplicantName(status, uid, &replicantInfo) != B_OK) continue; const char *name; - if (rep_info.FindString("result", &name) == B_OK + if (replicantInfo.FindString("result", &name) == B_OK && !strcmp(name, REPLICANT_CTL_NAME)) { BMessage replicant; - if (GetReplicantView(status, uid, &replicant) == B_OK) { + if (_GetReplicantView(status, uid, &replicant) == B_OK) { BMessenger result; if (replicant.FindMessenger("result", &result) == B_OK) { gInputServer->SetMethodReplicant(new BMessenger(result)); @@ -535,13 +558,13 @@ AddOnManager::LoadReplicant() } if (!gInputServer->MethodReplicant()) { - fprintf(stderr, "LoadReplicant(): Method replicant not found!\n"); + ERROR("LoadReplicant(): Method replicant not found!\n"); } } int32 -AddOnManager::GetReplicantAt(BMessenger target, int32 index) const +AddOnManager::_GetReplicantAt(BMessenger target, int32 index) const { // So here we want to get the Unique ID of the replicant at the given index // in the target Shelf. @@ -565,7 +588,8 @@ AddOnManager::GetReplicantAt(BMessenger target, int32 index) const status_t -AddOnManager::GetReplicantName(BMessenger target, int32 uid, BMessage *reply) const +AddOnManager::_GetReplicantName(BMessenger target, int32 uid, + BMessage* reply) const { // We send a message to the target shelf, asking it for the Name of the // replicant with the given unique id. @@ -593,7 +617,7 @@ AddOnManager::GetReplicantName(BMessenger target, int32 uid, BMessage *reply) co status_t -AddOnManager::GetReplicantView(BMessenger target, int32 uid, +AddOnManager::_GetReplicantView(BMessenger target, int32 uid, BMessage* reply) const { // We send a message to the target shelf, asking it for the Name of the @@ -624,42 +648,45 @@ AddOnManager::GetReplicantView(BMessenger target, int32 uid, void -AddOnManager::MessageReceived(BMessage *message) +AddOnManager::MessageReceived(BMessage* message) { CALLED(); BMessage reply; status_t status; - PRINT(("%s what:%c%c%c%c\n", __PRETTY_FUNCTION__, message->what >> 24, - message->what >> 16, message->what >> 8, message->what)); + ERROR("%s what: %.4s\n", __PRETTY_FUNCTION__, (char*)&message->what); switch (message->what) { case IS_FIND_DEVICES: - status = HandleFindDevices(message, &reply); + status = _HandleFindDevices(message, &reply); break; case IS_WATCH_DEVICES: - status = HandleWatchDevices(message, &reply); + status = _HandleWatchDevices(message, &reply); break; case IS_IS_DEVICE_RUNNING: - status = HandleIsDeviceRunning(message, &reply); + status = _HandleIsDeviceRunning(message, &reply); break; case IS_START_DEVICE: - status = HandleStartStopDevices(message, &reply); + status = _HandleStartStopDevices(message, &reply); break; case IS_STOP_DEVICE: - status = HandleStartStopDevices(message, &reply); + status = _HandleStartStopDevices(message, &reply); break; case IS_CONTROL_DEVICES: - status = HandleControlDevices(message, &reply); + status = _HandleControlDevices(message, &reply); break; case SYSTEM_SHUTTING_DOWN: - status = HandleSystemShuttingDown(message, &reply); + status = _HandleSystemShuttingDown(message, &reply); break; case IS_METHOD_REGISTER: - status = HandleMethodReplicant(message, &reply); + status = _HandleMethodReplicant(message, &reply); break; + case B_PATH_MONITOR: + _HandleDeviceMonitor(message); + return; + default: return; } @@ -670,8 +697,7 @@ AddOnManager::MessageReceived(BMessage *message) status_t -AddOnManager::HandleStartStopDevices(BMessage* message, - BMessage* reply) +AddOnManager::_HandleStartStopDevices(BMessage* message, BMessage* reply) { const char *name = NULL; int32 type = 0; @@ -685,7 +711,7 @@ AddOnManager::HandleStartStopDevices(BMessage* message, status_t -AddOnManager::HandleFindDevices(BMessage* message, BMessage* reply) +AddOnManager::_HandleFindDevices(BMessage* message, BMessage* reply) { CALLED(); const char *name = NULL; @@ -703,7 +729,7 @@ AddOnManager::HandleFindDevices(BMessage* message, BMessage* reply) status_t -AddOnManager::HandleWatchDevices(BMessage* message, BMessage* reply) +AddOnManager::_HandleWatchDevices(BMessage* message, BMessage* reply) { // TODO return B_OK; @@ -711,9 +737,9 @@ AddOnManager::HandleWatchDevices(BMessage* message, BMessage* reply) status_t -AddOnManager::HandleIsDeviceRunning(BMessage* message, BMessage* reply) +AddOnManager::_HandleIsDeviceRunning(BMessage* message, BMessage* reply) { - const char *name; + const char* name; bool running; if (message->FindString("device", &name) != B_OK || gInputServer->GetDeviceInfo(name, NULL, &running) != B_OK) @@ -724,20 +750,20 @@ AddOnManager::HandleIsDeviceRunning(BMessage* message, BMessage* reply) status_t -AddOnManager::HandleControlDevices(BMessage* message, BMessage* reply) +AddOnManager::_HandleControlDevices(BMessage* message, BMessage* reply) { CALLED(); const char *name = NULL; int32 type = 0; if (!((message->FindInt32("type", &type) != B_OK) ^ (message->FindString("device", &name) != B_OK))) - return B_ERROR; + return B_BAD_VALUE; uint32 code = 0; BMessage controlMessage; bool hasMessage = true; if (message->FindInt32("code", (int32*)&code) != B_OK) - return B_ERROR; + return B_BAD_VALUE; if (message->FindMessage("message", &controlMessage) != B_OK) hasMessage = false; @@ -747,14 +773,13 @@ AddOnManager::HandleControlDevices(BMessage* message, BMessage* reply) status_t -AddOnManager::HandleSystemShuttingDown(BMessage* message, - BMessage* reply) +AddOnManager::_HandleSystemShuttingDown(BMessage* message, BMessage* reply) { CALLED(); - device_info *pinfo; - for (fDeviceList.Rewind(); fDeviceList.GetNext(&pinfo);) { - pinfo->device->SystemShuttingDown(); + for (int32 i = 0; i < fDeviceList.CountItems(); i++) { + device_info* info = fDeviceList.ItemAt(i); + info->add_on->SystemShuttingDown(); } return B_OK; @@ -762,30 +787,154 @@ AddOnManager::HandleSystemShuttingDown(BMessage* message, status_t -AddOnManager::HandleMethodReplicant(BMessage* message, BMessage* reply) +AddOnManager::_HandleMethodReplicant(BMessage* message, BMessage* reply) { CALLED(); if (InputServer::gInputMethodList.CountItems() == 0) { - UnloadReplicant(); + _UnloadReplicant(); return B_OK; } - LoadReplicant(); + _LoadReplicant(); BAutolock lock(InputServer::gInputMethodListLocker); if (gInputServer->MethodReplicant()) { - _BMethodAddOn_ *addon = InputServer::gKeymapMethod.fOwner; + _BMethodAddOn_* addon = InputServer::gKeymapMethod.fOwner; addon->AddMethod(); - for (int32 i=0; ifOwner; + for (int32 i = 0; i < InputServer::gInputMethodList.CountItems(); i++) { + BInputServerMethod* method + = (BInputServerMethod*)InputServer::gInputMethodList.ItemAt(i); + + _BMethodAddOn_* addon = method->fOwner; addon->AddMethod(); } } return B_OK; } + + +void +AddOnManager::_HandleDeviceMonitor(BMessage* message) +{ + int32 opcode; + if (message->FindInt32("opcode", &opcode) != B_OK) + return; + + switch (opcode) { + case B_ENTRY_CREATED: + case B_ENTRY_REMOVED: + { + const char* path; + const char* watchedPath; + if (message->FindString("watched_path", &watchedPath) != B_OK + || message->FindString("path", &path) != B_OK) + return; + + // Notify all watching devices + + for (int32 i = 0; i < fDeviceAddOns.CountItems(); i++) { + DeviceAddOn* addOn = fDeviceAddOns.ItemAt(i); + if (!addOn->HasPath(watchedPath)) + continue; + + addOn->Device()->Control(NULL, NULL, B_NODE_MONITOR, message); + } + break; + } + } +} + + +status_t +AddOnManager::_AddDevicePath(DeviceAddOn* addOn, const char* path, + bool& newPath) +{ + newPath = !fDevicePaths.HasPath(path); + + status_t status = fDevicePaths.AddPath(path); + if (status == B_OK) { + status = addOn->AddPath(path); + if (status == B_OK) { + if (!fDeviceAddOns.HasItem(addOn) + && !fDeviceAddOns.AddItem(addOn)) { + addOn->RemovePath(path); + status = B_NO_MEMORY; + } + } else + fDevicePaths.RemovePath(path); + } + + return status; +} + + +status_t +AddOnManager::_RemoveDevicePath(DeviceAddOn* addOn, const char* path, + bool& lastPath) +{ + if (!fDevicePaths.HasPath(path) || !addOn->HasPath(path)) + return B_ENTRY_NOT_FOUND; + + fDevicePaths.RemovePath(path); + + lastPath = !fDevicePaths.HasPath(path); + + addOn->RemovePath(path); + if (addOn->CountPaths() == 0) + fDeviceAddOns.RemoveItem(addOn); + + return B_OK; +} + + +status_t +AddOnManager::StartMonitoringDevice(DeviceAddOn* addOn, const char* device) +{ + CALLED(); + + BString path; + if (device[0] != '/') + path = "/dev/"; + path += device; + + TRACE("AddOnMonitor::StartMonitoringDevice(%s)\n", path.String()); + + bool newPath; + status_t status = _AddDevicePath(addOn, path.String(), newPath); + if (status == B_OK && newPath) { + status = BPathMonitor::StartWatching(path.String(), B_ENTRY_CREATED + | B_ENTRY_REMOVED | B_ENTRY_MOVED | B_WATCH_FILES_ONLY + | B_WATCH_RECURSIVELY, this); + if (status != B_OK) { + bool lastPath; + _RemoveDevicePath(addOn, path.String(), lastPath); + } + } + + return status; +} + + +status_t +AddOnManager::StopMonitoringDevice(DeviceAddOn* addOn, const char *device) +{ + CALLED(); + + BString path; + if (device[0] != '/') + path = "/dev/"; + path += device; + + TRACE("AddOnMonitor::StopMonitoringDevice(%s)\n", path.String()); + + bool lastPath; + status_t status = _RemoveDevicePath(addOn, path.String(), lastPath); + if (status == B_OK && lastPath) + BPathMonitor::StopWatching(path.String(), this); + + return status; +} diff --git a/src/servers/input/AddOnManager.h b/src/servers/input/AddOnManager.h index 7e6be4c1d1..5efb4677b1 100644 --- a/src/servers/input/AddOnManager.h +++ b/src/servers/input/AddOnManager.h @@ -1,15 +1,14 @@ /* - * Copyright 2004-2005, Haiku, Inc. All rights reserved. + * Copyright 2004-2008, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Marcus Overhagen, Axel Dörfler + * Marcus Overhagen + * Axel Dörfler, axeld@pinc-software.de * Jérôme Duval */ -#ifndef _ADD_ON_MANAGER_H -#define _ADD_ON_MANAGER_H - -// Manager for input_server add-ons (devices, filters, methods) +#ifndef ADD_ON_MANAGER_H +#define ADD_ON_MANAGER_H #include @@ -18,74 +17,114 @@ #include #include -#include "AddOnMonitor.h" -#include "AddOnMonitorHandler.h" -#include "TList.h" +#include +#include +#include "PathList.h" + + +using namespace BPrivate; class AddOnManager : public BLooper { - public: - AddOnManager(bool safeMode); - ~AddOnManager(); +public: + AddOnManager(bool safeMode); + ~AddOnManager(); - void LoadState(); - void SaveState(); - void MessageReceived(BMessage *message); + void LoadState(); + void SaveState(); - private: - status_t RegisterAddOn(BEntry &entry); - status_t UnregisterAddOn(BEntry &entry); - void RegisterAddOns(); - void UnregisterAddOns(); + void MessageReceived(BMessage* message); - void RegisterDevice(BInputServerDevice *isd, const entry_ref &ref, image_id addon_image); - void RegisterFilter(BInputServerFilter *isf, const entry_ref &ref, image_id addon_image); - void RegisterMethod(BInputServerMethod *ism, const entry_ref &ref, image_id addon_image); + status_t StartMonitoringDevice(DeviceAddOn* addOn, + const char* device); + status_t StopMonitoringDevice(DeviceAddOn* addOn, + const char* device); - status_t HandleFindDevices(BMessage*, BMessage*); - status_t HandleWatchDevices(BMessage*, BMessage*); - status_t HandleIsDeviceRunning(BMessage*, BMessage*); - status_t HandleStartStopDevices(BMessage*, BMessage*); - status_t HandleControlDevices(BMessage*, BMessage*); - status_t HandleSystemShuttingDown(BMessage*, BMessage*); - status_t HandleMethodReplicant(BMessage*, BMessage*); - status_t HandleNodeMonitor(BMessage*); +private: + void _RegisterAddOns(); + void _UnregisterAddOns(); - void LoadReplicant(); - void UnloadReplicant(); - int32 GetReplicantAt(BMessenger target, int32 index) const; - status_t GetReplicantName(BMessenger target, int32 uid, BMessage *reply) const; - status_t GetReplicantView(BMessenger target, int32 uid, BMessage *reply) const; + status_t _RegisterAddOn(BEntry& entry); + status_t _UnregisterAddOn(BEntry& entry); - private: - class InputServerMonitorHandler; - friend class InputServerMonitorHandler; + bool _IsDevice(const char* path) const; + bool _IsFilter(const char* path) const; + bool _IsMethod(const char* path) const; - struct device_info { - entry_ref ref; - image_id addon_image; - BInputServerDevice *device; - }; - struct filter_info { - entry_ref ref; - image_id addon_image; - BInputServerFilter *filter; - }; - struct method_info { - entry_ref ref; - image_id addon_image; - BInputServerMethod *method; - }; + status_t _RegisterDevice(BInputServerDevice* device, + const entry_ref& ref, image_id image); + status_t _RegisterFilter(BInputServerFilter* filter, + const entry_ref& ref, image_id image); + status_t _RegisterMethod(BInputServerMethod* method, + const entry_ref& ref, image_id image); - BLocker fLock; - List fDeviceList; - List fFilterList; - List fMethodList; + status_t _HandleFindDevices(BMessage* message, + BMessage* reply); + status_t _HandleWatchDevices(BMessage* message, + BMessage* reply); + status_t _HandleIsDeviceRunning(BMessage* message, + BMessage* reply); + status_t _HandleStartStopDevices(BMessage* message, + BMessage* reply); + status_t _HandleControlDevices(BMessage* message, + BMessage* reply); + status_t _HandleSystemShuttingDown(BMessage* message, + BMessage* reply); + status_t _HandleMethodReplicant(BMessage* message, + BMessage* reply); + void _HandleDeviceMonitor(BMessage* message); - AddOnMonitorHandler *fHandler; - AddOnMonitor *fAddOnMonitor; + void _LoadReplicant(); + void _UnloadReplicant(); + int32 _GetReplicantAt(BMessenger target, + int32 index) const; + status_t _GetReplicantName(BMessenger target, + int32 uid, BMessage* reply) const; + status_t _GetReplicantView(BMessenger target, int32 uid, + BMessage* reply) const; - bool fSafeMode; + status_t _AddDevicePath(DeviceAddOn* addOn, + const char* path, bool& newPath); + status_t _RemoveDevicePath(DeviceAddOn* addOn, + const char* path, bool& lastPath); + +private: + class MonitorHandler; + friend class MonitorHandler; + + template struct add_on_info { + add_on_info() + : + image(-1), add_on(NULL) + { + } + + ~add_on_info() + { + delete add_on; + if (image >= 0) + unload_add_on(image); + } + + entry_ref ref; + image_id image; + T* add_on; + }; + typedef struct add_on_info device_info; + typedef struct add_on_info filter_info; + typedef struct add_on_info method_info; + + BObjectList fDeviceList; + BObjectList fFilterList; + BObjectList fMethodList; + + BObjectList fDeviceAddOns; + PathList fDevicePaths; + + MonitorHandler* fHandler; + AddOnMonitor* fAddOnMonitor; + + bool fSafeMode; }; -#endif // _ADD_ON_MANAGER_H +#endif // ADD_ON_MANAGER_H diff --git a/src/servers/input/DeviceManager.cpp b/src/servers/input/DeviceManager.cpp deleted file mode 100644 index 10940304ff..0000000000 --- a/src/servers/input/DeviceManager.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2004-2008, the Haiku project. All rights reserved. - * Distributed under the terms of the Haiku License. - * - * Authors: - * Marcus Overhagen, Axel Dörfler - * Jérôme Duval - */ - -#include "DeviceManager.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "InputServer.h" - - -void -DeviceManager::MessageReceived(BMessage *msg) -{ - CALLED(); - if (msg->what == B_NODE_MONITOR) { - int32 opcode; - if (msg->FindInt32("opcode", &opcode) == B_OK) { - switch (opcode) { - case B_ENTRY_CREATED: - case B_ENTRY_REMOVED: - case B_ENTRY_MOVED: - { - node_ref dir_nref; - if (msg->FindInt32("device", &dir_nref.device) != B_OK - || msg->FindInt64("directory", &dir_nref.node) != B_OK) - return; - - _BDeviceAddOn_ *addon = NULL; - int32 i = 0; - while ((addon = GetAddOn(i++)) !=NULL) { - int32 j=0; - node_ref *dnref = NULL; - while ((dnref = (node_ref *)addon->fMonitoredRefs.ItemAt(j++)) != NULL) { - if (*dnref == dir_nref) { - addon->fDevice->Control(NULL, NULL, msg->what, - msg); - } - } - } - break; - } - - case B_STAT_CHANGED: - case B_ATTR_CHANGED: - case B_DEVICE_MOUNTED: - case B_DEVICE_UNMOUNTED: - default: - BLooper::MessageReceived(msg); - break; - } - } - } -} - - -status_t -DeviceManager::AddDirectory(const node_ref *nref, _BDeviceAddOn_ *addon) -{ - CALLED(); - BDirectory directory(nref); - status_t status = directory.InitCheck(); - if (status != B_OK) - return status; - - status = watch_node(nref, B_WATCH_DIRECTORY, this); - if (status != B_OK) - return status; - - BEntry entry; - while (directory.GetNextEntry(&entry, true) == B_OK) { - entry_ref ref; - entry.GetRef(&ref); - BMessage msg(B_NODE_MONITOR); - msg.AddInt32("opcode", B_ENTRY_CREATED); - msg.AddInt32("device", nref->device); - msg.AddInt64("directory", nref->node); - msg.AddString("name", ref.name); - addon->fDevice->Control(NULL, NULL, msg.what, &msg); - } - - return B_OK; -} - - -status_t -DeviceManager::RemoveDirectory(const node_ref *nref, _BDeviceAddOn_ *addon) -{ - CALLED(); - BDirectory directory(nref); - status_t status = directory.InitCheck(); - if (status != B_OK) - return status; - - status = watch_node(nref, B_STOP_WATCHING, this); - if (status != B_OK) - return status; - - BEntry entry; - while (directory.GetNextEntry(&entry, true) == B_OK) { - entry_ref ref; - entry.GetRef(&ref); - BMessage msg(B_NODE_MONITOR); - msg.AddInt32("opcode", B_ENTRY_REMOVED); - msg.AddInt32("device", nref->device); - msg.AddInt64("directory", nref->node); - msg.AddString("name", ref.name); - addon->fDevice->Control(NULL, NULL, msg.what, &msg); - } - - return B_OK; -} - - -DeviceManager::DeviceManager() - : - fLock("device manager") -{ -} - - -DeviceManager::~DeviceManager() -{ - _BDeviceAddOn_ *addon = NULL; - while ((addon = (_BDeviceAddOn_ *)fDeviceAddons.RemoveItem((int32)0)) != NULL) - delete addon; -} - - -void -DeviceManager::LoadState() -{ - CALLED(); - if (!Lock()) - return; - Run(); - Unlock(); -} - - -void -DeviceManager::SaveState() -{ -} - - -status_t -DeviceManager::StartMonitoringDevice(_BDeviceAddOn_ *addon, const char *device) -{ - CALLED(); - status_t err; - node_ref nref; - BDirectory directory; - BPath path("/dev"); - if ((err = path.Append(device)) != B_OK) { - PRINTERR(("DeviceManager::StartMonitoringDevice BPath::Append() error %s: %s\n", path.Path(), strerror(err))); - return err; - } - - if ((err = directory.SetTo(path.Path())) != B_OK) { - if (err != B_ENTRY_NOT_FOUND) { - PRINTERR(("DeviceManager::StartMonitoringDevice SetTo error %s: %s\n", path.Path(), strerror(err))); - return err; - } - if ((err = create_directory(path.Path(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != B_OK - || (err = directory.SetTo(path.Path())) != B_OK) { - PRINTERR(("DeviceManager::StartMonitoringDevice CreateDirectory error %s: %s\n", path.Path(), strerror(err))); - return err; - } - } - - if ((err = directory.GetNodeRef(&nref)) != B_OK) { - PRINTERR(("DeviceManager::StartMonitoringDevice GetNodeRef error %s: %s\n", path.Path(), strerror(err))); - return err; - } - - // test if already monitored - bool alreadyMonitored = false; - _BDeviceAddOn_ *tmpaddon = NULL; - int32 i = 0; - while ((tmpaddon = (_BDeviceAddOn_ *)fDeviceAddons.ItemAt(i++)) !=NULL) { - int32 j=0; - node_ref *dnref = NULL; - while ((dnref = (node_ref *)tmpaddon->fMonitoredRefs.ItemAt(j++)) != NULL) { - if (*dnref == nref) { - PRINT(("StartMonitoringDevice already monitored\n")); - alreadyMonitored = true; - break; - } - } - if (alreadyMonitored) - break; - } - - // monitor if needed - if (!alreadyMonitored) { - if ((err = AddDirectory(&nref, addon)) != B_OK) - return err; - } - - // add addon in list - if (!fDeviceAddons.HasItem(addon)) - fDeviceAddons.AddItem(addon); - - // add dir ref in list - int32 j=0; - node_ref *dnref = NULL; - alreadyMonitored = false; - while ((dnref = (node_ref *)addon->fMonitoredRefs.ItemAt(j++)) != NULL) { - if (*dnref == nref) { - alreadyMonitored = true; - break; - } - } - - if (!alreadyMonitored) - addon->fMonitoredRefs.AddItem(new node_ref(nref)); - - return B_OK; -} - - -status_t -DeviceManager::StopMonitoringDevice(_BDeviceAddOn_ *addon, const char *device) -{ - CALLED(); - status_t err; - node_ref nref; - BDirectory directory; - BPath path("/dev"); - if ((err = path.Append(device)) != B_OK - || (err = directory.SetTo(path.Path())) != B_OK - || (err = directory.GetNodeRef(&nref)) != B_OK) - return err; - - // test if still monitored - bool stillMonitored = false; - _BDeviceAddOn_ *tmpaddon = NULL; - int32 i = 0; - while ((tmpaddon = (_BDeviceAddOn_ *)fDeviceAddons.ItemAt(i++)) != NULL) { - if (addon == tmpaddon) - continue; - - int32 j=0; - node_ref *dnref = NULL; - while ((dnref = (node_ref *)tmpaddon->fMonitoredRefs.ItemAt(j++)) != NULL) { - if (*dnref == nref) { - stillMonitored = true; - break; - } - } - if (stillMonitored) - break; - } - - // remove from list - node_ref *dnref = NULL; - int32 j = 0; - while ((dnref = (node_ref *)addon->fMonitoredRefs.ItemAt(j)) != NULL) { - if (*dnref == nref) { - addon->fMonitoredRefs.RemoveItem(j); - delete dnref; - break; - } - j++; - } - - if (addon->fMonitoredRefs.IsEmpty()) - fDeviceAddons.RemoveItem(addon); - - // stop monitoring if needed - if (!stillMonitored) { - if ((err = RemoveDirectory(&nref, addon)) != B_OK) - return err; - } - - return B_OK; -} diff --git a/src/servers/input/DeviceManager.h b/src/servers/input/DeviceManager.h deleted file mode 100644 index fbf3691749..0000000000 --- a/src/servers/input/DeviceManager.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2004-2008, the Haiku project. All rights reserved. - * Distributed under the terms of the Haiku License. - * - * Authors: - * Marcus Overhagen, Axel Dörfler - * Jérôme Duval - */ -#ifndef _DEVICE_MANAGER_H -#define _DEVICE_MANAGER_H - -//! Manager for devices monitoring - -#include -#include -#include -#include - -#include -#include -#include - -#include "TList.h" - - -class DeviceManager : public BLooper { -public: - DeviceManager(); - virtual ~DeviceManager(); - - void LoadState(); - void SaveState(); - - status_t StartMonitoringDevice(_BDeviceAddOn_ *addon, - const char *device); - status_t StopMonitoringDevice(_BDeviceAddOn_ *addon, - const char *device); - _BDeviceAddOn_ *GetAddOn(int32 index) - { return (_BDeviceAddOn_*) - fDeviceAddons.ItemAt(index); } - - virtual void MessageReceived(BMessage *msg); - -private: - status_t AddDirectory(const node_ref *nref, - _BDeviceAddOn_ *addon); - status_t RemoveDirectory(const node_ref *nref, - _BDeviceAddOn_ *addon); - - BList fDeviceAddons; - BLocker fLock; -}; - -#endif // _DEVICE_MANAGER_H diff --git a/src/servers/input/InputServer.cpp b/src/servers/input/InputServer.cpp index f6758e51d4..1d92db8987 100644 --- a/src/servers/input/InputServer.cpp +++ b/src/servers/input/InputServer.cpp @@ -58,8 +58,6 @@ BLocker InputServer::gInputFilterListLocker("is_filter_queue_sem"); BList InputServer::gInputMethodList; BLocker InputServer::gInputMethodListLocker("is_method_queue_sem"); -DeviceManager InputServer::gDeviceManager; - KeymapMethod InputServer::gKeymapMethod; @@ -180,8 +178,6 @@ InputServer::InputServer() fSafeMode = true; } - gDeviceManager.LoadState(); - #ifndef HAIKU_TARGET_PLATFORM_HAIKU if (has_data(find_thread(NULL))) { PRINT(("HasData == YES\n")); @@ -218,8 +214,11 @@ InputServer::InputServer() _InitKeyboardMouseStates(); - fAddOnManager = new AddOnManager(SafeMode()); - fAddOnManager->LoadState(); + fAddOnManager = new(std::nothrow) ::AddOnManager(SafeMode()); + if (fAddOnManager != NULL) { + fAddOnManager->Run(); + fAddOnManager->LoadState(); + } BMessenger messenger(this); BRoster().StartWatching(messenger, B_REQUEST_LAUNCHED); @@ -229,8 +228,10 @@ InputServer::InputServer() InputServer::~InputServer() { CALLED(); - fAddOnManager->Lock(); - fAddOnManager->Quit(); + if (fAddOnManager != NULL) { + fAddOnManager->Lock(); + fAddOnManager->Quit(); + } _ReleaseInput(NULL); } @@ -395,7 +396,6 @@ InputServer::QuitRequested() return false; } else { fAddOnManager->SaveState(); - gDeviceManager.SaveState(); delete_port(fEventLooperPort); // the event looper thread will exit after this diff --git a/src/servers/input/InputServer.h b/src/servers/input/InputServer.h index 47baf0cf90..ca02f61aab 100644 --- a/src/servers/input/InputServer.h +++ b/src/servers/input/InputServer.h @@ -1,18 +1,16 @@ /* - * Copyright 2001-2005, Haiku, Inc. All Rights Reserved. + * Copyright 2001-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef INPUT_SERVER_APP_H #define INPUT_SERVER_APP_H -// #define DEBUG 1 -#include "AddOnManager.h" -#include "DeviceManager.h" -#include "KeyboardSettings.h" -#include "MouseSettings.h" +#include +#include +#include -#include "shared_cursor_area.h" +//#define DEBUG 1 #include #include @@ -28,9 +26,12 @@ #include #include -#include -#include -#include +#include + +#include "AddOnManager.h" +#include "KeyboardSettings.h" +#include "MouseSettings.h" +#include "PathList.h" #define INPUTSERVER_SIGNATURE "application/x-vnd.Be-input_server" @@ -65,15 +66,27 @@ class InputDeviceListItem { bool fRunning; }; -class _BDeviceAddOn_ { - public: - _BDeviceAddOn_(BInputServerDevice *device) - : fDevice(device) {} +namespace BPrivate { - BInputServerDevice* fDevice; - BList fMonitoredRefs; +class DeviceAddOn { +public: + DeviceAddOn(BInputServerDevice* device); + ~DeviceAddOn(); + + bool HasPath(const char* path) const; + status_t AddPath(const char* path); + status_t RemovePath(const char* path); + int32 CountPaths() const; + + BInputServerDevice* Device() { return fDevice; } + +private: + BInputServerDevice* fDevice; + PathList fMonitoredPaths; }; +} // namespace BPrivate + class _BMethodAddOn_ { public: _BMethodAddOn_(BInputServerMethod *method, const char* name, @@ -109,7 +122,7 @@ class InputServer : public BApplication { virtual bool QuitRequested(); virtual void ReadyToRun(); - virtual void MessageReceived(BMessage* message); + virtual void MessageReceived(BMessage* message); void HandleSetMethod(BMessage* message); status_t HandleGetSetMouseType(BMessage* message, BMessage* reply); @@ -156,14 +169,14 @@ class InputServer : public BApplication { bool SafeMode(); + ::AddOnManager* AddOnManager() { return fAddOnManager; } + static BList gInputFilterList; static BLocker gInputFilterListLocker; static BList gInputMethodList; static BLocker gInputMethodListLocker; - static DeviceManager gDeviceManager; - static KeymapMethod gKeymapMethod; BRect& ScreenFrame() { return fFrame; } @@ -215,7 +228,7 @@ class InputServer : public BApplication { port_id fEventLooperPort; - AddOnManager* fAddOnManager; + ::AddOnManager* fAddOnManager; BScreen fScreen; BRect fFrame; @@ -259,7 +272,7 @@ extern InputServer* gInputServer; # define PRINT(x) _iprint x # else # undef PRINT -# define PRINT(x) SERIAL_PRINT(x) +# define PRINT(x) SERIAL_PRINT(x) # endif # define PRINTERR(x) PRINT(x) # define EXIT() PRINT(("EXIT %s\n", __PRETTY_FUNCTION__)) diff --git a/src/servers/input/InputServerDevice.cpp b/src/servers/input/InputServerDevice.cpp index b6271fcf54..4e6aefedaa 100644 --- a/src/servers/input/InputServerDevice.cpp +++ b/src/servers/input/InputServerDevice.cpp @@ -1,18 +1,68 @@ /* - * Copyright 2002-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2002-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ -#include "InputServer.h" - #include #include +#include +#include + +#include "InputServer.h" + + +DeviceAddOn::DeviceAddOn(BInputServerDevice *device) + : + fDevice(device) +{ +} + + +DeviceAddOn::~DeviceAddOn() +{ + while (const char* path = fMonitoredPaths.PathAt(0)) { + gInputServer->AddOnManager()->StopMonitoringDevice(this, path); + } +} + + +bool +DeviceAddOn::HasPath(const char* path) const +{ + return fMonitoredPaths.HasPath(path); +} + + +status_t +DeviceAddOn::AddPath(const char* path) +{ + return fMonitoredPaths.AddPath(path); +} + + +status_t +DeviceAddOn::RemovePath(const char* path) +{ + return fMonitoredPaths.RemovePath(path); +} + + +int32 +DeviceAddOn::CountPaths() const +{ + return fMonitoredPaths.CountPaths(); +} + + +// #pragma mark - + + BInputServerDevice::BInputServerDevice() { - fOwner = new (std::nothrow) _BDeviceAddOn_(this); + fOwner = new(std::nothrow) DeviceAddOn(this); } @@ -94,15 +144,41 @@ BInputServerDevice::StartMonitoringDevice(const char* device) CALLED(); PRINT(("StartMonitoringDevice %s\n", device)); - return InputServer::gDeviceManager.StartMonitoringDevice(fOwner, device); + return gInputServer->AddOnManager()->StartMonitoringDevice(fOwner, device); } status_t BInputServerDevice::StopMonitoringDevice(const char* device) { - CALLED(); - return InputServer::gDeviceManager.StopMonitoringDevice(fOwner, device); + return gInputServer->AddOnManager()->StopMonitoringDevice(fOwner, device); +} + + +status_t +BInputServerDevice::AddDevices(const char* path) +{ + BDirectory directory; + status_t status = directory.SetTo(path); + if (status != B_OK) + return status; + + BEntry entry; + while (directory.GetNextEntry(&entry) == B_OK) { + BPath entryPath(&entry); + + if (entry.IsDirectory()) { + AddDevices(entryPath.Path()); + } else { + BMessage added(B_NODE_MONITOR); + added.AddInt32("opcode", B_ENTRY_CREATED); + added.AddString("path", entryPath.Path()); + + Control(NULL, NULL, B_INPUT_DEVICE_ADDED, &added); + } + } + + return B_OK; } @@ -110,4 +186,3 @@ void BInputServerDevice::_ReservedInputServerDevice1() {} void BInputServerDevice::_ReservedInputServerDevice2() {} void BInputServerDevice::_ReservedInputServerDevice3() {} void BInputServerDevice::_ReservedInputServerDevice4() {} - diff --git a/src/servers/input/Jamfile b/src/servers/input/Jamfile index d6501f3f1c..322ffd3809 100644 --- a/src/servers/input/Jamfile +++ b/src/servers/input/Jamfile @@ -54,7 +54,6 @@ Server input_server : InputServerMethod.cpp AddOnManager.cpp - DeviceManager.cpp MouseSettings.cpp KeyboardSettings.cpp @@ -63,6 +62,8 @@ Server input_server : MethodMenuItem.cpp BottomlineWindow.cpp + PathList.cpp + # storage AddOnMonitor.cpp AddOnMonitorHandler.cpp diff --git a/src/servers/input/PathList.cpp b/src/servers/input/PathList.cpp new file mode 100644 index 0000000000..c60fd3709a --- /dev/null +++ b/src/servers/input/PathList.cpp @@ -0,0 +1,110 @@ +/* + * Copyright 2008 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "PathList.h" + +#include +#include + + +struct PathList::path_entry { + path_entry(const char* _path) + { + path = strdup(_path); + } + + ~path_entry() + { + free((char*)path); + } + + const char* path; + int32 ref_count; +}; + + +PathList::PathList() + : + fPaths(10, true) +{ +} + + +PathList::~PathList() +{ +} + + +bool +PathList::HasPath(const char* path, int32* _index) const +{ + for (int32 i = fPaths.CountItems(); i-- > 0;) { + if (!strcmp(fPaths.ItemAt(i)->path, path)) { + if (_index != NULL) + *_index = i; + return true; + } + } + + return false; +} + + +status_t +PathList::AddPath(const char* path) +{ + if (path == NULL) + return B_BAD_VALUE; + + int32 index; + if (HasPath(path, &index)) { + fPaths.ItemAt(index)->ref_count++; + return B_OK; + } + + path_entry* entry = new(std::nothrow) path_entry(path); + if (entry == NULL || entry->path == NULL || !fPaths.AddItem(entry)) { + delete entry; + return B_NO_MEMORY; + } + + return B_OK; +} + + +status_t +PathList::RemovePath(const char* path) +{ + int32 index; + if (!HasPath(path, &index)) + return B_ENTRY_NOT_FOUND; + + if (--fPaths.ItemAt(index)->ref_count == 0) + delete fPaths.RemoveItemAt(index); + + return B_OK; +} + + +int32 +PathList::CountPaths() const +{ + return fPaths.CountItems(); +} + + +const char* +PathList::PathAt(int32 index) const +{ + path_entry* entry = fPaths.ItemAt(index); + if (entry == NULL) + return NULL; + + return entry->path; +} diff --git a/src/servers/input/PathList.h b/src/servers/input/PathList.h new file mode 100644 index 0000000000..d8892498c6 --- /dev/null +++ b/src/servers/input/PathList.h @@ -0,0 +1,33 @@ +/* + * Copyright 2008 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef PATH_LIST_H +#define PATH_LIST_H + + +#include + + +class PathList { +public: + PathList(); + ~PathList(); + + bool HasPath(const char* path, + int32* _index = NULL) const; + status_t AddPath(const char* path); + status_t RemovePath(const char* path); + + int32 CountPaths() const; + const char* PathAt(int32 index) const; +private: + struct path_entry; + + BObjectList fPaths; +}; + +#endif // _DEVICE_MANAGER_H diff --git a/src/servers/input/TList.h b/src/servers/input/TList.h deleted file mode 100644 index 72a38bd2d3..0000000000 --- a/src/servers/input/TList.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef _MEDIA_T_LIST_H -#define _MEDIA_T_LIST_H - -#include - -template class List -{ -public: - List() - : item_max(INIT_COUNT), - item_count(0), - item_iter(-1), - items((value **)malloc(sizeof(value *) * INIT_COUNT)) - { - ASSERT(items); - } - - ~List() - { - MakeEmpty(); - free(items); - } - - List(const List &other) - { - *this = other; - } - - List &operator=(const List &other) - { - MakeEmpty(); - free(items); - item_max = other.item_max; - item_count = other.item_count; - items = (value **)malloc(sizeof(value *) * item_max); - ASSERT(items); - for (int i = 0; i < item_count; i++) { - items[i] = new value; - *items[i] = *other.items[i]; - } - return *this; - } - - bool Insert(const value &v) - { - if (item_count == item_max) { - item_max *= 2; - items = (value **)realloc(items, sizeof(value *) * item_max); - ASSERT(items); - } - items[item_count] = new value; - *items[item_count] = v; - item_count++; - return true; - } - - bool Get(int32 index, value **v) - { - if (index < 0 || index >= item_count) - return false; - *v = items[index]; - return true; - } - - bool Remove(int32 index) - { - if (index < 0 || index >= item_count) - return false; - delete items[index]; - item_count--; - items[index] = items[item_count]; - if (index == item_iter) - item_iter--; - return true; - } - - int Find(const value &v) - { - for (int i = 0; i < item_count; i++) - if (*items[i] == v) - return i; - return -1; - } - - int CountItems() - { - return item_count; - } - - bool IsEmpty() - { - return item_count == 0; - } - - void MakeEmpty() - { - if (items != 0) { - for (int i = 0; i < item_count; i++) { - delete items[i]; - } - item_count = 0; - } - } - - void Rewind() - { - item_iter = -1; - } - - bool GetNext(value **v) - { - item_iter++; - return Get(item_iter, v); - } - - bool RemoveCurrent() - { - return Remove(item_iter); - } - -private: - enum { INIT_COUNT=32 }; - int item_max; - int item_count; - int item_iter; - value **items; -}; - -#endif // _MEDIA_T_LIST_H