Open Barafu opened 3 months ago
It seems like this would require using a method that skips the first frame.
My opinion , this is not a bug, the monitor information provision and monitor selection features are not there yet.
There are functions for moving the window and setting it fullscreen. In the described conditions, they move window to the location that is different from the specified one, and fullscreen does not occupy full screen. That is what I call a bug.
Yes, you try to find a temporary solution.
I did this and it worked fine on Windows 10 with two different DPI monitors.
fn main() -> eframe::Result {
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_position([2000.0, 2000.0])
.with_drag_and_drop(false),
..Default::default()
};
return eframe::run_native(
"My egui App",
native_options,
Box::new(|_cc| Ok(Box::new(MyApp::default()))),
);
}
#[derive(Default)]
struct MyApp {
fullscreen_onetime: bool,
text: String,
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if !self.fullscreen_onetime {
self.fullscreen_onetime = true;
ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(true));
}
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(
egui::TextEdit::multiline(&mut self.text)
.desired_width(300.0)
.desired_rows(6)
.lock_focus(true)
.code_editor(),
);
});
}
}
I can't find a way to fix this for a secondary viewport (opened with show_viewport_deferred()). Even resizing and fullscreening as late as possible does not help in this case. Also, I doublechecked that X,Y coordinates I pass are correct. The left monitor is 2560 pixels wide, and I pass x=2561, y=-998 (since right monitor is higher than the primary monitor).
I tested it with the test example below and there was no problem with the fullscreen function.
fn main() -> eframe::Result {
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_position([2000.0, 500.0])
.with_drag_and_drop(false),
..Default::default()
};
return eframe::run_native(
"My egui App",
native_options,
Box::new(|_cc| Ok(Box::new(MyApp::default()))),
);
}
#[derive(Default)]
pub struct MyApp {
fullscreen_onetime: bool,
text: String,
visible_test_viewport: std::sync::Arc<std::sync::atomic::AtomicBool>,
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if !self.fullscreen_onetime {
self.fullscreen_onetime = true;
// ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(true));
}
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(
egui::TextEdit::multiline(&mut self.text)
.desired_width(300.0)
.desired_rows(6)
.lock_focus(true)
.code_editor(),
);
if !self.visible_test_viewport.load(std::sync::atomic::Ordering::Relaxed) {
test_viewport(self, ui);
}
});
}
}
pub fn test_viewport(app: &mut MyApp, ui: &mut egui::Ui) {
let show_deferred_viewport = app.visible_test_viewport.clone();
let title = "test viewport";
ui.ctx().show_viewport_deferred(
egui::ViewportId::from_hash_of(title.clone()),
egui::ViewportBuilder::default()
.with_title(title.clone())
.with_inner_size([1280.0, 720.0]),
move |ctx, class| {
assert!(
class == egui::ViewportClass::Deferred,
"This egui backend doesn't support multiple viewports"
);
egui::CentralPanel::default().show(ctx, |ui| {
ui.label("Hello from deferred viewport");
if ui.button("Fullscreen").clicked() {
let is_on = ui.input(|i| i.time) % 2.0 < 1.0;
ui.ctx()
.send_viewport_cmd(egui::ViewportCommand::Fullscreen(is_on));
}
});
if ctx.input(|i| i.viewport().close_requested()) {
// Tell parent to close us.
show_deferred_viewport.store(false, std::sync::atomic::Ordering::Relaxed);
}
},
);
}
I have modified your example to not work: to show error exactly like on my screenshot. Please note line 60: dbg!
there reports correct coordinates, but the window is not displayed on them.
use display_info::DisplayInfo;
fn main() -> eframe::Result {
let displays = DisplayInfo::all().unwrap();
let primary = displays.iter().find(|d| d.is_primary).unwrap();
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_position([primary.x as f32, primary.y as f32])
.with_drag_and_drop(false),
..Default::default()
};
return eframe::run_native(
"My egui App",
native_options,
Box::new(|_cc| Ok(Box::new(MyApp::default()))),
);
}
#[derive(Default)]
pub struct MyApp {
fullscreen_onetime: bool,
text: String,
visible_test_viewport: std::sync::Arc<std::sync::atomic::AtomicBool>,
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if !self.fullscreen_onetime {
self.fullscreen_onetime = true;
// ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(true));
}
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(
egui::TextEdit::multiline(&mut self.text)
.desired_width(300.0)
.desired_rows(6)
.lock_focus(true)
.code_editor(),
);
if !self.visible_test_viewport.load(std::sync::atomic::Ordering::Relaxed) {
test_viewport(self, ui);
}
});
}
}
pub fn test_viewport(app: &mut MyApp, ui: &mut egui::Ui) {
let show_deferred_viewport = app.visible_test_viewport.clone();
let title = "test viewport";
let displays = DisplayInfo::all().unwrap();
let non_primary = displays.iter().find(|d| !d.is_primary).unwrap();
ui.ctx().show_viewport_deferred(
egui::ViewportId::from_hash_of(title.clone()),
egui::ViewportBuilder::default()
.with_title(title.clone())
.with_position(dbg!([non_primary.x as f32, non_primary.y as f32]))
.with_inner_size([500.0, 500.0]),
move |ctx, class| {
assert!(
class == egui::ViewportClass::Deferred,
"This egui backend doesn't support multiple viewports"
);
egui::CentralPanel::default().show(ctx, |ui| {
ui.label("Hello from deferred viewport");
if ui.button("Fullscreen").clicked() {
let is_on = ui.input(|i| i.time) % 2.0 < 1.0;
ui.ctx()
.send_viewport_cmd(egui::ViewportCommand::Fullscreen(is_on));
}
});
if ctx.input(|i| i.viewport().close_requested()) {
// Tell parent to close us.
show_deferred_viewport.store(false, std::sync::atomic::Ordering::Relaxed);
}
},
);
}
As below, we have confirmed that there are no problems with the FullScreen function or other functions in Windows 10.
use display_info::DisplayInfo;
fn main() -> eframe::Result {
let displays = DisplayInfo::all().unwrap();
let primary = displays.iter().find(|d| d.is_primary).unwrap();
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_position([primary.x as f32, primary.y as f32])
.with_drag_and_drop(false),
..Default::default()
};
return eframe::run_native(
"My egui App",
native_options,
Box::new(|_cc| Ok(Box::new(MyApp::default()))),
);
}
#[derive(Default)]
pub struct MyApp {
fullscreen_onetime: bool,
text: String,
visible_test_viewport: std::sync::Arc<std::sync::atomic::AtomicBool>,
}
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if !self.fullscreen_onetime {
self.fullscreen_onetime = true;
// ctx.send_viewport_cmd(egui::ViewportCommand::Fullscreen(true));
}
egui::CentralPanel::default().show(ctx, |ui| {
ui.add(
egui::TextEdit::multiline(&mut self.text)
.desired_width(300.0)
.desired_rows(6)
.lock_focus(true)
.code_editor(),
);
if !self
.visible_test_viewport
.load(std::sync::atomic::Ordering::Relaxed)
{
test_viewport(self, ui);
}
});
}
}
pub fn test_viewport(app: &mut MyApp, ui: &mut egui::Ui) {
let show_deferred_viewport = app.visible_test_viewport.clone();
let title = "test viewport";
let displays = DisplayInfo::all().unwrap();
let _primary = displays.iter().find(|d| d.is_primary).unwrap();
let non_primary = displays.iter().find(|d| !d.is_primary).unwrap();
ui.ctx().show_viewport_deferred(
egui::ViewportId::from_hash_of(title),
egui::ViewportBuilder::default()
.with_title(title)
.with_position(dbg!([
non_primary.width as f32 / non_primary.scale_factor,
non_primary.y as f32
]))
.with_inner_size([500.0, 500.0]),
move |ctx, class| {
assert!(
class == egui::ViewportClass::Deferred,
"This egui backend doesn't support multiple viewports"
);
egui::CentralPanel::default().show(ctx, |ui| {
ui.label("Hello from deferred viewport");
if ui.button("Fullscreen").clicked() {
let is_on = ui.input(|i| i.time) % 2.0 < 1.0;
ui.ctx()
.send_viewport_cmd(egui::ViewportCommand::Fullscreen(is_on));
}
});
if ctx.input(|i| i.viewport().close_requested()) {
// Tell parent to close us.
show_deferred_viewport.store(false, std::sync::atomic::Ordering::Relaxed);
}
},
);
}
I also came to conclusion that coordinates need to be divided. However, I have run the example as you provided exactly, and it looks like this: (the white square seems to be a problem with screenshot tool)
However, then I modified it like this:
let non_primary = displays.iter().find(|d| !d.is_primary).unwrap();
ui.ctx().show_viewport_deferred(
egui::ViewportId::from_hash_of(title),
egui::ViewportBuilder::default()
.with_title(title)
.with_position(dbg!([
non_primary.x as f32 / non_primary.scale_factor,
non_primary.y as f32 / non_primary.scale_factor,
]))
.with_inner_size([500.0, 500.0]),
And now it looks perfect.
Anyway, even if not a problem with code, it needs to be addressed in the documentation.
Describe the bug I have Win11 and two monitors with different DPI and I wanted to make an app that displays something in fullscreen on the secondary monitor. I detect the position and size of the second monitor using
screen-info
crate, but when I create the window it is not positioned properly. See the screenshot. Because of the workaround below I don't think the problem can be inscreen-info
.To Reproduce Here is the relevant part of the code that creates a window.
(the primary display being set to non-primary is intentional for example)
Workarounds Any one of these measures solves the problem.
Screenshots Note how on the right display you can see parts of "Chatbox" app beside the supposedly fullscreen demo app.
Desktop (please complete the following information):