core: move to sdbus-cpp2 (#278)

* core: move to sdbus-cpp2

* oopsie LMAO

* thing

* nix/overlays: add sdbus overlay

---------

Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
Vaxry 2024-10-22 18:45:24 +01:00 committed by GitHub
parent fb9c8d665a
commit 5c72a7fea1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 161 additions and 251 deletions

View file

@ -68,7 +68,7 @@ pkg_check_modules(
hyprwayland-scanner>=0.4.2) hyprwayland-scanner>=0.4.2)
# check whether we can find sdbus-c++ through pkg-config # check whether we can find sdbus-c++ through pkg-config
pkg_check_modules(SDBUS IMPORTED_TARGET sdbus-c++) pkg_check_modules(SDBUS IMPORTED_TARGET sdbus-c++>=2.0.0)
if(NOT SDBUS_FOUND) if(NOT SDBUS_FOUND)
include_directories("subprojects/sdbus-cpp/include/") include_directories("subprojects/sdbus-cpp/include/")
add_subdirectory(subprojects/sdbus-cpp EXCLUDE_FROM_ALL) add_subdirectory(subprojects/sdbus-cpp EXCLUDE_FROM_ALL)

View file

@ -22,6 +22,7 @@ in {
inputs.hyprland-protocols.overlays.default inputs.hyprland-protocols.overlays.default
inputs.hyprutils.overlays.default inputs.hyprutils.overlays.default
inputs.hyprwayland-scanner.overlays.default inputs.hyprwayland-scanner.overlays.default
self.overlays.sdbuscpp
]); ]);
xdg-desktop-portal-hyprland = lib.composeManyExtensions [ xdg-desktop-portal-hyprland = lib.composeManyExtensions [
(final: prev: { (final: prev: {
@ -32,4 +33,17 @@ in {
}; };
}) })
]; ];
sdbuscpp = final: prev: {
sdbus-cpp = prev.sdbus-cpp.overrideAttrs (self: super: {
version = "2.0.0";
src = final.fetchFromGitHub {
owner = "Kistler-group";
repo = "sdbus-cpp";
rev = "refs/tags/v${self.version}";
hash = "sha256-W8V5FRhV3jtERMFrZ4gf30OpIQLYoj2yYGpnYOmH2+g=";
};
});
};
} }

View file

@ -201,7 +201,7 @@ void CPortalManager::init() {
m_iPID = getpid(); m_iPID = getpid();
try { try {
m_pConnection = sdbus::createSessionBusConnection("org.freedesktop.impl.portal.desktop.hyprland"); m_pConnection = sdbus::createSessionBusConnection(sdbus::ServiceName{"org.freedesktop.impl.portal.desktop.hyprland"});
} catch (std::exception& e) { } catch (std::exception& e) {
Debug::log(CRIT, "Couldn't create the dbus connection ({})", e.what()); Debug::log(CRIT, "Couldn't create the dbus connection ({})", e.what());
exit(1); exit(1);
@ -367,7 +367,7 @@ void CPortalManager::startEventLoop() {
m_mEventLock.lock(); m_mEventLock.lock();
if (pollfds[0].revents & POLLIN /* dbus */) { if (pollfds[0].revents & POLLIN /* dbus */) {
while (m_pConnection->processPendingRequest()) { while (m_pConnection->processPendingEvent()) {
; ;
} }
} }

View file

@ -20,6 +20,7 @@
#include "wlr-screencopy-unstable-v1.hpp" #include "wlr-screencopy-unstable-v1.hpp"
#include "../includes.hpp" #include "../includes.hpp"
#include "../dbusDefines.hpp"
#include <mutex> #include <mutex>

5
src/dbusDefines.hpp Normal file
View file

@ -0,0 +1,5 @@
#pragma once
#include <sdbus-c++/sdbus-c++.h>
typedef std::tuple<uint32_t, std::unordered_map<std::string, sdbus::Variant>> dbUasv;

View file

@ -58,9 +58,3 @@ bool inShellPath(const std::string& exec) {
return std::ranges::any_of(paths, [&exec](std::string& path) { return access((path + "/" + exec).c_str(), X_OK) == 0; }); return std::ranges::any_of(paths, [&exec](std::string& path) { return access((path + "/" + exec).c_str(), X_OK) == 0; });
} }
void sendEmptyDbusMethodReply(sdbus::MethodCall& call, u_int32_t responseCode) {
auto reply = call.createReply();
reply << (uint32_t)responseCode;
reply.send();
}

View file

@ -65,15 +65,8 @@ SKeybind* CGlobalShortcutsPortal::registerShortcut(SSession* session, const DBus
return PSHORTCUT; return PSHORTCUT;
} }
void CGlobalShortcutsPortal::onCreateSession(sdbus::MethodCall& call) { dbUasv CGlobalShortcutsPortal::onCreateSession(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID,
sdbus::ObjectPath requestHandle, sessionHandle; std::unordered_map<std::string, sdbus::Variant> opts) {
call >> requestHandle;
call >> sessionHandle;
std::string appID;
call >> appID;
Debug::log(LOG, "[globalshortcuts] New session:"); Debug::log(LOG, "[globalshortcuts] New session:");
Debug::log(LOG, "[globalshortcuts] | {}", requestHandle.c_str()); Debug::log(LOG, "[globalshortcuts] | {}", requestHandle.c_str());
Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str()); Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str());
@ -87,9 +80,6 @@ void CGlobalShortcutsPortal::onCreateSession(sdbus::MethodCall& call) {
PSESSION->request = createDBusRequest(requestHandle); PSESSION->request = createDBusRequest(requestHandle);
PSESSION->request->onDestroy = [PSESSION]() { PSESSION->request.release(); }; PSESSION->request->onDestroy = [PSESSION]() { PSESSION->request.release(); };
std::unordered_map<std::string, sdbus::Variant> opts;
call >> opts;
for (auto& [k, v] : opts) { for (auto& [k, v] : opts) {
if (k == "shortcuts") { if (k == "shortcuts") {
PSESSION->registered = true; PSESSION->registered = true;
@ -104,59 +94,43 @@ void CGlobalShortcutsPortal::onCreateSession(sdbus::MethodCall& call) {
} }
} }
auto reply = call.createReply(); return {0, {}};
reply << (uint32_t)0;
reply << std::unordered_map<std::string, sdbus::Variant>{};
reply.send();
} }
void CGlobalShortcutsPortal::onBindShortcuts(sdbus::MethodCall& call) { dbUasv CGlobalShortcutsPortal::onBindShortcuts(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::vector<DBusShortcut> shortcuts, std::string appID,
sdbus::ObjectPath sessionHandle, requestHandle; std::unordered_map<std::string, sdbus::Variant> opts) {
call >> requestHandle;
call >> sessionHandle;
Debug::log(LOG, "[globalshortcuts] Bind keys:"); Debug::log(LOG, "[globalshortcuts] Bind keys:");
Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str()); Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str());
std::vector<DBusShortcut> shortcuts;
std::vector<DBusShortcut> shortcutsToReturn;
call >> shortcuts;
const auto PSESSION = getSession(sessionHandle); const auto PSESSION = getSession(sessionHandle);
if (!PSESSION) { if (!PSESSION) {
Debug::log(ERR, "[globalshortcuts] No session?"); Debug::log(ERR, "[globalshortcuts] No session?");
return; return {1, {}};
} }
std::vector<DBusShortcut> shortcutsToReturn;
PSESSION->registered = true; PSESSION->registered = true;
for (auto& s : shortcuts) { for (auto& s : shortcuts) {
const auto* PSHORTCUT = registerShortcut(PSESSION, s); const auto* PSHORTCUT = registerShortcut(PSESSION, s);
std::unordered_map<std::string, sdbus::Variant> shortcutData; std::unordered_map<std::string, sdbus::Variant> shortcutData;
shortcutData["description"] = PSHORTCUT->description; shortcutData["description"] = sdbus::Variant{PSHORTCUT->description};
shortcutData["trigger_description"] = ""; shortcutData["trigger_description"] = sdbus::Variant{""};
shortcutsToReturn.push_back({PSHORTCUT->id, shortcutData}); shortcutsToReturn.push_back({PSHORTCUT->id, shortcutData});
} }
Debug::log(LOG, "[globalshortcuts] registered {} shortcuts", shortcuts.size()); Debug::log(LOG, "[globalshortcuts] registered {} shortcuts", shortcuts.size());
auto reply = call.createReply();
std::unordered_map<std::string, sdbus::Variant> data; std::unordered_map<std::string, sdbus::Variant> data;
data["shortcuts"] = shortcutsToReturn; data["shortcuts"] = sdbus::Variant{shortcutsToReturn};
reply << (uint32_t)0; return {0, data};
reply << data;
reply.send();
} }
void CGlobalShortcutsPortal::onListShortcuts(sdbus::MethodCall& call) { dbUasv CGlobalShortcutsPortal::onListShortcuts(sdbus::ObjectPath sessionHandle, sdbus::ObjectPath requestHandle) {
sdbus::ObjectPath sessionHandle, requestHandle;
call >> requestHandle;
call >> sessionHandle;
Debug::log(LOG, "[globalshortcuts] List keys:"); Debug::log(LOG, "[globalshortcuts] List keys:");
Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str()); Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str());
@ -164,26 +138,22 @@ void CGlobalShortcutsPortal::onListShortcuts(sdbus::MethodCall& call) {
if (!PSESSION) { if (!PSESSION) {
Debug::log(ERR, "[globalshortcuts] No session?"); Debug::log(ERR, "[globalshortcuts] No session?");
return; return {1, {}};
} }
std::vector<DBusShortcut> shortcuts; std::vector<DBusShortcut> shortcuts;
for (auto& s : PSESSION->keybinds) { for (auto& s : PSESSION->keybinds) {
std::unordered_map<std::string, sdbus::Variant> opts; std::unordered_map<std::string, sdbus::Variant> opts;
opts["description"] = s->description; opts["description"] = sdbus::Variant{s->description};
opts["trigger_description"] = ""; opts["trigger_description"] = sdbus::Variant{""};
shortcuts.push_back({s->id, opts}); shortcuts.push_back({s->id, opts});
} }
auto reply = call.createReply();
std::unordered_map<std::string, sdbus::Variant> data; std::unordered_map<std::string, sdbus::Variant> data;
data["shortcuts"] = shortcuts; data["shortcuts"] = sdbus::Variant{shortcuts};
reply << (uint32_t)0; return {0, data};
reply << data;
reply.send();
} }
CGlobalShortcutsPortal::CGlobalShortcutsPortal(SP<CCHyprlandGlobalShortcutsManagerV1> mgr) { CGlobalShortcutsPortal::CGlobalShortcutsPortal(SP<CCHyprlandGlobalShortcutsManagerV1> mgr) {
@ -191,14 +161,19 @@ CGlobalShortcutsPortal::CGlobalShortcutsPortal(SP<CCHyprlandGlobalShortcutsManag
m_pObject = sdbus::createObject(*g_pPortalManager->getConnection(), OBJECT_PATH); m_pObject = sdbus::createObject(*g_pPortalManager->getConnection(), OBJECT_PATH);
m_pObject->registerMethod(INTERFACE_NAME, "CreateSession", "oosa{sv}", "ua{sv}", [&](sdbus::MethodCall c) { onCreateSession(c); }); m_pObject
m_pObject->registerMethod(INTERFACE_NAME, "BindShortcuts", "ooa(sa{sv})sa{sv}", "ua{sv}", [&](sdbus::MethodCall c) { onBindShortcuts(c); }); ->addVTable(sdbus::registerMethod("CreateSession")
m_pObject->registerMethod(INTERFACE_NAME, "ListShortcuts", "oo", "ua{sv}", [&](sdbus::MethodCall c) { onListShortcuts(c); }); .implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2, std::string s, std::unordered_map<std::string, sdbus::Variant> m) {
m_pObject->registerSignal(INTERFACE_NAME, "Activated", "osta{sv}"); return onCreateSession(o1, o2, s, m);
m_pObject->registerSignal(INTERFACE_NAME, "Deactivated", "osta{sv}"); }),
m_pObject->registerSignal(INTERFACE_NAME, "ShortcutsChanged", "oa(sa{sv})"); sdbus::registerMethod("BindShortcuts")
.implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2, std::vector<DBusShortcut> v1, std::string s1,
m_pObject->finishRegistration(); std::unordered_map<std::string, sdbus::Variant> m2) { return onBindShortcuts(o1, o2, v1, s1, m2); }),
sdbus::registerMethod("ListShortcuts").implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2) { return onListShortcuts(o1, o2); }),
sdbus::registerSignal("Activated").withParameters<sdbus::ObjectPath, std::string, uint64_t, std::unordered_map<std::string, sdbus::Variant>>(),
sdbus::registerSignal("Deactivated").withParameters<sdbus::ObjectPath, std::string, uint64_t, std::unordered_map<std::string, sdbus::Variant>>(),
sdbus::registerSignal("ShortcutsChanged").withParameters<sdbus::ObjectPath, std::unordered_map<std::string, std::unordered_map<std::string, sdbus::Variant>>>())
.forInterface(INTERFACE_NAME);
Debug::log(LOG, "[globalshortcuts] registered"); Debug::log(LOG, "[globalshortcuts] registered");
} }
@ -208,13 +183,7 @@ void CGlobalShortcutsPortal::onActivated(SKeybind* pKeybind, uint64_t time) {
Debug::log(TRACE, "[gs] Session {} called activated on {}", PSESSION->sessionHandle.c_str(), pKeybind->id); Debug::log(TRACE, "[gs] Session {} called activated on {}", PSESSION->sessionHandle.c_str(), pKeybind->id);
auto signal = m_pObject->createSignal(INTERFACE_NAME, "Activated"); m_pObject->emitSignal("Activated").onInterface(INTERFACE_NAME).withArguments(PSESSION->sessionHandle, pKeybind->id, time, std::unordered_map<std::string, sdbus::Variant>{});
signal << PSESSION->sessionHandle;
signal << pKeybind->id;
signal << time;
signal << std::unordered_map<std::string, sdbus::Variant>{};
m_pObject->emitSignal(signal);
} }
void CGlobalShortcutsPortal::onDeactivated(SKeybind* pKeybind, uint64_t time) { void CGlobalShortcutsPortal::onDeactivated(SKeybind* pKeybind, uint64_t time) {
@ -222,11 +191,5 @@ void CGlobalShortcutsPortal::onDeactivated(SKeybind* pKeybind, uint64_t time) {
Debug::log(TRACE, "[gs] Session {} called deactivated on {}", PSESSION->sessionHandle.c_str(), pKeybind->id); Debug::log(TRACE, "[gs] Session {} called deactivated on {}", PSESSION->sessionHandle.c_str(), pKeybind->id);
auto signal = m_pObject->createSignal(INTERFACE_NAME, "Deactivated"); m_pObject->emitSignal("Deactivated").onInterface(INTERFACE_NAME).withArguments(PSESSION->sessionHandle, pKeybind->id, time, std::unordered_map<std::string, sdbus::Variant>{});
signal << PSESSION->sessionHandle;
signal << pKeybind->id;
signal << time;
signal << std::unordered_map<std::string, sdbus::Variant>{};
m_pObject->emitSignal(signal);
} }

View file

@ -3,6 +3,7 @@
#include <sdbus-c++/sdbus-c++.h> #include <sdbus-c++/sdbus-c++.h>
#include "hyprland-global-shortcuts-v1.hpp" #include "hyprland-global-shortcuts-v1.hpp"
#include "../shared/Session.hpp" #include "../shared/Session.hpp"
#include "../dbusDefines.hpp"
struct SKeybind { struct SKeybind {
SKeybind(SP<CCHyprlandGlobalShortcutV1> shortcut); SKeybind(SP<CCHyprlandGlobalShortcutV1> shortcut);
@ -15,12 +16,15 @@ class CGlobalShortcutsPortal {
public: public:
CGlobalShortcutsPortal(SP<CCHyprlandGlobalShortcutsManagerV1> mgr); CGlobalShortcutsPortal(SP<CCHyprlandGlobalShortcutsManagerV1> mgr);
void onCreateSession(sdbus::MethodCall& call); using DBusShortcut = sdbus::Struct<std::string, std::unordered_map<std::string, sdbus::Variant>>;
void onBindShortcuts(sdbus::MethodCall& call);
void onListShortcuts(sdbus::MethodCall& call);
void onActivated(SKeybind* pKeybind, uint64_t time); dbUasv onCreateSession(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID, std::unordered_map<std::string, sdbus::Variant> opts);
void onDeactivated(SKeybind* pKeybind, uint64_t time); dbUasv onBindShortcuts(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::vector<DBusShortcut> shortcuts, std::string appID,
std::unordered_map<std::string, sdbus::Variant> opts);
dbUasv onListShortcuts(sdbus::ObjectPath sessionHandle, sdbus::ObjectPath requestHandle);
void onActivated(SKeybind* pKeybind, uint64_t time);
void onDeactivated(SKeybind* pKeybind, uint64_t time);
struct SSession { struct SSession {
std::string appid; std::string appid;
@ -42,12 +46,10 @@ class CGlobalShortcutsPortal {
std::unique_ptr<sdbus::IObject> m_pObject; std::unique_ptr<sdbus::IObject> m_pObject;
using DBusShortcut = sdbus::Struct<std::string, std::unordered_map<std::string, sdbus::Variant>>; SSession* getSession(sdbus::ObjectPath& path);
SKeybind* getShortcutById(const std::string& appID, const std::string& shortcutId);
SKeybind* registerShortcut(SSession* session, const DBusShortcut& shortcut);
SSession* getSession(sdbus::ObjectPath& path); const sdbus::InterfaceName INTERFACE_NAME = sdbus::InterfaceName{"org.freedesktop.impl.portal.GlobalShortcuts"};
SKeybind* getShortcutById(const std::string& appID, const std::string& shortcutId); const sdbus::ObjectPath OBJECT_PATH = sdbus::ObjectPath{"/org/freedesktop/portal/desktop"};
SKeybind* registerShortcut(SSession* session, const DBusShortcut& shortcut);
const std::string INTERFACE_NAME = "org.freedesktop.impl.portal.GlobalShortcuts";
const std::string OBJECT_PATH = "/org/freedesktop/portal/desktop";
}; };

View file

@ -16,33 +16,24 @@ static sdbus::Struct<std::string, uint32_t, sdbus::Variant> getFullRestoreStruct
switch (data.type) { switch (data.type) {
case TYPE_GEOMETRY: case TYPE_GEOMETRY:
case TYPE_OUTPUT: mapData["output"] = data.output; break; case TYPE_OUTPUT: mapData["output"] = sdbus::Variant{data.output}; break;
case TYPE_WINDOW: case TYPE_WINDOW:
mapData["windowHandle"] = (uint64_t)data.windowHandle->resource(); mapData["windowHandle"] = sdbus::Variant{(uint64_t)data.windowHandle->resource()};
mapData["windowClass"] = data.windowClass; mapData["windowClass"] = sdbus::Variant{data.windowClass};
break; break;
default: Debug::log(ERR, "[screencopy] wonk selection in token saving"); break; default: Debug::log(ERR, "[screencopy] wonk selection in token saving"); break;
} }
mapData["timeIssued"] = uint64_t(time(nullptr)); mapData["timeIssued"] = sdbus::Variant{uint64_t(time(nullptr))};
mapData["token"] = std::string("todo"); mapData["token"] = sdbus::Variant{std::string("todo")};
mapData["withCursor"] = cursor; mapData["withCursor"] = sdbus::Variant{cursor};
sdbus::Variant restoreData{mapData}; sdbus::Variant restoreData{mapData};
return sdbus::Struct<std::string, uint32_t, sdbus::Variant>{"hyprland", 3, restoreData}; return sdbus::Struct<std::string, uint32_t, sdbus::Variant>{"hyprland", 3, restoreData};
} }
void CScreencopyPortal::onCreateSession(sdbus::MethodCall& call) { dbUasv CScreencopyPortal::onCreateSession(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID,
sdbus::ObjectPath requestHandle, sessionHandle; std::unordered_map<std::string, sdbus::Variant> opts) {
g_pPortalManager->m_sHelpers.toplevel->activate();
call >> requestHandle;
call >> sessionHandle;
std::string appID;
call >> appID;
Debug::log(LOG, "[screencopy] New session:"); Debug::log(LOG, "[screencopy] New session:");
Debug::log(LOG, "[screencopy] | {}", requestHandle.c_str()); Debug::log(LOG, "[screencopy] | {}", requestHandle.c_str());
Debug::log(LOG, "[screencopy] | {}", sessionHandle.c_str()); Debug::log(LOG, "[screencopy] | {}", sessionHandle.c_str());
@ -66,21 +57,11 @@ void CScreencopyPortal::onCreateSession(sdbus::MethodCall& call) {
PSESSION->request = createDBusRequest(requestHandle); PSESSION->request = createDBusRequest(requestHandle);
PSESSION->request->onDestroy = [PSESSION]() { PSESSION->request.release(); }; PSESSION->request->onDestroy = [PSESSION]() { PSESSION->request.release(); };
auto reply = call.createReply(); return {0, {}};
reply << (uint32_t)0;
reply << std::unordered_map<std::string, sdbus::Variant>{};
reply.send();
} }
void CScreencopyPortal::onSelectSources(sdbus::MethodCall& call) { dbUasv CScreencopyPortal::onSelectSources(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID,
sdbus::ObjectPath requestHandle, sessionHandle; std::unordered_map<std::string, sdbus::Variant> options) {
call >> requestHandle;
call >> sessionHandle;
std::string appID;
call >> appID;
Debug::log(LOG, "[screencopy] SelectSources:"); Debug::log(LOG, "[screencopy] SelectSources:");
Debug::log(LOG, "[screencopy] | {}", requestHandle.c_str()); Debug::log(LOG, "[screencopy] | {}", requestHandle.c_str());
Debug::log(LOG, "[screencopy] | {}", sessionHandle.c_str()); Debug::log(LOG, "[screencopy] | {}", sessionHandle.c_str());
@ -90,16 +71,10 @@ void CScreencopyPortal::onSelectSources(sdbus::MethodCall& call) {
if (!PSESSION) { if (!PSESSION) {
Debug::log(ERR, "[screencopy] SelectSources: no session found??"); Debug::log(ERR, "[screencopy] SelectSources: no session found??");
auto reply = call.createErrorReply(sdbus::Error{"NOSESSION", "No session found"}); throw sdbus::Error{sdbus::Error::Name{"NOSESSION"}, "No session found"};
reply << (uint32_t)1; return {1, {}};
reply.send();
return;
} }
std::unordered_map<std::string, sdbus::Variant> options;
call >> options;
struct { struct {
bool exists = false; bool exists = false;
std::string token, output; std::string token, output;
@ -233,22 +208,11 @@ void CScreencopyPortal::onSelectSources(sdbus::MethodCall& call) {
PSESSION->selection = SHAREDATA; PSESSION->selection = SHAREDATA;
auto reply = call.createReply(); return {SHAREDATA.type == TYPE_INVALID ? 1 : 0, {}};
reply << (uint32_t)(SHAREDATA.type == TYPE_INVALID ? 1 : 0);
reply << std::unordered_map<std::string, sdbus::Variant>{};
reply.send();
} }
void CScreencopyPortal::onStart(sdbus::MethodCall& call) { dbUasv CScreencopyPortal::onStart(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID, std::string parentWindow,
sdbus::ObjectPath requestHandle, sessionHandle; std::unordered_map<std::string, sdbus::Variant> opts) {
call >> requestHandle;
call >> sessionHandle;
std::string appID, parentWindow;
call >> appID;
call >> parentWindow;
Debug::log(LOG, "[screencopy] Start:"); Debug::log(LOG, "[screencopy] Start:");
Debug::log(LOG, "[screencopy] | {}", requestHandle.c_str()); Debug::log(LOG, "[screencopy] | {}", requestHandle.c_str());
Debug::log(LOG, "[screencopy] | {}", sessionHandle.c_str()); Debug::log(LOG, "[screencopy] | {}", sessionHandle.c_str());
@ -259,17 +223,12 @@ void CScreencopyPortal::onStart(sdbus::MethodCall& call) {
if (!PSESSION) { if (!PSESSION) {
Debug::log(ERR, "[screencopy] Start: no session found??"); Debug::log(ERR, "[screencopy] Start: no session found??");
auto reply = call.createErrorReply(sdbus::Error{"NOSESSION", "No session found"}); throw sdbus::Error{sdbus::Error::Name{"NOSESSION"}, "No session found"};
reply << (uint32_t)1; return {1, {}};
reply.send();
return;
} }
startSharing(PSESSION); startSharing(PSESSION);
auto reply = call.createReply();
reply << (uint32_t)0;
std::unordered_map<std::string, sdbus::Variant> options; std::unordered_map<std::string, sdbus::Variant> options;
if (PSESSION->selection.allowToken) { if (PSESSION->selection.allowToken) {
@ -288,7 +247,7 @@ void CScreencopyPortal::onStart(sdbus::MethodCall& call) {
case TYPE_WORKSPACE: type = 1 << VIRTUAL; break; case TYPE_WORKSPACE: type = 1 << VIRTUAL; break;
default: type = 0; break; default: type = 0; break;
} }
options["source_type"] = type; options["source_type"] = sdbus::Variant{type};
std::vector<sdbus::Struct<uint32_t, std::unordered_map<std::string, sdbus::Variant>>> streams; std::vector<sdbus::Struct<uint32_t, std::unordered_map<std::string, sdbus::Variant>>> streams;
@ -298,11 +257,9 @@ void CScreencopyPortal::onStart(sdbus::MethodCall& call) {
streamData["source_type"] = sdbus::Variant{uint32_t{type}}; streamData["source_type"] = sdbus::Variant{uint32_t{type}};
streams.emplace_back(sdbus::Struct<uint32_t, std::unordered_map<std::string, sdbus::Variant>>{PSESSION->sharingData.nodeID, streamData}); streams.emplace_back(sdbus::Struct<uint32_t, std::unordered_map<std::string, sdbus::Variant>>{PSESSION->sharingData.nodeID, streamData});
options["streams"] = streams; options["streams"] = sdbus::Variant{streams};
reply << options; return {0, options};
reply.send();
} }
void CScreencopyPortal::startSharing(CScreencopyPortal::SSession* pSession) { void CScreencopyPortal::startSharing(CScreencopyPortal::SSession* pSession) {
@ -628,14 +585,21 @@ CScreencopyPortal::SSession* CScreencopyPortal::getSession(sdbus::ObjectPath& pa
CScreencopyPortal::CScreencopyPortal(SP<CCZwlrScreencopyManagerV1> mgr) { CScreencopyPortal::CScreencopyPortal(SP<CCZwlrScreencopyManagerV1> mgr) {
m_pObject = sdbus::createObject(*g_pPortalManager->getConnection(), OBJECT_PATH); m_pObject = sdbus::createObject(*g_pPortalManager->getConnection(), OBJECT_PATH);
m_pObject->registerMethod(INTERFACE_NAME, "CreateSession", "oosa{sv}", "ua{sv}", [&](sdbus::MethodCall c) { onCreateSession(c); }); m_pObject
m_pObject->registerMethod(INTERFACE_NAME, "SelectSources", "oosa{sv}", "ua{sv}", [&](sdbus::MethodCall c) { onSelectSources(c); }); ->addVTable(sdbus::registerMethod("CreateSession")
m_pObject->registerMethod(INTERFACE_NAME, "Start", "oossa{sv}", "ua{sv}", [&](sdbus::MethodCall c) { onStart(c); }); .implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2, std::string s1, std::unordered_map<std::string, sdbus::Variant> m1) {
m_pObject->registerProperty(INTERFACE_NAME, "AvailableSourceTypes", "u", [](sdbus::PropertyGetReply& reply) -> void { reply << (uint32_t)(VIRTUAL | MONITOR | WINDOW); }); return onCreateSession(o1, o2, s1, m1);
m_pObject->registerProperty(INTERFACE_NAME, "AvailableCursorModes", "u", [](sdbus::PropertyGetReply& reply) -> void { reply << (uint32_t)(HIDDEN | EMBEDDED); }); }),
m_pObject->registerProperty(INTERFACE_NAME, "version", "u", [](sdbus::PropertyGetReply& reply) -> void { reply << (uint32_t)(3); }); sdbus::registerMethod("SelectSources")
.implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2, std::string s1, std::unordered_map<std::string, sdbus::Variant> m1) {
m_pObject->finishRegistration(); return onSelectSources(o1, o2, s1, m1);
}),
sdbus::registerMethod("Start").implementedAs([this](sdbus::ObjectPath o1, sdbus::ObjectPath o2, std::string s1, std::string s2,
std::unordered_map<std::string, sdbus::Variant> m1) { return onStart(o1, o2, s1, s2, m1); }),
sdbus::registerProperty("AvailableSourceTypes").withGetter([]() { return uint32_t{VIRTUAL | MONITOR | WINDOW}; }),
sdbus::registerProperty("AvailableCursorModes").withGetter([]() { return uint32_t{HIDDEN | EMBEDDED}; }),
sdbus::registerProperty("version").withGetter([]() { return uint32_t{3}; }))
.forInterface(INTERFACE_NAME);
m_sState.screencopy = mgr; m_sState.screencopy = mgr;
m_pPipewire = std::make_unique<CPipewireConnection>(); m_pPipewire = std::make_unique<CPipewireConnection>();

View file

@ -6,6 +6,7 @@
#include "../shared/ScreencopyShared.hpp" #include "../shared/ScreencopyShared.hpp"
#include <gbm.h> #include <gbm.h>
#include "../shared/Session.hpp" #include "../shared/Session.hpp"
#include "../dbusDefines.hpp"
#include <chrono> #include <chrono>
enum cursorModes { enum cursorModes {
@ -53,11 +54,12 @@ class CScreencopyPortal {
public: public:
CScreencopyPortal(SP<CCZwlrScreencopyManagerV1>); CScreencopyPortal(SP<CCZwlrScreencopyManagerV1>);
void appendToplevelExport(SP<CCHyprlandToplevelExportManagerV1>); void appendToplevelExport(SP<CCHyprlandToplevelExportManagerV1>);
void onCreateSession(sdbus::MethodCall& call); dbUasv onCreateSession(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID, std::unordered_map<std::string, sdbus::Variant> opts);
void onSelectSources(sdbus::MethodCall& call); dbUasv onSelectSources(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID, std::unordered_map<std::string, sdbus::Variant> opts);
void onStart(sdbus::MethodCall& call); dbUasv onStart(sdbus::ObjectPath requestHandle, sdbus::ObjectPath sessionHandle, std::string appID, std::string parentWindow,
std::unordered_map<std::string, sdbus::Variant> opts);
struct SSession { struct SSession {
std::string appid; std::string appid;
@ -123,8 +125,8 @@ class CScreencopyPortal {
SP<CCHyprlandToplevelExportManagerV1> toplevel = nullptr; SP<CCHyprlandToplevelExportManagerV1> toplevel = nullptr;
} m_sState; } m_sState;
const std::string INTERFACE_NAME = "org.freedesktop.impl.portal.ScreenCast"; const sdbus::InterfaceName INTERFACE_NAME = sdbus::InterfaceName{"org.freedesktop.impl.portal.ScreenCast"};
const std::string OBJECT_PATH = "/org/freedesktop/portal/desktop"; const sdbus::ObjectPath OBJECT_PATH = sdbus::ObjectPath{"/org/freedesktop/portal/desktop"};
friend struct SSession; friend struct SSession;
}; };

View file

@ -8,14 +8,14 @@
std::string lastScreenshot; std::string lastScreenshot;
void pickHyprPicker(sdbus::MethodCall& call) { //
static dbUasv pickHyprPicker(sdbus::ObjectPath requestHandle, std::string appID, std::string parentWindow, std::unordered_map<std::string, sdbus::Variant> options) {
const std::string HYPRPICKER_CMD = "hyprpicker --format=rgb --no-fancy"; const std::string HYPRPICKER_CMD = "hyprpicker --format=rgb --no-fancy";
std::string rgbColor = execAndGet(HYPRPICKER_CMD.c_str()); std::string rgbColor = execAndGet(HYPRPICKER_CMD.c_str());
if (rgbColor.size() > 12) { if (rgbColor.size() > 12) {
Debug::log(ERR, "hyprpicker returned strange output: " + rgbColor); Debug::log(ERR, "hyprpicker returned strange output: " + rgbColor);
sendEmptyDbusMethodReply(call, 1); return {1, {}};
return;
} }
std::array<uint8_t, 3> colors{0, 0, 0}; std::array<uint8_t, 3> colors{0, 0, 0};
@ -26,8 +26,7 @@ void pickHyprPicker(sdbus::MethodCall& call) {
if (next == std::string::npos) { if (next == std::string::npos) {
Debug::log(ERR, "hyprpicker returned strange output: " + rgbColor); Debug::log(ERR, "hyprpicker returned strange output: " + rgbColor);
sendEmptyDbusMethodReply(call, 1); return {1, {}};
return;
} }
colors[i] = std::stoi(rgbColor.substr(0, next)); colors[i] = std::stoi(rgbColor.substr(0, next));
@ -36,21 +35,17 @@ void pickHyprPicker(sdbus::MethodCall& call) {
colors[2] = std::stoi(rgbColor); colors[2] = std::stoi(rgbColor);
} catch (...) { } catch (...) {
Debug::log(ERR, "Reading RGB values from hyprpicker failed. This is likely a string to integer error."); Debug::log(ERR, "Reading RGB values from hyprpicker failed. This is likely a string to integer error.");
sendEmptyDbusMethodReply(call, 1); return {1, {}};
} }
auto [r, g, b] = colors; auto [r, g, b] = colors;
std::unordered_map<std::string, sdbus::Variant> results; std::unordered_map<std::string, sdbus::Variant> results;
results["color"] = sdbus::Struct<double, double, double>(r / 255.0, g / 255.0, b / 255.0); results["color"] = sdbus::Variant{sdbus::Struct<double, double, double>(r / 255.0, g / 255.0, b / 255.0)};
auto reply = call.createReply(); return {0, results};
reply << (uint32_t)0;
reply << results;
reply.send();
} }
void pickSlurp(sdbus::MethodCall& call) { static dbUasv pickSlurp(sdbus::ObjectPath requestHandle, std::string appID, std::string parentWindow, std::unordered_map<std::string, sdbus::Variant> options) {
const std::string PICK_COLOR_CMD = "grim -g \"$(slurp -p)\" -t ppm -"; const std::string PICK_COLOR_CMD = "grim -g \"$(slurp -p)\" -t ppm -";
std::string ppmColor = execAndGet(PICK_COLOR_CMD.c_str()); std::string ppmColor = execAndGet(PICK_COLOR_CMD.c_str());
@ -60,8 +55,7 @@ void pickSlurp(sdbus::MethodCall& call) {
// check if we got a 1x1 PPM Image // check if we got a 1x1 PPM Image
if (!ppmColor.starts_with("P6 1 1 ")) { if (!ppmColor.starts_with("P6 1 1 ")) {
Debug::log(ERR, "grim did not return a PPM Image for us."); Debug::log(ERR, "grim did not return a PPM Image for us.");
sendEmptyDbusMethodReply(call, 1); return {1, {}};
return;
} }
// convert it to a rgb value // convert it to a rgb value
@ -88,45 +82,33 @@ void pickSlurp(sdbus::MethodCall& call) {
b = ((byteString[4] << 8) | byteString[5]) / (maxVal * 1.0); b = ((byteString[4] << 8) | byteString[5]) / (maxVal * 1.0);
} }
auto reply = call.createReply();
std::unordered_map<std::string, sdbus::Variant> results; std::unordered_map<std::string, sdbus::Variant> results;
results["color"] = sdbus::Struct<double, double, double>(r, g, b); results["color"] = sdbus::Variant{sdbus::Struct<double, double, double>(r, g, b)};
reply << (uint32_t)0; return {0, results};
reply << results; } catch (...) { Debug::log(ERR, "Converting PPM to RGB failed. This is likely a string to integer error."); }
reply.send();
} catch (...) { return {1, {}};
Debug::log(ERR, "Converting PPM to RGB failed. This is likely a string to integer error.");
sendEmptyDbusMethodReply(call, 1);
}
} }
CScreenshotPortal::CScreenshotPortal() { CScreenshotPortal::CScreenshotPortal() {
m_pObject = sdbus::createObject(*g_pPortalManager->getConnection(), OBJECT_PATH); m_pObject = sdbus::createObject(*g_pPortalManager->getConnection(), OBJECT_PATH);
m_pObject->registerMethod(INTERFACE_NAME, "Screenshot", "ossa{sv}", "ua{sv}", [&](sdbus::MethodCall c) { onScreenshot(c); }); m_pObject
m_pObject->registerMethod(INTERFACE_NAME, "PickColor", "ossa{sv}", "ua{sv}", [&](sdbus::MethodCall c) { onPickColor(c); }); ->addVTable(
sdbus::registerMethod("Screenshot").implementedAs([this](sdbus::ObjectPath o, std::string s1, std::string s2, std::unordered_map<std::string, sdbus::Variant> m) {
m_pObject->registerProperty(INTERFACE_NAME, "version", "u", [](sdbus::PropertyGetReply& reply) -> void { reply << (uint32_t)(2); }); return onScreenshot(o, s1, s2, m);
}),
m_pObject->finishRegistration(); sdbus::registerMethod("PickColor").implementedAs([this](sdbus::ObjectPath o, std::string s1, std::string s2, std::unordered_map<std::string, sdbus::Variant> m) {
return onPickColor(o, s1, s2, m);
}),
sdbus::registerProperty("version").withGetter([]() { return uint32_t{2}; }))
.forInterface(INTERFACE_NAME);
Debug::log(LOG, "[screenshot] init successful"); Debug::log(LOG, "[screenshot] init successful");
} }
void CScreenshotPortal::onScreenshot(sdbus::MethodCall& call) { dbUasv CScreenshotPortal::onScreenshot(sdbus::ObjectPath requestHandle, std::string appID, std::string parentWindow, std::unordered_map<std::string, sdbus::Variant> options) {
sdbus::ObjectPath requestHandle;
call >> requestHandle;
std::string appID;
call >> appID;
std::string parentWindow;
call >> parentWindow;
std::unordered_map<std::string, sdbus::Variant> options;
call >> options;
Debug::log(LOG, "[screenshot] New screenshot request:"); Debug::log(LOG, "[screenshot] New screenshot request:");
Debug::log(LOG, "[screenshot] | {}", requestHandle.c_str()); Debug::log(LOG, "[screenshot] | {}", requestHandle.c_str());
@ -146,7 +128,7 @@ void CScreenshotPortal::onScreenshot(sdbus::MethodCall& call) {
const std::string SNAP_INTERACTIVE_CMD = "grim -g \"$(slurp)\" '" + FILE_PATH + "'"; const std::string SNAP_INTERACTIVE_CMD = "grim -g \"$(slurp)\" '" + FILE_PATH + "'";
std::unordered_map<std::string, sdbus::Variant> results; std::unordered_map<std::string, sdbus::Variant> results;
results["uri"] = "file://" + FILE_PATH; results["uri"] = sdbus::Variant{"file://" + FILE_PATH};
std::filesystem::remove(FILE_PATH); std::filesystem::remove(FILE_PATH);
std::filesystem::create_directory(HYPR_DIR); std::filesystem::create_directory(HYPR_DIR);
@ -163,21 +145,10 @@ void CScreenshotPortal::onScreenshot(sdbus::MethodCall& call) {
uint32_t responseCode = std::filesystem::exists(FILE_PATH) ? 0 : 1; uint32_t responseCode = std::filesystem::exists(FILE_PATH) ? 0 : 1;
auto reply = call.createReply(); return {responseCode, results};
reply << responseCode;
reply << results;
reply.send();
} }
void CScreenshotPortal::onPickColor(sdbus::MethodCall& call) { dbUasv CScreenshotPortal::onPickColor(sdbus::ObjectPath requestHandle, std::string appID, std::string parentWindow, std::unordered_map<std::string, sdbus::Variant> options) {
sdbus::ObjectPath requestHandle;
call >> requestHandle;
std::string appID;
call >> appID;
std::string parentWindow;
call >> parentWindow;
Debug::log(LOG, "[screenshot] New PickColor request:"); Debug::log(LOG, "[screenshot] New PickColor request:");
Debug::log(LOG, "[screenshot] | {}", requestHandle.c_str()); Debug::log(LOG, "[screenshot] | {}", requestHandle.c_str());
@ -188,13 +159,12 @@ void CScreenshotPortal::onPickColor(sdbus::MethodCall& call) {
if (!slurpInstalled && !hyprPickerInstalled) { if (!slurpInstalled && !hyprPickerInstalled) {
Debug::log(ERR, "Neither slurp nor hyprpicker found. We can't pick colors."); Debug::log(ERR, "Neither slurp nor hyprpicker found. We can't pick colors.");
sendEmptyDbusMethodReply(call, 1); return {1, {}};
return;
} }
// use hyprpicker if installed, slurp as fallback // use hyprpicker if installed, slurp as fallback
if (hyprPickerInstalled) if (hyprPickerInstalled)
pickHyprPicker(call); return pickHyprPicker(requestHandle, appID, parentWindow, options);
else else
pickSlurp(call); return pickSlurp(requestHandle, appID, parentWindow, options);
} }

View file

@ -1,17 +1,18 @@
#pragma once #pragma once
#include <sdbus-c++/sdbus-c++.h> #include <sdbus-c++/sdbus-c++.h>
#include "../dbusDefines.hpp"
class CScreenshotPortal { class CScreenshotPortal {
public: public:
CScreenshotPortal(); CScreenshotPortal();
void onScreenshot(sdbus::MethodCall& call); dbUasv onScreenshot(sdbus::ObjectPath requestHandle, std::string appID, std::string parentWindow, std::unordered_map<std::string, sdbus::Variant> options);
void onPickColor(sdbus::MethodCall& call); dbUasv onPickColor(sdbus::ObjectPath requestHandle, std::string appID, std::string parentWindow, std::unordered_map<std::string, sdbus::Variant> options);
private: private:
std::unique_ptr<sdbus::IObject> m_pObject; std::unique_ptr<sdbus::IObject> m_pObject;
const std::string INTERFACE_NAME = "org.freedesktop.impl.portal.Screenshot"; const sdbus::InterfaceName INTERFACE_NAME = sdbus::InterfaceName{"org.freedesktop.impl.portal.Screenshot"};
const std::string OBJECT_PATH = "/org/freedesktop/portal/desktop"; const sdbus::ObjectPath OBJECT_PATH = sdbus::ObjectPath{"/org/freedesktop/portal/desktop"};
}; };

View file

@ -2,30 +2,28 @@
#include "../core/PortalManager.hpp" #include "../core/PortalManager.hpp"
#include "../helpers/Log.hpp" #include "../helpers/Log.hpp"
static void onCloseRequest(sdbus::MethodCall& call, SDBusRequest* req) { static int onCloseRequest(SDBusRequest* req) {
Debug::log(TRACE, "[internal] Close Request {}", (void*)req); Debug::log(TRACE, "[internal] Close Request {}", (void*)req);
if (!req) if (!req)
return; return 0;
auto r = call.createReply();
r.send();
req->onDestroy(); req->onDestroy();
req->object.release(); req->object.release();
return 0;
} }
static void onCloseSession(sdbus::MethodCall& call, SDBusSession* sess) { static int onCloseSession(SDBusSession* sess) {
Debug::log(TRACE, "[internal] Close Session {}", (void*)sess); Debug::log(TRACE, "[internal] Close Session {}", (void*)sess);
if (!sess) if (!sess)
return; return 0;
auto r = call.createReply();
r.send();
sess->onDestroy(); sess->onDestroy();
sess->object.release(); sess->object.release();
return 0;
} }
std::unique_ptr<SDBusSession> createDBusSession(sdbus::ObjectPath handle) { std::unique_ptr<SDBusSession> createDBusSession(sdbus::ObjectPath handle) {
@ -36,9 +34,7 @@ std::unique_ptr<SDBusSession> createDBusSession(sdbus::ObjectPath handle) {
pSession->object = sdbus::createObject(*g_pPortalManager->getConnection(), handle); pSession->object = sdbus::createObject(*g_pPortalManager->getConnection(), handle);
pSession->object->registerMethod("org.freedesktop.impl.portal.Session", "Close", "", "", [PSESSION](sdbus::MethodCall c) { onCloseSession(c, PSESSION); }); pSession->object->addVTable(sdbus::registerMethod("Close").implementedAs([PSESSION]() { onCloseSession(PSESSION); })).forInterface("org.freedesktop.impl.portal.Session");
pSession->object->finishRegistration();
return pSession; return pSession;
} }
@ -51,9 +47,7 @@ std::unique_ptr<SDBusRequest> createDBusRequest(sdbus::ObjectPath handle) {
pRequest->object = sdbus::createObject(*g_pPortalManager->getConnection(), handle); pRequest->object = sdbus::createObject(*g_pPortalManager->getConnection(), handle);
pRequest->object->registerMethod("org.freedesktop.impl.portal.Request", "Close", "", "", [PREQUEST](sdbus::MethodCall c) { onCloseRequest(c, PREQUEST); }); pRequest->object->addVTable(sdbus::registerMethod("Close").implementedAs([PREQUEST]() { onCloseRequest(PREQUEST); })).forInterface("org.freedesktop.impl.portal.Request");
pRequest->object->finishRegistration();
return pRequest; return pRequest;
} }

@ -1 +1 @@
Subproject commit 0eda85574546d19d9f06d6d5418bc192b3846f96 Subproject commit b7d85f936d622299ee57966c2b2aefde5e4f3684