dbus: support ScreenSaver interface

This commit is contained in:
Vaxry 2024-02-17 23:24:01 +00:00
parent 55410176d4
commit 9320017b63
3 changed files with 107 additions and 10 deletions

View file

@ -27,6 +27,7 @@ void CConfigManager::init() {
m_config.addConfigValue("general:lock_cmd", Hyprlang::STRING{""}); m_config.addConfigValue("general:lock_cmd", Hyprlang::STRING{""});
m_config.addConfigValue("general:unlock_cmd", Hyprlang::STRING{""}); m_config.addConfigValue("general:unlock_cmd", Hyprlang::STRING{""});
m_config.addConfigValue("general:before_sleep_cmd", Hyprlang::STRING{""}); m_config.addConfigValue("general:before_sleep_cmd", Hyprlang::STRING{""});
m_config.addConfigValue("general:ignore_dbus_inhibit", Hyprlang::INT{0});
m_config.commence(); m_config.commence();

View file

@ -93,11 +93,15 @@ void CHypridle::enterEventLoop() {
.fd = wl_display_get_fd(m_sWaylandState.display), .fd = wl_display_get_fd(m_sWaylandState.display),
.events = POLLIN, .events = POLLIN,
}, },
{
.fd = m_sDBUSState.screenSaverServiceConnection ? m_sDBUSState.screenSaverServiceConnection->getEventLoopPollData().fd : 0,
.events = POLLIN,
},
}; };
std::thread pollThr([this, &pollfds]() { std::thread pollThr([this, &pollfds]() {
while (1) { while (1) {
int ret = poll(pollfds, 2, 5000 /* 5 seconds, reasonable. It's because we might need to terminate */); int ret = poll(pollfds, m_sDBUSState.screenSaverServiceConnection ? 3 : 2, 5000 /* 5 seconds, reasonable. It's because we might need to terminate */);
if (ret < 0) { if (ret < 0) {
Debug::log(CRIT, "[core] Polling fds failed with {}", errno); Debug::log(CRIT, "[core] Polling fds failed with {}", errno);
m_bTerminate = true; m_bTerminate = true;
@ -159,6 +163,13 @@ void CHypridle::enterEventLoop() {
} }
} }
if (pollfds[2].revents & POLLIN /* dbus2 */) {
Debug::log(TRACE, "got dbus event");
while (m_sDBUSState.screenSaverServiceConnection->processPendingRequest()) {
;
}
}
// finalize wayland dispatching. Dispatch pending on the queue // finalize wayland dispatching. Dispatch pending on the queue
int ret = 0; int ret = 0;
do { do {
@ -268,6 +279,27 @@ void CHypridle::onResumed(SIdleListener* pListener) {
spawn(pListener->onRestore); spawn(pListener->onRestore);
} }
void CHypridle::onInhibit(bool lock) {
m_iInhibitLocks += lock ? 1 : -1;
if (m_iInhibitLocks < 0)
Debug::log(WARN, "BUG THIS: inhibit locks < 0");
else
Debug::log(LOG, "Inhibit locks: {}", m_iInhibitLocks);
}
CHypridle::SDbusInhibitCookie CHypridle::getDbusInhibitCookie(uint32_t cookie) {
for (auto& c : m_sDBUSState.inhibitCookies) {
if (c.cookie == cookie)
return c;
}
return {};
}
void CHypridle::registerDbusInhibitCookie(CHypridle::SDbusInhibitCookie& cookie) {
m_sDBUSState.inhibitCookies.push_back(cookie);
}
void handleDbusLogin(sdbus::Message& msg) { void handleDbusLogin(sdbus::Message& msg) {
// lock & unlock // lock & unlock
static auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:lock_cmd"); static auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:lock_cmd");
@ -310,6 +342,46 @@ void handleDbusSleep(sdbus::Message& msg) {
spawn(*PSLEEPCMD); spawn(*PSLEEPCMD);
} }
void handleDbusScreensaver(sdbus::MethodCall call, bool inhibit) {
std::string app = "?", reason = "?";
if (inhibit) {
call >> app;
call >> reason;
} else {
uint32_t cookie = 0;
call >> cookie;
const auto COOKIE = g_pHypridle->getDbusInhibitCookie(cookie);
if (COOKIE.cookie == 0) {
Debug::log(WARN, "No cookie in uninhibit");
} else {
app = COOKIE.app;
reason = COOKIE.reason;
}
}
Debug::log(LOG, "ScreenSaver inhibit: {} dbus message from {} with content {}", inhibit, app, reason);
static auto* const PIGNORE = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:ignore_dbus_inhibit");
if (!**PIGNORE) {
if (inhibit)
g_pHypridle->onInhibit(true);
else
g_pHypridle->onInhibit(false);
}
static int cookieID = 1337;
if (inhibit) {
auto reply = call.createReply();
reply << uint32_t{cookieID++};
reply.send();
Debug::log(LOG, "Cookie {} sent", cookieID - 1);
}
}
void CHypridle::setupDBUS() { void CHypridle::setupDBUS() {
auto proxy = sdbus::createProxy("org.freedesktop.login1", "/org/freedesktop/login1"); auto proxy = sdbus::createProxy("org.freedesktop.login1", "/org/freedesktop/login1");
auto method = proxy->createMethodCall("org.freedesktop.login1.Manager", "GetSession"); auto method = proxy->createMethodCall("org.freedesktop.login1.Manager", "GetSession");
@ -323,4 +395,15 @@ void CHypridle::setupDBUS() {
m_sDBUSState.connection->addMatch("type='signal',path='" + path + "',interface='org.freedesktop.login1.Session'", handleDbusLogin, sdbus::floating_slot_t{}); m_sDBUSState.connection->addMatch("type='signal',path='" + path + "',interface='org.freedesktop.login1.Session'", handleDbusLogin, sdbus::floating_slot_t{});
m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.login1.Manager'", handleDbusSleep, sdbus::floating_slot_t{}); m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.login1.Manager'", handleDbusSleep, sdbus::floating_slot_t{});
// attempt to register as ScreenSaver
try {
m_sDBUSState.screenSaverServiceConnection = sdbus::createSessionBusConnection("org.freedesktop.ScreenSaver");
m_sDBUSState.screenSaverObject = sdbus::createObject(*m_sDBUSState.screenSaverServiceConnection, "/org/freedesktop/ScreenSaver");
m_sDBUSState.screenSaverObject->registerMethod("org.freedesktop.ScreenSaver", "Inhibit", "ss", "u", [&](sdbus::MethodCall c) { handleDbusScreensaver(c, true); });
m_sDBUSState.screenSaverObject->registerMethod("org.freedesktop.ScreenSaver", "UnInhibit", "u", "", [&](sdbus::MethodCall c) { handleDbusScreensaver(c, false); });
m_sDBUSState.screenSaverObject->finishRegistration();
} catch (std::exception& e) { Debug::log(ERR, "Failed registering for /org/freedesktop/ScreenSaver, perhaps taken?\nerr: {}", e.what()); }
} }

View file

@ -17,6 +17,11 @@ class CHypridle {
std::string onRestore = ""; std::string onRestore = "";
}; };
struct SDbusInhibitCookie {
uint32_t cookie = 0;
std::string app, reason;
};
void run(); void run();
void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version); void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
@ -25,11 +30,17 @@ class CHypridle {
void onIdled(SIdleListener*); void onIdled(SIdleListener*);
void onResumed(SIdleListener*); void onResumed(SIdleListener*);
void onInhibit(bool lock);
SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie);
void registerDbusInhibitCookie(SDbusInhibitCookie& cookie);
private: private:
void setupDBUS(); void setupDBUS();
void enterEventLoop(); void enterEventLoop();
bool m_bTerminate = false; bool m_bTerminate = false;
int64_t m_iInhibitLocks = 0;
struct { struct {
wl_display* display = nullptr; wl_display* display = nullptr;
@ -45,7 +56,9 @@ class CHypridle {
struct { struct {
std::unique_ptr<sdbus::IConnection> connection; std::unique_ptr<sdbus::IConnection> connection;
sdbus::Slot login1match; std::unique_ptr<sdbus::IConnection> screenSaverServiceConnection;
std::unique_ptr<sdbus::IObject> screenSaverObject;
std::vector<SDbusInhibitCookie> inhibitCookies;
} m_sDBUSState; } m_sDBUSState;
struct { struct {