git.lucas.co / cce-mail
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 }