Skip to content

Commit

Permalink
Allow users to create viewports larger than monitor on Windows & macOS (
Browse files Browse the repository at this point in the history
#4337)

Added clamp_size_to_monitor_size field on ViewportBuilder, which means
whether clamp the window's size to monitor's size. (default to `true`)

* Closes #3389

### simple example

```rust
pub struct MyApp {}

impl MyApp {
    pub fn new() -> MyApp {
        MyApp {}
    }
}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &Context, frame: &mut eframe::Frame) {
        egui::CentralPanel::default()
            .frame(Frame::none().fill(Color32::DARK_GRAY))
            .show(ctx, |ui| {
                if ctx.input(|i| i.key_pressed(Key::Escape)) {
                    ctx.send_viewport_cmd(ViewportCommand::Close);
                }
            });
    }
}

pub fn main() {
    let option = eframe::NativeOptions {
        viewport: ViewportBuilder::default()
            .with_position([10.0, 10.0])
            .with_inner_size([3000.0, 2000.0])
            .with_clamp_size_to_monitor_size(false),
        ..Default::default()
    };

    eframe::run_native(
        "a large window app",
        option,
        Box::new(|ctx| Box::new(MyApp::new())),
    ).unwrap();
}
```

It works on my windows (with 3 monitors), but I don't have a test
environment for macos

---------

Co-authored-by: Emil Ernerfeldt <[email protected]>
  • Loading branch information
lopo12123 and emilk authored Apr 22, 2024
1 parent 436c671 commit ff8cfc2
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 6 deletions.
23 changes: 17 additions & 6 deletions crates/eframe/src/native/epi_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,23 @@ pub fn viewport_builder<E>(

let mut viewport_builder = native_options.viewport.clone();

let clamp_size_to_monitor_size = viewport_builder.clamp_size_to_monitor_size.unwrap_or(
// On some Linux systems, a window size larger than the monitor causes crashes
cfg!(target_os = "linux"),
);

// Always use the default window size / position on iOS. Trying to restore the previous position
// causes the window to be shown too small.
#[cfg(not(target_os = "ios"))]
let inner_size_points = if let Some(mut window_settings) = window_settings {
// Restore pos/size from previous session

window_settings
.clamp_size_to_sane_values(largest_monitor_point_size(egui_zoom_factor, event_loop));
if clamp_size_to_monitor_size {
window_settings.clamp_size_to_sane_values(largest_monitor_point_size(
egui_zoom_factor,
event_loop,
));
}
window_settings.clamp_position_to_monitors(egui_zoom_factor, event_loop);

viewport_builder = window_settings.initialize_viewport_builder(viewport_builder);
Expand All @@ -37,10 +46,12 @@ pub fn viewport_builder<E>(
viewport_builder = viewport_builder.with_position(pos);
}

if let Some(initial_window_size) = viewport_builder.inner_size {
let initial_window_size = initial_window_size
.at_most(largest_monitor_point_size(egui_zoom_factor, event_loop));
viewport_builder = viewport_builder.with_inner_size(initial_window_size);
if clamp_size_to_monitor_size {
if let Some(initial_window_size) = viewport_builder.inner_size {
let initial_window_size = initial_window_size
.at_most(largest_monitor_point_size(egui_zoom_factor, event_loop));
viewport_builder = viewport_builder.with_inner_size(initial_window_size);
}
}

viewport_builder.inner_size
Expand Down
1 change: 1 addition & 0 deletions crates/egui-winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,7 @@ pub fn create_winit_window_builder<T>(
window_type: _window_type,

mouse_passthrough: _, // handled in `apply_viewport_builder_to_window`
clamp_size_to_monitor_size: _, // Handled in `viewport_builder` in `epi_integration.rs`
} = viewport_builder;

let mut window_builder = winit::window::WindowBuilder::new()
Expand Down
22 changes: 22 additions & 0 deletions crates/egui/src/viewport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ pub struct ViewportBuilder {
pub min_inner_size: Option<Vec2>,
pub max_inner_size: Option<Vec2>,

/// Whether clamp the window's size to monitor's size. The default is `true` on linux, otherwise it is `false`.
///
/// Note: On some Linux systems, a window size larger than the monitor causes crashes
pub clamp_size_to_monitor_size: Option<bool>,

pub fullscreen: Option<bool>,
pub maximized: Option<bool>,
pub resizable: Option<bool>,
Expand Down Expand Up @@ -493,6 +498,15 @@ impl ViewportBuilder {
self
}

/// Sets whether clamp the window's size to monitor's size. The default is `true` on linux, otherwise it is `false`.
///
/// Note: On some Linux systems, a window size larger than the monitor causes crashes
#[inline]
pub fn with_clamp_size_to_monitor_size(mut self, value: bool) -> Self {
self.clamp_size_to_monitor_size = Some(value);
self
}

/// Does not work on X11.
#[inline]
pub fn with_close_button(mut self, value: bool) -> Self {
Expand Down Expand Up @@ -606,6 +620,7 @@ impl ViewportBuilder {
inner_size: new_inner_size,
min_inner_size: new_min_inner_size,
max_inner_size: new_max_inner_size,
clamp_size_to_monitor_size: new_clamp_size_to_monitor_size,
fullscreen: new_fullscreen,
maximized: new_maximized,
resizable: new_resizable,
Expand Down Expand Up @@ -740,6 +755,13 @@ impl ViewportBuilder {

let mut recreate_window = false;

if new_clamp_size_to_monitor_size.is_some()
&& self.clamp_size_to_monitor_size != new_clamp_size_to_monitor_size
{
self.clamp_size_to_monitor_size = new_clamp_size_to_monitor_size;
recreate_window = true;
}

if new_active.is_some() && self.active != new_active {
self.active = new_active;
recreate_window = true;
Expand Down

0 comments on commit ff8cfc2

Please sign in to comment.