Skip to content

fix: honor AppView.FLET_APP_HIDDEN in Windows and Linux desktop runners#6527

Open
ihmily wants to merge 2 commits into
flet-dev:mainfrom
ihmily:fix/window-hide-start
Open

fix: honor AppView.FLET_APP_HIDDEN in Windows and Linux desktop runners#6527
ihmily wants to merge 2 commits into
flet-dev:mainfrom
ihmily:fix/window-hide-start

Conversation

@ihmily
Copy link
Copy Markdown
Contributor

@ihmily ihmily commented May 27, 2026

Description

This PR fixes a Windows desktop startup issue where ft.run(..., view=ft.AppView.FLET_APP_HIDDEN) does not keep the native app window fully hidden during startup.

Although the Python and Dart layers already support hidden startup mode via FLET_HIDE_WINDOW_ON_START, the Windows native runner still called Show() unconditionally on the first Flutter frame. As a result, flet.exe could briefly flash in the top-left corner before the app finished operations such as resizing or centering the window.

This change updates the Windows desktop runner to respect FLET_HIDE_WINDOW_ON_START before showing the native window.

The same fix is also applied to the Windows app template runner so generated apps behave consistently.

Fixes #5914#5897

Test code

import asyncio

import flet as ft


async def main(page: ft.Page):
    print("Window is hidden on start. Will show after 3 seconds...")
    page.add(
        ft.SafeArea(
            content=ft.Column(
                controls=[
                    ft.Text("Hello!"),
                ]
            )
        )
    )

    # some configuration that we want to do before showing the window
    page.window.width = 300
    page.window.height = 200
    page.update()
    await page.window.center()

    # wait for 3 seconds before showing the window
    await asyncio.sleep(3)

    # show the window
    page.window.visible = True
    page.update()


if __name__ == "__main__":
    ft.run(main, view=ft.AppView.FLET_APP_HIDDEN)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist

  • I signed the CLA.
  • I have performed a self-review of my own code.
  • My code follows the style guidelines of this project.
  • I have commented my code, particularly in hard-to-understand areas.
  • My changes generate no new warnings.
  • New and existing tests pass locally with my changes.
  • I have made corresponding documentation changes, if applicable.
  • I have added changelog entries for user-facing changes, if applicable.
  • I have updated release guide pages and website/sidebars.yml for breaking changes, removals, and deprecations, if applicable.

Screenshots

Before:
On Windows, flet.exe briefly flashes in the top-left corner during startup.
After:
With AppView.FLET_APP_HIDDEN, the window remains hidden until page.window.visible = True.

_2026_05_27_15_39_27_670.mp4

Summary by Sourcery

Respect hidden-startup configuration when showing Windows desktop windows.

Bug Fixes:

  • Prevent Windows desktop runner from briefly showing the app window when FLET_HIDE_WINDOW_ON_START is set.
  • Ensure generated Windows app templates also keep the window hidden on startup when configured to do so.

Enhancements:

  • Add a shared utility for checking the presence of environment variables in Windows runners and templates.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've reviewed this pull request using the Sourcery rules engine

Copy link
Copy Markdown
Contributor

@FeodorFitsner FeodorFitsner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks — diagnosis is spot on. The Windows runner called Show() on first frame unconditionally, racing past the hidden-on-start logic in packages/flet/lib/src/utils.dart (L19-24). Gating it on FLET_HIDE_WINDOW_ON_START is right, and the [&][this, hide_window_on_start] capture is a real fix too (callback fires after OnCreate returns).

One thing: Windows-only. macOS is already covered via window_manager's hiddenWindowAtLaunch(), but Linux still does unconditional gtk_widget_show(window) at linux/my_application.cc:51 — and ixenion in #5897 is on Linux reporting it persists. Extend the guard there too, or track as follow-up?

@chenyyoung
Copy link
Copy Markdown

大佬,可否重新编译一个0.28.3的客户端版本,,,,新版本变更太大了,迁移太难了。
Could you recompile a client version of 0.28.3? The changes in the new version are too significant, making migration extremely difficult.

@ihmily
Copy link
Copy Markdown
Contributor Author

ihmily commented May 29, 2026

大佬,可否重新编译一个0.28.3的客户端版本,,,,新版本变更太大了,迁移太难了。
Could you recompile a client version of 0.28.3? The changes in the new version are too significant, making migration extremely difficult.

sure, Then I will compile a package with version 0.28.3 for you

@chenyyoung
Copy link
Copy Markdown

大佬,可否重新编译一个0.28.3的客户端版本,,,,新版本变更太大了,迁移太难了。
Could you recompile a client version of 0.28.3? The changes in the new version are too significant, making migration extremely difficult.

sure, Then I will compile a package with version 0.28.3 for you

感谢大佬,,,看到0.85.2中你是国内的贡献者的时候,我就知道窗口居中闪烁的问题有救了。。。哈哈。

@ihmily ihmily changed the title fix: honor AppView.FLET_APP_HIDDEN in Windows desktop runners fix: honor AppView.FLET_APP_HIDDEN in Windows and Linux desktop runners May 29, 2026
@ihmily
Copy link
Copy Markdown
Contributor Author

ihmily commented May 29, 2026

@FeodorFitsner

Good catch — I extended the fix to Linux as well.
The Linux runner was still showing the native window unconditionally in client/linux/my_application.cc via:

gtk_widget_show(GTK_WIDGET(window));

That meant the GTK window was mapped before Dart/window_manager had a chance to apply the hidden-on-start behavior, so AppView.FLET_APP_HIDDEN could still appear briefly or start visible.
I fixed it by changing that call to:

gtk_widget_realize(GTK_WIDGET(window));

So the native window is created/realized, but not shown yet. That keeps the actual show/hide decision in Dart, where setupDesktop() and window_manager already respect FLET_HIDE_WINDOW_ON_START.
I also updated the Dart-side Linux window flow so that when the app starts hidden, a requested page.window.center() / window alignment is deferred until the native show event. This fixes the Linux case where centering before visible = True had no effect on a still-hidden window. macOS remains unchanged since it was already covered by hiddenWindowAtLaunch().

Linux native runner: gtk_widget_show(window) -> gtk_widget_realize(window)
Linux Dart window flow: defer center() / alignment until the hidden window is actually shown

New Files modified:
client/linux/my_application.cc
packages/flet/lib/src/services/window.dart

Test

Refer to @ixenion in # 5897

And nor await page.window.center() neither page.window.alignment = ft.Alignment.CENTER works for me.
all the time it chooses random point to open.

I also test it by Ubuntu 24.04 running in WSL2 (host is windows 10). The test results are consistent with what @ixenion mentioned. For example Launching with the hidden window mode doesn't work properly. Additionally, the window centering is intermittent and does not match our expected behavior.

As shown below

Before

_2026_05_29_14_44_13_763.mp4

Fixed

_2026_05_29_14_46_14_379.mp4

Kindly review and merge it promptly.

@ihmily
Copy link
Copy Markdown
Contributor Author

ihmily commented May 29, 2026

Could you recompile a client version of 0.28.3? The changes in the new version are too significant, making migration

@chenyyoung

Download fix/window-hide-start-for-windows:flet_desktop_package-v0.28.3

After extracting the archive, replace the folder Lib\site-packages\flet_desktop\app\flet with the flet folder from the extracted files.

@chenyyoung
Copy link
Copy Markdown

Could you recompile a client version of 0.28.3? The changes in the new version are too significant, making migration

@chenyyoung

Download fix/window-hide-start-for-windows:flet_desktop_package-v0.28.3

After extracting the archive, replace the folder Lib\site-packages\flet_desktop\app\flet with the flet folder from the extracted files.

Thanks so much

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes the Windows desktop runner so ft.run(..., view=AppView.FLET_APP_HIDDEN) (which sets FLET_HIDE_WINDOW_ON_START=true) actually keeps the native window hidden during startup, eliminating the brief top-left flash before Dart-side positioning happens. The Linux runner is changed to realize the window without showing it so Dart can control the show timing, and WindowService defers alignment/center calls on Linux until after the first show event. The window event handler is also refactored to avoid querying getWindowState() during close/hide/post-destroy transitions, where the call can hang or race.

Changes:

  • Add HasEnvironmentVariable helper in Windows runner utils.{h,cpp} (both client and template) and use it in FlutterWindow::OnCreate to skip the first-frame Show() when FLET_HIDE_WINDOW_ON_START is set.
  • Replace gtk_widget_show(window) with gtk_widget_realize(window) in the Linux client runner, matching the existing template behavior.
  • Refactor WindowService: cache helpers _cacheWindowState/_snapshotWindowState, Linux-only deferred alignment/center until the show event, and special-cased event handling for close/hide/closing state to avoid awaiting getWindowState().

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
client/windows/runner/utils.h Declares HasEnvironmentVariable helper.
client/windows/runner/utils.cpp Implements HasEnvironmentVariable via GetEnvironmentVariableW + GetLastError.
client/windows/runner/flutter_window.cpp Skip Show() on first frame when FLET_HIDE_WINDOW_ON_START is present.
sdk/python/templates/build/.../windows/runner/utils.h Template mirror of new helper declaration.
sdk/python/templates/build/.../windows/runner/utils.cpp Template mirror of helper implementation.
sdk/python/templates/build/.../windows/runner/flutter_window.cpp Template mirror of conditional Show().
client/linux/my_application.cc Realize window instead of showing it, letting Dart control visibility.
packages/flet/lib/src/services/window.dart Defer Linux alignment/center until show; refactor event handling to avoid getWindowState() during close/hide.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flet windows don't open centered by default

4 participants