<!-- Source: https://medius.k4tech.net/library/lock -->
# Lock

_Block one physical input; injection still drives it_

A lock blocks the _physical_ device from one input, while host [injection](/native/injection.md) still drives that same input. Lock what the user shouldn't touch, then drive it yourself.

```
  a locked input:
     physical  --X   blocked
     injected  -->   still reaches the PC
```

| Block a... | Lock | Release |
| --- | --- | --- |
| relative axis (X / Y / wheel) | [`lock`](/library/lock.md#lock) / [`lock_axis`](/library/lock.md#lock-axis) | [`unlock`](/library/lock.md#unlock) / [`unlock_axis`](/library/lock.md#lock-axis) |
| button, key, or media usage | [`lock`](/library/lock.md#lock) | [`unlock`](/library/lock.md#unlock) |
| a whole class (blanket) | [`lock_all`](/library/lock.md#lock-all) | [`unlock_all`](/library/lock.md#lock-all) |

All are [fire-and-forget](/native/injection.md#fire-and-forget): one frame, no reply. [`query_locks`](/library/requests.md#query-locks) reads the active set.

## lock

_Block a physical input_

```text
fn lock(&self, target: impl Into<LockTarget>, direction: LockDirection) -> Result<()>
```

_Fire-and-forget_

[`LockTarget`](/library/types/enums.md#lock-target) picks the input and [`LockDirection`](/library/types/enums.md#lock-direction) picks the sign or edge. For an axis or the wheel the direction is a sign, so you can block scrolling up but not down; for a usage it's an edge, so you can block the press but not the release.

#### PARAMETERS

| Parameter | Type | Description |
| --- | --- | --- |
| `target` | `impl Into<[LockTarget](/library/types/enums.md#lock-target)>` | An [`Axis`](/library/types/enums.md#axis) (X, Y, or wheel) or any [`Usage`](/library/types/enums.md#usage) (a button, key, or media usage). |
| `direction` | [`LockDirection`](/library/types/enums.md#lock-direction) | `Both`, `Positive` (axis +, usage press), or `Negative` (axis -, usage release). |

A lock blocks the physical device only, and holds until you [`unlock`](/library/lock.md#unlock) it. The box also clears every lock on control-PC silence, on [`reset`](/library/admin.md#reset), or on inter-chip link loss. See the native [`LOCK`](/native/commands/lock.md#lock) command for the wire layout.

#### EXAMPLE

```rust
use medius::{Device, Axis, Button, Key, LockDirection};

let device = Device::find()?;
device.lock(Axis::X, LockDirection::Both)?;              // freeze horizontal motion
device.lock(Button::Left, LockDirection::Positive)?;     // block left-click press
device.lock(Key::LEFT_GUI, LockDirection::Both)?;        // block the GUI/Windows key
device.move_rel(50, 0)?;                                 // injection still moves X
```

## unlock

_Clear a block_

```text
fn unlock(&self, target: impl Into<LockTarget>, direction: LockDirection) -> Result<()>
```

_Fire-and-forget_

The inverse of [`lock`](/library/lock.md#lock): same `target` and `direction`, but it clears the block instead of setting it. Hand a physical input back to the user.

#### EXAMPLE

```rust
use medius::{Device, Axis, LockDirection};

let device = Device::find()?;
device.unlock(Axis::X, LockDirection::Both)?;   // hand horizontal motion back
```

## lock_axis / unlock_axis

_Block a relative axis by sign_

```text
fn lock_axis(&self, axis: Axis, direction: LockDirection) -> Result<()>
```

```text
fn unlock_axis(&self, axis: Axis, direction: LockDirection) -> Result<()>
```

_Fire-and-forget_

Convenience for [`lock`](/library/lock.md#lock) / [`unlock`](/library/lock.md#unlock) with an [`Axis`](/library/types/enums.md#axis). The direction is a sign, so a positive-only lock freezes scroll-up while scroll-down still passes.

#### EXAMPLE

```rust
use medius::{Device, Axis, LockDirection};

let device = Device::find()?;
device.lock_axis(Axis::Wheel, LockDirection::Positive)?; // block scroll up, keep scroll down
device.unlock_axis(Axis::Wheel, LockDirection::Positive)?;
```

## lock_all / unlock_all

_Blanket-block a whole class_

```text
fn lock_all(&self, what: Blanket, direction: LockDirection) -> Result<()>
```

```text
fn unlock_all(&self, what: Blanket, direction: LockDirection) -> Result<()>
```

_Fire-and-forget_

Block an entire input group at once with a [`Blanket`](/library/types/enums.md#blanket) (`Aim`, `Wheel`, `Buttons`, `Keys`, or `Media`); `direction` applies to the whole group. Injection still drives any field you choose to.

#### EXAMPLE

```rust
use medius::{Device, Blanket, LockDirection};

let device = Device::find()?;
device.lock_all(Blanket::Keys, LockDirection::Both)?;   // every physical key blocked
device.unlock_all(Blanket::Keys, LockDirection::Both)?;
```

## On AsyncDevice

_locks fire, query_locks awaits_

[`AsyncDevice`](/library/features/async.md) keeps every lock call synchronous (`lock`/`unlock`, `lock_axis`, and `lock_all` with their unlock pairs) since they expect no reply; `query_locks` is a future like the other queries.

#### EXAMPLE

```rust
use futures::executor::block_on;
use medius::{AsyncDevice, Axis, LockDirection};

let device = AsyncDevice::open("/dev/ttyACM0")?;
device.lock(Axis::Y, LockDirection::Both)?;   // sync, no await
let locks = block_on(device.query_locks())?;  // query awaits
```
