11// SPDX-License-Identifier: GPL-3.0-or-later
22// Copyright (C) 2026 Maika Namuo
33
4- use super :: { TOAST_DISPLAY_DURATION , UiApp , windowing:: AppWindow } ;
5- use crate :: ui:: config:: { BarChange , BarOutputEvent , ConfigEffect , ConfigMessage } ;
4+ use super :: { BAR_RETRY_WINDOW , TOAST_DISPLAY_DURATION , UiApp , windowing:: AppWindow } ;
5+ use crate :: ui:: config:: { BarOutputChange , BarOutputEvent , ConfigEffect , ConfigMessage } ;
66use crate :: ui:: settings:: SettingsMessage ;
77use crate :: ui:: visuals:: VisualsMessage ;
88use crate :: ui:: widgets:: { fill, page, scroll_glow:: ScrollGlow } ;
@@ -50,16 +50,12 @@ pub(super) fn layershell_open(settings: NewLayerShellSettings) -> (window::Id, T
5050}
5151
5252pub ( super ) fn shell_event ( event : ShellEvent ) -> Option < Message > {
53+ use BarOutputEvent as Change ;
54+
5355 Some ( match event {
54- ShellEvent :: OutputAdded ( output) => {
55- Message :: BarOutput ( output. id , output. name , BarOutputEvent :: Added )
56- }
57- ShellEvent :: OutputUpdated ( output) => {
58- Message :: BarOutput ( output. id , output. name , BarOutputEvent :: Updated )
59- }
60- ShellEvent :: OutputRemoved ( output) => {
61- Message :: BarOutput ( output. id , output. name , BarOutputEvent :: Removed )
62- }
56+ ShellEvent :: OutputAdded ( o) => Message :: BarOutput ( o. id , o. name , Change :: Added ) ,
57+ ShellEvent :: OutputUpdated ( o) => Message :: BarOutput ( o. id , o. name , Change :: Updated ) ,
58+ ShellEvent :: OutputRemoved ( o) => Message :: BarOutput ( o. id , o. name , Change :: Removed ) ,
6359 ShellEvent :: WindowOutputChanged { window, output } => {
6460 Message :: BarWindowOutput ( window, output. map ( |output| output. id ) )
6561 }
@@ -113,11 +109,22 @@ pub(super) fn app_event(
113109 }
114110}
115111
112+ fn retry_bar ( app : & mut UiApp , closed : bool ) -> Task < Message > {
113+ if app
114+ . last_bar_retry
115+ . is_some_and ( |retry| retry. elapsed ( ) < BAR_RETRY_WINDOW )
116+ {
117+ return if closed { exit ( ) } else { Task :: none ( ) } ;
118+ }
119+ app. last_bar_retry = Some ( Instant :: now ( ) ) ;
120+ app. recreate_main_window ( !closed)
121+ }
122+
116123fn close_main_layer ( app : & mut UiApp , window : window:: Id ) -> Task < Message > {
117- if app. config_page . retry_bar_after_close ( ) {
118- app. handle_bar_config_change ( BarChange :: Monitor )
119- } else {
124+ if app. main_layer_ready {
120125 app. on_window_closed ( window)
126+ } else {
127+ retry_bar ( app, true )
121128 }
122129}
123130
@@ -141,11 +148,11 @@ pub(super) fn update(app: &mut UiApp, msg: Message) -> Task<Message> {
141148 app. frames . borrow_mut ( ) . set_rate ( rate) ;
142149 Task :: none ( )
143150 }
144- Some ( ConfigEffect :: DecorationsChanged ( enabled) ) if app. main_window_is_layer => {
145- app. recreate_popout_windows ( enabled)
151+ Some ( ConfigEffect :: DecorationsChanged ) => app. recreate_visual_windows ( ) ,
152+ Some ( ConfigEffect :: BarChanged ( change) ) => {
153+ app. last_bar_retry = None ;
154+ app. handle_bar_config_change ( change)
146155 }
147- Some ( ConfigEffect :: DecorationsChanged ( enabled) ) => app. recreate_windows ( enabled) ,
148- Some ( ConfigEffect :: BarChanged ( change) ) => app. handle_bar_config_change ( change) ,
149156 Some ( ConfigEffect :: ThemeChanged ) => {
150157 if let Some ( ( _, panel) ) = app. settings_window . as_mut ( ) {
151158 * panel = super :: ActiveSettings :: new ( panel. kind ( ) , & app. visual_manager ) ;
@@ -154,9 +161,7 @@ pub(super) fn update(app: &mut UiApp, msg: Message) -> Task<Message> {
154161 }
155162 None => Task :: none ( ) ,
156163 } ,
157- Message :: Visuals ( VisualsMessage :: SettingsRequested ( kind) ) => {
158- app. open_settings_window ( kind, false )
159- }
164+ Message :: Visuals ( VisualsMessage :: SettingsRequested ( kind) ) => app. open_settings_window ( kind) ,
160165 Message :: Visuals ( visuals_msg) => app. visuals_page . update ( visuals_msg) . map ( Message :: Visuals ) ,
161166 Message :: ToggleConfig => app. toggle_config_window ( ) ,
162167 Message :: TogglePause => {
@@ -189,23 +194,31 @@ pub(super) fn update(app: &mut UiApp, msg: Message) -> Task<Message> {
189194 Task :: none ( )
190195 }
191196 Message :: BarOutput ( id, name, event) => {
192- if app. config_page . sync_bar_output ( id, name, event) {
193- app. handle_bar_config_change ( BarChange :: Monitor )
197+ let change = app. config_page . sync_bar_output ( id, name, event) ;
198+ if app. main_window_is_layer && change != BarOutputChange :: Unchanged {
199+ app. last_bar_retry = None ;
200+ }
201+ if app. main_window_is_layer && change == BarOutputChange :: CurrentRemoved {
202+ app. main_layer_ready = false ;
203+ }
204+ if app. main_window_is_layer && change == BarOutputChange :: Retarget {
205+ retry_bar ( app, false )
194206 } else {
195207 Task :: none ( )
196208 }
197209 }
198- Message :: BarWindowOutput ( window, output) => {
199- if app. main_window_is_layer
200- && window == app . main_window_id
201- && app. config_page . sync_current_bar_output ( output )
202- {
203- app . handle_bar_config_change ( BarChange :: Monitor )
210+ Message :: BarWindowOutput ( window, output)
211+ if app. main_window_is_layer && window == app . main_window_id =>
212+ {
213+ app. main_layer_ready = true ;
214+ if app . config_page . sync_current_bar_output ( output ) {
215+ retry_bar ( app , false )
204216 } else {
205217 Task :: none ( )
206218 }
207219 }
208- // Shell close events are ordered after output changes in the same stream.
220+ Message :: BarWindowOutput ( _, _) => Task :: none ( ) ,
221+ // Output changes and shell closes share one ordered event stream.
209222 Message :: ShellWindowClosed ( window)
210223 if app. main_window_is_layer && window == app. main_window_id =>
211224 {
@@ -214,15 +227,15 @@ pub(super) fn update(app: &mut UiApp, msg: Message) -> Task<Message> {
214227 Message :: ShellWindowClosed ( _) => Task :: none ( ) ,
215228 Message :: WindowOpened ( window) => {
216229 if app. main_window_is_layer && window == app. main_window_id {
217- app. opened_main_layer_window = Some ( window ) ;
230+ app. main_layer_opened = true ;
218231 }
219232 Task :: none ( )
220233 }
221234 // After Opened, the ordered shell close is authoritative for the main layer.
222235 Message :: WindowClosed ( window)
223236 if app. main_window_is_layer && window == app. main_window_id =>
224237 {
225- if app. opened_main_layer_window == Some ( window ) {
238+ if app. main_layer_opened {
226239 Task :: none ( )
227240 } else {
228241 close_main_layer ( app, window)
0 commit comments