You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
neovide/src/window.rs

257 lines
9.5 KiB
Rust

use std::time::{Duration, Instant};
5 years ago
use std::thread::sleep;
5 years ago
use log::{info, debug, trace, error};
5 years ago
use skulpin::{LogicalSize, PhysicalSize};
use skulpin::sdl2;
use skulpin::sdl2::EventPump;
5 years ago
use skulpin::sdl2::event::{Event, WindowEvent};
use skulpin::sdl2::keyboard::Mod;
5 years ago
use skulpin::{RendererBuilder, PresentMode, CoordinateSystem, dpis};
5 years ago
use crate::bridge::{parse_keycode, append_modifiers, BRIDGE, UiCommand};
use crate::renderer::Renderer;
use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::editor::EDITOR;
use crate::settings::SETTINGS;
use crate::INITIAL_DIMENSIONS;
5 years ago
#[derive(RustEmbed)]
#[folder = "assets/"]
struct Asset;
5 years ago
#[cfg(windows)]
fn windows_fix_dpi() {
use winapi::um::winuser::SetProcessDpiAwarenessContext;
use winapi::shared::windef::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
unsafe {
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
}
fn handle_new_grid_size(new_size: LogicalSize, renderer: &Renderer) {
if new_size.width > 0 && new_size.height > 0 {
let new_width = ((new_size.width + 1) as f32 / renderer.font_width) as i64;
let new_height = ((new_size.height + 1) as f32 / renderer.font_height) as i64;
// Add 1 here to make sure resizing doesn't change the grid size on startup
BRIDGE.queue_command(UiCommand::Resize { width: new_width as i64, height: new_height as i64 });
}
}
pub fn ui_loop() {
let sdl_context = sdl2::init().expect("Failed to initialize sdl2");
let video_subsystem = sdl_context.video().expect("Failed to create sdl video subsystem");
5 years ago
let (width, height) = INITIAL_DIMENSIONS;
let mut renderer = Renderer::new();
5 years ago
let logical_size = LogicalSize {
width: (width as f32 * renderer.font_width) as u32,
height: (height as f32 * renderer.font_height + 1.0) as u32
};
5 years ago
// 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");
5 years ago
windows_fix_dpi();
let mut window = video_subsystem.window("Neovide", logical_size.width, logical_size.height)
5 years ago
.position_centered()
.allow_highdpi()
5 years ago
.resizable()
5 years ago
.vulkan()
.build()
.expect("Failed to create window");
info!("window created");
let mut skulpin_renderer = RendererBuilder::new()
.prefer_integrated_gpu()
.use_vulkan_debug_layer(true)
.present_mode_priority(vec![PresentMode::Mailbox, PresentMode::Immediate])
5 years ago
.coordinate_system(CoordinateSystem::Logical)
.build(&window)
.expect("Failed to create renderer");
info!("renderer created");
let mut mouse_down = false;
let mut mouse_pos = (0, 0);
// let mut allow_next_char = false;
// let mut next_char_modifiers = ModifiersState::empty();
let mut title = "Neovide".to_string();
5 years ago
let mut previous_size = LogicalSize::new(&window).unwrap();
let mut previous_dpis = dpis(&window).unwrap();
info!("Starting window event loop");
let mut event_pump = sdl_context.event_pump().expect("Could not create sdl event pump");
'running: loop {
5 years ago
let frame_start = Instant::now();
let editor_title = { EDITOR.lock().title.clone() };
if title != editor_title {
title = editor_title;
window.set_title(&title);
}
for event in event_pump.poll_iter() {
match event {
Event::Quit {..} => break 'running,
Event::KeyDown {
keycode: Some(keycode),
keymod: modifiers,
..
} => {
if let Some((key_text, special)) = parse_keycode(keycode) {
let will_text_input =
!modifiers.contains(Mod::LCTRLMOD) &&
!modifiers.contains(Mod::RCTRLMOD) &&
!modifiers.contains(Mod::LALTMOD) &&
!modifiers.contains(Mod::RALTMOD) &&
!modifiers.contains(Mod::LGUIMOD) &&
!modifiers.contains(Mod::RGUIMOD);
if will_text_input && !special {
break;
}
BRIDGE.queue_command(UiCommand::Keyboard(append_modifiers(modifiers, key_text, special)));
}
},
Event::TextInput {
text,
..
5 years ago
} => {
let text = if text == "<" {
String::from("<lt>")
} else {
text
};
BRIDGE.queue_command(UiCommand::Keyboard(text))
},
_ => {}
}
}
5 years ago
let new_size = LogicalSize::new(&window).unwrap();
if previous_size != new_size {
handle_new_grid_size(new_size, &renderer);
previous_size = new_size;
}
let new_dpis = dpis(&window).unwrap();
if previous_dpis != new_dpis {
let physical_size = PhysicalSize::new(&window);
window.set_size(
(physical_size.width as f32 * new_dpis.0 / previous_dpis.0) as u32,
(physical_size.height as f32 * new_dpis.1 / previous_dpis.1) as u32).unwrap();
previous_dpis = new_dpis;
}
debug!("Render Triggered");
5 years ago
if REDRAW_SCHEDULER.should_draw() || SETTINGS.get("no_idle").read_bool() {
if skulpin_renderer.draw(&window, |canvas, coordinate_system_helper| {
if renderer.draw(canvas, coordinate_system_helper) {
5 years ago
handle_new_grid_size(new_size, &renderer)
5 years ago
}
}).is_err() {
error!("Render failed. Closing");
break;
5 years ago
}
}
let elapsed = frame_start.elapsed();
5 years ago
let frame_length = Duration::from_secs_f32(1.0 / 60.0);
5 years ago
if elapsed < frame_length {
sleep(frame_length - elapsed);
}
}
// event_loop.run(move |event, _window_target, control_flow| {
// trace!("Window Event: {:?}", event);
// match event {
// Event::WindowEvent {
// event: WindowEvent::CursorMoved {
// position,
// ..
// },
// ..
// } => {
// let position: LogicalPosition<f64> = position.to_logical(window.scale_factor());
// let grid_y = (position.x / renderer.font_width as f64) as i64;
// let grid_x = (position.y / renderer.font_height as f64) as i64;
// let (old_x, old_y) = mouse_pos;
// mouse_pos = (grid_x, grid_y);
// if mouse_down && (old_x != grid_x || old_y != grid_y) {
// BRIDGE.queue_command(UiCommand::Drag(grid_x, grid_y));
// }
// }
// Event::WindowEvent {
// event: WindowEvent::MouseInput {
// state,
// ..
// },
// ..
// } => {
// let input_type = match (state, mouse_down) {
// (ElementState::Pressed, false) => {
// mouse_down = true;
// Some("press")
// },
// (ElementState::Released, true) => {
// mouse_down = false;
// Some("release")
// },
// _ => None
// };
// if let Some(input_type) = input_type {
// let (grid_x, grid_y) = mouse_pos;
// BRIDGE.queue_command(UiCommand::MouseButton { action: input_type.to_string(), position: (grid_x, grid_y) });
// }
// }
// Event::WindowEvent {
// event: WindowEvent::MouseWheel {
// delta: MouseScrollDelta::LineDelta(horizontal, vertical),
// ..
// },
// ..
// } => {
// let vertical_input_type = if vertical > 0.0 {
// Some("up")
// } else if vertical < 0.0 {
// Some("down")
// } else {
// None
// };
// if let Some(input_type) = vertical_input_type {
// BRIDGE.queue_command(UiCommand::Scroll { direction: input_type.to_string(), position: mouse_pos });
// }
// let horizontal_input_type = if horizontal > 0.0 {
// Some("right")
// } else if horizontal < 0.0 {
// Some("left")
// } else {
// None
// };
// if let Some(input_type) = horizontal_input_type {
// BRIDGE.queue_command(UiCommand::Scroll { direction: input_type.to_string(), position: mouse_pos });
// }
// }
// }
// })
}