app_input/lib.rs
1// SPDX-License-Identifier: MPL-2.0
2/*!
3
4app_input is a cross-platform library for receiving keyboard and mouse events.
5
6# Design principles
7
8* Use the best modern backend on each platform
9* Zero magic, this library can be easily used without interference alongside any other native code.
10 * When native code may interfere, instead this library will be a no-op by default. You must
11 call into it from your eventloop before our events are delivered.
12* Mouse events:
13 * Mouse position is determined by the compositor. Platform-specific acceleration will be applied.
14 * This is appropriate for GUI apps and topdown strategy games, or anytime you have a system-drawn cursor.
15 It is appropriate for some fullscreen games. It is not appropriate for Counter Strike.
16 * Coordinates are translated into a platform-independent upper-left coordinate system that works everywhere
17 * Mouse events may require the window to be 'active' to be delivered, per platform conventions
18* Keyboard events:
19 * Report raw up/down events whenever possible
20 * We map hardware keys rather than unicode characters
21 * If you are trying to implement text input, you have much work to do, including but not limited to the shift key
22 * Keycodes are translated into a platform-independent enum that works everywhere
23 * On Linux, key events are broadcasted over ATSPI. Due to some [questionable decisions in the Linux ecosystem](https://github.com/AccessKit/accesskit/discussions/503#discussioncomment-11862133)
24 this is required for screenreaders to work but nobody does it. We do!
25
26
27# Supported platforms
28| Platform | Backend |
29|----------|--------------------------|
30| Windows | win32* |
31| macOS | AppKit |
32| Linux | Wayland* |
33| wasm32 | KeyboardEvent \| MouseEvent |
34| Yours | Send a PR! |
35
36
37* `*`: Needs platform-native event integration before events are delivered. Consider using [app_window](https://sealedabstract.com/code/app_window)!
38
39# WASM/JavaScript Support
40
41This library is also available as an npm package for JavaScript/TypeScript projects targeting WebAssembly.
42The package provides type definitions and can be used in web applications.
43
44*/
45///Provides information about keyboard events.
46pub mod keyboard;
47///Provides information about mouse events.
48pub mod mouse;
49
50/// Shows a debug window for testing keyboard input (macOS only).
51///
52/// This function displays a native window that can be used to test keyboard input
53/// without interference from other applications. Useful for debugging keyboard event handling.
54///
55/// # Platform availability
56/// - Currently only implemented on macOS
57/// - No-op on other platforms
58pub use keyboard::sys::debug_window_show;
59
60/// Hides the debug window (macOS only).
61///
62/// Closes the debug window that was previously shown with `debug_window_show()`.
63///
64/// # Platform availability
65/// - Currently only implemented on macOS
66/// - No-op on other platforms
67pub use keyboard::sys::debug_window_hide;
68
69/**
70Provides information about the window an event was delivered to.
71
72# Platform specifics
73* On Windows, this value contains an HWND.
74* on macOS, this is the pointer of an NSWindow. No memory management is performed, so dereferencing the window may be invalid.
75* on wasm32, we attach to the global DOM window, and we choose an opaque value arbitrarily for this type.
76* on Linux, we return the wayland surface ID. No memory management is performed, so values may refer to previous surfaces, etc.
77*/
78#[derive(Debug, Copy, Clone)]
79pub struct Window(pub std::ptr::NonNull<std::ffi::c_void>);
80//we don't do anything with it so it's fine to send
81unsafe impl Send for Window {}
82
83#[cfg(target_os = "linux")]
84pub mod linux {
85 pub use crate::keyboard::linux::wl_keyboard_event;
86 pub use crate::mouse::linux::{button_event, motion_event, xdg_toplevel_configure_event};
87}
88
89#[cfg(target_os = "windows")]
90use windows::Win32::Foundation::{HWND, LPARAM, LRESULT, WPARAM};
91#[cfg(target_os = "windows")]
92pub fn window_proc(hwnd: HWND, msg: u32, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
93 if mouse::windows::window_proc(hwnd, msg, w_param, l_param) == LRESULT(0)
94 || keyboard::windows::kbd_window_proc(hwnd, msg, w_param, l_param) == LRESULT(0)
95 {
96 LRESULT(0)
97 } else {
98 LRESULT(1)
99 }
100}