fix(theme): stop the boot theme re-send from resurrecting hidden chrome
Since comments-ux 0002, WasmTool re-sends the shell theme through kicadSetColorTheme on every boot; setColorTheme ran CommonSettingsChanged unconditionally, which recreates the menubar/toolbars — and they come back SHOWN, undoing the kicadSetChrome(false) the read-only viewer and mobile canvas-only mode applied moments earlier (CI: read-only-editor + mobile-editor "9 visible menu titles"). Two-part fix in pcbjam_theme: - early-out when the requested theme AND the wx dark-chrome flag are already applied — the every-boot re-send (still needed for warm relaunches with stale MEMFS settings) becomes a true no-op; - after a REAL apply, re-assert the hidden chrome via a hook the merged image installs (kicadSetChrome(false) when the snapshot says hidden), queued with CallAfter from inside the fiber body so FIFO lands it behind the CallAfter-deferred ReCreateMenuBar. Covers viewers/mobile users toggling dark mode mid-session. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y32etYBCKV6t1qDoLoGmgF
This commit is contained in:
parent
3ff53f0a78
commit
b0e84ff849
2 changed files with 52 additions and 6 deletions
|
|
@ -83,6 +83,14 @@ bool pcbCollabTestClearSelection();
|
||||||
void pcbSetColorTheme( std::string aTheme );
|
void pcbSetColorTheme( std::string aTheme );
|
||||||
void pcbSetDarkChrome( bool aDark );
|
void pcbSetDarkChrome( bool aDark );
|
||||||
|
|
||||||
|
// Post-theme-apply hook shared with pcbjam_theme.h — identical inline-variable
|
||||||
|
// definition instead of including that header (this TU stays header-light);
|
||||||
|
// keep the two declarations in sync.
|
||||||
|
namespace pcbjam_theme
|
||||||
|
{
|
||||||
|
inline void ( *g_afterThemeApplied )() = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool schEditorActive();
|
bool schEditorActive();
|
||||||
int schLibsSymbolUsage( std::string aLibNickname, std::string aSymbolName );
|
int schLibsSymbolUsage( std::string aLibNickname, std::string aSymbolName );
|
||||||
void schCollabApply( std::string aJson );
|
void schCollabApply( std::string aJson );
|
||||||
|
|
@ -398,6 +406,15 @@ static void collabSetStyle( std::string aJson )
|
||||||
// Each side no-ops on a null frame.
|
// Each side no-ops on a null frame.
|
||||||
static void setColorTheme( std::string aTheme )
|
static void setColorTheme( std::string aTheme )
|
||||||
{
|
{
|
||||||
|
// A real theme apply rebuilds the menubar/toolbars, which come back
|
||||||
|
// SHOWN — re-hide them when the chrome is supposed to be hidden
|
||||||
|
// (read-only viewer / mobile canvas-only). Installed here, not in
|
||||||
|
// pcbjam_theme.h, because the chrome snapshot is merged-image state.
|
||||||
|
pcbjam_theme::g_afterThemeApplied = []() {
|
||||||
|
if( s_chromeSnap.valid )
|
||||||
|
kicadSetChrome( false );
|
||||||
|
};
|
||||||
|
|
||||||
pcbSetColorTheme( aTheme );
|
pcbSetColorTheme( aTheme );
|
||||||
schSetColorTheme( aTheme );
|
schSetColorTheme( aTheme );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,17 @@ extern "C" bool wxWasmGetDarkAppearance();
|
||||||
|
|
||||||
namespace pcbjam_theme {
|
namespace pcbjam_theme {
|
||||||
|
|
||||||
|
/** Merged-image hook (installed by kicad_editor_embind.cpp): re-assert the
|
||||||
|
* canvas-only chrome state after a theme apply. CommonSettingsChanged
|
||||||
|
* recreates the menubar (CallAfter-deferred, eda_base_frame.cpp) and the
|
||||||
|
* toolbars, and they come back SHOWN — without this, a theme apply
|
||||||
|
* resurrects the chrome kicadSetChrome(false) hid (read-only viewer /
|
||||||
|
* mobile canvas-only). Inline variable: the dispatcher TU re-declares the
|
||||||
|
* identical definition instead of including this (deliberately
|
||||||
|
* header-light) — keep the two in sync. Null in the standalone bundles,
|
||||||
|
* which have no chrome API. */
|
||||||
|
inline void ( *g_afterThemeApplied )() = nullptr;
|
||||||
|
|
||||||
/** Set the chrome appearance FLAG only — no widget traffic, no fiber. Safe
|
/** Set the chrome appearance FLAG only — no widget traffic, no fiber. Safe
|
||||||
* from the browser main thread at any point (it writes one bool in shared
|
* from the browser main thread at any point (it writes one bool in shared
|
||||||
* wasm memory); the embedder calls it at onRuntimeInitialized, BEFORE main()
|
* wasm memory); the embedder calls it at onRuntimeInitialized, BEFORE main()
|
||||||
|
|
@ -77,22 +88,40 @@ inline void setColorTheme( EDA_DRAW_FRAME* aFrame, const std::string& aTheme )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pcbjam_collab::runOnFiber( aFrame, [aFrame, aTheme]() {
|
pcbjam_collab::runOnFiber( aFrame, [aFrame, aTheme]() {
|
||||||
if( APP_SETTINGS_BASE* cfg = aFrame->config() )
|
// The shell only ever sends our dark theme name or the builtin
|
||||||
|
// default, so the chrome appearance rides on that distinction.
|
||||||
|
const bool dark = aTheme != "_builtin_default";
|
||||||
|
const wxString theme = wxString::FromUTF8( aTheme.c_str() );
|
||||||
|
APP_SETTINGS_BASE* cfg = aFrame->config();
|
||||||
|
|
||||||
|
// The shell re-sends its theme on EVERY boot (a warm relaunch can
|
||||||
|
// have stale MEMFS settings from a HomePage theme switch) — skip the
|
||||||
|
// apply when nothing changes: CommonSettingsChanged below is not
|
||||||
|
// free, it rebuilds the menubar and toolbars.
|
||||||
|
if( cfg && cfg->m_ColorTheme == theme && dark == wxWasmGetDarkAppearance() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( cfg )
|
||||||
{
|
{
|
||||||
cfg->m_ColorTheme = wxString::FromUTF8( aTheme.c_str() );
|
cfg->m_ColorTheme = theme;
|
||||||
// Persist now — wasm sessions never exit cleanly, so the normal
|
// Persist now — wasm sessions never exit cleanly, so the normal
|
||||||
// save-on-close path would lose the choice.
|
// save-on-close path would lose the choice.
|
||||||
Pgm().GetSettingsManager().Save( cfg );
|
Pgm().GetSettingsManager().Save( cfg );
|
||||||
}
|
}
|
||||||
|
|
||||||
// wx chrome first (panels/toolbars), then the GAL canvas colors. The
|
// wx chrome first (panels/toolbars), then the GAL canvas colors.
|
||||||
// shell only ever sends our dark theme name or the builtin default,
|
syncChromeAppearance( dark );
|
||||||
// so the chrome appearance rides on that distinction.
|
|
||||||
syncChromeAppearance( aTheme != "_builtin_default" );
|
|
||||||
|
|
||||||
// 0 flags: no env/text vars changed; the frame's override chain still
|
// 0 flags: no env/text vars changed; the frame's override chain still
|
||||||
// unconditionally reloads colors and recaches the view.
|
// unconditionally reloads colors and recaches the view.
|
||||||
aFrame->CommonSettingsChanged( 0 );
|
aFrame->CommonSettingsChanged( 0 );
|
||||||
|
|
||||||
|
// Queued from INSIDE the fiber body, AFTER CommonSettingsChanged: the
|
||||||
|
// menubar rebuild it triggers is itself a CallAfter on this same
|
||||||
|
// handler, so FIFO puts the re-assert behind the rebuilt (shown)
|
||||||
|
// menubar.
|
||||||
|
if( void ( *hook )() = g_afterThemeApplied )
|
||||||
|
aFrame->CallAfter( hook );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue