@@ -89,6 +89,22 @@ AppMenuButtonGroup::AppMenuButtonGroup(Decoration *decoration)
8989 m_delayedCacheTimer->setInterval (200 );
9090 m_delayedCacheTimer->setSingleShot (true );
9191 connect (m_delayedCacheTimer, &QTimer::timeout, this , &AppMenuButtonGroup::onDelayedCacheTimerTimeout);
92+
93+ m_resetTimer = new QTimer (this );
94+ m_resetTimer->setInterval (250 );
95+ m_resetTimer->setSingleShot (true );
96+ connect (m_resetTimer, &QTimer::timeout, this , &AppMenuButtonGroup::resetButtons);
97+
98+ m_menuLoadFallbackTimer = new QTimer (this );
99+ m_menuLoadFallbackTimer->setInterval (2000 );
100+ m_menuLoadFallbackTimer->setSingleShot (true );
101+ connect (m_menuLoadFallbackTimer, &QTimer::timeout, this , [this ]() {
102+ if (!m_menuLoadedOnce) {
103+ m_menuLoadedOnce = true ;
104+ Q_EMIT menuUpdated ();
105+ }
106+ });
107+
92108 // Assign showing and opacity before we bind the onShowingChanged animation
93109 // so that new windows do not animate.
94110 setAlwaysShow (decoration->menuAlwaysShow ());
@@ -350,6 +366,10 @@ void AppMenuButtonGroup::onMenuReadyForSearch()
350366void AppMenuButtonGroup::onHasApplicationMenuChanged (bool hasMenu)
351367{
352368 if (hasMenu) {
369+ if (!m_menuLoadedOnce) {
370+ m_menuLoadFallbackTimer->start ();
371+ }
372+
353373 if (m_isMenuUpdateThrottled) {
354374 m_pendingMenuUpdate = true ;
355375 return ;
@@ -361,7 +381,10 @@ void AppMenuButtonGroup::onHasApplicationMenuChanged(bool hasMenu)
361381 m_menuUpdateDebounceTimer->stop ();
362382 m_isMenuUpdateThrottled = false ;
363383 m_pendingMenuUpdate = false ;
364- resetButtons ();
384+ m_menuLoadFallbackTimer->stop ();
385+
386+ // Defer reset to avoid flicker during window closure
387+ m_resetTimer->start ();
365388 m_menuLoadedOnce = false ;
366389 }
367390}
@@ -410,14 +433,13 @@ void AppMenuButtonGroup::performDebouncedMenuUpdate()
410433 if (!serviceName.isEmpty () && !menuObjectPath.isEmpty ()) {
411434 m_appMenuModel->updateApplicationMenu (serviceName, menuObjectPath);
412435 } else {
413- resetButtons ();
436+ m_resetTimer-> start ();
414437 }
415438 }
416439}
417440
418441void AppMenuButtonGroup::updateAppMenuModel ()
419442{
420- m_menuLoadedOnce = true ;
421443 auto *deco = qobject_cast<Decoration *>(decoration ());
422444 if (!deco) {
423445 return ;
@@ -426,12 +448,13 @@ void AppMenuButtonGroup::updateAppMenuModel()
426448
427449 // Don't display AppMenu in modal windows.
428450 if (decoratedClient->isModal ()) {
429- resetButtons ();
451+ m_resetTimer-> start ();
430452 return ;
431453 }
432454
433455 if (!decoratedClient->hasApplicationMenu ()) {
434- resetButtons ();
456+ // Defer reset to avoid flicker during window closure
457+ m_resetTimer->start ();
435458 return ;
436459 }
437460
@@ -440,10 +463,15 @@ void AppMenuButtonGroup::updateAppMenuModel()
440463
441464 QMenu *menu = m_appMenuModel->menu ();
442465 if (!menu) {
443- resetButtons ();
466+ // Defer reset to avoid flicker during window closure
467+ m_resetTimer->start ();
444468 return ;
445469 }
446470
471+ m_resetTimer->stop ();
472+ m_menuLoadFallbackTimer->stop ();
473+ m_menuLoadedOnce = true ;
474+
447475 const auto actions = menu->actions ();
448476 const int menuActionCount = actions.count ();
449477
@@ -488,7 +516,7 @@ void AppMenuButtonGroup::updateAppMenuModel()
488516 filterMenu (m_lastSearchQuery);
489517 }
490518 } else {
491- resetButtons ();
519+ resetButtons (); // Immediate reset is intended here for structural changes
492520
493521 // Populate
494522 for (int i = 0 ; i < menuActionCount; ++i) {
0 commit comments