1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00

eframe: apply ViewportBuilder::with_monitor on the glow backend (#8302)

## Problem

`ViewportBuilder::with_monitor(idx)` is a **no-op on the glow backend**.
A window
built with `.with_monitor(...)` opens on the default monitor, not
fullscreen —
while the exact same code works on wgpu.

The monitor → `Fullscreen::Borderless(Some(monitor))` resolution only
lives in
`egui_winit::create_window`, which the **wgpu** backend uses. The
**glow**
backend builds its windows straight from
`egui_winit::create_winit_window_attributes`
at two sites in `glow_integration.rs` — the initial window and
per-viewport
deferred windows — so the monitor is never applied there.

## Repro

A multi-viewport app on the glow renderer with any viewport built via
`ViewportBuilder::default().with_monitor(1)` opens that window on
monitor 0,
un-fullscreen. Switching to the wgpu renderer places it correctly. Seen
on a
3-monitor GNOME/Wayland setup where the main window and secondary
viewports all
need to land borderless-fullscreen on specific outputs.

## Fix

Extract the resolution into a public
`apply_monitor_to_window_attributes` in
`egui-winit` and call it from `create_window` (unchanged behaviour) plus
both
glow window-creation sites, so `with_monitor` behaves the same on glow
and wgpu.

No public API change beyond the new helper; no behaviour change on wgpu.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
Sylvain
2026-08-25 14:07:33 +02:00
committed by GitHub
parent 7aa7f84858
commit 144b1a1f83
2 changed files with 38 additions and 15 deletions

View File

@@ -1094,9 +1094,10 @@ impl GlutinWindowContext {
//
// The justification for FallbackEgl over PreferEgl is at https://github.com/emilk/egui/pull/2526#issuecomment-1400229576 .
.with_preference(glutin_winit::ApiPreference::FallbackEgl)
.with_window_attributes(Some(egui_winit::create_winit_window_attributes(
egui_ctx,
viewport_builder.clone(),
.with_window_attributes(Some(egui_winit::apply_monitor_to_window_attributes(
egui_winit::create_winit_window_attributes(egui_ctx, viewport_builder.clone()),
&viewport_builder,
event_loop,
)));
let (window, gl_config) = {
@@ -1262,9 +1263,13 @@ impl GlutinWindowContext {
window
} else {
log::debug!("Creating a window for viewport {viewport_id:?}");
let window_attributes = egui_winit::create_winit_window_attributes(
&self.egui_ctx,
viewport.builder.clone(),
let window_attributes = egui_winit::apply_monitor_to_window_attributes(
egui_winit::create_winit_window_attributes(
&self.egui_ctx,
viewport.builder.clone(),
),
&viewport.builder,
event_loop,
);
if window_attributes.transparent()
&& self.gl_config.supports_transparency() == Some(false)

View File

@@ -1971,12 +1971,33 @@ pub fn create_window(
) -> Result<Window, winit::error::OsError> {
profiling::function_scope!();
let mut window_attributes = create_winit_window_attributes(egui_ctx, viewport_builder.clone());
let window_attributes = apply_monitor_to_window_attributes(
create_winit_window_attributes(egui_ctx, viewport_builder.clone()),
viewport_builder,
event_loop,
);
// Resolve target monitor index → MonitorHandle, so the window is created
// directly in borderless fullscreen on the requested output. This is the
// only reliable way to target a specific monitor under Wayland, and also
// avoids the Mutter race where OuterPosition is ignored pre-mapping.
let window = event_loop.create_window(window_attributes)?;
apply_viewport_builder_to_window(egui_ctx, &window, viewport_builder);
Ok(window)
}
/// Apply [`ViewportBuilder::with_monitor`] to freshly-built [`winit::window::WindowAttributes`].
///
/// Resolve the target monitor index → `MonitorHandle` and request borderless
/// fullscreen on that output, so the window is created directly on the right
/// monitor. This is the only reliable way to target a specific monitor under
/// Wayland, and also avoids the Mutter race where `OuterPosition` is ignored
/// pre-mapping.
///
/// Must be called by every backend that builds its own window from
/// [`create_winit_window_attributes`] (the glow backend and per-viewport window
/// creation do this) — otherwise `with_monitor` silently does nothing there.
pub fn apply_monitor_to_window_attributes(
mut window_attributes: winit::window::WindowAttributes,
viewport_builder: &ViewportBuilder,
event_loop: &ActiveEventLoop,
) -> winit::window::WindowAttributes {
if let Some(idx) = viewport_builder.monitor {
if let Some(monitor) = event_loop.available_monitors().nth(idx) {
window_attributes = window_attributes
@@ -1988,10 +2009,7 @@ pub fn create_window(
);
}
}
let window = event_loop.create_window(window_attributes)?;
apply_viewport_builder_to_window(egui_ctx, &window, viewport_builder);
Ok(window)
window_attributes
}
pub fn create_winit_window_attributes(