2022-06-10 20:43:33 +10:00
|
|
|
#![allow(clippy::single_match)]
|
|
|
|
|
2022-12-25 18:57:27 +11:00
|
|
|
#[cfg(not(wasm_platform))]
|
2023-04-11 21:50:52 +10:00
|
|
|
fn main() -> Result<(), impl std::error::Error> {
|
2019-07-11 08:54:54 +10:00
|
|
|
use std::{collections::HashMap, sync::mpsc, thread, time::Duration};
|
2019-05-02 09:03:30 +10:00
|
|
|
|
2020-09-10 11:58:30 +10:00
|
|
|
use simple_logger::SimpleLogger;
|
2019-07-11 08:54:54 +10:00
|
|
|
use winit::{
|
2020-01-04 17:32:34 +11:00
|
|
|
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
2023-05-29 04:02:59 +10:00
|
|
|
event::{ElementState, Event, KeyEvent, WindowEvent},
|
2022-04-10 11:32:02 +10:00
|
|
|
event_loop::EventLoop,
|
2023-05-29 04:02:59 +10:00
|
|
|
keyboard::{Key, ModifiersState},
|
2022-11-26 12:50:58 +11:00
|
|
|
window::{CursorGrabMode, CursorIcon, Fullscreen, WindowBuilder, WindowLevel},
|
2019-07-11 08:54:54 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
const WINDOW_COUNT: usize = 3;
|
2020-01-04 17:33:07 +11:00
|
|
|
const WINDOW_SIZE: PhysicalSize<u32> = PhysicalSize::new(600, 400);
|
2019-05-02 09:03:30 +10:00
|
|
|
|
2020-09-10 11:58:30 +10:00
|
|
|
SimpleLogger::new().init().unwrap();
|
2019-05-02 09:03:30 +10:00
|
|
|
let event_loop = EventLoop::new();
|
|
|
|
let mut window_senders = HashMap::with_capacity(WINDOW_COUNT);
|
|
|
|
for _ in 0..WINDOW_COUNT {
|
|
|
|
let window = WindowBuilder::new()
|
2019-06-20 06:49:43 +10:00
|
|
|
.with_inner_size(WINDOW_SIZE)
|
2019-05-02 09:03:30 +10:00
|
|
|
.build(&event_loop)
|
|
|
|
.unwrap();
|
2019-07-30 04:16:14 +10:00
|
|
|
|
2020-09-08 03:09:24 +10:00
|
|
|
let mut video_modes: Vec<_> = window.current_monitor().unwrap().video_modes().collect();
|
2019-07-30 04:16:14 +10:00
|
|
|
let mut video_mode_id = 0usize;
|
|
|
|
|
2019-05-02 09:03:30 +10:00
|
|
|
let (tx, rx) = mpsc::channel();
|
|
|
|
window_senders.insert(window.id(), tx);
|
2023-05-29 04:02:59 +10:00
|
|
|
let mut modifiers = ModifiersState::default();
|
2019-05-02 09:03:30 +10:00
|
|
|
thread::spawn(move || {
|
|
|
|
while let Ok(event) = rx.recv() {
|
|
|
|
match event {
|
2019-07-30 04:16:14 +10:00
|
|
|
WindowEvent::Moved { .. } => {
|
|
|
|
// We need to update our chosen video mode if the window
|
|
|
|
// was moved to an another monitor, so that the window
|
|
|
|
// appears on this monitor instead when we go fullscreen
|
2022-01-01 13:00:11 +11:00
|
|
|
let previous_video_mode = video_modes.get(video_mode_id).cloned();
|
2020-09-08 03:09:24 +10:00
|
|
|
video_modes = window.current_monitor().unwrap().video_modes().collect();
|
2019-07-30 04:16:14 +10:00
|
|
|
video_mode_id = video_mode_id.min(video_modes.len());
|
2022-01-01 13:00:11 +11:00
|
|
|
let video_mode = video_modes.get(video_mode_id);
|
2019-07-30 04:16:14 +10:00
|
|
|
|
|
|
|
// Different monitors may support different video modes,
|
|
|
|
// and the index we chose previously may now point to a
|
|
|
|
// completely different video mode, so notify the user
|
|
|
|
if video_mode != previous_video_mode.as_ref() {
|
|
|
|
println!(
|
|
|
|
"Window moved to another monitor, picked video mode: {}",
|
2022-01-01 13:00:11 +11:00
|
|
|
video_modes.get(video_mode_id).unwrap()
|
2019-07-30 04:16:14 +10:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2023-05-29 04:02:59 +10:00
|
|
|
WindowEvent::ModifiersChanged(new) => {
|
|
|
|
modifiers = new.state();
|
|
|
|
}
|
2019-06-22 01:33:15 +10:00
|
|
|
WindowEvent::KeyboardInput {
|
2023-05-29 04:02:59 +10:00
|
|
|
event:
|
|
|
|
KeyEvent {
|
2019-06-22 01:33:15 +10:00
|
|
|
state: ElementState::Released,
|
2023-05-29 04:02:59 +10:00
|
|
|
logical_key: key,
|
2019-06-22 01:33:15 +10:00
|
|
|
..
|
|
|
|
},
|
2019-05-02 09:03:30 +10:00
|
|
|
..
|
2019-06-22 01:33:15 +10:00
|
|
|
} => {
|
2023-05-29 04:02:59 +10:00
|
|
|
use Key::{ArrowLeft, ArrowRight};
|
2023-01-27 15:18:58 +11:00
|
|
|
window.set_title(&format!("{key:?}"));
|
2023-05-29 04:02:59 +10:00
|
|
|
let state = !modifiers.shift_key();
|
2019-05-02 09:03:30 +10:00
|
|
|
match key {
|
2019-07-30 04:16:14 +10:00
|
|
|
// Cycle through video modes
|
2023-05-29 04:02:59 +10:00
|
|
|
Key::ArrowRight | Key::ArrowLeft => {
|
2019-07-30 04:16:14 +10:00
|
|
|
video_mode_id = match key {
|
2023-05-29 04:02:59 +10:00
|
|
|
ArrowLeft => video_mode_id.saturating_sub(1),
|
|
|
|
ArrowRight => (video_modes.len() - 1).min(video_mode_id + 1),
|
2019-07-30 04:16:14 +10:00
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
2022-01-01 13:00:11 +11:00
|
|
|
println!("Picking video mode: {}", video_modes[video_mode_id]);
|
2019-07-30 04:16:14 +10:00
|
|
|
}
|
2023-05-29 04:02:59 +10:00
|
|
|
// WARNING: Consider using `key_without_modifers()` if available on your platform.
|
|
|
|
// See the `key_binding` example
|
|
|
|
Key::Character(ch) => match ch.to_lowercase().as_str() {
|
|
|
|
"1" => window.set_window_level(WindowLevel::AlwaysOnTop),
|
|
|
|
"2" => window.set_window_level(WindowLevel::AlwaysOnBottom),
|
|
|
|
"3" => window.set_window_level(WindowLevel::Normal),
|
|
|
|
"c" => window.set_cursor_icon(match state {
|
|
|
|
true => CursorIcon::Progress,
|
|
|
|
false => CursorIcon::Default,
|
|
|
|
}),
|
|
|
|
"d" => window.set_decorations(!state),
|
|
|
|
"f" => window.set_fullscreen(match (state, modifiers.alt_key()) {
|
|
|
|
(true, false) => Some(Fullscreen::Borderless(None)),
|
|
|
|
(true, true) => Some(Fullscreen::Exclusive(
|
|
|
|
video_modes[video_mode_id].clone(),
|
|
|
|
)),
|
|
|
|
(false, _) => None,
|
|
|
|
}),
|
|
|
|
"l" if state => {
|
|
|
|
if let Err(err) = window.set_cursor_grab(CursorGrabMode::Locked)
|
|
|
|
{
|
|
|
|
println!("error: {err}");
|
|
|
|
}
|
2022-01-01 13:00:11 +11:00
|
|
|
}
|
2023-05-29 04:02:59 +10:00
|
|
|
"g" if state => {
|
|
|
|
if let Err(err) =
|
|
|
|
window.set_cursor_grab(CursorGrabMode::Confined)
|
|
|
|
{
|
|
|
|
println!("error: {err}");
|
|
|
|
}
|
2022-06-13 16:43:14 +10:00
|
|
|
}
|
2023-05-29 04:02:59 +10:00
|
|
|
"g" | "l" if !state => {
|
|
|
|
if let Err(err) = window.set_cursor_grab(CursorGrabMode::None) {
|
|
|
|
println!("error: {err}");
|
|
|
|
}
|
2022-06-13 16:43:14 +10:00
|
|
|
}
|
2023-05-29 04:02:59 +10:00
|
|
|
"h" => window.set_cursor_visible(!state),
|
|
|
|
"i" => {
|
|
|
|
println!("Info:");
|
|
|
|
println!("-> outer_position : {:?}", window.outer_position());
|
|
|
|
println!("-> inner_position : {:?}", window.inner_position());
|
|
|
|
println!("-> outer_size : {:?}", window.outer_size());
|
|
|
|
println!("-> inner_size : {:?}", window.inner_size());
|
|
|
|
println!("-> fullscreen : {:?}", window.fullscreen());
|
2022-06-13 16:43:14 +10:00
|
|
|
}
|
2023-05-29 04:02:59 +10:00
|
|
|
"l" => window.set_min_inner_size(match state {
|
|
|
|
true => Some(WINDOW_SIZE),
|
|
|
|
false => None,
|
|
|
|
}),
|
|
|
|
"m" => window.set_maximized(state),
|
|
|
|
"p" => window.set_outer_position({
|
|
|
|
let mut position = window.outer_position().unwrap();
|
|
|
|
let sign = if state { 1 } else { -1 };
|
|
|
|
position.x += 10 * sign;
|
|
|
|
position.y += 10 * sign;
|
|
|
|
position
|
|
|
|
}),
|
|
|
|
"q" => window.request_redraw(),
|
|
|
|
"r" => window.set_resizable(state),
|
2023-07-10 14:02:26 +10:00
|
|
|
"s" => {
|
|
|
|
let _ = window.request_inner_size(match state {
|
|
|
|
true => PhysicalSize::new(
|
|
|
|
WINDOW_SIZE.width + 100,
|
|
|
|
WINDOW_SIZE.height + 100,
|
|
|
|
),
|
|
|
|
false => WINDOW_SIZE,
|
|
|
|
});
|
|
|
|
}
|
2023-05-29 04:02:59 +10:00
|
|
|
"w" => {
|
|
|
|
if let Size::Physical(size) = WINDOW_SIZE.into() {
|
|
|
|
window
|
|
|
|
.set_cursor_position(Position::Physical(
|
|
|
|
PhysicalPosition::new(
|
|
|
|
size.width as i32 / 2,
|
|
|
|
size.height as i32 / 2,
|
|
|
|
),
|
|
|
|
))
|
|
|
|
.unwrap()
|
|
|
|
}
|
2020-01-04 17:32:34 +11:00
|
|
|
}
|
2023-05-29 04:02:59 +10:00
|
|
|
"z" => {
|
|
|
|
window.set_visible(false);
|
|
|
|
thread::sleep(Duration::from_secs(1));
|
|
|
|
window.set_visible(true);
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
},
|
2019-05-02 09:03:30 +10:00
|
|
|
_ => (),
|
|
|
|
}
|
2019-06-25 02:14:55 +10:00
|
|
|
}
|
2019-05-02 09:03:30 +10:00
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
event_loop.run(move |event, _event_loop, control_flow| {
|
2022-04-10 11:32:02 +10:00
|
|
|
match !window_senders.is_empty() {
|
|
|
|
true => control_flow.set_wait(),
|
|
|
|
false => control_flow.set_exit(),
|
2019-05-02 09:03:30 +10:00
|
|
|
};
|
|
|
|
match event {
|
2019-06-25 02:14:55 +10:00
|
|
|
Event::WindowEvent { event, window_id } => match event {
|
|
|
|
WindowEvent::CloseRequested
|
|
|
|
| WindowEvent::Destroyed
|
|
|
|
| WindowEvent::KeyboardInput {
|
2023-05-29 04:02:59 +10:00
|
|
|
event:
|
|
|
|
KeyEvent {
|
2019-07-30 04:16:14 +10:00
|
|
|
state: ElementState::Released,
|
2023-05-29 04:02:59 +10:00
|
|
|
logical_key: Key::Escape,
|
2019-06-25 02:14:55 +10:00
|
|
|
..
|
|
|
|
},
|
|
|
|
..
|
|
|
|
} => {
|
|
|
|
window_senders.remove(&window_id);
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
if let Some(tx) = window_senders.get(&window_id) {
|
2019-06-20 06:49:43 +10:00
|
|
|
if let Some(event) = event.to_static() {
|
|
|
|
tx.send(event).unwrap();
|
|
|
|
}
|
2019-06-25 02:14:55 +10:00
|
|
|
}
|
2019-05-02 09:03:30 +10:00
|
|
|
}
|
2019-06-22 01:33:15 +10:00
|
|
|
},
|
2022-01-01 13:00:11 +11:00
|
|
|
_ => {}
|
2019-05-02 09:03:30 +10:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2019-07-11 08:54:54 +10:00
|
|
|
|
2022-12-25 18:57:27 +11:00
|
|
|
#[cfg(wasm_platform)]
|
2019-07-11 08:54:54 +10:00
|
|
|
fn main() {
|
|
|
|
panic!("Example not supported on Wasm");
|
|
|
|
}
|