From 5bbf7f1be073d376e37da34681c8e6c7acfcf198 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Wed, 5 Feb 2020 13:37:57 +0100 Subject: [PATCH] Actually handle more than 3 mouse buttons The code in input_server was pretty much all set for this, but there was no way to configure the extra buttons. Add them to the mouse view in Input preferences (up to 5 buttons are handled now) Define a new B_MOUSE_BUTTON(n) macro to generate the bitmask for a given button (numbered from 1). Change-Id: I9091082277937d89b08464ff474e7bbb5db82401 Reviewed-on: https://review.haiku-os.org/c/haiku/+/180 Reviewed-by: waddlesplash --- docs/user/interface/View.dox | 27 +++++++ headers/os/interface/View.h | 28 ++++--- .../devices/mouse/MouseInputDevice.cpp | 5 +- src/preferences/input/InputMouse.cpp | 17 +--- src/preferences/input/InputWindow.cpp | 3 +- src/preferences/input/MouseView.cpp | 81 ++++++++++--------- src/preferences/input/SettingsView.cpp | 35 +++----- src/preferences/input/SettingsView.h | 36 +++++---- 8 files changed, 122 insertions(+), 110 deletions(-) diff --git a/docs/user/interface/View.dox b/docs/user/interface/View.dox index 70af89ecde..d664253182 100644 --- a/docs/user/interface/View.dox +++ b/docs/user/interface/View.dox @@ -29,6 +29,11 @@ \var B_PRIMARY_MOUSE_BUTTON \brief Primary mouse button mask parameter. + The primary mouse button should be used for main operations (selecting, + dragging, or opening objects). + + This maps to B_MOUSE_BUTTON(1). + \since BeOS R3 */ @@ -37,6 +42,11 @@ \var B_SECONDARY_MOUSE_BUTTON \brief Secondary mouse button mask parameter. + The secondary button should be used for additional operations on the + pointed objects, such as popup menus. + + This maps to B_MOUSE_BUTTON(2). + \since BeOS R3 */ @@ -45,10 +55,27 @@ \var B_TERTIARY_MOUSE_BUTTON \brief Tertiary mouse button mask parameter. + The tertiary button should be used for clipboard paste. + + This maps to B_MOUSE_BUTTON(3). + \since BeOS R3 */ +/*! + \var B_MOUSE_BUTTON(n) + \brief Compute mouse button mask for button n + + Buttons are numbered from 1 to 32. + + Some mice may not have more than 2 buttons, so the extra buttons should + only be used as shortcuts for actions that can be done in alternative ways. + + \since Haiku R1 +*/ + + // mouse transit diff --git a/headers/os/interface/View.h b/headers/os/interface/View.h index d4523e5bbe..70827764d2 100644 --- a/headers/os/interface/View.h +++ b/headers/os/interface/View.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2019 Haiku, Inc. All rights reserved. + * Copyright 2001-2020 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _VIEW_H @@ -16,10 +16,13 @@ // mouse button +#define B_MOUSE_BUTTON(n) (1 << ((n) - 1)) + +// Legacy BeOS R5 mouse button definitions enum { - B_PRIMARY_MOUSE_BUTTON = 0x01, - B_SECONDARY_MOUSE_BUTTON = 0x02, - B_TERTIARY_MOUSE_BUTTON = 0x04 + B_PRIMARY_MOUSE_BUTTON = B_MOUSE_BUTTON(1), + B_SECONDARY_MOUSE_BUTTON = B_MOUSE_BUTTON(2), + B_TERTIARY_MOUSE_BUTTON = B_MOUSE_BUTTON(3) }; // mouse transit @@ -41,10 +44,11 @@ enum { B_LOCK_WINDOW_FOCUS = 0x00000001, B_SUSPEND_VIEW_FOCUS = 0x00000002, B_NO_POINTER_HISTORY = 0x00000004, - // NOTE: New in Haiku (unless this flag is - // specified, both BWindow and BView::GetMouse() - // will filter out older mouse moved messages) + // NOTE: This is the default behavior in Haiku, unlike in BeOS B_FULL_POINTER_HISTORY = 0x00000008 + // NOTE: New in Haiku (unless this flag is + // specified, both BWindow and BView::GetMouse() + // will filter out older mouse moved messages) }; enum { @@ -76,11 +80,11 @@ const uint32 B_FRAME_EVENTS = 0x04000000UL; /* 26 */ const uint32 B_NAVIGABLE = 0x02000000UL; /* 25 */ const uint32 B_SUBPIXEL_PRECISE = 0x01000000UL; /* 24 */ const uint32 B_DRAW_ON_CHILDREN = 0x00800000UL; /* 23 */ -const uint32 B_INPUT_METHOD_AWARE = 0x00400000UL; /* 23 */ -const uint32 B_SCROLL_VIEW_AWARE = 0x00200000UL; /* 22 */ -const uint32 B_SUPPORTS_LAYOUT = 0x00100000UL; /* 21 */ -const uint32 B_INVALIDATE_AFTER_LAYOUT = 0x00080000UL; /* 20 */ -const uint32 B_TRANSPARENT_BACKGROUND = 0x00040000UL; /* 19 */ +const uint32 B_INPUT_METHOD_AWARE = 0x00400000UL; /* 22 */ +const uint32 B_SCROLL_VIEW_AWARE = 0x00200000UL; /* 21 */ +const uint32 B_SUPPORTS_LAYOUT = 0x00100000UL; /* 20 */ +const uint32 B_INVALIDATE_AFTER_LAYOUT = 0x00080000UL; /* 19 */ +const uint32 B_TRANSPARENT_BACKGROUND = 0x00040000UL; /* 18 */ #define _RESIZE_MASK_ (0xffff) diff --git a/src/add-ons/input_server/devices/mouse/MouseInputDevice.cpp b/src/add-ons/input_server/devices/mouse/MouseInputDevice.cpp index 76ef0a41ef..1aea626bd8 100644 --- a/src/add-ons/input_server/devices/mouse/MouseInputDevice.cpp +++ b/src/add-ons/input_server/devices/mouse/MouseInputDevice.cpp @@ -183,9 +183,8 @@ MouseDevice::MouseDevice(MouseInputDevice& target, const char* driverPath) fDeviceRef.cookie = this; #ifdef HAIKU_TARGET_PLATFORM_HAIKU - 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); #endif }; diff --git a/src/preferences/input/InputMouse.cpp b/src/preferences/input/InputMouse.cpp index f38da8f735..ac9583a7c5 100644 --- a/src/preferences/input/InputMouse.cpp +++ b/src/preferences/input/InputMouse.cpp @@ -97,8 +97,8 @@ InputMouse::MessageReceived(BMessage* message) case kMsgMouseType: { int32 type; - if (message->FindInt32("index", &type) == B_OK) { - fSettings.SetMouseType(++type); + if (message->FindInt32("be:value", &type) == B_OK) { + fSettings.SetMouseType(type); fSettingsView->SetMouseType(type); fDefaultsButton->SetEnabled(fSettings.IsDefaultable()); fRevertButton->SetEnabled(fSettings.IsRevertable()); @@ -196,16 +196,7 @@ InputMouse::MessageReceived(BMessage* message) int32 button; if (message->FindInt32("index", &index) == B_OK && message->FindInt32("button", &button) == B_OK) { - int32 mapping = B_PRIMARY_MOUSE_BUTTON; - switch (index) { - case 1: - mapping = B_SECONDARY_MOUSE_BUTTON; - break; - case 2: - mapping = B_TERTIARY_MOUSE_BUTTON; - break; - } - + int32 mapping = B_MOUSE_BUTTON(index + 1); fSettings.SetMapping(button, mapping); fDefaultsButton->SetEnabled(fSettings.IsDefaultable()); fRevertButton->SetEnabled(fSettings.IsRevertable()); @@ -214,4 +205,4 @@ InputMouse::MessageReceived(BMessage* message) break; } } -} \ No newline at end of file +} diff --git a/src/preferences/input/InputWindow.cpp b/src/preferences/input/InputWindow.cpp index 3757fbf914..425f7d0e57 100644 --- a/src/preferences/input/InputWindow.cpp +++ b/src/preferences/input/InputWindow.cpp @@ -134,8 +134,7 @@ InputWindow::Show() { CenterOnScreen(); BWindow::Show(); - status_t x = watch_input_devices(this, true); - puts(strerror(x)); + watch_input_devices(this, true); } diff --git a/src/preferences/input/MouseView.cpp b/src/preferences/input/MouseView.cpp index 3f2ba55f56..38a53a29d5 100644 --- a/src/preferences/input/MouseView.cpp +++ b/src/preferences/input/MouseView.cpp @@ -35,12 +35,15 @@ static const int32 kButtonTop = 3; static const int32 kMouseDownWidth = 72; static const int32 kMouseDownHeight = 35; -static const int32 kOneButtonOffsets[4] - = { 0, kMouseDownWidth }; -static const int32 kTwoButtonOffsets[4] - = { 0, kMouseDownWidth / 2, kMouseDownWidth }; -static const int32 kThreeButtonOffsets[4] - = { 0, kMouseDownWidth / 3 + 1, kMouseDownWidth / 3 * 2, kMouseDownWidth }; +#define W kMouseDownWidth / 100 +static const int32 kButtonOffsets[][6] = { + { 0, 100 * W }, + { 0, 50 * W, 100 * W }, + { 0, 35 * W, 65 * W, 100 * W }, + { 0, 27 * W, 54 * W, 81 * W, 100 * W }, + { 0, 23 * W, 46 * W, 69 * W, 84 * W, 100 * W } +}; +#undef W static const rgb_color kButtonTextColor = { 0, 0, 0, 255 }; static const rgb_color kMouseShadowColor = { 100, 100, 100, 128 }; @@ -54,30 +57,23 @@ static const rgb_color kButtonPressedColor = { 110, 110, 110, 110 }; static const int32* getButtonOffsets(int32 type) { - switch (type) { - case 1: - return kOneButtonOffsets; - case 2: - return kTwoButtonOffsets; - case 3: - default: - return kThreeButtonOffsets; - } + if ((type - 1) >= (int32)B_COUNT_OF(kButtonOffsets)) + return kButtonOffsets[2]; + return kButtonOffsets[type - 1]; } static uint32 getMappingNumber(int32 mapping) { - switch (mapping) { - case B_PRIMARY_MOUSE_BUTTON: - return 0; - case B_SECONDARY_MOUSE_BUTTON: - return 1; - case B_TERTIARY_MOUSE_BUTTON: - return 2; - } - return 0; + if (mapping == 0) + return 0; + + int i; + for (i = 0; mapping != 1; i++) + mapping >>= 1; + + return i; } MouseView::MouseView(const MouseSettings &settings) @@ -89,7 +85,7 @@ MouseView::MouseView(const MouseSettings &settings) fOldButtons(0) { SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); - fScaling = std::max(1.0f, be_plain_font->Size() / 12.0f); + fScaling = std::max(1.0f, be_plain_font->Size() / 7.0f); } @@ -195,9 +191,11 @@ MouseView::MouseDown(BPoint where) BMessage message(kMsgMouseMap); message.AddInt32("button", button); - menu.AddItem(new BMenuItem("1", new BMessage(message))); - menu.AddItem(new BMenuItem("2", new BMessage(message))); - menu.AddItem(new BMenuItem("3", new BMessage(message))); + for (int i = 1; i < 6; i++) { + char tmp[2]; + sprintf(tmp, "%d", i); + menu.AddItem(new BMenuItem(tmp, new BMessage(message))); + } menu.ItemAt(getMappingNumber(fSettings.Mapping(button))) ->SetMarked(true); @@ -261,6 +259,15 @@ MouseView::Draw(BRect updateFrame) SetScale(1); SetOrigin(0, 0); + mouse_map map; + fSettings.Mapping(map); + + SetDrawingMode(B_OP_OVER); + + // All button drawing is clipped to the outline of the buttons area, + // simplifying the code below as it can overdraw things. + ClipToPicture(&fButtonsPicture, B_ORIGIN, false); + // Separator between the buttons const int32* offset = getButtonOffsets(fType); for (int32 i = 1; i < fType; i++) { @@ -268,14 +275,6 @@ MouseView::Draw(BRect updateFrame) StrokeLine(buttonRect.LeftTop(), buttonRect.LeftBottom()); } - mouse_map map; - fSettings.Mapping(map); - - SetDrawingMode(B_OP_OVER); - - if (fButtons != 0) - ClipToPicture(&fButtonsPicture, B_ORIGIN, false); - for (int32 i = 0; i < fType; i++) { // draw mapping number centered over the button @@ -307,8 +306,7 @@ MouseView::Draw(BRect updateFrame) + (border.IntegerHeight() - fDigitHeight) / 2)); } - if (fButtons != 0) - ClipToPicture(NULL); + ClipToPicture(NULL); } @@ -329,6 +327,8 @@ MouseView::_ButtonRect(const int32* offsets, int index) const } +/** The buttons on a mouse are normally 1 (left), 2 (right), 3 (middle) so + * we need to reorder them */ int32 MouseView::_ConvertFromVisualOrder(int32 i) { @@ -337,12 +337,13 @@ MouseView::_ConvertFromVisualOrder(int32 i) switch (i) { case 0: - default: return 0; case 1: return 2; case 2: return 1; + default: + return i; } } @@ -376,4 +377,4 @@ MouseView::_CreateButtonsPicture() EndPicture(); SetScale(1); -} \ No newline at end of file +} diff --git a/src/preferences/input/SettingsView.cpp b/src/preferences/input/SettingsView.cpp index f0cc6ab84a..c5ec4ef807 100644 --- a/src/preferences/input/SettingsView.cpp +++ b/src/preferences/input/SettingsView.cpp @@ -72,17 +72,13 @@ SettingsView::SettingsView(MouseSettings& settings) fSettings(settings) { // Add the "Mouse Type" pop up menu - fTypeMenu = new BPopUpMenu("unknown"); - fTypeMenu->AddItem(new BMenuItem(B_TRANSLATE("1-Button"), - new BMessage(kMsgMouseType))); - fTypeMenu->AddItem(new BMenuItem(B_TRANSLATE("2-Button"), - new BMessage(kMsgMouseType))); - fTypeMenu->AddItem(new BMenuItem(B_TRANSLATE("3-Button"), - new BMessage(kMsgMouseType))); - - BMenuField* typeField = new BMenuField(B_TRANSLATE("Mouse type:"), - fTypeMenu); - typeField->SetAlignment(B_ALIGN_LEFT); + fTypeMenu = new BOptionPopUp("type", B_TRANSLATE("Mouse type:"), + new BMessage(kMsgMouseType)); + fTypeMenu->AddOption(B_TRANSLATE("1-Button"), 1); + fTypeMenu->AddOption(B_TRANSLATE("2-Button"), 2); + fTypeMenu->AddOption(B_TRANSLATE("3-Button"), 3); + fTypeMenu->AddOption(B_TRANSLATE("4-Button"), 4); + fTypeMenu->AddOption(B_TRANSLATE("5-Button"), 5); // Create the "Double-click speed slider... fClickSpeedSlider = new BSlider("double_click_speed", @@ -174,12 +170,7 @@ SettingsView::SettingsView(MouseSettings& settings) // Vertical block A: mouse type/view/test .AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING) - .AddGroup(B_HORIZONTAL, 0) - .AddGlue() - .Add(typeField) - .AddGlue() - .End() - .AddGlue() + .Add(fTypeMenu) .AddGroup(B_HORIZONTAL, 0) .AddGlue() .Add(fMouseView) @@ -260,13 +251,11 @@ SettingsView::UpdateFromSettings() // slow = 0, fast = 262144 fAccelerationSlider->SetValue(value); - BMenuItem* item = fTypeMenu->ItemAt(fSettings.MouseType() - 1); - if (item != NULL) - item->SetMarked(true); - + fTypeMenu->SelectOptionFor(fSettings.MouseType()); fMouseView->SetMouseType(fSettings.MouseType()); - item = fFocusMenu->ItemAt(mouse_mode_to_index(fSettings.MouseMode())); + BMenuItem* item = fFocusMenu->ItemAt( + mouse_mode_to_index(fSettings.MouseMode())); if (item != NULL) item->SetMarked(true); @@ -282,4 +271,4 @@ SettingsView::UpdateFromSettings() ? B_CONTROL_ON : B_CONTROL_OFF); fAcceptFirstClickBox->SetEnabled(fSettings.MouseMode() != B_FOCUS_FOLLOWS_MOUSE); -} \ No newline at end of file +} diff --git a/src/preferences/input/SettingsView.h b/src/preferences/input/SettingsView.h index 29b2e940f5..1c5115aa08 100644 --- a/src/preferences/input/SettingsView.h +++ b/src/preferences/input/SettingsView.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -25,30 +26,31 @@ class MouseView; class SettingsView : public BBox { public: - SettingsView(MouseSettings &settings); - virtual ~SettingsView(); + SettingsView(MouseSettings &settings); + virtual ~SettingsView(); - virtual void AttachedToWindow(); + virtual void AttachedToWindow(); - void SetMouseType(int32 type); - void MouseMapUpdated(); - void UpdateFromSettings(); + void SetMouseType(int32 type); + void MouseMapUpdated(); + void UpdateFromSettings(); - BPopUpMenu* fFocusFollowsMouseMenu; - BCheckBox* fAcceptFirstClickBox; + public: + // FIXME use proper getters/setters for this? + BPopUpMenu* fFocusFollowsMouseMenu; + BCheckBox* fAcceptFirstClickBox; private: + typedef BBox inherited; - typedef BBox inherited; + const MouseSettings& fSettings; - const MouseSettings &fSettings; - - BPopUpMenu* fTypeMenu; - BPopUpMenu* fFocusMenu; - MouseView* fMouseView; - BSlider* fClickSpeedSlider; - BSlider* fMouseSpeedSlider; - BSlider* fAccelerationSlider; + BOptionPopUp* fTypeMenu; + BPopUpMenu* fFocusMenu; + MouseView* fMouseView; + BSlider* fClickSpeedSlider; + BSlider* fMouseSpeedSlider; + BSlider* fAccelerationSlider; }; #endif /* SETTINGS_VIEW_H */