qt: extract shared helpers into Util.{h,cpp} and a typed TabData
Three near-identical translateMods() copies and two key-name/trigger
formatters lived across MainWindow, GhosttySurface and InspectorWindow
— pulled into a single Util.{h,cpp} so each callsite uses one
canonical implementation:
- translateMods (Qt::KeyboardModifiers -> ghostty_input_mods_e)
- triggerKeyName / formatTrigger (chord rendering)
- BellFeature enum replaces hand-rolled (1u << 0..4) bit positions
in MainWindow::ringBell. The bitfield layout is fixed by the C ABI
and should not be open-coded in two places.
- configGet<T>(cfg, &out, "literal") template wrapper so callsites
stop repeating qstrlen("literal").
Replace the QStringList-of-length-2 stored in QTabBar::tabData with a
typed TabData { base, override_ } struct (Q_DECLARE_METATYPE'd so
QVariant carries it across windows during a tear-off). The previous
schema was comment-only — one off-by-one would have silently
corrupted titles.
CommandPalette and the rest are migrated to the new helpers. Net
effect: one source of truth, no behavior change.
Co-Authored-By: claude-flow <ruv@ruv.net>
pull/12846/head
parent
e50e876334
commit
14fddb5fff
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QPoint>
|
||||
#include <QString>
|
||||
#include <QTabBar>
|
||||
#include <QTabWidget>
|
||||
|
||||
|
|
@ -8,10 +10,20 @@ class QDragEnterEvent;
|
|||
class QDropEvent;
|
||||
class QMouseEvent;
|
||||
|
||||
// MIME type marking a Ghostty tab tear-off drag. Recognised by tab bars
|
||||
// MIME type marking a Ghastty tab tear-off drag. Recognised by tab bars
|
||||
// (to cancel the tear-off) and by terminal surfaces (to accept the drag
|
||||
// so no "forbidden" cursor is shown over a Ghostty window).
|
||||
inline constexpr char kGhosttyTabMime[] = "application/x-ghostty-tab";
|
||||
// so no "forbidden" cursor is shown over a Ghastty window).
|
||||
inline constexpr char kGhosttyTabMime[] = "application/x-ghastty-tab";
|
||||
|
||||
// Per-tab data stored in QTabBar::tabData. `base` is the terminal-set
|
||||
// title (libghostty SET_TITLE); `override` is a manual user-set title
|
||||
// (libghostty SET_TAB_TITLE). updateTabText shows override when set,
|
||||
// otherwise base.
|
||||
struct TabData {
|
||||
QString base;
|
||||
QString override_; // `override` is a reserved C++ identifier
|
||||
};
|
||||
Q_DECLARE_METATYPE(TabData)
|
||||
|
||||
// A QTabBar that tears a tab off into its own window when it is dragged
|
||||
// clear of the bar. QTabBar's built-in movable behaviour still handles
|
||||
|
|
@ -41,6 +53,7 @@ private:
|
|||
int m_pressIndex = -1; // tab under the press, or -1
|
||||
QPoint m_pressPos; // press point, for the drag hot spot
|
||||
bool m_tearing = false; // a tear-off QDrag is in progress
|
||||
bool m_dropHandled = false; // a TabBar dropEvent caught our tear-off
|
||||
};
|
||||
|
||||
// A QTabWidget wired to the tear-off-aware TabBar.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
#include "Util.h"
|
||||
|
||||
#include <QChar>
|
||||
#include <QStringLiteral>
|
||||
|
||||
QString triggerKeyName(const ghostty_input_trigger_s &t) {
|
||||
switch (t.tag) {
|
||||
case GHOSTTY_TRIGGER_UNICODE:
|
||||
if (t.key.unicode) return QString(QChar(t.key.unicode)).toUpper();
|
||||
return {};
|
||||
case GHOSTTY_TRIGGER_PHYSICAL: {
|
||||
const ghostty_input_key_e k = t.key.physical;
|
||||
if (k >= GHOSTTY_KEY_DIGIT_0 && k <= GHOSTTY_KEY_DIGIT_9)
|
||||
return QChar('0' + (k - GHOSTTY_KEY_DIGIT_0));
|
||||
if (k >= GHOSTTY_KEY_A && k <= GHOSTTY_KEY_Z)
|
||||
return QChar('A' + (k - GHOSTTY_KEY_A));
|
||||
if (k == GHOSTTY_KEY_ENTER) return QStringLiteral("Return");
|
||||
if (k == GHOSTTY_KEY_SPACE) return QStringLiteral("Space");
|
||||
if (k == GHOSTTY_KEY_TAB) return QStringLiteral("Tab");
|
||||
return {};
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
QString formatTrigger(const ghostty_input_trigger_s &t) {
|
||||
QString s;
|
||||
if (t.mods & GHOSTTY_MODS_CTRL) s += QStringLiteral("Ctrl+");
|
||||
if (t.mods & GHOSTTY_MODS_ALT) s += QStringLiteral("Alt+");
|
||||
if (t.mods & GHOSTTY_MODS_SHIFT) s += QStringLiteral("Shift+");
|
||||
if (t.mods & GHOSTTY_MODS_SUPER) s += QStringLiteral("Super+");
|
||||
|
||||
const QString name = triggerKeyName(t);
|
||||
if (!name.isEmpty()) {
|
||||
s += name;
|
||||
} else if (t.tag == GHOSTTY_TRIGGER_PHYSICAL) {
|
||||
s += QStringLiteral("•"); // an unmapped physical key
|
||||
} else {
|
||||
s += QStringLiteral("…"); // CATCH_ALL etc.
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <Qt>
|
||||
|
||||
#include "ghostty.h"
|
||||
|
||||
// Shared helpers used across the Qt frontend. Kept header-only where
|
||||
// possible so trivial wrappers stay inlined.
|
||||
|
||||
// bell-features is a packed struct returned by ghostty_config_get as a
|
||||
// bitfield. Layout is fixed by the libghostty C ABI; do not reorder.
|
||||
enum BellFeature : unsigned int {
|
||||
BellSystem = 1u << 0,
|
||||
BellAudio = 1u << 1,
|
||||
BellAttention = 1u << 2,
|
||||
BellTitle = 1u << 3,
|
||||
BellBorder = 1u << 4,
|
||||
};
|
||||
|
||||
// Translate Qt keyboard modifiers into libghostty's modifier bitfield.
|
||||
inline ghostty_input_mods_e translateMods(Qt::KeyboardModifiers m) {
|
||||
int r = GHOSTTY_MODS_NONE;
|
||||
if (m & Qt::ShiftModifier) r |= GHOSTTY_MODS_SHIFT;
|
||||
if (m & Qt::ControlModifier) r |= GHOSTTY_MODS_CTRL;
|
||||
if (m & Qt::AltModifier) r |= GHOSTTY_MODS_ALT;
|
||||
if (m & Qt::MetaModifier) r |= GHOSTTY_MODS_SUPER;
|
||||
return static_cast<ghostty_input_mods_e>(r);
|
||||
}
|
||||
|
||||
// Render the printable letter/digit/named key portion of a libghostty
|
||||
// trigger. Returns an empty string if the key is not displayable
|
||||
// (CATCH_ALL, an unmapped physical key, etc.).
|
||||
QString triggerKeyName(const ghostty_input_trigger_s &t);
|
||||
|
||||
// Format a libghostty trigger as a human-readable chord (e.g. "Ctrl+B").
|
||||
// Used for context-menu shortcut hints and the key-sequence overlay.
|
||||
// Unmapped physical keys render as "•"; trigger.tag CATCH_ALL renders
|
||||
// as "…".
|
||||
QString formatTrigger(const ghostty_input_trigger_s &t);
|
||||
|
||||
// Wrapper around ghostty_config_get that infers the value's length
|
||||
// from a string literal, so call sites stop repeating qstrlen().
|
||||
template <typename T, size_t N>
|
||||
inline bool configGet(ghostty_config_t cfg, T *out, const char (&key)[N]) {
|
||||
return cfg && ghostty_config_get(cfg, out, key, N - 1);
|
||||
}
|
||||
Loading…
Reference in New Issue