Medius - Rust LibraryMove

Move

Cursor motion and scroll

One field-generic verb, move_axis, drives the relative axes; the rest are thin wrappers over it. Each call queues one fire-and-forget MOVE frame.

Drive a...Rides a real moveGoes on the box's clock
cursormove_relmove_rel_now
wheelwheelwheel_now

The right-hand column only differs while movement riding is on. flush_motion and discard_motion act on motion it is already holding.

move_axis

Field-generic motion verb
fn move_axis(&self, motion: Motion, timing: MoveTiming, pending: PendingMotion) -> Result<()>

Fire-and-forget

ParameterTypeDescription
motionMotionThe axis to drive: Cursor { dx, dy } or Wheel(dz).
timingMoveTimingWhether this delta waits for a real move or emits on the box's own clock.
pendingPendingMotionWhat happens to motion the box is already holding for a real move.

Backs the MOVE command; the last two are its flags byte. With movement riding off, Now and Flush change nothing, while Discard still drops whatever has accumulated since the last emit.

EXAMPLE
use medius::{Motion, MoveTiming, PendingMotion};

device.move_axis(Motion::Cursor { dx: 20, dy: 20 }, MoveTiming::Ride, PendingMotion::Keep)?;
device.move_axis(Motion::Wheel(1), MoveTiming::Ride, PendingMotion::Keep)?;
// Send this one now, and the held motion with it.
device.move_axis(Motion::Cursor { dx: 5, dy: 0 }, MoveTiming::Now, PendingMotion::Flush)?;

move_rel

Relative cursor movement
fn move_rel(&self, dx: i16, dy: i16) -> Result<()>

Fire-and-forget

A wrapper over move_axis with Motion::Cursor.

ParameterTypeDescription
dxi16Horizontal offset in mouse counts. Positive moves right, negative moves left.
dyi16Vertical offset in mouse counts. Positive moves down, negative moves up (screen-style, not math-style).

Counts are not pixels: the OS pointer-speed and acceleration curve scale them. Both span the full i16 range (-32768 to 32767).

EXAMPLE
device.move_rel(20, 20)?;  // right and down
device.move_rel(-40, 0)?;  // left
device.move_rel(0, -10)?;  // up

wheel

Wheel scroll
fn wheel(&self, delta: i16) -> Result<()>

Fire-and-forget

A wrapper over move_axis with Motion::Wheel.

ParameterTypeDescription
deltai16Scroll steps. Positive scrolls up, negative scrolls down.

delta spans the full i16 range (-32768 to 32767) and feeds the same accumulator as cursor motion, pacing large values across reports.

EXAMPLE
device.wheel(3)?;   // up three notches
device.wheel(-1)?;  // down one notch

move_rel_now

Cursor movement that bypasses riding
fn move_rel_now(&self, dx: i16, dy: i16) -> Result<()>

Fire-and-forget

ParameterTypeDescription
dxi16Horizontal offset in mouse counts. Positive moves right, negative moves left.
dyi16Vertical offset in mouse counts. Positive moves down, negative moves up.

move_rel with MoveTiming::Now: the delta emits on the box's own clock rather than waiting for a real move to carry it, and leaves held motion held.

EXAMPLE
device.set_movement_riding(Some(Duration::from_millis(20)))?;
device.move_rel(100, 0)?;      // waits for the user to move, dropped if they don't
device.move_rel_now(100, 0)?;  // emits whether they move or not

wheel_now

Scroll that bypasses riding
fn wheel_now(&self, delta: i16) -> Result<()>

Fire-and-forget

ParameterTypeDescription
deltai16Scroll steps. Positive scrolls up, negative scrolls down.

wheel with MoveTiming::Now.

EXAMPLE
device.wheel_now(-1)?;  // one notch down, on the box's clock

flush_motion

Send what riding is holding
fn flush_motion(&self) -> Result<()>

Fire-and-forget

EFFECT
AccumulatorWhat flush does
RidingEmptied onto the box's own clock, whatever the ride window says. Sends no motion of its own.
ImmediateGains that amount, so it goes out on the next frame the box emits.
EXAMPLE
for _ in 0..10 {
    device.move_rel(4, 0)?;   // accumulates, waiting for a real move
}
device.flush_motion()?;       // 40 counts, now

discard_motion

Drop what riding is holding
fn discard_motion(&self) -> Result<()>

Fire-and-forget

EFFECT
StateWhat discard does
Riding accumulatorZeroed. That motion never reaches the game PC.
Immediate accumulatorUntouched, so a move sent with MoveTiming::Now still lands.
BearingCleared with it: a discarded delta is never emitted, so every With / Against scale stops applying until the box injects again.

Unlike reset, no held usage or lock is released.

EXAMPLE
device.move_rel(400, 0)?;   // queued, then superseded
device.discard_motion()?;   // it never reaches the game PC

On AsyncDevice

Movement stays synchronous

AsyncDevice keeps every movement verb synchronous: no .await, same signatures. The block_on pattern is only for async queries.

EXAMPLE
let dev = Device::find()?.into_async();
dev.move_rel(40, 0)?;  // no .await
dev.wheel(1)?;