xkbcommon_rs/lib.rs
1#![allow(warnings)]
2// Includes comments and exports from include/xkbcommon/xkbcommon.h
3/*
4 * Copyright 1985, 1987, 1990, 1998 The Open Group
5 * Copyright 2008 Dan Nicholson
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Except as contained in this notice, the names of the authors or their
25 * institutions shall not be used in advertising or otherwise to promote the
26 * sale, use or other dealings in this Software without prior written
27 * authorization from the authors.
28 */
29
30/************************************************************
31 * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
32 *
33 * Permission to use, copy, modify, and distribute this
34 * software and its documentation for any purpose and without
35 * fee is hereby granted, provided that the above copyright
36 * notice appear in all copies and that both that copyright
37 * notice and this permission notice appear in supporting
38 * documentation, and that the name of Silicon Graphics not be
39 * used in advertising or publicity pertaining to distribution
40 * of the software without specific prior written permission.
41 * Silicon Graphics makes no representation about the suitability
42 * of this software for any purpose. It is provided "as is"
43 * without any express or implied warranty.
44 *
45 * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
46 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
47 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
48 * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
49 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
50 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
51 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
52 * THE USE OR PERFORMANCE OF THIS SOFTWARE.
53 *
54 ********************************************************/
55
56/*
57 * Copyright © 2009-2012 Daniel Stone
58 * Copyright © 2012 Intel Corporation
59 * Copyright © 2012 Ran Benita
60 * Copyright © 2024 wysiwys
61 *
62 * Permission is hereby granted, free of charge, to any person obtaining a
63 * copy of this software and associated documentation files (the "Software"),
64 * to deal in the Software without restriction, including without limitation
65 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
66 * and/or sell copies of the Software, and to permit persons to whom the
67 * Software is furnished to do so, subject to the following conditions:
68 *
69 * The above copyright notice and this permission notice (including the next
70 * paragraph) shall be included in all copies or substantial portions of the
71 * Software.
72 *
73 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
76 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
77 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
78 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
79 * DEALINGS IN THE SOFTWARE.
80 *
81 * Author: Daniel Stone <daniel@fooishbar.org>
82 */
83
84//!
85//! A port of `libxkbcommon` version `1.7.0` in safe Rust.
86//!
87//! ### Use in Wayland client
88//! This crate is intended for use within a Wayland client written in Rust. It provides `Send + Sync` implementations of [Keymap] and [State].
89//!
90//!
91//!
92//! ### Example
93//!
94//! To set up the keymap/state on the Wayland client side:
95//! ```rust
96//! use xkbcommon_rs::*;
97//!
98//! let keymap = Keymap::new_from_string(
99//! Context::new(0).unwrap(),
100//! string, /* Read from the OwnedFd provided by the Wayland compositor */
101//! KeymapFormat::TextV1,
102//! 0).unwrap();
103//!
104//! let mut state = State::new(keymap);
105//!
106//! ```
107//!
108//! To get keysyms and update the state on the client side:
109//!
110//!
111//! ```rust
112//! // Get syms before updating state
113//! let sym = state.key_get_one_sym(keycode)?;
114//!
115//! // Update state with the parameters provided by the wl_keyboard::Event::Modifiers{..} event
116//! state.update_mask(
117//! mods_depressed, mods_latched, mods_locked,
118//! 0, 0, group as usize);
119//! ```
120//!
121//! For more information on using [State::update_mask()] in a Wayland client, please see <https://wayland-book.com/seat/keyboard.html>.
122//!
123//! # Server state and client state
124//! The `xkb_state` API is used by two distinct actors in most window-system architectures:
125//! 1. A *server* - for example, a Wayland compositor, and X11 server, or an evdev listener.
126//!
127//! Servers maintain the XKB state for a device according to input events from the device, such as
128//! key presses and releases, and out-of-band events from the user, like UI layout switchers.
129//!
130//! 2. A *client* - for example, a Wayland client, an X11 client.
131//!
132//! Clients do not listen to input from the device; instead, whenever the server state changes, the
133//! server state serializes the state and notifies the clients that the state has changed; the
134//! clients then update the state from the serialization.
135//!
136//! Some entry points in the `xkb_state` API are only meant for servers and some are only meant for
137//! clients, and the two should generally not be mixed.
138//!
139//!
140//! # Environment variables
141//!
142//! As in `libxkbcommon`, the user may set some environment variables which affect the library:
143//!
144//! `XKB_CONFIG_ROOT`, `XKB_CONFIG_EXTRA_PATH`, `XDG_CONFIG_DIR`, `HOME` - see [include-path].
145//! `XKB_DEFAULT_RULES`, `XKB_DEFAULT_MODEL`, `XKB_DEFAULT_LAYOUT`, `XKB_DEFAULT_VARIANT`,
146//! `XKB_DEFAULT_OPTIONS` - see [xkb_keymap::RuleNames].
147//!
148#![cfg_attr(docsrs, feature(doc_auto_cfg))]
149#![allow(clippy::module_inception)]
150#![allow(clippy::unwrap_or_default)]
151#![allow(clippy::absurd_extreme_comparisons)]
152#![crate_name = "xkbcommon_rs"]
153#![forbid(unsafe_code)]
154
155mod keysyms_utf;
156
157// generated in project 26
158// TODO: migrate over to build.rs
159mod keysyms_generated_phf;
160
161mod keysyms;
162
163mod atom;
164mod context;
165mod errors;
166mod keymap;
167mod message_codes;
168mod state;
169
170mod rust_xkbcommon;
171mod xkbcomp;
172
173mod parser_utils;
174mod utils;
175
176mod text;
177mod utf8;
178
179mod config;
180
181pub mod error {
182 //! Various error types for the crate.
183
184 pub use super::errors::{context, keymap, state};
185}
186pub mod xkb_context {
187 //! The module containing the [Keymap](crate::Keymap)'s [Context] struct and its associated options.
188 //!
189 //! The [Context] contains general library data and state, and is passed to a Keymap's
190 //! constructor.
191 //! ### Usage
192 //! ```rust
193 //! let context = Context::new(0).unwrap();
194 //! ```
195 //! The [Context] is passed to a Keymap's constructor to initialize the keymap.
196 /// A [Keymap](crate::Keymap)'s context object.
197 ///
198 /// The context contains various general data and state, like include paths.
199 ///
200 /// ### Differences from libxkbcommon
201 /// In `libxkbcommon`, multiple objects may share one context. This feature has yet to be implemented in this crate, so for now each [Keymap](crate::Keymap) has its own [Context], which is not shared by other keymaps.
202 ///
203 pub use super::context::Context;
204
205 pub use super::rust_xkbcommon::ContextFlags;
206}
207pub use xkb_context::Context;
208
209pub mod xkb_keymap {
210
211 //! The module containing the [Keymap] struct and its associated options and metadata.
212 //!
213 //! The keymap is initialized from e.g. a string representation of the keymap passed by the
214 //! Wayland server.
215 //!
216 //! ### Creating a [Keymap]
217 //! ```rust
218 //! let keymap = Keymap::new_from_string(
219 //! context,
220 //! string, /* Read from the OwnedFd provided by the Wayland compositor */
221 //! KeymapFormat::TextV1,
222 //! 0 // compile flags
223 //! ).unwrap();
224 //! ```
225 //! It is standard to pass [KeymapFormat::TextV1] and `0` or
226 //! `CompileFlags::empty()` to this function.
227 //!
228 //! A keymap can also be generated from RMLVO:
229 //! ```rust
230 //! let keymap = Keymap::new_from_names(
231 //! context,
232 //! Some(rmlvo),
233 //! 0 // compile flags
234 //! ).unwrap();
235 //!
236 //! ```
237 //! ### Creating a [State](crate::State) from a [Keymap]
238 //! ```rust
239 //! let mut state = State::new(keymap);
240 //! ```
241
242 /// An immutable representation of a keymap compiled from an XKB file. Used by the
243 /// [State](crate::State) struct.
244 ///
245 /// The keymap object holds all of the static keyboard information obtained from compiling XKB
246 /// files.
247 ///
248 /// A keymap is immutable after it is created.
249 /// If you need to change it, you must create a new one.
250 pub use super::keymap::Keymap;
251
252 pub use super::rust_xkbcommon::CompileFlags;
253
254 /// An alternative format that can be used to initialize a [Keymap]. RMLVO = Rules, Model,
255 /// Layout, Variant, Options
256 ///
257 /// You should prefer passing `None` to [Keymap::new_from_names()] instead of choosing your own defaults.
258 pub use super::rust_xkbcommon::RuleNames;
259
260 pub use super::rust_xkbcommon::KeymapFormat;
261}
262pub use xkb_keymap::Keymap;
263pub use xkb_keymap::KeymapFormat;
264
265pub mod xkb_state {
266 //! The module containing the [State] and its associated metadata and options.
267 //! ### Creating a [State] from a [Keymap](crate::Keymap)
268 //! ```rust
269 //! let mut state = State::new(keymap);
270 //! ```
271 //! ### Use in a Wayland client
272 //! To update the [State] on the Wayland client side, use the functions enabled by the `client`
273 //! feature. For example, in Cargo.toml:
274 //! ```toml
275 //! [dependencies]
276 //! xkbcommon-rs = { version = "0.1.1", features = ["client"] }
277 //! ```
278 //! Then to update the state based on data passed by the compositor:
279 //! ```rust
280 //! // Get syms before updating state
281 //! let sym = state.key_get_one_sym(keycode)?;
282 //!
283 //! // Update state with the parameters provided by the wl_keyboard::Event::Modifiers{..} event
284 //! state.update_mask(
285 //! mods_depressed, mods_latched, mods_locked,
286 //! 0, 0, group as usize);
287 //! ```
288 //!
289 /// Keyboard state object.
290 ///
291 /// ### Creating a [State] from a [Keymap](crate::Keymap)
292 /// ```rust
293 /// let mut state = State::new(keymap);
294 /// ```
295 /// State objects contain the active state of a keyboard
296 /// (or keyboards), such
297 /// as the currently effective layout and the active modifiers.
298 /// It acts as a simple state machine, wherein key presses
299 /// and releases are the input, and key symbols (keysyms) are the output.
300 ///
301 /// ### Usage in Wayland
302 /// On the Wayland client side, a local keyboard State is maintained by the client, which is
303 /// updated to reflect changes in the compositor's state. These changes are communicated over
304 /// the Wayland protocol. To update the client's [State] to reflect these changes, the
305 /// functions in the `client` feature are used.
306 pub use super::state::State;
307
308 pub use super::rust_xkbcommon::KeyDirection;
309 /// Index of a keyboard layout.
310 ///
311 /// The layout index is a state component which determines which <em>keyboard layout</em> is
312 /// active. These may be different alphabets, different key arrangements, etc.
313 ///
314 /// Layout indices are consecutive. The first layout has index 0.
315 ///
316 /// Each layout is not required to have a name, and the names are not guaranteed to be unique
317 /// (though they are usually provided and unique).
318 /// Therefore, it is not safe to use the name as a unique identifier for a layout.
319 /// Layout names are case-sensitive.
320 ///
321 /// Layout names are specified in the layout's definition,
322 /// for example "English (US)". These are different from the
323 /// (conventionally) short names which are used to locate the layout,
324 /// for example "us" or "us(intl)". These names are not present
325 /// in a compiled keymap.
326 ///
327 /// If the user selects layouts from a list generated from the XKB registry (using libxkbregistry
328 /// or directly), it is recommended to store it along with the keymap.
329 ///
330 /// Layouts are also called "groups" by XKB.
331 ///
332 pub use super::rust_xkbcommon::LayoutIndex;
333
334 /// A mask of layout indices.
335 pub use super::rust_xkbcommon::LayoutMask;
336
337 /// Index of a shift level.
338 ///
339 pub use super::rust_xkbcommon::LevelIndex;
340
341 /// Index of a modifier.
342 ///
343 pub use super::rust_xkbcommon::ModIndex;
344
345 /// A mask of modifier indices.
346 ///
347 pub use super::rust_xkbcommon::ModMask;
348
349 /// Index of a keyboard LED.
350 ///
351 pub use super::rust_xkbcommon::LedIndex;
352
353 /// A mask of LED indices.
354 ///
355 pub use super::rust_xkbcommon::LedMask;
356
357 pub use super::rust_xkbcommon::names::*;
358 /// Consumed modifiers mode.
359 ///
360 /// There are several possible methods for deciding which modifiers are consumed and which are not,
361 /// each applicable for different systems or situations. The mode selects the method to use.
362 ///
363 /// Keep in mind that in all methods the keymap may decide to "preserve" a modifier, meaning it is
364 /// not reported as consumed even if it would have otherwise.
365 pub use super::rust_xkbcommon::ConsumedMode;
366
367 pub use super::rust_xkbcommon::StateComponent;
368
369 pub use super::rust_xkbcommon::StateMatch;
370
371 pub use super::keymap::XKB_MAX_GROUPS;
372}
373pub use xkb_state::State;
374
375/// A [Keycode](crate::keycode::Keycode) is a number used to represent a physical key on a keyboard.
376///
377/// A standard PC-compatible keyboard might have 102 keys.
378/// An appropriate keymap would assign each of them a keycode,
379/// by which the user should refer to the key throughout the library.
380///
381/// Historically, the X11 protocol, and consequentially the XKB protocol,
382/// assign only 8 bits for keycodes. This limits the number of different keys
383/// that can be used simultaneously in a single keymap to 256
384/// (disregarding other limitations). This library does not share this limit;
385/// keycodes beyond 255 ('extended keycodes') are not treated specially.
386/// Keymaps and applications which are compatible with X11
387/// should not use these keycodes.
388///
389/// The values of specific keycodes are determined by the keymap and the underlying input system.
390/// For example, with an X11-compatible keymap
391/// and Linux evdev scan codes (see [evdev::Key](https://docs.rs/evdev/latest/evdev/struct.Key.html)), a fixed offset is used:
392///
393/// ```
394/// use evdev::Key;
395/// let keycode_A = Keycode::new(Key::KEY_A + 8);
396/// ```
397///
398/// The keymap defines a canonical name for each key, plus possible aliases.
399/// Historically, the XKB protocol restricts these names to at most 4 (ASCII) characters,
400/// but this library does not share this limit.
401pub mod keycode {
402 //! The [Keycode](crate::keycode::Keycode) struct, which is used to update the [State].
403 //!
404 //! ### Usage in [State]:
405 //! ```rust
406 //! state.update_key(keycode_A, KeyDirection::Down);
407 //! state.update_key(keycode_A, KeyDirection::Up);
408 //!
409 //! ```
410 pub use super::rust_xkbcommon::RawKeycode;
411
412 /// A wrapper struct for [RawKeycode].
413 ///
414 #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq)]
415 pub struct Keycode(pub RawKeycode);
416}
417
418// parser generated in build.rs
419mod lexer;
420mod lexer_utils;
421use lalrpop_util::lalrpop_mod;
422lalrpop_mod!(pub(crate) parser);
423
424// keywords list generated in build.rs
425mod keywords;
426
427/// Additional constants and functions for [`xkeysym`] keysyms
428pub mod keysym {
429 /// Re-export of [`xkeysym::NO_SYMBOL`]:
430 pub use xkeysym::NO_SYMBOL;
431
432 /*
433 /// Re-export of [`xkeysym::Keysym`]
434 ///
435 /// A keycode is a number used to represent the symbols generated from a key on a keyboard.
436 ///
437 /// A key, represented by a keycode, may generate different symbols
438 /// according to keyboard state. For example, on a QWERTY keyboard,
439 /// pressing the key labeled \<A\> generates the symbol 'a'. If the shift key is held, it generates
440 /// the symbol ‘α’. And so on.
441 ///
442 /// Each such symbol is represented by a *keysym* (short for "key symbol").
443 /// Note that keysyms are somewhat more general, in that they can also represent
444 /// some "function", such as "Left" or "Right" for the arrow keys.
445 /// For more information, see Appendix A ["KEYSYM
446 /// Encoding"](https://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#keysym_encoding) of the X Window System
447 /// Protocol.
448 ///
449 /// Keysym names are case-sensitive.
450 ///
451 pub use xkeysym::Keysym;
452
453 */
454 /// Get the name of a keysym.
455 ///
456 /// For a description of how keysyms are named, see [xkeysym::Keysym].
457 ///
458 pub use super::keysyms::keysym_get_name;
459
460 /// Determines whether a keysym is a keypad symbol.
461 pub use super::keysyms::keysym_is_keypad;
462
463 /// Determines whether a keysym is lowercase.
464 pub use super::keysyms::keysym_is_lower;
465
466 /// Determines whether a keysym is a modifier.
467 pub use super::keysyms::keysym_is_modifier;
468
469 /// Determines whether a keysym is uppercase.
470 pub use super::keysyms::keysym_is_upper;
471
472 /// Converts a keysym to its lowercase representation.
473 pub use super::keysyms::keysym_to_lower;
474
475 /// Converts a keysym to its uppercase representation.
476 pub use super::keysyms::keysym_to_upper;
477
478 /// The flags for [keysym_from_name()].
479 pub use super::rust_xkbcommon::KeysymFlags;
480
481 /// Get a keysym from its name.
482 ///
483 /// # Arguments
484 /// * `name`: The name of a keysym. See remarks in [keysym_get_name()];
485 /// this function will accept any name returned by that function.
486 /// * `flags`: A set of flags controlling how the search is done. If invalid flags are passed, this
487 /// will fail with `None`.
488 ///
489 /// If you use the [KeysymFlags::CASE_INSENSITIVE] flag and two keysym names differ only by case,
490 /// then the lower-case keysym is returned. For instance, for `KEY_a` and `KEY_A`, this function
491 /// would return `KEY_a` for the case-insensitive search. If this functionality is needed, it is
492 /// recommended to first call this function without this flag; and if that fails, only then to try
493 /// with this flag, while possibly warning the user he had misspelled the name, and might get wrong
494 /// results.
495 pub use super::keysyms::keysym_from_name;
496 /// Maximum keysym value
497 ///
498 pub use super::rust_xkbcommon::XKB_KEYSYM_MAX;
499}
500
501#[cfg(test)]
502pub(crate) mod test;
503
504#[cfg(test)]
505macro_rules! log_init {
506 () => {
507 use simplelog::*;
508
509 // Only initialize logger if not already initialized
510 let _ = TermLogger::init(
511 LevelFilter::Debug,
512 Config::default(),
513 TerminalMode::Mixed,
514 ColorChoice::Auto,
515 );
516 };
517}
518#[cfg(test)]
519pub(crate) use log_init;