From 2c8eb43704156b81a1ab8ae7700af792aa9ae47e Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 30 Aug 2023 13:05:00 +0200 Subject: [PATCH] Allow the user to disallow a restore token --- hyprland-share-picker/main.cpp | 72 +++++++++++++++++------------ hyprland-share-picker/mainpicker.ui | 28 +++++++++-- src/portals/Screencopy.cpp | 4 +- src/shared/ScreencopyShared.cpp | 23 ++++++--- src/shared/ScreencopyShared.hpp | 1 + 5 files changed, 89 insertions(+), 39 deletions(-) diff --git a/hyprland-share-picker/main.cpp b/hyprland-share-picker/main.cpp index b354641..9deeaca 100644 --- a/hyprland-share-picker/main.cpp +++ b/hyprland-share-picker/main.cpp @@ -18,8 +18,8 @@ #include "mainpicker.h" std::string execAndGet(const char* cmd) { - std::array buffer; - std::string result; + std::array buffer; + std::string result; std::unique_ptr pipe(popen(cmd, "r"), pclose); if (!pipe) { throw std::runtime_error("popen() failed!"); @@ -30,12 +30,12 @@ std::string execAndGet(const char* cmd) { return result; } -QApplication* pickerPtr = nullptr; -MainPicker* mainPickerPtr = nullptr; +QApplication* pickerPtr = nullptr; +MainPicker* mainPickerPtr = nullptr; struct SWindowEntry { - std::string name; - std::string clazz; + std::string name; + std::string clazz; unsigned long long id = 0; }; @@ -50,15 +50,15 @@ std::vector getWindows(const char* env) { while (!rolling.empty()) { // ID const auto IDSEPPOS = rolling.find("[HC>]"); - const auto IDSTR = rolling.substr(0, IDSEPPOS); + const auto IDSTR = rolling.substr(0, IDSEPPOS); // class const auto CLASSSEPPOS = rolling.find("[HT>]"); - const auto CLASSSTR = rolling.substr(IDSEPPOS + 5, CLASSSEPPOS - IDSEPPOS - 5); + const auto CLASSSTR = rolling.substr(IDSEPPOS + 5, CLASSSEPPOS - IDSEPPOS - 5); // title const auto TITLESEPPOS = rolling.find("[HE>]"); - const auto TITLESTR = rolling.substr(CLASSSEPPOS + 5, TITLESEPPOS - 5 - CLASSSEPPOS); + const auto TITLESTR = rolling.substr(CLASSSEPPOS + 5, TITLESEPPOS - 5 - CLASSSEPPOS); try { result.push_back({TITLESTR, CLASSSTR, std::stoull(IDSTR)}); @@ -75,9 +75,9 @@ std::vector getWindows(const char* env) { int main(int argc, char* argv[]) { qputenv("QT_LOGGING_RULES", "qml=false"); - const char* WINDOWLISTSTR = getenv("XDPH_WINDOW_SHARING_LIST"); + const char* WINDOWLISTSTR = getenv("XDPH_WINDOW_SHARING_LIST"); - const auto WINDOWLIST = getWindows(WINDOWLISTSTR); + const auto WINDOWLIST = getWindows(WINDOWLISTSTR); QApplication picker(argc, argv); pickerPtr = &picker; @@ -85,30 +85,37 @@ int main(int argc, char* argv[]) { mainPickerPtr = &w; // get the tabwidget - const auto TABWIDGET = (QTabWidget*)w.children()[1]->children()[0]; + const auto TABWIDGET = (QTabWidget*)w.children()[1]->children()[0]; + const auto ALLOWTOKENBUTTON = (QCheckBox*)w.children()[1]->children()[1]; const auto TAB1 = (QWidget*)TABWIDGET->children()[0]; - const auto SCREENS_SCROLL_AREA_CONTENTS = (QWidget*)TAB1->findChild("screens")->findChild("scrollArea")->findChild("scrollAreaWidgetContents"); + const auto SCREENS_SCROLL_AREA_CONTENTS = + (QWidget*)TAB1->findChild("screens")->findChild("scrollArea")->findChild("scrollAreaWidgetContents"); // add all screens - const auto SCREENS = picker.screens(); + const auto SCREENS = picker.screens(); - constexpr int BUTTON_WIDTH = 441; + constexpr int BUTTON_WIDTH = 441; constexpr int BUTTON_HEIGHT = 41; - constexpr int BUTTON_PAD = 4; + constexpr int BUTTON_PAD = 4; for (int i = 0; i < SCREENS.size(); ++i) { - const auto GEOMETRY = SCREENS[i]->geometry(); + const auto GEOMETRY = SCREENS[i]->geometry(); - QString text = QString::fromStdString(std::string("Screen " + std::to_string(i) + " at " + std::to_string(GEOMETRY.x()) + ", " + std::to_string(GEOMETRY.y()) + " (" + std::to_string(GEOMETRY.width()) + "x" + std::to_string(GEOMETRY.height()) + ") (") + SCREENS[i]->name().toStdString() + ")"); + QString text = QString::fromStdString(std::string("Screen " + std::to_string(i) + " at " + std::to_string(GEOMETRY.x()) + ", " + std::to_string(GEOMETRY.y()) + " (" + + std::to_string(GEOMETRY.width()) + "x" + std::to_string(GEOMETRY.height()) + ") (") + + SCREENS[i]->name().toStdString() + ")"); QPushButton* button = new QPushButton(text, (QWidget*)SCREENS_SCROLL_AREA_CONTENTS); button->move(9, 5 + (BUTTON_HEIGHT + BUTTON_PAD) * i); button->resize(BUTTON_WIDTH, BUTTON_HEIGHT); QObject::connect(button, &QPushButton::clicked, [=]() { std::string ID = button->text().toStdString(); - ID = ID.substr(ID.find_last_of('(') + 1); - ID = ID.substr(0, ID.find_last_of(')')); + ID = ID.substr(ID.find_last_of('(') + 1); + ID = ID.substr(0, ID.find_last_of(')')); + + std::cout << (ALLOWTOKENBUTTON->isChecked() ? "r" : ""); + std::cout << "/"; std::cout << "screen:" << ID << "\n"; pickerPtr->quit(); @@ -119,12 +126,13 @@ int main(int argc, char* argv[]) { SCREENS_SCROLL_AREA_CONTENTS->resize(SCREENS_SCROLL_AREA_CONTENTS->size().width(), 5 + (BUTTON_HEIGHT + BUTTON_PAD) * SCREENS.size()); // windows - const auto WINDOWS_SCROLL_AREA_CONTENTS = (QWidget*)TAB1->findChild("windows")->findChild("scrollArea_2")->findChild("scrollAreaWidgetContents_2"); + const auto WINDOWS_SCROLL_AREA_CONTENTS = + (QWidget*)TAB1->findChild("windows")->findChild("scrollArea_2")->findChild("scrollAreaWidgetContents_2"); // loop over them int windowIterator = 0; for (auto& window : WINDOWLIST) { - QString text = QString::fromStdString(window.clazz + ": " + window.name); + QString text = QString::fromStdString(window.clazz + ": " + window.name); QPushButton* button = new QPushButton(text, (QWidget*)WINDOWS_SCROLL_AREA_CONTENTS); button->move(9, 5 + (BUTTON_HEIGHT + BUTTON_PAD) * windowIterator); @@ -133,6 +141,9 @@ int main(int argc, char* argv[]) { mainPickerPtr->windowIDs[button] = window.id; QObject::connect(button, &QPushButton::clicked, [=]() { + std::cout << (ALLOWTOKENBUTTON->isChecked() ? "r" : ""); + std::cout << "/"; + std::cout << "window:" << mainPickerPtr->windowIDs[button] << "\n"; pickerPtr->quit(); return 0; @@ -144,16 +155,16 @@ int main(int argc, char* argv[]) { WINDOWS_SCROLL_AREA_CONTENTS->resize(WINDOWS_SCROLL_AREA_CONTENTS->size().width(), 5 + (BUTTON_HEIGHT + BUTTON_PAD) * windowIterator); // lastly, region - const auto REGION_OBJECT = (QWidget*)TAB1->findChild("region"); + const auto REGION_OBJECT = (QWidget*)TAB1->findChild("region"); - QString text = "Select region..."; + QString text = "Select region..."; QPushButton* button = new QPushButton(text, (QWidget*)REGION_OBJECT); button->move(79, 80); button->resize(321, 41); QObject::connect(button, &QPushButton::clicked, [=]() { auto REGION = execAndGet("slurp -f \"%o %x %y %w %h\""); - REGION = REGION.substr(0, REGION.length()); + REGION = REGION.substr(0, REGION.length()); // now, get the screen QScreen* pScreen = nullptr; @@ -179,15 +190,18 @@ int main(int argc, char* argv[]) { // get all the coords try { - REGION = REGION.substr(REGION.find_first_of(' ') + 1); + REGION = REGION.substr(REGION.find_first_of(' ') + 1); const auto X = std::stoi(REGION.substr(0, REGION.find_first_of(' '))); - REGION = REGION.substr(REGION.find_first_of(' ') + 1); + REGION = REGION.substr(REGION.find_first_of(' ') + 1); const auto Y = std::stoi(REGION.substr(0, REGION.find_first_of(' '))); - REGION = REGION.substr(REGION.find_first_of(' ') + 1); + REGION = REGION.substr(REGION.find_first_of(' ') + 1); const auto W = std::stoi(REGION.substr(0, REGION.find_first_of(' '))); - REGION = REGION.substr(REGION.find_first_of(' ') + 1); + REGION = REGION.substr(REGION.find_first_of(' ') + 1); const auto H = std::stoi(REGION); + std::cout << (ALLOWTOKENBUTTON->isChecked() ? "r" : ""); + std::cout << "/"; + std::cout << "region:" << SCREEN_NAME << "@" << X - pScreen->geometry().x() << "," << Y - pScreen->geometry().y() << "," << W << "," << H << "\n"; pickerPtr->quit(); return 0; diff --git a/hyprland-share-picker/mainpicker.ui b/hyprland-share-picker/mainpicker.ui index c40a385..c14d1d6 100644 --- a/hyprland-share-picker/mainpicker.ui +++ b/hyprland-share-picker/mainpicker.ui @@ -66,7 +66,7 @@ QTabWidget::North - 0 + 1 @@ -78,9 +78,12 @@ 9 9 461 - 241 + 201 + + Qt::ScrollBarAlwaysOff + false @@ -115,9 +118,12 @@ 9 9 461 - 241 + 201 + + Qt::ScrollBarAlwaysOff + false @@ -148,6 +154,22 @@ + + + + 340 + 256 + 140 + 21 + + + + By selecting this, the application will be given a restore token that it can use to skip prompting you next time. Only select if you trust the application. + + + Allow a restore token + + diff --git a/src/portals/Screencopy.cpp b/src/portals/Screencopy.cpp index 203ef7d..97e3e88 100644 --- a/src/portals/Screencopy.cpp +++ b/src/portals/Screencopy.cpp @@ -539,7 +539,7 @@ void CScreencopyPortal::onStart(sdbus::MethodCall& call) { std::unordered_map options; - if (PSESSION->persistMode != 0) { + if (PSESSION->persistMode != 0 && PSESSION->selection.allowToken) { // give them a token :) std::unordered_map mapData; @@ -564,6 +564,8 @@ void CScreencopyPortal::onStart(sdbus::MethodCall& call) { sdbus::Variant restoreData{mapData}; sdbus::Struct fullRestoreStruct{"hyprland", 3, restoreData}; options["restore_data"] = sdbus::Variant{fullRestoreStruct}; + + Debug::log(LOG, "[screencopy] Sent restore token to {}", PSESSION->sessionHandle.c_str()); } uint32_t type = 0; diff --git a/src/shared/ScreencopyShared.cpp b/src/shared/ScreencopyShared.cpp index 6bba71e..cc22875 100644 --- a/src/shared/ScreencopyShared.cpp +++ b/src/shared/ScreencopyShared.cpp @@ -49,14 +49,25 @@ SSelectionData promptForScreencopySelection() { Debug::log(LOG, "[sc] Selection: {}", RETVAL); - if (RETVAL.find("screen:") == 0) { + const auto FLAGS = RETVAL.substr(0, RETVAL.find_first_of('/')); + const auto SEL = RETVAL.substr(RETVAL.find_first_of('/') + 1); + + for (auto& flag : FLAGS) { + if (flag == 'r') { + data.allowToken = true; + } else { + Debug::log(LOG, "[screencopy] unknown flag from share-picker: {}", flag); + } + } + + if (SEL.find("screen:") == 0) { data.type = TYPE_OUTPUT; - data.output = RETVAL.substr(7); + data.output = SEL.substr(7); data.output.pop_back(); - } else if (RETVAL.find("window:") == 0) { + } else if (SEL.find("window:") == 0) { data.type = TYPE_WINDOW; - uint32_t handleLo = std::stoull(RETVAL.substr(7)); + uint32_t handleLo = std::stoull(SEL.substr(7)); data.windowHandle = nullptr; for (auto& e : g_pPortalManager->m_sHelpers.toplevel->m_vToplevels) { @@ -68,8 +79,8 @@ SSelectionData promptForScreencopySelection() { } } - } else if (RETVAL.find("region:") == 0) { - std::string running = RETVAL; + } else if (SEL.find("region:") == 0) { + std::string running = SEL; running = running.substr(7); data.type = TYPE_GEOMETRY; data.output = running.substr(0, running.find_first_of('@')); diff --git a/src/shared/ScreencopyShared.hpp b/src/shared/ScreencopyShared.hpp index 15fe6de..0ae48dd 100644 --- a/src/shared/ScreencopyShared.hpp +++ b/src/shared/ScreencopyShared.hpp @@ -35,6 +35,7 @@ struct SSelectionData { std::string output; zwlr_foreign_toplevel_handle_v1* windowHandle = nullptr; uint32_t x = 0, y = 0, w = 0, h = 0; // for TYPE_GEOMETRY + bool allowToken = false; }; struct wl_buffer;