mirror of https://github.com/sgoudham/neovide.git
in progress adding back winit
parent
a490e5992a
commit
451ff87272
@ -1,74 +1,75 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "neovide"
|
name = "neovide"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
authors = ["keith <keith@the-simmons.net>"]
|
authors = ["keith <keith@the-simmons.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
description = "A simple GUI for Neovim."
|
description = "A simple GUI for Neovim."
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["sdl2"]
|
default = ["sdl2"]
|
||||||
embed-fonts = []
|
embed-fonts = []
|
||||||
sdl2 = ["skulpin/skulpin_sdl2"]
|
sdl2 = ["skulpin/skulpin_sdl2"]
|
||||||
|
winit = ["skulpin/skulpin_winit"]
|
||||||
[dependencies]
|
|
||||||
euclid = "0.20.7"
|
[dependencies]
|
||||||
font-kit = "0.10.0"
|
euclid = "0.20.7"
|
||||||
skribo = { git = "https://github.com/linebender/skribo" }
|
font-kit = "0.10.0"
|
||||||
lru = "0.4.3"
|
skribo = { git = "https://github.com/linebender/skribo" }
|
||||||
skulpin = { git = "https://github.com/aclysma/skulpin", branch = "master", features = ["skulpin_sdl2"] }
|
lru = "0.4.3"
|
||||||
derive-new = "0.5"
|
skulpin = { git = "https://github.com/aclysma/skulpin", branch = "master", features = ["skulpin_sdl2"] }
|
||||||
rmpv = "0.4.4"
|
derive-new = "0.5"
|
||||||
rust-embed = { version = "5.2.0", features = ["debug-embed"] }
|
rmpv = "0.4.4"
|
||||||
image = "0.22.3"
|
rust-embed = { version = "5.2.0", features = ["debug-embed"] }
|
||||||
nvim-rs = { git = "https://github.com/kethku/nvim-rs", features = [ "use_tokio" ] }
|
image = "0.22.3"
|
||||||
tokio = { version = "0.2.9", features = [ "blocking", "process", "time" ] }
|
nvim-rs = { git = "https://github.com/kethku/nvim-rs", features = [ "use_tokio" ] }
|
||||||
async-trait = "0.1.18"
|
tokio = { version = "0.2.9", features = [ "blocking", "process", "time" ] }
|
||||||
crossfire = "0.1"
|
async-trait = "0.1.18"
|
||||||
lazy_static = "1.4.0"
|
crossfire = "0.1"
|
||||||
unicode-segmentation = "1.6.0"
|
lazy_static = "1.4.0"
|
||||||
log = "0.4.8"
|
unicode-segmentation = "1.6.0"
|
||||||
flexi_logger = { version = "0.14.6", default-features = false }
|
log = "0.4.8"
|
||||||
anyhow = "1.0.26"
|
flexi_logger = { version = "0.14.6", default-features = false }
|
||||||
parking_lot="0.10.0"
|
anyhow = "1.0.26"
|
||||||
cfg-if = "0.1.10"
|
parking_lot="0.10.0"
|
||||||
which = "4"
|
cfg-if = "0.1.10"
|
||||||
dirs = "2"
|
which = "4"
|
||||||
rand = "0.7"
|
dirs = "2"
|
||||||
skia-safe = "0.32.1"
|
rand = "0.7"
|
||||||
|
skia-safe = "0.32.1"
|
||||||
[dev-dependencies]
|
|
||||||
mockall = "0.7.0"
|
[dev-dependencies]
|
||||||
|
mockall = "0.7.0"
|
||||||
[dev-dependencies.cargo-husky]
|
|
||||||
version = "1"
|
[dev-dependencies.cargo-husky]
|
||||||
default-features = false
|
version = "1"
|
||||||
features = ["precommit-hook", "run-cargo-test", "run-cargo-clippy", "run-cargo-fmt"]
|
default-features = false
|
||||||
|
features = ["precommit-hook", "run-cargo-test", "run-cargo-clippy", "run-cargo-fmt"]
|
||||||
[target.'cfg(windows)'.dependencies]
|
|
||||||
winapi = "0.3.8"
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
winapi = "0.3.8"
|
||||||
[target.'cfg(windows)'.build-dependencies]
|
|
||||||
winres = "0.1.11"
|
[target.'cfg(windows)'.build-dependencies]
|
||||||
sdl2-sys = { version = "0.34.3", default-features = false, features = ["bundled", "static-link"] }
|
winres = "0.1.11"
|
||||||
|
sdl2-sys = { version = "0.34.3", default-features = false, features = ["bundled", "static-link"] }
|
||||||
[target.'cfg(macos)'.build-dependencies]
|
|
||||||
sdl2-sys = { version = "0.34.3", default-features = false, features = ["bundled", "static-link"] }
|
[target.'cfg(macos)'.build-dependencies]
|
||||||
|
sdl2-sys = { version = "0.34.3", default-features = false, features = ["bundled", "static-link"] }
|
||||||
[profile.release]
|
|
||||||
debug = true
|
[profile.release]
|
||||||
lto = true
|
debug = true
|
||||||
incremental = true
|
lto = true
|
||||||
|
incremental = true
|
||||||
[package.metadata.bundle]
|
|
||||||
name = "Neovide"
|
[package.metadata.bundle]
|
||||||
identifier = "com.kethku.neovide"
|
name = "Neovide"
|
||||||
icon = ["assets/nvim.ico"]
|
identifier = "com.kethku.neovide"
|
||||||
version = "0.6.0"
|
icon = ["assets/nvim.ico"]
|
||||||
resources = []
|
version = "0.6.0"
|
||||||
copyright = "Copyright (c) keith 2020. All rights reserved."
|
resources = []
|
||||||
category = "Productivity"
|
copyright = "Copyright (c) keith 2020. All rights reserved."
|
||||||
short_description = "A simple GUI for Neovim."
|
category = "Productivity"
|
||||||
long_description = """
|
short_description = "A simple GUI for Neovim."
|
||||||
This is a simple graphical user interface for Neovim. Where possible there are some graphical improvements, but it should act functionally like the terminal UI.
|
long_description = """
|
||||||
"""
|
This is a simple graphical user interface for Neovim. Where possible there are some graphical improvements, but it should act functionally like the terminal UI.
|
||||||
|
"""
|
||||||
|
@ -1,284 +1,280 @@
|
|||||||
#[macro_use]
|
mod events;
|
||||||
pub mod layouts;
|
mod handler;
|
||||||
|
mod ui_commands;
|
||||||
mod events;
|
|
||||||
mod handler;
|
use std::env;
|
||||||
mod ui_commands;
|
use std::path::Path;
|
||||||
|
use std::process::Stdio;
|
||||||
use std::env;
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::path::Path;
|
use std::sync::Arc;
|
||||||
use std::process::Stdio;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use crossfire::mpsc::{RxUnbounded, TxUnbounded};
|
||||||
use std::sync::Arc;
|
use log::{error, info, warn};
|
||||||
|
use nvim_rs::{create::tokio as create, UiAttachOptions};
|
||||||
use crossfire::mpsc::{RxUnbounded, TxUnbounded};
|
use rmpv::Value;
|
||||||
use log::{error, info, warn};
|
use tokio::process::Command;
|
||||||
use nvim_rs::{create::tokio as create, UiAttachOptions};
|
use tokio::runtime::Runtime;
|
||||||
use rmpv::Value;
|
|
||||||
use tokio::process::Command;
|
use crate::error_handling::ResultPanicExplanation;
|
||||||
use tokio::runtime::Runtime;
|
use crate::settings::*;
|
||||||
|
use crate::window::window_geometry_or_default;
|
||||||
use crate::error_handling::ResultPanicExplanation;
|
pub use events::*;
|
||||||
use crate::settings::*;
|
use handler::NeovimHandler;
|
||||||
use crate::window::window_geometry_or_default;
|
pub use ui_commands::UiCommand;
|
||||||
pub use events::*;
|
|
||||||
use handler::NeovimHandler;
|
#[cfg(windows)]
|
||||||
pub use layouts::*;
|
fn set_windows_creation_flags(cmd: &mut Command) {
|
||||||
pub use ui_commands::UiCommand;
|
cmd.creation_flags(0x0800_0000); // CREATE_NO_WINDOW
|
||||||
|
}
|
||||||
#[cfg(windows)]
|
|
||||||
fn set_windows_creation_flags(cmd: &mut Command) {
|
#[cfg(windows)]
|
||||||
cmd.creation_flags(0x0800_0000); // CREATE_NO_WINDOW
|
fn platform_build_nvim_cmd(bin: &str) -> Option<Command> {
|
||||||
}
|
if !Path::new(&bin).exists() {
|
||||||
|
return None;
|
||||||
#[cfg(windows)]
|
}
|
||||||
fn platform_build_nvim_cmd(bin: &str) -> Option<Command> {
|
|
||||||
if !Path::new(&bin).exists() {
|
if env::args().any(|arg| arg == "--wsl") {
|
||||||
return None;
|
let mut cmd = Command::new("wsl");
|
||||||
}
|
cmd.arg(bin);
|
||||||
|
Some(cmd)
|
||||||
if env::args().any(|arg| arg == "--wsl") {
|
} else {
|
||||||
let mut cmd = Command::new("wsl");
|
Some(Command::new(bin))
|
||||||
cmd.arg(bin);
|
}
|
||||||
Some(cmd)
|
}
|
||||||
} else {
|
|
||||||
Some(Command::new(bin))
|
#[cfg(unix)]
|
||||||
}
|
fn platform_build_nvim_cmd(bin: &str) -> Option<Command> {
|
||||||
}
|
if Path::new(&bin).exists() {
|
||||||
|
Some(Command::new(bin))
|
||||||
#[cfg(unix)]
|
} else {
|
||||||
fn platform_build_nvim_cmd(bin: &str) -> Option<Command> {
|
None
|
||||||
if Path::new(&bin).exists() {
|
}
|
||||||
Some(Command::new(bin))
|
}
|
||||||
} else {
|
|
||||||
None
|
fn build_nvim_cmd() -> Command {
|
||||||
}
|
if let Ok(path) = env::var("NEOVIM_BIN") {
|
||||||
}
|
if let Some(cmd) = platform_build_nvim_cmd(&path) {
|
||||||
|
return cmd;
|
||||||
fn build_nvim_cmd() -> Command {
|
} else {
|
||||||
if let Ok(path) = env::var("NEOVIM_BIN") {
|
warn!("NEOVIM_BIN is invalid falling back to first bin in PATH");
|
||||||
if let Some(cmd) = platform_build_nvim_cmd(&path) {
|
}
|
||||||
return cmd;
|
}
|
||||||
} else {
|
if let Ok(path) = which::which("nvim") {
|
||||||
warn!("NEOVIM_BIN is invalid falling back to first bin in PATH");
|
if let Some(cmd) = platform_build_nvim_cmd(path.to_str().unwrap()) {
|
||||||
}
|
cmd
|
||||||
}
|
} else {
|
||||||
if let Ok(path) = which::which("nvim") {
|
error!("nvim does not have proper permissions!");
|
||||||
if let Some(cmd) = platform_build_nvim_cmd(path.to_str().unwrap()) {
|
std::process::exit(1);
|
||||||
cmd
|
}
|
||||||
} else {
|
} else {
|
||||||
error!("nvim does not have proper permissions!");
|
error!("nvim not found!");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
error!("nvim not found!");
|
|
||||||
std::process::exit(1);
|
pub fn build_neovide_command(channel: u64, num_args: u64, command: &str, event: &str) -> String {
|
||||||
}
|
let nargs: String = if num_args > 1 {
|
||||||
}
|
"+".to_string()
|
||||||
|
} else {
|
||||||
pub fn build_neovide_command(channel: u64, num_args: u64, command: &str, event: &str) -> String {
|
num_args.to_string()
|
||||||
let nargs: String = if num_args > 1 {
|
};
|
||||||
"+".to_string()
|
if num_args == 0 {
|
||||||
} else {
|
return format!(
|
||||||
num_args.to_string()
|
"command! -nargs={} -complete=expression {} call rpcnotify({}, 'neovide.{}')",
|
||||||
};
|
nargs, command, channel, event
|
||||||
if num_args == 0 {
|
);
|
||||||
return format!(
|
} else {
|
||||||
"command! -nargs={} -complete=expression {} call rpcnotify({}, 'neovide.{}')",
|
return format!(
|
||||||
nargs, command, channel, event
|
"command! -nargs={} -complete=expression {} call rpcnotify({}, 'neovide.{}', <args>)",
|
||||||
);
|
nargs, command, channel, event
|
||||||
} else {
|
);
|
||||||
return format!(
|
};
|
||||||
"command! -nargs={} -complete=expression {} call rpcnotify({}, 'neovide.{}', <args>)",
|
}
|
||||||
nargs, command, channel, event
|
|
||||||
);
|
pub fn create_nvim_command() -> Command {
|
||||||
};
|
let mut cmd = build_nvim_cmd();
|
||||||
}
|
|
||||||
|
cmd.arg("--embed")
|
||||||
pub fn create_nvim_command() -> Command {
|
.args(SETTINGS.neovim_arguments.iter().skip(1))
|
||||||
let mut cmd = build_nvim_cmd();
|
.stderr(Stdio::inherit());
|
||||||
|
|
||||||
cmd.arg("--embed")
|
#[cfg(windows)]
|
||||||
.args(SETTINGS.neovim_arguments.iter().skip(1))
|
set_windows_creation_flags(&mut cmd);
|
||||||
.stderr(Stdio::inherit());
|
|
||||||
|
cmd
|
||||||
#[cfg(windows)]
|
}
|
||||||
set_windows_creation_flags(&mut cmd);
|
|
||||||
|
async fn start_neovim_runtime(
|
||||||
cmd
|
ui_command_sender: TxUnbounded<UiCommand>,
|
||||||
}
|
ui_command_receiver: RxUnbounded<UiCommand>,
|
||||||
|
redraw_event_sender: TxUnbounded<RedrawEvent>,
|
||||||
async fn start_neovim_runtime(
|
running: Arc<AtomicBool>,
|
||||||
ui_command_sender: TxUnbounded<UiCommand>,
|
) {
|
||||||
ui_command_receiver: RxUnbounded<UiCommand>,
|
let (width, height) = window_geometry_or_default();
|
||||||
redraw_event_sender: TxUnbounded<RedrawEvent>,
|
let handler = NeovimHandler::new(ui_command_sender.clone(), redraw_event_sender.clone());
|
||||||
running: Arc<AtomicBool>,
|
let (mut nvim, io_handler, _) = create::new_child_cmd(&mut create_nvim_command(), handler)
|
||||||
) {
|
.await
|
||||||
let (width, height) = window_geometry_or_default();
|
.unwrap_or_explained_panic("Could not locate or start neovim process");
|
||||||
let handler = NeovimHandler::new(ui_command_sender.clone(), redraw_event_sender.clone());
|
|
||||||
let (mut nvim, io_handler, _) = create::new_child_cmd(&mut create_nvim_command(), handler)
|
if nvim.get_api_info().await.is_err() {
|
||||||
.await
|
error!("Cannot get neovim api info, either neovide is launched with an unknown command line option or neovim version not supported!");
|
||||||
.unwrap_or_explained_panic("Could not locate or start neovim process");
|
std::process::exit(-1);
|
||||||
|
}
|
||||||
if nvim.get_api_info().await.is_err() {
|
|
||||||
error!("Cannot get neovim api info, either neovide is launched with an unknown command line option or neovim version not supported!");
|
let close_watcher_running = running.clone();
|
||||||
std::process::exit(-1);
|
tokio::spawn(async move {
|
||||||
}
|
info!("Close watcher started");
|
||||||
|
match io_handler.await {
|
||||||
let close_watcher_running = running.clone();
|
Err(join_error) => error!("Error joining IO loop: '{}'", join_error),
|
||||||
tokio::spawn(async move {
|
Ok(Err(error)) => {
|
||||||
info!("Close watcher started");
|
if !error.is_channel_closed() {
|
||||||
match io_handler.await {
|
error!("Error: '{}'", error);
|
||||||
Err(join_error) => error!("Error joining IO loop: '{}'", join_error),
|
}
|
||||||
Ok(Err(error)) => {
|
}
|
||||||
if !error.is_channel_closed() {
|
Ok(Ok(())) => {}
|
||||||
error!("Error: '{}'", error);
|
};
|
||||||
}
|
close_watcher_running.store(false, Ordering::Relaxed);
|
||||||
}
|
});
|
||||||
Ok(Ok(())) => {}
|
|
||||||
};
|
if let Ok(Value::Integer(correct_version)) = nvim.eval("has(\"nvim-0.4\")").await {
|
||||||
close_watcher_running.store(false, Ordering::Relaxed);
|
if correct_version.as_i64() != Some(1) {
|
||||||
});
|
error!("Neovide requires version 0.4 or higher");
|
||||||
|
std::process::exit(0);
|
||||||
if let Ok(Value::Integer(correct_version)) = nvim.eval("has(\"nvim-0.4\")").await {
|
}
|
||||||
if correct_version.as_i64() != Some(1) {
|
} else {
|
||||||
error!("Neovide requires version 0.4 or higher");
|
error!("Neovide requires version 0.4 or higher");
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
};
|
||||||
} else {
|
|
||||||
error!("Neovide requires version 0.4 or higher");
|
nvim.set_var("neovide", Value::Boolean(true))
|
||||||
std::process::exit(0);
|
.await
|
||||||
};
|
.unwrap_or_explained_panic("Could not communicate with neovim process");
|
||||||
|
|
||||||
nvim.set_var("neovide", Value::Boolean(true))
|
if let Err(command_error) = nvim.command("runtime! ginit.vim").await {
|
||||||
.await
|
nvim.command(&format!(
|
||||||
.unwrap_or_explained_panic("Could not communicate with neovim process");
|
"echomsg \"error encountered in ginit.vim {:?}\"",
|
||||||
|
command_error
|
||||||
if let Err(command_error) = nvim.command("runtime! ginit.vim").await {
|
))
|
||||||
nvim.command(&format!(
|
.await
|
||||||
"echomsg \"error encountered in ginit.vim {:?}\"",
|
.ok();
|
||||||
command_error
|
}
|
||||||
))
|
|
||||||
.await
|
nvim.set_client_info(
|
||||||
.ok();
|
"neovide",
|
||||||
}
|
vec![
|
||||||
|
(Value::from("major"), Value::from(0u64)),
|
||||||
nvim.set_client_info(
|
(Value::from("minor"), Value::from(6u64)),
|
||||||
"neovide",
|
],
|
||||||
vec![
|
"ui",
|
||||||
(Value::from("major"), Value::from(0u64)),
|
vec![],
|
||||||
(Value::from("minor"), Value::from(6u64)),
|
vec![],
|
||||||
],
|
)
|
||||||
"ui",
|
.await
|
||||||
vec![],
|
.ok();
|
||||||
vec![],
|
|
||||||
)
|
let neovide_channel: u64 = nvim
|
||||||
.await
|
.list_chans()
|
||||||
.ok();
|
.await
|
||||||
|
.ok()
|
||||||
let neovide_channel: u64 = nvim
|
.and_then(|channel_values| parse_channel_list(channel_values).ok())
|
||||||
.list_chans()
|
.and_then(|channel_list| {
|
||||||
.await
|
channel_list.iter().find_map(|channel| match channel {
|
||||||
.ok()
|
ChannelInfo {
|
||||||
.and_then(|channel_values| parse_channel_list(channel_values).ok())
|
id,
|
||||||
.and_then(|channel_list| {
|
client: Some(ClientInfo { name, .. }),
|
||||||
channel_list.iter().find_map(|channel| match channel {
|
..
|
||||||
ChannelInfo {
|
} if name == "neovide" => Some(*id),
|
||||||
id,
|
_ => None,
|
||||||
client: Some(ClientInfo { name, .. }),
|
})
|
||||||
..
|
})
|
||||||
} if name == "neovide" => Some(*id),
|
.unwrap_or(0);
|
||||||
_ => None,
|
|
||||||
})
|
info!(
|
||||||
})
|
"Neovide registered to nvim with channel id {}",
|
||||||
.unwrap_or(0);
|
neovide_channel
|
||||||
|
);
|
||||||
info!(
|
|
||||||
"Neovide registered to nvim with channel id {}",
|
#[cfg(windows)]
|
||||||
neovide_channel
|
nvim.command(&build_neovide_command(
|
||||||
);
|
neovide_channel,
|
||||||
|
0,
|
||||||
#[cfg(windows)]
|
"NeovideRegisterRightClick",
|
||||||
nvim.command(&build_neovide_command(
|
"register_right_click",
|
||||||
neovide_channel,
|
))
|
||||||
0,
|
.await
|
||||||
"NeovideRegisterRightClick",
|
.ok();
|
||||||
"register_right_click",
|
|
||||||
))
|
#[cfg(windows)]
|
||||||
.await
|
nvim.command(&build_neovide_command(
|
||||||
.ok();
|
neovide_channel,
|
||||||
|
0,
|
||||||
#[cfg(windows)]
|
"NeovideUnregisterRightClick",
|
||||||
nvim.command(&build_neovide_command(
|
"unregister_right_click",
|
||||||
neovide_channel,
|
))
|
||||||
0,
|
.await
|
||||||
"NeovideUnregisterRightClick",
|
.ok();
|
||||||
"unregister_right_click",
|
|
||||||
))
|
nvim.set_option("lazyredraw", Value::Boolean(false))
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
nvim.set_option("lazyredraw", Value::Boolean(false))
|
let mut options = UiAttachOptions::new();
|
||||||
.await
|
options.set_linegrid_external(true);
|
||||||
.ok();
|
if env::args().any(|arg| arg == "--multiGrid") || env::var("NeovideMultiGrid").is_ok() {
|
||||||
|
options.set_multigrid_external(true);
|
||||||
let mut options = UiAttachOptions::new();
|
}
|
||||||
options.set_linegrid_external(true);
|
options.set_rgb(true);
|
||||||
if env::args().any(|arg| arg == "--multiGrid") || env::var("NeovideMultiGrid").is_ok() {
|
nvim.ui_attach(width as i64, height as i64, &options)
|
||||||
options.set_multigrid_external(true);
|
.await
|
||||||
}
|
.unwrap_or_explained_panic("Could not attach ui to neovim process");
|
||||||
options.set_rgb(true);
|
|
||||||
nvim.ui_attach(width as i64, height as i64, &options)
|
info!("Neovim process attached");
|
||||||
.await
|
|
||||||
.unwrap_or_explained_panic("Could not attach ui to neovim process");
|
let nvim = Arc::new(nvim);
|
||||||
|
|
||||||
info!("Neovim process attached");
|
let ui_command_running = running.clone();
|
||||||
|
let input_nvim = nvim.clone();
|
||||||
let nvim = Arc::new(nvim);
|
tokio::spawn(async move {
|
||||||
|
loop {
|
||||||
let ui_command_running = running.clone();
|
if !ui_command_running.load(Ordering::Relaxed) {
|
||||||
let input_nvim = nvim.clone();
|
break;
|
||||||
tokio::spawn(async move {
|
}
|
||||||
loop {
|
|
||||||
if !ui_command_running.load(Ordering::Relaxed) {
|
match ui_command_receiver.recv().await {
|
||||||
break;
|
Ok(ui_command) => {
|
||||||
}
|
let input_nvim = input_nvim.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
match ui_command_receiver.recv().await {
|
ui_command.execute(&input_nvim).await;
|
||||||
Ok(ui_command) => {
|
});
|
||||||
let input_nvim = input_nvim.clone();
|
}
|
||||||
tokio::spawn(async move {
|
Err(_) => {
|
||||||
ui_command.execute(&input_nvim).await;
|
ui_command_running.store(false, Ordering::Relaxed);
|
||||||
});
|
break;
|
||||||
}
|
}
|
||||||
Err(_) => {
|
}
|
||||||
ui_command_running.store(false, Ordering::Relaxed);
|
}
|
||||||
break;
|
});
|
||||||
}
|
|
||||||
}
|
SETTINGS.read_initial_values(&nvim).await;
|
||||||
}
|
SETTINGS.setup_changed_listeners(&nvim).await;
|
||||||
});
|
}
|
||||||
|
|
||||||
SETTINGS.read_initial_values(&nvim).await;
|
pub struct Bridge {
|
||||||
SETTINGS.setup_changed_listeners(&nvim).await;
|
_runtime: Runtime, // Necessary to keep runtime running
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Bridge {
|
pub fn start_bridge(
|
||||||
_runtime: Runtime, // Necessary to keep runtime running
|
ui_command_sender: TxUnbounded<UiCommand>,
|
||||||
}
|
ui_command_receiver: RxUnbounded<UiCommand>,
|
||||||
|
redraw_event_sender: TxUnbounded<RedrawEvent>,
|
||||||
pub fn start_bridge(
|
running: Arc<AtomicBool>,
|
||||||
ui_command_sender: TxUnbounded<UiCommand>,
|
) -> Bridge {
|
||||||
ui_command_receiver: RxUnbounded<UiCommand>,
|
let runtime = Runtime::new().unwrap();
|
||||||
redraw_event_sender: TxUnbounded<RedrawEvent>,
|
runtime.spawn(start_neovim_runtime(
|
||||||
running: Arc<AtomicBool>,
|
ui_command_sender,
|
||||||
) -> Bridge {
|
ui_command_receiver,
|
||||||
let runtime = Runtime::new().unwrap();
|
redraw_event_sender,
|
||||||
runtime.spawn(start_neovim_runtime(
|
running,
|
||||||
ui_command_sender,
|
));
|
||||||
ui_command_receiver,
|
Bridge { _runtime: runtime }
|
||||||
redraw_event_sender,
|
}
|
||||||
running,
|
|
||||||
));
|
|
||||||
Bridge { _runtime: runtime }
|
|
||||||
}
|
|
||||||
|
@ -1,158 +1,157 @@
|
|||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod settings;
|
mod settings;
|
||||||
|
|
||||||
mod bridge;
|
mod bridge;
|
||||||
mod editor;
|
mod editor;
|
||||||
mod error_handling;
|
mod error_handling;
|
||||||
mod redraw_scheduler;
|
mod redraw_scheduler;
|
||||||
mod renderer;
|
mod renderer;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate derive_new;
|
extern crate derive_new;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rust_embed;
|
extern crate rust_embed;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crossfire::mpsc::unbounded_future;
|
use crossfire::mpsc::unbounded_future;
|
||||||
|
|
||||||
use window::window_geometry;
|
use window::window_geometry;
|
||||||
|
|
||||||
use bridge::start_bridge;
|
use bridge::start_bridge;
|
||||||
use editor::start_editor;
|
use editor::start_editor;
|
||||||
use window::create_window;
|
use window::create_window;
|
||||||
|
|
||||||
pub const INITIAL_DIMENSIONS: (u64, u64) = (100, 50);
|
pub const INITIAL_DIMENSIONS: (u64, u64) = (100, 50);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// -----------
|
// -----------
|
||||||
// | DATA FLOW |
|
// | DATA FLOW |
|
||||||
// -----------
|
// -----------
|
||||||
//
|
//
|
||||||
// Data flows in a circular motion via channels. This allows each component to handle and
|
// Data flows in a circular motion via channels. This allows each component to handle and
|
||||||
// process data on their own thread while not blocking the other components from processing.
|
// process data on their own thread while not blocking the other components from processing.
|
||||||
//
|
//
|
||||||
// This way Neovim continues to produce events, the window doesn't freeze and queues up ui
|
// This way Neovim continues to produce events, the window doesn't freeze and queues up ui
|
||||||
// commands, and the editor can do the processing necessary to handle the UI events
|
// commands, and the editor can do the processing necessary to handle the UI events
|
||||||
// effectively.
|
// effectively.
|
||||||
//
|
//
|
||||||
// BRIDGE
|
// BRIDGE
|
||||||
// V REDRAW EVENT
|
// V REDRAW EVENT
|
||||||
// EDITOR
|
// EDITOR
|
||||||
// V DRAW COMMAND
|
// V DRAW COMMAND
|
||||||
// WINDOW
|
// WINDOW
|
||||||
// V UI COMMAND
|
// V UI COMMAND
|
||||||
// BRIDGE
|
// BRIDGE
|
||||||
//
|
//
|
||||||
// BRIDGE:
|
// BRIDGE:
|
||||||
// The bridge is responsible for the connection to the neovim process itself. It is in charge
|
// The bridge is responsible for the connection to the neovim process itself. It is in charge
|
||||||
// of starting and communicating to and from the process.
|
// of starting and communicating to and from the process.
|
||||||
//
|
//
|
||||||
// REDRAW EVENT:
|
// REDRAW EVENT:
|
||||||
// Redraw events are direct events from the neovim process meant to specify how the editor
|
// Redraw events are direct events from the neovim process meant to specify how the editor
|
||||||
// should be drawn to the screen. They also include other things such as whether the mouse is
|
// should be drawn to the screen. They also include other things such as whether the mouse is
|
||||||
// enabled. The bridge takes these events, filters out some of them meant only for
|
// enabled. The bridge takes these events, filters out some of them meant only for
|
||||||
// filtering, and forwards them to the editor.
|
// filtering, and forwards them to the editor.
|
||||||
//
|
//
|
||||||
// EDITOR:
|
// EDITOR:
|
||||||
// The editor is responsible for processing and transforming redraw events into something
|
// The editor is responsible for processing and transforming redraw events into something
|
||||||
// more readily renderable. Ligature support and multi window management requires some
|
// more readily renderable. Ligature support and multi window management requires some
|
||||||
// significant preprocessing of the redraw events in order to capture what exactly should get
|
// significant preprocessing of the redraw events in order to capture what exactly should get
|
||||||
// drawn where. Futher this step takes a bit of processing power to accomplish, so it is done
|
// drawn where. Futher this step takes a bit of processing power to accomplish, so it is done
|
||||||
// on it's own thread. Ideally heavily computationally expensive tasks should be done in the
|
// on it's own thread. Ideally heavily computationally expensive tasks should be done in the
|
||||||
// editor.
|
// editor.
|
||||||
//
|
//
|
||||||
// DRAW COMMAND:
|
// DRAW COMMAND:
|
||||||
// The draw commands are distilled render information describing actions to be done at the
|
// The draw commands are distilled render information describing actions to be done at the
|
||||||
// window by window level.
|
// window by window level.
|
||||||
//
|
//
|
||||||
// WINDOW:
|
// WINDOW:
|
||||||
// The window is responsible for rendering and gathering input events from the user. This
|
// The window is responsible for rendering and gathering input events from the user. This
|
||||||
// inncludes taking the draw commands from the editor and turning them into pixels on the
|
// inncludes taking the draw commands from the editor and turning them into pixels on the
|
||||||
// screen. The ui commands are then forwarded back to the BRIDGE to convert them into
|
// screen. The ui commands are then forwarded back to the BRIDGE to convert them into
|
||||||
// commands for neovim to handle properly.
|
// commands for neovim to handle properly.
|
||||||
//
|
//
|
||||||
// UI COMMAND:
|
// UI COMMAND:
|
||||||
// The ui commands are things like text input/key bindings, outer window resizes, and mouse
|
// The ui commands are things like text input/key bindings, outer window resizes, and mouse
|
||||||
// inputs.
|
// inputs.
|
||||||
//
|
//
|
||||||
// ------------------
|
// ------------------
|
||||||
// | Other Components |
|
// | Other Components |
|
||||||
// ------------------
|
// ------------------
|
||||||
//
|
//
|
||||||
// Neovide also includes some other systems which are globally available via lazy static
|
// Neovide also includes some other systems which are globally available via lazy static
|
||||||
// instantiations.
|
// instantiations.
|
||||||
//
|
//
|
||||||
// SETTINGS:
|
// SETTINGS:
|
||||||
// The settings system is live updated from global variables in neovim with the prefix
|
// The settings system is live updated from global variables in neovim with the prefix
|
||||||
// "neovide". They allow us to configure and manage the functionality of neovide from neovim
|
// "neovide". They allow us to configure and manage the functionality of neovide from neovim
|
||||||
// init scripts and variables.
|
// init scripts and variables.
|
||||||
//
|
//
|
||||||
// REDRAW SCHEDULER:
|
// REDRAW SCHEDULER:
|
||||||
// The redraw scheduler is a simple system in charge of deciding if the renderer should draw
|
// The redraw scheduler is a simple system in charge of deciding if the renderer should draw
|
||||||
// another frame next frame, or if it can safely skip drawing to save battery and cpu power.
|
// another frame next frame, or if it can safely skip drawing to save battery and cpu power.
|
||||||
// Multiple other parts of the app "queue_next_frame" function to ensure animations continue
|
// Multiple other parts of the app "queue_next_frame" function to ensure animations continue
|
||||||
// properly or updates to the graphics are pushed to the screen.
|
// properly or updates to the graphics are pushed to the screen.
|
||||||
|
|
||||||
if let Err(err) = window_geometry() {
|
if let Err(err) = window_geometry() {
|
||||||
eprintln!("{}", err);
|
eprintln!("{}", err);
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
use std::env;
|
use std::env;
|
||||||
if env::var_os("TERM").is_none() {
|
if env::var_os("TERM").is_none() {
|
||||||
let mut profile_path = dirs::home_dir().unwrap();
|
let mut profile_path = dirs::home_dir().unwrap();
|
||||||
profile_path.push(".profile");
|
profile_path.push(".profile");
|
||||||
let shell = env::var("SHELL").unwrap();
|
let shell = env::var("SHELL").unwrap();
|
||||||
let cmd = format!(
|
let cmd = format!(
|
||||||
"(source /etc/profile && source {} && echo $PATH)",
|
"(source /etc/profile && source {} && echo $PATH)",
|
||||||
profile_path.to_str().unwrap()
|
profile_path.to_str().unwrap()
|
||||||
);
|
);
|
||||||
if let Ok(path) = process::Command::new(shell).arg("-c").arg(cmd).output() {
|
if let Ok(path) = process::Command::new(shell).arg("-c").arg(cmd).output() {
|
||||||
env::set_var("PATH", std::str::from_utf8(&path.stdout).unwrap());
|
env::set_var("PATH", std::str::from_utf8(&path.stdout).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge::layouts::initialize_settings();
|
window::initialize_settings();
|
||||||
window::initialize_settings();
|
redraw_scheduler::initialize_settings();
|
||||||
redraw_scheduler::initialize_settings();
|
renderer::initialize_settings();
|
||||||
renderer::initialize_settings();
|
renderer::cursor_renderer::initialize_settings();
|
||||||
renderer::cursor_renderer::initialize_settings();
|
|
||||||
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
let running = Arc::new(AtomicBool::new(true));
|
|
||||||
|
let (redraw_event_sender, redraw_event_receiver) = unbounded_future();
|
||||||
let (redraw_event_sender, redraw_event_receiver) = unbounded_future();
|
let (batched_draw_command_sender, batched_draw_command_receiver) = channel();
|
||||||
let (batched_draw_command_sender, batched_draw_command_receiver) = channel();
|
let (ui_command_sender, ui_command_receiver) = unbounded_future();
|
||||||
let (ui_command_sender, ui_command_receiver) = unbounded_future();
|
let (window_command_sender, window_command_receiver) = channel();
|
||||||
let (window_command_sender, window_command_receiver) = channel();
|
|
||||||
|
// We need to keep the bridge reference around to prevent the tokio runtime from getting freed
|
||||||
// We need to keep the bridge reference around to prevent the tokio runtime from getting freed
|
let _bridge = start_bridge(
|
||||||
let _bridge = start_bridge(
|
ui_command_sender.clone(),
|
||||||
ui_command_sender.clone(),
|
ui_command_receiver,
|
||||||
ui_command_receiver,
|
redraw_event_sender,
|
||||||
redraw_event_sender,
|
running.clone(),
|
||||||
running.clone(),
|
);
|
||||||
);
|
start_editor(
|
||||||
start_editor(
|
redraw_event_receiver,
|
||||||
redraw_event_receiver,
|
batched_draw_command_sender,
|
||||||
batched_draw_command_sender,
|
window_command_sender,
|
||||||
window_command_sender,
|
);
|
||||||
);
|
create_window(
|
||||||
create_window(
|
batched_draw_command_receiver,
|
||||||
batched_draw_command_receiver,
|
window_command_receiver,
|
||||||
window_command_receiver,
|
ui_command_sender,
|
||||||
ui_command_sender,
|
running,
|
||||||
running,
|
);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
@ -1,114 +1,81 @@
|
|||||||
mod qwerty;
|
use log::{error, trace};
|
||||||
|
|
||||||
use log::{error, trace};
|
use crate::settings::*;
|
||||||
use skulpin::sdl2::keyboard::{Keycode, Mod};
|
|
||||||
|
#[derive(Clone)]
|
||||||
use crate::settings::{FromValue, Value, SETTINGS};
|
pub enum KeyboardLayout {
|
||||||
|
Qwerty,
|
||||||
use qwerty::*;
|
}
|
||||||
|
|
||||||
pub fn unsupported_key<R>(keycode: Keycode) -> Option<R> {
|
impl FromValue for KeyboardLayout {
|
||||||
trace!("Unsupported key: {:?}", keycode);
|
fn from_value(&mut self, value: Value) {
|
||||||
None
|
match value.as_str() {
|
||||||
}
|
Some("qwerty") => *self = KeyboardLayout::Qwerty,
|
||||||
|
_ => error!(
|
||||||
#[derive(Clone)]
|
"keyboard_layout setting expected a known keyboard layout name, but received: {}",
|
||||||
pub enum KeyboardLayout {
|
value
|
||||||
Qwerty,
|
),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
impl FromValue for KeyboardLayout {
|
}
|
||||||
fn from_value(&mut self, value: Value) {
|
|
||||||
match value.as_str() {
|
impl From<KeyboardLayout> for Value {
|
||||||
Some("qwerty") => *self = KeyboardLayout::Qwerty,
|
fn from(layout: KeyboardLayout) -> Self {
|
||||||
_ => error!(
|
match layout {
|
||||||
"keyboard_layout setting expected a known keyboard layout name, but received: {}",
|
KeyboardLayout::Qwerty => "qwerty".into(),
|
||||||
value
|
}
|
||||||
),
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
#[derive(Clone)]
|
||||||
|
pub struct KeyboardSettings {
|
||||||
impl From<KeyboardLayout> for Value {
|
pub layout: KeyboardLayout,
|
||||||
fn from(layout: KeyboardLayout) -> Self {
|
}
|
||||||
match layout {
|
|
||||||
KeyboardLayout::Qwerty => "qwerty".into(),
|
pub fn initialize_settings() {
|
||||||
}
|
SETTINGS.set(&KeyboardSettings {
|
||||||
}
|
layout: KeyboardLayout::Qwerty,
|
||||||
}
|
});
|
||||||
|
|
||||||
#[derive(Clone)]
|
register_nvim_setting!("keyboard_layout", KeyboardSettings::layout);
|
||||||
struct KeyboardSettings {
|
}
|
||||||
layout: KeyboardLayout,
|
|
||||||
}
|
pub fn append_modifiers(
|
||||||
|
keycode_text: &str,
|
||||||
pub fn initialize_settings() {
|
special: bool,
|
||||||
SETTINGS.set(&KeyboardSettings {
|
shift: bool,
|
||||||
layout: KeyboardLayout::Qwerty,
|
ctrl: bool,
|
||||||
});
|
alt: bool,
|
||||||
|
gui: bool,
|
||||||
register_nvim_setting!("keyboard_layout", KeyboardSettings::layout);
|
) -> String {
|
||||||
}
|
let mut result = keycode_text.to_string();
|
||||||
|
let mut special = if result == "<" {
|
||||||
fn append_modifiers(
|
result = "lt".to_string();
|
||||||
keycode_text: &str,
|
true
|
||||||
special: bool,
|
} else {
|
||||||
shift: bool,
|
special
|
||||||
ctrl: bool,
|
};
|
||||||
alt: bool,
|
|
||||||
gui: bool,
|
if shift {
|
||||||
) -> String {
|
special = true;
|
||||||
let mut result = keycode_text.to_string();
|
result = format!("S-{}", result);
|
||||||
let mut special = if result == "<" {
|
}
|
||||||
result = "lt".to_string();
|
if ctrl {
|
||||||
true
|
special = true;
|
||||||
} else {
|
result = format!("C-{}", result);
|
||||||
special
|
}
|
||||||
};
|
if alt {
|
||||||
|
special = true;
|
||||||
if shift {
|
result = format!("M-{}", result);
|
||||||
special = true;
|
}
|
||||||
result = format!("S-{}", result);
|
if cfg!(not(target_os = "windows")) && gui {
|
||||||
}
|
special = true;
|
||||||
if ctrl {
|
result = format!("D-{}", result);
|
||||||
special = true;
|
}
|
||||||
result = format!("C-{}", result);
|
|
||||||
}
|
if special {
|
||||||
if alt {
|
result = format!("<{}>", result);
|
||||||
special = true;
|
}
|
||||||
result = format!("M-{}", result);
|
|
||||||
}
|
result
|
||||||
if cfg!(not(target_os = "windows")) && gui {
|
}
|
||||||
special = true;
|
|
||||||
result = format!("D-{}", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
if special {
|
|
||||||
result = format!("<{}>", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn produce_neovim_keybinding_string(
|
|
||||||
keycode: Option<Keycode>,
|
|
||||||
keytext: Option<String>,
|
|
||||||
modifiers: Mod,
|
|
||||||
) -> Option<String> {
|
|
||||||
let shift = modifiers.contains(Mod::LSHIFTMOD) || modifiers.contains(Mod::RSHIFTMOD);
|
|
||||||
let ctrl = modifiers.contains(Mod::LCTRLMOD) || modifiers.contains(Mod::RCTRLMOD);
|
|
||||||
let alt = modifiers.contains(Mod::LALTMOD) || modifiers.contains(Mod::RALTMOD);
|
|
||||||
let gui = modifiers.contains(Mod::LGUIMOD) || modifiers.contains(Mod::RGUIMOD);
|
|
||||||
if let Some(text) = keytext {
|
|
||||||
Some(append_modifiers(&text, false, false, ctrl, alt, gui))
|
|
||||||
} else if let Some(keycode) = keycode {
|
|
||||||
(match SETTINGS.get::<KeyboardSettings>().layout {
|
|
||||||
KeyboardLayout::Qwerty => handle_qwerty_layout(keycode, shift, ctrl, alt),
|
|
||||||
})
|
|
||||||
.map(|(transformed_text, special, shift, ctrl, alt)| {
|
|
||||||
append_modifiers(transformed_text, special, shift, ctrl, alt, gui)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,36 @@
|
|||||||
|
mod qwerty;
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
use skulpin::sdl2::keyboard::{Keycode, Mod};
|
||||||
|
|
||||||
|
use qwerty::*;
|
||||||
|
use super::keyboard::*;
|
||||||
|
use crate::settings::*;
|
||||||
|
|
||||||
|
pub fn unsupported_key<R>(keycode: Keycode) -> Option<R> {
|
||||||
|
trace!("Unsupported key: {:?}", keycode);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn produce_neovim_keybinding_string(
|
||||||
|
keycode: Option<Keycode>,
|
||||||
|
keytext: Option<String>,
|
||||||
|
modifiers: Mod,
|
||||||
|
) -> Option<String> {
|
||||||
|
let shift = modifiers.contains(Mod::LSHIFTMOD) || modifiers.contains(Mod::RSHIFTMOD);
|
||||||
|
let ctrl = modifiers.contains(Mod::LCTRLMOD) || modifiers.contains(Mod::RCTRLMOD);
|
||||||
|
let alt = modifiers.contains(Mod::LALTMOD) || modifiers.contains(Mod::RALTMOD);
|
||||||
|
let gui = modifiers.contains(Mod::LGUIMOD) || modifiers.contains(Mod::RGUIMOD);
|
||||||
|
if let Some(text) = keytext {
|
||||||
|
Some(append_modifiers(&text, false, false, ctrl, alt, gui))
|
||||||
|
} else if let Some(keycode) = keycode {
|
||||||
|
(match SETTINGS.get::<KeyboardSettings>().layout {
|
||||||
|
KeyboardLayout::Qwerty => handle_qwerty_layout(keycode, shift, ctrl, alt),
|
||||||
|
})
|
||||||
|
.map(|(transformed_text, special, shift, ctrl, alt)| {
|
||||||
|
append_modifiers(transformed_text, special, shift, ctrl, alt, gui)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -1,269 +1,269 @@
|
|||||||
use super::unsupported_key;
|
use super::unsupported_key;
|
||||||
|
|
||||||
use skulpin::sdl2::keyboard::Keycode;
|
use skulpin::sdl2::keyboard::Keycode;
|
||||||
|
|
||||||
pub fn handle_qwerty_layout(
|
pub fn handle_qwerty_layout(
|
||||||
keycode: Keycode,
|
keycode: Keycode,
|
||||||
shift: bool,
|
shift: bool,
|
||||||
ctrl: bool,
|
ctrl: bool,
|
||||||
alt: bool,
|
alt: bool,
|
||||||
) -> Option<(&'static str, bool, bool, bool, bool)> {
|
) -> Option<(&'static str, bool, bool, bool, bool)> {
|
||||||
match (keycode, shift, ctrl, alt) {
|
match (keycode, shift, ctrl, alt) {
|
||||||
(Keycode::Backspace, shift, ctrl, alt) => Some(("BS", true, shift, ctrl, alt)),
|
(Keycode::Backspace, shift, ctrl, alt) => Some(("BS", true, shift, ctrl, alt)),
|
||||||
(Keycode::Tab, shift, ctrl, alt) => Some(("Tab", true, shift, ctrl, alt)),
|
(Keycode::Tab, shift, ctrl, alt) => Some(("Tab", true, shift, ctrl, alt)),
|
||||||
(Keycode::Return, shift, ctrl, alt) => Some(("Enter", true, shift, ctrl, alt)),
|
(Keycode::Return, shift, ctrl, alt) => Some(("Enter", true, shift, ctrl, alt)),
|
||||||
(Keycode::Escape, shift, ctrl, alt) => Some(("Esc", true, shift, ctrl, alt)),
|
(Keycode::Escape, shift, ctrl, alt) => Some(("Esc", true, shift, ctrl, alt)),
|
||||||
(Keycode::Space, shift, ctrl, alt) => Some((" ", false, shift, ctrl, alt)),
|
(Keycode::Space, shift, ctrl, alt) => Some((" ", false, shift, ctrl, alt)),
|
||||||
(Keycode::Exclaim, shift, ctrl, alt) => Some(("!", false, shift, ctrl, alt)),
|
(Keycode::Exclaim, shift, ctrl, alt) => Some(("!", false, shift, ctrl, alt)),
|
||||||
(Keycode::Quotedbl, shift, ctrl, alt) => Some(("\"", false, shift, ctrl, alt)),
|
(Keycode::Quotedbl, shift, ctrl, alt) => Some(("\"", false, shift, ctrl, alt)),
|
||||||
(Keycode::Hash, shift, ctrl, alt) => Some(("#", false, shift, ctrl, alt)),
|
(Keycode::Hash, shift, ctrl, alt) => Some(("#", false, shift, ctrl, alt)),
|
||||||
(Keycode::Dollar, shift, ctrl, alt) => Some(("$", false, shift, ctrl, alt)),
|
(Keycode::Dollar, shift, ctrl, alt) => Some(("$", false, shift, ctrl, alt)),
|
||||||
(Keycode::Percent, shift, ctrl, alt) => Some(("%", false, shift, ctrl, alt)),
|
(Keycode::Percent, shift, ctrl, alt) => Some(("%", false, shift, ctrl, alt)),
|
||||||
(Keycode::Ampersand, shift, ctrl, alt) => Some(("&", false, shift, ctrl, alt)),
|
(Keycode::Ampersand, shift, ctrl, alt) => Some(("&", false, shift, ctrl, alt)),
|
||||||
(Keycode::Quote, false, ctrl, alt) => Some(("'", false, false, ctrl, alt)),
|
(Keycode::Quote, false, ctrl, alt) => Some(("'", false, false, ctrl, alt)),
|
||||||
(Keycode::Quote, true, ctrl, alt) => Some(("\"", false, false, ctrl, alt)),
|
(Keycode::Quote, true, ctrl, alt) => Some(("\"", false, false, ctrl, alt)),
|
||||||
(Keycode::LeftParen, shift, ctrl, alt) => Some(("(", false, shift, ctrl, alt)),
|
(Keycode::LeftParen, shift, ctrl, alt) => Some(("(", false, shift, ctrl, alt)),
|
||||||
(Keycode::RightParen, shift, ctrl, alt) => Some((")", false, shift, ctrl, alt)),
|
(Keycode::RightParen, shift, ctrl, alt) => Some((")", false, shift, ctrl, alt)),
|
||||||
(Keycode::Asterisk, shift, ctrl, alt) => Some(("*", false, shift, ctrl, alt)),
|
(Keycode::Asterisk, shift, ctrl, alt) => Some(("*", false, shift, ctrl, alt)),
|
||||||
(Keycode::Plus, shift, ctrl, alt) => Some(("+", false, shift, ctrl, alt)),
|
(Keycode::Plus, shift, ctrl, alt) => Some(("+", false, shift, ctrl, alt)),
|
||||||
(Keycode::Comma, false, ctrl, alt) => Some((",", false, shift, ctrl, alt)),
|
(Keycode::Comma, false, ctrl, alt) => Some((",", false, shift, ctrl, alt)),
|
||||||
(Keycode::Comma, true, ctrl, alt) => Some(("<", false, shift, ctrl, alt)),
|
(Keycode::Comma, true, ctrl, alt) => Some(("<", false, shift, ctrl, alt)),
|
||||||
(Keycode::Minus, false, ctrl, alt) => Some(("-", false, false, ctrl, alt)),
|
(Keycode::Minus, false, ctrl, alt) => Some(("-", false, false, ctrl, alt)),
|
||||||
(Keycode::Minus, true, ctrl, alt) => Some(("_", false, false, ctrl, alt)),
|
(Keycode::Minus, true, ctrl, alt) => Some(("_", false, false, ctrl, alt)),
|
||||||
(Keycode::Period, false, ctrl, alt) => Some((".", false, false, ctrl, alt)),
|
(Keycode::Period, false, ctrl, alt) => Some((".", false, false, ctrl, alt)),
|
||||||
(Keycode::Period, true, ctrl, alt) => Some((">", false, false, ctrl, alt)),
|
(Keycode::Period, true, ctrl, alt) => Some((">", false, false, ctrl, alt)),
|
||||||
(Keycode::Slash, false, ctrl, alt) => Some(("/", false, false, ctrl, alt)),
|
(Keycode::Slash, false, ctrl, alt) => Some(("/", false, false, ctrl, alt)),
|
||||||
(Keycode::Slash, true, ctrl, alt) => Some(("?", false, false, ctrl, alt)),
|
(Keycode::Slash, true, ctrl, alt) => Some(("?", false, false, ctrl, alt)),
|
||||||
(Keycode::Num0, false, ctrl, alt) => Some(("0", false, shift, ctrl, alt)),
|
(Keycode::Num0, false, ctrl, alt) => Some(("0", false, shift, ctrl, alt)),
|
||||||
(Keycode::Num0, true, ctrl, alt) => Some((")", true, shift, ctrl, alt)),
|
(Keycode::Num0, true, ctrl, alt) => Some((")", true, shift, ctrl, alt)),
|
||||||
(Keycode::Num1, false, ctrl, alt) => Some(("1", false, shift, ctrl, alt)),
|
(Keycode::Num1, false, ctrl, alt) => Some(("1", false, shift, ctrl, alt)),
|
||||||
(Keycode::Num1, true, ctrl, alt) => Some(("!", true, shift, ctrl, alt)),
|
(Keycode::Num1, true, ctrl, alt) => Some(("!", true, shift, ctrl, alt)),
|
||||||
(Keycode::Num2, false, ctrl, alt) => Some(("2", false, false, ctrl, alt)),
|
(Keycode::Num2, false, ctrl, alt) => Some(("2", false, false, ctrl, alt)),
|
||||||
(Keycode::Num2, true, ctrl, alt) => Some(("@", false, false, ctrl, alt)),
|
(Keycode::Num2, true, ctrl, alt) => Some(("@", false, false, ctrl, alt)),
|
||||||
(Keycode::Num3, false, ctrl, alt) => Some(("3", false, false, ctrl, alt)),
|
(Keycode::Num3, false, ctrl, alt) => Some(("3", false, false, ctrl, alt)),
|
||||||
(Keycode::Num3, true, ctrl, alt) => Some(("#", false, false, ctrl, alt)),
|
(Keycode::Num3, true, ctrl, alt) => Some(("#", false, false, ctrl, alt)),
|
||||||
(Keycode::Num4, false, ctrl, alt) => Some(("4", false, false, ctrl, alt)),
|
(Keycode::Num4, false, ctrl, alt) => Some(("4", false, false, ctrl, alt)),
|
||||||
(Keycode::Num4, true, ctrl, alt) => Some(("$", false, false, ctrl, alt)),
|
(Keycode::Num4, true, ctrl, alt) => Some(("$", false, false, ctrl, alt)),
|
||||||
(Keycode::Num5, false, ctrl, alt) => Some(("5", false, false, ctrl, alt)),
|
(Keycode::Num5, false, ctrl, alt) => Some(("5", false, false, ctrl, alt)),
|
||||||
(Keycode::Num5, true, ctrl, alt) => Some(("%", false, false, ctrl, alt)),
|
(Keycode::Num5, true, ctrl, alt) => Some(("%", false, false, ctrl, alt)),
|
||||||
(Keycode::Num6, false, ctrl, alt) => Some(("6", false, false, ctrl, alt)),
|
(Keycode::Num6, false, ctrl, alt) => Some(("6", false, false, ctrl, alt)),
|
||||||
(Keycode::Num6, true, ctrl, alt) => Some(("^", false, false, ctrl, alt)),
|
(Keycode::Num6, true, ctrl, alt) => Some(("^", false, false, ctrl, alt)),
|
||||||
(Keycode::Num7, false, ctrl, alt) => Some(("7", false, false, ctrl, alt)),
|
(Keycode::Num7, false, ctrl, alt) => Some(("7", false, false, ctrl, alt)),
|
||||||
(Keycode::Num7, true, ctrl, alt) => Some(("&", false, false, ctrl, alt)),
|
(Keycode::Num7, true, ctrl, alt) => Some(("&", false, false, ctrl, alt)),
|
||||||
(Keycode::Num8, false, ctrl, alt) => Some(("8", false, false, ctrl, alt)),
|
(Keycode::Num8, false, ctrl, alt) => Some(("8", false, false, ctrl, alt)),
|
||||||
(Keycode::Num8, true, ctrl, alt) => Some(("*", false, false, ctrl, alt)),
|
(Keycode::Num8, true, ctrl, alt) => Some(("*", false, false, ctrl, alt)),
|
||||||
(Keycode::Num9, false, ctrl, alt) => Some(("9", false, false, ctrl, alt)),
|
(Keycode::Num9, false, ctrl, alt) => Some(("9", false, false, ctrl, alt)),
|
||||||
(Keycode::Num9, true, ctrl, alt) => Some(("(", true, false, ctrl, alt)),
|
(Keycode::Num9, true, ctrl, alt) => Some(("(", true, false, ctrl, alt)),
|
||||||
(Keycode::Colon, shift, ctrl, alt) => Some((":", false, shift, ctrl, alt)),
|
(Keycode::Colon, shift, ctrl, alt) => Some((":", false, shift, ctrl, alt)),
|
||||||
(Keycode::Semicolon, false, ctrl, alt) => Some((";", false, false, ctrl, alt)),
|
(Keycode::Semicolon, false, ctrl, alt) => Some((";", false, false, ctrl, alt)),
|
||||||
(Keycode::Semicolon, true, ctrl, alt) => Some((":", false, false, ctrl, alt)),
|
(Keycode::Semicolon, true, ctrl, alt) => Some((":", false, false, ctrl, alt)),
|
||||||
(Keycode::Less, shift, ctrl, alt) => Some(("lt", false, shift, ctrl, alt)),
|
(Keycode::Less, shift, ctrl, alt) => Some(("lt", false, shift, ctrl, alt)),
|
||||||
(Keycode::Equals, false, ctrl, alt) => Some(("=", false, false, ctrl, alt)),
|
(Keycode::Equals, false, ctrl, alt) => Some(("=", false, false, ctrl, alt)),
|
||||||
(Keycode::Equals, true, ctrl, alt) => Some(("+", false, false, ctrl, alt)),
|
(Keycode::Equals, true, ctrl, alt) => Some(("+", false, false, ctrl, alt)),
|
||||||
(Keycode::Greater, shift, ctrl, alt) => Some(("gt", false, shift, ctrl, alt)),
|
(Keycode::Greater, shift, ctrl, alt) => Some(("gt", false, shift, ctrl, alt)),
|
||||||
(Keycode::Question, shift, ctrl, alt) => Some(("?", false, shift, ctrl, alt)),
|
(Keycode::Question, shift, ctrl, alt) => Some(("?", false, shift, ctrl, alt)),
|
||||||
(Keycode::At, shift, ctrl, alt) => Some(("@", false, shift, ctrl, alt)),
|
(Keycode::At, shift, ctrl, alt) => Some(("@", false, shift, ctrl, alt)),
|
||||||
(Keycode::LeftBracket, false, ctrl, alt) => Some(("[", false, false, ctrl, alt)),
|
(Keycode::LeftBracket, false, ctrl, alt) => Some(("[", false, false, ctrl, alt)),
|
||||||
(Keycode::LeftBracket, true, ctrl, alt) => Some(("{", false, false, ctrl, alt)),
|
(Keycode::LeftBracket, true, ctrl, alt) => Some(("{", false, false, ctrl, alt)),
|
||||||
(Keycode::Backslash, false, ctrl, alt) => Some(("\\", false, false, ctrl, alt)),
|
(Keycode::Backslash, false, ctrl, alt) => Some(("\\", false, false, ctrl, alt)),
|
||||||
(Keycode::Backslash, true, ctrl, alt) => Some(("|", false, false, ctrl, alt)),
|
(Keycode::Backslash, true, ctrl, alt) => Some(("|", false, false, ctrl, alt)),
|
||||||
(Keycode::RightBracket, false, ctrl, alt) => Some(("]", false, false, ctrl, alt)),
|
(Keycode::RightBracket, false, ctrl, alt) => Some(("]", false, false, ctrl, alt)),
|
||||||
(Keycode::RightBracket, true, ctrl, alt) => Some(("}", false, false, ctrl, alt)),
|
(Keycode::RightBracket, true, ctrl, alt) => Some(("}", false, false, ctrl, alt)),
|
||||||
(Keycode::Caret, shift, ctrl, alt) => Some(("^", false, shift, ctrl, alt)),
|
(Keycode::Caret, shift, ctrl, alt) => Some(("^", false, shift, ctrl, alt)),
|
||||||
(Keycode::Underscore, shift, ctrl, alt) => Some(("_", false, shift, ctrl, alt)),
|
(Keycode::Underscore, shift, ctrl, alt) => Some(("_", false, shift, ctrl, alt)),
|
||||||
(Keycode::Backquote, false, ctrl, alt) => Some(("`", false, false, ctrl, alt)),
|
(Keycode::Backquote, false, ctrl, alt) => Some(("`", false, false, ctrl, alt)),
|
||||||
(Keycode::Backquote, true, ctrl, alt) => Some(("~", false, false, ctrl, alt)),
|
(Keycode::Backquote, true, ctrl, alt) => Some(("~", false, false, ctrl, alt)),
|
||||||
(Keycode::A, shift, ctrl, alt) => Some(("a", false, shift, ctrl, alt)),
|
(Keycode::A, shift, ctrl, alt) => Some(("a", false, shift, ctrl, alt)),
|
||||||
(Keycode::B, shift, ctrl, alt) => Some(("b", false, shift, ctrl, alt)),
|
(Keycode::B, shift, ctrl, alt) => Some(("b", false, shift, ctrl, alt)),
|
||||||
(Keycode::C, shift, ctrl, alt) => Some(("c", false, shift, ctrl, alt)),
|
(Keycode::C, shift, ctrl, alt) => Some(("c", false, shift, ctrl, alt)),
|
||||||
(Keycode::D, shift, ctrl, alt) => Some(("d", false, shift, ctrl, alt)),
|
(Keycode::D, shift, ctrl, alt) => Some(("d", false, shift, ctrl, alt)),
|
||||||
(Keycode::E, shift, ctrl, alt) => Some(("e", false, shift, ctrl, alt)),
|
(Keycode::E, shift, ctrl, alt) => Some(("e", false, shift, ctrl, alt)),
|
||||||
(Keycode::F, shift, ctrl, alt) => Some(("f", false, shift, ctrl, alt)),
|
(Keycode::F, shift, ctrl, alt) => Some(("f", false, shift, ctrl, alt)),
|
||||||
(Keycode::G, shift, ctrl, alt) => Some(("g", false, shift, ctrl, alt)),
|
(Keycode::G, shift, ctrl, alt) => Some(("g", false, shift, ctrl, alt)),
|
||||||
(Keycode::H, shift, ctrl, alt) => Some(("h", false, shift, ctrl, alt)),
|
(Keycode::H, shift, ctrl, alt) => Some(("h", false, shift, ctrl, alt)),
|
||||||
(Keycode::I, shift, ctrl, alt) => Some(("i", false, shift, ctrl, alt)),
|
(Keycode::I, shift, ctrl, alt) => Some(("i", false, shift, ctrl, alt)),
|
||||||
(Keycode::J, shift, ctrl, alt) => Some(("j", false, shift, ctrl, alt)),
|
(Keycode::J, shift, ctrl, alt) => Some(("j", false, shift, ctrl, alt)),
|
||||||
(Keycode::K, shift, ctrl, alt) => Some(("k", false, shift, ctrl, alt)),
|
(Keycode::K, shift, ctrl, alt) => Some(("k", false, shift, ctrl, alt)),
|
||||||
(Keycode::L, shift, ctrl, alt) => Some(("l", false, shift, ctrl, alt)),
|
(Keycode::L, shift, ctrl, alt) => Some(("l", false, shift, ctrl, alt)),
|
||||||
(Keycode::M, shift, ctrl, alt) => Some(("m", false, shift, ctrl, alt)),
|
(Keycode::M, shift, ctrl, alt) => Some(("m", false, shift, ctrl, alt)),
|
||||||
(Keycode::N, shift, ctrl, alt) => Some(("n", false, shift, ctrl, alt)),
|
(Keycode::N, shift, ctrl, alt) => Some(("n", false, shift, ctrl, alt)),
|
||||||
(Keycode::O, shift, ctrl, alt) => Some(("o", false, shift, ctrl, alt)),
|
(Keycode::O, shift, ctrl, alt) => Some(("o", false, shift, ctrl, alt)),
|
||||||
(Keycode::P, shift, ctrl, alt) => Some(("p", false, shift, ctrl, alt)),
|
(Keycode::P, shift, ctrl, alt) => Some(("p", false, shift, ctrl, alt)),
|
||||||
(Keycode::Q, shift, ctrl, alt) => Some(("q", false, shift, ctrl, alt)),
|
(Keycode::Q, shift, ctrl, alt) => Some(("q", false, shift, ctrl, alt)),
|
||||||
(Keycode::R, shift, ctrl, alt) => Some(("r", false, shift, ctrl, alt)),
|
(Keycode::R, shift, ctrl, alt) => Some(("r", false, shift, ctrl, alt)),
|
||||||
(Keycode::S, shift, ctrl, alt) => Some(("s", false, shift, ctrl, alt)),
|
(Keycode::S, shift, ctrl, alt) => Some(("s", false, shift, ctrl, alt)),
|
||||||
(Keycode::T, shift, ctrl, alt) => Some(("t", false, shift, ctrl, alt)),
|
(Keycode::T, shift, ctrl, alt) => Some(("t", false, shift, ctrl, alt)),
|
||||||
(Keycode::U, shift, ctrl, alt) => Some(("u", false, shift, ctrl, alt)),
|
(Keycode::U, shift, ctrl, alt) => Some(("u", false, shift, ctrl, alt)),
|
||||||
(Keycode::V, shift, ctrl, alt) => Some(("v", false, shift, ctrl, alt)),
|
(Keycode::V, shift, ctrl, alt) => Some(("v", false, shift, ctrl, alt)),
|
||||||
(Keycode::W, shift, ctrl, alt) => Some(("w", false, shift, ctrl, alt)),
|
(Keycode::W, shift, ctrl, alt) => Some(("w", false, shift, ctrl, alt)),
|
||||||
(Keycode::X, shift, ctrl, alt) => Some(("x", false, shift, ctrl, alt)),
|
(Keycode::X, shift, ctrl, alt) => Some(("x", false, shift, ctrl, alt)),
|
||||||
(Keycode::Y, shift, ctrl, alt) => Some(("y", false, shift, ctrl, alt)),
|
(Keycode::Y, shift, ctrl, alt) => Some(("y", false, shift, ctrl, alt)),
|
||||||
(Keycode::Z, shift, ctrl, alt) => Some(("z", false, shift, ctrl, alt)),
|
(Keycode::Z, shift, ctrl, alt) => Some(("z", false, shift, ctrl, alt)),
|
||||||
(Keycode::Delete, shift, ctrl, alt) => Some(("Delete", true, shift, ctrl, alt)),
|
(Keycode::Delete, shift, ctrl, alt) => Some(("Delete", true, shift, ctrl, alt)),
|
||||||
(Keycode::CapsLock, _, _, _) => unsupported_key(Keycode::CapsLock),
|
(Keycode::CapsLock, _, _, _) => unsupported_key(Keycode::CapsLock),
|
||||||
(Keycode::F1, shift, ctrl, alt) => Some(("F1", true, shift, ctrl, alt)),
|
(Keycode::F1, shift, ctrl, alt) => Some(("F1", true, shift, ctrl, alt)),
|
||||||
(Keycode::F2, shift, ctrl, alt) => Some(("F2", true, shift, ctrl, alt)),
|
(Keycode::F2, shift, ctrl, alt) => Some(("F2", true, shift, ctrl, alt)),
|
||||||
(Keycode::F3, shift, ctrl, alt) => Some(("F3", true, shift, ctrl, alt)),
|
(Keycode::F3, shift, ctrl, alt) => Some(("F3", true, shift, ctrl, alt)),
|
||||||
(Keycode::F4, shift, ctrl, alt) => Some(("F4", true, shift, ctrl, alt)),
|
(Keycode::F4, shift, ctrl, alt) => Some(("F4", true, shift, ctrl, alt)),
|
||||||
(Keycode::F5, shift, ctrl, alt) => Some(("F5", true, shift, ctrl, alt)),
|
(Keycode::F5, shift, ctrl, alt) => Some(("F5", true, shift, ctrl, alt)),
|
||||||
(Keycode::F6, shift, ctrl, alt) => Some(("F6", true, shift, ctrl, alt)),
|
(Keycode::F6, shift, ctrl, alt) => Some(("F6", true, shift, ctrl, alt)),
|
||||||
(Keycode::F7, shift, ctrl, alt) => Some(("F7", true, shift, ctrl, alt)),
|
(Keycode::F7, shift, ctrl, alt) => Some(("F7", true, shift, ctrl, alt)),
|
||||||
(Keycode::F8, shift, ctrl, alt) => Some(("F8", true, shift, ctrl, alt)),
|
(Keycode::F8, shift, ctrl, alt) => Some(("F8", true, shift, ctrl, alt)),
|
||||||
(Keycode::F9, shift, ctrl, alt) => Some(("F9", true, shift, ctrl, alt)),
|
(Keycode::F9, shift, ctrl, alt) => Some(("F9", true, shift, ctrl, alt)),
|
||||||
(Keycode::F10, shift, ctrl, alt) => Some(("F10", true, shift, ctrl, alt)),
|
(Keycode::F10, shift, ctrl, alt) => Some(("F10", true, shift, ctrl, alt)),
|
||||||
(Keycode::F11, shift, ctrl, alt) => Some(("F11", true, shift, ctrl, alt)),
|
(Keycode::F11, shift, ctrl, alt) => Some(("F11", true, shift, ctrl, alt)),
|
||||||
(Keycode::F12, shift, ctrl, alt) => Some(("F12", true, shift, ctrl, alt)),
|
(Keycode::F12, shift, ctrl, alt) => Some(("F12", true, shift, ctrl, alt)),
|
||||||
(Keycode::PrintScreen, _, _, _) => unsupported_key(Keycode::PrintScreen),
|
(Keycode::PrintScreen, _, _, _) => unsupported_key(Keycode::PrintScreen),
|
||||||
(Keycode::ScrollLock, _, _, _) => unsupported_key(Keycode::ScrollLock),
|
(Keycode::ScrollLock, _, _, _) => unsupported_key(Keycode::ScrollLock),
|
||||||
(Keycode::Pause, _, _, _) => unsupported_key(Keycode::Pause),
|
(Keycode::Pause, _, _, _) => unsupported_key(Keycode::Pause),
|
||||||
(Keycode::Insert, shift, ctrl, alt) => Some(("Insert", true, shift, ctrl, alt)),
|
(Keycode::Insert, shift, ctrl, alt) => Some(("Insert", true, shift, ctrl, alt)),
|
||||||
(Keycode::Home, shift, ctrl, alt) => Some(("Home", true, shift, ctrl, alt)),
|
(Keycode::Home, shift, ctrl, alt) => Some(("Home", true, shift, ctrl, alt)),
|
||||||
(Keycode::PageUp, shift, ctrl, alt) => Some(("PageUp", true, shift, ctrl, alt)),
|
(Keycode::PageUp, shift, ctrl, alt) => Some(("PageUp", true, shift, ctrl, alt)),
|
||||||
(Keycode::End, shift, ctrl, alt) => Some(("End", true, shift, ctrl, alt)),
|
(Keycode::End, shift, ctrl, alt) => Some(("End", true, shift, ctrl, alt)),
|
||||||
(Keycode::PageDown, shift, ctrl, alt) => Some(("PageDown", true, shift, ctrl, alt)),
|
(Keycode::PageDown, shift, ctrl, alt) => Some(("PageDown", true, shift, ctrl, alt)),
|
||||||
(Keycode::Right, shift, ctrl, alt) => Some(("Right", true, shift, ctrl, alt)),
|
(Keycode::Right, shift, ctrl, alt) => Some(("Right", true, shift, ctrl, alt)),
|
||||||
(Keycode::Left, shift, ctrl, alt) => Some(("Left", true, shift, ctrl, alt)),
|
(Keycode::Left, shift, ctrl, alt) => Some(("Left", true, shift, ctrl, alt)),
|
||||||
(Keycode::Down, shift, ctrl, alt) => Some(("Down", true, shift, ctrl, alt)),
|
(Keycode::Down, shift, ctrl, alt) => Some(("Down", true, shift, ctrl, alt)),
|
||||||
(Keycode::Up, shift, ctrl, alt) => Some(("Up", true, shift, ctrl, alt)),
|
(Keycode::Up, shift, ctrl, alt) => Some(("Up", true, shift, ctrl, alt)),
|
||||||
(Keycode::NumLockClear, _, _, _) => unsupported_key(Keycode::NumLockClear),
|
(Keycode::NumLockClear, _, _, _) => unsupported_key(Keycode::NumLockClear),
|
||||||
(Keycode::KpDivide, shift, ctrl, alt) => Some(("/", true, shift, ctrl, alt)),
|
(Keycode::KpDivide, shift, ctrl, alt) => Some(("/", true, shift, ctrl, alt)),
|
||||||
(Keycode::KpMultiply, shift, ctrl, alt) => Some(("*", true, shift, ctrl, alt)),
|
(Keycode::KpMultiply, shift, ctrl, alt) => Some(("*", true, shift, ctrl, alt)),
|
||||||
(Keycode::KpMinus, shift, ctrl, alt) => Some(("-", true, shift, ctrl, alt)),
|
(Keycode::KpMinus, shift, ctrl, alt) => Some(("-", true, shift, ctrl, alt)),
|
||||||
(Keycode::KpPlus, shift, ctrl, alt) => Some(("+", true, shift, ctrl, alt)),
|
(Keycode::KpPlus, shift, ctrl, alt) => Some(("+", true, shift, ctrl, alt)),
|
||||||
(Keycode::KpEnter, shift, ctrl, alt) => Some(("Enter", true, shift, ctrl, alt)),
|
(Keycode::KpEnter, shift, ctrl, alt) => Some(("Enter", true, shift, ctrl, alt)),
|
||||||
(Keycode::Kp0, shift, ctrl, alt) => Some(("0", false, shift, ctrl, alt)),
|
(Keycode::Kp0, shift, ctrl, alt) => Some(("0", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp1, shift, ctrl, alt) => Some(("1", false, shift, ctrl, alt)),
|
(Keycode::Kp1, shift, ctrl, alt) => Some(("1", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp2, shift, ctrl, alt) => Some(("2", false, shift, ctrl, alt)),
|
(Keycode::Kp2, shift, ctrl, alt) => Some(("2", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp3, shift, ctrl, alt) => Some(("3", false, shift, ctrl, alt)),
|
(Keycode::Kp3, shift, ctrl, alt) => Some(("3", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp4, shift, ctrl, alt) => Some(("4", false, shift, ctrl, alt)),
|
(Keycode::Kp4, shift, ctrl, alt) => Some(("4", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp5, shift, ctrl, alt) => Some(("5", false, shift, ctrl, alt)),
|
(Keycode::Kp5, shift, ctrl, alt) => Some(("5", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp6, shift, ctrl, alt) => Some(("6", false, shift, ctrl, alt)),
|
(Keycode::Kp6, shift, ctrl, alt) => Some(("6", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp7, shift, ctrl, alt) => Some(("7", false, shift, ctrl, alt)),
|
(Keycode::Kp7, shift, ctrl, alt) => Some(("7", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp8, shift, ctrl, alt) => Some(("8", false, shift, ctrl, alt)),
|
(Keycode::Kp8, shift, ctrl, alt) => Some(("8", false, shift, ctrl, alt)),
|
||||||
(Keycode::Kp9, shift, ctrl, alt) => Some(("9", false, shift, ctrl, alt)),
|
(Keycode::Kp9, shift, ctrl, alt) => Some(("9", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpPeriod, shift, ctrl, alt) => Some((".", false, shift, ctrl, alt)),
|
(Keycode::KpPeriod, shift, ctrl, alt) => Some((".", false, shift, ctrl, alt)),
|
||||||
(Keycode::Application, _, _, _) => unsupported_key(Keycode::Application),
|
(Keycode::Application, _, _, _) => unsupported_key(Keycode::Application),
|
||||||
(Keycode::Power, _, _, _) => unsupported_key(Keycode::Power),
|
(Keycode::Power, _, _, _) => unsupported_key(Keycode::Power),
|
||||||
(Keycode::KpEquals, shift, ctrl, alt) => Some(("=", false, shift, ctrl, alt)),
|
(Keycode::KpEquals, shift, ctrl, alt) => Some(("=", false, shift, ctrl, alt)),
|
||||||
(Keycode::F13, shift, ctrl, alt) => Some(("F13", true, shift, ctrl, alt)),
|
(Keycode::F13, shift, ctrl, alt) => Some(("F13", true, shift, ctrl, alt)),
|
||||||
(Keycode::F14, shift, ctrl, alt) => Some(("F14", true, shift, ctrl, alt)),
|
(Keycode::F14, shift, ctrl, alt) => Some(("F14", true, shift, ctrl, alt)),
|
||||||
(Keycode::F15, shift, ctrl, alt) => Some(("F15", true, shift, ctrl, alt)),
|
(Keycode::F15, shift, ctrl, alt) => Some(("F15", true, shift, ctrl, alt)),
|
||||||
(Keycode::F16, shift, ctrl, alt) => Some(("F16", true, shift, ctrl, alt)),
|
(Keycode::F16, shift, ctrl, alt) => Some(("F16", true, shift, ctrl, alt)),
|
||||||
(Keycode::F17, shift, ctrl, alt) => Some(("F17", true, shift, ctrl, alt)),
|
(Keycode::F17, shift, ctrl, alt) => Some(("F17", true, shift, ctrl, alt)),
|
||||||
(Keycode::F18, shift, ctrl, alt) => Some(("F18", true, shift, ctrl, alt)),
|
(Keycode::F18, shift, ctrl, alt) => Some(("F18", true, shift, ctrl, alt)),
|
||||||
(Keycode::F19, shift, ctrl, alt) => Some(("F19", true, shift, ctrl, alt)),
|
(Keycode::F19, shift, ctrl, alt) => Some(("F19", true, shift, ctrl, alt)),
|
||||||
(Keycode::F20, shift, ctrl, alt) => Some(("F20", true, shift, ctrl, alt)),
|
(Keycode::F20, shift, ctrl, alt) => Some(("F20", true, shift, ctrl, alt)),
|
||||||
(Keycode::F21, shift, ctrl, alt) => Some(("F21", true, shift, ctrl, alt)),
|
(Keycode::F21, shift, ctrl, alt) => Some(("F21", true, shift, ctrl, alt)),
|
||||||
(Keycode::F22, shift, ctrl, alt) => Some(("F22", true, shift, ctrl, alt)),
|
(Keycode::F22, shift, ctrl, alt) => Some(("F22", true, shift, ctrl, alt)),
|
||||||
(Keycode::F23, shift, ctrl, alt) => Some(("F23", true, shift, ctrl, alt)),
|
(Keycode::F23, shift, ctrl, alt) => Some(("F23", true, shift, ctrl, alt)),
|
||||||
(Keycode::F24, shift, ctrl, alt) => Some(("F24", true, shift, ctrl, alt)),
|
(Keycode::F24, shift, ctrl, alt) => Some(("F24", true, shift, ctrl, alt)),
|
||||||
(Keycode::Execute, _, _, _) => unsupported_key(Keycode::Execute),
|
(Keycode::Execute, _, _, _) => unsupported_key(Keycode::Execute),
|
||||||
(Keycode::Help, _, _, _) => unsupported_key(Keycode::Help),
|
(Keycode::Help, _, _, _) => unsupported_key(Keycode::Help),
|
||||||
(Keycode::Menu, _, _, _) => unsupported_key(Keycode::Menu),
|
(Keycode::Menu, _, _, _) => unsupported_key(Keycode::Menu),
|
||||||
(Keycode::Select, _, _, _) => unsupported_key(Keycode::Select),
|
(Keycode::Select, _, _, _) => unsupported_key(Keycode::Select),
|
||||||
(Keycode::Stop, _, _, _) => unsupported_key(Keycode::Stop),
|
(Keycode::Stop, _, _, _) => unsupported_key(Keycode::Stop),
|
||||||
(Keycode::Again, _, _, _) => unsupported_key(Keycode::Again),
|
(Keycode::Again, _, _, _) => unsupported_key(Keycode::Again),
|
||||||
(Keycode::Undo, _, _, _) => unsupported_key(Keycode::Undo),
|
(Keycode::Undo, _, _, _) => unsupported_key(Keycode::Undo),
|
||||||
(Keycode::Cut, _, _, _) => unsupported_key(Keycode::Cut),
|
(Keycode::Cut, _, _, _) => unsupported_key(Keycode::Cut),
|
||||||
(Keycode::Copy, _, _, _) => unsupported_key(Keycode::Copy),
|
(Keycode::Copy, _, _, _) => unsupported_key(Keycode::Copy),
|
||||||
(Keycode::Paste, _, _, _) => unsupported_key(Keycode::Paste),
|
(Keycode::Paste, _, _, _) => unsupported_key(Keycode::Paste),
|
||||||
(Keycode::Find, _, _, _) => unsupported_key(Keycode::Find),
|
(Keycode::Find, _, _, _) => unsupported_key(Keycode::Find),
|
||||||
(Keycode::Mute, _, _, _) => unsupported_key(Keycode::Mute),
|
(Keycode::Mute, _, _, _) => unsupported_key(Keycode::Mute),
|
||||||
(Keycode::VolumeUp, _, _, _) => unsupported_key(Keycode::VolumeUp),
|
(Keycode::VolumeUp, _, _, _) => unsupported_key(Keycode::VolumeUp),
|
||||||
(Keycode::VolumeDown, _, _, _) => unsupported_key(Keycode::VolumeDown),
|
(Keycode::VolumeDown, _, _, _) => unsupported_key(Keycode::VolumeDown),
|
||||||
(Keycode::KpComma, _, _, _) => unsupported_key(Keycode::KpComma),
|
(Keycode::KpComma, _, _, _) => unsupported_key(Keycode::KpComma),
|
||||||
(Keycode::KpEqualsAS400, _, _, _) => unsupported_key(Keycode::KpEqualsAS400),
|
(Keycode::KpEqualsAS400, _, _, _) => unsupported_key(Keycode::KpEqualsAS400),
|
||||||
(Keycode::AltErase, _, _, _) => unsupported_key(Keycode::AltErase),
|
(Keycode::AltErase, _, _, _) => unsupported_key(Keycode::AltErase),
|
||||||
(Keycode::Sysreq, _, _, _) => unsupported_key(Keycode::Sysreq),
|
(Keycode::Sysreq, _, _, _) => unsupported_key(Keycode::Sysreq),
|
||||||
(Keycode::Cancel, _, _, _) => unsupported_key(Keycode::Cancel),
|
(Keycode::Cancel, _, _, _) => unsupported_key(Keycode::Cancel),
|
||||||
(Keycode::Clear, _, _, _) => unsupported_key(Keycode::Clear),
|
(Keycode::Clear, _, _, _) => unsupported_key(Keycode::Clear),
|
||||||
(Keycode::Prior, _, _, _) => unsupported_key(Keycode::Prior),
|
(Keycode::Prior, _, _, _) => unsupported_key(Keycode::Prior),
|
||||||
(Keycode::Return2, _, _, _) => unsupported_key(Keycode::Return2),
|
(Keycode::Return2, _, _, _) => unsupported_key(Keycode::Return2),
|
||||||
(Keycode::Separator, _, _, _) => unsupported_key(Keycode::Separator),
|
(Keycode::Separator, _, _, _) => unsupported_key(Keycode::Separator),
|
||||||
(Keycode::Out, _, _, _) => unsupported_key(Keycode::Out),
|
(Keycode::Out, _, _, _) => unsupported_key(Keycode::Out),
|
||||||
(Keycode::Oper, _, _, _) => unsupported_key(Keycode::Oper),
|
(Keycode::Oper, _, _, _) => unsupported_key(Keycode::Oper),
|
||||||
(Keycode::ClearAgain, _, _, _) => unsupported_key(Keycode::ClearAgain),
|
(Keycode::ClearAgain, _, _, _) => unsupported_key(Keycode::ClearAgain),
|
||||||
(Keycode::CrSel, _, _, _) => unsupported_key(Keycode::CrSel),
|
(Keycode::CrSel, _, _, _) => unsupported_key(Keycode::CrSel),
|
||||||
(Keycode::ExSel, _, _, _) => unsupported_key(Keycode::ExSel),
|
(Keycode::ExSel, _, _, _) => unsupported_key(Keycode::ExSel),
|
||||||
(Keycode::Kp00, _, _, _) => unsupported_key(Keycode::Kp00),
|
(Keycode::Kp00, _, _, _) => unsupported_key(Keycode::Kp00),
|
||||||
(Keycode::Kp000, _, _, _) => unsupported_key(Keycode::Kp000),
|
(Keycode::Kp000, _, _, _) => unsupported_key(Keycode::Kp000),
|
||||||
(Keycode::ThousandsSeparator, _, _, _) => unsupported_key(Keycode::ThousandsSeparator),
|
(Keycode::ThousandsSeparator, _, _, _) => unsupported_key(Keycode::ThousandsSeparator),
|
||||||
(Keycode::DecimalSeparator, _, _, _) => unsupported_key(Keycode::DecimalSeparator),
|
(Keycode::DecimalSeparator, _, _, _) => unsupported_key(Keycode::DecimalSeparator),
|
||||||
(Keycode::CurrencyUnit, _, _, _) => unsupported_key(Keycode::CurrencyUnit),
|
(Keycode::CurrencyUnit, _, _, _) => unsupported_key(Keycode::CurrencyUnit),
|
||||||
(Keycode::CurrencySubUnit, _, _, _) => unsupported_key(Keycode::CurrencySubUnit),
|
(Keycode::CurrencySubUnit, _, _, _) => unsupported_key(Keycode::CurrencySubUnit),
|
||||||
(Keycode::KpLeftParen, shift, ctrl, alt) => Some(("(", false, shift, ctrl, alt)),
|
(Keycode::KpLeftParen, shift, ctrl, alt) => Some(("(", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpRightParen, shift, ctrl, alt) => Some(("(", false, shift, ctrl, alt)),
|
(Keycode::KpRightParen, shift, ctrl, alt) => Some(("(", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpLeftBrace, shift, ctrl, alt) => Some(("[", false, shift, ctrl, alt)),
|
(Keycode::KpLeftBrace, shift, ctrl, alt) => Some(("[", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpRightBrace, shift, ctrl, alt) => Some(("]", false, shift, ctrl, alt)),
|
(Keycode::KpRightBrace, shift, ctrl, alt) => Some(("]", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpTab, shift, ctrl, alt) => Some(("TAB", true, shift, ctrl, alt)),
|
(Keycode::KpTab, shift, ctrl, alt) => Some(("TAB", true, shift, ctrl, alt)),
|
||||||
(Keycode::KpBackspace, shift, ctrl, alt) => Some(("BS", true, shift, ctrl, alt)),
|
(Keycode::KpBackspace, shift, ctrl, alt) => Some(("BS", true, shift, ctrl, alt)),
|
||||||
(Keycode::KpA, shift, ctrl, alt) => Some(("A", false, shift, ctrl, alt)),
|
(Keycode::KpA, shift, ctrl, alt) => Some(("A", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpB, shift, ctrl, alt) => Some(("B", false, shift, ctrl, alt)),
|
(Keycode::KpB, shift, ctrl, alt) => Some(("B", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpC, shift, ctrl, alt) => Some(("C", false, shift, ctrl, alt)),
|
(Keycode::KpC, shift, ctrl, alt) => Some(("C", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpD, shift, ctrl, alt) => Some(("D", false, shift, ctrl, alt)),
|
(Keycode::KpD, shift, ctrl, alt) => Some(("D", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpE, shift, ctrl, alt) => Some(("E", false, shift, ctrl, alt)),
|
(Keycode::KpE, shift, ctrl, alt) => Some(("E", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpF, shift, ctrl, alt) => Some(("F", false, shift, ctrl, alt)),
|
(Keycode::KpF, shift, ctrl, alt) => Some(("F", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpXor, _, _, _) => unsupported_key(Keycode::KpXor),
|
(Keycode::KpXor, _, _, _) => unsupported_key(Keycode::KpXor),
|
||||||
(Keycode::KpPower, shift, ctrl, alt) => Some(("^", false, shift, ctrl, alt)),
|
(Keycode::KpPower, shift, ctrl, alt) => Some(("^", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpPercent, shift, ctrl, alt) => Some(("%", false, shift, ctrl, alt)),
|
(Keycode::KpPercent, shift, ctrl, alt) => Some(("%", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpLess, shift, ctrl, alt) => Some(("lt", true, shift, ctrl, alt)),
|
(Keycode::KpLess, shift, ctrl, alt) => Some(("lt", true, shift, ctrl, alt)),
|
||||||
(Keycode::KpGreater, shift, ctrl, alt) => Some(("gt", true, shift, ctrl, alt)),
|
(Keycode::KpGreater, shift, ctrl, alt) => Some(("gt", true, shift, ctrl, alt)),
|
||||||
(Keycode::KpAmpersand, shift, ctrl, alt) => Some(("&", false, shift, ctrl, alt)),
|
(Keycode::KpAmpersand, shift, ctrl, alt) => Some(("&", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpDblAmpersand, _, _, _) => unsupported_key(Keycode::KpDblAmpersand),
|
(Keycode::KpDblAmpersand, _, _, _) => unsupported_key(Keycode::KpDblAmpersand),
|
||||||
(Keycode::KpVerticalBar, shift, ctrl, alt) => Some(("|", false, shift, ctrl, alt)),
|
(Keycode::KpVerticalBar, shift, ctrl, alt) => Some(("|", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpDblVerticalBar, _, _, _) => unsupported_key(Keycode::KpDblVerticalBar),
|
(Keycode::KpDblVerticalBar, _, _, _) => unsupported_key(Keycode::KpDblVerticalBar),
|
||||||
(Keycode::KpColon, shift, ctrl, alt) => Some((":", false, shift, ctrl, alt)),
|
(Keycode::KpColon, shift, ctrl, alt) => Some((":", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpHash, shift, ctrl, alt) => Some(("#", false, shift, ctrl, alt)),
|
(Keycode::KpHash, shift, ctrl, alt) => Some(("#", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpSpace, shift, ctrl, alt) => Some((" ", false, shift, ctrl, alt)),
|
(Keycode::KpSpace, shift, ctrl, alt) => Some((" ", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpAt, shift, ctrl, alt) => Some(("@", false, shift, ctrl, alt)),
|
(Keycode::KpAt, shift, ctrl, alt) => Some(("@", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpExclam, shift, ctrl, alt) => Some(("!", false, shift, ctrl, alt)),
|
(Keycode::KpExclam, shift, ctrl, alt) => Some(("!", false, shift, ctrl, alt)),
|
||||||
(Keycode::KpMemStore, _, _, _) => unsupported_key(Keycode::KpMemStore),
|
(Keycode::KpMemStore, _, _, _) => unsupported_key(Keycode::KpMemStore),
|
||||||
(Keycode::KpMemRecall, _, _, _) => unsupported_key(Keycode::KpMemRecall),
|
(Keycode::KpMemRecall, _, _, _) => unsupported_key(Keycode::KpMemRecall),
|
||||||
(Keycode::KpMemClear, _, _, _) => unsupported_key(Keycode::KpMemClear),
|
(Keycode::KpMemClear, _, _, _) => unsupported_key(Keycode::KpMemClear),
|
||||||
(Keycode::KpMemAdd, _, _, _) => unsupported_key(Keycode::KpMemAdd),
|
(Keycode::KpMemAdd, _, _, _) => unsupported_key(Keycode::KpMemAdd),
|
||||||
(Keycode::KpMemSubtract, _, _, _) => unsupported_key(Keycode::KpMemSubtract),
|
(Keycode::KpMemSubtract, _, _, _) => unsupported_key(Keycode::KpMemSubtract),
|
||||||
(Keycode::KpMemMultiply, _, _, _) => unsupported_key(Keycode::KpMemMultiply),
|
(Keycode::KpMemMultiply, _, _, _) => unsupported_key(Keycode::KpMemMultiply),
|
||||||
(Keycode::KpMemDivide, _, _, _) => unsupported_key(Keycode::KpMemDivide),
|
(Keycode::KpMemDivide, _, _, _) => unsupported_key(Keycode::KpMemDivide),
|
||||||
(Keycode::KpPlusMinus, _, _, _) => unsupported_key(Keycode::KpPlusMinus),
|
(Keycode::KpPlusMinus, _, _, _) => unsupported_key(Keycode::KpPlusMinus),
|
||||||
(Keycode::KpClear, _, _, _) => unsupported_key(Keycode::KpClear),
|
(Keycode::KpClear, _, _, _) => unsupported_key(Keycode::KpClear),
|
||||||
(Keycode::KpClearEntry, _, _, _) => unsupported_key(Keycode::KpClearEntry),
|
(Keycode::KpClearEntry, _, _, _) => unsupported_key(Keycode::KpClearEntry),
|
||||||
(Keycode::KpBinary, _, _, _) => unsupported_key(Keycode::KpBinary),
|
(Keycode::KpBinary, _, _, _) => unsupported_key(Keycode::KpBinary),
|
||||||
(Keycode::KpOctal, _, _, _) => unsupported_key(Keycode::KpOctal),
|
(Keycode::KpOctal, _, _, _) => unsupported_key(Keycode::KpOctal),
|
||||||
(Keycode::KpDecimal, _, _, _) => unsupported_key(Keycode::KpDecimal),
|
(Keycode::KpDecimal, _, _, _) => unsupported_key(Keycode::KpDecimal),
|
||||||
(Keycode::KpHexadecimal, _, _, _) => unsupported_key(Keycode::KpHexadecimal),
|
(Keycode::KpHexadecimal, _, _, _) => unsupported_key(Keycode::KpHexadecimal),
|
||||||
(Keycode::LCtrl, _, _, _) => None,
|
(Keycode::LCtrl, _, _, _) => None,
|
||||||
(Keycode::LShift, _, _, _) => None,
|
(Keycode::LShift, _, _, _) => None,
|
||||||
(Keycode::LAlt, _, _, _) => None,
|
(Keycode::LAlt, _, _, _) => None,
|
||||||
(Keycode::LGui, _, _, _) => None,
|
(Keycode::LGui, _, _, _) => None,
|
||||||
(Keycode::RCtrl, _, _, _) => None,
|
(Keycode::RCtrl, _, _, _) => None,
|
||||||
(Keycode::RShift, _, _, _) => None,
|
(Keycode::RShift, _, _, _) => None,
|
||||||
(Keycode::RAlt, _, _, _) => None,
|
(Keycode::RAlt, _, _, _) => None,
|
||||||
(Keycode::RGui, _, _, _) => None,
|
(Keycode::RGui, _, _, _) => None,
|
||||||
(Keycode::Mode, _, _, _) => unsupported_key(Keycode::Mode),
|
(Keycode::Mode, _, _, _) => unsupported_key(Keycode::Mode),
|
||||||
(Keycode::AudioNext, _, _, _) => unsupported_key(Keycode::AudioNext),
|
(Keycode::AudioNext, _, _, _) => unsupported_key(Keycode::AudioNext),
|
||||||
(Keycode::AudioPrev, _, _, _) => unsupported_key(Keycode::AudioPrev),
|
(Keycode::AudioPrev, _, _, _) => unsupported_key(Keycode::AudioPrev),
|
||||||
(Keycode::AudioStop, _, _, _) => unsupported_key(Keycode::AudioStop),
|
(Keycode::AudioStop, _, _, _) => unsupported_key(Keycode::AudioStop),
|
||||||
(Keycode::AudioPlay, _, _, _) => unsupported_key(Keycode::AudioPlay),
|
(Keycode::AudioPlay, _, _, _) => unsupported_key(Keycode::AudioPlay),
|
||||||
(Keycode::AudioMute, _, _, _) => unsupported_key(Keycode::AudioMute),
|
(Keycode::AudioMute, _, _, _) => unsupported_key(Keycode::AudioMute),
|
||||||
(Keycode::MediaSelect, _, _, _) => unsupported_key(Keycode::MediaSelect),
|
(Keycode::MediaSelect, _, _, _) => unsupported_key(Keycode::MediaSelect),
|
||||||
(Keycode::Www, _, _, _) => unsupported_key(Keycode::Www),
|
(Keycode::Www, _, _, _) => unsupported_key(Keycode::Www),
|
||||||
(Keycode::Mail, _, _, _) => unsupported_key(Keycode::Mail),
|
(Keycode::Mail, _, _, _) => unsupported_key(Keycode::Mail),
|
||||||
(Keycode::Calculator, _, _, _) => unsupported_key(Keycode::Calculator),
|
(Keycode::Calculator, _, _, _) => unsupported_key(Keycode::Calculator),
|
||||||
(Keycode::Computer, _, _, _) => unsupported_key(Keycode::Computer),
|
(Keycode::Computer, _, _, _) => unsupported_key(Keycode::Computer),
|
||||||
(Keycode::AcSearch, _, _, _) => unsupported_key(Keycode::AcSearch),
|
(Keycode::AcSearch, _, _, _) => unsupported_key(Keycode::AcSearch),
|
||||||
(Keycode::AcHome, _, _, _) => unsupported_key(Keycode::AcHome),
|
(Keycode::AcHome, _, _, _) => unsupported_key(Keycode::AcHome),
|
||||||
(Keycode::AcBack, _, _, _) => unsupported_key(Keycode::AcBack),
|
(Keycode::AcBack, _, _, _) => unsupported_key(Keycode::AcBack),
|
||||||
(Keycode::AcForward, _, _, _) => unsupported_key(Keycode::AcForward),
|
(Keycode::AcForward, _, _, _) => unsupported_key(Keycode::AcForward),
|
||||||
(Keycode::AcStop, _, _, _) => unsupported_key(Keycode::AcStop),
|
(Keycode::AcStop, _, _, _) => unsupported_key(Keycode::AcStop),
|
||||||
(Keycode::AcRefresh, _, _, _) => unsupported_key(Keycode::AcRefresh),
|
(Keycode::AcRefresh, _, _, _) => unsupported_key(Keycode::AcRefresh),
|
||||||
(Keycode::AcBookmarks, _, _, _) => unsupported_key(Keycode::AcBookmarks),
|
(Keycode::AcBookmarks, _, _, _) => unsupported_key(Keycode::AcBookmarks),
|
||||||
(Keycode::BrightnessDown, _, _, _) => unsupported_key(Keycode::BrightnessDown),
|
(Keycode::BrightnessDown, _, _, _) => unsupported_key(Keycode::BrightnessDown),
|
||||||
(Keycode::BrightnessUp, _, _, _) => unsupported_key(Keycode::BrightnessUp),
|
(Keycode::BrightnessUp, _, _, _) => unsupported_key(Keycode::BrightnessUp),
|
||||||
(Keycode::DisplaySwitch, _, _, _) => unsupported_key(Keycode::DisplaySwitch),
|
(Keycode::DisplaySwitch, _, _, _) => unsupported_key(Keycode::DisplaySwitch),
|
||||||
(Keycode::KbdIllumToggle, _, _, _) => unsupported_key(Keycode::KbdIllumToggle),
|
(Keycode::KbdIllumToggle, _, _, _) => unsupported_key(Keycode::KbdIllumToggle),
|
||||||
(Keycode::KbdIllumDown, _, _, _) => unsupported_key(Keycode::KbdIllumDown),
|
(Keycode::KbdIllumDown, _, _, _) => unsupported_key(Keycode::KbdIllumDown),
|
||||||
(Keycode::KbdIllumUp, _, _, _) => unsupported_key(Keycode::KbdIllumUp),
|
(Keycode::KbdIllumUp, _, _, _) => unsupported_key(Keycode::KbdIllumUp),
|
||||||
(Keycode::Eject, _, _, _) => unsupported_key(Keycode::Eject),
|
(Keycode::Eject, _, _, _) => unsupported_key(Keycode::Eject),
|
||||||
(Keycode::Sleep, _, _, _) => unsupported_key(Keycode::Sleep),
|
(Keycode::Sleep, _, _, _) => unsupported_key(Keycode::Sleep),
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,27 +1,30 @@
|
|||||||
use crate::settings::*;
|
use crate::settings::*;
|
||||||
|
use super::keyboard::initialize_settings as keyboard_initialize_settings;
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct WindowSettings {
|
#[derive(Clone)]
|
||||||
pub refresh_rate: u64,
|
pub struct WindowSettings {
|
||||||
pub transparency: f32,
|
pub refresh_rate: u64,
|
||||||
pub no_idle: bool,
|
pub transparency: f32,
|
||||||
pub fullscreen: bool,
|
pub no_idle: bool,
|
||||||
}
|
pub fullscreen: bool,
|
||||||
|
}
|
||||||
pub fn initialize_settings() {
|
|
||||||
let no_idle = SETTINGS
|
pub fn initialize_settings() {
|
||||||
.neovim_arguments
|
let no_idle = SETTINGS
|
||||||
.contains(&String::from("--noIdle"));
|
.neovim_arguments
|
||||||
|
.contains(&String::from("--noIdle"));
|
||||||
SETTINGS.set(&WindowSettings {
|
|
||||||
refresh_rate: 60,
|
SETTINGS.set(&WindowSettings {
|
||||||
transparency: 1.0,
|
refresh_rate: 60,
|
||||||
no_idle,
|
transparency: 1.0,
|
||||||
fullscreen: false,
|
no_idle,
|
||||||
});
|
fullscreen: false,
|
||||||
|
});
|
||||||
register_nvim_setting!("refresh_rate", WindowSettings::refresh_rate);
|
|
||||||
register_nvim_setting!("transparency", WindowSettings::transparency);
|
register_nvim_setting!("refresh_rate", WindowSettings::refresh_rate);
|
||||||
register_nvim_setting!("no_idle", WindowSettings::no_idle);
|
register_nvim_setting!("transparency", WindowSettings::transparency);
|
||||||
register_nvim_setting!("fullscreen", WindowSettings::fullscreen);
|
register_nvim_setting!("no_idle", WindowSettings::no_idle);
|
||||||
}
|
register_nvim_setting!("fullscreen", WindowSettings::fullscreen);
|
||||||
|
|
||||||
|
keyboard_initialize_settings();
|
||||||
|
}
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
mod qwerty;
|
||||||
|
|
||||||
|
use log::trace;
|
||||||
|
use skulpin::winit::event::ModifiersState;
|
||||||
|
use skulpin::winit::event::VirtualKeyCode as Keycode;
|
||||||
|
|
||||||
|
use qwerty::*;
|
||||||
|
use super::keyboard::*;
|
||||||
|
use crate::settings::*;
|
||||||
|
|
||||||
|
pub fn unsupported_key<R>(keycode: Keycode) -> Option<R> {
|
||||||
|
trace!("Unsupported key: {:?}", keycode);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn produce_neovim_keybinding_string(
|
||||||
|
keycode: Option<Keycode>,
|
||||||
|
keytext: Option<String>,
|
||||||
|
modifiers: Option<ModifiersState>,
|
||||||
|
) -> Option<String> {
|
||||||
|
let mut shift = false;
|
||||||
|
let mut ctrl = false;
|
||||||
|
let mut alt = false;
|
||||||
|
let mut gui = false;
|
||||||
|
if let Some(modifiers) = modifiers {
|
||||||
|
shift = modifiers.shift();
|
||||||
|
ctrl = modifiers.ctrl();
|
||||||
|
alt = modifiers.alt();
|
||||||
|
gui = modifiers.logo();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(text) = keytext {
|
||||||
|
Some(append_modifiers(&text, false, false, ctrl, alt, gui))
|
||||||
|
} else if let Some(keycode) = keycode {
|
||||||
|
(match SETTINGS.get::<KeyboardSettings>().layout {
|
||||||
|
KeyboardLayout::Qwerty => handle_qwerty_layout(keycode, shift, ctrl, alt),
|
||||||
|
})
|
||||||
|
.map(|(transformed_text, special, shift, ctrl, alt)| {
|
||||||
|
append_modifiers(transformed_text, special, shift, ctrl, alt, gui)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,164 @@
|
|||||||
|
use super::unsupported_key;
|
||||||
|
|
||||||
|
use skulpin::winit::event::VirtualKeyCode as Keycode;
|
||||||
|
|
||||||
|
pub fn handle_qwerty_layout(
|
||||||
|
keycode: Keycode,
|
||||||
|
shift: bool,
|
||||||
|
ctrl: bool,
|
||||||
|
alt: bool,
|
||||||
|
) -> Option<(&'static str, bool, bool, bool, bool)> {
|
||||||
|
match (keycode, shift, ctrl, alt) {
|
||||||
|
(Keycode::Back, shift, ctrl, alt) => Some(("BS", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Tab, shift, ctrl, alt) => Some(("Tab", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Return, shift, ctrl, alt) => Some(("Enter", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Escape, shift, ctrl, alt) => Some(("Esc", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Space, shift, ctrl, alt) => Some((" ", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Apostrophe, false, ctrl, alt) => Some(("'", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Apostrophe, true, ctrl, alt) => Some(("\"", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Comma, false, ctrl, alt) => Some((",", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Comma, true, ctrl, alt) => Some(("<", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Minus, false, ctrl, alt) => Some(("-", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Minus, true, ctrl, alt) => Some(("_", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Period, false, ctrl, alt) => Some((".", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Period, true, ctrl, alt) => Some((">", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Slash, false, ctrl, alt) => Some(("/", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Slash, true, ctrl, alt) => Some(("?", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key0, false, ctrl, alt) => Some(("0", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Key0, true, ctrl, alt) => Some((")", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Key1, false, ctrl, alt) => Some(("1", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Key1, true, ctrl, alt) => Some(("!", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Key2, false, ctrl, alt) => Some(("2", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key2, true, ctrl, alt) => Some(("@", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key3, false, ctrl, alt) => Some(("3", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key3, true, ctrl, alt) => Some(("#", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key4, false, ctrl, alt) => Some(("4", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key4, true, ctrl, alt) => Some(("$", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key5, false, ctrl, alt) => Some(("5", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key5, true, ctrl, alt) => Some(("%", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key6, false, ctrl, alt) => Some(("6", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key6, true, ctrl, alt) => Some(("^", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key7, false, ctrl, alt) => Some(("7", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key7, true, ctrl, alt) => Some(("&", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key8, false, ctrl, alt) => Some(("8", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key8, true, ctrl, alt) => Some(("*", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key9, false, ctrl, alt) => Some(("9", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Key9, true, ctrl, alt) => Some(("(", true, false, ctrl, alt)),
|
||||||
|
(Keycode::Colon, shift, ctrl, alt) => Some((":", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Semicolon, false, ctrl, alt) => Some((";", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Semicolon, true, ctrl, alt) => Some((":", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Equals, false, ctrl, alt) => Some(("=", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Equals, true, ctrl, alt) => Some(("+", false, false, ctrl, alt)),
|
||||||
|
(Keycode::At, shift, ctrl, alt) => Some(("@", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::LBracket, false, ctrl, alt) => Some(("[", false, false, ctrl, alt)),
|
||||||
|
(Keycode::LBracket, true, ctrl, alt) => Some(("{", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Backslash, false, ctrl, alt) => Some(("\\", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Backslash, true, ctrl, alt) => Some(("|", false, false, ctrl, alt)),
|
||||||
|
(Keycode::RBracket, false, ctrl, alt) => Some(("]", false, false, ctrl, alt)),
|
||||||
|
(Keycode::RBracket, true, ctrl, alt) => Some(("}", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Caret, shift, ctrl, alt) => Some(("^", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Grave, false, ctrl, alt) => Some(("`", false, false, ctrl, alt)),
|
||||||
|
(Keycode::Grave, true, ctrl, alt) => Some(("~", false, false, ctrl, alt)),
|
||||||
|
(Keycode::A, shift, ctrl, alt) => Some(("a", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::B, shift, ctrl, alt) => Some(("b", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::C, shift, ctrl, alt) => Some(("c", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::D, shift, ctrl, alt) => Some(("d", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::E, shift, ctrl, alt) => Some(("e", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::F, shift, ctrl, alt) => Some(("f", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::G, shift, ctrl, alt) => Some(("g", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::H, shift, ctrl, alt) => Some(("h", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::I, shift, ctrl, alt) => Some(("i", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::J, shift, ctrl, alt) => Some(("j", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::K, shift, ctrl, alt) => Some(("k", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::L, shift, ctrl, alt) => Some(("l", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::M, shift, ctrl, alt) => Some(("m", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::N, shift, ctrl, alt) => Some(("n", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::O, shift, ctrl, alt) => Some(("o", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::P, shift, ctrl, alt) => Some(("p", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Q, shift, ctrl, alt) => Some(("q", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::R, shift, ctrl, alt) => Some(("r", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::S, shift, ctrl, alt) => Some(("s", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::T, shift, ctrl, alt) => Some(("t", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::U, shift, ctrl, alt) => Some(("u", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::V, shift, ctrl, alt) => Some(("v", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::W, shift, ctrl, alt) => Some(("w", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::X, shift, ctrl, alt) => Some(("x", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Y, shift, ctrl, alt) => Some(("y", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Z, shift, ctrl, alt) => Some(("z", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Delete, shift, ctrl, alt) => Some(("Delete", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F1, shift, ctrl, alt) => Some(("F1", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F2, shift, ctrl, alt) => Some(("F2", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F3, shift, ctrl, alt) => Some(("F3", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F4, shift, ctrl, alt) => Some(("F4", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F5, shift, ctrl, alt) => Some(("F5", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F6, shift, ctrl, alt) => Some(("F6", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F7, shift, ctrl, alt) => Some(("F7", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F8, shift, ctrl, alt) => Some(("F8", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F9, shift, ctrl, alt) => Some(("F9", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F10, shift, ctrl, alt) => Some(("F10", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F11, shift, ctrl, alt) => Some(("F11", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F12, shift, ctrl, alt) => Some(("F12", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Snapshot, _, _, _) => unsupported_key(Keycode::Snapshot),
|
||||||
|
(Keycode::Pause, _, _, _) => unsupported_key(Keycode::Pause),
|
||||||
|
(Keycode::Insert, shift, ctrl, alt) => Some(("Insert", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Home, shift, ctrl, alt) => Some(("Home", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::PageUp, shift, ctrl, alt) => Some(("PageUp", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::End, shift, ctrl, alt) => Some(("End", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::PageDown, shift, ctrl, alt) => Some(("PageDown", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Right, shift, ctrl, alt) => Some(("Right", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Left, shift, ctrl, alt) => Some(("Left", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Down, shift, ctrl, alt) => Some(("Down", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Up, shift, ctrl, alt) => Some(("Up", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad0, shift, ctrl, alt) => Some(("0", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad1, shift, ctrl, alt) => Some(("1", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad2, shift, ctrl, alt) => Some(("2", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad3, shift, ctrl, alt) => Some(("3", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad4, shift, ctrl, alt) => Some(("4", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad5, shift, ctrl, alt) => Some(("5", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad6, shift, ctrl, alt) => Some(("6", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad7, shift, ctrl, alt) => Some(("7", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad8, shift, ctrl, alt) => Some(("8", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Numpad9, shift, ctrl, alt) => Some(("9", false, shift, ctrl, alt)),
|
||||||
|
(Keycode::Apps, _, _, _) => unsupported_key(Keycode::Apps),
|
||||||
|
(Keycode::Power, _, _, _) => unsupported_key(Keycode::Power),
|
||||||
|
(Keycode::F13, shift, ctrl, alt) => Some(("F13", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F14, shift, ctrl, alt) => Some(("F14", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F15, shift, ctrl, alt) => Some(("F15", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F16, shift, ctrl, alt) => Some(("F16", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F17, shift, ctrl, alt) => Some(("F17", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F18, shift, ctrl, alt) => Some(("F18", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F19, shift, ctrl, alt) => Some(("F19", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F20, shift, ctrl, alt) => Some(("F20", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F21, shift, ctrl, alt) => Some(("F21", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F22, shift, ctrl, alt) => Some(("F22", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F23, shift, ctrl, alt) => Some(("F23", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::F24, shift, ctrl, alt) => Some(("F24", true, shift, ctrl, alt)),
|
||||||
|
(Keycode::Cut, _, _, _) => unsupported_key(Keycode::Cut),
|
||||||
|
(Keycode::Copy, _, _, _) => unsupported_key(Keycode::Copy),
|
||||||
|
(Keycode::Paste, _, _, _) => unsupported_key(Keycode::Paste),
|
||||||
|
(Keycode::Mute, _, _, _) => unsupported_key(Keycode::Mute),
|
||||||
|
(Keycode::VolumeUp, _, _, _) => unsupported_key(Keycode::VolumeUp),
|
||||||
|
(Keycode::VolumeDown, _, _, _) => unsupported_key(Keycode::VolumeDown),
|
||||||
|
(Keycode::Sysrq, _, _, _) => unsupported_key(Keycode::Sysrq),
|
||||||
|
(Keycode::LControl, _, _, _) => None,
|
||||||
|
(Keycode::LShift, _, _, _) => None,
|
||||||
|
(Keycode::LAlt, _, _, _) => None,
|
||||||
|
(Keycode::RControl, _, _, _) => None,
|
||||||
|
(Keycode::RShift, _, _, _) => None,
|
||||||
|
(Keycode::RAlt, _, _, _) => None,
|
||||||
|
(Keycode::MediaStop, _, _, _) => unsupported_key(Keycode::MediaStop),
|
||||||
|
(Keycode::MediaSelect, _, _, _) => unsupported_key(Keycode::MediaSelect),
|
||||||
|
(Keycode::Calculator, _, _, _) => unsupported_key(Keycode::Calculator),
|
||||||
|
(Keycode::MyComputer, _, _, _) => unsupported_key(Keycode::MyComputer),
|
||||||
|
(Keycode::WebSearch, _, _, _) => unsupported_key(Keycode::WebSearch),
|
||||||
|
(Keycode::WebHome, _, _, _) => unsupported_key(Keycode::WebHome),
|
||||||
|
(Keycode::WebBack, _, _, _) => unsupported_key(Keycode::WebBack),
|
||||||
|
(Keycode::WebForward, _, _, _) => unsupported_key(Keycode::WebForward),
|
||||||
|
(Keycode::NavigateBackward, _, _, _) => unsupported_key(Keycode::NavigateBackward),
|
||||||
|
(Keycode::NavigateForward, _, _, _) => unsupported_key(Keycode::NavigateForward),
|
||||||
|
(Keycode::WebStop, _, _, _) => unsupported_key(Keycode::WebStop),
|
||||||
|
(Keycode::WebRefresh, _, _, _) => unsupported_key(Keycode::WebRefresh),
|
||||||
|
(Keycode::Sleep, _, _, _) => unsupported_key(Keycode::Sleep),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,473 @@
|
|||||||
|
#[macro_use]
|
||||||
|
mod layouts;
|
||||||
|
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::mpsc::Receiver;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
use crossfire::mpsc::TxUnbounded;
|
||||||
|
use image::{load_from_memory, GenericImageView, Pixel};
|
||||||
|
use log::{debug, error, info, trace};
|
||||||
|
use skulpin::winit;
|
||||||
|
use skulpin::winit::dpi::Size;
|
||||||
|
use skulpin::winit::event::VirtualKeyCode as Keycode;
|
||||||
|
use skulpin::winit::event::{
|
||||||
|
ElementState, Event, ModifiersState, MouseButton, MouseScrollDelta, WindowEvent,
|
||||||
|
};
|
||||||
|
use skulpin::winit::event_loop::{ControlFlow, EventLoop};
|
||||||
|
use skulpin::winit::window::{Fullscreen, Icon};
|
||||||
|
use skulpin::{
|
||||||
|
CoordinateSystem, LogicalSize, PhysicalSize, PresentMode, Renderer as SkulpinRenderer,
|
||||||
|
RendererBuilder, Window, WinitWindow,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::handle_new_grid_size;
|
||||||
|
use super::settings::*;
|
||||||
|
pub use super::keyboard;
|
||||||
|
use crate::bridge::UiCommand;
|
||||||
|
use crate::editor::WindowCommand;
|
||||||
|
use crate::error_handling::ResultPanicExplanation;
|
||||||
|
use crate::redraw_scheduler::REDRAW_SCHEDULER;
|
||||||
|
use crate::renderer::Renderer;
|
||||||
|
use crate::settings::*;
|
||||||
|
use layouts::produce_neovim_keybinding_string;
|
||||||
|
|
||||||
|
#[derive(RustEmbed)]
|
||||||
|
#[folder = "assets/"]
|
||||||
|
struct Asset;
|
||||||
|
|
||||||
|
pub struct WinitWindowWrapper {
|
||||||
|
window: winit::window::Window,
|
||||||
|
skulpin_renderer: SkulpinRenderer,
|
||||||
|
renderer: Renderer,
|
||||||
|
mouse_down: bool,
|
||||||
|
mouse_position: LogicalSize,
|
||||||
|
mouse_enabled: bool,
|
||||||
|
grid_id_under_mouse: u64,
|
||||||
|
title: String,
|
||||||
|
previous_size: LogicalSize,
|
||||||
|
transparency: f32,
|
||||||
|
fullscreen: bool,
|
||||||
|
cached_size: (u32, u32),
|
||||||
|
cached_position: (i32, i32),
|
||||||
|
ui_command_sender: TxUnbounded<UiCommand>,
|
||||||
|
window_command_receiver: Receiver<WindowCommand>,
|
||||||
|
running: Arc<AtomicBool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WinitWindowWrapper {
|
||||||
|
pub fn toggle_fullscreen(&mut self) {
|
||||||
|
if self.fullscreen {
|
||||||
|
self.window.set_fullscreen(None);
|
||||||
|
|
||||||
|
// Use cached size and position
|
||||||
|
self.window.set_inner_size(self.cached_size.into::<Size>());
|
||||||
|
self.window.set_outer_position(self.cached_position.into::<Size>());
|
||||||
|
} else {
|
||||||
|
self.cached_size = self.window.inner_size().into();
|
||||||
|
self.cached_position = self.window.outer_position().unwrap().into();
|
||||||
|
let handle = self.window.current_monitor();
|
||||||
|
self.window
|
||||||
|
.set_fullscreen(Some(Fullscreen::Borderless(handle)));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fullscreen = !self.fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn synchronize_settings(&mut self) {
|
||||||
|
let editor_title = { EDITOR.lock().title.clone() };
|
||||||
|
|
||||||
|
if self.title != editor_title {
|
||||||
|
self.title = editor_title;
|
||||||
|
self.window.set_title(&self.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fullscreen = { SETTINGS.get::<WindowSettings>().fullscreen };
|
||||||
|
|
||||||
|
if self.fullscreen != fullscreen {
|
||||||
|
self.toggle_fullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_quit(&mut self) {
|
||||||
|
self.running.store(false, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_keyboard_input(
|
||||||
|
&mut self,
|
||||||
|
keycode: Option<Keycode>,
|
||||||
|
modifiers: Option<ModifiersState>,
|
||||||
|
) {
|
||||||
|
if keycode.is_some() {
|
||||||
|
trace!(
|
||||||
|
"Keyboard Input Received: keycode-{:?} modifiers-{:?} ",
|
||||||
|
keycode,
|
||||||
|
modifiers
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(keybinding_string) = produce_neovim_keybinding_string(keycode, None, modifiers)
|
||||||
|
{
|
||||||
|
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 previous_position = self.mouse_position;
|
||||||
|
let winit_window_wrapper = WinitWindow::new(&self.window);
|
||||||
|
let logical_position =
|
||||||
|
PhysicalSize::new(x as u32, y as u32).to_logical(winit_window_wrapper.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::new(
|
||||||
|
logical_position.width - details.region.left as u32,
|
||||||
|
logical_position.height - details.region.top as u32,
|
||||||
|
),
|
||||||
|
details.floating,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((grid_id, grid_position, grid_floating)) = top_grid_position {
|
||||||
|
self.grid_id_under_mouse = grid_id;
|
||||||
|
self.mouse_position = LogicalSize::new(
|
||||||
|
(grid_position.width as f32 / self.renderer.font_width) as u32,
|
||||||
|
(grid_position.height as f32 / 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.width, self.mouse_position.height)
|
||||||
|
} else {
|
||||||
|
let adjusted_drag_left =
|
||||||
|
self.mouse_position.width + (window_left / self.renderer.font_width) as u32;
|
||||||
|
let adjusted_drag_top = self.mouse_position.height
|
||||||
|
+ (window_top / self.renderer.font_height) 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.width, self.mouse_position.height),
|
||||||
|
})
|
||||||
|
.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.width, self.mouse_position.height),
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
self.mouse_down = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_mouse_wheel(&mut self, x: i32, y: i32) {
|
||||||
|
if !self.mouse_enabled {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let vertical_input_type = match y {
|
||||||
|
_ if y > 0 => Some("up"),
|
||||||
|
_ if y < 0 => 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.width, self.mouse_position.height),
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
let horizontal_input_type = match y {
|
||||||
|
_ if x > 0 => Some("right"),
|
||||||
|
_ if x < 0 => 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.width, self.mouse_position.height),
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_focus_lost(&mut self) {
|
||||||
|
self.ui_command_sender.send(UiCommand::FocusLost).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_focus_gained(&mut self) {
|
||||||
|
self.ui_command_sender.send(UiCommand::FocusGained).ok();
|
||||||
|
REDRAW_SCHEDULER.queue_next_frame();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_event(&mut self, event: Event<()>) {
|
||||||
|
let mut keycode = None;
|
||||||
|
let mut modifiers = None;
|
||||||
|
let mut ignore_text_this_frame = false;
|
||||||
|
|
||||||
|
match event {
|
||||||
|
Event::LoopDestroyed => {
|
||||||
|
self.handle_quit();
|
||||||
|
}
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::CloseRequested,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
self.handle_quit();
|
||||||
|
}
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::DroppedFile(path),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
self.ui_command_sender.send(UiCommand::FileDrop(
|
||||||
|
path.into_os_string().into_string().unwrap(),
|
||||||
|
)).ok();
|
||||||
|
}
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::KeyboardInput { input, .. },
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if input.state == ElementState::Pressed {
|
||||||
|
keycode = input.virtual_keycode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::WindowEvent {
|
||||||
|
event: WindowEvent::ModifiersChanged(m),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
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 i32, y as i32),
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::WindowEvent { .. } => REDRAW_SCHEDULER.queue_next_frame(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignore_text_this_frame {
|
||||||
|
window.handle_keyboard_input(keycode, modifiers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_frame(&mut self, dt: f32) -> VkResult<bool> {
|
||||||
|
let winit_window_wrapper = WinitWindow::new(&self.window);
|
||||||
|
let new_size = winit_window_wrapper.logical_size();
|
||||||
|
if self.previous_size != new_size {
|
||||||
|
handle_new_grid_size(new_size, &self.renderer, &self.ui_command_sender);
|
||||||
|
self.previous_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_size = self.previous_size;
|
||||||
|
let ui_command_sender = self.ui_command_sender.clone();
|
||||||
|
|
||||||
|
if REDRAW_SCHEDULER.should_draw() || SETTINGS.get::<WindowSettings>().no_idle {
|
||||||
|
debug!("Render Triggered");
|
||||||
|
|
||||||
|
let renderer = &mut self.renderer;
|
||||||
|
self.skulpin_renderer.draw(
|
||||||
|
&sdl_window_wrapper,
|
||||||
|
|canvas, coordinate_system_helper| {
|
||||||
|
if renderer.draw_frame(canvas, &coordinate_system_helper, dt) {
|
||||||
|
handle_new_grid_size(current_size, &renderer, &ui_command_sender);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_loop(
|
||||||
|
window_command_receiver: Receiver<WindowCommand>,
|
||||||
|
ui_command_sender: TxUnbounded<UiCommand>,
|
||||||
|
running: Arc<AtomicBool>,
|
||||||
|
logical_size: LogicalSize,
|
||||||
|
renderer: Renderer,
|
||||||
|
) {
|
||||||
|
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");
|
||||||
|
|
||||||
|
let winit_window = winit::window::WindowBuilder::new()
|
||||||
|
.with_title("Neovide")
|
||||||
|
.with_inner_size((logical_size.width, logical_size.height).into())
|
||||||
|
.with_window_icon(Some(icon))
|
||||||
|
.build(event_loop)
|
||||||
|
.expect("Failed to create window");
|
||||||
|
info!("window created");
|
||||||
|
|
||||||
|
let scale_factor = winit_window.scale_factor();
|
||||||
|
|
||||||
|
let skulpin_renderer = {
|
||||||
|
let winit_window_wrapper = WinitWindow::new(&winit_window);
|
||||||
|
RendererBuilder::new()
|
||||||
|
.prefer_integrated_gpu()
|
||||||
|
.use_vulkan_debug_layer(false)
|
||||||
|
.present_mode_priority(vec![PresentMode::Immediate])
|
||||||
|
.coordinate_system(CoordinateSystem::Logical)
|
||||||
|
.build(&winit_window_wrapper)
|
||||||
|
.expect("Failed to create renderer")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut window_wrapper = WinitWindowWrapper {
|
||||||
|
window: winit_window,
|
||||||
|
skulpin_renderer,
|
||||||
|
renderer,
|
||||||
|
mouse_down: false,
|
||||||
|
mouse_position: LogicalSize {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
},
|
||||||
|
mouse_enabled: true,
|
||||||
|
grid_id_under_mouse: 0,
|
||||||
|
title: String::from("Neovide"),
|
||||||
|
previous_size: logical_size,
|
||||||
|
transparency: 1.0,
|
||||||
|
fullscreen: false,
|
||||||
|
cached_size: (0, 0),
|
||||||
|
cached_position: (0, 0),
|
||||||
|
ui_command_sender,
|
||||||
|
window_command_receiver,
|
||||||
|
running: running.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut was_animating = false;
|
||||||
|
let mut previous_frame_start = Instant::now();
|
||||||
|
|
||||||
|
let event_loop = EventLoop::new();
|
||||||
|
event_loop.run(move |e, _window_target, control_flow| {
|
||||||
|
if !running.load(Ordering::Relaxed) {
|
||||||
|
*control_flow = ControlFlow::Exit;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let frame_start = Instant::now();
|
||||||
|
|
||||||
|
let refresh_rate = { SETTINGS.get::<WindowSettings>().refresh_rate as f32 };
|
||||||
|
let dt = if was_animating {
|
||||||
|
previous_frame_start.elapsed().as_secs_f32()
|
||||||
|
} else {
|
||||||
|
1.0 / refresh_rate
|
||||||
|
};
|
||||||
|
|
||||||
|
window_wrapper.synchronize_settings();
|
||||||
|
|
||||||
|
window_wrapper.handle_event(e);
|
||||||
|
|
||||||
|
match window_wrapper.draw_frame(dt) {
|
||||||
|
Ok(animating) => {
|
||||||
|
was_animating = animating;
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
error!("Render failed: {}", error);
|
||||||
|
self.running.store(false, Ordering::Relaxed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let elapsed = frame_start.elapsed();
|
||||||
|
let frame_length = Duration::from_secs_f32(1.0 / refresh_rate);
|
||||||
|
|
||||||
|
if elapsed < frame_length {
|
||||||
|
*control_flow = ControlFlow::WaitUntil(Instant::now() + frame_length);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue