input: Implement click finger behaviour (enabled by default)

input touchpad settings header:
- click finger behaviour (enabled by default)
- Emulation of different button clicks depending on the
  number of fingers that are pressed at the same time on
  any location of the touchable surface of the device.
    - Clicking with 1 finger triggers a primary button click,
      usually left button click.
    - Clicking with 2 fingers triggers a secondary button click,
      usually right button click.
    - Clicking with 3 fingers triggers a terciary button click,
      usually middle button click.

  This feature is useful for clickpads that are input devices
  lacking a separated set of buttons from the touch area.

input preflet:
- Implement clickfinger

input mouse:
- Handle and provide new settings for clickfinger behaviour

input mouse mm:
- Implement clickfinger in the user space
- Enables button emulation based on the number of fingers pressing
  at the same time the touch surface.

  Userful feature for clickpads.

Change-Id: Ibaa06df3887793158093cc08f6281fc080e85c3b
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9923
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Samuel Rodríguez Pérez
2026-01-02 11:01:29 +00:00
committed by Adrien Destugues
parent f44235f7e5
commit a3f6c4d484
7 changed files with 52 additions and 2 deletions
@@ -34,6 +34,10 @@ typedef struct {
// 0x04: edge motion on button click move
// 0x08: edge motion on button click drag
bool finger_click; // 1 finger click -> click button id 1
// 2 fingers' click -> click button id 2
// 3 fingers' click -> click button id 3
bool software_button_areas;
} touchpad_settings;
@@ -53,6 +57,7 @@ const static touchpad_settings kDefaultTouchpadSettings = {
false,
true,
0x02,
true,
false
};
@@ -608,6 +608,8 @@ MouseDevice::_UpdateTouchpadSettings(BMessage* message)
&settings.scroll_twofinger_natural_scrolling);
message->FindInt8("edge_motion",
(int8*)&settings.edge_motion);
message->FindBool("finger_click",
&settings.finger_click);
message->FindBool("software_button_areas",
&settings.software_button_areas);
@@ -353,7 +353,8 @@ TouchpadMovement::EventToMovement(const touchpad_movement* _event, mouse_movemen
movement->timestamp = system_time();
touchpad_movement event2 = *_event;
_SoftwareButtonAreas(&event2);
if (!_ClickFingerButtonEmulator(&event2))
_SoftwareButtonAreas(&event2);
const touchpad_movement* event = &event2;
if ((movement->timestamp - fTapTime) > fTapTimeOUT) {
@@ -398,6 +399,27 @@ TouchpadMovement::EventToMovement(const touchpad_movement* _event, mouse_movemen
}
bool
TouchpadMovement::_ClickFingerButtonEmulator(touchpad_movement *event) {
CALLED();
if (event->buttons != 0) {
// ClickFinger behaviour.
// Simulate with 2 fingers click => right button click
// Simulate with 3 fingers click => middle button click
if (fSettings.finger_click && two_fingers(event)) {
event->buttons = 2;
return true;
} else if (fSettings.finger_click && three_fingers(event)) {
event->buttons = 4;
return true;
}
}
return false;
}
void
TouchpadMovement::_SoftwareButtonAreas(touchpad_movement *event) {
CALLED();
@@ -76,6 +76,7 @@ private:
void _UpdateButtons(mouse_movement *movement);
bool _EdgeMotion(const touchpad_movement *event,
mouse_movement *movement, bool validStart);
inline bool _ClickFingerButtonEmulator(touchpad_movement *event);
inline void _SoftwareButtonAreas(touchpad_movement *event);
inline void _NoTouchToMovement(const touchpad_movement *event,
mouse_movement *movement);
@@ -72,6 +72,7 @@ TouchpadPref::BuildSettingsMessage()
msg.AddInt32("trackpad_acceleration", fSettings.trackpad_acceleration);
msg.AddBool("scroll_twofinger_natural_scrolling", fSettings.scroll_twofinger_natural_scrolling);
msg.AddInt8("edge_motion", fSettings.edge_motion);
msg.AddBool("finger_click", fSettings.finger_click);
msg.AddBool("software_button_areas", fSettings.software_button_areas);
return msg;
@@ -161,6 +162,9 @@ TouchpadPref::LoadSettings()
fSettings.edge_motion = settingsMsg.GetInt8(
"edge_motion",
kDefaultTouchpadSettings.edge_motion);
fSettings.finger_click = settingsMsg.GetBool(
"finger_click",
kDefaultTouchpadSettings.finger_click);
fSettings.software_button_areas = settingsMsg.GetBool(
"software_button_areas",
kDefaultTouchpadSettings.software_button_areas);
@@ -315,6 +315,12 @@ TouchpadPrefView::MessageReceived(BMessage* message)
fTouchpadPref.UpdateRunningSettings();
break;
case FINGER_CLICK_CHANGED:
settings.finger_click = fFingerClickBox->Value() == B_CONTROL_ON;
fRevertButton->SetEnabled(true);
fTouchpadPref.UpdateRunningSettings();
break;
case SOFTWARE_BUTTON_AREAS_CHANGED:
settings.software_button_areas = fSoftwareButtonAreasBox->Value() == B_CONTROL_ON;
fRevertButton->SetEnabled(true);
@@ -382,6 +388,7 @@ TouchpadPrefView::AttachedToWindow()
fScrollAccelSlider->SetTarget(this);
fEdgeMotionOptionPopUp->SetTarget(this);
fFingerClickBox->SetTarget(this);
fSoftwareButtonAreasBox->SetTarget(this);
fPadBlockerSlider->SetTarget(this);
@@ -479,6 +486,8 @@ TouchpadPrefView::SetupView()
B_EDGE_MOTION_ON_MOVE | B_EDGE_MOTION_ON_TAP_DRAG
| B_EDGE_MOTION_ON_BUTTON_CLICK_MOVE | B_EDGE_MOTION_ON_BUTTON_CLICK_DRAG);
fFingerClickBox = new BCheckBox(B_TRANSLATE("Finger click"),
new BMessage(FINGER_CLICK_CHANGED));
fSoftwareButtonAreasBox = new BCheckBox(B_TRANSLATE("Software button areas"),
new BMessage(SOFTWARE_BUTTON_AREAS_CHANGED));
@@ -545,7 +554,11 @@ TouchpadPrefView::SetupView()
.SetInsets(B_USE_WINDOW_SPACING)
.Add(scrollBox)
.Add(fEdgeMotionOptionPopUp)
.Add(fSoftwareButtonAreasBox)
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
.Add(fFingerClickBox)
.Add(new BSeparatorView(B_VERTICAL))
.Add(fSoftwareButtonAreasBox)
.End()
.Add(new BSeparatorView(B_HORIZONTAL))
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
@@ -580,6 +593,7 @@ TouchpadPrefView::SetValues(touchpad_settings* settings)
fTwoFingerNaturalScrollingBox->SetValue(
settings->scroll_twofinger_natural_scrolling ? B_CONTROL_ON : B_CONTROL_OFF);
fTwoFingerNaturalScrollingBox->SetEnabled(settings->scroll_twofinger);
fFingerClickBox->SetValue(settings->finger_click);
fSoftwareButtonAreasBox->SetValue(settings->software_button_areas);
fEdgeMotionOptionPopUp->SetValue(settings->edge_motion);
fScrollStepXSlider->SetValue(20 - settings->scroll_xstepsize / 2);
@@ -41,6 +41,7 @@ const uint PADBLOCK_TIME_CHANGED = '&ptc';
const uint PAD_SPEED_CHANGED = '&psc';
const uint PAD_ACCELERATION_CHANGED = '&pac';
const uint EDGE_MOTION_CHANGED = '&emc';
const uint FINGER_CLICK_CHANGED = '&fcc';
const uint SOFTWARE_BUTTON_AREAS_CHANGED = '&sbc';
class DeviceListView;
@@ -102,6 +103,7 @@ private:
BCheckBox* fTwoFingerBox;
BCheckBox* fTwoFingerHorizontalBox;
BCheckBox* fTwoFingerNaturalScrollingBox;
BCheckBox* fFingerClickBox;
BCheckBox* fSoftwareButtonAreasBox;
BSlider* fScrollStepXSlider;
BSlider* fScrollStepYSlider;