root/src/preferences/input/InputTouchpadPrefView.cpp
/*
 * Copyright 2019-2025, Haiku, Inc.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *              Preetpal Kaur <preetpalok123@gmail.com>
 *              Pawan Yerramilli <me@pawanyerramilli.com>
 *              Samuel Rodríguez Pérez <samuelrp84@gmail.com>
 */


#include "InputTouchpadPrefView.h"

#include <stdio.h>

#include <Alert.h>
#include <Box.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <ControlLook.h>
#include <File.h>
#include <FindDirectory.h>
#include <Input.h>
#include <LayoutBuilder.h>
#include <Locale.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Message.h>
#include <Path.h>
#include <Screen.h>
#include <SeparatorView.h>
#include <SpaceLayoutItem.h>
#include <Window.h>

#include <keyboard_mouse_driver.h>


const uint32 SCROLL_X_DRAG = 'sxdr';
const uint32 SCROLL_Y_DRAG = 'sydr';

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "TouchpadPrefView"


TouchpadView::TouchpadView(BRect frame)
        :
        BView(frame, "TouchpadView", B_FOLLOW_NONE, B_WILL_DRAW)
{
        fXTracking = false;
        fYTracking = false;
        fOffScreenView = NULL;
        fOffScreenBitmap = NULL;

        fPrefRect = frame;
        fPadRect = fPrefRect;
        fPadRect.InsetBy(10, 10);
        fXScrollRange = fPadRect.Width();
        fYScrollRange = fPadRect.Height();
}


TouchpadView::~TouchpadView()
{
        delete fOffScreenBitmap;
}


void
TouchpadView::Draw(BRect updateRect)
{
        DrawSliders();
}


void
TouchpadView::MouseDown(BPoint point)
{
        if (fXScrollDragZone.Contains(point)) {
                fXTracking = true;
                fOldXScrollRange = fXScrollRange;
                SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
        }

        if (fYScrollDragZone.Contains(point)) {
                fYTracking = true;
                fOldYScrollRange = fYScrollRange;
                SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
        }
}


void
TouchpadView::MouseUp(BPoint point)
{
        if (!fXTracking && !fYTracking)
                return;

        fXTracking = false;
        fYTracking = false;

        const float kSoftScrollLimit = 0.7;

        int32 result = 0;
        if (GetRightScrollRatio() > kSoftScrollLimit
                || GetBottomScrollRatio() > kSoftScrollLimit) {
                BAlert* alert = new BAlert(B_TRANSLATE("Please confirm"),
                        B_TRANSLATE(
                                "The new scroll area is very large and may impede "
                                "normal mouse operation. Do you really want to change it?"),
                        B_TRANSLATE("OK"), B_TRANSLATE("Cancel"), NULL, B_WIDTH_AS_USUAL,
                        B_WARNING_ALERT);
                alert->SetShortcut(1, B_ESCAPE);
                result = alert->Go();
        }

        if (result == 0) {
                BMessage msg(SCROLL_AREA_CHANGED);
                Invoke(&msg);
        } else {
                if (GetRightScrollRatio() > kSoftScrollLimit)
                        fXScrollRange = fOldXScrollRange;
                if (GetBottomScrollRatio() > kSoftScrollLimit)
                        fYScrollRange = fOldYScrollRange;
                DrawSliders();
        }
}


void
TouchpadView::AttachedToWindow()
{
        if (!fOffScreenView)
                fOffScreenView = new BView(Bounds(), "", B_FOLLOW_ALL, B_WILL_DRAW);

        if (!fOffScreenBitmap) {
                fOffScreenBitmap = new BBitmap(Bounds(), B_CMAP8, true, false);

                if (fOffScreenBitmap && fOffScreenView)
                        fOffScreenBitmap->AddChild(fOffScreenView);
        }
}


void
TouchpadView::SetValues(float rightRange, float bottomRange)
{
        fXScrollRange = fPadRect.Width() * (1 - rightRange);
        fYScrollRange = fPadRect.Height() * (1 - bottomRange);
        Invalidate();
}


void
TouchpadView::GetPreferredSize(float* width, float* height)
{
        if (width != NULL)
                *width = fPrefRect.Width();
        if (height != NULL)
                *height = fPrefRect.Height();
}


void
TouchpadView::MouseMoved(BPoint point, uint32 transit, const BMessage* message)
{
        if (fXTracking) {
                if (point.x > fPadRect.right)
                        fXScrollRange = fPadRect.Width();
                else if (point.x < fPadRect.left)
                        fXScrollRange = 0;
                else
                        fXScrollRange = point.x - fPadRect.left;

                DrawSliders();
        }

        if (fYTracking) {
                if (point.y > fPadRect.bottom)
                        fYScrollRange = fPadRect.Height();
                else if (point.y < fPadRect.top)
                        fYScrollRange = 0;
                else
                        fYScrollRange = point.y - fPadRect.top;

                DrawSliders();
        }
}


void
TouchpadView::DrawSliders()
{
        BView* view = fOffScreenView != NULL ? fOffScreenView : this;

        if (!LockLooper())
                return;

        if (fOffScreenBitmap->Lock()) {
                view->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
                view->FillRect(Bounds());
                view->SetHighColor(100, 100, 100);
                view->FillRoundRect(fPadRect, 4, 4);

                int32 dragSize = 3; // half drag size

                // scroll areas
                view->SetHighColor(145, 100, 100);
                BRect rightRect(fPadRect.left + fXScrollRange, fPadRect.top,
                        fPadRect.right, fPadRect.bottom);
                view->FillRoundRect(rightRect, 4, 4);

                BRect bottomRect(fPadRect.left, fPadRect.top + fYScrollRange,
                        fPadRect.right, fPadRect.bottom);
                view->FillRoundRect(bottomRect, 4, 4);

                // Stroke Rect
                view->SetHighColor(100, 100, 100);
                view->SetPenSize(2);
                view->StrokeRoundRect(fPadRect, 4, 4);

                // x scroll range line
                view->SetHighColor(200, 0, 0);
                view->StrokeLine(BPoint(fPadRect.left + fXScrollRange, fPadRect.top),
                        BPoint(fPadRect.left + fXScrollRange, fPadRect.bottom));

                fXScrollDragZone = BRect(fPadRect.left + fXScrollRange - dragSize,
                        fPadRect.top - dragSize, fPadRect.left + fXScrollRange + dragSize,
                        fPadRect.bottom + dragSize);
                BRect xscrollDragZone1 = BRect(fPadRect.left + fXScrollRange - dragSize,
                        fPadRect.top - dragSize, fPadRect.left + fXScrollRange + dragSize,
                        fPadRect.top + dragSize);
                view->FillRect(xscrollDragZone1);
                BRect xscrollDragZone2 = BRect(fPadRect.left + fXScrollRange - dragSize,
                        fPadRect.bottom - dragSize,
                        fPadRect.left + fXScrollRange + dragSize,
                        fPadRect.bottom + dragSize);
                view->FillRect(xscrollDragZone2);

                // y scroll range line
                view->StrokeLine(BPoint(fPadRect.left, fPadRect.top + fYScrollRange),
                        BPoint(fPadRect.right, fPadRect.top + fYScrollRange));

                fYScrollDragZone = BRect(fPadRect.left - dragSize,
                        fPadRect.top + fYScrollRange - dragSize, fPadRect.right + dragSize,
                        fPadRect.top + fYScrollRange + dragSize);
                BRect yscrollDragZone1 = BRect(fPadRect.left - dragSize,
                        fPadRect.top + fYScrollRange - dragSize, fPadRect.left + dragSize,
                        fPadRect.top + fYScrollRange + dragSize);
                view->FillRect(yscrollDragZone1);
                BRect yscrollDragZone2 = BRect(fPadRect.right - dragSize,
                        fPadRect.top + fYScrollRange - dragSize, fPadRect.right + dragSize,
                        fPadRect.top + fYScrollRange + dragSize);
                view->FillRect(yscrollDragZone2);

                view->Sync();
                fOffScreenBitmap->Unlock();
                DrawBitmap(fOffScreenBitmap, B_ORIGIN);
        }

        UnlockLooper();
}


//      #pragma mark - TouchpadPrefView


TouchpadPrefView::TouchpadPrefView(BInputDevice* dev)
        :
        BGroupView(),
        fTouchpadPref(dev)
{
        SetupView();
        // set view values
        SetValues(&fTouchpadPref.Settings());
}


TouchpadPrefView::~TouchpadPrefView()
{
}


void
TouchpadPrefView::MessageReceived(BMessage* message)
{
        touchpad_settings& settings = fTouchpadPref.Settings();

        switch (message->what) {
                case SCROLL_AREA_CHANGED:
                        settings.scroll_rightrange = fTouchpadView->GetRightScrollRatio();
                        settings.scroll_bottomrange = fTouchpadView->GetBottomScrollRatio();
                        fRevertButton->SetEnabled(true);
                        fTouchpadPref.UpdateRunningSettings();
                        break;

                case SCROLL_CONTROL_CHANGED:
                        settings.scroll_reverse = fScrollReverseBox->Value() == B_CONTROL_ON;
                        settings.scroll_twofinger = fTwoFingerBox->Value() == B_CONTROL_ON;
                        settings.scroll_twofinger_horizontal
                                = fTwoFingerHorizontalBox->Value() == B_CONTROL_ON;
                        settings.scroll_twofinger_natural_scrolling
                                = fTwoFingerNaturalScrollingBox->Value() == B_CONTROL_ON;
                        settings.scroll_acceleration = fScrollAccelSlider->Value();
                        settings.scroll_xstepsize = (20 - fScrollStepXSlider->Value()) * 3;
                        settings.scroll_ystepsize = (20 - fScrollStepYSlider->Value()) * 3;
                        fTwoFingerHorizontalBox->SetEnabled(settings.scroll_twofinger);
                        fTwoFingerNaturalScrollingBox->SetEnabled(settings.scroll_twofinger);
                        fRevertButton->SetEnabled(true);
                        fTouchpadPref.UpdateRunningSettings();
                        break;

                case EDGE_MOTION_CHANGED:
                        settings.edge_motion = fEdgeMotionOptionPopUp->Value();
                        fRevertButton->SetEnabled(true);
                        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);
                        fTouchpadPref.UpdateRunningSettings();
                        break;

                case TAP_CONTROL_CHANGED:
                        settings.tapgesture_sensibility = fTapSlider->Value();
                        fRevertButton->SetEnabled(true);
                        fTouchpadPref.UpdateRunningSettings();
                        break;

                case PADBLOCK_TIME_CHANGED:
                        settings.padblocker_threshold = fPadBlockerSlider->Value();
                        // The maximum value means "disabled", but in the settings file that
                        // must be stored as 0
                        if (settings.padblocker_threshold == 1000)
                                settings.padblocker_threshold = 0;
                        fRevertButton->SetEnabled(true);
                        fTouchpadPref.UpdateRunningSettings();
                        break;

                case PAD_SPEED_CHANGED:
                {
                        fTouchpadPref.SetSpeed(fSpeedSlider->Value());
                        fRevertButton->SetEnabled(true);
                        break;
                }
                case PAD_ACCELERATION_CHANGED:
                {
                        fTouchpadPref.SetAcceleration(fAccelSlider->Value());
                        fRevertButton->SetEnabled(true);
                        break;
                }
                case DEFAULT_SETTINGS:
                        fTouchpadPref.Defaults();
                        fRevertButton->SetEnabled(true);
                        fTouchpadPref.UpdateRunningSettings();
                        SetValues(&settings);
                        break;

                case REVERT_SETTINGS:
                        fTouchpadPref.Revert();
                        fTouchpadPref.UpdateRunningSettings();
                        fRevertButton->SetEnabled(false);
                        SetValues(&settings);
                        break;

                default:
                        BView::MessageReceived(message);
        }
}


void
TouchpadPrefView::AttachedToWindow()
{
        fTouchpadView->SetTarget(this);
        fScrollReverseBox->SetTarget(this);
        fTwoFingerBox->SetTarget(this);
        fTwoFingerHorizontalBox->SetTarget(this);
        fTwoFingerNaturalScrollingBox->SetTarget(this);
        fScrollStepXSlider->SetTarget(this);
        fScrollStepYSlider->SetTarget(this);
        fScrollAccelSlider->SetTarget(this);

        fEdgeMotionOptionPopUp->SetTarget(this);
        fFingerClickBox->SetTarget(this);
        fSoftwareButtonAreasBox->SetTarget(this);

        fPadBlockerSlider->SetTarget(this);
        fTapSlider->SetTarget(this);
        fSpeedSlider->SetTarget(this);
        fAccelSlider->SetTarget(this);

        fDefaultButton->SetTarget(this);
        fRevertButton->SetTarget(this);

        BSize size = PreferredSize();
        Window()->ResizeTo(size.width, size.height);

        BPoint position = fTouchpadPref.WindowPosition();
        // center window on screen if it had a bad position
        if (position.x < 0 && position.y < 0)
                Window()->CenterOnScreen();
        else
                Window()->MoveTo(position);
}


void
TouchpadPrefView::DetachedFromWindow()
{
        fTouchpadPref.SetWindowPosition(Window()->Frame().LeftTop());
}


void
TouchpadPrefView::SetupView()
{
        SetLayout(new BGroupLayout(B_VERTICAL));
        BBox* scrollBox = new BBox("Touchpad");
        scrollBox->SetLabel(B_TRANSLATE("Scrolling"));


        fTouchpadView = new TouchpadView(BRect(0, 0, 130, 120));
        fTouchpadView->SetExplicitMaxSize(BSize(130, 120));

        // Create the scrolling acceleration slider...
        fScrollAccelSlider = new BSlider("scroll_accel",
                B_TRANSLATE("Acceleration"),
                new BMessage(SCROLL_CONTROL_CHANGED), 0, 20, B_HORIZONTAL);
        fScrollAccelSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
        fScrollAccelSlider->SetHashMarkCount(7);
        fScrollAccelSlider->SetLimitLabels(
                B_TRANSLATE("Low"), B_TRANSLATE("High"));
        fScrollAccelSlider->SetExplicitMinSize(BSize(150, B_SIZE_UNSET));

        fScrollStepXSlider = new BSlider("scroll_stepX", B_TRANSLATE("Horizontal"),
                new BMessage(SCROLL_CONTROL_CHANGED), 0, 20, B_HORIZONTAL);
        fScrollStepXSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
        fScrollStepXSlider->SetHashMarkCount(7);
        fScrollStepXSlider->SetLimitLabels(
                B_TRANSLATE("Slow"), B_TRANSLATE("Fast"));

        fScrollStepYSlider = new BSlider("scroll_stepY", B_TRANSLATE("Vertical"),
                new BMessage(SCROLL_CONTROL_CHANGED), 0, 20, B_HORIZONTAL);
        fScrollStepYSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
        fScrollStepYSlider->SetHashMarkCount(7);
        fScrollStepYSlider->SetLimitLabels(
                B_TRANSLATE("Slow"), B_TRANSLATE("Fast"));

        fPadBlockerSlider
                = new BSlider("padblocker", B_TRANSLATE("Keyboard lock delay"),
                        new BMessage(PADBLOCK_TIME_CHANGED), 5, 1000, B_HORIZONTAL);
        fPadBlockerSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
        fPadBlockerSlider->SetHashMarkCount(10);
        fPadBlockerSlider->SetLimitLabels(
                B_TRANSLATE("Quick"), B_TRANSLATE("Never"));

        fScrollReverseBox = new BCheckBox(B_TRANSLATE("Reverse scroll direction"),
                new BMessage(SCROLL_CONTROL_CHANGED));
        fTwoFingerBox = new BCheckBox(B_TRANSLATE("Two finger scrolling"),
                new BMessage(SCROLL_CONTROL_CHANGED));
        fTwoFingerHorizontalBox = new BCheckBox(B_TRANSLATE("Horizontal scrolling"),
                new BMessage(SCROLL_CONTROL_CHANGED));
        fTwoFingerNaturalScrollingBox = new BCheckBox(B_TRANSLATE("Natural scrolling"),
                new BMessage(SCROLL_CONTROL_CHANGED));

        fEdgeMotionOptionPopUp = new BOptionPopUp("edge_motion",
                B_TRANSLATE("Edge motion:"), new BMessage(EDGE_MOTION_CHANGED));
        fEdgeMotionOptionPopUp->AddOption(B_TRANSLATE("Disabled"), B_EDGE_MOTION_DISABLED);
#if 0
        // Not exposed in the UI because it makes little sense to have this enabled on move but not
        // on drag
        fEdgeMotionOptionPopUp->AddOption(B_TRANSLATE("On move"), B_EDGE_MOTION_ON_MOVE);
#endif
        fEdgeMotionOptionPopUp->AddOption(B_TRANSLATE("On tap-drag only"), B_EDGE_MOTION_ON_TAP_DRAG);
        fEdgeMotionOptionPopUp->AddOption(B_TRANSLATE("When dragging"),
                B_EDGE_MOTION_ON_TAP_DRAG
                | B_EDGE_MOTION_ON_BUTTON_CLICK_MOVE | B_EDGE_MOTION_ON_BUTTON_CLICK_DRAG);
        fEdgeMotionOptionPopUp->AddOption(B_TRANSLATE("Always"),
                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));


        float spacing = be_control_look->DefaultItemSpacing();

        BView* scrollPrefLeftLayout
                = BLayoutBuilder::Group<>(B_VERTICAL, 0)
                .Add(fTouchpadView)
                .AddStrut(spacing)
                .Add(fScrollReverseBox)
                .Add(fTwoFingerBox)
                .AddGroup(B_VERTICAL, 0)
                        .SetInsets(spacing * 2, 0, 0, 0)
                        .Add(fTwoFingerHorizontalBox)
                        .Add(fTwoFingerNaturalScrollingBox)
                .End()
                .AddGlue()
                .View();

        BGroupView* scrollPrefRightLayout = new BGroupView(B_VERTICAL);
        scrollPrefRightLayout->AddChild(fScrollAccelSlider);
        scrollPrefRightLayout->AddChild(fScrollStepXSlider);
        scrollPrefRightLayout->AddChild(fScrollStepYSlider);

        BGroupLayout* scrollPrefLayout = new BGroupLayout(B_HORIZONTAL);
        scrollPrefLayout->SetSpacing(spacing);
        scrollPrefLayout->SetInsets(
                spacing, scrollBox->TopBorderOffset() * 2 + spacing, spacing, spacing);
        scrollBox->SetLayout(scrollPrefLayout);

        scrollPrefLayout->AddView(scrollPrefLeftLayout);
        scrollPrefLayout->AddItem(
                BSpaceLayoutItem::CreateVerticalStrut(spacing * 1.5));
        scrollPrefLayout->AddView(scrollPrefRightLayout);

        fTapSlider = new BSlider("tap_sens", B_TRANSLATE("Tapping sensitivity"),
                new BMessage(TAP_CONTROL_CHANGED), 0, 50, B_HORIZONTAL);
        fTapSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
        fTapSlider->SetHashMarkCount(11);
        fTapSlider->SetLimitLabels(B_TRANSLATE("Off"), B_TRANSLATE("High"));

        fSpeedSlider = new BSlider("pad_speed", B_TRANSLATE("Trackpad speed"),
                new BMessage(PAD_SPEED_CHANGED), 0, 1000, B_HORIZONTAL);
        fSpeedSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
        fSpeedSlider->SetHashMarkCount(7);
        fSpeedSlider->SetLimitLabels(B_TRANSLATE("Slow"), B_TRANSLATE("Fast"));

        fAccelSlider = new BSlider("pad_accel", B_TRANSLATE("Trackpad acceleration"),
                new BMessage(PAD_ACCELERATION_CHANGED), 0, 1000, B_HORIZONTAL);
        fAccelSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
        fAccelSlider->SetHashMarkCount(7);
        fAccelSlider->SetLimitLabels(B_TRANSLATE("Low"), B_TRANSLATE("High"));

        fDefaultButton
                = new BButton(B_TRANSLATE("Defaults"), new BMessage(DEFAULT_SETTINGS));

        fRevertButton
                = new BButton(B_TRANSLATE("Revert"), new BMessage(REVERT_SETTINGS));
        fRevertButton->SetEnabled(false);


        BLayoutBuilder::Group<>(this, B_VERTICAL)
                .SetInsets(B_USE_WINDOW_SPACING)
                .Add(scrollBox)
                .Add(fEdgeMotionOptionPopUp)
                .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)
                                .Add(fTapSlider)
                                .Add(fPadBlockerSlider)
                                .End()
                        .Add(new BSeparatorView(B_VERTICAL))
                        .AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
                                .Add(fSpeedSlider)
                                .Add(fAccelSlider)
                                .End()
                        .End()
                .Add(new BSeparatorView(B_HORIZONTAL))
                        .AddGroup(B_HORIZONTAL)
                        .Add(fDefaultButton)
                        .Add(fRevertButton)
                        .AddGlue()
                        .End()
                .End();
}


void
TouchpadPrefView::SetValues(touchpad_settings* settings)
{
        fTouchpadView->SetValues(settings->scroll_rightrange, settings->scroll_bottomrange);
        fScrollReverseBox->SetValue(settings->scroll_reverse ? B_CONTROL_ON : B_CONTROL_OFF);
        fTwoFingerBox->SetValue(settings->scroll_twofinger ? B_CONTROL_ON : B_CONTROL_OFF);
        fTwoFingerHorizontalBox->SetValue(
                settings->scroll_twofinger_horizontal ? B_CONTROL_ON : B_CONTROL_OFF);
        fTwoFingerHorizontalBox->SetEnabled(settings->scroll_twofinger);
        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);
        fScrollStepYSlider->SetValue(20 - settings->scroll_ystepsize / 2);
        fScrollAccelSlider->SetValue(settings->scroll_acceleration);
        fTapSlider->SetValue(settings->tapgesture_sensibility);
        fPadBlockerSlider->SetValue(settings->padblocker_threshold);
        int32 value = int32((log(settings->trackpad_speed / 8192.0) / log(2)) * 1000 / 6);
        fSpeedSlider->SetValue(value);
        value = int32(sqrt(settings->trackpad_acceleration / 16384.0) * 1000 / 4);
        fAccelSlider->SetValue(value);
}