From edc05ce88f79ceda0cdcb9aa68ec371b1af323de Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Mon, 16 Feb 2026 21:50:16 -0800 Subject: [PATCH 2/2] hyprexpo: add bring selection mode --- hyprexpo/README.md | 1 + hyprexpo/main.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++ hyprexpo/overview.cpp | 12 +++++++++-- hyprexpo/overview.hpp | 3 ++- 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index aac2e97..084f02b 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Here are a list of options you can use: | --- | --- | toggle | displays if hidden, hide if displayed select | selects the hovered desktop +bring | brings a window from the hovered desktop to the current desktop off | hides the overview disable | same as `off` on | displays the overview diff --git a/main.cpp b/main.cpp index ff9f380..78bac24 100644 --- a/main.cpp +++ b/main.cpp @@ -65,6 +65,47 @@ static void hkAddDamageB(void* thisptr, const pixman_region32_t* rg) { g_pOverview->onDamageReported(); } +static PHLWINDOW windowToBringFromWorkspace(const PHLWORKSPACE& workspace) { + if (!workspace) + return nullptr; + + for (auto it = g_pCompositor->m_windows.rbegin(); it != g_pCompositor->m_windows.rend(); ++it) { + const auto& w = *it; + if (!w || w->m_workspace != workspace || !w->m_isMapped || w->isHidden()) + continue; + + return w; + } + + return nullptr; +} + +static SDispatchResult bringWindowFromWorkspace(int64_t sourceWorkspaceID) { + if (sourceWorkspaceID == WORKSPACE_INVALID) + return {.success = false, .error = "selected workspace is empty"}; + + const auto FOCUSSTATE = Desktop::focusState(); + const auto MONITOR = FOCUSSTATE->monitor(); + if (!MONITOR || !MONITOR->m_activeWorkspace) + return {.success = false, .error = "no active monitor/workspace"}; + + if (sourceWorkspaceID == MONITOR->activeWorkspaceID()) + return {}; + + const auto SOURCEWORKSPACE = g_pCompositor->getWorkspaceByID(sourceWorkspaceID); + if (!SOURCEWORKSPACE) + return {.success = false, .error = "selected workspace is not open"}; + + const auto WINDOW = windowToBringFromWorkspace(SOURCEWORKSPACE); + if (!WINDOW) + return {.success = false, .error = "selected workspace has no mapped windows"}; + + g_pCompositor->moveWindowToWorkspaceSafe(WINDOW, MONITOR->m_activeWorkspace); + FOCUSSTATE->fullWindowFocus(WINDOW); + g_pCompositor->warpCursorTo(WINDOW->middle()); + return {}; +} + static SDispatchResult onExpoDispatcher(std::string arg) { if (g_pOverview && g_pOverview->m_isSwiping) @@ -77,6 +118,15 @@ static SDispatchResult onExpoDispatcher(std::string arg) { } return {}; } + if (arg == "bring") { + if (g_pOverview) { + g_pOverview->selectHoveredWorkspace(); + const auto BRINGRESULT = bringWindowFromWorkspace(g_pOverview->selectedWorkspaceID()); + g_pOverview->close(false); + return BRINGRESULT; + } + return {}; + } if (arg == "toggle") { if (g_pOverview) g_pOverview->close(); diff --git a/overview.cpp b/overview.cpp index 926a9f8..45ee982 100644 --- a/overview.cpp +++ b/overview.cpp @@ -343,6 +343,14 @@ void COverview::selectHoveredWorkspace() { closeOnID = x + y * SIDE_LENGTH; } +int64_t COverview::selectedWorkspaceID() const { + const int ID = closeOnID == -1 ? openedID : closeOnID; + if (ID < 0 || ID >= (int)images.size()) + return WORKSPACE_INVALID; + + return images[ID].workspaceID; +} + void COverview::redrawID(int id, bool forcelowres) { if (!pMonitor) return; @@ -451,7 +459,7 @@ void COverview::onDamageReported() { g_pCompositor->scheduleFrameForMonitor(pMonitor.lock()); } -void COverview::close() { +void COverview::close(bool switchToSelection) { if (closing) return; @@ -471,7 +479,7 @@ void COverview::close() { redrawAll(); - if (TILE.workspaceID != pMonitor->activeWorkspaceID()) { + if (switchToSelection && TILE.workspaceID != pMonitor->activeWorkspaceID()) { pMonitor->setSpecialWorkspace(0); // If this tile's workspace was WORKSPACE_INVALID, move to the next diff --git a/overview.hpp b/overview.hpp index 1f6bf3c..ca59f32 100644 --- a/overview.hpp +++ b/overview.hpp @@ -33,8 +33,9 @@ class COverview { void onSwipeEnd(); // close without a selection - void close(); + void close(bool switchToSelection = true); void selectHoveredWorkspace(); + int64_t selectedWorkspaceID() const; bool blockOverviewRendering = false; bool blockDamageReporting = false; -- 2.52.0