From 7d56597f027341fe7f48e7368ef4da4d87065574 Mon Sep 17 00:00:00 2001 From: rewine Date: Fri, 14 Feb 2025 18:00:32 +0800 Subject: [PATCH] feat: support idlenotify idleinhibit and outputpowermanagement Log: protocols used for idle behavior such as screen blanking, locking, and screensaving --- src/seat/helper.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++ src/seat/helper.h | 13 +++++++ 2 files changed, 95 insertions(+) diff --git a/src/seat/helper.cpp b/src/seat/helper.cpp index 2e0d979c..ddb9caac 100644 --- a/src/seat/helper.cpp +++ b/src/seat/helper.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include #include @@ -77,6 +78,9 @@ #include #include #include +#include +#include +#include #include #include @@ -468,6 +472,71 @@ void Helper::onOutputTestOrApply(qw_output_configuration_v1 *config, bool onlyTe m_outputManager->sendResult(config, ok); } +void Helper::onSetOutputPowerMode(wlr_output_power_v1_set_mode_event *event) +{ + auto output = qw_output::from(event->output); + qw_output_state newState; + + switch (event->mode) { + case ZWLR_OUTPUT_POWER_V1_MODE_OFF: + if (!output->handle()->enabled) { + return; + } + newState.set_enabled(false); + output->commit_state(newState); + break; + case ZWLR_OUTPUT_POWER_V1_MODE_ON: + if (output->handle()->enabled) { + return; + } + newState.set_enabled(true); + output->commit_state(newState); + break; + } +} + +void Helper::onNewIdleInhibitor(wlr_idle_inhibitor_v1 *wlr_inhibitor) +{ + auto inhibitor = qw_idle_inhibitor_v1::from(wlr_inhibitor); + m_idleInhibitors.append(inhibitor); + + connect(inhibitor, &qw_idle_inhibitor_v1::before_destroy, this, [this, inhibitor]() { + m_idleInhibitors.removeOne(inhibitor); + updateIdleInhibitor(); + }); + + auto wsurface = WSurface::fromHandle(wlr_inhibitor->surface); + connect(wsurface, &WSurface::mappedChanged, inhibitor, [this]() { + updateIdleInhibitor(); + }); + + auto toplevel = WXdgToplevelSurface::fromSurface(wsurface); + if (toplevel) { + connect(toplevel, &WXdgToplevelSurface::minimizeChanged, inhibitor, [this]() { + updateIdleInhibitor(); + }); + } + + updateIdleInhibitor(); +} + +void Helper::updateIdleInhibitor() +{ + for (const auto &inhibitor : std::as_const(m_idleInhibitors)) { + auto wsurface = WSurface::fromHandle((*inhibitor)->surface); + bool visible = wsurface->mapped(); + auto toplevel = WXdgToplevelSurface::fromSurface(wsurface); + if (toplevel) + visible &= !toplevel->isMinimized(); + + if (visible) { + m_idleNotifier->set_inhibited(true); + return; + } + } + m_idleNotifier->set_inhibited(false); +} + void Helper::onDockPreview(std::vector surfaces, WSurface *target, QPoint pos, @@ -994,6 +1063,16 @@ void Helper::init() QMetaObject::invokeMethod(m_dockPreview, "close"); }); + + m_idleNotifier = qw_idle_notifier_v1::create(*m_server->handle()); + + m_idleInhibitManager = qw_idle_inhibit_manager_v1::create(*m_server->handle()); + connect(m_idleInhibitManager, &qw_idle_inhibit_manager_v1::notify_new_inhibitor, this, &Helper::onNewIdleInhibitor); + + m_outputPowerManager = qw_output_power_manager_v1::create(*m_server->handle()); + + connect(m_outputPowerManager, &qw_output_power_manager_v1::notify_set_mode, this, &Helper::onSetOutputPowerMode); + m_backend->handle()->start(); qCInfo(qLcHelper) << "Listing on:" << m_socket->fullServerName(); @@ -1080,6 +1159,9 @@ void Helper::fakePressSurfaceBottomRightToReszie(SurfaceWrapper *surface) bool Helper::beforeDisposeEvent(WSeat *seat, QWindow *, QInputEvent *event) { + if (event->isInputEvent()) { + m_idleNotifier->notify_activity(seat->nativeHandle()); + } // NOTE: Unable to distinguish meta from other key combinations // For example, Meta+S will still receive Meta release after // fully releasing the key, actively detect whether there are diff --git a/src/seat/helper.h b/src/seat/helper.h index 185e840e..dfee4f04 100644 --- a/src/seat/helper.h +++ b/src/seat/helper.h @@ -56,7 +56,11 @@ QW_BEGIN_NAMESPACE class qw_renderer; class qw_allocator; class qw_compositor; +class qw_idle_notifier_v1; +class qw_idle_inhibit_manager_v1; class qw_output_configuration_v1; +class qw_output_power_manager_v1; +class qw_idle_inhibitor_v1; QW_END_NAMESPACE WAYLIB_SERVER_USE_NAMESPACE @@ -84,6 +88,8 @@ class IMultitaskView; class LockScreenInterface; class ILockScreen; class UserModel; +struct wlr_idle_inhibitor_v1; +struct wlr_output_power_v1_set_mode_event; class Helper : public WSeatEventFilter { @@ -220,6 +226,8 @@ private Q_SLOTS: void onSurfaceModeChanged(WSurface *surface, WXdgDecorationManager::DecorationMode mode); void setGamma(struct wlr_gamma_control_manager_v1_set_gamma_event *event); void onOutputTestOrApply(qw_output_configuration_v1 *config, bool onlyTest); + void onSetOutputPowerMode(wlr_output_power_v1_set_mode_event *event); + void onNewIdleInhibitor(wlr_idle_inhibitor_v1 *inhibitor); void onDockPreview(std::vector surfaces, WSurface *target, QPoint pos, @@ -272,6 +280,7 @@ private Q_SLOTS: bool isNvidiaCardPresent(); void setWorkspaceVisible(bool visible); void restoreFromShowDesktop(SurfaceWrapper *activeSurface = nullptr); + void updateIdleInhibitor(); static Helper *m_instance; @@ -295,6 +304,9 @@ private Q_SLOTS: // protocols qw_compositor *m_compositor = nullptr; + qw_idle_notifier_v1 *m_idleNotifier = nullptr; + qw_idle_inhibit_manager_v1 *m_idleInhibitManager = nullptr; + qw_output_power_manager_v1 *m_outputPowerManager = nullptr; ShellHandler *m_shellHandler = nullptr; WXWayland *m_defaultXWayland = nullptr; WXdgDecorationManager *m_xdgDecorationManager = nullptr; @@ -313,6 +325,7 @@ private Q_SLOTS: // private data QList m_outputList; QPointer m_taskSwitch; + QList m_idleInhibitors; SurfaceWrapper *m_activatedSurface = nullptr; RootSurfaceContainer *m_rootSurfaceContainer = nullptr;