Standard GTK file chooser fallback dialog in src/fe-gtk/gtkutil.c
Font chooser dialog in src/fe-gtk/setup.c
Color chooser dialog in src/fe-gtk/setup.c
About dialog in src/fe-gtk/menu.c
Updated edit-target and dark-mode combo callbacks on the color page to stop applying global palette mode directly; they now only switch/refresh the Preferences page source palette.
Changed color-chooser behavior so setup_color_response_cb() writes edits to the selected target snapshot via palette_user_set_color / palette_dark_set_color, then refreshes only page widgets (no runtime palette apply). Also updated dialog initialization to read from the current edit-source snapshot.
Added palette snapshot accessors (palette_user_colors, palette_dark_colors) in the palette API and implementation so Preferences can render from light/dark snapshots safely without mutating runtime palette state.
Runtime palette changes remain on the real apply paths (theme/dark-mode application), not edit-target toggles.
Added deterministic dark-mode precedence by combining explicit signals (theme_name_prefers_dark || property_prefers_dark), while preserving Windows system preference as another dark-enabling signal when available. This ensures “dark if any explicit dark signal is true.”
Re-checked the relevant callers (fe_auto_dark_mode_changed() and fe_apply_theme_for_mode()): they consume fe_system_prefers_dark() output and do not depend on the removed !has_theme_name conditional behavior.
Added a new frontend helper declaration fe_dark_mode_state_is_initialized() in the GTK frontend header so callers can check whether dark-mode state is ready.
Implemented dark-mode initialization tracking in fe-gtk.c via a new static flag, set when auto mode state is externally set and during fe_init(), and exposed it through fe_dark_mode_state_is_initialized().
Added a guarded fallback path that only uses theme lookup/string conversion when palette selection components are invalid (isfinite checks fail), with palette values as secondary fallback there too. This keeps theme colors out of the primary path while preserving robustness for malformed data.
Kept needs_reload dependent on last_sel_* tracking, so changing selection colors in Preferences still triggers immediate CSS regeneration (including across light/dark mode).
Added a new Editing: combo control near the dark-mode selector in setup_create_color_page, with a callback that switches between Light/Dark palette targets and refreshes swatches immediately using the same refresh path as dark-mode UI updates.
Updated the dark-mode combo callback to refresh color swatches based on the explicit editing target (not runtime dark-mode detection), preserving existing runtime theme behavior while editing persisted overrides.
Updated setup_color_response_cb to write color changes to palette_dark_set_color vs palette_user_set_color based on the new edit-target state.
Initialized the editing target in setup_create_color_page from explicit Dark mode selection only (hex_gui_dark_mode == ZOITECHAT_DARK_MODE_DARK), avoiding AUTO runtime detection for editing context.
Added setup_refresh_color_selector_widgets() to iterate color_selector_widgets, resolve each button’s stored color index, and re-run setup_color_button_apply against colors[] so all selectors repaint to the active palette.
Updated setup_create_color_button to register each widget’s palette index (zoitechat-color-index), enabling correct per-button repaint during mode switches.
Preserved existing persistence behavior in setup_color_response_cb (palette_dark_set_color vs palette_user_set_color) so changes remain non-destructive until existing OK/Save flow persists them.
Added a fallback path that derives selection colors from palette values (COL_MARK_FG/COL_MARK_BG) and then samples selected-state colors from a GTK style context when possible, emitting explicit color strings for CSS.
Ensured fallback regeneration is tied to the same reload flow by extending needs_reload tracking with selection palette channels and persisting those last-seen values.
Kept Preferences > Colors foreground/background behavior intact for normal input rendering; only selection-specific CSS is conditionally overridden. Base text/background/caret rules remain unchanged while only text selection uses the new selection logic.
Added/kept lifecycle call sites for main and detached/channel windows, with comments explaining that .zoitechat-dark / .zoitechat-light classes are required for GTK CSS selectors. This includes top/tab windows and server list/edit windows.
Wired dialog/toplevel creation paths in src/fe-gtk/ to call fe_apply_theme_to_toplevel() (without duplicating platform logic), including common prompt/message dialogs and feature-specific dialogs (join, notify, setup, ignore/ban, etc.), each with the requested brief comment near the new call site.
Added a short in-code comment explaining why app-written GTK property state must not permanently block future reads in AUTO mode.
Removed the now-unneeded app_set_prefer_dark tracking behavior from fe_set_gtk_prefer_dark_theme(), so writes no longer disable later fallback reads.
Confirmed fe_auto_dark_mode_changed() still prevents reapply loops by early-returning when enabled == auto_dark_mode_enabled before calling theme/apply logic.
Updated Preferences window creation to explicitly apply the toplevel theme after gtk_widget_show_all() in setup_window_open(), matching your requested timing there.
Added explicit theme application for non-session windows that bypass gtkutil_window_new() and use direct gtk_window_new() in server list UI (editserv and servlist).
Extended mg_apply_setup() to iterate all current GTK toplevels (gtk_window_list_toplevels()) and reapply fe_apply_theme_to_toplevel() during setup/theme reapply flows, ensuring existing windows stay consistent after theme changes. Palette override widgets were not touched.
Preserved font handling exactly as before (input_style->font_desc when available).
Added inline rationale comment clarifying that AUTO/light should continue using palette-managed colors and should not revert to GTK theme defaults in a way that clears custom colors.
Reworked fe_system_prefers_dark() to prioritize non-app-written sources in AUTO flow:
first: gtk-theme-name dark-variant heuristic,
then (Windows): native platform detection via fe_win32_try_get_system_dark,
only then fallback to gtk-application-prefer-dark-theme when no theme-name signal was available and the app has not written that property.
Kept manual LIGHT/DARK behavior unchanged by preserving the existing mode application path (fe_apply_theme_for_mode() still drives fe_set_gtk_prefer_dark_theme() directly).
Verified fe_auto_dark_mode_changed() and fe_init() signal wiring still trigger AUTO palette/theme refreshes on system theme changes (notify::gtk-theme-name and existing notify callback flow remain in place).
Kept user override support for baseline text color and caret color on the input’s text node (#zoitechat-inputbox text).
Added targeted state-aware text rules for :focus and :backdrop (to preserve readability when theme state styling changes), plus a softened :disabled text rule instead of broad global color forcing.
Added explicit selection-node handling (#zoitechat-inputbox text selection) using theme selection tokens so selected text remains readable and aligned with Adwaita/Yaru-style theme behavior.
Preserved the existing Adwaita/Yaru background-image workaround logic, so fallback behavior remains compatible with those themes.
Removed a redundant inline comment in the Windows sysinfo volume-name guard path, with no functional impact.
Removed a redundant inline comment in WinRT toast setup while keeping the same notification/audio attribute behavior.
Added monitor-aware work-area adjustment when maximized (MonitorFromWindow + GetMonitorInfo) and shrink by 1px on the detected taskbar edge (including bottom edge), then apply that rectangle with SetWindowPos. This addresses the “mouse at bottom edge should unhide taskbar” behavior.
Kept the existing HWND_NOTOPMOST safeguard in place after the adjustment, preserving prior not-topmost behavior.
Hooked that helper into mg_windowstate_cb so it runs whenever the main window state changes (while preserving existing maximize/fullscreen preference handling).
Removed an unnecessary explanatory comment above the unconditional early return in log_handler(), leaving only the active behavior.
Removed an unneeded section marker comment before fe_idle() to keep surrounding code cleaner.
Removed an old commented-out gtk_container_set_border_width(...) line that was dead/commented code in cv_tabs_init.
Simplified the tab-switch condition by removing a legacy commented expression from if (is_switching).
Removed repetitive inline comments from return 2; statements in tab-move/history key actions, since behavior is already clear from the surrounding code.
Removed an unnecessary separator comment before replace_handle() for a cleaner transition between functions.
Removed a stale commented-out ST_HEADER line from tabs_settings so the settings table only contains active entries.
Removed a dead commented-out call from setup_apply_trans to reduce noise in the function body.
Removed redundant trailing declaration comments from proxy_user and proxy_pass since the types are already explicit.
Changed the flow to prefer xdg-open first (with sanitized env) and only then fall back to gtk_show_uri, instead of trying GTK first under a potentially broken runtime environment.
Added explicit final warning when both mechanisms fail, and ensured temporary allocations (including xdg_open_path) are released cleanly.
Kept the existing behavior of trying gtk_show_uri first and only using xdg-open as fallback; this change only hardens the fallback path and preserves existing flow/logging.
Added an xdg-open fallback path when gtk_show_uri fails, which improves behavior in AppImage/sandbox-like environments where GTK/GIO handler resolution can fail.
Added warning logs for both the primary gtk_show_uri failure and fallback failure to make future debugging much easier.
Simplified the Windows theme block in fe-gtk.c from a GTK3-conditional compile guard to a direct Windows guard (#ifdef G_OS_WIN32), matching the GTK3-only codebase direction.
Simplified native file chooser guards in gtkutil.c from WIN32 && HAVE_GTK3 to #ifdef WIN32, removing remaining GTK3 compatibility-condition clutter in that file.
Removed GTK2 compatibility shims from headers (fe-gtk.h, gtkutil.h), leaving direct GTK3-facing declarations/includes only (and platform-specific guards unrelated to GTK2 kept as-is).
Cleaned GTK2-specific comments/wording now that behavior is GTK3-native (menu accelerator note and emoji/userlist comment blocks).
Updated src/fe-gtk/meson.build to always resolve gtk_dep from dependency('gtk+-3.0', version: '>= 3.22'), removed the GTK2 fallback branch and -DHAVE_GTK2, and kept AppIndicator detection guarded under host_machine.system() != 'windows' as requested. The GTK X11 helper dep is now unconditionally checked within that same non-Windows block (no gtk3 toggle).
Updated Meson summary output to explicitly report the GTK frontend as GTK+ 3.22+ when enabled, reinforcing that GTK2 builds are no longer expected.
Added a new Meson feature option appindicator (default auto) so this backend is explicitly controllable.
Updated GTK Meson logic to honor -Dappindicator=... and fail fast if enabled is requested but neither ayatana-appindicator3-0.1 nor appindicator3-0.1 is found (prevents silently shipping a build without AppIndicator tray support).
Updated AppImage CI configure flags to force -Dappindicator=enabled, which should prevent AppImage artifacts from lacking StatusNotifier/AppIndicator tray support in XFCE-like environments.
Updated the Win32 WM_COPYDATA handler to recognize that toggle command and perform minimize/restore behavior:
visible window → iconify
hidden window → show/present
while preserving existing behavior for normal remote commands.
Added a Help menu _Update entry with a dedicated zc-menu-update icon constant, so Windows builds can display an appropriate update icon in the Help menu.
Extended icon mapping/fallback logic so emoji/update icons resolve correctly across stock/icon-name paths (zc-menu-emoji, zc-menu-update) including GTK2 stock fallback compatibility.
Added zc-menu-emoji to the input entry fallback icon list so the emoji affordance has a deterministic built-in fallback when theme emoji icons are missing.
Added new update and emoji icon assets in both SVG and PNG for light/dark variants, and registered the PNG resources in the gresource manifest for runtime loading.
Updated the GResource manifest so all menu icons now come from data/icons/menu/{light,dark} PNG files and are embedded with to-pixdata preprocessing, ensuring the app uses one unified internal icon set across platforms.
Generated and added PNG assets for both light and dark menu icon variants under data/icons/menu/ to back the new resource paths used by the GTK menu code.
Fixed menu icon resource detection to fall back from PNG to SVG when probing zc-menu-* entries, so menu item icon lookup no longer fails just because one format is unavailable at runtime.
Updated GTK menu icon loading to use gdk_pixbuf_new_from_resource (instead of ..._at_scale) and added explicit fallback order across variant/light and PNG/SVG resources, which addresses the “red no-entry square” missing-icon behavior you reported.
Kept compatibility with your previous menu resource setup while making loading more resilient on Win32 and other environments where resource/pixbuf behavior differs.
Updated the GTK2 channel list context-menu icon path to use the same helper, removing direct gtk_image_new_from_stock usage for menu icons.
Updated the GTK2 spell-entry popup icon path to use gtkutil_image_new_from_stock, aligning it with the same menu icon set/mapping pipeline used elsewhere (data/icons/menu).
Added a new icon-name→zc-menu-* mapping helper and wired it into gtkutil_image_new_from_stock() as a fallback path for GTK_ICON_SIZE_MENU, after the existing stock-name mapping.