mail client (IMAP/SMTP)
git clone https://git.lucas.co/cce-mail.git
src/wpe/input.rs (4.2K)
1 //! Translating cce-ui input into `WPEEvent`s.
2 //!
3 //! Unlike the Servo backend — where `main.rs` carried `dom_key`/`dom_button`
4 //! helpers and the host took engine types — the mapping lives *here* and
5 //! [`super::WebKitHost`] takes cce-ui's own `MouseButton` / `KeyEvent`. That
6 //! keeps engine vocabulary out of the chrome, so switching backends deletes
7 //! those helpers from `main.rs` rather than rewriting them.
8 //!
9 //! **Keyboard is the fiddly part.** `wpe_event_keyboard_new` wants an X11
10 //! *keysym* (`keyval`), not a character. Latin-1 codepoints are their own
11 //! keysym; anything above maps to `codepoint + 0x0100_0000`; named keys have
12 //! fixed `XK_*` values. Getting this wrong is silent — the page just receives
13 //! nothing useful.
14
15 use cce_ui::widget::{ElementState, Key, KeyEvent, MouseButton, NamedKey};
16
17 use super::ffi::*;
18
19 /// X11 keysyms for the named keys cce-ui reports (`/usr/include/X11/keysymdef.h`).
20 mod keysym {
21 pub const BACKSPACE: u32 = 0xff08;
22 pub const TAB: u32 = 0xff09;
23 pub const RETURN: u32 = 0xff0d;
24 pub const ESCAPE: u32 = 0xff1b;
25 pub const SPACE: u32 = 0x0020;
26 pub const HOME: u32 = 0xff50;
27 pub const LEFT: u32 = 0xff51;
28 pub const UP: u32 = 0xff52;
29 pub const RIGHT: u32 = 0xff53;
30 pub const DOWN: u32 = 0xff54;
31 pub const PAGE_UP: u32 = 0xff55;
32 pub const PAGE_DOWN: u32 = 0xff56;
33 pub const END: u32 = 0xff57;
34 pub const DELETE: u32 = 0xffff;
35 pub const F5: u32 = 0xffc2;
36 pub const SHIFT_L: u32 = 0xffe1;
37 pub const CONTROL_L: u32 = 0xffe3;
38 pub const ALT_L: u32 = 0xffe9;
39 pub const SUPER_L: u32 = 0xffeb;
40 }
41
42 /// A Unicode scalar as an X11 keysym: Latin-1 is identity, the rest is the
43 /// codepoint in the 0x01000000 plane.
44 fn unicode_keysym(c: char) -> u32 {
45 match c as u32 {
46 cp @ 0x20..=0xff => cp,
47 cp => cp + 0x0100_0000,
48 }
49 }
50
51 /// cce-ui key -> X11 keysym. `None` for keys with no sensible mapping.
52 pub(super) fn keyval(key: &Key) -> Option<u32> {
53 Some(match key {
54 Key::Character(s) => unicode_keysym(s.chars().next()?),
55 Key::Named(n) => match n {
56 NamedKey::Backspace => keysym::BACKSPACE,
57 NamedKey::Tab => keysym::TAB,
58 NamedKey::Enter => keysym::RETURN,
59 NamedKey::Escape => keysym::ESCAPE,
60 NamedKey::Space => keysym::SPACE,
61 NamedKey::ArrowDown => keysym::DOWN,
62 NamedKey::ArrowLeft => keysym::LEFT,
63 NamedKey::ArrowRight => keysym::RIGHT,
64 NamedKey::ArrowUp => keysym::UP,
65 NamedKey::End => keysym::END,
66 NamedKey::Home => keysym::HOME,
67 NamedKey::PageDown => keysym::PAGE_DOWN,
68 NamedKey::PageUp => keysym::PAGE_UP,
69 NamedKey::Delete => keysym::DELETE,
70 NamedKey::Control => keysym::CONTROL_L,
71 NamedKey::Shift => keysym::SHIFT_L,
72 NamedKey::Alt => keysym::ALT_L,
73 NamedKey::Super => keysym::SUPER_L,
74 NamedKey::F5 => keysym::F5,
75 },
76 })
77 }
78
79 /// X11 button numbering, which is what WPE expects.
80 pub(super) fn button_number(b: MouseButton) -> Option<u32> {
81 Some(match b {
82 MouseButton::Left => 1,
83 MouseButton::Middle => 2,
84 MouseButton::Right => 3,
85 // Back/Forward are chrome navigation in `main.rs`, deliberately not
86 // forwarded to the page.
87 _ => return None,
88 })
89 }
90
91 pub(super) fn modifiers(ctrl: bool, shift: bool, alt: bool) -> WPEModifiers::Type {
92 let mut m: WPEModifiers::Type = 0;
93 if ctrl {
94 m |= WPEModifiers::WPE_MODIFIER_KEYBOARD_CONTROL;
95 }
96 if shift {
97 m |= WPEModifiers::WPE_MODIFIER_KEYBOARD_SHIFT;
98 }
99 if alt {
100 m |= WPEModifiers::WPE_MODIFIER_KEYBOARD_ALT;
101 }
102 m
103 }
104
105 pub(super) fn is_pressed(e: &KeyEvent) -> bool {
106 e.state == ElementState::Pressed
107 }
108
109 /// WPE stamps events with a millisecond clock. It only has to be monotonic
110 /// and consistent — `wpe_view_compute_press_count` uses it for double-click
111 /// detection, so a frozen value would turn every click into a triple-click.
112 pub(super) fn now_ms() -> u32 {
113 use std::time::{SystemTime, UNIX_EPOCH};
114 SystemTime::now()
115 .duration_since(UNIX_EPOCH)
116 .map(|d| d.as_millis() as u32)
117 .unwrap_or(0)
118 }