diff --git a/headers/private/input/touchpad_settings.h b/headers/private/input/touchpad_settings.h index b6d5b27d5a..8fc38e60da 100644 --- a/headers/private/input/touchpad_settings.h +++ b/headers/private/input/touchpad_settings.h @@ -33,6 +33,8 @@ typedef struct { // 0x02: edge motion on tap drag // 0x04: edge motion on button click move // 0x08: edge motion on button click drag + + bool software_button_areas; } touchpad_settings; @@ -50,7 +52,8 @@ const static touchpad_settings kDefaultTouchpadSettings = { 65536, false, true, - 0x02 + 0x02, + false }; #define TOUCHPAD_SETTINGS_FILE "Touchpad_settings" diff --git a/src/add-ons/input_server/devices/mouse/MouseInputDevice.cpp b/src/add-ons/input_server/devices/mouse/MouseInputDevice.cpp index 4874fa8f8e..8ae0be1af7 100644 --- a/src/add-ons/input_server/devices/mouse/MouseInputDevice.cpp +++ b/src/add-ons/input_server/devices/mouse/MouseInputDevice.cpp @@ -608,6 +608,8 @@ MouseDevice::_UpdateTouchpadSettings(BMessage* message) &settings.scroll_twofinger_natural_scrolling); message->FindInt8("edge_motion", (int8*)&settings.edge_motion); + message->FindBool("software_button_areas", + &settings.software_button_areas); if (fIsTouchpad) fTouchpadMovementMaker.SetSettings(settings); diff --git a/src/add-ons/input_server/devices/mouse/movement_maker.cpp b/src/add-ons/input_server/devices/mouse/movement_maker.cpp index adcba132e5..aaebc2e138 100644 --- a/src/add-ons/input_server/devices/mouse/movement_maker.cpp +++ b/src/add-ons/input_server/devices/mouse/movement_maker.cpp @@ -307,7 +307,7 @@ TouchpadMovement::~TouchpadMovement() { status_t -TouchpadMovement::EventToMovement(const touchpad_movement* event, mouse_movement* movement, +TouchpadMovement::EventToMovement(const touchpad_movement* _event, mouse_movement* movement, bigtime_t& repeatTimeout) { CALLED(); @@ -317,13 +317,13 @@ TouchpadMovement::EventToMovement(const touchpad_movement* event, mouse_movement TRACE("TM_EVENT: b:0x%" B_PRIx8 " nf:%" B_PRId8 " f:0x%" B_PRIx8 " x:%" B_PRIu32 " y:%" B_PRIu32 " p:%" B_PRIu8 " w:%" B_PRIu8 "\n", - event->buttons, - count_set_bits(event->fingers), - event->fingers, - event->xPosition, - event->yPosition, - event->zPressure, - event->fingerWidth + _event->buttons, + count_set_bits(_event->fingers), + _event->fingers, + _event->xPosition, + _event->yPosition, + _event->zPressure, + _event->fingerWidth ); TRACE("TM_STATUS: b:0x%" B_PRIx8 " %c%c%c%c%c%c" " dx:%" B_PRId32 " dy:%" B_PRId32 @@ -352,6 +352,10 @@ TouchpadMovement::EventToMovement(const touchpad_movement* event, mouse_movement movement->clicks = 0; movement->timestamp = system_time(); + touchpad_movement event2 = *_event; + _SoftwareButtonAreas(&event2); + const touchpad_movement* event = &event2; + if ((movement->timestamp - fTapTime) > fTapTimeOUT) { if (fTapStarted) TRACE("TouchpadMovement: tap gesture timed out\n"); @@ -394,6 +398,55 @@ TouchpadMovement::EventToMovement(const touchpad_movement* event, mouse_movement } +void +TouchpadMovement::_SoftwareButtonAreas(touchpad_movement *event) { + CALLED(); + + // Software button areas. + // - Emulation of button areas as clickpads do not have separated physical buttons from the one + // overlapping the touch area. + // - Pretend the the same button is still pressed if the finger hasn't been released regardless + // of its current possition. + // TODO: + // - Implement top button area. + // - Implement trackpoint emulator in an area. + // i.e.: small centered square on the top of the clickpad. + // - Make the areas configurable from settings and Input preference app. + // i.e.: to allow switch left and right buttons, etc. + if (event->buttons != 0) { + if (fSettings.software_button_areas) { + if (fButtonsState == 0) { + uint32 evaluatePositionX = (event->xPosition == 0) ? fPreviousX : event->xPosition; + uint32 evaluatePositionY = (event->yPosition == 0) ? fPreviousY : event->yPosition; + if (evaluatePositionY > 0 && evaluatePositionY < (uint32) fSpecs.areaEndY / 5) { + #if 0 + // 2 software buttons: + // - Emulates right buttom hardcoded to half left side of the touchpad, + // otherwise left button. + if (evaluatePositionX > (uint32) fSpecs.areaEndX / 2) { + event->buttons = 2; + } else { + event->buttons = 1; + } + #else + // 3 software buttons where the the middle button uses 1/6 of the area. + if (evaluatePositionX > (uint32) fSpecs.areaEndX / 12 * 7) { + event->buttons = 2; + } else if (evaluatePositionX > (uint32) fSpecs.areaEndX / 12 * 5) { + // Middle button area smaller than left and right buttons' area. + event->buttons = 4; + } else { + event->buttons = 1; + } + #endif + } + } else { + event->buttons = fButtonsState; + } + } + } +} + // in pixel per second const int32 kEdgeMotionSpeed = 200; diff --git a/src/add-ons/input_server/devices/mouse/movement_maker.h b/src/add-ons/input_server/devices/mouse/movement_maker.h index c33f726b7d..70d3364023 100644 --- a/src/add-ons/input_server/devices/mouse/movement_maker.h +++ b/src/add-ons/input_server/devices/mouse/movement_maker.h @@ -42,10 +42,11 @@ private: bool fMovementMakerStarted; -private: +protected: uint32 fPreviousX; uint32 fPreviousY; +private: float fDeltaSumX; float fDeltaSumY; @@ -75,6 +76,7 @@ private: void _UpdateButtons(mouse_movement *movement); bool _EdgeMotion(const touchpad_movement *event, mouse_movement *movement, bool validStart); + inline void _SoftwareButtonAreas(touchpad_movement *event); inline void _NoTouchToMovement(const touchpad_movement *event, mouse_movement *movement); inline void _MoveToMovement(const touchpad_movement *event, diff --git a/src/preferences/input/InputTouchpadPref.cpp b/src/preferences/input/InputTouchpadPref.cpp index 5ece53632e..40649e09ef 100644 --- a/src/preferences/input/InputTouchpadPref.cpp +++ b/src/preferences/input/InputTouchpadPref.cpp @@ -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("software_button_areas", fSettings.software_button_areas); return msg; } @@ -160,6 +161,9 @@ TouchpadPref::LoadSettings() fSettings.edge_motion = settingsMsg.GetInt8( "edge_motion", kDefaultTouchpadSettings.edge_motion); + fSettings.software_button_areas = settingsMsg.GetBool( + "software_button_areas", + kDefaultTouchpadSettings.software_button_areas); return B_OK; } diff --git a/src/preferences/input/InputTouchpadPrefView.cpp b/src/preferences/input/InputTouchpadPrefView.cpp index a934c86942..459d0b51ad 100644 --- a/src/preferences/input/InputTouchpadPrefView.cpp +++ b/src/preferences/input/InputTouchpadPrefView.cpp @@ -315,6 +315,12 @@ TouchpadPrefView::MessageReceived(BMessage* message) fTouchpadPref.UpdateRunningSettings(); break; + case SOFTWARE_BUTTON_AREAS_CHANGED: + settings.software_button_areas = fSoftwareButtonAreasBox->Value() == B_CONTROL_ON; + fRevertButton->SetEnabled(true); + fTouchpadPref.UpdateRunningSettings(); + break; + case TAP_CONTROL_CHANGED: settings.tapgesture_sensibility = fTapSlider->Value(); fRevertButton->SetEnabled(true); @@ -376,6 +382,7 @@ TouchpadPrefView::AttachedToWindow() fScrollAccelSlider->SetTarget(this); fEdgeMotionOptionPopUp->SetTarget(this); + fSoftwareButtonAreasBox->SetTarget(this); fPadBlockerSlider->SetTarget(this); fTapSlider->SetTarget(this); @@ -472,6 +479,10 @@ 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); + fSoftwareButtonAreasBox = new BCheckBox(B_TRANSLATE("Software button areas"), + new BMessage(SOFTWARE_BUTTON_AREAS_CHANGED)); + + float spacing = be_control_look->DefaultItemSpacing(); BView* scrollPrefLeftLayout @@ -534,6 +545,7 @@ TouchpadPrefView::SetupView() .SetInsets(B_USE_WINDOW_SPACING) .Add(scrollBox) .Add(fEdgeMotionOptionPopUp) + .Add(fSoftwareButtonAreasBox) .Add(new BSeparatorView(B_HORIZONTAL)) .AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) .AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING) @@ -568,6 +580,7 @@ TouchpadPrefView::SetValues(touchpad_settings* settings) fTwoFingerNaturalScrollingBox->SetValue( settings->scroll_twofinger_natural_scrolling ? B_CONTROL_ON : B_CONTROL_OFF); fTwoFingerNaturalScrollingBox->SetEnabled(settings->scroll_twofinger); + fSoftwareButtonAreasBox->SetValue(settings->software_button_areas); fEdgeMotionOptionPopUp->SetValue(settings->edge_motion); fScrollStepXSlider->SetValue(20 - settings->scroll_xstepsize / 2); fScrollStepYSlider->SetValue(20 - settings->scroll_ystepsize / 2); diff --git a/src/preferences/input/InputTouchpadPrefView.h b/src/preferences/input/InputTouchpadPrefView.h index d7831b07eb..2cfe7814d5 100644 --- a/src/preferences/input/InputTouchpadPrefView.h +++ b/src/preferences/input/InputTouchpadPrefView.h @@ -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 SOFTWARE_BUTTON_AREAS_CHANGED = '&sbc'; class DeviceListView; @@ -101,6 +102,7 @@ private: BCheckBox* fTwoFingerBox; BCheckBox* fTwoFingerHorizontalBox; BCheckBox* fTwoFingerNaturalScrollingBox; + BCheckBox* fSoftwareButtonAreasBox; BSlider* fScrollStepXSlider; BSlider* fScrollStepYSlider; BSlider* fScrollAccelSlider;