mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-23 22:55:58 +01:00
add gs
This commit is contained in:
parent
ee577b571c
commit
f8a847109e
5 changed files with 320 additions and 3 deletions
|
@ -203,6 +203,10 @@ void CPortalManager::onGlobal(void* data, struct wl_registry* registry, uint32_t
|
|||
if (INTERFACE == zwlr_screencopy_manager_v1_interface.name && m_sPipewire.loop)
|
||||
m_sPortals.screencopy = std::make_unique<CScreencopyPortal>((zwlr_screencopy_manager_v1*)wl_registry_bind(registry, name, &zwlr_screencopy_manager_v1_interface, version));
|
||||
|
||||
if (INTERFACE == hyprland_global_shortcuts_manager_v1_interface.name)
|
||||
m_sPortals.globalShortcuts = std::make_unique<CGlobalShortcutsPortal>(
|
||||
(hyprland_global_shortcuts_manager_v1*)wl_registry_bind(registry, name, &hyprland_global_shortcuts_manager_v1_interface, version));
|
||||
|
||||
else if (INTERFACE == hyprland_toplevel_export_manager_v1_interface.name)
|
||||
m_sWaylandConnection.hyprlandToplevelMgr = wl_registry_bind(registry, name, &hyprland_toplevel_export_manager_v1_interface, version);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <wayland-client.h>
|
||||
|
||||
#include "../portals/Screencopy.hpp"
|
||||
#include "../portals/GlobalShortcuts.hpp"
|
||||
#include "../helpers/Timer.hpp"
|
||||
#include "../shared/ToplevelManager.hpp"
|
||||
#include <gbm.h>
|
||||
|
@ -42,6 +43,7 @@ class CPortalManager {
|
|||
|
||||
struct {
|
||||
std::unique_ptr<CScreencopyPortal> screencopy;
|
||||
std::unique_ptr<CGlobalShortcutsPortal> globalShortcuts;
|
||||
} m_sPortals;
|
||||
|
||||
struct {
|
||||
|
|
265
src/portals/GlobalShortcuts.cpp
Normal file
265
src/portals/GlobalShortcuts.cpp
Normal file
|
@ -0,0 +1,265 @@
|
|||
#include "GlobalShortcuts.hpp"
|
||||
#include "../core/PortalManager.hpp"
|
||||
#include "../helpers/Log.hpp"
|
||||
|
||||
// wayland
|
||||
|
||||
static void handleActivated(void* data, hyprland_global_shortcut_v1* hyprland_global_shortcut_v1, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) {
|
||||
const auto PKEYBIND = (SKeybind*)data;
|
||||
|
||||
g_pPortalManager->m_sPortals.globalShortcuts->onActivated(PKEYBIND, ((uint64_t)tv_sec_hi << 32) | (uint64_t)(tv_sec_lo));
|
||||
}
|
||||
|
||||
static void handleDeactivated(void* data, hyprland_global_shortcut_v1* hyprland_global_shortcut_v1, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) {
|
||||
const auto PKEYBIND = (SKeybind*)data;
|
||||
|
||||
g_pPortalManager->m_sPortals.globalShortcuts->onDeactivated(PKEYBIND, ((uint64_t)tv_sec_hi << 32) | (uint64_t)(tv_sec_lo));
|
||||
}
|
||||
|
||||
static const hyprland_global_shortcut_v1_listener shortcutListener = {
|
||||
.pressed = handleActivated,
|
||||
.released = handleDeactivated,
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
static void onCloseRequest(sdbus::MethodCall& call, CGlobalShortcutsPortal::SSession* sess) {
|
||||
Debug::log(TRACE, "[globalshortcuts] Close Request {}", (void*)sess);
|
||||
|
||||
if (!sess || !sess->request)
|
||||
return;
|
||||
|
||||
auto r = call.createReply();
|
||||
r.send();
|
||||
|
||||
sess->request.release();
|
||||
}
|
||||
|
||||
static void onCloseSession(sdbus::MethodCall& call, CGlobalShortcutsPortal::SSession* sess) {
|
||||
Debug::log(TRACE, "[globalshortcuts] Close Session {}", (void*)sess);
|
||||
|
||||
if (!sess || !sess->session)
|
||||
return;
|
||||
|
||||
auto r = call.createReply();
|
||||
r.send();
|
||||
|
||||
sess->session.release();
|
||||
}
|
||||
|
||||
CGlobalShortcutsPortal::SSession* CGlobalShortcutsPortal::getSession(sdbus::ObjectPath& path) {
|
||||
for (auto& s : m_vSessions) {
|
||||
if (s->sessionHandle == path)
|
||||
return s.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CGlobalShortcutsPortal::onCreateSession(sdbus::MethodCall& call) {
|
||||
sdbus::ObjectPath requestHandle, sessionHandle;
|
||||
|
||||
call >> requestHandle;
|
||||
call >> sessionHandle;
|
||||
|
||||
std::string appID;
|
||||
call >> appID;
|
||||
|
||||
Debug::log(LOG, "[globalshortcuts] New session:");
|
||||
Debug::log(LOG, "[globalshortcuts] | {}", requestHandle.c_str());
|
||||
Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str());
|
||||
Debug::log(LOG, "[globalshortcuts] | appid: {}", appID);
|
||||
|
||||
const auto PSESSION = m_vSessions.emplace_back(std::make_unique<SSession>(appID, requestHandle, sessionHandle)).get();
|
||||
|
||||
// create objects
|
||||
PSESSION->request = sdbus::createObject(*g_pPortalManager->getConnection(), requestHandle);
|
||||
PSESSION->session = sdbus::createObject(*g_pPortalManager->getConnection(), sessionHandle);
|
||||
|
||||
PSESSION->request->registerMethod("org.freedesktop.impl.portal.Request", "Close", "", "", [PSESSION](sdbus::MethodCall c) { onCloseRequest(c, PSESSION); });
|
||||
PSESSION->session->registerMethod("org.freedesktop.impl.portal.Session", "Close", "", "", [PSESSION](sdbus::MethodCall c) { onCloseSession(c, PSESSION); });
|
||||
|
||||
PSESSION->request->finishRegistration();
|
||||
PSESSION->session->finishRegistration();
|
||||
|
||||
std::unordered_map<std::string, sdbus::Variant> opts;
|
||||
call >> opts;
|
||||
|
||||
for (auto& [k, v] : opts) {
|
||||
if (k == "shortcuts") {
|
||||
PSESSION->registered = true;
|
||||
|
||||
std::vector<sdbus::Struct<std::string, std::unordered_map<std::string, sdbus::Variant>>> shortcuts;
|
||||
|
||||
shortcuts = v.get<std::vector<sdbus::Struct<std::string, std::unordered_map<std::string, sdbus::Variant>>>>();
|
||||
|
||||
for (auto& s : shortcuts) {
|
||||
const auto PSHORTCUT = PSESSION->keybinds.emplace_back(std::make_unique<SKeybind>()).get();
|
||||
|
||||
PSHORTCUT->id = s.get<0>();
|
||||
|
||||
std::unordered_map<std::string, sdbus::Variant> data = s.get<1>();
|
||||
|
||||
for (auto& [k, v] : data) {
|
||||
if (k == "description") {
|
||||
PSHORTCUT->description = v.get<std::string>();
|
||||
} else {
|
||||
Debug::log(LOG, "[globalshortcuts] unknown shortcut data type {}", k);
|
||||
}
|
||||
}
|
||||
|
||||
PSHORTCUT->shortcut =
|
||||
hyprland_global_shortcuts_manager_v1_register_shortcut(m_sState.manager, PSHORTCUT->id.c_str(), PSESSION->appid.c_str(), PSHORTCUT->description.c_str(), "");
|
||||
hyprland_global_shortcut_v1_add_listener(PSHORTCUT->shortcut, &shortcutListener, PSHORTCUT);
|
||||
|
||||
PSHORTCUT->session = PSESSION;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "[globalshortcuts] registered {} shortcuts", shortcuts.size());
|
||||
}
|
||||
}
|
||||
|
||||
auto reply = call.createReply();
|
||||
reply << (uint32_t)0;
|
||||
reply << std::unordered_map<std::string, sdbus::Variant>{};
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void CGlobalShortcutsPortal::onBindShortcuts(sdbus::MethodCall& call) {
|
||||
sdbus::ObjectPath sessionHandle, requestHandle;
|
||||
call >> requestHandle;
|
||||
call >> sessionHandle;
|
||||
|
||||
Debug::log(LOG, "[globalshortcuts] Bind keys:");
|
||||
Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str());
|
||||
|
||||
std::vector<sdbus::Struct<std::string, std::unordered_map<std::string, sdbus::Variant>>> shortcuts;
|
||||
std::vector<sdbus::Struct<std::string, std::unordered_map<std::string, sdbus::Variant>>> shortcutsToReturn;
|
||||
call >> shortcuts;
|
||||
|
||||
const auto PSESSION = getSession(sessionHandle);
|
||||
|
||||
if (!PSESSION) {
|
||||
Debug::log(ERR, "[globalshortcuts] No session?");
|
||||
return;
|
||||
}
|
||||
|
||||
PSESSION->registered = true;
|
||||
|
||||
for (auto& s : shortcuts) {
|
||||
const auto PSHORTCUT = PSESSION->keybinds.emplace_back(std::make_unique<SKeybind>()).get();
|
||||
|
||||
PSHORTCUT->id = s.get<0>();
|
||||
|
||||
std::unordered_map<std::string, sdbus::Variant> data = s.get<1>();
|
||||
|
||||
for (auto& [k, v] : data) {
|
||||
if (k == "description") {
|
||||
PSHORTCUT->description = v.get<std::string>();
|
||||
} else {
|
||||
Debug::log(LOG, "[globalshortcuts] unknown shortcut data type {}", k);
|
||||
}
|
||||
}
|
||||
|
||||
PSHORTCUT->shortcut =
|
||||
hyprland_global_shortcuts_manager_v1_register_shortcut(m_sState.manager, PSHORTCUT->id.c_str(), PSESSION->appid.c_str(), PSHORTCUT->description.c_str(), "");
|
||||
hyprland_global_shortcut_v1_add_listener(PSHORTCUT->shortcut, &shortcutListener, PSHORTCUT);
|
||||
|
||||
PSHORTCUT->session = PSESSION;
|
||||
|
||||
std::unordered_map<std::string, sdbus::Variant> shortcutData;
|
||||
shortcutData["description"] = PSHORTCUT->description;
|
||||
shortcutData["trigger_description"] = "";
|
||||
shortcutsToReturn.push_back({PSHORTCUT->id, shortcutData});
|
||||
}
|
||||
|
||||
Debug::log(LOG, "[globalshortcuts] registered {} shortcuts", shortcuts.size());
|
||||
|
||||
auto reply = call.createReply();
|
||||
|
||||
std::unordered_map<std::string, sdbus::Variant> data;
|
||||
data["shortcuts"] = shortcutsToReturn;
|
||||
|
||||
reply << (uint32_t)0;
|
||||
reply << data;
|
||||
reply.send();
|
||||
}
|
||||
|
||||
void CGlobalShortcutsPortal::onListShortcuts(sdbus::MethodCall& call) {
|
||||
sdbus::ObjectPath sessionHandle, requestHandle;
|
||||
call >> requestHandle;
|
||||
call >> sessionHandle;
|
||||
|
||||
Debug::log(LOG, "[globalshortcuts] List keys:");
|
||||
Debug::log(LOG, "[globalshortcuts] | {}", sessionHandle.c_str());
|
||||
|
||||
const auto PSESSION = getSession(sessionHandle);
|
||||
|
||||
if (!PSESSION) {
|
||||
Debug::log(ERR, "[globalshortcuts] No session?");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<sdbus::Struct<std::string, std::unordered_map<std::string, sdbus::Variant>>> shortcuts;
|
||||
|
||||
for (auto& s : PSESSION->keybinds) {
|
||||
std::unordered_map<std::string, sdbus::Variant> opts;
|
||||
opts["description"] = s->description;
|
||||
opts["trigger_description"] = "";
|
||||
shortcuts.push_back({s->id, opts});
|
||||
}
|
||||
|
||||
auto reply = call.createReply();
|
||||
|
||||
std::unordered_map<std::string, sdbus::Variant> data;
|
||||
data["shortcuts"] = shortcuts;
|
||||
|
||||
reply << (uint32_t)0;
|
||||
reply << data;
|
||||
reply.send();
|
||||
}
|
||||
|
||||
CGlobalShortcutsPortal::CGlobalShortcutsPortal(hyprland_global_shortcuts_manager_v1* mgr) {
|
||||
m_sState.manager = mgr;
|
||||
|
||||
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->registerMethod(INTERFACE_NAME, "BindShortcuts", "ooa(sa{sv})sa{sv}", "ua{sv}", [&](sdbus::MethodCall c) { onBindShortcuts(c); });
|
||||
m_pObject->registerMethod(INTERFACE_NAME, "ListShortcuts", "oo", "ua{sv}", [&](sdbus::MethodCall c) { onListShortcuts(c); });
|
||||
m_pObject->registerSignal(INTERFACE_NAME, "Activated", "osta{sv}");
|
||||
m_pObject->registerSignal(INTERFACE_NAME, "Deactivated", "osta{sv}");
|
||||
m_pObject->registerSignal(INTERFACE_NAME, "ShortcutsChanged", "oa(sa{sv})");
|
||||
|
||||
m_pObject->finishRegistration();
|
||||
|
||||
Debug::log(LOG, "[globalshortcuts] registered");
|
||||
}
|
||||
|
||||
void CGlobalShortcutsPortal::onActivated(SKeybind* pKeybind, uint64_t time) {
|
||||
const auto PSESSION = (CGlobalShortcutsPortal::SSession*)pKeybind->session;
|
||||
|
||||
Debug::log(TRACE, "[gs] Session {} called activated on {}", (void*)PSESSION, pKeybind->id);
|
||||
|
||||
auto signal = m_pObject->createSignal(INTERFACE_NAME, "Activated");
|
||||
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) {
|
||||
const auto PSESSION = (CGlobalShortcutsPortal::SSession*)pKeybind->session;
|
||||
|
||||
Debug::log(TRACE, "[gs] Session {} called deactivated on {}", (void*)PSESSION, pKeybind->id);
|
||||
|
||||
auto signal = m_pObject->createSignal(INTERFACE_NAME, "Deactivated");
|
||||
signal << PSESSION->sessionHandle;
|
||||
signal << pKeybind->id;
|
||||
signal << time;
|
||||
signal << std::unordered_map<std::string, sdbus::Variant>{};
|
||||
|
||||
m_pObject->emitSignal(signal);
|
||||
}
|
46
src/portals/GlobalShortcuts.hpp
Normal file
46
src/portals/GlobalShortcuts.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <protocols/hyprland-global-shortcuts-v1-protocol.h>
|
||||
|
||||
struct SKeybind {
|
||||
std::string id, description, preferredTrigger;
|
||||
hyprland_global_shortcut_v1* shortcut = nullptr;
|
||||
void* session = nullptr;
|
||||
};
|
||||
|
||||
class CGlobalShortcutsPortal {
|
||||
public:
|
||||
CGlobalShortcutsPortal(hyprland_global_shortcuts_manager_v1* mgr);
|
||||
|
||||
void onCreateSession(sdbus::MethodCall& call);
|
||||
void onBindShortcuts(sdbus::MethodCall& call);
|
||||
void onListShortcuts(sdbus::MethodCall& call);
|
||||
|
||||
void onActivated(SKeybind* pKeybind, uint64_t time);
|
||||
void onDeactivated(SKeybind* pKeybind, uint64_t time);
|
||||
|
||||
struct SSession {
|
||||
std::string appid;
|
||||
sdbus::ObjectPath requestHandle, sessionHandle;
|
||||
std::unique_ptr<sdbus::IObject> request, session;
|
||||
|
||||
bool registered = false;
|
||||
|
||||
std::vector<std::unique_ptr<SKeybind>> keybinds;
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<SSession>> m_vSessions;
|
||||
|
||||
private:
|
||||
struct {
|
||||
hyprland_global_shortcuts_manager_v1* manager;
|
||||
} m_sState;
|
||||
|
||||
std::unique_ptr<sdbus::IObject> m_pObject;
|
||||
|
||||
SSession* getSession(sdbus::ObjectPath& path);
|
||||
|
||||
const std::string INTERFACE_NAME = "org.freedesktop.impl.portal.GlobalShortcuts";
|
||||
const std::string OBJECT_PATH = "/org/freedesktop/portal/desktop";
|
||||
};
|
|
@ -280,7 +280,7 @@ static const hyprland_toplevel_export_frame_v1_listener hyprlandFrameListener =
|
|||
|
||||
// --------------------------------------------------------- //
|
||||
|
||||
void onCloseRequest(sdbus::MethodCall& call, CScreencopyPortal::SSession* sess) {
|
||||
static void onCloseRequest(sdbus::MethodCall& call, CScreencopyPortal::SSession* sess) {
|
||||
Debug::log(TRACE, "[screencopy] Close Request {}", (void*)sess);
|
||||
|
||||
if (!sess || !sess->request)
|
||||
|
@ -292,7 +292,7 @@ void onCloseRequest(sdbus::MethodCall& call, CScreencopyPortal::SSession* sess)
|
|||
sess->request.release();
|
||||
}
|
||||
|
||||
void onCloseSession(sdbus::MethodCall& call, CScreencopyPortal::SSession* sess) {
|
||||
static void onCloseSession(sdbus::MethodCall& call, CScreencopyPortal::SSession* sess) {
|
||||
Debug::log(TRACE, "[screencopy] Close Session {}", (void*)sess);
|
||||
|
||||
if (!sess || !sess->session)
|
||||
|
|
Loading…
Reference in a new issue