2023-01-12 04:07:09 +11:00
|
|
|
//! Demonstrates capability to create in-app draggable regions for client-side decoration support.
|
|
|
|
|
|
|
|
use simple_logger::SimpleLogger;
|
|
|
|
use winit::{
|
2023-05-29 04:02:59 +10:00
|
|
|
event::{ElementState, Event, KeyEvent, MouseButton, StartCause, WindowEvent},
|
2023-01-12 04:07:09 +11:00
|
|
|
event_loop::{ControlFlow, EventLoop},
|
2023-05-29 04:02:59 +10:00
|
|
|
keyboard::Key,
|
2023-01-12 04:07:09 +11:00
|
|
|
window::{CursorIcon, ResizeDirection, WindowBuilder},
|
|
|
|
};
|
|
|
|
|
|
|
|
const BORDER: f64 = 8.0;
|
|
|
|
|
2023-06-20 04:46:38 +10:00
|
|
|
#[path = "util/fill.rs"]
|
|
|
|
mod fill;
|
|
|
|
|
2023-01-12 04:07:09 +11:00
|
|
|
fn main() {
|
|
|
|
SimpleLogger::new().init().unwrap();
|
|
|
|
let event_loop = EventLoop::new();
|
|
|
|
|
|
|
|
let window = WindowBuilder::new()
|
|
|
|
.with_inner_size(winit::dpi::LogicalSize::new(600.0, 400.0))
|
|
|
|
.with_min_inner_size(winit::dpi::LogicalSize::new(400.0, 200.0))
|
|
|
|
.with_decorations(false)
|
|
|
|
.build(&event_loop)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let mut border = false;
|
|
|
|
let mut cursor_location = None;
|
|
|
|
|
|
|
|
event_loop.run(move |event, _, control_flow| match event {
|
|
|
|
Event::NewEvents(StartCause::Init) => {
|
|
|
|
eprintln!("Press 'B' to toggle borderless")
|
|
|
|
}
|
|
|
|
Event::WindowEvent { event, .. } => match event {
|
|
|
|
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
|
|
|
WindowEvent::CursorMoved { position, .. } => {
|
|
|
|
if !window.is_decorated() {
|
|
|
|
let new_location =
|
|
|
|
cursor_resize_direction(window.inner_size(), position, BORDER);
|
|
|
|
|
|
|
|
if new_location != cursor_location {
|
|
|
|
cursor_location = new_location;
|
|
|
|
window.set_cursor_icon(cursor_direction_icon(cursor_location))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
WindowEvent::MouseInput {
|
|
|
|
state: ElementState::Pressed,
|
|
|
|
button: MouseButton::Left,
|
|
|
|
..
|
|
|
|
} => {
|
|
|
|
if let Some(dir) = cursor_location {
|
|
|
|
let _res = window.drag_resize_window(dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
WindowEvent::KeyboardInput {
|
2023-05-29 04:02:59 +10:00
|
|
|
event:
|
|
|
|
KeyEvent {
|
2023-01-12 04:07:09 +11:00
|
|
|
state: ElementState::Released,
|
2023-05-29 04:02:59 +10:00
|
|
|
logical_key: Key::Character(c),
|
2023-01-12 04:07:09 +11:00
|
|
|
..
|
|
|
|
},
|
|
|
|
..
|
2023-05-29 04:02:59 +10:00
|
|
|
} if matches!(c.as_ref(), "B" | "b") => {
|
2023-01-12 04:07:09 +11:00
|
|
|
border = !border;
|
|
|
|
window.set_decorations(border);
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
},
|
2023-06-20 04:46:38 +10:00
|
|
|
Event::RedrawRequested(_) => {
|
|
|
|
fill::fill_window(&window);
|
|
|
|
}
|
2023-01-12 04:07:09 +11:00
|
|
|
_ => (),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cursor_direction_icon(resize_direction: Option<ResizeDirection>) -> CursorIcon {
|
|
|
|
match resize_direction {
|
|
|
|
Some(resize_direction) => match resize_direction {
|
|
|
|
ResizeDirection::East => CursorIcon::EResize,
|
|
|
|
ResizeDirection::North => CursorIcon::NResize,
|
|
|
|
ResizeDirection::NorthEast => CursorIcon::NeResize,
|
|
|
|
ResizeDirection::NorthWest => CursorIcon::NwResize,
|
|
|
|
ResizeDirection::South => CursorIcon::SResize,
|
|
|
|
ResizeDirection::SouthEast => CursorIcon::SeResize,
|
|
|
|
ResizeDirection::SouthWest => CursorIcon::SwResize,
|
|
|
|
ResizeDirection::West => CursorIcon::WResize,
|
|
|
|
},
|
|
|
|
None => CursorIcon::Default,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cursor_resize_direction(
|
|
|
|
win_size: winit::dpi::PhysicalSize<u32>,
|
|
|
|
position: winit::dpi::PhysicalPosition<f64>,
|
|
|
|
border_size: f64,
|
|
|
|
) -> Option<ResizeDirection> {
|
|
|
|
enum XDirection {
|
|
|
|
West,
|
|
|
|
East,
|
|
|
|
Default,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum YDirection {
|
|
|
|
North,
|
|
|
|
South,
|
|
|
|
Default,
|
|
|
|
}
|
|
|
|
|
|
|
|
let xdir = if position.x < border_size {
|
|
|
|
XDirection::West
|
|
|
|
} else if position.x > (win_size.width as f64 - border_size) {
|
|
|
|
XDirection::East
|
|
|
|
} else {
|
|
|
|
XDirection::Default
|
|
|
|
};
|
|
|
|
|
|
|
|
let ydir = if position.y < border_size {
|
|
|
|
YDirection::North
|
|
|
|
} else if position.y > (win_size.height as f64 - border_size) {
|
|
|
|
YDirection::South
|
|
|
|
} else {
|
|
|
|
YDirection::Default
|
|
|
|
};
|
|
|
|
|
|
|
|
Some(match xdir {
|
|
|
|
XDirection::West => match ydir {
|
|
|
|
YDirection::North => ResizeDirection::NorthWest,
|
|
|
|
YDirection::South => ResizeDirection::SouthWest,
|
|
|
|
YDirection::Default => ResizeDirection::West,
|
|
|
|
},
|
|
|
|
|
|
|
|
XDirection::East => match ydir {
|
|
|
|
YDirection::North => ResizeDirection::NorthEast,
|
|
|
|
YDirection::South => ResizeDirection::SouthEast,
|
|
|
|
YDirection::Default => ResizeDirection::East,
|
|
|
|
},
|
|
|
|
|
|
|
|
XDirection::Default => match ydir {
|
|
|
|
YDirection::North => ResizeDirection::North,
|
|
|
|
YDirection::South => ResizeDirection::South,
|
|
|
|
YDirection::Default => return None,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|