Add Hyprspace to Hyprland

This commit is contained in:
2026-05-12 20:41:25 -07:00
parent 7946892f7f
commit 191a83bb7b
8 changed files with 158 additions and 2 deletions

View File

@@ -24,8 +24,8 @@ function M.setup(ctx)
default_action = "bring", default_action = "bring",
}), overview_bind_opts) }), overview_bind_opts)
bind(main_mod .. " + SHIFT + slash", hyprwinview({ action = "toggle-filter" }), overview_bind_opts) bind(main_mod .. " + SHIFT + slash", hyprwinview({ action = "toggle-filter" }), overview_bind_opts)
bind("ALT + Tab", hyprexpo("open"), overview_bind_opts) bind("ALT + Tab", hyprspace("toggle"), overview_bind_opts)
bind("ALT + SHIFT + Tab", hyprexpo("bring"), overview_bind_opts) bind("ALT + SHIFT + Tab", hyprexpo("open"), overview_bind_opts)
bind(main_mod .. " + G", hyprwinview({ bind(main_mod .. " + G", hyprwinview({
action = "show", action = "show",
start_in_filter_mode = true, start_in_filter_mode = true,

View File

@@ -70,6 +70,24 @@ function M.setup(ctx)
end end
end end
local function hyprspace(action)
action = action or "toggle"
return function()
overview_trace("hyprspace " .. tostring(action))
if hl.plugin and hl.plugin.hyprspace and hl.plugin.hyprspace.overview then
hl.plugin.hyprspace.overview(action)
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 hyprwinview(action) local function hyprwinview(action)
return function() return function()
local label = "hyprwinview" local label = "hyprwinview"
@@ -496,6 +514,7 @@ 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.hyprspace = hyprspace
ctx.hyprwinview = hyprwinview ctx.hyprwinview = hyprwinview
ctx.workspacehistory = workspacehistory ctx.workspacehistory = workspacehistory
ctx.apply_nstack_config = apply_nstack_config ctx.apply_nstack_config = apply_nstack_config

View File

@@ -8,6 +8,9 @@ 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("/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

@@ -46,6 +46,7 @@ return {
current_layout = columns_layout, current_layout = columns_layout,
enable_nstack = true, enable_nstack = true,
enable_hyprexpo = true, enable_hyprexpo = true,
enable_hyprspace = true,
enable_hyprwinview = true, enable_hyprwinview = true,
enable_workspace_history = true, enable_workspace_history = true,
configure_nstack_plugin_from_lua = false, configure_nstack_plugin_from_lua = false,

24
nixos/flake.lock generated
View File

@@ -1,5 +1,28 @@
{ {
"nodes": { "nodes": {
"Hyprspace": {
"inputs": {
"hyprland": [
"hyprland"
],
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1775071961,
"narHash": "sha256-LXkeeH9Blr6ohS1LAsVZbkJ/EAkkMDATh5qu45hC7Zo=",
"owner": "KZDKM",
"repo": "Hyprspace",
"rev": "12ddde04f8584bf7de3151e6169918e0dda9f822",
"type": "github"
},
"original": {
"owner": "KZDKM",
"repo": "Hyprspace",
"type": "github"
}
},
"agenix": { "agenix": {
"inputs": { "inputs": {
"darwin": "darwin", "darwin": "darwin",
@@ -1705,6 +1728,7 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"Hyprspace": "Hyprspace",
"agenix": "agenix", "agenix": "agenix",
"claude-code-nix": "claude-code-nix", "claude-code-nix": "claude-code-nix",
"codex-cli-nix": "codex-cli-nix", "codex-cli-nix": "codex-cli-nix",

View File

@@ -109,6 +109,12 @@
inputs.hyprland.follows = "hyprland"; inputs.hyprland.follows = "hyprland";
}; };
Hyprspace = {
url = "github:KZDKM/Hyprspace";
inputs.hyprland.follows = "hyprland";
inputs.systems.follows = "systems";
};
hyprwinview = { hyprwinview = {
url = "github:colonelpanic8/hyprwinview"; url = "github:colonelpanic8/hyprwinview";
inputs.hyprland.follows = "hyprland"; inputs.hyprland.follows = "hyprland";

View File

@@ -89,9 +89,25 @@
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}-pr230";
__intentionallyOverridingVersion = true;
patches =
(old.patches or [])
++ [
# Hyprspace main has not caught up with Hyprland 0.55 yet.
# https://github.com/KZDKM/Hyprspace/pull/230
(pkgs.fetchpatch {
url = "https://github.com/KZDKM/Hyprspace/pull/230.patch";
hash = "sha256-jwSuIyhUi8KMIpgBxqyDZvcRHxHjiji8GMipDX4Dot8=";
})
./packages/hyprspace-lua-api.patch
];
});
hyprlandPluginPackages = [ hyprlandPluginPackages = [
inputs.hyprNStack.packages.${system}.hyprNStack inputs.hyprNStack.packages.${system}.hyprNStack
inputs.hyprland-plugins-lua.packages.${system}.hyprexpo inputs.hyprland-plugins-lua.packages.${system}.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
]; ];

View File

@@ -0,0 +1,87 @@
diff --git a/src/main.cpp b/src/main.cpp
index 9b75f8a..b69b459 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -5,6 +5,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 "Overview.hpp"
#include "Globals.hpp"
@@ -377,6 +378,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);
@@ -516,6 +566,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