From 59e6e82c06a3e6dabacff648cc8a552d6943a0f6 Mon Sep 17 00:00:00 2001 From: Anthony Lazzaro Date: Wed, 15 Jul 2026 10:18:58 -0700 Subject: [PATCH 01/14] Update version to 0.9.6 --- CMakeLists.txt | 2 +- docs/INTERNAL.md | 2 +- installer/Bundle.wxs | 2 +- installer/TrackClick.wxs | 2 +- main.cpp | 2 +- settingsdialog.cpp | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9806bda..b55b0bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.16) -project(TrackClick VERSION 0.9.5 LANGUAGES CXX) +project(TrackClick VERSION 0.9.6 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/docs/INTERNAL.md b/docs/INTERNAL.md index 6280e81..38aa954 100644 --- a/docs/INTERNAL.md +++ b/docs/INTERNAL.md @@ -5,7 +5,7 @@ > either don't want to advertise or that are too in-the-weeds for users. Keep > sensitive specifics here, not in user-facing docs. -Current version: **0.9.4** (pre-1.0 — see "Release gaps" below). +Current version: **0.9.6** (pre-1.0 — see "Release gaps" below). macOS bundle id: `com.trackclick.TrackClick`. --- diff --git a/installer/Bundle.wxs b/installer/Bundle.wxs index 3533f61..8d8e7ac 100644 --- a/installer/Bundle.wxs +++ b/installer/Bundle.wxs @@ -4,7 +4,7 @@ xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal"> diff --git a/installer/TrackClick.wxs b/installer/TrackClick.wxs index ed57998..092be6f 100644 --- a/installer/TrackClick.wxs +++ b/installer/TrackClick.wxs @@ -5,7 +5,7 @@ diff --git a/main.cpp b/main.cpp index 739e448..53892a1 100644 --- a/main.cpp +++ b/main.cpp @@ -40,7 +40,7 @@ int main(int argc, char* argv[]) QApplication app(argc, argv); app.setApplicationName("TrackClick"); - app.setApplicationVersion("0.9.5"); + app.setApplicationVersion("0.9.6"); app.setOrganizationName("TrackClick"); app.setOrganizationDomain("trackclick.app"); diff --git a/settingsdialog.cpp b/settingsdialog.cpp index 8ebd05c..f69d677 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -762,9 +762,9 @@ void SettingsDialog::buildUi() #ifdef BUILD_NUMBER # define TC_STR_(x) #x # define TC_STR(x) TC_STR_(x) - auto* versionLbl = new QLabel("Version 0.9.5 (build " TC_STR(BUILD_NUMBER) ")"); + auto* versionLbl = new QLabel("Version 0.9.6 (build " TC_STR(BUILD_NUMBER) ")"); #else - auto* versionLbl = new QLabel("Version 0.9.5"); + auto* versionLbl = new QLabel("Version 0.9.6"); #endif versionLbl->setStyleSheet( "color: #666666; font-size: 11px; background: transparent;"); From 8bee9b396205b4c9db34d12e683800cbfb2f3f2b Mon Sep 17 00:00:00 2001 From: Anthony Lazzaro Date: Wed, 15 Jul 2026 10:50:39 -0700 Subject: [PATCH 02/14] Attempted translation fixes for some new features. --- main.cpp | 3 +++ mainwindow.cpp | 4 ++++ translations/trackclick_ar.ts | 8 ++++++-- translations/trackclick_bn.ts | 8 ++++++-- translations/trackclick_cs.ts | 8 ++++++-- translations/trackclick_es.ts | 8 ++++++-- translations/trackclick_fr.ts | 8 ++++++-- translations/trackclick_hi.ts | 8 ++++++-- translations/trackclick_ja.ts | 8 ++++++-- translations/trackclick_ko.ts | 8 ++++++-- translations/trackclick_pt.ts | 8 ++++++-- translations/trackclick_ru.ts | 8 ++++++-- translations/trackclick_ur.ts | 8 ++++++-- translations/trackclick_zh_CN.ts | 8 ++++++-- translations/tsparser.cpp | 33 ++++++++++++++++++++++++++++++++ translations/tsparser.h | 9 +++++++++ 16 files changed, 121 insertions(+), 24 deletions(-) diff --git a/main.cpp b/main.cpp index 53892a1..a16cc1c 100644 --- a/main.cpp +++ b/main.cpp @@ -88,6 +88,9 @@ int main(int argc, char* argv[]) startupTranslator = loadBestTranslator(lang, &app); if (startupTranslator) app.installTranslator(startupTranslator); + // Also translate Qt's own built-in widget strings (e.g. QKeySequenceEdit's + // "Press shortcut" placeholder) for the saved language. + installQtBaseTranslator(lang); } // Don't quit when last window is hidden (keep tray alive) diff --git a/mainwindow.cpp b/mainwindow.cpp index 11727df..8a0b5fb 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1834,6 +1834,10 @@ void MainWindow::installLanguage(const QString& lang) qApp->installTranslator(m_translator); } + // Keep Qt's own built-in widget strings (e.g. QKeySequenceEdit's "Press + // shortcut" placeholder) in sync with the app language on every switch. + installQtBaseTranslator(lang); + retranslateUi(); } diff --git a/translations/trackclick_ar.ts b/translations/trackclick_ar.ts index 3074eec..f2b7573 100644 --- a/translations/trackclick_ar.ts +++ b/translations/trackclick_ar.ts @@ -40,7 +40,8 @@ Hold Alt modifier for next clickاضغط مع الاستمرار Alt للنقر التالي Hold Shift modifier for next clickاضغط مع الاستمرار Shift للنقر التالي Ready — hover to dwell-clickجاهز — حوّم للنقر بالتحوم - Selected: المحدد: + Selected: %1المحدد: %1 + Audio click active: %1النقر الصوتي نشط: %1 Running in the system tray. Right-click the tray icon to quit.يعمل في حاوية النظام. انقر بزر الفأرة الأيمن على أيقونة الحاوية للإنهاء. Quit Programإنهاء البرنامج No Clickبدون نقر @@ -71,7 +72,10 @@ Repeat click:تكرار النقر: Permissions:الأذونات: Open Accessibility Settings…فتح إعدادات إمكانية الوصول… - Visible Buttonsالأزرار المرئية + Visible Buttons (check to show, Move Up/Down to reorder)الأزرار المرئية (حدد للإظهار، لأعلى/لأسفل لإعادة الترتيب) + Move Upتحريك لأعلى + Move Downتحريك لأسفل + Zoom:تكبير: Buttonsالأزرار No Clickبدون نقر Left Clickنقر بالزر الأيسر diff --git a/translations/trackclick_bn.ts b/translations/trackclick_bn.ts index 8c1c185..88a5ba4 100644 --- a/translations/trackclick_bn.ts +++ b/translations/trackclick_bn.ts @@ -40,7 +40,8 @@ Hold Alt modifier for next clickপরবর্তী ক্লিকের জন্য Alt ধরে রাখুন Hold Shift modifier for next clickপরবর্তী ক্লিকের জন্য Shift ধরে রাখুন Ready — hover to dwell-clickপ্রস্তুত — ড্ওয়েল-ক্লিকের জন্য হোভার করুন - Selected: নির্বাচিত: + Selected: %1নির্বাচিত: %1 + Audio click active: %1অডিও ক্লিক সক্রিয়: %1 Running in the system tray. Right-click the tray icon to quit.সিস্টেম ট্রেতে চলছে। প্রস্থান করতে ট্রে আইকনে ডান-ক্লিক করুন। Quit Programপ্রোগ্রাম ছেড়ে দিন No Clickকোনো ক্লিক নেই @@ -71,7 +72,10 @@ Repeat click:ক্লিক পুনরাবৃত্তি: Permissions:অনুমতি: Open Accessibility Settings…অ্যাক্সেসিবিলিটি সেটিংস খুলুন… - Visible Buttonsদৃশ্যমান বোতাম + Visible Buttons (check to show, Move Up/Down to reorder)দৃশ্যমান বোতাম (দেখাতে চেক করুন, সাজাতে উপরে/নিচে সরান) + Move Upউপরে সরান + Move Downনিচে সরান + Zoom:জুম: Buttonsবোতাম No Clickকোনো ক্লিক নেই Left Clickবাম ক্লিক diff --git a/translations/trackclick_cs.ts b/translations/trackclick_cs.ts index bed101a..617ea0a 100644 --- a/translations/trackclick_cs.ts +++ b/translations/trackclick_cs.ts @@ -38,7 +38,8 @@ Hold Alt modifier for next clickPodržet Alt pro příští kliknutí Hold Shift modifier for next clickPodržet Shift pro příští kliknutí Ready — hover to dwell-clickPřipraveno — najeďte pro kliknutí - Selected: Vybráno: + Selected: %1Vybráno: %1 + Audio click active: %1Zvukové kliknutí aktivní: %1 Running in the system tray. Right-click the tray icon to quit.Běží v systémové liště. Pravým klikem na ikonu ukončíte. Quit ProgramUkončit program No ClickŽádná akce @@ -65,7 +66,10 @@ How long a toolbar button must be hovered before the selection switches to it, as a percentage of the dwell time.Jak dlouho musí kurzor setrvat na tlačítku panelu nástrojů, než se na něj přepne výběr, jako procento času najetí. Permissions:Oprávnění: Open Accessibility Settings…Otevřít nastavení zpřístupnění… - Visible ButtonsViditelná tlačítka + Visible Buttons (check to show, Move Up/Down to reorder)Viditelná tlačítka (zaškrtnutím zobrazíte, Nahoru/Dolů pro změnu pořadí) + Move UpNahoru + Move DownDolů + Zoom:Přiblížení: ButtonsTlačítka No ClickŽádná akce Left ClickLevé kliknutí diff --git a/translations/trackclick_es.ts b/translations/trackclick_es.ts index 62eb390..96969e2 100644 --- a/translations/trackclick_es.ts +++ b/translations/trackclick_es.ts @@ -36,7 +36,8 @@ Hold Alt modifier for next clickMantener Alt para el siguiente clic Hold Shift modifier for next clickMantener Mayús para el siguiente clic Ready — hover to dwell-clickListo — pase el cursor para hacer clic - Selected: Seleccionado: + Selected: %1Seleccionado: %1 + Audio click active: %1Clic por audio activo: %1 Running in the system tray. Right-click the tray icon to quit.Ejecutándose en la bandeja. Clic derecho en el icono para salir. Quit ProgramSalir del programa No ClickSin acción @@ -63,7 +64,10 @@ How long a toolbar button must be hovered before the selection switches to it, as a percentage of the dwell time.Cuánto tiempo debe pasar el cursor sobre un botón de la barra de herramientas antes de que la selección cambie a él, como porcentaje del tiempo de permanencia. Permissions:Permisos: Open Accessibility Settings…Abrir configuración de accesibilidad… - Visible ButtonsBotones visibles + Visible Buttons (check to show, Move Up/Down to reorder)Botones visibles (marcar para mostrar, Subir/Bajar para reordenar) + Move UpSubir + Move DownBajar + Zoom:Zoom: ButtonsBotones No ClickSin acción Left ClickClic izquierdo diff --git a/translations/trackclick_fr.ts b/translations/trackclick_fr.ts index b73b97c..2b8a8ae 100644 --- a/translations/trackclick_fr.ts +++ b/translations/trackclick_fr.ts @@ -36,7 +36,8 @@ Hold Alt modifier for next clickMaintenir Alt pour le prochain clic Hold Shift modifier for next clickMaintenir Maj pour le prochain clic Ready — hover to dwell-clickPrêt — survolez pour cliquer - Selected: Sélectionné : + Selected: %1Sélectionné : %1 + Audio click active: %1Clic audio actif : %1 Running in the system tray. Right-click the tray icon to quit.En cours d'exécution dans la zone de notification. Clic droit pour quitter. Quit ProgramQuitter le programme No ClickAucune action @@ -63,7 +64,10 @@ How long a toolbar button must be hovered before the selection switches to it, as a percentage of the dwell time.Durée pendant laquelle un bouton de la barre d'outils doit être survolé avant que la sélection y passe, en pourcentage de la durée de survol. Permissions:Autorisations : Open Accessibility Settings…Ouvrir les réglages d'accessibilité… - Visible ButtonsBoutons visibles + Visible Buttons (check to show, Move Up/Down to reorder)Boutons visibles (cocher pour afficher, Monter/Descendre pour réorganiser) + Move UpMonter + Move DownDescendre + Zoom:Zoom : ButtonsBoutons No ClickAucune action Left ClickClic gauche diff --git a/translations/trackclick_hi.ts b/translations/trackclick_hi.ts index 24dc85b..42e479a 100644 --- a/translations/trackclick_hi.ts +++ b/translations/trackclick_hi.ts @@ -40,7 +40,8 @@ Hold Alt modifier for next clickअगले क्लिक के लिए Alt दबाकर रखें Hold Shift modifier for next clickअगले क्लिक के लिए Shift दबाकर रखें Ready — hover to dwell-clickतैयार — ड्वेल-क्लिक के लिए होवर करें - Selected: चयनित: + Selected: %1चयनित: %1 + Audio click active: %1ऑडियो क्लिक सक्रिय: %1 Running in the system tray. Right-click the tray icon to quit.सिस्टम ट्रे में चल रहा है। बंद करने के लिए ट्रे आइकन पर राइट-क्लिक करें। Quit Programप्रोग्राम बंद करें No Clickकोई क्लिक नहीं @@ -71,7 +72,10 @@ Repeat click:क्लिक दोहराएं: Permissions:अनुमतियां: Open Accessibility Settings…एक्सेसिबिलिटी सेटिंग्स खोलें… - Visible Buttonsदृश्य बटन + Visible Buttons (check to show, Move Up/Down to reorder)दृश्य बटन (दिखाने के लिए चेक करें, क्रम बदलने के लिए ऊपर/नीचे ले जाएँ) + Move Upऊपर ले जाएँ + Move Downनीचे ले जाएँ + Zoom:ज़ूम: Buttonsबटन No Clickकोई क्लिक नहीं Left Clickबाएं क्लिक diff --git a/translations/trackclick_ja.ts b/translations/trackclick_ja.ts index 5b787c7..24a1cb7 100644 --- a/translations/trackclick_ja.ts +++ b/translations/trackclick_ja.ts @@ -36,7 +36,8 @@ Hold Alt modifier for next click次のクリックに Alt を保持 Hold Shift modifier for next click次のクリックに Shift を保持 Ready — hover to dwell-click準備完了 — ホバーでクリック - Selected: 選択済み: + Selected: %1選択済み:%1 + Audio click active: %1オーディオクリック有効:%1 Running in the system tray. Right-click the tray icon to quit.システムトレイで実行中。トレイアイコンを右クリックして終了。 Quit Programプログラムを終了 No Click何もしない @@ -63,7 +64,10 @@ How long a toolbar button must be hovered before the selection switches to it, as a percentage of the dwell time.選択がツールバーボタンに切り替わるまでにホバーする必要がある長さ(滞留時間に対する割合)。 Permissions:権限: Open Accessibility Settings…アクセシビリティ設定を開く… - Visible Buttons表示ボタン + Visible Buttons (check to show, Move Up/Down to reorder)表示ボタン(チェックで表示、「上へ」/「下へ」で並べ替え) + Move Up上へ + Move Down下へ + Zoom:ズーム: Buttonsボタン No Click何もしない Left Click左クリック diff --git a/translations/trackclick_ko.ts b/translations/trackclick_ko.ts index 0af9cb1..7fa3e5e 100644 --- a/translations/trackclick_ko.ts +++ b/translations/trackclick_ko.ts @@ -36,7 +36,8 @@ Hold Alt modifier for next click다음 클릭에 Alt 키 유지 Hold Shift modifier for next click다음 클릭에 Shift 키 유지 Ready — hover to dwell-click준비 완료 — 마우스를 올려 클릭 - Selected: 선택됨: + Selected: %1선택됨: %1 + Audio click active: %1오디오 클릭 활성화: %1 Running in the system tray. Right-click the tray icon to quit.시스템 트레이에서 실행 중. 트레이 아이콘을 오른쪽 클릭하여 종료. Quit Program프로그램 종료 No Click동작 없음 @@ -63,7 +64,10 @@ How long a toolbar button must be hovered before the selection switches to it, as a percentage of the dwell time.선택이 도구 모음 버튼으로 전환되기까지 마우스를 올려 두어야 하는 시간(머물기 시간의 백분율). Permissions:권한: Open Accessibility Settings…접근성 설정 열기… - Visible Buttons표시 버튼 + Visible Buttons (check to show, Move Up/Down to reorder)표시 버튼 (체크하여 표시, 위로/아래로로 순서 변경) + Move Up위로 + Move Down아래로 + Zoom:확대: Buttons버튼 No Click동작 없음 Left Click왼쪽 클릭 diff --git a/translations/trackclick_pt.ts b/translations/trackclick_pt.ts index 140b09c..8eb3a37 100644 --- a/translations/trackclick_pt.ts +++ b/translations/trackclick_pt.ts @@ -40,7 +40,8 @@ Hold Alt modifier for next clickManter Alt para o próximo clique Hold Shift modifier for next clickManter Shift para o próximo clique Ready — hover to dwell-clickPronto — passe o cursor para clicar por permanência - Selected: Selecionado: + Selected: %1Selecionado: %1 + Audio click active: %1Clique por áudio ativo: %1 Running in the system tray. Right-click the tray icon to quit.Executando na bandeja do sistema. Clique com botão direito no ícone para sair. Quit ProgramSair do programa No ClickSem clique @@ -71,7 +72,10 @@ Repeat click:Repetir clique: Permissions:Permissões: Open Accessibility Settings…Abrir configurações de acessibilidade… - Visible ButtonsBotões visíveis + Visible Buttons (check to show, Move Up/Down to reorder)Botões visíveis (marque para mostrar, Cima/Baixo para reordenar) + Move UpMover para cima + Move DownMover para baixo + Zoom:Zoom: ButtonsBotões No ClickSem clique Left ClickClique esquerdo diff --git a/translations/trackclick_ru.ts b/translations/trackclick_ru.ts index d170605..eeb8aaa 100644 --- a/translations/trackclick_ru.ts +++ b/translations/trackclick_ru.ts @@ -40,7 +40,8 @@ Hold Alt modifier for next clickУдержать Alt для следующего клика Hold Shift modifier for next clickУдержать Shift для следующего клика Ready — hover to dwell-clickГотово — наведите для нажатия с задержкой - Selected: Выбрано: + Selected: %1Выбрано: %1 + Audio click active: %1Аудиоклик активен: %1 Running in the system tray. Right-click the tray icon to quit.Работает в системном трее. Правая кнопка на иконке для выхода. Quit ProgramВыйти из программы No ClickБез клика @@ -71,7 +72,10 @@ Repeat click:Повтор клика: Permissions:Разрешения: Open Accessibility Settings…Открыть параметры специальных возможностей… - Visible ButtonsВидимые кнопки + Visible Buttons (check to show, Move Up/Down to reorder)Видимые кнопки (отметьте для показа, «Вверх»/«Вниз» для изменения порядка) + Move UpВверх + Move DownВниз + Zoom:Масштаб: ButtonsКнопки No ClickБез клика Left ClickЛевый клик diff --git a/translations/trackclick_ur.ts b/translations/trackclick_ur.ts index e13e4a8..1c982bc 100644 --- a/translations/trackclick_ur.ts +++ b/translations/trackclick_ur.ts @@ -40,7 +40,8 @@ Hold Alt modifier for next clickاگلے کلک کے لیے Alt دبائے رکھیں Hold Shift modifier for next clickاگلے کلک کے لیے Shift دبائے رکھیں Ready — hover to dwell-clickتیار — ڈویل-کلک کے لیے ہوور کریں - Selected: منتخب: + Selected: %1منتخب: %1 + Audio click active: %1آڈیو کلک فعال: %1 Running in the system tray. Right-click the tray icon to quit.سسٹم ٹرے میں چل رہا ہے۔ بند کرنے کے لیے ٹرے آئیکن پر رائٹ-کلک کریں۔ Quit Programپروگرام بند کریں No Clickکوئی کلک نہیں @@ -71,7 +72,10 @@ Repeat click:کلک دہرائیں: Permissions:اجازتیں: Open Accessibility Settings…رسائی ترتیبات کھولیں… - Visible Buttonsنظر آنے والے بٹن + Visible Buttons (check to show, Move Up/Down to reorder)نظر آنے والے بٹن (دکھانے کے لیے چیک کریں، ترتیب بدلنے کے لیے اوپر/نیچے کریں) + Move Upاوپر لے جائیں + Move Downنیچے لے جائیں + Zoom:زوم: Buttonsبٹن No Clickکوئی کلک نہیں Left Clickبایاں کلک diff --git a/translations/trackclick_zh_CN.ts b/translations/trackclick_zh_CN.ts index 7b82980..66b652b 100644 --- a/translations/trackclick_zh_CN.ts +++ b/translations/trackclick_zh_CN.ts @@ -36,7 +36,8 @@ Hold Alt modifier for next click按住Alt键进行下一次点击 Hold Shift modifier for next click按住Shift键进行下一次点击 Ready — hover to dwell-click就绪 — 悬停以点击 - Selected: 已选择: + Selected: %1已选择:%1 + Audio click active: %1音频点击已激活:%1 Running in the system tray. Right-click the tray icon to quit.正在系统托盘中运行。右键单击托盘图标退出。 Quit Program退出程序 No Click无操作 @@ -63,7 +64,10 @@ How long a toolbar button must be hovered before the selection switches to it, as a percentage of the dwell time.在选择切换到某个工具栏按钮之前,需要在其上悬停的时长,以悬停时间的百分比表示。 Permissions:辅助功能权限: Open Accessibility Settings…打开辅助功能设置… - Visible Buttons可见按钮 + Visible Buttons (check to show, Move Up/Down to reorder)可见按钮(勾选以显示,上移/下移以重新排序) + Move Up上移 + Move Down下移 + Zoom:缩放: Buttons按钮 No Click无操作 Left Click单击左键 diff --git a/translations/tsparser.cpp b/translations/tsparser.cpp index 2b4434c..7f85ec1 100644 --- a/translations/tsparser.cpp +++ b/translations/tsparser.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -122,3 +123,35 @@ QTranslator* loadBestTranslator(const QString& lang, QObject* parent) << "NO translator found (embedded parse failed or resource missing)"; return nullptr; } + +// ─── installQtBaseTranslator ────────────────────────────────────────────────── +void installQtBaseTranslator(const QString& lang) +{ + // One process-wide Qt catalog translator; swap it out on each call so this is + // safe to invoke on every language change. + static QTranslator* qtCatalog = nullptr; + if (qtCatalog) { + QCoreApplication::removeTranslator(qtCatalog); + delete qtCatalog; + qtCatalog = nullptr; + } + if (lang == "en") return; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const QString dir = QLibraryInfo::path(QLibraryInfo::TranslationsPath); +#else + const QString dir = QLibraryInfo::location(QLibraryInfo::TranslationsPath); +#endif + auto* t = new QTranslator(QCoreApplication::instance()); + if (t->load("qtbase_" + lang, dir)) { + QCoreApplication::installTranslator(t); + qtCatalog = t; + if (i18nDebug()) + qWarning() << "TrackClick i18n: Qt catalog for" << lang << "loaded from" << dir; + } else { + if (i18nDebug()) + qWarning() << "TrackClick i18n: no Qt catalog for" << lang << "in" << dir + << "(Qt-provided strings stay English)"; + delete t; + } +} diff --git a/translations/tsparser.h b/translations/tsparser.h index 4347b1a..3f5aa2a 100644 --- a/translations/tsparser.h +++ b/translations/tsparser.h @@ -31,3 +31,12 @@ class TsTranslator : public QTranslator // 4. :/translations ← embedded fallback // Returns nullptr only when lang == "en" or no file is found at all. QTranslator* loadBestTranslator(const QString& lang, QObject* parent = nullptr); + +// Install Qt's own bundled catalog (qtbase_.qm) so text rendered by Qt's +// built-in widgets — e.g. QKeySequenceEdit's "Press shortcut" placeholder and the +// standard line-edit context menu — follows the app language. Our own .ts files +// only cover our strings; Qt-provided strings come from Qt's catalog. Replaces any +// previously-installed Qt catalog (manages a single process-wide translator), so +// it is safe to call on every language change. No-op for "en" or when the +// platform's Qt translations aren't installed. +void installQtBaseTranslator(const QString& lang); From c49c9181fc74c58f747a26c0695765a1a8aa4ef0 Mon Sep 17 00:00:00 2001 From: Anthony Lazzaro Date: Wed, 15 Jul 2026 10:59:56 -0700 Subject: [PATCH 03/14] Attempt to move the view into the middle of the screen when disabling Slide off screen. --- mainwindow.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index 8a0b5fb..c9a2793 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1240,7 +1240,20 @@ void MainWindow::applyEdgeLock() m_edgeHideCountMs = 0; const EdgeLock lock = m_settings.edgeLock; - if (lock == EdgeLock::None) return; + if (lock == EdgeLock::None) { + // Edge-lock (and its slide-off-when-idle) is off, so nothing will pull the + // window back on-screen. A previous slide-away can leave it parked with only + // a thin peek strip showing; with the lock now removed it would be stranded + // there, unreachable. If its centre has landed off every screen, recentre it + // on the primary screen so the window is always visible and draggable. + if (!QGuiApplication::screenAt(frameGeometry().center())) { + const QRect avail = QGuiApplication::primaryScreen()->availableGeometry(); + move(avail.left() + (avail.width() - width()) / 2, + avail.top() + (avail.height() - height()) / 2); + raise(); + } + return; + } QRect avail = QGuiApplication::primaryScreen()->availableGeometry(); int shownX = (lock == EdgeLock::Left) From d5585791f6d69c58c270941826dfeffc53f4a1dc Mon Sep 17 00:00:00 2001 From: skynab Date: Wed, 15 Jul 2026 16:17:09 -0700 Subject: [PATCH 04/14] Attempted improvement to the jitter calculation tool. --- settingsdialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/settingsdialog.cpp b/settingsdialog.cpp index f69d677..8670dce 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -468,7 +468,9 @@ void SensitivityTesterDialog::finishMeasurement() m_bar->setValue(100); double avg = m_samples > 0 ? m_sumDelta / m_samples : 1.0; - int recommended = qBound(1, static_cast(std::ceil(avg * 2.0)), 100); + // Recommend ~2x what the earlier factor produced: measured jitter alone was + // running too low to filter real-world cursor tremor, so scale it up. + int recommended = qBound(1, static_cast(std::ceil(avg * 4.0)), 100); m_resultLbl->setText(tr("Sensitivity set to %1 px").arg(recommended)); m_resultLbl->show(); From 79a17f4710729bb3cca02901c20dff28880c61dd Mon Sep 17 00:00:00 2001 From: skynab Date: Fri, 17 Jul 2026 08:02:49 -0700 Subject: [PATCH 05/14] Link to EULA --- installer/Bundle.wxs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/Bundle.wxs b/installer/Bundle.wxs index 8d8e7ac..ee33988 100644 --- a/installer/Bundle.wxs +++ b/installer/Bundle.wxs @@ -11,7 +11,7 @@ From 44cbba1a443ffee84aa67a7016b269a9c6f8e87f Mon Sep 17 00:00:00 2001 From: skynab Date: Fri, 24 Jul 2026 19:07:38 -0700 Subject: [PATCH 06/14] Minor usability improvements to icons. --- .DS_Store | Bin 8196 -> 8196 bytes icons/.DS_Store | Bin 6148 -> 8196 bytes icons/left_click.svg | 2 +- icons/left_double.svg | 2 +- icons/left_drag.svg | 2 +- icons/middle_click.svg | 2 +- icons/middle_double.svg | 2 +- icons/middle_drag.svg | 2 +- icons/right_click.svg | 2 +- icons/right_double.svg | 2 +- icons/right_drag.svg | 2 +- icons/scroll.svg | 2 +- icons/selected/left_click.svg | 2 +- icons/selected/left_double.svg | 2 +- icons/selected/left_drag.svg | 2 +- icons/selected/middle_click.svg | 2 +- icons/selected/middle_double.svg | 2 +- icons/selected/middle_drag.svg | 2 +- icons/selected/right_click.svg | 2 +- icons/selected/right_double.svg | 2 +- icons/selected/right_drag.svg | 2 +- icons/selected/scroll.svg | 2 +- 22 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.DS_Store b/.DS_Store index 627550019cbffa0a93f0829433605d38956d56c0..efa99a668a75ce6545a404ce2f9f97354011c2ea 100644 GIT binary patch delta 40 wcmZp1XmQwJDLC0mpp?VVz)VNM*vw$^0U`UzUj&6288>qXxiM|_7um`U0QM>il>h($ delta 113 zcmZp1XmQwJDJZ->sURn_xWvHV8Y2@k3o9Et2ghVzfoLsG&UgXw>S`lX9R)*6i&`Cp zYD*In9R*WEv)Wot4pC)&>!A4ToZP(p&dK+M8xF4%Wn%yx^n9eda1WmiwMZ=9|rn|y)FF%%HF$cS=jEDyL)eo zwc4m53ehKjP!nG?Dr$T&7&U4FM1wveVhkoe7<@1>YIrg+=$W0p{IvAZig72IIXh?O zo7r>rd^>yYC4@j@&Zs4%f)K*6a;cPIbB)5sd7V*cs3}1Sh$kdNd}0zKJ?4$hm>nr1 z4@4e_JP>&x@<8N)>%jwfX7j>kIrqhA)J7hNJn+Bt0DnJdSh-Awa!SbH)qzcr0-!8L zbx`mc^MC-Og)$k+DIo(Wt|_ty2%!+B7$D#{uJP$8lcAgvQosoaIDv3y2s0E2c1N5R zOec^OGHN3aL>`#w0iL@v;$hZqW4$7OPup%9$39Gt+Lq@h5@&%H6_?B_Wu>f)?M&@) z$5OuT=e$NeJIH(8u4|_Y*Lr%pWsVIgi<(@=*Dc4)1^~-2amtQf%Q4)sMmOgeUVu%B z0VXkNNU4~Zs7=(zwYvJmWL%qAw%Qp?Df2z_!j_EdY|EN?w7xgv+PM)2N6It0oyp;3v%$7g*2AVZppSQ(<37LUz)aS) z?QO1S`IhVS_xZC8^$mD#)^7^d?Xz$zvA_bpUFRqVd)v*dhfn_r>bvZ|);-i?h9 zw05S>DCG+l%JPz>y?M*C(ze;Jdl}O)EN8f9%rg8v1NaOa-+IV0vyxN}wcUoZE^Y14S^fdBhZ?Jvm~w1~f%dk$24B$#MpQL+J7a@f-;_16 z6>3?HuSS60?V&fq+pJw9Ns8CK4+BL&<@&WuQj8v3Pn&kATE78Rt-X0+ai~l-FuePC zU&b97L3=!*R$DeRrkvWv_iocYzjM@dF5OkjR>lUrJ$lyc9K%R0AUYTe9xCcNq{Xm& zH!BPopk<`l|(nL)o2Pu28(X3RwpY($WJN2)@wDg0!(!7lQ+mp zF)~$jH^~jMLio!=^qaNKn!I5^`GK5A2K+%TLK!Hq7^*Sq>tG{Bd@Hm=2RsN} z81*}07wiTd_JR!~;35YOzyv%3kHTZ{6dXbZJOj_di|`V>46nfJ@CNeWD7=j$`EOY)t0RL*6yU+0G{EyE6Y1#GlasK}eE=;J~ delta 150 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{MGpJ516t-XlGFTZr8Il?D8S)s4Q;L&wlJfI& zK*9`6AOZ+L93Td2Ldb6{oW?$}fp0N82ZtatSQUc+H;{G(V%3d>- \ No newline at end of file + \ No newline at end of file diff --git a/icons/left_double.svg b/icons/left_double.svg index 6a6199b..75438f3 100644 --- a/icons/left_double.svg +++ b/icons/left_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/left_drag.svg b/icons/left_drag.svg index c6b7253..d407a80 100644 --- a/icons/left_drag.svg +++ b/icons/left_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/middle_click.svg b/icons/middle_click.svg index 3f56204..3835c66 100644 --- a/icons/middle_click.svg +++ b/icons/middle_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/middle_double.svg b/icons/middle_double.svg index 981a635..aaa9e93 100644 --- a/icons/middle_double.svg +++ b/icons/middle_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/middle_drag.svg b/icons/middle_drag.svg index 956c802..ba08cbe 100644 --- a/icons/middle_drag.svg +++ b/icons/middle_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/right_click.svg b/icons/right_click.svg index 4e0cbc3..1ba559c 100644 --- a/icons/right_click.svg +++ b/icons/right_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/right_double.svg b/icons/right_double.svg index 51ce6f9..34ec59b 100644 --- a/icons/right_double.svg +++ b/icons/right_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/right_drag.svg b/icons/right_drag.svg index 9a50201..f946746 100644 --- a/icons/right_drag.svg +++ b/icons/right_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/scroll.svg b/icons/scroll.svg index aa8f9ae..55e0450 100644 --- a/icons/scroll.svg +++ b/icons/scroll.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/left_click.svg b/icons/selected/left_click.svg index 95d67c7..6d9a86a 100644 --- a/icons/selected/left_click.svg +++ b/icons/selected/left_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/left_double.svg b/icons/selected/left_double.svg index 4f3f766..235fc65 100644 --- a/icons/selected/left_double.svg +++ b/icons/selected/left_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/left_drag.svg b/icons/selected/left_drag.svg index 462472e..a6a4709 100644 --- a/icons/selected/left_drag.svg +++ b/icons/selected/left_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/middle_click.svg b/icons/selected/middle_click.svg index 441b7dc..df975c1 100644 --- a/icons/selected/middle_click.svg +++ b/icons/selected/middle_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/middle_double.svg b/icons/selected/middle_double.svg index 98fb642..c5092b8 100644 --- a/icons/selected/middle_double.svg +++ b/icons/selected/middle_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/middle_drag.svg b/icons/selected/middle_drag.svg index 8161a2a..34d68fb 100644 --- a/icons/selected/middle_drag.svg +++ b/icons/selected/middle_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/right_click.svg b/icons/selected/right_click.svg index 5ae9f5c..b9c0db1 100644 --- a/icons/selected/right_click.svg +++ b/icons/selected/right_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/right_double.svg b/icons/selected/right_double.svg index 115720d..a038c74 100644 --- a/icons/selected/right_double.svg +++ b/icons/selected/right_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/right_drag.svg b/icons/selected/right_drag.svg index 017d3a4..f67a8df 100644 --- a/icons/selected/right_drag.svg +++ b/icons/selected/right_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/scroll.svg b/icons/selected/scroll.svg index 4d12ac1..8d60b19 100644 --- a/icons/selected/scroll.svg +++ b/icons/selected/scroll.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 9adde2f2668674a30bff8486b1ea41bbb63af1a1 Mon Sep 17 00:00:00 2001 From: skynab Date: Fri, 24 Jul 2026 21:07:11 -0700 Subject: [PATCH 07/14] Better middle mouse icon changes. --- .DS_Store | Bin 8196 -> 10244 bytes icons/.DS_Store | Bin 8196 -> 8196 bytes icons/left_click.svg | 2 +- icons/left_double.svg | 2 +- icons/left_drag.svg | 2 +- icons/middle_click.svg | 2 +- icons/middle_double.svg | 2 +- icons/middle_drag.svg | 2 +- icons/right_click.svg | 2 +- icons/right_double.svg | 2 +- icons/right_drag.svg | 2 +- icons/scroll.svg | 2 +- icons/selected/left_click.svg | 2 +- icons/selected/left_double.svg | 2 +- icons/selected/left_drag.svg | 2 +- icons/selected/middle_click.svg | 2 +- icons/selected/middle_double.svg | 2 +- icons/selected/middle_drag.svg | 2 +- icons/selected/right_click.svg | 2 +- icons/selected/right_double.svg | 2 +- icons/selected/right_drag.svg | 2 +- icons/selected/scroll.svg | 2 +- 22 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.DS_Store b/.DS_Store index efa99a668a75ce6545a404ce2f9f97354011c2ea..681654a905409822f07cb5121b25ec7ad8edff81 100644 GIT binary patch literal 10244 zcmeHMTWl0n7(V~>!i??EX$x2wS4PTJH?UAzDc9{yE`=1?w!0K`ncW%agy~G(ncY^J zCiQ|Q5RDq6zIowQi6H?^)TnQWMhz0Hz{*2$mSY-LYPy<|yNVoZ^zZ6X5Oyf}SB*p#bY0{WNAy zAkJlY4G{~&gQo9iMs3UUW3g{RsHm)} zo+Hi?Ys5zq!|qtZ*ZsWLspk$*tsgf5GR1p6GiaG(X=PrQ>-f6mm^tQP877(>Oj?fN zj&-_u$MBeMf>(%=D5aIAiHVkVtx>I|b;D#-n`mDbi)!mz+9oF@aenifP5aVE?GeX4 z!6Sp<=|JSNNKc}EHJ<646juuiiJW7*&Ji@EjZ`5XSq$Hq{qWbu+A#dK*bRn1Eu!fF zOe?m%LKmOsiuU3>|5%)7>8_eud9FGzm>fvS$&{6KorHDFOe=LBPWMh!_vXw3PIEHr z+W8U3ODpwR-OlE1-8VaIn;K(TotMqIw!PQ&EZ=gS{b{9vI`xfG%^Ngx9?Fz&j{C*d zOYBoao}2T#SPyAM$$REL6Faa9W;b@@4e8_kfopR-#yKFJu4{@cS^hw*b>r5q?Y(`M zl=_CodGZ2z2x;c{)?v%c?bp4m=@^!CWMIrP{NZH5@~n()_B;BBDb+(%x}-GJH!fVH zs;PX&dMt1Gk1Nfh$lAJB)#QT)cE86pXlsV3oJD)=rCHU~1GJ_qXX4ce99F2SXzH zvTbUI`Y7#ox9<6UqozZLbe`9BW8IK9tmn+WG0ekYL_4sQ%_Npnryj%dT~>)v@77dx zKW(nVFjx$Y4fTrpu$mB+iy}^fHWAE<^JsD(OEU?D7lrLYW^!y4EOTVNZ+ zVJ8g0ASB@sm~a?|!Gau&!8ja)33wV#z)5%xo`+ZAb$A2bf>ZD|oP~4n9()2{!PjsR zzJZ_MGW-g^!Jk5CZS{k|~Vy zj03Im7Ij@K}jpaX+%j9?R7XY%n z5t<+ZQD{YGZ-+gQfPUn53WgvH2D1AI@OK%P_mpxOu9R}Q>UL}1ntsNf^e=>C7t%>VyqeVpL{LIgqtZXE(p*`4U_#P*Ae+VZaG zUb}|pAw20p?WVY7E_h+v@hI7LJSucMekGpNHrR+^_wk@?ic98>Hq0F*-_5_}KLf(` T|9@L>|7S}rT>szk>;HcN?s$Tb delta 98 zcmZn(XmOBWU|?W$DortDU;r^WfEYvza8E20o2aMA$g?qEH$NlKW*z}}$h!Ca# diff --git a/icons/.DS_Store b/icons/.DS_Store index 499856fdc6aa98ed8b0bf0fb4013997ad30d5671..e5da9126803125b1c9d7f5f70e0139e7b087c768 100644 GIT binary patch literal 8196 zcmeHMU2GLa6rOKe=v?dC?GMn4APZFxZQ#~IBL&LkwkV}&k^UF7+BC<0Lgq6kD0xDp~j-)vF%0^fZ(8nsabq6qviBOvYvovM(@P)4IVELaN^8pO0ih|v6a&(n#&t2BWHOXfQc80MY0ePtj4(q%ushl5 z!E}bClu;W+Ad0};2#DOBGmo-%o9ZR`d&YJ%H1=L*)V4f7kvI#bq;%2ZGG4~Z`Mq7k z?pT+f_VZpUojV|U-L7kAiqGjxuVs!6X*I2`#JfTlWtgwMQKH3F!*L>wu}V zTzhgpzYH&HXXu>5XpYmiS7?<^m$Vd}K38-)c1`)U>UHtnzW&|;wZGrWx=xq%pgE*f zc;tIKb@%1W0{PsRb?y9!;|*z**|eR_+iBn2Y1?8l=_kJHORl=xq zRP?-FGv|@)_swy?xcZFw{ezyH^IL-*hBPhjnfp!Jz$%z+w2e2I9`6oK>yil>kl2Ze z+Lde8-kR9lyrXUR-hF4Z%BpHrUAnBVV0l)?HV4vP)^rTZInpy`8UFAfy$i>;4qIj} z7OO-umu9Z$7#u6=Qz*n4l<^E*dP=i;eScXB@H4X1Nv=NKWgXwkuW z@H$B^Om-QT@6w=fT#t8hJ|Gs`X&AIlbycNy&;EFv-ht&5EaCyZHc1EVH0Qjo2*#S? zLnu*~te1~LSYw33RqSTg%u=kE4YNr$&5p6->>YNJeaTL-@7XWxH+G&~z+#kvqZ}II zSdJA~iM7~>1RBtYB-*hD9q7X$q>+IE3psf3QNRQq!K0YQ<9G@$;22)SOE`|#@H$T5 zO}vj!@F_mS=QxWW@e_W=?>LV?@s|=)s+4M_M!7**r!*_ulb?SOu zTTIN6-Fkh4t|>%V*=^7pRjq{R7z=Eh^bM*8E<4TYHdQMnV#@9gb*HK^aVN-rn|_C` z37TC#!2iI0Wq+{q00F)lwFL8eY{pjXB6xS92fY};AhIxV7{dX~edIBQaXf^F3F^~$ z3{T@3Jd5Y>JYL2tcr}3g3A{mYe+wVrLwtmj_!y_~6~4wd_!g&eE`a^tvtWJqOjzT> ze6TKb8xF4%Wn%yx^n9eda1WmiwMZ=9|rn|y)FF%%HF$cS=jEDyL)eo zwc4m53ehKjP!nG?Dr$T&7&U4FM1wveVhkoe7<@1>YIrg+=$W0p{IvAZig72IIXh?O zo7r>rd^>yYC4@j@&Zs4%f)K*6a;cPIbB)5sd7V*cs3}1Sh$kdNd}0zKJ?4$hm>nr1 z4@4e_JP>&x@<8N)>%jwfX7j>kIrqhA)J7hNJn+Bt0DnJdSh-Awa!SbH)qzcr0-!8L zbx`mc^MC-Og)$k+DIo(Wt|_ty2%!+B7$D#{uJP$8lcAgvQosoaIDv3y2s0E2c1N5R zOec^OGHN3aL>`#w0iL@v;$hZqW4$7OPup%9$39Gt+Lq@h5@&%H6_?B_Wu>f)?M&@) z$5OuT=e$NeJIH(8u4|_Y*Lr%pWsVIgi<(@=*Dc4)1^~-2amtQf%Q4)sMmOgeUVu%B z0VXkNNU4~Zs7=(zwYvJmWL%qAw%Qp?Df2z_!j_EdY|EN?w7xgv+PM)2N6It0oyp;3v%$7g*2AVZppSQ(<37LUz)aS) z?QO1S`IhVS_xZC8^$mD#)^7^d?Xz$zvA_bpUFRqVd)v*dhfn_r>bvZ|);-i?h9 zw05S>DCG+l%JPz>y?M*C(ze;Jdl}O)EN8f9%rg8v1NaOa-+IV0vyxN}wcUoZE^Y14S^fdBhZ?Jvm~w1~f%dk$24B$#MpQL+J7a@f-;_16 z6>3?HuSS60?V&fq+pJw9Ns8CK4+BL&<@&WuQj8v3Pn&kATE78Rt-X0+ai~l-FuePC zU&b97L3=!*R$DeRrkvWv_iocYzjM@dF5OkjR>lUrJ$lyc9K%R0AUYTe9xCcNq{Xm& zH!BPopk<`l|(nL)o2Pu28(X3RwpY($WJN2)@wDg0!(!7lQ+mp zF)~$jH^~jMLio!=^qaNKn!I5^`GK5A2K+%TLK!Hq7^*Sq>tG{Bd@Hm=2RsN} z81*}07wiTd_JR!~;35YOzyv%3kHTZ{6dXbZJOj_di|`V>46nfJ@CNeWD7=j$`EOY)t0RL*6yU+0G{EyE6Y1#GlasK}eE=;J~ diff --git a/icons/left_click.svg b/icons/left_click.svg index e121cf8..85f4cca 100644 --- a/icons/left_click.svg +++ b/icons/left_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/left_double.svg b/icons/left_double.svg index 75438f3..681dcbb 100644 --- a/icons/left_double.svg +++ b/icons/left_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/left_drag.svg b/icons/left_drag.svg index d407a80..f55785a 100644 --- a/icons/left_drag.svg +++ b/icons/left_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/middle_click.svg b/icons/middle_click.svg index 3835c66..7b4416f 100644 --- a/icons/middle_click.svg +++ b/icons/middle_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/middle_double.svg b/icons/middle_double.svg index aaa9e93..d9cd880 100644 --- a/icons/middle_double.svg +++ b/icons/middle_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/middle_drag.svg b/icons/middle_drag.svg index ba08cbe..eca57fb 100644 --- a/icons/middle_drag.svg +++ b/icons/middle_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/right_click.svg b/icons/right_click.svg index 1ba559c..f729985 100644 --- a/icons/right_click.svg +++ b/icons/right_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/right_double.svg b/icons/right_double.svg index 34ec59b..ea5200e 100644 --- a/icons/right_double.svg +++ b/icons/right_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/right_drag.svg b/icons/right_drag.svg index f946746..1d5189b 100644 --- a/icons/right_drag.svg +++ b/icons/right_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/scroll.svg b/icons/scroll.svg index 55e0450..22d291c 100644 --- a/icons/scroll.svg +++ b/icons/scroll.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/left_click.svg b/icons/selected/left_click.svg index 6d9a86a..dc56503 100644 --- a/icons/selected/left_click.svg +++ b/icons/selected/left_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/left_double.svg b/icons/selected/left_double.svg index 235fc65..264d7b5 100644 --- a/icons/selected/left_double.svg +++ b/icons/selected/left_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/left_drag.svg b/icons/selected/left_drag.svg index a6a4709..2598036 100644 --- a/icons/selected/left_drag.svg +++ b/icons/selected/left_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/middle_click.svg b/icons/selected/middle_click.svg index df975c1..e8fa399 100644 --- a/icons/selected/middle_click.svg +++ b/icons/selected/middle_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/middle_double.svg b/icons/selected/middle_double.svg index c5092b8..a5527be 100644 --- a/icons/selected/middle_double.svg +++ b/icons/selected/middle_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/middle_drag.svg b/icons/selected/middle_drag.svg index 34d68fb..493281d 100644 --- a/icons/selected/middle_drag.svg +++ b/icons/selected/middle_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/right_click.svg b/icons/selected/right_click.svg index b9c0db1..7d45abf 100644 --- a/icons/selected/right_click.svg +++ b/icons/selected/right_click.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/right_double.svg b/icons/selected/right_double.svg index a038c74..fa6463a 100644 --- a/icons/selected/right_double.svg +++ b/icons/selected/right_double.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/right_drag.svg b/icons/selected/right_drag.svg index f67a8df..c7699d8 100644 --- a/icons/selected/right_drag.svg +++ b/icons/selected/right_drag.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/icons/selected/scroll.svg b/icons/selected/scroll.svg index 8d60b19..6393de2 100644 --- a/icons/selected/scroll.svg +++ b/icons/selected/scroll.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 023abd30b97fb8537ff1081e6844dad4a98646dc Mon Sep 17 00:00:00 2001 From: Anthony Lazzaro Date: Fri, 24 Jul 2026 21:35:51 -0700 Subject: [PATCH 08/14] Diagnostic tools (#6) * Test diagnostics tools. * Add translations for diagnostics --- mainwindow.cpp | 61 +++++++++ mainwindow.h | 10 ++ settingsdialog.cpp | 211 +++++++++++++++++++++++++++++++ settingsdialog.h | 18 +++ translations/trackclick_ar.ts | 26 ++++ translations/trackclick_bn.ts | 26 ++++ translations/trackclick_cs.ts | 26 ++++ translations/trackclick_es.ts | 26 ++++ translations/trackclick_fr.ts | 26 ++++ translations/trackclick_hi.ts | 26 ++++ translations/trackclick_ja.ts | 26 ++++ translations/trackclick_ko.ts | 26 ++++ translations/trackclick_pt.ts | 26 ++++ translations/trackclick_ru.ts | 26 ++++ translations/trackclick_ur.ts | 26 ++++ translations/trackclick_zh_CN.ts | 26 ++++ 16 files changed, 612 insertions(+) diff --git a/mainwindow.cpp b/mainwindow.cpp index c9a2793..9d13e5e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -602,6 +602,23 @@ void MainWindow::buildUi() m_titleLabel = new QLabel(tr("TrackClick")); m_titleLabel->setMinimumWidth(0); // let it clip rather than force window wider tbLayout->addWidget(m_titleLabel); + + // Injection-status dot: a small circle that turns red when TrackClick cannot + // deliver clicks (most commonly a missing OS permission). Clicking it opens + // the permission flow when blocked, or the Settings ▸ Diagnostics tab when + // healthy, so a confused user has an obvious next step. + m_statusDot = new QPushButton; + m_statusDot->setFixedSize(14, 14); + m_statusDot->setFocusPolicy(Qt::NoFocus); + m_statusDot->setCursor(Qt::PointingHandCursor); + connect(m_statusDot, &QPushButton::clicked, this, [this]() { + if (!ClickInjector::hasInputDeviceAccess()) + promptForInputAccessIfNeeded(); + else + onSettingsClicked(); + }); + tbLayout->addWidget(m_statusDot); + tbLayout->addStretch(1); // always pushes the action buttons to the right // Auto button @@ -702,9 +719,52 @@ void MainWindow::buildUi() m_statusLabel->setVisible(false); root->addWidget(m_statusLabel); + // Keep the injection-status dot current: access can be granted while the app + // runs (e.g. the user flips the macOS Accessibility switch), so poll it. + m_statusTimer = new QTimer(this); + m_statusTimer->setInterval(2000); + connect(m_statusTimer, &QTimer::timeout, this, &MainWindow::updateStatusDot); + m_statusTimer->start(); + updateStatusDot(); + adjustSize(); } +void MainWindow::updateStatusDot() +{ + if (!m_statusDot) + return; + + const bool ok = ClickInjector::hasInputDeviceAccess(); + + // hasInputDeviceAccess() means different things per platform, so tailor the + // tooltip: on macOS it is the Accessibility grant that gates clicking; on + // Linux it is pointer-tracking (evdev) access used on Wayland; on Windows + // injection is always available. + QString tip; + if (ok) { + tip = tr("Click injection is available. Click for diagnostics."); + } else { +#if defined(Q_OS_MAC) + tip = tr("Clicks are disabled — Accessibility permission not granted. " + "Click to fix."); +#elif defined(Q_OS_LINUX) + tip = tr("Pointer-tracking access is unavailable (needed on Wayland). " + "Click to fix."); +#else + tip = tr("Click injection is unavailable. Click for diagnostics."); +#endif + } + m_statusDot->setToolTip(tip); + + const QString colour = ok ? "#3FB950" : "#E5534B"; // green / red + const QString ring = ok ? "#2A6E33" : "#7A2A26"; + m_statusDot->setStyleSheet(QString( + "QPushButton { background: %1; border: 1px solid %2; border-radius: 7px; }" + "QPushButton:hover { border: 1px solid #FFA600; }" + ).arg(colour, ring)); +} + // Attaches hover-toggle behaviour to a modifier QPushButton: the button toggles // once the cursor has rested on it for the hover-select interval — the same // timing used to switch the active click type (see hoverSelectMs()). The @@ -1862,6 +1922,7 @@ void MainWindow::retranslateUi() if (m_autoBtn) m_autoBtn->setToolTip(tr("Toggle AutoMouse dwell-clicking")); if (m_settingsBtn) m_settingsBtn->setToolTip(tr("Settings")); + updateStatusDot(); // its tooltip is translatable if (m_exitBtn) m_exitBtn->setToolTip(m_settings.xMinimizesApp ? tr("Hide to tray (right-click tray icon to quit)") : tr("Close application")); diff --git a/mainwindow.h b/mainwindow.h index 0aacaa8..08096ac 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -61,6 +61,9 @@ private slots: private: void buildUi(); void buildTray(); + // Refresh the title-bar status dot's colour and tooltip from the current + // injection-access state. Cheap; called on a short timer and on show. + void updateStatusDot(); void rebuildButtons(); void setClickType(ClickType t); void onHotkeySelected(int index); @@ -101,6 +104,10 @@ private slots: QWidget* m_titleBar = nullptr; QLabel* m_titleIcon = nullptr; QLabel* m_titleLabel = nullptr; + // Small clickable dot reflecting whether click injection is available + // (ClickInjector::hasInputDeviceAccess()) — green when ready, red when + // clicks can't be delivered (e.g. Accessibility not granted on macOS). + QPushButton* m_statusDot = nullptr; QPushButton* m_autoBtn = nullptr; QPushButton* m_settingsBtn= nullptr; QPushButton* m_exitBtn = nullptr; @@ -152,6 +159,9 @@ private slots: // ── Sub-objects ─────────────────────────────────────────── DwellManager* m_dwell = nullptr; + // Polls injection-access state so the status dot self-heals after the user + // grants permission (e.g. macOS Accessibility) without restarting. + QTimer* m_statusTimer = nullptr; QSystemTrayIcon* m_tray = nullptr; QMenu* m_trayMenu = nullptr; QAction* m_showAct = nullptr; diff --git a/settingsdialog.cpp b/settingsdialog.cpp index 8670dce..9dd8040 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -3,6 +3,8 @@ #include "audioclicklistener.h" #include "clickinjector.h" #include +#include +#include #include #include #include @@ -665,6 +667,18 @@ void SettingsDialog::retranslateUi() m_cmbAudioDevice->setItemText(0, tr("System default")); m_lblAudioThreshold->setText(tr("Loudness threshold:")); m_lblAudioMeter->setText(tr("Input level:")); + + m_tabs->setTabText(4, tr("Diagnostics")); + m_lblDiagIntro->setText( + tr("If clicking isn't working, this information helps pin down why.")); + m_btnCopyDiag->setText(tr("Copy diagnostics")); + m_lblSelfTestHelp->setText( + tr("Click self-test: TrackClick moves the pointer to the target below and " + "injects a real click. If the target lights up green, click injection " + "is working end-to-end.")); + m_btnSelfTest->setText(tr("Run click self-test")); + m_diagTarget->setText(tr("Target")); + refreshDiagnostics(); } QString SettingsDialog::audioClickInfoText() const @@ -1186,6 +1200,9 @@ void SettingsDialog::buildUi() m_tabs->addTab(pageAudio, tr("Audio Click")); + // ── Diagnostics ─────────────────────────────────────────── + buildDiagnosticsTab(); + // ── Buttons ─────────────────────────────────────────────── m_buttons = new QDialogButtonBox(); m_okBtn = m_buttons->addButton(tr("OK"), QDialogButtonBox::AcceptRole); @@ -1194,6 +1211,200 @@ void SettingsDialog::buildUi() root->addWidget(m_buttons); } +// ── Diagnostics tab ────────────────────────────────────────────────────────── +namespace { + +// One row of the environment read-out. status: -1 problem, 0 neutral, 1 good. +struct DiagRow { QString key; QString value; int status; }; + +QString injectionBackend() +{ +#if defined(Q_OS_WIN) + return QStringLiteral("SendInput (Win32)"); +#elif defined(Q_OS_MAC) + return QStringLiteral("CGEvent (Quartz)"); +#elif defined(Q_OS_LINUX) + return QStringLiteral("XTest (X11 / XWayland)"); +#else + return QStringLiteral("unsupported platform"); +#endif +} + +QVector collectDiagRows() +{ + QVector rows; + +#ifdef BUILD_NUMBER + rows.push_back({ SettingsDialog::tr("TrackClick version"), + QStringLiteral("0.9.6 (build " TC_STR(BUILD_NUMBER) ")"), 0 }); +#else + rows.push_back({ SettingsDialog::tr("TrackClick version"), QStringLiteral("0.9.6"), 0 }); +#endif + rows.push_back({ SettingsDialog::tr("Operating system"), QSysInfo::prettyProductName(), 0 }); + rows.push_back({ SettingsDialog::tr("Windowing system"), QGuiApplication::platformName(), 0 }); + rows.push_back({ SettingsDialog::tr("Click backend"), injectionBackend(), 0 }); + + const bool access = ClickInjector::hasInputDeviceAccess(); +#if defined(Q_OS_MAC) + rows.push_back({ SettingsDialog::tr("Accessibility permission"), + access ? SettingsDialog::tr("Granted") + : SettingsDialog::tr("NOT granted — clicks are blocked"), + access ? 1 : -1 }); +#elif defined(Q_OS_LINUX) + rows.push_back({ SettingsDialog::tr("Pointer tracking (evdev)"), + access ? SettingsDialog::tr("Available") + : SettingsDialog::tr("Unavailable — needed for dwell tracking on Wayland"), + access ? 1 : -1 }); +#else + rows.push_back({ SettingsDialog::tr("Input injection"), + access ? SettingsDialog::tr("Available") : SettingsDialog::tr("Unavailable"), + access ? 1 : -1 }); +#endif + return rows; +} + +} // namespace + +void SettingsDialog::buildDiagnosticsTab() +{ + auto* page = new QWidget; + auto* v = new QVBoxLayout(page); + v->setSpacing(8); + + m_lblDiagIntro = new QLabel( + tr("If clicking isn't working, this information helps pin down why.")); + m_lblDiagIntro->setWordWrap(true); + v->addWidget(m_lblDiagIntro); + + // Environment read-out (rich text; colours flag problem rows). + m_lblDiagInfo = new QLabel; + m_lblDiagInfo->setTextInteractionFlags(Qt::TextSelectableByMouse); + m_lblDiagInfo->setStyleSheet( + "background:#1E1E1E; border:1px solid #444; border-radius:4px; padding:6px;"); + v->addWidget(m_lblDiagInfo); + + m_btnCopyDiag = new QPushButton(tr("Copy diagnostics")); + m_btnCopyDiag->setProperty("flat", true); + connect(m_btnCopyDiag, &QPushButton::clicked, this, [this]() { + QApplication::clipboard()->setText(diagnosticsPlainText()); + m_btnCopyDiag->setText(tr("Copied!")); + QTimer::singleShot(1500, m_btnCopyDiag, [this]() { + if (m_btnCopyDiag) m_btnCopyDiag->setText(tr("Copy diagnostics")); + }); + }); + v->addWidget(m_btnCopyDiag, 0, Qt::AlignLeft); + + auto* sep = new QFrame; + sep->setFrameShape(QFrame::HLine); + sep->setStyleSheet("QFrame { color:#555; }"); + v->addWidget(sep); + + m_lblSelfTestHelp = new QLabel( + tr("Click self-test: TrackClick moves the pointer to the target below and " + "injects a real click. If the target lights up green, click injection " + "is working end-to-end.")); + m_lblSelfTestHelp->setWordWrap(true); + v->addWidget(m_lblSelfTestHelp); + + auto* testRow = new QHBoxLayout; + m_btnSelfTest = new QPushButton(tr("Run click self-test")); + connect(m_btnSelfTest, &QPushButton::clicked, this, &SettingsDialog::runClickSelfTest); + testRow->addWidget(m_btnSelfTest); + + // The synthetic click is aimed here; its clicked() proves the event landed. + m_diagTarget = new QPushButton(tr("Target")); + m_diagTarget->setFixedSize(90, 40); + m_diagTarget->setFocusPolicy(Qt::NoFocus); + const QString targetIdle = + "QPushButton { background:#3A3A3A; color:#DDD; border:2px solid #666; border-radius:5px; }"; + const QString targetHit = + "QPushButton { background:#204A26; color:#FFF; border:2px solid #3FB950; border-radius:5px; }"; + m_diagTarget->setStyleSheet(targetIdle); + connect(m_diagTarget, &QPushButton::clicked, this, [this, targetIdle, targetHit]() { + m_selfTestHit = true; + m_diagTarget->setStyleSheet(targetHit); + QTimer::singleShot(600, m_diagTarget, [this, targetIdle]() { + if (m_diagTarget) m_diagTarget->setStyleSheet(targetIdle); + }); + }); + testRow->addWidget(m_diagTarget); + testRow->addStretch(1); + v->addLayout(testRow); + + m_lblSelfTestResult = new QLabel; + m_lblSelfTestResult->setWordWrap(true); + v->addWidget(m_lblSelfTestResult); + + v->addStretch(1); + + refreshDiagnostics(); + m_tabs->addTab(page, tr("Diagnostics")); +} + +void SettingsDialog::refreshDiagnostics() +{ + if (!m_lblDiagInfo) + return; + QString html = QStringLiteral(""); + for (const DiagRow& r : collectDiagRows()) { + const QString colour = r.status < 0 ? QStringLiteral("#E5534B") + : r.status > 0 ? QStringLiteral("#3FB950") + : QStringLiteral("#E6E6E6"); + html += QStringLiteral("" + "") + .arg(r.key.toHtmlEscaped(), colour, r.value.toHtmlEscaped()); + } + html += QStringLiteral("
%1  %3
"); + m_lblDiagInfo->setText(html); +} + +QString SettingsDialog::diagnosticsPlainText() const +{ + QString out = QStringLiteral("TrackClick diagnostics\n----------------------\n"); + for (const DiagRow& r : collectDiagRows()) + out += r.key + QStringLiteral(": ") + r.value + QChar('\n'); + return out; +} + +void SettingsDialog::runClickSelfTest() +{ + if (!m_diagTarget || !m_btnSelfTest || !m_lblSelfTestResult) + return; + + m_selfTestHit = false; + m_btnSelfTest->setEnabled(false); + m_lblSelfTestResult->setStyleSheet("color:#E6A100; background:transparent;"); + m_lblSelfTestResult->setText(tr("Testing… please don't move the mouse.")); + + // Aim at the target's centre and remember the pointer's spot so it can be + // restored — the test drives the real system cursor to deliver a real click. + const QPoint target = m_diagTarget->mapToGlobal(m_diagTarget->rect().center()); + const QPoint saved = ClickInjector::cursorPos(); + + ClickInjector::moveCursor(target); + + // Let the move settle, inject the click, then evaluate after it round-trips + // through the OS back to the target widget. + QTimer::singleShot(120, this, [this, target, saved]() { + ClickInjector::performClick(ClickType::LeftClick, target); + QTimer::singleShot(350, this, [this, saved]() { + ClickInjector::moveCursor(saved); // put the pointer back + if (m_btnSelfTest) m_btnSelfTest->setEnabled(true); + if (!m_lblSelfTestResult) return; + if (m_selfTestHit) { + m_lblSelfTestResult->setStyleSheet("color:#3FB950; background:transparent;"); + m_lblSelfTestResult->setText( + tr("PASS — the injected click was delivered. Click injection works.")); + } else { + m_lblSelfTestResult->setStyleSheet("color:#E5534B; background:transparent;"); + m_lblSelfTestResult->setText( + tr("FAIL — the click was injected but never arrived. This usually " + "means TrackClick lacks permission to control the mouse.")); + } + }); + }); +} + #ifdef Q_OS_LINUX void SettingsDialog::promptInstallOnScreenKeyboard() { diff --git a/settingsdialog.h b/settingsdialog.h index c653123..b3f09f6 100644 --- a/settingsdialog.h +++ b/settingsdialog.h @@ -170,6 +170,14 @@ class SettingsDialog : public QDialog void moveSelectedButton(int delta); void updateMoveButtons(); QString clickButtonLabel(const QString& id) const; + // ── Diagnostics tab ─────────────────────────────────────── + // Build the Diagnostics tab, refresh its environment read-out, and run the + // end-to-end click self-test (injects a real click at an in-dialog target + // and checks it is delivered). diagnosticsPlainText() is the clipboard form. + void buildDiagnosticsTab(); + void refreshDiagnostics(); + void runClickSelfTest(); + QString diagnosticsPlainText() const; #ifdef Q_OS_LINUX // When no on-screen keyboard is installed, offer to install one through the // system package manager (with a graphical pkexec password prompt) rather @@ -262,6 +270,16 @@ class SettingsDialog : public QDialog QLineEdit* m_edtHotkeyLabel[3] = {}; QKeySequenceEdit* m_kseHotkey[3] = {}; + // ── Diagnostics tab ─────────────────────────────────────── + QLabel* m_lblDiagIntro = nullptr; + QLabel* m_lblDiagInfo = nullptr; // environment read-out (rich text) + QPushButton* m_btnCopyDiag = nullptr; + QLabel* m_lblSelfTestHelp = nullptr; + QPushButton* m_btnSelfTest = nullptr; + QPushButton* m_diagTarget = nullptr; // synthetic click lands here + QLabel* m_lblSelfTestResult = nullptr; + bool m_selfTestHit = false; // set when the target receives a click + QDialogButtonBox* m_buttons; QPushButton* m_okBtn = nullptr; QPushButton* m_cancelBtn = nullptr; diff --git a/translations/trackclick_ar.ts b/translations/trackclick_ar.ts index f2b7573..f6d5dd8 100644 --- a/translations/trackclick_ar.ts +++ b/translations/trackclick_ar.ts @@ -50,6 +50,10 @@ Dwell Activeالتحوم نشط Enable dwell-clicking (same as the Auto button)تمكين النقر بالتحوم (مثل زر Auto) Close applicationإغلاق التطبيق + Click injection is available. Click for diagnostics.حقن النقر متاح. انقر لعرض التشخيص. + Clicks are disabled — Accessibility permission not granted. Click to fix.النقرات معطّلة — لم يُمنح إذن إمكانية الوصول. انقر للإصلاح. + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.الوصول إلى تتبّع المؤشر غير متاح (مطلوب على Wayland). انقر للإصلاح. + Click injection is unavailable. Click for diagnostics.حقن النقر غير متاح. انقر لعرض التشخيص. SettingsDialog @@ -127,6 +131,28 @@ Please install 'onboard' or 'florence'.لم يتم الع Show click indicator ring (Windows)إظهار حلقة مؤشر النقر (Windows) OKموافق Cancelإلغاء + Diagnosticsالتشخيص + If clicking isn't working, this information helps pin down why.إذا كان النقر لا يعمل، فهذه المعلومات تساعد في تحديد السبب. + Copy diagnosticsنسخ التشخيص + Copied!تم النسخ! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.اختبار ذاتي للنقر: يحرّك TrackClick المؤشر إلى الهدف أدناه ويحقن نقرة حقيقية. إذا أضاء الهدف باللون الأخضر، فإن حقن النقر يعمل من البداية إلى النهاية. + Run click self-testتشغيل الاختبار الذاتي للنقر + Targetالهدف + Testing… please don't move the mouse.جارٍ الاختبار… لا تحرّك الماوس. + PASS — the injected click was delivered. Click injection works.نجاح — تم تسليم النقرة المحقونة. حقن النقر يعمل. + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.فشل — تم حقن النقرة لكنها لم تصل أبدًا. يعني هذا عادةً أن TrackClick لا يملك إذنًا للتحكم في الماوس. + TrackClick versionإصدار TrackClick + Operating systemنظام التشغيل + Windowing systemنظام النوافذ + Click backendخلفية النقر + Accessibility permissionإذن إمكانية الوصول + Grantedممنوح + NOT granted — clicks are blockedغير ممنوح — النقرات محظورة + Pointer tracking (evdev)تتبّع المؤشر (evdev) + Availableمتاح + Unavailable — needed for dwell tracking on Waylandغير متاح — مطلوب لتتبّع التمرير على Wayland + Input injectionحقن الإدخال + Unavailableغير متاح SensitivityTesterDialog diff --git a/translations/trackclick_bn.ts b/translations/trackclick_bn.ts index 88a5ba4..649e711 100644 --- a/translations/trackclick_bn.ts +++ b/translations/trackclick_bn.ts @@ -50,6 +50,10 @@ Dwell Activeড্ওয়েল সক্রিয় Enable dwell-clicking (same as the Auto button)ড্ওয়েল-ক্লিকিং সক্ষম করুন (Auto বোতামের মতো) Close applicationঅ্যাপ্লিকেশন বন্ধ করুন + Click injection is available. Click for diagnostics.ক্লিক ইনজেকশন উপলব্ধ। ডায়াগনস্টিকসের জন্য ক্লিক করুন। + Clicks are disabled — Accessibility permission not granted. Click to fix.ক্লিক নিষ্ক্রিয় — Accessibility অনুমতি দেওয়া হয়নি। ঠিক করতে ক্লিক করুন। + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.পয়েন্টার ট্র্যাকিং অ্যাক্সেস উপলব্ধ নয় (Wayland-এ প্রয়োজন)। ঠিক করতে ক্লিক করুন। + Click injection is unavailable. Click for diagnostics.ক্লিক ইনজেকশন উপলব্ধ নয়। ডায়াগনস্টিকসের জন্য ক্লিক করুন। SettingsDialog @@ -127,6 +131,28 @@ Please install 'onboard' or 'florence'.কোনো অন Show click indicator ring (Windows)ক্লিক ইন্ডিকেটর রিং দেখান (Windows) OKঠিক আছে Cancelবাতিল + Diagnosticsডায়াগনস্টিকস + If clicking isn't working, this information helps pin down why.ক্লিক কাজ না করলে, এই তথ্য কারণ খুঁজে বের করতে সাহায্য করে। + Copy diagnosticsডায়াগনস্টিকস কপি করুন + Copied!কপি হয়েছে! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.ক্লিক স্ব-পরীক্ষা: TrackClick পয়েন্টারটিকে নিচের লক্ষ্যে সরিয়ে নেয় এবং একটি প্রকৃত ক্লিক ইনজেক্ট করে। লক্ষ্যটি সবুজ হয়ে উঠলে, ক্লিক ইনজেকশন শুরু থেকে শেষ পর্যন্ত কাজ করছে। + Run click self-testক্লিক স্ব-পরীক্ষা চালান + Targetলক্ষ্য + Testing… please don't move the mouse.পরীক্ষা করা হচ্ছে… মাউস নাড়াবেন না। + PASS — the injected click was delivered. Click injection works.সফল — ইনজেক্ট করা ক্লিকটি পৌঁছেছে। ক্লিক ইনজেকশন কাজ করছে। + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.ব্যর্থ — ক্লিকটি ইনজেক্ট করা হয়েছিল কিন্তু কখনও পৌঁছায়নি। এর সাধারণত অর্থ হল TrackClick-এর মাউস নিয়ন্ত্রণের অনুমতি নেই। + TrackClick versionTrackClick সংস্করণ + Operating systemঅপারেটিং সিস্টেম + Windowing systemউইন্ডোয়িং সিস্টেম + Click backendক্লিক ব্যাকএন্ড + Accessibility permissionAccessibility অনুমতি + Grantedপ্রদত্ত + NOT granted — clicks are blockedপ্রদান করা হয়নি — ক্লিক অবরুদ্ধ + Pointer tracking (evdev)পয়েন্টার ট্র্যাকিং (evdev) + Availableউপলব্ধ + Unavailable — needed for dwell tracking on Waylandঅনুপলব্ধ — Wayland-এ হোভার ট্র্যাকিংয়ের জন্য প্রয়োজন + Input injectionইনপুট ইনজেকশন + Unavailableঅনুপলব্ধ SensitivityTesterDialog diff --git a/translations/trackclick_cs.ts b/translations/trackclick_cs.ts index 617ea0a..3704b4e 100644 --- a/translations/trackclick_cs.ts +++ b/translations/trackclick_cs.ts @@ -47,6 +47,10 @@ No actionŽádná akce Dwell ActiveNajetí aktivní Enable dwell-clicking (same as the Auto button)Povolit klikání při najetí (stejné jako tlačítko Auto) + Click injection is available. Click for diagnostics.Vkládání kliknutí je dostupné. Klikněte pro diagnostiku. + Clicks are disabled — Accessibility permission not granted. Click to fix.Klikání je zakázáno — oprávnění Zpřístupnění nebylo uděleno. Klikněte pro nápravu. + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.Přístup ke sledování ukazatele není dostupný (potřebný na Waylandu). Klikněte pro nápravu. + Click injection is unavailable. Click for diagnostics.Vkládání kliknutí není dostupné. Klikněte pro diagnostiku. SettingsDialog @@ -124,6 +128,28 @@ Nainstalujte prosím 'onboard' nebo 'florence'. Reset to DefaultsObnovit výchozí nastavení OKOK CancelZrušit + DiagnosticsDiagnostika + If clicking isn't working, this information helps pin down why.Pokud klikání nefunguje, tyto informace pomohou zjistit příčinu. + Copy diagnosticsKopírovat diagnostiku + Copied!Zkopírováno! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.Automatický test kliknutí: TrackClick přesune ukazatel na cíl níže a vloží skutečné kliknutí. Pokud se cíl rozsvítí zeleně, vkládání kliknutí funguje od začátku do konce. + Run click self-testSpustit automatický test kliknutí + TargetCíl + Testing… please don't move the mouse.Testování… nehýbejte myší. + PASS — the injected click was delivered. Click injection works.ÚSPĚCH — vložené kliknutí bylo doručeno. Vkládání kliknutí funguje. + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.SELHÁNÍ — kliknutí bylo vloženo, ale nikdy nedorazilo. To obvykle znamená, že TrackClick nemá oprávnění ovládat myš. + TrackClick versionVerze TrackClick + Operating systemOperační systém + Windowing systemOkenní systém + Click backendNástroj pro klikání + Accessibility permissionOprávnění Zpřístupnění + GrantedUděleno + NOT granted — clicks are blockedNEuděleno — klikání je blokováno + Pointer tracking (evdev)Sledování ukazatele (evdev) + AvailableDostupné + Unavailable — needed for dwell tracking on WaylandNedostupné — potřebné pro sledování najetí na Waylandu + Input injectionVkládání vstupu + UnavailableNedostupné SensitivityTesterDialog diff --git a/translations/trackclick_es.ts b/translations/trackclick_es.ts index 96969e2..520d680 100644 --- a/translations/trackclick_es.ts +++ b/translations/trackclick_es.ts @@ -45,6 +45,10 @@ No actionSin acción Dwell ActivePermanencia activa Enable dwell-clicking (same as the Auto button)Activar clic por permanencia (igual que el botón Auto) + Click injection is available. Click for diagnostics.La inyección de clic está disponible. Haga clic para ver el diagnóstico. + Clicks are disabled — Accessibility permission not granted. Click to fix.Los clics están desactivados — permiso de Accesibilidad no concedido. Haga clic para solucionarlo. + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.El acceso al seguimiento del puntero no está disponible (necesario en Wayland). Haga clic para solucionarlo. + Click injection is unavailable. Click for diagnostics.La inyección de clic no está disponible. Haga clic para ver el diagnóstico. SettingsDialog @@ -122,6 +126,28 @@ Instale 'onboard' o 'florence'. Reset to DefaultsRestablecer valores predeterminados OKAceptar CancelCancelar + DiagnosticsDiagnóstico + If clicking isn't working, this information helps pin down why.Si los clics no funcionan, esta información ayuda a identificar la causa. + Copy diagnosticsCopiar diagnóstico + Copied!¡Copiado! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.Autoprueba de clic: TrackClick mueve el puntero al objetivo de abajo e inyecta un clic real. Si el objetivo se ilumina en verde, la inyección de clic funciona de principio a fin. + Run click self-testEjecutar autoprueba de clic + TargetObjetivo + Testing… please don't move the mouse.Probando… no mueva el ratón. + PASS — the injected click was delivered. Click injection works.CORRECTO — el clic inyectado se entregó. La inyección de clic funciona. + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.FALLO — el clic se inyectó pero nunca llegó. Esto suele significar que TrackClick no tiene permiso para controlar el ratón. + TrackClick versionVersión de TrackClick + Operating systemSistema operativo + Windowing systemSistema de ventanas + Click backendMotor de clic + Accessibility permissionPermiso de Accesibilidad + GrantedConcedido + NOT granted — clicks are blockedNO concedido — los clics están bloqueados + Pointer tracking (evdev)Seguimiento del puntero (evdev) + AvailableDisponible + Unavailable — needed for dwell tracking on WaylandNo disponible — necesario para el seguimiento en Wayland + Input injectionInyección de entrada + UnavailableNo disponible SensitivityTesterDialog diff --git a/translations/trackclick_fr.ts b/translations/trackclick_fr.ts index 2b8a8ae..56e547f 100644 --- a/translations/trackclick_fr.ts +++ b/translations/trackclick_fr.ts @@ -45,6 +45,10 @@ No actionAucune action Dwell ActiveSurvol actif Enable dwell-clicking (same as the Auto button)Activer le clic par survol (même que le bouton Auto) + Click injection is available. Click for diagnostics.L'injection de clic est disponible. Cliquez pour le diagnostic. + Clicks are disabled — Accessibility permission not granted. Click to fix.Les clics sont désactivés — permission d'accessibilité non accordée. Cliquez pour corriger. + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.L'accès au suivi du pointeur est indisponible (requis sous Wayland). Cliquez pour corriger. + Click injection is unavailable. Click for diagnostics.L'injection de clic est indisponible. Cliquez pour le diagnostic. SettingsDialog @@ -122,6 +126,28 @@ Veuillez installer 'onboard' ou 'florence'. Reset to DefaultsRéinitialiser les valeurs par défaut OKOK CancelAnnuler + DiagnosticsDiagnostic + If clicking isn't working, this information helps pin down why.Si les clics ne fonctionnent pas, ces informations aident à en trouver la cause. + Copy diagnosticsCopier le diagnostic + Copied!Copié ! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.Auto-test de clic : TrackClick déplace le pointeur vers la cible ci-dessous et injecte un vrai clic. Si la cible devient verte, l'injection de clic fonctionne de bout en bout. + Run click self-testLancer l'auto-test de clic + TargetCible + Testing… please don't move the mouse.Test en cours… ne bougez pas la souris. + PASS — the injected click was delivered. Click injection works.RÉUSSITE — le clic injecté a été délivré. L'injection de clic fonctionne. + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.ÉCHEC — le clic a été injecté mais n'est jamais arrivé. Cela signifie généralement que TrackClick n'a pas la permission de contrôler la souris. + TrackClick versionVersion de TrackClick + Operating systemSystème d'exploitation + Windowing systemSystème de fenêtrage + Click backendMoteur de clic + Accessibility permissionPermission d'accessibilité + GrantedAccordée + NOT granted — clicks are blockedNON accordée — les clics sont bloqués + Pointer tracking (evdev)Suivi du pointeur (evdev) + AvailableDisponible + Unavailable — needed for dwell tracking on WaylandIndisponible — requis pour le suivi du survol sous Wayland + Input injectionInjection d'entrée + UnavailableIndisponible SensitivityTesterDialog diff --git a/translations/trackclick_hi.ts b/translations/trackclick_hi.ts index 42e479a..8967a58 100644 --- a/translations/trackclick_hi.ts +++ b/translations/trackclick_hi.ts @@ -50,6 +50,10 @@ Dwell Activeड्वेल सक्रिय Enable dwell-clicking (same as the Auto button)ड्वेल-क्लिकिंग सक्षम करें (Auto बटन के समान) Close applicationएप्लिकेशन बंद करें + Click injection is available. Click for diagnostics.क्लिक इंजेक्शन उपलब्ध है। निदान के लिए क्लिक करें। + Clicks are disabled — Accessibility permission not granted. Click to fix.क्लिक अक्षम हैं — Accessibility अनुमति नहीं दी गई। ठीक करने के लिए क्लिक करें। + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.पॉइंटर ट्रैकिंग एक्सेस उपलब्ध नहीं है (Wayland पर आवश्यक)। ठीक करने के लिए क्लिक करें। + Click injection is unavailable. Click for diagnostics.क्लिक इंजेक्शन उपलब्ध नहीं है। निदान के लिए क्लिक करें। SettingsDialog @@ -127,6 +131,28 @@ Please install 'onboard' or 'florence'.कोई ऑन- Show click indicator ring (Windows)क्लिक संकेतक रिंग दिखाएं (Windows) OKठीक है Cancelरद्द करें + Diagnosticsनिदान + If clicking isn't working, this information helps pin down why.यदि क्लिक काम नहीं कर रहा है, तो यह जानकारी कारण पता लगाने में मदद करती है। + Copy diagnosticsनिदान कॉपी करें + Copied!कॉपी हो गया! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.क्लिक स्व-परीक्षण: TrackClick पॉइंटर को नीचे दिए लक्ष्य पर ले जाता है और एक वास्तविक क्लिक इंजेक्ट करता है। यदि लक्ष्य हरा हो जाता है, तो क्लिक इंजेक्शन आरंभ से अंत तक काम कर रहा है। + Run click self-testक्लिक स्व-परीक्षण चलाएँ + Targetलक्ष्य + Testing… please don't move the mouse.परीक्षण हो रहा है… माउस न हिलाएँ। + PASS — the injected click was delivered. Click injection works.पास — इंजेक्ट किया गया क्लिक पहुँच गया। क्लिक इंजेक्शन काम करता है। + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.विफल — क्लिक इंजेक्ट हुआ लेकिन कभी नहीं पहुँचा। इसका आमतौर पर मतलब है कि TrackClick के पास माउस को नियंत्रित करने की अनुमति नहीं है। + TrackClick versionTrackClick संस्करण + Operating systemऑपरेटिंग सिस्टम + Windowing systemविंडोइंग सिस्टम + Click backendक्लिक बैकएंड + Accessibility permissionAccessibility अनुमति + Grantedदी गई + NOT granted — clicks are blockedनहीं दी गई — क्लिक अवरुद्ध हैं + Pointer tracking (evdev)पॉइंटर ट्रैकिंग (evdev) + Availableउपलब्ध + Unavailable — needed for dwell tracking on Waylandअनुपलब्ध — Wayland पर होवर ट्रैकिंग के लिए आवश्यक + Input injectionइनपुट इंजेक्शन + Unavailableअनुपलब्ध SensitivityTesterDialog diff --git a/translations/trackclick_ja.ts b/translations/trackclick_ja.ts index 24a1cb7..b2bd40d 100644 --- a/translations/trackclick_ja.ts +++ b/translations/trackclick_ja.ts @@ -45,6 +45,10 @@ No action何もしない Dwell Activeドウェル有効 Enable dwell-clicking (same as the Auto button)滞留クリックを有効にする(Autoボタンと同じ) + Click injection is available. Click for diagnostics.クリックの送信が利用可能です。クリックして診断を表示します。 + Clicks are disabled — Accessibility permission not granted. Click to fix.クリックが無効です — アクセシビリティの許可が付与されていません。クリックして修正します。 + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.ポインター追跡へのアクセスが利用できません(Wayland で必要)。クリックして修正します。 + Click injection is unavailable. Click for diagnostics.クリックの送信が利用できません。クリックして診断を表示します。 SettingsDialog @@ -122,6 +126,28 @@ Please install 'onboard' or 'florence'.スクリーンキ Reset to Defaultsデフォルトに戻す OKOK Cancelキャンセル + Diagnostics診断 + If clicking isn't working, this information helps pin down why.クリックが動作しない場合、この情報が原因の特定に役立ちます。 + Copy diagnostics診断をコピー + Copied!コピーしました! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.クリックの自己テスト:TrackClick はポインターを下のターゲットに移動し、実際のクリックを送信します。ターゲットが緑色に点灯すれば、クリックの送信は端から端まで正常に機能しています。 + Run click self-testクリックの自己テストを実行 + Targetターゲット + Testing… please don't move the mouse.テスト中… マウスを動かさないでください。 + PASS — the injected click was delivered. Click injection works.成功 — 送信されたクリックが届きました。クリックの送信は機能しています。 + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.失敗 — クリックは送信されましたが届きませんでした。通常、これは TrackClick にマウスを制御する許可がないことを意味します。 + TrackClick versionTrackClick のバージョン + Operating systemオペレーティングシステム + Windowing systemウィンドウシステム + Click backendクリックのバックエンド + Accessibility permissionアクセシビリティの許可 + Granted付与済み + NOT granted — clicks are blocked未付与 — クリックはブロックされています + Pointer tracking (evdev)ポインター追跡 (evdev) + Available利用可能 + Unavailable — needed for dwell tracking on Wayland利用不可 — Wayland でのホバー追跡に必要 + Input injection入力送信 + Unavailable利用不可 SensitivityTesterDialog diff --git a/translations/trackclick_ko.ts b/translations/trackclick_ko.ts index 7fa3e5e..b06309a 100644 --- a/translations/trackclick_ko.ts +++ b/translations/trackclick_ko.ts @@ -45,6 +45,10 @@ No action동작 없음 Dwell Active머물기 활성 Enable dwell-clicking (same as the Auto button)머물기 클릭 활성화 (자동 버튼과 동일) + Click injection is available. Click for diagnostics.클릭 주입을 사용할 수 있습니다. 클릭하면 진단이 표시됩니다. + Clicks are disabled — Accessibility permission not granted. Click to fix.클릭이 비활성화되었습니다 — 손쉬운 사용 권한이 부여되지 않았습니다. 클릭하여 해결하세요. + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.포인터 추적 액세스를 사용할 수 없습니다(Wayland에서 필요). 클릭하여 해결하세요. + Click injection is unavailable. Click for diagnostics.클릭 주입을 사용할 수 없습니다. 클릭하면 진단이 표시됩니다. SettingsDialog @@ -122,6 +126,28 @@ Please install 'onboard' or 'florence'.화상 키보드를 Reset to Defaults기본값으로 재설정 OK확인 Cancel취소 + Diagnostics진단 + If clicking isn't working, this information helps pin down why.클릭이 작동하지 않는 경우 이 정보가 원인을 파악하는 데 도움이 됩니다. + Copy diagnostics진단 복사 + Copied!복사됨! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.클릭 자체 테스트: TrackClick이 포인터를 아래 대상으로 이동하고 실제 클릭을 주입합니다. 대상이 녹색으로 켜지면 클릭 주입이 처음부터 끝까지 작동하는 것입니다. + Run click self-test클릭 자체 테스트 실행 + Target대상 + Testing… please don't move the mouse.테스트 중… 마우스를 움직이지 마세요. + PASS — the injected click was delivered. Click injection works.성공 — 주입된 클릭이 전달되었습니다. 클릭 주입이 작동합니다. + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.실패 — 클릭이 주입되었지만 도달하지 않았습니다. 일반적으로 TrackClick에 마우스를 제어할 권한이 없다는 의미입니다. + TrackClick versionTrackClick 버전 + Operating system운영 체제 + Windowing system윈도우 시스템 + Click backend클릭 백엔드 + Accessibility permission손쉬운 사용 권한 + Granted부여됨 + NOT granted — clicks are blocked부여되지 않음 — 클릭이 차단됨 + Pointer tracking (evdev)포인터 추적 (evdev) + Available사용 가능 + Unavailable — needed for dwell tracking on Wayland사용 불가 — Wayland에서 호버 추적에 필요 + Input injection입력 주입 + Unavailable사용 불가 SensitivityTesterDialog diff --git a/translations/trackclick_pt.ts b/translations/trackclick_pt.ts index 8eb3a37..9b71a3d 100644 --- a/translations/trackclick_pt.ts +++ b/translations/trackclick_pt.ts @@ -50,6 +50,10 @@ Dwell ActivePermanência ativa Enable dwell-clicking (same as the Auto button)Ativar clique por permanência (igual ao botão Auto) Close applicationFechar aplicação + Click injection is available. Click for diagnostics.A injeção de clique está disponível. Clique para ver o diagnóstico. + Clicks are disabled — Accessibility permission not granted. Click to fix.Os cliques estão desativados — permissão de Acessibilidade não concedida. Clique para corrigir. + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.O acesso ao rastreamento do ponteiro está indisponível (necessário no Wayland). Clique para corrigir. + Click injection is unavailable. Click for diagnostics.A injeção de clique está indisponível. Clique para ver o diagnóstico. SettingsDialog @@ -127,6 +131,28 @@ Instale 'onboard' ou 'florence'. Show click indicator ring (Windows)Mostrar anel indicador de clique (Windows) OKOK CancelCancelar + DiagnosticsDiagnóstico + If clicking isn't working, this information helps pin down why.Se os cliques não estiverem funcionando, estas informações ajudam a identificar o motivo. + Copy diagnosticsCopiar diagnóstico + Copied!Copiado! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.Autoteste de clique: o TrackClick move o ponteiro para o alvo abaixo e injeta um clique real. Se o alvo acender em verde, a injeção de clique está funcionando de ponta a ponta. + Run click self-testExecutar autoteste de clique + TargetAlvo + Testing… please don't move the mouse.Testando… não mova o mouse. + PASS — the injected click was delivered. Click injection works.APROVADO — o clique injetado foi entregue. A injeção de clique funciona. + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.FALHA — o clique foi injetado, mas nunca chegou. Isso geralmente significa que o TrackClick não tem permissão para controlar o mouse. + TrackClick versionVersão do TrackClick + Operating systemSistema operacional + Windowing systemSistema de janelas + Click backendBackend de clique + Accessibility permissionPermissão de Acessibilidade + GrantedConcedida + NOT granted — clicks are blockedNÃO concedida — os cliques estão bloqueados + Pointer tracking (evdev)Rastreamento do ponteiro (evdev) + AvailableDisponível + Unavailable — needed for dwell tracking on WaylandIndisponível — necessário para rastreamento de foco no Wayland + Input injectionInjeção de entrada + UnavailableIndisponível SensitivityTesterDialog diff --git a/translations/trackclick_ru.ts b/translations/trackclick_ru.ts index eeb8aaa..a3c7436 100644 --- a/translations/trackclick_ru.ts +++ b/translations/trackclick_ru.ts @@ -50,6 +50,10 @@ Dwell ActiveЗадержка активна Enable dwell-clicking (same as the Auto button)Включить нажатие с задержкой (то же что кнопка Auto) Close applicationЗакрыть приложение + Click injection is available. Click for diagnostics.Внедрение щелчков доступно. Нажмите для диагностики. + Clicks are disabled — Accessibility permission not granted. Click to fix.Щелчки отключены — разрешение «Универсальный доступ» не предоставлено. Нажмите, чтобы исправить. + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.Доступ к отслеживанию указателя недоступен (требуется в Wayland). Нажмите, чтобы исправить. + Click injection is unavailable. Click for diagnostics.Внедрение щелчков недоступно. Нажмите для диагностики. SettingsDialog @@ -127,6 +131,28 @@ Please install 'onboard' or 'florence'.Экранная к Show click indicator ring (Windows)Показать кольцо индикатора щелчка (Windows) OKОК CancelОтмена + DiagnosticsДиагностика + If clicking isn't working, this information helps pin down why.Если щелчки не работают, эта информация поможет определить причину. + Copy diagnosticsКопировать диагностику + Copied!Скопировано! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.Самопроверка щелчка: TrackClick перемещает указатель на цель ниже и внедряет настоящий щелчок. Если цель загорается зелёным, внедрение щелчков работает от начала до конца. + Run click self-testЗапустить самопроверку щелчка + TargetЦель + Testing… please don't move the mouse.Проверка… не двигайте мышь. + PASS — the injected click was delivered. Click injection works.УСПЕХ — внедрённый щелчок доставлен. Внедрение щелчков работает. + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.СБОЙ — щелчок был внедрён, но не дошёл. Обычно это означает, что у TrackClick нет разрешения управлять мышью. + TrackClick versionВерсия TrackClick + Operating systemОперационная система + Windowing systemОконная система + Click backendМеханизм щелчков + Accessibility permissionРазрешение «Универсальный доступ» + GrantedПредоставлено + NOT granted — clicks are blockedНЕ предоставлено — щелчки заблокированы + Pointer tracking (evdev)Отслеживание указателя (evdev) + AvailableДоступно + Unavailable — needed for dwell tracking on WaylandНедоступно — требуется для отслеживания наведения в Wayland + Input injectionВнедрение ввода + UnavailableНедоступно SensitivityTesterDialog diff --git a/translations/trackclick_ur.ts b/translations/trackclick_ur.ts index 1c982bc..67aede6 100644 --- a/translations/trackclick_ur.ts +++ b/translations/trackclick_ur.ts @@ -50,6 +50,10 @@ Dwell Activeڈویل فعال Enable dwell-clicking (same as the Auto button)ڈویل-کلکنگ فعال کریں (Auto بٹن کی طرح) Close applicationایپلیکیشن بند کریں + Click injection is available. Click for diagnostics.کلک انجیکشن دستیاب ہے۔ تشخیص کے لیے کلک کریں۔ + Clicks are disabled — Accessibility permission not granted. Click to fix.کلک غیر فعال ہیں — Accessibility اجازت نہیں دی گئی۔ درست کرنے کے لیے کلک کریں۔ + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.پوائنٹر ٹریکنگ تک رسائی دستیاب نہیں (Wayland پر درکار)۔ درست کرنے کے لیے کلک کریں۔ + Click injection is unavailable. Click for diagnostics.کلک انجیکشن دستیاب نہیں۔ تشخیص کے لیے کلک کریں۔ SettingsDialog @@ -127,6 +131,28 @@ Please install 'onboard' or 'florence'.کوئی آن-اس Show click indicator ring (Windows)کلک انڈیکیٹر رِنگ دکھائیں (Windows) OKٹھیک ہے Cancelمنسوخ + Diagnosticsتشخیص + If clicking isn't working, this information helps pin down why.اگر کلک کام نہیں کر رہا، تو یہ معلومات وجہ معلوم کرنے میں مدد کرتی ہے۔ + Copy diagnosticsتشخیص کاپی کریں + Copied!کاپی ہو گیا! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.کلک خود جانچ: TrackClick پوائنٹر کو نیچے دیے گئے ہدف پر لے جاتا ہے اور ایک حقیقی کلک انجیکٹ کرتا ہے۔ اگر ہدف سبز ہو جائے، تو کلک انجیکشن شروع سے آخر تک کام کر رہا ہے۔ + Run click self-testکلک خود جانچ چلائیں + Targetہدف + Testing… please don't move the mouse.جانچ ہو رہی ہے… ماؤس کو نہ ہلائیں۔ + PASS — the injected click was delivered. Click injection works.کامیاب — انجیکٹ کیا گیا کلک پہنچ گیا۔ کلک انجیکشن کام کرتا ہے۔ + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.ناکام — کلک انجیکٹ ہوا لیکن کبھی نہیں پہنچا۔ اس کا عام طور پر مطلب ہے کہ TrackClick کو ماؤس کنٹرول کرنے کی اجازت نہیں ہے۔ + TrackClick versionTrackClick ورژن + Operating systemآپریٹنگ سسٹم + Windowing systemونڈوئنگ سسٹم + Click backendکلک بیک اینڈ + Accessibility permissionAccessibility اجازت + Grantedدی گئی + NOT granted — clicks are blockedنہیں دی گئی — کلک بلاک ہیں + Pointer tracking (evdev)پوائنٹر ٹریکنگ (evdev) + Availableدستیاب + Unavailable — needed for dwell tracking on Waylandغیر دستیاب — Wayland پر ہوور ٹریکنگ کے لیے درکار + Input injectionان پٹ انجیکشن + Unavailableغیر دستیاب SensitivityTesterDialog diff --git a/translations/trackclick_zh_CN.ts b/translations/trackclick_zh_CN.ts index 66b652b..9bba0f9 100644 --- a/translations/trackclick_zh_CN.ts +++ b/translations/trackclick_zh_CN.ts @@ -45,6 +45,10 @@ No action无操作 Dwell Active悬停激活 Enable dwell-clicking (same as the Auto button)启用悬停点击(与自动按钮相同) + Click injection is available. Click for diagnostics.点击注入可用。单击以查看诊断。 + Clicks are disabled — Accessibility permission not granted. Click to fix.点击已禁用 — 未授予辅助功能权限。单击以修复。 + Pointer-tracking access is unavailable (needed on Wayland). Click to fix.指针跟踪访问不可用(在 Wayland 上需要)。单击以修复。 + Click injection is unavailable. Click for diagnostics.点击注入不可用。单击以查看诊断。 SettingsDialog @@ -122,6 +126,28 @@ Please install 'onboard' or 'florence'.未找到屏幕键 Reset to Defaults恢复默认设置 OK确定 Cancel取消 + Diagnostics诊断 + If clicking isn't working, this information helps pin down why.如果点击无法工作,这些信息有助于查明原因。 + Copy diagnostics复制诊断信息 + Copied!已复制! + Click self-test: TrackClick moves the pointer to the target below and injects a real click. If the target lights up green, click injection is working end-to-end.点击自检:TrackClick 将指针移动到下方的目标并注入真实的点击。如果目标变为绿色,则表示点击注入端到端正常工作。 + Run click self-test运行点击自检 + Target目标 + Testing… please don't move the mouse.正在测试… 请勿移动鼠标。 + PASS — the injected click was delivered. Click injection works.通过 — 注入的点击已送达。点击注入正常工作。 + FAIL — the click was injected but never arrived. This usually means TrackClick lacks permission to control the mouse.失败 — 点击已注入但从未到达。这通常意味着 TrackClick 没有控制鼠标的权限。 + TrackClick versionTrackClick 版本 + Operating system操作系统 + Windowing system窗口系统 + Click backend点击后端 + Accessibility permission辅助功能权限 + Granted已授予 + NOT granted — clicks are blocked未授予 — 点击被阻止 + Pointer tracking (evdev)指针跟踪 (evdev) + Available可用 + Unavailable — needed for dwell tracking on Wayland不可用 — 在 Wayland 上进行悬停跟踪时需要 + Input injection输入注入 + Unavailable不可用 SensitivityTesterDialog From 78071750119449a7fae84871e712c064392ebf59 Mon Sep 17 00:00:00 2001 From: Anthony Lazzaro Date: Fri, 24 Jul 2026 23:13:07 -0700 Subject: [PATCH 09/14] Keyboard button (#7) --- icons/keyboard.svg | 1 + mainwindow.cpp | 154 +++++++++++++++++++++++++++++++ mainwindow.h | 20 ++++ resources.qrc | 1 + settingsdialog.cpp | 8 +- settingsdialog.h | 3 + translations/trackclick_ar.ts | 5 + translations/trackclick_bn.ts | 5 + translations/trackclick_cs.ts | 5 + translations/trackclick_es.ts | 5 + translations/trackclick_fr.ts | 5 + translations/trackclick_hi.ts | 5 + translations/trackclick_ja.ts | 5 + translations/trackclick_ko.ts | 5 + translations/trackclick_pt.ts | 5 + translations/trackclick_ru.ts | 5 + translations/trackclick_ur.ts | 5 + translations/trackclick_zh_CN.ts | 5 + 18 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 icons/keyboard.svg diff --git a/icons/keyboard.svg b/icons/keyboard.svg new file mode 100644 index 0000000..edcdc32 --- /dev/null +++ b/icons/keyboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mainwindow.cpp b/mainwindow.cpp index 9d13e5e..6ee679d 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -32,6 +32,7 @@ # include "macos_utils.h" # include # include +# include #endif // ───────────────────────────────────────────────────────────── @@ -332,6 +333,7 @@ MainWindow::MainWindow(QTranslator* startupTranslator, QWidget* parent) m_settings.showModShift = m_persist.value("show/modShift", true).toBool(); m_settings.showQuitButton = m_persist.value("show/quitButton", true).toBool(); m_settings.showDwellActiveBtn= m_persist.value("show/dwellActiveBtn", true).toBool(); + m_settings.showKeyboardButton= m_persist.value("show/keyboardButton", false).toBool(); m_settings.startMinimized = m_persist.value("window/startMin", false).toBool(); m_settings.xMinimizesApp = m_persist.value("window/xMinimizesApp", false).toBool(); // Top X minimizes app is a read-only option locked off: the top X always @@ -833,6 +835,23 @@ static QString modBtnStyle(bool selected, bool large) "QPushButton:hover { background:#4A4A4A; border:1px solid #FFA600; color:#FFA600; }").arg(fs).arg(pad); } +// Style for the on-screen-keyboard toggle button. "on" (keyboard open) uses the +// same amber highlight as the Dwell Active toggle; "off" matches the modifier +// buttons. Shared by makeKeyboard() and refreshKeyboardButton() so the look +// stays in sync whether the state changes by click or by the keyboard closing. +static QString kbdBtnStyle(bool on, bool large) +{ + const char* fs = large ? "14px" : "11px"; + const char* pad = large ? "4px" : "2px"; + return on + ? QString("QPushButton { background:#FFA028; color:#1A1A1A; border:2px solid #FFB040; " + "border-radius:4px; font-weight:bold; font-size:%1; padding:%2; }" + "QPushButton:hover { background:#FFB040; }").arg(fs).arg(pad) + : QString("QPushButton { background:#3A3A3A; color:#DDDDDD; border:1px solid #555; " + "border-radius:4px; font-size:%1; padding:%2; }" + "QPushButton:hover { background:#4A4A4A; border:1px solid #FFA028; color:#FFA028; }").arg(fs).arg(pad); +} + // Uniform minimum cell size for every toolbar button, so click buttons, // modifiers, Dwell Active, Quit and hotkeys share the same footprint and line // up in the grid regardless of which are shown. Width is 0 in the vertical @@ -861,6 +880,7 @@ void MainWindow::rebuildButtons() } m_clickButtons.clear(); m_ctrlBtn = m_altBtn = m_shiftBtn = m_dwellActiveBtn = nullptr; + m_keyboardBtn = nullptr; m_hotkeyBtns[0] = m_hotkeyBtns[1] = m_hotkeyBtns[2] = nullptr; auto* grid = new QGridLayout(m_btnArea); @@ -974,6 +994,30 @@ void MainWindow::rebuildButtons() return quitBtn; }; + // Factory: the on-screen-keyboard toggle. Checkable so it reflects whether + // the keyboard we launched is currently open; hover-select enabled so dwell + // users can trigger it without a physical click (like the modifier buttons). + auto makeKeyboard = [&]() -> QWidget* { + auto* btn = new QPushButton(m_btnArea); + m_keyboardBtn = btn; + btn->setCheckable(true); + btn->setMinimumSize(modSize); + btn->setIcon(QIcon(":/icons/keyboard.svg")); + btn->setIconSize(large ? QSize(28, 24) : QSize(20, 17)); + if (!m_settings.iconsOnly) + btn->setText(tr("Keyboard")); + btn->setToolTip(tr("Show or hide the on-screen keyboard")); + refreshKeyboardButton(); // set initial checked state + style + connect(btn, &QPushButton::toggled, this, [this](bool on){ + // Apply the request, then re-sync the look to the real keyboard + // state (on macOS the button is momentary — see setOnScreenKeyboard). + setOnScreenKeyboard(on); + refreshKeyboardButton(); + }); + new ModHoverFilter(btn, [this]{ return hoverSelectMs(); }); + return btn; + }; + // Factory: a custom-hotkey button for slot i, or nullptr if that slot is off // or has no key assigned. Flows inline with the other reorderable buttons. auto makeHotkey = [&](int i) -> QWidget* { @@ -1036,6 +1080,8 @@ void MainWindow::rebuildButtons() if (m_settings.showDwellActiveBtn) place(makeDwellActive()); } else if (id == QLatin1String("quit")) { if (m_settings.showQuitButton) place(makeQuit()); + } else if (id == QLatin1String("keyboard")) { + if (m_settings.showKeyboardButton) place(makeKeyboard()); } else if (id.startsWith(QLatin1String("hotkey_"))) { bool ok = false; const int i = id.mid(7).toInt(&ok); @@ -1104,6 +1150,113 @@ ClickButton* MainWindow::makeButton(const QString& label, const QString& tooltip return btn; } +// ── On-screen keyboard toggle ──────────────────────────────────────────────── + +bool MainWindow::keyboardIsOpen() const +{ +#if defined(Q_OS_MAC) + return m_macKbdOpen; +#else + return m_kbdProcess && m_kbdProcess->state() != QProcess::NotRunning; +#endif +} + +void MainWindow::refreshKeyboardButton() +{ + if (!m_keyboardBtn) + return; + // Keep the button's checked state and style in sync with the real keyboard + // state without re-triggering the toggle handler. + const bool on = keyboardIsOpen(); + QSignalBlocker block(m_keyboardBtn); + m_keyboardBtn->setChecked(on); + m_keyboardBtn->setStyleSheet(kbdBtnStyle(on, m_settings.largeButtons)); +} + +void MainWindow::setOnScreenKeyboard(bool open) +{ + if (open == keyboardIsOpen()) + return; // already in the requested state + +#if defined(Q_OS_MAC) + // macOS has no launch-and-quit on-screen keyboard: the system Accessibility + // Keyboard is switched on from System Settings and can't be closed + // programmatically. So match the Settings dialog's keyboard button — open + // that pane — and keep the toolbar button momentary (never latched "open"), + // since there is nothing for a second click to close. + if (open) { + const int macMajor = QSysInfo::productVersion().split('.').value(0).toInt(); + QDesktopServices::openUrl(QUrl(macMajor >= 13 + ? "x-apple.systempreferences:com.apple.Accessibility-Settings.extension?Keyboard" + : "x-apple.systempreferences:com.apple.preference.universalaccess?Keyboard")); + } + m_macKbdOpen = false; // keyboardIsOpen() stays false → button un-latches + refreshKeyboardButton(); + return; +#else + if (!open) { + // Close the keyboard we launched. terminate() delivers WM_CLOSE on + // Windows and SIGTERM on Linux, both of which close the keyboard. + if (m_kbdProcess && m_kbdProcess->state() != QProcess::NotRunning) { + m_kbdProcess->terminate(); + if (!m_kbdProcess->waitForFinished(1500)) + m_kbdProcess->kill(); + } + refreshKeyboardButton(); + return; + } + + // ── Launch ──────────────────────────────────────────────── + QString program; + QStringList args; +#if defined(Q_OS_WIN) + // Full path from %SystemRoot% so PATH resolution isn't required. + const QString sysRoot = QString::fromLocal8Bit(qgetenv("SystemRoot")); + program = (sysRoot.isEmpty() ? QString("C:\\Windows") : sysRoot) + + "\\System32\\osk.exe"; +#else + // Linux: launch the first on-screen keyboard that's actually installed, + // preferring Wayland-native ones on Wayland (X11 keyboards can "start" and + // then immediately die on pure Wayland). + const bool onWayland = !qgetenv("WAYLAND_DISPLAY").isEmpty(); + const QStringList kbs = onWayland + ? QStringList{"onboard", "squeekboard", "wvkbd", "maliit-keyboard", + "florence", "kvkbd", "matchbox-keyboard"} + : QStringList{"onboard", "florence", "xvkbd", "kvkbd", "matchbox-keyboard"}; + for (const QString& kb : kbs) { + if (!QStandardPaths::findExecutable(kb).isEmpty()) { program = kb; break; } + } + if (program.isEmpty()) { + QMessageBox::information(this, tr("On-Screen Keyboard"), + tr("No on-screen keyboard was found. You can install one from the " + "Settings window, under the Window tab.")); + refreshKeyboardButton(); // revert the button to unchecked + return; + } +#endif + + auto* proc = new QProcess(this); + // When the keyboard exits (user closed its window, or we terminated it), + // drop our handle and refresh the button so it un-checks. + connect(proc, QOverload::of(&QProcess::finished), + this, [this, proc](int, QProcess::ExitStatus) { + if (m_kbdProcess == proc) m_kbdProcess = nullptr; + proc->deleteLater(); + refreshKeyboardButton(); + }); + proc->start(program, args); + if (proc->waitForStarted(1500)) { + m_kbdProcess = proc; + } else { + // Couldn't track it (rare) — fall back to a detached launch so the + // keyboard still opens, even though we then can't close it from here. + proc->deleteLater(); + QProcess::startDetached(program, args); + } + refreshKeyboardButton(); +#endif +} + void MainWindow::buildTray() { if (!QSystemTrayIcon::isSystemTrayAvailable()) return; @@ -1829,6 +1982,7 @@ void MainWindow::applySettings(const AppSettings& s) m_persist.setValue("show/modShift", s.showModShift); m_persist.setValue("show/quitButton", s.showQuitButton); m_persist.setValue("show/dwellActiveBtn", s.showDwellActiveBtn); + m_persist.setValue("show/keyboardButton", s.showKeyboardButton); m_persist.setValue("show/iconsOnly", s.iconsOnly); m_persist.setValue("show/largeButtons", s.largeButtons); m_persist.setValue("show/buttonLayout", static_cast(s.buttonLayout)); diff --git a/mainwindow.h b/mainwindow.h index 08096ac..60d222c 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -16,6 +16,8 @@ #include #include "clickinjector.h" #include "dwellmanager.h" + +class QProcess; // forward — on-screen keyboard process handle #include "settingsdialog.h" #include "audioclicklistener.h" @@ -61,6 +63,14 @@ private slots: private: void buildUi(); void buildTray(); + // On-screen keyboard toggle used by the toolbar Keyboard button. open(true) + // launches the OS keyboard; open(false) closes the one we launched. Works on + // Windows (osk.exe), Linux (onboard/… via a tracked process) and macOS + // (Keyboard Viewer). keyboardIsOpen() reports the tracked state; + // refreshKeyboardButton() syncs the button's checked look to it. + void setOnScreenKeyboard(bool open); + bool keyboardIsOpen() const; + void refreshKeyboardButton(); // Refresh the title-bar status dot's colour and tooltip from the current // injection-access state. Cheap; called on a short timer and on show. void updateStatusDot(); @@ -126,6 +136,8 @@ private slots: QPushButton* m_altBtn = nullptr; QPushButton* m_shiftBtn = nullptr; QPushButton* m_dwellActiveBtn = nullptr; + // Toolbar button that toggles the OS on-screen keyboard on/off. + QPushButton* m_keyboardBtn = nullptr; // Custom hotkey action buttons (up to 3) QPushButton* m_hotkeyBtns[3] = {}; @@ -159,6 +171,14 @@ private slots: // ── Sub-objects ─────────────────────────────────────────── DwellManager* m_dwell = nullptr; + // On-screen keyboard we launched (Windows/Linux); kept so a second click can + // close it. Null when nothing is running. macOS opens System Settings instead + // (it has no closable keyboard process), tracked by m_macKbdOpen. +#ifdef Q_OS_MAC + bool m_macKbdOpen = false; +#else + QProcess* m_kbdProcess = nullptr; +#endif // Polls injection-access state so the status dot self-heals after the user // grants permission (e.g. macOS Accessibility) without restarting. QTimer* m_statusTimer = nullptr; diff --git a/resources.qrc b/resources.qrc index 3e24aed..04de6d9 100644 --- a/resources.qrc +++ b/resources.qrc @@ -22,6 +22,7 @@ icons/scroll_down.svg icons/scroll_left.svg icons/scroll_right.svg + icons/keyboard.svg icons/selected/no_click.svg diff --git a/settingsdialog.cpp b/settingsdialog.cpp index 9dd8040..7fb14eb 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -201,6 +201,7 @@ const QVector& clickButtonDescs() { "shift", &AppSettings::showModShift }, { "dwell_active", &AppSettings::showDwellActiveBtn }, { "quit", &AppSettings::showQuitButton }, + { "keyboard", &AppSettings::showKeyboardButton }, }; return v; } @@ -224,13 +225,15 @@ static QStringList canonicalButtonIds() QStringList ids; for (const auto& d : clickButtonDescs()) { const QString id = QLatin1String(d.id); - if (id == QLatin1String("dwell_active") || id == QLatin1String("quit")) + if (id == QLatin1String("dwell_active") || id == QLatin1String("quit") + || id == QLatin1String("keyboard")) continue; // appended at the very end below ids << id; } for (int i = 0; i < kHotkeyCount; ++i) ids << QStringLiteral("hotkey_%1").arg(i); - ids << QStringLiteral("dwell_active") << QStringLiteral("quit"); + ids << QStringLiteral("dwell_active") << QStringLiteral("quit") + << QStringLiteral("keyboard"); return ids; } @@ -1512,6 +1515,7 @@ QString SettingsDialog::clickButtonLabel(const QString& id) const if (id == QLatin1String("shift")) return tr("Shift Modifier"); if (id == QLatin1String("dwell_active")) return tr("Dwell Active Button"); if (id == QLatin1String("quit")) return tr("Quit Button"); + if (id == QLatin1String("keyboard")) return tr("Keyboard Button"); const int hk = hotkeyIndexForId(id); if (hk >= 0) return tr("Hotkey %1").arg(hk + 1); return id; diff --git a/settingsdialog.h b/settingsdialog.h index b3f09f6..f78a7b5 100644 --- a/settingsdialog.h +++ b/settingsdialog.h @@ -63,6 +63,9 @@ struct AppSettings { bool showModShift = true; bool showQuitButton = true; bool showDwellActiveBtn = true; + // Toolbar button that toggles the operating-system on-screen keyboard. + // Off by default; users enable it from the visible-buttons list. + bool showKeyboardButton = false; // Window double windowOpacity = 1.0; diff --git a/translations/trackclick_ar.ts b/translations/trackclick_ar.ts index f6d5dd8..aa80e40 100644 --- a/translations/trackclick_ar.ts +++ b/translations/trackclick_ar.ts @@ -50,6 +50,10 @@ Dwell Activeالتحوم نشط Enable dwell-clicking (same as the Auto button)تمكين النقر بالتحوم (مثل زر Auto) Close applicationإغلاق التطبيق + Keyboardلوحة المفاتيح + Show or hide the on-screen keyboardإظهار أو إخفاء لوحة المفاتيح على الشاشة + On-Screen Keyboardلوحة المفاتيح على الشاشة + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.لم يتم العثور على لوحة مفاتيح على الشاشة. يمكنك تثبيت واحدة من نافذة الإعدادات، ضمن علامة التبويب نافذة. Click injection is available. Click for diagnostics.حقن النقر متاح. انقر لعرض التشخيص. Clicks are disabled — Accessibility permission not granted. Click to fix.النقرات معطّلة — لم يُمنح إذن إمكانية الوصول. انقر للإصلاح. Pointer-tracking access is unavailable (needed on Wayland). Click to fix.الوصول إلى تتبّع المؤشر غير متاح (مطلوب على Wayland). انقر للإصلاح. @@ -131,6 +135,7 @@ Please install 'onboard' or 'florence'.لم يتم الع Show click indicator ring (Windows)إظهار حلقة مؤشر النقر (Windows) OKموافق Cancelإلغاء + Keyboard Buttonزر لوحة المفاتيح Diagnosticsالتشخيص If clicking isn't working, this information helps pin down why.إذا كان النقر لا يعمل، فهذه المعلومات تساعد في تحديد السبب. Copy diagnosticsنسخ التشخيص diff --git a/translations/trackclick_bn.ts b/translations/trackclick_bn.ts index 649e711..3b40867 100644 --- a/translations/trackclick_bn.ts +++ b/translations/trackclick_bn.ts @@ -50,6 +50,10 @@ Dwell Activeড্ওয়েল সক্রিয় Enable dwell-clicking (same as the Auto button)ড্ওয়েল-ক্লিকিং সক্ষম করুন (Auto বোতামের মতো) Close applicationঅ্যাপ্লিকেশন বন্ধ করুন + Keyboardকীবোর্ড + Show or hide the on-screen keyboardঅন-স্ক্রিন কীবোর্ড দেখান বা লুকান + On-Screen Keyboardঅন-স্ক্রিন কীবোর্ড + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.কোনো অন-স্ক্রিন কীবোর্ড পাওয়া যায়নি। আপনি সেটিংস উইন্ডোর উইন্ডো ট্যাব থেকে একটি ইনস্টল করতে পারেন। Click injection is available. Click for diagnostics.ক্লিক ইনজেকশন উপলব্ধ। ডায়াগনস্টিকসের জন্য ক্লিক করুন। Clicks are disabled — Accessibility permission not granted. Click to fix.ক্লিক নিষ্ক্রিয় — Accessibility অনুমতি দেওয়া হয়নি। ঠিক করতে ক্লিক করুন। Pointer-tracking access is unavailable (needed on Wayland). Click to fix.পয়েন্টার ট্র্যাকিং অ্যাক্সেস উপলব্ধ নয় (Wayland-এ প্রয়োজন)। ঠিক করতে ক্লিক করুন। @@ -131,6 +135,7 @@ Please install 'onboard' or 'florence'.কোনো অন Show click indicator ring (Windows)ক্লিক ইন্ডিকেটর রিং দেখান (Windows) OKঠিক আছে Cancelবাতিল + Keyboard Buttonকীবোর্ড বোতাম Diagnosticsডায়াগনস্টিকস If clicking isn't working, this information helps pin down why.ক্লিক কাজ না করলে, এই তথ্য কারণ খুঁজে বের করতে সাহায্য করে। Copy diagnosticsডায়াগনস্টিকস কপি করুন diff --git a/translations/trackclick_cs.ts b/translations/trackclick_cs.ts index 3704b4e..5ae38af 100644 --- a/translations/trackclick_cs.ts +++ b/translations/trackclick_cs.ts @@ -47,6 +47,10 @@ No actionŽádná akce Dwell ActiveNajetí aktivní Enable dwell-clicking (same as the Auto button)Povolit klikání při najetí (stejné jako tlačítko Auto) + KeyboardKlávesnice + Show or hide the on-screen keyboardZobrazit nebo skrýt klávesnici na obrazovce + On-Screen KeyboardKlávesnice na obrazovce + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.Nebyla nalezena žádná klávesnice na obrazovce. Můžete si ji nainstalovat z okna Nastavení, na kartě Okno. Click injection is available. Click for diagnostics.Vkládání kliknutí je dostupné. Klikněte pro diagnostiku. Clicks are disabled — Accessibility permission not granted. Click to fix.Klikání je zakázáno — oprávnění Zpřístupnění nebylo uděleno. Klikněte pro nápravu. Pointer-tracking access is unavailable (needed on Wayland). Click to fix.Přístup ke sledování ukazatele není dostupný (potřebný na Waylandu). Klikněte pro nápravu. @@ -128,6 +132,7 @@ Nainstalujte prosím 'onboard' nebo 'florence'. Reset to DefaultsObnovit výchozí nastavení OKOK CancelZrušit + Keyboard ButtonTlačítko klávesnice DiagnosticsDiagnostika If clicking isn't working, this information helps pin down why.Pokud klikání nefunguje, tyto informace pomohou zjistit příčinu. Copy diagnosticsKopírovat diagnostiku diff --git a/translations/trackclick_es.ts b/translations/trackclick_es.ts index 520d680..db6d98c 100644 --- a/translations/trackclick_es.ts +++ b/translations/trackclick_es.ts @@ -45,6 +45,10 @@ No actionSin acción Dwell ActivePermanencia activa Enable dwell-clicking (same as the Auto button)Activar clic por permanencia (igual que el botón Auto) + KeyboardTeclado + Show or hide the on-screen keyboardMostrar u ocultar el teclado en pantalla + On-Screen KeyboardTeclado en pantalla + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.No se encontró ningún teclado en pantalla. Puede instalar uno desde la ventana de Ajustes, en la pestaña Ventana. Click injection is available. Click for diagnostics.La inyección de clic está disponible. Haga clic para ver el diagnóstico. Clicks are disabled — Accessibility permission not granted. Click to fix.Los clics están desactivados — permiso de Accesibilidad no concedido. Haga clic para solucionarlo. Pointer-tracking access is unavailable (needed on Wayland). Click to fix.El acceso al seguimiento del puntero no está disponible (necesario en Wayland). Haga clic para solucionarlo. @@ -126,6 +130,7 @@ Instale 'onboard' o 'florence'. Reset to DefaultsRestablecer valores predeterminados OKAceptar CancelCancelar + Keyboard ButtonBotón de teclado DiagnosticsDiagnóstico If clicking isn't working, this information helps pin down why.Si los clics no funcionan, esta información ayuda a identificar la causa. Copy diagnosticsCopiar diagnóstico diff --git a/translations/trackclick_fr.ts b/translations/trackclick_fr.ts index 56e547f..e418795 100644 --- a/translations/trackclick_fr.ts +++ b/translations/trackclick_fr.ts @@ -45,6 +45,10 @@ No actionAucune action Dwell ActiveSurvol actif Enable dwell-clicking (same as the Auto button)Activer le clic par survol (même que le bouton Auto) + KeyboardClavier + Show or hide the on-screen keyboardAfficher ou masquer le clavier à l'écran + On-Screen KeyboardClavier à l'écran + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.Aucun clavier à l'écran n'a été trouvé. Vous pouvez en installer un depuis la fenêtre des paramètres, dans l'onglet Fenêtre. Click injection is available. Click for diagnostics.L'injection de clic est disponible. Cliquez pour le diagnostic. Clicks are disabled — Accessibility permission not granted. Click to fix.Les clics sont désactivés — permission d'accessibilité non accordée. Cliquez pour corriger. Pointer-tracking access is unavailable (needed on Wayland). Click to fix.L'accès au suivi du pointeur est indisponible (requis sous Wayland). Cliquez pour corriger. @@ -126,6 +130,7 @@ Veuillez installer 'onboard' ou 'florence'. Reset to DefaultsRéinitialiser les valeurs par défaut OKOK CancelAnnuler + Keyboard ButtonBouton Clavier DiagnosticsDiagnostic If clicking isn't working, this information helps pin down why.Si les clics ne fonctionnent pas, ces informations aident à en trouver la cause. Copy diagnosticsCopier le diagnostic diff --git a/translations/trackclick_hi.ts b/translations/trackclick_hi.ts index 8967a58..767ba7f 100644 --- a/translations/trackclick_hi.ts +++ b/translations/trackclick_hi.ts @@ -50,6 +50,10 @@ Dwell Activeड्वेल सक्रिय Enable dwell-clicking (same as the Auto button)ड्वेल-क्लिकिंग सक्षम करें (Auto बटन के समान) Close applicationएप्लिकेशन बंद करें + Keyboardकीबोर्ड + Show or hide the on-screen keyboardऑन-स्क्रीन कीबोर्ड दिखाएँ या छिपाएँ + On-Screen Keyboardऑन-स्क्रीन कीबोर्ड + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.कोई ऑन-स्क्रीन कीबोर्ड नहीं मिला। आप इसे सेटिंग्स विंडो में, विंडो टैब से इंस्टॉल कर सकते हैं। Click injection is available. Click for diagnostics.क्लिक इंजेक्शन उपलब्ध है। निदान के लिए क्लिक करें। Clicks are disabled — Accessibility permission not granted. Click to fix.क्लिक अक्षम हैं — Accessibility अनुमति नहीं दी गई। ठीक करने के लिए क्लिक करें। Pointer-tracking access is unavailable (needed on Wayland). Click to fix.पॉइंटर ट्रैकिंग एक्सेस उपलब्ध नहीं है (Wayland पर आवश्यक)। ठीक करने के लिए क्लिक करें। @@ -131,6 +135,7 @@ Please install 'onboard' or 'florence'.कोई ऑन- Show click indicator ring (Windows)क्लिक संकेतक रिंग दिखाएं (Windows) OKठीक है Cancelरद्द करें + Keyboard Buttonकीबोर्ड बटन Diagnosticsनिदान If clicking isn't working, this information helps pin down why.यदि क्लिक काम नहीं कर रहा है, तो यह जानकारी कारण पता लगाने में मदद करती है। Copy diagnosticsनिदान कॉपी करें diff --git a/translations/trackclick_ja.ts b/translations/trackclick_ja.ts index b2bd40d..a4d416a 100644 --- a/translations/trackclick_ja.ts +++ b/translations/trackclick_ja.ts @@ -45,6 +45,10 @@ No action何もしない Dwell Activeドウェル有効 Enable dwell-clicking (same as the Auto button)滞留クリックを有効にする(Autoボタンと同じ) + Keyboardキーボード + Show or hide the on-screen keyboardオンスクリーンキーボードを表示または非表示 + On-Screen Keyboardオンスクリーンキーボード + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.オンスクリーンキーボードが見つかりませんでした。設定ウィンドウの「ウィンドウ」タブからインストールできます。 Click injection is available. Click for diagnostics.クリックの送信が利用可能です。クリックして診断を表示します。 Clicks are disabled — Accessibility permission not granted. Click to fix.クリックが無効です — アクセシビリティの許可が付与されていません。クリックして修正します。 Pointer-tracking access is unavailable (needed on Wayland). Click to fix.ポインター追跡へのアクセスが利用できません(Wayland で必要)。クリックして修正します。 @@ -126,6 +130,7 @@ Please install 'onboard' or 'florence'.スクリーンキ Reset to Defaultsデフォルトに戻す OKOK Cancelキャンセル + Keyboard Buttonキーボードボタン Diagnostics診断 If clicking isn't working, this information helps pin down why.クリックが動作しない場合、この情報が原因の特定に役立ちます。 Copy diagnostics診断をコピー diff --git a/translations/trackclick_ko.ts b/translations/trackclick_ko.ts index b06309a..09d586c 100644 --- a/translations/trackclick_ko.ts +++ b/translations/trackclick_ko.ts @@ -45,6 +45,10 @@ No action동작 없음 Dwell Active머물기 활성 Enable dwell-clicking (same as the Auto button)머물기 클릭 활성화 (자동 버튼과 동일) + Keyboard키보드 + Show or hide the on-screen keyboard화상 키보드 표시 또는 숨기기 + On-Screen Keyboard화상 키보드 + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.화상 키보드를 찾을 수 없습니다. 설정 창의 '창' 탭에서 설치할 수 있습니다. Click injection is available. Click for diagnostics.클릭 주입을 사용할 수 있습니다. 클릭하면 진단이 표시됩니다. Clicks are disabled — Accessibility permission not granted. Click to fix.클릭이 비활성화되었습니다 — 손쉬운 사용 권한이 부여되지 않았습니다. 클릭하여 해결하세요. Pointer-tracking access is unavailable (needed on Wayland). Click to fix.포인터 추적 액세스를 사용할 수 없습니다(Wayland에서 필요). 클릭하여 해결하세요. @@ -126,6 +130,7 @@ Please install 'onboard' or 'florence'.화상 키보드를 Reset to Defaults기본값으로 재설정 OK확인 Cancel취소 + Keyboard Button키보드 버튼 Diagnostics진단 If clicking isn't working, this information helps pin down why.클릭이 작동하지 않는 경우 이 정보가 원인을 파악하는 데 도움이 됩니다. Copy diagnostics진단 복사 diff --git a/translations/trackclick_pt.ts b/translations/trackclick_pt.ts index 9b71a3d..b7d7bbc 100644 --- a/translations/trackclick_pt.ts +++ b/translations/trackclick_pt.ts @@ -50,6 +50,10 @@ Dwell ActivePermanência ativa Enable dwell-clicking (same as the Auto button)Ativar clique por permanência (igual ao botão Auto) Close applicationFechar aplicação + KeyboardTeclado + Show or hide the on-screen keyboardMostrar ou ocultar o teclado na tela + On-Screen KeyboardTeclado na tela + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.Nenhum teclado na tela foi encontrado. Você pode instalar um na janela de Configurações, na aba Janela. Click injection is available. Click for diagnostics.A injeção de clique está disponível. Clique para ver o diagnóstico. Clicks are disabled — Accessibility permission not granted. Click to fix.Os cliques estão desativados — permissão de Acessibilidade não concedida. Clique para corrigir. Pointer-tracking access is unavailable (needed on Wayland). Click to fix.O acesso ao rastreamento do ponteiro está indisponível (necessário no Wayland). Clique para corrigir. @@ -131,6 +135,7 @@ Instale 'onboard' ou 'florence'. Show click indicator ring (Windows)Mostrar anel indicador de clique (Windows) OKOK CancelCancelar + Keyboard ButtonBotão do teclado DiagnosticsDiagnóstico If clicking isn't working, this information helps pin down why.Se os cliques não estiverem funcionando, estas informações ajudam a identificar o motivo. Copy diagnosticsCopiar diagnóstico diff --git a/translations/trackclick_ru.ts b/translations/trackclick_ru.ts index a3c7436..99eebbd 100644 --- a/translations/trackclick_ru.ts +++ b/translations/trackclick_ru.ts @@ -50,6 +50,10 @@ Dwell ActiveЗадержка активна Enable dwell-clicking (same as the Auto button)Включить нажатие с задержкой (то же что кнопка Auto) Close applicationЗакрыть приложение + KeyboardКлавиатура + Show or hide the on-screen keyboardПоказать или скрыть экранную клавиатуру + On-Screen KeyboardЭкранная клавиатура + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.Экранная клавиатура не найдена. Вы можете установить её в окне настроек, на вкладке «Окно». Click injection is available. Click for diagnostics.Внедрение щелчков доступно. Нажмите для диагностики. Clicks are disabled — Accessibility permission not granted. Click to fix.Щелчки отключены — разрешение «Универсальный доступ» не предоставлено. Нажмите, чтобы исправить. Pointer-tracking access is unavailable (needed on Wayland). Click to fix.Доступ к отслеживанию указателя недоступен (требуется в Wayland). Нажмите, чтобы исправить. @@ -131,6 +135,7 @@ Please install 'onboard' or 'florence'.Экранная к Show click indicator ring (Windows)Показать кольцо индикатора щелчка (Windows) OKОК CancelОтмена + Keyboard ButtonКнопка клавиатуры DiagnosticsДиагностика If clicking isn't working, this information helps pin down why.Если щелчки не работают, эта информация поможет определить причину. Copy diagnosticsКопировать диагностику diff --git a/translations/trackclick_ur.ts b/translations/trackclick_ur.ts index 67aede6..b16fd03 100644 --- a/translations/trackclick_ur.ts +++ b/translations/trackclick_ur.ts @@ -50,6 +50,10 @@ Dwell Activeڈویل فعال Enable dwell-clicking (same as the Auto button)ڈویل-کلکنگ فعال کریں (Auto بٹن کی طرح) Close applicationایپلیکیشن بند کریں + Keyboardکی بورڈ + Show or hide the on-screen keyboardآن اسکرین کی بورڈ دکھائیں یا چھپائیں + On-Screen Keyboardآن اسکرین کی بورڈ + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.کوئی آن اسکرین کی بورڈ نہیں ملا۔ آپ اسے سیٹنگز ونڈو میں، ونڈو ٹیب سے انسٹال کر سکتے ہیں۔ Click injection is available. Click for diagnostics.کلک انجیکشن دستیاب ہے۔ تشخیص کے لیے کلک کریں۔ Clicks are disabled — Accessibility permission not granted. Click to fix.کلک غیر فعال ہیں — Accessibility اجازت نہیں دی گئی۔ درست کرنے کے لیے کلک کریں۔ Pointer-tracking access is unavailable (needed on Wayland). Click to fix.پوائنٹر ٹریکنگ تک رسائی دستیاب نہیں (Wayland پر درکار)۔ درست کرنے کے لیے کلک کریں۔ @@ -131,6 +135,7 @@ Please install 'onboard' or 'florence'.کوئی آن-اس Show click indicator ring (Windows)کلک انڈیکیٹر رِنگ دکھائیں (Windows) OKٹھیک ہے Cancelمنسوخ + Keyboard Buttonکی بورڈ بٹن Diagnosticsتشخیص If clicking isn't working, this information helps pin down why.اگر کلک کام نہیں کر رہا، تو یہ معلومات وجہ معلوم کرنے میں مدد کرتی ہے۔ Copy diagnosticsتشخیص کاپی کریں diff --git a/translations/trackclick_zh_CN.ts b/translations/trackclick_zh_CN.ts index 9bba0f9..30382e3 100644 --- a/translations/trackclick_zh_CN.ts +++ b/translations/trackclick_zh_CN.ts @@ -45,6 +45,10 @@ No action无操作 Dwell Active悬停激活 Enable dwell-clicking (same as the Auto button)启用悬停点击(与自动按钮相同) + Keyboard键盘 + Show or hide the on-screen keyboard显示或隐藏屏幕键盘 + On-Screen Keyboard屏幕键盘 + No on-screen keyboard was found. You can install one from the Settings window, under the Window tab.未找到屏幕键盘。您可以从设置窗口的“窗口”选项卡中安装一个。 Click injection is available. Click for diagnostics.点击注入可用。单击以查看诊断。 Clicks are disabled — Accessibility permission not granted. Click to fix.点击已禁用 — 未授予辅助功能权限。单击以修复。 Pointer-tracking access is unavailable (needed on Wayland). Click to fix.指针跟踪访问不可用(在 Wayland 上需要)。单击以修复。 @@ -126,6 +130,7 @@ Please install 'onboard' or 'florence'.未找到屏幕键 Reset to Defaults恢复默认设置 OK确定 Cancel取消 + Keyboard Button键盘按钮 Diagnostics诊断 If clicking isn't working, this information helps pin down why.如果点击无法工作,这些信息有助于查明原因。 Copy diagnostics复制诊断信息 From 98f23becf42bfeb295fd7e20f1fcec2f059ea4df Mon Sep 17 00:00:00 2001 From: skynab Date: Sat, 25 Jul 2026 00:44:57 -0700 Subject: [PATCH 10/14] Diagnostics improvements --- settingsdialog.cpp | 20 +++++++++++++++++--- translations/trackclick_ar.ts | 3 +++ translations/trackclick_bn.ts | 3 +++ translations/trackclick_cs.ts | 3 +++ translations/trackclick_es.ts | 3 +++ translations/trackclick_fr.ts | 3 +++ translations/trackclick_hi.ts | 3 +++ translations/trackclick_ja.ts | 3 +++ translations/trackclick_ko.ts | 3 +++ translations/trackclick_pt.ts | 3 +++ translations/trackclick_ru.ts | 3 +++ translations/trackclick_ur.ts | 3 +++ translations/trackclick_zh_CN.ts | 3 +++ 13 files changed, 53 insertions(+), 3 deletions(-) diff --git a/settingsdialog.cpp b/settingsdialog.cpp index 7fb14eb..66903a5 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -1233,7 +1233,7 @@ QString injectionBackend() #endif } -QVector collectDiagRows() +QVector collectDiagRows(bool audioClickEnabled) { QVector rows; @@ -1263,6 +1263,13 @@ QVector collectDiagRows() access ? SettingsDialog::tr("Available") : SettingsDialog::tr("Unavailable"), access ? 1 : -1 }); #endif + + // Which trigger fires clicks: audio click replaces the dwell timer when on, + // otherwise the dwell timer is active. + rows.push_back({ SettingsDialog::tr("Click trigger"), + audioClickEnabled ? SettingsDialog::tr("Audio click") + : SettingsDialog::tr("Dwell click"), + 0 }); return rows; } @@ -1340,6 +1347,13 @@ void SettingsDialog::buildDiagnosticsTab() v->addStretch(1); + // Keep the "Click trigger" row live: toggling Audio Click (here or via the + // Audio Click tab) updates the read-out immediately. This connect is made + // before loadFrom() runs, so the initial value syncs too. + if (m_chkAudioClick) + connect(m_chkAudioClick, &QCheckBox::toggled, + this, &SettingsDialog::refreshDiagnostics); + refreshDiagnostics(); m_tabs->addTab(page, tr("Diagnostics")); } @@ -1349,7 +1363,7 @@ void SettingsDialog::refreshDiagnostics() if (!m_lblDiagInfo) return; QString html = QStringLiteral(""); - for (const DiagRow& r : collectDiagRows()) { + for (const DiagRow& r : collectDiagRows(m_chkAudioClick && m_chkAudioClick->isChecked())) { const QString colour = r.status < 0 ? QStringLiteral("#E5534B") : r.status > 0 ? QStringLiteral("#3FB950") : QStringLiteral("#E6E6E6"); @@ -1364,7 +1378,7 @@ void SettingsDialog::refreshDiagnostics() QString SettingsDialog::diagnosticsPlainText() const { QString out = QStringLiteral("TrackClick diagnostics\n----------------------\n"); - for (const DiagRow& r : collectDiagRows()) + for (const DiagRow& r : collectDiagRows(m_chkAudioClick && m_chkAudioClick->isChecked())) out += r.key + QStringLiteral(": ") + r.value + QChar('\n'); return out; } diff --git a/translations/trackclick_ar.ts b/translations/trackclick_ar.ts index aa80e40..af36d28 100644 --- a/translations/trackclick_ar.ts +++ b/translations/trackclick_ar.ts @@ -158,6 +158,9 @@ Please install 'onboard' or 'florence'.لم يتم الع Unavailable — needed for dwell tracking on Waylandغير متاح — مطلوب لتتبّع التمرير على Wayland Input injectionحقن الإدخال Unavailableغير متاح + Click triggerمُشغِّل النقر + Audio clickالنقر الصوتي + Dwell clickالنقر بالتحوم SensitivityTesterDialog diff --git a/translations/trackclick_bn.ts b/translations/trackclick_bn.ts index 3b40867..dc5e3ec 100644 --- a/translations/trackclick_bn.ts +++ b/translations/trackclick_bn.ts @@ -158,6 +158,9 @@ Please install 'onboard' or 'florence'.কোনো অন Unavailable — needed for dwell tracking on Waylandঅনুপলব্ধ — Wayland-এ হোভার ট্র্যাকিংয়ের জন্য প্রয়োজন Input injectionইনপুট ইনজেকশন Unavailableঅনুপলব্ধ + Click triggerক্লিক ট্রিগার + Audio clickঅডিও ক্লিক + Dwell clickড্ওয়েল ক্লিক SensitivityTesterDialog diff --git a/translations/trackclick_cs.ts b/translations/trackclick_cs.ts index 5ae38af..ef563fb 100644 --- a/translations/trackclick_cs.ts +++ b/translations/trackclick_cs.ts @@ -155,6 +155,9 @@ Nainstalujte prosím 'onboard' nebo 'florence'.Unavailable — needed for dwell tracking on WaylandNedostupné — potřebné pro sledování najetí na WaylanduInput injectionVkládání vstupuUnavailableNedostupné + Click triggerSpouštěč kliknutí + Audio clickZvukové kliknutí + Dwell clickKliknutí najetím SensitivityTesterDialog diff --git a/translations/trackclick_es.ts b/translations/trackclick_es.ts index db6d98c..06816ce 100644 --- a/translations/trackclick_es.ts +++ b/translations/trackclick_es.ts @@ -153,6 +153,9 @@ Instale 'onboard' o 'florence'. Unavailable — needed for dwell tracking on WaylandNo disponible — necesario para el seguimiento en Wayland Input injectionInyección de entrada UnavailableNo disponible + Click triggerDisparador del clic + Audio clickClic por sonido + Dwell clickClic por permanencia SensitivityTesterDialog diff --git a/translations/trackclick_fr.ts b/translations/trackclick_fr.ts index e418795..6cbc63c 100644 --- a/translations/trackclick_fr.ts +++ b/translations/trackclick_fr.ts @@ -153,6 +153,9 @@ Veuillez installer 'onboard' ou 'florence'. Unavailable — needed for dwell tracking on WaylandIndisponible — requis pour le suivi du survol sous Wayland Input injectionInjection d'entrée UnavailableIndisponible + Click triggerDéclencheur du clic + Audio clickClic audio + Dwell clickClic par survol SensitivityTesterDialog diff --git a/translations/trackclick_hi.ts b/translations/trackclick_hi.ts index 767ba7f..7f72683 100644 --- a/translations/trackclick_hi.ts +++ b/translations/trackclick_hi.ts @@ -158,6 +158,9 @@ Please install 'onboard' or 'florence'.कोई ऑन- Unavailable — needed for dwell tracking on Waylandअनुपलब्ध — Wayland पर होवर ट्रैकिंग के लिए आवश्यक Input injectionइनपुट इंजेक्शन Unavailableअनुपलब्ध + Click triggerक्लिक ट्रिगर + Audio clickऑडियो क्लिक + Dwell clickड्वेल क्लिक SensitivityTesterDialog diff --git a/translations/trackclick_ja.ts b/translations/trackclick_ja.ts index a4d416a..24c55a6 100644 --- a/translations/trackclick_ja.ts +++ b/translations/trackclick_ja.ts @@ -153,6 +153,9 @@ Please install 'onboard' or 'florence'.スクリーンキ Unavailable — needed for dwell tracking on Wayland利用不可 — Wayland でのホバー追跡に必要 Input injection入力送信 Unavailable利用不可 + Click triggerクリックのトリガー + Audio click音声クリック + Dwell clickドウェルクリック SensitivityTesterDialog diff --git a/translations/trackclick_ko.ts b/translations/trackclick_ko.ts index 09d586c..0a2ba59 100644 --- a/translations/trackclick_ko.ts +++ b/translations/trackclick_ko.ts @@ -153,6 +153,9 @@ Please install 'onboard' or 'florence'.화상 키보드를 Unavailable — needed for dwell tracking on Wayland사용 불가 — Wayland에서 호버 추적에 필요 Input injection입력 주입 Unavailable사용 불가 + Click trigger클릭 트리거 + Audio click소리 클릭 + Dwell click머물기 클릭 SensitivityTesterDialog diff --git a/translations/trackclick_pt.ts b/translations/trackclick_pt.ts index b7d7bbc..fef31f6 100644 --- a/translations/trackclick_pt.ts +++ b/translations/trackclick_pt.ts @@ -158,6 +158,9 @@ Instale 'onboard' ou 'florence'. Unavailable — needed for dwell tracking on WaylandIndisponível — necessário para rastreamento de foco no Wayland Input injectionInjeção de entrada UnavailableIndisponível + Click triggerDisparador do clique + Audio clickClique por som + Dwell clickClique por permanência SensitivityTesterDialog diff --git a/translations/trackclick_ru.ts b/translations/trackclick_ru.ts index 99eebbd..18487b2 100644 --- a/translations/trackclick_ru.ts +++ b/translations/trackclick_ru.ts @@ -158,6 +158,9 @@ Please install 'onboard' or 'florence'.Экранная к Unavailable — needed for dwell tracking on WaylandНедоступно — требуется для отслеживания наведения в Wayland Input injectionВнедрение ввода UnavailableНедоступно + Click triggerТриггер щелчка + Audio clickЗвуковой щелчок + Dwell clickЩелчок по задержке SensitivityTesterDialog diff --git a/translations/trackclick_ur.ts b/translations/trackclick_ur.ts index b16fd03..828aa0e 100644 --- a/translations/trackclick_ur.ts +++ b/translations/trackclick_ur.ts @@ -158,6 +158,9 @@ Please install 'onboard' or 'florence'.کوئی آن-اس Unavailable — needed for dwell tracking on Waylandغیر دستیاب — Wayland پر ہوور ٹریکنگ کے لیے درکار Input injectionان پٹ انجیکشن Unavailableغیر دستیاب + Click triggerکلک ٹرگر + Audio clickآڈیو کلک + Dwell clickڈویل کلک SensitivityTesterDialog diff --git a/translations/trackclick_zh_CN.ts b/translations/trackclick_zh_CN.ts index 30382e3..146cc5c 100644 --- a/translations/trackclick_zh_CN.ts +++ b/translations/trackclick_zh_CN.ts @@ -153,6 +153,9 @@ Please install 'onboard' or 'florence'.未找到屏幕键 Unavailable — needed for dwell tracking on Wayland不可用 — 在 Wayland 上进行悬停跟踪时需要 Input injection输入注入 Unavailable不可用 + Click trigger点击触发方式 + Audio click声音点击 + Dwell click悬停点击 SensitivityTesterDialog From 88841e420f24a5093a80e491ade79ead8aa7c406 Mon Sep 17 00:00:00 2001 From: skynab Date: Sat, 25 Jul 2026 08:19:59 -0700 Subject: [PATCH 11/14] Attempt to add new return to left click feature. --- .DS_Store | Bin 10244 -> 10244 bytes mainwindow.cpp | 43 +++++++++++++++++++++++++++++++ settingsdialog.cpp | 6 +++++ settingsdialog.h | 4 +++ translations/trackclick_ar.ts | 1 + translations/trackclick_bn.ts | 1 + translations/trackclick_cs.ts | 1 + translations/trackclick_es.ts | 1 + translations/trackclick_fr.ts | 1 + translations/trackclick_hi.ts | 1 + translations/trackclick_ja.ts | 1 + translations/trackclick_ko.ts | 1 + translations/trackclick_pt.ts | 1 + translations/trackclick_ru.ts | 1 + translations/trackclick_ur.ts | 1 + translations/trackclick_zh_CN.ts | 1 + 16 files changed, 65 insertions(+) diff --git a/.DS_Store b/.DS_Store index 681654a905409822f07cb5121b25ec7ad8edff81..04cd742864d9e72e9138973383935e8cadfb16b9 100644 GIT binary patch delta 14 VcmZn(XbITBA;ieAnN#SuC;%dv1X2J1 delta 14 VcmZn(XbITBA;ieInN#SuC;%d#1XBP2 diff --git a/mainwindow.cpp b/mainwindow.cpp index 6ee679d..fda3072 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -354,6 +354,7 @@ MainWindow::MainWindow(QTranslator* startupTranslator, QWidget* parent) m_settings.buttonOrder = m_persist.value("show/buttonOrder").toStringList(); m_settings.scrollRepeat = m_persist.value("scroll/repeat", 7).toInt(); m_settings.repeatOnDwell = m_persist.value("dwell/repeatOnDwell", false).toBool(); + m_settings.returnToLeftAfterClick = m_persist.value("dwell/returnToLeftAfterClick", false).toBool(); m_settings.hoverSelectPercent = m_persist.value("dwell/hoverSelectPercent", 60).toInt(); m_settings.edgeLock = static_cast(m_persist.value("window/edgeLock", 0).toInt()); m_settings.edgeHide = m_persist.value("window/edgeHide", false).toBool(); @@ -1551,6 +1552,28 @@ void MainWindow::animateEdgeTo(QPoint target) } // ─── Slots ──────────────────────────────────────────────────────────────── +// Whether a just-fired action should trigger "return to left click": true for +// the actual click types (single/double left/right/middle) and for the Up event +// that completes a drag. False for NoClick, the Down events (a drag is still in +// progress and must be released first), and scrolls (kept selected so the user +// can scroll repeatedly). +static bool endsInLeftReturn(ClickType t) +{ + switch (t) { + case ClickType::LeftClick: + case ClickType::LeftDoubleClick: + case ClickType::RightClick: + case ClickType::RightDoubleClick: + case ClickType::MiddleClick: + case ClickType::MiddleDoubleClick: + case ClickType::LeftUp: // drag just completed + case ClickType::RightUp: // drag just completed + return true; + default: + return false; + } +} + void MainWindow::onClickButtonPressed(ClickType type) { setClickType(type); @@ -1581,6 +1604,11 @@ void MainWindow::onClickButtonPressed(ClickType type) if (m_ctrlBtn) { m_ctrlBtn->setChecked(false); } if (m_altBtn) { m_altBtn->setChecked(false); } if (m_shiftBtn) { m_shiftBtn->setChecked(false); } + + // Optionally snap the selection back to Left Click after a click. + if (m_settings.returnToLeftAfterClick && endsInLeftReturn(type) + && m_selectedType != ClickType::LeftClick) + setClickType(ClickType::LeftClick); } } @@ -1730,6 +1758,20 @@ void MainWindow::onDwellFired(QPoint pos, ClickType type) #ifdef HAVE_MULTIMEDIA if (m_settings.audioFeedback) m_clickSound->play(); #endif + + // Optionally snap the selection back to Left Click after a completed click. + // Deferred: this runs inside DwellManager::fireSelected's emit, which then + // updates its own drag state — re-arming here directly would race with it, + // so do it once control returns to the event loop. + if (m_settings.returnToLeftAfterClick && !hotkeyAction + && endsInLeftReturn(type) && m_selectedType != ClickType::LeftClick) { + QTimer::singleShot(0, this, [this]() { + if (!m_settings.returnToLeftAfterClick) return; // may have changed + setClickType(ClickType::LeftClick); + if (m_autoEnabled) + m_dwell->arm(ClickType::LeftClick, m_modifiers); + }); + } } void MainWindow::updateAudioClick() @@ -1991,6 +2033,7 @@ void MainWindow::applySettings(const AppSettings& s) m_persist.setValue("show/buttonOrder", s.buttonOrder); m_persist.setValue("scroll/repeat", s.scrollRepeat); m_persist.setValue("dwell/repeatOnDwell", s.repeatOnDwell); + m_persist.setValue("dwell/returnToLeftAfterClick", s.returnToLeftAfterClick); m_persist.setValue("dwell/hoverSelectPercent", s.hoverSelectPercent); m_persist.setValue("window/edgeLock", static_cast(s.edgeLock)); m_persist.setValue("window/edgeHide", s.edgeHide); diff --git a/settingsdialog.cpp b/settingsdialog.cpp index 66903a5..7d05152 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -616,6 +616,7 @@ void SettingsDialog::retranslateUi() "selection switches to it, as a percentage of the dwell time.")); m_lblScrollRepeat->setText(tr("Scroll repeat:")); m_lblRepeatMode->setText(tr("Repeat click:")); + m_lblReturnToLeft->setText(tr("Return to left click after click:")); #ifdef Q_OS_MAC m_lblPermissions->setText(tr("Permissions:")); m_btnAccessibility->setText(tr("Open Accessibility Settings…")); @@ -883,12 +884,14 @@ void SettingsDialog::buildUi() m_scrollRepeat = new QSpinBox; m_scrollRepeat->setRange(1, 20); m_chkRepeatMode = new QCheckBox; + m_chkReturnToLeft = new QCheckBox; m_lblDwellTime = new QLabel(tr("Dwell time:")); m_lblSensitivity = new QLabel(tr("Sensitivity:")); m_lblHoverSelect = new QLabel(tr("Hover to switch:")); m_lblScrollRepeat = new QLabel(tr("Scroll repeat:")); m_lblRepeatMode = new QLabel(tr("Repeat click:")); + m_lblReturnToLeft = new QLabel(tr("Return to left click after click:")); m_btnSensTester = new QPushButton(tr("Sensitivity Tester…")); m_btnSensTester->setProperty("flat", true); connect(m_btnSensTester, &QPushButton::clicked, this, [this](){ @@ -904,6 +907,7 @@ void SettingsDialog::buildUi() fl->addRow(m_btnSensTester); fl->addRow(m_lblHoverSelect, m_hoverSelectPct); fl->addRow(m_lblScrollRepeat, m_scrollRepeat); + fl->addRow(m_lblReturnToLeft, m_chkReturnToLeft); fl->addRow(m_lblRepeatMode, m_chkRepeatMode); #ifdef Q_OS_MAC @@ -1563,6 +1567,7 @@ void SettingsDialog::loadFrom(const AppSettings& s) m_hoverSelectPct->setValue(s.hoverSelectPercent); m_scrollRepeat->setValue(s.scrollRepeat); m_chkRepeatMode->setChecked(s.repeatOnDwell); + m_chkReturnToLeft->setChecked(s.returnToLeftAfterClick); // Populate the reorder list in the saved order, with saved visibility as the // check state. Right Double / Right Drag stay read-only and off, so they're @@ -1633,6 +1638,7 @@ AppSettings SettingsDialog::readUi() const s.hoverSelectPercent = m_hoverSelectPct->value(); s.scrollRepeat = m_scrollRepeat->value(); s.repeatOnDwell = m_chkRepeatMode->isChecked(); + s.returnToLeftAfterClick = m_chkReturnToLeft->isChecked(); // Read click-button order and per-button visibility from the reorder list. // Right Double / Right Drag aren't listed, so they keep their default (off). diff --git a/settingsdialog.h b/settingsdialog.h index f78a7b5..985575e 100644 --- a/settingsdialog.h +++ b/settingsdialog.h @@ -40,6 +40,8 @@ struct AppSettings { int scrollRepeat = 7; bool repeatOnDwell = true; // true = repeat every dwell period; false = fire once per arm bool autoSelectEnabled = false; // start with AutoSelect on + // After any click completes, revert the selected action back to Left Click. + bool returnToLeftAfterClick = false; // Percentage of the dwell time a toolbar button must be hovered before the // hover-select timer switches the active selection to it. Independent of // dwellMs so the switch delay can be tuned separately from the click delay. @@ -223,6 +225,8 @@ class SettingsDialog : public QDialog QSpinBox* m_scrollRepeat; QLabel* m_lblRepeatMode = nullptr; QCheckBox* m_chkRepeatMode; + QLabel* m_lblReturnToLeft = nullptr; // revert to Left Click after a click + QCheckBox* m_chkReturnToLeft = nullptr; // Buttons visibility + order — the click-action buttons live in a reorderable // checkable list (check = visible, row order = toolbar order); Move Up/Down diff --git a/translations/trackclick_ar.ts b/translations/trackclick_ar.ts index af36d28..b41c0f4 100644 --- a/translations/trackclick_ar.ts +++ b/translations/trackclick_ar.ts @@ -161,6 +161,7 @@ Please install 'onboard' or 'florence'.لم يتم الع Click triggerمُشغِّل النقر Audio clickالنقر الصوتي Dwell clickالنقر بالتحوم + Return to left click after click:العودة إلى النقر بالزر الأيسر بعد النقر: SensitivityTesterDialog diff --git a/translations/trackclick_bn.ts b/translations/trackclick_bn.ts index dc5e3ec..497ab20 100644 --- a/translations/trackclick_bn.ts +++ b/translations/trackclick_bn.ts @@ -161,6 +161,7 @@ Please install 'onboard' or 'florence'.কোনো অন Click triggerক্লিক ট্রিগার Audio clickঅডিও ক্লিক Dwell clickড্ওয়েল ক্লিক + Return to left click after click:ক্লিকের পরে বাম ক্লিকে ফিরে যান: SensitivityTesterDialog diff --git a/translations/trackclick_cs.ts b/translations/trackclick_cs.ts index ef563fb..5f13383 100644 --- a/translations/trackclick_cs.ts +++ b/translations/trackclick_cs.ts @@ -158,6 +158,7 @@ Nainstalujte prosím 'onboard' nebo 'florence'. Click triggerSpouštěč kliknutí Audio clickZvukové kliknutí Dwell clickKliknutí najetím + Return to left click after click:Po kliknutí se vrátit na levé kliknutí: SensitivityTesterDialog diff --git a/translations/trackclick_es.ts b/translations/trackclick_es.ts index 06816ce..a0149bf 100644 --- a/translations/trackclick_es.ts +++ b/translations/trackclick_es.ts @@ -156,6 +156,7 @@ Instale 'onboard' o 'florence'. Click triggerDisparador del clic Audio clickClic por sonido Dwell clickClic por permanencia + Return to left click after click:Volver al clic izquierdo después de hacer clic: SensitivityTesterDialog diff --git a/translations/trackclick_fr.ts b/translations/trackclick_fr.ts index 6cbc63c..2bb08a0 100644 --- a/translations/trackclick_fr.ts +++ b/translations/trackclick_fr.ts @@ -156,6 +156,7 @@ Veuillez installer 'onboard' ou 'florence'. Click triggerDéclencheur du clic Audio clickClic audio Dwell clickClic par survol + Return to left click after click:Revenir au clic gauche après un clic : SensitivityTesterDialog diff --git a/translations/trackclick_hi.ts b/translations/trackclick_hi.ts index 7f72683..172c349 100644 --- a/translations/trackclick_hi.ts +++ b/translations/trackclick_hi.ts @@ -161,6 +161,7 @@ Please install 'onboard' or 'florence'.कोई ऑन- Click triggerक्लिक ट्रिगर Audio clickऑडियो क्लिक Dwell clickड्वेल क्लिक + Return to left click after click:क्लिक के बाद बाएं क्लिक पर लौटें: SensitivityTesterDialog diff --git a/translations/trackclick_ja.ts b/translations/trackclick_ja.ts index 24c55a6..24a7567 100644 --- a/translations/trackclick_ja.ts +++ b/translations/trackclick_ja.ts @@ -156,6 +156,7 @@ Please install 'onboard' or 'florence'.スクリーンキ Click triggerクリックのトリガー Audio click音声クリック Dwell clickドウェルクリック + Return to left click after click:クリック後に左クリックに戻る: SensitivityTesterDialog diff --git a/translations/trackclick_ko.ts b/translations/trackclick_ko.ts index 0a2ba59..bb4b7ca 100644 --- a/translations/trackclick_ko.ts +++ b/translations/trackclick_ko.ts @@ -156,6 +156,7 @@ Please install 'onboard' or 'florence'.화상 키보드를 Click trigger클릭 트리거 Audio click소리 클릭 Dwell click머물기 클릭 + Return to left click after click:클릭 후 왼쪽 클릭으로 돌아가기: SensitivityTesterDialog diff --git a/translations/trackclick_pt.ts b/translations/trackclick_pt.ts index fef31f6..8366179 100644 --- a/translations/trackclick_pt.ts +++ b/translations/trackclick_pt.ts @@ -161,6 +161,7 @@ Instale 'onboard' ou 'florence'. Click triggerDisparador do clique Audio clickClique por som Dwell clickClique por permanência + Return to left click after click:Voltar ao clique esquerdo após clicar: SensitivityTesterDialog diff --git a/translations/trackclick_ru.ts b/translations/trackclick_ru.ts index 18487b2..d0c4c33 100644 --- a/translations/trackclick_ru.ts +++ b/translations/trackclick_ru.ts @@ -161,6 +161,7 @@ Please install 'onboard' or 'florence'.Экранная к Click triggerТриггер щелчка Audio clickЗвуковой щелчок Dwell clickЩелчок по задержке + Return to left click after click:Возврат к левому клику после клика: SensitivityTesterDialog diff --git a/translations/trackclick_ur.ts b/translations/trackclick_ur.ts index 828aa0e..10b840f 100644 --- a/translations/trackclick_ur.ts +++ b/translations/trackclick_ur.ts @@ -161,6 +161,7 @@ Please install 'onboard' or 'florence'.کوئی آن-اس Click triggerکلک ٹرگر Audio clickآڈیو کلک Dwell clickڈویل کلک + Return to left click after click:کلک کے بعد بایاں کلک پر واپس جائیں: SensitivityTesterDialog diff --git a/translations/trackclick_zh_CN.ts b/translations/trackclick_zh_CN.ts index 146cc5c..11caa60 100644 --- a/translations/trackclick_zh_CN.ts +++ b/translations/trackclick_zh_CN.ts @@ -156,6 +156,7 @@ Please install 'onboard' or 'florence'.未找到屏幕键 Click trigger点击触发方式 Audio click声音点击 Dwell click悬停点击 + Return to left click after click:点击后返回左键单击: SensitivityTesterDialog From 7e4b25a817641b9a7c1e1062f0998d1c5e9fca62 Mon Sep 17 00:00:00 2001 From: Anthony Lazzaro Date: Sat, 25 Jul 2026 08:28:00 -0700 Subject: [PATCH 12/14] UI improvements (#8) * Added sections to the Window tab * Darker border for Window sections * Color audio buttons cyan to make that feature visually pop. --- icons/toggle_on_cyan.svg | 17 +++++ resources.qrc | 1 + settingsdialog.cpp | 109 +++++++++++++++++++++---------- settingsdialog.h | 9 ++- translations/trackclick_ar.ts | 4 ++ translations/trackclick_bn.ts | 4 ++ translations/trackclick_cs.ts | 4 ++ translations/trackclick_es.ts | 4 ++ translations/trackclick_fr.ts | 4 ++ translations/trackclick_hi.ts | 4 ++ translations/trackclick_ja.ts | 4 ++ translations/trackclick_ko.ts | 4 ++ translations/trackclick_pt.ts | 4 ++ translations/trackclick_ru.ts | 4 ++ translations/trackclick_ur.ts | 4 ++ translations/trackclick_zh_CN.ts | 4 ++ 16 files changed, 147 insertions(+), 37 deletions(-) create mode 100644 icons/toggle_on_cyan.svg diff --git a/icons/toggle_on_cyan.svg b/icons/toggle_on_cyan.svg new file mode 100644 index 0000000..20e8fca --- /dev/null +++ b/icons/toggle_on_cyan.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/resources.qrc b/resources.qrc index 04de6d9..473652b 100644 --- a/resources.qrc +++ b/resources.qrc @@ -9,6 +9,7 @@ icons/checkmark.svg icons/toggle_off.svg icons/toggle_on.svg + icons/toggle_on_cyan.svg icons/no_click.svg icons/left_click.svg icons/left_double.svg diff --git a/settingsdialog.cpp b/settingsdialog.cpp index 7d05152..4ea7741 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -58,7 +58,7 @@ QDialog { } QGroupBox { color: #FFA600; - border: 1px solid #979797; + border: 1px solid #3A3A3A; border-radius: 4px; margin-top: 10px; padding-top: 6px; @@ -638,6 +638,9 @@ void SettingsDialog::retranslateUi() } m_tabs->setTabText(2, tr("Window")); + m_grpWinBehavior->setTitle(tr("Window Behavior")); + m_grpButtonControls->setTitle(tr("Button Controls")); + m_grpFeedback->setTitle(tr("Feedback")); m_lblEdgeLock->setText(tr("Lock to screen edge:")); m_cmbEdgeLock->setItemText(0, tr("None")); m_cmbEdgeLock->setItemText(1, tr("Left edge")); @@ -649,7 +652,7 @@ void SettingsDialog::retranslateUi() m_chkLaunchOnStartup->setText(tr("Launch on system startup (Windows)")); m_chkAudio->setText(tr("Audio feedback on click")); m_chkClickIndicator->setText(tr("Show click indicator ring (Windows)")); - m_chkIconsOnly->setText(tr("Icons only (hide button labels)")); + m_chkShowLabels->setText(tr("Show button labels")); m_chkLargeButtons->setText(tr("Large buttons")); m_lblOpacity->setText(tr("Opacity:")); m_lblBtnLayout->setText(tr("Button layout:")); @@ -1003,12 +1006,13 @@ void SettingsDialog::buildUi() m_tabs->addTab(pageBtns, tr("Buttons")); // ── Window ──────────────────────────────────────────────── + // Grouped into titled sections: Window Behavior, Button Controls, Feedback, + // with the on-screen keyboard launcher at the very bottom. auto* pageWin = new QWidget; - auto* wfl = new QFormLayout(pageWin); - wfl->setSpacing(6); - wfl->setFormAlignment(Qt::AlignHCenter | Qt::AlignTop); - wfl->setLabelAlignment(Qt::AlignHCenter); + auto* winCol = new QVBoxLayout(pageWin); + winCol->setSpacing(10); + // Opacity slider + live percentage (placed in the Window Behavior section). auto* opRow = new QHBoxLayout; m_opacitySlider = new QSlider(Qt::Horizontal); m_opacitySlider->setRange(20, 100); @@ -1020,6 +1024,11 @@ void SettingsDialog::buildUi() m_opacityLabel->setText(QString::number(v) + "%"); }); + // ── Section: Window Behavior ────────────────────────────── + m_grpWinBehavior = new QGroupBox(tr("Window Behavior")); + auto* behForm = new QFormLayout(m_grpWinBehavior); + behForm->setSpacing(6); + m_lblEdgeLock = new QLabel(tr("Lock to screen edge:")); m_cmbEdgeLock = new QComboBox; m_cmbEdgeLock->setSizeAdjustPolicy(QComboBox::AdjustToContents); @@ -1030,19 +1039,30 @@ void SettingsDialog::buildUi() m_chkEdgeHide = new QCheckBox(tr("Slide off screen when idle")); connect(m_cmbEdgeLock, QOverload::of(&QComboBox::currentIndexChanged), this, [this](int idx){ m_chkEdgeHide->setEnabled(idx != 0); }); - wfl->addRow(m_lblEdgeLock, m_cmbEdgeLock); - wfl->addRow(m_chkEdgeHide); + m_lblOpacity = new QLabel(tr("Opacity:")); m_chkAlwaysOnTop = new QCheckBox(tr("Always on top")); m_chkStartMinimized = new QCheckBox(tr("Start minimized to tray")); m_chkXMinimizesApp = new QCheckBox(tr("Top X minimizes app")); - // Kept read-only for now: the top X always quits (see makeCheckboxReadOnly). - // To re-enable, drop this call and restore its loadFrom() line. - makeCheckboxReadOnly(m_chkXMinimizesApp); m_chkLaunchOnStartup= new QCheckBox(tr("Launch on system startup (Windows)")); - m_chkAudio = new QCheckBox(tr("Audio feedback on click")); - m_chkClickIndicator = new QCheckBox(tr("Show click indicator ring (Windows)")); - m_chkIconsOnly = new QCheckBox(tr("Icons only (hide button labels)")); + + behForm->addRow(m_lblEdgeLock, m_cmbEdgeLock); + behForm->addRow(m_chkEdgeHide); + behForm->addRow(m_lblOpacity, opRow); + behForm->addRow(m_chkAlwaysOnTop); + // "Start minimized to tray" and "Top X minimizes app" stay constructed + // (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); + winCol->addWidget(m_grpWinBehavior); + + // ── Section: Button Controls ────────────────────────────── + m_grpButtonControls = new QGroupBox(tr("Button Controls")); + auto* ctrlForm = new QFormLayout(m_grpButtonControls); + ctrlForm->setSpacing(6); + + // Inverse of iconsOnly: checked = labels shown. Defaults on (iconsOnly off). + m_chkShowLabels = new QCheckBox(tr("Show button labels")); m_chkLargeButtons = new QCheckBox(tr("Large buttons")); m_cmbLayout = new QComboBox; @@ -1052,26 +1072,29 @@ void SettingsDialog::buildUi() m_cmbLayout->addItem(tr("Horizontal (one row)")); m_cmbLayout->addItem(tr("Vertical (one column)")); m_cmbLayout->addItem(tr("Vertical (two columns)")); - - m_lblOpacity = new QLabel(tr("Opacity:")); m_lblBtnLayout = new QLabel(tr("Button layout:")); - wfl->addRow(m_lblOpacity, opRow); - wfl->addRow(m_chkAlwaysOnTop); - // "Start minimized to tray" hidden from the UI — not added to the layout. - // The checkbox is still constructed above so load/save/retranslate refs stay valid. - // wfl->addRow(m_chkStartMinimized); - wfl->addRow(m_chkXMinimizesApp); - wfl->addRow(m_chkLaunchOnStartup); - wfl->addRow(m_chkAudio); - wfl->addRow(m_chkClickIndicator); - wfl->addRow(m_chkIconsOnly); - wfl->addRow(m_chkLargeButtons); - wfl->addRow(m_lblBtnLayout, m_cmbLayout); + ctrlForm->addRow(m_chkShowLabels); + ctrlForm->addRow(m_chkLargeButtons); + ctrlForm->addRow(m_lblBtnLayout, m_cmbLayout); + winCol->addWidget(m_grpButtonControls); + + // ── Section: Feedback ───────────────────────────────────── + m_grpFeedback = new QGroupBox(tr("Feedback")); + auto* fbForm = new QFormLayout(m_grpFeedback); + fbForm->setSpacing(6); + + m_chkAudio = new QCheckBox(tr("Audio feedback on click")); + m_chkClickIndicator = new QCheckBox(tr("Show click indicator ring (Windows)")); + fbForm->addRow(m_chkAudio); + fbForm->addRow(m_chkClickIndicator); + winCol->addWidget(m_grpFeedback); + // On-screen keyboard launcher — at the bottom of the tab. m_btnOnScreenKbd = new QPushButton(tr("Open On-Screen Keyboard")); m_btnOnScreenKbd->setFlat(true); - wfl->addRow(m_btnOnScreenKbd); + winCol->addWidget(m_btnOnScreenKbd); + winCol->addStretch(1); connect(m_btnOnScreenKbd, &QPushButton::clicked, this, [this]() { #if defined(Q_OS_WIN) // Build full path from %SystemRoot% so PATH resolution isn't needed. @@ -1118,6 +1141,13 @@ void SettingsDialog::buildUi() aufl->setSpacing(8); m_chkAudioClick = new QCheckBox(tr("Trigger the selected action with a loud sound")); + // Cyan "on" toggle so the feature's main switch matches its slider/meter. + // Fully specifies the indicator so the sizing survives the widget stylesheet; + // the off state keeps the grey toggle. + m_chkAudioClick->setStyleSheet( + "QCheckBox::indicator { width:25px; height:11px; border:none;" + " background:transparent; image:url(:/icons/toggle_off.svg); }" + "QCheckBox::indicator:checked { image:url(:/icons/toggle_on_cyan.svg); }"); aufl->addWidget(m_chkAudioClick); m_lblAudioClickInfo = new QLabel; @@ -1150,6 +1180,11 @@ void SettingsDialog::buildUi() m_lblAudioThreshold = new QLabel(tr("Loudness threshold:")); m_audioThreshSlider = new QSlider(Qt::Horizontal); m_audioThreshSlider->setRange(1, 100); + // Cyan handle + fill so the threshold slider matches the audio meter and + // toggle (the feature's colour); the base track stays grey. + m_audioThreshSlider->setStyleSheet( + "QSlider::handle:horizontal { background:#00EBFF; }" + "QSlider::sub-page:horizontal { background:#00EBFF; }"); m_audioThreshValue = new QLabel("50%"); m_audioThreshValue->setFixedWidth(36); calGrid->addWidget(m_lblAudioThreshold, 1, 0); @@ -1221,7 +1256,8 @@ void SettingsDialog::buildUi() // ── Diagnostics tab ────────────────────────────────────────────────────────── namespace { -// One row of the environment read-out. status: -1 problem, 0 neutral, 1 good. +// One row of the environment read-out. +// status: -1 problem (red), 0 neutral, 1 good (green), 2 audio feature (cyan). struct DiagRow { QString key; QString value; int status; }; QString injectionBackend() @@ -1273,7 +1309,7 @@ QVector collectDiagRows(bool audioClickEnabled) rows.push_back({ SettingsDialog::tr("Click trigger"), audioClickEnabled ? SettingsDialog::tr("Audio click") : SettingsDialog::tr("Dwell click"), - 0 }); + audioClickEnabled ? 2 : 0 }); // 2 → cyan when audio click is on return rows; } @@ -1368,9 +1404,10 @@ void SettingsDialog::refreshDiagnostics() return; QString html = QStringLiteral("
"); for (const DiagRow& r : collectDiagRows(m_chkAudioClick && m_chkAudioClick->isChecked())) { - const QString colour = r.status < 0 ? QStringLiteral("#E5534B") - : r.status > 0 ? QStringLiteral("#3FB950") - : QStringLiteral("#E6E6E6"); + const QString colour = r.status < 0 ? QStringLiteral("#E5534B") + : r.status == 2 ? QStringLiteral("#00EBFF") + : r.status > 0 ? QStringLiteral("#3FB950") + : QStringLiteral("#E6E6E6"); html += QStringLiteral("" "") .arg(r.key.toHtmlEscaped(), colour, r.value.toHtmlEscaped()); @@ -1597,7 +1634,7 @@ void SettingsDialog::loadFrom(const AppSettings& s) m_chkLaunchOnStartup->setChecked(s.launchOnStartup); m_chkAudio->setChecked(s.audioFeedback); m_chkClickIndicator->setChecked(s.showClickIndicator); - m_chkIconsOnly->setChecked(s.iconsOnly); + m_chkShowLabels->setChecked(!s.iconsOnly); // checked = labels shown m_chkLargeButtons->setChecked(s.largeButtons); m_cmbLayout->setCurrentIndex(static_cast(s.buttonLayout)); for (int i = 0; i < m_cmbLanguage->count(); ++i) { @@ -1660,7 +1697,7 @@ AppSettings SettingsDialog::readUi() const s.launchOnStartup = m_chkLaunchOnStartup->isChecked(); s.audioFeedback = m_chkAudio->isChecked(); s.showClickIndicator = m_chkClickIndicator->isChecked(); - s.iconsOnly = m_chkIconsOnly->isChecked(); + s.iconsOnly = !m_chkShowLabels->isChecked(); // unchecked = icons only s.largeButtons = m_chkLargeButtons->isChecked(); s.buttonLayout = static_cast(m_cmbLayout->currentIndex()); s.language = m_cmbLanguage->currentData().toString(); diff --git a/settingsdialog.h b/settingsdialog.h index 985575e..6cd500f 100644 --- a/settingsdialog.h +++ b/settingsdialog.h @@ -245,11 +245,18 @@ class SettingsDialog : public QDialog QCheckBox* m_chkLaunchOnStartup; QCheckBox* m_chkAudio; QCheckBox* m_chkClickIndicator; - QCheckBox* m_chkIconsOnly; + // "Show button labels" — the inverse of AppSettings::iconsOnly (checked = + // labels shown = iconsOnly false). Defaults on. + QCheckBox* m_chkShowLabels; QCheckBox* m_chkLargeButtons; QComboBox* m_cmbLayout; QComboBox* m_cmbLanguage; + // Window-tab section boxes (titles are retranslated). + QGroupBox* m_grpWinBehavior = nullptr; + QGroupBox* m_grpButtonControls = nullptr; + QGroupBox* m_grpFeedback = nullptr; + // Edge lock QLabel* m_lblEdgeLock = nullptr; QComboBox* m_cmbEdgeLock = nullptr; diff --git a/translations/trackclick_ar.ts b/translations/trackclick_ar.ts index b41c0f4..d15446a 100644 --- a/translations/trackclick_ar.ts +++ b/translations/trackclick_ar.ts @@ -161,6 +161,10 @@ Please install 'onboard' or 'florence'.لم يتم الع Click triggerمُشغِّل النقر Audio clickالنقر الصوتي Dwell clickالنقر بالتحوم + Window Behaviorسلوك النافذة + Button Controlsعناصر تحكم الأزرار + Feedbackالملاحظات + Show button labelsإظهار تسميات الأزرار Return to left click after click:العودة إلى النقر بالزر الأيسر بعد النقر: diff --git a/translations/trackclick_bn.ts b/translations/trackclick_bn.ts index 497ab20..8df1ee7 100644 --- a/translations/trackclick_bn.ts +++ b/translations/trackclick_bn.ts @@ -161,6 +161,10 @@ Please install 'onboard' or 'florence'.কোনো অন Click triggerক্লিক ট্রিগার Audio clickঅডিও ক্লিক Dwell clickড্ওয়েল ক্লিক + Window Behaviorউইন্ডো আচরণ + Button Controlsবোতাম নিয়ন্ত্রণ + Feedbackফিডব্যাক + Show button labelsবোতামের লেবেল দেখান Return to left click after click:ক্লিকের পরে বাম ক্লিকে ফিরে যান: diff --git a/translations/trackclick_cs.ts b/translations/trackclick_cs.ts index 5f13383..7b99db6 100644 --- a/translations/trackclick_cs.ts +++ b/translations/trackclick_cs.ts @@ -158,6 +158,10 @@ Nainstalujte prosím 'onboard' nebo 'florence'. Click triggerSpouštěč kliknutí Audio clickZvukové kliknutí Dwell clickKliknutí najetím + Window BehaviorChování okna + Button ControlsOvládání tlačítek + FeedbackZpětná vazba + Show button labelsZobrazit popisky tlačítek Return to left click after click:Po kliknutí se vrátit na levé kliknutí: diff --git a/translations/trackclick_es.ts b/translations/trackclick_es.ts index a0149bf..bf497c4 100644 --- a/translations/trackclick_es.ts +++ b/translations/trackclick_es.ts @@ -156,6 +156,10 @@ Instale 'onboard' o 'florence'. Click triggerDisparador del clic Audio clickClic por sonido Dwell clickClic por permanencia + Window BehaviorComportamiento de la ventana + Button ControlsControles de botones + FeedbackRetroalimentación + Show button labelsMostrar etiquetas de botones Return to left click after click:Volver al clic izquierdo después de hacer clic: diff --git a/translations/trackclick_fr.ts b/translations/trackclick_fr.ts index 2bb08a0..3254daa 100644 --- a/translations/trackclick_fr.ts +++ b/translations/trackclick_fr.ts @@ -156,6 +156,10 @@ Veuillez installer 'onboard' ou 'florence'. Click triggerDéclencheur du clic Audio clickClic audio Dwell clickClic par survol + Window BehaviorComportement de la fenêtre + Button ControlsContrôles des boutons + FeedbackRetour d'information + Show button labelsAfficher les libellés des boutons Return to left click after click:Revenir au clic gauche après un clic : diff --git a/translations/trackclick_hi.ts b/translations/trackclick_hi.ts index 172c349..1710e0b 100644 --- a/translations/trackclick_hi.ts +++ b/translations/trackclick_hi.ts @@ -161,6 +161,10 @@ Please install 'onboard' or 'florence'.कोई ऑन- Click triggerक्लिक ट्रिगर Audio clickऑडियो क्लिक Dwell clickड्वेल क्लिक + Window Behaviorविंडो व्यवहार + Button Controlsबटन नियंत्रण + Feedbackफ़ीडबैक + Show button labelsबटन लेबल दिखाएँ Return to left click after click:क्लिक के बाद बाएं क्लिक पर लौटें: diff --git a/translations/trackclick_ja.ts b/translations/trackclick_ja.ts index 24a7567..00ac740 100644 --- a/translations/trackclick_ja.ts +++ b/translations/trackclick_ja.ts @@ -156,6 +156,10 @@ Please install 'onboard' or 'florence'.スクリーンキ Click triggerクリックのトリガー Audio click音声クリック Dwell clickドウェルクリック + Window Behaviorウィンドウの動作 + Button Controlsボタンの設定 + Feedbackフィードバック + Show button labelsボタンのラベルを表示 Return to left click after click:クリック後に左クリックに戻る: diff --git a/translations/trackclick_ko.ts b/translations/trackclick_ko.ts index bb4b7ca..d1e0460 100644 --- a/translations/trackclick_ko.ts +++ b/translations/trackclick_ko.ts @@ -156,6 +156,10 @@ Please install 'onboard' or 'florence'.화상 키보드를 Click trigger클릭 트리거 Audio click소리 클릭 Dwell click머물기 클릭 + Window Behavior창 동작 + Button Controls버튼 제어 + Feedback피드백 + Show button labels버튼 레이블 표시 Return to left click after click:클릭 후 왼쪽 클릭으로 돌아가기: diff --git a/translations/trackclick_pt.ts b/translations/trackclick_pt.ts index 8366179..a0959f7 100644 --- a/translations/trackclick_pt.ts +++ b/translations/trackclick_pt.ts @@ -161,6 +161,10 @@ Instale 'onboard' ou 'florence'. Click triggerDisparador do clique Audio clickClique por som Dwell clickClique por permanência + Window BehaviorComportamento da janela + Button ControlsControles de botões + FeedbackFeedback + Show button labelsMostrar rótulos dos botões Return to left click after click:Voltar ao clique esquerdo após clicar: diff --git a/translations/trackclick_ru.ts b/translations/trackclick_ru.ts index d0c4c33..9aeb382 100644 --- a/translations/trackclick_ru.ts +++ b/translations/trackclick_ru.ts @@ -161,6 +161,10 @@ Please install 'onboard' or 'florence'.Экранная к Click triggerТриггер щелчка Audio clickЗвуковой щелчок Dwell clickЩелчок по задержке + Window BehaviorПоведение окна + Button ControlsУправление кнопками + FeedbackОбратная связь + Show button labelsПоказывать подписи кнопок Return to left click after click:Возврат к левому клику после клика: diff --git a/translations/trackclick_ur.ts b/translations/trackclick_ur.ts index 10b840f..5a529a3 100644 --- a/translations/trackclick_ur.ts +++ b/translations/trackclick_ur.ts @@ -161,6 +161,10 @@ Please install 'onboard' or 'florence'.کوئی آن-اس Click triggerکلک ٹرگر Audio clickآڈیو کلک Dwell clickڈویل کلک + Window Behaviorونڈو کا رویہ + Button Controlsبٹن کنٹرولز + Feedbackفیڈ بیک + Show button labelsبٹن لیبل دکھائیں Return to left click after click:کلک کے بعد بایاں کلک پر واپس جائیں: diff --git a/translations/trackclick_zh_CN.ts b/translations/trackclick_zh_CN.ts index 11caa60..ac3b51b 100644 --- a/translations/trackclick_zh_CN.ts +++ b/translations/trackclick_zh_CN.ts @@ -156,6 +156,10 @@ Please install 'onboard' or 'florence'.未找到屏幕键 Click trigger点击触发方式 Audio click声音点击 Dwell click悬停点击 + Window Behavior窗口行为 + Button Controls按钮控制 + Feedback反馈 + Show button labels显示按钮标签 Return to left click after click:点击后返回左键单击: From dc412e59387cdb3b9272f1965d2a74c1ed7626de Mon Sep 17 00:00:00 2001 From: skynab Date: Sat, 25 Jul 2026 08:37:00 -0700 Subject: [PATCH 13/14] Keyboard button default reordered. --- settingsdialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settingsdialog.cpp b/settingsdialog.cpp index 4ea7741..a4caa4b 100644 --- a/settingsdialog.cpp +++ b/settingsdialog.cpp @@ -232,8 +232,8 @@ static QStringList canonicalButtonIds() } for (int i = 0; i < kHotkeyCount; ++i) ids << QStringLiteral("hotkey_%1").arg(i); - ids << QStringLiteral("dwell_active") << QStringLiteral("quit") - << QStringLiteral("keyboard"); + ids << QStringLiteral("dwell_active") << QStringLiteral("keyboard") + << QStringLiteral("quit"); return ids; } From c178728e384c95cb1becbb3ff523bddd3bcc4218 Mon Sep 17 00:00:00 2001 From: Anthony Lazzaro Date: Sat, 25 Jul 2026 14:06:43 -0700 Subject: [PATCH 14/14] Minimal width feature (#9) * Minimal width feature attempt. * Attempt 2 * Translation updates. --- mainwindow.cpp | 21 +++++++++++++++++++++ settingsdialog.cpp | 23 +++++++++++++++++++++++ settingsdialog.h | 10 ++++++++++ translations/trackclick_ar.ts | 3 +++ translations/trackclick_bn.ts | 3 +++ translations/trackclick_cs.ts | 3 +++ translations/trackclick_es.ts | 3 +++ translations/trackclick_fr.ts | 3 +++ translations/trackclick_hi.ts | 3 +++ translations/trackclick_ja.ts | 3 +++ translations/trackclick_ko.ts | 3 +++ translations/trackclick_pt.ts | 3 +++ translations/trackclick_ru.ts | 3 +++ translations/trackclick_ur.ts | 3 +++ translations/trackclick_zh_CN.ts | 3 +++ 15 files changed, 90 insertions(+) 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'.未找到屏幕键盘。
%1  %3