@ -24,9 +24,14 @@ pub use window_settings::WindowSettings;
use raw_window_handle ::HasRawDisplayHandle ;
pub fn native_pixels_per_point ( window : & Window ) -> f32 {
window . scale_factor ( ) as f32
}
#[ allow(unused_imports) ]
pub ( crate ) use profiling_scopes ::* ;
use winit ::{
dpi ::{ PhysicalPosition , PhysicalSize } ,
event_loop ::EventLoopWindowTarget ,
window ::{ CursorGrabMode , Window , WindowButtons , WindowLevel } ,
} ;
pub fn screen_size_in_pixels ( window : & Window ) -> egui ::Vec2 {
let size = window . inner_size ( ) ;
@ -111,7 +116,7 @@ impl State {
pointer_pos_in_points : None ,
any_pointer_button_down : false ,
current_cursor_icon : None ,
current_pixels_per_point : 1.0 ,
current_pixels_per_point : native_pixels_per_point . unwrap_or ( 1.0 ) ,
clipboard : clipboard ::Clipboard ::new ( display_target ) ,
@ -125,9 +130,13 @@ impl State {
allow_ime : false ,
} ;
if let Some ( native_pixels_per_point ) = native_pixels_per_point {
slf . set_pixels_per_point ( native_pixels_per_point ) ;
}
slf . egui_input
. viewports
. entry ( ViewportId ::ROOT )
. or_default ( )
. native_pixels_per_point = native_pixels_per_point ;
if let Some ( max_texture_side ) = max_texture_side {
slf . set_max_texture_side ( max_texture_side ) ;
}
@ -155,19 +164,6 @@ impl State {
self . egui_input . max_texture_side = Some ( max_texture_side ) ;
}
/// Call this when a new native Window is created for rendering to initialize the `pixels_per_point`
/// for that window.
///
/// In particular, on Android it is necessary to call this after each `Resumed` lifecycle
/// event, each time a new native window is created.
///
/// Once this has been initialized for a new window then this state will be maintained by handling
/// [`winit::event::WindowEvent::ScaleFactorChanged`] events.
pub fn set_pixels_per_point ( & mut self , pixels_per_point : f32 ) {
self . egui_input . pixels_per_point = Some ( pixels_per_point ) ;
self . current_pixels_per_point = pixels_per_point ;
}
/// The number of physical pixels per logical point,
/// as configured on the current egui context (see [`egui::Context::pixels_per_point`]).
#[ inline ]
@ -193,7 +189,7 @@ impl State {
///
/// Call before [`Self::update_viewport_info`]
pub fn update_viewport_info ( & self , info : & mut ViewportInfo , window : & Window ) {
update_viewport_info ( info , window , self . pixels_per_point ( ) ) ;
update_viewport_info ( info , window , self . current_ pixels_per_point) ;
}
/// Prepare for a new frame by extracting the accumulated input,
@ -206,8 +202,6 @@ impl State {
pub fn take_egui_input ( & mut self , window : & Window ) -> egui ::RawInput {
crate ::profile_function ! ( ) ;
let pixels_per_point = self . pixels_per_point ( ) ;
self . egui_input . time = Some ( self . start_time . elapsed ( ) . as_secs_f64 ( ) ) ;
// TODO remove this in winit 0.29
@ -220,7 +214,7 @@ impl State {
// See: https://github.com/rust-windowing/winit/issues/208
// This solves an issue where egui window positions would be changed when minimizing on Windows.
let screen_size_in_pixels = screen_size_in_pixels ( window ) ;
let screen_size_in_points = screen_size_in_pixels / pixels_per_point ;
let screen_size_in_points = screen_size_in_pixels / self . current_ pixels_per_point;
self . egui_input . screen_rect = ( screen_size_in_points . x > 0.0
& & screen_size_in_points . y > 0.0 )
@ -228,7 +222,13 @@ impl State {
// Tell egui which viewport is now active:
self . egui_input . viewport_id = self . viewport_id ;
self . egui_input . native_pixels_per_point = Some ( native_pixels_per_point ( window ) ) ;
self . egui_input
. viewports
. entry ( self . viewport_id )
. or_default ( )
. native_pixels_per_point = Some ( window . scale_factor ( ) as f32 ) ;
self . egui_input . take ( )
}
@ -245,9 +245,14 @@ impl State {
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 ;
let native_pixels_per_point = * scale_factor as f32 ;
self . egui_input
. viewports
. entry ( self . viewport_id )
. or_default ( )
. native_pixels_per_point = Some ( native_pixels_per_point ) ;
self . current_pixels_per_point = egui_ctx . zoom_factor ( ) * native_pixels_per_point ;
EventResponse {
repaint : true ,
consumed : false ,
@ -709,8 +714,7 @@ impl State {
accesskit_update ,
} = platform_output ;
self . current_pixels_per_point =
egui_ctx . input_for ( self . viewport_id , | i | i . pixels_per_point ) ; // someone can have changed it to scale the UI
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 ) ;
@ -829,15 +833,15 @@ fn update_viewport_info(viewport_info: &mut ViewportInfo, window: &Window, pixel
}
} ;
viewport_info . title = Some ( window . title ( ) ) ;
viewport_info . pixels_per_point = pixels_per_point ;
viewport_info . monitor_size = monitor_size ;
viewport_info . inner_rect = inner_rect ;
viewport_info . outer_rect = outer_rect ;
viewport_info . fullscreen = Some ( window . fullscreen ( ) . is_some ( ) ) ;
viewport_info . focused = Some ( window . has_focus ( ) ) ;
viewport_info . minimized = window . is_minimized ( ) . or ( viewport_info . minimized ) ;
viewport_info . fullscreen = Some ( window . fullscreen ( ) . is_some ( ) ) ;
viewport_info . inner_rect = inner_rect ;
viewport_info . maximized = Some ( window . is_maximized ( ) ) ;
viewport_info . minimized = window . is_minimized ( ) . or ( viewport_info . minimized ) ;
viewport_info . monitor_size = monitor_size ;
viewport_info . native_pixels_per_point = Some ( window . scale_factor ( ) as f32 ) ;
viewport_info . outer_rect = outer_rect ;
viewport_info . title = Some ( window . title ( ) ) ;
}
fn open_url_in_browser ( _url : & str ) {
@ -1039,17 +1043,42 @@ fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option<winit::window::Curs
// ---------------------------------------------------------------------------
pub fn process_viewport_commands (
egui_ctx : & egui ::Context ,
info : & mut ViewportInfo ,
commands : impl IntoIterator < Item = ViewportCommand > ,
window : & Window ,
is_viewport_focused : bool ,
screenshot_requested : & mut bool ,
) {
for command in commands {
process_viewport_command (
egui_ctx ,
window ,
command ,
info ,
is_viewport_focused ,
screenshot_requested ,
) ;
}
}
fn process_viewport_command (
egui_ctx : & egui ::Context ,
window : & Window ,
command : ViewportCommand ,
info : & mut ViewportInfo ,
is_viewport_focused : bool ,
screenshot_requested : & mut bool ,
) {
crate ::profile_function ! ( ) ;
use winit ::window ::ResizeDirection ;
for command in commands {
log ::debug ! ( "Processing ViewportCommand::{command:?}" ) ;
let egui_zoom_factor = egui_ctx . zoom_factor ( ) ;
let pixels_per_point = egui_zoom_factor * window . scale_factor ( ) as f32 ;
match command {
ViewportCommand ::Close = > {
info . events . push ( egui ::ViewportEvent ::Close ) ;
@ -1067,9 +1096,9 @@ pub fn process_viewport_commands(
}
}
ViewportCommand ::InnerSize ( size ) = > {
let width = size . x . max ( 1.0 ) ;
let height = size . y . max ( 1.0 ) ;
window . set_inner_size ( Log icalSize ::new ( width , height ) ) ;
let width_px = pixels_per_point * size . x . max ( 1.0 ) ;
let height_px = pixels_per_point * size . y . max ( 1.0 ) ;
window . set_inner_size ( Phys icalSize ::new ( width_px , height_px ) ) ;
}
ViewportCommand ::BeginResize ( direction ) = > {
if let Err ( err ) = window . drag_resize_window ( match direction {
@ -1090,20 +1119,25 @@ pub fn process_viewport_commands(
ViewportCommand ::Transparent ( v ) = > window . set_transparent ( v ) ,
ViewportCommand ::Visible ( v ) = > window . set_visible ( v ) ,
ViewportCommand ::OuterPosition ( pos ) = > {
window . set_outer_position ( LogicalPosition ::new ( pos . x , pos . y ) ) ;
window . set_outer_position ( PhysicalPosition ::new (
pixels_per_point * pos . x ,
pixels_per_point * pos . y ,
) ) ;
}
ViewportCommand ::MinInnerSize ( s ) = > {
window . set_min_inner_size (
( s . is_finite ( ) & & s ! = Vec2 ::ZERO ) . then_some ( LogicalSize ::new ( s . x , s . y ) ) ,
) ;
window . set_min_inner_size ( ( s . is_finite ( ) & & s ! = Vec2 ::ZERO ) . then_some (
PhysicalSize ::new ( pixels_per_point * s . x , pixels_per_point * s . y ) ,
) ) ;
}
ViewportCommand ::MaxInnerSize ( s ) = > {
window . set_max_inner_size (
( s . is_finite ( ) & & s ! = Vec2 ::INFINITY ) . then_some ( LogicalSize ::new ( s . x , s . y ) ) ,
) ;
window . set_max_inner_size ( ( s . is_finite ( ) & & s ! = Vec2 ::INFINITY ) . then_some (
PhysicalSize ::new ( pixels_per_point * s . x , pixels_per_point * s . y ) ,
) ) ;
}
ViewportCommand ::ResizeIncrements ( s ) = > {
window . set_resize_increments ( s . map ( | s | LogicalSize ::new ( s . x , s . y ) ) ) ;
window . set_resize_increments (
s . map ( | s | PhysicalSize ::new ( pixels_per_point * s . x , pixels_per_point * s . y ) ) ,
) ;
}
ViewportCommand ::Resizable ( v ) = > window . set_resizable ( v ) ,
ViewportCommand ::EnableButtons {
@ -1149,7 +1183,10 @@ pub fn process_viewport_commands(
} ) ) ;
}
ViewportCommand ::IMEPosition ( pos ) = > {
window . set_ime_position ( LogicalPosition ::new ( pos . x , pos . y ) ) ;
window . set_ime_position ( PhysicalPosition ::new (
pixels_per_point * pos . x ,
pixels_per_point * pos . y ,
) ) ;
}
ViewportCommand ::IMEAllowed ( v ) = > window . set_ime_allowed ( v ) ,
ViewportCommand ::IMEPurpose ( p ) = > window . set_ime_purpose ( match p {
@ -1180,7 +1217,10 @@ pub fn process_viewport_commands(
} ) ,
ViewportCommand ::ContentProtected ( v ) = > window . set_content_protected ( v ) ,
ViewportCommand ::CursorPosition ( pos ) = > {
if let Err ( err ) = window . set_cursor_position ( LogicalPosition ::new ( pos . x , pos . y ) ) {
if let Err ( err ) = window . set_cursor_position ( PhysicalPosition ::new (
pixels_per_point * pos . x ,
pixels_per_point * pos . y ,
) ) {
log ::warn ! ( "{command:?}: {err}" ) ;
}
}
@ -1204,13 +1244,29 @@ pub fn process_viewport_commands(
}
}
}
}
pub fn create_winit_window_builder (
pub fn create_winit_window_builder < T > (
egui_ctx : & egui ::Context ,
event_loop : & EventLoopWindowTarget < T > ,
viewport_builder : ViewportBuilder ,
) -> winit ::window ::WindowBuilder {
crate ::profile_function ! ( ) ;
// We set sizes and positions in egui:s own ui points, which depends on the egui
// zoom_factor and the native pixels per point, so we need to know that here.
let native_pixels_per_point = event_loop
. primary_monitor ( )
. or_else ( | | event_loop . available_monitors ( ) . next ( ) )
. map_or_else (
| | {
log ::debug ! ( "Failed to find a monitor - assuming native_pixels_per_point of 1.0" ) ;
1.0
} ,
| m | m . scale_factor ( ) as f32 ,
) ;
let zoom_factor = egui_ctx . zoom_factor ( ) ;
let pixels_per_point = zoom_factor * native_pixels_per_point ;
let ViewportBuilder {
title ,
position ,
@ -1271,27 +1327,31 @@ pub fn create_winit_window_builder(
. with_active ( active . unwrap_or ( true ) ) ;
if let Some ( inner_size ) = inner_size {
window_builder = window_builder
. with_inner_size ( winit ::dpi ::LogicalSize ::new ( inner_size . x , inner_size . y ) ) ;
window_builder = window_builder . with_inner_size ( PhysicalSize ::new (
pixels_per_point * inner_size . x ,
pixels_per_point * inner_size . y ,
) ) ;
}
if let Some ( min_inner_size ) = min_inner_size {
window_builder = window_builder . with_min_inner_size ( winit ::dpi ::Log icalSize ::new (
min_inner_size . x ,
min_inner_size . y ,
window_builder = window_builder . with_min_inner_size ( Phys icalSize ::new (
pixels_per_point * min_inner_size . x ,
pixels_per_point * min_inner_size . y ,
) ) ;
}
if let Some ( max_inner_size ) = max_inner_size {
window_builder = window_builder . with_max_inner_size ( winit ::dpi ::Log icalSize ::new (
max_inner_size . x ,
max_inner_size . y ,
window_builder = window_builder . with_max_inner_size ( Phys icalSize ::new (
pixels_per_point * max_inner_size . x ,
pixels_per_point * max_inner_size . y ,
) ) ;
}
if let Some ( position ) = position {
window_builder =
window_builder . with_position ( winit ::dpi ::LogicalPosition ::new ( position . x , position . y ) ) ;
window_builder = window_builder . with_position ( PhysicalPosition ::new (
pixels_per_point * position . x ,
pixels_per_point * position . y ,
) ) ;
}
if let Some ( icon ) = icon {
@ -1430,10 +1490,3 @@ mod profiling_scopes {
}
pub ( crate ) use profile_scope ;
}
#[ allow(unused_imports) ]
pub ( crate ) use profiling_scopes ::* ;
use winit ::{
dpi ::{ LogicalPosition , LogicalSize } ,
window ::{ CursorGrabMode , Window , WindowButtons , WindowLevel } ,
} ;