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 <[email protected]>
This commit is contained in:
Adrien Destugues
2020-04-18 18:20:37 +00:00
committed by waddlesplash
parent 6ae1da352b
commit 5bbf7f1be0
8 changed files with 122 additions and 110 deletions
+27
View File
@@ -29,6 +29,11 @@
\var B_PRIMARY_MOUSE_BUTTON \var B_PRIMARY_MOUSE_BUTTON
\brief Primary mouse button mask parameter. \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 \since BeOS R3
*/ */
@@ -37,6 +42,11 @@
\var B_SECONDARY_MOUSE_BUTTON \var B_SECONDARY_MOUSE_BUTTON
\brief Secondary mouse button mask parameter. \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 \since BeOS R3
*/ */
@@ -45,10 +55,27 @@
\var B_TERTIARY_MOUSE_BUTTON \var B_TERTIARY_MOUSE_BUTTON
\brief Tertiary mouse button mask parameter. \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 \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 // mouse transit
+16 -12
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _VIEW_H #ifndef _VIEW_H
@@ -16,10 +16,13 @@
// mouse button // mouse button
#define B_MOUSE_BUTTON(n) (1 << ((n) - 1))
// Legacy BeOS R5 mouse button definitions
enum { enum {
B_PRIMARY_MOUSE_BUTTON = 0x01, B_PRIMARY_MOUSE_BUTTON = B_MOUSE_BUTTON(1),
B_SECONDARY_MOUSE_BUTTON = 0x02, B_SECONDARY_MOUSE_BUTTON = B_MOUSE_BUTTON(2),
B_TERTIARY_MOUSE_BUTTON = 0x04 B_TERTIARY_MOUSE_BUTTON = B_MOUSE_BUTTON(3)
}; };
// mouse transit // mouse transit
@@ -41,10 +44,11 @@ enum {
B_LOCK_WINDOW_FOCUS = 0x00000001, B_LOCK_WINDOW_FOCUS = 0x00000001,
B_SUSPEND_VIEW_FOCUS = 0x00000002, B_SUSPEND_VIEW_FOCUS = 0x00000002,
B_NO_POINTER_HISTORY = 0x00000004, B_NO_POINTER_HISTORY = 0x00000004,
// NOTE: New in Haiku (unless this flag is // NOTE: This is the default behavior in Haiku, unlike in BeOS
// specified, both BWindow and BView::GetMouse()
// will filter out older mouse moved messages)
B_FULL_POINTER_HISTORY = 0x00000008 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 { enum {
@@ -76,11 +80,11 @@ const uint32 B_FRAME_EVENTS = 0x04000000UL; /* 26 */
const uint32 B_NAVIGABLE = 0x02000000UL; /* 25 */ const uint32 B_NAVIGABLE = 0x02000000UL; /* 25 */
const uint32 B_SUBPIXEL_PRECISE = 0x01000000UL; /* 24 */ const uint32 B_SUBPIXEL_PRECISE = 0x01000000UL; /* 24 */
const uint32 B_DRAW_ON_CHILDREN = 0x00800000UL; /* 23 */ const uint32 B_DRAW_ON_CHILDREN = 0x00800000UL; /* 23 */
const uint32 B_INPUT_METHOD_AWARE = 0x00400000UL; /* 23 */ const uint32 B_INPUT_METHOD_AWARE = 0x00400000UL; /* 22 */
const uint32 B_SCROLL_VIEW_AWARE = 0x00200000UL; /* 22 */ const uint32 B_SCROLL_VIEW_AWARE = 0x00200000UL; /* 21 */
const uint32 B_SUPPORTS_LAYOUT = 0x00100000UL; /* 21 */ const uint32 B_SUPPORTS_LAYOUT = 0x00100000UL; /* 20 */
const uint32 B_INVALIDATE_AFTER_LAYOUT = 0x00080000UL; /* 20 */ const uint32 B_INVALIDATE_AFTER_LAYOUT = 0x00080000UL; /* 19 */
const uint32 B_TRANSPARENT_BACKGROUND = 0x00040000UL; /* 19 */ const uint32 B_TRANSPARENT_BACKGROUND = 0x00040000UL; /* 18 */
#define _RESIZE_MASK_ (0xffff) #define _RESIZE_MASK_ (0xffff)
@@ -183,9 +183,8 @@ MouseDevice::MouseDevice(MouseInputDevice& target, const char* driverPath)
fDeviceRef.cookie = this; fDeviceRef.cookie = this;
#ifdef HAIKU_TARGET_PLATFORM_HAIKU #ifdef HAIKU_TARGET_PLATFORM_HAIKU
fSettings.map.button[0] = B_PRIMARY_MOUSE_BUTTON; for (int i = 0; i < B_MAX_MOUSE_BUTTONS; i++)
fSettings.map.button[1] = B_SECONDARY_MOUSE_BUTTON; fSettings.map.button[i] = B_MOUSE_BUTTON(i + 1);
fSettings.map.button[2] = B_TERTIARY_MOUSE_BUTTON;
#endif #endif
}; };
+4 -13
View File
@@ -97,8 +97,8 @@ InputMouse::MessageReceived(BMessage* message)
case kMsgMouseType: case kMsgMouseType:
{ {
int32 type; int32 type;
if (message->FindInt32("index", &type) == B_OK) { if (message->FindInt32("be:value", &type) == B_OK) {
fSettings.SetMouseType(++type); fSettings.SetMouseType(type);
fSettingsView->SetMouseType(type); fSettingsView->SetMouseType(type);
fDefaultsButton->SetEnabled(fSettings.IsDefaultable()); fDefaultsButton->SetEnabled(fSettings.IsDefaultable());
fRevertButton->SetEnabled(fSettings.IsRevertable()); fRevertButton->SetEnabled(fSettings.IsRevertable());
@@ -196,16 +196,7 @@ InputMouse::MessageReceived(BMessage* message)
int32 button; int32 button;
if (message->FindInt32("index", &index) == B_OK if (message->FindInt32("index", &index) == B_OK
&& message->FindInt32("button", &button) == B_OK) { && message->FindInt32("button", &button) == B_OK) {
int32 mapping = B_PRIMARY_MOUSE_BUTTON; int32 mapping = B_MOUSE_BUTTON(index + 1);
switch (index) {
case 1:
mapping = B_SECONDARY_MOUSE_BUTTON;
break;
case 2:
mapping = B_TERTIARY_MOUSE_BUTTON;
break;
}
fSettings.SetMapping(button, mapping); fSettings.SetMapping(button, mapping);
fDefaultsButton->SetEnabled(fSettings.IsDefaultable()); fDefaultsButton->SetEnabled(fSettings.IsDefaultable());
fRevertButton->SetEnabled(fSettings.IsRevertable()); fRevertButton->SetEnabled(fSettings.IsRevertable());
@@ -214,4 +205,4 @@ InputMouse::MessageReceived(BMessage* message)
break; break;
} }
} }
} }
+1 -2
View File
@@ -134,8 +134,7 @@ InputWindow::Show()
{ {
CenterOnScreen(); CenterOnScreen();
BWindow::Show(); BWindow::Show();
status_t x = watch_input_devices(this, true); watch_input_devices(this, true);
puts(strerror(x));
} }
+41 -40
View File
@@ -35,12 +35,15 @@ static const int32 kButtonTop = 3;
static const int32 kMouseDownWidth = 72; static const int32 kMouseDownWidth = 72;
static const int32 kMouseDownHeight = 35; static const int32 kMouseDownHeight = 35;
static const int32 kOneButtonOffsets[4] #define W kMouseDownWidth / 100
= { 0, kMouseDownWidth }; static const int32 kButtonOffsets[][6] = {
static const int32 kTwoButtonOffsets[4] { 0, 100 * W },
= { 0, kMouseDownWidth / 2, kMouseDownWidth }; { 0, 50 * W, 100 * W },
static const int32 kThreeButtonOffsets[4] { 0, 35 * W, 65 * W, 100 * W },
= { 0, kMouseDownWidth / 3 + 1, kMouseDownWidth / 3 * 2, kMouseDownWidth }; { 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 kButtonTextColor = { 0, 0, 0, 255 };
static const rgb_color kMouseShadowColor = { 100, 100, 100, 128 }; 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* static const int32*
getButtonOffsets(int32 type) getButtonOffsets(int32 type)
{ {
switch (type) { if ((type - 1) >= (int32)B_COUNT_OF(kButtonOffsets))
case 1: return kButtonOffsets[2];
return kOneButtonOffsets; return kButtonOffsets[type - 1];
case 2:
return kTwoButtonOffsets;
case 3:
default:
return kThreeButtonOffsets;
}
} }
static uint32 static uint32
getMappingNumber(int32 mapping) getMappingNumber(int32 mapping)
{ {
switch (mapping) { if (mapping == 0)
case B_PRIMARY_MOUSE_BUTTON: return 0;
return 0;
case B_SECONDARY_MOUSE_BUTTON: int i;
return 1; for (i = 0; mapping != 1; i++)
case B_TERTIARY_MOUSE_BUTTON: mapping >>= 1;
return 2;
} return i;
return 0;
} }
MouseView::MouseView(const MouseSettings &settings) MouseView::MouseView(const MouseSettings &settings)
@@ -89,7 +85,7 @@ MouseView::MouseView(const MouseSettings &settings)
fOldButtons(0) fOldButtons(0)
{ {
SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); 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); BMessage message(kMsgMouseMap);
message.AddInt32("button", button); message.AddInt32("button", button);
menu.AddItem(new BMenuItem("1", new BMessage(message))); for (int i = 1; i < 6; i++) {
menu.AddItem(new BMenuItem("2", new BMessage(message))); char tmp[2];
menu.AddItem(new BMenuItem("3", new BMessage(message))); sprintf(tmp, "%d", i);
menu.AddItem(new BMenuItem(tmp, new BMessage(message)));
}
menu.ItemAt(getMappingNumber(fSettings.Mapping(button))) menu.ItemAt(getMappingNumber(fSettings.Mapping(button)))
->SetMarked(true); ->SetMarked(true);
@@ -261,6 +259,15 @@ MouseView::Draw(BRect updateFrame)
SetScale(1); SetScale(1);
SetOrigin(0, 0); 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 // Separator between the buttons
const int32* offset = getButtonOffsets(fType); const int32* offset = getButtonOffsets(fType);
for (int32 i = 1; i < fType; i++) { for (int32 i = 1; i < fType; i++) {
@@ -268,14 +275,6 @@ MouseView::Draw(BRect updateFrame)
StrokeLine(buttonRect.LeftTop(), buttonRect.LeftBottom()); 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++) { for (int32 i = 0; i < fType; i++) {
// draw mapping number centered over the button // draw mapping number centered over the button
@@ -307,8 +306,7 @@ MouseView::Draw(BRect updateFrame)
+ (border.IntegerHeight() - fDigitHeight) / 2)); + (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 int32
MouseView::_ConvertFromVisualOrder(int32 i) MouseView::_ConvertFromVisualOrder(int32 i)
{ {
@@ -337,12 +337,13 @@ MouseView::_ConvertFromVisualOrder(int32 i)
switch (i) { switch (i) {
case 0: case 0:
default:
return 0; return 0;
case 1: case 1:
return 2; return 2;
case 2: case 2:
return 1; return 1;
default:
return i;
} }
} }
@@ -376,4 +377,4 @@ MouseView::_CreateButtonsPicture()
EndPicture(); EndPicture();
SetScale(1); SetScale(1);
} }
+12 -23
View File
@@ -72,17 +72,13 @@ SettingsView::SettingsView(MouseSettings& settings)
fSettings(settings) fSettings(settings)
{ {
// Add the "Mouse Type" pop up menu // Add the "Mouse Type" pop up menu
fTypeMenu = new BPopUpMenu("unknown"); fTypeMenu = new BOptionPopUp("type", B_TRANSLATE("Mouse type:"),
fTypeMenu->AddItem(new BMenuItem(B_TRANSLATE("1-Button"), new BMessage(kMsgMouseType));
new BMessage(kMsgMouseType))); fTypeMenu->AddOption(B_TRANSLATE("1-Button"), 1);
fTypeMenu->AddItem(new BMenuItem(B_TRANSLATE("2-Button"), fTypeMenu->AddOption(B_TRANSLATE("2-Button"), 2);
new BMessage(kMsgMouseType))); fTypeMenu->AddOption(B_TRANSLATE("3-Button"), 3);
fTypeMenu->AddItem(new BMenuItem(B_TRANSLATE("3-Button"), fTypeMenu->AddOption(B_TRANSLATE("4-Button"), 4);
new BMessage(kMsgMouseType))); fTypeMenu->AddOption(B_TRANSLATE("5-Button"), 5);
BMenuField* typeField = new BMenuField(B_TRANSLATE("Mouse type:"),
fTypeMenu);
typeField->SetAlignment(B_ALIGN_LEFT);
// Create the "Double-click speed slider... // Create the "Double-click speed slider...
fClickSpeedSlider = new BSlider("double_click_speed", fClickSpeedSlider = new BSlider("double_click_speed",
@@ -174,12 +170,7 @@ SettingsView::SettingsView(MouseSettings& settings)
// Vertical block A: mouse type/view/test // Vertical block A: mouse type/view/test
.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING) .AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
.AddGroup(B_HORIZONTAL, 0) .Add(fTypeMenu)
.AddGlue()
.Add(typeField)
.AddGlue()
.End()
.AddGlue()
.AddGroup(B_HORIZONTAL, 0) .AddGroup(B_HORIZONTAL, 0)
.AddGlue() .AddGlue()
.Add(fMouseView) .Add(fMouseView)
@@ -260,13 +251,11 @@ SettingsView::UpdateFromSettings()
// slow = 0, fast = 262144 // slow = 0, fast = 262144
fAccelerationSlider->SetValue(value); fAccelerationSlider->SetValue(value);
BMenuItem* item = fTypeMenu->ItemAt(fSettings.MouseType() - 1); fTypeMenu->SelectOptionFor(fSettings.MouseType());
if (item != NULL)
item->SetMarked(true);
fMouseView->SetMouseType(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) if (item != NULL)
item->SetMarked(true); item->SetMarked(true);
@@ -282,4 +271,4 @@ SettingsView::UpdateFromSettings()
? B_CONTROL_ON : B_CONTROL_OFF); ? B_CONTROL_ON : B_CONTROL_OFF);
fAcceptFirstClickBox->SetEnabled(fSettings.MouseMode() fAcceptFirstClickBox->SetEnabled(fSettings.MouseMode()
!= B_FOCUS_FOLLOWS_MOUSE); != B_FOCUS_FOLLOWS_MOUSE);
} }
+19 -17
View File
@@ -15,6 +15,7 @@
#include <Bitmap.h> #include <Bitmap.h>
#include <Button.h> #include <Button.h>
#include <CheckBox.h> #include <CheckBox.h>
#include <OptionPopUp.h>
#include <PopUpMenu.h> #include <PopUpMenu.h>
#include <Slider.h> #include <Slider.h>
@@ -25,30 +26,31 @@ class MouseView;
class SettingsView : public BBox { class SettingsView : public BBox {
public: public:
SettingsView(MouseSettings &settings); SettingsView(MouseSettings &settings);
virtual ~SettingsView(); virtual ~SettingsView();
virtual void AttachedToWindow(); virtual void AttachedToWindow();
void SetMouseType(int32 type); void SetMouseType(int32 type);
void MouseMapUpdated(); void MouseMapUpdated();
void UpdateFromSettings(); void UpdateFromSettings();
BPopUpMenu* fFocusFollowsMouseMenu; public:
BCheckBox* fAcceptFirstClickBox; // FIXME use proper getters/setters for this?
BPopUpMenu* fFocusFollowsMouseMenu;
BCheckBox* fAcceptFirstClickBox;
private: private:
typedef BBox inherited;
typedef BBox inherited; const MouseSettings& fSettings;
const MouseSettings &fSettings; BOptionPopUp* fTypeMenu;
BPopUpMenu* fFocusMenu;
BPopUpMenu* fTypeMenu; MouseView* fMouseView;
BPopUpMenu* fFocusMenu; BSlider* fClickSpeedSlider;
MouseView* fMouseView; BSlider* fMouseSpeedSlider;
BSlider* fClickSpeedSlider; BSlider* fAccelerationSlider;
BSlider* fMouseSpeedSlider;
BSlider* fAccelerationSlider;
}; };
#endif /* SETTINGS_VIEW_H */ #endif /* SETTINGS_VIEW_H */