Skip to content

Commit

Permalink
dbus: support ScreenSaver interface
Browse files Browse the repository at this point in the history
  • Loading branch information
vaxerski committed Feb 17, 2024
1 parent 5541017 commit 9320017
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ void CConfigManager::init() {
m_config.addConfigValue("general:lock_cmd", Hyprlang::STRING{""});
m_config.addConfigValue("general:unlock_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();

Expand Down
85 changes: 84 additions & 1 deletion src/core/Hypridle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,15 @@ void CHypridle::enterEventLoop() {
.fd = wl_display_get_fd(m_sWaylandState.display),
.events = POLLIN,
},
{
.fd = m_sDBUSState.screenSaverServiceConnection ? m_sDBUSState.screenSaverServiceConnection->getEventLoopPollData().fd : 0,
.events = POLLIN,
},
};

std::thread pollThr([this, &pollfds]() {
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) {
Debug::log(CRIT, "[core] Polling fds failed with {}", errno);
m_bTerminate = true;
Expand Down Expand Up @@ -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
int ret = 0;
do {
Expand Down Expand Up @@ -268,6 +279,27 @@ void CHypridle::onResumed(SIdleListener* pListener) {
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) {
// lock & unlock
static auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:lock_cmd");
Expand Down Expand Up @@ -310,6 +342,46 @@ void handleDbusSleep(sdbus::Message& msg) {
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() {
auto proxy = sdbus::createProxy("org.freedesktop.login1", "/org/freedesktop/login1");
auto method = proxy->createMethodCall("org.freedesktop.login1.Manager", "GetSession");
Expand All @@ -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='/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()); }
}
31 changes: 22 additions & 9 deletions src/core/Hypridle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,30 @@ class CHypridle {
std::string onRestore = "";
};

void run();
struct SDbusInhibitCookie {
uint32_t cookie = 0;
std::string app, reason;
};

void run();

void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
void onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name);

void onIdled(SIdleListener*);
void onResumed(SIdleListener*);

void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
void onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name);
void onInhibit(bool lock);

void onIdled(SIdleListener*);
void onResumed(SIdleListener*);
SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie);
void registerDbusInhibitCookie(SDbusInhibitCookie& cookie);

private:
void setupDBUS();
void enterEventLoop();
void setupDBUS();
void enterEventLoop();

bool m_bTerminate = false;
bool m_bTerminate = false;
int64_t m_iInhibitLocks = 0;

struct {
wl_display* display = nullptr;
Expand All @@ -45,7 +56,9 @@ class CHypridle {

struct {
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;

struct {
Expand Down

0 comments on commit 9320017

Please sign in to comment.