hyprland: switch overview to patched hyprexpo

This commit is contained in:
2026-05-16 12:32:50 -07:00
parent 890bdb0925
commit 24c1a0a4d4
11 changed files with 217 additions and 221 deletions

View File

@@ -89,7 +89,7 @@ function M.setup(ctx)
local function setup_window_overview_bindings() local function setup_window_overview_bindings()
bind(main_mod .. " + SHIFT + C", hl.dsp.window.close(), desc("Close active window")) bind(main_mod .. " + SHIFT + C", hl.dsp.window.close(), desc("Close active window"))
bind(main_mod .. " + SHIFT + Q", hl.dsp.exit(), desc("Exit Hyprland")) bind(main_mod .. " + SHIFT + Q", hl.dsp.exit(), desc("Exit Hyprland"))
bind(main_mod .. " + Tab", hyprspace("toggle"), desc("Toggle Hyprspace workspace overview", overview_bind_opts)) bind(main_mod .. " + Tab", hyprexpo("toggle"), desc("Toggle hyprexpo workspace overview", overview_bind_opts))
bind(main_mod .. " + SHIFT + Tab", hyprwinview({ bind(main_mod .. " + SHIFT + Tab", hyprwinview({
action = "show", action = "show",
include_current_workspace = false, include_current_workspace = false,
@@ -195,21 +195,6 @@ function M.setup(ctx)
bind("catchall", hl.dsp.submap("reset"), desc("Exit window picker")) bind("catchall", hl.dsp.submap("reset"), desc("Exit window picker"))
end) end)
hl.define_submap("hyprexpo", function()
bind("Up", hyprexpo_dispatch("kb_focus", "up"), desc("Focus workspace tile above"))
bind("Left", hyprexpo_dispatch("kb_focus", "left"), desc("Focus workspace tile to the left"))
bind("Down", hyprexpo_dispatch("kb_focus", "down"), desc("Focus workspace tile below"))
bind("Right", hyprexpo_dispatch("kb_focus", "right"), desc("Focus workspace tile to the right"))
bind("Return", hyprexpo_dispatch("kb_confirm"), desc("Select focused workspace tile"))
bind("Space", hyprexpo_dispatch("kb_confirm"), desc("Select focused workspace tile"))
for _, token in ipairs({ "a", "s", "d", "f", "g", "q", "w", "e", "r", "t", "z", "x", "c", "v", "b" }) do
bind(string.upper(token), hyprexpo_dispatch("kb_select", token), desc("Select workspace tile " .. token))
end
bind("Escape", hyprexpo("off"), desc("Close workspace expo"))
bind("catchall", hyprexpo("off"), desc("Close workspace expo"))
end)
end end
local function setup_window_resize_and_monitor_bindings() local function setup_window_resize_and_monitor_bindings()

View File

@@ -127,10 +127,6 @@ function M.setup(ctx)
return hyprexpo_call("expo", action or "toggle") return hyprexpo_call("expo", action or "toggle")
end end
local function hyprexpo_dispatch(dispatcher, arg)
return hyprexpo_call(dispatcher, arg)
end
local function hyprwinview(action) local function hyprwinview(action)
return function() return function()
local label = "hyprwinview" local label = "hyprwinview"
@@ -175,33 +171,6 @@ function M.setup(ctx)
end end
end end
local function hyprspace(action)
return function()
local request = action
if type(request) == "table" then
request.action = request.action or "toggle"
if request.all == nil then
request.all = true
end
else
request = { action = action or "toggle", all = true }
end
overview_trace("hyprspace " .. tostring(request.action))
if hl.plugin and hl.plugin.hyprspace and hl.plugin.hyprspace.overview then
hl.plugin.hyprspace.overview(request)
else
hl.notification.create({
text = "hyprspace is not loaded",
duration = 1800,
icon = notification_icons.warning,
color = "rgba(edb443ff)",
font_size = 13,
})
end
end
end
local function apply_nstack_config() local function apply_nstack_config()
if verify_config or not enable_nstack or not configure_nstack_plugin_from_lua then if verify_config or not enable_nstack or not configure_nstack_plugin_from_lua then
return return
@@ -240,8 +209,9 @@ function M.setup(ctx)
gap_size = 5, gap_size = 5,
gap_size_outer = 0, gap_size_outer = 0,
bg_col = 0xff111111, bg_col = 0xff111111,
workspace_method = "center current", workspace_method = "first 1",
skip_empty = false, skip_empty = false,
max_workspace = max_workspace,
gesture_distance = 200, gesture_distance = 200,
keynav_wrap_h = 1, keynav_wrap_h = 1,
keynav_wrap_v = 1, keynav_wrap_v = 1,
@@ -258,12 +228,7 @@ function M.setup(ctx)
label_position = "center", label_position = "center",
label_offset_x = 6, label_offset_x = 6,
label_offset_y = 6, label_offset_y = 6,
selection_label_enable = 1, selection_label_enable = 0,
selection_label_token_map = "a,s,d,f,g,q,w,e,r,t,z,x,c,v,b",
selection_label_position = "top-right",
selection_label_offset_x = 6,
selection_label_offset_y = 6,
selection_label_color = 0xffedb443,
label_show = "always", label_show = "always",
label_color_default = 0xffffffff, label_color_default = 0xffffffff,
label_color_hover = 0xffeeeeee, label_color_hover = 0xffeeeeee,
@@ -614,10 +579,8 @@ function M.setup(ctx)
ctx.overview_trace = overview_trace ctx.overview_trace = overview_trace
ctx.window_selector = window_selector ctx.window_selector = window_selector
ctx.hyprexpo = hyprexpo ctx.hyprexpo = hyprexpo
ctx.hyprexpo_dispatch = hyprexpo_dispatch
ctx.hyprwinview = hyprwinview ctx.hyprwinview = hyprwinview
ctx.workspacehistory = workspacehistory ctx.workspacehistory = workspacehistory
ctx.hyprspace = hyprspace
ctx.apply_nstack_config = apply_nstack_config ctx.apply_nstack_config = apply_nstack_config
ctx.apply_hyprexpo_config = apply_hyprexpo_config ctx.apply_hyprexpo_config = apply_hyprexpo_config
ctx.apply_hyprwinview_config = apply_hyprwinview_config ctx.apply_hyprwinview_config = apply_hyprwinview_config

View File

@@ -4,10 +4,6 @@ function M.setup(ctx)
local _ENV = ctx local _ENV = ctx
local file_chooser_title_rule = "^(Open File|Open Files|Save File|Save Files|Save As|Select File|Select Files|Choose File|Choose Files|File Upload|Upload File|Upload Files|Select Folder|Choose Folder|Open Folder|Save Folder)$" local file_chooser_title_rule = "^(Open File|Open Files|Save File|Save Files|Save As|Select File|Select Files|Choose File|Choose Files|File Upload|Upload File|Upload Files|Select Folder|Choose Folder|Open Folder|Save Folder)$"
local function plugin_path(env_name, default)
return os.getenv(env_name) or default
end
local function lower_string(value) local function lower_string(value)
return string.lower(tostring(value or "")) return string.lower(tostring(value or ""))
end end
@@ -79,9 +75,6 @@ function M.setup(ctx)
if enable_hyprexpo and not verify_config then if enable_hyprexpo and not verify_config then
hl.plugin.load("/run/current-system/sw/lib/libhyprexpo.so") hl.plugin.load("/run/current-system/sw/lib/libhyprexpo.so")
end end
if enable_hyprspace and not verify_config then
hl.plugin.load(plugin_path("HYPRLAND_HYPRSPACE_PLUGIN", "/run/current-system/sw/lib/libHyprspace.so"))
end
if enable_hyprwinview and not verify_config then if enable_hyprwinview and not verify_config then
hl.plugin.load("/run/current-system/sw/lib/libhyprwinview.so") hl.plugin.load("/run/current-system/sw/lib/libhyprwinview.so")
end end

View File

@@ -1,20 +1,3 @@
local function env_bool(name, default)
local value = os.getenv(name)
if value == nil or value == "" then
return default
end
value = value:lower()
if value == "1" or value == "true" or value == "yes" or value == "on" then
return true
end
if value == "0" or value == "false" or value == "no" or value == "off" then
return false
end
return default
end
local shell_ui_command = "hypr_shell_ui" local shell_ui_command = "hypr_shell_ui"
local columns_layout = "nStack" local columns_layout = "nStack"
local large_main_layout = "master" local large_main_layout = "master"
@@ -63,7 +46,6 @@ return {
current_layout = columns_layout, current_layout = columns_layout,
enable_nstack = true, enable_nstack = true,
enable_hyprexpo = true, enable_hyprexpo = true,
enable_hyprspace = env_bool("HYPRLAND_ENABLE_HYPRSPACE", true),
enable_hyprwinview = true, enable_hyprwinview = true,
enable_workspace_history = true, enable_workspace_history = true,
enable_hyprwobbly = true, enable_hyprwobbly = true,

View File

@@ -20,7 +20,6 @@ Options:
--config PATH Run Hyprland with this config instead of a generated --config PATH Run Hyprland with this config instead of a generated
minimal config. minimal config.
--user-config Run the normal user Lua config. --user-config Run the normal user Lua config.
--enable-hyprspace Set HYPRLAND_ENABLE_HYPRSPACE=1 for the nested config.
--no-load Start the nested compositor but do not load a plugin. --no-load Start the nested compositor but do not load a plugin.
--detach Leave the nested compositor running and exit after setup. --detach Leave the nested compositor running and exit after setup.
--keep-tmp Do not delete the generated config/log directory. --keep-tmp Do not delete the generated config/log directory.
@@ -33,7 +32,7 @@ Examples:
hypr_plugin_dev_session hypr_plugin_dev_session
hypr_plugin_dev_session --repo ~/Projects/hyprwobbly --attr .#hyprwobbly hypr_plugin_dev_session --repo ~/Projects/hyprwobbly --attr .#hyprwobbly
hypr_plugin_dev_session --plugin "$PWD/result/lib/libhyprwobbly.so" hypr_plugin_dev_session --plugin "$PWD/result/lib/libhyprwobbly.so"
hypr_plugin_dev_session --user-config --enable-hyprspace --no-load hypr_plugin_dev_session --user-config --no-load
EOF EOF
} }
@@ -51,7 +50,6 @@ hyprland_bin=""
force_system_hyprland=0 force_system_hyprland=0
load_plugin=1 load_plugin=1
config_arg="" config_arg=""
enable_hyprspace=0
detach=0 detach=0
keep_tmp=0 keep_tmp=0
size="1280x720" size="1280x720"
@@ -94,10 +92,6 @@ while [[ $# -gt 0 ]]; do
config_arg="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/hyprland.lua" config_arg="${XDG_CONFIG_HOME:-$HOME/.config}/hypr/hyprland.lua"
shift shift
;; ;;
--enable-hyprspace)
enable_hyprspace=1
shift
;;
--no-load) --no-load)
load_plugin=0 load_plugin=0
shift shift
@@ -347,7 +341,6 @@ setsid env \
WAYLAND_DISPLAY="$parent_wayland" \ WAYLAND_DISPLAY="$parent_wayland" \
XDG_SESSION_TYPE=wayland \ XDG_SESSION_TYPE=wayland \
IMALISON_HYPRLAND_DEV_SESSION=1 \ IMALISON_HYPRLAND_DEV_SESSION=1 \
HYPRLAND_ENABLE_HYPRSPACE="$enable_hyprspace" \
bash -c 'trap "" HUP; exec "$1" --config "$2"' hyprland-launch "$hyprland_bin" "$config" >"$stdout_log" 2>&1 & bash -c 'trap "" HUP; exec "$1" --config "$2"' hyprland-launch "$hyprland_bin" "$config" >"$stdout_log" 2>&1 &
pid=$! pid=$!

25
nixos/flake.lock generated
View File

@@ -1,29 +1,5 @@
{ {
"nodes": { "nodes": {
"Hyprspace": {
"inputs": {
"hyprland": [
"hyprland"
],
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1778832075,
"narHash": "sha256-q+5ETwj+oiZBT9j6/huwB8nwV4nbZdZmCrchL2E7tDQ=",
"owner": "colonelpanic8",
"repo": "Hyprspace",
"rev": "bf2ef21007e8963fcb0016ae26b6b21704946f80",
"type": "github"
},
"original": {
"owner": "colonelpanic8",
"ref": "codex/defer-hyprspace-initial-reload",
"repo": "Hyprspace",
"type": "github"
}
},
"agenix": { "agenix": {
"inputs": { "inputs": {
"darwin": "darwin", "darwin": "darwin",
@@ -1661,7 +1637,6 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"Hyprspace": "Hyprspace",
"agenix": "agenix", "agenix": "agenix",
"aquamarine": [ "aquamarine": [
"hyprland", "hyprland",

View File

@@ -125,14 +125,6 @@
inputs.hyprland.follows = "hyprland"; inputs.hyprland.follows = "hyprland";
}; };
Hyprspace = {
url = "github:colonelpanic8/Hyprspace/codex/defer-hyprspace-initial-reload";
inputs = {
hyprland.follows = "hyprland";
systems.follows = "systems";
};
};
hyprwinview = { hyprwinview = {
url = "github:colonelpanic8/hyprwinview"; url = "github:colonelpanic8/hyprwinview";
inputs.hyprland.follows = "hyprland"; inputs.hyprland.follows = "hyprland";

View File

@@ -26,7 +26,13 @@
hyprlang = inputs.hyprlang.packages.${system}.hyprlang; hyprlang = inputs.hyprlang.packages.${system}.hyprlang;
hyprutils = inputs.hyprutils.packages.${system}.hyprutils; hyprutils = inputs.hyprutils.packages.${system}.hyprutils;
}; };
hyprexpo = inputs.hyprexpo.packages.${system}.hyprexpo; hyprexpo = inputs.hyprexpo.packages.${system}.hyprexpo.overrideAttrs (old: {
patches =
(old.patches or [])
++ [
../packages/hyprexpo-drag-windows.patch
];
});
tangledConfig = dotfilesOrgApi.org-agenda-custom-config; tangledConfig = dotfilesOrgApi.org-agenda-custom-config;
# Import container build logic # Import container build logic

View File

@@ -89,15 +89,6 @@
overrideAttrs = f: makeHyprlandLuaPackage (package.overrideAttrs f); overrideAttrs = f: makeHyprlandLuaPackage (package.overrideAttrs f);
}; };
hyprlandPackage = makeHyprlandLuaPackage baseHyprlandPackage; hyprlandPackage = makeHyprlandLuaPackage baseHyprlandPackage;
hyprspace = inputs.Hyprspace.packages.${system}.Hyprspace.overrideAttrs (old: {
version = "${old.version}-pr231";
__intentionallyOverridingVersion = true;
patches =
(old.patches or [])
++ [
./packages/hyprspace-lua-api.patch
];
});
enableHyprglass = false; enableHyprglass = false;
hyprglass = pkgs.callPackage ./packages/hyprglass { hyprglass = pkgs.callPackage ./packages/hyprglass {
src = inputs.hyprglass; src = inputs.hyprglass;
@@ -115,12 +106,17 @@
./packages/hyprwobbly-safe-geometry-and-idle-timer.patch ./packages/hyprwobbly-safe-geometry-and-idle-timer.patch
]; ];
}); });
hyprexpo = inputs.hyprexpo.packages.${system}.hyprexpo; hyprexpo = inputs.hyprexpo.packages.${system}.hyprexpo.overrideAttrs (old: {
patches =
(old.patches or [])
++ [
./packages/hyprexpo-drag-windows.patch
];
});
hyprlandPluginPackages = hyprlandPluginPackages =
[ [
inputs.hyprNStack.packages.${system}.hyprNStack inputs.hyprNStack.packages.${system}.hyprNStack
hyprexpo hyprexpo
hyprspace
inputs.hyprwinview.packages.${system}.hyprwinview inputs.hyprwinview.packages.${system}.hyprwinview
inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history inputs.hypr-workspace-history.packages.${system}.hypr-workspace-history
hyprwobbly hyprwobbly

View File

@@ -0,0 +1,198 @@
--- a/Overview.hpp
+++ b/Overview.hpp
@@ -80,6 +80,12 @@
void updateHoveredFromMouse();
bool isTileValid(int id) const;
void ensureKeyboardFocus();
+ void beginWindowDrag();
+ bool finishWindowDrag();
+ void updateWindowDrag();
+ PHLWINDOW windowAtTilePoint(int id, const Vector2D& localPoint) const;
+ Vector2D tilePointToWorkspacePoint(int id, const Vector2D& localPoint) const;
+ PHLWORKSPACE ensureWorkspaceForTile(int id);
int SIDE_LENGTH = 3;
int GAP_WIDTH = 5;
@@ -94,6 +100,11 @@
int hoveredID = -1;
int kbFocusID = -1;
+ Vector2D dragStartLocal = Vector2D{};
+ int dragSourceID = -1;
+ bool dragMoved = false;
+ PHLWINDOW dragWindow;
+
std::vector<SWorkspaceImage> images;
PHLWORKSPACE startedOn;
--- a/Overview.cpp
+++ b/Overview.cpp
@@ -5,6 +5,7 @@
#include <cctype>
#include <cmath>
#include <optional>
+#include <string>
#define private public
#define protected public
#include <hyprland/src/render/Renderer.hpp>
@@ -79,6 +80,10 @@
return grad;
}
+static bool windowVisibleOnWorkspace(const PHLWINDOW& window, const PHLWORKSPACE& workspace) {
+ return window && workspace && window->m_workspace == workspace && window->m_isMapped && !window->isHidden() && !window->m_pinned;
+}
+
static void ensureFramebuffer(COverview::SWorkspaceImage& image, const CBox& monbox, uint32_t drmFormat) {
if (!image.fb)
image.fb = g_pHyprRenderer->createFB("hyprexpo");
@@ -337,9 +342,29 @@
info.cancelled = true;
lastMousePosLocal = g_pInputManager->getMouseCoordsInternal() - pMonitor->m_position;
updateHoveredFromMouse();
+ updateWindowDrag();
+ };
+
+ auto onCursorSelect = [this](IPointer::SButtonEvent event, Event::SCallbackInfo& info) {
+ if (closing)
+ return;
+
+ info.cancelled = true;
+
+ if (event.state == WL_POINTER_BUTTON_STATE_PRESSED) {
+ beginWindowDrag();
+ return;
+ }
+
+ if (finishWindowDrag())
+ return;
+
+ selectHoveredWorkspace();
+
+ close();
};
- auto onCursorSelect = [this](Event::SCallbackInfo& info) {
+ auto onTouchSelect = [this](Event::SCallbackInfo& info) {
if (closing)
return;
@@ -353,8 +378,107 @@
mouseMoveHook = Event::bus()->m_events.input.mouse.move.listen([onCursorMove](Vector2D, Event::SCallbackInfo& info) { onCursorMove(info); });
touchMoveHook = Event::bus()->m_events.input.touch.motion.listen([onCursorMove](ITouch::SMotionEvent, Event::SCallbackInfo& info) { onCursorMove(info); });
- mouseButtonHook = Event::bus()->m_events.input.mouse.button.listen([onCursorSelect](IPointer::SButtonEvent, Event::SCallbackInfo& info) { onCursorSelect(info); });
- touchDownHook = Event::bus()->m_events.input.touch.down.listen([onCursorSelect](ITouch::SDownEvent, Event::SCallbackInfo& info) { onCursorSelect(info); });
+ mouseButtonHook = Event::bus()->m_events.input.mouse.button.listen([onCursorSelect](IPointer::SButtonEvent event, Event::SCallbackInfo& info) { onCursorSelect(event, info); });
+ touchDownHook = Event::bus()->m_events.input.touch.down.listen([onTouchSelect](ITouch::SDownEvent, Event::SCallbackInfo& info) { onTouchSelect(info); });
+}
+
+Vector2D COverview::tilePointToWorkspacePoint(int id, const Vector2D& localPoint) const {
+ const Vector2D tileSize = pMonitor->m_size / SIDE_LENGTH;
+ const Vector2D tilePos = tileSize * Vector2D{id % SIDE_LENGTH, id / SIDE_LENGTH};
+ const Vector2D inTile = localPoint - tilePos;
+
+ return pMonitor->m_position + Vector2D{std::clamp(inTile.x / tileSize.x, 0.0, 1.0) * pMonitor->m_size.x, std::clamp(inTile.y / tileSize.y, 0.0, 1.0) * pMonitor->m_size.y};
+}
+
+PHLWINDOW COverview::windowAtTilePoint(int id, const Vector2D& localPoint) const {
+ if (!isTileValid(id))
+ return nullptr;
+
+ const auto WORKSPACE = images[id].pWorkspace ? images[id].pWorkspace : g_pCompositor->getWorkspaceByID(images[id].workspaceID);
+ if (!WORKSPACE)
+ return nullptr;
+
+ const auto POINT = tilePointToWorkspacePoint(id, localPoint);
+ for (auto it = g_pCompositor->m_windows.rbegin(); it != g_pCompositor->m_windows.rend(); ++it) {
+ const auto& window = *it;
+ if (!windowVisibleOnWorkspace(window, WORKSPACE))
+ continue;
+
+ if (window->getWindowMainSurfaceBox().containsPoint(POINT))
+ return window;
+ }
+
+ return nullptr;
+}
+
+void COverview::beginWindowDrag() {
+ updateHoveredFromMouse();
+ dragStartLocal = lastMousePosLocal;
+ dragSourceID = hoveredID;
+ dragMoved = false;
+ dragWindow = windowAtTilePoint(dragSourceID, dragStartLocal);
+}
+
+void COverview::updateWindowDrag() {
+ if (!dragWindow || dragMoved)
+ return;
+
+ const auto DX = lastMousePosLocal.x - dragStartLocal.x;
+ const auto DY = lastMousePosLocal.y - dragStartLocal.y;
+ if (std::hypot(DX, DY) < 12.0)
+ return;
+
+ dragMoved = true;
+ damage();
+}
+
+PHLWORKSPACE COverview::ensureWorkspaceForTile(int id) {
+ if (!isTileValid(id))
+ return nullptr;
+
+ auto& image = images[id];
+ if (image.pWorkspace)
+ return image.pWorkspace;
+
+ auto workspace = g_pCompositor->getWorkspaceByID(image.workspaceID);
+ if (!workspace)
+ workspace = g_pCompositor->createNewWorkspace(image.workspaceID, pMonitor->m_id, std::to_string(image.workspaceID), false);
+
+ image.pWorkspace = workspace;
+ return workspace;
+}
+
+bool COverview::finishWindowDrag() {
+ const auto WINDOW = dragWindow;
+ const int SOURCE = dragSourceID;
+ const bool MOVED = dragMoved;
+
+ dragWindow = nullptr;
+ dragSourceID = -1;
+ dragMoved = false;
+
+ if (!WINDOW)
+ return false;
+
+ if (!MOVED)
+ return false;
+
+ updateHoveredFromMouse();
+
+ const int TARGET = hoveredID;
+ if (!isTileValid(SOURCE) || !isTileValid(TARGET) || SOURCE == TARGET)
+ return true;
+
+ const auto SOURCEWS = images[SOURCE].pWorkspace;
+ const auto TARGETWS = ensureWorkspaceForTile(TARGET);
+ if (!windowVisibleOnWorkspace(WINDOW, SOURCEWS) || !TARGETWS || TARGETWS == SOURCEWS)
+ return true;
+
+ g_pCompositor->moveWindowToWorkspaceSafe(WINDOW, TARGETWS);
+ redrawID(SOURCE);
+ redrawID(TARGET);
+ damage();
+ return true;
}
void COverview::selectHoveredWorkspace() {
@@ -954,6 +1078,8 @@
drawBorder(openedID, *PBORDERCURRENT);
if (kbFocusID != -1)
drawBorder(kbFocusID, *PBORDERFOCUS);
+ if (dragMoved && dragSourceID != -1)
+ drawBorder(dragSourceID, *PBORDERFOCUS);
}
static float lerp(const float& from, const float& to, const float perc) {

View File

@@ -1,87 +0,0 @@
diff --git a/src/main.cpp b/src/main.cpp
index 9dd0286..51fd8d7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,6 +6,7 @@
#include <hyprland/src/debug/log/Logger.hpp>
#include <hyprland/src/managers/SeatManager.hpp>
#include <hyprland/src/desktop/view/Window.hpp>
+#include <lua.hpp>
#include <hyprutils/memory/SharedPtr.hpp>
#include <any>
#include "Overview.hpp"
@@ -380,6 +381,65 @@ static SDispatchResult dispatchCloseOverview(std::string arg) {
return SDispatchResult{};
}
+static int luaOverview(lua_State* L) {
+ std::string action = "toggle";
+ std::string arg;
+
+ if (lua_gettop(L) >= 1 && !lua_isnil(L, 1)) {
+ if (lua_istable(L, 1)) {
+ lua_getfield(L, 1, "action");
+ if (lua_isstring(L, -1))
+ action = lua_tostring(L, -1);
+ else if (!lua_isnil(L, -1))
+ return luaL_error(L, "hyprspace.overview: field \"action\" must be a string");
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "all");
+ if (lua_isboolean(L, -1) && lua_toboolean(L, -1))
+ arg = "all";
+ else if (!lua_isnil(L, -1) && !lua_isboolean(L, -1))
+ return luaL_error(L, "hyprspace.overview: field \"all\" must be a boolean");
+ lua_pop(L, 1);
+ } else if (lua_isstring(L, 1)) {
+ action = lua_tostring(L, 1);
+ } else {
+ return luaL_error(L, "hyprspace.overview: argument must be a string or table");
+ }
+ }
+
+ if (action == "toggle") {
+ dispatchToggleOverview(arg);
+ return 0;
+ }
+
+ if (action == "open") {
+ dispatchOpenOverview(arg);
+ return 0;
+ }
+
+ if (action == "close") {
+ dispatchCloseOverview(arg);
+ return 0;
+ }
+
+ if (action == "toggle all") {
+ dispatchToggleOverview("all");
+ return 0;
+ }
+
+ if (action == "open all") {
+ dispatchOpenOverview("all");
+ return 0;
+ }
+
+ if (action == "close all") {
+ dispatchCloseOverview("all");
+ return 0;
+ }
+
+ return luaL_error(L, "hyprspace.overview: unknown action \"%s\"", action.c_str());
+}
+
void* findFunctionBySymbol(HANDLE inHandle, const std::string func, const std::string sym) {
// should return all functions
auto funcSearch = HyprlandAPI::findFunctionsByName(inHandle, func);
@@ -545,6 +605,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE inHandle) {
HyprlandAPI::addDispatcherV2(pHandle, "overview:open", ::dispatchOpenOverview);
HyprlandAPI::addDispatcherV2(pHandle, "overview:close", ::dispatchCloseOverview);
+ HyprlandAPI::addLuaFunction(pHandle, "hyprspace", "overview", ::luaOverview);
+
g_pRenderHook = Event::bus()->m_events.render.stage.listen([](eRenderStage stage) { onRender(stage); });
// refresh on layer change