Files
2025-08-10 14:14:04 -05:00

76 lines
3.1 KiB
Markdown

# `osui::extensions::input_handling`
The `input_handling` module provides the `InputExtension`, which integrates `crossterm` for low-level terminal input and dispatches these events throughout the OSUI system. This is a fundamental extension required for any interactive OSUI application.
## `InputExtension`
Manages raw terminal input and dispatches `crossterm` events.
```rust
pub struct InputExtension;
```
### `Extension` Trait Implementation
#### `init(&mut self, ctx: &Context)`
Called when the extension is initialized.
1. Enables `crossterm`'s raw mode (`crossterm::terminal::enable_raw_mode().unwrap()`). Raw mode allows direct, unbuffered input capture, essential for TUI applications.
2. Spawns a new thread. This thread continuously listens for `crossterm::event::read()` events.
3. Whenever an event is read successfully, it dispatches the event using `ctx.event(&e)`. This makes the `crossterm::event::Event` available to all widgets (via `Element::event` or `Handler<crossterm::event::Event>` components) and other extensions.
**Why a separate thread?**
Reading input from the terminal (`crossterm::event::read()`) is a blocking operation. Spawning it in a separate thread prevents the main rendering loop from freezing while waiting for user input, ensuring the UI remains responsive.
#### `on_close(&mut self)`
Called when `Screen::close()` is invoked.
1. Disables `crossterm`'s raw mode (`crossterm::terminal::disable_raw_mode().unwrap()`). This restores the terminal to its normal, buffered input state, which is crucial for a clean exit.
### `Event` Trait Implementation
The `crossterm::event::Event` enum itself implements OSUI's `Event` trait, allowing `InputExtension` to dispatch it directly.
```rust
impl crate::extensions::Event for crossterm::event::Event {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
```
This means you can easily listen for `crossterm` events in your widgets or other extensions using `Handler<crossterm::event::Event>` or by downcasting the `dyn Event` in an `Extension::event` method.
## Usage
You must register the `InputExtension` with your `Screen` for keyboard and mouse input to work in your OSUI application.
**Example:**
```rust
use osui::prelude::*;
fn main() -> std::io::Result<()> {
let screen = Screen::new();
// Register the InputExtension
screen.extension(InputExtension);
// Other extensions and UI setup
screen.extension(RelativeFocusExtension::new()); // Often used with InputExtension for navigation
rsx! {
// A global event handler to exit on Escape key, relying on InputExtension
@Handler::new({
let screen = screen.clone();
move |_, e: &crossterm::event::Event| {
if let crossterm::event::Event::Key(crossterm::event::KeyEvent { code: crossterm::event::KeyCode::Esc, .. }) = e {
screen.close();
}
}
});
// An Input widget that will receive key events from InputExtension
Input { }
}.draw(&screen);
screen.run()
}
```
`InputExtension` is a foundational component for building interactive terminal user interfaces with OSUI.