From 5d3fec25cda57f2dbe1c44754a4faf6f0f642605 Mon Sep 17 00:00:00 2001 From: Allan Chain <36528777+AllanChain@users.noreply.github.com> Date: Sat, 18 Jul 2026 12:45:31 +0800 Subject: [PATCH 1/5] treat idle inhibitor as user activity But keep inhibitor ignore during break window --- src/app/pref-window.cpp | 3 + src/app/pref-window.ui | 10 +++ src/core/app-states.cpp | 16 ++++ src/core/app-states.h | 4 + src/core/app.cpp | 5 ++ src/core/idle-time.h | 17 +++- src/core/preferences.cpp | 2 + src/core/preferences.h | 4 + src/idle/CMakeLists.txt | 22 +++-- src/idle/factory.cpp | 13 ++- src/idle/idle-interface.h | 8 +- src/idle/idle-reader.cpp | 34 ++++++++ src/idle/idle-reader.h | 37 +++++++++ src/idle/linux/factory.cpp | 19 ++++- src/idle/linux/logind-inhibitor.cpp | 66 +++++++++++++++ src/idle/linux/logind-inhibitor.h | 34 ++++++++ src/idle/linux/wayland/wayland-idle.cpp | 29 ++++++- src/idle/linux/wayland/wayland-idle.h | 9 ++- src/idle/linux/x11/x11-idle.cpp | 8 +- src/idle/linux/x11/x11-idle.h | 12 ++- src/idle/macos-inhibitor.cpp | 63 +++++++++++++++ src/idle/macos-inhibitor.h | 36 +++++++++ src/idle/read-based-idle.cpp | 15 +++- src/idle/read-based-idle.h | 14 +++- src/idle/windows-inhibitor.cpp | 23 ++++++ src/idle/windows-inhibitor.h | 21 +++++ test/CMakeLists.txt | 7 +- test/dummy.h | 13 ++- test/test-app.cpp | 58 ++++++++++++++ test/test-idle-reader.cpp | 102 ++++++++++++++++++++++++ 30 files changed, 671 insertions(+), 33 deletions(-) create mode 100644 src/idle/idle-reader.cpp create mode 100644 src/idle/idle-reader.h create mode 100644 src/idle/linux/logind-inhibitor.cpp create mode 100644 src/idle/linux/logind-inhibitor.h create mode 100644 src/idle/macos-inhibitor.cpp create mode 100644 src/idle/macos-inhibitor.h create mode 100644 src/idle/windows-inhibitor.cpp create mode 100644 src/idle/windows-inhibitor.h create mode 100644 test/test-idle-reader.cpp 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..66440c5b 100644 --- a/src/idle/CMakeLists.txt +++ b/src/idle/CMakeLists.txt @@ -1,16 +1,28 @@ 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/logind-inhibitor.h + linux/logind-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..b69512e6 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,6 +13,7 @@ #include "core/idle-time.h" #include "idle/idle-interface.h" #include "idle/read-based-idle.h" +#include "logind-inhibitor.h" #define SANE_BREAK_LIB_PREFIX "libsanebreak_idle_" @@ -30,7 +31,12 @@ SystemIdleTime* createLinuxIdleTimer(QObject* parent) { 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(); }); + // Mutter's GetIdletime is input-only; logind catches idle inhibitors (GNOME + // forwards its SessionManager/ScreenSaver inhibitors to logind). + auto* rbt = new ReadBasedIdleTime(parent, [reader]() { return reader->read(); }); + auto* logind = new LogindInhibitor(parent); + rbt->setInhibitor([logind]() { return logind->isIdleInhibited(); }); + return rbt; } QPluginLoader loader(SANE_BREAK_LIB_PREFIX "wayland"); if (!loader.load()) { @@ -50,6 +56,13 @@ SystemIdleTime* createLinuxIdleTimer(QObject* parent) { auto reader = qobject_cast(loader.instance()); if (!reader) qFatal("Fail to instantiate X11 idle time plugin."); reader->setParent(parent); - return new ReadBasedIdleTime(parent, [reader]() { return reader->read(); }); + // X11: the ScreenSaverDisabled heuristic (XScreenSaverSuspend) is free in the + // same call as idle, and logind catches D-Bus inhibitors that forward to it. + auto* rbt = new ReadBasedIdleTime(parent, [reader]() { return reader->read(); }); + auto* logind = new LogindInhibitor(parent); + rbt->setInhibitor([logind, reader]() { + return logind->isIdleInhibited() || reader->isInhibited(); + }); + return rbt; } } diff --git a/src/idle/linux/logind-inhibitor.cpp b/src/idle/linux/logind-inhibitor.cpp new file mode 100644 index 00000000..5a769c64 --- /dev/null +++ b/src/idle/linux/logind-inhibitor.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 "logind-inhibitor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Each inhibitor is (what, who, why, mode, pid, uid). +using InhibitorTuple = std::tuple; + +LogindInhibitor::LogindInhibitor(QObject* parent) : QObject(parent) { + QDBusConnection bus = QDBusConnection::systemBus(); + // We only need the service if it's actually on the bus; otherwise refresh() is a + // no-op and we stay "not inhibited". + if (!bus.interface()->isServiceRegistered("org.freedesktop.login1")) return; + + // Re-scan whenever the set of active block locks changes (event-driven, no polling). + bus.connect("org.freedesktop.login1", "/org/freedesktop/login1", + "org.freedesktop.DBus.Properties", "PropertiesChanged", this, + SLOT(refresh())); + refresh(); +} + +void LogindInhibitor::refresh() { + QDBusInterface login1("org.freedesktop.login1", "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", QDBusConnection::systemBus()); + + bool inhibited = false; + + // Prefer the per-inhibitor list: an inhibitor is relevant iff `what` contains + // "idle" and it is a "block" lock (delay locks don't prevent idle). + QDBusReply> reply = login1.call("ListInhibitors"); + if (reply.isValid()) { + for (const InhibitorTuple& inhibitor : reply.value()) { + const QString& what = std::get<0>(inhibitor); + const QString& mode = std::get<3>(inhibitor); + if (what.split(u':').contains("idle", Qt::CaseSensitive) && mode == "block") { + inhibited = true; + break; + } + } + } else { + // ListInhibitors unavailable (old systemd): fall back to the BlockInhibited + // property, a colon-separated string of active block-lock types. + QDBusReply prop = + login1.call("Get", "org.freedesktop.login1.Manager", "BlockInhibited"); + if (prop.isValid()) { + inhibited = prop.value().variant().toString().split(u':').contains( + "idle", Qt::CaseSensitive); + } + } + + m_inhibited = inhibited; +} diff --git a/src/idle/linux/logind-inhibitor.h b/src/idle/linux/logind-inhibitor.h new file mode 100644 index 00000000..4eb2f813 --- /dev/null +++ b/src/idle/linux/logind-inhibitor.h @@ -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 + +#pragma once + +#include +#include + +// Detects active idle/display inhibitors via logind on the system bus. +// +// logind subsumes the GNOME SessionManager inhibit path (GNOME forwards its +// inhibitors to logind) and is DE-agnostic, so the same code covers GNOME-Wayland, +// wlroots/KDE Wayland (D-Bus callers) and X11. Used as the cached bool flag feeding +// IdleReader for polling backends. +// +// The inhibitor *list* (`ListInhibitors`) is not polkit-gated; in Flatpak it needs +// `--system-talk-name=org.freedesktop.login1`. We subscribe to the `BlockInhibited` +// property (a colon-separated string of active block-lock types) which emits +// PropertiesChanged on change, then re-scan ListInhibitors — event-driven, no polling. +class LogindInhibitor : public QObject { + Q_OBJECT + public: + explicit LogindInhibitor(QObject* parent = nullptr); + // Cached flag: is there at least one active block-lock inhibitor whose `what` + // contains "idle"? Refreshed from the BlockInhibited property and ListInhibitors. + bool isIdleInhibited() const { return m_inhibited; } + + private slots: + void refresh(); + + private: + bool m_inhibited = false; +}; diff --git a/src/idle/linux/wayland/wayland-idle.cpp b/src/idle/linux/wayland/wayland-idle.cpp index 39e0567a..d4b35718 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" @@ -18,6 +18,7 @@ #include #include +#include "core/idle-time.h" #include "wayland-ext-idle-notify-v1-client-protocol.h" IdleTimeWayland::IdleTimeWayland(QObject* parent) { @@ -40,10 +41,16 @@ 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; } else { get_idle_notification = ext_idle_notifier_v1_get_input_idle_notification; @@ -104,6 +111,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..4f476812 100644 --- a/src/idle/linux/x11/x11-idle.cpp +++ b/src/idle/linux/x11/x11-idle.cpp @@ -1,10 +1,11 @@ // 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" #include +#include #include #include @@ -14,6 +15,11 @@ int IdleTimeX11::read() { 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). + m_inhibited = (ssi->state == ScreenSaverDisabled); 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..3813d72b --- /dev/null +++ b/src/idle/windows-inhibitor.cpp @@ -0,0 +1,23 @@ +// 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 + +// 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" + return (execState & ES_DISPLAY_REQUIRED) != 0; +} 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" From 6be3ae837184f5d9470e4cd5fe54e9f2efbdac2d Mon Sep 17 00:00:00 2001 From: Allan Chain <36528777+AllanChain@users.noreply.github.com> Date: Sat, 18 Jul 2026 12:46:11 +0800 Subject: [PATCH 2/5] add debug logging for idle inhibitor --- src/idle/linux/logind-inhibitor.cpp | 3 +++ src/idle/linux/wayland/wayland-idle.cpp | 3 +++ src/idle/linux/x11/x11-idle.cpp | 12 +++++++++--- src/idle/windows-inhibitor.cpp | 10 +++++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/idle/linux/logind-inhibitor.cpp b/src/idle/linux/logind-inhibitor.cpp index 5a769c64..3bae9e7a 100644 --- a/src/idle/linux/logind-inhibitor.cpp +++ b/src/idle/linux/logind-inhibitor.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -62,5 +63,7 @@ void LogindInhibitor::refresh() { } } + if (inhibited != m_inhibited) + qDebug() << "idle: logind inhibitor" << (inhibited ? "active" : "released"); m_inhibited = inhibited; } diff --git a/src/idle/linux/wayland/wayland-idle.cpp b/src/idle/linux/wayland/wayland-idle.cpp index d4b35718..c47bfdad 100644 --- a/src/idle/linux/wayland/wayland-idle.cpp +++ b/src/idle/linux/wayland/wayland-idle.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -52,8 +53,10 @@ void IdleTimeWayland::chooseGetIdleNotification() { // 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)"; } } diff --git a/src/idle/linux/x11/x11-idle.cpp b/src/idle/linux/x11/x11-idle.cpp index 4f476812..74f61dd4 100644 --- a/src/idle/linux/x11/x11-idle.cpp +++ b/src/idle/linux/x11/x11-idle.cpp @@ -4,11 +4,14 @@ #include "x11-idle.h" +// clang-format off +#include +#include + #include #include #include - -#include +// clang-format on int IdleTimeX11::read() { Display* dpy = XOpenDisplay(NULL); @@ -19,7 +22,10 @@ int IdleTimeX11::read() { // 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). - m_inhibited = (ssi->state == ScreenSaverDisabled); + 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/windows-inhibitor.cpp b/src/idle/windows-inhibitor.cpp index 3813d72b..b99224ee 100644 --- a/src/idle/windows-inhibitor.cpp +++ b/src/idle/windows-inhibitor.cpp @@ -6,6 +6,8 @@ #include +#include + // ES_DISPLAY_REQUIRED: an app is requesting the display stay on. #ifndef ES_DISPLAY_REQUIRED #define ES_DISPLAY_REQUIRED 0x00000002 @@ -19,5 +21,11 @@ bool windowsDisplayInhibited() { NTSTATUS status = CallNtPowerInformation(SystemExecutionState, nullptr, 0, &execState, sizeof(execState)); if (status != 0) return false; // treat errors as "not inhibited" - return (execState & ES_DISPLAY_REQUIRED) != 0; + 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; } From cfb77b4e910a2c3b409874122a5ee2f057f95950 Mon Sep 17 00:00:00 2001 From: Allan Chain <36528777+AllanChain@users.noreply.github.com> Date: Sat, 18 Jul 2026 16:58:14 +0800 Subject: [PATCH 3/5] update pref screenshot --- screenshots/pref-pause.png | Bin 86162 -> 92206 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/screenshots/pref-pause.png b/screenshots/pref-pause.png index e6673d295da36642fa30c7f6a882ea7442bd1aef..7826647177c4c777df0ce13f61edc331fec1ffa0 100644 GIT binary patch literal 92206 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ʰaC?V6gWGu#_gd&DnMZM<_Ya&LO$XSaMpAJ0L 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

FTdaX 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

d&nsY5k+<>+DqGskDpdc^uPnsiL?ZN!v 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 From 95dddd833e5220530a52076731afa9501997c052 Mon Sep 17 00:00:00 2001 From: Allan Chain <36528777+AllanChain@users.noreply.github.com> Date: Sat, 18 Jul 2026 17:02:02 +0800 Subject: [PATCH 4/5] update translations by LLM --- resources/translations/cs.ts | 138 ++++++++++++++++--------------- resources/translations/de.ts | 138 ++++++++++++++++--------------- resources/translations/en.ts | 8 +- resources/translations/es.ts | 138 ++++++++++++++++--------------- resources/translations/fr.ts | 138 ++++++++++++++++--------------- resources/translations/he.ts | 138 ++++++++++++++++--------------- resources/translations/hu.ts | 138 ++++++++++++++++--------------- resources/translations/it.ts | 138 ++++++++++++++++--------------- resources/translations/nl.ts | 140 +++++++++++++++++--------------- resources/translations/pl.ts | 138 ++++++++++++++++--------------- resources/translations/ru.ts | 138 ++++++++++++++++--------------- resources/translations/sv.ts | 138 ++++++++++++++++--------------- resources/translations/uk.ts | 138 ++++++++++++++++--------------- resources/translations/zh_CN.ts | 138 ++++++++++++++++--------------- resources/translations/zh_TW.ts | 138 ++++++++++++++++--------------- 15 files changed, 1041 insertions(+), 901 deletions(-) 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 breaks Zvonek před přestávkami - - + + Bell after breaks Zvonek 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 threshold Hranice dlouhého pozastavení - + Short pause threshold Hranice 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 start Automatické 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 sound Zkuste restartovat Sane Break, pokud nejsou žádné zvuky - - - - + + + + Play Př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 battery Pozastavit 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 connected Pozastavit při připojení neznámého monitoru - + Mark currently connected monitors as known Označit právě připojené monitory jako známé - + Remove selected Odstranit 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 - - - - + + + + Browse Prochá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 file Konfigurační soubor - + Database file Soubor databáze - + Launch Sane Break at start up Spustit Sane Break při spuštění - + Get the Source Code Získat zdrojový kód - + Help Us Translate! Pomozte nám přeložit! - + Revert to Last Saved Vrátit se na poslední uložené - + Language Jazyk - + Change of language will take effect after app restart. Změna jazyka se projeví po restartu aplikace. - + Third-party Libraries Licenses Licence třetích stran - + Defaults Výchozí hodnoty - + Save Ulož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 - + Disabled Vypnuto - + Start next break after middle clicking on tray icon Začít další přestávku po stisku prostředního tlačítka na ikoně v panelu - + Start next break after double clicking on tray icon Začít další přestávku po dvojitém kliknutí na ikonu v panelu - + Save Uložit - + Discard Zahodit - + Cancel Zrušit - + Select Sound File Vybrat zvukový soubor - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) Zvukové soubory (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Chyba - + Failed to save a copy of the selected sound file. Nepodařilo se uložit kopii vybraného zvukového souboru. - + Select Background Image Vybrat 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 failed Nastavení 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 breaks Klang vor Pause - - + + Bell after breaks Klang nach Pause @@ -776,17 +776,17 @@ Alle Farben sind im <code>#AARRGGBB</code>-Format. <h3>Bedingungen fürs Pausieren</h3> - + Long pause threshold Schwellenwert lange Pause - + Short pause threshold Schwellenwert 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 start Automatische 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 sound Versuche, Sane Break neu zu starten, wenn kein Ton vorhanden ist - - - - + + + + Play Wiedergeben @@ -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 battery Bei 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 connected Pausieren, wenn ein unbekannter Monitor angeschlossen wird - + Mark currently connected monitors as known Derzeit angeschlossene Monitore als bekannt markieren - + Remove selected Ausgewä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 - - - - + + + + Browse Durchsuchen @@ -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 file Konfigurationsdatei - + Database file Datenbankdatei - + Launch Sane Break at start up Sane Break beim Start starten - + Get the Source Code Quellcode abrufen - + Help Us Translate! Helfen Sie uns zu übersetzen! - + Revert to Last Saved Auf zuletzt Gespeichertes zurücksetzen - + Language Sprache - + Change of language will take effect after app restart. Die Sprachänderung wirkt nach einem Neustart der App. - + Third-party Libraries Licenses Lizenzbedingungen von Drittanbieter-Bibliotheken - + Defaults Standardwerte - + Save Speichern @@ -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 - + Disabled Deaktiviert - + Start next break after middle clicking on tray icon Nächste Pause nach Mittelklick auf das Systemtray-Symbol starten - + Start next break after double clicking on tray icon Nächste Pause nach Doppelklick auf das Systemtray-Symbol starten - + Save Speichern - + Discard Verwerfen - + Cancel Abbrechen - + Select Sound File Sounddatei auswählen - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) Sounddateien (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Fehler - + Failed to save a copy of the selected sound file. Konnte keine Kopie der ausgewählten Sounddatei speichern. - + Select Background Image Hintergrundbild 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 failed Festlegen 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 breaks Sonido al comenzar descanso - - + + Bell after breaks Sonido 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 threshold Límite de la pausa larga - + Short pause threshold Lí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 start Bloqueo 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 sound Prueba a reiniciar Sane Break si no funciona el sonido - - - - + + + + Play Reproducir @@ -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 battery Pausar 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 connected Pausar cuando se conecte un monitor desconocido - + Mark currently connected monitors as known Marcar los monitores actualmente conectados como conocidos - + Remove selected Eliminar 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 - - - - + + + + Browse Examinar @@ -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 file Archivo de configuración - + Database file Archivo de base de datos - + Launch Sane Break at start up Ejecutar Sane Break al iniciar el ordenador - + Get the Source Code Ver el código fuente - + Help Us Translate! ¡Aúdanos a traducir! - + Revert to Last Saved Revertir a la última configuración guardada - + Language Idioma - + Change of language will take effect after app restart. El cambio de idioma tendrá efecto tras reiniciar la aplicación. - + Third-party Libraries Licenses Licencias de bibliotecas de terceros - + Defaults Valores por defecto - + Save Guardar @@ -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 - + Disabled Desactivado - + Start next break after middle clicking on tray icon Comenzar el siguiente descanso tras clicar con el botón central en el icono de la bandeja - + Start next break after double clicking on tray icon Comenzar el siguiente descanso tras hacer doble clic en el icono de la bandeja - + Save Guardar - + Discard Descartar - + Cancel Cancelar - + Select Sound File Seleccionar archivo de sonido - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) Archivos de sonido (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Error - + Failed to save a copy of the selected sound file. No se pudo guardar una copia del archivo de sonido seleccionado. - + Select Background Image Seleccionar 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 failed La 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 threshold Seuil d'une longue pause - + Short pause threshold Seuil 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 start Verrouillage 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 sound Si 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 breaks Son de cloche avant les pauses @@ -968,8 +968,8 @@ v%1 Durée d'une pause - - + + Bell after breaks Son 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 battery Mettre 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) - - - - + + + + Browse Parcourir @@ -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 connected Mettre en pause lorsque un moniteur inconnu est connecté - + Mark currently connected monitors as known Marquer les moniteurs actuellement connectés comme connus - + Remove selected Supprimer 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 file Fichier 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 file Fichier de base de données - + Launch Sane Break at start up Lancer Sane Break au démarrage de l'ordinateur - + Get the Source Code Obtenir le code source - + Help Us Translate! Aidez-nous à traduire ! - + Revert to Last Saved Revenir aux anciens paramètres sauvegardés - + Language Langue - + 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 Licenses Licences des bibliothèques tierces - + Defaults Paramètres par défaut - + Save Sauvegarder @@ -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 - + Disabled Désactivé - + Start next break after middle clicking on tray icon Dé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 icon Démarrer la pause suivante en faisant double-clic sur l'icône dans la barre des tâches - + Save Sauvegarder - + Discard Rejeter - + Cancel Annuler - + Select Sound File Sélectionner un fichier son - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) Fichiers son (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Erreur - + Failed to save a copy of the selected sound file. Échec de l’enregistrement d’une copie du fichier son sélectionné. - + Select Background Image Sé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 failed La 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 breaks Hangjelzés szünetek előtt - - + + Bell after breaks Hangjelzé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 threshold Hosszú szünet ideje - + Short pause threshold Rö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 start Ké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 sound Próbálja meg újraindítani a Sane Break-et, ha nincs hang - - - - + + + + Play Lejátszás @@ -864,7 +864,7 @@ v%1 - + <h3>Small Breaks</h3> <h3>Kis szünetek</h3> @@ -874,8 +874,8 @@ v%1 - - + + min perc @@ -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 battery Szü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 connected Szüneteltetés ismeretlen monitor csatlakoztatásakor - + Mark currently connected monitors as known Jelenleg csatlakoztatott monitorok megjelölése ismertként - + Remove selected Kijelö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 - - - - + + + + Browse Tallózás - + Configuration file Konfigurációs fájl - + Database file Adatbázis fájl - + Launch Sane Break at start up Sane Break indítása rendszerindításkor - + Get the Source Code Forráskód letöltése - + Help Us Translate! Segítsen a fordításban! - + Revert to Last Saved Visszaállítás az utolsó mentett állapotra - + Language Nyelv - + 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 Licenses Harmadik féltől származó könyvtárak licencei - + Defaults Alapértelmezések - + Save Mentés @@ -1123,9 +1133,9 @@ v%1 PreferenceWindow - - - + + + %n min %n perc @@ -1140,90 +1150,90 @@ v%1 - + %n sec %n mp - + Disabled Letiltva - + Start next break after middle clicking on tray icon Kö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 icon Következő szünet indítása a tálca ikon dupla kattintásával - + Save Mentés - + Discard Elvetés - + Cancel Mégse - + Select Sound File Hangfájl kiválasztása - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) Hangfájlok (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Hiba - + Failed to save a copy of the selected sound file. Nem sikerült menteni a kiválasztott hangfájl másolatát. - + Select Background Image Há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 failed Az 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 breaks Suono prima delle pause - - + + Bell after breaks Suono dopo le pause @@ -776,17 +776,17 @@ Tutti i colori sono in formato <code>#AARRGGBB</code>. <h3>Condizioni di pausa</h3> - + Long pause threshold Soglia pausa lunga - + Short pause threshold Soglia 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 start Blocco 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 sound Prova a riavviare Sane Break se non suona - - - - + + + + Play Riproduci @@ -873,7 +873,7 @@ v%1 - + <h3>Small Breaks</h3> <h3>Pause Brevi</h3> @@ -883,8 +883,8 @@ v%1 - - + + min min @@ -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 battery Pausa 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 connected Pausa quando viene collegato un monitor sconosciuto - + Mark currently connected monitors as known Contrassegna i monitor attualmente collegati come noti - + Remove selected Rimuovi 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 - - - - + + + + Browse Sfoglia @@ -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 file File di configurazione - + Database file File del database - + Launch Sane Break at start up Avvia Sane Break all'avvio - + Get the Source Code Ottieni il codice sorgente - + Help Us Translate! Aiutaci a tradurre! - + Revert to Last Saved Ripristina ultima impostazione salvata - + Language Lingua - + Change of language will take effect after app restart. Il cambio della lingua avrà effetto dopo il riavvio dell'app. - + Third-party Libraries Licenses Licenze librerie di terze parti - + Defaults Predefiniti - + Save Salva @@ -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 - + Disabled Disattivato - + Start next break after middle clicking on tray icon Inizia la prossima pausa dopo aver fatto clic col tasto centrale sull'icona nella barra - + Start next break after double clicking on tray icon Inizia la prossima pausa dopo aver fatto doppio clic sull'icona nella barra - + Save Salva - + Discard Scarta - + Cancel Annulla - + Select Sound File Seleziona file audio - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) File audio (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Errore - + Failed to save a copy of the selected sound file. Impossibile salvare una copia del file audio selezionato. - + Select Background Image Seleziona 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 failed Impostazione 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 threshold Drempelwaarde van lange pauze - + Short pause threshold Drempelwaarde 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 start Scherm 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 sound Herstart Sane Break als er geen geluid wordt afgespeeld - - - - + + + + Play Afspelen @@ -851,7 +851,7 @@ v%1 - + <h3>Small Breaks</h3> <h3>Korte pauzes</h3> @@ -861,14 +861,14 @@ v%1 - - + + min min. - - + + Bell before breaks Bel vóór pauzes @@ -993,8 +993,8 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat. Aftellen - - + + Bell after breaks Bel 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 battery Opschorten 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 file Configuratiebestand - + Launch Sane Break at start up Sane Break automatisch opstarten - + Get the Source Code Broncode bekijken - + Revert to Last Saved Vorig bewaard bestand terugzetten - + Language Taal @@ -1163,10 +1163,10 @@ Alle kleuren zijn in <code>#AARRGGBB</code>-formaat. - - - - + + + + Browse Bladeren @@ -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 connected Pauzeren wanneer een onbekende monitor wordt aangesloten - + Mark currently connected monitors as known Momenteel aangesloten monitoren markeren als bekend - + Remove selected Geselecteerde 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 file Databasebestand - + Third-party Libraries Licenses Licenties van externe bibliotheken - + Help Us Translate! Help ons vertalen! - + Defaults Standaardwaarden - + Save Opslaan @@ -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. - + Disabled Uitgeschakeld - + Start next break after middle clicking on tray icon Volgende pauze starten na middelklikken op systeemvakpictogram - + Start next break after double clicking on tray icon Volgende pauze starten na dubbelklikken op systeemvakpictogram - + Save Opslaan - + Discard Verwerpen - + Cancel Annuleren - + Select Sound File Geluidsbestand selecteren - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) Geluidsbestanden (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Fout - + Failed to save a copy of the selected sound file. Kan geen kopie van het geselecteerde geluidsbestand opslaan. - + Select Background Image Achtergrondafbeelding 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 failed Automatisch 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 breaks Dzwonek przed przerwami - - + + Bell after breaks Dzwonek po przerwach @@ -780,17 +780,17 @@ Wszystkie kolory są w formacie <code>#AARRGGBB</code>.<h3>Warunki pauzy</h3> - + Long pause threshold Próg długiej pauzy - + Short pause threshold Pró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 start Automatyczne 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 sound Spróbuj ponownie uruchomić Sane Break, jeśli nie ma dźwięku - - - - + + + + Play Odtwórz @@ -875,7 +875,7 @@ v%1 - + <h3>Small Breaks</h3> <h3>Krótkie przerwy</h3> @@ -885,8 +885,8 @@ v%1 - - + + min min @@ -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 battery Wstrzymaj 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 connected Wstrzymaj po podłączeniu nieznanego monitora - + Mark currently connected monitors as known Oznacz obecnie podłączone monitory jako znane - + Remove selected Usuń 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 - - - - + + + + Browse Przeglą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 file Plik konfiguracyjny - + Database file Plik bazy danych - + Launch Sane Break at start up Uruchamiaj Sane Break przy starcie - + Get the Source Code Pobierz kod źródłowy - + Help Us Translate! Pomóż nam przetłumaczyć! - + Revert to Last Saved Cofnij do ostatnio zapisanego - + Language Język - + Change of language will take effect after app restart. Zmiana języka wstępuje w życie po ponownym uruchomieniu aplikacji. - + Third-party Libraries Licenses Licencje bibliotek第三方 - + Defaults Domyślnie - + Save Zapisz @@ -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 - + Disabled Wyłączone - + Start next break after middle clicking on tray icon Rozpocznij następną przerwę po kliknięciu środkowym przyciskiem na ikonie zasobnika - + Start next break after double clicking on tray icon Rozpocznij następną przerwę po podwójnym kliknięciu na ikonie zasobnika - + Save Zapisz - + Discard Odrzuć - + Cancel Anuluj - + Select Sound File Wybierz plik dźwiękowy - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) Pliki dźwiękowe (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Błąd - + Failed to save a copy of the selected sound file. Nie udało się zapisać kopii wybranego pliku dźwiękowego. - + Select Background Image Wybierz 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 failed Ustawienie 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 breaks Ljudsignal före raster - - + + Bell after breaks Ljudsignal efter raster @@ -776,17 +776,17 @@ Alla färger är i formatet <code>#AARRGGBB</code>. <h3>Pausvillkor</h3> - + Long pause threshold Lång rastgräns - + Short pause threshold Kort 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 start Automatisk 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 sound Prova att starta om Sane Break om det inte hörs något ljud - - - - + + + + Play Spela @@ -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 battery Paus 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 connected Pausa när en okänd skärm ansluts - + Mark currently connected monitors as known Markera aktuellt anslutna skärmar som kända - + Remove selected Ta 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 - - - - + + + + Browse Blä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 file Konfigurationsfil - + Database file Databasfil - + Launch Sane Break at start up Starta Sane Break vid uppstart - + Get the Source Code Hämta källkoden - + Help Us Translate! Hjälp oss att översätta! - + Revert to Last Saved Återgå till senast sparade - + Language Språ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 Licenses Licenser för tredjepartsbibliotek - + Defaults Standard - + Save Spara @@ -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 - + Disabled Inaktiverad - + Start next break after middle clicking on tray icon Starta nästa rast efter att ha klickat med mittknappen på ikonen i aktivitetsfältet - + Start next break after double clicking on tray icon Starta nästa rast efter att ha dubbelklickat på ikonen i aktivitetsfältet - + Save Spara - + Discard Förkasta - + Cancel Avbryt - + Select Sound File Välj ljudfil - + Sound Files (*.mp3 *.wav *.ogg *.flac *.m4a) Ljudfiler (*.mp3 *.wav *.ogg *.flac *.m4a) - - + + Error Fel - + Failed to save a copy of the selected sound file. Det gick inte att spara en kopia av den valda ljudfilen. - + Select Background Image Vä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 failed Instä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? 是否保存修改? From 857bce700547fc31e9a65bf22d5ad4977c860db4 Mon Sep 17 00:00:00 2001 From: Allan Chain <36528777+AllanChain@users.noreply.github.com> Date: Sat, 18 Jul 2026 23:17:06 +0800 Subject: [PATCH 5/5] fix linux idle inhibitor detection --- src/idle/CMakeLists.txt | 6 +- src/idle/linux/factory.cpp | 67 ++++++-------- src/idle/linux/inhibitor-proxy-idle.cpp | 66 +++++++++++++ src/idle/linux/inhibitor-proxy-idle.h | 46 ++++++++++ src/idle/linux/linux-idle-inhibitor.cpp | 117 ++++++++++++++++++++++++ src/idle/linux/linux-idle-inhibitor.h | 41 +++++++++ src/idle/linux/logind-inhibitor.cpp | 69 -------------- src/idle/linux/logind-inhibitor.h | 34 ------- 8 files changed, 302 insertions(+), 144 deletions(-) create mode 100644 src/idle/linux/inhibitor-proxy-idle.cpp create mode 100644 src/idle/linux/inhibitor-proxy-idle.h create mode 100644 src/idle/linux/linux-idle-inhibitor.cpp create mode 100644 src/idle/linux/linux-idle-inhibitor.h delete mode 100644 src/idle/linux/logind-inhibitor.cpp delete mode 100644 src/idle/linux/logind-inhibitor.h diff --git a/src/idle/CMakeLists.txt b/src/idle/CMakeLists.txt index 66440c5b..893b65f9 100644 --- a/src/idle/CMakeLists.txt +++ b/src/idle/CMakeLists.txt @@ -12,8 +12,10 @@ add_library( if(CMAKE_SYSTEM_NAME STREQUAL "Linux") find_package(Qt6 REQUIRED COMPONENTS DBus) target_sources( - sane-idle PRIVATE linux/factory.h linux/factory.cpp linux/logind-inhibitor.h - linux/logind-inhibitor.cpp + 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) diff --git a/src/idle/linux/factory.cpp b/src/idle/linux/factory.cpp index b69512e6..6d720704 100644 --- a/src/idle/linux/factory.cpp +++ b/src/idle/linux/factory.cpp @@ -13,56 +13,45 @@ #include "core/idle-time.h" #include "idle/idle-interface.h" #include "idle/read-based-idle.h" -#include "logind-inhibitor.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); - // Mutter's GetIdletime is input-only; logind catches idle inhibitors (GNOME - // forwards its SessionManager/ScreenSaver inhibitors to logind). - auto* rbt = new ReadBasedIdleTime(parent, [reader]() { return reader->read(); }); - auto* logind = new LogindInhibitor(parent); - rbt->setInhibitor([logind]() { return logind->isIdleInhibited(); }); - return rbt; - } - 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); - // X11: the ScreenSaverDisabled heuristic (XScreenSaverSuspend) is free in the - // same call as idle, and logind catches D-Bus inhibitors that forward to it. auto* rbt = new ReadBasedIdleTime(parent, [reader]() { return reader->read(); }); - auto* logind = new LogindInhibitor(parent); 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/logind-inhibitor.cpp b/src/idle/linux/logind-inhibitor.cpp deleted file mode 100644 index 3bae9e7a..00000000 --- a/src/idle/linux/logind-inhibitor.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// 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 "logind-inhibitor.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Each inhibitor is (what, who, why, mode, pid, uid). -using InhibitorTuple = std::tuple; - -LogindInhibitor::LogindInhibitor(QObject* parent) : QObject(parent) { - QDBusConnection bus = QDBusConnection::systemBus(); - // We only need the service if it's actually on the bus; otherwise refresh() is a - // no-op and we stay "not inhibited". - if (!bus.interface()->isServiceRegistered("org.freedesktop.login1")) return; - - // Re-scan whenever the set of active block locks changes (event-driven, no polling). - bus.connect("org.freedesktop.login1", "/org/freedesktop/login1", - "org.freedesktop.DBus.Properties", "PropertiesChanged", this, - SLOT(refresh())); - refresh(); -} - -void LogindInhibitor::refresh() { - QDBusInterface login1("org.freedesktop.login1", "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", QDBusConnection::systemBus()); - - bool inhibited = false; - - // Prefer the per-inhibitor list: an inhibitor is relevant iff `what` contains - // "idle" and it is a "block" lock (delay locks don't prevent idle). - QDBusReply> reply = login1.call("ListInhibitors"); - if (reply.isValid()) { - for (const InhibitorTuple& inhibitor : reply.value()) { - const QString& what = std::get<0>(inhibitor); - const QString& mode = std::get<3>(inhibitor); - if (what.split(u':').contains("idle", Qt::CaseSensitive) && mode == "block") { - inhibited = true; - break; - } - } - } else { - // ListInhibitors unavailable (old systemd): fall back to the BlockInhibited - // property, a colon-separated string of active block-lock types. - QDBusReply prop = - login1.call("Get", "org.freedesktop.login1.Manager", "BlockInhibited"); - if (prop.isValid()) { - inhibited = prop.value().variant().toString().split(u':').contains( - "idle", Qt::CaseSensitive); - } - } - - if (inhibited != m_inhibited) - qDebug() << "idle: logind inhibitor" << (inhibited ? "active" : "released"); - m_inhibited = inhibited; -} diff --git a/src/idle/linux/logind-inhibitor.h b/src/idle/linux/logind-inhibitor.h deleted file mode 100644 index 4eb2f813..00000000 --- a/src/idle/linux/logind-inhibitor.h +++ /dev/null @@ -1,34 +0,0 @@ -// 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/display inhibitors via logind on the system bus. -// -// logind subsumes the GNOME SessionManager inhibit path (GNOME forwards its -// inhibitors to logind) and is DE-agnostic, so the same code covers GNOME-Wayland, -// wlroots/KDE Wayland (D-Bus callers) and X11. Used as the cached bool flag feeding -// IdleReader for polling backends. -// -// The inhibitor *list* (`ListInhibitors`) is not polkit-gated; in Flatpak it needs -// `--system-talk-name=org.freedesktop.login1`. We subscribe to the `BlockInhibited` -// property (a colon-separated string of active block-lock types) which emits -// PropertiesChanged on change, then re-scan ListInhibitors — event-driven, no polling. -class LogindInhibitor : public QObject { - Q_OBJECT - public: - explicit LogindInhibitor(QObject* parent = nullptr); - // Cached flag: is there at least one active block-lock inhibitor whose `what` - // contains "idle"? Refreshed from the BlockInhibited property and ListInhibitors. - bool isIdleInhibited() const { return m_inhibited; } - - private slots: - void refresh(); - - private: - bool m_inhibited = false; -};