integrate new keyboard api (#736)

* use new keyboard api using my fork of in progress winit keyboard pr branches

* attempt fix for modifiers stuck bug
macos-click-through
Keith Simmons 3 years ago committed by GitHub
parent 113a3f421c
commit 76237c6d47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

2
.ok

@ -1,3 +1 @@
install: cargo build --release; rm c:/dev/tools/neovide.* -ErrorAction SilentlyContinue; cp ./target/release/neovide.exe c:/dev/tools/neovide.exe
check: cargo fmt --all -- --check
code: code . -g {0}:{1}:{2}

168
Cargo.lock generated

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ab_glyph_rasterizer"
version = "0.1.4"
@ -267,22 +269,6 @@ dependencies = [
"bitflags",
]
[[package]]
name = "cocoa"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54201c07dcf3a5ca33fececb8042aed767ee4bfd5a0235a8ceabcda956044b2"
dependencies = [
"bitflags",
"block",
"cocoa-foundation",
"core-foundation 0.9.1",
"core-graphics 0.22.2",
"foreign-types",
"libc",
"objc",
]
[[package]]
name = "cocoa"
version = "0.24.0"
@ -443,10 +429,24 @@ dependencies = [
"crossbeam-channel 0.4.4",
"crossbeam-deque 0.7.3",
"crossbeam-epoch 0.8.2",
"crossbeam-queue",
"crossbeam-queue 0.2.3",
"crossbeam-utils 0.7.2",
]
[[package]]
name = "crossbeam"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd01a6eb3daaafa260f6fc94c3a6c36390abc2080e38e3e34ced87393fb77d80"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-channel 0.5.1",
"crossbeam-deque 0.8.0",
"crossbeam-epoch 0.9.4",
"crossbeam-queue 0.3.1",
"crossbeam-utils 0.8.4",
]
[[package]]
name = "crossbeam-channel"
version = "0.4.4"
@ -528,6 +528,16 @@ dependencies = [
"maybe-uninit",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils 0.8.4",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
@ -557,7 +567,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8434f61eb40fc72030b18a370f7a06b428d27de66b0281977967216312b14dc7"
dependencies = [
"async-trait",
"crossbeam",
"crossbeam 0.7.3",
"futures 0.3.15",
]
@ -986,12 +996,11 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "glutin"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ae1cbb9176b9151c4ce03f012e3cd1c6c18c4be79edeaeb3d99f5d8085c5fa3"
source = "git+https://github.com/Kethku/glutin?branch=new-keyboard-all#72e148c299afe3570ab1990c553b03b4d7fdadf2"
dependencies = [
"android_glue",
"cgl",
"cocoa 0.23.0",
"cocoa",
"core-foundation 0.9.1",
"glutin_egl_sys",
"glutin_emscripten_sys",
@ -999,7 +1008,7 @@ dependencies = [
"glutin_glx_sys",
"glutin_wgl_sys",
"lazy_static",
"libloading 0.6.7",
"libloading 0.7.0",
"log",
"objc",
"osmesa-sys",
@ -1013,8 +1022,7 @@ dependencies = [
[[package]]
name = "glutin_egl_sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2abb6aa55523480c4adc5a56bbaa249992e2dddb2fc63dc96e04a3355364c211"
source = "git+https://github.com/Kethku/glutin?branch=new-keyboard-all#72e148c299afe3570ab1990c553b03b4d7fdadf2"
dependencies = [
"gl_generator",
"winapi 0.3.9",
@ -1023,14 +1031,12 @@ dependencies = [
[[package]]
name = "glutin_emscripten_sys"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80de4146df76e8a6c32b03007bc764ff3249dcaeb4f675d68a06caf1bac363f1"
source = "git+https://github.com/Kethku/glutin?branch=new-keyboard-all#72e148c299afe3570ab1990c553b03b4d7fdadf2"
[[package]]
name = "glutin_gles2_sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8094e708b730a7c8a1954f4f8a31880af00eb8a1c5b5bf85d28a0a3c6d69103"
source = "git+https://github.com/Kethku/glutin?branch=new-keyboard-all#72e148c299afe3570ab1990c553b03b4d7fdadf2"
dependencies = [
"gl_generator",
"objc",
@ -1039,8 +1045,7 @@ dependencies = [
[[package]]
name = "glutin_glx_sys"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e393c8fc02b807459410429150e9c4faffdb312d59b8c038566173c81991351"
source = "git+https://github.com/Kethku/glutin?branch=new-keyboard-all#72e148c299afe3570ab1990c553b03b4d7fdadf2"
dependencies = [
"gl_generator",
"x11-dl",
@ -1049,8 +1054,7 @@ dependencies = [
[[package]]
name = "glutin_wgl_sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3da5951a1569dbab865c6f2a863efafff193a93caf05538d193e9e3816d21696"
source = "git+https://github.com/Kethku/glutin?branch=new-keyboard-all#72e148c299afe3570ab1990c553b03b4d7fdadf2"
dependencies = [
"gl_generator",
]
@ -1312,6 +1316,15 @@ dependencies = [
"libc",
]
[[package]]
name = "memmap2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "723e3ebdcdc5c023db1df315364573789f8857c11b631a2fdfad7c00f5c046b4"
dependencies = [
"libc",
]
[[package]]
name = "memoffset"
version = "0.5.6"
@ -1360,15 +1373,28 @@ dependencies = [
]
[[package]]
name = "mio-extras"
version = "2.0.6"
name = "mio"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
dependencies = [
"lazycell",
"libc",
"log",
"mio",
"slab",
"miow 0.3.7",
"ntapi",
"winapi 0.3.9",
]
[[package]]
name = "mio-misc"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ddf05411bb159cdb5801bb10002afb66cb4572be656044315e363460ce69dc2"
dependencies = [
"crossbeam 0.8.0",
"crossbeam-queue 0.3.1",
"log",
"mio 0.7.11",
]
[[package]]
@ -1378,7 +1404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
dependencies = [
"log",
"mio",
"mio 0.6.23",
"miow 0.3.7",
"winapi 0.3.9",
]
@ -1391,7 +1417,7 @@ checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
dependencies = [
"iovec",
"libc",
"mio",
"mio 0.6.23",
]
[[package]]
@ -1442,11 +1468,17 @@ dependencies = [
"syn 1.0.72",
]
[[package]]
name = "nameof"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba896fb4d7fe86433ebaf18c532bd9202e54c450a1bf7723855220e0e76d71d1"
[[package]]
name = "ndk"
version = "0.2.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73"
checksum = "8794322172319b972f528bf90c6b467be0079f1fa82780ffb431088e741a73ab"
dependencies = [
"jni-sys",
"ndk-sys",
@ -1456,9 +1488,9 @@ dependencies = [
[[package]]
name = "ndk-glue"
version = "0.2.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241"
checksum = "c5caf0c24d51ac1c905c27d4eda4fa0635bbe0de596b8f79235e0b17a4d29385"
dependencies = [
"lazy_static",
"libc",
@ -1521,6 +1553,7 @@ dependencies = [
"unicode-segmentation",
"which 4.1.0",
"winapi 0.3.9",
"winit",
"winres",
]
@ -1593,6 +1626,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "ntapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "num-derive"
version = "0.2.5"
@ -1657,9 +1699,9 @@ dependencies = [
[[package]]
name = "num_enum"
version = "0.4.3"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4"
checksum = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066"
dependencies = [
"derivative",
"num_enum_derive",
@ -1667,9 +1709,9 @@ dependencies = [
[[package]]
name = "num_enum_derive"
version = "0.4.3"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d"
checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e"
dependencies = [
"proc-macro-crate",
"proc-macro2 1.0.26",
@ -2285,7 +2327,7 @@ dependencies = [
"dlib 0.4.2",
"lazy_static",
"log",
"memmap2",
"memmap2 0.1.0",
"nix 0.18.0",
"wayland-client",
"wayland-cursor",
@ -2449,7 +2491,7 @@ dependencies = [
"lazy_static",
"libc",
"memchr",
"mio",
"mio 0.6.23",
"mio-named-pipes",
"mio-uds",
"num_cpus",
@ -2845,11 +2887,10 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winit"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da4eda6fce0eb84bd0a33e3c8794eb902e1033d0a1d5a31bc4f19b1b4bbff597"
source = "git+https://github.com/Kethku/winit?branch=new-keyboard-all#3b5462ec315aae8d95b9440ff6c52a5412c2cca4"
dependencies = [
"bitflags",
"cocoa 0.24.0",
"cocoa",
"core-foundation 0.9.1",
"core-graphics 0.22.2",
"core-video-sys",
@ -2858,8 +2899,10 @@ dependencies = [
"lazy_static",
"libc",
"log",
"mio",
"mio-extras",
"memmap2 0.2.3",
"mio 0.7.11",
"mio-misc",
"nameof",
"ndk",
"ndk-glue",
"ndk-sys",
@ -2867,10 +2910,13 @@ dependencies = [
"parking_lot 0.11.1",
"percent-encoding",
"raw-window-handle",
"scopeguard",
"smithay-client-toolkit",
"unicode-segmentation",
"wayland-client",
"winapi 0.3.9",
"x11-dl",
"xkbcommon-dl",
]
[[package]]
@ -2928,6 +2974,18 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
[[package]]
name = "xkbcommon-dl"
version = "0.1.0"
source = "git+https://github.com/maroider/xkbcommon-dl?rev=900832888ad6f11011d1369befb344a9aa8a9610#900832888ad6f11011d1369befb344a9aa8a9610"
dependencies = [
"bitflags",
"dlib 0.5.0",
"lazy_static",
"log",
"x11-dl",
]
[[package]]
name = "xml-rs"
version = "0.8.3"

@ -37,7 +37,8 @@ dirs = "2"
rand = "0.7"
pin-project = "0.4.27"
futures = "0.3.12"
glutin = "0.26"
glutin = { git = "https://github.com/Kethku/glutin", branch = "new-keyboard-all" }
winit = { git = "https://github.com/Kethku/winit", branch = "new-keyboard-all", default-features = false }
gl = "0.14.0"
regex = "1.5.4"
swash = "0.1.2"

@ -127,6 +127,7 @@ pub enum EditorMode {
Normal,
Insert,
Visual,
Replace,
CmdLine,
Unknown(String),
}
@ -477,6 +478,7 @@ fn parse_mode_change(mode_change_arguments: Vec<Value>) -> Result<RedrawEvent> {
"normal" => EditorMode::Normal,
"insert" => EditorMode::Insert,
"visual" => EditorMode::Visual,
"replace" => EditorMode::Replace,
"cmdline_normal" => EditorMode::CmdLine,
_ => EditorMode::Unknown(mode_name),
},

@ -33,7 +33,7 @@ pub struct CursorMode {
pub blinkoff: Option<u64>,
}
#[derive(Clone, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct Cursor {
pub grid_position: (u64, u64),
pub parent_window_id: u64,

@ -5,7 +5,6 @@ mod style;
mod window;
use std::collections::HashMap;
use std::fmt;
use std::sync::Arc;
use std::thread;
@ -47,6 +46,7 @@ impl WindowAnchor {
}
}
#[derive(Debug)]
pub enum DrawCommand {
CloseWindow(u64),
Window {
@ -65,21 +65,6 @@ pub enum WindowCommand {
SetMouseEnabled(bool),
}
impl fmt::Debug for DrawCommand {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
DrawCommand::CloseWindow(_) => write!(formatter, "CloseWindow"),
DrawCommand::Window { grid_id, command } => {
write!(formatter, "Window {} {:?}", grid_id, command)
}
DrawCommand::UpdateCursor(_) => write!(formatter, "UpdateCursor"),
DrawCommand::FontChanged(_) => write!(formatter, "FontChanged"),
DrawCommand::DefaultStyleChanged(_) => write!(formatter, "DefaultStyleChanged"),
DrawCommand::ModeChanged(_) => write!(formatter, "ModeChanged"),
}
}
}
pub struct Editor {
pub windows: HashMap<u64, Window>,
pub cursor: Cursor,

@ -41,7 +41,7 @@ use editor::start_editor;
use renderer::{cursor_renderer::CursorSettings, RendererSettings};
#[cfg(not(test))]
use settings::SETTINGS;
use window::{create_window, window_geometry, KeyboardSettings, WindowSettings};
use window::{create_window, window_geometry, WindowSettings};
pub use channel_utils::*;
pub const INITIAL_DIMENSIONS: (u64, u64) = (100, 50);
@ -162,7 +162,6 @@ fn main() {
}
}
KeyboardSettings::register();
WindowSettings::register();
RendererSettings::register();
CursorSettings::register();

@ -1,26 +0,0 @@
use crate::settings::{FromValue, Value};
#[derive(Clone)]
pub enum KeyboardLayout {
Qwerty,
}
impl FromValue for KeyboardLayout {
fn from_value(&mut self, value: Value) {
match value.as_str() {
Some("qwerty") => *self = KeyboardLayout::Qwerty,
_ => log::error!(
"keyboard_layout setting expected a known keyboard layout name, but received: {}",
value
),
}
}
}
impl From<KeyboardLayout> for Value {
fn from(layout: KeyboardLayout) -> Self {
match layout {
KeyboardLayout::Qwerty => "qwerty".into(),
}
}
}

@ -1,49 +0,0 @@
mod layout;
mod modifiers;
mod settings;
mod token;
use crate::settings::SETTINGS;
pub use self::{
layout::KeyboardLayout, modifiers::Modifiers, settings::KeyboardSettings, token::Token,
};
type KeycodeToTokenFn<T> = fn(T, bool) -> Option<Token<'static>>;
pub fn neovim_keybinding_string<T, U>(
keycode: Option<U>,
keytext: Option<String>,
modifiers: T,
keycode_to_token: KeycodeToTokenFn<U>,
) -> Option<String>
where
T: Into<Modifiers>,
{
let modifiers: Modifiers = modifiers.into();
if let Some(text) = keytext {
Some(
if text == "<" {
Token::new("lt", true, true)
} else {
Token::new(&text, false, false)
}
.into_string(modifiers),
)
} else if let Some(keycode) = keycode {
match SETTINGS.get::<KeyboardSettings>().layout {
KeyboardLayout::Qwerty => keycode_to_token(keycode, modifiers.shift),
}
.map(|e| e.into_string(modifiers))
} else {
None
}
}
pub fn unsupported_key<T, R>(keycode: T) -> Option<R>
where
T: std::fmt::Debug,
{
log::trace!("Unsupported key: {:?}", keycode);
None
}

@ -1,15 +0,0 @@
/// The keyboard modifiers associated with a keystroke
#[derive(Debug, Copy, Clone)]
pub struct Modifiers {
/// Shift key
pub shift: bool,
/// Control key
pub control: bool,
/// Alt on Windows, option on Mac
pub meta: bool,
/// Windows key on PC, command key on Mac
pub logo: bool,
}

@ -1,17 +0,0 @@
use super::KeyboardLayout;
use crate::settings::FromValue;
#[derive(SettingGroup)]
#[setting_prefix = "keyboard"]
#[derive(Clone)]
pub struct KeyboardSettings {
pub layout: KeyboardLayout,
}
impl Default for KeyboardSettings {
fn default() -> Self {
Self {
layout: KeyboardLayout::Qwerty,
}
}
}

@ -1,53 +0,0 @@
use super::Modifiers;
/// Information about how to translate keyboard into Vim input
#[derive(Debug, Clone)]
pub struct Token<'a> {
/// The name of the key in Vimscript.
/// See `:help key-notation` for more details.
key_name: &'a str,
/// Whether the token should be enclosed in brackets, such as <Esc> or <BS>
special: bool,
/// Whether the shift key should be considered for inclusion in the token.
use_shift: bool,
}
impl<'a> Token<'a> {
pub const fn new(key_name: &'a str, special: bool, use_shift: bool) -> Self {
Self {
key_name,
special,
use_shift,
}
}
/// Converts the keypress to a Neovim input
pub fn into_string(self, mods: Modifiers) -> String {
let shift = self.use_shift && mods.shift;
let special = self.special || shift || mods.control || mods.meta || use_logo(mods.logo);
let open = if special { "<" } else { "" };
let command = if use_logo(mods.logo) { "D-" } else { "" };
let shift = if shift { "S-" } else { "" };
let control = if mods.control { "C-" } else { "" };
let meta = if mods.meta { "M-" } else { "" };
let close = if special { ">" } else { "" };
format!(
"{}{}{}{}{}{}{}",
open, command, shift, control, meta, self.key_name, close
)
}
}
#[cfg(not(target_os = "windows"))]
fn use_logo(logo: bool) -> bool {
logo
}
// The Windows key is used for OS-level shortcuts,
// so we want to ignore the logo key on this platform.
#[cfg(target_os = "windows")]
fn use_logo(_: bool) -> bool {
false
}

@ -1,4 +1,3 @@
mod keyboard;
mod settings;
mod window_wrapper;

@ -1,7 +1,5 @@
use crate::{cmd_line::CmdLineSettings, settings::*};
pub use super::keyboard::KeyboardSettings;
#[derive(Clone, SettingGroup)]
pub struct WindowSettings {
pub refresh_rate: u64,

@ -0,0 +1,131 @@
use glutin::event::{ElementState, Event, WindowEvent};
use glutin::keyboard::Key;
use crate::bridge::UiCommand;
use crate::channel_utils::LoggingTx;
pub struct KeyboardManager {
command_sender: LoggingTx<UiCommand>,
shift: bool,
ctrl: bool,
alt: bool,
logo: bool,
}
#[cfg(not(target_os = "windows"))]
fn use_logo(logo: bool) -> bool {
logo
}
// The Windows key is used for OS-level shortcuts,
// so we want to ignore the logo key on this platform.
#[cfg(target_os = "windows")]
fn use_logo(_: bool) -> bool {
false
}
fn or_empty(condition: bool, text: &str) -> &str {
if condition {
text
} else {
""
}
}
fn get_key_text(key: Key<'static>) -> Option<(&str, bool)> {
match key {
Key::Character(character_text) => match character_text {
" " => Some(("Space", true)),
"<" => Some(("lt", true)),
"\\" => Some(("Bslash", true)),
"|" => Some(("Bar", true)),
" " => Some(("Tab", true)),
"\n" => Some(("CR", true)),
_ => Some((character_text, false)),
},
Key::Backspace => Some(("BS", true)),
Key::Tab => Some(("Tab", true)),
Key::Enter => Some(("CR", true)),
Key::Escape => Some(("Esc", true)),
Key::Space => Some(("Space", true)),
Key::Delete => Some(("Del", true)),
Key::ArrowUp => Some(("Up", true)),
Key::ArrowDown => Some(("Down", true)),
Key::ArrowLeft => Some(("Left", true)),
Key::ArrowRight => Some(("Right", true)),
Key::F1 => Some(("F1", true)),
Key::F2 => Some(("F2", true)),
Key::F3 => Some(("F3", true)),
Key::F4 => Some(("F4", true)),
Key::F5 => Some(("F5", true)),
Key::F6 => Some(("F6", true)),
Key::F7 => Some(("F7", true)),
Key::F8 => Some(("F8", true)),
Key::F9 => Some(("F9", true)),
Key::F10 => Some(("F10", true)),
Key::F11 => Some(("F11", true)),
Key::F12 => Some(("F12", true)),
Key::Insert => Some(("Insert", true)),
Key::Home => Some(("Home", true)),
Key::End => Some(("End", true)),
Key::PageUp => Some(("PageUp", true)),
Key::PageDown => Some(("PageDown", true)),
_ => None,
}
}
impl KeyboardManager {
pub fn new(command_sender: LoggingTx<UiCommand>) -> KeyboardManager {
KeyboardManager {
command_sender,
shift: false,
ctrl: false,
alt: false,
logo: false,
}
}
fn format_keybinding_string(&self, special: bool, text: &str) -> String {
let special = special || self.shift || self.ctrl || self.alt || self.logo;
let open = or_empty(special, "<");
let shift = or_empty(self.shift, "S-");
let ctrl = or_empty(self.ctrl, "C-");
let alt = or_empty(self.alt, "M-");
let logo = or_empty(use_logo(self.logo), "D-");
let close = or_empty(special, ">");
format!("{}{}{}{}{}{}{}", open, shift, ctrl, alt, logo, text, close)
}
pub fn handle_event(&mut self, event: &Event<()>) {
match event {
Event::WindowEvent {
event: WindowEvent::KeyboardInput {
event: key_event, ..
},
..
} => {
if key_event.state == ElementState::Pressed {
if let Some((key_text, special)) = get_key_text(key_event.logical_key) {
let keybinding_string = self.format_keybinding_string(special, key_text);
self.command_sender
.send(UiCommand::Keyboard(keybinding_string))
.expect("Could not send keyboard ui command");
}
}
},
Event::WindowEvent {
event: WindowEvent::ModifiersChanged(modifiers),
..
} => {
self.shift = modifiers.shift_key();
self.ctrl = modifiers.control_key();
self.alt = modifiers.alt_key();
self.logo = modifiers.super_key();
},
_ => { }
}
}
}

@ -1,26 +0,0 @@
mod qwerty;
use crate::window::keyboard::Modifiers;
use glutin::event::ModifiersState;
pub use qwerty::handle_qwerty_layout;
impl From<Option<ModifiersState>> for Modifiers {
fn from(state: Option<ModifiersState>) -> Modifiers {
if let Some(modifiers) = state {
Modifiers {
shift: modifiers.shift(),
control: modifiers.ctrl(),
meta: modifiers.alt(),
logo: modifiers.logo(),
}
} else {
Modifiers {
shift: false,
control: false,
meta: false,
logo: false,
}
}
}
}

@ -1,138 +0,0 @@
use crate::window::keyboard::{unsupported_key, Token};
use glutin::event::VirtualKeyCode::{self, *};
/// Maps winit keyboard events to Vim tokens
pub fn handle_qwerty_layout(keycode: VirtualKeyCode, shift: bool) -> Option<Token<'static>> {
let special = |text| Some(Token::new(text, true, true));
let normal = |text| Some(Token::new(text, false, true));
let partial = |text| Some(Token::new(text, false, false));
match (keycode, shift) {
(Back, _) => special("BS"),
(Tab, _) => special("Tab"),
(Return, _) => special("Enter"),
(Escape, _) => special("Esc"),
(Space, _) => normal(" "),
(Apostrophe, false) => partial("'"),
(Apostrophe, true) => partial("\""),
(Comma, false) => normal(","),
(Comma, true) => special("lt"),
(Minus, false) => partial("-"),
(Minus, true) => partial("_"),
(Period, false) => partial("."),
(Period, true) => partial(">"),
(Slash, false) => partial("/"),
(Slash, true) => partial("?"),
(Key0, false) => normal("0"),
(Key0, true) => partial(")"),
(Key1, false) => normal("1"),
(Key1, true) => partial("!"),
(Key2, false) => partial("2"),
(Key2, true) => partial("@"),
(Key3, false) => partial("3"),
(Key3, true) => partial("#"),
(Key4, false) => partial("4"),
(Key4, true) => partial("$"),
(Key5, false) => partial("5"),
(Key5, true) => partial("%"),
(Key6, false) => partial("6"),
(Key6, true) => partial("^"),
(Key7, false) => partial("7"),
(Key7, true) => partial("&"),
(Key8, false) => partial("8"),
(Key8, true) => partial("*"),
(Key9, false) => partial("9"),
(Key9, true) => partial("("),
(Colon, _) => normal(":"),
(Semicolon, false) => partial(";"),
(Semicolon, true) => partial(":"),
(Equals, false) => partial("="),
(Equals, true) => partial("+"),
(At, _) => normal("@"),
(LBracket, false) => partial("["),
(LBracket, true) => partial("{"),
(Backslash, false) => partial("\\"),
(Backslash, true) => partial("|"),
(RBracket, false) => partial("]"),
(RBracket, true) => partial("}"),
(Caret, _) => normal("^"),
(Grave, false) => partial("`"),
(Grave, true) => partial("~"),
(A, _) => normal("a"),
(B, _) => normal("b"),
(C, _) => normal("c"),
(D, _) => normal("d"),
(E, _) => normal("e"),
(F, _) => normal("f"),
(G, _) => normal("g"),
(H, _) => normal("h"),
(I, _) => normal("i"),
(J, _) => normal("j"),
(K, _) => normal("k"),
(L, _) => normal("l"),
(M, _) => normal("m"),
(N, _) => normal("n"),
(O, _) => normal("o"),
(P, _) => normal("p"),
(Q, _) => normal("q"),
(R, _) => normal("r"),
(S, _) => normal("s"),
(T, _) => normal("t"),
(U, _) => normal("u"),
(V, _) => normal("v"),
(W, _) => normal("w"),
(X, _) => normal("x"),
(Y, _) => normal("y"),
(Z, _) => normal("z"),
(Delete, _) => special("Delete"),
(F1, _) => special("F1"),
(F2, _) => special("F2"),
(F3, _) => special("F3"),
(F4, _) => special("F4"),
(F5, _) => special("F5"),
(F6, _) => special("F6"),
(F7, _) => special("F7"),
(F8, _) => special("F8"),
(F9, _) => special("F9"),
(F10, _) => special("F10"),
(F11, _) => special("F11"),
(F12, _) => special("F12"),
(Insert, _) => special("Insert"),
(Home, _) => special("Home"),
(PageUp, _) => special("PageUp"),
(End, _) => special("End"),
(PageDown, _) => special("PageDown"),
(Right, _) => special("Right"),
(Left, _) => special("Left"),
(Down, _) => special("Down"),
(Up, _) => special("Up"),
(Numpad0, _) => normal("0"),
(Numpad1, _) => normal("1"),
(Numpad2, _) => normal("2"),
(Numpad3, _) => normal("3"),
(Numpad4, _) => normal("4"),
(Numpad5, _) => normal("5"),
(Numpad6, _) => normal("6"),
(Numpad7, _) => normal("7"),
(Numpad8, _) => normal("8"),
(Numpad9, _) => normal("9"),
(F13, _) => special("F13"),
(F14, _) => special("F14"),
(F15, _) => special("F15"),
(F16, _) => special("F16"),
(F17, _) => special("F17"),
(F18, _) => special("F18"),
(F19, _) => special("F19"),
(F20, _) => special("F20"),
(F21, _) => special("F21"),
(F22, _) => special("F22"),
(F23, _) => special("F23"),
(F24, _) => special("F24"),
(LControl, _) => None,
(LShift, _) => None,
(LAlt, _) => None,
(RControl, _) => None,
(RShift, _) => None,
(RAlt, _) => None,
(keycode, _) => unsupported_key(keycode),
}
}

@ -1,35 +1,34 @@
#[macro_use]
mod layouts;
mod keyboard_manager;
mod mouse_manager;
mod renderer;
use super::{handle_new_grid_size, keyboard::neovim_keybinding_string, settings::WindowSettings};
use crate::{
bridge::UiCommand, channel_utils::*, cmd_line::CmdLineSettings, editor::WindowCommand,
error_handling::ResultPanicExplanation, redraw_scheduler::REDRAW_SCHEDULER, renderer::Renderer,
settings::SETTINGS,
use std::{
sync::{
atomic::{AtomicBool, Ordering},
mpsc::Receiver,
Arc,
},
time::{Duration, Instant},
};
use glutin::{
self,
dpi::{LogicalPosition, LogicalSize, PhysicalSize},
event::{
ElementState, Event, ModifiersState, MouseButton, MouseScrollDelta,
VirtualKeyCode as Keycode, WindowEvent,
},
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{self, Fullscreen, Icon},
ContextBuilder, GlProfile, WindowedContext,
};
use super::{handle_new_grid_size, settings::WindowSettings};
use crate::{
bridge::UiCommand, channel_utils::*, cmd_line::CmdLineSettings, editor::WindowCommand,
redraw_scheduler::REDRAW_SCHEDULER, renderer::Renderer, settings::SETTINGS,
};
use image::{load_from_memory, GenericImageView, Pixel};
use layouts::handle_qwerty_layout;
use keyboard_manager::KeyboardManager;
use mouse_manager::MouseManager;
use renderer::SkiaRenderer;
use std::{
sync::{
atomic::{AtomicBool, Ordering},
mpsc::Receiver,
Arc,
},
time::{Duration, Instant},
};
#[derive(RustEmbed)]
#[folder = "assets/"]
@ -39,11 +38,8 @@ pub struct GlutinWindowWrapper {
windowed_context: WindowedContext<glutin::PossiblyCurrent>,
skia_renderer: SkiaRenderer,
renderer: Renderer,
mouse_down: bool,
mouse_position: LogicalPosition<u32>,
mouse_enabled: bool,
grid_id_under_mouse: u64,
current_modifiers: Option<ModifiersState>,
keyboard_manager: KeyboardManager,
mouse_manager: MouseManager,
title: String,
previous_size: PhysicalSize<u32>,
fullscreen: bool,
@ -95,7 +91,9 @@ impl GlutinWindowWrapper {
for window_command in window_commands.into_iter() {
match window_command {
WindowCommand::TitleChanged(new_title) => self.handle_title_changed(new_title),
WindowCommand::SetMouseEnabled(mouse_enabled) => self.mouse_enabled = mouse_enabled,
WindowCommand::SetMouseEnabled(mouse_enabled) => {
self.mouse_manager.enabled = mouse_enabled
}
}
}
}
@ -115,160 +113,6 @@ impl GlutinWindowWrapper {
}
}
pub fn handle_keyboard_input(
&mut self,
keycode: Option<Keycode>,
modifiers: Option<ModifiersState>,
) {
if keycode.is_some() {
log::trace!(
"Keyboard Input Received: keycode-{:?} modifiers-{:?} ",
keycode,
modifiers
);
}
if let Some(keybinding_string) =
neovim_keybinding_string(keycode, None, modifiers, handle_qwerty_layout)
{
self.ui_command_sender
.send(UiCommand::Keyboard(keybinding_string))
.unwrap_or_explained_panic(
"Could not send UI command from the window system to the neovim process.",
);
}
}
pub fn handle_pointer_motion(&mut self, x: i32, y: i32) {
let size = self.windowed_context.window().inner_size();
if x < 0 || x as u32 >= size.width || y < 0 || y as u32 >= size.height {
return;
}
let previous_position = self.mouse_position;
let logical_position: LogicalSize<u32> = PhysicalSize::new(x as u32, y as u32)
.to_logical(self.windowed_context.window().scale_factor());
let mut top_window_position = (0.0, 0.0);
let mut top_grid_position = None;
for details in self.renderer.window_regions.iter() {
if logical_position.width >= details.region.left as u32
&& logical_position.width < details.region.right as u32
&& logical_position.height >= details.region.top as u32
&& logical_position.height < details.region.bottom as u32
{
top_window_position = (details.region.left, details.region.top);
top_grid_position = Some((
details.id,
LogicalSize::<u32>::new(
logical_position.width - details.region.left as u32,
logical_position.height - details.region.top as u32,
),
details.floating_order.is_some(),
));
}
}
if let Some((grid_id, grid_position, grid_floating)) = top_grid_position {
self.grid_id_under_mouse = grid_id;
self.mouse_position = LogicalPosition::new(
(grid_position.width as u64 / self.renderer.font_width) as u32,
(grid_position.height as u64 / self.renderer.font_height) as u32,
);
if self.mouse_enabled && self.mouse_down && previous_position != self.mouse_position {
let (window_left, window_top) = top_window_position;
// Until https://github.com/neovim/neovim/pull/12667 is merged, we have to special
// case non floating windows. Floating windows correctly transform mouse positions
// into grid coordinates, but non floating windows do not.
let position = if grid_floating {
(self.mouse_position.x, self.mouse_position.y)
} else {
let adjusted_drag_left = self.mouse_position.x
+ (window_left / self.renderer.font_width as f32) as u32;
let adjusted_drag_top = self.mouse_position.y
+ (window_top / self.renderer.font_height as f32) as u32;
(adjusted_drag_left, adjusted_drag_top)
};
self.ui_command_sender
.send(UiCommand::Drag {
grid_id: self.grid_id_under_mouse,
position,
})
.ok();
}
}
}
pub fn handle_pointer_down(&mut self) {
if self.mouse_enabled {
self.ui_command_sender
.send(UiCommand::MouseButton {
action: String::from("press"),
grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.x, self.mouse_position.y),
})
.ok();
}
self.mouse_down = true;
}
pub fn handle_pointer_up(&mut self) {
if self.mouse_enabled {
self.ui_command_sender
.send(UiCommand::MouseButton {
action: String::from("release"),
grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.x, self.mouse_position.y),
})
.ok();
}
self.mouse_down = false;
}
pub fn handle_mouse_wheel(&mut self, x: f32, y: f32) {
let scroll_dead_zone = SETTINGS.get::<WindowSettings>().scroll_dead_zone;
if !self.mouse_enabled {
return;
}
let vertical_input_type = match y {
_ if y > scroll_dead_zone => Some("up"),
_ if y < -scroll_dead_zone => Some("down"),
_ => None,
};
if let Some(input_type) = vertical_input_type {
self.ui_command_sender
.send(UiCommand::Scroll {
direction: input_type.to_string(),
grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.x, self.mouse_position.y),
})
.ok();
}
let horizontal_input_type = match x {
_ if x > scroll_dead_zone => Some("right"),
_ if x < -scroll_dead_zone => Some("left"),
_ => None,
};
if let Some(input_type) = horizontal_input_type {
self.ui_command_sender
.send(UiCommand::Scroll {
direction: input_type.to_string(),
grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.x, self.mouse_position.y),
})
.ok();
}
}
pub fn handle_focus_lost(&mut self) {
self.ui_command_sender.send(UiCommand::FocusLost).ok();
}
@ -279,9 +123,9 @@ impl GlutinWindowWrapper {
}
pub fn handle_event(&mut self, event: Event<()>, running: &Arc<AtomicBool>) {
let mut keycode = None;
let mut ignore_text_this_frame = false;
self.keyboard_manager.handle_event(&event);
self.mouse_manager
.handle_event(&event, &self.renderer, &self.windowed_context);
match event {
Event::LoopDestroyed => {
self.handle_quit(running);
@ -302,61 +146,11 @@ impl GlutinWindowWrapper {
))
.ok();
}
Event::WindowEvent {
event: WindowEvent::KeyboardInput { input, .. },
..
} => {
if input.state == ElementState::Pressed {
keycode = input.virtual_keycode;
}
}
Event::WindowEvent {
event: WindowEvent::ModifiersChanged(m),
..
} => {
self.current_modifiers = Some(m);
}
Event::WindowEvent {
event: WindowEvent::CursorMoved { position, .. },
..
} => self.handle_pointer_motion(position.x as i32, position.y as i32),
Event::WindowEvent {
event:
WindowEvent::MouseWheel {
delta: MouseScrollDelta::LineDelta(x, y),
..
},
..
} => self.handle_mouse_wheel(x as f32, y as f32),
Event::WindowEvent {
event:
WindowEvent::MouseWheel {
delta: MouseScrollDelta::PixelDelta(logical_position),
..
},
..
} => self.handle_mouse_wheel(logical_position.x as f32, logical_position.y as f32),
Event::WindowEvent {
event:
WindowEvent::MouseInput {
button: MouseButton::Left,
state,
..
},
..
} => {
if state == ElementState::Pressed {
self.handle_pointer_down();
} else {
self.handle_pointer_up();
}
}
Event::WindowEvent {
event: WindowEvent::Focused(focus),
..
} => {
if focus {
ignore_text_this_frame = true; // Ignore any text events on the first frame when focus is regained. https://github.com/Kethku/neovide/issues/193
self.handle_focus_gained();
} else {
self.handle_focus_lost();
@ -365,10 +159,6 @@ impl GlutinWindowWrapper {
Event::WindowEvent { .. } => REDRAW_SCHEDULER.queue_next_frame(),
_ => {}
}
if !ignore_text_this_frame {
self.handle_keyboard_input(keycode, self.current_modifiers);
}
}
pub fn draw_frame(&mut self, dt: f32) {
@ -461,11 +251,8 @@ pub fn start_loop(
windowed_context,
skia_renderer,
renderer,
mouse_down: false,
mouse_position: LogicalPosition::new(0, 0),
mouse_enabled: true,
grid_id_under_mouse: 0,
current_modifiers: None,
keyboard_manager: KeyboardManager::new(ui_command_sender.clone()),
mouse_manager: MouseManager::new(ui_command_sender.clone()),
title: String::from("Neovide"),
previous_size,
fullscreen: false,

@ -0,0 +1,213 @@
use glutin::{
self,
WindowedContext,
dpi::{
LogicalPosition,
LogicalSize,
PhysicalSize
},
event::{
ElementState,
Event,
MouseButton,
MouseScrollDelta,
WindowEvent,
},
PossiblyCurrent
};
use crate::channel_utils::LoggingTx;
use crate::bridge::UiCommand;
use crate::renderer::Renderer;
pub struct MouseManager {
command_sender: LoggingTx<UiCommand>,
button_down: bool,
position: LogicalPosition<u32>,
grid_id_under_mouse: u64,
pub enabled: bool,
}
impl MouseManager {
pub fn new(command_sender: LoggingTx<UiCommand>) -> MouseManager {
MouseManager {
command_sender,
button_down: false,
position: LogicalPosition::new(0, 0),
grid_id_under_mouse: 0,
enabled: true,
}
}
fn handle_pointer_motion(&mut self, x: i32, y: i32, renderer: &Renderer, windowed_context: &WindowedContext<PossiblyCurrent>) {
let size = windowed_context.window().inner_size();
if x < 0 || x as u32 >= size.width || y < 0 || y as u32 >= size.height {
return;
}
let previous_position = self.position;
let logical_position: LogicalSize<u32> = PhysicalSize::new(x as u32, y as u32)
.to_logical(windowed_context.window().scale_factor());
let mut top_window_position = (0.0, 0.0);
let mut top_grid_position = None;
for details in renderer.window_regions.iter() {
if logical_position.width >= details.region.left as u32
&& logical_position.width < details.region.right as u32
&& logical_position.height >= details.region.top as u32
&& logical_position.height < details.region.bottom as u32
{
top_window_position = (details.region.left, details.region.top);
top_grid_position = Some((
details.id,
LogicalSize::<u32>::new(
logical_position.width - details.region.left as u32,
logical_position.height - details.region.top as u32,
),
details.floating_order.is_some(),
));
}
}
if let Some((grid_id, grid_position, grid_floating)) = top_grid_position {
self.grid_id_under_mouse = grid_id;
self.position = LogicalPosition::new(
(grid_position.width as u64 / renderer.font_width) as u32,
(grid_position.height as u64 / renderer.font_height) as u32,
);
if self.enabled && self.button_down && previous_position != self.position {
let (window_left, window_top) = top_window_position;
// Until https://github.com/neovim/neovim/pull/12667 is merged, we have to special
// case non floating windows. Floating windows correctly transform mouse positions
// into grid coordinates, but non floating windows do not.
let position = if grid_floating {
(self.position.x, self.position.y)
} else {
let adjusted_drag_left = self.position.x
+ (window_left / renderer.font_width as f32) as u32;
let adjusted_drag_top = self.position.y
+ (window_top / renderer.font_height as f32) as u32;
(adjusted_drag_left, adjusted_drag_top)
};
self.command_sender
.send(UiCommand::Drag {
grid_id: self.grid_id_under_mouse,
position,
})
.ok();
}
}
}
fn handle_pointer_down(&mut self) {
if self.enabled {
self.command_sender
.send(UiCommand::MouseButton {
action: String::from("press"),
grid_id: self.grid_id_under_mouse,
position: (self.position.x, self.position.y),
})
.ok();
}
self.button_down = true;
}
fn handle_pointer_up(&mut self) {
if self.enabled {
self.command_sender
.send(UiCommand::MouseButton {
action: String::from("release"),
grid_id: self.grid_id_under_mouse,
position: (self.position.x, self.position.y),
})
.ok();
}
self.button_down = false;
}
fn handle_mouse_wheel(&mut self, x: f32, y: f32) {
if !self.enabled {
return;
}
let vertical_input_type = match y {
_ if y > 1.8 => Some("up"),
_ if y < -1.8 => Some("down"),
_ => None,
};
if let Some(input_type) = vertical_input_type {
self.command_sender
.send(UiCommand::Scroll {
direction: input_type.to_string(),
grid_id: self.grid_id_under_mouse,
position: (self.position.x, self.position.y),
})
.ok();
}
let horizontal_input_type = match x {
_ if x > 1.8 => Some("right"),
_ if x < -1.8 => Some("left"),
_ => None,
};
if let Some(input_type) = horizontal_input_type {
self.command_sender
.send(UiCommand::Scroll {
direction: input_type.to_string(),
grid_id: self.grid_id_under_mouse,
position: (self.position.x, self.position.y),
})
.ok();
}
}
pub fn handle_event(&mut self, event: &Event<()>, renderer: &Renderer, windowed_context: &WindowedContext<PossiblyCurrent>) {
match event {
Event::WindowEvent {
event: WindowEvent::CursorMoved { position, .. },
..
} => self.handle_pointer_motion(
position.x as i32, position.y as i32,
renderer, windowed_context),
Event::WindowEvent {
event:
WindowEvent::MouseWheel {
delta: MouseScrollDelta::LineDelta(x, y),
..
},
..
} => self.handle_mouse_wheel(*x as f32, *y as f32),
Event::WindowEvent {
event:
WindowEvent::MouseWheel {
delta: MouseScrollDelta::PixelDelta(logical_position),
..
},
..
} => self.handle_mouse_wheel(logical_position.x as f32, logical_position.y as f32),
Event::WindowEvent {
event:
WindowEvent::MouseInput {
button: MouseButton::Left,
state,
..
},
..
} => {
if state == &ElementState::Pressed {
self.handle_pointer_down();
} else {
self.handle_pointer_up();
}
},
_ => {}
}
}
}
Loading…
Cancel
Save