Skip to content

# Changing WindowResolution doesn't impact the window properly inside bevy_winit #24724

Description

@B0ryskart0n

Bevy version and features

bevy = { version = "0.19" }

Relevant system information

  • cargo 1.96.0 (30a34c682 2026-05-25)
  • Latest CachyOS, KDE
AdapterInfo { name: "AMD Radeon RX 9070 XT (RADV GFX1201)", vendor: 4098, device: 30032, device_type: DiscreteGpu, device_pci_bus_id: "0000:03:00.0", driver: "radv", driver_info: "Mesa 26.1.2-arch3.1", backend: Vulkan, subgroup_min_size: 32, subgroup_max_size: 64, transient_saves_memory: false }

What you did

I'm working on a pixel-style game and I'm trying to utilizing resolution scaling for that.
I want to keep my logical resolution as 640x360 at all times, while overriding the scale factor, which should scale the physical resolution.

Below is a MRE of what I'm doing: setting the physical resolution to 1280x720 and the scale_factor_override to Some(2.0):

use bevy::input::common_conditions::input_just_pressed;
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, startup)
        .add_systems(
            Update,
            (
                update_resolution_text,
                change_resolution.run_if(input_just_pressed(KeyCode::Space)),
                reset_resolution.run_if(input_just_pressed(KeyCode::Escape)),
            ),
        )
        .run();
}

fn startup(mut commands: Commands) {
    commands.spawn(Camera2d);
    commands.spawn(Text::default());
    commands.spawn((
        Text2d::new("I'm at [0, -180]"),
        Transform::from_translation(vec3(0.0, -180.0, 0.0)),
    ));
}
fn reset_resolution(mut q_window: Query<&mut Window>) {
    let mut bevy_window = q_window.single_mut().unwrap();
    bevy_window.resolution.set_scale_factor_override(None);
    bevy_window.resolution.set_physical_resolution(1280, 720);
}
fn change_resolution(mut q_window: Query<&mut Window>) {
    let mut bevy_window = q_window.single_mut().unwrap();
    bevy_window.resolution.set_scale_factor_override(Some(2.0));
    bevy_window.resolution.set_physical_resolution(1280, 720);
    // After setting the above I expect a window with HD size, but 640x360 internal resolution
}
/// Only for informative purposes, to display the current window state.
fn update_resolution_text(mut q_text: Query<&mut Text>, q_window: Query<&Window>) {
    let res = q_window.single().unwrap().resolution.clone();

    q_text.single_mut().unwrap().0 = format!(
        "Logical size: {}\nPhysical size: {}\nBase scale: {}\nScale override: {:?}",
        res.size(),
        res.physical_size(),
        res.base_scale_factor(),
        res.scale_factor_override()
    );
}

What went wrong

My expectation would be that I get a window of HD (physical) size and 640x360 logical size.
As a visual check, I've put a Text entity at [0, -180], which should place it just at the bottom of the window.

What happens is that I get a window with physical size: 2560x1440 (double 1280x720) and logical size: 1280x720.
Only after calling the system and changing the resolution an additional time do I get the desired effect.
(If I were to request 1920x1080 with override=3.0 I would get the FHD logical size and triple that in physical size).

This to me is a bug (or at least an unexpected behaviour).
The requested WindowResolution should be resolved to the same window state regardless of the state it's requested in.

I believe the culprit is in

pub(crate) fn changed_windows(
.

I'm happy to work on this and provide a PR, but I'd like to first confirm that this is reproducible for others and we have an agreement of the desired behaviour.

Additional information

I'm also pretty sure that there is another bug in this WindowResolution handling.
If I were to, instead of bevy_window.resolution.set_scale_factor_override(Some(2.0)), set the base scale factor with bevy_window.resolution.set_scale_factor(2.0) then (with the default initial window resolution of 1280x720) it would have no effect on the window state.
Only after resizing the window manually (or setting it to a different value than the current one) I will get the scaling factor effect.
So it looks like: if the physical resolution was not changed, the base_scale_factor will have no effect.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-WindowingPlatform-agnostic interface layer to run your app inC-BugAn unexpected or incorrect behaviorD-StraightforwardSimple bug fixes and API improvements, docs, test and examplesS-Ready-For-ImplementationThis issue is ready for an implementation PR. Go for it!

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions