medius 3.4.6

Rust library for Medius, replacement firmware for the MAKCU box
Documentation
use crate::error::Result;
use crate::protocol::FrameType;
use crate::protocol::command::{move_cursor_payload, move_pan_payload, move_wheel_payload};
use crate::types::{Motion, MoveTiming, PendingMotion};

use super::Device;

impl Device {
    /// `MOVE` (cursor): relative cursor motion; full `i16`, no clamp.
    pub fn move_rel(&self, dx: i16, dy: i16) -> Result<()> {
        self.move_axis(
            Motion::Cursor { dx, dy },
            MoveTiming::Ride,
            PendingMotion::Keep,
        )
    }

    /// `MOVE` (wheel): vertical scroll; full `i16`, no clamp.
    pub fn wheel(&self, delta: i16) -> Result<()> {
        self.move_axis(Motion::Wheel(delta), MoveTiming::Ride, PendingMotion::Keep)
    }

    /// `MOVE` (cursor) bypassing movement riding: emitted on the next mouse report, native or made
    /// by the box. Motion already held for a ride stays held.
    pub fn move_rel_now(&self, dx: i16, dy: i16) -> Result<()> {
        self.move_axis(
            Motion::Cursor { dx, dy },
            MoveTiming::Now,
            PendingMotion::Keep,
        )
    }

    /// `MOVE` (wheel) bypassing movement riding.
    pub fn wheel_now(&self, delta: i16) -> Result<()> {
        self.move_axis(Motion::Wheel(delta), MoveTiming::Now, PendingMotion::Keep)
    }

    /// `MOVE` (AC Pan): horizontal scroll; full `i16`, no clamp.
    pub fn pan(&self, delta: i16) -> Result<()> {
        self.move_axis(Motion::Pan(delta), MoveTiming::Ride, PendingMotion::Keep)
    }

    /// `MOVE` (AC Pan) bypassing movement riding.
    pub fn pan_now(&self, delta: i16) -> Result<()> {
        self.move_axis(Motion::Pan(delta), MoveTiming::Now, PendingMotion::Keep)
    }

    /// `MOVE` (zero delta, `FLUSH`): emit motion held for a ride now, ignoring the ride window.
    pub fn flush_motion(&self) -> Result<()> {
        self.move_axis(
            Motion::Cursor { dx: 0, dy: 0 },
            MoveTiming::Ride,
            PendingMotion::Flush,
        )
    }

    /// `MOVE` (zero delta, `DISCARD`): drop motion held for a ride. Motion sent with
    /// [`move_rel_now`](Self::move_rel_now) is untouched.
    pub fn discard_motion(&self) -> Result<()> {
        self.move_axis(
            Motion::Cursor { dx: 0, dy: 0 },
            MoveTiming::Ride,
            PendingMotion::Discard,
        )
    }

    /// `MOVE`: drive a relative axis, choosing when the delta is emitted and what happens to motion
    /// already held for a ride.
    pub fn move_axis(
        &self,
        motion: Motion,
        timing: MoveTiming,
        pending: PendingMotion,
    ) -> Result<()> {
        let flags = timing.as_u8() | pending.as_u8();
        match motion {
            Motion::Cursor { dx, dy } => self
                .link
                .send(FrameType::Move, &move_cursor_payload(dx, dy, flags)),
            Motion::Wheel(dz) => self
                .link
                .send(FrameType::Move, &move_wheel_payload(dz, flags)),
            Motion::Pan(dpan) => self
                .link
                .send(FrameType::Move, &move_pan_payload(dpan, flags)),
        }
    }
}