Skip to content

Scroll and other mode for pointing devices #703

@Jaraxzus

Description

@Jaraxzus

Now there are a few modes for working with the trackball
I only use scroll mode, but there is also a high-precision mode, etc.
I searched through the source code and pool requests, and I liked the idea of an abstract PointingProcessor from PMW3360 and PMW3389 input devices
It seemed to me a good idea to make such modes options of the contact Pointing device, and not a specific implementation, since the algorithms are most likely universal for all devices, at least software implementations
I made one for myself

struct ScrollConfig {
    delta_per_tick: u8,
}

impl Default for ScrollConfig {
    fn default() -> Self {
        Self { delta_per_tick: 25 }
    }
}

struct MotionAccumulator {
    acc_x: i32,
    acc_y: i32,
}

impl MotionAccumulator {
    const fn new() -> Self {
        Self { acc_x: 0, acc_y: 0 }
    }

    fn process(&mut self, dx: i16, dy: i16, divisor: u8) -> (i16, i16) {
        self.acc_x += dx as i32;
        self.acc_y += dy as i32;

        let out_x = (self.acc_x / divisor as i32) as i16;
        let out_y = (self.acc_y / divisor as i32) as i16;

        self.acc_x -= out_x as i32 * divisor as i32;
        self.acc_y -= out_y as i32 * divisor as i32;

        (out_x, out_y)
    }

    fn reset(&mut self) {
        self.acc_x = 0;
        self.acc_y = 0;
    }
}

enum PointingMode {
    Cursor,
    Scroll {
        config: ScrollConfig,
        accumulator: MotionAccumulator,
    },
}

impl PointingMode {
    fn generate_report(&mut self, x: i16, y: i16) -> MouseReport {
        match self {
            Self::Cursor => MouseReport {
                buttons: 0,
                x: x.clamp(i8::MIN as i16, i8::MAX as i16) as i8,
                y: y.clamp(i8::MIN as i16, i8::MAX as i16) as i8,
                wheel: 0,
                pan: 0,
            },
            Self::Scroll { config, accumulator } => {
                let (pan, wheel) = accumulator.process(x, y, config.delta_per_tick);
                MouseReport {
                    buttons: 0,
                    x: 0,
                    y: 0,
                    wheel: wheel.clamp(i8::MIN as i16, i8::MAX as i16) as i8,
                    pan: pan.clamp(i8::MIN as i16, i8::MAX as i16) as i8,
                }
            }
        }
    }
}

But I haven't figured out how to push values from configs here, so I've hardcoded them at the initialization stage so far.

Next I found ScrollWheelProcessor in Add config for input devices
so far, I don't understand how this will work, with the current settings
in the presence of processor_chain, the current code will be ignored, for example in Pmw3610Processor::process? Since it also processes the delta arrival event and moves the cursor.
or you will also have to add scroll_mode: bool to Pmw3610Processor so that the main and auxiliary processors do not work together. But then there will be a strong connectivity of components, which doesn't look very good.

In general, I have some doubts about how this will work, which I decided to share with you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions