Merge pull request #136 from Kethku/sdl2

Sdl2
macos-click-through
Keith Simmons 5 years ago committed by GitHub
commit 1f0d93ca3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -60,7 +60,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get install -y curl gnupg ca-certificates git gcc-multilib g++-multilib cmake libssl-dev pkg-config libfreetype6-dev libasound2-dev libexpat1-dev libxcb-composite0-dev libbz2-dev freeglut3-dev libxi-dev
sudo apt-get install -y curl gnupg ca-certificates git gcc-multilib g++-multilib cmake libssl-dev pkg-config libfreetype6-dev libasound2-dev libexpat1-dev libxcb-composite0-dev libbz2-dev freeglut3-dev libxi-dev libsdl2-dev
- name: Build
run: cargo build --release

1795
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -11,7 +11,8 @@ euclid = "0.20.7"
font-kit = "0.5.0"
skribo = { git = "https://github.com/linebender/skribo" }
lru = "0.4.3"
skulpin = { git = "https://github.com/kethku/skulpin", branch = "winit_20" }
skulpin = { git = "https://github.com/Kethku/skulpin", branch = "sdl2" }
# skulpin = { path = "../skulpin" }
derive-new = "0.5"
rmpv = "0.4.4"
rust-embed = { version = "5.2.0", features = ["debug-embed"] }
@ -26,6 +27,9 @@ flexi_logger = { version = "0.14.6", default-features = false }
anyhow = "1.0.26"
parking_lot="0.10.0"
[target.'cfg(windows)'.dependencies]
winapi = "0.3.8"
[build-dependencies]
winres = "0.1.11"

@ -56,11 +56,13 @@ Note: Neovide requires neovim version 0.4 or greater.
### Windows
1. Install the latest version of Rust. I recommend <https://rustup.rs/>
2. Ensure graphics libraries are up to date.
3. `git clone https://github.com/Kethku/neovide`
4. `cd neovide`
5. `cargo build --release`
6. Copy `./target/release/neovide.exe` to a known location and enjoy.
2. Install CMake. I use chocolatey: `choco install cmake --installargs '"ADD_CMAKE_TO_PATH=System"' -y`
3. Install LLVM. I use chocolatey: `choco install llvm -y`
4. Ensure graphics libraries are up to date.
5. `git clone https://github.com/Kethku/neovide`
6. `cd neovide`
7. `cargo build --release`
8. Copy `./target/release/neovide.exe` to a known location and enjoy.
### Mac
@ -73,7 +75,7 @@ Note: Neovide requires neovim version 0.4 or greater.
### Linux
Instructions to build on Ubuntu
Note: Neovide has been successfully built on other destros but this reportedly works on ubuntu.
1. Install necessary dependencies

@ -1,7 +1,8 @@
use log::trace;
use skulpin::winit::event::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode};
// use skulpin::winit::event::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode};
use skulpin::sdl2::keyboard::{Keycode, Mod};
fn parse_keycode(keycode: VirtualKeyCode) -> Option<(&'static str, bool)> {
pub fn parse_keycode(keycode: Keycode) -> Option<(&'static str, bool)> {
macro_rules! unsupported_key {
($name: ident) => {{
if cfg!(debug_assertions) {
@ -11,228 +12,263 @@ fn parse_keycode(keycode: VirtualKeyCode) -> Option<(&'static str, bool)> {
}};
}
// Documentation: https://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlkey.html
match keycode {
VirtualKeyCode::Key1 => Some(("1", false)),
VirtualKeyCode::Key2 => Some(("2", false)),
VirtualKeyCode::Key3 => Some(("3", false)),
VirtualKeyCode::Key4 => Some(("4", false)),
VirtualKeyCode::Key5 => Some(("5", false)),
VirtualKeyCode::Key6 => Some(("6", false)),
VirtualKeyCode::Key7 => Some(("7", false)),
VirtualKeyCode::Key8 => Some(("8", false)),
VirtualKeyCode::Key9 => Some(("9", false)),
VirtualKeyCode::Key0 => Some(("0", false)),
VirtualKeyCode::A => Some(("a", false)),
VirtualKeyCode::B => Some(("b", false)),
VirtualKeyCode::C => Some(("c", false)),
VirtualKeyCode::D => Some(("d", false)),
VirtualKeyCode::E => Some(("e", false)),
VirtualKeyCode::F => Some(("f", false)),
VirtualKeyCode::G => Some(("g", false)),
VirtualKeyCode::H => Some(("h", false)),
VirtualKeyCode::I => Some(("i", false)),
VirtualKeyCode::J => Some(("j", false)),
VirtualKeyCode::K => Some(("k", false)),
VirtualKeyCode::L => Some(("l", false)),
VirtualKeyCode::M => Some(("m", false)),
VirtualKeyCode::N => Some(("n", false)),
VirtualKeyCode::O => Some(("o", false)),
VirtualKeyCode::P => Some(("p", false)),
VirtualKeyCode::Q => Some(("q", false)),
VirtualKeyCode::R => Some(("r", false)),
VirtualKeyCode::S => Some(("s", false)),
VirtualKeyCode::T => Some(("t", false)),
VirtualKeyCode::U => Some(("u", false)),
VirtualKeyCode::V => Some(("v", false)),
VirtualKeyCode::W => Some(("w", false)),
VirtualKeyCode::X => Some(("x", false)),
VirtualKeyCode::Y => Some(("y", false)),
VirtualKeyCode::Z => Some(("z", false)),
VirtualKeyCode::Escape => Some(("ESC", true)),
VirtualKeyCode::F1 => Some(("F1", true)),
VirtualKeyCode::F2 => Some(("F2", true)),
VirtualKeyCode::F3 => Some(("F3", true)),
VirtualKeyCode::F4 => Some(("F4", true)),
VirtualKeyCode::F5 => Some(("F5", true)),
VirtualKeyCode::F6 => Some(("F6", true)),
VirtualKeyCode::F7 => Some(("F7", true)),
VirtualKeyCode::F8 => Some(("F8", true)),
VirtualKeyCode::F9 => Some(("F9", true)),
VirtualKeyCode::F10 => Some(("F10", true)),
VirtualKeyCode::F11 => Some(("F11", true)),
VirtualKeyCode::F12 => Some(("F12", true)),
VirtualKeyCode::F13 => Some(("F13", true)),
VirtualKeyCode::F14 => Some(("F14", true)),
VirtualKeyCode::F15 => Some(("F15", true)),
VirtualKeyCode::F16 => Some(("F16", true)),
VirtualKeyCode::F17 => Some(("F17", true)),
VirtualKeyCode::F18 => Some(("F18", true)),
VirtualKeyCode::F19 => Some(("F19", true)),
VirtualKeyCode::F20 => Some(("F20", true)),
VirtualKeyCode::F21 => Some(("F21", true)),
VirtualKeyCode::F22 => Some(("F22", true)),
VirtualKeyCode::F23 => Some(("F23", true)),
VirtualKeyCode::F24 => Some(("F24", true)),
VirtualKeyCode::Snapshot => unsupported_key!(Snapshot),
VirtualKeyCode::Scroll => unsupported_key!(Scroll),
VirtualKeyCode::Pause => unsupported_key!(Pause),
VirtualKeyCode::Insert => Some(("Insert", true)),
VirtualKeyCode::Home => Some(("Home", true)),
VirtualKeyCode::Delete => Some(("Delete", true)),
VirtualKeyCode::End => Some(("End", true)),
VirtualKeyCode::PageDown => Some(("PageDown", true)),
VirtualKeyCode::PageUp => Some(("PageUp", true)),
VirtualKeyCode::Left => Some(("Left", true)),
VirtualKeyCode::Up => Some(("Up", true)),
VirtualKeyCode::Right => Some(("Right", true)),
VirtualKeyCode::Down => Some(("Down", true)),
VirtualKeyCode::Back => Some(("BS", true)),
VirtualKeyCode::Return => Some(("Enter", true)),
VirtualKeyCode::Space => Some(("Space", true)),
VirtualKeyCode::Compose => unsupported_key!(Compose),
VirtualKeyCode::Caret => Some(("^", false)),
VirtualKeyCode::Numlock => unsupported_key!(Numlock),
VirtualKeyCode::Numpad0 => Some(("0", false)),
VirtualKeyCode::Numpad1 => Some(("1", false)),
VirtualKeyCode::Numpad2 => Some(("2", false)),
VirtualKeyCode::Numpad3 => Some(("3", false)),
VirtualKeyCode::Numpad4 => Some(("4", false)),
VirtualKeyCode::Numpad5 => Some(("5", false)),
VirtualKeyCode::Numpad6 => Some(("6", false)),
VirtualKeyCode::Numpad7 => Some(("7", false)),
VirtualKeyCode::Numpad8 => Some(("8", false)),
VirtualKeyCode::Numpad9 => Some(("9", false)),
// These next two are for Brazillian keyboards according to
// https://hg.mozilla.org/integration/mozilla-inbound/rev/28039c359ce8#l2.31
// Mapping both to the same thing as firefox
VirtualKeyCode::AbntC1 => Some(("/", false)),
VirtualKeyCode::AbntC2 => Some((".", false)),
VirtualKeyCode::Add => Some(("+", true)),
VirtualKeyCode::Apostrophe => Some(("'", false)),
VirtualKeyCode::Apps => unsupported_key!(Apps),
VirtualKeyCode::At => Some(("@", false)),
VirtualKeyCode::Ax => unsupported_key!(Ax),
VirtualKeyCode::Backslash => Some(("Bslash", true)),
VirtualKeyCode::Calculator => unsupported_key!(Calculator),
VirtualKeyCode::Capital => unsupported_key!(Capital),
VirtualKeyCode::Colon => Some((":", false)),
VirtualKeyCode::Comma => Some((",", false)),
VirtualKeyCode::Convert => unsupported_key!(Convert),
VirtualKeyCode::Decimal => Some((".", false)),
VirtualKeyCode::Divide => Some(("/", false)),
VirtualKeyCode::Equals => Some(("=", false)),
VirtualKeyCode::Grave => Some(("`", false)),
VirtualKeyCode::Kana => unsupported_key!(Kana),
VirtualKeyCode::Kanji => unsupported_key!(Kanji),
VirtualKeyCode::LAlt => None, // Regular modifier key
VirtualKeyCode::LBracket => Some(("[", false)),
VirtualKeyCode::LControl => None, // Regular modifier key
VirtualKeyCode::LShift => None, // Regular modifier key
VirtualKeyCode::LWin => unsupported_key!(LWin),
VirtualKeyCode::Mail => unsupported_key!(Mail),
VirtualKeyCode::MediaSelect => unsupported_key!(MediaSelect),
VirtualKeyCode::MediaStop => unsupported_key!(MediaStop),
VirtualKeyCode::Minus => Some(("-", false)),
VirtualKeyCode::Multiply => Some(("*", false)),
VirtualKeyCode::Mute => unsupported_key!(Mute),
VirtualKeyCode::MyComputer => unsupported_key!(MyComputer),
VirtualKeyCode::NavigateForward => unsupported_key!(NavigateForward),
VirtualKeyCode::NavigateBackward => unsupported_key!(NavigateBackward),
VirtualKeyCode::NextTrack => unsupported_key!(NextTrack),
VirtualKeyCode::NoConvert => unsupported_key!(NoConvert),
VirtualKeyCode::NumpadComma => Some((",", false)),
VirtualKeyCode::NumpadEnter => Some(("Enter", true)),
VirtualKeyCode::NumpadEquals => Some(("=", false)),
VirtualKeyCode::OEM102 => unsupported_key!(OEM102),
VirtualKeyCode::Period => Some((".", false)),
VirtualKeyCode::PlayPause => unsupported_key!(PlayPause),
VirtualKeyCode::Power => unsupported_key!(Power),
VirtualKeyCode::PrevTrack => unsupported_key!(PrevTrack),
VirtualKeyCode::RAlt => None, // Regular modifier key
VirtualKeyCode::RBracket => Some(("]", false)),
VirtualKeyCode::RControl => None, // Regular modifier key
VirtualKeyCode::RShift => None, // Regular modifier key
VirtualKeyCode::RWin => unsupported_key!(RWin),
VirtualKeyCode::Semicolon => Some((";", false)),
VirtualKeyCode::Slash => Some(("/", false)),
VirtualKeyCode::Sleep => unsupported_key!(Sleep),
VirtualKeyCode::Stop => unsupported_key!(Stop),
VirtualKeyCode::Subtract => Some(("-", false)),
VirtualKeyCode::Sysrq => unsupported_key!(Sysrq),
VirtualKeyCode::Tab => Some(("Tab", true)),
VirtualKeyCode::Underline => unsupported_key!(Underline),
VirtualKeyCode::Unlabeled => unsupported_key!(Unlabeled),
VirtualKeyCode::VolumeDown => unsupported_key!(VolumeDown),
VirtualKeyCode::VolumeUp => unsupported_key!(VolumeUp),
VirtualKeyCode::Wake => unsupported_key!(Wake),
VirtualKeyCode::WebBack => unsupported_key!(WebBack),
VirtualKeyCode::WebFavorites => unsupported_key!(WebFavorites),
VirtualKeyCode::WebForward => unsupported_key!(WebForward),
VirtualKeyCode::WebHome => unsupported_key!(WebHome),
VirtualKeyCode::WebRefresh => unsupported_key!(WebRefresh),
VirtualKeyCode::WebSearch => unsupported_key!(WebSearch),
VirtualKeyCode::WebStop => unsupported_key!(WebStop),
VirtualKeyCode::Yen => Some(("¥", false)),
VirtualKeyCode::Copy => unsupported_key!(Copy),
VirtualKeyCode::Paste => unsupported_key!(Paste),
VirtualKeyCode::Cut => unsupported_key!(Cut),
Keycode::Backspace => Some(("BS", true)),
Keycode::Tab => Some(("Tab", true)),
Keycode::Return => Some(("Enter", true)),
Keycode::Escape => Some(("Esc", true)),
Keycode::Space => Some((" ", false)),
Keycode::Exclaim => Some(("!", false)),
Keycode::Quotedbl => Some(("\"", false)),
Keycode::Hash => Some(("#", false)),
Keycode::Dollar => Some(("$", false)),
Keycode::Percent => Some(("%", false)),
Keycode::Ampersand => Some(("&", false)),
Keycode::Quote => Some(("'", false)),
Keycode::LeftParen => Some(("(", false)),
Keycode::RightParen => Some((")", false)),
Keycode::Asterisk => Some(("*", false)),
Keycode::Plus => Some(("+", false)),
Keycode::Comma => Some((",", false)),
Keycode::Minus => Some(("-", false)),
Keycode::Period => Some((".", false)),
Keycode::Slash => Some(("/", false)),
Keycode::Num0 => Some(("0", false)),
Keycode::Num1 => Some(("1", false)),
Keycode::Num2 => Some(("2", false)),
Keycode::Num3 => Some(("3", false)),
Keycode::Num4 => Some(("4", false)),
Keycode::Num5 => Some(("5", false)),
Keycode::Num6 => Some(("6", false)),
Keycode::Num7 => Some(("7", false)),
Keycode::Num8 => Some(("8", false)),
Keycode::Num9 => Some(("9", false)),
Keycode::Colon => Some((":", false)),
Keycode::Semicolon => Some((";", false)),
Keycode::Less => Some(("lt", true)),
Keycode::Equals => Some(("=", false)),
Keycode::Greater => Some(("gt", true)),
Keycode::Question => Some(("?", false)),
Keycode::At => Some(("@", false)),
Keycode::LeftBracket => Some(("[", false)),
Keycode::Backslash => Some(("\\", false)),
Keycode::RightBracket => Some(("]", false)),
Keycode::Caret => Some(("^", false)),
Keycode::Underscore => Some(("_", false)),
Keycode::Backquote => Some(("`", false)),
Keycode::A => Some(("a", false)),
Keycode::B => Some(("b", false)),
Keycode::C => Some(("c", false)),
Keycode::D => Some(("d", false)),
Keycode::E => Some(("e", false)),
Keycode::F => Some(("f", false)),
Keycode::G => Some(("g", false)),
Keycode::H => Some(("h", false)),
Keycode::I => Some(("i", false)),
Keycode::J => Some(("j", false)),
Keycode::K => Some(("k", false)),
Keycode::L => Some(("l", false)),
Keycode::M => Some(("m", false)),
Keycode::N => Some(("n", false)),
Keycode::O => Some(("o", false)),
Keycode::P => Some(("p", false)),
Keycode::Q => Some(("q", false)),
Keycode::R => Some(("r", false)),
Keycode::S => Some(("s", false)),
Keycode::T => Some(("t", false)),
Keycode::U => Some(("u", false)),
Keycode::V => Some(("v", false)),
Keycode::W => Some(("w", false)),
Keycode::X => Some(("x", false)),
Keycode::Y => Some(("y", false)),
Keycode::Z => Some(("z", false)),
Keycode::Delete => Some(("Delete", true)),
Keycode::CapsLock => unsupported_key!(CapsLock),
Keycode::F1 => Some(("F1", true)),
Keycode::F2 => Some(("F2", true)),
Keycode::F3 => Some(("F3", true)),
Keycode::F4 => Some(("F4", true)),
Keycode::F5 => Some(("F5", true)),
Keycode::F6 => Some(("F6", true)),
Keycode::F7 => Some(("F7", true)),
Keycode::F8 => Some(("F8", true)),
Keycode::F9 => Some(("F9", true)),
Keycode::F10 => Some(("F10", true)),
Keycode::F11 => Some(("F11", true)),
Keycode::F12 => Some(("F12", true)),
Keycode::PrintScreen => unsupported_key!(PrintScreen),
Keycode::ScrollLock => unsupported_key!(ScrollLock),
Keycode::Pause => unsupported_key!(Pause),
Keycode::Insert => Some(("Insert", true)),
Keycode::Home => Some(("Home", true)),
Keycode::PageUp => Some(("PageUp", true)),
Keycode::End => Some(("End", true)),
Keycode::PageDown => Some(("PageDown", true)),
Keycode::Right => Some(("Right", true)),
Keycode::Left => Some(("Left", true)),
Keycode::Down => Some(("Down", true)),
Keycode::Up => Some(("Up", true)),
Keycode::NumLockClear => unsupported_key!(NumLockClear),
Keycode::KpDivide => Some(("/", true)),
Keycode::KpMultiply => Some(("*", true)),
Keycode::KpMinus => Some(("-", true)),
Keycode::KpPlus => Some(("+", true)),
Keycode::KpEnter => Some(("Enter", true)),
Keycode::Kp0 => Some(("0", false)),
Keycode::Kp1 => Some(("1", false)),
Keycode::Kp2 => Some(("2", false)),
Keycode::Kp3 => Some(("3", false)),
Keycode::Kp4 => Some(("4", false)),
Keycode::Kp5 => Some(("5", false)),
Keycode::Kp6 => Some(("6", false)),
Keycode::Kp7 => Some(("7", false)),
Keycode::Kp8 => Some(("8", false)),
Keycode::Kp9 => Some(("9", false)),
Keycode::KpPeriod => Some((".", false)),
Keycode::Application => unsupported_key!(Application),
Keycode::Power => unsupported_key!(Power),
Keycode::KpEquals => Some(("=", false)),
Keycode::F13 => Some(("F13", true)),
Keycode::F14 => Some(("F14", true)),
Keycode::F15 => Some(("F15", true)),
Keycode::F16 => Some(("F16", true)),
Keycode::F17 => Some(("F17", true)),
Keycode::F18 => Some(("F18", true)),
Keycode::F19 => Some(("F19", true)),
Keycode::F20 => Some(("F20", true)),
Keycode::F21 => Some(("F21", true)),
Keycode::F22 => Some(("F22", true)),
Keycode::F23 => Some(("F23", true)),
Keycode::F24 => Some(("F24", true)),
Keycode::Execute => unsupported_key!(Execute),
Keycode::Help => unsupported_key!(Help),
Keycode::Menu => unsupported_key!(Menu),
Keycode::Select => unsupported_key!(Select),
Keycode::Stop => unsupported_key!(Stop),
Keycode::Again => unsupported_key!(Again),
Keycode::Undo => unsupported_key!(Undo),
Keycode::Cut => unsupported_key!(Cut),
Keycode::Copy => unsupported_key!(Copy),
Keycode::Paste => unsupported_key!(Paste),
Keycode::Find => unsupported_key!(Find),
Keycode::Mute => unsupported_key!(Mute),
Keycode::VolumeUp => unsupported_key!(VolumeUp),
Keycode::VolumeDown => unsupported_key!(VolumeDown),
Keycode::KpComma => unsupported_key!(KpComma),
Keycode::KpEqualsAS400 => unsupported_key!(KpEqualsAS400),
Keycode::AltErase => unsupported_key!(AltErase),
Keycode::Sysreq => unsupported_key!(Sysreq),
Keycode::Cancel => unsupported_key!(Cancel),
Keycode::Clear => unsupported_key!(Clear),
Keycode::Prior => unsupported_key!(Prior),
Keycode::Return2 => unsupported_key!(Return2),
Keycode::Separator => unsupported_key!(Separator),
Keycode::Out => unsupported_key!(Out),
Keycode::Oper => unsupported_key!(Oper),
Keycode::ClearAgain => unsupported_key!(ClearAgain),
Keycode::CrSel => unsupported_key!(CrSel),
Keycode::ExSel => unsupported_key!(ExSel),
Keycode::Kp00 => unsupported_key!(Kp00),
Keycode::Kp000 => unsupported_key!(Kp000),
Keycode::ThousandsSeparator => unsupported_key!(ThousandsSeparator),
Keycode::DecimalSeparator => unsupported_key!(DecimalSeparator),
Keycode::CurrencyUnit => unsupported_key!(CurrencyUnit),
Keycode::CurrencySubUnit => unsupported_key!(CurrencySubUnit),
Keycode::KpLeftParen => Some(("(", false)),
Keycode::KpRightParen => Some((")", false)),
Keycode::KpLeftBrace => Some(("[", false)),
Keycode::KpRightBrace => Some(("]", false)),
Keycode::KpTab => Some(("TAB", true)),
Keycode::KpBackspace => Some(("BS", true)),
Keycode::KpA => Some(("A", false)),
Keycode::KpB => Some(("B", false)),
Keycode::KpC => Some(("C", false)),
Keycode::KpD => Some(("D", false)),
Keycode::KpE => Some(("E", false)),
Keycode::KpF => Some(("F", false)),
Keycode::KpXor => unsupported_key!(KpXor),
Keycode::KpPower => Some(("^", false)),
Keycode::KpPercent => Some(("%", false)),
Keycode::KpLess => Some(("lt", true)),
Keycode::KpGreater => Some(("gt", true)),
Keycode::KpAmpersand => Some(("&", false)),
Keycode::KpDblAmpersand => unsupported_key!(KpDblAmpersand),
Keycode::KpVerticalBar => Some(("|", false)),
Keycode::KpDblVerticalBar => unsupported_key!(KpDblVerticalBar),
Keycode::KpColon => Some((":", false)),
Keycode::KpHash => Some(("#", false)),
Keycode::KpSpace => Some((" ", false)),
Keycode::KpAt => Some(("@", false)),
Keycode::KpExclam => Some(("!", false)),
Keycode::KpMemStore => unsupported_key!(KpMemStore),
Keycode::KpMemRecall => unsupported_key!(KpMemRecall),
Keycode::KpMemClear => unsupported_key!(KpMemClear),
Keycode::KpMemAdd => unsupported_key!(KpMemAdd),
Keycode::KpMemSubtract => unsupported_key!(KpMemSubtract),
Keycode::KpMemMultiply => unsupported_key!(KpMemMultiply),
Keycode::KpMemDivide => unsupported_key!(KpMemDivide),
Keycode::KpPlusMinus => unsupported_key!(KpPlusMinus),
Keycode::KpClear => unsupported_key!(KpClear),
Keycode::KpClearEntry => unsupported_key!(KpClearEntry),
Keycode::KpBinary => unsupported_key!(KpBinary),
Keycode::KpOctal => unsupported_key!(KpOctal),
Keycode::KpDecimal => unsupported_key!(KpDecimal),
Keycode::KpHexadecimal => unsupported_key!(KpHexadecimal),
Keycode::LCtrl => None,
Keycode::LShift => None,
Keycode::LAlt => None,
Keycode::LGui => None,
Keycode::RCtrl => None,
Keycode::RShift => None,
Keycode::RAlt => None,
Keycode::RGui => None,
Keycode::Mode => unsupported_key!(Mode),
Keycode::AudioNext => unsupported_key!(AudioNext),
Keycode::AudioPrev => unsupported_key!(AudioPrev),
Keycode::AudioStop => unsupported_key!(AudioStop),
Keycode::AudioPlay => unsupported_key!(AudioPlay),
Keycode::AudioMute => unsupported_key!(AudioMute),
Keycode::MediaSelect => unsupported_key!(MediaSelect),
Keycode::Www => unsupported_key!(Www),
Keycode::Mail => unsupported_key!(Mail),
Keycode::Calculator => unsupported_key!(Calculator),
Keycode::Computer => unsupported_key!(Computer),
Keycode::AcSearch => unsupported_key!(AcSearch),
Keycode::AcHome => unsupported_key!(AcHome),
Keycode::AcBack => unsupported_key!(AcBack),
Keycode::AcForward => unsupported_key!(AcForward),
Keycode::AcStop => unsupported_key!(AcStop),
Keycode::AcRefresh => unsupported_key!(AcRefresh),
Keycode::AcBookmarks => unsupported_key!(AcBookmarks),
Keycode::BrightnessDown => unsupported_key!(BrightnessDown),
Keycode::BrightnessUp => unsupported_key!(BrightnessUp),
Keycode::DisplaySwitch => unsupported_key!(DisplaySwitch),
Keycode::KbdIllumToggle =>unsupported_key!(KbdIllumToggle),
Keycode::KbdIllumDown => unsupported_key!(KbdIllumDown),
Keycode::KbdIllumUp => unsupported_key!(KbdIllumUp),
Keycode::Eject => unsupported_key!(Eject),
Keycode::Sleep => unsupported_key!(Sleep)
}
}
pub fn append_modifiers(modifiers: ModifiersState, keycode_text: &str, special: bool) -> String {
pub fn append_modifiers(modifiers: Mod, keycode_text: &str, special: bool) -> String {
let mut result = keycode_text.to_string();
let mut special = special;
if modifiers.shift() {
result = match result.as_ref() {
"1" => "!".to_string(),
"2" => "@".to_string(),
"3" => "#".to_string(),
"4" => "$".to_string(),
"5" => "%".to_string(),
"6" => "^".to_string(),
"7" => "&".to_string(),
"8" => "*".to_string(),
"9" => "(".to_string(),
"0" => ")".to_string(),
"'" => "\"".to_string(),
"Bslash" => {
special = false;
"|".to_string()
},
"," => {
if modifiers.contains(Mod::LSHIFTMOD) || modifiers.contains(Mod::RSHIFTMOD) {
special = true;
"lt".to_string()
},
"=" => "+".to_string(),
"`" => "~".to_string(),
"[" => "{".to_string(),
"-" => "_".to_string(),
"." => ">".to_string(),
"]" => "}".to_string(),
";" => ":".to_string(),
"/" => "?".to_string(),
other => {
special = true;
format!("S-{}", other)
}
};
}
if result == "<" {
special = true;
result = "lt".to_string();
result = format!("S-{}", result);
}
if modifiers.ctrl() {
if modifiers.contains(Mod::LCTRLMOD) || modifiers.contains(Mod::RCTRLMOD) {
special = true;
result = format!("C-{}", result);
}
if modifiers.alt() {
if modifiers.contains(Mod::LALTMOD) || modifiers.contains(Mod::RALTMOD) {
special = true;
result = format!("M-{}", result);
}
if modifiers.logo() {
if modifiers.contains(Mod::LGUIMOD) || modifiers.contains(Mod::RGUIMOD) {
special = true;
result = format!("D-{}", result);
}
@ -243,21 +279,3 @@ pub fn append_modifiers(modifiers: ModifiersState, keycode_text: &str, special:
result
}
pub fn construct_keybinding_string(input: KeyboardInput) -> Option<String> {
match input {
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(keycode),
modifiers,
..
} => {
if let Some((keycode_text, special)) = parse_keycode(keycode) {
Some(append_modifiers(modifiers, keycode_text, special))
} else {
None
}
},
_ => None
}
}

@ -4,31 +4,31 @@ use tokio::process::ChildStdin;
#[derive(Debug, Clone)]
pub enum UiCommand {
Resize { width: i64, height: i64 },
Resize { width: u32, height: u32 },
Keyboard(String),
MouseButton { action: String, position: (i64, i64) },
Scroll { direction: String, position: (i64, i64) },
Drag(i64, i64)
MouseButton { action: String, position: (u32, u32) },
Scroll { direction: String, position: (u32, u32) },
Drag(u32, u32)
}
impl UiCommand {
pub async fn execute(self, nvim: &Neovim<Compat<ChildStdin>>) {
match self {
UiCommand::Resize { width, height } =>
nvim.ui_try_resize(width.max(10), height.max(3)).await
nvim.ui_try_resize(width.max(10) as i64, height.max(3) as i64).await
.expect("Resize failed"),
UiCommand::Keyboard(input_command) => {
nvim.input(&input_command).await
.expect("Input failed");
},
UiCommand::MouseButton { action, position: (grid_x, grid_y) } =>
nvim.input_mouse("left", &action, "", 0, grid_x, grid_y).await
nvim.input_mouse("left", &action, "", 0, grid_y as i64, grid_x as i64).await
.expect("Mouse Input Failed"),
UiCommand::Scroll { direction, position: (grid_x, grid_y) } =>
nvim.input_mouse("wheel", &direction, "", 0, grid_x, grid_y).await
nvim.input_mouse("wheel", &direction, "", 0, grid_y as i64, grid_x as i64).await
.expect("Mouse Scroll Failed"),
UiCommand::Drag(grid_x, grid_y) =>
nvim.input_mouse("left", "drag", "", 0, grid_x, grid_y).await
nvim.input_mouse("left", "drag", "", 0, grid_y as i64, grid_x as i64).await
.expect("Mouse Drag Failed")
}
}

@ -7,6 +7,7 @@ use nvim_rs::compat::tokio::Compat;
use flexi_logger::{Logger, Criterion, Naming, Cleanup};
use tokio::process::ChildStdin;
use parking_lot::Mutex;
use log::warn;
use crate::error_handling::ResultPanicExplanation;
@ -14,6 +15,7 @@ lazy_static! {
pub static ref SETTINGS: Settings = Settings::new();
}
#[derive(Debug)]
pub enum Setting {
Bool(bool),
U16(u16),
@ -111,20 +113,22 @@ pub struct Settings {
impl Settings {
pub async fn read_initial_values(&self, nvim: &Neovim<Compat<ChildStdin>>) {
let keys : Vec<String>= self.settings.lock().keys().cloned().collect();
let keys : Vec<String> = self.settings.lock().keys().cloned().collect();
for name in keys {
let variable_name = format!("g:neovide_{}", name.to_string());
if let Ok(value) = nvim.get_var(&variable_name).await {
self.settings.lock().get_mut(&name).unwrap().parse(value);
} else {
let variable_name = format!("neovide_{}", name.to_string());
match nvim.get_var(&variable_name).await {
Ok(value) => self.settings.lock().get_mut(&name).unwrap().parse(value),
Err(error) => {
warn!("Initial value load failed for {}: {}", name, error);
let setting = self.get(&name);
nvim.set_var(&variable_name, setting.unparse()).await.ok();
}
}
}
}
pub async fn setup_changed_listeners(&self, nvim: &Neovim<Compat<ChildStdin>>) {
let keys : Vec<String>= self.settings.lock().keys().cloned().collect();
let keys : Vec<String> = self.settings.lock().keys().cloned().collect();
for name in keys {
let vimscript =
format!("function NeovideNotify{}Changed(d, k, z)\n", name) +
@ -139,7 +143,6 @@ impl Settings {
pub fn handle_changed_notification(&self, arguments: Vec<Value>) {
let mut arguments = arguments.into_iter();
let (name, value) = (arguments.next().unwrap(), arguments.next().unwrap());
dbg!(&name, &value);
let name: Result<String, _>= name.try_into();
let name = name.unwrap();
@ -180,6 +183,7 @@ impl Settings {
settings.insert("no_idle".to_string(), Setting::new_bool(no_idle));
settings.insert("extra_buffer_frames".to_string(), Setting::new_u16(buffer_frames));
settings.insert("refresh_rate".to_string(), Setting::new_u16(60));
Settings { neovim_arguments, settings: Mutex::new(settings) }
}

@ -1,16 +1,14 @@
use std::sync::Arc;
use std::sync::atomic::Ordering;
use std::time::{Duration, Instant};
use std::thread::sleep;
use image::{load_from_memory, GenericImageView, Pixel};
use skulpin::{CoordinateSystem, RendererBuilder, PresentMode};
use skulpin::winit::dpi::{LogicalSize, LogicalPosition};
use skulpin::winit::event::{ElementState, Event, MouseScrollDelta, StartCause, WindowEvent, ModifiersState};
use skulpin::winit::event_loop::{ControlFlow, EventLoop};
use skulpin::winit::window::{Icon, WindowBuilder};
use log::{info, debug, trace, error};
use log::{info, debug, error};
use skulpin::{LogicalSize, PhysicalSize};
use skulpin::sdl2;
use skulpin::sdl2::event::Event;
use skulpin::sdl2::keyboard::Mod;
use skulpin::{RendererBuilder, PresentMode, CoordinateSystem, dpis};
use crate::bridge::{construct_keybinding_string, BRIDGE, UiCommand};
use crate::bridge::{parse_keycode, append_modifiers, BRIDGE, UiCommand};
use crate::renderer::Renderer;
use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::editor::EDITOR;
@ -21,216 +19,206 @@ use crate::INITIAL_DIMENSIONS;
#[folder = "assets/"]
struct Asset;
fn handle_new_grid_size(new_size: LogicalSize<f32>, renderer: &Renderer) {
if new_size.width > 0.0 && new_size.height > 0.0 {
let new_width = ((new_size.width + 1.0) / renderer.font_width) as i64;
let new_height = ((new_size.height + 1.0) / renderer.font_height) as i64;
#[cfg(target_os = "windows")]
fn windows_fix_dpi() {
use winapi::um::winuser::SetProcessDpiAwarenessContext;
use winapi::shared::windef::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
unsafe {
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
}
fn handle_new_grid_size(new_size: LogicalSize, renderer: &Renderer) {
if new_size.width > 0 && new_size.height > 0 {
let new_width = ((new_size.width + 1) as f32 / renderer.font_width) as u32;
let new_height = ((new_size.height + 1) as f32 / renderer.font_height) as u32;
// Add 1 here to make sure resizing doesn't change the grid size on startup
BRIDGE.queue_command(UiCommand::Resize { width: new_width as i64, height: new_height as i64 });
BRIDGE.queue_command(UiCommand::Resize { width: new_width, height: new_height });
}
}
pub fn ui_loop() {
let event_loop = EventLoop::<()>::with_user_event();
let sdl_context = sdl2::init().expect("Failed to initialize sdl2");
let video_subsystem = sdl_context.video().expect("Failed to create sdl video subsystem");
let mut renderer = Renderer::new();
let (width, height) = INITIAL_DIMENSIONS;
let logical_size = LogicalSize::new(
(width as f32 * renderer.font_width) as f64,
(height as f32 * renderer.font_height + 1.0) as f64
);
let icon = {
let icon_data = Asset::get("nvim.ico").expect("Failed to read icon data");
let icon = load_from_memory(&icon_data).expect("Failed to parse icon data");
let (width, height) = icon.dimensions();
let mut rgba = Vec::with_capacity((width * height) as usize * 4);
for (_, _, pixel) in icon.pixels() {
rgba.extend_from_slice(&pixel.to_rgba().0);
}
Icon::from_rgba(rgba, width, height).expect("Failed to create icon object")
let mut renderer = Renderer::new();
let logical_size = LogicalSize {
width: (width as f32 * renderer.font_width) as u32,
height: (height as f32 * renderer.font_height + 1.0) as u32
};
info!("icon created");
let mut title = "Neovide".to_string();
let window = Arc::new(WindowBuilder::new()
.with_title(&title)
.with_inner_size(logical_size)
.with_window_icon(Some(icon))
.build(&event_loop)
.expect("Failed to create window"));
// let icon = {
// let icon_data = Asset::get("nvim.ico").expect("Failed to read icon data");
// let icon = load_from_memory(&icon_data).expect("Failed to parse icon data");
// let (width, height) = icon.dimensions();
// let mut rgba = Vec::with_capacity((width * height) as usize * 4);
// for (_, _, pixel) in icon.pixels() {
// rgba.extend_from_slice(&pixel.to_rgba().0);
// }
// Icon::from_rgba(rgba, width, height).expect("Failed to create icon object")
// };
// info!("icon created");
#[cfg(target_os = "windows")]
windows_fix_dpi();
sdl2::hint::set("SDL_MOUSE_FOCUS_CLICKTHROUGH", "1");
let mut window = video_subsystem.window("Neovide", logical_size.width, logical_size.height)
.position_centered()
.allow_highdpi()
.resizable()
.vulkan()
.build()
.expect("Failed to create window");
info!("window created");
let mut skulpin_renderer = RendererBuilder::new()
.prefer_integrated_gpu()
.use_vulkan_debug_layer(true)
.present_mode_priority(vec![PresentMode::Mailbox, PresentMode::Immediate])
.present_mode_priority(vec![PresentMode::Immediate])
.coordinate_system(CoordinateSystem::Logical)
.build(&window)
.expect("Failed to create renderer");
info!("renderer created");
let mut mouse_down = false;
let mut mouse_pos = (0, 0);
let mut mouse_position = LogicalSize {
width: 0,
height: 0
};
let mut allow_next_char = false;
let mut next_char_modifiers = ModifiersState::empty();
let mut title = "Neovide".to_string();
let mut previous_size = LogicalSize::new(&window).unwrap();
let mut previous_dpis = dpis(&window).unwrap();
info!("Starting window event loop");
event_loop.run(move |event, _window_target, control_flow| {
trace!("Window Event: {:?}", event);
match event {
Event::NewEvents(StartCause::Init) |
Event::NewEvents(StartCause::ResumeTimeReached { .. }) => {
window.request_redraw()
},
let mut event_pump = sdl_context.event_pump().expect("Could not create sdl event pump");
'running: loop {
let frame_start = Instant::now();
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => *control_flow = ControlFlow::Exit,
let editor_title = { EDITOR.lock().title.clone() };
if title != editor_title {
title = editor_title;
window.set_title(&title).expect("Could not set title");
}
Event::WindowEvent {
event: WindowEvent::Resized(new_size),
..
} => {
handle_new_grid_size(new_size.to_logical(window.scale_factor()), &renderer)
},
let mut ignore_text_input = false;
for event in event_pump.poll_iter() {
match event {
Event::Quit {..} => break 'running,
Event::Window {..} => REDRAW_SCHEDULER.queue_next_frame(),
Event::KeyDown { keycode: Some(keycode), keymod: modifiers, .. } => {
if let Some((key_text, special)) = parse_keycode(keycode) {
let will_text_input =
Event::WindowEvent {
event: WindowEvent::KeyboardInput {
input,
..
},
..
} => {
// Only interpret 'char' events when we get a previous event without a virtual
// keycode (which we ignore for KeyboardInput events).
// This is a hack so we don't lose a bunch of input events on Linux
if input.virtual_keycode == None {
allow_next_char = true;
}else {
allow_next_char = false;
}
next_char_modifiers = input.modifiers;
if let Some(keybinding_string) = construct_keybinding_string(input)
.map(UiCommand::Keyboard) {
BRIDGE.queue_command(keybinding_string);
!modifiers.contains(Mod::LCTRLMOD) &&
!modifiers.contains(Mod::RCTRLMOD) &&
!modifiers.contains(Mod::LALTMOD) &&
!modifiers.contains(Mod::RALTMOD) &&
!modifiers.contains(Mod::LGUIMOD) &&
!modifiers.contains(Mod::RGUIMOD);
if will_text_input && !special {
break;
}
},
Event::WindowEvent {
event: WindowEvent::ReceivedCharacter(c),
..
} => {
if allow_next_char {
next_char_modifiers.remove(ModifiersState::SHIFT);
let keybinding = super::bridge::append_modifiers(next_char_modifiers, &c.to_string(), false);
BRIDGE.queue_command(UiCommand::Keyboard(keybinding));
BRIDGE.queue_command(UiCommand::Keyboard(append_modifiers(modifiers, key_text, special)));
ignore_text_input = true;
}
},
Event::WindowEvent {
event: WindowEvent::CursorMoved {
position,
..
Event::TextInput { text, .. } => {
if ignore_text_input {
ignore_text_input = false;
} else {
let text = if text == "<" {
String::from("<lt>")
} else {
text
};
BRIDGE.queue_command(UiCommand::Keyboard(text))
}
},
..
} => {
let position: LogicalPosition<f64> = position.to_logical(window.scale_factor());
let grid_y = (position.x / renderer.font_width as f64) as i64;
let grid_x = (position.y / renderer.font_height as f64) as i64;
let (old_x, old_y) = mouse_pos;
mouse_pos = (grid_x, grid_y);
if mouse_down && (old_x != grid_x || old_y != grid_y) {
BRIDGE.queue_command(UiCommand::Drag(grid_x, grid_y));
}
}
Event::WindowEvent {
event: WindowEvent::MouseInput {
state,
..
Event::MouseMotion { x, y, .. } => {
let previous_position = mouse_position;
mouse_position = LogicalSize::from_physical_size_tuple((
(x as f32 / renderer.font_width) as u32,
(y as f32 / renderer.font_height) as u32
),
&window
).expect("Could not calculate logical mouse position");
if mouse_down && previous_position != mouse_position {
BRIDGE.queue_command(UiCommand::Drag(mouse_position.width, mouse_position.height));
}
},
..
} => {
let input_type = match (state, mouse_down) {
(ElementState::Pressed, false) => {
Event::MouseButtonDown { .. } => {
BRIDGE.queue_command(UiCommand::MouseButton { action: String::from("press"), position: (mouse_position.width, mouse_position.height) });
mouse_down = true;
Some("press")
},
(ElementState::Released, true) => {
Event::MouseButtonUp { .. } => {
BRIDGE.queue_command(UiCommand::MouseButton { action: String::from("release"), position: (mouse_position.width, mouse_position.height) });
mouse_down = false;
Some("release")
},
_ => None
};
if let Some(input_type) = input_type {
let (grid_x, grid_y) = mouse_pos;
BRIDGE.queue_command(UiCommand::MouseButton { action: input_type.to_string(), position: (grid_x, grid_y) });
}
}
Event::WindowEvent {
event: WindowEvent::MouseWheel {
delta: MouseScrollDelta::LineDelta(horizontal, vertical),
..
},
..
} => {
let vertical_input_type = if vertical > 0.0 {
Event::MouseWheel { x, y, .. } => {
let vertical_input_type = if y > 0 {
Some("up")
} else if vertical < 0.0 {
} else if y < 0 {
Some("down")
} else {
None
};
if let Some(input_type) = vertical_input_type {
BRIDGE.queue_command(UiCommand::Scroll { direction: input_type.to_string(), position: mouse_pos });
BRIDGE.queue_command(UiCommand::Scroll { direction: input_type.to_string(), position: (mouse_position.width, mouse_position.height) });
}
let horizontal_input_type = if horizontal > 0.0 {
let horizontal_input_type = if x > 0 {
Some("right")
} else if horizontal < 0.0 {
} else if x < 0 {
Some("left")
} else {
None
};
if let Some(input_type) = horizontal_input_type {
BRIDGE.queue_command(UiCommand::Scroll { direction: input_type.to_string(), position: mouse_pos });
BRIDGE.queue_command(UiCommand::Scroll { direction: input_type.to_string(), position: (mouse_position.width, mouse_position.height) });
}
},
_ => {}
}
}
Event::RedrawRequested { .. } => {
let frame_start = Instant::now();
let new_size = LogicalSize::new(&window).unwrap();
if previous_size != new_size {
handle_new_grid_size(new_size, &renderer);
previous_size = new_size;
}
let editor_title = { EDITOR.lock().title.clone() };
if title != editor_title {
title = editor_title;
window.set_title(&title);
let new_dpis = dpis(&window).unwrap();
if previous_dpis != new_dpis {
let physical_size = PhysicalSize::new(&window);
window.set_size(
(physical_size.width as f32 * new_dpis.0 / previous_dpis.0) as u32,
(physical_size.height as f32 * new_dpis.1 / previous_dpis.1) as u32).unwrap();
previous_dpis = new_dpis;
}
if REDRAW_SCHEDULER.should_draw() || SETTINGS.get("no_idle").read_bool() {
debug!("Render Triggered");
if REDRAW_SCHEDULER.should_draw() || SETTINGS.get("no_idle").read_bool() {
if skulpin_renderer.draw(&window, |canvas, coordinate_system_helper| {
if renderer.draw(canvas, coordinate_system_helper) {
handle_new_grid_size(window.inner_size().to_logical(window.scale_factor()), &renderer)
handle_new_grid_size(new_size, &renderer)
}
}).is_err() {
error!("Render failed. Closing");
*control_flow = ControlFlow::Exit;
return;
break;
}
}
*control_flow = ControlFlow::WaitUntil(frame_start + Duration::from_secs_f32(1.0 / 60.0));
},
_ => {}
let elapsed = frame_start.elapsed();
let refresh_rate = SETTINGS.get("refresh_rate").read_u16() as f32;
let frame_length = Duration::from_secs_f32(1.0 / refresh_rate);
if elapsed < frame_length {
sleep(frame_length - elapsed);
}
}
})
}

Loading…
Cancel
Save