From 9aea709ddaf55539f52597baf512fa9b156f7cbf Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 3 Sep 2020 21:22:20 +0200 Subject: [PATCH] Input prefs: handle errors Various error handling cases were missing, which would lead to corrupt settings and crashes. Add the missing error checks and make sure we always revert to sane settings in case of problems. Change-Id: Ib72621d6e4974345f5f6ee88e01a918cbf09d7ea Reviewed-on: https://review.haiku-os.org/c/haiku/+/3069 Reviewed-by: Adrien Destugues --- src/kits/interface/InterfaceDefs.cpp | 2 +- src/preferences/input/MouseSettings.cpp | 34 ++--- src/preferences/input/MouseView.cpp | 16 ++- src/preferences/input/SettingsView.cpp | 5 +- src/servers/input/InputServer.cpp | 181 +++++++++++------------- src/servers/input/InputServer.h | 1 + src/servers/input/MouseSettings.cpp | 6 +- 7 files changed, 120 insertions(+), 125 deletions(-) diff --git a/src/kits/interface/InterfaceDefs.cpp b/src/kits/interface/InterfaceDefs.cpp index af2943534a..ac89efaa59 100644 --- a/src/kits/interface/InterfaceDefs.cpp +++ b/src/kits/interface/InterfaceDefs.cpp @@ -531,7 +531,7 @@ set_mouse_type_by_name(BString mouse_name, int32 type) if (err_mouse_name != B_OK) return err_mouse_name; - status_t err = command.AddInt32("mouse_type", type); + status_t err = command.AddInt32("mouse_type", type); if (err != B_OK) return err; return _control_input_server_(&command, &reply); diff --git a/src/preferences/input/MouseSettings.cpp b/src/preferences/input/MouseSettings.cpp index cbe630978c..8774d5bb95 100644 --- a/src/preferences/input/MouseSettings.cpp +++ b/src/preferences/input/MouseSettings.cpp @@ -33,7 +33,8 @@ MouseSettings::MouseSettings(BString name) : fName(name) { - _RetrieveSettings(); + if (_RetrieveSettings() != B_OK) { + Defaults(); fOriginalSettings = fSettings; fOriginalMode = fMode; @@ -180,15 +181,16 @@ MouseSettings::Defaults() SetAcceptFirstClick(kDefaultAcceptFirstClick); mouse_map map; - if (get_mouse_map(&map) == B_OK) { + if (get_mouse_map(&map) != B_OK) { + // Set some default values map.button[0] = B_PRIMARY_MOUSE_BUTTON; map.button[1] = B_SECONDARY_MOUSE_BUTTON; map.button[2] = B_TERTIARY_MOUSE_BUTTON; map.button[3] = B_MOUSE_BUTTON(4); map.button[4] = B_MOUSE_BUTTON(5); map.button[5] = B_MOUSE_BUTTON(6); - SetMapping(map); } + SetMapping(map); } @@ -424,7 +426,10 @@ MultipleMouseSettings::RetrieveSettings() } else { // Does not look like a BMessage, try loading using the old format fDeprecatedMouseSettings = new MouseSettings(""); - fDeprecatedMouseSettings->_RetrieveSettings(); + if (fDeprecatedMouseSettings->_LoadLegacySettings() != B_OK) { + delete fDeprecatedMouseSettings; + fDeprecatedMouseSettings = NULL; + } } } @@ -509,20 +514,17 @@ MultipleMouseSettings::AddMouseSettings(BString mouse_name) } } - std::map::iterator itr; - itr = fMouseSettingsObject.find(mouse_name); + MouseSettings* settings = GetMouseSettings(mouse_name); + if (settings) + return settings; - if (itr != fMouseSettingsObject.end()) - return GetMouseSettings(mouse_name); + settings = new (std::nothrow) MouseSettings(mouse_name); + if (settings == NULL) + return NULL; - MouseSettings* settings = new (std::nothrow) MouseSettings(mouse_name); - - if(settings !=NULL) { - fMouseSettingsObject.insert(std::pair - (mouse_name, settings)); - return settings; - } - return B_OK; + fMouseSettingsObject.insert(std::pair + (mouse_name, settings)); + return settings; } diff --git a/src/preferences/input/MouseView.cpp b/src/preferences/input/MouseView.cpp index 2049e5a7cd..f4e2d0fba7 100644 --- a/src/preferences/input/MouseView.cpp +++ b/src/preferences/input/MouseView.cpp @@ -200,8 +200,10 @@ MouseView::MouseDown(BPoint where) menu.AddItem(new BMenuItem(tmp, new BMessage(message))); } - menu.ItemAt(getMappingNumber(fSettings.Mapping(button))) - ->SetMarked(true); + int32 mapping = fSettings.Mapping(button); + BMenuItem* item = menu.ItemAt(getMappingNumber(mapping)); + if (item) + item->SetMarked(true); menu.SetTargetForItems(Window()); ConvertToScreen(&where); @@ -297,14 +299,14 @@ MouseView::Draw(BRect updateFrame) if (i == fType - 1) border.right -= fScaling * 4; - char number[2] = {0}; - number[0] = getMappingNumber(map.button[_ConvertFromVisualOrder(i)]) - + '1'; + char label[2] = {0}; + int32 number = getMappingNumber(map.button[_ConvertFromVisualOrder(i)]); + label[0] = number + '1'; SetDrawingMode(B_OP_OVER); SetHighColor(kButtonTextColor); - DrawString(number, BPoint( - border.left + (border.Width() - StringWidth(number)) / 2, + DrawString(label, BPoint( + border.left + (border.Width() - StringWidth(label)) / 2, border.top + fDigitBaseline + (border.IntegerHeight() - fDigitHeight) / 2)); } diff --git a/src/preferences/input/SettingsView.cpp b/src/preferences/input/SettingsView.cpp index 647e8e37dd..53426079b1 100644 --- a/src/preferences/input/SettingsView.cpp +++ b/src/preferences/input/SettingsView.cpp @@ -71,6 +71,9 @@ SettingsView::SettingsView(MouseSettings& settings) : BBox("main_view"), fSettings(settings) { + if (fSettings.MouseType() > 6) + debugger("Mouse type is invalid"); + // Add the "Mouse Type" pop up menu fTypeMenu = new BOptionPopUp("type", B_TRANSLATE("Mouse type:"), new BMessage(kMsgMouseType)); @@ -255,8 +258,6 @@ SettingsView::UpdateFromSettings() fAccelerationSlider->SetValue(value); fTypeMenu->SelectOptionFor(fSettings.MouseType()); - if (fSettings.MouseType() > 6) - debugger("Mouse type is invalid"); fMouseView->SetMouseType(fSettings.MouseType()); BMenuItem* item = fFocusMenu->ItemAt( diff --git a/src/servers/input/InputServer.cpp b/src/servers/input/InputServer.cpp index 734035bd03..60c443d44c 100644 --- a/src/servers/input/InputServer.cpp +++ b/src/servers/input/InputServer.cpp @@ -853,30 +853,46 @@ InputServer::HandleSetKeyboardLocks(BMessage* message, BMessage* reply) } +// #pragma mark - Mouse settings + + +/** This method does all possible efforts to return some settings. + * + * The settings will be created if they do not exist. If a mouse name is + * specified, the settings for that mouse are created and used. Otherwise, + * default settings are returned. + */ +MouseSettings* +InputServer::_GetSettingsForMouse(BString mouseName) +{ + // If no mouse name is specified, use the first one found in settings + if (mouseName == "") { + std::map::iterator itr + = fMouseSettingsObject.begin(); + if (itr != fMouseSettingsObject.end()) + return itr->second; + } + + // If a mouse name is specified or there are no settings yet, get or create + // some + return fMouseSettings.AddMouseSettings(mouseName); +} + + status_t InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply) { BString mouseName; + message->FindString("mouse_name", &mouseName); - MouseSettings* settings = NULL; - if (message->FindString("mouse_name", &mouseName) == B_OK) { - settings = fMouseSettings.GetMouseSettings(mouseName); - if (settings == NULL) - return B_NAME_NOT_FOUND; - } + MouseSettings* settings = _GetSettingsForMouse(mouseName); + + if (settings == NULL) + return B_NO_MEMORY; int32 speed; if (message->FindInt32("speed", &speed) == B_OK) { - if (settings != NULL) - settings->SetMouseSpeed(speed); - else { - std::map::iterator itr; - for (itr = fMouseSettingsObject.begin(); - itr != fMouseSettingsObject.end(); ++itr) { - itr->second->SetMouseSpeed(speed); - } - return B_OK; - } + settings->SetMouseSpeed(speed); be_app_messenger.SendMessage(IS_SAVE_SETTINGS); BMessage msg(IS_CONTROL_DEVICES); @@ -885,11 +901,60 @@ InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply) return fAddOnManager->PostMessage(&msg); } - if (settings != NULL) - return reply->AddInt32("speed", settings->MouseSpeed()); - else { - return B_OK; + return reply->AddInt32("speed", settings->MouseSpeed()); +} + + +status_t +InputServer::HandleGetSetMouseMap(BMessage* message, BMessage* reply) +{ + BString mouseName; + message->FindString("mouse_name", &mouseName); + + MouseSettings* settings = _GetSettingsForMouse(mouseName); + if (settings == NULL) + return B_NO_MEMORY; + + mouse_map *map; + ssize_t size; + if (message->FindData("mousemap", B_RAW_TYPE, (const void**)&map, &size) == B_OK) { + settings->SetMapping(*map); + be_app_messenger.SendMessage(IS_SAVE_SETTINGS); + + BMessage msg(IS_CONTROL_DEVICES); + msg.AddInt32("type", B_POINTING_DEVICE); + msg.AddInt32("code", B_MOUSE_MAP_CHANGED); + return fAddOnManager->PostMessage(&msg); } + + mouse_map getmap; + settings->Mapping(getmap); + return reply->AddData("mousemap", B_RAW_TYPE, &getmap, sizeof(mouse_map)); +} + + +status_t +InputServer::HandleGetSetClickSpeed(BMessage* message, BMessage* reply) +{ + BString mouseName; + message->FindString("mouse_name", &mouseName); + + MouseSettings* settings = _GetSettingsForMouse(mouseName); + if (settings == NULL) + return B_NO_MEMORY; + + bigtime_t clickSpeed; + if (message->FindInt64("speed", &clickSpeed) == B_OK) { + settings->SetClickSpeed(clickSpeed); + be_app_messenger.SendMessage(IS_SAVE_SETTINGS); + + BMessage msg(IS_CONTROL_DEVICES); + msg.AddInt32("type", B_POINTING_DEVICE); + msg.AddInt32("code", B_CLICK_SPEED_CHANGED); + return fAddOnManager->PostMessage(&msg); + } + + return reply->AddInt64("speed", settings->ClickSpeed()); } @@ -919,44 +984,7 @@ InputServer::HandleSetMousePosition(BMessage* message, BMessage* reply) } -status_t -InputServer::HandleGetSetMouseMap(BMessage* message, BMessage* reply) -{ - BString mouseName; - MouseSettings* settings = NULL; - if (message->FindString("mouse_name", &mouseName) == B_OK) { - settings = fMouseSettings.GetMouseSettings(mouseName); - if (settings == NULL) - return B_NAME_NOT_FOUND; - } - - mouse_map *map; - ssize_t size; - if (message->FindData("mousemap", B_RAW_TYPE, (const void**)&map, &size) == B_OK) { - if (settings != NULL) - settings->SetMapping(*map); - else { - // TODO if no mouse_name was specified, apply the setting to - // all mouses - return B_NOT_SUPPORTED; - } - be_app_messenger.SendMessage(IS_SAVE_SETTINGS); - - BMessage msg(IS_CONTROL_DEVICES); - msg.AddInt32("type", B_POINTING_DEVICE); - msg.AddInt32("code", B_MOUSE_MAP_CHANGED); - return fAddOnManager->PostMessage(&msg); - } - - if (settings != NULL) { - mouse_map map; - settings->Mapping(map); - return reply->AddData("mousemap", B_RAW_TYPE, &map, sizeof(mouse_map)); - } else { - // TODO return type of the "first" mouse? - return B_NOT_SUPPORTED; - } -} +// #pragma mark - Keyboard settings status_t @@ -971,43 +999,6 @@ InputServer::HandleGetSetKeyboardID(BMessage* message, BMessage* reply) } -status_t -InputServer::HandleGetSetClickSpeed(BMessage* message, BMessage* reply) -{ - BString mouseName; - MouseSettings* settings = NULL; - if (message->FindString("mouse_name", &mouseName) == B_OK) { - settings = fMouseSettings.GetMouseSettings(mouseName); - if (settings == NULL) - return B_NAME_NOT_FOUND; - } - - bigtime_t clickSpeed; - if (message->FindInt64("speed", &clickSpeed) == B_OK) { - if (settings != NULL) - settings->SetClickSpeed(clickSpeed); - else { - // TODO if no mouse_name was specified, apply the setting to - // all mouses - return B_NOT_SUPPORTED; - } - be_app_messenger.SendMessage(IS_SAVE_SETTINGS); - - BMessage msg(IS_CONTROL_DEVICES); - msg.AddInt32("type", B_POINTING_DEVICE); - msg.AddInt32("code", B_CLICK_SPEED_CHANGED); - return fAddOnManager->PostMessage(&msg); - } - - if (settings != NULL) { - return reply->AddInt64("speed", settings->ClickSpeed()); - } else { - // TODO return type of the "first" mouse? - return B_NOT_SUPPORTED; - } -} - - status_t InputServer::HandleGetSetKeyRepeatRate(BMessage* message, BMessage* reply) { diff --git a/src/servers/input/InputServer.h b/src/servers/input/InputServer.h index 8c2e3ebcd6..46eec5f13c 100644 --- a/src/servers/input/InputServer.h +++ b/src/servers/input/InputServer.h @@ -187,6 +187,7 @@ class InputServer : public BApplication { status_t _LoadSystemKeymap(); status_t _SaveKeymap(bool isDefault = false); void _InitKeyboardMouseStates(); + MouseSettings* _GetSettingsForMouse(BString mouseName); status_t _StartEventLoop(); void _EventLoop(); diff --git a/src/servers/input/MouseSettings.cpp b/src/servers/input/MouseSettings.cpp index 7a64db9d80..1699845de9 100644 --- a/src/servers/input/MouseSettings.cpp +++ b/src/servers/input/MouseSettings.cpp @@ -171,10 +171,8 @@ MouseSettings::Defaults() SetFocusFollowsMouseMode(B_NORMAL_FOCUS_FOLLOWS_MOUSE); SetAcceptFirstClick(kDefaultAcceptFirstClick); - fSettings.map.button[0] = B_PRIMARY_MOUSE_BUTTON; - fSettings.map.button[1] = B_SECONDARY_MOUSE_BUTTON; - fSettings.map.button[2] = B_TERTIARY_MOUSE_BUTTON; - + for (int i = 0; i < B_MAX_MOUSE_BUTTONS; i++) + fSettings.map.button[i] = B_MOUSE_BUTTON(i + 1); }