#hyprland #workspace #window #switch #keyboard-shortcuts #gui #switching

bin+lib hyprswitch

一个 CLI/GUI,允许在 Hyprland 之间切换窗口

16 个稳定版本

2.1.1 2024 年 8 月 11 日
2.1.0 2024 年 8 月 10 日
2.0.4 2024 年 7 月 7 日
1.3.1 2024 年 6 月 4 日
1.1.1 2024 年 2 月 25 日

#150 in 命令行工具

Download history 205/week @ 2024-05-04 210/week @ 2024-05-11 72/week @ 2024-05-18 35/week @ 2024-05-25 183/week @ 2024-06-01 50/week @ 2024-06-08 27/week @ 2024-06-15 10/week @ 2024-06-22 265/week @ 2024-06-29 311/week @ 2024-07-06 54/week @ 2024-07-13 22/week @ 2024-07-20 145/week @ 2024-07-27 27/week @ 2024-08-03 469/week @ 2024-08-10 101/week @ 2024-08-17

每月下载 746

MITGPL-3.0-or-later

3MB
5K SLoC

C 3K SLoC // 0.0% comments Rust 1.5K SLoC // 0.1% comments Python 324 SLoC // 0.1% comments Lua 29 SLoC // 0.1% comments Vala 22 SLoC

hyprswitch

crates.io Docs Tests

Hyprland 中切换窗口的 Rust CLI/GUI

它可以通过键盘快捷键或 GUI 在窗口间循环。

窗口按其在屏幕上的位置排序,并且可以按类或工作空间进行筛选。

要使用 GUI,您需要在 Hyprland 启动时启动一次守护进程,在您的配置中使用 exec-once = hyprswitch init &。随后的 hyprswitch 调用(使用 gui 命令)将命令发送到守护进程,该守护进程将执行命令并更新 GUI。

image.png

安装

从源代码安装

Arch

  • paru -S hyprswitch / yay -S hyprswitch

Nixos

  • hyprswitch.url = "github:h3rmt/hyprswitch/release"; 添加到 flake 输入
  • specialArgs = { inherit inputs; }; 添加到 nixpkgs.lib.nixosSystem
  • inputs.hyprswitch.packages.x86_64-linux.default 添加到您的 environment.systemPackages
  • 可用系统: aarch64-linux, i686-linux, riscv32-linux, riscv64-linux, x86_64-linux

使用方法

安装二进制文件后,您可以修改您的 ~/.config/hypr/hyprland.conf

参数

  • --dry-run/-d 打印将要执行的命令

  • -v 增加详细程度级别(最大:-vv)

  • init 初始化并启动守护进程

    • --switch-ws-on-hover 在GUI中悬停时切换到工作区
    • --stay-open-on-close 点击客户端时不要关闭GUI(只有通过hyprswitch close关闭)
    • --custom-css 指定自定义CSS文件路径
    • --show-title 在GUI中显示窗口标题(如果标题为空则回退到类)
  • simple 不使用GUI/守护进程进行切换(直接切换)

    • --reverse/-r 反转窗口顺序/反向切换
    • --offset/-o 切换到特定的窗口偏移(默认1)
    • --include-special-workspaces 包含特殊工作区(例如,便签板)
    • --ignore-workspaces 将所有窗口在每个监视器上排序,就像一个连续的工作区一样
    • --ignore-monitors 将匹配的工作区上的所有窗口排序,就像一个大监视器一样
    • --filter-same-class/-s 只切换与当前焦点窗口具有相同类/类型的窗口
    • --filter-current-workspace/-w 只切换与当前焦点窗口位于同一工作区的窗口
    • --filter-current-monitor/-m 只切换与当前焦点窗口位于同一监视器的窗口
    • --sort-recent 按最近焦点排序窗口
  • gui 启动/打开GUI + 如果GUI已经打开,则向GUI的守护进程发送命令

    • --do-initial-execute 如果GUI没有打开,则立即执行第一个切换,否则只打开GUI
    • simple相同的选项
  • close 关闭GUI,执行切换窗口的命令

    • kill 不切换到选定的窗口,仅关闭GUI

示例

(修改$...变量以使用您喜欢的键)

简单(无GUI)

下一个上一个

# 2 Keybindings to switch to 'next' or 'previous' window
$key = TAB
$modifier = CTRL
$reverse = SHIFT

bind = $modifier, $key, exec, hyprswitch simple
bind = $modifier $reverse, $key, exec, hyprswitch simple -r

最后一个焦点

# 1 Keybinding to switch to previously focused application
$key = TAB
$modifier = CTRL

bind = $modifier, $key, exec, hyprswitch simple --sort-recent

相同类/类型

# 2 Keybindings to switch to next' or 'previous' window of same class/type
$key = TAB
$modifier = CTRL
$reverse = SHIFT

bind = $modifier, $key, exec, hyprswitch simple -s
bind = $modifier $reverse, $key, exec, hyprswitch simple -s -r

GUI

exec-once = hyprswitch init &添加到您的~/.config/hypr/hyprland.conf以在启动时启动守护进程

按$modifier + $key打开GUI,使用鼠标点击窗口

exec-once = hyprswitch init --show-title &

......

$key = TAB
$modifier = SUPER
$switch_release = SUPER_L

# open hyprswitch
bind = $modifier, $key, exec, hyprswitch gui

# close hyprswitch
bindr = $modifier, $switch_release, exec, hyprswitch close
# if it somehow doesn't close on releasing $switch_release, escape can kill (doesnt switch)
bindrn = ,escape, exec, hyprswitch close --kill

GUI + 键盘配置

复杂的配置与子映射,允许在打开hyprswitch时具有许多不同的键绑定(如果卡在切换子映射中,请运行hyprctl dispatch submap reset

  • 按住$modifier + $key打开GUI并切换窗口
  • 释放$key并按3切换到下一个第三个窗口
  • 释放$key并按住$reverse + $key以反向遍历
  • 释放$modifier($modifier_release)以执行切换并关闭GUI
exec-once = hyprswitch init --show-title &

......

$key = TAB
$modifier = ALT
$modifier_release = ALT_L
$reverse = SHIFT

# allows repeated switching with same keypress that starts the submap
binde = $modifier, $key, exec, hyprswitch gui --do-initial-execute
bind = $modifier, $key, submap, switch

# allows repeated switching with same keypress that starts the submap
binde = $modifier $reverse, $key, exec, hyprswitch gui --do-initial-execute -r
bind = $modifier $reverse, $key, submap, switch

submap = switch
# allow repeated window switching in submap (same keys as repeating while starting)
binde = $modifier, $key, exec, hyprswitch gui
binde = $modifier $reverse, $key, exec, hyprswitch gui -r

# switch to specific window offset (TODO replace with a more dynamic solution)
bind = $modifier, 1, exec, hyprswitch gui --offset=1
bind = $modifier, 2, exec, hyprswitch gui --offset=2
bind = $modifier, 3, exec, hyprswitch gui --offset=3
bind = $modifier, 4, exec, hyprswitch gui --offset=4
bind = $modifier, 5, exec, hyprswitch gui --offset=5

bind = $modifier $reverse, 1, exec, hyprswitch gui --offset=1 -r
bind = $modifier $reverse, 2, exec, hyprswitch gui --offset=2 -r
bind = $modifier $reverse, 3, exec, hyprswitch gui --offset=3 -r
bind = $modifier $reverse, 4, exec, hyprswitch gui --offset=4 -r
bind = $modifier $reverse, 5, exec, hyprswitch gui --offset=5 -r


# exit submap and stop hyprswitch
bindrt = $modifier, $modifier_release, exec, hyprswitch close
bindrt = $modifier, $modifier_release, submap, reset

# if it somehow doesn't close on releasing $switch_release, escape can kill (doesnt switch)
bindr = ,escape, exec, hyprswitch close --kill
bindr = ,escape, submap, reset
submap = reset

CSS

使用的类

  • client-image

    .client-image {
      margin: 15px;
    }
    
  • client-index

    .client-index {
      margin: 6px;
      padding: 5px;
      font-size: 30px;
      font-weight: bold;
      border-radius: 15px;
      border: 3px solid rgba(80, 90, 120, 0.80);
      background-color: rgba(20, 20, 20, 1);
    }
    
  • client + client_active

    client_active是当前聚焦的客户端/在退出hyprswitch时将被聚焦的客户端

    .client {
      border-radius: 15px;
      border: 3px solid rgba(80, 90, 120, 0.80);
      background-color: rgba(25, 25, 25, 0.90);
    }
    .client:hover {
      background-color: rgba(40, 40, 50, 1);
    }
    .client_active {
      border: 3px solid rgba(239, 9, 9, 0.94);
    }
    
  • workspace_frame + workspace_frame_special

    当workspaceId小于0时(例如,便签板),添加workspace_frame_special

    .workspace {
      font-size: 25px;
      font-weight: bold;
      border-radius: 15px;
      border: 3px solid rgba(70, 80, 90, 0.80);
      background-color: rgba(20, 20, 25, 0.90);
    }
    .workspace_special {
      border: 3px solid rgba(0, 255, 0, 0.4);
    }
    
  • 工作区

    .workspaces {
      margin: 10px;
    }
    
  • 窗口

    window {
      border-radius: 15px;
      opacity: 0.85;
      border: 6px solid rgba(15, 170, 190, 0.85);
    }
    

完整的配置

.client-image {
    margin: 15px;
}

.client-index {
    margin: 6px;
    padding: 5px;
    font-size: 30px;
    font-weight: bold;
    border-radius: 15px;
    border: 3px solid rgba(80, 90, 120, 0.80);
    background-color: rgba(20, 20, 20, 1);
}

.client {
    border-radius: 15px;
    border: 3px solid rgba(80, 90, 120, 0.80);
    background-color: rgba(25, 25, 25, 0.90);
}

.client:hover {
    background-color: rgba(40, 40, 50, 1);
}

.client_active {
    border: 3px solid rgba(239, 9, 9, 0.94);
}

.workspace {
    font-size: 25px;
    font-weight: bold;
    border-radius: 15px;
    border: 3px solid rgba(70, 80, 90, 0.80);
    background-color: rgba(20, 20, 25, 0.90);
}

.workspace_special {
    border: 3px solid rgba(0, 255, 0, 0.4);
}

.workspaces {
    margin: 10px;
}

window {
    border-radius: 15px;
    opacity: 0.85;
    border: 6px solid rgba(17, 171, 192, 0.85);
}

示例

.client_active {
    border: 3px solid rgba(239, 9, 9, 0.94);
    background-color: rgba(200, 9, 9, 0.80);
}

.client-image {
    margin: 10px;
}

window {
    opacity: 1;
    border: 6px solid rgba(0, 0, 0, 0.85);
}

其他

窗口排序

查看tests以了解窗口排序的更多细节

   1      2  3      4
1  +------+  +------+
2  |  1   |  |  2   |
3  |      |  +------+
4  +------+  +------+
5  +------+  |  4   |
6  |  3   |  |      |
7  +------+  +------+
   1      2  3      4
                  Monitor 1
      Workspace 1           Workspace 2
1  +------+  +------+ | +------+  +------+
2  |  1   |  |  2   |   |  5   |  |  6   |
3  |      |  |      | | |      |  +------+
4  +------+  +------+   +------+  +------+
5  +------+  +------+ | +------+  |  8   |
6  |  3   |  |  4   |   |  7   |  |      |
7  +------+  +------+ | +------+  +------+
   1      2  3      4   1      2  3      4
      1       3    5   6     8   10  11  12
   +----------------------------------------+
1  |  +-------+                      +---+  |
2  |  |   1   |              +---+   | 5 |  |
3  |  |       |    +---+     | 3 |   |   |  |
4  |  +-------+    | 2 |     +---+   |   |  |
5  |               +---+     +---+   |   |  |
6  |                         | 4 |   |   |  |
7  |    +-------+            +---+   +---+  |
8  |    |   6   |         +----+            |
9  |    |       |         | 7  |            |
10 |    +-------+         +----+            |
   +----------------------------------------+
        2       4         7    9

--ignore-workspaces

  • 不带--ignore-workspaces的顺序
                   Monitor 1                                   Monitor 2
       Workspace 0           Workspace 1           Workspace 10          Workspace 11
 1  +------+  +------+ | +------+  +------+  |  +------+  +------+ | +------+  +------+
 2  |  1   |  |  2   | | |  5   |  |  6   |  |  |  9   |  |  10  | | |  13  |  |  14  |
 3  |      |  |      | | |      |  +------+  |  |      |  |      | | |      |  +------+
 4  +------+  +------+ | +------+  +------+  |  +------+  +------+ | +------+  +------+
 5  +------+  +------+ | +------+  |  8   |  |  +---------+  +---+ | +------+  |  16  |
 6  |  3   |  |  4   | | |  7   |  |      |  |  |   11    |  |12 | | |  15  |  |      |
 7  +------+  +------+ | +------+  +------+  |  +---------+  +---+ | +------+  +------+
    1      2  3      4   1      2  3      4     5      6  7  8   9   5      6  7   8  9
  • --ignore-workspaces的顺序
                   Monitor 1                                   Monitor 2
       Workspace 0           Workspace 1           Workspace 10         Workspace 11
 1  +------+  +------+ | +------+  +------+  |  +------+  +------+ | +------+  +------+
 2  |  1   |  |  2   | | |  3   |  |  4   |  |  |  9   |  |  10  | | |  11  |  |  12  |
 3  |      |  |      | | |      |  +------+  |  |      |  |      | | |      |  +------+
 4  +------+  +------+ | +------+  +------+  |  +------+  +------+ | +------+  +------+
 5  +------+  +------+ | +------+  |  8   |  |  +---------+  +---+ | +------+  |  16  |
 6  |  5   |  |  6   | | |  7   |  |      |  |  |   13    |  |14 | | |  15  |  |      |
 7  +------+  +------+ | +------+  +------+  |  +---------+  +---+ | +------+  +------+
    1      2  3      4   1      2  3      4     5      6  7  8   9   5      6  7   8  9

--ignore-monitors

  • 不带--ignore-monitors的顺序
                   Monitor 1                                   Monitor 2
       Workspace 0           Workspace 1           Workspace 10          Workspace 11
 1  +------+  +------+ | +------+  +------+  |  +------+  +------+ | +------+  +------+
 2  |  1   |  |  2   | | |  5   |  |  6   |  |  |  9   |  |  10  | | |  13  |  |  14  |
 3  |      |  |      | | |      |  +------+  |  |      |  |      | | |      |  +------+
 4  +------+  +------+ | +------+  +------+  |  +------+  +------+ | +------+  +------+
 5  +------+  +------+ | +------+  |  8   |  |  +---------+  +---+ | +------+  |  16  |
 6  |  3   |  |  4   | | |  7   |  |      |  |  |   11    |  |12 | | |  15  |  |      |
 7  +------+  +------+ | +------+  +------+  |  +---------+  +---+ | +------+  +------+
    1      2  3      4   1      2  3      4     5      6  7  8   9   5      6  7   8  9
  • --ignore-monitors的顺序
                   Monitor 1                                   Monitor 2
       Workspace 0           Workspace 1           Workspace 10          Workspace 11
 1  +------+  +------+ | +------+  +------+  |  +------+  +------+ | +------+  +------+
 2  |  1   |  |  2   | | |  9   |  |  10  |  |  |  3   |  |  4   | | |  11  |  |  12  |
 3  |      |  |      | | |      |  +------+  |  |      |  |      | | |      |  +------+
 4  +------+  +------+ | +------+  +------+  |  +------+  +------+ | +------+  +------+
 5  +------+  +------+ | +------+  |  14  |  |  +---------+  +---+ | +------+  |  16  |
 6  |  5   |  |  6   | | |  13  |  |      |  |  |   7     |  | 8 | | |  15  |  |      |
 7  +------+  +------+ | +------+  +------+  |  +---------+  +---+ | +------+  +------+
    1      2  3      4   1      2  3      4     5      6  7  8   9   5      6  7  8   9

实验性环境变量

  • SIZE_FACTOR i16 [默认: 7]: 窗口和工作区大小被除以的因子,用于缩小它们
  • ICON_SIZE i32 [默认: 128]: 传递给theme.lookup_icon函数的参数(确定图标的分辨率,因为它会被缩放到窗口大小,而不管图标的分辨率如何)
  • ICON_SCALE i32 [默认: 1]: 传递给theme.lookup_icon函数的参数(不清楚这做什么,将值设置为除1以外的任何值都没有变化)
  • NEXT_INDEX_MAX i32 [默认: 5]: 显示下一个索引的最大窗口数(如果为-1,将禁用下一个索引指示器)
  • WORKSPACE_GAP usize [默认: 15]: GUI中工作区之间的间隙(由于工作区位置是从实际工作区位置计算的,因此无法通过CSS配置)

依赖项

~23–54MB
~1M SLoC