fix(audit): pass 1 — latent QT-hide bug, dead includes, header tidy

- QuickTerminal.cpp animateIn: clear the previous `finished -> hide()`
  handler that animateOut left attached to the cached
  QPropertyAnimation. Without this, an out-then-in cycle (autohide
  followed by re-toggle while the fade-out was still running) lets
  the leftover hide handler fire at the end of the in-fade and
  silently hide the just-revealed window. Latent in the original
  MainWindow code; fixed during the extraction.
- QuickTerminal.cpp kAnimProperty: rename `_ghastty_qt_anim` →
  `ghastty.quickterm.anim`. Qt reserves the underscore-prefix
  property namespace; the dotted form is application-scoped and
  unambiguous.
- QuickTerminal.cpp setupLayerShell: comment the `screen` reassignment
  after `ls->setScreen(...)` so a future reader doesn't think the
  anchor is being re-pointed. The reassignment is for sizing only.
- MainWindow.h: drop stale `<QRect>` and `<QStringList>` includes
  (UndoEntry-era leftovers; consumers that need them include them
  directly), and drop the orphaned three-line comment that survived
  the m_quickTerminalAnim member removal.
- UndoStack.{h,cpp} pushTab: drop the dead `quickTerminal` parameter.
  Every caller in MainWindow.cpp already gates on `!m_quickTerminal`,
  so the function-local re-check was vacuous; the comment now
  documents the caller-side contract.
- XkbState.cpp: include `<xkbcommon/xkbcommon.h>` directly per IWYU
  (was reaching it transitively through XkbState.h); cache the
  XkbTracker singleton in `consumedMods` instead of calling
  `XkbTracker::instance()` twice in succession.
- GhosttySurface.cpp: drop the now-dead `XkbTracker.h` include — the
  TU's only XkbTracker reference moved into XkbState.cpp during
  Phase 7. The remaining mention of "XkbTracker" in this file is a
  doc comment, not code.

Co-Authored-By: claude-flow <ruv@ruv.net>
pull/12846/head
ntomsic 2026-05-23 15:43:22 -05:00
parent f070cff504
commit 6a90de48d9
7 changed files with 24 additions and 19 deletions

View File

@ -8,7 +8,6 @@
#include "SearchBar.h"
#include "TabWidget.h"
#include "Util.h"
#include "XkbTracker.h"
#include <algorithm>
#include <cmath>

View File

@ -440,7 +440,7 @@ void MainWindow::removeSurface(GhosttySurface *surface) {
// double-stack. Also skip the quick terminal (which doesn't push
// to either stack by design).
if (index >= 0 && m_tabs->count() > 1 && !m_quickTerminal)
undo::pushTab(m_tabs->tabText(index), m_quickTerminal);
undo::pushTab(m_tabs->tabText(index));
if (index >= 0) m_tabs->removeTab(index);
if (parent) parent->deleteLater(); // page; destroys the surface too
// The surface close was already confirmed; don't re-prompt on the
@ -458,7 +458,7 @@ void MainWindow::closeTab(int index) {
// undo::pushTab is no-op for the last tab in a window — that close
// ends up triggering undo::pushWindow via closeEvent instead.
if (m_tabs->count() > 1 && !m_quickTerminal)
undo::pushTab(m_tabs->tabText(index), m_quickTerminal);
undo::pushTab(m_tabs->tabText(index));
const auto inTab = page->findChildren<GhosttySurface *>();
for (GhosttySurface *s : inTab) m_surfaces.removeOne(s);
// If the zoomed surface was in this tab, clear the stash so a later

View File

@ -1,9 +1,7 @@
#pragma once
#include <QList>
#include <QRect>
#include <QSize>
#include <QStringList>
#include <QWidget>
#include "ghostty.h"
@ -227,9 +225,6 @@ private:
ghostty_surface_t m_firstTabParent = nullptr; // inherited by the 1st tab
bool m_skipCloseConfirm = false; // close already confirmed elsewhere
bool m_quickTerminal = false; // this is the dropdown quick terminal
// Per-window opacity animation for the quick terminal (fade in/out
// using quick-terminal-animation-duration). Owned by quickterm/'s
// dynamic-property cache on this widget; cleared on widget delete.
QSize m_defaultWindowSize; // for RESET_WINDOW_SIZE; from INITIAL_SIZE
// Last cell size reported by libghostty for this window's surfaces
// (CELL_SIZE action). Stored so future grid-snap resizing can use

View File

@ -1,5 +1,7 @@
#include "XkbState.h"
#include <xkbcommon/xkbcommon.h>
#include "../XkbTracker.h"
XkbState &XkbState::instance() {
@ -70,8 +72,8 @@ ghostty_input_mods_e XkbState::consumedMods(uint32_t keycode,
depressed |= (1u << m_idxSuper);
// Use the live group from the tracker so a layout switch (e.g.
// us↔ru) takes effect immediately.
const uint32_t group =
XkbTracker::instance() ? XkbTracker::instance()->activeGroup() : 0;
XkbTracker *t = XkbTracker::instance();
const uint32_t group = t ? t->activeGroup() : 0;
xkb_state_update_mask(m_query, depressed, 0, 0, 0, 0, group);
const xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2(
m_query, keycode, XKB_CONSUMED_MODE_XKB);

View File

@ -25,8 +25,10 @@ namespace {
// Anim and toggle live on the QObject child tree of `window`, so
// they die with it. We keep the QPropertyAnimation as a dynamic
// property so callers don't need to thread it through.
constexpr const char *kAnimProperty = "_ghastty_qt_anim";
// property so callers don't need to thread it through. The "_q_"
// underscore-prefix space is reserved by Qt; any other prefix is
// fine and the dotted form keeps it visibly application-scoped.
constexpr const char *kAnimProperty = "ghastty.quickterm.anim";
// Read quick-terminal-animation-duration (seconds) and convert to ms.
// Clamps to a sane range so a misconfigured 0/negative value doesn't
@ -98,6 +100,9 @@ void setupLayerShell(QWidget *window) {
screen = QGuiApplication::primaryScreen();
}
ls->setScreen(screen);
// For sizing only — LayerShellQt already has the anchor screen above
// (or fell back to the QWindow's screen via setScreen(nullptr)). We
// need a non-null QScreen below to read its pixel dimensions.
if (!screen) screen = handle->screen();
// quick-terminal-space-behavior (`remain` / `move`) is intentionally
@ -171,6 +176,12 @@ void animateIn(QWidget *window) {
// animations.
QPropertyAnimation *anim = animFor(window);
anim->stop();
// animateOut leaves a `finished -> hide()` handler attached to the
// shared animation object. If a fade-out was interrupted by this
// fade-in (rapid out/in cycle), the leftover handler would fire at
// the end of the in-fade and silently hide the just-revealed
// window — clear it before starting.
QObject::disconnect(anim, &QPropertyAnimation::finished, window, nullptr);
anim->setDuration(ms);
anim->setStartValue(0.0);
anim->setEndValue(1.0);

View File

@ -74,9 +74,8 @@ void pushUndo(Entry e) {
} // namespace
void pushTab(const QString &tabText, bool quickTerminal) {
void pushTab(const QString &tabText) {
if (g_redoInProgress) return;
if (quickTerminal) return;
Entry e;
e.kind = Entry::Kind::Tab;
e.pageTitles << tabText;

View File

@ -30,11 +30,10 @@ struct Entry {
QRect geometry;
};
// Snapshot the tab at `index` — single title — onto the undo stack.
// `tabText` is the tab's last-known display text; `quickTerminal` is
// the window's quick-terminal flag (quick-terminal tabs are excluded
// from the stack, mirroring the prior MainWindow behavior).
void pushTab(const QString &tabText, bool quickTerminal);
// Snapshot a closed tab — its last-known display text — onto the
// undo stack. Callers MUST exclude quick-terminal and last-tab
// closes (the latter routes through pushWindow via closeEvent).
void pushTab(const QString &tabText);
// Snapshot every tab's title plus the window's geometry as a single
// Window entry. Excluded for the quick terminal and for empty