diff --git a/resources/translations/cs.ts b/resources/translations/cs.ts
index 07c0000f..9f2ef40f 100644
--- a/resources/translations/cs.ts
+++ b/resources/translations/cs.ts
@@ -584,14 +584,14 @@
O této aplikaci
-
-
+
+ Bell before breaksZvonek před přestávkami
-
-
+
+ Bell after breaksZvonek po přestávkách
@@ -780,17 +780,17 @@ Všechny barvy jsou ve formátu <code>#AARRGGBB</code>.<h3>Podmínky pozastavení</h3>
-
+ Long pause thresholdHranice dlouhého pozastavení
-
+ Short pause thresholdHranice krátkého pozastavení
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -798,17 +798,17 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
Řekněme, že jste nastavili na 2 minuty. Pokud je přestávka kratší než 2 minuty, obrazovka se zamkne 2 minuty po zahájení přestávky, pokud po ní není žádná aktivita. Pokud je přestávka delší než 2 minuty, obrazovka se zamkne bez ohledu na aktivitu.
-
+ Automatic screen lock after break startAutomatické zamknutí obrazovky po zahájení přestávky
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Pomozte přeložit!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -848,16 +848,16 @@ v%1
<h3>Vzhled připomínky</h3>
-
-
+
+ Try restart Sane Break if no soundZkuste restartovat Sane Break, pokud nejsou žádné zvuky
-
-
-
-
+
+
+
+ PlayPřehrát
@@ -875,7 +875,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Malé přestávky</h3>
@@ -885,8 +885,8 @@ v%1
-
-
+
+ min min
@@ -915,7 +915,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Velké přestávky</h3>
@@ -1026,41 +1026,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ Přehrávače videa, prezentace a některé hry zabraňují uspání obrazovky. Pokud je tato možnost zapnuta, počítá se to jako aktivita, takže se při jejich běhu nespustí pozastavení kvůli nečinnosti; pokud je vypnuta, počítá se pouze váš skutečný vstup. Účinnost se liší podle platformy: plná podpora na Waylandu s ext-idle-notify; nejlepší možný odhad na X11, kde je detekována pouze inhibice založená na XScreenSaverSuspend.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ Když aplikace udržuje obrazovku aktivní, počítat ji jako aktivitu (např. přehrávání videa)
+
+
+ Pause on batteryPozastavit při baterii
-
+ Pause breaks when any of the following program is running:Pozastavit přestávky, když běží některý z následujících programů:
-
+ (Write one program name per line)(Pište název programu na každý řádek)
-
+ <h3>External Monitors</h3><h3>Externí monitory</h3>
-
+ Pause when unknown monitor is connectedPozastavit při připojení neznámého monitoru
-
+ Mark currently connected monitors as knownOznačit právě připojené monitory jako známé
-
+ Remove selectedOdstranit vybrané
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1076,10 +1086,10 @@ v%1
-
-
-
-
+
+
+
+ BrowseProcházet
@@ -1094,62 +1104,62 @@ v%1
Když aktivujete režim zaměření z panelu, přestávky se budou řídit tímto rozvrhem. Použijte jej pro kratší přestávky, když potřebujete zůstat soustředění.
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Tip</strong>: Pomocí <i>Procházet</i> vyberte vlastní zvukový soubor. Kopie souboru bude uložena, aby bylo možné jej vždy přehrát.
-
+ Configuration fileKonfigurační soubor
-
+ Database fileSoubor databáze
-
+ Launch Sane Break at start upSpustit Sane Break při spuštění
-
+ Get the Source CodeZískat zdrojový kód
-
+ Help Us Translate!Pomozte nám přeložit!
-
+ Revert to Last SavedVrátit se na poslední uložené
-
+ LanguageJazyk
-
+ Change of language will take effect after app restart.Změna jazyka se projeví po restartu aplikace.
-
+ Third-party Libraries LicensesLicence třetích stran
-
+ DefaultsVýchozí hodnoty
-
+ SaveUložit
@@ -1157,9 +1167,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n minuta
@@ -1178,7 +1188,7 @@ v%1
-
+ %n sec%n sekunda
@@ -1187,83 +1197,83 @@ v%1
-
+ DisabledVypnuto
-
+ Start next break after middle clicking on tray iconZačít další přestávku po stisku prostředního tlačítka na ikoně v panelu
-
+ Start next break after double clicking on tray iconZačít další přestávku po dvojitém kliknutí na ikonu v panelu
-
+ SaveUložit
-
+ DiscardZahodit
-
+ CancelZrušit
-
+ Select Sound FileVybrat zvukový soubor
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Zvukové soubory (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorChyba
-
+ Failed to save a copy of the selected sound file.Nepodařilo se uložit kopii vybraného zvukového souboru.
-
+ Select Background ImageVybrat obrázek pozadí
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Obrázkové soubory (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Nepodařilo se uložit kopii vybraného obrázkového souboru.
-
+ Setting autostart failedNastavení automatického spuštění selhalo
-
+ The preferences have been modified.Nastavení bylo změněno.
-
+ Do you want to save your changes?Chcete uložit své změny?
diff --git a/resources/translations/de.ts b/resources/translations/de.ts
index b40821a3..2db6aa61 100644
--- a/resources/translations/de.ts
+++ b/resources/translations/de.ts
@@ -584,14 +584,14 @@
Über
-
-
+
+ Bell before breaksKlang vor Pause
-
-
+
+ Bell after breaksKlang nach Pause
@@ -776,17 +776,17 @@ Alle Farben sind im <code>#AARRGGBB</code>-Format.
<h3>Bedingungen fürs Pausieren</h3>
-
+ Long pause thresholdSchwellenwert lange Pause
-
+ Short pause thresholdSchwellenwert kurze Pause
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -794,17 +794,17 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
Angenommen, 2 Minuten sind eingestellt. Wenn die Pause kürzer als 2 Minuten ist, wird der Bildschirm 2 Minuten nach Beginn der Pause gesperrt, sofern keine Aktivität stattfindet. Bei Pausen länger als 2 Minuten wird der Bildschirm unabhängig davon gesperrt.
-
+ Automatic screen lock after break startAutomatische Bildschirmsperre nach Pausenbeginn
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Übersetzen helfen!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -844,16 +844,16 @@ v%1
<h3>Erscheinungsbild der Benachrichtigung</h3>
-
-
+
+ Try restart Sane Break if no soundVersuche, Sane Break neu zu starten, wenn kein Ton vorhanden ist
-
-
-
-
+
+
+
+ PlayWiedergeben
@@ -871,7 +871,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Kleine Pausen</h3>
@@ -881,8 +881,8 @@ v%1
-
-
+
+ min min
@@ -911,7 +911,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Große Pausen</h3>
@@ -1022,41 +1022,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ Videoplayer, Präsentationen und einige Spiele verhindern, dass der Bildschirm in den Ruhezustand geht. Wenn aktiviert, zählt dies als Aktivität, sodass die Inaktivitäts-Pause nicht ausgelöst wird, während sie laufen; wenn deaktiviert, zählt nur Ihre tatsächliche Eingabe. Die Wirksamkeit variiert je nach Plattform: vollständig bei ext-idle-notify unter Wayland; nach bestem Ermessen unter X11, wo nur auf XScreenSaverSuspend basierende Unterdrückung erkannt wird.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ Wenn eine App den Bildschirm wach hält, zähle dies als Aktivität (z. B. Videowiedergabe)
+
+
+ Pause on batteryBei Akkunutzung anhalten
-
+ Pause breaks when any of the following program is running:Pausieren Sie Pausen, wenn eines der folgenden Programme läuft:
-
+ (Write one program name per line)(Pro Zeile einen Programmnamen eingeben)
-
+ <h3>External Monitors</h3><h3>Externe Monitore</h3>
-
+ Pause when unknown monitor is connectedPausieren, wenn ein unbekannter Monitor angeschlossen wird
-
+ Mark currently connected monitors as knownDerzeit angeschlossene Monitore als bekannt markieren
-
+ Remove selectedAusgewählte entfernen
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1072,10 +1082,10 @@ v%1
-
-
-
-
+
+
+
+ BrowseDurchsuchen
@@ -1090,62 +1100,62 @@ v%1
Wenn Sie den Fokusmodus über das Systemtray aktivieren, folgen die Pausen stattdessen diesem Plan. Verwenden Sie ihn für kürzere Pausen, wenn Sie sich konzentrieren müssen.
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Tipp</strong>: Verwenden Sie <i>Durchsuchen</i>, um eine benutzerdefinierte Sounddatei auszuwählen. Eine Kopie der Datei wird gespeichert, damit sie immer wiedergegeben werden kann.
-
+ Configuration fileKonfigurationsdatei
-
+ Database fileDatenbankdatei
-
+ Launch Sane Break at start upSane Break beim Start starten
-
+ Get the Source CodeQuellcode abrufen
-
+ Help Us Translate!Helfen Sie uns zu übersetzen!
-
+ Revert to Last SavedAuf zuletzt Gespeichertes zurücksetzen
-
+ LanguageSprache
-
+ Change of language will take effect after app restart.Die Sprachänderung wirkt nach einem Neustart der App.
-
+ Third-party Libraries LicensesLizenzbedingungen von Drittanbieter-Bibliotheken
-
+ DefaultsStandardwerte
-
+ SaveSpeichern
@@ -1153,9 +1163,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n Minute
@@ -1172,7 +1182,7 @@ v%1
-
+ %n sec%n Sekunde
@@ -1180,83 +1190,83 @@ v%1
-
+ DisabledDeaktiviert
-
+ Start next break after middle clicking on tray iconNächste Pause nach Mittelklick auf das Systemtray-Symbol starten
-
+ Start next break after double clicking on tray iconNächste Pause nach Doppelklick auf das Systemtray-Symbol starten
-
+ SaveSpeichern
-
+ DiscardVerwerfen
-
+ CancelAbbrechen
-
+ Select Sound FileSounddatei auswählen
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Sounddateien (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorFehler
-
+ Failed to save a copy of the selected sound file.Konnte keine Kopie der ausgewählten Sounddatei speichern.
-
+ Select Background ImageHintergrundbild auswählen
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Bilddateien (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Konnte keine Kopie der ausgewählten Bilddatei speichern.
-
+ Setting autostart failedFestlegen des Autostarts fehlgeschlagen
-
+ The preferences have been modified.Die Einstellungen wurden geändert.
-
+ Do you want to save your changes?Möchten Sie Ihre Änderungen speichern?
diff --git a/resources/translations/en.ts b/resources/translations/en.ts
index d6a5ceb2..f403d9f0 100644
--- a/resources/translations/en.ts
+++ b/resources/translations/en.ts
@@ -4,9 +4,9 @@
PreferenceWindow
-
-
-
+
+
+ %n min%n min
@@ -23,7 +23,7 @@
-
+ %n sec%n sec
diff --git a/resources/translations/es.ts b/resources/translations/es.ts
index bd6bc93a..de8f17cd 100644
--- a/resources/translations/es.ts
+++ b/resources/translations/es.ts
@@ -600,14 +600,14 @@
Acerca de
-
-
+
+ Bell before breaksSonido al comenzar descanso
-
-
+
+ Bell after breaksSonido al finalizar descanso
@@ -790,17 +790,17 @@ Todos los colores están en formato <code>#AARRGGBB</code>.<h3>Condiciones de la pausa</h3>
-
+ Long pause thresholdLímite de la pausa larga
-
+ Short pause thresholdLímite de la pausa breve
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -810,7 +810,7 @@ de 2 minutos, la pantalla se bloqueará 2 minutos después de que comience el de
inactividad tras finalizar el descanso. Si el descanso dura más de 2 minutos, la pantalla se bloqueará en cualquier caso.
-
+ Automatic screen lock after break startBloqueo automático de la pantalla tras comenzar el descanso
@@ -819,12 +819,12 @@ inactividad tras finalizar el descanso. Si el descanso dura más de 2 minutos, l
Por favor, concede permisos de acceso y reinicia la aplicación para usar el bloqueo automático de la pantalla
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">¡Ayuda en la traducción!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -884,16 +884,16 @@ v%1
Más rápido
-
-
+
+ Try restart Sane Break if no soundPrueba a reiniciar Sane Break si no funciona el sonido
-
-
-
-
+
+
+
+ PlayReproducir
@@ -911,7 +911,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Descansos breves</h3>
@@ -921,8 +921,8 @@ v%1
-
-
+
+ min min
@@ -951,7 +951,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Descansos largos</h3>
@@ -1072,41 +1072,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ Los reproductores de vídeo, las presentaciones y algunos juegos impiden que la pantalla se apague. Si está activado, esto se cuenta como actividad, por lo que la pausa por inactividad no se activará mientras se ejecuten; si está desactivado, solo cuenta tu entrada real. La eficacia varía según la plataforma: total en Wayland con ext-idle-notify; esfuerzo máximo en X11, donde solo se detecta la inhibición basada en XScreenSaverSuspend.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ Cuando una aplicación mantiene la pantalla encendida, contarla como actividad (p. ej., reproducción de vídeo)
+
+
+ Pause on batteryPausar cuando se está usando la batería
-
+ Pause breaks when any of the following program is running:Pausar los descansos cuando cualquiera de estas aplicaciones se está ejecutando:
-
+ (Write one program name per line)(Escribir una aplicación por línea)
-
+ <h3>External Monitors</h3><h3>Monitores externos</h3>
-
+ Pause when unknown monitor is connectedPausar cuando se conecte un monitor desconocido
-
+ Mark currently connected monitors as knownMarcar los monitores actualmente conectados como conocidos
-
+ Remove selectedEliminar seleccionados
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1122,10 +1132,10 @@ v%1
-
-
-
-
+
+
+
+ BrowseExaminar
@@ -1140,62 +1150,62 @@ v%1
Cuando actives el modo de enfoque desde la bandeja, los descansos seguirán este horario. Úsalo para descansos más cortos cuando necesites mantener el enfoque.
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Consejo</strong>: Usa <i>Examinar</i> para seleccionar un archivo de sonido personalizado. Se guardará una copia del archivo para que siempre pueda reproducirse.
-
+ Configuration fileArchivo de configuración
-
+ Database fileArchivo de base de datos
-
+ Launch Sane Break at start upEjecutar Sane Break al iniciar el ordenador
-
+ Get the Source CodeVer el código fuente
-
+ Help Us Translate!¡Aúdanos a traducir!
-
+ Revert to Last SavedRevertir a la última configuración guardada
-
+ LanguageIdioma
-
+ Change of language will take effect after app restart.El cambio de idioma tendrá efecto tras reiniciar la aplicación.
-
+ Third-party Libraries LicensesLicencias de bibliotecas de terceros
-
+ DefaultsValores por defecto
-
+ SaveGuardar
@@ -1203,9 +1213,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n min
@@ -1222,7 +1232,7 @@ v%1
-
+ %n sec%n seg
@@ -1230,83 +1240,83 @@ v%1
-
+ DisabledDesactivado
-
+ Start next break after middle clicking on tray iconComenzar el siguiente descanso tras clicar con el botón central en el icono de la bandeja
-
+ Start next break after double clicking on tray iconComenzar el siguiente descanso tras hacer doble clic en el icono de la bandeja
-
+ SaveGuardar
-
+ DiscardDescartar
-
+ CancelCancelar
-
+ Select Sound FileSeleccionar archivo de sonido
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Archivos de sonido (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorError
-
+ Failed to save a copy of the selected sound file.No se pudo guardar una copia del archivo de sonido seleccionado.
-
+ Select Background ImageSeleccionar imagen de fondo
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Archivos de imagen (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.No se pudo guardar una copia del archivo de imagen seleccionado.
-
+ Setting autostart failedLa configuración de inicio automático falló
-
+ The preferences have been modified.Las preferencias se han modificado.
-
+ Do you want to save your changes?¿Quieres guardar los cambios?
diff --git a/resources/translations/fr.ts b/resources/translations/fr.ts
index cf35fcfc..23cfa7df 100644
--- a/resources/translations/fr.ts
+++ b/resources/translations/fr.ts
@@ -764,7 +764,7 @@ Toutes les couleurs sont au format <code>#AARRGGBB</code>.<h3>Conditions de pause</h3>
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -779,17 +779,17 @@ Toutes les couleurs sont au format <code>#AARRGGBB</code>.
-
+ Long pause thresholdSeuil d'une longue pause
-
+ Short pause thresholdSeuil d'une petite pause
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -800,7 +800,7 @@ est que l'utilisateur est bien inactif. Si la pause dure plus longue que 2
l'écran sera quand même bloqué.
-
+ Automatic screen lock after break startVerrouillage automatique de l'écran après le début de la pause
@@ -809,7 +809,7 @@ l'écran sera quand même bloqué.
Merci d'octroyer les droits d'accès et de redémarrer l'appli pour utiliser le verrouillage d'écran
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -883,16 +883,16 @@ v%1
Transparence du compte à rebours
-
-
+
+ Try restart Sane Break if no soundSi le son ne fonctionne pas, essayez de redémarrer Sane Break
-
-
-
-
+
+
+
+ PlayÉcouter
@@ -928,7 +928,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Petites pauses</h3>
@@ -938,14 +938,14 @@ v%1
-
-
+
+ min min
-
-
+
+ Bell before breaksSon de cloche avant les pauses
@@ -968,8 +968,8 @@ v%1
Durée d'une pause
-
-
+
+ Bell after breaksSon de cloche après les pauses
@@ -980,7 +980,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Grosses pauses</h3>
@@ -1101,25 +1101,35 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ Les lecteurs vidéo, les présentations et certains jeux empêchent la mise en veille de l’écran. Lorsque cette option est activée, cela compte comme une activité, donc la pause pour inactivité ne se déclenchera pas pendant leur exécution ; lorsqu’elle est désactivée, seule votre saisie réelle compte. L’efficacité varie selon la plateforme : totale avec ext-idle-notify sous Wayland ; au mieux sous X11 où seule l’inhibition basée sur XScreenSaverSuspend est détectée.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ Lorsqu’une application maintient l’écran éveillé, la considérer comme une activité (par exemple, la lecture vidéo)
+
+
+ Pause on batteryMettre en pause sur batterie
-
+ Pause breaks when any of the following program is running:La pause s'arrête dès que l'un de ces programmes se met en route :
-
+ (Write one program name per line)(écrire un seul nom de programme par ligne)
-
-
-
-
+
+
+
+ BrowseParcourir
@@ -1134,87 +1144,87 @@ v%1
Lorsque vous activez le mode concentration depuis la barre des tâches, les pauses suivront ce programme à la place. Utilisez-le pour des pauses plus courtes lorsque vous devez rester concentré.
-
+ <h3>External Monitors</h3><h3>Moniteurs externes</h3>
-
+ Pause when unknown monitor is connectedMettre en pause lorsque un moniteur inconnu est connecté
-
+ Mark currently connected monitors as knownMarquer les moniteurs actuellement connectés comme connus
-
+ Remove selectedSupprimer la sélection
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Astuce</strong> : Utilisez <i>Parcourir</i> pour sélectionner un fichier son personnalisé. Une copie du fichier sera enregistrée afin qu’il puisse toujours être lu.
-
+ Configuration fileFichier de configuration
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Aidez-nous à faire la traduction !</a>
-
+ Database fileFichier de base de données
-
+ Launch Sane Break at start upLancer Sane Break au démarrage de l'ordinateur
-
+ Get the Source CodeObtenir le code source
-
+ Help Us Translate!Aidez-nous à traduire !
-
+ Revert to Last SavedRevenir aux anciens paramètres sauvegardés
-
+ LanguageLangue
-
+ Change of language will take effect after app restart.Le changement de langue prendra effet après redémarrage de l'appli.
-
+ Third-party Libraries LicensesLicences des bibliothèques tierces
-
+ DefaultsParamètres par défaut
-
+ SaveSauvegarder
@@ -1222,9 +1232,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n min
@@ -1241,7 +1251,7 @@ v%1
-
+ %n sec%n sec
@@ -1249,83 +1259,83 @@ v%1
-
+ DisabledDésactivé
-
+ Start next break after middle clicking on tray iconDémarrer la pause suivante en faisant clic du milieu sur l'icône dans la barre des tâches
-
+ Start next break after double clicking on tray iconDémarrer la pause suivante en faisant double-clic sur l'icône dans la barre des tâches
-
+ SaveSauvegarder
-
+ DiscardRejeter
-
+ CancelAnnuler
-
+ Select Sound FileSélectionner un fichier son
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Fichiers son (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorErreur
-
+ Failed to save a copy of the selected sound file.Échec de l’enregistrement d’une copie du fichier son sélectionné.
-
+ Select Background ImageSélectionner une image d’arrière-plan
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Fichiers image (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Échec de l’enregistrement d’une copie du fichier image sélectionné.
-
+ Setting autostart failedLa mise en place du démarrage automatique a échoué
-
+ The preferences have been modified.Les préférences ont été modifiées.
-
+ Do you want to save your changes?Voulez-vous sauvegarder les changements ?
diff --git a/resources/translations/he.ts b/resources/translations/he.ts
index 87987014..d2a256d0 100644
--- a/resources/translations/he.ts
+++ b/resources/translations/he.ts
@@ -584,14 +584,14 @@
על אודות
-
-
+
+ Bell before breaksצלצול פעמונים לפני הפסקות
-
-
+
+ Bell after breaksצלצול פעמונים אחרי הפסקות
@@ -780,17 +780,17 @@ All color are in <code>#AARRGGBB</code> format.
<h3>תנאי השהיה</h3>
-
+ Long pause thresholdסף השהיה ארוכה
-
+ Short pause thresholdסף השהיה קצרה
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -800,7 +800,7 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
ההפסקה. אם ההפסקה ארוכה מ-2 דקות, המסך י נעול בכל מקרה.
-
+ Automatic screen lock after break startנעילת מסך אוטומטית לאחר תחילת ההפסקה
@@ -809,12 +809,12 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
יש להעניק הרשאת נגישות ו рестארט את האפליקציה כדי להשתמש בנעילת מסך אוטומטית
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">עזרו לנו לתרגם!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -874,16 +874,16 @@ v%1
מהיר יותר
-
-
+
+ Try restart Sane Break if no soundכדאי לנסות לפתוח את Sane Break מחדש אם אין צליל
-
-
-
-
+
+
+
+ Playניגון
@@ -901,7 +901,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>הפסקות קצרות</h3>
@@ -911,8 +911,8 @@ v%1
-
-
+
+ min דק׳
@@ -941,7 +941,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>הפסקות ארוכות</h3>
@@ -1052,41 +1052,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ נגני וידאו, מצגות ומשחקים מסוימים מונעים מהמסך להיכנס למצב שינה. כאשר אפשרות זו פעילה, הדבר נחשב כפעילות ולכן ההשהיה עקב חוסר פעילות לא תופעל בזמן שהם רצים; כאשר היא כבויה, רק הקלט הישיר שלך נספר. היעילות משתנה לפי הפלטפורמה: מלא ב-Wayland עם ext-idle-notify; מאמץ מיטבי ב-X11 שם מזוהה רק מניעה המבוססת על XScreenSaverSuspend.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ כשאפליקציה שומרת את המסך ער, ספור זאת כפעילות (למשל השמעת וידאו)
+
+
+ Pause on batteryהשהיה בעת שימוש בסוללה
-
+ Pause breaks when any of the following program is running:השהיית ההפסקות כאשר אחת מהתוכניות הבאות מופעלת:
-
+ (Write one program name per line)(כתוב שם תוכנה אחת לשורה)
-
+ <h3>External Monitors</h3><h3>צגים חיצוניים</h3>
-
+ Pause when unknown monitor is connectedהשהה כאשר מחובר מוניטור לא מוכר
-
+ Mark currently connected monitors as knownסמן את המוניטורים המחוברים כרגע כידועים
-
+ Remove selectedהסר את הנבחר
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1102,10 +1112,10 @@ v%1
-
-
-
-
+
+
+
+ Browseעיון
@@ -1120,62 +1130,62 @@ v%1
כאשר תפעיל את מצב הריכוז מהמקלדת, ההפסקות יתנהלו לפי לוח זה במקום. השתמש בו לפסקות קצרות כשאתה צריך לשמור על ריכוז.
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>טיפ</strong>: השתמש ב-<i>דפדף</i> כדי לבחור קובץ צליל מותאם אישית. עותק של הקובץ יישמר כדי שיהיה ניתן לנגן אותו תמיד.
-
+ Configuration fileקובץ תצורה
-
+ Database fileקובץ מסד נתונים
-
+ Launch Sane Break at start upהפעלת Sane Break בעת עליית המערכת
-
+ Get the Source Codeקבל את קוד המקור
-
+ Help Us Translate!עזרו לנו לתרגם!
-
+ Revert to Last Savedשחזר להגדרות האחרונות שנשמרו
-
+ Languageשפה
-
+ Change of language will take effect after app restart.שינוי השפה ייכנס לתוקף לאחר פתיחת היישום מחדש.
-
+ Third-party Libraries Licensesרישיונות של ספריות צד־שלישי
-
+ Defaultsברירות מחדל
-
+ Saveשמירה
@@ -1183,9 +1193,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n minדקה
@@ -1202,7 +1212,7 @@ v%1
-
+ %n secשנייה
@@ -1210,83 +1220,83 @@ v%1
-
+ Disabledמושבת
-
+ Start next break after middle clicking on tray iconהתחל את ההפסקה הבאה לאחר לחיצה אמצעית בסמל במקלדת
-
+ Start next break after double clicking on tray iconהתחל את ההפסקה הבאה לאחר לחיצה כפולה בסמל במקלדת
-
+ Saveשמירה
-
+ Discardהשלכה
-
+ Cancelביטול
-
+ Select Sound Fileבחר קובץ צליל
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)קובצי צליל (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ Errorשגיאה
-
+ Failed to save a copy of the selected sound file.נכשל בשמירת עותק של קובץ הצליל שנבחר.
-
+ Select Background Imageבחר תמונה לרקע
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)קבצי תמונה (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.נכשל בשמירת עותק של קובץ התמונה שנבחר.
-
+ Setting autostart failedהגדרת ההפעלה האוטומטית נכשלה
-
+ The preferences have been modified.ההעדפות השתנו.
-
+ Do you want to save your changes?לשמור את השינויים?
diff --git a/resources/translations/hu.ts b/resources/translations/hu.ts
index c9fef175..d3e028c2 100644
--- a/resources/translations/hu.ts
+++ b/resources/translations/hu.ts
@@ -568,14 +568,14 @@
Az alkalmazásról
-
-
+
+ Bell before breaksHangjelzés szünetek előtt
-
-
+
+ Bell after breaksHangjelzés szünetek végénél
@@ -766,22 +766,22 @@ A színkódok <code>#AARRGGBB</code> formátumban vannak.<h3>Szünet feltételei</h3>
-
+ Long pause thresholdHosszú szünet ideje
-
+ Short pause thresholdRövid szünet ideje
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Tipp</strong>: Használja a <i>Tallózás</i> gombot egyéni hangfájl kiválasztásához. A fájl másolata elmentésre kerül, hogy mindig lejátszható legyen.
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -791,17 +791,17 @@ kezdés után két perccel lesz lezárva, ha a szünet vége után nincs aktivit
legalább két perc, akkor a képernyő mindenképpen lezár.
-
+ Automatic screen lock after break startKépernyő automatikus lezárása a szünet kezdése után
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Segíts a fordításban!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -837,16 +837,16 @@ v%1
<h3>Értesítés megjelenése</h3>
-
-
+
+ Try restart Sane Break if no soundPróbálja meg újraindítani a Sane Break-et, ha nincs hang
-
-
-
-
+
+
+
+ PlayLejátszás
@@ -864,7 +864,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Kis szünetek</h3>
@@ -874,8 +874,8 @@ v%1
-
-
+
+ minperc
@@ -900,7 +900,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Nagy szünetek</h3>
@@ -1007,41 +1007,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+
+
+
+ Pause on batterySzüneteltetés akkumulátorról történő üzemelés során
-
+ Pause breaks when any of the following program is running:Szünetek szüneteltetése, ha a következő programok bármelyike fut:
-
+ (Write one program name per line)(Soronként egy programnév)
-
+ <h3>External Monitors</h3><h3>Külső monitorok</h3>
-
+ Pause when unknown monitor is connectedSzüneteltetés ismeretlen monitor csatlakoztatásakor
-
+ Mark currently connected monitors as knownJelenleg csatlakoztatott monitorok megjelölése ismertként
-
+ Remove selectedKijelölt eltávolítása
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1057,65 +1067,65 @@ v%1
-
-
-
-
+
+
+
+ BrowseTallózás
-
+ Configuration fileKonfigurációs fájl
-
+ Database fileAdatbázis fájl
-
+ Launch Sane Break at start upSane Break indítása rendszerindításkor
-
+ Get the Source CodeForráskód letöltése
-
+ Help Us Translate!Segítsen a fordításban!
-
+ Revert to Last SavedVisszaállítás az utolsó mentett állapotra
-
+ LanguageNyelv
-
+ Change of language will take effect after app restart.A nyelvváltás az alkalmazás újraindítása után lép életbe.
-
+ Third-party Libraries LicensesHarmadik féltől származó könyvtárak licencei
-
+ DefaultsAlapértelmezések
-
+ SaveMentés
@@ -1123,9 +1133,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n perc
@@ -1140,90 +1150,90 @@ v%1
-
+ %n sec%n mp
-
+ DisabledLetiltva
-
+ Start next break after middle clicking on tray iconKövetkező szünet indítása a tálca ikon középső gombbal történő kattintásával
-
+ Start next break after double clicking on tray iconKövetkező szünet indítása a tálca ikon dupla kattintásával
-
+ SaveMentés
-
+ DiscardElvetés
-
+ CancelMégse
-
+ Select Sound FileHangfájl kiválasztása
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Hangfájlok (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorHiba
-
+ Failed to save a copy of the selected sound file.Nem sikerült menteni a kiválasztott hangfájl másolatát.
-
+ Select Background ImageHáttérkép kiválasztása
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Képfájlok (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Nem sikerült menteni a kiválasztott képfájl másolatát.
-
+ Setting autostart failedAz automatikus indítás beállítása sikertelen
-
+ The preferences have been modified.A beállítások módosultak.
-
+ Do you want to save your changes?Szeretné menteni a változtatásokat?
diff --git a/resources/translations/it.ts b/resources/translations/it.ts
index b65378d0..2cc205e6 100644
--- a/resources/translations/it.ts
+++ b/resources/translations/it.ts
@@ -584,14 +584,14 @@
Informazioni
-
-
+
+ Bell before breaksSuono prima delle pause
-
-
+
+ Bell after breaksSuono dopo le pause
@@ -776,17 +776,17 @@ Tutti i colori sono in formato <code>#AARRGGBB</code>.
<h3>Condizioni di pausa</h3>
-
+ Long pause thresholdSoglia pausa lunga
-
+ Short pause thresholdSoglia pausa breve
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -796,17 +796,17 @@ lo schermo si bloccherà 2 minuti dopo l'inizio della pausa, a condizione c
pausa. Se la pausa è più lunga di 2 minuti, lo schermo verrà bloccato comunque.
-
+ Automatic screen lock after break startBlocco dello schermo automatico dopo l'inizio della pausa
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Aiutaci a tradurre!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -846,16 +846,16 @@ v%1
<h3>Aspetto Prompt</h3>
-
-
+
+ Try restart Sane Break if no soundProva a riavviare Sane Break se non suona
-
-
-
-
+
+
+
+ PlayRiproduci
@@ -873,7 +873,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Pause Brevi</h3>
@@ -883,8 +883,8 @@ v%1
-
-
+
+ minmin
@@ -913,7 +913,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Pause lunghe</h3>
@@ -1024,41 +1024,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ I lettori video, le presentazioni e alcuni giochi impediscono allo schermo di andare in sospensione. Quando attivato, ciò viene conteggiato come attività, quindi la pausa per inattività non verrà attivata mentre sono in esecuzione; quando disattivato, viene conteggiato solo il tuo input effettivo. L'efficacia varia a seconda della piattaforma: completa su Wayland con ext-idle-notify; miglior tentativo su X11, dove viene rilevata solo l'inibizione basata su XScreenSaverSuspend.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ Quando un'app mantiene lo schermo acceso, considerala come attività (ad es. riproduzione video)
+
+
+ Pause on batteryPausa su batteria
-
+ Pause breaks when any of the following program is running:Interrompi pause quando uno dei seguenti programmi è in esecuzione:
-
+ (Write one program name per line)(Scrivi un nome di programma per riga)
-
+ <h3>External Monitors</h3><h3>Monitor esterni</h3>
-
+ Pause when unknown monitor is connectedPausa quando viene collegato un monitor sconosciuto
-
+ Mark currently connected monitors as knownContrassegna i monitor attualmente collegati come noti
-
+ Remove selectedRimuovi selezionati
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1074,10 +1084,10 @@ v%1
-
-
-
-
+
+
+
+ BrowseSfoglia
@@ -1092,62 +1102,62 @@ v%1
Quando attivi la modalità concentrazione dalla barra, le pause seguiranno questo programma invece di quello normale. Usalo per pause più brevi quando devi mantenere la concentrazione.
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Suggerimento</strong>: Usa <i>Sfoglia</i> per selezionare un file audio personalizzato. Una copia del file verrà salvata in modo che possa essere sempre riprodotta.
-
+ Configuration fileFile di configurazione
-
+ Database fileFile del database
-
+ Launch Sane Break at start upAvvia Sane Break all'avvio
-
+ Get the Source CodeOttieni il codice sorgente
-
+ Help Us Translate!Aiutaci a tradurre!
-
+ Revert to Last SavedRipristina ultima impostazione salvata
-
+ LanguageLingua
-
+ Change of language will take effect after app restart.Il cambio della lingua avrà effetto dopo il riavvio dell'app.
-
+ Third-party Libraries LicensesLicenze librerie di terze parti
-
+ DefaultsPredefiniti
-
+ SaveSalva
@@ -1155,9 +1165,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n minuto
@@ -1174,7 +1184,7 @@ v%1
-
+ %n sec%n secondo
@@ -1182,83 +1192,83 @@ v%1
-
+ DisabledDisattivato
-
+ Start next break after middle clicking on tray iconInizia la prossima pausa dopo aver fatto clic col tasto centrale sull'icona nella barra
-
+ Start next break after double clicking on tray iconInizia la prossima pausa dopo aver fatto doppio clic sull'icona nella barra
-
+ SaveSalva
-
+ DiscardScarta
-
+ CancelAnnulla
-
+ Select Sound FileSeleziona file audio
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)File audio (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorErrore
-
+ Failed to save a copy of the selected sound file.Impossibile salvare una copia del file audio selezionato.
-
+ Select Background ImageSeleziona immagine di sfondo
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)File immagine (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Impossibile salvare una copia del file immagine selezionato.
-
+ Setting autostart failedImpostazione avvio automatico fallita
-
+ The preferences have been modified.Le impostazioni sono state modificate.
-
+ Do you want to save your changes?Vuoi salvare i tuoi cambiamenti?
diff --git a/resources/translations/nl.ts b/resources/translations/nl.ts
index ecf61b96..cce046ac 100644
--- a/resources/translations/nl.ts
+++ b/resources/translations/nl.ts
@@ -692,7 +692,7 @@
<h3>Pauzevoorwaarden</h3>
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -707,17 +707,17 @@
</ul>
-
+ Long pause thresholdDrempelwaarde van lange pauze
-
+ Short pause thresholdDrempelwaarde van korte pauze
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -727,7 +727,7 @@ tot vergrendeling van het scherm, 2 minuten nadat de pauze is begonnen. Als de p
dan 2 minuten duurt, zal het scherm sowieso worden vergrendeld.
-
+ Automatic screen lock after break startScherm automatisch vergrendelen tijdens pauze
@@ -736,12 +736,12 @@ dan 2 minuten duurt, zal het scherm sowieso worden vergrendeld.
Verleen toegang tot de toegankelijkheidsinstellingen en herstart het programma
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Helpen met vertalen!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -816,16 +816,16 @@ v%1
Doorzichtigheid van aftelklok
-
-
+
+ Try restart Sane Break if no soundHerstart Sane Break als er geen geluid wordt afgespeeld
-
-
-
-
+
+
+
+ PlayAfspelen
@@ -851,7 +851,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Korte pauzes</h3>
@@ -861,14 +861,14 @@ v%1
-
-
+
+ min min.
-
-
+
+ Bell before breaksBel vóór pauzes
@@ -993,8 +993,8 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat.
Aftellen
-
-
+
+ Bell after breaksBel ná pauzes
@@ -1005,7 +1005,7 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat.
-
+ <h3>Big Breaks</h3><h3>Lange pauzes</h3>
@@ -1020,42 +1020,42 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat.
<h3>Gedeelde opties</h3>
-
+ Pause on batteryOpschorten tijdens werken op accu
-
+ Pause breaks when any of the following program is running:Pauzes opschorten indien een van deze programma's actief is:
-
+ (Write one program name per line)(Eén programma per regel)
-
+ Configuration fileConfiguratiebestand
-
+ Launch Sane Break at start upSane Break automatisch opstarten
-
+ Get the Source CodeBroncode bekijken
-
+ Revert to Last SavedVorig bewaard bestand terugzetten
-
+ LanguageTaal
@@ -1163,10 +1163,10 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat.
-
-
-
-
+
+
+
+ BrowseBladeren
@@ -1181,57 +1181,67 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat.
Wanneer u de concentratiemodus activeert via het systeemvak, worden pauzes volgens dit schema ingepland. Gebruik dit voor kortere pauzes wanneer u geconcentreerd moet blijven.
-
+
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ Videospelers, presentaties en sommige games voorkomen dat het scherm in de slaapstand gaat. Wanneer ingeschakeld, telt dit als activiteit, zodat de pauze bij inactiviteit niet wordt geactiveerd terwijl deze programma's draaien; wanneer uitgeschakeld, telt alleen uw daadwerkelijke invoer. De effectiviteit varieert per platform: volledig ondersteund op ext-idle-notify Wayland; beperkte ondersteuning op X11 waarbij alleen onderdrukking op basis van XScreenSaverSuspend wordt gedetecteerd.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ Wanneer een app het scherm actief houdt, tel dit dan als activiteit (bijv. videoafspeeling)
+
+
+ <h3>External Monitors</h3><h3>Externe monitoren</h3>
-
+ Pause when unknown monitor is connectedPauzeren wanneer een onbekende monitor wordt aangesloten
-
+ Mark currently connected monitors as knownMomenteel aangesloten monitoren markeren als bekend
-
+ Remove selectedGeselecteerde verwijderen
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Tip</strong>: Gebruik <i>Bladeren</i> om een aangepast geluidsbestand te selecteren. Een kopie van het bestand wordt opgeslagen, zodat het altijd kan worden afgespeeld.
-
+ Change of language will take effect after app restart.Herstart het programma om de wijziging toe te passen.
-
+ Database fileDatabasebestand
-
+ Third-party Libraries LicensesLicenties van externe bibliotheken
-
+ Help Us Translate!Help ons vertalen!
-
+ DefaultsStandaardwaarden
-
+ SaveOpslaan
@@ -1239,9 +1249,9 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat.
PreferenceWindow
-
-
-
+
+
+ %n min%n min.
@@ -1258,7 +1268,7 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat.
-
+ %n sec%n sec.
@@ -1266,83 +1276,83 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat.
-
+ DisabledUitgeschakeld
-
+ Start next break after middle clicking on tray iconVolgende pauze starten na middelklikken op systeemvakpictogram
-
+ Start next break after double clicking on tray iconVolgende pauze starten na dubbelklikken op systeemvakpictogram
-
+ SaveOpslaan
-
+ DiscardVerwerpen
-
+ CancelAnnuleren
-
+ Select Sound FileGeluidsbestand selecteren
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Geluidsbestanden (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorFout
-
+ Failed to save a copy of the selected sound file.Kan geen kopie van het geselecteerde geluidsbestand opslaan.
-
+ Select Background ImageAchtergrondafbeelding selecteren
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Afbeeldingsbestanden (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Kan geen kopie van het geselecteerde afbeeldingsbestand opslaan.
-
+ Setting autostart failedAutomatisch opstarten is niet mogelijk
-
+ The preferences have been modified.De instellingen zijn aangepast.
-
+ Do you want to save your changes?Wilt u de instellingen opslaan?
diff --git a/resources/translations/pl.ts b/resources/translations/pl.ts
index 59faf780..1d9d517b 100644
--- a/resources/translations/pl.ts
+++ b/resources/translations/pl.ts
@@ -584,14 +584,14 @@
O Sane Break
-
-
+
+ Bell before breaksDzwonek przed przerwami
-
-
+
+ Bell after breaksDzwonek po przerwach
@@ -780,17 +780,17 @@ Wszystkie kolory są w formacie <code>#AARRGGBB</code>.<h3>Warunki pauzy</h3>
-
+ Long pause thresholdPróg długiej pauzy
-
+ Short pause thresholdPróg krótkiej pauzy
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -798,17 +798,17 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
Załóżmy, że ustawiono to na 2 minuty. Jeśli przerwa jest krótsza niż 2 minuty, ekran zostanie zablokowany 2 minuty po rozpoczęciu przerwy, o ile nie będzie aktywności po przerwie. Jeśli przerwa jest dłuższa niż 2 minuty, ekran zostanie zablokowany bez względu na aktywność.
-
+ Automatic screen lock after break startAutomatyczne blokowanie ekranu po rozpoczęciu przerwy
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Pomóż w tłumaczeniu!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -848,16 +848,16 @@ v%1
<h3>Wygląd przypomnienia</h3>
-
-
+
+ Try restart Sane Break if no soundSpróbuj ponownie uruchomić Sane Break, jeśli nie ma dźwięku
-
-
-
-
+
+
+
+ PlayOdtwórz
@@ -875,7 +875,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Krótkie przerwy</h3>
@@ -885,8 +885,8 @@ v%1
-
-
+
+ minmin
@@ -915,7 +915,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Długie przerwy</h3>
@@ -1026,41 +1026,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ Odtwarzacze wideo, prezentacje i niektóre gry zapobiegają usypianiu ekranu. Gdy ta opcja jest włączona, działanie tych programów liczone jest jako aktywność, więc pauza z powodu bezczynności nie zostanie uruchomiona podczas ich działania; gdy wyłączona, liczy się tylko rzeczywiste wprowadzanie danych przez użytkownika. Skuteczność zależy od platformy: pełna obsługa przy użyciu ext-idle-notify w Wayland; ograniczona w X11, gdzie wykrywana jest tylko blokada oparta na XScreenSaverSuspend.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ Gdy aplikacja utrzymuje ekran w stanie czuwania, traktuj to jako aktywność (np. odtwarzanie wideo)
+
+
+ Pause on batteryWstrzymaj przy baterii
-
+ Pause breaks when any of the following program is running:Wstrzymuj przerwy, gdy którykolwiek z poniższych programów działa:
-
+ (Write one program name per line)(Pisz nazwę jednego programu na linię)
-
+ <h3>External Monitors</h3><h3>Zewnętrzne monitory</h3>
-
+ Pause when unknown monitor is connectedWstrzymaj po podłączeniu nieznanego monitora
-
+ Mark currently connected monitors as knownOznacz obecnie podłączone monitory jako znane
-
+ Remove selectedUsuń zaznaczone
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1076,10 +1086,10 @@ v%1
-
-
-
-
+
+
+
+ BrowsePrzeglądaj
@@ -1094,62 +1104,62 @@ v%1
Po włączeniu trybu skupienia z ikony w zasobniku przerwy będą odbywać się zgodnie z tym harmonogramem. Użyj go do krótszych przerw, gdy musisz zachować skupienie.
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Wskazówka</strong>: Użyj opcji <i>Przeglądaj</i>, aby wybrać niestandardowy plik dźwiękowy. Kopia pliku zostanie zapisana, aby można było ją zawsze odtworzyć.
-
+ Configuration filePlik konfiguracyjny
-
+ Database filePlik bazy danych
-
+ Launch Sane Break at start upUruchamiaj Sane Break przy starcie
-
+ Get the Source CodePobierz kod źródłowy
-
+ Help Us Translate!Pomóż nam przetłumaczyć!
-
+ Revert to Last SavedCofnij do ostatnio zapisanego
-
+ LanguageJęzyk
-
+ Change of language will take effect after app restart.Zmiana języka wstępuje w życie po ponownym uruchomieniu aplikacji.
-
+ Third-party Libraries LicensesLicencje bibliotek第三方
-
+ DefaultsDomyślnie
-
+ SaveZapisz
@@ -1157,9 +1167,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n minuta
@@ -1178,7 +1188,7 @@ v%1
-
+ %n sec%n sekunda
@@ -1187,83 +1197,83 @@ v%1
-
+ DisabledWyłączone
-
+ Start next break after middle clicking on tray iconRozpocznij następną przerwę po kliknięciu środkowym przyciskiem na ikonie zasobnika
-
+ Start next break after double clicking on tray iconRozpocznij następną przerwę po podwójnym kliknięciu na ikonie zasobnika
-
+ SaveZapisz
-
+ DiscardOdrzuć
-
+ CancelAnuluj
-
+ Select Sound FileWybierz plik dźwiękowy
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Pliki dźwiękowe (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorBłąd
-
+ Failed to save a copy of the selected sound file.Nie udało się zapisać kopii wybranego pliku dźwiękowego.
-
+ Select Background ImageWybierz obraz tła
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Pliki obrazów (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Nie udało się zapisać kopii wybranego pliku obrazu.
-
+ Setting autostart failedUstawienie autostartu nie powiodło się
-
+ The preferences have been modified.Preferencje zostały zmodyfikowane.
-
+ Do you want to save your changes?Czy chcesz zapisać zmiany?
diff --git a/resources/translations/ru.ts b/resources/translations/ru.ts
index 2a62899e..6e4081ba 100644
--- a/resources/translations/ru.ts
+++ b/resources/translations/ru.ts
@@ -584,14 +584,14 @@
О Программе
-
-
+
+ Bell before breaksСигнал перед перерывами
-
-
+
+ Bell after breaksСигнал после перерывов
@@ -780,17 +780,17 @@ All color are in <code>#AARRGGBB</code> format.
<h3>Условия паузы</h3>
-
+ Long pause thresholdПорог длинной паузы
-
+ Short pause thresholdПорог короткой паузы
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -798,7 +798,7 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
Предположим, вы настроили это на 2 минуты. Если перерыв короче 2 минут, экран заблокируется через 2 минуты после начала перерыва, при условии отсутствия активности после перерыва. Если перерыв дольше 2 минут, экран будет заблокирован независимо от этого.
-
+ Automatic screen lock after break startАвтоматическая блокировка экрана после начала перерыва
@@ -807,12 +807,12 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
Пожалуйста, предоставьте разрешение на доступность и перезапустите приложение, чтобы использовать автоматическую блокировку экрана
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Помогите перевести!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -872,16 +872,16 @@ v%1
Быстрее
-
-
+
+ Try restart Sane Break if no soundПопробуйте перезапустить Sane Break, если нет звука
-
-
-
-
+
+
+
+ PlayВоспроизвести
@@ -899,7 +899,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Короткие перерывы</h3>
@@ -909,8 +909,8 @@ v%1
-
-
+
+ minмин
@@ -939,7 +939,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Длинные перерывы</h3>
@@ -1050,41 +1050,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ Видеоплееры, презентации и некоторые игры предотвращают переход экрана в спящий режим. Если эта функция включена, это считается активностью, поэтому пауза при бездействии не сработает во время их работы; если выключена, учитывается только ваш ввод. Эффективность зависит от платформы: полная поддержка через ext-idle-notify в Wayland; частичная поддержка в X11, где обнаруживается только блокировка на основе XScreenSaverSuspend.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ Считать активность приложения, поддерживающего экран включенным (например, воспроизведение видео)
+
+
+ Pause on batteryПауза при питании от батареи
-
+ Pause breaks when any of the following program is running:Приостановить перерывы, когда один из следующих программ запущен:
-
+ (Write one program name per line)(Введите одно имя программы на строку)
-
+ <h3>External Monitors</h3><h3>Внешние мониторы</h3>
-
+ Pause when unknown monitor is connectedПриостановить при подключении неизвестного монитора
-
+ Mark currently connected monitors as knownПометить текущие подключённые мониторы как известные
-
+ Remove selectedУдалить выбранное
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1100,10 +1110,10 @@ v%1
-
-
-
-
+
+
+
+ BrowseОбзор
@@ -1118,62 +1128,62 @@ v%1
Когда вы активируете режим фокуса из трея, перерывы будут следовать этому графику. Используйте его для более коротких перерывов, когда вам нужно сохранять концентрацию.
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Совет</strong>: Используйте <i>Обзор</i>, чтобы выбрать пользовательский звуковой файл. Копия файла будет сохранена, чтобы его можно было воспроизвести в любое время.
-
+ Configuration fileКонфигурационный файл
-
+ Database fileФайл базы данных
-
+ Launch Sane Break at start upЗапускать Sane Break при старте системы
-
+ Get the Source CodeПросмотреть исходный код
-
+ Help Us Translate!Помогите нам с переводом!
-
+ Revert to Last SavedВернуться к последнему сохраненному
-
+ LanguageЯзык
-
+ Change of language will take effect after app restart.Изменение языка вступит в силу после перезапуска приложения.
-
+ Third-party Libraries LicensesЛицензии сторонних библиотек
-
+ DefaultsПо умолчанию
-
+ SaveСохранить
@@ -1181,9 +1191,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n мин
@@ -1202,7 +1212,7 @@ v%1
-
+ %n sec%n сек
@@ -1211,83 +1221,83 @@ v%1
-
+ DisabledОтключено
-
+ Setting autostart failedНастройка автозапуска не удалась
-
+ Start next break after middle clicking on tray iconНачать следующий перерыв после среднего клика на значке в трее
-
+ Start next break after double clicking on tray iconНачать следующий перерыв после двойного клика на значке в трее
-
+ SaveСохранить
-
+ DiscardОтменить
-
+ CancelОтмена
-
+ Select Sound FileВыбрать звуковой файл
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Звуковые файлы (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorОшибка
-
+ Failed to save a copy of the selected sound file.Не удалось сохранить копию выбранного звукового файла.
-
+ Select Background ImageВыбрать фоновое изображение
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Файлы изображений (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Не удалось сохранить копию выбранного изображения.
-
+ The preferences have been modified.Настройки были изменены.
-
+ Do you want to save your changes?Хотите сохранить изменения?
diff --git a/resources/translations/sv.ts b/resources/translations/sv.ts
index 1e2a10e0..60fa1013 100644
--- a/resources/translations/sv.ts
+++ b/resources/translations/sv.ts
@@ -584,14 +584,14 @@
Om
-
-
+
+ Bell before breaksLjudsignal före raster
-
-
+
+ Bell after breaksLjudsignal efter raster
@@ -776,17 +776,17 @@ Alla färger är i formatet <code>#AARRGGBB</code>.
<h3>Pausvillkor</h3>
-
+ Long pause thresholdLång rastgräns
-
+ Short pause thresholdKort pausgräns
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -796,17 +796,17 @@ låses skärmen 2 minuter efter att rasten har börjat, förutsatt att det inte
aktivitet efter rasten. Om rasten är längre än 2 minuter låses skärmen oavsett.
-
+ Automatic screen lock after break startAutomatisk skärmlåsning efter raststart
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Hjälp till att översätta!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -846,16 +846,16 @@ v%1
<h3>Promptutseende</h3>
-
-
+
+ Try restart Sane Break if no soundProva att starta om Sane Break om det inte hörs något ljud
-
-
-
-
+
+
+
+ PlaySpela
@@ -873,7 +873,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Korta raster</h3>
@@ -883,8 +883,8 @@ v%1
-
-
+
+ min min
@@ -913,7 +913,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Långa raster</h3>
@@ -1024,41 +1024,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ Videospelare, presentationer och vissa spel förhindrar att skärmen går i viloläge. När detta är påslaget räknas det som aktivitet, så paus vid overksamhet utlöses inte medan de körs; när det är avstängt räknas endast din faktiska inmatning. Effektiviteten varierar beroende på plattform: fullt stöd via ext-idle-notify på Wayland; bästa möjliga uppskattning på X11 där endast inaktivering baserad på XScreenSaverSuspend detekteras.
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ När en app håller skärmen vaken, räkna det som aktivitet (t.ex. videouppspelning)
+
+
+ Pause on batteryPaus på batteri
-
+ Pause breaks when any of the following program is running:Pausar raster när något av följande program körs:
-
+ (Write one program name per line)(Skriv ett programnamn per rad)
-
+ <h3>External Monitors</h3><h3>Externa skärmar</h3>
-
+ Pause when unknown monitor is connectedPausa när en okänd skärm ansluts
-
+ Mark currently connected monitors as knownMarkera aktuellt anslutna skärmar som kända
-
+ Remove selectedTa bort markerade
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1074,10 +1084,10 @@ v%1
-
-
-
-
+
+
+
+ BrowseBläddra
@@ -1092,62 +1102,62 @@ v%1
När du aktiverar fokusläget från aktivitetsfältet följer raster istället detta schema. Använd det för kortare raster när du behöver hålla fokus.
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Tips</strong>: Använd <i>Bläddra</i> för att välja en anpassad ljudfil. En kopia av filen sparas så att den alltid kan spelas upp.
-
+ Configuration fileKonfigurationsfil
-
+ Database fileDatabasfil
-
+ Launch Sane Break at start upStarta Sane Break vid uppstart
-
+ Get the Source CodeHämta källkoden
-
+ Help Us Translate!Hjälp oss att översätta!
-
+ Revert to Last SavedÅtergå till senast sparade
-
+ LanguageSpråk
-
+ Change of language will take effect after app restart.Språksändringen träder i kraft efter att appen startats om.
-
+ Third-party Libraries LicensesLicenser för tredjepartsbibliotek
-
+ DefaultsStandard
-
+ SaveSpara
@@ -1155,9 +1165,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n min
@@ -1174,7 +1184,7 @@ v%1
-
+ %n sec%n s
@@ -1182,83 +1192,83 @@ v%1
-
+ DisabledInaktiverad
-
+ Start next break after middle clicking on tray iconStarta nästa rast efter att ha klickat med mittknappen på ikonen i aktivitetsfältet
-
+ Start next break after double clicking on tray iconStarta nästa rast efter att ha dubbelklickat på ikonen i aktivitetsfältet
-
+ SaveSpara
-
+ DiscardFörkasta
-
+ CancelAvbryt
-
+ Select Sound FileVälj ljudfil
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Ljudfiler (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorFel
-
+ Failed to save a copy of the selected sound file.Det gick inte att spara en kopia av den valda ljudfilen.
-
+ Select Background ImageVälj bakgrundsbild
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Bilddfiler (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Det gick inte att spara en kopia av den valda bildfilen.
-
+ Setting autostart failedInställning av autostart misslyckades
-
+ The preferences have been modified.Inställningarna har ändrats.
-
+ Do you want to save your changes?Vill du spara dina ändringar?
diff --git a/resources/translations/uk.ts b/resources/translations/uk.ts
index b54bf068..49ea39ad 100644
--- a/resources/translations/uk.ts
+++ b/resources/translations/uk.ts
@@ -568,14 +568,14 @@
Про
-
-
+
+ Bell before breaksДзвінок перед перервою
-
-
+
+ Bell after breaksДзвінок після перерви
@@ -766,22 +766,22 @@ All color are in <code>#AARRGGBB</code> format.
<h3>Умови припинення</h3>
-
+ Long pause thresholdПоріг для довгого припинення
-
+ Short pause thresholdПоріг для короткого припинення
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>Порада</strong>: Використовуйте <i>Огляд</i>, щоб вибрати власний звуковий файл. Копія файлу буде збережена, щоб його завжди можна було відтворити.
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -792,17 +792,17 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
заблоковано у будь-якому разі.
-
+ Automatic screen lock after break startАвтоматично блокувати екран після початку перерви
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">Допоможіть з перекладом!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -838,16 +838,16 @@ v%1
<h3>Вигляд запрошення</h3>
-
-
+
+ Try restart Sane Break if no soundЯкщо немає звуку, спробуйте перезапустити Sane Break
-
-
-
-
+
+
+
+ PlayВідтворити
@@ -865,7 +865,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>Короткі перерви</h3>
@@ -875,8 +875,8 @@ v%1
-
-
+
+ min хв
@@ -901,7 +901,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>Довгі перерви</h3>
@@ -1008,41 +1008,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+
+
+
+ Pause on batteryПризупиняти під час живлення від акумулятора
-
+ Pause breaks when any of the following program is running:Призупинити перерви, якщо працює будь-яка з таких програм:
-
+ (Write one program name per line)(Одна програма на рядок)
-
+ <h3>External Monitors</h3><h3>Зовнішні монітори</h3>
-
+ Pause when unknown monitor is connectedПризупиняти при підключенні невідомого монітора
-
+ Mark currently connected monitors as knownПозначити з'єднані монітори як відомі
-
+ Remove selectedВидалити вибране
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1058,65 +1068,65 @@ v%1
-
-
-
-
+
+
+
+ BrowseОгляд
-
+ Configuration fileФайл параметрів
-
+ Database fileФайл бази даних
-
+ Launch Sane Break at start upЗапускати Sane Break на початку сеансу
-
+ Get the Source CodeОтримати джерельний код
-
+ Help Us Translate!Допоможіть нам з перекладом!
-
+ Revert to Last SavedПовернути збережені
-
+ LanguageМова
-
+ Change of language will take effect after app restart.Зміна мови набере чинності після перезапускання застосунку.
-
+ Third-party Libraries LicensesЛіцензії для бібліотек від третіх сторін
-
+ DefaultsТипові значення
-
+ SaveЗберегти
@@ -1124,9 +1134,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n хв
@@ -1145,7 +1155,7 @@ v%1
-
+ %n sec%n сек
@@ -1154,83 +1164,83 @@ v%1
-
+ DisabledВимкнено
-
+ Start next break after middle clicking on tray iconРозпочати наступну перерву після натискання середньої кнопки миші на іконці в системній панелі
-
+ Start next break after double clicking on tray iconРозпочати наступну перерву після подвійного натискання на іконці в системній панелі
-
+ SaveЗберегти
-
+ DiscardСкинути
-
+ CancelСкасувати
-
+ Select Sound FileВибрати звуковий файл
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)Звукові файли (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ ErrorПомилка
-
+ Failed to save a copy of the selected sound file.Не вдалося зберегти копію вибраного звукового файлу.
-
+ Select Background ImageВибрати зображення для тла
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)Файли зображень (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.Не вдалося зберегти копію вибраного файлу зображення.
-
+ Setting autostart failedНалаштування автозапуску зазнало невдачі
-
+ The preferences have been modified.Параметри було змінено.
-
+ Do you want to save your changes?Бажаєте зберегти зміни?
diff --git a/resources/translations/zh_CN.ts b/resources/translations/zh_CN.ts
index 288ff8d7..b78fc7cb 100644
--- a/resources/translations/zh_CN.ts
+++ b/resources/translations/zh_CN.ts
@@ -568,14 +568,14 @@
关于
-
-
+
+ Bell before breaks休息前提示音
-
-
+
+ Bell after breaks休息后提示音
@@ -766,22 +766,22 @@ All color are in <code>#AARRGGBB</code> format.
<h3>暂停条件</h3>
-
+ Long pause threshold长时间暂停阈值
-
+ Short pause threshold短时间暂停阈值
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>提示</strong>: 使用 <i>浏览</i> 来选取自定义的声音文件。文件会被复制一份以保证可以被播放。
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -791,17 +791,17 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
定。如果休息持续超过 2 分钟,则屏幕必然会自动锁定。
-
+ Automatic screen lock after break start休息开始一段时间后自动锁屏
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">帮我们翻译!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -837,16 +837,16 @@ v%1
<h3>提示小窗外观</h3>
-
-
+
+ Try restart Sane Break if no sound如果没有声音,请尝试重启 Sane Break
-
-
-
-
+
+
+
+ Play播放
@@ -864,7 +864,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>小休息</h3>
@@ -874,8 +874,8 @@ v%1
-
-
+
+ min 分钟
@@ -900,7 +900,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>大休息</h3>
@@ -1007,41 +1007,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ 视频播放器、演示文稿和某些游戏会阻止屏幕休眠。启用时,这些情况会被视为活动,因此在它们运行时不会触发空闲暂停;禁用时,仅将您的实际输入视为活动。效果因平台而异:在支持 ext-idle-notify 的 Wayland 上效果完整;在 X11 上尽力而为,仅能检测基于 XScreenSaverSuspend 的抑制。
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ 当应用保持屏幕唤醒时,将其视为活动(例如视频播放)
+
+
+ Pause on battery电池供电时暂停
-
+ Pause breaks when any of the following program is running:当以下程序运行时暂停休息提示:
-
+ (Write one program name per line)(每一行写一个程序名)
-
+ <h3>External Monitors</h3><h3>外接显示器</h3>
-
+ Pause when unknown monitor is connected在连接未知显示器时暂停
-
+ Mark currently connected monitors as known将当前连接的显示器标记为已知
-
+ Remove selected删除选中
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1057,65 +1067,65 @@ v%1
-
-
-
-
+
+
+
+ Browse浏览
-
+ Configuration file配置文件
-
+ Database file数据库文件
-
+ Launch Sane Break at start up开机自动启动 Sane Break
-
+ Get the Source Code获取源代码
-
+ Help Us Translate!帮助我们翻译!
-
+ Revert to Last Saved恢复上次设置
-
+ Language语言
-
+ Change of language will take effect after app restart.改变语言将在重启应用后生效。
-
+ Third-party Libraries Licenses第三方库许可
-
+ Defaults恢复默认
-
+ Save保存
@@ -1123,9 +1133,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n 分钟
@@ -1140,90 +1150,90 @@ v%1
-
+ %n sec%n 秒
-
+ Disabled禁用
-
+ Start next break after middle clicking on tray icon在中键托盘图标后,立刻开始下一次休息
-
+ Start next break after double clicking on tray icon在双击托盘图标后,立刻开始下一次休息
-
+ Save保存
-
+ Discard放弃
-
+ Cancel取消
-
+ Select Sound File选取声音文件
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)声音文件 (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ Error错误
-
+ Failed to save a copy of the selected sound file.保存所选的声音文件失败。
-
+ Select Background Image选择背景图片
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)图片文件 (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.保存所选的图片文件失败。
-
+ Setting autostart failed设置开机自启失败
-
+ The preferences have been modified.偏好设置已被修改。
-
+ Do you want to save your changes?是否保存修改?
diff --git a/resources/translations/zh_TW.ts b/resources/translations/zh_TW.ts
index bbd97b64..929b3b82 100644
--- a/resources/translations/zh_TW.ts
+++ b/resources/translations/zh_TW.ts
@@ -568,14 +568,14 @@
關於
-
-
+
+ Bell before breaks休息前提示音
-
-
+
+ Bell after breaks休息後提示音
@@ -766,22 +766,22 @@ All color are in <code>#AARRGGBB</code> format.
<h3>暫停條件</h3>
-
+ Long pause threshold長時間暫停閾值
-
+ Short pause threshold短時間暫停閾值
-
+ <strong>Tip</strong>: Use <i>Browse</i> to select a custom sound file. A copy of the file will be saved so it can always be played.<strong>提示</strong>: 使用 <i>瀏覽</i> 來選取自定義的聲音文件。文件會被複制一份以保證可以被播放。
-
+ Let's say you've configured it to 2 minutes. If the break is shorter than 2 minutes, the
screen will lock 2 minutes after the break starts, provided there is no activity after the
break. If the break is longer than 2 minutes, the screen will be locked regardless.
@@ -791,17 +791,17 @@ break. If the break is longer than 2 minutes, the screen will be locked regardle
定。如果休息持續超過 2 分鐘,則屏幕必然會自動鎖定。
-
+ Automatic screen lock after break start休息開始一段時間後自動鎖屏
-
+ <a href="https://hosted.weblate.org/engage/sane-break/">Help translate!</a><a href="https://hosted.weblate.org/engage/sane-break/">幫我們翻譯!</a>
-
+ <div>
<span style="font-size: 26px; font-weight: bold">Sane Break</span>
v%1
@@ -837,16 +837,16 @@ v%1
<h3>提示小窗外觀</h3>
-
-
+
+ Try restart Sane Break if no sound如果沒有聲音,請嘗試重啟 Sane Break
-
-
-
-
+
+
+
+ Play播放
@@ -864,7 +864,7 @@ v%1
-
+ <h3>Small Breaks</h3><h3>小休息</h3>
@@ -874,8 +874,8 @@ v%1
-
-
+
+ min 分鐘
@@ -900,7 +900,7 @@ v%1
-
+ <h3>Big Breaks</h3><h3>大休息</h3>
@@ -1007,41 +1007,51 @@ v%1
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+ 視頻播放器、演示文稿和某些遊戲會阻止屏幕休眠。啟用時,這些情況會被視為活動,因此在它們運行時不會觸發空閒暫停;禁用時,僅將您的實際輸入視為活動。效果因平臺而異:在支持 ext-idle-notify 的 Wayland 上效果完整;在 X11 上盡力而為,僅能檢測基於 XScreenSaverSuspend 的抑制。
+
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+ 當應用保持屏幕喚醒時,將其視為活動(例如視頻播放)
+
+
+ Pause on battery電池供電時暫停
-
+ Pause breaks when any of the following program is running:當以下程序運行時暫停休息提示:
-
+ (Write one program name per line)(每一行寫一個程序名)
-
+ <h3>External Monitors</h3><h3>外接顯示器</h3>
-
+ Pause when unknown monitor is connected在連接未知顯示器時暫停
-
+ Mark currently connected monitors as known將當前連接的顯示器標記為已知
-
+ Remove selected刪除選中
-
+ <h3>Reset Break Schedule After Pause</h3>
<p>Sane Break will adjust the break schedule after pausing:</p>
<ul>
@@ -1057,65 +1067,65 @@ v%1
-
-
-
-
+
+
+
+ Browse瀏覽
-
+ Configuration file配置文件
-
+ Database file數據庫文件
-
+ Launch Sane Break at start up開機自動啟動 Sane Break
-
+ Get the Source Code獲取源代碼
-
+ Help Us Translate!幫助我們翻譯!
-
+ Revert to Last Saved恢復上次設置
-
+ Language語言
-
+ Change of language will take effect after app restart.改變語言將在重啟應用後生效。
-
+ Third-party Libraries Licenses第三方庫許可
-
+ Defaults恢復默認
-
+ Save保存
@@ -1123,9 +1133,9 @@ v%1
PreferenceWindow
-
-
-
+
+
+ %n min%n 分鐘
@@ -1140,90 +1150,90 @@ v%1
-
+ %n sec%n 秒
-
+ Disabled禁用
-
+ Start next break after middle clicking on tray icon在中鍵托盤圖標後,立刻開始下一次休息
-
+ Start next break after double clicking on tray icon在雙擊托盤圖標後,立刻開始下一次休息
-
+ Save保存
-
+ Discard放棄
-
+ Cancel取消
-
+ Select Sound File選取聲音文件
-
+ Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a)聲音文件 (*.mp3 *.wav *.ogg *.flac *.m4a)
-
-
+
+ Error錯誤
-
+ Failed to save a copy of the selected sound file.保存所選的聲音文件失敗。
-
+ Select Background Image選擇背景圖片
-
+ Image Files (*.png *.jpg *.jpeg *.bmp *.webp)圖片文件 (*.png *.jpg *.jpeg *.bmp *.webp)
-
+ Failed to save a copy of the selected image file.保存所選的圖片文件失敗。
-
+ Setting autostart failed設置開機自啟失敗
-
+ The preferences have been modified.偏好設置已被修改。
-
+ Do you want to save your changes?是否保存修改?
diff --git a/screenshots/pref-pause.png b/screenshots/pref-pause.png
index e6673d29..78266471 100644
Binary files a/screenshots/pref-pause.png and b/screenshots/pref-pause.png differ
diff --git a/src/app/pref-window.cpp b/src/app/pref-window.cpp
index 9eed717d..ca6ffa53 100644
--- a/src/app/pref-window.cpp
+++ b/src/app/pref-window.cpp
@@ -372,6 +372,9 @@ PreferenceWindow::PreferenceWindow(SanePreferences* preferences, QWidget* parent
controllers->add(PrefGroup::Pause,
new PrefController(ui->pauseOnIdleBox,
preferences->pauseOnIdleFor, 60));
+ controllers->add(PrefGroup::Pause, new PrefController(
+ ui->treatInhibitorAsActivityCheck,
+ preferences->treatInhibitorAsActivity));
connect(controllers->add(PrefGroup::Pause,
new PrefController(
ui->resetBreakBox, preferences->resetAfterPause, 60)),
diff --git a/src/app/pref-window.ui b/src/app/pref-window.ui
index 885a9d77..5e604b85 100644
--- a/src/app/pref-window.ui
+++ b/src/app/pref-window.ui
@@ -1530,6 +1530,16 @@ All color are in <code>#AARRGGBB</code> format.
+
+
+
+ Video players, presentations, and some games prevent the screen from sleeping. When on, that counts as activity so the idle pause won't trigger while they run; when off, only your actual input counts. Effectiveness varies by platform: full on ext-idle-notify Wayland; best-effort on X11 where only XScreenSaverSuspend-based inhibition is detected.
+
+
+ When an app keeps the screen awake, count it as activity (e.g. video playback)
+
+
+
diff --git a/src/core/app-states.cpp b/src/core/app-states.cpp
index cd5cab8b..51d8c387 100644
--- a/src/core/app-states.cpp
+++ b/src/core/app-states.cpp
@@ -15,6 +15,7 @@
#include "core/app-data.h"
#include "core/break-windows.h"
#include "core/flags.h"
+#include "core/idle-time.h"
namespace {
@@ -146,11 +147,20 @@ void AppContext::checkBreakReadiness() {
if (secondsToNextBreak <= 0) transitionTo(std::make_unique());
}
+void AppContext::applyIdleMode() {
+ idleTimer->setIdleMode(preferences->treatInhibitorAsActivity->get()
+ ? IdleMode::InhibitorAware
+ : IdleMode::InputOnly);
+}
+
void AppStateNormal::enter(AppContext* app) {
app->openCurrentSpan("normal");
// Use low accuracy (5s) for idle detection in normal state as it can last a long time
app->idleTimer->setWatchAccuracy(5000);
app->idleTimer->setMinIdleTime(app->preferences->pauseOnIdleFor->get() * 1000);
+ // Restore the user's preferred idle mode (inhibitor-aware idle pause suppression
+ // belongs here, not during breaks which override it to InputOnly).
+ app->applyIdleMode();
}
void AppStateNormal::exit(AppContext* app) {
app->closeCurrentSpan();
@@ -309,6 +319,11 @@ void AppStateBreak::enter(AppContext* app) {
// transitions
app->idleTimer->setWatchAccuracy(500);
app->idleTimer->setMinIdleTime(2000);
+ // Breaks always use raw input idle (InputOnly), ignoring idle inhibitors. A
+ // background video player holding an inhibitor must not make the break think the
+ // user is active — we need to detect actual presence to drive phase transitions
+ // (prompt ↔ full-screen), force-break escalation, and post-break auto-close.
+ app->idleTimer->setIdleMode(IdleMode::InputOnly);
app->breakWindows->create(app->data->breakType(), app->preferences,
data->totalSeconds(),
app->data->schedule().isBreakExtendedByPostpone());
@@ -517,6 +532,7 @@ void AppStateMeeting::enter(AppContext* app) {
app->data->schedule().resetSecondsToNextBreak(app->data->currentBreakConfig());
app->idleTimer->setWatchAccuracy(5000);
app->idleTimer->setMinIdleTime(app->preferences->pauseOnIdleFor->get() * 1000);
+ app->applyIdleMode();
}
void AppStateMeeting::exit(AppContext* app) {
diff --git a/src/core/app-states.h b/src/core/app-states.h
index 1939c32a..838a8023 100644
--- a/src/core/app-states.h
+++ b/src/core/app-states.h
@@ -100,6 +100,10 @@ class AppContext : public QObject {
void transitionTo(std::unique_ptr state);
void exitCurrentState();
void checkBreakReadiness();
+ // Apply the user's preferred idle mode (treatInhibitorAsActivity pref → IdleMode)
+ // to the idle timer. Called on start, on preference change, and by states that
+ // resume normal idle measurement after a break (which overrides it to InputOnly).
+ void applyIdleMode();
signals:
void appStateChanged();
diff --git a/src/core/app.cpp b/src/core/app.cpp
index 5a3ab07a..ff5567f2 100644
--- a/src/core/app.cpp
+++ b/src/core/app.cpp
@@ -68,6 +68,8 @@ AbstractApp::AbstractApp(const AppDependencies& deps, QObject* parent)
connect(preferences->pauseOnBattery, &SettingWithSignal::changed, this,
&AbstractApp::onBatterySettingChange);
+ connect(preferences->treatInhibitorAsActivity, &SettingWithSignal::changed, this,
+ [this]() { applyIdleMode(); });
connect(preferences->smallEvery, &SettingWithSignal::changed, this, [this]() {
if (!this->data->focus().isActive()) {
this->data->schedule().resetSecondsToNextBreak(this->data->currentBreakConfig());
@@ -85,6 +87,9 @@ AbstractApp::AbstractApp(const AppDependencies& deps, QObject* parent)
void AbstractApp::start() {
db->logEvent("app::start");
transitionTo(std::make_unique());
+ // Apply the idle mode before watching so the correct notification request /
+ // wrapper is active first.
+ applyIdleMode();
idleTimer->startWatching();
m_countDownTimer->start();
m_systemMonitor->start();
diff --git a/src/core/idle-time.h b/src/core/idle-time.h
index 483c753b..eb07c8b9 100644
--- a/src/core/idle-time.h
+++ b/src/core/idle-time.h
@@ -1,5 +1,5 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
@@ -22,6 +22,15 @@
#define COREIDLE_EXPORT
#endif
+// How idle is measured. The enum describes the *mechanism*; the user-facing
+// policy is a single bool preference mapped to this enum in app.cpp.
+// InputOnly - input-only idle (Wayland v2; polling backends use the raw
+// reader). Pause still applies during a video (old behavior).
+// InhibitorAware - inhibitor-aware idle (Wayland v1; polling backends wrap the
+// raw reader so idle is held at 0 while an inhibitor is
+// active). Don't pause during video (default).
+enum class IdleMode { InputOnly, InhibitorAware };
+
class COREIDLE_EXPORT SystemIdleTime : public QObject {
Q_OBJECT
public:
@@ -32,6 +41,11 @@ class COREIDLE_EXPORT SystemIdleTime : public QObject {
int minIdleTime() { return m_minIdleTime; }
virtual void setWatchAccuracy(int accuracy) = 0;
virtual void setMinIdleTime(int idleTime) = 0;
+ // Select how idle is measured. Default no-op just records the mode; backends
+ // that support inhibitor-aware idle (Wayland v1/v2 switch, or polling backends
+ // with an inhibitor monitor wired in) override this.
+ virtual void setIdleMode(IdleMode mode) { m_idleMode = mode; }
+ IdleMode idleMode() const { return m_idleMode; }
bool isIdle() { return m_isIdle; }
signals:
void idleStart();
@@ -41,4 +55,5 @@ class COREIDLE_EXPORT SystemIdleTime : public QObject {
bool m_isIdle = false;
int m_watchAccuracy = 500; // How often we watch idle time (ms)
int m_minIdleTime = 2000; // How long will we consider idle (ms)
+ IdleMode m_idleMode = IdleMode::InhibitorAware; // matches pref default (on)
};
diff --git a/src/core/preferences.cpp b/src/core/preferences.cpp
index fb713bd7..76afa3db 100644
--- a/src/core/preferences.cpp
+++ b/src/core/preferences.cpp
@@ -95,6 +95,8 @@ SanePreferences::SanePreferences(QSettings* settings, QObject* parent)
resetAfterPause = new Setting(settings, "pause/reset-after", 120);
resetCycleAfterPause = new Setting(settings, "pause/reset-cycle-after", 300);
pauseOnBattery = new Setting(settings, "pause/on-battery", false);
+ treatInhibitorAsActivity =
+ new Setting(settings, "pause/treat-inhibitor-as-activity", true);
programsToMonitor =
new Setting(settings, "pause/programs-to-monitor", QStringList());
pauseOnUnknownMonitor =
diff --git a/src/core/preferences.h b/src/core/preferences.h
index 038e632d..8077dc70 100644
--- a/src/core/preferences.h
+++ b/src/core/preferences.h
@@ -133,6 +133,10 @@ class SanePreferences : public QObject {
Setting* resetAfterPause;
Setting* resetCycleAfterPause;
Setting* pauseOnBattery;
+ // When true (default), an app keeping the screen awake (video player,
+ // presentation) counts as activity and the idle pause won't trigger.
+ // Mapped to IdleMode in app.cpp.
+ Setting* treatInhibitorAsActivity;
Setting* programsToMonitor;
Setting* pauseOnUnknownMonitor;
Setting* knownMonitors;
diff --git a/src/idle/CMakeLists.txt b/src/idle/CMakeLists.txt
index 63492eb2..893b65f9 100644
--- a/src/idle/CMakeLists.txt
+++ b/src/idle/CMakeLists.txt
@@ -1,16 +1,30 @@
find_package(Qt6 REQUIRED COMPONENTS Widgets)
add_library(
- sane-idle STATIC factory.cpp factory.h idle-interface.h read-based-idle.cpp
- read-based-idle.h
+ sane-idle STATIC
+ factory.cpp
+ factory.h
+ idle-interface.h
+ idle-reader.cpp
+ idle-reader.h
+ read-based-idle.cpp
+ read-based-idle.h
)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_package(Qt6 REQUIRED COMPONENTS DBus)
- target_sources(sane-idle PRIVATE linux/factory.h linux/factory.cpp)
+ target_sources(
+ sane-idle
+ PRIVATE linux/factory.h linux/factory.cpp linux/inhibitor-proxy-idle.h
+ linux/inhibitor-proxy-idle.cpp linux/linux-idle-inhibitor.h
+ linux/linux-idle-inhibitor.cpp
+ )
target_link_libraries(sane-idle PRIVATE Qt6::DBus)
add_subdirectory(linux)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
- target_sources(sane-idle PRIVATE windows-idle.h)
+ target_sources(
+ sane-idle PRIVATE windows-idle.h windows-inhibitor.h windows-inhibitor.cpp
+ )
+ target_link_libraries(sane-idle PRIVATE PowrProf)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- target_sources(sane-idle PRIVATE macos-idle.h)
+ target_sources(sane-idle PRIVATE macos-idle.h macos-inhibitor.h macos-inhibitor.cpp)
endif()
target_link_libraries(sane-idle PUBLIC Qt6::Widgets)
diff --git a/src/idle/factory.cpp b/src/idle/factory.cpp
index 8d453b00..20a83574 100644
--- a/src/idle/factory.cpp
+++ b/src/idle/factory.cpp
@@ -1,5 +1,5 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#include "factory.h"
@@ -16,18 +16,25 @@
#include "linux/factory.h"
#elif defined Q_OS_MACOS
#include "macos-idle.h"
+#include "macos-inhibitor.h"
#include "read-based-idle.h"
#elif defined Q_OS_WIN
#include "read-based-idle.h"
#include "windows-idle.h"
+#include "windows-inhibitor.h"
#endif
SystemIdleTime* createIdleTimer(QObject* parent) {
#ifdef Q_OS_LINUX
return createLinuxIdleTimer(parent);
#elif defined Q_OS_MACOS
- return new ReadBasedIdleTime(parent, macosIdleTime);
+ auto* rbt = new ReadBasedIdleTime(parent, macosIdleTime);
+ auto* monitor = new MacosInhibitor(rbt);
+ rbt->setInhibitor([monitor]() { return monitor->isDisplayInhibited(); });
+ return rbt;
#elif defined Q_OS_WIN
- return new ReadBasedIdleTime(parent, windowsIdleTime);
+ auto* rbt = new ReadBasedIdleTime(parent, windowsIdleTime);
+ rbt->setInhibitor(windowsDisplayInhibited);
+ return rbt;
#endif
}
diff --git a/src/idle/idle-interface.h b/src/idle/idle-interface.h
index 00f1cd18..d5792a3c 100644
--- a/src/idle/idle-interface.h
+++ b/src/idle/idle-interface.h
@@ -1,5 +1,5 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
@@ -19,8 +19,12 @@ Q_DECLARE_INTERFACE(IdleTimeInterface, IdleTimeInterface_iid)
class IdleTimeReaderInterface : public QObject {
public:
virtual int read() = 0;
+ // Whether an idle/display inhibitor is currently active, as observed alongside
+ // the idle read. Default false; X11 overrides it (XScreenSaverQueryInfo.state ==
+ // ScreenSaverDisabled) since inhibition is free in the same call as idle.
+ virtual bool isInhibited() { return false; }
};
#define IdleTimeReaderInterface_iid \
- "io.github.AllanChain.sane-break.IdleTimeReaderInterface/1.0"
+ "io.github.AllanChain.sane-break.IdleTimeReaderInterface/1.1"
Q_DECLARE_INTERFACE(IdleTimeReaderInterface, IdleTimeReaderInterface_iid)
diff --git a/src/idle/idle-reader.cpp b/src/idle/idle-reader.cpp
new file mode 100644
index 00000000..5743c5fd
--- /dev/null
+++ b/src/idle/idle-reader.cpp
@@ -0,0 +1,34 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "idle-reader.h"
+
+#include
+#include
+
+#include "core/idle-time.h"
+
+IdleReader::IdleReader(std::function rawReader, std::function inhibited)
+ : m_rawReader(std::move(rawReader)), m_inhibited(std::move(inhibited)) {}
+
+int IdleReader::read(IdleMode mode) {
+ int raw = m_rawReader();
+ if (raw < 0) return raw; // propagate error sentinels
+ if (mode == IdleMode::InputOnly) return raw; // raw passthrough, inhibitor ignored
+ if (m_inhibited()) {
+ // Advance the baseline so that, on release, counting starts from 0 (the user is
+ // treated as having just become active). This prevents an instant idleStart the
+ // moment a long video ends.
+ m_baseline = raw;
+ return 0; // "reset the idle time to zero"
+ }
+ int reported = raw - m_baseline; // fresh count since release
+ if (reported < 0) {
+ // Raw dropped below the baseline (e.g. input during inhibition that the reader
+ // still observed). Reset and follow raw.
+ m_baseline = 0;
+ reported = raw;
+ }
+ return reported;
+}
diff --git a/src/idle/idle-reader.h b/src/idle/idle-reader.h
new file mode 100644
index 00000000..b20fedaa
--- /dev/null
+++ b/src/idle/idle-reader.h
@@ -0,0 +1,37 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+
+#include "core/idle-time.h"
+
+// Composes a raw idle source with an inhibitor flag and yields the effective idle time
+// for a given IdleMode. This is the polling-backend implementation of the mode
+// mechanism; the Wayland equivalent is the v1/v2 protocol-object switch.
+//
+// read(InputOnly) - raw input idle, passthrough (inhibitor ignored).
+// read(InhibitorAware) - idle held at 0 while inhibited; on release, counting
+// starts from 0 via a captured baseline (matching Wayland
+// v1 compositor semantics).
+//
+// Mode is passed to read() rather than stored, so it lives only on SystemIdleTime and
+// there is no second copy to keep in sync. The baseline is inhibit-tracking state
+// (not mode) and persists across reads here.
+//
+// Used by polling backends (GNOME, X11, macOS, Windows). Pure logic over injected
+// callables, so it is unit-testable without a real platform.
+class IdleReader {
+ public:
+ // rawReader - returns raw input idle (ms), or a negative sentinel on error.
+ // inhibited - reads a cached bool: is an idle/display inhibitor active right now?
+ IdleReader(std::function rawReader, std::function inhibited);
+ int read(IdleMode mode);
+
+ private:
+ std::function m_rawReader;
+ std::function m_inhibited;
+ int m_baseline = 0; // raw idle captured while inhibited
+};
diff --git a/src/idle/linux/factory.cpp b/src/idle/linux/factory.cpp
index 2b70a7bb..6d720704 100644
--- a/src/idle/linux/factory.cpp
+++ b/src/idle/linux/factory.cpp
@@ -1,5 +1,5 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#include "factory.h"
@@ -13,43 +13,45 @@
#include "core/idle-time.h"
#include "idle/idle-interface.h"
#include "idle/read-based-idle.h"
+#include "inhibitor-proxy-idle.h"
+#include "linux-idle-inhibitor.h"
#define SANE_BREAK_LIB_PREFIX "libsanebreak_idle_"
SystemIdleTime* createLinuxIdleTimer(QObject* parent) {
+ QString pluginName;
if (QGuiApplication::platformName() == "wayland") {
- QDBusInterface iface("org.gnome.Mutter.IdleMonitor",
- "/org/gnome/Mutter/IdleMonitor/Core",
- "org.gnome.Mutter.IdleMonitor", QDBusConnection::sessionBus());
- if (iface.isValid()) {
- QPluginLoader loader(SANE_BREAK_LIB_PREFIX "gnome");
- if (!loader.load()) {
- qCritical() << loader.errorString();
- qFatal("Fail to load GNOME idle time plugin.");
- }
- auto reader = qobject_cast(loader.instance());
- if (!reader) qFatal("Fail to instantiate GNOME idle time plugin.");
- reader->setParent(parent);
- return new ReadBasedIdleTime(parent, [reader]() { return reader->read(); });
- }
- QPluginLoader loader(SANE_BREAK_LIB_PREFIX "wayland");
- if (!loader.load()) {
- qCritical() << loader.errorString();
- qFatal("Fail to load Wayland idle time plugin.");
- }
- auto reader = qobject_cast(loader.instance());
- if (!reader) qFatal("Fail to instantiate Wayland idle time plugin.");
- reader->setParent(parent);
- return reader;
+ QDBusInterface mutter(
+ "org.gnome.Mutter.IdleMonitor", "/org/gnome/Mutter/IdleMonitor/Core",
+ "org.gnome.Mutter.IdleMonitor", QDBusConnection::sessionBus());
+ pluginName = mutter.isValid() ? "gnome" : "wayland";
} else {
- QPluginLoader loader(SANE_BREAK_LIB_PREFIX "x11");
- if (!loader.load()) {
- qCritical() << loader.errorString();
- qFatal("Fail to load X11 idle time plugin.");
- }
- auto reader = qobject_cast(loader.instance());
- if (!reader) qFatal("Fail to instantiate X11 idle time plugin.");
+ pluginName = "x11";
+ }
+
+ QPluginLoader loader(SANE_BREAK_LIB_PREFIX + pluginName);
+ if (!loader.load()) {
+ qCritical() << loader.errorString();
+ qFatal("Fail to load %s idle time plugin.", qPrintable(pluginName));
+ }
+
+ auto* logind = new LinuxIdleInhibitor(parent);
+
+ // Reader plugins (GNOME, X11) expose a polling interface; the Wayland plugin is
+ // event-driven and uses the proxy wrapper instead.
+ if (auto* reader = qobject_cast(loader.instance())) {
reader->setParent(parent);
- return new ReadBasedIdleTime(parent, [reader]() { return reader->read(); });
+ auto* rbt = new ReadBasedIdleTime(parent, [reader]() { return reader->read(); });
+ rbt->setInhibitor([logind, reader]() {
+ return logind->isIdleInhibited() || reader->isInhibited();
+ });
+ return rbt;
}
+
+ if (auto* reader = qobject_cast(loader.instance())) {
+ reader->setParent(parent);
+ return new InhibitorProxyIdleTime(reader, logind, parent);
+ }
+
+ qFatal("Fail to instantiate %s idle time plugin.", qPrintable(pluginName));
}
diff --git a/src/idle/linux/inhibitor-proxy-idle.cpp b/src/idle/linux/inhibitor-proxy-idle.cpp
new file mode 100644
index 00000000..b92bfa7a
--- /dev/null
+++ b/src/idle/linux/inhibitor-proxy-idle.cpp
@@ -0,0 +1,66 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "inhibitor-proxy-idle.h"
+
+#include
+
+#include "core/idle-time.h"
+#include "linux-idle-inhibitor.h"
+
+InhibitorProxyIdleTime::InhibitorProxyIdleTime(SystemIdleTime* source,
+ LinuxIdleInhibitor* inhibitor,
+ QObject* parent)
+ : SystemIdleTime(parent), m_source(source), m_inhibitor(inhibitor) {
+ m_source->setParent(this);
+ m_inhibitor->setParent(this);
+ connect(m_source, &SystemIdleTime::idleStart, this,
+ &InhibitorProxyIdleTime::onSourceIdleStart);
+ connect(m_source, &SystemIdleTime::idleEnd, this,
+ &InhibitorProxyIdleTime::onSourceIdleEnd);
+ connect(m_inhibitor, &LinuxIdleInhibitor::inhibitorChanged, this,
+ &InhibitorProxyIdleTime::onInhibitorChanged);
+}
+
+void InhibitorProxyIdleTime::startWatching() {
+ m_isIdle = false;
+ m_source->startWatching();
+}
+
+void InhibitorProxyIdleTime::stopWatching() { m_source->stopWatching(); }
+
+void InhibitorProxyIdleTime::setWatchAccuracy(int accuracy) {
+ m_watchAccuracy = accuracy;
+ m_source->setWatchAccuracy(accuracy);
+}
+
+void InhibitorProxyIdleTime::setMinIdleTime(int idleTime) {
+ m_minIdleTime = idleTime;
+ m_source->setMinIdleTime(idleTime);
+}
+
+void InhibitorProxyIdleTime::setIdleMode(IdleMode mode) {
+ m_idleMode = mode;
+ m_source->setIdleMode(mode);
+ reevaluate();
+}
+
+void InhibitorProxyIdleTime::onSourceIdleStart() { reevaluate(); }
+
+void InhibitorProxyIdleTime::onSourceIdleEnd() { reevaluate(); }
+
+void InhibitorProxyIdleTime::onInhibitorChanged() { reevaluate(); }
+
+void InhibitorProxyIdleTime::reevaluate() {
+ bool shouldBeIdle = m_source->isIdle();
+ if (m_idleMode == IdleMode::InhibitorAware && m_inhibitor->isIdleInhibited())
+ shouldBeIdle = false;
+ if (shouldBeIdle && !m_isIdle) {
+ m_isIdle = true;
+ emit idleStart();
+ } else if (!shouldBeIdle && m_isIdle) {
+ m_isIdle = false;
+ emit idleEnd();
+ }
+}
diff --git a/src/idle/linux/inhibitor-proxy-idle.h b/src/idle/linux/inhibitor-proxy-idle.h
new file mode 100644
index 00000000..87fd134e
--- /dev/null
+++ b/src/idle/linux/inhibitor-proxy-idle.h
@@ -0,0 +1,46 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+
+#include "core/idle-time.h"
+
+class LinuxIdleInhibitor;
+
+// Wraps an event-driven SystemIdleTime (e.g. the Wayland plugin) with logind
+// inhibitor monitoring.
+//
+// This exists as a wrapper rather than inlined into IdleTimeWayland because the
+// Wayland plugin is a dynamically-loaded .so that links only sane-core-idle,
+// while LinuxIdleInhibitor lives in sane-idle (the static lib that loads the plugin).
+// Wiring them at the factory composition root avoids dragging Qt DBus into the
+// plugin or creating a circular dependency.
+//
+// ext-idle-notify v1 respects Wayland-protocol inhibitors (zwp_idle_inhibitor_v1)
+// but not logind D-Bus inhibitors, so some apps' inhibitors are invisible to it.
+// This wrapper gates idleStart on the inhibitor state and re-emits on inhibitor release
+// (the compositor won't re-fire idled() for an already-idle session).
+class InhibitorProxyIdleTime : public SystemIdleTime {
+ Q_OBJECT
+ public:
+ InhibitorProxyIdleTime(SystemIdleTime* source, LinuxIdleInhibitor* inhibitor,
+ QObject* parent = nullptr);
+ void startWatching() override;
+ void stopWatching() override;
+ void setWatchAccuracy(int accuracy) override;
+ void setMinIdleTime(int idleTime) override;
+ void setIdleMode(IdleMode mode) override;
+
+ private slots:
+ void onSourceIdleStart();
+ void onSourceIdleEnd();
+ void onInhibitorChanged();
+
+ private:
+ SystemIdleTime* m_source;
+ LinuxIdleInhibitor* m_inhibitor;
+ void reevaluate();
+};
diff --git a/src/idle/linux/linux-idle-inhibitor.cpp b/src/idle/linux/linux-idle-inhibitor.cpp
new file mode 100644
index 00000000..1b4e6a46
--- /dev/null
+++ b/src/idle/linux/linux-idle-inhibitor.cpp
@@ -0,0 +1,117 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "linux-idle-inhibitor.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+// logind inhibitor struct: (what, who, why, mode, pid, uid).
+// KDE PolicyAgent inhibition struct: (what, who, why, mode, flags).
+// QDBusArgument has no operator>> for std::tuple (only std::pair), so we parse
+// the D-Bus structs manually via beginArray/beginStructure.
+
+LinuxIdleInhibitor::LinuxIdleInhibitor(QObject* parent) : QObject(parent) {
+ QDBusConnection system = QDBusConnection::systemBus();
+ if (system.interface()->isServiceRegistered("org.freedesktop.login1")) {
+ system.connect("org.freedesktop.login1", "/org/freedesktop/login1",
+ "org.freedesktop.DBus.Properties", "PropertiesChanged", this,
+ SLOT(refresh()));
+ }
+
+ QDBusConnection session = QDBusConnection::sessionBus();
+ if (session.interface()->isServiceRegistered("org.kde.Solid.PowerManagement")) {
+ session.connect(
+ "org.kde.Solid.PowerManagement", "/org/kde/Solid/PowerManagement/PolicyAgent",
+ "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(refresh()));
+ }
+
+ refresh();
+}
+
+void LinuxIdleInhibitor::refresh() {
+ bool inhibited = checkLogind() || checkKDE();
+
+ if (inhibited != m_inhibited) {
+ qDebug() << "idle: inhibitor" << (inhibited ? "active" : "released");
+ m_inhibited = inhibited;
+ emit inhibitorChanged(m_inhibited);
+ }
+}
+
+bool LinuxIdleInhibitor::checkLogind() {
+ QDBusInterface login1("org.freedesktop.login1", "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager", QDBusConnection::systemBus());
+
+ // ListInhibitors returns a(ssssuu) — an array of structs, each with
+ // (what, who, why, mode, pid, uid). Parse manually since QDBusArgument
+ // has no operator>> for std::tuple with >2 elements.
+ QDBusMessage reply = login1.call("ListInhibitors");
+ if (reply.type() == QDBusMessage::ReplyMessage && !reply.arguments().isEmpty()) {
+ const QDBusArgument arg = reply.arguments().at(0).value();
+ arg.beginArray();
+ while (!arg.atEnd()) {
+ arg.beginStructure();
+ QString what, who, why, mode;
+ uint pid, uid;
+ arg >> what >> who >> why >> mode >> pid >> uid;
+ arg.endStructure();
+ if (what.split(u':').contains("idle", Qt::CaseSensitive) && mode == "block")
+ return true;
+ }
+ arg.endArray();
+ } else {
+ // ListInhibitors unavailable (old systemd): fall back to the BlockInhibited
+ // property. Must use org.freedesktop.DBus.Properties for Get.
+ QDBusInterface props("org.freedesktop.login1", "/org/freedesktop/login1",
+ "org.freedesktop.DBus.Properties",
+ QDBusConnection::systemBus());
+ QDBusReply prop =
+ props.call("Get", "org.freedesktop.login1.Manager", "BlockInhibited");
+ if (prop.isValid())
+ return prop.value().variant().toString().split(u':').contains("idle",
+ Qt::CaseSensitive);
+ }
+ return false;
+}
+
+bool LinuxIdleInhibitor::checkKDE() {
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ if (!bus.interface()->isServiceRegistered("org.kde.Solid.PowerManagement"))
+ return false;
+
+ // ActiveInhibitions is a property; must read it via org.freedesktop.DBus.Properties,
+ // not via the PolicyAgent interface (Get belongs to Properties, not PolicyAgent).
+ QDBusInterface props("org.kde.Solid.PowerManagement",
+ "/org/kde/Solid/PowerManagement/PolicyAgent",
+ "org.freedesktop.DBus.Properties", bus);
+ QDBusReply reply = props.call(
+ "Get", "org.kde.Solid.PowerManagement.PolicyAgent", "ActiveInhibitions");
+ if (!reply.isValid()) return false;
+
+ // ActiveInhibitions is a(ssssu) — an array of structs, each with
+ // (what, who, why, mode, flags). Parse manually.
+ const QDBusArgument arg = reply.value().variant().value();
+ arg.beginArray();
+ while (!arg.atEnd()) {
+ arg.beginStructure();
+ QString what, who, why, mode;
+ uint flags;
+ arg >> what >> who >> why >> mode >> flags;
+ arg.endStructure();
+ if (what.split(u':').contains("idle", Qt::CaseSensitive) && mode == "block")
+ return true;
+ }
+ arg.endArray();
+ return false;
+}
diff --git a/src/idle/linux/linux-idle-inhibitor.h b/src/idle/linux/linux-idle-inhibitor.h
new file mode 100644
index 00000000..b1ed1d8e
--- /dev/null
+++ b/src/idle/linux/linux-idle-inhibitor.h
@@ -0,0 +1,41 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+#include
+
+// Detects active idle inhibitors on Linux via two complementary D-Bus sources:
+//
+// 1. logind (system bus): ListInhibitors() / BlockInhibited property.
+// Catches GNOME-forwarded SessionManager/ScreenSaver inhibitors and direct
+// systemd-inhibit calls. GNOME-specific for ScreenSaver forwarding — KDE's
+// PowerDevil does NOT forward idle inhibitors to logind.
+//
+// 2. KDE PowerDevil PolicyAgent (session bus): ActiveInhibitions property.
+// Catches portal-based inhibitors (Firefox, Chromium) on KDE. xdg-desktop-portal-kde
+// routes Inhibit calls to PolicyAgent.AddInhibition, not to ScreenSaver or logind.
+// The ActiveInhibitions property emits PropertiesChanged — event-driven, no polling.
+//
+// Both sources are queried in refresh() and ORed together. On GNOME only logind is
+// active (PowerDevil absent); on KDE both are active but only PolicyAgent catches
+// app idle inhibitors; on wlroots only logind is active (portal Inhibit unimplemented).
+class LinuxIdleInhibitor : public QObject {
+ Q_OBJECT
+ public:
+ explicit LinuxIdleInhibitor(QObject* parent = nullptr);
+ bool isIdleInhibited() const { return m_inhibited; }
+
+ signals:
+ void inhibitorChanged(bool inhibited);
+
+ private slots:
+ void refresh();
+
+ private:
+ bool m_inhibited = false;
+ bool checkLogind();
+ bool checkKDE();
+};
diff --git a/src/idle/linux/wayland/wayland-idle.cpp b/src/idle/linux/wayland/wayland-idle.cpp
index 39e0567a..c47bfdad 100644
--- a/src/idle/linux/wayland/wayland-idle.cpp
+++ b/src/idle/linux/wayland/wayland-idle.cpp
@@ -1,5 +1,5 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#include "wayland-idle.h"
@@ -9,6 +9,7 @@
#include
#include
+#include
#include
#include
#include
@@ -18,6 +19,7 @@
#include
#include
+#include "core/idle-time.h"
#include "wayland-ext-idle-notify-v1-client-protocol.h"
IdleTimeWayland::IdleTimeWayland(QObject* parent) {
@@ -40,13 +42,21 @@ IdleTimeWayland::IdleTimeWayland(QObject* parent) {
wl_registry_add_listener(registry, &globalListener, this);
wl_display_roundtrip(display);
- const auto wl_ntfr_ver = ext_idle_notifier_v1_get_version(idleNotifier);
- const auto wl_ntfr_ver_w_input_idle = decltype(wl_ntfr_ver){2};
+ chooseGetIdleNotification();
+}
- if (wl_ntfr_ver < wl_ntfr_ver_w_input_idle) {
+void IdleTimeWayland::chooseGetIdleNotification() {
+ if (idleNotifier == nullptr) return;
+ const auto wl_ntfr_ver = ext_idle_notifier_v1_get_version(idleNotifier);
+ // InhibitorAware (default): use v1 get_idle_notification, which respects
+ // zwp_idle_inhibitor_v1. InputOnly: use v2 get_input_idle_notification, which
+ // ignores inhibitors; fall back to v1 on v1-only compositors.
+ if (m_idleMode == IdleMode::InhibitorAware || wl_ntfr_ver < 2) {
get_idle_notification = ext_idle_notifier_v1_get_idle_notification;
+ qDebug() << "idle: wayland using v1 get_idle_notification (inhibitor-aware)";
} else {
get_idle_notification = ext_idle_notifier_v1_get_input_idle_notification;
+ qDebug() << "idle: wayland using v2 get_input_idle_notification (input-only)";
}
}
@@ -104,6 +114,20 @@ void IdleTimeWayland::setMinIdleTime(int idleTime) {
ext_idle_notification_v1_add_listener(idleNotification, &idleListener, this);
}
+void IdleTimeWayland::setIdleMode(IdleMode mode) {
+ if (mode == m_idleMode) return;
+ m_idleMode = mode;
+ // Re-evaluate which request to use, then re-create the notification object so the
+ // new request (v1 vs v2) takes effect immediately (mirrors setMinIdleTime()).
+ chooseGetIdleNotification();
+ if (!isWatching) return;
+ if (idleNotification != nullptr) {
+ ext_idle_notification_v1_destroy(idleNotification);
+ }
+ idleNotification = get_idle_notification(idleNotifier, m_minIdleTime, seat);
+ ext_idle_notification_v1_add_listener(idleNotification, &idleListener, this);
+}
+
IdleTimeWayland::~IdleTimeWayland() {
if (idleNotifier != nullptr) ext_idle_notifier_v1_destroy(idleNotifier);
if (idleNotification != nullptr) ext_idle_notification_v1_destroy(idleNotification);
diff --git a/src/idle/linux/wayland/wayland-idle.h b/src/idle/linux/wayland/wayland-idle.h
index 809ae6a7..c9f0356c 100644
--- a/src/idle/linux/wayland/wayland-idle.h
+++ b/src/idle/linux/wayland/wayland-idle.h
@@ -1,5 +1,5 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
@@ -13,6 +13,7 @@
#include
#include
+#include "core/idle-time.h"
#include "idle/idle-interface.h"
#include "wayland-ext-idle-notify-v1-client-protocol.h"
@@ -28,6 +29,7 @@ class IdleTimeWayland : public IdleTimeInterface {
void stopWatching() override;
void setWatchAccuracy(int) override {};
void setMinIdleTime(int idleTime) override;
+ void setIdleMode(IdleMode mode) override;
private:
static void globalAdded(void* data, wl_registry* registry, uint32_t name,
@@ -37,6 +39,11 @@ class IdleTimeWayland : public IdleTimeInterface {
static void idled(void* data, ext_idle_notification_v1* object);
static void resumed(void* data, ext_idle_notification_v1* object);
const struct ext_idle_notification_v1_listener idleListener{idled, resumed};
+ // Choose get_idle_notification (v1, respects inhibitors) vs
+ // get_input_idle_notification (v2, input-only) based on the mode and the bound
+ // notifier version. Called from the constructor after binding and from
+ // setIdleMode() on a mode change.
+ void chooseGetIdleNotification();
wl_seat* seat;
ext_idle_notifier_v1* idleNotifier = nullptr;
ext_idle_notification_v1* idleNotification = nullptr;
diff --git a/src/idle/linux/x11/x11-idle.cpp b/src/idle/linux/x11/x11-idle.cpp
index 8e4221bf..74f61dd4 100644
--- a/src/idle/linux/x11/x11-idle.cpp
+++ b/src/idle/linux/x11/x11-idle.cpp
@@ -1,19 +1,31 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#include "x11-idle.h"
+// clang-format off
+#include
+#include
+
#include
+#include
#include
-
-#include
+// clang-format on
int IdleTimeX11::read() {
Display* dpy = XOpenDisplay(NULL);
XScreenSaverInfo* ssi = XScreenSaverAllocInfo();
XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), ssi);
int idleTime = ssi->idle;
+ // state == ScreenSaverDisabled means a client is holding a XScreenSaverSuspend(True)
+ // inhibition — the standard programmatic X11 inhibition path used by most media
+ // players. Best-effort: apps that inhibit via DPMS-direct or timer-resetting are
+ // not detected (documented limitation).
+ bool inhibited = (ssi->state == ScreenSaverDisabled);
+ if (inhibited != m_inhibited)
+ qDebug() << "idle: x11 inhibitor" << (inhibited ? "active" : "released");
+ m_inhibited = inhibited;
XFree(ssi);
XCloseDisplay(dpy);
return idleTime;
diff --git a/src/idle/linux/x11/x11-idle.h b/src/idle/linux/x11/x11-idle.h
index c8dfdb1f..0602a418 100644
--- a/src/idle/linux/x11/x11-idle.h
+++ b/src/idle/linux/x11/x11-idle.h
@@ -1,7 +1,9 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
+#pragma once
+
#include
#include "idle/idle-interface.h"
@@ -14,4 +16,12 @@ class IdleTimeX11 : public IdleTimeReaderInterface {
IdleTimeX11() = default;
~IdleTimeX11() = default;
int read() override;
+ // True while any client holds a XScreenSaverSuspend(True) inhibition, which
+ // flips XScreenSaverInfo.state to ScreenSaverDisabled. Read from the same
+ // XScreenSaverQueryInfo call as idle, so it is free and always current after
+ // read() has been called.
+ bool isInhibited() override { return m_inhibited; }
+
+ private:
+ bool m_inhibited = false;
};
diff --git a/src/idle/macos-inhibitor.cpp b/src/idle/macos-inhibitor.cpp
new file mode 100644
index 00000000..8cc6d0ba
--- /dev/null
+++ b/src/idle/macos-inhibitor.cpp
@@ -0,0 +1,63 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "macos-inhibitor.h"
+
+#include
+#include
+
+#include
+#include
+
+MacosInhibitor::MacosInhibitor(QObject* parent) : QObject(parent) {
+ m_timer = new QTimer(this);
+ m_timer->setInterval(2000); // slow poll; the per-tick reader only reads the cache
+ connect(m_timer, &QTimer::timeout, this, &MacosInhibitor::refresh);
+ refresh();
+ m_timer->start();
+}
+
+void MacosInhibitor::refresh() {
+ bool inhibited = false;
+ // Returns a dictionary mapping PID (CFNumberRef) -> CFArrayRef of assertion dicts.
+ CFDictionaryRef assertionsByProcess = nullptr;
+ if (IOPMCopyAssertionsByProcess(&assertionsByProcess) == kIOReturnSuccess &&
+ assertionsByProcess != nullptr) {
+ CFIndex count = CFDictionaryGetCount(assertionsByProcess);
+ if (count > 0) {
+ const void** keys = new const void*[count];
+ const void** values = new const void*[count];
+ CFDictionaryGetKeysAndValues(assertionsByProcess, keys, values);
+ for (CFIndex i = 0; i < count && !inhibited; ++i) {
+ CFArrayRef assertions = static_cast(values[i]);
+ CFIndex n = CFArrayGetCount(assertions);
+ for (CFIndex j = 0; j < n; ++j) {
+ CFDictionaryRef dict =
+ static_cast(CFArrayGetValueAtIndex(assertions, j));
+ CFStringRef type = static_cast(
+ CFDictionaryGetValue(dict, kIOPMAssertionTypeKey));
+ CFNumberRef level = static_cast(
+ CFDictionaryGetValue(dict, kIOPMAssertionLevelKey));
+ if (type && level) {
+ if (CFStringCompare(type, CFSTR("PreventUserIdleDisplaySleep"), 0) ==
+ kCFCompareEqualTo) {
+ IOPMAssertionLevel lvl = kIOPMAssertionLevelOff;
+ if (CFNumberGetValue(level, kCFNumberIntType, &lvl) &&
+ lvl == kIOPMAssertionLevelOn) {
+ inhibited = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ delete[] keys;
+ delete[] values;
+ }
+ CFRelease(assertionsByProcess);
+ }
+ if (inhibited != m_inhibited)
+ qDebug() << "idle: macos inhibitor" << (inhibited ? "active" : "released");
+ m_inhibited = inhibited;
+}
diff --git a/src/idle/macos-inhibitor.h b/src/idle/macos-inhibitor.h
new file mode 100644
index 00000000..8a3b3c7c
--- /dev/null
+++ b/src/idle/macos-inhibitor.h
@@ -0,0 +1,36 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+#include
+#include
+
+#include
+#include
+
+// Detects active display-idle power assertions on macOS.
+//
+// HIDIdleTime (read by macosIdleTime()) only tracks HID input, so a video player
+// holding a PreventUserIdleDisplaySleep assertion does not pause it. In InhibitorAware
+// mode we detect such assertions via IOPMCopyAssertionsByProcess and zero the reported
+// idle while one is active.
+//
+// The assertion list is polled on a slow timer (~2 s) and cached; the per-tick reader
+// only reads the cached flag. No entitlement changes.
+class MacosInhibitor : public QObject {
+ Q_OBJECT
+ public:
+ explicit MacosInhibitor(QObject* parent = nullptr);
+ // Cached flag: is there any active assertion of type PreventUserIdleDisplaySleep?
+ bool isDisplayInhibited() const { return m_inhibited; }
+
+ private slots:
+ void refresh();
+
+ private:
+ QTimer* m_timer;
+ bool m_inhibited = false;
+};
diff --git a/src/idle/read-based-idle.cpp b/src/idle/read-based-idle.cpp
index 932c6a58..14ec8eea 100644
--- a/src/idle/read-based-idle.cpp
+++ b/src/idle/read-based-idle.cpp
@@ -1,5 +1,5 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#include "read-based-idle.h"
@@ -7,11 +7,14 @@
#include
#include
#include
+#include
+#include
#include "core/idle-time.h"
+#include "idle-reader.h"
ReadBasedIdleTime::ReadBasedIdleTime(QObject* parent, std::function idleReader)
- : SystemIdleTime(parent), m_idleReader(idleReader) {
+ : SystemIdleTime(parent), m_rawReader(std::move(idleReader)) {
m_timer = new QTimer(this);
m_delay = new QTimer(this);
m_delay->setSingleShot(true);
@@ -20,7 +23,7 @@ ReadBasedIdleTime::ReadBasedIdleTime(QObject* parent, std::function idleR
};
void ReadBasedIdleTime::startWatching() {
- // Assume currently not idle and nofity first idle event
+ // Assume currently not idle and notifity first idle event
m_isIdle = false;
m_timer->setInterval(m_watchAccuracy);
// We emit idleStart after at least m_minIdleTime msec.
@@ -44,8 +47,12 @@ void ReadBasedIdleTime::setWatchAccuracy(int accuracy) {
void ReadBasedIdleTime::setMinIdleTime(int idleTime) { m_minIdleTime = idleTime; };
+void ReadBasedIdleTime::setInhibitor(std::function inhibited) {
+ m_reader = std::make_unique(m_rawReader, std::move(inhibited));
+}
+
void ReadBasedIdleTime::tick() {
- int currentIdleTime = m_idleReader();
+ int currentIdleTime = m_reader ? m_reader->read(m_idleMode) : m_rawReader();
if (currentIdleTime < m_minIdleTime && m_isIdle) {
m_isIdle = false;
emit idleEnd();
diff --git a/src/idle/read-based-idle.h b/src/idle/read-based-idle.h
index 4736990e..427ac2b5 100644
--- a/src/idle/read-based-idle.h
+++ b/src/idle/read-based-idle.h
@@ -1,5 +1,5 @@
// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
-// Copyright (C) 2024-2025 Sane Break developers
+// Copyright (C) 2024-2026 Sane Break developers
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
@@ -7,9 +7,10 @@
#include
#include
#include
+#include
#include "core/idle-time.h"
-#include "idle-interface.h"
+#include "idle-reader.h"
class ReadBasedIdleTime : public SystemIdleTime {
Q_OBJECT
@@ -19,10 +20,17 @@ class ReadBasedIdleTime : public SystemIdleTime {
void stopWatching() override;
void setWatchAccuracy(int accuracy) override;
void setMinIdleTime(int idleTime) override;
+ // Install an inhibitor monitor. When present, tick() routes the raw reader through
+ // IdleReader, which zeroes idle while inhibited (in InhibitorAware mode) and passes
+ // it through unchanged (in InputOnly mode). No-op if never called.
+ void setInhibitor(std::function inhibited);
private:
QTimer* m_timer;
QTimer* m_delay;
- std::function m_idleReader = nullptr;
+ std::function m_rawReader; // raw input idle (always available)
+ // When set, read(m_idleMode) applies inhibitor-aware zeroing; otherwise raw is
+ // used directly. Mode is read from the base SystemIdleTime::m_idleMode at tick.
+ std::unique_ptr m_reader;
void tick();
};
diff --git a/src/idle/windows-inhibitor.cpp b/src/idle/windows-inhibitor.cpp
new file mode 100644
index 00000000..b99224ee
--- /dev/null
+++ b/src/idle/windows-inhibitor.cpp
@@ -0,0 +1,31 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "windows-inhibitor.h"
+
+#include
+
+#include
+
+// ES_DISPLAY_REQUIRED: an app is requesting the display stay on.
+#ifndef ES_DISPLAY_REQUIRED
+#define ES_DISPLAY_REQUIRED 0x00000002
+#endif
+
+bool windowsDisplayInhibited() {
+ // SystemExecutionState (level 16) returns a ULONG of execution-state flags. It
+ // reflects cross-process SetThreadExecutionState/PowerSetRequest holds; a single
+ // documented, no-admin syscall.
+ ULONG execState = 0;
+ NTSTATUS status = CallNtPowerInformation(SystemExecutionState, nullptr, 0, &execState,
+ sizeof(execState));
+ if (status != 0) return false; // treat errors as "not inhibited"
+ bool inhibited = (execState & ES_DISPLAY_REQUIRED) != 0;
+ static bool lastInhibited = false; // edge-triggered log; stateless free fn
+ if (inhibited != lastInhibited) {
+ lastInhibited = inhibited;
+ qDebug() << "idle: windows inhibitor" << (inhibited ? "active" : "released");
+ }
+ return inhibited;
+}
diff --git a/src/idle/windows-inhibitor.h b/src/idle/windows-inhibitor.h
new file mode 100644
index 00000000..13bd14cc
--- /dev/null
+++ b/src/idle/windows-inhibitor.h
@@ -0,0 +1,21 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+
+// Detects whether an app is keeping the display awake on Windows.
+//
+// GetLastInputInfo (read by windowsIdleTime()) only tracks input, so a video player
+// holding a display power request does not pause it. In InhibitorAware mode we detect
+// such requests via CallNtPowerInformation(SystemExecutionState) — a documented,
+// no-admin, no-spawn syscall that returns ES_DISPLAY_REQUIRED for *both* the legacy
+// SetThreadExecutionState and the modern PowerSetRequest(PowerRequestDisplayRequired)
+// paths (verified cross-process, Win 11 24H2 non-elevated). The admin-only
+// powercfg/GetPowerRequestList path is deliberately *not* used.
+//
+// Cheap (single syscall), so it is polled on the idle tick directly via this free
+// function rather than a cached monitor object.
+bool windowsDisplayInhibited();
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 2c72817b..530f2ffc 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -7,7 +7,7 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --verbose --output-on-fai
include_directories("../src")
-set(TEST_FILES test-app.cpp test-db.cpp test-window.cpp)
+set(TEST_FILES test-app.cpp test-db.cpp test-window.cpp test-idle-reader.cpp)
if(SANE_BREAK_CLI_CONTROL_ENABLED)
list(APPEND TEST_FILES test-command.cpp)
endif()
@@ -26,6 +26,11 @@ foreach(TEST_FILE ${TEST_FILES})
add_dependencies(check "${TEST_FILE_NAME}")
endforeach()
+# test-idle-reader exercises the pure-logic IdleReader, which has no platform
+# dependencies. Compile it directly rather than linking the full (platform-specific)
+# sane-idle static library.
+target_sources(test-idle-reader PRIVATE ${CMAKE_SOURCE_DIR}/src/idle/idle-reader.cpp)
+
# Screenshot harness (not part of check target)
add_executable(
test-screenshot test-screenshot.cpp ${CMAKE_SOURCE_DIR}/resources/index.qrc
diff --git a/test/dummy.h b/test/dummy.h
index dcd21c4a..b8857da8 100644
--- a/test/dummy.h
+++ b/test/dummy.h
@@ -35,10 +35,12 @@ class DummyIdleTime : public SystemIdleTime {
Q_OBJECT
public:
using SystemIdleTime::SystemIdleTime;
- void startWatching() { m_isIdle = false; };
- void stopWatching() {};
- void setWatchAccuracy(int) {};
- void setMinIdleTime(int) {};
+ void startWatching() override { m_isIdle = false; };
+ void stopWatching() override {};
+ void setWatchAccuracy(int) override {};
+ void setMinIdleTime(int) override {};
+ void setIdleMode(IdleMode mode) override { m_recordedMode = mode; };
+ IdleMode recordedMode() const { return m_recordedMode; };
void setIdle(bool idle) {
m_isIdle = idle;
if (idle) {
@@ -47,6 +49,9 @@ class DummyIdleTime : public SystemIdleTime {
emit idleEnd();
}
}
+
+ private:
+ IdleMode m_recordedMode = IdleMode::InhibitorAware;
};
class DummyBreakWindows : public AbstractBreakWindows {
diff --git a/test/test-app.cpp b/test/test-app.cpp
index 2331736a..03957319 100644
--- a/test/test-app.cpp
+++ b/test/test-app.cpp
@@ -14,6 +14,7 @@
#include "core/app.h"
#include "core/flags.h"
+#include "core/idle-time.h"
#include "dummy.h"
#include "gmock/gmock.h"
@@ -167,6 +168,63 @@ class TestApp : public QObject {
app.advance(1);
QCOMPARE(app.trayData.secondsToNextBreak, secondsToNextBreak - 1);
}
+ // Default preference (treatInhibitorAsActivity == true) maps to InhibitorAware.
+ void idle_mode_default_is_inhibitor_aware() {
+ NiceMock app(deps);
+ QCOMPARE(deps.preferences->treatInhibitorAsActivity->get(), true);
+ app.start();
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InhibitorAware);
+ }
+ // Setting the preference to false before start maps to InputOnly.
+ void idle_mode_false_pref_is_input_only() {
+ deps.preferences->treatInhibitorAsActivity->set(false);
+ NiceMock app(deps);
+ app.start();
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InputOnly);
+ }
+ // Changing the preference at runtime re-applies the mode live.
+ void idle_mode_live_change() {
+ NiceMock app(deps);
+ app.start();
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InhibitorAware);
+ deps.preferences->treatInhibitorAsActivity->set(false);
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InputOnly);
+ deps.preferences->treatInhibitorAsActivity->set(true);
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InhibitorAware);
+ }
+ // During a break, idle must be measured with raw input (InputOnly) regardless of
+ // the preference, so phase transitions and force-break escalation correctly detect
+ // actual user presence instead of being masked by a background inhibitor.
+ void idle_mode_during_break_is_input_only() {
+ NiceMock app(deps);
+ app.start();
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InhibitorAware);
+ app.advance(app.trayData.secondsToNextBreak);
+ QVERIFY(app.trayData.isBreaking);
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InputOnly);
+ }
+ // After a break ends, the preferred mode is restored when returning to normal.
+ void idle_mode_restores_after_break() {
+ NiceMock app(deps);
+ app.start();
+ app.advance(app.trayData.secondsToNextBreak);
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InputOnly);
+ app.advanceToBreakEnd();
+ QVERIFY(!app.trayData.isBreaking);
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InhibitorAware);
+ }
+ // Force break also uses InputOnly — an inhibitor must not prevent force-break
+ // escalation when the user is actually active.
+ void idle_mode_during_force_break_is_input_only() {
+ NiceMock app(deps);
+ app.start();
+ app.advance(app.trayData.secondsToNextBreak);
+ // User stays "active" (not idle) so the break escalates to force break.
+ app.advanceToForceBreakStart();
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InputOnly);
+ app.advanceToBreakEnd();
+ QCOMPARE(deps.idleTimer->recordedMode(), IdleMode::InhibitorAware);
+ }
void long_post_break_idle_resets_cycle_data() {
QTest::addColumn("autoCloseWindow");
QTest::newRow("auto-close") << true;
diff --git a/test/test-idle-reader.cpp b/test/test-idle-reader.cpp
new file mode 100644
index 00000000..63763a65
--- /dev/null
+++ b/test/test-idle-reader.cpp
@@ -0,0 +1,102 @@
+// Sane Break is a gentle break reminder that helps you avoid mindlessly skipping breaks
+// Copyright (C) 2024-2026 Sane Break developers
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include
+
+#include
+#include
+
+#include "core/idle-time.h"
+#include "idle/idle-reader.h"
+
+// Pure-logic tests for the idle reader. No Qt platform is needed: the raw reader and
+// the inhibited flag are lambdas, so this exercises only the baseline/reset behavior
+// that the per-platform monitors feed.
+class TestIdleReader : public QObject {
+ Q_OBJECT
+
+ private slots:
+ void inhibitorOffPassesRawThrough() {
+ int raw = 5000;
+ bool inhibited = false;
+ IdleReader reader([&raw]() { return raw; }, [&inhibited]() { return inhibited; });
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 5000);
+ raw = 7000;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 7000);
+ }
+
+ void inhibitorOnReportsZero() {
+ int raw = 5000;
+ bool inhibited = true;
+ IdleReader reader([&raw]() { return raw; }, [&inhibited]() { return inhibited; });
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 0);
+ raw = 60000;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 0); // stays zero while inhibited
+ }
+
+ void baselineResetOnRelease() {
+ int raw = 0;
+ bool inhibited = false;
+ IdleReader reader([&raw]() { return raw; }, [&inhibited]() { return inhibited; });
+
+ // Inhibited while raw climbs 0 -> 60s; reader reports 0 throughout.
+ inhibited = true;
+ for (int ms = 0; ms <= 60000; ms += 1000) {
+ raw = ms;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 0);
+ }
+
+ // Release at raw=60s: reader reports 0 at release (no instant idleStart) and
+ // grows from there, matching Wayland v1 compositor semantics.
+ inhibited = false;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 0); // 60s - 60s baseline
+ raw = 61000;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 1000); // counts from release
+ raw = 65000;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 5000);
+ }
+
+ void inputDuringInhibitionResetsBaseline() {
+ int raw = 0;
+ bool inhibited = true;
+ IdleReader reader([&raw]() { return raw; }, [&inhibited]() { return inhibited; });
+
+ raw = 30000;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 0); // baseline captured at 30000
+
+ // User provides input during inhibition that the reader still observes: raw drops.
+ raw = 5000;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware),
+ 0); // still inhibited -> 0, baseline advances to 5000
+
+ // On release the reported value follows raw (baseline reset to the lower value).
+ inhibited = false;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 0); // 5000 - 5000
+ raw = 10000;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 5000); // grows from post-input
+ }
+
+ void inputOnlyIgnoresInhibitor() {
+ int raw = 5000;
+ bool inhibited = true;
+ IdleReader reader([&raw]() { return raw; }, [&inhibited]() { return inhibited; });
+ // In InputOnly mode the inhibitor is ignored entirely: raw passes through.
+ QCOMPARE(reader.read(IdleMode::InputOnly), 5000);
+ raw = 8000;
+ QCOMPARE(reader.read(IdleMode::InputOnly), 8000);
+ // And it must not disturb the baseline used by a later InhibitorAware read.
+ inhibited = false;
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), 8000); // raw - 0 baseline
+ }
+
+ void errorSentinelPropagated() {
+ bool inhibited = true;
+ IdleReader reader([]() { return -1; }, [&inhibited]() { return inhibited; });
+ // Negative raw is propagated even while inhibited (no false "active" zero).
+ QCOMPARE(reader.read(IdleMode::InhibitorAware), -1);
+ }
+};
+
+QTEST_GUILESS_MAIN(TestIdleReader)
+#include "test-idle-reader.moc"