Skip to content

Reduce usage of PrimaryWindow #18362

Open

Description

@madsmtm

Bevy has multi-window support by modelling each window as an entity, and then (heavily handwaving) delegating to Winit for the rest. The user can then choose:

  • To create two cameras for their scene, and assign it to different windows.
  • To create sub-apps to get a new World, to allow e.g. running multiple instances of their game (not really supported yet, but I assume this is roughly how we'd go about it).

This is all great, but unfortunately, some functionality uses the PrimaryWindow to implement their windowing. This is basically never desired, as it locks that piece of functionality to only being available in a single window. This issue is intended to track removing instances of this, to improve multi-window support.

I've condensed the usages of PrimaryWindow to essentially the following:

  • bevy_render::camera::RenderTarget::normalize should be changed to not need the primary window. Affects bevy_core_pipeline, bevy_picking, bevy_sprite and bevy_ui.
  • bevy_input_focus::InputFocus (and possibly InputFocusVisible) should be made Components on the window Entity instead of Resources. Affects bevy_winit's ability to update accessibility nodes.
  • bevy_text: , seems to be a remnant of Support window independent UI scaling #5621.

A few previous efforts in this vein:

To be clear: I'm not advocating we get rid of PrimaryWindow, it can be useful for the user, and it's useful for controlling the close behaviour in bevy_window (also discussed in #13698). But we should avoid using it internally in Bevy (perhaps even add it as a Clippy disallowed-types?).

Activity

  1. added
    A-WindowingPlatform-agnostic interface layer to run your app in
    C-BugAn unexpected or incorrect behavior
    S-Needs-TriageThis issue needs to be labelled
    on Mar 17, 2025
  2. madsmtm commented on Mar 17, 2025

    @madsmtm
    MemberAuthor

    @viridia is there a reason why bevy_input_focus::InputFocus is a resource and not a Window-local component?

    And API-wise there, would y'all prefer a required InputFocus(Option<Entity>) component on Window, or InputFocus(Entity) that can be added/removed.
    (Where the None/not present here signifies that nothing has focus, and the event should be delivered to the Window itself).

    Or perhaps: A required InputFocus(Entity), which defaults to Entity = window entity (if that's technically possible).

  3. viridia commented on Mar 18, 2025

    @viridia
    Contributor

    The question, as posed, seems kind of abstract - do you have a concrete use case in mind?

    I'll be honest, in all my years of playing and making games, I have never experienced a game that used more than one window, so it's hard for me to know exactly how multiple windows ought to behave in a game context. However, I have used non-game productivity apps that had more than one window. In these cases, there was only one input focus - that is, only one window could have focus at a time, and only one widget within that window could have focus. So it makes sense to me that input focus would be a singleton.

    Focus behavior isn't really something that applications are supposed to make up for themselves; rather, it's part of the general user interface guidelines for the operating system (the Macintosh Computer Interface Guidelines had a long chapter on this, however that book is no longer in print). And most operating systems assume that there is one keyboard input device active at any given time, or at the very least, if there are multiple keyboard input devices (like a separate numpad) they are all being controlled by the same user.

    Mostly I tried to model things on the browser / JavaScript APIs for managing focus, since that's what I know best.

    The usage of PrimaryWindow is a bit trickier here: mainly it's only meant to be used as a fallback when no widget has focus, so we have somewhere to bubble events to. However, it could also be changed to use whichever window has focus; but at the time I did not know how to get that information from winit.

  4. added
    C-Tracking-IssueAn issue that collects information about a broad development initiative
    on Mar 18, 2025
  5. madsmtm commented on Mar 19, 2025

    @madsmtm
    MemberAuthor

    I think my point with making focus window-relative is that when switching between windows (e.g. two text-boxes in two Firefox windows), you want to keep whatever item is focused focused, regardless of the window itself loosing focus.

    But perhaps I'm misunderstanding the design of bevy_input_focus?

    In any case, you're correct that multi-window support is rare in games.

  6. viridia commented on Mar 19, 2025

    @viridia
    Contributor

    Preserving focus when switching windows is a reasonable thing to want, I agree.

    However, making focus a non-global puts a heavy burden on widget authors. Most widgets just want to know, "am I focused or not?" so that they can draw themselves differently when that is true. Widgets don't generally have knowledge of what window contains them, to answer the question "am I focused" they would need to walk up the hierarchy, find the target camera component, use that to look up the window, etc. This makes it a lot more complicated.

  7. Freyja-moth commented on Dec 25, 2025

    @Freyja-moth
    Contributor

    Wouldn't it be possible to store an InputFocus on each window and then copy that to the InputFocus resource whenever the focused window is changed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-WindowingPlatform-agnostic interface layer to run your app inC-BugAn unexpected or incorrect behaviorC-Tracking-IssueAn issue that collects information about a broad development initiative

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions