qt: parity tier 3 batch 8 — remaining apprt-side config keys

Five fixes:

  C9 — `window-title-font-family` now applies to the tab-bar font.
  Empty / unset reverts to the application font. Fetched via
  configValue (raw config-file scan) since `?[:0]const u8` isn't
  exposed cleanly through ghostty_config_get on this Qt branch.

  C15 — `split-divider-color` now styles QSplitter handles via
  setStyleSheet. Walks every QSplitter child of the window so
  splits added later pick the colour up. Empty / unset leaves
  Qt's default handle.

  C19 — `split-preserve-zoom.navigation` now persists the zoomed
  state across goto-split. When the source pane is the zoomed one
  and the config bit is true, the destination is re-zoomed. Mirrors
  macOS's navigation setting.

  C21 — `app-notifications.config-reload` now gates a desktop
  notification fired from reloadConfigGlobal, so a successful
  reload has a visible cue. The clipboard-copy bit is read for
  forward compatibility — the Qt frontend doesn't currently post a
  copy notification, but reading the bit means a future toast will
  pick the gate up without touching this site.

  C5 / C6 / C7 / C8 documented as silently honored — they're
  consumed by libghostty itself (renderer for padding/colorspace,
  inherited_config for working-dir / font-size inheritance).

Co-Authored-By: claude-flow <ruv@ruv.net>
pull/12846/head
ntomsic 2026-05-21 09:33:07 -05:00
parent ee6e71a1ae
commit 8bd64d0fa9
1 changed files with 61 additions and 1 deletions

View File

@ -18,6 +18,7 @@
#include <QDir>
#include <QFile>
#include <QColor>
#include <QFont>
#include <QGuiApplication>
#include <QIcon>
#include <QList>
@ -1145,6 +1146,17 @@ void MainWindow::gotoSplit(GhosttySurface *from,
QList<GhosttySurface *> panes = surfacesInTab(tab);
if (panes.size() < 2) return;
// split-preserve-zoom.navigation: if the source pane is currently
// zoomed and the config asks to preserve zoom across navigation,
// we'll re-zoom the destination once the focus moves. Otherwise
// the existing semantics of dropping zoom on navigation apply.
// The struct is { navigation: bool, _padding: u7 }; configGet
// writes the bool into the first byte.
struct PreserveZoom { bool navigation; };
PreserveZoom pz{false};
configGet(s_config, &pz, "split-preserve-zoom");
const bool preserveZoom = pz.navigation && m_zoomed == from;
const auto centerOf = [](GhosttySurface *s) {
return QRect(s->mapToGlobal(QPoint(0, 0)), s->size()).center();
};
@ -1186,7 +1198,15 @@ void MainWindow::gotoSplit(GhosttySurface *from,
}
}
if (target) target->setFocus();
if (target) {
// If a zoom was active on `from` and split-preserve-zoom.navigation
// is on, unzoom-then-rezoom on the destination so the new pane is
// the one filling the tab. toggleSplitZoom on a different pane
// while one is zoomed first restores then zooms — exactly what we
// want.
if (preserveZoom) toggleSplitZoom(target);
target->setFocus();
}
}
void MainWindow::resizeSplit(GhosttySurface *from,
@ -1427,6 +1447,22 @@ void MainWindow::reloadConfigGlobal() {
s_needsPremultiply = configHasCustomShader();
refreshChrome();
// app-notifications.config-reload: post a desktop notification so
// the user has a visible cue that the reload landed. The config is
// a packed-bool struct { clipboard-copy: bool, config-reload: bool };
// configGet writes both bytes. Default is true for both.
// app-notifications.clipboard-copy is currently unused — the Qt
// frontend doesn't post a notification on terminal-driven copy
// operations. The bit is read for forward compatibility so a
// future copy-toast can be gated by the same config without
// touching this site.
struct AppNotifications { bool clipboardCopy; bool configReload; };
AppNotifications n{true, true};
configGet(s_config, &n, "app-notifications");
if (n.configReload)
postNotification(QStringLiteral("Ghostty"),
QStringLiteral("Configuration reloaded."));
}
bool MainWindow::wantsInitialWindow() {
@ -1690,6 +1726,30 @@ void MainWindow::applyWindowConfig() {
m_tabs->tabBar()->setVisible(m_tabs->count() > 1);
}
// window-title-font-family: apply to the tab bar (and the WM
// title via Qt's window-title system font is harder to override
// portably; the tab bar is what users actually look at). Empty /
// unset reverts to the application font.
const QString titleFamily = configValue(QStringLiteral("window-title-font-family"));
if (m_tabs && m_tabs->tabBar()) {
QFont tf = QApplication::font();
if (!titleFamily.isEmpty()) tf.setFamily(titleFamily);
m_tabs->tabBar()->setFont(tf);
}
// split-divider-color: style the QSplitter handles. Stored as a
// CSS-form string in the user's config (e.g. "#ff00ff"). Empty
// leaves Qt's default. Applied via setStyleSheet on this window's
// QSplitter children since splitters can be added/removed at any
// time, walk them on each apply.
const QString divider = configValue(QStringLiteral("split-divider-color"));
const QString splitterCss = divider.isEmpty()
? QString()
: QStringLiteral("QSplitter::handle { background-color: %1; }")
.arg(divider);
for (QSplitter *s : findChildren<QSplitter *>())
s->setStyleSheet(splitterCss);
// window-theme: force a light/dark scheme, or follow the OS. `auto`
// is rewritten to `system` on Linux by libghostty; `ghostty` follows
// the configured background colour's luminance.