aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xCMakeLists.txt2
-rw-r--r--protocols/idle.xml49
-rw-r--r--protocols/meson.build2
-rw-r--r--src/Compositor.cpp9
-rw-r--r--src/Compositor.hpp3
-rw-r--r--src/includes.hpp1
-rw-r--r--src/managers/ProtocolManager.cpp3
-rw-r--r--src/managers/input/IdleInhibitor.cpp19
-rw-r--r--src/managers/input/InputManager.cpp9
-rw-r--r--src/managers/input/Tablets.cpp9
-rw-r--r--src/managers/input/Touch.cpp3
-rw-r--r--src/protocols/IdleNotify.cpp104
-rw-r--r--src/protocols/IdleNotify.hpp55
13 files changed, 186 insertions, 82 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 23d2b085..6d0d1437 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -249,7 +249,6 @@ target_link_libraries(Hyprland
uuid
)
-protocol("protocols/idle.xml" "idle" true)
protocol("protocols/tablet-unstable-v2.xml" "tablet-unstable-v2" true)
protocol("protocols/wlr-layer-shell-unstable-v1.xml" "wlr-layer-shell-unstable-v1" true)
protocol("protocols/wlr-screencopy-unstable-v1.xml" "wlr-screencopy-unstable-v1" true)
@@ -276,6 +275,7 @@ protocolNew("unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unst
protocolNew("unstable/text-input/text-input-unstable-v3.xml" "text-input-unstable-v3" false)
protocolNew("unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" "pointer-constraints-unstable-v1" false)
protocolNew("staging/xdg-activation/xdg-activation-v1.xml" "xdg-activation-v1" false)
+protocolNew("staging/ext-idle-notify/ext-idle-notify-v1.xml" "ext-idle-notify-v1" false)
# tools
add_subdirectory(hyprctl)
diff --git a/protocols/idle.xml b/protocols/idle.xml
deleted file mode 100644
index 92d9989c..00000000
--- a/protocols/idle.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<protocol name="idle">
- <copyright><![CDATA[
- Copyright (C) 2015 Martin Gräßlin
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- ]]></copyright>
- <interface name="org_kde_kwin_idle" version="1">
- <description summary="User idle time manager">
- This interface allows to monitor user idle time on a given seat. The interface
- allows to register timers which trigger after no user activity was registered
- on the seat for a given interval. It notifies when user activity resumes.
-
- This is useful for applications wanting to perform actions when the user is not
- interacting with the system, e.g. chat applications setting the user as away, power
- management features to dim screen, etc..
- </description>
- <request name="get_idle_timeout">
- <arg name="id" type="new_id" interface="org_kde_kwin_idle_timeout"/>
- <arg name="seat" type="object" interface="wl_seat"/>
- <arg name="timeout" type="uint" summary="The idle timeout in msec"/>
- </request>
- </interface>
- <interface name="org_kde_kwin_idle_timeout" version="1">
- <request name="release" type="destructor">
- <description summary="release the timeout object"/>
- </request>
- <request name="simulate_user_activity">
- <description summary="Simulates user activity for this timeout, behaves just like real user activity on the seat"/>
- </request>
- <event name="idle">
- <description summary="Triggered when there has not been any user activity in the requested idle time interval"/>
- </event>
- <event name="resumed">
- <description summary="Triggered on the first user activity after an idle event"/>
- </event>
- </interface>
-</protocol>
diff --git a/protocols/meson.build b/protocols/meson.build
index 6e7ae666..3b4c4dd1 100644
--- a/protocols/meson.build
+++ b/protocols/meson.build
@@ -30,7 +30,6 @@ protocols = [
['wlr-layer-shell-unstable-v1.xml'],
['wlr-screencopy-unstable-v1.xml'],
['tablet-unstable-v2.xml'],
- ['idle.xml'],
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'],
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml']
]
@@ -53,6 +52,7 @@ new_protocols = [
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'],
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
+ [wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'],
]
wl_protos_src = []
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index d1b41e1d..b8358cbe 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -237,8 +237,6 @@ void CCompositor::initServer() {
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
- m_sWLRIdleNotifier = wlr_idle_notifier_v1_create(m_sWLDisplay);
-
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay, 4);
m_sWLRServerDecoMgr = wlr_server_decoration_manager_create(m_sWLDisplay);
@@ -2701,13 +2699,6 @@ PHLWINDOW CCompositor::getForceFocus() {
return nullptr;
}
-void CCompositor::notifyIdleActivity() {
- wlr_idle_notifier_v1_notify_activity(g_pCompositor->m_sWLRIdleNotifier, g_pCompositor->m_sSeat.seat);
-}
-
-void CCompositor::setIdleActivityInhibit(bool enabled) {
- wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled);
-}
void CCompositor::arrangeMonitors() {
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index bfb347af..d0acad4d 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -52,7 +52,6 @@ class CCompositor {
wlr_drm* m_sWRLDRM;
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
wlr_output_layout* m_sWLROutputLayout;
- wlr_idle_notifier_v1* m_sWLRIdleNotifier;
wlr_layer_shell_v1* m_sWLRLayerShell;
wlr_xdg_shell* m_sWLRXDGShell;
wlr_cursor* m_sWLRCursor;
@@ -185,8 +184,6 @@ class CCompositor {
void performUserChecks();
void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace);
PHLWINDOW getForceFocus();
- void notifyIdleActivity();
- void setIdleActivityInhibit(bool inhibit);
void arrangeMonitors();
void enterUnsafeState();
void leaveUnsafeState();
diff --git a/src/includes.hpp b/src/includes.hpp
index cdb38bd7..d6f98a88 100644
--- a/src/includes.hpp
+++ b/src/includes.hpp
@@ -92,7 +92,6 @@ extern "C" {
#include <wlr/backend/wayland.h>
#include <wlr/types/wlr_session_lock_v1.h>
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
-#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/util/box.h>
#include <wlr/util/transform.h>
#include <wlr/render/swapchain.h>
diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp
index b00e111e..b721f17a 100644
--- a/src/managers/ProtocolManager.cpp
+++ b/src/managers/ProtocolManager.cpp
@@ -17,6 +17,7 @@
#include "../protocols/PointerConstraints.hpp"
#include "../protocols/OutputPower.hpp"
#include "../protocols/XDGActivation.hpp"
+#include "../protocols/IdleNotify.hpp"
#include "tearing-control-v1.hpp"
#include "fractional-scale-v1.hpp"
@@ -35,6 +36,7 @@
#include "pointer-constraints-unstable-v1.hpp"
#include "wlr-output-power-management-unstable-v1.hpp"
#include "xdg-activation-v1.hpp"
+#include "ext-idle-notify-v1.hpp"
CProtocolManager::CProtocolManager() {
@@ -55,6 +57,7 @@ CProtocolManager::CProtocolManager() {
PROTO::constraints = std::make_unique<CPointerConstraintsProtocol>(&zwp_pointer_constraints_v1_interface, 1, "PointerConstraints");
PROTO::outputPower = std::make_unique<COutputPowerProtocol>(&zwlr_output_power_manager_v1_interface, 1, "OutputPower");
PROTO::activation = std::make_unique<CXDGActivationProtocol>(&xdg_activation_v1_interface, 1, "XDGActivation");
+ PROTO::idle = std::make_unique<CIdleNotifyProtocol>(&ext_idle_notifier_v1_interface, 1, "IdleNotify");
// Old protocol implementations.
// TODO: rewrite them to use hyprwayland-scanner.
diff --git a/src/managers/input/IdleInhibitor.cpp b/src/managers/input/IdleInhibitor.cpp
index 6ec5fc81..40c8c637 100644
--- a/src/managers/input/IdleInhibitor.cpp
+++ b/src/managers/input/IdleInhibitor.cpp
@@ -1,6 +1,7 @@
#include "InputManager.hpp"
#include "../../Compositor.hpp"
#include "../../protocols/IdleInhibit.hpp"
+#include "../../protocols/IdleNotify.hpp"
void CInputManager::newIdleInhibitor(std::any inhibitor) {
const auto PINHIBIT = m_vIdleInhibitors.emplace_back(std::make_unique<SIdleInhibitor>()).get();
@@ -29,11 +30,11 @@ void CInputManager::newIdleInhibitor(std::any inhibitor) {
void CInputManager::recheckIdleInhibitorStatus() {
for (auto& ii : m_vIdleInhibitors) {
- if (ii->pWindow.expired()) {
- g_pCompositor->setIdleActivityInhibit(false);
- return;
- } else if (g_pHyprRenderer->shouldRenderWindow(ii->pWindow.lock())) {
- g_pCompositor->setIdleActivityInhibit(false);
+ if (ii->pWindow.expired())
+ continue;
+
+ if (g_pHyprRenderer->shouldRenderWindow(ii->pWindow.lock())) {
+ PROTO::idle->setInhibit(true);
return;
}
}
@@ -44,21 +45,21 @@ void CInputManager::recheckIdleInhibitorStatus() {
continue;
if (w->m_eIdleInhibitMode == IDLEINHIBIT_ALWAYS) {
- g_pCompositor->setIdleActivityInhibit(false);
+ PROTO::idle->setInhibit(true);
return;
}
if (w->m_eIdleInhibitMode == IDLEINHIBIT_FOCUS && g_pCompositor->isWindowActive(w)) {
- g_pCompositor->setIdleActivityInhibit(false);
+ PROTO::idle->setInhibit(true);
return;
}
if (w->m_eIdleInhibitMode == IDLEINHIBIT_FULLSCREEN && w->m_bIsFullscreen && g_pCompositor->isWorkspaceVisible(w->m_pWorkspace)) {
- g_pCompositor->setIdleActivityInhibit(false);
+ PROTO::idle->setInhibit(true);
return;
}
}
- g_pCompositor->setIdleActivityInhibit(true);
+ PROTO::idle->setInhibit(false);
return;
}
diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp
index adfa5029..47dc2bf6 100644
--- a/src/managers/input/InputManager.cpp
+++ b/src/managers/input/InputManager.cpp
@@ -8,6 +8,7 @@
#include "../../protocols/IdleInhibit.hpp"
#include "../../protocols/RelativePointer.hpp"
#include "../../protocols/PointerConstraints.hpp"
+#include "../../protocols/IdleNotify.hpp"
CInputManager::CInputManager() {
m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) {
@@ -144,7 +145,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED);
if (time)
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
@@ -480,7 +481,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
EMIT_HOOK_EVENT_CANCELLABLE("mouseButton", e);
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
m_tmrLastCursorMovement.reset();
@@ -705,7 +706,7 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
bool passEvent = g_pKeybindManager->onAxisEvent(e);
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
if (!passEvent)
return;
@@ -1216,7 +1217,7 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
bool passEvent = g_pKeybindManager->onKeyEvent(e, pKeyboard);
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
if (passEvent) {
diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp
index d60a6a6f..979eb1a7 100644
--- a/src/managers/input/Tablets.cpp
+++ b/src/managers/input/Tablets.cpp
@@ -1,5 +1,6 @@
#include "InputManager.hpp"
#include "../../Compositor.hpp"
+#include "../../protocols/IdleNotify.hpp"
void CInputManager::newTabletTool(wlr_input_device* pDevice) {
const auto PNEWTABLET = &m_lTablets.emplace_back();
@@ -99,7 +100,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
if (EVENT->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y))
wlr_tablet_v2_tablet_tool_notify_tilt(PTOOL->wlrTabletToolV2, PTOOL->tiltX, PTOOL->tiltY);
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
},
PNEWTABLET, "Tablet");
@@ -120,7 +121,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
wlr_send_tablet_v2_tablet_tool_up(PTOOL->wlrTabletToolV2);
}
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
},
PNEWTABLET, "Tablet");
@@ -132,7 +133,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
wlr_tablet_v2_tablet_tool_notify_button(PTOOL->wlrTabletToolV2, (zwp_tablet_pad_v2_button_state)EVENT->button, (zwp_tablet_pad_v2_button_state)EVENT->state);
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
},
PNEWTABLET, "Tablet");
@@ -158,7 +159,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
g_pInputManager->focusTablet(PTAB, EVENT->tool);
}
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
},
PNEWTABLET, "Tablet");
diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp
index 302d9e1d..a3f28ac0 100644
--- a/src/managers/input/Touch.cpp
+++ b/src/managers/input/Touch.cpp
@@ -1,6 +1,7 @@
#include "InputManager.hpp"
#include "../../Compositor.hpp"
#include "../../config/ConfigValue.hpp"
+#include "../../protocols/IdleNotify.hpp"
void CInputManager::onTouchDown(wlr_touch_down_event* e) {
static auto PSWIPETOUCH = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_touch");
@@ -83,7 +84,7 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, m_sTouchData.touchFocusSurface, e->time_msec, e->touch_id, local.x, local.y);
- g_pCompositor->notifyIdleActivity();
+ PROTO::idle->onActivity();
}
void CInputManager::onTouchUp(wlr_touch_up_event* e) {
diff --git a/src/protocols/IdleNotify.cpp b/src/protocols/IdleNotify.cpp
new file mode 100644
index 00000000..950fbf06
--- /dev/null
+++ b/src/protocols/IdleNotify.cpp
@@ -0,0 +1,104 @@
+#include "IdleNotify.hpp"
+#include "../managers/eventLoop/EventLoopManager.hpp"
+
+#define LOGM PROTO::idle->protoLog
+
+static int onTimer(std::shared_ptr<CEventLoopTimer> self, void* data) {
+
+ const auto NOTIF = (CExtIdleNotification*)data;
+
+ NOTIF->onTimerFired();
+
+ return 0;
+}
+
+CExtIdleNotification::CExtIdleNotification(SP<CExtIdleNotificationV1> resource_, uint32_t timeoutMs_) : resource(resource_), timeoutMs(timeoutMs_) {
+ if (!resource_->resource())
+ return;
+
+ resource->setDestroy([this](CExtIdleNotificationV1* r) { PROTO::idle->destroyNotification(this); });
+ resource->setOnDestroy([this](CExtIdleNotificationV1* r) { PROTO::idle->destroyNotification(this); });
+
+ timer = std::make_shared<CEventLoopTimer>(std::nullopt, onTimer, this);
+ g_pEventLoopManager->addTimer(timer);
+
+ updateTimer();
+
+ LOGM(LOG, "Registered idle-notification for {}ms", timeoutMs_);
+}
+
+CExtIdleNotification::~CExtIdleNotification() {
+ g_pEventLoopManager->removeTimer(timer);
+ timer.reset();
+}
+
+bool CExtIdleNotification::good() {
+ return resource->resource();
+}
+
+void CExtIdleNotification::updateTimer() {
+ if (PROTO::idle->isInhibited)
+ timer->updateTimeout(std::nullopt);
+ else
+ timer->updateTimeout(std::chrono::milliseconds(timeoutMs));
+}
+
+void CExtIdleNotification::onTimerFired() {
+ resource->sendIdled();
+ idled = true;
+}
+
+void CExtIdleNotification::onActivity() {
+ if (idled)
+ resource->sendResumed();
+
+ idled = false;
+ updateTimer();
+}
+
+CIdleNotifyProtocol::CIdleNotifyProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ ;
+}
+
+void CIdleNotifyProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CExtIdleNotifierV1>(client, ver, id)).get();
+ RESOURCE->setOnDestroy([this](CExtIdleNotifierV1* p) { this->onManagerResourceDestroy(p->resource()); });
+
+ RESOURCE->setDestroy([this](CExtIdleNotifierV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); });
+ RESOURCE->setGetIdleNotification([this](CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat) { this->onGetNotification(pMgr, id, timeout, seat); });
+}
+
+void CIdleNotifyProtocol::onManagerResourceDestroy(wl_resource* res) {
+ std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; });
+}
+
+void CIdleNotifyProtocol::destroyNotification(CExtIdleNotification* notif) {
+ std::erase_if(m_vNotifications, [&](const auto& other) { return other.get() == notif; });
+}
+
+void CIdleNotifyProtocol::onGetNotification(CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat) {
+ const auto CLIENT = wl_resource_get_client(pMgr->resource());
+ const auto RESOURCE =
+ m_vNotifications
+ .emplace_back(std::make_unique<CExtIdleNotification>(std::make_shared<CExtIdleNotificationV1>(CLIENT, wl_resource_get_version(pMgr->resource()), id), timeout))
+ .get();
+
+ if (!RESOURCE->good()) {
+ wl_resource_post_no_memory(pMgr->resource());
+ m_vNotifications.pop_back();
+ return;
+ }
+}
+
+void CIdleNotifyProtocol::onActivity() {
+ for (auto& n : m_vNotifications) {
+ n->onActivity();
+ }
+}
+
+void CIdleNotifyProtocol::setInhibit(bool inhibited) {
+ isInhibited = inhibited;
+ for (auto& n : m_vNotifications) {
+ n->onActivity();
+ }
+} \ No newline at end of file
diff --git a/src/protocols/IdleNotify.hpp b/src/protocols/IdleNotify.hpp
new file mode 100644
index 00000000..c1c7b62d
--- /dev/null
+++ b/src/protocols/IdleNotify.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <unordered_map>
+#include "WaylandProtocol.hpp"
+#include "ext-idle-notify-v1.hpp"
+
+class CEventLoopTimer;
+
+class CExtIdleNotification {
+ public:
+ CExtIdleNotification(SP<CExtIdleNotificationV1> resource_, uint32_t timeoutMs);
+ ~CExtIdleNotification();
+
+ bool good();
+ void onTimerFired();
+ void onActivity();
+
+ private:
+ SP<CExtIdleNotificationV1> resource;
+ uint32_t timeoutMs = 0;
+ std::shared_ptr<CEventLoopTimer> timer;
+
+ bool idled = false;
+
+ void updateTimer();
+};
+
+class CIdleNotifyProtocol : public IWaylandProtocol {
+ public:
+ CIdleNotifyProtocol(const wl_interface* iface, const int& ver, const std::string& name);
+
+ virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
+
+ void onActivity();
+ void setInhibit(bool inhibited);
+
+ private:
+ void onManagerResourceDestroy(wl_resource* res);
+ void destroyNotification(CExtIdleNotification* notif);
+ void onGetNotification(CExtIdleNotifierV1* pMgr, uint32_t id, uint32_t timeout, wl_resource* seat);
+
+ bool isInhibited = false;
+
+ //
+ std::vector<UP<CExtIdleNotifierV1>> m_vManagers;
+ std::vector<SP<CExtIdleNotification>> m_vNotifications;
+
+ friend class CExtIdleNotification;
+};
+
+namespace PROTO {
+ inline UP<CIdleNotifyProtocol> idle;
+};