2021-09-28 15:33:28 +00:00
//! [`egui`] bindings for [`winit`](https://github.com/rust-windowing/winit).
//!
//! The library translates winit events to egui, handled copy/paste,
//! updates the cursor, open links clicked in egui, etc.
#![ allow(clippy::manual_range_contains) ]
2022-03-28 11:23:07 +00:00
pub use egui ;
2021-09-28 15:33:28 +00:00
pub use winit ;
pub mod clipboard ;
pub mod screen_reader ;
2021-09-30 17:18:51 +00:00
mod window_settings ;
pub use window_settings ::WindowSettings ;
2021-09-28 15:33:28 +00:00
pub fn native_pixels_per_point ( window : & winit ::window ::Window ) -> f32 {
window . scale_factor ( ) as f32
}
pub fn screen_size_in_pixels ( window : & winit ::window ::Window ) -> egui ::Vec2 {
let size = window . inner_size ( ) ;
egui ::vec2 ( size . width as f32 , size . height as f32 )
}
/// Handles the integration between egui and winit.
pub struct State {
2022-01-03 21:13:53 +00:00
start_time : instant ::Instant ,
2021-09-28 15:33:28 +00:00
egui_input : egui ::RawInput ,
pointer_pos_in_points : Option < egui ::Pos2 > ,
any_pointer_button_down : bool ,
current_cursor_icon : egui ::CursorIcon ,
/// What egui uses.
current_pixels_per_point : f32 ,
clipboard : clipboard ::Clipboard ,
screen_reader : screen_reader ::ScreenReader ,
/// If `true`, mouse inputs will be treated as touches.
/// Useful for debugging touch support in egui.
2021-10-17 18:30:22 +00:00
///
/// Creates duplicate touches, if real touch inputs are coming.
2021-09-28 15:33:28 +00:00
simulate_touch_screen : bool ,
2021-10-17 18:30:22 +00:00
/// Is Some(…) when a touch is being translated to a pointer.
///
/// Only one touch will be interpreted as pointer at any time.
pointer_touch_id : Option < u64 > ,
2021-09-28 15:33:28 +00:00
}
impl State {
2022-01-24 13:32:36 +00:00
/// Initialize with:
/// * `max_texture_side`: e.g. `GL_MAX_TEXTURE_SIZE`
/// * the native `pixels_per_point` (dpi scaling).
pub fn new ( max_texture_side : usize , window : & winit ::window ::Window ) -> Self {
Self ::from_pixels_per_point ( max_texture_side , native_pixels_per_point ( window ) )
2021-09-28 15:33:28 +00:00
}
2022-01-24 13:32:36 +00:00
/// Initialize with:
/// * `max_texture_side`: e.g. `GL_MAX_TEXTURE_SIZE`
/// * the given `pixels_per_point` (dpi scaling).
pub fn from_pixels_per_point ( max_texture_side : usize , pixels_per_point : f32 ) -> Self {
2021-09-28 15:33:28 +00:00
Self {
2022-01-03 21:13:53 +00:00
start_time : instant ::Instant ::now ( ) ,
2021-09-28 15:33:28 +00:00
egui_input : egui ::RawInput {
pixels_per_point : Some ( pixels_per_point ) ,
2022-02-22 12:21:28 +00:00
max_texture_side : Some ( max_texture_side ) ,
2021-09-28 15:33:28 +00:00
.. Default ::default ( )
} ,
pointer_pos_in_points : None ,
any_pointer_button_down : false ,
current_cursor_icon : egui ::CursorIcon ::Default ,
current_pixels_per_point : pixels_per_point ,
clipboard : Default ::default ( ) ,
screen_reader : screen_reader ::ScreenReader ::default ( ) ,
simulate_touch_screen : false ,
2021-10-17 18:30:22 +00:00
pointer_touch_id : None ,
2021-09-28 15:33:28 +00:00
}
}
/// The number of physical pixels per logical point,
/// as configured on the current egui context (see [`egui::Context::pixels_per_point`]).
#[ inline ]
pub fn pixels_per_point ( & self ) -> f32 {
self . current_pixels_per_point
}
/// The current input state.
/// This is changed by [`Self::on_event`] and cleared by [`Self::take_egui_input`].
#[ inline ]
pub fn egui_input ( & self ) -> & egui ::RawInput {
& self . egui_input
}
/// Prepare for a new frame by extracting the accumulated input,
/// as well as setting [the time](egui::RawInput::time) and [screen rectangle](egui::RawInput::screen_rect).
2021-11-03 12:45:51 +00:00
pub fn take_egui_input ( & mut self , window : & winit ::window ::Window ) -> egui ::RawInput {
2021-09-28 15:33:28 +00:00
let pixels_per_point = self . pixels_per_point ( ) ;
self . egui_input . time = Some ( self . start_time . elapsed ( ) . as_secs_f64 ( ) ) ;
// On Windows, a minimized window will have 0 width and height.
// See: https://github.com/rust-windowing/winit/issues/208
// This solves an issue where egui window positions would be changed when minimizing on Windows.
2021-11-03 12:45:51 +00:00
let screen_size_in_pixels = screen_size_in_pixels ( window ) ;
2021-09-28 15:33:28 +00:00
let screen_size_in_points = screen_size_in_pixels / pixels_per_point ;
self . egui_input . screen_rect =
if screen_size_in_points . x > 0.0 & & screen_size_in_points . y > 0.0 {
Some ( egui ::Rect ::from_min_size (
egui ::Pos2 ::ZERO ,
screen_size_in_points ,
) )
} else {
None
} ;
self . egui_input . take ( )
}
/// Call this when there is a new event.
///
/// The result can be found in [`Self::egui_input`] and be extracted with [`Self::take_egui_input`].
///
/// Returns `true` if egui wants exclusive use of this event
/// (e.g. a mouse click on an egui window, or entering text into a text field).
/// For instance, if you use egui for a game, you want to first call this
/// and only when this returns `false` pass on the events to your game.
///
/// Note that egui uses `tab` to move focus between elements, so this will always return `true` for tabs.
pub fn on_event (
& mut self ,
egui_ctx : & egui ::Context ,
event : & winit ::event ::WindowEvent < '_ > ,
) -> bool {
use winit ::event ::WindowEvent ;
match event {
WindowEvent ::ScaleFactorChanged { scale_factor , .. } = > {
let pixels_per_point = * scale_factor as f32 ;
self . egui_input . pixels_per_point = Some ( pixels_per_point ) ;
self . current_pixels_per_point = pixels_per_point ;
false
}
WindowEvent ::MouseInput { state , button , .. } = > {
self . on_mouse_button_input ( * state , * button ) ;
egui_ctx . wants_pointer_input ( )
}
WindowEvent ::MouseWheel { delta , .. } = > {
self . on_mouse_wheel ( * delta ) ;
egui_ctx . wants_pointer_input ( )
}
WindowEvent ::CursorMoved { position , .. } = > {
self . on_cursor_moved ( * position ) ;
egui_ctx . is_using_pointer ( )
}
WindowEvent ::CursorLeft { .. } = > {
self . pointer_pos_in_points = None ;
self . egui_input . events . push ( egui ::Event ::PointerGone ) ;
false
}
// WindowEvent::TouchpadPressure {device_id, pressure, stage, .. } => {} // TODO
WindowEvent ::Touch ( touch ) = > {
self . on_touch ( touch ) ;
match touch . phase {
winit ::event ::TouchPhase ::Started
| winit ::event ::TouchPhase ::Ended
| winit ::event ::TouchPhase ::Cancelled = > egui_ctx . wants_pointer_input ( ) ,
winit ::event ::TouchPhase ::Moved = > egui_ctx . is_using_pointer ( ) ,
}
}
WindowEvent ::ReceivedCharacter ( ch ) = > {
2021-10-13 06:55:00 +00:00
// On Mac we get here when the user presses Cmd-C (copy), ctrl-W, etc.
// We need to ignore these characters that are side-effects of commands.
let is_mac_cmd = cfg! ( target_os = " macos " )
& & ( self . egui_input . modifiers . ctrl | | self . egui_input . modifiers . mac_cmd ) ;
if is_printable_char ( * ch ) & & ! is_mac_cmd {
2021-09-28 15:33:28 +00:00
self . egui_input
. events
. push ( egui ::Event ::Text ( ch . to_string ( ) ) ) ;
egui_ctx . wants_keyboard_input ( )
} else {
false
}
}
WindowEvent ::KeyboardInput { input , .. } = > {
self . on_keyboard_input ( input ) ;
egui_ctx . wants_keyboard_input ( )
| | input . virtual_keycode = = Some ( winit ::event ::VirtualKeyCode ::Tab )
}
WindowEvent ::Focused ( _ ) = > {
// We will not be given a KeyboardInput event when the modifiers are released while
// the window does not have focus. Unset all modifier state to be safe.
self . egui_input . modifiers = egui ::Modifiers ::default ( ) ;
false
}
WindowEvent ::HoveredFile ( path ) = > {
self . egui_input . hovered_files . push ( egui ::HoveredFile {
path : Some ( path . clone ( ) ) ,
.. Default ::default ( )
} ) ;
false
}
WindowEvent ::HoveredFileCancelled = > {
self . egui_input . hovered_files . clear ( ) ;
false
}
WindowEvent ::DroppedFile ( path ) = > {
self . egui_input . hovered_files . clear ( ) ;
self . egui_input . dropped_files . push ( egui ::DroppedFile {
path : Some ( path . clone ( ) ) ,
.. Default ::default ( )
} ) ;
false
}
2021-11-01 20:34:06 +00:00
WindowEvent ::ModifiersChanged ( state ) = > {
self . egui_input . modifiers . alt = state . alt ( ) ;
self . egui_input . modifiers . ctrl = state . ctrl ( ) ;
self . egui_input . modifiers . shift = state . shift ( ) ;
self . egui_input . modifiers . mac_cmd = cfg! ( target_os = " macos " ) & & state . logo ( ) ;
self . egui_input . modifiers . command = if cfg! ( target_os = " macos " ) {
state . logo ( )
} else {
state . ctrl ( )
} ;
false
}
2021-09-28 15:33:28 +00:00
_ = > {
// dbg!(event);
false
}
}
}
fn on_mouse_button_input (
& mut self ,
state : winit ::event ::ElementState ,
button : winit ::event ::MouseButton ,
) {
if let Some ( pos ) = self . pointer_pos_in_points {
if let Some ( button ) = translate_mouse_button ( button ) {
let pressed = state = = winit ::event ::ElementState ::Pressed ;
self . egui_input . events . push ( egui ::Event ::PointerButton {
pos ,
button ,
pressed ,
modifiers : self . egui_input . modifiers ,
} ) ;
if self . simulate_touch_screen {
if pressed {
self . any_pointer_button_down = true ;
self . egui_input . events . push ( egui ::Event ::Touch {
device_id : egui ::TouchDeviceId ( 0 ) ,
id : egui ::TouchId ( 0 ) ,
phase : egui ::TouchPhase ::Start ,
pos ,
force : 0.0 ,
} ) ;
} else {
self . any_pointer_button_down = false ;
self . egui_input . events . push ( egui ::Event ::PointerGone ) ;
self . egui_input . events . push ( egui ::Event ::Touch {
device_id : egui ::TouchDeviceId ( 0 ) ,
id : egui ::TouchId ( 0 ) ,
phase : egui ::TouchPhase ::End ,
pos ,
force : 0.0 ,
} ) ;
} ;
}
}
}
}
fn on_cursor_moved ( & mut self , pos_in_pixels : winit ::dpi ::PhysicalPosition < f64 > ) {
let pos_in_points = egui ::pos2 (
pos_in_pixels . x as f32 / self . pixels_per_point ( ) ,
pos_in_pixels . y as f32 / self . pixels_per_point ( ) ,
) ;
self . pointer_pos_in_points = Some ( pos_in_points ) ;
if self . simulate_touch_screen {
if self . any_pointer_button_down {
self . egui_input
. events
. push ( egui ::Event ::PointerMoved ( pos_in_points ) ) ;
self . egui_input . events . push ( egui ::Event ::Touch {
device_id : egui ::TouchDeviceId ( 0 ) ,
id : egui ::TouchId ( 0 ) ,
phase : egui ::TouchPhase ::Move ,
pos : pos_in_points ,
force : 0.0 ,
} ) ;
}
} else {
self . egui_input
. events
. push ( egui ::Event ::PointerMoved ( pos_in_points ) ) ;
}
}
fn on_touch ( & mut self , touch : & winit ::event ::Touch ) {
2021-10-17 18:30:22 +00:00
// Emit touch event
2021-09-28 15:33:28 +00:00
self . egui_input . events . push ( egui ::Event ::Touch {
device_id : egui ::TouchDeviceId ( egui ::epaint ::util ::hash ( touch . device_id ) ) ,
id : egui ::TouchId ::from ( touch . id ) ,
phase : match touch . phase {
winit ::event ::TouchPhase ::Started = > egui ::TouchPhase ::Start ,
winit ::event ::TouchPhase ::Moved = > egui ::TouchPhase ::Move ,
winit ::event ::TouchPhase ::Ended = > egui ::TouchPhase ::End ,
winit ::event ::TouchPhase ::Cancelled = > egui ::TouchPhase ::Cancel ,
} ,
pos : egui ::pos2 (
touch . location . x as f32 / self . pixels_per_point ( ) ,
touch . location . y as f32 / self . pixels_per_point ( ) ,
) ,
force : match touch . force {
Some ( winit ::event ::Force ::Normalized ( force ) ) = > force as f32 ,
Some ( winit ::event ::Force ::Calibrated {
force ,
max_possible_force ,
..
} ) = > ( force / max_possible_force ) as f32 ,
None = > 0_ f32 ,
} ,
} ) ;
2021-10-17 18:30:22 +00:00
// If we're not yet tanslating a touch or we're translating this very
// touch …
if self . pointer_touch_id . is_none ( ) | | self . pointer_touch_id . unwrap ( ) = = touch . id {
// … emit PointerButton resp. PointerMoved events to emulate mouse
match touch . phase {
winit ::event ::TouchPhase ::Started = > {
self . pointer_touch_id = Some ( touch . id ) ;
// First move the pointer to the right location
self . on_cursor_moved ( touch . location ) ;
self . on_mouse_button_input (
winit ::event ::ElementState ::Pressed ,
winit ::event ::MouseButton ::Left ,
) ;
}
winit ::event ::TouchPhase ::Moved = > {
self . on_cursor_moved ( touch . location ) ;
}
winit ::event ::TouchPhase ::Ended = > {
self . pointer_touch_id = None ;
self . on_mouse_button_input (
winit ::event ::ElementState ::Released ,
winit ::event ::MouseButton ::Left ,
) ;
// The pointer should vanish completely to not get any
// hover effects
self . pointer_pos_in_points = None ;
self . egui_input . events . push ( egui ::Event ::PointerGone ) ;
}
winit ::event ::TouchPhase ::Cancelled = > {
self . pointer_touch_id = None ;
self . pointer_pos_in_points = None ;
self . egui_input . events . push ( egui ::Event ::PointerGone ) ;
}
}
}
2021-09-28 15:33:28 +00:00
}
fn on_mouse_wheel ( & mut self , delta : winit ::event ::MouseScrollDelta ) {
let mut delta = match delta {
winit ::event ::MouseScrollDelta ::LineDelta ( x , y ) = > {
let points_per_scroll_line = 50.0 ; // Scroll speed decided by consensus: https://github.com/emilk/egui/issues/461
egui ::vec2 ( x , y ) * points_per_scroll_line
}
winit ::event ::MouseScrollDelta ::PixelDelta ( delta ) = > {
egui ::vec2 ( delta . x as f32 , delta . y as f32 ) / self . pixels_per_point ( )
}
} ;
2022-01-16 08:49:22 +00:00
delta . x * = - 1.0 ; // Winit has inverted hscroll. Remove this line when we update winit after https://github.com/rust-windowing/winit/pull/2105 is merged and released
2021-09-28 15:33:28 +00:00
if self . egui_input . modifiers . ctrl | | self . egui_input . modifiers . command {
// Treat as zoom instead:
2021-11-03 21:57:13 +00:00
let factor = ( delta . y / 200.0 ) . exp ( ) ;
self . egui_input . events . push ( egui ::Event ::Zoom ( factor ) ) ;
2022-01-21 09:48:44 +00:00
} else if self . egui_input . modifiers . shift {
// Treat as horizontal scrolling.
// Note: one Mac we already get horizontal scroll events when shift is down.
self . egui_input
. events
. push ( egui ::Event ::Scroll ( egui ::vec2 ( delta . x + delta . y , 0.0 ) ) ) ;
2021-09-28 15:33:28 +00:00
} else {
2021-11-03 21:57:13 +00:00
self . egui_input . events . push ( egui ::Event ::Scroll ( delta ) ) ;
2021-09-28 15:33:28 +00:00
}
}
fn on_keyboard_input ( & mut self , input : & winit ::event ::KeyboardInput ) {
if let Some ( keycode ) = input . virtual_keycode {
let pressed = input . state = = winit ::event ::ElementState ::Pressed ;
if pressed {
// VirtualKeyCode::Paste etc in winit are broken/untrustworthy,
// so we detect these things manually:
if is_cut_command ( self . egui_input . modifiers , keycode ) {
self . egui_input . events . push ( egui ::Event ::Cut ) ;
} else if is_copy_command ( self . egui_input . modifiers , keycode ) {
self . egui_input . events . push ( egui ::Event ::Copy ) ;
} else if is_paste_command ( self . egui_input . modifiers , keycode ) {
if let Some ( contents ) = self . clipboard . get ( ) {
2022-04-12 09:39:35 +00:00
let contents = contents . replace ( " \r \n " , " \n " ) ;
if ! contents . is_empty ( ) {
self . egui_input . events . push ( egui ::Event ::Paste ( contents ) ) ;
}
2021-09-28 15:33:28 +00:00
}
}
}
if let Some ( key ) = translate_virtual_key_code ( keycode ) {
self . egui_input . events . push ( egui ::Event ::Key {
key ,
pressed ,
modifiers : self . egui_input . modifiers ,
} ) ;
}
}
}
/// Call with the output given by `egui`.
///
/// This will, if needed:
/// * update the cursor
/// * copy text to the clipboard
/// * open any clicked urls
/// * update the IME
/// *
2022-02-22 16:13:53 +00:00
pub fn handle_platform_output (
2021-09-28 15:33:28 +00:00
& mut self ,
window : & winit ::window ::Window ,
egui_ctx : & egui ::Context ,
2022-02-22 16:13:53 +00:00
platform_output : egui ::PlatformOutput ,
) {
2022-01-29 16:53:41 +00:00
if egui_ctx . options ( ) . screen_reader {
2022-02-22 16:13:53 +00:00
self . screen_reader
. speak ( & platform_output . events_description ( ) ) ;
2021-09-28 15:33:28 +00:00
}
2022-02-22 16:13:53 +00:00
let egui ::PlatformOutput {
2022-01-15 12:59:52 +00:00
cursor_icon ,
open_url ,
copied_text ,
events : _ , // handled above
2022-04-30 08:44:35 +00:00
mutable_text_under_cursor : _ , // only used in eframe web
2022-01-15 12:59:52 +00:00
text_cursor_pos ,
2022-02-22 16:13:53 +00:00
} = platform_output ;
2021-09-28 15:33:28 +00:00
2022-01-15 12:59:52 +00:00
self . current_pixels_per_point = egui_ctx . pixels_per_point ( ) ; // someone can have changed it to scale the UI
self . set_cursor_icon ( window , cursor_icon ) ;
if let Some ( open_url ) = open_url {
open_url_in_browser ( & open_url . url ) ;
2021-09-28 15:33:28 +00:00
}
2022-01-15 12:59:52 +00:00
if ! copied_text . is_empty ( ) {
self . clipboard . set ( copied_text ) ;
2021-09-28 15:33:28 +00:00
}
2022-01-15 12:59:52 +00:00
if let Some ( egui ::Pos2 { x , y } ) = text_cursor_pos {
2021-10-20 14:43:40 +00:00
window . set_ime_position ( winit ::dpi ::LogicalPosition { x , y } ) ;
2021-09-28 15:33:28 +00:00
}
}
fn set_cursor_icon ( & mut self , window : & winit ::window ::Window , cursor_icon : egui ::CursorIcon ) {
// prevent flickering near frame boundary when Windows OS tries to control cursor icon for window resizing
if self . current_cursor_icon = = cursor_icon {
return ;
}
self . current_cursor_icon = cursor_icon ;
if let Some ( cursor_icon ) = translate_cursor ( cursor_icon ) {
window . set_cursor_visible ( true ) ;
let is_pointer_in_window = self . pointer_pos_in_points . is_some ( ) ;
if is_pointer_in_window {
window . set_cursor_icon ( cursor_icon ) ;
}
} else {
window . set_cursor_visible ( false ) ;
}
}
}
2022-01-15 12:59:52 +00:00
fn open_url_in_browser ( _url : & str ) {
2021-09-28 15:33:28 +00:00
#[ cfg(feature = " webbrowser " ) ]
if let Err ( err ) = webbrowser ::open ( _url ) {
2022-02-01 11:27:39 +00:00
tracing ::warn! ( " Failed to open url: {} " , err ) ;
2021-09-28 15:33:28 +00:00
}
#[ cfg(not(feature = " webbrowser " )) ]
{
2022-02-01 11:27:39 +00:00
tracing ::warn! ( " Cannot open url - feature \" links \" not enabled. " ) ;
2021-09-28 15:33:28 +00:00
}
}
2021-10-13 09:52:34 +00:00
/// Winit sends special keys (backspace, delete, F1, …) as characters.
2021-09-28 15:33:28 +00:00
/// Ignore those.
/// We also ignore '\r', '\n', '\t'.
/// Newlines are handled by the `Key::Enter` event.
fn is_printable_char ( chr : char ) -> bool {
let is_in_private_use_area = '\u{e000}' < = chr & & chr < = '\u{f8ff}'
| | '\u{f0000}' < = chr & & chr < = '\u{ffffd}'
| | '\u{100000}' < = chr & & chr < = '\u{10fffd}' ;
! is_in_private_use_area & & ! chr . is_ascii_control ( )
}
fn is_cut_command ( modifiers : egui ::Modifiers , keycode : winit ::event ::VirtualKeyCode ) -> bool {
( modifiers . command & & keycode = = winit ::event ::VirtualKeyCode ::X )
| | ( cfg! ( target_os = " windows " )
& & modifiers . shift
& & keycode = = winit ::event ::VirtualKeyCode ::Delete )
}
fn is_copy_command ( modifiers : egui ::Modifiers , keycode : winit ::event ::VirtualKeyCode ) -> bool {
( modifiers . command & & keycode = = winit ::event ::VirtualKeyCode ::C )
| | ( cfg! ( target_os = " windows " )
& & modifiers . ctrl
& & keycode = = winit ::event ::VirtualKeyCode ::Insert )
}
fn is_paste_command ( modifiers : egui ::Modifiers , keycode : winit ::event ::VirtualKeyCode ) -> bool {
( modifiers . command & & keycode = = winit ::event ::VirtualKeyCode ::V )
| | ( cfg! ( target_os = " windows " )
& & modifiers . shift
& & keycode = = winit ::event ::VirtualKeyCode ::Insert )
}
fn translate_mouse_button ( button : winit ::event ::MouseButton ) -> Option < egui ::PointerButton > {
match button {
winit ::event ::MouseButton ::Left = > Some ( egui ::PointerButton ::Primary ) ,
winit ::event ::MouseButton ::Right = > Some ( egui ::PointerButton ::Secondary ) ,
winit ::event ::MouseButton ::Middle = > Some ( egui ::PointerButton ::Middle ) ,
winit ::event ::MouseButton ::Other ( _ ) = > None ,
}
}
fn translate_virtual_key_code ( key : winit ::event ::VirtualKeyCode ) -> Option < egui ::Key > {
use egui ::Key ;
use winit ::event ::VirtualKeyCode ;
Some ( match key {
VirtualKeyCode ::Down = > Key ::ArrowDown ,
VirtualKeyCode ::Left = > Key ::ArrowLeft ,
VirtualKeyCode ::Right = > Key ::ArrowRight ,
VirtualKeyCode ::Up = > Key ::ArrowUp ,
VirtualKeyCode ::Escape = > Key ::Escape ,
VirtualKeyCode ::Tab = > Key ::Tab ,
VirtualKeyCode ::Back = > Key ::Backspace ,
VirtualKeyCode ::Return = > Key ::Enter ,
VirtualKeyCode ::Space = > Key ::Space ,
VirtualKeyCode ::Insert = > Key ::Insert ,
VirtualKeyCode ::Delete = > Key ::Delete ,
VirtualKeyCode ::Home = > Key ::Home ,
VirtualKeyCode ::End = > Key ::End ,
VirtualKeyCode ::PageUp = > Key ::PageUp ,
VirtualKeyCode ::PageDown = > Key ::PageDown ,
VirtualKeyCode ::Key0 | VirtualKeyCode ::Numpad0 = > Key ::Num0 ,
VirtualKeyCode ::Key1 | VirtualKeyCode ::Numpad1 = > Key ::Num1 ,
VirtualKeyCode ::Key2 | VirtualKeyCode ::Numpad2 = > Key ::Num2 ,
VirtualKeyCode ::Key3 | VirtualKeyCode ::Numpad3 = > Key ::Num3 ,
VirtualKeyCode ::Key4 | VirtualKeyCode ::Numpad4 = > Key ::Num4 ,
VirtualKeyCode ::Key5 | VirtualKeyCode ::Numpad5 = > Key ::Num5 ,
VirtualKeyCode ::Key6 | VirtualKeyCode ::Numpad6 = > Key ::Num6 ,
VirtualKeyCode ::Key7 | VirtualKeyCode ::Numpad7 = > Key ::Num7 ,
VirtualKeyCode ::Key8 | VirtualKeyCode ::Numpad8 = > Key ::Num8 ,
VirtualKeyCode ::Key9 | VirtualKeyCode ::Numpad9 = > Key ::Num9 ,
VirtualKeyCode ::A = > Key ::A ,
VirtualKeyCode ::B = > Key ::B ,
VirtualKeyCode ::C = > Key ::C ,
VirtualKeyCode ::D = > Key ::D ,
VirtualKeyCode ::E = > Key ::E ,
VirtualKeyCode ::F = > Key ::F ,
VirtualKeyCode ::G = > Key ::G ,
VirtualKeyCode ::H = > Key ::H ,
VirtualKeyCode ::I = > Key ::I ,
VirtualKeyCode ::J = > Key ::J ,
VirtualKeyCode ::K = > Key ::K ,
VirtualKeyCode ::L = > Key ::L ,
VirtualKeyCode ::M = > Key ::M ,
VirtualKeyCode ::N = > Key ::N ,
VirtualKeyCode ::O = > Key ::O ,
VirtualKeyCode ::P = > Key ::P ,
VirtualKeyCode ::Q = > Key ::Q ,
VirtualKeyCode ::R = > Key ::R ,
VirtualKeyCode ::S = > Key ::S ,
VirtualKeyCode ::T = > Key ::T ,
VirtualKeyCode ::U = > Key ::U ,
VirtualKeyCode ::V = > Key ::V ,
VirtualKeyCode ::W = > Key ::W ,
VirtualKeyCode ::X = > Key ::X ,
VirtualKeyCode ::Y = > Key ::Y ,
VirtualKeyCode ::Z = > Key ::Z ,
_ = > {
return None ;
}
} )
}
fn translate_cursor ( cursor_icon : egui ::CursorIcon ) -> Option < winit ::window ::CursorIcon > {
match cursor_icon {
egui ::CursorIcon ::None = > None ,
egui ::CursorIcon ::Alias = > Some ( winit ::window ::CursorIcon ::Alias ) ,
egui ::CursorIcon ::AllScroll = > Some ( winit ::window ::CursorIcon ::AllScroll ) ,
egui ::CursorIcon ::Cell = > Some ( winit ::window ::CursorIcon ::Cell ) ,
egui ::CursorIcon ::ContextMenu = > Some ( winit ::window ::CursorIcon ::ContextMenu ) ,
egui ::CursorIcon ::Copy = > Some ( winit ::window ::CursorIcon ::Copy ) ,
egui ::CursorIcon ::Crosshair = > Some ( winit ::window ::CursorIcon ::Crosshair ) ,
egui ::CursorIcon ::Default = > Some ( winit ::window ::CursorIcon ::Default ) ,
egui ::CursorIcon ::Grab = > Some ( winit ::window ::CursorIcon ::Grab ) ,
egui ::CursorIcon ::Grabbing = > Some ( winit ::window ::CursorIcon ::Grabbing ) ,
egui ::CursorIcon ::Help = > Some ( winit ::window ::CursorIcon ::Help ) ,
egui ::CursorIcon ::Move = > Some ( winit ::window ::CursorIcon ::Move ) ,
egui ::CursorIcon ::NoDrop = > Some ( winit ::window ::CursorIcon ::NoDrop ) ,
egui ::CursorIcon ::NotAllowed = > Some ( winit ::window ::CursorIcon ::NotAllowed ) ,
egui ::CursorIcon ::PointingHand = > Some ( winit ::window ::CursorIcon ::Hand ) ,
egui ::CursorIcon ::Progress = > Some ( winit ::window ::CursorIcon ::Progress ) ,
2022-04-19 14:56:27 +00:00
2021-09-28 15:33:28 +00:00
egui ::CursorIcon ::ResizeHorizontal = > Some ( winit ::window ::CursorIcon ::EwResize ) ,
egui ::CursorIcon ::ResizeNeSw = > Some ( winit ::window ::CursorIcon ::NeswResize ) ,
egui ::CursorIcon ::ResizeNwSe = > Some ( winit ::window ::CursorIcon ::NwseResize ) ,
egui ::CursorIcon ::ResizeVertical = > Some ( winit ::window ::CursorIcon ::NsResize ) ,
2022-04-19 14:56:27 +00:00
egui ::CursorIcon ::ResizeEast = > Some ( winit ::window ::CursorIcon ::EResize ) ,
egui ::CursorIcon ::ResizeSouthEast = > Some ( winit ::window ::CursorIcon ::SeResize ) ,
egui ::CursorIcon ::ResizeSouth = > Some ( winit ::window ::CursorIcon ::SResize ) ,
egui ::CursorIcon ::ResizeSouthWest = > Some ( winit ::window ::CursorIcon ::SwResize ) ,
egui ::CursorIcon ::ResizeWest = > Some ( winit ::window ::CursorIcon ::WResize ) ,
egui ::CursorIcon ::ResizeNorthWest = > Some ( winit ::window ::CursorIcon ::NwResize ) ,
egui ::CursorIcon ::ResizeNorth = > Some ( winit ::window ::CursorIcon ::NResize ) ,
egui ::CursorIcon ::ResizeNorthEast = > Some ( winit ::window ::CursorIcon ::NeResize ) ,
egui ::CursorIcon ::ResizeColumn = > Some ( winit ::window ::CursorIcon ::ColResize ) ,
egui ::CursorIcon ::ResizeRow = > Some ( winit ::window ::CursorIcon ::RowResize ) ,
2021-09-28 15:33:28 +00:00
egui ::CursorIcon ::Text = > Some ( winit ::window ::CursorIcon ::Text ) ,
egui ::CursorIcon ::VerticalText = > Some ( winit ::window ::CursorIcon ::VerticalText ) ,
egui ::CursorIcon ::Wait = > Some ( winit ::window ::CursorIcon ::Wait ) ,
egui ::CursorIcon ::ZoomIn = > Some ( winit ::window ::CursorIcon ::ZoomIn ) ,
egui ::CursorIcon ::ZoomOut = > Some ( winit ::window ::CursorIcon ::ZoomOut ) ,
}
}
2022-04-13 09:06:13 +00:00
// ---------------------------------------------------------------------------
/// Profiling macro for feature "puffin"
2022-04-27 08:15:32 +00:00
#[ allow(unused_macros) ]
2022-04-13 09:06:13 +00:00
macro_rules ! profile_function {
( $( $arg : tt ) * ) = > {
#[ cfg(feature = " puffin " ) ]
puffin ::profile_function! ( $( $arg ) * ) ;
} ;
}
2022-04-27 08:15:32 +00:00
#[ allow(unused_imports) ]
2022-04-25 20:01:32 +00:00
pub ( crate ) use profile_function ;
2022-04-13 09:06:13 +00:00
/// Profiling macro for feature "puffin"
2022-04-27 08:15:32 +00:00
#[ allow(unused_macros) ]
2022-04-13 09:06:13 +00:00
macro_rules ! profile_scope {
( $( $arg : tt ) * ) = > {
#[ cfg(feature = " puffin " ) ]
puffin ::profile_scope! ( $( $arg ) * ) ;
} ;
}
2022-04-27 08:15:32 +00:00
#[ allow(unused_imports) ]
2022-04-25 20:01:32 +00:00
pub ( crate ) use profile_scope ;