Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1eb333f

Browse files
rustbasicemilk
authored andcommittedApr 2, 2024
Fix ViewportCommand::InnerSize not resizing viewport on Wayland (#4211)
1 parent c73deae commit 1eb333f

File tree

3 files changed

+198
-160
lines changed

3 files changed

+198
-160
lines changed
 

‎crates/eframe/src/native/glow_integration.rs

+50-43
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ use winit::{
2323

2424
use egui::{
2525
epaint::ahash::HashMap, DeferredViewportUiCallback, ImmediateViewport, ViewportBuilder,
26-
ViewportClass, ViewportId, ViewportIdMap, ViewportIdPair, ViewportIdSet, ViewportInfo,
27-
ViewportOutput,
26+
ViewportClass, ViewportId, ViewportIdMap, ViewportIdPair, ViewportInfo, ViewportOutput,
2827
};
2928
#[cfg(feature = "accesskit")]
3029
use egui_winit::accesskit_winit;
@@ -103,6 +102,7 @@ struct Viewport {
103102
ids: ViewportIdPair,
104103
class: ViewportClass,
105104
builder: ViewportBuilder,
105+
deferred_commands: Vec<egui::viewport::ViewportCommand>,
106106
info: ViewportInfo,
107107
screenshot_requested: bool,
108108

@@ -550,7 +550,7 @@ impl GlowWinitRunning {
550550
let Some(window) = viewport.window.as_ref() else {
551551
return EventResult::Wait;
552552
};
553-
egui_winit::update_viewport_info(&mut viewport.info, &egui_ctx, window);
553+
egui_winit::update_viewport_info(&mut viewport.info, &egui_ctx, window, false);
554554

555555
let Some(egui_winit) = viewport.egui_winit.as_mut() else {
556556
return EventResult::Wait;
@@ -636,6 +636,8 @@ impl GlowWinitRunning {
636636
viewport_output,
637637
} = full_output;
638638

639+
glutin.remove_viewports_not_in(&viewport_output);
640+
639641
let GlutinWindowContext {
640642
viewports,
641643
current_gl_context,
@@ -645,6 +647,7 @@ impl GlowWinitRunning {
645647
let Some(viewport) = viewports.get_mut(&viewport_id) else {
646648
return EventResult::Wait;
647649
};
650+
648651
viewport.info.events.clear(); // they should have been processed
649652
let window = viewport.window.clone().unwrap();
650653
let gl_surface = viewport.gl_surface.as_ref().unwrap();
@@ -711,7 +714,7 @@ impl GlowWinitRunning {
711714
}
712715
}
713716

714-
glutin.handle_viewport_output(event_loop, &integration.egui_ctx, viewport_output);
717+
glutin.handle_viewport_output(event_loop, &integration.egui_ctx, &viewport_output);
715718

716719
integration.report_frame_time(frame_timer.total_time_sec()); // don't count auto-save time as part of regular frame time
717720

@@ -986,8 +989,7 @@ impl GlutinWindowContext {
986989
if let Some(window) = &window {
987990
viewport_from_window.insert(window.id(), ViewportId::ROOT);
988991
window_from_viewport.insert(ViewportId::ROOT, window.id());
989-
info.minimized = window.is_minimized();
990-
info.maximized = Some(window.is_maximized());
992+
egui_winit::update_viewport_info(&mut info, egui_ctx, window, true);
991993
}
992994

993995
let mut viewports = ViewportIdMap::default();
@@ -997,6 +999,7 @@ impl GlutinWindowContext {
997999
ids: ViewportIdPair::ROOT,
9981000
class: ViewportClass::Root,
9991001
builder: viewport_builder,
1002+
deferred_commands: vec![],
10001003
info,
10011004
screenshot_requested: false,
10021005
viewport_ui_cb: None,
@@ -1078,8 +1081,8 @@ impl GlutinWindowContext {
10781081
&window,
10791082
&viewport.builder,
10801083
);
1081-
viewport.info.minimized = window.is_minimized();
1082-
viewport.info.maximized = Some(window.is_maximized());
1084+
1085+
egui_winit::update_viewport_info(&mut viewport.info, &self.egui_ctx, &window, true);
10831086
viewport.window.insert(Arc::new(window))
10841087
};
10851088

@@ -1208,75 +1211,88 @@ impl GlutinWindowContext {
12081211
self.gl_config.display().get_proc_address(addr)
12091212
}
12101213

1214+
pub(crate) fn remove_viewports_not_in(
1215+
&mut self,
1216+
viewport_output: &ViewportIdMap<ViewportOutput>,
1217+
) {
1218+
// GC old viewports
1219+
self.viewports
1220+
.retain(|id, _| viewport_output.contains_key(id));
1221+
self.viewport_from_window
1222+
.retain(|_, id| viewport_output.contains_key(id));
1223+
self.window_from_viewport
1224+
.retain(|id, _| viewport_output.contains_key(id));
1225+
}
1226+
12111227
fn handle_viewport_output(
12121228
&mut self,
12131229
event_loop: &EventLoopWindowTarget<UserEvent>,
12141230
egui_ctx: &egui::Context,
1215-
viewport_output: ViewportIdMap<ViewportOutput>,
1231+
viewport_output: &ViewportIdMap<ViewportOutput>,
12161232
) {
12171233
crate::profile_function!();
12181234

1219-
let active_viewports_ids: ViewportIdSet = viewport_output.keys().copied().collect();
1220-
12211235
for (
12221236
viewport_id,
12231237
ViewportOutput {
12241238
parent,
12251239
class,
12261240
builder,
12271241
viewport_ui_cb,
1228-
commands,
1242+
mut commands,
12291243
repaint_delay: _, // ignored - we listened to the repaint callback instead
12301244
},
1231-
) in viewport_output
1245+
) in viewport_output.clone()
12321246
{
12331247
let ids = ViewportIdPair::from_self_and_parent(viewport_id, parent);
12341248

12351249
let viewport = initialize_or_update_viewport(
1236-
egui_ctx,
12371250
&mut self.viewports,
12381251
ids,
12391252
class,
12401253
builder,
12411254
viewport_ui_cb,
1242-
self.focused_viewport,
12431255
);
12441256

12451257
if let Some(window) = &viewport.window {
1258+
let old_inner_size = window.inner_size();
1259+
12461260
let is_viewport_focused = self.focused_viewport == Some(viewport_id);
1261+
viewport.deferred_commands.append(&mut commands);
1262+
12471263
egui_winit::process_viewport_commands(
12481264
egui_ctx,
12491265
&mut viewport.info,
1250-
commands,
1266+
std::mem::take(&mut viewport.deferred_commands),
12511267
window,
12521268
is_viewport_focused,
12531269
&mut viewport.screenshot_requested,
12541270
);
1271+
1272+
// For Wayland : https://github.com/emilk/egui/issues/4196
1273+
if cfg!(target_os = "linux") {
1274+
let new_inner_size = window.inner_size();
1275+
if new_inner_size != old_inner_size {
1276+
self.resize(viewport_id, new_inner_size);
1277+
}
1278+
}
12551279
}
12561280
}
12571281

12581282
// Create windows for any new viewports:
12591283
self.initialize_all_windows(event_loop);
12601284

1261-
// GC old viewports
1262-
self.viewports
1263-
.retain(|id, _| active_viewports_ids.contains(id));
1264-
self.viewport_from_window
1265-
.retain(|_, id| active_viewports_ids.contains(id));
1266-
self.window_from_viewport
1267-
.retain(|id, _| active_viewports_ids.contains(id));
1285+
self.remove_viewports_not_in(viewport_output);
12681286
}
12691287
}
12701288

1271-
fn initialize_or_update_viewport<'vp>(
1272-
egu_ctx: &egui::Context,
1273-
viewports: &'vp mut ViewportIdMap<Viewport>,
1289+
fn initialize_or_update_viewport(
1290+
viewports: &mut ViewportIdMap<Viewport>,
12741291
ids: ViewportIdPair,
12751292
class: ViewportClass,
12761293
mut builder: ViewportBuilder,
12771294
viewport_ui_cb: Option<Arc<dyn Fn(&egui::Context) + Send + Sync>>,
1278-
focused_viewport: Option<ViewportId>,
1279-
) -> &'vp mut Viewport {
1295+
) -> &mut Viewport {
12801296
crate::profile_function!();
12811297

12821298
if builder.icon.is_none() {
@@ -1294,6 +1310,7 @@ fn initialize_or_update_viewport<'vp>(
12941310
ids,
12951311
class,
12961312
builder,
1313+
deferred_commands: vec![],
12971314
info: Default::default(),
12981315
screenshot_requested: false,
12991316
viewport_ui_cb,
@@ -1311,7 +1328,7 @@ fn initialize_or_update_viewport<'vp>(
13111328
viewport.class = class;
13121329
viewport.viewport_ui_cb = viewport_ui_cb;
13131330

1314-
let (delta_commands, recreate) = viewport.builder.patch(builder);
1331+
let (mut delta_commands, recreate) = viewport.builder.patch(builder);
13151332

13161333
if recreate {
13171334
log::debug!(
@@ -1321,18 +1338,10 @@ fn initialize_or_update_viewport<'vp>(
13211338
);
13221339
viewport.window = None;
13231340
viewport.egui_winit = None;
1324-
} else if let Some(window) = &viewport.window {
1325-
let is_viewport_focused = focused_viewport == Some(ids.this);
1326-
egui_winit::process_viewport_commands(
1327-
egu_ctx,
1328-
&mut viewport.info,
1329-
delta_commands,
1330-
window,
1331-
is_viewport_focused,
1332-
&mut viewport.screenshot_requested,
1333-
);
13341341
}
13351342

1343+
viewport.deferred_commands.append(&mut delta_commands);
1344+
13361345
entry.into_mut()
13371346
}
13381347
}
@@ -1362,13 +1371,11 @@ fn render_immediate_viewport(
13621371
let mut glutin = glutin.borrow_mut();
13631372

13641373
initialize_or_update_viewport(
1365-
egui_ctx,
13661374
&mut glutin.viewports,
13671375
ids,
13681376
ViewportClass::Immediate,
13691377
builder,
13701378
None,
1371-
None,
13721379
);
13731380

13741381
if let Err(err) = glutin.initialize_window(viewport_id, event_loop) {
@@ -1388,7 +1395,7 @@ fn render_immediate_viewport(
13881395
let (Some(egui_winit), Some(window)) = (&mut viewport.egui_winit, &viewport.window) else {
13891396
return;
13901397
};
1391-
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window);
1398+
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window, false);
13921399

13931400
let mut raw_input = egui_winit.take_egui_input(window);
13941401
raw_input.viewports = glutin
@@ -1487,7 +1494,7 @@ fn render_immediate_viewport(
14871494

14881495
egui_winit.handle_platform_output(window, platform_output);
14891496

1490-
glutin.handle_viewport_output(event_loop, egui_ctx, viewport_output);
1497+
glutin.handle_viewport_output(event_loop, egui_ctx, &viewport_output);
14911498
}
14921499

14931500
#[cfg(feature = "__screenshot")]

‎crates/eframe/src/native/wgpu_integration.rs

+85-64
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub struct Viewport {
7676
ids: ViewportIdPair,
7777
class: ViewportClass,
7878
builder: ViewportBuilder,
79+
deferred_commands: Vec<egui::viewport::ViewportCommand>,
7980
info: ViewportInfo,
8081
screenshot_requested: bool,
8182

@@ -154,13 +155,11 @@ impl WgpuWinitApp {
154155
} = &mut *running.shared.borrow_mut();
155156

156157
initialize_or_update_viewport(
157-
egui_ctx,
158158
viewports,
159159
ViewportIdPair::ROOT,
160160
ViewportClass::Root,
161161
self.native_options.viewport.clone(),
162162
None,
163-
None,
164163
)
165164
.initialize_window(event_loop, egui_ctx, viewport_from_window, painter);
166165
}
@@ -276,18 +275,18 @@ impl WgpuWinitApp {
276275
let mut viewport_from_window = HashMap::default();
277276
viewport_from_window.insert(window.id(), ViewportId::ROOT);
278277

278+
let mut info = ViewportInfo::default();
279+
egui_winit::update_viewport_info(&mut info, &egui_ctx, &window, true);
280+
279281
let mut viewports = Viewports::default();
280282
viewports.insert(
281283
ViewportId::ROOT,
282284
Viewport {
283285
ids: ViewportIdPair::ROOT,
284286
class: ViewportClass::Root,
285287
builder,
286-
info: ViewportInfo {
287-
minimized: window.is_minimized(),
288-
maximized: Some(window.is_maximized()),
289-
..Default::default()
290-
},
288+
deferred_commands: vec![],
289+
info,
291290
screenshot_requested: false,
292291
viewport_ui_cb: None,
293292
window: Some(window),
@@ -601,7 +600,7 @@ impl WgpuWinitRunning {
601600
let Some(window) = window else {
602601
return EventResult::Wait;
603602
};
604-
egui_winit::update_viewport_info(info, &integration.egui_ctx, window);
603+
egui_winit::update_viewport_info(info, &integration.egui_ctx, window, false);
605604

606605
{
607606
crate::profile_scope!("set_window");
@@ -636,15 +635,25 @@ impl WgpuWinitRunning {
636635

637636
// ------------------------------------------------------------
638637

639-
let mut shared = shared.borrow_mut();
638+
let mut shared_mut = shared.borrow_mut();
640639

641640
let SharedState {
642641
egui_ctx,
643642
viewports,
644643
painter,
645644
viewport_from_window,
646645
focused_viewport,
647-
} = &mut *shared;
646+
} = &mut *shared_mut;
647+
648+
let FullOutput {
649+
platform_output,
650+
textures_delta,
651+
shapes,
652+
pixels_per_point,
653+
viewport_output,
654+
} = full_output;
655+
656+
remove_viewports_not_in(viewports, painter, viewport_from_window, &viewport_output);
648657

649658
let Some(viewport) = viewports.get_mut(&viewport_id) else {
650659
return EventResult::Wait;
@@ -661,14 +670,6 @@ impl WgpuWinitRunning {
661670
return EventResult::Wait;
662671
};
663672

664-
let FullOutput {
665-
platform_output,
666-
textures_delta,
667-
shapes,
668-
pixels_per_point,
669-
viewport_output,
670-
} = full_output;
671-
672673
egui_winit.handle_platform_output(window, platform_output);
673674

674675
let clipped_primitives = egui_ctx.tessellate(shapes, pixels_per_point);
@@ -698,8 +699,10 @@ impl WgpuWinitRunning {
698699

699700
handle_viewport_output(
700701
&integration.egui_ctx,
701-
viewport_output,
702+
&viewport_output,
702703
viewports,
704+
painter,
705+
viewport_from_window,
703706
*focused_viewport,
704707
);
705708

@@ -874,9 +877,7 @@ impl Viewport {
874877
painter.max_texture_side(),
875878
));
876879

877-
self.info.minimized = window.is_minimized();
878-
self.info.maximized = Some(window.is_maximized());
879-
880+
egui_winit::update_viewport_info(&mut self.info, egui_ctx, &window, true);
880881
self.window = Some(window);
881882
}
882883
Err(err) => {
@@ -931,23 +932,16 @@ fn render_immediate_viewport(
931932
..
932933
} = &mut *shared.borrow_mut();
933934

934-
let viewport = initialize_or_update_viewport(
935-
egui_ctx,
936-
viewports,
937-
ids,
938-
ViewportClass::Immediate,
939-
builder,
940-
None,
941-
None,
942-
);
935+
let viewport =
936+
initialize_or_update_viewport(viewports, ids, ViewportClass::Immediate, builder, None);
943937
if viewport.window.is_none() {
944938
viewport.initialize_window(event_loop, egui_ctx, viewport_from_window, painter);
945939
}
946940

947941
let (Some(window), Some(egui_winit)) = (&viewport.window, &mut viewport.egui_winit) else {
948942
return;
949943
};
950-
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window);
944+
egui_winit::update_viewport_info(&mut viewport.info, egui_ctx, window, false);
951945

952946
let mut input = egui_winit.take_egui_input(window);
953947
input.viewports = viewports
@@ -976,13 +970,14 @@ fn render_immediate_viewport(
976970

977971
// ------------------------------------------
978972

979-
let mut shared = shared.borrow_mut();
973+
let mut shared_mut = shared.borrow_mut();
980974
let SharedState {
981975
viewports,
982976
painter,
977+
viewport_from_window,
983978
focused_viewport,
984979
..
985-
} = &mut *shared;
980+
} = &mut *shared_mut;
986981

987982
let Some(viewport) = viewports.get_mut(&ids.this) else {
988983
return;
@@ -1014,14 +1009,37 @@ fn render_immediate_viewport(
10141009

10151010
egui_winit.handle_platform_output(window, platform_output);
10161011

1017-
handle_viewport_output(&egui_ctx, viewport_output, viewports, *focused_viewport);
1012+
handle_viewport_output(
1013+
&egui_ctx,
1014+
&viewport_output,
1015+
viewports,
1016+
painter,
1017+
viewport_from_window,
1018+
*focused_viewport,
1019+
);
1020+
}
1021+
1022+
pub(crate) fn remove_viewports_not_in(
1023+
viewports: &mut ViewportIdMap<Viewport>,
1024+
painter: &mut egui_wgpu::winit::Painter,
1025+
viewport_from_window: &mut HashMap<WindowId, ViewportId>,
1026+
viewport_output: &ViewportIdMap<ViewportOutput>,
1027+
) {
1028+
let active_viewports_ids: ViewportIdSet = viewport_output.keys().copied().collect();
1029+
1030+
// Prune dead viewports:
1031+
viewports.retain(|id, _| active_viewports_ids.contains(id));
1032+
viewport_from_window.retain(|_, id| active_viewports_ids.contains(id));
1033+
painter.gc_viewports(&active_viewports_ids);
10181034
}
10191035

10201036
/// Add new viewports, and update existing ones:
10211037
fn handle_viewport_output(
10221038
egui_ctx: &egui::Context,
1023-
viewport_output: ViewportIdMap<ViewportOutput>,
1039+
viewport_output: &ViewportIdMap<ViewportOutput>,
10241040
viewports: &mut ViewportIdMap<Viewport>,
1041+
painter: &mut egui_wgpu::winit::Painter,
1042+
viewport_from_window: &mut HashMap<WindowId, ViewportId>,
10251043
focused_viewport: Option<ViewportId>,
10261044
) {
10271045
for (
@@ -1031,46 +1049,56 @@ fn handle_viewport_output(
10311049
class,
10321050
builder,
10331051
viewport_ui_cb,
1034-
commands,
1052+
mut commands,
10351053
repaint_delay: _, // ignored - we listened to the repaint callback instead
10361054
},
1037-
) in viewport_output
1055+
) in viewport_output.clone()
10381056
{
10391057
let ids = ViewportIdPair::from_self_and_parent(viewport_id, parent);
10401058

1041-
let viewport = initialize_or_update_viewport(
1042-
egui_ctx,
1043-
viewports,
1044-
ids,
1045-
class,
1046-
builder,
1047-
viewport_ui_cb,
1048-
focused_viewport,
1049-
);
1059+
let viewport =
1060+
initialize_or_update_viewport(viewports, ids, class, builder, viewport_ui_cb);
10501061

10511062
if let Some(window) = viewport.window.as_ref() {
1063+
let old_inner_size = window.inner_size();
1064+
10521065
let is_viewport_focused = focused_viewport == Some(viewport_id);
1066+
viewport.deferred_commands.append(&mut commands);
1067+
10531068
egui_winit::process_viewport_commands(
10541069
egui_ctx,
10551070
&mut viewport.info,
1056-
commands,
1071+
std::mem::take(&mut viewport.deferred_commands),
10571072
window,
10581073
is_viewport_focused,
10591074
&mut viewport.screenshot_requested,
10601075
);
1076+
1077+
// For Wayland : https://github.com/emilk/egui/issues/4196
1078+
if cfg!(target_os = "linux") {
1079+
let new_inner_size = window.inner_size();
1080+
if new_inner_size != old_inner_size {
1081+
if let (Some(width), Some(height)) = (
1082+
NonZeroU32::new(new_inner_size.width),
1083+
NonZeroU32::new(new_inner_size.height),
1084+
) {
1085+
painter.on_window_resized(viewport_id, width, height);
1086+
}
1087+
}
1088+
}
10611089
}
10621090
}
1091+
1092+
remove_viewports_not_in(viewports, painter, viewport_from_window, viewport_output);
10631093
}
10641094

1065-
fn initialize_or_update_viewport<'vp>(
1066-
egui_ctx: &egui::Context,
1067-
viewports: &'vp mut Viewports,
1095+
fn initialize_or_update_viewport(
1096+
viewports: &mut Viewports,
10681097
ids: ViewportIdPair,
10691098
class: ViewportClass,
10701099
mut builder: ViewportBuilder,
10711100
viewport_ui_cb: Option<Arc<dyn Fn(&egui::Context) + Send + Sync>>,
1072-
focused_viewport: Option<ViewportId>,
1073-
) -> &'vp mut Viewport {
1101+
) -> &mut Viewport {
10741102
crate::profile_function!();
10751103

10761104
if builder.icon.is_none() {
@@ -1088,6 +1116,7 @@ fn initialize_or_update_viewport<'vp>(
10881116
ids,
10891117
class,
10901118
builder,
1119+
deferred_commands: vec![],
10911120
info: Default::default(),
10921121
screenshot_requested: false,
10931122
viewport_ui_cb,
@@ -1104,7 +1133,7 @@ fn initialize_or_update_viewport<'vp>(
11041133
viewport.ids.parent = ids.parent;
11051134
viewport.viewport_ui_cb = viewport_ui_cb;
11061135

1107-
let (delta_commands, recreate) = viewport.builder.patch(builder);
1136+
let (mut delta_commands, recreate) = viewport.builder.patch(builder);
11081137

11091138
if recreate {
11101139
log::debug!(
@@ -1114,18 +1143,10 @@ fn initialize_or_update_viewport<'vp>(
11141143
);
11151144
viewport.window = None;
11161145
viewport.egui_winit = None;
1117-
} else if let Some(window) = &viewport.window {
1118-
let is_viewport_focused = focused_viewport == Some(ids.this);
1119-
egui_winit::process_viewport_commands(
1120-
egui_ctx,
1121-
&mut viewport.info,
1122-
delta_commands,
1123-
window,
1124-
is_viewport_focused,
1125-
&mut viewport.screenshot_requested,
1126-
);
11271146
}
11281147

1148+
viewport.deferred_commands.append(&mut delta_commands);
1149+
11291150
entry.into_mut()
11301151
}
11311152
}

‎crates/egui-winit/src/lib.rs

+63-53
Original file line numberDiff line numberDiff line change
@@ -874,70 +874,62 @@ impl State {
874874
}
875875
}
876876

877+
pub fn inner_rect_in_points(window: &Window, pixels_per_point: f32) -> Option<Rect> {
878+
let inner_pos_px = window.inner_position().ok()?;
879+
let inner_pos_px = egui::pos2(inner_pos_px.x as f32, inner_pos_px.y as f32);
880+
881+
let inner_size_px = window.inner_size();
882+
let inner_size_px = egui::vec2(inner_size_px.width as f32, inner_size_px.height as f32);
883+
884+
let inner_rect_px = egui::Rect::from_min_size(inner_pos_px, inner_size_px);
885+
886+
Some(inner_rect_px / pixels_per_point)
887+
}
888+
889+
pub fn outer_rect_in_points(window: &Window, pixels_per_point: f32) -> Option<Rect> {
890+
let outer_pos_px = window.outer_position().ok()?;
891+
let outer_pos_px = egui::pos2(outer_pos_px.x as f32, outer_pos_px.y as f32);
892+
893+
let outer_size_px = window.outer_size();
894+
let outer_size_px = egui::vec2(outer_size_px.width as f32, outer_size_px.height as f32);
895+
896+
let outer_rect_px = egui::Rect::from_min_size(outer_pos_px, outer_size_px);
897+
898+
Some(outer_rect_px / pixels_per_point)
899+
}
900+
877901
/// Update the given viewport info with the current state of the window.
878902
///
879903
/// Call before [`State::take_egui_input`].
904+
///
905+
/// If this is called right after window creation, `is_init` should be `true`, otherwise `false`.
880906
pub fn update_viewport_info(
881907
viewport_info: &mut ViewportInfo,
882908
egui_ctx: &egui::Context,
883909
window: &Window,
910+
is_init: bool,
884911
) {
885912
crate::profile_function!();
886913

887914
let pixels_per_point = pixels_per_point(egui_ctx, window);
888915

889916
let has_a_position = match window.is_minimized() {
890-
None | Some(true) => false,
891-
Some(false) => true,
892-
};
893-
894-
let inner_pos_px = if has_a_position {
895-
window
896-
.inner_position()
897-
.map(|pos| Pos2::new(pos.x as f32, pos.y as f32))
898-
.ok()
899-
} else {
900-
None
901-
};
902-
903-
let outer_pos_px = if has_a_position {
904-
window
905-
.outer_position()
906-
.map(|pos| Pos2::new(pos.x as f32, pos.y as f32))
907-
.ok()
908-
} else {
909-
None
910-
};
911-
912-
let inner_size_px = if has_a_position {
913-
let size = window.inner_size();
914-
Some(Vec2::new(size.width as f32, size.height as f32))
915-
} else {
916-
None
917-
};
918-
919-
let outer_size_px = if has_a_position {
920-
let size = window.outer_size();
921-
Some(Vec2::new(size.width as f32, size.height as f32))
922-
} else {
923-
None
917+
Some(true) => false,
918+
Some(false) | None => true,
924919
};
925920

926-
let inner_rect_px = if let (Some(pos), Some(size)) = (inner_pos_px, inner_size_px) {
927-
Some(Rect::from_min_size(pos, size))
921+
let inner_rect = if has_a_position {
922+
inner_rect_in_points(window, pixels_per_point)
928923
} else {
929924
None
930925
};
931926

932-
let outer_rect_px = if let (Some(pos), Some(size)) = (outer_pos_px, outer_size_px) {
933-
Some(Rect::from_min_size(pos, size))
927+
let outer_rect = if has_a_position {
928+
outer_rect_in_points(window, pixels_per_point)
934929
} else {
935930
None
936931
};
937932

938-
let inner_rect = inner_rect_px.map(|r| r / pixels_per_point);
939-
let outer_rect = outer_rect_px.map(|r| r / pixels_per_point);
940-
941933
let monitor_size = {
942934
crate::profile_scope!("monitor_size");
943935
if let Some(monitor) = window.current_monitor() {
@@ -948,21 +940,23 @@ pub fn update_viewport_info(
948940
}
949941
};
950942

951-
viewport_info.focused = Some(window.has_focus());
952-
viewport_info.fullscreen = Some(window.fullscreen().is_some());
953-
viewport_info.inner_rect = inner_rect;
954-
viewport_info.monitor_size = monitor_size;
943+
viewport_info.title = Some(window.title());
955944
viewport_info.native_pixels_per_point = Some(window.scale_factor() as f32);
945+
946+
viewport_info.monitor_size = monitor_size;
947+
viewport_info.inner_rect = inner_rect;
956948
viewport_info.outer_rect = outer_rect;
957-
viewport_info.title = Some(window.title());
958949

959-
if cfg!(target_os = "windows") {
960-
// It's tempting to do this, but it leads to a deadlock on Mac when running
950+
if is_init || !cfg!(target_os = "macos") {
951+
// Asking for minimized/maximized state at runtime leads to a deadlock on Mac when running
961952
// `cargo run -p custom_window_frame`.
962953
// See https://github.com/emilk/egui/issues/3494
963954
viewport_info.maximized = Some(window.is_maximized());
964955
viewport_info.minimized = Some(window.is_minimized().unwrap_or(false));
965956
}
957+
958+
viewport_info.fullscreen = Some(window.fullscreen().is_some());
959+
viewport_info.focused = Some(window.has_focus());
966960
}
967961

968962
fn open_url_in_browser(_url: &str) {
@@ -1319,11 +1313,27 @@ fn process_viewport_command(
13191313
ViewportCommand::InnerSize(size) => {
13201314
let width_px = pixels_per_point * size.x.max(1.0);
13211315
let height_px = pixels_per_point * size.y.max(1.0);
1322-
if window
1323-
.request_inner_size(PhysicalSize::new(width_px, height_px))
1324-
.is_some()
1325-
{
1326-
log::debug!("ViewportCommand::InnerSize ignored by winit");
1316+
let requested_size = PhysicalSize::new(width_px, height_px);
1317+
if let Some(_returned_inner_size) = window.request_inner_size(requested_size) {
1318+
// On platforms where the size is entirely controlled by the user the
1319+
// applied size will be returned immediately, resize event in such case
1320+
// may not be generated.
1321+
// e.g. Linux
1322+
1323+
// On platforms where resizing is disallowed by the windowing system, the current
1324+
// inner size is returned immediately, and the user one is ignored.
1325+
// e.g. Android, iOS, …
1326+
1327+
// However, comparing the results is prone to numerical errors
1328+
// because the linux backend converts physical to logical and back again.
1329+
// So let's just assume it worked:
1330+
1331+
info.inner_rect = inner_rect_in_points(window, pixels_per_point);
1332+
info.outer_rect = outer_rect_in_points(window, pixels_per_point);
1333+
} else {
1334+
// e.g. macOS, Windows
1335+
// The request went to the display system,
1336+
// and the actual size will be delivered later with the [`WindowEvent::Resized`].
13271337
}
13281338
}
13291339
ViewportCommand::BeginResize(direction) => {

0 commit comments

Comments
 (0)
Please sign in to comment.