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}