mirror of
https://github.com/Trensa-Organization/hy3.git
synced 2025-03-15 10:43:40 +01:00
Merge https://github.com/outfoxxed/hy3 into outfoxxed-master
This commit is contained in:
commit
29968771e0
15 changed files with 978 additions and 770 deletions
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,5 +1,21 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
# hl0.41.1 and before
|
||||||
|
|
||||||
|
- Fixed glitchy tab bar effects when switching workspaces with fade effect.
|
||||||
|
- Fixed wrongly sized layout when moving resized nodes between workspaces.
|
||||||
|
|
||||||
|
# hl0.41.0 and before
|
||||||
|
|
||||||
|
- Fixed IPC and wlr-foreign-toplevel not getting fullscreen and maximize events.
|
||||||
|
- Fixed glitches when moving nodes between monitors with hy3 dispatchers.
|
||||||
|
- Fixed glitchy tab bar effects when switching workspaces
|
||||||
|
|
||||||
|
## hl0.40.0 and before
|
||||||
|
|
||||||
|
- Added `hy3:warpcursor` dispatcher to warp cursor to current node.
|
||||||
|
- Added cursor warping options for `hy3:movefocus`.
|
||||||
|
|
||||||
## hl0.37.1 and before
|
## hl0.37.1 and before
|
||||||
|
|
||||||
- Added `no_gaps_when_only = 2`
|
- Added `no_gaps_when_only = 2`
|
||||||
|
|
|
@ -11,7 +11,7 @@ if(CMAKE_EXPORT_COMPILE_COMMANDS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(DEPS REQUIRED hyprland pixman-1 libdrm pango pangocairo)
|
pkg_check_modules(DEPS REQUIRED hyprland pixman-1 libdrm pango pangocairo libinput wayland-client xkbcommon)
|
||||||
|
|
||||||
add_library(hy3 SHARED
|
add_library(hy3 SHARED
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
|
49
README.md
49
README.md
|
@ -79,7 +79,8 @@ Assuming you use hyprland's home manager module, you can easily integrate hy3 by
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
hyprland.url = "github:hyprwm/Hyprland?ref=v{version}"; # where {version} is the hyprland release version
|
hyprland.url = "git+https://github.com/hyprwm/Hyprland?submodules=1&ref={version}";
|
||||||
|
# where {version} is the hyprland release version
|
||||||
# or "github:hyprwm/Hyprland" to follow the development branch
|
# or "github:hyprwm/Hyprland" to follow the development branch
|
||||||
|
|
||||||
hy3 = {
|
hy3 = {
|
||||||
|
@ -123,6 +124,47 @@ wayland.windowManager.hyprland = {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### hyprpm
|
||||||
|
Hyprland now has a dedicated plugin manager, which should be used when your package manager
|
||||||
|
isn't capable of locking hy3 builds to the correct hyprland version.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Make sure hyprpm is activated by putting
|
||||||
|
>
|
||||||
|
> ```conf
|
||||||
|
> exec-once = hyprpm reload -n
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> in your hyprland.conf. (See [the wiki](https://wiki.hyprland.org/Plugins/Using-Plugins/) for details.)
|
||||||
|
|
||||||
|
To install hy3 via hyprpm run
|
||||||
|
|
||||||
|
```sh
|
||||||
|
hyprpm add https://github.com/outfoxxed/hy3
|
||||||
|
```
|
||||||
|
|
||||||
|
To update hy3 (and all other plugins), run
|
||||||
|
|
||||||
|
```sh
|
||||||
|
hyprpm update
|
||||||
|
```
|
||||||
|
|
||||||
|
Sometimes the headers from hyprland are not updated, if this happens run (See [issue #109](https://github.com/outfoxxed/hy3/issues/109) for an example of where this happened)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
hyprpm update -f
|
||||||
|
```
|
||||||
|
|
||||||
|
(See [the wiki](https://wiki.hyprland.org/Plugins/Using-Plugins/) for details.)
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> When you are running a tagged hyprland version hyprpm (0.34.0+) will build against hy3's
|
||||||
|
> corrosponding release. However if you are running an untagged build (aka `-git`) hyprpm
|
||||||
|
> will build against hy3's *latest* commit. This means **if you are running an out of date
|
||||||
|
> untagged build of hyprland, hyprpm may pick an incompatible revision of hy3**.
|
||||||
|
>
|
||||||
|
> To fix this problem you will either need to update hyprland or manually build the correct
|
||||||
|
> version of hy3.
|
||||||
|
|
||||||
### Manual
|
### Manual
|
||||||
Install hyprland, including its headers and pkg-config file, then run the following commands:
|
Install hyprland, including its headers and pkg-config file, then run the following commands:
|
||||||
|
@ -284,8 +326,11 @@ plugin {
|
||||||
- `toggletab` will untab if group is tabbed, and tab if group is untabbed
|
- `toggletab` will untab if group is tabbed, and tab if group is untabbed
|
||||||
- `opposite` will toggle between horizontal and vertical layouts if the group is not tabbed.
|
- `opposite` will toggle between horizontal and vertical layouts if the group is not tabbed.
|
||||||
- `hy3:setephemeral, <true | false>` - change the ephemerality of the group the node belongs to
|
- `hy3:setephemeral, <true | false>` - change the ephemerality of the group the node belongs to
|
||||||
- `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible]` - move the focus left, up, down, or right
|
- `hy3:movefocus, <l | u | d | r | left | down | up | right>, [visible], [warp | nowarp]` - move the focus left, up, down, or right
|
||||||
- `visible` - only move between visible nodes, not hidden tabs
|
- `visible` - only move between visible nodes, not hidden tabs
|
||||||
|
- `warp` - warp the mouse to the selected window, even if `general:no_cursor_warps` is true.
|
||||||
|
- `nowarp` - does not warp the mouse to the selected window, even if `general:no_cursor_warps` is false.
|
||||||
|
- `hy3:warpcursor` - warp the cursor to the center of the focused node
|
||||||
- `hy3:movewindow, <l | u | d | r | left | down | up | right>, [once], [visible]` - move a window left, up, down, or right
|
- `hy3:movewindow, <l | u | d | r | left | down | up | right>, [once], [visible]` - move a window left, up, down, or right
|
||||||
- `once` - only move directly to the neighboring group, without moving into any of its subgroups
|
- `once` - only move directly to the neighboring group, without moving into any of its subgroups
|
||||||
- `visible` - only move between visible nodes, not hidden tabs
|
- `visible` - only move between visible nodes, not hidden tabs
|
||||||
|
|
189
flake.lock
generated
189
flake.lock
generated
|
@ -1,8 +1,15 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"hyprcursor": {
|
"aquamarine": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"hyprlang": "hyprlang",
|
"hyprutils": [
|
||||||
|
"hyprland",
|
||||||
|
"hyprutils"
|
||||||
|
],
|
||||||
|
"hyprwayland-scanner": [
|
||||||
|
"hyprland",
|
||||||
|
"hyprwayland-scanner"
|
||||||
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"hyprland",
|
"hyprland",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
|
@ -13,11 +20,40 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710257359,
|
"lastModified": 1721487522,
|
||||||
"narHash": "sha256-43re5pzE/cswFAgw92/ugsB3+d5ufDaCcLtl9ztKfBo=",
|
"narHash": "sha256-aF3uwUwUK2CgbItoMe3IJF0yidIEWcDx47AiH5y8VKk=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "aquamarine",
|
||||||
|
"rev": "acfea3bd1d9e756c7152e639240d52c6628844b0",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "aquamarine",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hyprcursor": {
|
||||||
|
"inputs": {
|
||||||
|
"hyprlang": [
|
||||||
|
"hyprland",
|
||||||
|
"hyprlang"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"hyprland",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"hyprland",
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1720108799,
|
||||||
|
"narHash": "sha256-AxRkTJlbB8r7aG6gvc7IaLhc2T9TO4/8uqanKRxukBQ=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprcursor",
|
"repo": "hyprcursor",
|
||||||
"rev": "1761f6cefd77f4fcd2039d930c88d6716ddc4974",
|
"rev": "a5c0d57325c5f0814c39110a70ca19c070ae9486",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -28,46 +64,51 @@
|
||||||
},
|
},
|
||||||
"hyprland": {
|
"hyprland": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"aquamarine": "aquamarine",
|
||||||
"hyprcursor": "hyprcursor",
|
"hyprcursor": "hyprcursor",
|
||||||
"hyprland-protocols": "hyprland-protocols",
|
"hyprlang": "hyprlang",
|
||||||
"hyprlang": "hyprlang_2",
|
"hyprutils": "hyprutils",
|
||||||
|
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"systems": "systems_2",
|
"systems": "systems",
|
||||||
"wlroots": "wlroots",
|
|
||||||
"xdph": "xdph"
|
"xdph": "xdph"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710600709,
|
"lastModified": 1721579057,
|
||||||
"narHash": "sha256-W+34KhCnqscRXN/IkvuJMiVx0Fa64RcYn8H4sZjzceI=",
|
"narHash": "sha256-x/RIzkL8PwLDNiRV/R308RdCmS8h3G9Xf62XVH/WAp0=",
|
||||||
"owner": "hyprwm",
|
"ref": "refs/heads/main",
|
||||||
"repo": "Hyprland",
|
"rev": "928d1dd38a6e4a791d4a4374a4a3bf02311adbb2",
|
||||||
"rev": "c5e28ebcfe00a510922779b2c568cfa52a317445",
|
"revCount": 4942,
|
||||||
"type": "github"
|
"submodules": true,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/hyprwm/Hyprland"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "hyprwm",
|
"rev": "928d1dd38a6e4a791d4a4374a4a3bf02311adbb2",
|
||||||
"ref": "v0.37.1",
|
"submodules": true,
|
||||||
"repo": "Hyprland",
|
"type": "git",
|
||||||
"type": "github"
|
"url": "https://github.com/hyprwm/Hyprland"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hyprland-protocols": {
|
"hyprland-protocols": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"hyprland",
|
"hyprland",
|
||||||
|
"xdph",
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"systems": [
|
"systems": [
|
||||||
"hyprland",
|
"hyprland",
|
||||||
|
"xdph",
|
||||||
"systems"
|
"systems"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1691753796,
|
"lastModified": 1718746314,
|
||||||
"narHash": "sha256-zOEwiWoXk3j3+EoF3ySUJmberFewWlagvewDRuWYAso=",
|
"narHash": "sha256-HUklK5u86w2Yh9dOkk4FdsL8eehcOZ95jPhLixGDRQY=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprland-protocols",
|
"repo": "hyprland-protocols",
|
||||||
"rev": "0c2ce70625cb30aef199cb388f99e19a61a6ce03",
|
"rev": "1b61f0093afff20ab44d88ad707aed8bf2215290",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -78,19 +119,25 @@
|
||||||
},
|
},
|
||||||
"hyprlang": {
|
"hyprlang": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"hyprutils": [
|
||||||
|
"hyprland",
|
||||||
|
"hyprutils"
|
||||||
|
],
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"hyprland",
|
"hyprland",
|
||||||
"hyprcursor",
|
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"systems": "systems"
|
"systems": [
|
||||||
|
"hyprland",
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1709914708,
|
"lastModified": 1720381373,
|
||||||
"narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=",
|
"narHash": "sha256-lyC/EZdHULsaAKVryK11lgHY9u6pXr7qR4irnxNWC7k=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprlang",
|
"repo": "hyprlang",
|
||||||
"rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2",
|
"rev": "5df0174fd09de4ac5475233d65ffc703e89b82eb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -99,7 +146,7 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hyprlang_2": {
|
"hyprutils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"hyprland",
|
"hyprland",
|
||||||
|
@ -111,26 +158,51 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1709914708,
|
"lastModified": 1721071737,
|
||||||
"narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=",
|
"narHash": "sha256-qmC9jGfbE4+EIBbbSAkrfR/p49wShjpv4/KztgE/P54=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprlang",
|
"repo": "hyprutils",
|
||||||
"rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2",
|
"rev": "eb1ceff2b87f6820789249f63faa8e9dcb54d05f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprlang",
|
"repo": "hyprutils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hyprwayland-scanner": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"hyprland",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"hyprland",
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1720215857,
|
||||||
|
"narHash": "sha256-JPdL+Qul+jEueAn8CARfcWP83eJgwkhMejQYfDvrgvU=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprwayland-scanner",
|
||||||
|
"rev": "d5fa094ca27e0039be5e94c0a80ae433145af8bb",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprwayland-scanner",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710272261,
|
"lastModified": 1720957393,
|
||||||
"narHash": "sha256-g0bDwXFmTE7uGDOs9HcJsfLFhH7fOsASbAuOzDC+fhQ=",
|
"narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "0ad13a6833440b8e238947e47bea7f11071dc2b2",
|
"rev": "693bc46d169f5af9c992095736e82c3488bf7dbb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -160,46 +232,9 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1689347949,
|
|
||||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default-linux",
|
|
||||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default-linux",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wlroots": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"host": "gitlab.freedesktop.org",
|
|
||||||
"lastModified": 1709983277,
|
|
||||||
"narHash": "sha256-wXWIJLd4F2JZeMaihWVDW/yYXCLEC8OpeNJZg9a9ly8=",
|
|
||||||
"owner": "wlroots",
|
|
||||||
"repo": "wlroots",
|
|
||||||
"rev": "50eae512d9cecbf0b3b1898bb1f0b40fa05fe19b",
|
|
||||||
"type": "gitlab"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"host": "gitlab.freedesktop.org",
|
|
||||||
"owner": "wlroots",
|
|
||||||
"repo": "wlroots",
|
|
||||||
"rev": "50eae512d9cecbf0b3b1898bb1f0b40fa05fe19b",
|
|
||||||
"type": "gitlab"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"xdph": {
|
"xdph": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"hyprland-protocols": [
|
"hyprland-protocols": "hyprland-protocols",
|
||||||
"hyprland",
|
|
||||||
"hyprland-protocols"
|
|
||||||
],
|
|
||||||
"hyprlang": [
|
"hyprlang": [
|
||||||
"hyprland",
|
"hyprland",
|
||||||
"hyprlang"
|
"hyprlang"
|
||||||
|
@ -214,11 +249,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1709299639,
|
"lastModified": 1720194466,
|
||||||
"narHash": "sha256-jYqJM5khksLIbqSxCLUUcqEgI+O2LdlSlcMEBs39CAU=",
|
"narHash": "sha256-Rizg9efi6ue95zOp0MeIV2ZedNo+5U9G2l6yirgBUnA=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "xdg-desktop-portal-hyprland",
|
"repo": "xdg-desktop-portal-hyprland",
|
||||||
"rev": "2d2fb547178ec025da643db57d40a971507b82fe",
|
"rev": "b9b97e5ba23fe7bd5fa4df54696102e8aa863cf6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
14
flake.nix
14
flake.nix
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
hyprland.url = "github:hyprwm/Hyprland?ref=v0.37.1";
|
hyprland.url = "git+https://github.com/hyprwm/Hyprland?submodules=1&rev=928d1dd38a6e4a791d4a4374a4a3bf02311adbb2";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, hyprland, ... }: let
|
outputs = { self, hyprland, ... }: let
|
||||||
|
@ -10,12 +10,12 @@
|
||||||
(builtins.attrNames hyprland.packages)
|
(builtins.attrNames hyprland.packages)
|
||||||
(system: fn system nixpkgs.legacyPackages.${system});
|
(system: fn system nixpkgs.legacyPackages.${system});
|
||||||
|
|
||||||
props = builtins.fromJSON (builtins.readFile "${hyprland}/props.json");
|
hyprlandVersion = nixpkgs.lib.removeSuffix "\n" (builtins.readFile "${hyprland}/VERSION");
|
||||||
in {
|
in {
|
||||||
packages = hyprlandSystems (system: pkgs: rec {
|
packages = hyprlandSystems (system: pkgs: rec {
|
||||||
hy3 = pkgs.callPackage ./default.nix {
|
hy3 = pkgs.callPackage ./default.nix {
|
||||||
hyprland = hyprland.packages.${system}.hyprland;
|
hyprland = hyprland.packages.${system}.hyprland;
|
||||||
hlversion = props.version;
|
hlversion = hyprlandVersion;
|
||||||
};
|
};
|
||||||
default = hy3;
|
default = hy3;
|
||||||
});
|
});
|
||||||
|
@ -23,14 +23,16 @@
|
||||||
devShells = hyprlandSystems (system: pkgs: {
|
devShells = hyprlandSystems (system: pkgs: {
|
||||||
default = import ./shell.nix {
|
default = import ./shell.nix {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
hlversion = props.version;
|
hlversion = hyprlandVersion;
|
||||||
hyprland = hyprland.packages.${system}.hyprland-debug;
|
hyprland = hyprland.packages.${system}.hyprland-debug;
|
||||||
};
|
};
|
||||||
|
|
||||||
impure = import ./shell.nix {
|
impure = import ./shell.nix {
|
||||||
pkgs = import <nixpkgs> {};
|
pkgs = import <nixpkgs> {};
|
||||||
hlversion = props.version;
|
hlversion = hyprlandVersion;
|
||||||
hyprland = (pkgs.appendOverlays [ hyprland.overlays.hyprland-packages ]).hyprland-debug;
|
hyprland = (pkgs.appendOverlays [ hyprland.overlays.hyprland-packages ]).hyprland-debug.overrideAttrs {
|
||||||
|
dontStrip = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
10
hyprpm.toml
10
hyprpm.toml
|
@ -5,7 +5,15 @@ commit_pins = [
|
||||||
["03ebbe18ed8517ee22591eac82cd54322f42cb7d", "2f28dc810c0e1f42763a1f14fb011c4fce6db8be"],
|
["03ebbe18ed8517ee22591eac82cd54322f42cb7d", "2f28dc810c0e1f42763a1f14fb011c4fce6db8be"],
|
||||||
["84ab8d11e8951a6551d1e1bf87796a8589da6d47", "d3e20856a9896f28b506195b31407eddc6df2e20"],
|
["84ab8d11e8951a6551d1e1bf87796a8589da6d47", "d3e20856a9896f28b506195b31407eddc6df2e20"],
|
||||||
["1c460e98f870676b15871fe4e5bfeb1a32a3d6d8", "c880e0f00946273ee0304bba9c1de276062d496f"],
|
["1c460e98f870676b15871fe4e5bfeb1a32a3d6d8", "c880e0f00946273ee0304bba9c1de276062d496f"],
|
||||||
["c5e28ebcfe00a510922779b2c568cfa52a317445", "8ac36f3954619a9a5c1a1bb3296f782452987e82"]
|
["c5e28ebcfe00a510922779b2c568cfa52a317445", "8ac36f3954619a9a5c1a1bb3296f782452987e82"],
|
||||||
|
["3875679755014997776e091ff8903acfb311dd2f", "6f9719291386d5e3baad211420d60e54e9967ee6"],
|
||||||
|
["360ede79d124ffdeebbe8401f1ac4bc0dbec2c91", "6f9719291386d5e3baad211420d60e54e9967ee6"],
|
||||||
|
["e93fbd7c4f991cb8ef03e433ccc4d43587923e15", "6f9719291386d5e3baad211420d60e54e9967ee6"],
|
||||||
|
["fe7b748eb668136dd0558b7c8279bfcd7ab4d759", "6f9719291386d5e3baad211420d60e54e9967ee6"],
|
||||||
|
["cba1ade848feac44b2eda677503900639581c3f4", "584a1b1e357412a1a4ac40dbc6c4e5adaa7ec59b"], # 0.40.0
|
||||||
|
["ea2501d4556f84d3de86a4ae2f4b22a474555b9f", "b6a777d2714628d2cda8843aec73a700ef269899"], # 0.41.0
|
||||||
|
["9e781040d9067c2711ec2e9f5b47b76ef70762b3", "b2c10c0f4d45aa6ef493f88c3eb0a20516fb9d2b"], # 0.41.1
|
||||||
|
["918d8340afd652b011b937d29d5eea0be08467f5", "df75070f7fbc1a894fb309dcbb4573034634d036"], # 0.41.2
|
||||||
]
|
]
|
||||||
|
|
||||||
[hy3]
|
[hy3]
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
||||||
class Hy3Layout;
|
class Hy3Layout;
|
||||||
|
|
||||||
enum class GroupEphemeralityOption {
|
enum class GroupEphemeralityOption {
|
||||||
|
@ -69,38 +70,39 @@ enum class ExpandFullscreenOption {
|
||||||
|
|
||||||
class Hy3Layout: public IHyprLayout {
|
class Hy3Layout: public IHyprLayout {
|
||||||
public:
|
public:
|
||||||
virtual void onWindowCreated(CWindow*, eDirection = DIRECTION_DEFAULT);
|
void onWindowCreated(PHLWINDOW, eDirection = DIRECTION_DEFAULT) override;
|
||||||
virtual void onWindowCreatedTiling(CWindow*, eDirection = DIRECTION_DEFAULT);
|
void onWindowCreatedTiling(PHLWINDOW, eDirection = DIRECTION_DEFAULT) override;
|
||||||
virtual void onWindowRemovedTiling(CWindow*);
|
void onWindowRemovedTiling(PHLWINDOW) override;
|
||||||
virtual void onWindowFocusChange(CWindow*);
|
void onWindowFocusChange(PHLWINDOW) override;
|
||||||
virtual bool isWindowTiled(CWindow*);
|
bool isWindowTiled(PHLWINDOW) override;
|
||||||
virtual void recalculateMonitor(const int& monitor_id);
|
void recalculateMonitor(const int& monitor_id) override;
|
||||||
virtual void recalculateWindow(CWindow*);
|
void recalculateWindow(PHLWINDOW) override;
|
||||||
virtual void
|
void resizeActiveWindow(const Vector2D& delta, eRectCorner corner, PHLWINDOW pWindow = nullptr)
|
||||||
resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CWindow* pWindow = nullptr);
|
override;
|
||||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool enable_fullscreen);
|
void fullscreenRequestForWindow(PHLWINDOW, eFullscreenMode, bool enable_fullscreen) override;
|
||||||
virtual std::any layoutMessage(SLayoutMessageHeader header, std::string content);
|
std::any layoutMessage(SLayoutMessageHeader header, std::string content) override;
|
||||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
SWindowRenderLayoutHints requestRenderHints(PHLWINDOW) override;
|
||||||
virtual void switchWindows(CWindow*, CWindow*);
|
void switchWindows(PHLWINDOW, PHLWINDOW) override;
|
||||||
virtual void moveWindowTo(CWindow*, const std::string& direction);
|
void moveWindowTo(PHLWINDOW, const std::string& direction, bool silent) override;
|
||||||
virtual void alterSplitRatio(CWindow*, float, bool);
|
void alterSplitRatio(PHLWINDOW, float, bool) override;
|
||||||
virtual std::string getLayoutName();
|
std::string getLayoutName() override;
|
||||||
virtual CWindow* getNextWindowCandidate(CWindow*);
|
PHLWINDOW getNextWindowCandidate(PHLWINDOW) override;
|
||||||
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
void replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) override;
|
||||||
virtual bool isWindowReachable(CWindow*);
|
bool isWindowReachable(PHLWINDOW) override;
|
||||||
virtual void bringWindowToTop(CWindow*);
|
void bringWindowToTop(PHLWINDOW) override;
|
||||||
|
Vector2D predictSizeForNewWindowTiled() override { return Vector2D(); }
|
||||||
|
|
||||||
virtual void onEnable();
|
void onEnable() override;
|
||||||
virtual void onDisable();
|
void onDisable() override;
|
||||||
|
|
||||||
void insertNode(Hy3Node& node);
|
void insertNode(Hy3Node& node);
|
||||||
void makeGroupOnWorkspace(int workspace, Hy3GroupLayout, GroupEphemeralityOption);
|
void makeGroupOnWorkspace(const PHLWORKSPACE& workspace, Hy3GroupLayout, GroupEphemeralityOption);
|
||||||
void makeOppositeGroupOnWorkspace(int workspace, GroupEphemeralityOption);
|
void makeOppositeGroupOnWorkspace(const PHLWORKSPACE& workspace, GroupEphemeralityOption);
|
||||||
void changeGroupOnWorkspace(int workspace, Hy3GroupLayout);
|
void changeGroupOnWorkspace(const PHLWORKSPACE& workspace, Hy3GroupLayout);
|
||||||
void untabGroupOnWorkspace(int workspace);
|
void untabGroupOnWorkspace(const PHLWORKSPACE& workspace);
|
||||||
void toggleTabGroupOnWorkspace(int workspace);
|
void toggleTabGroupOnWorkspace(const PHLWORKSPACE& workspace);
|
||||||
void changeGroupToOppositeOnWorkspace(int workspace);
|
void changeGroupToOppositeOnWorkspace(const PHLWORKSPACE& workspace);
|
||||||
void changeGroupEphemeralityOnWorkspace(int workspace, bool ephemeral);
|
void changeGroupEphemeralityOnWorkspace(const PHLWORKSPACE& workspace, bool ephemeral);
|
||||||
void makeGroupOn(Hy3Node*, Hy3GroupLayout, GroupEphemeralityOption);
|
void makeGroupOn(Hy3Node*, Hy3GroupLayout, GroupEphemeralityOption);
|
||||||
void makeOppositeGroupOn(Hy3Node*, GroupEphemeralityOption);
|
void makeOppositeGroupOn(Hy3Node*, GroupEphemeralityOption);
|
||||||
void changeGroupOn(Hy3Node&, Hy3GroupLayout);
|
void changeGroupOn(Hy3Node&, Hy3GroupLayout);
|
||||||
|
@ -109,20 +111,28 @@ public:
|
||||||
void changeGroupToOppositeOn(Hy3Node&);
|
void changeGroupToOppositeOn(Hy3Node&);
|
||||||
void changeGroupEphemeralityOn(Hy3Node&, bool ephemeral);
|
void changeGroupEphemeralityOn(Hy3Node&, bool ephemeral);
|
||||||
void shiftNode(Hy3Node&, ShiftDirection, bool once, bool visible);
|
void shiftNode(Hy3Node&, ShiftDirection, bool once, bool visible);
|
||||||
void shiftWindow(int workspace, ShiftDirection, bool once, bool visible);
|
void shiftWindow(const PHLWORKSPACE& workspace, ShiftDirection, bool once, bool visible);
|
||||||
void shiftFocus(int workspace, ShiftDirection, bool visible);
|
void shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection, bool visible, bool warp);
|
||||||
void moveNodeToWorkspace(int origin, std::string wsname, bool follow);
|
void warpCursor();
|
||||||
void changeFocus(int workspace, FocusShift);
|
void moveNodeToWorkspace(const PHLWORKSPACE& origin, std::string wsname, bool follow);
|
||||||
void focusTab(int workspace, TabFocus target, TabFocusMousePriority, bool wrap_scroll, int index);
|
void changeFocus(const PHLWORKSPACE& workspace, FocusShift);
|
||||||
void setNodeSwallow(int workspace, SetSwallowOption);
|
void focusTab(
|
||||||
void killFocusedNode(int workspace);
|
const PHLWORKSPACE& workspace,
|
||||||
void expand(int workspace, ExpandOption, ExpandFullscreenOption);
|
TabFocus target,
|
||||||
|
TabFocusMousePriority,
|
||||||
|
bool wrap_scroll,
|
||||||
|
int index
|
||||||
|
);
|
||||||
|
void setNodeSwallow(const PHLWORKSPACE& workspace, SetSwallowOption);
|
||||||
|
void killFocusedNode(const PHLWORKSPACE& workspace);
|
||||||
|
void expand(const PHLWORKSPACE& workspace, ExpandOption, ExpandFullscreenOption);
|
||||||
|
static void warpCursorToBox(const Vector2D& pos, const Vector2D& size);
|
||||||
|
|
||||||
bool shouldRenderSelected(CWindow*);
|
bool shouldRenderSelected(const PHLWINDOW&);
|
||||||
|
|
||||||
Hy3Node* getWorkspaceRootGroup(const int& workspace);
|
Hy3Node* getWorkspaceRootGroup(const PHLWORKSPACE& workspace);
|
||||||
Hy3Node* getWorkspaceFocusedNode(
|
Hy3Node* getWorkspaceFocusedNode(
|
||||||
const int& workspace,
|
const PHLWORKSPACE& workspace,
|
||||||
bool ignore_group_focus = false,
|
bool ignore_group_focus = false,
|
||||||
bool stop_at_expanded = false
|
bool stop_at_expanded = false
|
||||||
);
|
);
|
||||||
|
@ -136,7 +146,7 @@ public:
|
||||||
std::list<Hy3TabGroup> tab_groups;
|
std::list<Hy3TabGroup> tab_groups;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Hy3Node* getNodeFromWindow(CWindow*);
|
Hy3Node* getNodeFromWindow(const PHLWINDOW&);
|
||||||
void applyNodeDataToWindow(Hy3Node*, bool no_animation = false);
|
void applyNodeDataToWindow(Hy3Node*, bool no_animation = false);
|
||||||
|
|
||||||
// if shift is true, shift the window in the given direction, returning
|
// if shift is true, shift the window in the given direction, returning
|
||||||
|
@ -145,7 +155,7 @@ private:
|
||||||
Hy3Node* shiftOrGetFocus(Hy3Node&, ShiftDirection, bool shift, bool once, bool visible);
|
Hy3Node* shiftOrGetFocus(Hy3Node&, ShiftDirection, bool shift, bool once, bool visible);
|
||||||
|
|
||||||
void updateAutotileWorkspaces();
|
void updateAutotileWorkspaces();
|
||||||
bool shouldAutotileWorkspace(int);
|
bool shouldAutotileWorkspace(const PHLWORKSPACE& workspace);
|
||||||
void resizeNode(Hy3Node*, Vector2D, ShiftDirection resize_edge_x, ShiftDirection resize_edge_y);
|
void resizeNode(Hy3Node*, Vector2D, ShiftDirection resize_edge_x, ShiftDirection resize_edge_y);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
414
src/Hy3Node.cpp
414
src/Hy3Node.cpp
|
@ -1,9 +1,14 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include <bits/ranges_util.h>
|
||||||
#include <hyprland/src/Compositor.hpp>
|
#include <hyprland/src/Compositor.hpp>
|
||||||
#include <hyprland/src/helpers/Box.hpp>
|
#include <hyprland/src/defines.hpp>
|
||||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||||
|
#include <hyprutils/math/Box.hpp>
|
||||||
|
|
||||||
|
#include "Hy3Layout.hpp"
|
||||||
#include "Hy3Node.hpp"
|
#include "Hy3Node.hpp"
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
|
|
||||||
|
@ -37,8 +42,8 @@ bool Hy3GroupData::hasChild(Hy3Node* node) {
|
||||||
for (auto child: this->children) {
|
for (auto child: this->children) {
|
||||||
if (child == node) return true;
|
if (child == node) return true;
|
||||||
|
|
||||||
if (child->data.type == Hy3NodeType::Group) {
|
if (child->data.is_group()) {
|
||||||
if (child->data.as_group.hasChild(node)) return true;
|
if (child->data.as_group().hasChild(node)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +56,10 @@ void Hy3GroupData::collapseExpansions() {
|
||||||
|
|
||||||
Hy3Node* node = this->focused_child;
|
Hy3Node* node = this->focused_child;
|
||||||
|
|
||||||
while (node->data.type == Hy3NodeType::Group
|
while (node->data.is_group() && node->data.as_group().expand_focused == ExpandFocusType::Stack) {
|
||||||
&& node->data.as_group.expand_focused == ExpandFocusType::Stack)
|
auto& group = node->data.as_group();
|
||||||
{
|
group.expand_focused = ExpandFocusType::NotExpanded;
|
||||||
node->data.as_group.expand_focused = ExpandFocusType::NotExpanded;
|
node = group.focused_child;
|
||||||
node = node->data.as_group.focused_child;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,116 +83,143 @@ void Hy3GroupData::setEphemeral(GroupEphemeralityOption ephemeral) {
|
||||||
|
|
||||||
// Hy3NodeData //
|
// Hy3NodeData //
|
||||||
|
|
||||||
Hy3NodeData::Hy3NodeData(): Hy3NodeData((CWindow*) nullptr) {}
|
Hy3NodeData::Hy3NodeData(Hy3GroupLayout layout) { this->data.emplace<1>(layout); }
|
||||||
|
|
||||||
Hy3NodeData::Hy3NodeData(CWindow* window): type(Hy3NodeType::Window) { this->as_window = window; }
|
Hy3NodeData::Hy3NodeData(PHLWINDOW window) { this->data.emplace<0>(window); }
|
||||||
|
|
||||||
Hy3NodeData::Hy3NodeData(Hy3GroupLayout layout): Hy3NodeData(Hy3GroupData(layout)) {}
|
Hy3NodeData::Hy3NodeData(Hy3GroupData group) { this->data.emplace<1>(std::move(group)); }
|
||||||
|
|
||||||
Hy3NodeData::Hy3NodeData(Hy3GroupData group): type(Hy3NodeType::Group) {
|
Hy3NodeData::Hy3NodeData(Hy3NodeData&& node) {
|
||||||
new (&this->as_group) Hy3GroupData(std::move(group));
|
if (std::holds_alternative<PHLWINDOWREF>(node.data)) {
|
||||||
}
|
this->data.emplace<0>(std::get<PHLWINDOWREF>(node.data));
|
||||||
|
} else if (std::holds_alternative<Hy3GroupData>(node.data)) {
|
||||||
Hy3NodeData::Hy3NodeData(Hy3NodeData&& from): type(from.type) {
|
this->data.emplace<1>(std::move(std::get<Hy3GroupData>(node.data)));
|
||||||
switch (from.type) {
|
|
||||||
case Hy3NodeType::Window: this->as_window = from.as_window; break;
|
|
||||||
case Hy3NodeType::Group: new (&this->as_group) Hy3GroupData(std::move(from.as_group)); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3NodeData::~Hy3NodeData() {
|
Hy3NodeData& Hy3NodeData::operator=(PHLWINDOW window) {
|
||||||
switch (this->type) {
|
|
||||||
case Hy3NodeType::Window: break;
|
|
||||||
case Hy3NodeType::Group:
|
|
||||||
this->as_group.~Hy3GroupData();
|
|
||||||
|
|
||||||
// who ever thought calling the dtor after a move was a good idea?
|
|
||||||
this->type = Hy3NodeType::Window;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Hy3NodeData& Hy3NodeData::operator=(CWindow* window) {
|
|
||||||
*this = Hy3NodeData(window);
|
*this = Hy3NodeData(window);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3NodeData& Hy3NodeData::operator=(Hy3GroupLayout layout) {
|
Hy3NodeData& Hy3NodeData::operator=(Hy3GroupLayout layout) {
|
||||||
*this = Hy3NodeData(layout);
|
*this = Hy3NodeData(layout);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3NodeData& Hy3NodeData::operator=(Hy3NodeData&& from) {
|
Hy3NodeData& Hy3NodeData::operator=(Hy3NodeData&& from) {
|
||||||
if (this->type == Hy3NodeType::Group) {
|
this->~Hy3NodeData();
|
||||||
this->as_group.~Hy3GroupData();
|
new (this) Hy3NodeData(std::move(from));
|
||||||
}
|
|
||||||
|
|
||||||
this->type = from.type;
|
|
||||||
|
|
||||||
switch (this->type) {
|
|
||||||
case Hy3NodeType::Window: this->as_window = from.as_window; break;
|
|
||||||
case Hy3NodeType::Group: new (&this->as_group) Hy3GroupData(std::move(from.as_group)); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hy3NodeData::operator==(const Hy3NodeData& rhs) const { return this == &rhs; }
|
bool Hy3NodeData::operator==(const Hy3NodeData& rhs) const { return this == &rhs; }
|
||||||
|
|
||||||
|
bool Hy3NodeData::valid() const {
|
||||||
|
if (std::holds_alternative<Hy3GroupData>(this->data)) {
|
||||||
|
return true;
|
||||||
|
} else if (std::holds_alternative<PHLWINDOWREF>(this->data)) {
|
||||||
|
return !std::get<PHLWINDOWREF>(this->data).expired();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Hy3NodeType Hy3NodeData::type() const {
|
||||||
|
if (std::holds_alternative<Hy3GroupData>(this->data)) {
|
||||||
|
return Hy3NodeType::Group;
|
||||||
|
} else if (std::holds_alternative<PHLWINDOWREF>(this->data)) {
|
||||||
|
return Hy3NodeType::Window;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Attempted to get Hy3NodeType of uninitialized Hy3NodeData");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Hy3NodeData::is_group() const { return this->type() == Hy3NodeType::Group; }
|
||||||
|
|
||||||
|
bool Hy3NodeData::is_window() const { return this->type() == Hy3NodeType::Window; }
|
||||||
|
|
||||||
|
Hy3GroupData& Hy3NodeData::as_group() {
|
||||||
|
if (std::holds_alternative<Hy3GroupData>(this->data)) {
|
||||||
|
return std::get<Hy3GroupData>(this->data);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Attempted to get group value of a non-group Hy3NodeData");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PHLWINDOW Hy3NodeData::as_window() {
|
||||||
|
if (std::holds_alternative<PHLWINDOWREF>(this->data)) {
|
||||||
|
auto& ref = std::get<PHLWINDOWREF>(this->data);
|
||||||
|
if (ref.expired()) {
|
||||||
|
throw std::runtime_error("Attempted to upgrade an expired Hy3NodeData of a window");
|
||||||
|
} else {
|
||||||
|
return ref.lock();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Attempted to get window value of a non-window Hy3NodeData");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hy3Node //
|
// Hy3Node //
|
||||||
|
|
||||||
bool Hy3Node::operator==(const Hy3Node& rhs) const { return this->data == rhs.data; }
|
bool Hy3Node::operator==(const Hy3Node& rhs) const { return this->data == rhs.data; }
|
||||||
|
|
||||||
void Hy3Node::focus() {
|
void Hy3Node::focus(bool warp) {
|
||||||
this->markFocused();
|
this->markFocused();
|
||||||
|
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window:
|
case Hy3NodeType::Window: {
|
||||||
this->data.as_window->setHidden(false);
|
auto window = this->data.as_window();
|
||||||
g_pCompositor->focusWindow(this->data.as_window);
|
window->setHidden(false);
|
||||||
|
g_pCompositor->focusWindow(window);
|
||||||
|
if (warp) Hy3Layout::warpCursorToBox(window->m_vPosition, window->m_vSize);
|
||||||
break;
|
break;
|
||||||
case Hy3NodeType::Group:
|
}
|
||||||
|
case Hy3NodeType::Group: {
|
||||||
g_pCompositor->focusWindow(nullptr);
|
g_pCompositor->focusWindow(nullptr);
|
||||||
this->raiseToTop();
|
this->raiseToTop();
|
||||||
|
|
||||||
|
if (warp) Hy3Layout::warpCursorToBox(this->position, this->size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CWindow* Hy3Node::bringToTop() {
|
PHLWINDOW Hy3Node::bringToTop() {
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window:
|
case Hy3NodeType::Window: {
|
||||||
this->markFocused();
|
this->markFocused();
|
||||||
this->data.as_window->setHidden(false);
|
auto window = this->data.as_window();
|
||||||
|
window->setHidden(false);
|
||||||
return this->data.as_window;
|
return window;
|
||||||
case Hy3NodeType::Group:
|
}
|
||||||
if (this->data.as_group.layout == Hy3GroupLayout::Tabbed) {
|
case Hy3NodeType::Group: {
|
||||||
if (this->data.as_group.focused_child != nullptr) {
|
auto& group = this->data.as_group();
|
||||||
return this->data.as_group.focused_child->bringToTop();
|
if (group.layout == Hy3GroupLayout::Tabbed) {
|
||||||
|
if (group.focused_child != nullptr) {
|
||||||
|
return group.focused_child->bringToTop();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto* node: this->data.as_group.children) {
|
for (auto* node: group.children) {
|
||||||
auto* window = node->bringToTop();
|
auto window = node->bringToTop();
|
||||||
if (window != nullptr) return window;
|
if (window != nullptr) return window;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
default: return nullptr;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Node::focusWindow() {
|
void Hy3Node::focusWindow() {
|
||||||
auto* window = this->bringToTop();
|
auto window = this->bringToTop();
|
||||||
if (window != nullptr) g_pCompositor->focusWindow(window);
|
if (window != nullptr) g_pCompositor->focusWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void markGroupFocusedRecursive(Hy3GroupData& group) {
|
void markGroupFocusedRecursive(Hy3GroupData& group) {
|
||||||
group.group_focused = true;
|
group.group_focused = true;
|
||||||
for (auto& child: group.children) {
|
for (auto& child: group.children) {
|
||||||
if (child->data.type == Hy3NodeType::Group) markGroupFocusedRecursive(child->data.as_group);
|
if (child->data.is_group()) markGroupFocusedRecursive(child->data.as_group());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,14 +231,15 @@ void Hy3Node::markFocused() {
|
||||||
while (root->parent != nullptr) root = root->parent;
|
while (root->parent != nullptr) root = root->parent;
|
||||||
|
|
||||||
// update focus
|
// update focus
|
||||||
if (this->data.type == Hy3NodeType::Group) {
|
if (this->data.is_group()) {
|
||||||
markGroupFocusedRecursive(this->data.as_group);
|
markGroupFocusedRecursive(this->data.as_group());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* node2 = node;
|
auto* node2 = node;
|
||||||
while (node2->parent != nullptr) {
|
while (node2->parent != nullptr) {
|
||||||
node2->parent->data.as_group.focused_child = node2;
|
auto& group = node2->parent->data.as_group();
|
||||||
node2->parent->data.as_group.group_focused = false;
|
group.focused_child = node2;
|
||||||
|
group.group_focused = false;
|
||||||
node2 = node2->parent;
|
node2 = node2->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,10 +247,10 @@ void Hy3Node::markFocused() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Node::raiseToTop() {
|
void Hy3Node::raiseToTop() {
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window: g_pCompositor->changeWindowZOrder(this->data.as_window, true); break;
|
case Hy3NodeType::Window: g_pCompositor->changeWindowZOrder(this->data.as_window(), true); break;
|
||||||
case Hy3NodeType::Group:
|
case Hy3NodeType::Group:
|
||||||
for (auto* child: this->data.as_group.children) {
|
for (auto* child: this->data.as_group().children) {
|
||||||
child->raiseToTop();
|
child->raiseToTop();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -226,21 +258,19 @@ void Hy3Node::raiseToTop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3Node* Hy3Node::getFocusedNode(bool ignore_group_focus, bool stop_at_expanded) {
|
Hy3Node* Hy3Node::getFocusedNode(bool ignore_group_focus, bool stop_at_expanded) {
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window: return this;
|
case Hy3NodeType::Window: return this;
|
||||||
case Hy3NodeType::Group:
|
case Hy3NodeType::Group: {
|
||||||
if (this->data.as_group.focused_child == nullptr
|
auto& group = this->data.as_group();
|
||||||
|| (!ignore_group_focus && this->data.as_group.group_focused)
|
|
||||||
|| (stop_at_expanded && this->data.as_group.expand_focused != ExpandFocusType::NotExpanded))
|
if (group.focused_child == nullptr || (!ignore_group_focus && group.group_focused)
|
||||||
|
|| (stop_at_expanded && group.expand_focused != ExpandFocusType::NotExpanded))
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
} else {
|
} else {
|
||||||
return this->data.as_group.focused_child->getFocusedNode(
|
return group.focused_child->getFocusedNode(ignore_group_focus, stop_at_expanded);
|
||||||
ignore_group_focus,
|
|
||||||
stop_at_expanded
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
default: return nullptr;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,9 +278,8 @@ bool Hy3Node::isIndirectlyFocused() {
|
||||||
Hy3Node* node = this;
|
Hy3Node* node = this;
|
||||||
|
|
||||||
while (node->parent != nullptr) {
|
while (node->parent != nullptr) {
|
||||||
if (!node->parent->data.as_group.group_focused
|
auto& group = node->parent->data.as_group();
|
||||||
&& node->parent->data.as_group.focused_child != node)
|
if (!group.group_focused && group.focused_child != node) return false;
|
||||||
return false;
|
|
||||||
node = node->parent;
|
node = node->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +291,7 @@ Hy3Node& Hy3Node::getExpandActor() {
|
||||||
Hy3Node* node = this;
|
Hy3Node* node = this;
|
||||||
|
|
||||||
while (node->parent != nullptr
|
while (node->parent != nullptr
|
||||||
&& node->parent->data.as_group.expand_focused != ExpandFocusType::NotExpanded)
|
&& node->parent->data.as_group().expand_focused != ExpandFocusType::NotExpanded)
|
||||||
node = node->parent;
|
node = node->parent;
|
||||||
|
|
||||||
return *node;
|
return *node;
|
||||||
|
@ -275,37 +304,35 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
static const auto group_inset = ConfigValue<Hyprlang::INT>("plugin:hy3:group_inset");
|
static const auto group_inset = ConfigValue<Hyprlang::INT>("plugin:hy3:group_inset");
|
||||||
static const auto tab_bar_height = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:height");
|
static const auto tab_bar_height = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:height");
|
||||||
static const auto tab_bar_padding = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:padding");
|
static const auto tab_bar_padding = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:padding");
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
auto gap_topleft_offset = Vector2D(
|
auto gap_topleft_offset = Vector2D(
|
||||||
-(gaps_in->left - gaps_out->left),
|
(int) -(gaps_in->left - gaps_out->left),
|
||||||
-(gaps_in->top - gaps_out->top)
|
(int) -(gaps_in->top - gaps_out->top)
|
||||||
);
|
);
|
||||||
|
|
||||||
auto gap_bottomright_offset = Vector2D(
|
auto gap_bottomright_offset = Vector2D(
|
||||||
-(gaps_in->right - gaps_out->right),
|
(int) -(gaps_in->right - gaps_out->right),
|
||||||
-(gaps_in->bottom - gaps_out->bottom)
|
(int) -(gaps_in->bottom - gaps_out->bottom)
|
||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
if (this->data.type == Hy3NodeType::Window && this->data.as_window->m_bIsFullscreen) {
|
if (this->data.is_window() && this->data.as_window()->m_bIsFullscreen) {
|
||||||
auto* workspace = g_pCompositor->getWorkspaceByID(this->workspace_id);
|
auto window = this->data.as_window();
|
||||||
auto* monitor = g_pCompositor->getMonitorFromID(workspace->m_iMonitorID);
|
auto* monitor = g_pCompositor->getMonitorFromID(this->workspace->m_iMonitorID);
|
||||||
|
|
||||||
if (workspace->m_efFullscreenMode == FULLSCREEN_FULL) {
|
if (this->workspace->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||||
this->data.as_window->m_vRealPosition = monitor->vecPosition;
|
window->m_vRealPosition = monitor->vecPosition;
|
||||||
this->data.as_window->m_vRealSize = monitor->vecSize;
|
window->m_vRealSize = monitor->vecSize;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3Node fake_node = {
|
Hy3Node fake_node = {
|
||||||
.data = this->data.as_window,
|
.data = window,
|
||||||
.position = monitor->vecPosition + monitor->vecReservedTopLeft,
|
.position = monitor->vecPosition + monitor->vecReservedTopLeft,
|
||||||
.size = monitor->vecSize - monitor->vecReservedTopLeft - monitor->vecReservedBottomRight,
|
.size = monitor->vecSize - monitor->vecReservedTopLeft - monitor->vecReservedBottomRight,
|
||||||
.gap_topleft_offset = gap_topleft_offset,
|
.gap_topleft_offset = gap_topleft_offset,
|
||||||
.gap_bottomright_offset = gap_bottomright_offset,
|
.gap_bottomright_offset = gap_bottomright_offset,
|
||||||
.workspace_id = this->workspace_id,
|
.workspace = this->workspace,
|
||||||
};
|
};
|
||||||
|
|
||||||
this->layout->applyNodeDataToWindow(&fake_node);
|
this->layout->applyNodeDataToWindow(&fake_node);
|
||||||
|
@ -322,16 +349,16 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
|
|
||||||
double tab_height_offset = *tab_bar_height + *tab_bar_padding;
|
double tab_height_offset = *tab_bar_height + *tab_bar_padding;
|
||||||
|
|
||||||
if (this->data.type == Hy3NodeType::Window) {
|
if (this->data.is_window()) {
|
||||||
this->data.as_window->setHidden(this->hidden);
|
this->data.as_window()->setHidden(this->hidden);
|
||||||
this->layout->applyNodeDataToWindow(this, no_animation);
|
this->layout->applyNodeDataToWindow(this, no_animation);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* group = &this->data.as_group;
|
auto& group = this->data.as_group();
|
||||||
|
|
||||||
double constraint;
|
double constraint;
|
||||||
switch (group->layout) {
|
switch (group.layout) {
|
||||||
case Hy3GroupLayout::SplitH:
|
case Hy3GroupLayout::SplitH:
|
||||||
constraint = tsize.x - gap_topleft_offset.x - gap_bottomright_offset.x;
|
constraint = tsize.x - gap_topleft_offset.x - gap_bottomright_offset.x;
|
||||||
break;
|
break;
|
||||||
|
@ -341,34 +368,34 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
case Hy3GroupLayout::Tabbed: break;
|
case Hy3GroupLayout::Tabbed: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto expand_focused = group->expand_focused != ExpandFocusType::NotExpanded;
|
auto expand_focused = group.expand_focused != ExpandFocusType::NotExpanded;
|
||||||
bool directly_contains_expanded =
|
bool directly_contains_expanded =
|
||||||
expand_focused
|
expand_focused
|
||||||
&& (group->focused_child->data.type == Hy3NodeType::Window
|
&& (group.focused_child->data.is_window()
|
||||||
|| group->focused_child->data.as_group.expand_focused == ExpandFocusType::NotExpanded);
|
|| group.focused_child->data.as_group().expand_focused == ExpandFocusType::NotExpanded);
|
||||||
|
|
||||||
auto child_count = group->children.size();
|
auto child_count = group.children.size();
|
||||||
double ratio_mul =
|
double ratio_mul =
|
||||||
group->layout != Hy3GroupLayout::Tabbed ? child_count <= 0 ? 0 : constraint / child_count : 0;
|
group.layout != Hy3GroupLayout::Tabbed ? child_count <= 0 ? 0 : constraint / child_count : 0;
|
||||||
|
|
||||||
double offset = 0;
|
double offset = 0;
|
||||||
|
|
||||||
if (group->layout == Hy3GroupLayout::Tabbed && group->focused_child != nullptr
|
if (group.layout == Hy3GroupLayout::Tabbed && group.focused_child != nullptr
|
||||||
&& !group->focused_child->hidden)
|
&& !group.focused_child->hidden)
|
||||||
{
|
{
|
||||||
group->focused_child->setHidden(false);
|
group.focused_child->setHidden(false);
|
||||||
|
|
||||||
auto box = CBox {tpos.x, tpos.y, tsize.x, tsize.y};
|
auto box = CBox {tpos.x, tpos.y, tsize.x, tsize.y};
|
||||||
g_pHyprRenderer->damageBox(&box);
|
g_pHyprRenderer->damageBox(&box);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group->expand_focused == ExpandFocusType::Latch) {
|
if (group.expand_focused == ExpandFocusType::Latch) {
|
||||||
auto* expanded_node = group->focused_child;
|
auto* expanded_node = group.focused_child;
|
||||||
|
|
||||||
while (expanded_node != nullptr && expanded_node->data.type == Hy3NodeType::Group
|
while (expanded_node != nullptr && expanded_node->data.is_group()
|
||||||
&& expanded_node->data.as_group.expand_focused != ExpandFocusType::NotExpanded)
|
&& expanded_node->data.as_group().expand_focused != ExpandFocusType::NotExpanded)
|
||||||
{
|
{
|
||||||
expanded_node = expanded_node->data.as_group.focused_child;
|
expanded_node = expanded_node->data.as_group().focused_child;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expanded_node == nullptr) {
|
if (expanded_node == nullptr) {
|
||||||
|
@ -391,9 +418,9 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
expanded_node->recalcSizePosRecursive(no_animation);
|
expanded_node->recalcSizePosRecursive(no_animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* child: group->children) {
|
for (auto* child: group.children) {
|
||||||
if (directly_contains_expanded && child == group->focused_child) {
|
if (directly_contains_expanded && child == group.focused_child) {
|
||||||
switch (group->layout) {
|
switch (group.layout) {
|
||||||
case Hy3GroupLayout::SplitH: offset += child->size_ratio * ratio_mul; break;
|
case Hy3GroupLayout::SplitH: offset += child->size_ratio * ratio_mul; break;
|
||||||
case Hy3GroupLayout::SplitV: offset += child->size_ratio * ratio_mul; break;
|
case Hy3GroupLayout::SplitV: offset += child->size_ratio * ratio_mul; break;
|
||||||
case Hy3GroupLayout::Tabbed: break;
|
case Hy3GroupLayout::Tabbed: break;
|
||||||
|
@ -402,7 +429,7 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (group->layout) {
|
switch (group.layout) {
|
||||||
case Hy3GroupLayout::SplitH:
|
case Hy3GroupLayout::SplitH:
|
||||||
child->position.x = tpos.x + offset;
|
child->position.x = tpos.x + offset;
|
||||||
child->size.x = child->size_ratio * ratio_mul;
|
child->size.x = child->size_ratio * ratio_mul;
|
||||||
|
@ -411,23 +438,23 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
child->size.y = tsize.y;
|
child->size.y = tsize.y;
|
||||||
child->hidden = this->hidden || expand_focused;
|
child->hidden = this->hidden || expand_focused;
|
||||||
|
|
||||||
if (group->children.size() == 1) {
|
if (group.children.size() == 1) {
|
||||||
child->gap_topleft_offset = gap_topleft_offset;
|
child->gap_topleft_offset = gap_topleft_offset;
|
||||||
child->gap_bottomright_offset = gap_bottomright_offset;
|
child->gap_bottomright_offset = gap_bottomright_offset;
|
||||||
child->size.x = tsize.x;
|
child->size.x = tsize.x;
|
||||||
if (this->parent != nullptr) child->gap_bottomright_offset.x += *group_inset;
|
if (this->parent != nullptr) child->gap_bottomright_offset.x += *group_inset;
|
||||||
} else if (child == group->children.front()) {
|
} else if (child == group.children.front()) {
|
||||||
child->gap_topleft_offset = gap_topleft_offset;
|
child->gap_topleft_offset = gap_topleft_offset;
|
||||||
child->gap_bottomright_offset = Vector2D(0, gap_bottomright_offset.y);
|
child->gap_bottomright_offset = Vector2D(0.0, gap_bottomright_offset.y);
|
||||||
child->size.x += gap_topleft_offset.x;
|
child->size.x += gap_topleft_offset.x;
|
||||||
offset += gap_topleft_offset.x;
|
offset += gap_topleft_offset.x;
|
||||||
} else if (child == group->children.back()) {
|
} else if (child == group.children.back()) {
|
||||||
child->gap_topleft_offset = Vector2D(0, gap_topleft_offset.y);
|
child->gap_topleft_offset = Vector2D(0.0, gap_topleft_offset.y);
|
||||||
child->gap_bottomright_offset = gap_bottomright_offset;
|
child->gap_bottomright_offset = gap_bottomright_offset;
|
||||||
child->size.x += gap_bottomright_offset.x;
|
child->size.x += gap_bottomright_offset.x;
|
||||||
} else {
|
} else {
|
||||||
child->gap_topleft_offset = Vector2D(0, gap_topleft_offset.y);
|
child->gap_topleft_offset = Vector2D(0.0, gap_topleft_offset.y);
|
||||||
child->gap_bottomright_offset = Vector2D(0, gap_bottomright_offset.y);
|
child->gap_bottomright_offset = Vector2D(0.0, gap_bottomright_offset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
child->recalcSizePosRecursive(no_animation);
|
child->recalcSizePosRecursive(no_animation);
|
||||||
|
@ -440,23 +467,23 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
child->size.x = tsize.x;
|
child->size.x = tsize.x;
|
||||||
child->hidden = this->hidden || expand_focused;
|
child->hidden = this->hidden || expand_focused;
|
||||||
|
|
||||||
if (group->children.size() == 1) {
|
if (group.children.size() == 1) {
|
||||||
child->gap_topleft_offset = gap_topleft_offset;
|
child->gap_topleft_offset = gap_topleft_offset;
|
||||||
child->gap_bottomright_offset = gap_bottomright_offset;
|
child->gap_bottomright_offset = gap_bottomright_offset;
|
||||||
child->size.y = tsize.y;
|
child->size.y = tsize.y;
|
||||||
if (this->parent != nullptr) child->gap_bottomright_offset.y += *group_inset;
|
if (this->parent != nullptr) child->gap_bottomright_offset.y += *group_inset;
|
||||||
} else if (child == group->children.front()) {
|
} else if (child == group.children.front()) {
|
||||||
child->gap_topleft_offset = gap_topleft_offset;
|
child->gap_topleft_offset = gap_topleft_offset;
|
||||||
child->gap_bottomright_offset = Vector2D(gap_bottomright_offset.x, 0);
|
child->gap_bottomright_offset = Vector2D(gap_bottomright_offset.x, 0.0);
|
||||||
child->size.y += gap_topleft_offset.y;
|
child->size.y += gap_topleft_offset.y;
|
||||||
offset += gap_topleft_offset.y;
|
offset += gap_topleft_offset.y;
|
||||||
} else if (child == group->children.back()) {
|
} else if (child == group.children.back()) {
|
||||||
child->gap_topleft_offset = Vector2D(gap_topleft_offset.x, 0);
|
child->gap_topleft_offset = Vector2D(gap_topleft_offset.x, 0.0);
|
||||||
child->gap_bottomright_offset = gap_bottomright_offset;
|
child->gap_bottomright_offset = gap_bottomright_offset;
|
||||||
child->size.y += gap_bottomright_offset.y;
|
child->size.y += gap_bottomright_offset.y;
|
||||||
} else {
|
} else {
|
||||||
child->gap_topleft_offset = Vector2D(gap_topleft_offset.x, 0);
|
child->gap_topleft_offset = Vector2D(gap_topleft_offset.x, 0.0);
|
||||||
child->gap_bottomright_offset = Vector2D(gap_bottomright_offset.x, 0);
|
child->gap_bottomright_offset = Vector2D(gap_bottomright_offset.x, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
child->recalcSizePosRecursive(no_animation);
|
child->recalcSizePosRecursive(no_animation);
|
||||||
|
@ -464,7 +491,7 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
case Hy3GroupLayout::Tabbed:
|
case Hy3GroupLayout::Tabbed:
|
||||||
child->position = tpos;
|
child->position = tpos;
|
||||||
child->size = tsize;
|
child->size = tsize;
|
||||||
child->hidden = this->hidden || expand_focused || group->focused_child != child;
|
child->hidden = this->hidden || expand_focused || group.focused_child != child;
|
||||||
|
|
||||||
child->gap_topleft_offset =
|
child->gap_topleft_offset =
|
||||||
Vector2D(gap_topleft_offset.x, gap_topleft_offset.y + tab_height_offset);
|
Vector2D(gap_topleft_offset.x, gap_topleft_offset.y + tab_height_offset);
|
||||||
|
@ -479,18 +506,18 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FindTopWindowInNodeResult {
|
struct FindTopWindowInNodeResult {
|
||||||
CWindow* window = nullptr;
|
PHLWINDOW window = nullptr;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void findTopWindowInNode(Hy3Node& node, FindTopWindowInNodeResult& result) {
|
void findTopWindowInNode(Hy3Node& node, FindTopWindowInNodeResult& result) {
|
||||||
switch (node.data.type) {
|
switch (node.data.type()) {
|
||||||
case Hy3NodeType::Window: {
|
case Hy3NodeType::Window: {
|
||||||
auto* window = node.data.as_window;
|
auto window = node.data.as_window();
|
||||||
auto& windows = g_pCompositor->m_vWindows;
|
auto& windows = g_pCompositor->m_vWindows;
|
||||||
|
|
||||||
for (; result.index < windows.size(); result.index++) {
|
for (; result.index < windows.size(); result.index++) {
|
||||||
if (&*windows[result.index] == window) {
|
if (windows[result.index] == window) {
|
||||||
result.window = window;
|
result.window = window;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -498,7 +525,7 @@ void findTopWindowInNode(Hy3Node& node, FindTopWindowInNodeResult& result) {
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Hy3NodeType::Group: {
|
case Hy3NodeType::Group: {
|
||||||
auto& group = node.data.as_group;
|
auto& group = node.data.as_group();
|
||||||
|
|
||||||
if (group.layout == Hy3GroupLayout::Tabbed) {
|
if (group.layout == Hy3GroupLayout::Tabbed) {
|
||||||
if (group.focused_child != nullptr) findTopWindowInNode(*group.focused_child, result);
|
if (group.focused_child != nullptr) findTopWindowInNode(*group.focused_child, result);
|
||||||
|
@ -512,8 +539,8 @@ void findTopWindowInNode(Hy3Node& node, FindTopWindowInNodeResult& result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Node::updateTabBar(bool no_animation) {
|
void Hy3Node::updateTabBar(bool no_animation) {
|
||||||
if (this->data.type == Hy3NodeType::Group) {
|
if (this->data.type() == Hy3NodeType::Group) {
|
||||||
auto& group = this->data.as_group;
|
auto& group = this->data.as_group();
|
||||||
|
|
||||||
if (group.layout == Hy3GroupLayout::Tabbed) {
|
if (group.layout == Hy3GroupLayout::Tabbed) {
|
||||||
if (group.tab_bar == nullptr) group.tab_bar = &this->layout->tab_groups.emplace_back(*this);
|
if (group.tab_bar == nullptr) group.tab_bar = &this->layout->tab_groups.emplace_back(*this);
|
||||||
|
@ -522,7 +549,7 @@ void Hy3Node::updateTabBar(bool no_animation) {
|
||||||
FindTopWindowInNodeResult result;
|
FindTopWindowInNodeResult result;
|
||||||
findTopWindowInNode(*this, result);
|
findTopWindowInNode(*this, result);
|
||||||
group.tab_bar->target_window = result.window;
|
group.tab_bar->target_window = result.window;
|
||||||
if (result.window != nullptr) group.tab_bar->workspace_id = result.window->m_iWorkspaceID;
|
if (result.window != nullptr) group.tab_bar->workspace = result.window->m_pWorkspace;
|
||||||
} else if (group.tab_bar != nullptr) {
|
} else if (group.tab_bar != nullptr) {
|
||||||
group.tab_bar->bar.beginDestroy();
|
group.tab_bar->bar.beginDestroy();
|
||||||
group.tab_bar = nullptr;
|
group.tab_bar = nullptr;
|
||||||
|
@ -540,13 +567,12 @@ void Hy3Node::updateTabBarRecursive() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Node::updateDecos() {
|
void Hy3Node::updateDecos() {
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window:
|
case Hy3NodeType::Window:
|
||||||
if (this->data.as_window->m_bIsMapped)
|
g_pCompositor->updateWindowAnimatedDecorationValues(this->data.as_window());
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(this->data.as_window);
|
|
||||||
break;
|
break;
|
||||||
case Hy3NodeType::Group:
|
case Hy3NodeType::Group:
|
||||||
for (auto* child: this->data.as_group.children) {
|
for (auto* child: this->data.as_group().children) {
|
||||||
child->updateDecos();
|
child->updateDecos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,21 +581,22 @@ void Hy3Node::updateDecos() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Hy3Node::getTitle() {
|
std::string Hy3Node::getTitle() {
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window: return this->data.as_window->m_szTitle;
|
case Hy3NodeType::Window: return this->data.as_window()->m_szTitle;
|
||||||
case Hy3NodeType::Group:
|
case Hy3NodeType::Group:
|
||||||
std::string title;
|
std::string title;
|
||||||
|
auto& group = this->data.as_group();
|
||||||
|
|
||||||
switch (this->data.as_group.layout) {
|
switch (group.layout) {
|
||||||
case Hy3GroupLayout::SplitH: title = "[H] "; break;
|
case Hy3GroupLayout::SplitH: title = "[H] "; break;
|
||||||
case Hy3GroupLayout::SplitV: title = "[V] "; break;
|
case Hy3GroupLayout::SplitV: title = "[V] "; break;
|
||||||
case Hy3GroupLayout::Tabbed: title = "[T] "; break;
|
case Hy3GroupLayout::Tabbed: title = "[T] "; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->data.as_group.focused_child == nullptr) {
|
if (group.focused_child == nullptr) {
|
||||||
title += "Group";
|
title += "Group";
|
||||||
} else {
|
} else {
|
||||||
title += this->data.as_group.focused_child->getTitle();
|
title += group.focused_child->getTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
return title;
|
return title;
|
||||||
|
@ -579,33 +606,31 @@ std::string Hy3Node::getTitle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hy3Node::isUrgent() {
|
bool Hy3Node::isUrgent() {
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window: return this->data.as_window->m_bIsUrgent;
|
case Hy3NodeType::Window: return this->data.as_window()->m_bIsUrgent;
|
||||||
case Hy3NodeType::Group:
|
case Hy3NodeType::Group:
|
||||||
for (auto* child: this->data.as_group.children) {
|
for (auto* child: this->data.as_group().children) {
|
||||||
if (child->isUrgent()) return true;
|
if (child->isUrgent()) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
default: return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Node::setHidden(bool hidden) {
|
void Hy3Node::setHidden(bool hidden) {
|
||||||
this->hidden = hidden;
|
this->hidden = hidden;
|
||||||
|
|
||||||
if (this->data.type == Hy3NodeType::Group) {
|
if (this->data.is_group()) {
|
||||||
for (auto* child: this->data.as_group.children) {
|
for (auto* child: this->data.as_group().children) {
|
||||||
child->setHidden(hidden);
|
child->setHidden(hidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
|
Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
|
||||||
if (this->data.type == Hy3NodeType::Group) {
|
if (this->data.is_group()) {
|
||||||
if (this->hidden) return nullptr;
|
if (this->hidden) return nullptr;
|
||||||
|
auto& group = this->data.as_group();
|
||||||
auto& group = this->data.as_group;
|
|
||||||
|
|
||||||
if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) {
|
if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) {
|
||||||
return this;
|
return this;
|
||||||
|
@ -620,11 +645,11 @@ Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hy3Node::appendAllWindows(std::vector<CWindow*>& list) {
|
void Hy3Node::appendAllWindows(std::vector<PHLWINDOW>& list) {
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window: list.push_back(this->data.as_window); break;
|
case Hy3NodeType::Window: list.push_back(this->data.as_window()); break;
|
||||||
case Hy3NodeType::Group:
|
case Hy3NodeType::Group:
|
||||||
for (auto* child: this->data.as_group.children) {
|
for (auto* child: this->data.as_group().children) {
|
||||||
child->appendAllWindows(list);
|
child->appendAllWindows(list);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -634,12 +659,12 @@ void Hy3Node::appendAllWindows(std::vector<CWindow*>& list) {
|
||||||
std::string Hy3Node::debugNode() {
|
std::string Hy3Node::debugNode() {
|
||||||
std::stringstream buf;
|
std::stringstream buf;
|
||||||
std::string addr = "0x" + std::to_string((size_t) this);
|
std::string addr = "0x" + std::to_string((size_t) this);
|
||||||
switch (this->data.type) {
|
switch (this->data.type()) {
|
||||||
case Hy3NodeType::Window:
|
case Hy3NodeType::Window:
|
||||||
buf << "window(";
|
buf << "window(";
|
||||||
buf << std::hex << this;
|
buf << std::hex << this;
|
||||||
buf << ") [hypr ";
|
buf << ") [hypr ";
|
||||||
buf << this->data.as_window;
|
buf << this->data.as_window();
|
||||||
buf << "] size ratio: ";
|
buf << "] size ratio: ";
|
||||||
buf << this->size_ratio;
|
buf << this->size_ratio;
|
||||||
break;
|
break;
|
||||||
|
@ -648,7 +673,8 @@ std::string Hy3Node::debugNode() {
|
||||||
buf << std::hex << this;
|
buf << std::hex << this;
|
||||||
buf << ") [";
|
buf << ") [";
|
||||||
|
|
||||||
switch (this->data.as_group.layout) {
|
auto& group = this->data.as_group();
|
||||||
|
switch (group.layout) {
|
||||||
case Hy3GroupLayout::SplitH: buf << "splith"; break;
|
case Hy3GroupLayout::SplitH: buf << "splith"; break;
|
||||||
case Hy3GroupLayout::SplitV: buf << "splitv"; break;
|
case Hy3GroupLayout::SplitV: buf << "splitv"; break;
|
||||||
case Hy3GroupLayout::Tabbed: buf << "tabs"; break;
|
case Hy3GroupLayout::Tabbed: buf << "tabs"; break;
|
||||||
|
@ -657,19 +683,19 @@ std::string Hy3Node::debugNode() {
|
||||||
buf << "] size ratio: ";
|
buf << "] size ratio: ";
|
||||||
buf << this->size_ratio;
|
buf << this->size_ratio;
|
||||||
|
|
||||||
if (this->data.as_group.expand_focused != ExpandFocusType::NotExpanded) {
|
if (group.expand_focused != ExpandFocusType::NotExpanded) {
|
||||||
buf << ", has-expanded";
|
buf << ", has-expanded";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->data.as_group.ephemeral) {
|
if (group.ephemeral) {
|
||||||
buf << ", ephemeral";
|
buf << ", ephemeral";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->data.as_group.containment) {
|
if (group.containment) {
|
||||||
buf << ", containment";
|
buf << ", containment";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* child: this->data.as_group.children) {
|
for (auto* child: group.children) {
|
||||||
buf << "\n|-";
|
buf << "\n|-";
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
buf << "nullptr";
|
buf << "nullptr";
|
||||||
|
@ -695,8 +721,8 @@ Hy3Node* Hy3Node::removeFromParentRecursive(Hy3Node** expand_actor) {
|
||||||
|
|
||||||
if (this->parent != nullptr) {
|
if (this->parent != nullptr) {
|
||||||
auto& actor = this->getExpandActor();
|
auto& actor = this->getExpandActor();
|
||||||
if (actor.data.type == Hy3NodeType::Group) {
|
if (actor.data.is_group()) {
|
||||||
actor.data.as_group.collapseExpansions();
|
actor.data.as_group().collapseExpansions();
|
||||||
if (expand_actor != nullptr) *expand_actor = &actor;
|
if (expand_actor != nullptr) *expand_actor = &actor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -709,7 +735,7 @@ Hy3Node* Hy3Node::removeFromParentRecursive(Hy3Node** expand_actor) {
|
||||||
|
|
||||||
auto* child = parent;
|
auto* child = parent;
|
||||||
parent = parent->parent;
|
parent = parent->parent;
|
||||||
auto& group = parent->data.as_group;
|
auto& group = parent->data.as_group();
|
||||||
|
|
||||||
if (group.children.size() > 2) {
|
if (group.children.size() > 2) {
|
||||||
auto iter = std::find(group.children.begin(), group.children.end(), child);
|
auto iter = std::find(group.children.begin(), group.children.end(), child);
|
||||||
|
@ -771,7 +797,7 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout, GroupEphemeralityOption ephem
|
||||||
this->layout->nodes.push_back({
|
this->layout->nodes.push_back({
|
||||||
.parent = this,
|
.parent = this,
|
||||||
.data = layout,
|
.data = layout,
|
||||||
.workspace_id = this->workspace_id,
|
.workspace = this->workspace,
|
||||||
.layout = this->layout,
|
.layout = this->layout,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -779,11 +805,12 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout, GroupEphemeralityOption ephem
|
||||||
swapData(*this, *node);
|
swapData(*this, *node);
|
||||||
|
|
||||||
this->data = layout;
|
this->data = layout;
|
||||||
this->data.as_group.children.push_back(node);
|
auto& group = this->data.as_group();
|
||||||
this->data.as_group.group_focused = false;
|
group.children.push_back(node);
|
||||||
this->data.as_group.focused_child = node;
|
group.group_focused = false;
|
||||||
this->data.as_group.ephemeral = ephemeral == GroupEphemeralityOption::Ephemeral
|
group.focused_child = node;
|
||||||
|| ephemeral == GroupEphemeralityOption::ForceEphemeral;
|
group.ephemeral = ephemeral == GroupEphemeralityOption::Ephemeral
|
||||||
|
|| ephemeral == GroupEphemeralityOption::ForceEphemeral;
|
||||||
this->recalcSizePosRecursive();
|
this->recalcSizePosRecursive();
|
||||||
this->updateTabBarRecursive();
|
this->updateTabBarRecursive();
|
||||||
|
|
||||||
|
@ -791,15 +818,14 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout, GroupEphemeralityOption ephem
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hy3Node::swallowGroups(Hy3Node* into) {
|
bool Hy3Node::swallowGroups(Hy3Node* into) {
|
||||||
if (into == nullptr || into->data.type != Hy3NodeType::Group
|
if (into == nullptr || into->data.is_window() || into->data.as_group().children.size() != 1)
|
||||||
|| into->data.as_group.children.size() != 1)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto* child = into->data.as_group.children.front();
|
auto* child = into->data.as_group().children.front();
|
||||||
|
|
||||||
// a lot of segfaulting happens once the assumption that the root node is a
|
// a lot of segfaulting happens once the assumption that the root node is a
|
||||||
// group is wrong.
|
// group is wrong.
|
||||||
if (into->parent == nullptr && child->data.type != Hy3NodeType::Group) return false;
|
if (into->parent == nullptr && child->data.is_window()) return false;
|
||||||
|
|
||||||
hy3_log(TRACE, "swallowing node {:x} into node {:x}", (uintptr_t) child, (uintptr_t) into);
|
hy3_log(TRACE, "swallowing node {:x} into node {:x}", (uintptr_t) child, (uintptr_t) into);
|
||||||
|
|
||||||
|
@ -820,7 +846,7 @@ Hy3Node* getOuterChild(Hy3GroupData& group, ShiftDirection direction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3Node* Hy3Node::getImmediateSibling(ShiftDirection direction) {
|
Hy3Node* Hy3Node::getImmediateSibling(ShiftDirection direction) {
|
||||||
const auto& group = this->parent->data.as_group;
|
const auto& group = this->parent->data.as_group();
|
||||||
|
|
||||||
auto iter = std::find(group.children.begin(), group.children.end(), this);
|
auto iter = std::find(group.children.begin(), group.children.end(), this);
|
||||||
|
|
||||||
|
@ -865,7 +891,7 @@ Hy3Node* Hy3Node::findNeighbor(ShiftDirection direction) {
|
||||||
Hy3Node* sibling = nullptr;
|
Hy3Node* sibling = nullptr;
|
||||||
|
|
||||||
while (sibling == nullptr && current_node->parent != nullptr) {
|
while (sibling == nullptr && current_node->parent != nullptr) {
|
||||||
auto& parent_group = current_node->parent->data.as_group;
|
auto& parent_group = current_node->parent->data.as_group();
|
||||||
|
|
||||||
if (parent_group.layout != Hy3GroupLayout::Tabbed
|
if (parent_group.layout != Hy3GroupLayout::Tabbed
|
||||||
&& getAxis(parent_group.layout) == getAxis(direction))
|
&& getAxis(parent_group.layout) == getAxis(direction))
|
||||||
|
@ -896,7 +922,7 @@ int directionToIteratorIncrement(ShiftDirection direction) {
|
||||||
|
|
||||||
void Hy3Node::resize(ShiftDirection direction, double delta, bool no_animation) {
|
void Hy3Node::resize(ShiftDirection direction, double delta, bool no_animation) {
|
||||||
auto& parent_node = this->parent;
|
auto& parent_node = this->parent;
|
||||||
auto& containing_group = parent_node->data.as_group;
|
auto& containing_group = parent_node->data.as_group();
|
||||||
|
|
||||||
if (containing_group.layout != Hy3GroupLayout::Tabbed
|
if (containing_group.layout != Hy3GroupLayout::Tabbed
|
||||||
&& getAxis(direction) == getAxis(containing_group.layout))
|
&& getAxis(direction) == getAxis(containing_group.layout))
|
||||||
|
@ -937,14 +963,14 @@ void Hy3Node::swapData(Hy3Node& a, Hy3Node& b) {
|
||||||
a.data = std::move(b.data);
|
a.data = std::move(b.data);
|
||||||
b.data = std::move(aData);
|
b.data = std::move(aData);
|
||||||
|
|
||||||
if (a.data.type == Hy3NodeType::Group) {
|
if (a.data.is_group()) {
|
||||||
for (auto child: a.data.as_group.children) {
|
for (auto child: a.data.as_group().children) {
|
||||||
child->parent = &a;
|
child->parent = &a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.data.type == Hy3NodeType::Group) {
|
if (b.data.is_group()) {
|
||||||
for (auto child: b.data.as_group.children) {
|
for (auto child: b.data.as_group().children) {
|
||||||
child->parent = &b;
|
child->parent = &b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,10 @@ struct Hy3Node;
|
||||||
struct Hy3GroupData;
|
struct Hy3GroupData;
|
||||||
enum class Hy3GroupLayout;
|
enum class Hy3GroupLayout;
|
||||||
|
|
||||||
#include <list>
|
#include <variant>
|
||||||
|
|
||||||
#include <hyprland/src/Window.hpp>
|
#include <hyprland/src/defines.hpp>
|
||||||
|
#include <hyprland/src/desktop/Window.hpp>
|
||||||
|
|
||||||
#include "Hy3Layout.hpp"
|
#include "Hy3Layout.hpp"
|
||||||
#include "TabGroup.hpp"
|
#include "TabGroup.hpp"
|
||||||
|
@ -47,7 +48,6 @@ struct Hy3GroupData {
|
||||||
void setLayout(Hy3GroupLayout layout);
|
void setLayout(Hy3GroupLayout layout);
|
||||||
void setEphemeral(GroupEphemeralityOption ephemeral);
|
void setEphemeral(GroupEphemeralityOption ephemeral);
|
||||||
|
|
||||||
private:
|
|
||||||
Hy3GroupData(Hy3GroupData&&);
|
Hy3GroupData(Hy3GroupData&&);
|
||||||
Hy3GroupData(const Hy3GroupData&) = delete;
|
Hy3GroupData(const Hy3GroupData&) = delete;
|
||||||
|
|
||||||
|
@ -56,26 +56,28 @@ private:
|
||||||
|
|
||||||
class Hy3NodeData {
|
class Hy3NodeData {
|
||||||
public:
|
public:
|
||||||
Hy3NodeType type;
|
Hy3NodeData() = default;
|
||||||
union {
|
Hy3NodeData(Hy3GroupData);
|
||||||
Hy3GroupData as_group;
|
Hy3NodeData(PHLWINDOW window);
|
||||||
CWindow* as_window;
|
|
||||||
};
|
|
||||||
|
|
||||||
Hy3NodeData();
|
|
||||||
Hy3NodeData(CWindow* window);
|
|
||||||
Hy3NodeData(Hy3GroupLayout layout);
|
Hy3NodeData(Hy3GroupLayout layout);
|
||||||
~Hy3NodeData();
|
Hy3NodeData(Hy3NodeData&&);
|
||||||
|
~Hy3NodeData() = default;
|
||||||
|
|
||||||
Hy3NodeData& operator=(CWindow*);
|
Hy3NodeData& operator=(PHLWINDOW);
|
||||||
Hy3NodeData& operator=(Hy3GroupLayout);
|
Hy3NodeData& operator=(Hy3GroupLayout);
|
||||||
|
Hy3NodeData& operator=(Hy3NodeData&&);
|
||||||
|
|
||||||
bool operator==(const Hy3NodeData&) const;
|
bool operator==(const Hy3NodeData&) const;
|
||||||
|
|
||||||
// private: - I give up, C++ wins
|
bool valid() const;
|
||||||
Hy3NodeData(Hy3GroupData);
|
Hy3NodeType type() const;
|
||||||
Hy3NodeData(Hy3NodeData&&);
|
bool is_window() const;
|
||||||
Hy3NodeData& operator=(Hy3NodeData&&);
|
bool is_group() const;
|
||||||
|
Hy3GroupData& as_group();
|
||||||
|
PHLWINDOW as_window();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::variant<PHLWINDOWREF, Hy3GroupData> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Hy3Node {
|
struct Hy3Node {
|
||||||
|
@ -87,15 +89,15 @@ struct Hy3Node {
|
||||||
Vector2D gap_topleft_offset;
|
Vector2D gap_topleft_offset;
|
||||||
Vector2D gap_bottomright_offset;
|
Vector2D gap_bottomright_offset;
|
||||||
float size_ratio = 1.0;
|
float size_ratio = 1.0;
|
||||||
int workspace_id = -1;
|
PHLWORKSPACE workspace = nullptr;
|
||||||
bool hidden = false;
|
bool hidden = false;
|
||||||
Hy3Layout* layout = nullptr;
|
Hy3Layout* layout = nullptr;
|
||||||
|
|
||||||
bool operator==(const Hy3Node&) const;
|
bool operator==(const Hy3Node&) const;
|
||||||
|
|
||||||
void focus();
|
void focus(bool warp);
|
||||||
void focusWindow();
|
void focusWindow();
|
||||||
CWindow* bringToTop();
|
PHLWINDOW bringToTop();
|
||||||
void markFocused();
|
void markFocused();
|
||||||
void raiseToTop();
|
void raiseToTop();
|
||||||
Hy3Node* getFocusedNode(bool ignore_group_focus = false, bool stop_at_expanded = false);
|
Hy3Node* getFocusedNode(bool ignore_group_focus = false, bool stop_at_expanded = false);
|
||||||
|
@ -115,7 +117,7 @@ struct Hy3Node {
|
||||||
void setHidden(bool);
|
void setHidden(bool);
|
||||||
|
|
||||||
Hy3Node* findNodeForTabGroup(Hy3TabGroup&);
|
Hy3Node* findNodeForTabGroup(Hy3TabGroup&);
|
||||||
void appendAllWindows(std::vector<CWindow*>&);
|
void appendAllWindows(std::vector<PHLWINDOW>&);
|
||||||
std::string debugNode();
|
std::string debugNode();
|
||||||
|
|
||||||
// Remove this node from its parent, deleting the parent if it was
|
// Remove this node from its parent, deleting the parent if it was
|
||||||
|
|
|
@ -6,15 +6,15 @@
|
||||||
namespace selection_hook {
|
namespace selection_hook {
|
||||||
inline CFunctionHook* g_LastSelectionHook = nullptr;
|
inline CFunctionHook* g_LastSelectionHook = nullptr;
|
||||||
|
|
||||||
void hook_updateDecos(void* thisptr, CWindow* window) {
|
void hook_updateDecos(void* thisptr, PHLWINDOW window) {
|
||||||
bool explicitly_selected = g_Hy3Layout->shouldRenderSelected(window);
|
bool explicitly_selected = g_Hy3Layout->shouldRenderSelected(window);
|
||||||
|
|
||||||
auto* lastWindow = g_pCompositor->m_pLastWindow;
|
auto lastWindow = g_pCompositor->m_pLastWindow;
|
||||||
if (explicitly_selected) {
|
if (explicitly_selected) {
|
||||||
g_pCompositor->m_pLastWindow = window;
|
g_pCompositor->m_pLastWindow = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
((void (*)(void*, CWindow*)) g_LastSelectionHook->m_pOriginal)(thisptr, window);
|
((void (*)(void*, PHLWINDOW)) g_LastSelectionHook->m_pOriginal)(thisptr, window);
|
||||||
|
|
||||||
if (explicitly_selected) {
|
if (explicitly_selected) {
|
||||||
g_pCompositor->m_pLastWindow = lastWindow;
|
g_pCompositor->m_pLastWindow = lastWindow;
|
||||||
|
|
158
src/TabGroup.cpp
158
src/TabGroup.cpp
|
@ -2,56 +2,36 @@
|
||||||
|
|
||||||
#include <cairo/cairo.h>
|
#include <cairo/cairo.h>
|
||||||
#include <hyprland/src/Compositor.hpp>
|
#include <hyprland/src/Compositor.hpp>
|
||||||
#include <hyprland/src/helpers/Box.hpp>
|
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
||||||
|
#include <hyprland/src/desktop/Workspace.hpp>
|
||||||
#include <hyprland/src/helpers/Color.hpp>
|
#include <hyprland/src/helpers/Color.hpp>
|
||||||
#include <hyprland/src/render/OpenGL.hpp>
|
#include <hyprland/src/render/OpenGL.hpp>
|
||||||
|
#include <hyprland/src/render/Texture.hpp>
|
||||||
|
#include <hyprutils/memory/SharedPtr.hpp>
|
||||||
|
#include <hyprutils/math/Box.hpp>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
|
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
|
|
||||||
Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_bar), node(node) {
|
Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_bar), node(node) {
|
||||||
this->focused.create(
|
this->focused
|
||||||
0.0f,
|
.create(0.0f, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->urgent.create(
|
this->urgent
|
||||||
0.0f,
|
.create(0.0f, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->offset.create(
|
this->offset
|
||||||
-1.0f,
|
.create(-1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("windowsMove"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->width.create(
|
this->width
|
||||||
-1.0f,
|
.create(-1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("windowsMove"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->vertical_pos.create(
|
this->vertical_pos
|
||||||
1.0f,
|
.create(1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("windowsIn"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->fade_opacity.create(
|
this->fade_opacity
|
||||||
0.0f,
|
.create(0.0f, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("windowsIn"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->focused.registerVar();
|
this->focused.registerVar();
|
||||||
this->urgent.registerVar();
|
this->urgent.registerVar();
|
||||||
|
@ -74,6 +54,8 @@ Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_b
|
||||||
|
|
||||||
this->vertical_pos = 0.0;
|
this->vertical_pos = 0.0;
|
||||||
this->fade_opacity = 1.0;
|
this->fade_opacity = 1.0;
|
||||||
|
|
||||||
|
this->texture = makeShared<CTexture>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Hy3TabBarEntry::operator==(const Hy3Node& node) const { return this->node == node; }
|
bool Hy3TabBarEntry::operator==(const Hy3Node& node) const { return this->node == node; }
|
||||||
|
@ -139,7 +121,7 @@ void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) {
|
||||||
|
|
||||||
auto rounding = std::min((double) *s_rounding * scale, std::min(width * 0.5, height * 0.5));
|
auto rounding = std::min((double) *s_rounding * scale, std::min(width * 0.5, height * 0.5));
|
||||||
|
|
||||||
if (this->texture.m_iTexID == 0
|
if (this->texture->m_iTexID == 0
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|| this->last_render.x != box.x
|
|| this->last_render.x != box.x
|
||||||
|| this->last_render.y != box.y
|
|| this->last_render.y != box.y
|
||||||
|
@ -250,9 +232,9 @@ void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) {
|
||||||
cairo_surface_flush(cairo_surface);
|
cairo_surface_flush(cairo_surface);
|
||||||
|
|
||||||
auto data = cairo_image_surface_get_data(cairo_surface);
|
auto data = cairo_image_surface_get_data(cairo_surface);
|
||||||
this->texture.allocate();
|
this->texture->allocate();
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, this->texture.m_iTexID);
|
glBindTexture(GL_TEXTURE_2D, this->texture->m_iTexID);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
@ -266,17 +248,13 @@ void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) {
|
||||||
cairo_destroy(cairo);
|
cairo_destroy(cairo);
|
||||||
cairo_surface_destroy(cairo_surface);
|
cairo_surface_destroy(cairo_surface);
|
||||||
} else {
|
} else {
|
||||||
glBindTexture(GL_TEXTURE_2D, this->texture.m_iTexID);
|
glBindTexture(GL_TEXTURE_2D, this->texture->m_iTexID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3TabBar::Hy3TabBar() {
|
Hy3TabBar::Hy3TabBar() {
|
||||||
this->fade_opacity.create(
|
this->fade_opacity
|
||||||
1.0f,
|
.create(1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("windowsMove"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->fade_opacity.registerVar();
|
this->fade_opacity.registerVar();
|
||||||
this->fade_opacity.setUpdateCallback([this](void*) { this->dirty = true; });
|
this->fade_opacity.setUpdateCallback([this](void*) { this->dirty = true; });
|
||||||
|
@ -356,7 +334,7 @@ exitloop:
|
||||||
|
|
||||||
// set stats from node data
|
// set stats from node data
|
||||||
auto* parent = (*node)->parent;
|
auto* parent = (*node)->parent;
|
||||||
auto& parent_group = parent->data.as_group;
|
auto& parent_group = parent->data.as_group();
|
||||||
|
|
||||||
entry->setFocused(
|
entry->setFocused(
|
||||||
parent_group.focused_child == *node
|
parent_group.focused_child == *node
|
||||||
|
@ -423,17 +401,9 @@ void Hy3TabBar::setSize(Vector2D size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Hy3TabGroup::Hy3TabGroup(Hy3Node& node) {
|
Hy3TabGroup::Hy3TabGroup(Hy3Node& node) {
|
||||||
this->pos.create(
|
this->pos.create(g_pConfigManager->getAnimationPropertyConfig("windowsMove"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("windowsMove"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->size.create(
|
this->size.create(g_pConfigManager->getAnimationPropertyConfig("windowsMove"), AVARDAMAGE_NONE);
|
||||||
g_pConfigManager->getAnimationPropertyConfig("windowsMove"),
|
|
||||||
nullptr,
|
|
||||||
AVARDAMAGE_NONE
|
|
||||||
);
|
|
||||||
|
|
||||||
this->pos.registerVar();
|
this->pos.registerVar();
|
||||||
this->size.registerVar();
|
this->size.registerVar();
|
||||||
|
@ -449,7 +419,7 @@ void Hy3TabGroup::updateWithGroup(Hy3Node& node, bool warp) {
|
||||||
static const auto bar_height = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:height");
|
static const auto bar_height = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:height");
|
||||||
|
|
||||||
auto& gaps = node.parent == nullptr ? gaps_out : gaps_in;
|
auto& gaps = node.parent == nullptr ? gaps_out : gaps_in;
|
||||||
auto tpos = node.position + Vector2D(gaps->left, gaps->top) + node.gap_topleft_offset;
|
auto tpos = node.position + Vector2D((int) gaps->left, (int) gaps->top) + node.gap_topleft_offset;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
auto tsize = Vector2D(
|
auto tsize = Vector2D(
|
||||||
|
@ -469,35 +439,62 @@ void Hy3TabGroup::updateWithGroup(Hy3Node& node, bool warp) {
|
||||||
if (warp) this->size.warp();
|
if (warp) this->size.warp();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->bar.updateNodeList(node.data.as_group.children);
|
this->bar.updateNodeList(node.data.as_group().children);
|
||||||
this->bar.updateAnimations(warp);
|
this->bar.updateAnimations(warp);
|
||||||
|
|
||||||
if (node.data.as_group.focused_child != nullptr) {
|
if (node.data.as_group().focused_child != nullptr) {
|
||||||
this->updateStencilWindows(*node.data.as_group.focused_child);
|
this->updateStencilWindows(*node.data.as_group().focused_child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void damageBox(const Vector2D* position, const Vector2D* size) {
|
||||||
|
auto box = CBox {position->x, position->y, size->x, size->y};
|
||||||
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
}
|
||||||
|
|
||||||
void Hy3TabGroup::tick() {
|
void Hy3TabGroup::tick() {
|
||||||
static const auto enter_from_top = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:from_top");
|
static const auto enter_from_top = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:from_top");
|
||||||
static const auto padding = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:padding");
|
static const auto padding = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:padding");
|
||||||
auto* workspace = g_pCompositor->getWorkspaceByID(this->workspace_id);
|
|
||||||
|
|
||||||
this->bar.tick();
|
this->bar.tick();
|
||||||
|
|
||||||
if (workspace != nullptr) {
|
if (valid(this->workspace)) {
|
||||||
if (workspace->m_bHasFullscreenWindow) {
|
if (this->workspace->m_bHasFullscreenWindow) {
|
||||||
if (this->bar.fade_opacity.goal() != 0.0) this->bar.fade_opacity = 0.0;
|
if (this->bar.fade_opacity.goal() != 0.0) this->bar.fade_opacity = 0.0;
|
||||||
} else {
|
} else {
|
||||||
if (this->bar.fade_opacity.goal() != 1.0) this->bar.fade_opacity = 1.0;
|
if (this->bar.fade_opacity.goal() != 1.0) this->bar.fade_opacity = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto workspaceOffset = this->workspace->m_vRenderOffset.value();
|
||||||
|
if (this->last_workspace_offset != workspaceOffset) {
|
||||||
|
// First we damage the area where the bar was during the previous
|
||||||
|
// tick, cleaning up after ourselves
|
||||||
|
auto pos = this->last_pos + this->last_workspace_offset;
|
||||||
|
auto size = this->last_size;
|
||||||
|
damageBox(&pos, &size);
|
||||||
|
|
||||||
|
// Then we damage the current position of the bar, to avoid seeing
|
||||||
|
// glitches with animations disabled
|
||||||
|
pos = this->pos.value() + workspaceOffset;
|
||||||
|
size = this->size.value();
|
||||||
|
damageBox(&pos, &size);
|
||||||
|
|
||||||
|
this->bar.damaged = true;
|
||||||
|
this->last_workspace_offset = workspaceOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->workspace->m_fAlpha.isBeingAnimated()) {
|
||||||
|
auto pos = this->pos.value();
|
||||||
|
auto size = this->size.value();
|
||||||
|
damageBox(&pos, &size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pos = this->pos.value();
|
auto pos = this->pos.value();
|
||||||
auto size = this->size.value();
|
auto size = this->size.value();
|
||||||
|
|
||||||
if (this->last_pos != pos || this->last_size != size) {
|
if (this->last_pos != pos || this->last_size != size) {
|
||||||
CBox damage_box = {this->last_pos.x, this->last_pos.y, this->last_size.x, this->last_size.y};
|
damageBox(&this->last_pos, &this->last_size);
|
||||||
g_pHyprRenderer->damageBox(&damage_box);
|
|
||||||
|
|
||||||
this->bar.damaged = true;
|
this->bar.damaged = true;
|
||||||
this->last_pos = pos;
|
this->last_pos = pos;
|
||||||
|
@ -511,8 +508,7 @@ void Hy3TabGroup::tick() {
|
||||||
pos.y -= *padding;
|
pos.y -= *padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBox damage_box = {pos.x, pos.y, size.x, size.y};
|
damageBox(&pos, &size);
|
||||||
g_pHyprRenderer->damageBox(&damage_box);
|
|
||||||
|
|
||||||
this->bar.damaged = true;
|
this->bar.damaged = true;
|
||||||
this->bar.dirty = false;
|
this->bar.dirty = false;
|
||||||
|
@ -525,20 +521,19 @@ void Hy3TabGroup::renderTabBar() {
|
||||||
static const auto padding = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:padding");
|
static const auto padding = ConfigValue<Hyprlang::INT>("plugin:hy3:tabs:padding");
|
||||||
|
|
||||||
auto* monitor = g_pHyprOpenGL->m_RenderData.pMonitor;
|
auto* monitor = g_pHyprOpenGL->m_RenderData.pMonitor;
|
||||||
auto* workspace = g_pCompositor->getWorkspaceByID(this->workspace_id);
|
|
||||||
auto scale = monitor->scale;
|
auto scale = monitor->scale;
|
||||||
|
|
||||||
auto monitor_size = monitor->vecSize;
|
auto monitor_size = monitor->vecSize;
|
||||||
auto pos = this->pos.value() - monitor->vecPosition;
|
auto pos = this->pos.value() - monitor->vecPosition;
|
||||||
auto size = this->size.value();
|
auto size = this->size.value();
|
||||||
|
|
||||||
if (workspace != nullptr) {
|
if (valid(this->workspace)) {
|
||||||
pos = pos + workspace->m_vRenderOffset.value();
|
pos = pos + this->workspace->m_vRenderOffset.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto scaled_pos = Vector2D(std::round(pos.x * scale), std::round(pos.y * scale));
|
auto scaled_pos = Vector2D(std::round(pos.x * scale), std::round(pos.y * scale));
|
||||||
auto scaled_size = Vector2D(std::round(size.x * scale), std::round(size.y * scale));
|
auto scaled_size = Vector2D(std::round(size.x * scale), std::round(size.y * scale));
|
||||||
wlr_box box = {scaled_pos.x, scaled_pos.y, scaled_size.x, scaled_size.y};
|
CBox box = {scaled_pos.x, scaled_pos.y, scaled_size.x, scaled_size.y};
|
||||||
|
|
||||||
// monitor size is not scaled
|
// monitor size is not scaled
|
||||||
if (pos.x > monitor_size.x || pos.y > monitor_size.y || scaled_pos.x + scaled_size.x < 0
|
if (pos.x > monitor_size.x || pos.y > monitor_size.y || scaled_pos.x + scaled_size.x < 0
|
||||||
|
@ -577,8 +572,9 @@ void Hy3TabGroup::renderTabBar() {
|
||||||
|
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
|
||||||
for (auto* window: this->stencil_windows) {
|
for (auto windowref: this->stencil_windows) {
|
||||||
if (!g_pCompositor->windowExists(window)) continue;
|
if (!valid(windowref)) continue;
|
||||||
|
auto window = windowref.lock();
|
||||||
|
|
||||||
auto wpos = window->m_vRealPosition.value() - monitor->vecPosition;
|
auto wpos = window->m_vRealPosition.value() - monitor->vecPosition;
|
||||||
auto wsize = window->m_vRealSize.value();
|
auto wsize = window->m_vRealSize.value();
|
||||||
|
@ -598,8 +594,8 @@ void Hy3TabGroup::renderTabBar() {
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fade_opacity =
|
auto fade_opacity = this->bar.fade_opacity.value()
|
||||||
this->bar.fade_opacity.value() * (workspace == nullptr ? 1.0 : workspace->m_fAlpha.value());
|
* (valid(this->workspace) ? this->workspace->m_fAlpha.value() : 1.0);
|
||||||
|
|
||||||
auto render_entry = [&](Hy3TabBarEntry& entry) {
|
auto render_entry = [&](Hy3TabBarEntry& entry) {
|
||||||
Vector2D entry_pos = {
|
Vector2D entry_pos = {
|
||||||
|
@ -641,11 +637,11 @@ void Hy3TabGroup::renderTabBar() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void findOverlappingWindows(Hy3Node& node, float height, std::vector<CWindow*>& windows) {
|
void findOverlappingWindows(Hy3Node& node, float height, std::vector<PHLWINDOWREF>& windows) {
|
||||||
switch (node.data.type) {
|
switch (node.data.type()) {
|
||||||
case Hy3NodeType::Window: windows.push_back(node.data.as_window); break;
|
case Hy3NodeType::Window: windows.push_back(node.data.as_window()); break;
|
||||||
case Hy3NodeType::Group:
|
case Hy3NodeType::Group:
|
||||||
auto& group = node.data.as_group;
|
auto& group = node.data.as_group();
|
||||||
|
|
||||||
switch (group.layout) {
|
switch (group.layout) {
|
||||||
case Hy3GroupLayout::SplitH:
|
case Hy3GroupLayout::SplitH:
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Hy3TabBar;
|
||||||
struct Hy3TabBarEntry {
|
struct Hy3TabBarEntry {
|
||||||
std::string window_title;
|
std::string window_title;
|
||||||
bool destroying = false;
|
bool destroying = false;
|
||||||
CTexture texture;
|
SP<CTexture> texture;
|
||||||
CAnimatedVariable<float> focused;
|
CAnimatedVariable<float> focused;
|
||||||
CAnimatedVariable<float> urgent;
|
CAnimatedVariable<float> urgent;
|
||||||
CAnimatedVariable<float> offset; // 0.0-1.0 of total bar
|
CAnimatedVariable<float> offset; // 0.0-1.0 of total bar
|
||||||
|
@ -85,8 +85,8 @@ private:
|
||||||
|
|
||||||
class Hy3TabGroup {
|
class Hy3TabGroup {
|
||||||
public:
|
public:
|
||||||
CWindow* target_window = nullptr;
|
PHLWINDOW target_window = nullptr;
|
||||||
int workspace_id = -1;
|
PHLWORKSPACE workspace = nullptr;
|
||||||
bool hidden = false;
|
bool hidden = false;
|
||||||
Hy3TabBar bar;
|
Hy3TabBar bar;
|
||||||
CAnimatedVariable<Vector2D> pos;
|
CAnimatedVariable<Vector2D> pos;
|
||||||
|
@ -102,7 +102,8 @@ public:
|
||||||
void renderTabBar();
|
void renderTabBar();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<CWindow*> stencil_windows;
|
std::vector<PHLWINDOWREF> stencil_windows;
|
||||||
|
Vector2D last_workspace_offset;
|
||||||
Vector2D last_pos;
|
Vector2D last_pos;
|
||||||
Vector2D last_size;
|
Vector2D last_size;
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include <hyprland/src/Compositor.hpp>
|
#include <hyprland/src/Compositor.hpp>
|
||||||
|
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
||||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
|
||||||
#include "dispatchers.hpp"
|
#include "dispatchers.hpp"
|
||||||
#include "globals.hpp"
|
#include "globals.hpp"
|
||||||
|
|
||||||
int workspace_for_action(bool allow_fullscreen = false) {
|
PHLWORKSPACE workspace_for_action(bool allow_fullscreen = false) {
|
||||||
if (g_pLayoutManager->getCurrentLayout() != g_Hy3Layout.get()) return -1;
|
if (g_pLayoutManager->getCurrentLayout() != g_Hy3Layout.get()) return nullptr;
|
||||||
|
|
||||||
int workspace_id = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
auto workspace = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||||
|
|
||||||
if (workspace_id == -1) return -1;
|
if (!valid(workspace)) return nullptr;
|
||||||
auto* workspace = g_pCompositor->getWorkspaceByID(workspace_id);
|
if (!allow_fullscreen && workspace->m_bHasFullscreenWindow) return nullptr;
|
||||||
if (workspace == nullptr) return -1;
|
|
||||||
if (!allow_fullscreen && workspace->m_bHasFullscreenWindow) return -1;
|
|
||||||
|
|
||||||
return workspace_id;
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_makegroup(std::string value) {
|
void dispatch_makegroup(std::string value) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
auto args = CVarList(value);
|
auto args = CVarList(value);
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ void dispatch_makegroup(std::string value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_changegroup(std::string value) {
|
void dispatch_changegroup(std::string value) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
auto args = CVarList(value);
|
auto args = CVarList(value);
|
||||||
|
|
||||||
|
@ -65,8 +65,8 @@ void dispatch_changegroup(std::string value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_setephemeral(std::string value) {
|
void dispatch_setephemeral(std::string value) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
auto args = CVarList(value);
|
auto args = CVarList(value);
|
||||||
|
|
||||||
|
@ -84,8 +84,8 @@ std::optional<ShiftDirection> parseShiftArg(std::string arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_movewindow(std::string value) {
|
void dispatch_movewindow(std::string value) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
auto args = CVarList(value);
|
auto args = CVarList(value);
|
||||||
|
|
||||||
|
@ -109,19 +109,32 @@ void dispatch_movewindow(std::string value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_movefocus(std::string value) {
|
void dispatch_movefocus(std::string value) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
auto args = CVarList(value);
|
auto args = CVarList(value);
|
||||||
|
|
||||||
if (auto shift = parseShiftArg(args[0])) {
|
static const auto no_cursor_warps = ConfigValue<Hyprlang::INT>("cursor:no_warps");
|
||||||
g_Hy3Layout->shiftFocus(workspace, shift.value(), args[1] == "visible");
|
auto warp_cursor = !*no_cursor_warps;
|
||||||
}
|
|
||||||
|
int argi = 0;
|
||||||
|
auto shift = parseShiftArg(args[argi++]);
|
||||||
|
if (!shift) return;
|
||||||
|
|
||||||
|
auto visible = args[argi] == "visible";
|
||||||
|
if (visible) argi++;
|
||||||
|
|
||||||
|
if (args[argi] == "nowarp") warp_cursor = false;
|
||||||
|
else if (args[argi] == "warp") warp_cursor = true;
|
||||||
|
|
||||||
|
g_Hy3Layout->shiftFocus(workspace, shift.value(), visible, warp_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dispatch_warpcursor(std::string value) { g_Hy3Layout->warpCursor(); }
|
||||||
|
|
||||||
void dispatch_move_to_workspace(std::string value) {
|
void dispatch_move_to_workspace(std::string value) {
|
||||||
int origin_workspace = workspace_for_action(true);
|
auto origin_workspace = workspace_for_action(true);
|
||||||
if (origin_workspace == -1) return;
|
if (!valid(origin_workspace)) return;
|
||||||
|
|
||||||
auto args = CVarList(value);
|
auto args = CVarList(value);
|
||||||
|
|
||||||
|
@ -134,8 +147,8 @@ void dispatch_move_to_workspace(std::string value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_changefocus(std::string arg) {
|
void dispatch_changefocus(std::string arg) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
if (arg == "top") g_Hy3Layout->changeFocus(workspace, FocusShift::Top);
|
if (arg == "top") g_Hy3Layout->changeFocus(workspace, FocusShift::Top);
|
||||||
else if (arg == "bottom") g_Hy3Layout->changeFocus(workspace, FocusShift::Bottom);
|
else if (arg == "bottom") g_Hy3Layout->changeFocus(workspace, FocusShift::Bottom);
|
||||||
|
@ -146,8 +159,8 @@ void dispatch_changefocus(std::string arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_focustab(std::string value) {
|
void dispatch_focustab(std::string value) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
auto args = CVarList(value);
|
auto args = CVarList(value);
|
||||||
|
@ -186,8 +199,8 @@ void dispatch_focustab(std::string value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_setswallow(std::string arg) {
|
void dispatch_setswallow(std::string arg) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
SetSwallowOption option;
|
SetSwallowOption option;
|
||||||
if (arg == "true") {
|
if (arg == "true") {
|
||||||
|
@ -202,15 +215,15 @@ void dispatch_setswallow(std::string arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_killactive(std::string value) {
|
void dispatch_killactive(std::string value) {
|
||||||
int workspace = workspace_for_action(true);
|
auto workspace = workspace_for_action(true);
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
g_Hy3Layout->killFocusedNode(workspace);
|
g_Hy3Layout->killFocusedNode(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_expand(std::string value) {
|
void dispatch_expand(std::string value) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
if (!valid(workspace)) return;
|
||||||
|
|
||||||
auto args = CVarList(value);
|
auto args = CVarList(value);
|
||||||
|
|
||||||
|
@ -234,11 +247,10 @@ void dispatch_expand(std::string value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatch_debug(std::string arg) {
|
void dispatch_debug(std::string arg) {
|
||||||
int workspace = workspace_for_action();
|
auto workspace = workspace_for_action();
|
||||||
if (workspace == -1) return;
|
|
||||||
|
|
||||||
auto* root = g_Hy3Layout->getWorkspaceRootGroup(workspace);
|
auto* root = g_Hy3Layout->getWorkspaceRootGroup(workspace);
|
||||||
if (workspace == -1) {
|
if (!valid(workspace)) {
|
||||||
hy3_log(LOG, "DEBUG NODES: no nodes on workspace");
|
hy3_log(LOG, "DEBUG NODES: no nodes on workspace");
|
||||||
} else {
|
} else {
|
||||||
hy3_log(LOG, "DEBUG NODES\n{}", root->debugNode().c_str());
|
hy3_log(LOG, "DEBUG NODES\n{}", root->debugNode().c_str());
|
||||||
|
@ -250,6 +262,7 @@ void registerDispatchers() {
|
||||||
HyprlandAPI::addDispatcher(PHANDLE, "hy3:changegroup", dispatch_changegroup);
|
HyprlandAPI::addDispatcher(PHANDLE, "hy3:changegroup", dispatch_changegroup);
|
||||||
HyprlandAPI::addDispatcher(PHANDLE, "hy3:setephemeral", dispatch_setephemeral);
|
HyprlandAPI::addDispatcher(PHANDLE, "hy3:setephemeral", dispatch_setephemeral);
|
||||||
HyprlandAPI::addDispatcher(PHANDLE, "hy3:movefocus", dispatch_movefocus);
|
HyprlandAPI::addDispatcher(PHANDLE, "hy3:movefocus", dispatch_movefocus);
|
||||||
|
HyprlandAPI::addDispatcher(PHANDLE, "hy3:warpcursor", dispatch_warpcursor);
|
||||||
HyprlandAPI::addDispatcher(PHANDLE, "hy3:movewindow", dispatch_movewindow);
|
HyprlandAPI::addDispatcher(PHANDLE, "hy3:movewindow", dispatch_movewindow);
|
||||||
HyprlandAPI::addDispatcher(PHANDLE, "hy3:movetoworkspace", dispatch_move_to_workspace);
|
HyprlandAPI::addDispatcher(PHANDLE, "hy3:movetoworkspace", dispatch_move_to_workspace);
|
||||||
HyprlandAPI::addDispatcher(PHANDLE, "hy3:changefocus", dispatch_changefocus);
|
HyprlandAPI::addDispatcher(PHANDLE, "hy3:changefocus", dispatch_changefocus);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include <hyprland/src/desktop/Workspace.hpp>
|
||||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||||
#include <hyprlang.hpp>
|
#include <hyprlang.hpp>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue