@@ -33,30 +33,104 @@ extension _DeskTidyHomeBootstrap on _DeskTidyHomePageState {
3333 service.stopPolling ();
3434 }
3535
36+ void _pokeUi () {
37+ if (! mounted) return ;
38+ _setState (() {});
39+ SchedulerBinding .instance.scheduleFrame ();
40+ }
41+
42+ Future <void > _awaitUiFrame ({
43+ Duration timeout = const Duration (milliseconds: 120 ),
44+ }) async {
45+ final binding = WidgetsBinding .instance;
46+ final frameFuture = binding.endOfFrame;
47+ binding.scheduleFrame ();
48+ try {
49+ await frameFuture.timeout (timeout);
50+ } catch (_) {}
51+ }
52+
53+ Future <void > _prepareUiForShow ({bool forceAppTab = false }) async {
54+ _visibilityToken++ ;
55+ if (mounted) {
56+ _setState (() {
57+ _panelVisible = true ;
58+ if (forceAppTab) _selectedIndex = 0 ;
59+ });
60+ }
61+ await _awaitUiFrame ();
62+ }
63+
64+ Future <void > _nudgeWindowSizeForRedraw ({required int token}) async {
65+ if (! mounted) return ;
66+ if (_trayMode || ! _panelVisible) return ;
67+ if (_visibilityToken != token) return ;
68+ try {
69+ final currentSize = await windowManager.getSize ();
70+ await windowManager.setSize (
71+ Size (currentSize.width + 1 , currentSize.height),
72+ );
73+ await windowManager.setSize (currentSize);
74+ } catch (_) {}
75+ _pokeUi ();
76+ }
77+
78+ void _scheduleRedrawNudges () {
79+ final token = _visibilityToken;
80+ unawaited (_nudgeWindowSizeForRedraw (token: token));
81+ unawaited (
82+ Future .delayed (
83+ const Duration (milliseconds: 160 ),
84+ () => _nudgeWindowSizeForRedraw (token: token),
85+ ),
86+ );
87+ unawaited (
88+ Future .delayed (
89+ const Duration (milliseconds: 420 ),
90+ () => _nudgeWindowSizeForRedraw (token: token),
91+ ),
92+ );
93+ }
94+
95+ Future <void > _ensureWindowOpaque () async {
96+ try {
97+ await windowManager.setOpacity (1.0 );
98+ } catch (_) {}
99+ unawaited (
100+ Future .delayed (const Duration (milliseconds: 120 ), () async {
101+ try {
102+ await windowManager.setOpacity (1.0 );
103+ } catch (_) {}
104+ }),
105+ );
106+ }
107+
108+ void _ensurePanelVisible () {
109+ if (! mounted) return ;
110+ if (_trayMode) return ;
111+ if (! _panelVisible) {
112+ _setState (() => _panelVisible = true );
113+ }
114+ }
115+
36116 Future <void > _bringWindowToFrontFromHotkey () async {
37117 _windowHandle = findMainFlutterWindowHandle () ?? _windowHandle;
38118 _trayMode = false ;
39119 _lastActivationMode = _ActivationMode .hotkey;
40120 _ignoreBlurUntil = DateTime .now ().add (const Duration (milliseconds: 600 ));
41-
42- if (mounted) {
43- // Switch to App tab before showing the window to avoid a visible
44- // "tab jump" (e.g. from Settings -> Apps) after the window is already up.
45- if (! _panelVisible || _selectedIndex != 0 ) {
46- _setState (() {
47- _panelVisible = true ;
48- _selectedIndex = 0 ;
49- });
50- }
51- }
121+ await _prepareUiForShow (forceAppTab: true );
52122
53123 await windowManager.setAlwaysOnTop (true );
54124 await windowManager.setSkipTaskbar (true );
55125 await windowManager.restore ();
56126 await windowManager.show ();
127+ _scheduleRedrawNudges ();
57128
58129 _dockManager.onPresentFromHotkey ();
59130 _updateHotkeyPolling ();
131+ await _ensureWindowOpaque ();
132+ _ensurePanelVisible ();
133+ _pokeUi ();
60134
61135 forceSetForegroundWindow (_windowHandle);
62136 await windowManager.focus ();
@@ -97,14 +171,7 @@ extension _DeskTidyHomeBootstrap on _DeskTidyHomePageState {
97171 _ignoreBlurUntil = DateTime .now ().add (const Duration (milliseconds: 600 ));
98172
99173 // 先准备内容,避免白屏闪烁
100- if (mounted) {
101- // Prepare content and switch to App tab before showing the window.
102- // This makes hotkey wake-up feel immediate and avoids a delayed tab swap.
103- _setState (() {
104- _panelVisible = true ;
105- _selectedIndex = 0 ;
106- });
107- }
174+ await _prepareUiForShow (forceAppTab: true );
108175
109176 // 加载快捷键专属窗口布局并应用
110177 final layout = await AppPreferences .loadHotkeyWindowLayout ();
@@ -117,24 +184,15 @@ extension _DeskTidyHomeBootstrap on _DeskTidyHomePageState {
117184 Offset (bounds.x.toDouble (), bounds.y.toDouble ()),
118185 );
119186
120- // [Anti-Flash] 先设置透明度为0,防止白屏闪烁
121- await windowManager.setOpacity (0.0 );
122-
123187 await windowManager.setAlwaysOnTop (true );
124188 await windowManager.setSkipTaskbar (true );
125189 await windowManager.restore (); // 先恢复窗口状态
126190 await windowManager.show (); // 再显示窗口
127191
128- // [Fix] Force a tiny resize to trigger WM_SIZE and sync child HWND in Release mode
129- final currentSize = await windowManager.getSize ();
130- await windowManager.setSize (
131- Size (currentSize.width + 1 , currentSize.height),
132- );
133- await windowManager.setSize (currentSize);
192+ _scheduleRedrawNudges ();
134193
135- // 等待一帧渲染
136- await Future .delayed (const Duration (milliseconds: 50 ));
137- await windowManager.setOpacity (1.0 );
194+ await _ensureWindowOpaque ();
195+ _ensurePanelVisible ();
138196
139197 _dockManager.onPresentFromHotkey ();
140198 _updateHotkeyPolling ();
@@ -144,6 +202,7 @@ extension _DeskTidyHomeBootstrap on _DeskTidyHomePageState {
144202 await windowManager.focus (); // 也调用 Flutter 的 focus 作为补充
145203 await _syncDesktopIconVisibility ();
146204 // _startDesktopIconSync removed (handled by service)
205+ _pokeUi ();
147206
148207 unawaited (
149208 Future .delayed (const Duration (milliseconds: 800 ), () {
@@ -162,6 +221,9 @@ extension _DeskTidyHomeBootstrap on _DeskTidyHomePageState {
162221 });
163222 });
164223 } finally {
224+ unawaited (_ensureWindowOpaque ());
225+ _ensurePanelVisible ();
226+ _pokeUi ();
165227 _hotkeyPresentInFlight = false ;
166228 if (_hotkeyRefocusRequested) {
167229 _hotkeyRefocusRequested = false ;
@@ -233,11 +295,14 @@ extension _DeskTidyHomeBootstrap on _DeskTidyHomePageState {
233295 await windowManager.setSkipTaskbar (false );
234296 await windowManager.show ();
235297 await windowManager.restore ();
298+ _scheduleRedrawNudges ();
236299 await windowManager.focus ();
237300 await _syncDesktopIconVisibility ();
238301 if (mounted) _setState (() => _panelVisible = true );
239302 // _startDesktopIconSync removed
240303 _onMainWindowPresented ();
304+ unawaited (_ensureWindowOpaque ());
305+ _pokeUi ();
241306 }
242307 _updateHotkeyPolling ();
243308 },
0 commit comments