From abbdcfb0cef7c8fddf3d20fe099f4524229c140b Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Sun, 15 Feb 2026 12:30:02 +0800 Subject: fix: address copilot review comments - Fix log level from INFO to DEBUG in DataDevice.cpp for offer operations - Remove unused permissionToHumanString function - Add I18n keys for clipboard read/write permissions - Add primary selection permission check in XWM.cpp (was only checking clipboard) - Add async permission handling in DataDeviceWlr.cpp for zwlr protocol --- src/i18n/Engine.cpp | 4 ++ src/i18n/Engine.hpp | 2 + .../permissions/DynamicPermissionManager.cpp | 15 +--- src/protocols/DataDeviceWlr.cpp | 84 ++++++++++++++++++++++ src/protocols/core/DataDevice.cpp | 2 +- src/xwayland/XWM.cpp | 2 +- 6 files changed, 94 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/i18n/Engine.cpp b/src/i18n/Engine.cpp index d31da80b..d4e88ff0 100644 --- a/src/i18n/Engine.cpp +++ b/src/i18n/Engine.cpp @@ -162,6 +162,10 @@ I18n::CI18nEngine::CI18nEngine() { huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "An application {app} is trying to capture your screen.\n\nDo you want to allow it to?"); huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "An application {app} is trying to load a plugin: {plugin}.\n\nDo you want to allow it to?"); huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "A new keyboard has been detected: {keyboard}.\n\nDo you want to allow it to operate?"); + huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_CLIPBOARD_READ, + "An application {app} is trying to read from your clipboard.\n\nDo you want to allow it to?"); + huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_CLIPBOARD_WRITE, + "An application {app} is trying to write to your clipboard.\n\nDo you want to allow it to?"); huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(unknown)"); huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_TITLE, "Permission request"); huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Hint: you can set persistent rules for these in the Hyprland config file."); diff --git a/src/i18n/Engine.hpp b/src/i18n/Engine.hpp index c3892546..096b20e8 100644 --- a/src/i18n/Engine.hpp +++ b/src/i18n/Engine.hpp @@ -18,6 +18,8 @@ namespace I18n { TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, TXT_KEY_PERMISSION_REQUEST_PLUGIN, TXT_KEY_PERMISSION_REQUEST_KEYBOARD, + TXT_KEY_PERMISSION_REQUEST_CLIPBOARD_READ, + TXT_KEY_PERMISSION_REQUEST_CLIPBOARD_WRITE, TXT_KEY_PERMISSION_UNKNOWN_NAME, TXT_KEY_PERMISSION_TITLE, TXT_KEY_PERMISSION_PERSISTENCE_HINT, diff --git a/src/managers/permissions/DynamicPermissionManager.cpp b/src/managers/permissions/DynamicPermissionManager.cpp index ff5a376c..223dea86 100644 --- a/src/managers/permissions/DynamicPermissionManager.cpp +++ b/src/managers/permissions/DynamicPermissionManager.cpp @@ -60,19 +60,6 @@ static const char* permissionToString(eDynamicPermissionType type) { return "error"; } -static const char* permissionToHumanString(eDynamicPermissionType type) { - switch (type) { - case PERMISSION_TYPE_UNKNOWN: return "An application {} is requesting an unknown permission."; - case PERMISSION_TYPE_SCREENCOPY: return "An application {} is trying to capture your screen.

Do you want to allow it to do so?"; - case PERMISSION_TYPE_PLUGIN: return "An application {} is trying to load a plugin: {}.

Do you want to load it?"; - case PERMISSION_TYPE_KEYBOARD: return "A new keyboard has been plugged in: {}.

Do you want to allow it to operate?"; - case PERMISSION_TYPE_CLIPBOARD_READ: return "An application {} is trying to read from your clipboard.

Do you want to allow it to do so?"; - case PERMISSION_TYPE_CLIPBOARD_WRITE: return "An application {} is trying to write to your clipboard.

Do you want to allow it to do so?"; - } - - return "error"; -} - static const char* specialPidToString(eSpecialPidTypes type) { switch (type) { case SPECIAL_PID_TYPE_CONFIG: return "config"; @@ -276,6 +263,8 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s case PERMISSION_TYPE_SCREENCOPY: description = I18n::i18nEngine()->localize(I18n::TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, {{"app", appName}}); break; case PERMISSION_TYPE_PLUGIN: description = I18n::i18nEngine()->localize(I18n::TXT_KEY_PERMISSION_REQUEST_PLUGIN, {{"app", appName}, {"plugin", binaryPath}}); break; case PERMISSION_TYPE_KEYBOARD: description = I18n::i18nEngine()->localize(I18n::TXT_KEY_PERMISSION_REQUEST_KEYBOARD, {{"keyboard", binaryPath}}); break; + case PERMISSION_TYPE_CLIPBOARD_READ: description = I18n::i18nEngine()->localize(I18n::TXT_KEY_PERMISSION_REQUEST_CLIPBOARD_READ, {{"app", appName}}); break; + case PERMISSION_TYPE_CLIPBOARD_WRITE: description = I18n::i18nEngine()->localize(I18n::TXT_KEY_PERMISSION_REQUEST_CLIPBOARD_WRITE, {{"app", appName}}); break; case PERMISSION_TYPE_UNKNOWN: description = I18n::i18nEngine()->localize(I18n::TXT_KEY_PERMISSION_REQUEST_UNKNOWN, {{"app", appName}}); break; } diff --git a/src/protocols/DataDeviceWlr.cpp b/src/protocols/DataDeviceWlr.cpp index 6cf343bd..e42156fd 100644 --- a/src/protocols/DataDeviceWlr.cpp +++ b/src/protocols/DataDeviceWlr.cpp @@ -32,6 +32,32 @@ CWLRDataOffer::CWLRDataOffer(SP resource_, SPpromiseFor(CLIENT, PERMISSION_TYPE_CLIPBOARD_READ); + if (!PROMISE) { + LOGM(Log::ERR, "BUG THIS: No promise for client permission for clipboard read"); + return; + } + auto sharedFd = std::make_shared(std::move(sendFd)); + PROMISE->then([this, mime = std::string(mime ? mime : ""), sharedFd](SP> pr) { + if (pr->hasError()) { + LOGM(Log::ERR, "BUG THIS: No permission returned for clipboard read"); + return; + } + + if (pr->result() != PERMISSION_RULE_ALLOW_MODE_ALLOW) { + LOGM(Log::INFO, "Clipboard read denied by user"); + return; + } + + if (!m_source) { + LOGM(Log::WARN, "Source disappeared while waiting for permission"); + return; + } + + LOGM(Log::DEBUG, "Offer {:x} asks to send data from source {:x} (permission granted)", (uintptr_t)this, (uintptr_t)m_source.get()); + + m_source->send(mime, std::move(*sharedFd)); + }); return; } @@ -137,6 +163,35 @@ CWLRDataDevice::CWLRDataDevice(SP resource_) : m_resou return; } else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) { LOGM(Log::INFO, "Clipboard write permission pending for client {:x}", (uintptr_t)CLIENT); + const auto PROMISE = g_pDynamicPermissionManager->promiseFor(CLIENT, PERMISSION_TYPE_CLIPBOARD_WRITE); + if (!PROMISE) { + LOGM(Log::ERR, "BUG THIS: No promise for client permission for clipboard write"); + return; + } + PROMISE->then([source](SP> pr) mutable { + if (pr->hasError()) { + LOGM(Log::ERR, "BUG THIS: No permission returned for clipboard write"); + return; + } + + if (pr->result() != PERMISSION_RULE_ALLOW_MODE_ALLOW) { + LOGM(Log::INFO, "Clipboard write denied by user"); + return; + } + + if (!source) { + LOGM(Log::WARN, "Source disappeared while waiting for permission"); + return; + } + + if (source && source->used()) + LOGM(Log::WARN, "setSelection on a used resource. By protocol, this is a violation, but firefox et al insist on doing this."); + + source->markUsed(); + + LOGM(Log::DEBUG, "wlr manager requests selection to {:x}", (uintptr_t)source.get()); + g_pSeatManager->setCurrentSelection(source); + }); return; } @@ -164,6 +219,35 @@ CWLRDataDevice::CWLRDataDevice(SP resource_) : m_resou return; } else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) { LOGM(Log::INFO, "Clipboard write permission pending for client {:x}", (uintptr_t)CLIENT); + const auto PROMISE = g_pDynamicPermissionManager->promiseFor(CLIENT, PERMISSION_TYPE_CLIPBOARD_WRITE); + if (!PROMISE) { + LOGM(Log::ERR, "BUG THIS: No promise for client permission for clipboard write"); + return; + } + PROMISE->then([source](SP> pr) mutable { + if (pr->hasError()) { + LOGM(Log::ERR, "BUG THIS: No permission returned for clipboard write"); + return; + } + + if (pr->result() != PERMISSION_RULE_ALLOW_MODE_ALLOW) { + LOGM(Log::INFO, "Clipboard write denied by user"); + return; + } + + if (!source) { + LOGM(Log::WARN, "Source disappeared while waiting for permission"); + return; + } + + if (source && source->used()) + LOGM(Log::WARN, "setSelection on a used resource. By protocol, this is a violation, but firefox et al insist on doing this."); + + source->markUsed(); + + LOGM(Log::DEBUG, "wlr manager requests primary selection to {:x}", (uintptr_t)source.get()); + g_pSeatManager->setCurrentPrimarySelection(source); + }); return; } diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index d0ccd123..e61f6776 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -97,7 +97,7 @@ CWLDataOfferResource::CWLDataOfferResource(SP resource_, SPm_server ? g_pXWayland->m_server->m_xwaylandClient : nullptr; - if (CLIENT && &sel == &m_clipboard) { + if (CLIENT) { const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(CLIENT, PERMISSION_TYPE_CLIPBOARD_WRITE); if (PERM == PERMISSION_RULE_ALLOW_MODE_DENY) { Log::logger->log(Log::INFO, "[xwm] Clipboard write denied by permission manager for XWayland"); -- cgit v1.2.3