fix: notice input on the lock screen despite idle inhibitors
This commit is contained in:
1 parent
7c87adb733
commit
77ae883b98
12 files changed
+280
-38
No files matched your search
@@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: Install the build tools
|
- name: Install the build tools
|
||||||
run: |
|
run: |
|
||||||
pacman -Syu --noconfirm --needed git base-devel cmake pkgconf \
|
pacman -Syu --noconfirm --needed git base-devel cmake pkgconf \
|
||||||
qt6-base qt6-declarative layer-shell-qt kidletime ki18n \
|
qt6-base qt6-declarative layer-shell-qt ki18n \
|
||||||
opencv pam systemd-libs gettext scdoc shellcheck desktop-file-utils
|
opencv pam systemd-libs gettext scdoc shellcheck desktop-file-utils
|
||||||
|
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ jobs:
|
|||||||
git make cmake gcc-c++ gettext scdoc tar curl rpm-build rpm-sign systemd-rpm-macros \
|
git make cmake gcc-c++ gettext scdoc tar curl rpm-build rpm-sign systemd-rpm-macros \
|
||||||
'pkgconfig(systemd)' 'pkgconfig(libsystemd)' pam-devel opencv-devel \
|
'pkgconfig(systemd)' 'pkgconfig(libsystemd)' pam-devel opencv-devel \
|
||||||
qt6-qtbase-devel qt6-qtbase-private-devel qt6-qtdeclarative-devel qt6-qtwayland-devel \
|
qt6-qtbase-devel qt6-qtbase-private-devel qt6-qtdeclarative-devel qt6-qtwayland-devel \
|
||||||
layer-shell-qt-devel kf6-kidletime-devel kf6-ki18n-devel
|
layer-shell-qt-devel kf6-ki18n-devel
|
||||||
|
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -136,7 +136,6 @@ if(PFU_BUILD_AGENT)
|
|||||||
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
||||||
find_package(Qt6 REQUIRED COMPONENTS GuiPrivate WaylandClientPrivate)
|
find_package(Qt6 REQUIRED COMPONENTS GuiPrivate WaylandClientPrivate)
|
||||||
find_package(LayerShellQt REQUIRED)
|
find_package(LayerShellQt REQUIRED)
|
||||||
find_package(KF6IdleTime REQUIRED)
|
|
||||||
find_package(KF6I18n REQUIRED)
|
find_package(KF6I18n REQUIRED)
|
||||||
|
|
||||||
qt_add_executable(plasma-face-unlock-agent
|
qt_add_executable(plasma-face-unlock-agent
|
||||||
@@ -147,6 +146,7 @@ if(PFU_BUILD_AGENT)
|
|||||||
src/agent/bubblewindow.cpp
|
src/agent/bubblewindow.cpp
|
||||||
src/agent/bubblecontroller.cpp
|
src/agent/bubblecontroller.cpp
|
||||||
src/agent/lockcontroller.cpp
|
src/agent/lockcontroller.cpp
|
||||||
|
src/agent/inputwatcher.cpp
|
||||||
src/agent/enrollcontroller.cpp
|
src/agent/enrollcontroller.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(plasma-face-unlock-agent PRIVATE src/agent)
|
target_include_directories(plasma-face-unlock-agent PRIVATE src/agent)
|
||||||
@@ -155,7 +155,8 @@ if(PFU_BUILD_AGENT)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt6_generate_wayland_protocol_client_sources(plasma-face-unlock-agent
|
qt6_generate_wayland_protocol_client_sources(plasma-face-unlock-agent
|
||||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/protocols/kde-lockscreen-overlay-v1.xml)
|
FILES ${CMAKE_CURRENT_SOURCE_DIR}/protocols/kde-lockscreen-overlay-v1.xml
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/protocols/ext-idle-notify-v1.xml)
|
||||||
|
|
||||||
# The QML files sit next to the module's qmldir in the resources, so they
|
# The QML files sit next to the module's qmldir in the resources, so they
|
||||||
# see each other (and the Theme singleton) without importing anything.
|
# see each other (and the Theme singleton) without importing anything.
|
||||||
@@ -189,7 +190,7 @@ if(PFU_BUILD_AGENT)
|
|||||||
Qt6::Gui Qt6::GuiPrivate Qt6::Quick Qt6::DBus Qt6::Network
|
Qt6::Gui Qt6::GuiPrivate Qt6::Quick Qt6::DBus Qt6::Network
|
||||||
Qt6::WaylandClient Qt6::WaylandClientPrivate
|
Qt6::WaylandClient Qt6::WaylandClientPrivate
|
||||||
LayerShellQt::Interface
|
LayerShellQt::Interface
|
||||||
KF6::IdleTime KF6::I18n KF6::I18nQml
|
KF6::I18n KF6::I18nQml
|
||||||
pfu_common
|
pfu_common
|
||||||
)
|
)
|
||||||
install(TARGETS plasma-face-unlock-agent DESTINATION ${PFU_LIBEXECDIR})
|
install(TARGETS plasma-face-unlock-agent DESTINATION ${PFU_LIBEXECDIR})
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ sudo make install
|
|||||||
```
|
```
|
||||||
|
|
||||||
Needs CMake, a C++20 compiler, Qt 6 (Core, DBus, Network, Gui, Quick, WaylandClient), LayerShellQt,
|
Needs CMake, a C++20 compiler, Qt 6 (Core, DBus, Network, Gui, Quick, WaylandClient), LayerShellQt,
|
||||||
KIdleTime, KI18n, OpenCV 4.5.4 or newer with the DNN module, Linux-PAM and libsystemd. Optionally
|
KI18n, OpenCV 4.5.4 or newer with the DNN module, Linux-PAM and libsystemd. Optionally
|
||||||
`msgfmt` (gettext) for translations and `scdoc` for the man page. Supports `PREFIX` and `DESTDIR`.
|
`msgfmt` (gettext) for translations and `scdoc` for the man page. Supports `PREFIX` and `DESTDIR`.
|
||||||
`make check` runs syntax checks and shellcheck.
|
`make check` runs syntax checks and shellcheck.
|
||||||
|
|
||||||
|
|||||||
@@ -171,7 +171,9 @@ The agent watches for the screen to lock (org.freedesktop.ScreenSaver) and
|
|||||||
scans when somebody comes back:
|
scans when somebody comes back:
|
||||||
|
|
||||||
- on any key or mouse movement after the screen locked, once 1.5 seconds have
|
- on any key or mouse movement after the screen locked, once 1.5 seconds have
|
||||||
passed (the key that locked it does not count);
|
passed (the key that locked it does not count). Enter on the empty password
|
||||||
|
field is a key like any other. This works while a video or an app keeps the
|
||||||
|
screen on, too (ext_idle_notifier_v1, input notification);
|
||||||
- when the machine wakes from sleep;
|
- when the machine wakes from sleep;
|
||||||
- right after locking, if *Look right after the screen locks* is on. Off by
|
- right after locking, if *Look right after the screen locks* is on. Off by
|
||||||
default: whoever locks their screen on purpose is usually still in front of
|
default: whoever locks their screen on purpose is usually still in front of
|
||||||
@@ -256,7 +258,7 @@ _$XDG_RUNTIME_DIR/plasma-face-unlock/agent.socket_
|
|||||||
# REQUIREMENTS
|
# REQUIREMENTS
|
||||||
|
|
||||||
KDE Plasma 6 on Wayland, a camera, OpenCV 4.5.4 or newer with its DNN module,
|
KDE Plasma 6 on Wayland, a camera, OpenCV 4.5.4 or newer with its DNN module,
|
||||||
Qt 6, LayerShellQt, KIdleTime, KI18n, systemd, polkit and Linux-PAM.
|
Qt 6, LayerShellQt, KI18n, systemd, polkit and Linux-PAM.
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ arch=('x86_64' 'aarch64')
|
|||||||
url="https://github.com/LoonixTools/plasma-face-unlock"
|
url="https://github.com/LoonixTools/plasma-face-unlock"
|
||||||
license=('GPL-3.0-or-later' 'MIT' 'Apache-2.0')
|
license=('GPL-3.0-or-later' 'MIT' 'Apache-2.0')
|
||||||
depends=('bash' 'coreutils' 'gawk' 'grep' 'sed' 'gettext' 'systemd' 'systemd-libs' 'pam' 'polkit'
|
depends=('bash' 'coreutils' 'gawk' 'grep' 'sed' 'gettext' 'systemd' 'systemd-libs' 'pam' 'polkit'
|
||||||
'opencv' 'qt6-base' 'qt6-declarative' 'layer-shell-qt' 'kidletime' 'ki18n' 'kscreenlocker')
|
'opencv' 'qt6-base' 'qt6-declarative' 'layer-shell-qt' 'ki18n' 'kscreenlocker')
|
||||||
makedepends=('cmake' 'scdoc')
|
makedepends=('cmake' 'scdoc')
|
||||||
install="${pkgname}.install"
|
install="${pkgname}.install"
|
||||||
source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz"
|
source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz"
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ BuildRequires: cmake(Qt6WaylandClient)
|
|||||||
BuildRequires: qt6-qtbase-private-devel
|
BuildRequires: qt6-qtbase-private-devel
|
||||||
BuildRequires: qt6-qtwayland-devel
|
BuildRequires: qt6-qtwayland-devel
|
||||||
BuildRequires: cmake(LayerShellQt)
|
BuildRequires: cmake(LayerShellQt)
|
||||||
BuildRequires: cmake(KF6IdleTime)
|
|
||||||
BuildRequires: cmake(KF6I18n)
|
BuildRequires: cmake(KF6I18n)
|
||||||
|
|
||||||
Requires: bash >= 4.2
|
Requires: bash >= 4.2
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="ext_idle_notify_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2015 Martin Gräßlin
|
||||||
|
Copyright © 2022 Simon Ser
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<interface name="ext_idle_notifier_v1" version="2">
|
||||||
|
<description summary="idle notification manager">
|
||||||
|
This interface allows clients to monitor user idle status.
|
||||||
|
|
||||||
|
After binding to this global, clients can create ext_idle_notification_v1
|
||||||
|
objects to get notified when the user is idle for a given amount of time.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the manager">
|
||||||
|
Destroy the manager object. All objects created via this interface
|
||||||
|
remain valid.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="get_idle_notification">
|
||||||
|
<description summary="create a notification object">
|
||||||
|
Create a new idle notification object.
|
||||||
|
|
||||||
|
The notification object has a minimum timeout duration and is tied to a
|
||||||
|
seat. The client will be notified if the seat is inactive for at least
|
||||||
|
the provided timeout. See ext_idle_notification_v1 for more details.
|
||||||
|
|
||||||
|
A zero timeout is valid and means the client wants to be notified as
|
||||||
|
soon as possible when the seat is inactive.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="ext_idle_notification_v1"/>
|
||||||
|
<arg name="timeout" type="uint" summary="minimum idle timeout in msec"/>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<!-- Version 2 additions -->
|
||||||
|
|
||||||
|
<request name="get_input_idle_notification" since="2">
|
||||||
|
<description summary="create a notification object">
|
||||||
|
Create a new idle notification object to track input from the
|
||||||
|
user, such as keyboard and mouse movement. Because this object is
|
||||||
|
meant to track user input alone, it ignores idle inhibitors.
|
||||||
|
|
||||||
|
The notification object has a minimum timeout duration and is tied to a
|
||||||
|
seat. The client will be notified if the seat is inactive for at least
|
||||||
|
the provided timeout. See ext_idle_notification_v1 for more details.
|
||||||
|
|
||||||
|
A zero timeout is valid and means the client wants to be notified as
|
||||||
|
soon as possible when the seat is inactive.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="ext_idle_notification_v1"/>
|
||||||
|
<arg name="timeout" type="uint" summary="minimum idle timeout in msec"/>
|
||||||
|
<arg name="seat" type="object" interface="wl_seat"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="ext_idle_notification_v1" version="2">
|
||||||
|
<description summary="idle notification">
|
||||||
|
This interface is used by the compositor to send idle notification events
|
||||||
|
to clients.
|
||||||
|
|
||||||
|
Initially the notification object is not idle. The notification object
|
||||||
|
becomes idle when no user activity has happened for at least the timeout
|
||||||
|
duration, starting from the creation of the notification object. User
|
||||||
|
activity may include input events or a presence sensor, but is
|
||||||
|
compositor-specific.
|
||||||
|
|
||||||
|
How this notification responds to idle inhibitors depends on how
|
||||||
|
it was constructed. If constructed from the
|
||||||
|
get_idle_notification request, then if an idle inhibitor is
|
||||||
|
active (e.g. another client has created a zwp_idle_inhibitor_v1
|
||||||
|
on a visible surface), the compositor must not make the
|
||||||
|
notification object idle. However, if constructed from the
|
||||||
|
get_input_idle_notification request, then idle inhibitors are
|
||||||
|
ignored, and only input from the user, e.g. from a keyboard or
|
||||||
|
mouse, counts as activity.
|
||||||
|
|
||||||
|
When the notification object becomes idle, an idled event is sent. When
|
||||||
|
user activity starts again, the notification object stops being idle,
|
||||||
|
a resumed event is sent and the timeout is restarted.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the notification object">
|
||||||
|
Destroy the notification object.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="idled">
|
||||||
|
<description summary="notification object is idle">
|
||||||
|
This event is sent when the notification object becomes idle.
|
||||||
|
|
||||||
|
It's a compositor protocol error to send this event twice without a
|
||||||
|
resumed event in-between.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="resumed">
|
||||||
|
<description summary="notification object is no longer idle">
|
||||||
|
This event is sent when the notification object stops being idle.
|
||||||
|
|
||||||
|
It's a compositor protocol error to send this event twice without an
|
||||||
|
idled event in-between. It's a compositor protocol error to send this
|
||||||
|
event prior to any idled event.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "inputwatcher.h"
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QWaylandClientExtensionTemplate>
|
||||||
|
#include <QtGui/qguiapplication_platform.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "qwayland-ext-idle-notify-v1.h"
|
||||||
|
|
||||||
|
class IdleNotifier : public QWaylandClientExtensionTemplate<IdleNotifier>, public QtWayland::ext_idle_notifier_v1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IdleNotifier()
|
||||||
|
: QWaylandClientExtensionTemplate<IdleNotifier>(2)
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
~IdleNotifier() override
|
||||||
|
{
|
||||||
|
if (isActive()) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IdleNotification : public QtWayland::ext_idle_notification_v1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IdleNotification(::ext_idle_notification_v1 *object, std::function<void()> resumed)
|
||||||
|
: QtWayland::ext_idle_notification_v1(object)
|
||||||
|
, m_resumed(std::move(resumed))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~IdleNotification() override
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Only ever sent after idled: calm first, then this.
|
||||||
|
void ext_idle_notification_v1_resumed() override
|
||||||
|
{
|
||||||
|
if (!m_fired) {
|
||||||
|
m_fired = true;
|
||||||
|
m_resumed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::function<void()> m_resumed;
|
||||||
|
bool m_fired = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
InputWatcher::InputWatcher(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_notifier(std::make_unique<IdleNotifier>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
InputWatcher::~InputWatcher() = default;
|
||||||
|
|
||||||
|
void InputWatcher::watch(int calmMs)
|
||||||
|
{
|
||||||
|
m_notification.reset();
|
||||||
|
auto *wayland = qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
|
||||||
|
if (!m_notifier->isActive() || !wayland || !wayland->seat()) {
|
||||||
|
qWarning("no ext_idle_notifier_v1, so no telling when somebody comes back");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Version 1 has only the notification that inhibitors hold back.
|
||||||
|
::ext_idle_notification_v1 *object = m_notifier->QWaylandClientExtension::version() >= 2
|
||||||
|
? m_notifier->get_input_idle_notification(uint32_t(calmMs), wayland->seat())
|
||||||
|
: m_notifier->get_idle_notification(uint32_t(calmMs), wayland->seat());
|
||||||
|
// Queued: not from inside the Wayland event, which the receiver might
|
||||||
|
// answer by watching anew and so destroying the notification.
|
||||||
|
m_notification = std::make_unique<IdleNotification>(object, [this] {
|
||||||
|
QMetaObject::invokeMethod(this, &InputWatcher::input, Qt::QueuedConnection);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputWatcher::stop()
|
||||||
|
{
|
||||||
|
m_notification.reset();
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
//
|
||||||
|
// Somebody touching the machine: a key, a click, the mouse, the touchpad.
|
||||||
|
//
|
||||||
|
// From ext_idle_notifier_v1, like KIdleTime, but with the input notification
|
||||||
|
// of version 2. KIdleTime's own honours idle inhibitors: with a video playing
|
||||||
|
// or an app keeping the screen on, no key reached it and the lock screen never
|
||||||
|
// scanned.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class IdleNotifier;
|
||||||
|
class IdleNotification;
|
||||||
|
|
||||||
|
class InputWatcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit InputWatcher(QObject *parent = nullptr);
|
||||||
|
~InputWatcher() override;
|
||||||
|
|
||||||
|
// Emit input() once, for the first input after nothing was touched for
|
||||||
|
// calmMs. 0: the next input. Replaces what was watched before.
|
||||||
|
void watch(int calmMs);
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void input();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<IdleNotifier> m_notifier;
|
||||||
|
std::unique_ptr<IdleNotification> m_notification;
|
||||||
|
};
|
||||||
@@ -6,8 +6,6 @@
|
|||||||
#include "daemonclient.h"
|
#include "daemonclient.h"
|
||||||
#include "userconfig.h"
|
#include "userconfig.h"
|
||||||
|
|
||||||
#include <KIdleTime>
|
|
||||||
|
|
||||||
#include <QDBusConnection>
|
#include <QDBusConnection>
|
||||||
#include <QDBusMessage>
|
#include <QDBusMessage>
|
||||||
#include <QDBusPendingCallWatcher>
|
#include <QDBusPendingCallWatcher>
|
||||||
@@ -38,7 +36,10 @@ LockController::LockController(BubbleController *bubble, UserConfig *config, QOb
|
|||||||
, m_config(config)
|
, m_config(config)
|
||||||
{
|
{
|
||||||
m_armTimer.setSingleShot(true);
|
m_armTimer.setSingleShot(true);
|
||||||
connect(&m_armTimer, &QTimer::timeout, this, &LockController::arm);
|
connect(&m_armTimer, &QTimer::timeout, this, [this] {
|
||||||
|
arm(0);
|
||||||
|
});
|
||||||
|
connect(&m_input, &InputWatcher::input, this, &LockController::onResume);
|
||||||
|
|
||||||
QDBusConnection session = QDBusConnection::sessionBus();
|
QDBusConnection session = QDBusConnection::sessionBus();
|
||||||
session.connect(QStringLiteral("org.freedesktop.ScreenSaver"),
|
session.connect(QStringLiteral("org.freedesktop.ScreenSaver"),
|
||||||
@@ -55,17 +56,6 @@ LockController::LockController(BubbleController *bubble, UserConfig *config, QOb
|
|||||||
this,
|
this,
|
||||||
SLOT(onPrepareForSleep(bool)));
|
SLOT(onPrepareForSleep(bool)));
|
||||||
|
|
||||||
KIdleTime *idle = KIdleTime::instance();
|
|
||||||
connect(idle, &KIdleTime::resumingFromIdle, this, &LockController::onResume);
|
|
||||||
connect(idle, qOverload<int, int>(&KIdleTime::timeoutReached), this, [this, idle](int id, int) {
|
|
||||||
if (id != m_idleId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
idle->removeIdleTimeout(id);
|
|
||||||
m_idleId = -1;
|
|
||||||
arm();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Started while the screen is already locked (the agent restarted).
|
// Started while the screen is already locked (the agent restarted).
|
||||||
const QDBusMessage get = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.ScreenSaver"),
|
const QDBusMessage get = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.ScreenSaver"),
|
||||||
QStringLiteral("/ScreenSaver"),
|
QStringLiteral("/ScreenSaver"),
|
||||||
@@ -86,16 +76,10 @@ void LockController::onActiveChanged(bool active)
|
|||||||
if (active == m_locked) {
|
if (active == m_locked) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
KIdleTime *idle = KIdleTime::instance();
|
|
||||||
|
|
||||||
if (!active) {
|
if (!active) {
|
||||||
m_locked = false;
|
m_locked = false;
|
||||||
m_armTimer.stop();
|
m_armTimer.stop();
|
||||||
if (m_idleId >= 0) {
|
m_input.stop();
|
||||||
idle->removeIdleTimeout(m_idleId);
|
|
||||||
m_idleId = -1;
|
|
||||||
}
|
|
||||||
idle->stopCatchingResumeEvent();
|
|
||||||
if (m_scan) {
|
if (m_scan) {
|
||||||
m_scan->abort();
|
m_scan->abort();
|
||||||
m_scan->deleteLater();
|
m_scan->deleteLater();
|
||||||
@@ -148,12 +132,12 @@ void LockController::onPrepareForSleep(bool sleeping)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LockController::arm()
|
void LockController::arm(int calmMs)
|
||||||
{
|
{
|
||||||
if (!m_locked || m_stopped || !m_config->scanOnWake()) {
|
if (!m_locked || m_stopped || !m_config->scanOnWake()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
KIdleTime::instance()->catchNextResumeEvent();
|
m_input.watch(calmMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LockController::onResume()
|
void LockController::onResume()
|
||||||
@@ -221,9 +205,7 @@ void LockController::onScanFinished(const QJsonObject &result)
|
|||||||
m_armTimer.start(GraceAfterLockMs);
|
m_armTimer.start(GraceAfterLockMs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_idleId < 0) {
|
arm(CalmBeforeRetryMs);
|
||||||
m_idleId = KIdleTime::instance()->addIdleTimeout(CalmBeforeRetryMs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LockController::unlock()
|
void LockController::unlock()
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "inputwatcher.h"
|
||||||
|
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
@@ -44,7 +46,8 @@ private Q_SLOTS:
|
|||||||
void onPrepareForSleep(bool sleeping);
|
void onPrepareForSleep(bool sleeping);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void arm();
|
// Scan at the next input after calmMs without any.
|
||||||
|
void arm(int calmMs);
|
||||||
void onResume();
|
void onResume();
|
||||||
void startScan(const QString &why);
|
void startScan(const QString &why);
|
||||||
void onScanFinished(const QJsonObject &result);
|
void onScanFinished(const QJsonObject &result);
|
||||||
@@ -58,5 +61,5 @@ private:
|
|||||||
QElapsedTimer m_lockedFor;
|
QElapsedTimer m_lockedFor;
|
||||||
QPointer<DaemonRequest> m_scan;
|
QPointer<DaemonRequest> m_scan;
|
||||||
QTimer m_armTimer;
|
QTimer m_armTimer;
|
||||||
int m_idleId = -1;
|
InputWatcher m_input;
|
||||||
};
|
};
|
||||||
Reference in new issue
Block a user