mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-22 06:35:57 +01:00
screencopy: improve restore data handling
This commit is contained in:
parent
5d64be5bd8
commit
5e40936fa0
5 changed files with 59 additions and 62 deletions
|
@ -84,6 +84,7 @@ void CScreencopyPortal::onSelectSources(sdbus::MethodCall& call) {
|
||||||
uint64_t windowHandle;
|
uint64_t windowHandle;
|
||||||
bool withCursor;
|
bool withCursor;
|
||||||
uint64_t timeIssued;
|
uint64_t timeIssued;
|
||||||
|
std::string windowClass;
|
||||||
} restoreData;
|
} restoreData;
|
||||||
|
|
||||||
for (auto& [key, val] : options) {
|
for (auto& [key, val] : options) {
|
||||||
|
@ -130,58 +131,32 @@ void CScreencopyPortal::onSelectSources(sdbus::MethodCall& call) {
|
||||||
restoreData.timeIssued);
|
restoreData.timeIssued);
|
||||||
} else {
|
} else {
|
||||||
// ver 3
|
// ver 3
|
||||||
auto sv = data.get<std::unordered_map<std::string, sdbus::Variant>>();
|
auto sv = data.get<std::unordered_map<std::string, sdbus::Variant>>();
|
||||||
|
|
||||||
uint64_t windowHandle = 0;
|
uint64_t windowHandle = 0;
|
||||||
std::string windowClass;
|
|
||||||
|
|
||||||
restoreData.windowHandle = 0;
|
restoreData.windowHandle = 0;
|
||||||
restoreData.exists = true;
|
restoreData.exists = true;
|
||||||
|
|
||||||
for (auto& [tkkey, tkval] : sv) {
|
for (auto& [tkkey, tkval] : sv) {
|
||||||
if (tkkey == "output") {
|
if (tkkey == "output")
|
||||||
restoreData.output = tkval.get<std::string>();
|
restoreData.output = tkval.get<std::string>();
|
||||||
} else if (tkkey == "windowHandle") {
|
else if (tkkey == "windowHandle")
|
||||||
windowHandle = tkval.get<uint64_t>();
|
windowHandle = tkval.get<uint64_t>();
|
||||||
} else if (tkkey == "windowClass") {
|
else if (tkkey == "windowClass")
|
||||||
windowClass = tkval.get<std::string>();
|
restoreData.windowClass = tkval.get<std::string>();
|
||||||
} else if (tkkey == "withCursor") {
|
else if (tkkey == "withCursor")
|
||||||
restoreData.withCursor = (bool)tkval.get<uint32_t>();
|
restoreData.withCursor = (bool)tkval.get<uint32_t>();
|
||||||
} else if (tkkey == "timeIssued") {
|
else if (tkkey == "timeIssued")
|
||||||
restoreData.timeIssued = tkval.get<uint64_t>();
|
restoreData.timeIssued = tkval.get<uint64_t>();
|
||||||
} else if (tkkey == "token") {
|
else if (tkkey == "token")
|
||||||
restoreData.token = tkval.get<std::string>();
|
restoreData.token = tkval.get<std::string>();
|
||||||
} else {
|
else
|
||||||
Debug::log(LOG, "[screencopy] restore token v3, unknown prop {}", tkkey);
|
Debug::log(LOG, "[screencopy] restore token v3, unknown prop {}", tkkey);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "[screencopy] Restore token v3 {} with data: {} {} {} {} {}", restoreData.token, windowHandle, windowClass, restoreData.output,
|
Debug::log(LOG, "[screencopy] Restore token v3 {} with data: {} {} {} {} {}", restoreData.token, windowHandle, restoreData.windowClass, restoreData.output,
|
||||||
restoreData.withCursor, restoreData.timeIssued);
|
restoreData.withCursor, restoreData.timeIssued);
|
||||||
|
|
||||||
// find window
|
|
||||||
if (windowHandle != 0 || !windowClass.empty()) {
|
|
||||||
if (windowHandle != 0) {
|
|
||||||
for (auto& h : g_pPortalManager->m_sHelpers.toplevel->m_vToplevels) {
|
|
||||||
if ((uint64_t)h->handle == windowHandle) {
|
|
||||||
restoreData.windowHandle = (uint64_t)h->handle;
|
|
||||||
Debug::log(LOG, "[screencopy] token v3 window found by handle {}", (void*)windowHandle);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (restoreData.windowHandle == 0 && !windowClass.empty()) {
|
|
||||||
// try class
|
|
||||||
for (auto& h : g_pPortalManager->m_sHelpers.toplevel->m_vToplevels) {
|
|
||||||
if (h->windowClass == windowClass) {
|
|
||||||
restoreData.windowHandle = (uint64_t)h->handle;
|
|
||||||
Debug::log(LOG, "[screencopy] token v3 window found by class {}", windowClass);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (key == "persist_mode") {
|
} else if (key == "persist_mode") {
|
||||||
|
@ -192,16 +167,23 @@ void CScreencopyPortal::onSelectSources(sdbus::MethodCall& call) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool RESTOREDATAVALID = restoreData.exists && g_pPortalManager->getOutputFromName(restoreData.output);
|
// clang-format off
|
||||||
|
const bool RESTOREDATAVALID = restoreData.exists &&
|
||||||
|
(
|
||||||
|
(!restoreData.output.empty() && g_pPortalManager->getOutputFromName(restoreData.output)) || // output exists
|
||||||
|
(!restoreData.windowClass.empty() && g_pPortalManager->m_sHelpers.toplevel->handleFromClass(restoreData.windowClass)) // window exists
|
||||||
|
);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
SSelectionData SHAREDATA;
|
SSelectionData SHAREDATA;
|
||||||
if (RESTOREDATAVALID) {
|
if (RESTOREDATAVALID) {
|
||||||
Debug::log(LOG, "[screencopy] restore data valid, not prompting");
|
Debug::log(LOG, "[screencopy] restore data valid, not prompting");
|
||||||
|
|
||||||
SHAREDATA.output = restoreData.output;
|
SHAREDATA.output = restoreData.output;
|
||||||
SHAREDATA.type = restoreData.windowHandle ? TYPE_WINDOW : TYPE_OUTPUT;
|
SHAREDATA.type = !restoreData.windowClass.empty() ? TYPE_WINDOW : TYPE_OUTPUT;
|
||||||
SHAREDATA.allowToken = true; // user allowed token before
|
SHAREDATA.windowHandle = !restoreData.windowClass.empty() ? g_pPortalManager->m_sHelpers.toplevel->handleFromClass(restoreData.windowClass)->handle : nullptr;
|
||||||
PSESSION->cursorMode = restoreData.withCursor;
|
SHAREDATA.allowToken = true; // user allowed token before
|
||||||
|
PSESSION->cursorMode = restoreData.withCursor;
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "[screencopy] restore data invalid / missing, prompting");
|
Debug::log(LOG, "[screencopy] restore data invalid / missing, prompting");
|
||||||
|
|
||||||
|
@ -275,13 +257,8 @@ void CScreencopyPortal::onStart(sdbus::MethodCall& call) {
|
||||||
case TYPE_GEOMETRY:
|
case TYPE_GEOMETRY:
|
||||||
case TYPE_OUTPUT: mapData["output"] = PSESSION->selection.output; break;
|
case TYPE_OUTPUT: mapData["output"] = PSESSION->selection.output; break;
|
||||||
case TYPE_WINDOW:
|
case TYPE_WINDOW:
|
||||||
mapData["windowHandle"] = (uint64_t)PSESSION->selection.windowHandle;
|
mapData["windowHandle"] = (uint64_t)PSESSION->selection.windowHandle->resource();
|
||||||
for (auto& w : g_pPortalManager->m_sHelpers.toplevel->m_vToplevels) {
|
mapData["windowClass"] = PSESSION->selection.windowClass;
|
||||||
if (w->handle == PSESSION->selection.windowHandle) {
|
|
||||||
mapData["windowClass"] = w->windowClass;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default: Debug::log(ERR, "[screencopy] wonk selection in token saving"); break;
|
default: Debug::log(ERR, "[screencopy] wonk selection in token saving"); break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ std::string buildWindowList() {
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
for (auto& e : g_pPortalManager->m_sHelpers.toplevel->m_vToplevels) {
|
for (auto& e : g_pPortalManager->m_sHelpers.toplevel->m_vToplevels) {
|
||||||
|
|
||||||
result += std::format("{}[HC>]{}[HT>]{}[HE>]", (uint32_t)(((uint64_t)e->handle->resource()) & 0xFFFFFFFF), sanitizeNameForWindowList(e->windowClass),
|
result += std::format("{}[HC>]{}[HT>]{}[HE>]", (uint32_t)(((uint64_t)e->handle->resource()) & 0xFFFFFFFF), sanitizeNameForWindowList(e->windowClass),
|
||||||
sanitizeNameForWindowList(e->windowTitle));
|
sanitizeNameForWindowList(e->windowTitle));
|
||||||
}
|
}
|
||||||
|
@ -87,15 +86,11 @@ SSelectionData promptForScreencopySelection() {
|
||||||
uint32_t handleLo = std::stoull(SEL.substr(7));
|
uint32_t handleLo = std::stoull(SEL.substr(7));
|
||||||
data.windowHandle = nullptr;
|
data.windowHandle = nullptr;
|
||||||
|
|
||||||
for (auto& e : g_pPortalManager->m_sHelpers.toplevel->m_vToplevels) {
|
const auto HANDLE = g_pPortalManager->m_sHelpers.toplevel->handleFromHandleLower(handleLo);
|
||||||
uint32_t handleLoE = (uint32_t)(((uint64_t)e->handle->resource()) & 0xFFFFFFFF);
|
if (HANDLE) {
|
||||||
|
data.windowHandle = HANDLE->handle;
|
||||||
if (handleLoE == handleLo) {
|
data.windowClass = HANDLE->windowClass;
|
||||||
data.windowHandle = e->handle;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (SEL.find("region:") == 0) {
|
} else if (SEL.find("region:") == 0) {
|
||||||
std::string running = SEL;
|
std::string running = SEL;
|
||||||
running = running.substr(7);
|
running = running.substr(7);
|
||||||
|
|
|
@ -36,6 +36,9 @@ struct SSelectionData {
|
||||||
SP<CCZwlrForeignToplevelHandleV1> windowHandle = nullptr;
|
SP<CCZwlrForeignToplevelHandleV1> windowHandle = nullptr;
|
||||||
uint32_t x = 0, y = 0, w = 0, h = 0; // for TYPE_GEOMETRY
|
uint32_t x = 0, y = 0, w = 0, h = 0; // for TYPE_GEOMETRY
|
||||||
bool allowToken = false;
|
bool allowToken = false;
|
||||||
|
|
||||||
|
// for restoring
|
||||||
|
std::string windowClass;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wl_buffer;
|
struct wl_buffer;
|
||||||
|
|
|
@ -41,7 +41,7 @@ void CToplevelManager::activate() {
|
||||||
m_pManager->setToplevel([this](CCZwlrForeignToplevelManagerV1* r, wl_proxy* newHandle) {
|
m_pManager->setToplevel([this](CCZwlrForeignToplevelManagerV1* r, wl_proxy* newHandle) {
|
||||||
Debug::log(TRACE, "[toplevel] New toplevel at {}", (void*)newHandle);
|
Debug::log(TRACE, "[toplevel] New toplevel at {}", (void*)newHandle);
|
||||||
|
|
||||||
m_vToplevels.emplace_back(std::make_unique<SToplevelHandle>(makeShared<CCZwlrForeignToplevelHandleV1>(newHandle)));
|
m_vToplevels.emplace_back(makeShared<SToplevelHandle>(makeShared<CCZwlrForeignToplevelHandleV1>(newHandle)));
|
||||||
});
|
});
|
||||||
m_pManager->setFinished([this](CCZwlrForeignToplevelManagerV1* r) { m_vToplevels.clear(); });
|
m_pManager->setFinished([this](CCZwlrForeignToplevelManagerV1* r) { m_vToplevels.clear(); });
|
||||||
|
|
||||||
|
@ -62,4 +62,22 @@ void CToplevelManager::deactivate() {
|
||||||
m_vToplevels.clear();
|
m_vToplevels.clear();
|
||||||
|
|
||||||
Debug::log(LOG, "[toplevel] unbound manager");
|
Debug::log(LOG, "[toplevel] unbound manager");
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<SToplevelHandle> CToplevelManager::handleFromClass(const std::string& windowClass) {
|
||||||
|
for (auto& tl : m_vToplevels) {
|
||||||
|
if (tl->windowClass == windowClass)
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<SToplevelHandle> CToplevelManager::handleFromHandleLower(uint32_t handle) {
|
||||||
|
for (auto& tl : m_vToplevels) {
|
||||||
|
if (((uint64_t)tl->handle->resource() & 0xFFFFFFFF) == handle)
|
||||||
|
return tl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
|
@ -21,10 +21,12 @@ class CToplevelManager {
|
||||||
public:
|
public:
|
||||||
CToplevelManager(uint32_t name, uint32_t version);
|
CToplevelManager(uint32_t name, uint32_t version);
|
||||||
|
|
||||||
void activate();
|
void activate();
|
||||||
void deactivate();
|
void deactivate();
|
||||||
|
SP<SToplevelHandle> handleFromClass(const std::string& windowClass);
|
||||||
|
SP<SToplevelHandle> handleFromHandleLower(uint32_t handle);
|
||||||
|
|
||||||
std::vector<std::unique_ptr<SToplevelHandle>> m_vToplevels;
|
std::vector<SP<SToplevelHandle>> m_vToplevels;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SP<CCZwlrForeignToplevelManagerV1> m_pManager = nullptr;
|
SP<CCZwlrForeignToplevelManagerV1> m_pManager = nullptr;
|
||||||
|
@ -35,4 +37,6 @@ class CToplevelManager {
|
||||||
uint32_t name = 0;
|
uint32_t name = 0;
|
||||||
uint32_t version = 0;
|
uint32_t version = 0;
|
||||||
} m_sWaylandConnection;
|
} m_sWaylandConnection;
|
||||||
|
|
||||||
|
friend struct SToplevelHandle;
|
||||||
};
|
};
|
Loading…
Reference in a new issue