diff --git a/mainwindow.cpp b/mainwindow.cpp
index fda3072..2852fc2 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -341,6 +341,8 @@ MainWindow::MainWindow(QTranslator* startupTranslator, QWidget* parent)
// remove this override — see settingsdialog.cpp buildUi.
m_settings.xMinimizesApp = false;
m_settings.launchOnStartup = m_persist.value("window/launchOnStartup", false).toBool();
+ m_settings.minimalWidth = m_persist.value("window/minimalWidth", false).toBool();
+ m_settings.minimalWidthPx = m_persist.value("window/minimalWidthPx", 0).toInt();
m_settings.audioFeedback = m_persist.value("audio/enabled", false).toBool();
m_settings.showClickIndicator = m_persist.value("visual/clickIndicator", AppSettings{}.showClickIndicator).toBool();
m_settings.audioClickEnabled = m_persist.value("audioClick/enabled", false).toBool();
@@ -1130,6 +1132,16 @@ void MainWindow::rebuildButtons()
lay->activate();
adjustSize();
+
+ // Minimal width with an explicit pixel limit overrides the natural
+ // (sizeHint-driven) width computed by adjustSize() above. Floored to the
+ // title bar's own minimum so its controls (settings/exit/status dot)
+ // never become unreachable — that floor is the one clipping guarantee
+ // that survives a user-chosen limit; button/label text is not protected.
+ if (m_settings.minimalWidth && m_settings.minimalWidthPx > 0) {
+ const int floorPx = m_titleBar ? m_titleBar->minimumSizeHint().width() : 0;
+ resize(qMax(m_settings.minimalWidthPx, floorPx), height());
+ }
}
ClickButton* MainWindow::makeButton(const QString& label, const QString& tooltip, ClickType type, const QString& iconName)
@@ -1295,6 +1307,13 @@ MainWindow::ResizeEdge MainWindow::edgeAt(QPoint p) const
const bool onR = p.x() >= r.width() - m;
const bool onT = p.y() <= m;
const bool onB = p.y() >= r.height() - m;
+ if (m_settings.minimalWidth) {
+ // Width is locked to its natural minimum: offer vertical-only resize,
+ // never the horizontal (or diagonal) edges/corners.
+ if (onT) return ResizeEdge::Top;
+ if (onB) return ResizeEdge::Bottom;
+ return ResizeEdge::None;
+ }
if (onT && onL) return ResizeEdge::TopLeft;
if (onT && onR) return ResizeEdge::TopRight;
if (onB && onL) return ResizeEdge::BottomLeft;
@@ -1998,6 +2017,8 @@ void MainWindow::applySettings(const AppSettings& s)
m_persist.setValue("window/startMin", s.startMinimized);
m_persist.setValue("window/xMinimizesApp", s.xMinimizesApp);
m_persist.setValue("window/launchOnStartup", s.launchOnStartup);
+ m_persist.setValue("window/minimalWidth", s.minimalWidth);
+ m_persist.setValue("window/minimalWidthPx", s.minimalWidthPx);
// Reconcile unconditionally: the registry/autostart entry must match the
// setting even when it is unchanged here but was lost externally, never
// written by an older build, or points at a stale executable path.
diff --git a/settingsdialog.cpp b/settingsdialog.cpp
index a4caa4b..54c165c 100644
--- a/settingsdialog.cpp
+++ b/settingsdialog.cpp
@@ -650,6 +650,9 @@ void SettingsDialog::retranslateUi()
m_chkStartMinimized->setText(tr("Start minimized to tray"));
m_chkXMinimizesApp->setText(tr("Top X minimizes app"));
m_chkLaunchOnStartup->setText(tr("Launch on system startup (Windows)"));
+ m_chkMinimalWidth->setText(tr("Minimal width"));
+ m_lblMinimalWidthPx->setText(tr("Width limit (px):"));
+ m_spinMinimalWidthPx->setSpecialValueText(tr("Auto (fit content)"));
m_chkAudio->setText(tr("Audio feedback on click"));
m_chkClickIndicator->setText(tr("Show click indicator ring (Windows)"));
m_chkShowLabels->setText(tr("Show button labels"));
@@ -1045,6 +1048,18 @@ void SettingsDialog::buildUi()
m_chkStartMinimized = new QCheckBox(tr("Start minimized to tray"));
m_chkXMinimizesApp = new QCheckBox(tr("Top X minimizes app"));
m_chkLaunchOnStartup= new QCheckBox(tr("Launch on system startup (Windows)"));
+ m_chkMinimalWidth = new QCheckBox(tr("Minimal width"));
+ m_lblMinimalWidthPx = new QLabel(tr("Width limit (px):"));
+ m_spinMinimalWidthPx = new QSpinBox;
+ m_spinMinimalWidthPx->setRange(0, 2000);
+ m_spinMinimalWidthPx->setSingleStep(10);
+ m_spinMinimalWidthPx->setSpecialValueText(tr("Auto (fit content)"));
+ m_lblMinimalWidthPx->setEnabled(false);
+ m_spinMinimalWidthPx->setEnabled(false);
+ connect(m_chkMinimalWidth, &QCheckBox::toggled, this, [this](bool on){
+ m_lblMinimalWidthPx->setEnabled(on);
+ m_spinMinimalWidthPx->setEnabled(on);
+ });
behForm->addRow(m_lblEdgeLock, m_cmbEdgeLock);
behForm->addRow(m_chkEdgeHide);
@@ -1054,6 +1069,8 @@ void SettingsDialog::buildUi()
// (load/save/retranslate refs) but are hidden from the UI — the top X always
// quits. To restore the option, add it back to the layout here.
behForm->addRow(m_chkLaunchOnStartup);
+ behForm->addRow(m_chkMinimalWidth);
+ behForm->addRow(m_lblMinimalWidthPx, m_spinMinimalWidthPx);
winCol->addWidget(m_grpWinBehavior);
// ── Section: Button Controls ──────────────────────────────
@@ -1632,6 +1649,10 @@ void SettingsDialog::loadFrom(const AppSettings& s)
// Top X minimizes app is intentionally left read-only and unchecked (see
// buildUi); don't drive it from settings. Restore this line to re-enable.
m_chkLaunchOnStartup->setChecked(s.launchOnStartup);
+ m_chkMinimalWidth->setChecked(s.minimalWidth);
+ m_spinMinimalWidthPx->setValue(s.minimalWidthPx);
+ m_lblMinimalWidthPx->setEnabled(s.minimalWidth);
+ m_spinMinimalWidthPx->setEnabled(s.minimalWidth);
m_chkAudio->setChecked(s.audioFeedback);
m_chkClickIndicator->setChecked(s.showClickIndicator);
m_chkShowLabels->setChecked(!s.iconsOnly); // checked = labels shown
@@ -1695,6 +1716,8 @@ AppSettings SettingsDialog::readUi() const
s.startMinimized = m_chkStartMinimized->isChecked();
s.xMinimizesApp = m_chkXMinimizesApp->isChecked();
s.launchOnStartup = m_chkLaunchOnStartup->isChecked();
+ s.minimalWidth = m_chkMinimalWidth->isChecked();
+ s.minimalWidthPx = m_spinMinimalWidthPx->value();
s.audioFeedback = m_chkAudio->isChecked();
s.showClickIndicator = m_chkClickIndicator->isChecked();
s.iconsOnly = !m_chkShowLabels->isChecked(); // unchecked = icons only
diff --git a/settingsdialog.h b/settingsdialog.h
index 6cd500f..fa7cb36 100644
--- a/settingsdialog.h
+++ b/settingsdialog.h
@@ -75,6 +75,13 @@ struct AppSettings {
bool startMinimized = false;
bool xMinimizesApp = false;
bool launchOnStartup = false;
+ // Locks the window width and disables horizontal edge/corner resizing.
+ // minimalWidthPx == 0 means "auto": fit the natural content width
+ // (sizeHint) with no clipping. A positive value forces that exact width
+ // instead — the user's explicit choice, so unlike the auto case it is not
+ // guaranteed clip-free (only floored to keep the title bar controls usable).
+ bool minimalWidth = false;
+ int minimalWidthPx = 0;
// Audio feedback
bool audioFeedback = false;
@@ -243,6 +250,9 @@ class SettingsDialog : public QDialog
QCheckBox* m_chkStartMinimized;
QCheckBox* m_chkXMinimizesApp;
QCheckBox* m_chkLaunchOnStartup;
+ QCheckBox* m_chkMinimalWidth;
+ QLabel* m_lblMinimalWidthPx = nullptr;
+ QSpinBox* m_spinMinimalWidthPx = nullptr;
QCheckBox* m_chkAudio;
QCheckBox* m_chkClickIndicator;
// "Show button labels" — the inverse of AppSettings::iconsOnly (checked =
diff --git a/translations/trackclick_ar.ts b/translations/trackclick_ar.ts
index d15446a..46f607c 100644
--- a/translations/trackclick_ar.ts
+++ b/translations/trackclick_ar.ts
@@ -114,6 +114,9 @@
Top X minimizes appزر X العلوي يصغّر التطبيق
Close applicationإغلاق التطبيق
Launch on system startup (Windows)التشغيل عند بدء تشغيل النظام (Windows)
+ Minimal widthالحد الأدنى للعرض
+ Width limit (px):حد العرض (بكسل):
+ Auto (fit content)تلقائي (يلائم المحتوى)
Audio feedback on clickردود فعل صوتية عند النقر
Icons only (hide button labels)أيقونات فقط (إخفاء تسميات الأزرار)
Large buttonsأزرار كبيرة
diff --git a/translations/trackclick_bn.ts b/translations/trackclick_bn.ts
index 8df1ee7..4a04b0c 100644
--- a/translations/trackclick_bn.ts
+++ b/translations/trackclick_bn.ts
@@ -114,6 +114,9 @@
Top X minimizes appউপরের X অ্যাপ ছোট করে
Close applicationঅ্যাপ্লিকেশন বন্ধ করুন
Launch on system startup (Windows)সিস্টেম স্টার্টআপে চালু করুন (Windows)
+ Minimal widthসর্বনিম্ন প্রস্থ
+ Width limit (px):প্রস্থের সীমা (px):
+ Auto (fit content)স্বয়ংক্রিয় (বিষয়বস্তু অনুযায়ী)
Audio feedback on clickক্লিকে অডিও ফিডব্যাক
Icons only (hide button labels)শুধু আইকন (বোতামের লেবেল লুকান)
Large buttonsবড় বোতাম
diff --git a/translations/trackclick_cs.ts b/translations/trackclick_cs.ts
index 7b99db6..abc712f 100644
--- a/translations/trackclick_cs.ts
+++ b/translations/trackclick_cs.ts
@@ -115,6 +115,9 @@
Scroll repeat:Opakování rolování:
Repeat click:Opakovat kliknutí:
Launch on system startup (Windows)Spustit při startu systému (Windows)
+ Minimal widthMinimální šířka
+ Width limit (px):Omezení šířky (px):
+ Auto (fit content)Automaticky (podle obsahu)
Open On-Screen KeyboardOtevřít klávesnici na obrazovce
No on-screen keyboard was found.
Please install 'onboard' or 'florence'.Klávesnice na obrazovce nebyla nalezena.
diff --git a/translations/trackclick_es.ts b/translations/trackclick_es.ts
index bf497c4..e9639cd 100644
--- a/translations/trackclick_es.ts
+++ b/translations/trackclick_es.ts
@@ -113,6 +113,9 @@
Scroll repeat:Repetición de desplazamiento:
Repeat click:Repetir clic:
Launch on system startup (Windows)Iniciar con el sistema (Windows)
+ Minimal widthAncho mínimo
+ Width limit (px):Límite de ancho (px):
+ Auto (fit content)Automático (ajustar al contenido)
Open On-Screen KeyboardAbrir teclado en pantalla
No on-screen keyboard was found.
Please install 'onboard' or 'florence'.No se encontró ningún teclado en pantalla.
diff --git a/translations/trackclick_fr.ts b/translations/trackclick_fr.ts
index 3254daa..f86cded 100644
--- a/translations/trackclick_fr.ts
+++ b/translations/trackclick_fr.ts
@@ -113,6 +113,9 @@
Scroll repeat:Répétition du défilement :
Repeat click:Répétition du clic :
Launch on system startup (Windows)Lancer au démarrage du système (Windows)
+ Minimal widthLargeur minimale
+ Width limit (px):Largeur limite (px) :
+ Auto (fit content)Auto (ajusté au contenu)
Open On-Screen KeyboardOuvrir le clavier virtuel
No on-screen keyboard was found.
Please install 'onboard' or 'florence'.Aucun clavier virtuel trouvé.
diff --git a/translations/trackclick_hi.ts b/translations/trackclick_hi.ts
index 1710e0b..b3f061c 100644
--- a/translations/trackclick_hi.ts
+++ b/translations/trackclick_hi.ts
@@ -114,6 +114,9 @@
Top X minimizes appऊपरी X एप्प को छोटा करता है
Close applicationएप्लिकेशन बंद करें
Launch on system startup (Windows)सिस्टम स्टार्टअप पर लॉन्च करें (Windows)
+ Minimal widthन्यूनतम चौड़ाई
+ Width limit (px):चौड़ाई सीमा (px):
+ Auto (fit content)स्वतः (सामग्री के अनुरूप)
Audio feedback on clickक्लिक पर ऑडियो फीडबैक
Icons only (hide button labels)केवल आइकन (बटन लेबल छुपाएं)
Large buttonsबड़े बटन
diff --git a/translations/trackclick_ja.ts b/translations/trackclick_ja.ts
index 00ac740..5f932e0 100644
--- a/translations/trackclick_ja.ts
+++ b/translations/trackclick_ja.ts
@@ -113,6 +113,9 @@
Scroll repeat:スクロール繰り返し:
Repeat click:クリック繰り返し:
Launch on system startup (Windows)システム起動時に起動 (Windows)
+ Minimal width最小幅
+ Width limit (px):幅の上限 (px):
+ Auto (fit content)自動(内容に合わせる)
Open On-Screen Keyboardスクリーンキーボードを開く
No on-screen keyboard was found.
Please install 'onboard' or 'florence'.スクリーンキーボードが見つかりませんでした。
diff --git a/translations/trackclick_ko.ts b/translations/trackclick_ko.ts
index d1e0460..75ec193 100644
--- a/translations/trackclick_ko.ts
+++ b/translations/trackclick_ko.ts
@@ -113,6 +113,9 @@
Scroll repeat:스크롤 반복:
Repeat click:클릭 반복:
Launch on system startup (Windows)시스템 시작 시 실행 (Windows)
+ Minimal width최소 너비
+ Width limit (px):너비 제한 (px):
+ Auto (fit content)자동 (내용에 맞춤)
Open On-Screen Keyboard화상 키보드 열기
No on-screen keyboard was found.
Please install 'onboard' or 'florence'.화상 키보드를 찾을 수 없습니다.
diff --git a/translations/trackclick_pt.ts b/translations/trackclick_pt.ts
index a0959f7..c85854a 100644
--- a/translations/trackclick_pt.ts
+++ b/translations/trackclick_pt.ts
@@ -114,6 +114,9 @@
Top X minimizes appX superior minimiza o app
Close applicationFechar aplicação
Launch on system startup (Windows)Iniciar com o sistema (Windows)
+ Minimal widthLargura mínima
+ Width limit (px):Limite de largura (px):
+ Auto (fit content)Automático (ajustar ao conteúdo)
Audio feedback on clickFeedback de áudio ao clicar
Icons only (hide button labels)Apenas ícones (ocultar rótulos)
Large buttonsBotões grandes
diff --git a/translations/trackclick_ru.ts b/translations/trackclick_ru.ts
index 9aeb382..f17c861 100644
--- a/translations/trackclick_ru.ts
+++ b/translations/trackclick_ru.ts
@@ -114,6 +114,9 @@
Top X minimizes appКрестик сворачивает приложение
Close applicationЗакрыть приложение
Launch on system startup (Windows)Запускать при старте системы (Windows)
+ Minimal widthМинимальная ширина
+ Width limit (px):Ограничение ширины (px):
+ Auto (fit content)Авто (по содержимому)
Audio feedback on clickЗвуковой отклик при нажатии
Icons only (hide button labels)Только иконки (скрыть надписи кнопок)
Large buttonsКрупные кнопки
diff --git a/translations/trackclick_ur.ts b/translations/trackclick_ur.ts
index 5a529a3..e1a2158 100644
--- a/translations/trackclick_ur.ts
+++ b/translations/trackclick_ur.ts
@@ -114,6 +114,9 @@
Top X minimizes appاوپر X ایپ کو چھوٹا کرتا ہے
Close applicationایپلیکیشن بند کریں
Launch on system startup (Windows)سسٹم اسٹارٹ پر لانچ کریں (Windows)
+ Minimal widthکم از کم چوڑائی
+ Width limit (px):چوڑائی کی حد (px):
+ Auto (fit content)خودکار (مواد کے مطابق)
Audio feedback on clickکلک پر آڈیو فیڈبیک
Icons only (hide button labels)صرف آئیکن (بٹن لیبل چھپائیں)
Large buttonsبڑے بٹن
diff --git a/translations/trackclick_zh_CN.ts b/translations/trackclick_zh_CN.ts
index ac3b51b..b3f2f6c 100644
--- a/translations/trackclick_zh_CN.ts
+++ b/translations/trackclick_zh_CN.ts
@@ -113,6 +113,9 @@
Scroll repeat:滚动重复次数:
Repeat click:重复点击:
Launch on system startup (Windows)开机自动启动 (Windows)
+ Minimal width最小宽度
+ Width limit (px):宽度限制(像素):
+ Auto (fit content)自动(适应内容)
Open On-Screen Keyboard打开屏幕键盘
No on-screen keyboard was found.
Please install 'onboard' or 'florence'.未找到屏幕键盘。