Support HiresScroll gesture remapping
This commit allows HiresScroll (when target is true) to map the up and down events to gestures that support it (i.e.AxisGesture/ IntervalGesture). This check is done by checking if wheelCompatibility() is true. This also allows hires scroll events to send low-res scroll events as well. TODO: Fix bug w/ Chromium (and some other programs?) where mapping scroll wheel to REL_WHEEL_HI_RES will cause the program to skip events occassionally. I have literally been stuck on this bug for a week and I still don't know what causes it. evtest shows proper scroll events, Firefox works fine, and libinput test-gui reports proper scrolling.
This commit is contained in:
		@@ -89,6 +89,17 @@ uint InputDevice::toAxisCode(const std::string& name)
 | 
				
			|||||||
    return _toEventCode(EV_REL, name);
 | 
					    return _toEventCode(EV_REL, name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Returns -1 if axis_code is not hi-res */
 | 
				
			||||||
 | 
					int InputDevice::getLowResAxis(const uint axis_code)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(axis_code == REL_WHEEL_HI_RES)
 | 
				
			||||||
 | 
					        return REL_WHEEL;
 | 
				
			||||||
 | 
					    if(axis_code == REL_HWHEEL_HI_RES)
 | 
				
			||||||
 | 
					        return REL_HWHEEL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint InputDevice::_toEventCode(uint type, const std::string& name)
 | 
					uint InputDevice::_toEventCode(uint type, const std::string& name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int code = libevdev_event_code_from_name(type, name.c_str());
 | 
					    int code = libevdev_event_code_from_name(type, name.c_str());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,6 +49,8 @@ namespace logid
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        static uint toKeyCode(const std::string& name);
 | 
					        static uint toKeyCode(const std::string& name);
 | 
				
			||||||
        static uint toAxisCode(const std::string& name);
 | 
					        static uint toAxisCode(const std::string& name);
 | 
				
			||||||
 | 
					        static int getLowResAxis(uint axis_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        void _sendEvent(uint type, uint code, int value);
 | 
					        void _sendEvent(uint type, uint code, int value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,10 +27,11 @@ AxisGesture::AxisGesture(Device *device, libconfig::Setting &root) :
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AxisGesture::press()
 | 
					void AxisGesture::press(bool init_threshold)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _axis = 0;
 | 
					    _axis = init_threshold ? _config.threshold() : 0;
 | 
				
			||||||
    _axis_remainder = 0;
 | 
					    _axis_remainder = 0;
 | 
				
			||||||
 | 
					    _hires_remainder = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AxisGesture::release(bool primary)
 | 
					void AxisGesture::release(bool primary)
 | 
				
			||||||
@@ -41,7 +42,10 @@ void AxisGesture::release(bool primary)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void AxisGesture::move(int16_t axis)
 | 
					void AxisGesture::move(int16_t axis)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int16_t new_axis = _axis + axis;
 | 
					    int16_t new_axis = _axis+axis;
 | 
				
			||||||
 | 
					    int low_res_axis = InputDevice::getLowResAxis(_config.axis());
 | 
				
			||||||
 | 
					    int hires_remainder = _hires_remainder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(new_axis > _config.threshold()) {
 | 
					    if(new_axis > _config.threshold()) {
 | 
				
			||||||
        double move = axis;
 | 
					        double move = axis;
 | 
				
			||||||
        if(_axis < _config.threshold())
 | 
					        if(_axis < _config.threshold())
 | 
				
			||||||
@@ -63,7 +67,22 @@ void AxisGesture::move(int16_t axis)
 | 
				
			|||||||
        if(negative_multiplier)
 | 
					        if(negative_multiplier)
 | 
				
			||||||
            move_floor = -move_floor;
 | 
					            move_floor = -move_floor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual_input->moveAxis(_config.axis(), move_floor);
 | 
					        if(low_res_axis != -1) {
 | 
				
			||||||
 | 
					            int lowres_movement = 0, hires_movement = move_floor;
 | 
				
			||||||
 | 
					            virtual_input->moveAxis(_config.axis(), hires_movement);
 | 
				
			||||||
 | 
					            hires_remainder += hires_movement;
 | 
				
			||||||
 | 
					            if(abs(hires_remainder) >= 60) {
 | 
				
			||||||
 | 
					                lowres_movement = hires_remainder/120;
 | 
				
			||||||
 | 
					                if(lowres_movement == 0)
 | 
				
			||||||
 | 
					                    lowres_movement = hires_remainder > 0 ? 1 : -1;
 | 
				
			||||||
 | 
					                hires_remainder -= lowres_movement*120;
 | 
				
			||||||
 | 
					                virtual_input->moveAxis(low_res_axis, lowres_movement);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _hires_remainder = hires_remainder;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            virtual_input->moveAxis(_config.axis(), move_floor);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    _axis = new_axis;
 | 
					    _axis = new_axis;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -73,6 +92,11 @@ bool AxisGesture::metThreshold() const
 | 
				
			|||||||
    return _axis >= _config.threshold();
 | 
					    return _axis >= _config.threshold();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AxisGesture::setHiresMultiplier(double multiplier)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _config.setHiresMultiplier(multiplier);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AxisGesture::Config::Config(Device *device, libconfig::Setting &setting) :
 | 
					AxisGesture::Config::Config(Device *device, libconfig::Setting &setting) :
 | 
				
			||||||
    Gesture::Config(device, setting, false)
 | 
					    Gesture::Config(device, setting, false)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -113,6 +137,9 @@ AxisGesture::Config::Config(Device *device, libconfig::Setting &setting) :
 | 
				
			|||||||
    } catch(libconfig::SettingNotFoundException& e) {
 | 
					    } catch(libconfig::SettingNotFoundException& e) {
 | 
				
			||||||
        // Ignore
 | 
					        // Ignore
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(InputDevice::getLowResAxis(_axis) != -1)
 | 
				
			||||||
 | 
					        _multiplier *= 120;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int AxisGesture::Config::axis() const
 | 
					unsigned int AxisGesture::Config::axis() const
 | 
				
			||||||
@@ -124,3 +151,21 @@ double AxisGesture::Config::multiplier() const
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    return _multiplier;
 | 
					    return _multiplier;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool AxisGesture::wheelCompatibility() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AxisGesture::Config::setHiresMultiplier(double multiplier)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(_hires_multiplier == multiplier || multiplier == 0)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(InputDevice::getLowResAxis(_axis) != -1) {
 | 
				
			||||||
 | 
					        _multiplier *= _hires_multiplier;
 | 
				
			||||||
 | 
					        _multiplier /= multiplier;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _hires_multiplier = multiplier;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -28,26 +28,32 @@ namespace logid {
 | 
				
			|||||||
        public:
 | 
					        public:
 | 
				
			||||||
            AxisGesture(Device* device, libconfig::Setting& root);
 | 
					            AxisGesture(Device* device, libconfig::Setting& root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            virtual void press();
 | 
					            virtual void press(bool init_threshold=false);
 | 
				
			||||||
            virtual void release(bool primary=false);
 | 
					            virtual void release(bool primary=false);
 | 
				
			||||||
            virtual void move(int16_t axis);
 | 
					            virtual void move(int16_t axis);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            virtual bool wheelCompatibility() const;
 | 
				
			||||||
            virtual bool metThreshold() const;
 | 
					            virtual bool metThreshold() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void setHiresMultiplier(double multiplier);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            class Config : public Gesture::Config
 | 
					            class Config : public Gesture::Config
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
            public:
 | 
					            public:
 | 
				
			||||||
                Config(Device* device, libconfig::Setting& setting);
 | 
					                Config(Device* device, libconfig::Setting& setting);
 | 
				
			||||||
                unsigned int axis() const;
 | 
					                unsigned int axis() const;
 | 
				
			||||||
                double multiplier() const;
 | 
					                double multiplier() const;
 | 
				
			||||||
 | 
					                void setHiresMultiplier(double multiplier);
 | 
				
			||||||
            private:
 | 
					            private:
 | 
				
			||||||
                unsigned int _axis;
 | 
					                unsigned int _axis;
 | 
				
			||||||
                double _multiplier = 1;
 | 
					                double _multiplier = 1;
 | 
				
			||||||
 | 
					                double _hires_multiplier = 1;
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected:
 | 
					        protected:
 | 
				
			||||||
            int16_t _axis;
 | 
					            int16_t _axis;
 | 
				
			||||||
            double _axis_remainder;
 | 
					            double _axis_remainder;
 | 
				
			||||||
 | 
					            int _hires_remainder;
 | 
				
			||||||
            Config _config;
 | 
					            Config _config;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }}
 | 
					    }}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,10 +42,11 @@ namespace actions
 | 
				
			|||||||
    class Gesture
 | 
					    class Gesture
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        virtual void press() = 0;
 | 
					        virtual void press(bool init_threshold=false) = 0;
 | 
				
			||||||
        virtual void release(bool primary=false) = 0;
 | 
					        virtual void release(bool primary=false) = 0;
 | 
				
			||||||
        virtual void move(int16_t axis) = 0;
 | 
					        virtual void move(int16_t axis) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual bool wheelCompatibility() const = 0;
 | 
				
			||||||
        virtual bool metThreshold() const = 0;
 | 
					        virtual bool metThreshold() const = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class Config
 | 
					        class Config
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,9 +25,9 @@ IntervalGesture::IntervalGesture(Device *device, libconfig::Setting &root) :
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void IntervalGesture::press()
 | 
					void IntervalGesture::press(bool init_threshold)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _axis = 0;
 | 
					    _axis = init_threshold ? _config.threshold() : 0;
 | 
				
			||||||
    _interval_pass_count = 0;
 | 
					    _interval_pass_count = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,6 +52,11 @@ void IntervalGesture::move(int16_t axis)
 | 
				
			|||||||
    _interval_pass_count = new_interval_count;
 | 
					    _interval_pass_count = new_interval_count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool IntervalGesture::wheelCompatibility() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool IntervalGesture::metThreshold() const
 | 
					bool IntervalGesture::metThreshold() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return _axis >= _config.threshold();
 | 
					    return _axis >= _config.threshold();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,10 +28,11 @@ namespace actions
 | 
				
			|||||||
    public:
 | 
					    public:
 | 
				
			||||||
        IntervalGesture(Device* device, libconfig::Setting& root);
 | 
					        IntervalGesture(Device* device, libconfig::Setting& root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void press();
 | 
					        virtual void press(bool init_threshold=false);
 | 
				
			||||||
        virtual void release(bool primary=false);
 | 
					        virtual void release(bool primary=false);
 | 
				
			||||||
        virtual void move(int16_t axis);
 | 
					        virtual void move(int16_t axis);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual bool wheelCompatibility() const;
 | 
				
			||||||
        virtual bool metThreshold() const;
 | 
					        virtual bool metThreshold() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class Config : public Gesture::Config
 | 
					        class Config : public Gesture::Config
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,9 +24,9 @@ NullGesture::NullGesture(Device *device, libconfig::Setting& setting) :
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NullGesture::press()
 | 
					void NullGesture::press(bool init_threshold)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _axis = 0;
 | 
					    _axis = init_threshold ? _config.threshold() : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NullGesture::release(bool primary)
 | 
					void NullGesture::release(bool primary)
 | 
				
			||||||
@@ -40,6 +40,11 @@ void NullGesture::move(int16_t axis)
 | 
				
			|||||||
    _axis += axis;
 | 
					    _axis += axis;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool NullGesture::wheelCompatibility() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool NullGesture::metThreshold() const
 | 
					bool NullGesture::metThreshold() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return _axis > _config.threshold();
 | 
					    return _axis > _config.threshold();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,10 +28,11 @@ namespace actions
 | 
				
			|||||||
    public:
 | 
					    public:
 | 
				
			||||||
        NullGesture(Device* device, libconfig::Setting& setting);
 | 
					        NullGesture(Device* device, libconfig::Setting& setting);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void press();
 | 
					        virtual void press(bool init_threshold=false);
 | 
				
			||||||
        virtual void release(bool primary=false);
 | 
					        virtual void release(bool primary=false);
 | 
				
			||||||
        virtual void move(int16_t axis);
 | 
					        virtual void move(int16_t axis);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual bool wheelCompatibility() const;
 | 
				
			||||||
        virtual bool metThreshold() const;
 | 
					        virtual bool metThreshold() const;
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
        int16_t _axis;
 | 
					        int16_t _axis;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,9 +24,9 @@ ReleaseGesture::ReleaseGesture(Device *device, libconfig::Setting &root) :
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ReleaseGesture::press()
 | 
					void ReleaseGesture::press(bool init_threshold)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _axis = 0;
 | 
					    _axis = init_threshold ? _config.threshold() : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ReleaseGesture::release(bool primary)
 | 
					void ReleaseGesture::release(bool primary)
 | 
				
			||||||
@@ -42,6 +42,11 @@ void ReleaseGesture::move(int16_t axis)
 | 
				
			|||||||
    _axis += axis;
 | 
					    _axis += axis;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ReleaseGesture::wheelCompatibility() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ReleaseGesture::metThreshold() const
 | 
					bool ReleaseGesture::metThreshold() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return _axis >= _config.threshold();
 | 
					    return _axis >= _config.threshold();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,10 +28,11 @@ namespace actions
 | 
				
			|||||||
    public:
 | 
					    public:
 | 
				
			||||||
        ReleaseGesture(Device* device, libconfig::Setting& root);
 | 
					        ReleaseGesture(Device* device, libconfig::Setting& root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void press();
 | 
					        virtual void press(bool init_threshold=false);
 | 
				
			||||||
        virtual void release(bool primary=false);
 | 
					        virtual void release(bool primary=false);
 | 
				
			||||||
        virtual void move(int16_t axis);
 | 
					        virtual void move(int16_t axis);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual bool wheelCompatibility() const;
 | 
				
			||||||
        virtual bool metThreshold() const;
 | 
					        virtual bool metThreshold() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,7 +75,7 @@ namespace hidpp20
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            bool hiRes;
 | 
					            bool hiRes;
 | 
				
			||||||
            uint8_t periods;
 | 
					            uint8_t periods;
 | 
				
			||||||
            uint16_t deltaV;
 | 
					            int16_t deltaV;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        explicit HiresScroll(Device* device);
 | 
					        explicit HiresScroll(Device* device);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,10 +17,15 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#include "HiresScroll.h"
 | 
					#include "HiresScroll.h"
 | 
				
			||||||
#include "../Device.h"
 | 
					#include "../Device.h"
 | 
				
			||||||
 | 
					#include "../InputDevice.h"
 | 
				
			||||||
 | 
					#include "../actions/gesture/Gesture.h"
 | 
				
			||||||
 | 
					#include "../actions/gesture/AxisGesture.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace logid::features;
 | 
					using namespace logid::features;
 | 
				
			||||||
using namespace logid::backend;
 | 
					using namespace logid::backend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MOVE_EVENTHANDLER_NAME "HIRES_SCROLL"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HiresScroll::HiresScroll(Device *dev) : DeviceFeature(dev), _config(dev)
 | 
					HiresScroll::HiresScroll(Device *dev) : DeviceFeature(dev), _config(dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
@@ -28,6 +33,32 @@ HiresScroll::HiresScroll(Device *dev) : DeviceFeature(dev), _config(dev)
 | 
				
			|||||||
    } catch(hidpp20::UnsupportedFeature& e) {
 | 
					    } catch(hidpp20::UnsupportedFeature& e) {
 | 
				
			||||||
        throw UnsupportedFeature();
 | 
					        throw UnsupportedFeature();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(_config.upAction()) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            auto up_axis = std::dynamic_pointer_cast<actions::AxisGesture>(
 | 
				
			||||||
 | 
					                    _config.upAction());
 | 
				
			||||||
 | 
					            if(up_axis)
 | 
				
			||||||
 | 
					                up_axis->setHiresMultiplier(
 | 
				
			||||||
 | 
					                        _hires_scroll->getCapabilities().multiplier);
 | 
				
			||||||
 | 
					        } catch(std::bad_cast& e) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _config.upAction()->press(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(_config.downAction()) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            auto down_axis = std::dynamic_pointer_cast<actions::AxisGesture>(
 | 
				
			||||||
 | 
					                    _config.downAction());
 | 
				
			||||||
 | 
					            if(down_axis)
 | 
				
			||||||
 | 
					                down_axis->setHiresMultiplier(
 | 
				
			||||||
 | 
					                        _hires_scroll->getCapabilities().multiplier);
 | 
				
			||||||
 | 
					        } catch(std::bad_cast& e) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _config.downAction()->press(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _last_scroll = std::chrono::system_clock::now();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void HiresScroll::configure()
 | 
					void HiresScroll::configure()
 | 
				
			||||||
@@ -40,7 +71,21 @@ void HiresScroll::configure()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void HiresScroll::listen()
 | 
					void HiresScroll::listen()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ///TODO: Map hires scroll events
 | 
					    if(_device->hidpp20().eventHandlers().find(MOVE_EVENTHANDLER_NAME) ==
 | 
				
			||||||
 | 
					       _device->hidpp20().eventHandlers().end()) {
 | 
				
			||||||
 | 
					        auto handler = std::make_shared<hidpp::EventHandler>();
 | 
				
			||||||
 | 
					        handler->condition = [index=_hires_scroll->featureIndex()]
 | 
				
			||||||
 | 
					                (hidpp::Report& report)->bool {
 | 
				
			||||||
 | 
					            return (report.feature() == index) && (report.function() ==
 | 
				
			||||||
 | 
					                hidpp20::HiresScroll::WheelMovement);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        handler->callback = [this](hidpp::Report& report)->void {
 | 
				
			||||||
 | 
					            this->_handleScroll(_hires_scroll->wheelMovementEvent(report));
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _device->hidpp20().addEventHandler(MOVE_EVENTHANDLER_NAME, handler);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t HiresScroll::getMode()
 | 
					uint8_t HiresScroll::getMode()
 | 
				
			||||||
@@ -53,6 +98,48 @@ void HiresScroll::setMode(uint8_t mode)
 | 
				
			|||||||
    _hires_scroll->setMode(mode);
 | 
					    _hires_scroll->setMode(mode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void HiresScroll::_handleScroll(hidpp20::HiresScroll::WheelStatus event)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    auto now = std::chrono::system_clock::now();
 | 
				
			||||||
 | 
					    if(std::chrono::duration_cast<std::chrono::seconds>(
 | 
				
			||||||
 | 
					            now - _last_scroll).count() >= 1) {
 | 
				
			||||||
 | 
					        if(_config.upAction()) {
 | 
				
			||||||
 | 
					            _config.upAction()->release();
 | 
				
			||||||
 | 
					            _config.upAction()->press(true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(_config.downAction()) {
 | 
				
			||||||
 | 
					            _config.downAction()->release();
 | 
				
			||||||
 | 
					            _config.downAction()->press(true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _last_direction = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(event.deltaV > 0) {
 | 
				
			||||||
 | 
					        if(_last_direction == -1) {
 | 
				
			||||||
 | 
					            if(_config.downAction()){
 | 
				
			||||||
 | 
					                _config.downAction()->release();
 | 
				
			||||||
 | 
					                _config.downAction()->press(true);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(_config.upAction())
 | 
				
			||||||
 | 
					            _config.upAction()->move(event.deltaV);
 | 
				
			||||||
 | 
					        _last_direction = 1;
 | 
				
			||||||
 | 
					    } else if(event.deltaV < 0) {
 | 
				
			||||||
 | 
					        if(_last_direction == 1) {
 | 
				
			||||||
 | 
					            if(_config.upAction()){
 | 
				
			||||||
 | 
					                _config.upAction()->release();
 | 
				
			||||||
 | 
					                _config.upAction()->press(true);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(_config.downAction())
 | 
				
			||||||
 | 
					            _config.downAction()->move(-event.deltaV);
 | 
				
			||||||
 | 
					        _last_direction = -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _last_scroll = now;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HiresScroll::Config::Config(Device *dev) : DeviceFeature::Config(dev)
 | 
					HiresScroll::Config::Config(Device *dev) : DeviceFeature::Config(dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
@@ -99,6 +186,48 @@ HiresScroll::Config::Config(Device *dev) : DeviceFeature::Config(dev)
 | 
				
			|||||||
                          target.getSourceLine());
 | 
					                          target.getSourceLine());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch(libconfig::SettingNotFoundException& e) { }
 | 
					        } catch(libconfig::SettingNotFoundException& e) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(_mode & hidpp20::HiresScroll::Mode::Target) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                auto& up = config_root.lookup("up");
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    auto g = actions::Gesture::makeGesture(dev, up);
 | 
				
			||||||
 | 
					                    if(g->wheelCompatibility()) {
 | 
				
			||||||
 | 
					                        _up_action = g;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        logPrintf(WARN, "Line %d: This gesture cannot be used"
 | 
				
			||||||
 | 
					                                        " as a scroll action.",
 | 
				
			||||||
 | 
					                                        up.getSourceLine());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } catch(actions::InvalidGesture& e) {
 | 
				
			||||||
 | 
					                    logPrintf(WARN, "Line %d: Invalid scroll action",
 | 
				
			||||||
 | 
					                            up.getSourceLine());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } catch(libconfig::SettingNotFoundException&) {
 | 
				
			||||||
 | 
					                logPrintf(WARN, "Line %d: target is true but no up action was"
 | 
				
			||||||
 | 
					                                " set", config_root.getSourceLine());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                auto& down = config_root.lookup("down");
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    auto g = actions::Gesture::makeGesture(dev, down);
 | 
				
			||||||
 | 
					                    if(g->wheelCompatibility()) {
 | 
				
			||||||
 | 
					                        _down_action = g;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        logPrintf(WARN, "Line %d: This gesture cannot be used"
 | 
				
			||||||
 | 
					                                        " as a scroll action.",
 | 
				
			||||||
 | 
					                                  down.getSourceLine());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } catch(actions::InvalidGesture& e) {
 | 
				
			||||||
 | 
					                    logPrintf(WARN, "Line %d: Invalid scroll action",
 | 
				
			||||||
 | 
					                              down.getSourceLine());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } catch(libconfig::SettingNotFoundException&) {
 | 
				
			||||||
 | 
					                logPrintf(WARN, "Line %d: target is true but no down action was"
 | 
				
			||||||
 | 
					                                " set", config_root.getSourceLine());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    } catch(libconfig::SettingNotFoundException& e) {
 | 
					    } catch(libconfig::SettingNotFoundException& e) {
 | 
				
			||||||
        // HiresScroll not configured, use default
 | 
					        // HiresScroll not configured, use default
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -113,3 +242,15 @@ uint8_t HiresScroll::Config::getMask() const
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    return _mask;
 | 
					    return _mask;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const std::shared_ptr<logid::actions::Gesture>&
 | 
				
			||||||
 | 
					        HiresScroll::Config::upAction() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return _up_action;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const std::shared_ptr<logid::actions::Gesture>&
 | 
				
			||||||
 | 
					        HiresScroll::Config::downAction() const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return _down_action;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -20,6 +20,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "../backend/hidpp20/features/HiresScroll.h"
 | 
					#include "../backend/hidpp20/features/HiresScroll.h"
 | 
				
			||||||
#include "DeviceFeature.h"
 | 
					#include "DeviceFeature.h"
 | 
				
			||||||
 | 
					#include "../actions/gesture/Gesture.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace logid {
 | 
					namespace logid {
 | 
				
			||||||
namespace features
 | 
					namespace features
 | 
				
			||||||
@@ -40,12 +41,21 @@ namespace features
 | 
				
			|||||||
            explicit Config(Device* dev);
 | 
					            explicit Config(Device* dev);
 | 
				
			||||||
            uint8_t getMode() const;
 | 
					            uint8_t getMode() const;
 | 
				
			||||||
            uint8_t getMask() const;
 | 
					            uint8_t getMask() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const std::shared_ptr<actions::Gesture>& upAction() const;
 | 
				
			||||||
 | 
					            const std::shared_ptr<actions::Gesture>& downAction() const;
 | 
				
			||||||
        protected:
 | 
					        protected:
 | 
				
			||||||
            uint8_t _mode;
 | 
					            uint8_t _mode;
 | 
				
			||||||
            uint8_t _mask;
 | 
					            uint8_t _mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::shared_ptr<actions::Gesture> _up_action;
 | 
				
			||||||
 | 
					            std::shared_ptr<actions::Gesture> _down_action;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
 | 
					        void _handleScroll(backend::hidpp20::HiresScroll::WheelStatus event);
 | 
				
			||||||
        std::shared_ptr<backend::hidpp20::HiresScroll> _hires_scroll;
 | 
					        std::shared_ptr<backend::hidpp20::HiresScroll> _hires_scroll;
 | 
				
			||||||
 | 
					        std::chrono::time_point<std::chrono::system_clock> _last_scroll;
 | 
				
			||||||
 | 
					        int16_t _last_direction = 0;
 | 
				
			||||||
        Config _config;
 | 
					        Config _config;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}}
 | 
					}}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user