Compare commits

..

248 Commits

Author SHA1 Message Date
vaxerski
af4b9700b7 bump ver to 0.20.1 2023-01-07 13:49:19 +01:00
vaxerski
2858e08ce0 remove color rassert to fix overshot beziers 2023-01-07 13:38:19 +01:00
vaxerski
2b248b25c8 clamp a instead of asserting 2023-01-07 13:12:08 +01:00
rubyowo
0d2e1e1270 fix crashes and bug wiki link (#1333) 2023-01-07 12:33:36 +01:00
vaxerski
464dd79246 fix crashes on monitor ls remove 2023-01-06 16:13:50 +01:00
Mihai Fufezan
85a71d15b6 CI: add jq to Arch Meson build 2023-01-06 16:43:10 +02:00
Mihai Fufezan
f3551021e0 Nix: add jq 2023-01-06 16:31:57 +02:00
Mihai Fufezan
a54247125f Build: use props file for versioning 2023-01-06 16:22:00 +02:00
vaxerski
98ce867104 added hyprctl binds 2023-01-06 14:32:25 +01:00
vaxerski
461fab0f27 minor fixes for fakefullscreen 2023-01-06 13:29:49 +01:00
Mihai Fufezan
e9a6c3b498 Nix & meson: 0.19.2 -> 0.20.0 2023-01-06 01:24:47 +02:00
vaxerski
c02ac5e08a fix un-normalized missed color 2023-01-05 23:30:24 +01:00
vaxerski
c56b2b99f5 [gha] bump flake inputs 2023-01-05 19:19:03 +00:00
jrun
0d14fd9136 add systemd support (#1253)
* add systemd support
motivation for this is is proper ordering of related/bound/required
services to Hyprland (e.g. swaybg) that would need to have a compositor
ready.

this could possibly be a build-time option of course.

see also:
example/ files for example of services

Signed-off-by: Paymon MARANDI <darwinskernel@gmail.com>

* nix: add withSystemd flag

Signed-off-by: Paymon MARANDI <darwinskernel@gmail.com>
Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
Co-authored-by: Vaxerski <vaxry@vaxry.net>
2023-01-05 20:17:55 +01:00
vaxerski
96198dae55 Normalize color storage
Colors are now normalized to 0 - 1 values instead of 0 - 255

causes calculations to be simpler and generally cleans up the codebase.
2023-01-05 19:25:45 +01:00
vaxerski
0e3547e0f6 add touchdevice to devicevalue 2023-01-03 15:51:43 +01:00
vaxerski
3d1b255199 update constraint on constraint state region commit 2023-01-03 13:06:18 +01:00
Cole Mickens
0b26b1eed6 s/pkgs.system/pkgs.hostPlatform.system/g 2023-01-03 13:56:23 +02:00
vaxerski
a33ecec61e destroy LS-es on disconnected monitor 2023-01-02 16:16:28 +01:00
vaxerski
9ba93f4b0a fix double remove in destroyKeyboard 2023-01-02 12:08:00 +01:00
vaxerski
85d1b06a79 clean draggedwindow in dragend 2023-01-02 12:06:06 +01:00
vaxerski
cb4f748226 added fakefullscreen 2023-01-01 16:54:13 +01:00
vaxerski
7525818097 account for dimAround in fullboundingbox 2022-12-31 19:23:02 +01:00
vaxerski
ddcae74e09 normalize gradients and denormalize in groupbar 2022-12-31 17:31:33 +01:00
vaxerski
228e630f40 fix group bar color calc 2022-12-31 17:04:41 +01:00
vaxerski
7f595ed0ca support gradients in dwindle group colors 2022-12-31 16:23:56 +01:00
vaxerski
a91d0a374a fix mouse resize on master orientations 2022-12-30 13:01:43 +01:00
vaxerski
0baef17a02 simplify workspace sanity checks 2022-12-29 17:06:30 +01:00
vaxerski
5d095bb9e1 use curves for special dim anim 2022-12-29 12:30:43 +01:00
vaxerski
759490689c fix damage issues with dimaround unmap 2022-12-29 12:19:11 +01:00
vaxerski
3e2200ed90 get window under cursor in kill 2022-12-29 11:52:46 +01:00
vaxerski
a55db95a3b ignore dim when pass popup 2022-12-28 19:56:18 +01:00
vaxerski
b4ebc18367 remove main_mod 2022-12-28 19:52:12 +01:00
vaxerski
a6699ef30c added dimaround 2022-12-28 15:39:17 +01:00
vaxerski
b5f5c26be3 added dim_special 2022-12-28 15:18:23 +01:00
vaxerski
d64fc7d336 remove useless log 2022-12-27 15:28:41 +01:00
vaxerski
659a5195d4 render overlay layers in reverse
prevents stuff leaking when locked
2022-12-27 15:25:51 +01:00
vaxerski
545e63d1dd sanity check workspaces after enabling mirror 2022-12-26 13:27:02 +01:00
vaxerski
fa79703b04 [gha] build man pages 2022-12-26 12:25:58 +00:00
vaxerski
d39ed9254a update debug coredump instructions 2022-12-26 13:25:32 +01:00
vaxerski
17b4a2786d clarify layout enum 2022-12-26 12:05:34 +01:00
vaxerski
cd08fa22fd added workspace_swipe_numbered 2022-12-25 15:42:11 +00:00
Mihai Fufezan
d87d2dac0b nix: update wlroots & fix updater 2022-12-24 02:20:02 +02:00
Mihai Fufezan
f7ce3c27ea nix: update xdph 2022-12-24 01:26:38 +02:00
vaxerski
5fe437da7e added maximize windowrule 2022-12-23 19:34:28 +00:00
vaxerski
e6cbb6072b update wlroots dep 2022-12-22 15:52:11 +00:00
vaxerski
fbc7a9391a downgrade wlroots due to issues 2022-12-22 15:19:54 +00:00
vaxerski
2b888d5106 ignore focus to empty input region ls-es 2022-12-22 15:03:32 +00:00
vaxerski
4b8d417fca update wlroots dep 2022-12-22 14:45:49 +00:00
vaxerski
21cc6d7ae5 update wlroots dep 2022-12-22 12:25:38 +00:00
vaxerski
6749c8abd7 fix dynamic monitor disables corrupting pmosthz 2022-12-22 12:15:07 +00:00
TheOnlyMrCat
8c094b0eec Make libinput tap-and-drag configurable (#1267) 2022-12-22 12:05:26 +00:00
vaxerski
eb9d063229 Added make configdebug 2022-12-22 01:25:04 +00:00
vaxerski
a1143521d3 Allow floats in % rules 2022-12-21 23:18:47 +00:00
Gaoyang Zhang
8a23b66c39 nix: handle reloading of multiple/dead instances on home manager generation switch
Signed-off-by: Gaoyang Zhang <gy@blurgy.xyz>
2022-12-22 00:07:38 +02:00
Rens Porre
de5e784e07 Nix & meson: 0.18.0 -> 0.19.2 2022-12-22 00:05:56 +02:00
vaxerski
96cb47fc64 Add sane permissions for /tmp/hypr 2022-12-21 15:41:02 +00:00
vaxerski
e9bd2ee996 move setActiveMonitor backup later in onDisconnect 2022-12-21 15:17:24 +00:00
vaxerski
41cdfb7420 allow binding tablets to outputs 2022-12-21 15:11:39 +00:00
vaxerski
fc37ce4a72 render pinned windows above floating separately 2022-12-20 23:07:25 +00:00
Maarten van Gompel
edcf4cd61d fix for gap in master layout orientation right #1171 (#1260) 2022-12-20 22:24:36 +00:00
vaxerski
261fbb5b62 adjust medium ppi values 2022-12-20 13:33:29 +00:00
vaxerski
4fd90144d1 touch up the clang format and format all files 2022-12-20 02:18:47 +00:00
vaxerski
3e2785b970 fix restack in xwayland stubs 2022-12-19 23:43:50 +00:00
Mihai Fufezan
ab7f2e847e nix/flake: remove merged overrides 2022-12-19 23:46:18 +02:00
Mihai Fufezan
781f0adad4 nix/hm-module: add disableAutoreload option 2022-12-19 23:39:37 +02:00
vaxerski
668cc93962 refocus on special move 2022-12-19 14:49:19 +00:00
Jan Beich
2f6b37e103 Drop Pango (unused) (#1251)
* Drop unused Pango dependency

* nix: explicitly depend on cairo (previously pulled via pango)

src/meson.build:4:0: ERROR: Dependency "cairo" not found, tried pkgconfig
2022-12-19 12:13:07 +00:00
Jan Beich
e2ee8b9f20 Drop X11 headers (unused) (#1252)
* Move libX11 header under Xwayland support

In file included from ../src/layout/../defines.hpp:1,
                 from ../src/layout/IHyprLayout.hpp:3,
                 from ../src/layout/IHyprLayout.cpp:1:
../src/layout/../includes.hpp:9:10: fatal error: X11/Xlib.h: No such file or directory
    9 | #include <X11/Xlib.h>
      |          ^~~~~~~~~~~~

* Drop unused X11 headers
2022-12-19 12:12:58 +00:00
vaxerski
6424a1e398 mark blur dirty on dynamic blur keywords 2022-12-18 15:05:34 +00:00
vaxerski
a163ca9237 fix blur damage spam on no blurred windows 2022-12-18 12:41:19 +00:00
Mihai Fufezan
27b8561d25 nix/hm-module: add nvidiaPatches option 2022-12-18 13:43:56 +02:00
vaxerski
974739457f remove damage_entire_on_snapshot 2022-12-17 23:05:15 +00:00
vaxerski
563835404f remember master width on master close 2022-12-17 22:53:03 +00:00
Julian Schuler
2daabfa0e9 Add 'exact' option for 'splitratio' (#1245)
* Simplify getPlusMinusKeywordResult()

* Add an 'exact' option for 'splitratio'
2022-12-17 22:37:44 +00:00
vaxerski
0f3214714f respect ls protocol by forcing kb focus to kb interactive top and overlay 2022-12-17 22:35:51 +00:00
Mihai Fufezan
e7940569dd nix/wlroots: add nvidia patch 2022-12-17 21:41:22 +02:00
Mihai Fufezan
f59c9a805e nix/module: add nvidiaPatches option
Also fixes wrong package passing.
2022-12-17 21:41:22 +02:00
vaxerski
85f50a4a13 update wlroots dep 2022-12-17 18:34:06 +00:00
Julian Schuler
a3b37b0191 Fix focus not changing on (empty) workspace change (#1243) 2022-12-17 17:28:43 +00:00
Julian Schuler
11ba6afdd3 Fix cycleprev bug introduced in 46891b12cf (#1213) (#1242) 2022-12-17 14:37:10 +00:00
vaxerski
99ca1ad353 remember pos and size across fullscreen moves 2022-12-17 12:15:56 +00:00
vaxerski
2076905d6e remember size and pos on fullscreen 1 2022-12-17 12:14:43 +00:00
vaxerski
deb8d3d82e ignore self in candidate floating 2022-12-16 20:07:44 +00:00
vaxerski
f72c237d85 add disabling keyboards 2022-12-16 17:20:51 +00:00
Vaxry
98a4fa2b0d Added clang format (#1239)
* clang-format stuff and format files
2022-12-16 17:17:31 +00:00
vaxerski
7c33c7fc64 fix stupid typo 2022-12-16 11:47:02 +00:00
vaxerski
20899b597e log more in group creation 2022-12-16 00:22:23 +00:00
vaxerski
198b7cae12 ignore silent workspace rules to same workspace 2022-12-15 17:36:34 +00:00
vaxerski
121ea1fac2 set created over fullscreen in movetotop 2022-12-15 17:29:06 +00:00
vaxerski
3bd9ee0d32 minor xcursor and scale fixes 2022-12-15 17:17:15 +00:00
vaxerski
95a042691a Revert "Send initial focus to X11 type dialog"
This reverts commit efc686423a.

Issues with select dialogs.
2022-12-15 16:47:14 +00:00
Vaxry
702c0a0fbf update readme images 2022-12-15 14:32:36 +00:00
vaxerski
e405490593 fix workspace special rules 2022-12-15 12:49:39 +00:00
vaxerski
ac07e447b8 [gha] build man pages 2022-12-15 12:40:24 +00:00
NotAShelf
9702b8ce75 do not overwrite existing hyprland.desktop (#1228)
* copy desktop file only if does not exist

- Should no longer overwrite modified desktop files for pre-packaged versions of Hyprland.

* re-add cleaninstall with deprecation notice

Co-authored-by: NotAShelf <NotAShelf@users.noreply.github.com>
2022-12-15 12:39:55 +00:00
vaxerski
efc686423a Send initial focus to X11 type dialog 2022-12-15 12:38:47 +00:00
vaxerski
b89a07596e prevent moving to invalid workspaces 2022-12-14 18:42:48 +00:00
vaxerski
5a138bed6b use auto scale in fallback rule 2022-12-14 18:00:04 +00:00
vaxerski
a2ecca936e use auto scale in default cfgs 2022-12-14 17:57:45 +00:00
vaxerski
374571da96 add auto scale 2022-12-14 17:57:45 +00:00
vaxerski
f8188ed7f8 stuff 2022-12-14 17:57:45 +00:00
Mihai Fufezan
516949380d nix/hm-module: make config optional 2022-12-14 14:08:53 +02:00
Mihai Fufezan
5d66122689 nix: update xdph 2022-12-13 17:56:48 +02:00
Mihai Fufezan
de9396d2a1 nix: update xdph 2022-12-12 23:45:24 +02:00
vaxerski
f8a6799d4e verify lastmon status on connect 2022-12-12 20:51:20 +00:00
Vaxry
111d209bff Added toplevel handle sharing Rev2 (#1203)
* Added toplevel handle sharing

* nix: fix build

* update hyprland-protocols

Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
2022-12-12 14:56:42 +00:00
vaxerski
b45a213413 always build with ASan in debug 2022-12-12 14:38:50 +00:00
vaxerski
1a9ee959dd static-ize master opt 2022-12-12 14:37:49 +00:00
Maarten van Gompel
46891b12cf Master layout: lose or inherit fullscreen on deliberate window switching (#1213)
* Master layout: Lose fullscreen status when deliberately switching away from a fullscreen window

* Master layout: implemented inherit_fullscreen config parameter

When set, if you are on a fullscreen window and you cycle to the next,
swap master, etc, it will be automatically fullscreened.
2022-12-12 14:34:52 +00:00
vaxerski
0c1bec023f unset cursor image on end drag if it gets destroyed 2022-12-12 14:32:23 +00:00
vaxerski
80f58bc93f fix blur damage issues with scaled 2022-12-12 14:29:04 +00:00
vaxerski
06e6c6021e fix memory read-after-free in master layout 2022-12-12 14:18:43 +00:00
vaxerski
e8b99ae13a add override to opacity rules 2022-12-11 17:15:02 +00:00
vaxerski
bb99f151da fix pinned offset calc 2022-12-11 16:58:29 +00:00
vaxerski
f97289a3c0 fix rendering multi special ws 2022-12-11 16:53:59 +00:00
Maarten van Gompel
6381b6474f Implement orientation (placement of master area) for master layout (#1202)
* Implemented choosing placement of master area (#1059)

This implement a per workspace 'orientation' that can be set
to left, right, top or bottom. Reflecting placement of the master area.

Left (default) and right are horizontal layouts, top and bottom produce vertical
layouts. Orientation can be switched with: 'hyprctl dispatch layoutmsg orientationleft'
2022-12-10 21:59:16 +00:00
vaxerski
c3f1dc3f52 fix minor issues with move focus and follow mouse 0 2022-12-10 15:15:40 +00:00
vaxerski
62f4503f07 handle constraint cursor hints better 2022-12-10 14:43:46 +00:00
vaxerski
bf78dcecf0 add changefloatingmode event 2022-12-09 18:51:44 +00:00
vaxerski
d5352a5d12 find a default workspace smarter 2022-12-09 17:17:02 +00:00
vaxerski
fd43d2bea7 fix drag resizing on special ws-es 2022-12-09 17:08:04 +00:00
vaxerski
b9812f8bc0 use anim callbacks and don't spam config resets in drag 2022-12-09 15:00:58 +00:00
vaxerski
fba03540d5 fix sharing scaled windows 2022-12-09 14:44:20 +00:00
Mihai Fufezan
11a1a6c271 nix: add xdph to flake and enable it in the nixos module 2022-12-09 16:25:57 +02:00
vaxerski
ff12a41c40 minor focus fixes with LS-es and moving windows 2022-12-09 14:03:37 +00:00
vaxerski
629cca4816 fix string escaping in CMakeLists.txt 2022-12-09 13:57:39 +00:00
Mihai Fufezan
9fc143cf3d Revert "nix: add cachix to nixos module"
This reverts commit 5b7fec481b.
Will clarify better how to enable Cachix, in the wiki.
2022-12-09 13:36:23 +02:00
vaxerski
726732244a sort valid ws-es in relative 2022-12-08 21:24:55 +00:00
vaxerski
be6e1a33b1 ensure mapped state in addViewCoords 2022-12-08 18:52:48 +00:00
vaxerski
6e3bd440ba do not reject drags on visible windows over fullscreen 2022-12-08 17:45:25 +00:00
vaxerski
cba10ba5b7 fix memory safety in getWindowFromSurface 2022-12-08 17:43:15 +00:00
vaxerski
050693be2e fix up relative monitors 2022-12-08 12:09:48 +00:00
vaxerski
0803febac5 optimize m+- and e+- workspace opts 2022-12-08 12:08:41 +00:00
vaxerski
6259202c01 add missing c_str in debug log 2022-12-07 22:47:32 +00:00
vaxerski
e1d7a13333 unset fullscreen in onWindowRemoved 2022-12-07 18:57:02 +00:00
vaxerski
bf5844d607 add failsafe for dwindle windows 2022-12-07 18:57:02 +00:00
Mihai Fufezan
5b7fec481b nix: add cachix to nixos module 2022-12-07 19:18:15 +02:00
vaxerski
73b3bbe49b added nomaxsize rule 2022-12-07 16:08:44 +00:00
vaxerski
d8dcf670da fix lost windows clogging up memory 2022-12-07 14:32:24 +00:00
vaxerski
87b9313034 updated wlroots dep 2022-12-06 23:16:37 +00:00
vaxerski
993c382e74 minor fixes to special workspace behavior 2022-12-06 20:31:44 +00:00
vaxerski
3c9a7811b8 fix up moving to special workspace 2022-12-06 20:20:37 +00:00
vaxerski
6c8d993477 minor toplevel sharing fixups 2022-12-06 18:58:42 +00:00
vaxerski
dfa9277867 remove double semicolons 2022-12-06 15:06:27 +00:00
vaxerski
50e37419e9 fix the release CI 2022-12-06 13:25:24 +00:00
vaxerski
22978aa31e fix tarbomb with source tars 2022-12-06 13:15:18 +00:00
vaxerski
7ed401e5e0 fix group border oversaturation 2022-12-06 12:57:10 +00:00
vaxerski
da76a1ed9e block surface feedback on window sharing 2022-12-05 19:12:15 +00:00
vaxerski
9c67e08dbd ignore alpha when sharing window 2022-12-05 18:00:57 +00:00
vaxerski
6cf716f182 fix handle finding 2022-12-05 17:57:59 +00:00
vaxerski
9fb24ac1e9 avoid using wayland-0 as a socket name 2022-12-05 17:21:09 +00:00
Vaxry
66fb083003 Implement window sharing with the hl toplevel export proto (#1179)
* implement window sharing

Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
2022-12-05 17:05:15 +00:00
vaxerski
20b91f58f8 remove idiotic guard in processMouseDownNormal 2022-12-05 14:30:04 +00:00
vaxerski
ac0e675f3b better capability handling 2022-12-05 14:28:27 +00:00
Mihai Fufezan
f71f04db9e nix: add xdph to nixos module 2022-12-05 03:13:31 +02:00
vaxerski
9e4e98acfb fix crash in blurls remove 2022-12-04 22:34:30 +00:00
eriedaberrie
826e35f7a4 show groupings and swallowing in hyprctl (#1159)
* feat: show groupings and swallowing in hyprctl
2022-12-04 21:03:29 +00:00
Flafy
ffc580dda9 blur xray for layers (#1158)
* feat: apply blur_xray to non window surfaces

* don't blur optimize bottom and background layers
2022-12-04 20:57:41 +00:00
Mihai Fufezan
4557d13a32 nix: update nixpkgs (includes merged hwdata update) 2022-12-04 21:43:28 +02:00
Mihai Fufezan
215c7bd3cb nix: remove merged hwdata override 2022-12-04 21:24:34 +02:00
Flafy
ea2ef63de5 nix: add cmake and wlroots to devshell (#1155) 2022-12-04 19:58:45 +02:00
Paul
d9998f2ca5 Use internal device naming for Hyprctl devices (#1174)
* Use internal naming for Hyprctl devices

* Use c-strings rather than std::string
2022-12-04 17:32:55 +00:00
Flafy
686d6fc6d1 Fix wrong layout recalculate if statement (#1167)
* fix: wrong layout recalculate if statement

* change from find to contains
2022-12-04 17:32:27 +00:00
vaxerski
9e8df888eb fix warning 2022-12-04 00:03:48 +00:00
vaxerski
409ac12f23 avoid duplicate device names 2022-12-03 20:36:52 +00:00
vaxerski
6aa26582f6 added hyprctl switchxkblayout 2022-12-03 16:22:02 +00:00
vaxerski
056a45d035 fix shader destroy id unset 2022-12-03 14:45:10 +00:00
vaxerski
fbc839e8d9 reload shader on dynamic shader keyword 2022-12-03 14:45:10 +00:00
vaxerski
cb85eea261 [gha] build man pages 2022-12-02 20:15:25 +00:00
Hemish
439b827a08 Update wiki link in manpage (#1144)
As wiki is migrated to wiki.hyprland.org, I changed the github wiki link to wiki.hyprland.org in the manpage.
2022-12-02 20:15:03 +00:00
vaxerski
d39d6cc1e3 don't initial focus on LS keyboard grab 2022-12-02 20:10:15 +00:00
vaxerski
d6b3bfc48e don't attempt rendering on begin failure 2022-12-02 19:33:54 +00:00
vaxerski
70d4fadc39 schedule frames and reloads on session re-activate 2022-12-02 18:47:57 +00:00
vaxerski
a2a12018d9 minor changes to unsafe state handling 2022-12-02 18:45:45 +00:00
vaxerski
10d34ef818 added blur_xray 2022-12-02 18:37:11 +00:00
vaxerski
bf52545a91 [gha] bump flake inputs 2022-12-01 21:01:57 +00:00
vaxerski
c012e3d66b update wlroots dep 2022-12-01 21:00:54 +00:00
vaxerski
39a4f82460 fix crash with invalid frag dynamic shaders 2022-12-01 13:40:05 +00:00
vaxerski
7b020ffa84 Added screen shaders 2022-12-01 13:36:07 +00:00
Vaxry
b8ccf3dc3a updated the readme 2022-11-30 22:49:47 +00:00
vaxerski
869f0a0238 remove global var 2022-11-30 13:33:21 +00:00
vaxerski
ff4ea1a13a fix border inner offset in shader 2022-11-29 21:11:37 +00:00
vaxerski
51aebb2845 fix minor issues with blur w/o new optim 2022-11-29 11:21:03 +00:00
vaxerski
212f599412 fix AA on borders 2022-11-29 11:12:29 +00:00
vaxerski
55776df685 fix double free 2022-11-29 11:10:19 +00:00
vaxerski
3dd06b674a clean up blur code and fix minor issues 2022-11-28 19:19:07 +00:00
vaxerski
12df799572 recalculate layout only when needed on dynamic keywords 2022-11-28 19:05:50 +00:00
vaxerski
c341792092 fix minor issues with blur_new_optimize 2022-11-28 19:04:30 +00:00
Eric_Luo
afe12dc90b Fix a compiler warning (#1124)
Co-authored-by: hnboy <hnboy@users.noreply.github.com>
2022-11-28 19:04:24 +00:00
Jef
45d2d1e97d convert bordercolors to GradientValueData correctly (#1122)
Co-authored-by: Jef Steelant <jef.steelant_ext@softathome.com>
2022-11-28 11:44:31 +00:00
vaxerski
0a302901d2 Added handling more special workspaces 2022-11-27 22:42:22 +00:00
vaxerski
49063f949d find floating windows below closed one 2022-11-27 12:11:45 +00:00
vaxerski
7699d657d9 optimize border shader
Do not calculate gradient for discarded fragments
2022-11-27 00:30:44 +00:00
vaxerski
b2cb3b8bf2 use gradients in default configs 2022-11-27 00:26:13 +00:00
vaxerski
6cbaad896c use highp for pixcoord to fix nvidia border issues 2022-11-26 23:55:41 +00:00
vaxerski
9247f88d0c update readme 2022-11-26 20:56:18 +00:00
vaxerski
92f2e342a3 use unreachable instead of break on invalid cvd enum value 2022-11-26 20:46:39 +00:00
Dashie
e2f3f5fe63 Add nofullscreen to windowrules (#1107)
* feat: add windowrule to prevent fullscreen
2022-11-26 20:44:40 +00:00
vaxerski
0db75852f3 fix transformed border thickness 2022-11-26 20:36:05 +00:00
vaxerski
afe688e6ab allow 360 degrees of freedom in gradients 2022-11-26 19:37:20 +00:00
vaxerski
493fc00953 fix decorations missing after no_gaps_when_only toggle floating 2022-11-26 18:48:16 +00:00
vaxerski
c709dc5e8e fix fadeout with animated border 2022-11-26 18:41:30 +00:00
vaxerski
684c59e5bc optimize data feeding to gradient renderer 2022-11-26 18:09:57 +00:00
vaxerski
0948b078e1 added border gradients 2022-11-26 17:57:02 +00:00
vaxerski
52c0356900 monitor rule fixes 2022-11-26 15:41:08 +00:00
vaxerski
1c9a0be8c4 fix up the border shader 2022-11-26 13:51:30 +00:00
vaxerski
f45ec24977 don't focus back after dnd on follow mouse 1 2022-11-26 00:00:36 +00:00
vaxerski
75b7e661e7 damage windows after switch 2022-11-25 19:52:23 +00:00
vaxerski
381d7a4300 check for special workspace open in attemptDirectScanout 2022-11-25 18:25:04 +00:00
vaxerski
0e6e8461eb reset m_bEmptyFocusCursorSet on workspace switch 2022-11-25 11:34:52 +00:00
Mihai Fufezan
141456dd89 Nix & meson: 0.17.0 -> 0.18.0 2022-11-25 08:34:23 +02:00
vaxerski
9616dc7bd8 don't change alpha on special anims 2022-11-24 20:51:33 +00:00
vaxerski
379597e78f remove redundant strval_empty checks 2022-11-24 17:11:21 +00:00
vaxerski
f6067816fb skip covered windows on fullscreen workspaces in getWindowInDirection 2022-11-23 23:40:05 +00:00
vaxerski
750eb76df3 default blur new optimizations to 1 2022-11-23 15:41:19 +00:00
Julian Schuler
79a9bc9076 Add option for retrieving first empty workspace (#1085) 2022-11-23 14:10:26 +00:00
vaxerski
dcb6a0425c override force opaque rule on keybind 2022-11-23 09:55:52 +00:00
vaxerski
e15a9f3d7d damage monitor on group switch 2022-11-22 23:47:00 +00:00
vaxerski
b0f95c63c9 fix crash in setActiveMonitor null 2022-11-22 23:17:10 +00:00
vaxerski
5327565b33 remove resize transitions 2022-11-22 17:20:58 +00:00
vaxerski
95047fb083 return full monitor box for fullscreen windows in idealBB 2022-11-21 23:33:53 +00:00
CactiChameleon9
f00b2fd509 Fix swiping on the first workspace going to the last (#1067) 2022-11-21 23:30:26 +00:00
vaxerski
eb86e7967f add scroll_button libinput opt 2022-11-21 23:26:18 +00:00
Maks
88874fcfe2 Fix cmake error when using clang (#1009) 2022-11-21 21:20:51 +00:00
vaxerski
d504c1e5ab fix master resizes all 2022-11-21 18:14:25 +00:00
vaxerski
c78db1212b Unify rounding shaders 2022-11-21 18:09:47 +00:00
vaxerski
be03a6186c fix invisible windows on moving fullscreen out 2022-11-20 18:50:27 +00:00
Julian Schuler
41a8975bd1 Render focused window at last (#1060) 2022-11-20 18:50:01 +00:00
vaxerski
254c3d166f don't send motion events to lock constraints 2022-11-20 18:38:53 +00:00
vaxerski
137cf9e582 improve constraint handling 2022-11-20 17:35:13 +00:00
Mihai Fufezan
11e841580f Nix: add libdrm and wayland-protocols overlay
fixes #1055
2022-11-20 17:34:11 +02:00
vaxerski
f8b9138383 make focus/swap master layoutmsgs two-way 2022-11-20 11:55:50 +00:00
Narice
c03e4c36b0 Setting wayland environment variables at startup (#1045)
* Nix modules: removed GDK_BACKEND env variable

* setting wayland environment variables at startup

setting XDG_BACKEND and _JAVA_AWT_WM_NONREPARENTING in main.cpp
removed these variables from nix modules recommended environemnt
removed XCURSOR_SIZE from nix modules as it is already set

* Making _JAVA_AWT_WM_NONREPARENTING not overwritten
2022-11-19 19:37:16 +00:00
vaxerski
5530cf6e79 respect no_gaps_when_only in fullscreen 1 2022-11-19 17:35:37 +00:00
vaxerski
1f72237291 Fix incorrect layout positions in mirror re-add 2022-11-19 16:58:14 +00:00
vaxerski
e427d9f622 unify setting of the active monitor 2022-11-19 16:41:41 +00:00
vaxerski
f88feec02b [gha] bump flake inputs 2022-11-19 16:29:06 +00:00
vaxerski
df132e5ff3 update wlroots dep 2022-11-19 16:28:04 +00:00
vaxerski
0ffaa8d667 Fix minor issues with mirrors 2022-11-19 13:14:55 +00:00
vaxerski
e887149f25 minor fixes for mirrors & log more monitor events 2022-11-19 13:01:32 +00:00
vaxerski
250d61e0b3 find base surface if no subsurface found in ls 2022-11-18 20:35:15 +00:00
vaxerski
ba05c43ae3 minor monitor code fixups 2022-11-18 14:15:19 +00:00
vaxerski
82fe530045 don't set AS in onConnect 2022-11-18 14:08:34 +00:00
vaxerski
f91f3d1c81 Reset callbacks on remap 2022-11-18 13:53:54 +00:00
vaxerski
5d39223239 fix events in changeworkspace with bound ws-es 2022-11-17 21:58:22 +00:00
vaxerski
d2a7e22efd more memory safety around onDisconnect 2022-11-17 21:52:45 +00:00
vaxerski
724e411ffc avoid header clashes in make all 2022-11-17 18:27:50 +00:00
129 changed files with 7521 additions and 4753 deletions

65
.clang-format Normal file
View File

@@ -0,0 +1,65 @@
---
Language: Cpp
BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: true
AlignEscapedNewlines: Right
AlignOperands: false
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: AfterColon
ColumnLimit: 180
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
IncludeBlocks: Preserve
IndentCaseLabels: true
IndentWidth: 4
PointerAlignment: Left
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 4
UseTab: Never
AllowShortEnumsOnASingleLine: false
BraceWrapping:
AfterEnum: false
AlignConsecutiveDeclarations: AcrossEmptyLines
NamespaceIndentation: All

View File

@@ -62,7 +62,7 @@ jobs:
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq
- name: Checkout Hyprland
uses: actions/checkout@v3
with:

View File

@@ -17,7 +17,7 @@ jobs:
- name: Create tarball with submodules
id: tar
run: tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
run: mkdir hyprland-source; mv ./* ./hyprland-source || tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
- id: whatrelease
name: Get latest release

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "wlroots"]
path = subprojects/wlroots
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
[submodule "subprojects/hyprland-protocols"]
path = subprojects/hyprland-protocols
url = https://github.com/hyprwm/hyprland-protocols

View File

@@ -1,6 +1,12 @@
cmake_minimum_required(VERSION 3.4)
# Get version
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/props.json PROPS)
string(JSON VER GET ${PROPS} version)
project(Hyprland
DESCRIPTION "A Modern C++ Wayland Compositor"
VERSION ${VER}
)
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
@@ -22,7 +28,7 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -s 's/#|\"//g'"
COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g'"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE
OUTPUT_STRIP_TRAILING_WHITESPACE)
@@ -45,7 +51,8 @@ ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
include_directories(. PRIVATE "subprojects/wlroots/include/")
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
add_compile_options(-std=c++23 -DWLR_USE_UNSTABLE )
set(CMAKE_CXX_STANDARD 23)
add_compile_options(-DWLR_USE_UNSTABLE)
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
message(STATUS "Checking deps...")
@@ -53,7 +60,7 @@ message(STATUS "Checking deps...")
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput) # we do not check for wlroots, as we provide it ourselves
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm egl xkbcommon libinput) # we do not check for wlroots, as we provide it ourselves
file(GLOB_RECURSE SRCFILES "src/*.cpp")
@@ -73,6 +80,19 @@ ELSE()
target_link_libraries(Hyprland xcb)
ENDIF(NO_XWAYLAND MATCHES true)
IF(NO_SYSTEMD MATCHES true)
message(STATUS "SYSTEMD support is disabled...")
ELSE()
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined) checking deps...")
pkg_check_modules(LIBSYSTEMD libsystemd)
IF(LIBSYSTEMD_FOUND)
add_definitions( -DUSES_SYSTEMD )
target_link_libraries(Hyprland "${LIBSYSTEMD_LIBRARIES}")
ELSE()
message(WARNING "Systemd support requested but libsystemd was not found")
ENDIF(LIBSYSTEMD_FOUND)
ENDIF(NO_SYSTEMD MATCHES true)
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
target_compile_definitions(Hyprland PRIVATE "-DGIT_BRANCH=\"${GIT_BRANCH}\"")
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\"")
@@ -88,6 +108,16 @@ message(STATUS "Setting link libraries")
target_link_libraries(Hyprland PkgConfig::deps)
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Setting debug flags")
target_link_libraries(Hyprland asan)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin -fsanitize=address")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg -no-pie -fno-builtin")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg -no-pie -fno-builtin")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
target_link_libraries(Hyprland
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us
pixman-1
@@ -96,12 +126,6 @@ target_link_libraries(Hyprland
pthread
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_SOURCE_DIR}/ext-workspace-unstable-v1-protocol.o
${CMAKE_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1-protocol.o
${CMAKE_SOURCE_DIR}/hyprland-toplevel-export-v1-protocol.o
)
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Setting debug flags")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg -no-pie -fno-builtin")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg -no-pie -fno-builtin")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)

View File

@@ -91,6 +91,16 @@ wlr-output-power-management-unstable-v1-protocol.c:
wlr-output-power-management-unstable-v1-protocol.o: wlr-output-power-management-unstable-v1-protocol.h
hyprland-toplevel-export-v1-protocol.h:
$(WAYLAND_SCANNER) server-header \
subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml $@
hyprland-toplevel-export-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
subprojects/hyprland-protocols/protocols/hyprland-toplevel-export-v1.xml $@
hyprland-toplevel-export-v1-protocol.o: hyprland-toplevel-export-v1-protocol.h
linux-dmabuf-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) server-header \
$(WAYLAND_PROTOCOLS)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml $@
@@ -101,6 +111,16 @@ linux-dmabuf-unstable-v1-protocol.c:
linux-dmabuf-unstable-v1-protocol.o: linux-dmabuf-unstable-v1-protocol.h
wlr-foreign-toplevel-management-unstable-v1-protocol.h:
$(WAYLAND_SCANNER) server-header \
protocols/wlr-foreign-toplevel-management-unstable-v1.xml $@
wlr-foreign-toplevel-management-unstable-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
protocols/wlr-foreign-toplevel-management-unstable-v1.xml $@
wlr-foreign-toplevel-management-unstable-v1-protocol.o: wlr-foreign-toplevel-management-unstable-v1-protocol.h
legacyrenderer:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
cmake --build ./build --config Release --target all -j$(shell nproc)
@@ -124,9 +144,12 @@ clear:
rm -rf ./subprojects/wlroots/build
all:
make config
make clear
make fixwlr
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.12032 /usr/lib/ && cd ../..
make protocols
make release
cd ./hyprctl && make all && cd ..
cd hyprctl && make all && cd ..
install:
make clear
@@ -137,10 +160,10 @@ install:
cd hyprctl && make all && cd ..
mkdir -p /usr/share/wayland-sessions
cp ./example/hyprland.desktop /usr/share/wayland-sessions/
mkdir -p ${PREFIX}/bin
cp ./build/Hyprland ${PREFIX}/bin
cp ./hyprctl/hyprctl ${PREFIX}/bin
if [ ! -f /usr/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop /usr/share/wayland-sessions; fi
mkdir -p ${PREFIX}/share/hyprland
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
@@ -149,23 +172,8 @@ install:
install -Dm644 -t ${PREFIX}/share/man/man1 ./docs/*.1
cleaninstall:
make clear
make fixwlr
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.12032 /usr/lib/ && cd ../..
make protocols
make release
cd hyprctl && make all && cd ..
mkdir -p /usr/share/wayland-sessions
mkdir -p ${PREFIX}/bin
cp ./build/Hyprland ${PREFIX}/bin
cp ./hyprctl/hyprctl ${PREFIX}/bin
mkdir -p ${PREFIX}/share/hyprland
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
install -Dm644 -t ${PREFIX}/share/man/man1 ./docs/*.1
echo -en "make cleaninstall has been DEPRECATED, you should avoid using it in the future.\nRunning make install instead...\n"
make install
uninstall:
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
@@ -176,7 +184,7 @@ uninstall:
rm -f ${PREFIX}/share/man/man1/Hyprland.1
rm -f ${PREFIX}/share/man/man1/hyprctl.1
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o
fixwlr:
sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build
@@ -193,6 +201,16 @@ config:
cd subprojects/wlroots && ninja -C build/ install
configdebug:
make protocols
make fixwlr
cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=debug -Dwerror=false -Dexamples=false -Db_sanitize=address
cd subprojects/wlroots && ninja -C build/
cd subprojects/wlroots && ninja -C build/ install
man:
pandoc ./docs/Hyprland.1.rst \
--standalone \

View File

@@ -6,7 +6,6 @@
![Badge Workflow]
[![Badge License]][License]
![Badge Lines]
![Badge Language]
[![Badge Pull Requests]][Pull Requests]
[![Badge Issues]][Issues]
@@ -40,31 +39,28 @@ Hyprland is still in pretty early development compared to some other Wayland com
Although Hyprland is pretty stable, it may have some bugs.
### Help Wanted
Hyprland needs testers! <br/>
Try it out and report bugs / suggestions!
# Features
- Easily expandable and readable codebase
- Config reloaded instantly upon saving
- Custom bezier curve based animations
- `wlr_ext` workspaces protocol support
- Dual Kawase blur
- Drop shadows
- Rounded corners
- Gradient borders
- Fully dynamic workspaces
- Closely follows `wlroots-git`
- Global keybinds passed to your apps of choice
- A lot of customization
- Bundled wlroots
- Window/layer fade in/out
- Tiling/pseudotiling/floating/fullscreen windows
- Switching workspaces between window modes on the fly
- Special workspace (scratchpad)
- Special workspaces (scratchpads)
- Window/monitor rules
- Socket-based IPC
- `wlr_ext` workspaces protocol support
- Event system for bash scripts
- Rounded corners
- Full damage tracking
- Docks support
- Drawing tablet support
@@ -150,9 +146,9 @@ Try it out and report bugs / suggestions!
<!----------------------------------{ Images }--------------------------------->
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
[Preview A]: https://i.imgur.com/pC6YF1Y.png
[Preview B]: https://i.imgur.com/NbrTnZH.png
[Preview C]: https://i.imgur.com/sCafdKQ.png
[Preview A]: https://i.ibb.co/SX7GbYR/winter-rice.png
[Preview B]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
[Preview C]: https://i.imgur.com/pC6YF1Y.png
<!----------------------------------{ Badges }--------------------------------->

View File

@@ -1,10 +1,10 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "Hyprland" "1" "11 Oct 2022" "" "Hyprland User Manual"
.TH "Hyprland" "1" "26 Dec 2022" "" "Hyprland User Manual"
.hy
.SH NAME
.PP
Hyprland \- Dynamic tiling Wayland compositor
Hyprland - Dynamic tiling Wayland compositor
.SH SYNOPSIS
.PP
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
@@ -27,14 +27,14 @@ For configuration information please see
<\f[I]https://github.com/hyprwm/Hyprland/wiki\f[R]>.
.SH OPTIONS
.TP
.B \f[B]\-h\f[R], \f[B]\-\-help\f[R]
\f[B]-h\f[R], \f[B]--help\f[R]
Show command usage.
.TP
.B \f[B]\-c\f[R], \f[B]\-\-config\f[R]
\f[B]-c\f[R], \f[B]--config\f[R]
Specify config file to use.
.SH BUGS
.TP
.B Submit bug reports and request features online at:
Submit bug reports and request features online at:
<\f[I]https://github.com/hyprwm/Hyprland/issues\f[R]>
.SH SEE ALSO
.PP

View File

@@ -58,14 +58,17 @@ coredumpctl info [PID]
where `[PID]` is the PID you remembered.
## Obtaining the debug Hyprland coredump
In very rare cases, the normal coredump would not be enough.
If that's the case, you could try obtaining the debug coredump.
A debug coredump provides more information for debugging and may speed up the process of fixing the bug.
Make sure you're on latest git. Run `git pull --recurse-submodules` to sync everything.
1. [Compile Hyprland with debug mode](http://wiki.hyprland.org/Contributing-and-Debugging/#build-in-debug-mode)
> Note: The config file used will be `hyprlandd.conf` instead of `hyprland.conf`
2. Reproduce the crash in debug mode.
3. `env DEBUGINFOD_URLS="https://debuginfod.archlinux.org/" coredumpctl debug [PID]`(see section above)
4. Wait until the `(gdb)` appears
5. If gdb asks you `press y to continue without paging?` Type `y`
6. `bt -full`
7. copy the output of the command and provide that.
2. `cd ~`
3. For your own convenience, launch Hyprland from a tty with the envvar `ASAN_OPTIONS="log_path=asan.log"`:
- If using a wrapper, add `export ASAN_OPTIONS="log_path=asan.log"` in a separate line before the `exec Hyprland` line.
- If launching straight from the tty, execute `ASAN_OPTIONS="log_path=asan.log" ~/path/to/Hyprland`
4. Reproduce the crash. Hyprland should instantly close.
5. Check out your `~` and find a file called `asan.log.XXXXX` where `XXXXX` will be a number corresponding to the PID of the Hyprland instance that crashed.
6. That is your coredump. Attach it to your issue.

View File

@@ -1,10 +1,10 @@
.\" Automatically generated by Pandoc 2.5
.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "hyprctl" "1" "11 Oct 2022" "" "hyprctl User Manual"
.TH "hyprctl" "1" "26 Dec 2022" "" "hyprctl User Manual"
.hy
.SH NAME
.PP
hyprctl \- Utility for controlling parts of Hyprland from a CLI or a
hyprctl - Utility for controlling parts of Hyprland from a CLI or a
script
.SH SYNOPSIS
.PP
@@ -26,7 +26,7 @@ For dispatchers without parameters it can be anything.
.PP
Returns: \f[I]ok\f[R] on success, and an error message on failure.
.TP
.B Examples:
Examples:
\f[B]hyprctl\f[R] \f[I]dispatch exec kitty\f[R]
.RS
.PP
@@ -41,7 +41,7 @@ Set a config keyword dynamically.
.PP
Returns: \f[I]ok\f[R] on success, and an error message on failure.
.TP
.B Examples:
Examples:
\f[B]hyprctl\f[R] \f[I]keyword bind SUPER,0,pseudo\f[R]
.RS
.PP
@@ -112,13 +112,13 @@ Returns the current random splash.
.RE
.SH OPTIONS
.PP
\f[B]\-\-batch\f[R]
\f[B]--batch\f[R]
.RS
.PP
Specify a batch of commands to execute.
.TP
.B Example:
\f[B]hyprctl\f[R] \f[I]\-\-batch \[dq]keyword general:border_size 2 ;
Example:
\f[B]hyprctl\f[R] \f[I]--batch \[dq]keyword general:border_size 2 ;
keyword general:gaps_out 20\[dq]\f[R]
.RS
.PP
@@ -126,14 +126,14 @@ keyword general:gaps_out 20\[dq]\f[R]
.RE
.RE
.PP
\f[B]\-j\f[R]
\f[B]-j\f[R]
.RS
.PP
Outputs information in JSON.
.RE
.SH BUGS
.TP
.B Submit bug reports and request features online at:
Submit bug reports and request features online at:
<\f[I]https://github.com/hyprwm/Hyprland/issues\f[R]>
.SH SEE ALSO
.PP

View File

@@ -8,7 +8,7 @@
#
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=,preferred,auto,1
monitor=,preferred,auto,auto
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
@@ -42,7 +42,7 @@ general {
gaps_in = 5
gaps_out = 20
border_size = 2
col.active_border = rgba(1affffee)
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.inactive_border = rgba(595959aa)
layout = dwindle

12
example/hyprland.service Normal file
View File

@@ -0,0 +1,12 @@
; a primitive systemd --user example
[Unit]
Description = %p
BindsTo = graphical-session.target
Upholds = swaybg@333333.service
[Service]
Type = notify
ExecStart = /usr/bin/Hyprland
[Install]
WantedBy = default.target

16
example/screenShader.frag Normal file
View File

@@ -0,0 +1,16 @@
//
// Example blue light filter shader.
//
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;
void main() {
vec4 pixColor = texture2D(tex, v_texcoord);
pixColor[2] *= 0.8;
gl_FragColor = pixColor;
}

13
example/swaybg@.service Normal file
View File

@@ -0,0 +1,13 @@
; a primitive systemd --user example
; see example/hyprland.service for more details
[Unit]
Description = %p
BindsTo = hyprland.service
Wants = hyprland.service
After = hyprland.service
[Service]
ExecStart = /usr/bin/swaybg --color #%i
[Install]
WantedBy = default.target

69
flake.lock generated
View File

@@ -1,12 +1,44 @@
{
"nodes": {
"hyprland-protocols": {
"flake": false,
"locked": {
"lastModified": 1670703428,
"narHash": "sha256-4KUW5SKR0Y9uaYGcYwy53YJ3B/sgiprCL4fRGO+mpOA=",
"owner": "hyprwm",
"repo": "hyprland-protocols",
"rev": "d0d6db8cb5bef6d93ca3ad8fb2124964173396da",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprland-protocols",
"type": "github"
}
},
"hyprland-protocols_2": {
"flake": false,
"locked": {
"lastModified": 1670703428,
"narHash": "sha256-4KUW5SKR0Y9uaYGcYwy53YJ3B/sgiprCL4fRGO+mpOA=",
"owner": "hyprwm",
"repo": "hyprland-protocols",
"rev": "d0d6db8cb5bef6d93ca3ad8fb2124964173396da",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprland-protocols",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1668087632,
"narHash": "sha256-T/cUx44aYDuLMFfaiVpMdTjL4kpG7bh0VkN6JEM78/E=",
"lastModified": 1672791794,
"narHash": "sha256-mqGPpGmwap0Wfsf3o2b6qHJW1w2kk/I6cGCGIU+3t6o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5f588eb4a958f1a526ed8da02d6ea1bea0047b9f",
"rev": "9813adc7f7c0edd738c6bdd8431439688bb0cb3d",
"type": "github"
},
"original": {
@@ -18,19 +50,21 @@
},
"root": {
"inputs": {
"hyprland-protocols": "hyprland-protocols",
"nixpkgs": "nixpkgs",
"wlroots": "wlroots"
"wlroots": "wlroots",
"xdph": "xdph"
}
},
"wlroots": {
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1668292512,
"narHash": "sha256-lCMnIguyZgAGq7W2IwIVPoQS8fAfZ/XFwz/1TQ53eI8=",
"lastModified": 1671183014,
"narHash": "sha256-oMWT5Zbe/3HFINAk38jNVxiZ4PCYvPJj2Jo4iiyBtm0=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "627a5c511278e67c3c308cdc6a639cbb490f48c3",
"rev": "dc7cc98cf21a8dc19ab8895505500e3700646af0",
"type": "gitlab"
},
"original": {
@@ -39,6 +73,27 @@
"repo": "wlroots",
"type": "gitlab"
}
},
"xdph": {
"inputs": {
"hyprland-protocols": "hyprland-protocols_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1671837878,
"narHash": "sha256-OmFDyktTc/l+3wHboHeFpAQgPt3r7jjqZf8MrwuUGMo=",
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
"rev": "e47f4cec698080768821b271510985ab94a37e91",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
"type": "github"
}
}
},
"root": "root",

View File

@@ -7,6 +7,16 @@
url = "gitlab:wlroots/wlroots?host=gitlab.freedesktop.org";
flake = false;
};
xdph = {
url = "github:hyprwm/xdg-desktop-portal-hyprland";
inputs.nixpkgs.follows = "nixpkgs";
};
hyprland-protocols = {
url = "github:hyprwm/hyprland-protocols";
flake = false;
};
};
outputs = inputs @ {
@@ -21,12 +31,9 @@
"x86_64-linux"
];
pkgsFor = genSystems (system: import nixpkgs {
inherit system;
overlays = [(_: prev: {
hwdata = prev.callPackage ./nix/hwdata.nix {};
})];
});
pkgsFor = nixpkgs.legacyPackages;
props = builtins.fromJSON (builtins.readFile ./props.json);
mkDate = longDate: (lib.concatStringsSep "-" [
(builtins.substring 0 4 longDate)
@@ -41,8 +48,9 @@
};
hyprland = prev.callPackage ./nix/default.nix {
stdenv = prev.gcc12Stdenv;
version = "0.17.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
version = props.version + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
wlroots = wlroots-hyprland;
inherit (inputs) hyprland-protocols;
};
hyprland-debug = hyprland.override {debug = true;};
hyprland-no-hidpi = hyprland.override {hidpiXWayland = false;};
@@ -50,6 +58,10 @@
waybar-hyprland = prev.waybar.overrideAttrs (oldAttrs: {
mesonFlags = oldAttrs.mesonFlags ++ ["-Dexperimental=true"];
});
xdg-desktop-portal-hyprland = inputs.xdph.packages.${prev.hostPlatform.system}.default.override {
hyprland-share-picker = inputs.xdph.packages.${prev.hostPlatform.system}.hyprland-share-picker.override {inherit hyprland;};
};
};
packages = genSystems (system:
@@ -61,6 +73,12 @@
devShells = genSystems (system: {
default = pkgsFor.${system}.mkShell.override {stdenv = pkgsFor.${system}.gcc12Stdenv;} {
name = "hyprland-shell";
nativeBuildInputs = with pkgsFor.${system}; [
cmake
];
buildInputs = [
self.packages.${system}.wlroots-hyprland
];
inputsFrom = [
self.packages.${system}.wlroots-hyprland
self.packages.${system}.hyprland
@@ -70,7 +88,7 @@
formatter = genSystems (system: pkgsFor.${system}.alejandra);
nixosModules.default = import ./nix/module.nix self;
nixosModules.default = import ./nix/module.nix inputs;
homeManagerModules.default = import ./nix/hm-module.nix self;
};

View File

@@ -27,6 +27,7 @@ commands:
activewindow
layers
devices
binds
dispatch
keyword
version
@@ -37,21 +38,28 @@ commands:
setcursor
getoption
cursorpos
switchxkblayout
flags:
-j -> output in JSON
--batch -> execute a batch of commands, separated by ';'
)#";
void request(std::string arg) {
void request(std::string arg, int minArgs = 0) {
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
const auto ARGS = std::count(arg.begin(), arg.end(), ' ');
if (ARGS < minArgs) {
std::cout << "Not enough arguments, expected at least " << minArgs;
return;
}
if (SERVERSOCKET < 0) {
std::cout << "Couldn't open a socket (1)";
return;
}
// get the instance signature
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
@@ -63,7 +71,7 @@ void request(std::string arg) {
std::string instanceSigStr = std::string(instanceSig);
sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX;
serverAddress.sun_family = AF_UNIX;
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.socket.sock";
@@ -81,8 +89,8 @@ void request(std::string arg) {
return;
}
std::string reply = "";
char buffer[8192] = {0};
std::string reply = "";
char buffer[8192] = {0};
sizeWritten = read(SERVERSOCKET, buffer, 8192);
@@ -126,7 +134,7 @@ void requestHyprpaper(std::string arg) {
std::string instanceSigStr = std::string(instanceSig);
sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX;
serverAddress.sun_family = AF_UNIX;
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.hyprpaper.sock";
@@ -168,7 +176,7 @@ int dispatchRequest(int argc, char** argv) {
std::string rq = "/dispatch";
for(int i = 2; i < argc; i++) {
for (int i = 2; i < argc; i++) {
if (!strcmp(argv[i], "--"))
continue;
rq += " " + std::string(argv[i]);
@@ -187,7 +195,7 @@ int keywordRequest(int argc, char** argv) {
std::string rq = "/keyword";
for(int i = 2; i < argc; i++)
for (int i = 2; i < argc; i++)
rq += " " + std::string(argv[i]);
request(rq);
@@ -257,7 +265,7 @@ bool isNumber(const std::string& str, bool allowfloat) {
}
int main(int argc, char** argv) {
int bflag = 0, sflag = 0, index, c;
int bflag = 0, sflag = 0, index, c;
bool parseArgs = true;
if (argc < 2) {
@@ -266,8 +274,8 @@ int main(int argc, char** argv) {
}
std::string fullRequest = "";
std::string fullArgs = "";
const auto ARGS = splitArgs(argc, argv);
std::string fullArgs = "";
const auto ARGS = splitArgs(argc, argv);
for (auto i = 0; i < ARGS.size(); ++i) {
if (ARGS[i] == "--") {
@@ -303,25 +311,48 @@ int main(int argc, char** argv) {
int exitStatus = 0;
if (fullRequest.contains("/--batch")) batchRequest(fullRequest);
else if (fullRequest.contains("/monitors")) request(fullRequest);
else if (fullRequest.contains("/clients")) request(fullRequest);
else if (fullRequest.contains("/workspaces")) request(fullRequest);
else if (fullRequest.contains("/activewindow")) request(fullRequest);
else if (fullRequest.contains("/layers")) request(fullRequest);
else if (fullRequest.contains("/version")) request(fullRequest);
else if (fullRequest.contains("/kill")) request(fullRequest);
else if (fullRequest.contains("/splash")) request(fullRequest);
else if (fullRequest.contains("/devices")) request(fullRequest);
else if (fullRequest.contains("/reload")) request(fullRequest);
else if (fullRequest.contains("/getoption")) request(fullRequest);
else if (fullRequest.contains("/cursorpos")) request(fullRequest);
else if (fullRequest.contains("/output")) exitStatus = outputRequest(argc, argv);
else if (fullRequest.contains("/setcursor")) exitStatus = setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch")) exitStatus = dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword")) exitStatus = keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper")) exitStatus = hyprpaperRequest(argc, argv);
else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str());
if (fullRequest.contains("/--batch"))
batchRequest(fullRequest);
else if (fullRequest.contains("/monitors"))
request(fullRequest);
else if (fullRequest.contains("/clients"))
request(fullRequest);
else if (fullRequest.contains("/workspaces"))
request(fullRequest);
else if (fullRequest.contains("/activewindow"))
request(fullRequest);
else if (fullRequest.contains("/layers"))
request(fullRequest);
else if (fullRequest.contains("/version"))
request(fullRequest);
else if (fullRequest.contains("/kill"))
request(fullRequest);
else if (fullRequest.contains("/splash"))
request(fullRequest);
else if (fullRequest.contains("/devices"))
request(fullRequest);
else if (fullRequest.contains("/reload"))
request(fullRequest);
else if (fullRequest.contains("/getoption"))
request(fullRequest);
else if (fullRequest.contains("/binds"))
request(fullRequest);
else if (fullRequest.contains("/cursorpos"))
request(fullRequest);
else if (fullRequest.contains("/switchxkblayout"))
request(fullRequest, 2);
else if (fullRequest.contains("/output"))
exitStatus = outputRequest(argc, argv);
else if (fullRequest.contains("/setcursor"))
exitStatus = setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch"))
exitStatus = dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword"))
exitStatus = keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper"))
exitStatus = hyprpaperRequest(argc, argv);
else if (fullRequest.contains("/--help"))
printf("%s", USAGE.c_str());
else {
printf("%s\n", USAGE.c_str());
return 1;

View File

@@ -1,5 +1,5 @@
project('Hyprland', 'cpp', 'c',
version : '0.17.0beta',
version : run_command('jq', '-r', '.version', join_paths(meson.source_root(), 'props.json'), check: true).stdout().strip(),
default_options : [
'warning_level=2',
'default_library=static',
@@ -50,6 +50,16 @@ if not have_xwayland
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
endif
systemd_dep = dependency('libsystemd', required: get_option('systemd'))
if get_option('systemd').enabled()
if systemd_dep.found()
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
else
error('Cannot enable systemd in Hyprland: libsystemd was not found')
endif
endif
if get_option('buildtype') == 'debug'
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
endif

View File

@@ -1 +1,2 @@
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration')

View File

@@ -6,15 +6,18 @@
pkg-config,
meson,
ninja,
cairo,
git,
hyprland-protocols,
jq,
libdrm,
libinput,
libxcb,
libxkbcommon,
mesa,
mount,
pango,
pciutils,
systemd,
wayland,
wayland-protocols,
wayland-scanner,
@@ -26,6 +29,7 @@
hidpiXWayland ? true,
legacyRenderer ? false,
nvidiaPatches ? false,
withSystemd ? true,
version ? "git",
}: let
assertXWayland = lib.assertMsg (hidpiXWayland -> enableXWayland) ''
@@ -48,6 +52,7 @@ in
};
nativeBuildInputs = [
jq
meson
ninja
pkg-config
@@ -61,18 +66,19 @@ in
buildInputs =
[
git
cairo
libdrm
libinput
libxkbcommon
mesa
pango
wayland
wayland-protocols
wayland-scanner
pciutils
(wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;})
]
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland];
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland]
++ lib.optionals withSystemd [systemd];
mesonBuildType =
if debug
@@ -82,6 +88,7 @@ in
mesonFlags = builtins.concatLists [
(lib.optional (!enableXWayland) "-Dxwayland=disabled")
(lib.optional legacyRenderer "-DLEGACY_RENDERER:STRING=true")
(lib.optional withSystemd "-Dsystemd=enabled")
];
patches = [
@@ -89,9 +96,13 @@ in
./meson-build.patch
];
# Fix hardcoded paths to /usr installation
postPatch = ''
# Fix hardcoded paths to /usr installation
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
# for some reason rmdir doesn't work in a dirty tree
rmdir subprojects/hyprland-protocols || true
ln -s ${hyprland-protocols} subprojects/hyprland-protocols
'';
passthru.providedSessions = ["hyprland"];

View File

@@ -5,13 +5,15 @@ self: {
...
}: let
cfg = config.wayland.windowManager.hyprland;
defaultHyprlandPackage = self.packages.${pkgs.system}.default.override {
defaultHyprlandPackage = self.packages.${pkgs.hostPlatform.system}.default.override {
enableXWayland = cfg.xwayland.enable;
hidpiXWayland = cfg.xwayland.hidpi;
nvidiaPatches = cfg.nvidiaPatches;
};
in {
options.wayland.windowManager.hyprland = {
enable = lib.mkEnableOption "hyprland wayland compositor";
package = lib.mkOption {
type = with lib.types; nullOr package;
default = defaultHyprlandPackage;
@@ -26,6 +28,7 @@ in {
be done if you want to use the NixOS module to install Hyprland.
'';
};
systemdIntegration = lib.mkOption {
type = lib.types.bool;
default = pkgs.stdenv.isLinux;
@@ -42,6 +45,18 @@ in {
</itemizedlist>
'';
};
disableAutoreload = lib.mkOption {
type = lib.types.bool;
default = false;
defaultText = lib.literalExpression "false";
example = lib.literalExpression "true";
description = ''
Whether to disable automatically reloading Hyprland's configuration when
rebuilding the Home Manager profile.
'';
};
xwayland = {
enable = lib.mkOption {
type = lib.types.bool;
@@ -59,8 +74,18 @@ in {
};
};
nvidiaPatches = lib.mkOption {
type = lib.types.bool;
default = false;
defaultText = lib.literalExpression "false";
example = lib.liberalExpression "true";
description = ''
Patch wlroots for better Nvidia support.
'';
};
extraConfig = lib.mkOption {
type = lib.types.lines;
type = lib.types.nullOr lib.types.lines;
default = "";
description = ''
Extra configuration lines to add to ~/.config/hypr/hyprland.conf.
@@ -92,14 +117,10 @@ in {
++ lib.optional cfg.xwayland.enable pkgs.xwayland;
home.sessionVariables = lib.mkIf cfg.recommendedEnvironment {
GDK_BACKEND = "wayland,x11";
_JAVA_AWT_WM_NONREPARENTING = "1";
NIXOS_OZONE_WL = "1";
XCURSOR_SIZE = toString config.home.pointerCursor.size or "24";
XDG_SESSION_TYPE = "wayland";
};
xdg.configFile."hypr/hyprland.conf" = {
xdg.configFile."hypr/hyprland.conf" = lib.mkIf (cfg.extraConfig != null) {
text =
(lib.optionalString cfg.systemdIntegration ''
exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && systemctl --user start hyprland-session.target
@@ -111,7 +132,14 @@ in {
if cfg.package == null
then defaultHyprlandPackage
else cfg.package;
in "HYPRLAND_INSTANCE_SIGNATURE=$(ls -w 1 /tmp/hypr | tail -1) ${hyprlandPackage}/bin/hyprctl reload config-only";
in
lib.mkIf (!cfg.disableAutoreload) ''( # execute in subshell so that `shopt` won't affect other scripts
shopt -s nullglob # so that nothing is done if /tmp/hypr/ does not exist or is empty
for instance in /tmp/hypr/*; do
HYPRLAND_INSTANCE_SIGNATURE=''${instance##*/} ${hyprlandPackage}/bin/hyprctl reload config-only \
|| true # ignore dead instance(s)
done
)'';
};
systemd.user.targets.hyprland-session = lib.mkIf cfg.systemdIntegration {

View File

@@ -1,28 +0,0 @@
{ lib, stdenv, fetchFromGitHub }:
stdenv.mkDerivation rec {
pname = "hwdata";
version = "0.363";
src = fetchFromGitHub {
owner = "vcrhonek";
repo = "hwdata";
rev = "v${version}";
sha256 = "sha256-A6GNrHc/t2SVyAyJWmzQTa+pD9wGESsz7DNruW2kH4s=";
};
postPatch = ''
patchShebangs ./configure
'';
configureFlags = [ "--datadir=${placeholder "out"}/share" ];
doCheck = false; # this does build machine-specific checks (e.g. enumerates PCI bus)
meta = {
homepage = "https://github.com/vcrhonek/hwdata";
description = "Hardware Database, including Monitors, pci.ids, usb.ids, and video cards";
license = lib.licenses.gpl2Plus;
platforms = lib.platforms.all;
};
}

View File

@@ -25,12 +25,10 @@ diff --git a/src/meson.build b/src/meson.build
index 5d64188..a676333 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -7,7 +7,7 @@ executable('Hyprland', src,
@@ -7,5 +7,5 @@ executable('Hyprland', src,
server_protos,
dependency('wayland-server'),
dependency('wayland-client'),
- wlroots.get_variable('wlroots'),
+ wlroots,
dependency('cairo'),
dependency('pango'),
dependency('pangocairo'),

View File

@@ -1,5 +1,5 @@
# Copied from https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/programs/sway.nix
self: {
inputs: {
config,
lib,
pkgs,
@@ -7,6 +7,12 @@ self: {
}:
with lib; let
cfg = config.programs.hyprland;
defaultHyprlandPackage = inputs.self.packages.${pkgs.hostPlatform.system}.default.override {
enableXWayland = cfg.xwayland.enable;
hidpiXWayland = cfg.xwayland.hidpi;
nvidiaPatches = cfg.nvidiaPatches;
};
in {
imports = [
(mkRemovedOptionModule ["programs" "hyprland" "extraPackages"] "extraPackages has been removed. Use environment.systemPackages instead.")
@@ -23,7 +29,7 @@ in {
package = mkOption {
type = types.nullOr types.package;
default = self.packages.${pkgs.system}.default;
default = defaultHyprlandPackage;
defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
description = ''
@@ -31,6 +37,32 @@ in {
'';
};
xwayland = {
enable = mkOption {
type = types.bool;
default = true;
description = ''
Enable XWayland.
'';
};
hidpi = mkOption {
type = types.bool;
default = true;
description = ''
Enable HiDPI XWayland.
'';
};
};
nvidiaPatches = mkOption {
type = types.bool;
default = false;
example = liberalExpression "true";
description = ''
Patch wlroots for better Nvidia support.
'';
};
recommendedEnvironment = mkOption {
type = types.bool;
default = true;
@@ -47,11 +79,7 @@ in {
systemPackages = lib.optional (cfg.package != null) cfg.package;
sessionVariables = mkIf cfg.recommendedEnvironment {
GDK_BACKEND = "wayland,x11";
_JAVA_AWT_WM_NONREPARENTING = "1";
NIXOS_OZONE_WL = "1";
XCURSOR_SIZE = "24";
XDG_SESSION_TYPE = "wayland";
};
};
fonts.enableDefaultFonts = mkDefault true;
@@ -64,7 +92,14 @@ in {
services.xserver.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;
xdg.portal = {
enable = mkDefault true;
extraPortals = [pkgs.xdg-desktop-portal-wlr];
# xdg-desktop-portal-hyprland
extraPortals = lib.mkIf (cfg.package != null) [
(inputs.xdph.packages.${pkgs.hostPlatform.system}.xdg-desktop-portal-hyprland.override {
hyprland-share-picker = inputs.xdph.packages.${pkgs.hostPlatform.system}.hyprland-share-picker.override {
hyprland = cfg.package;
};
})
];
};
};
}

View File

@@ -1,7 +1,9 @@
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#moreutils nixpkgs#jq -c bash
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#moreutils nixpkgs#jq nixpkgs#ripgrep -c bash
set -ex
# get wlroots revision from submodule
SUB_REV=$(git submodule status | awk '{ print substr($1,2)}')
SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2)}')
# and from lockfile
CRT_REV=$(jq < flake.lock '.nodes.wlroots.locked.rev' -r)

View File

@@ -42,6 +42,12 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
revert = true;
})
])
++ (lib.optionals nvidiaPatches [
(fetchpatch {
url = "https://aur.archlinux.org/cgit/aur.git/plain/0001-nvidia-format-workaround.patch?h=hyprland-nvidia-screenshare-git";
sha256 = "A9f1p5EW++mGCaNq8w7ZJfeWmvTfUm4iO+1KDcnqYX8=";
})
]);
postPatch =
(old.postPatch or "")

1
props.json Normal file
View File

@@ -0,0 +1 @@
{"version": "0.20.1"}

View File

@@ -3,7 +3,14 @@ wayland_protos = dependency('wayland-protocols',
fallback: 'wayland-protocols',
default_options: ['tests=false'],
)
hyprland_protos = dependency('hyprland-protocols',
version: '>=0.1',
fallback: 'hyprland-protocols',
)
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
wayland_scanner_dep = dependency('wayland-scanner', native: true)
wayland_scanner = find_program(
@@ -14,12 +21,14 @@ wayland_scanner = find_program(
protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
['wlr-foreign-toplevel-management-unstable-v1.xml'],
['wlr-layer-shell-unstable-v1.xml'],
['wlr-output-power-management-unstable-v1.xml'],
['ext-workspace-unstable-v1.xml'],
['pointer-constraints-unstable-v1.xml'],
['tablet-unstable-v2.xml'],
['idle.xml']
['idle.xml'],
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml']
]
wl_protos_src = []
wl_protos_headers = []

View File

@@ -0,0 +1,270 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="wlr_foreign_toplevel_management_unstable_v1">
<copyright>
Copyright © 2018 Ilia Bozhinov
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
</copyright>
<interface name="zwlr_foreign_toplevel_manager_v1" version="3">
<description summary="list and control opened apps">
The purpose of this protocol is to enable the creation of taskbars
and docks by providing them with a list of opened applications and
letting them request certain actions on them, like maximizing, etc.
After a client binds the zwlr_foreign_toplevel_manager_v1, each opened
toplevel window will be sent via the toplevel event
</description>
<event name="toplevel">
<description summary="a toplevel has been created">
This event is emitted whenever a new toplevel window is created. It
is emitted for all toplevels, regardless of the app that has created
them.
All initial details of the toplevel(title, app_id, states, etc.) will
be sent immediately after this event via the corresponding events in
zwlr_foreign_toplevel_handle_v1.
</description>
<arg name="toplevel" type="new_id" interface="zwlr_foreign_toplevel_handle_v1"/>
</event>
<request name="stop">
<description summary="stop sending events">
Indicates the client no longer wishes to receive events for new toplevels.
However the compositor may emit further toplevel_created events, until
the finished event is emitted.
The client must not send any more requests after this one.
</description>
</request>
<event name="finished" type="destructor">
<description summary="the compositor has finished with the toplevel manager">
This event indicates that the compositor is done sending events to the
zwlr_foreign_toplevel_manager_v1. The server will destroy the object
immediately after sending this request, so it will become invalid and
the client should free any resources associated with it.
</description>
</event>
</interface>
<interface name="zwlr_foreign_toplevel_handle_v1" version="3">
<description summary="an opened toplevel">
A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
window. Each app may have multiple opened toplevels.
Each toplevel has a list of outputs it is visible on, conveyed to the
client with the output_enter and output_leave events.
</description>
<event name="title">
<description summary="title change">
This event is emitted whenever the title of the toplevel changes.
</description>
<arg name="title" type="string"/>
</event>
<event name="app_id">
<description summary="app-id change">
This event is emitted whenever the app-id of the toplevel changes.
</description>
<arg name="app_id" type="string"/>
</event>
<event name="output_enter">
<description summary="toplevel entered an output">
This event is emitted whenever the toplevel becomes visible on
the given output. A toplevel may be visible on multiple outputs.
</description>
<arg name="output" type="object" interface="wl_output"/>
</event>
<event name="output_leave">
<description summary="toplevel left an output">
This event is emitted whenever the toplevel stops being visible on
the given output. It is guaranteed that an entered-output event
with the same output has been emitted before this event.
</description>
<arg name="output" type="object" interface="wl_output"/>
</event>
<request name="set_maximized">
<description summary="requests that the toplevel be maximized">
Requests that the toplevel be maximized. If the maximized state actually
changes, this will be indicated by the state event.
</description>
</request>
<request name="unset_maximized">
<description summary="requests that the toplevel be unmaximized">
Requests that the toplevel be unmaximized. If the maximized state actually
changes, this will be indicated by the state event.
</description>
</request>
<request name="set_minimized">
<description summary="requests that the toplevel be minimized">
Requests that the toplevel be minimized. If the minimized state actually
changes, this will be indicated by the state event.
</description>
</request>
<request name="unset_minimized">
<description summary="requests that the toplevel be unminimized">
Requests that the toplevel be unminimized. If the minimized state actually
changes, this will be indicated by the state event.
</description>
</request>
<request name="activate">
<description summary="activate the toplevel">
Request that this toplevel be activated on the given seat.
There is no guarantee the toplevel will be actually activated.
</description>
<arg name="seat" type="object" interface="wl_seat"/>
</request>
<enum name="state">
<description summary="types of states on the toplevel">
The different states that a toplevel can have. These have the same meaning
as the states with the same names defined in xdg-toplevel
</description>
<entry name="maximized" value="0" summary="the toplevel is maximized"/>
<entry name="minimized" value="1" summary="the toplevel is minimized"/>
<entry name="activated" value="2" summary="the toplevel is active"/>
<entry name="fullscreen" value="3" summary="the toplevel is fullscreen" since="2"/>
</enum>
<event name="state">
<description summary="the toplevel state changed">
This event is emitted immediately after the zlw_foreign_toplevel_handle_v1
is created and each time the toplevel state changes, either because of a
compositor action or because of a request in this protocol.
</description>
<arg name="state" type="array"/>
</event>
<event name="done">
<description summary="all information about the toplevel has been sent">
This event is sent after all changes in the toplevel state have been
sent.
This allows changes to the zwlr_foreign_toplevel_handle_v1 properties
to be seen as atomic, even if they happen via multiple events.
</description>
</event>
<request name="close">
<description summary="request that the toplevel be closed">
Send a request to the toplevel to close itself. The compositor would
typically use a shell-specific method to carry out this request, for
example by sending the xdg_toplevel.close event. However, this gives
no guarantees the toplevel will actually be destroyed. If and when
this happens, the zwlr_foreign_toplevel_handle_v1.closed event will
be emitted.
</description>
</request>
<request name="set_rectangle">
<description summary="the rectangle which represents the toplevel">
The rectangle of the surface specified in this request corresponds to
the place where the app using this protocol represents the given toplevel.
It can be used by the compositor as a hint for some operations, e.g
minimizing. The client is however not required to set this, in which
case the compositor is free to decide some default value.
If the client specifies more than one rectangle, only the last one is
considered.
The dimensions are given in surface-local coordinates.
Setting width=height=0 removes the already-set rectangle.
</description>
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</request>
<enum name="error">
<entry name="invalid_rectangle" value="0"
summary="the provided rectangle is invalid"/>
</enum>
<event name="closed">
<description summary="this toplevel has been destroyed">
This event means the toplevel has been destroyed. It is guaranteed there
won't be any more events for this zwlr_foreign_toplevel_handle_v1. The
toplevel itself becomes inert so any requests will be ignored except the
destroy request.
</description>
</event>
<request name="destroy" type="destructor">
<description summary="destroy the zwlr_foreign_toplevel_handle_v1 object">
Destroys the zwlr_foreign_toplevel_handle_v1 object.
This request should be called either when the client does not want to
use the toplevel anymore or after the closed event to finalize the
destruction of the object.
</description>
</request>
<!-- Version 2 additions -->
<request name="set_fullscreen" since="2">
<description summary="request that the toplevel be fullscreened">
Requests that the toplevel be fullscreened on the given output. If the
fullscreen state and/or the outputs the toplevel is visible on actually
change, this will be indicated by the state and output_enter/leave
events.
The output parameter is only a hint to the compositor. Also, if output
is NULL, the compositor should decide which output the toplevel will be
fullscreened on, if at all.
</description>
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
</request>
<request name="unset_fullscreen" since="2">
<description summary="request that the toplevel be unfullscreened">
Requests that the toplevel be unfullscreened. If the fullscreen state
actually changes, this will be indicated by the state event.
</description>
</request>
<!-- Version 3 additions -->
<event name="parent" since="3">
<description summary="parent change">
This event is emitted whenever the parent of the toplevel changes.
No event is emitted when the parent handle is destroyed by the client.
</description>
<arg name="parent" type="object" interface="zwlr_foreign_toplevel_handle_v1" allow-null="true"/>
</event>
</interface>
</protocol>

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,7 @@
#include "managers/KeybindManager.hpp"
#include "managers/AnimationManager.hpp"
#include "managers/EventManager.hpp"
#include "managers/ProtocolManager.hpp"
#include "debug/HyprDebugOverlay.hpp"
#include "helpers/Monitor.hpp"
#include "helpers/Workspace.hpp"
@@ -24,175 +25,177 @@
#include "hyprerror/HyprError.hpp"
class CCompositor {
public:
public:
CCompositor();
~CCompositor();
// ------------------ WLR BASICS ------------------ //
wl_display* m_sWLDisplay;
wl_event_loop* m_sWLEventLoop;
wlr_backend* m_sWLRBackend;
wlr_session* m_sWLRSession;
wlr_renderer* m_sWLRRenderer;
wlr_allocator* m_sWLRAllocator;
wlr_compositor* m_sWLRCompositor;
wlr_subcompositor* m_sWLRSubCompositor;
wlr_data_device_manager* m_sWLRDataDevMgr;
wlr_drm* m_sWRLDRM;
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
wlr_xdg_activation_v1* m_sWLRXDGActivation;
wlr_output_layout* m_sWLROutputLayout;
wlr_idle* m_sWLRIdle;
wlr_layer_shell_v1* m_sWLRLayerShell;
wlr_xdg_shell* m_sWLRXDGShell;
wlr_cursor* m_sWLRCursor;
wlr_xcursor_manager* m_sWLRXCursorMgr;
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
wlr_output_manager_v1* m_sWLROutputMgr;
wlr_presentation* m_sWLRPresentation;
wlr_scene* m_sWLRScene;
wlr_input_inhibit_manager* m_sWLRInhibitMgr;
wl_display* m_sWLDisplay;
wl_event_loop* m_sWLEventLoop;
wlr_backend* m_sWLRBackend;
wlr_session* m_sWLRSession;
wlr_renderer* m_sWLRRenderer;
wlr_allocator* m_sWLRAllocator;
wlr_compositor* m_sWLRCompositor;
wlr_subcompositor* m_sWLRSubCompositor;
wlr_data_device_manager* m_sWLRDataDevMgr;
wlr_drm* m_sWRLDRM;
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
wlr_xdg_activation_v1* m_sWLRXDGActivation;
wlr_output_layout* m_sWLROutputLayout;
wlr_idle* m_sWLRIdle;
wlr_layer_shell_v1* m_sWLRLayerShell;
wlr_xdg_shell* m_sWLRXDGShell;
wlr_cursor* m_sWLRCursor;
wlr_xcursor_manager* m_sWLRXCursorMgr;
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
wlr_output_manager_v1* m_sWLROutputMgr;
wlr_presentation* m_sWLRPresentation;
wlr_scene* m_sWLRScene;
wlr_input_inhibit_manager* m_sWLRInhibitMgr;
wlr_keyboard_shortcuts_inhibit_manager_v1* m_sWLRKbShInhibitMgr;
wlr_egl* m_sWLREGL;
int m_iDRMFD;
wlr_ext_workspace_manager_v1* m_sWLREXTWorkspaceMgr;
wlr_pointer_constraints_v1* m_sWLRPointerConstraints;
wlr_relative_pointer_manager_v1* m_sWLRRelPointerMgr;
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
wlr_output_power_manager_v1* m_sWLROutputPowerMgr;
wlr_input_method_manager_v2* m_sWLRIMEMgr;
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
wlr_xdg_activation_v1* m_sWLRActivation;
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
wlr_backend* m_sWLRHeadlessBackend;
wlr_egl* m_sWLREGL;
int m_iDRMFD;
wlr_ext_workspace_manager_v1* m_sWLREXTWorkspaceMgr;
wlr_pointer_constraints_v1* m_sWLRPointerConstraints;
wlr_relative_pointer_manager_v1* m_sWLRRelPointerMgr;
wlr_server_decoration_manager* m_sWLRServerDecoMgr;
wlr_xdg_decoration_manager_v1* m_sWLRXDGDecoMgr;
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
wlr_output_power_manager_v1* m_sWLROutputPowerMgr;
wlr_input_method_manager_v2* m_sWLRIMEMgr;
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
wlr_xdg_activation_v1* m_sWLRActivation;
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
wlr_backend* m_sWLRHeadlessBackend;
// ------------------------------------------------- //
std::string m_szWLDisplaySocket = "";
std::string m_szInstanceSignature = "";
std::string m_szCurrentSplash = "error";
const char* m_szWLDisplaySocket;
std::string m_szInstanceSignature = "";
std::string m_szCurrentSplash = "error";
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
std::vector<std::unique_ptr<CWindow>> m_vWindows;
std::deque<std::unique_ptr<CWindow>> m_dUnmanagedX11Windows;
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
std::vector<CWindow*> m_vWindowsFadingOut;
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
std::vector<std::unique_ptr<CWindow>> m_vWindows;
std::deque<std::unique_ptr<CWindow>> m_dUnmanagedX11Windows;
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
std::vector<CWindow*> m_vWindowsFadingOut;
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
void startCompositor();
void cleanup();
void startCompositor();
void cleanup();
wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr;
CMonitor* m_pLastMonitor = nullptr;
wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr;
CMonitor* m_pLastMonitor = nullptr;
SSeat m_sSeat;
SSeat m_sSeat;
bool m_bReadyToProcess = false;
bool m_bSessionActive = true;
bool m_bDPMSStateON = true;
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
bool m_bIsShuttingDown = false;
std::deque<uint64_t> m_dProcessPIDsOnShutdown; // stores PIDs of apps to kill later when shutting down
bool m_bReadyToProcess = false;
bool m_bSessionActive = true;
bool m_bDPMSStateON = true;
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
bool m_bIsShuttingDown = false;
std::deque<uint64_t> m_dProcessPIDsOnShutdown; // stores PIDs of apps to kill later when shutting down
// ------------------------------------------------- //
CMonitor* getMonitorFromID(const int&);
CMonitor* getMonitorFromName(const std::string&);
CMonitor* getMonitorFromCursor();
CMonitor* getMonitorFromVector(const Vector2D&);
void removeWindowFromVectorSafe(CWindow*);
void focusWindow(CWindow*, wlr_surface* pSurface = nullptr);
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
bool windowExists(CWindow*);
bool windowValidMapped(CWindow*);
CWindow* vectorToWindow(const Vector2D&);
CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
CWindow* vectorToWindowTiled(const Vector2D&);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
CWindow* windowFromCursor();
CWindow* windowFloatingFromCursor();
CMonitor* getMonitorFromOutput(wlr_output*);
CWindow* getWindowForPopup(wlr_xdg_popup*);
CWindow* getWindowFromSurface(wlr_surface*);
bool isWorkspaceVisible(const int&);
CWorkspace* getWorkspaceByID(const int&);
CWorkspace* getWorkspaceByName(const std::string&);
CWorkspace* getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces();
void updateWorkspaceWindowDecos(const int&);
int getWindowsOnWorkspace(const int&);
CWindow* getFirstWindowOnWorkspace(const int&);
CWindow* getFullscreenWindowOnWorkspace(const int&);
bool doesSeatAcceptInput(wlr_surface*);
bool isWindowActive(CWindow*);
void moveWindowToTop(CWindow*);
void cleanupFadingOut(const int& monid);
CWindow* getWindowInDirection(CWindow*, char);
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false);
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false);
int getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&);
CWindow* getConstraintWindow(SMouse*);
CMonitor* getMonitorInDirection(const char&);
void updateAllWindowsAnimatedDecorationValues();
void updateWindowAnimatedDecorationValues(CWindow*);
int getNextAvailableMonitorID();
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
void swapActiveWorkspaces(CMonitor*, CMonitor*);
CMonitor* getMonitorFromString(const std::string&);
bool workspaceIDOutOfBounds(const int&);
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
void moveUnmanagedX11ToWindows(CWindow*);
CWindow* getX11Parent(CWindow*);
void scheduleFrameForMonitor(CMonitor*);
void addToFadingOutSafe(SLayerSurface*);
void addToFadingOutSafe(CWindow*);
CWindow* getWindowByRegex(const std::string&);
void warpCursorTo(const Vector2D&);
SLayerSurface* getLayerSurfaceFromWlr(wlr_layer_surface_v1*);
SLayerSurface* getLayerSurfaceFromSurface(wlr_surface*);
void closeWindow(CWindow*);
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
void forceReportSizesToWindowsOnWorkspace(const int&);
bool cursorOnReservedArea();
CWorkspace* createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused!
CMonitor* getMonitorFromID(const int&);
CMonitor* getMonitorFromName(const std::string&);
CMonitor* getMonitorFromCursor();
CMonitor* getMonitorFromVector(const Vector2D&);
void removeWindowFromVectorSafe(CWindow*);
void focusWindow(CWindow*, wlr_surface* pSurface = nullptr);
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
bool windowExists(CWindow*);
bool windowValidMapped(CWindow*);
CWindow* vectorToWindow(const Vector2D&);
CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
CWindow* vectorToWindowTiled(const Vector2D&);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
CWindow* windowFromCursor();
CWindow* windowFloatingFromCursor();
CMonitor* getMonitorFromOutput(wlr_output*);
CWindow* getWindowForPopup(wlr_xdg_popup*);
CWindow* getWindowFromSurface(wlr_surface*);
CWindow* getWindowFromHandle(uint32_t);
CWindow* getWindowFromZWLRHandle(wl_resource*);
bool isWorkspaceVisible(const int&);
CWorkspace* getWorkspaceByID(const int&);
CWorkspace* getWorkspaceByName(const std::string&);
CWorkspace* getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces();
void updateWorkspaceWindowDecos(const int&);
int getWindowsOnWorkspace(const int&);
CWindow* getFirstWindowOnWorkspace(const int&);
CWindow* getFullscreenWindowOnWorkspace(const int&);
bool doesSeatAcceptInput(wlr_surface*);
bool isWindowActive(CWindow*);
void moveWindowToTop(CWindow*);
void cleanupFadingOut(const int& monid);
CWindow* getWindowInDirection(CWindow*, char);
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false);
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false);
int getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&);
CWindow* getConstraintWindow(SMouse*);
CMonitor* getMonitorInDirection(const char&);
void updateAllWindowsAnimatedDecorationValues();
void updateWindowAnimatedDecorationValues(CWindow*);
int getNextAvailableMonitorID();
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
void swapActiveWorkspaces(CMonitor*, CMonitor*);
CMonitor* getMonitorFromString(const std::string&);
bool workspaceIDOutOfBounds(const int&);
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
void moveUnmanagedX11ToWindows(CWindow*);
CWindow* getX11Parent(CWindow*);
void scheduleFrameForMonitor(CMonitor*);
void addToFadingOutSafe(SLayerSurface*);
void addToFadingOutSafe(CWindow*);
CWindow* getWindowByRegex(const std::string&);
void warpCursorTo(const Vector2D&);
SLayerSurface* getLayerSurfaceFromWlr(wlr_layer_surface_v1*);
SLayerSurface* getLayerSurfaceFromSurface(wlr_surface*);
void closeWindow(CWindow*);
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
void forceReportSizesToWindowsOnWorkspace(const int&);
bool cursorOnReservedArea();
CWorkspace* createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused!
void setActiveMonitor(CMonitor*);
bool isWorkspaceSpecial(const int&);
int getNewSpecialID();
std::string explicitConfigPath;
std::string explicitConfigPath;
private:
void initAllSignals();
void setRandomSplash();
private:
void initAllSignals();
void setRandomSplash();
uint64_t m_iHyprlandPID = 0;
uint64_t m_iHyprlandPID = 0;
};
inline std::unique_ptr<CCompositor> g_pCompositor;
// For XWayland
inline std::map<std::string, xcb_atom_t> HYPRATOMS = {
HYPRATOM("_NET_WM_WINDOW_TYPE"),
HYPRATOM("_NET_WM_WINDOW_TYPE_NORMAL"),
HYPRATOM("_NET_WM_WINDOW_TYPE_DOCK"),
HYPRATOM("_NET_WM_WINDOW_TYPE_DIALOG"),
HYPRATOM("_NET_WM_WINDOW_TYPE_UTILITY"),
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLBAR"),
HYPRATOM("_NET_WM_WINDOW_TYPE_SPLASH"),
HYPRATOM("_NET_WM_WINDOW_TYPE_MENU"),
HYPRATOM("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"),
HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"),
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"),
HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION")};
inline std::map<std::string, xcb_atom_t> HYPRATOMS = {HYPRATOM("_NET_WM_WINDOW_TYPE"),
HYPRATOM("_NET_WM_WINDOW_TYPE_NORMAL"),
HYPRATOM("_NET_WM_WINDOW_TYPE_DOCK"),
HYPRATOM("_NET_WM_WINDOW_TYPE_DIALOG"),
HYPRATOM("_NET_WM_WINDOW_TYPE_UTILITY"),
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLBAR"),
HYPRATOM("_NET_WM_WINDOW_TYPE_SPLASH"),
HYPRATOM("_NET_WM_WINDOW_TYPE_MENU"),
HYPRATOM("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"),
HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"),
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"),
HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION")};

View File

@@ -5,7 +5,7 @@
CWindow::CWindow() {
m_vRealPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
m_vRealSize.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE);
m_cRealBorderColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
m_fBorderAnimationProgress.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("border"), (void*)this, AVARDAMAGE_BORDER);
m_fAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), (void*)this, AVARDAMAGE_ENTIRE);
m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), (void*)this, AVARDAMAGE_ENTIRE);
m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
@@ -16,13 +16,18 @@ CWindow::CWindow() {
CWindow::~CWindow() {
if (g_pCompositor->isWindowActive(this)) {
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastWindow = nullptr;
}
}
wlr_box CWindow::getFullWindowBoundingBox() {
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
if (m_sAdditionalConfigData.dimAround) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
}
SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 2, *PBORDERSIZE + 2}, {*PBORDERSIZE + 2, *PBORDERSIZE + 2}};
@@ -44,10 +49,8 @@ wlr_box CWindow::getFullWindowBoundingBox() {
}
// Add extents to the real base BB and return
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x,
m_vRealPosition.vec().y - maxExtents.topLeft.y,
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x,
m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
return finalBox;
}
@@ -56,8 +59,15 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
auto POS = m_vPosition;
auto SIZE = m_vSize;
auto POS = m_vPosition;
auto SIZE = m_vSize;
if (m_bIsFullscreen) {
POS = PMONITOR->vecPosition;
SIZE = PMONITOR->vecSize;
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
}
if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) {
POS.y = PMONITOR->vecPosition.y;
@@ -128,25 +138,20 @@ void CWindow::createToplevelHandle() {
wlr_foreign_toplevel_handle_v1_set_fullscreen(m_phForeignToplevel, false);
// handle events
hyprListener_toplevelActivate.initCallback(&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) {
hyprListener_toplevelActivate.initCallback(
&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) { g_pCompositor->focusWindow(this); }, this, "Toplevel");
g_pCompositor->focusWindow(this);
hyprListener_toplevelFullscreen.initCallback(
&m_phForeignToplevel->events.request_fullscreen,
[&](void* owner, void* data) {
const auto EV = (wlr_foreign_toplevel_handle_v1_fullscreen_event*)data;
}, this, "Toplevel");
g_pCompositor->setWindowFullscreen(this, EV->fullscreen, FULLSCREEN_FULL);
},
this, "Toplevel");
hyprListener_toplevelFullscreen.initCallback(&m_phForeignToplevel->events.request_fullscreen, [&](void* owner, void* data) {
const auto EV = (wlr_foreign_toplevel_handle_v1_fullscreen_event*)data;
g_pCompositor->setWindowFullscreen(this, EV->fullscreen, FULLSCREEN_FULL);
}, this, "Toplevel");
hyprListener_toplevelClose.initCallback(&m_phForeignToplevel->events.request_close, [&](void* owner, void* data) {
g_pCompositor->closeWindow(this);
}, this, "Toplevel");
hyprListener_toplevelClose.initCallback(
&m_phForeignToplevel->events.request_close, [&](void* owner, void* data) { g_pCompositor->closeWindow(this); }, this, "Toplevel");
m_iLastToplevelMonitorID = m_iMonitorID;
}
@@ -255,7 +260,7 @@ void CWindow::onUnmap() {
m_vRealPosition.setCallbackOnEnd(unregisterVar);
m_vRealSize.setCallbackOnEnd(unregisterVar);
m_cRealBorderColor.setCallbackOnEnd(unregisterVar);
m_fBorderAnimationProgress.setCallbackOnEnd(unregisterVar);
m_fActiveInactiveAlpha.setCallbackOnEnd(unregisterVar);
m_fAlpha.setCallbackOnEnd(unregisterVar);
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
@@ -265,20 +270,26 @@ void CWindow::onUnmap() {
}
void CWindow::onMap() {
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
m_vRealPosition.resetAllCallbacks();
m_vRealSize.resetAllCallbacks();
m_fBorderAnimationProgress.resetAllCallbacks();
m_fActiveInactiveAlpha.resetAllCallbacks();
m_fAlpha.resetAllCallbacks();
m_cRealShadowColor.resetAllCallbacks();
m_fDimPercent.resetAllCallbacks();
m_vRealPosition.registerVar();
m_vRealSize.registerVar();
m_cRealBorderColor.registerVar();
m_fBorderAnimationProgress.registerVar();
m_fActiveInactiveAlpha.registerVar();
m_fAlpha.registerVar();
m_cRealShadowColor.registerVar();
m_fDimPercent.registerVar();
m_vRealSize.setCallbackOnEnd([&] (void* ptr) {
g_pHyprOpenGL->onWindowResizeEnd(this);
}, false);
m_vRealSize.setCallbackOnBegin([&] (void* ptr) {
g_pHyprOpenGL->onWindowResizeStart(this);
}, false);
m_vRealSize.setCallbackOnEnd([&](void* ptr) { g_pHyprOpenGL->onWindowResizeEnd(this); }, false);
m_vRealSize.setCallbackOnBegin([&](void* ptr) { g_pHyprOpenGL->onWindowResizeStart(this); }, false);
}
void CWindow::setHidden(bool hidden) {
@@ -301,61 +312,69 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
} else if (r.szRule == "noshadow") {
m_sAdditionalConfigData.forceNoShadow = true;
} else if (r.szRule == "opaque") {
m_sAdditionalConfigData.forceOpaque = true;
if (!m_sAdditionalConfigData.forceOpaqueOverriden)
m_sAdditionalConfigData.forceOpaque = true;
} else if (r.szRule.find("rounding") == 0) {
try {
m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
} catch (std::exception& e) {
Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
} catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
} else if (r.szRule.find("opacity") == 0) {
try {
std::string alphaPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
CVarList vars(r.szRule, 0, ' ');
if (alphaPart.contains(' ')) {
// we have a space, 2 values
m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
} else {
m_sSpecialRenderData.alpha = std::stof(alphaPart);
for (size_t i = 1 /* first item is "opacity" */; i < vars.size(); ++i) {
if (i == 1) {
// first arg, alpha
m_sSpecialRenderData.alpha = std::stof(vars[i]);
} else {
if (vars[i] == "override") {
if (i == 2) {
m_sSpecialRenderData.alphaOverride = true;
} else {
m_sSpecialRenderData.alphaInactiveOverride = true;
}
} else {
m_sSpecialRenderData.alphaInactive = std::stof(vars[i]);
}
}
}
} catch(std::exception& e) {
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
} else if (r.szRule == "noanim") {
m_sAdditionalConfigData.forceNoAnims = true;
} else if (r.szRule.find("animation") == 0) {
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
m_sAdditionalConfigData.animationStyle = STYLE;
} else if (r.szRule.find("bordercolor") == 0) {
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
} else if (r.szRule == "noanim") {
m_sAdditionalConfigData.forceNoAnims = true;
} else if (r.szRule.find("animation") == 0) {
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
m_sAdditionalConfigData.animationStyle = STYLE;
} else if (r.szRule.find("bordercolor") == 0) {
try {
std::string colorPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
if (colorPart.contains(' ')) {
// we have a space, 2 values
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart.substr(0, colorPart.find_first_of(' ')));
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart.substr(0, colorPart.find_first_of(' ')));
m_sSpecialRenderData.inactiveBorderColor = configStringToInt(colorPart.substr(colorPart.find_first_of(' ') + 1));
} else {
m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart);
}
} catch(std::exception& e) {
Debug::log(ERR, "BorderColor rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
}
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
} else if (r.szRule == "dimaround") {
m_sAdditionalConfigData.dimAround = true;
}
}
void CWindow::updateDynamicRules() {
m_sSpecialRenderData.activeBorderColor = -1;
m_sSpecialRenderData.activeBorderColor = -1;
m_sSpecialRenderData.inactiveBorderColor = -1;
m_sSpecialRenderData.alpha = 1.f;
m_sSpecialRenderData.alphaInactive = -1.f;
m_sAdditionalConfigData.forceNoBlur = false;
m_sAdditionalConfigData.forceNoBorder = false;
m_sAdditionalConfigData.forceNoShadow = false;
m_sAdditionalConfigData.forceOpaque = false;
m_sAdditionalConfigData.forceNoAnims = false;
m_sSpecialRenderData.alpha = 1.f;
m_sSpecialRenderData.alphaInactive = -1.f;
m_sAdditionalConfigData.forceNoBlur = false;
m_sAdditionalConfigData.forceNoBorder = false;
m_sAdditionalConfigData.forceNoShadow = false;
if (!m_sAdditionalConfigData.forceOpaqueOverriden)
m_sAdditionalConfigData.forceOpaque = false;
m_sAdditionalConfigData.forceNoAnims = false;
m_sAdditionalConfigData.animationStyle = "";
m_sAdditionalConfigData.rounding = -1;
m_sAdditionalConfigData.rounding = -1;
m_sAdditionalConfigData.dimAround = false;
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this);
for (auto& r : WINDOWRULES) {

View File

@@ -6,6 +6,7 @@
#include "helpers/AnimatedVariable.hpp"
#include "render/decorations/IHyprWindowDecoration.hpp"
#include <deque>
#include "config/ConfigDataValues.hpp"
enum eIdleInhibitMode {
IDLEINHIBIT_NONE = 0,
@@ -15,45 +16,50 @@ enum eIdleInhibitMode {
};
struct SWindowSpecialRenderData {
float alpha = 1.f;
float alphaInactive = -1.f; // -1 means unset
bool alphaOverride = false;
float alpha = 1.f;
bool alphaInactiveOverride = false;
float alphaInactive = -1.f; // -1 means unset
int64_t activeBorderColor = -1; // -1 means unset
int64_t activeBorderColor = -1; // -1 means unset
int64_t inactiveBorderColor = -1; // -1 means unset
// set by the layout
bool rounding = true;
bool border = true;
bool border = true;
bool decorate = true;
};
struct SWindowAdditionalConfigData {
std::string animationStyle = "";
int rounding = -1; // -1 means no
bool forceNoBlur = false;
bool forceOpaque = false;
bool forceAllowsInput = false;
bool forceNoAnims = false;
bool forceNoBorder = false;
bool forceNoShadow = false;
bool windowDanceCompat = false;
std::string animationStyle = "";
int rounding = -1; // -1 means no
bool forceNoBlur = false;
bool forceOpaque = false;
bool forceOpaqueOverriden = false; // if true, a rule will not change the forceOpaque state. This is for the force opaque dispatcher.
bool forceAllowsInput = false;
bool forceNoAnims = false;
bool forceNoBorder = false;
bool forceNoShadow = false;
bool windowDanceCompat = false;
bool noMaxSize = false;
bool dimAround = false;
};
struct SWindowRule {
std::string szRule;
std::string szValue;
bool v2 = false;
bool v2 = false;
std::string szTitle;
std::string szClass;
int bX11 = -1; // -1 means "ANY"
int bFloating = -1;
int bFullscreen = -1;
int bPinned = -1;
int bX11 = -1; // -1 means "ANY"
int bFloating = -1;
int bFullscreen = -1;
int bPinned = -1;
};
class CWindow {
public:
public:
CWindow();
~CWindow();
@@ -74,91 +80,98 @@ public:
DYNLISTENER(toplevelClose);
DYNLISTENER(toplevelActivate);
DYNLISTENER(toplevelFullscreen);
// DYNLISTENER(newSubsurfaceWindow);
// DYNLISTENER(newSubsurfaceWindow);
union {
wlr_xdg_surface* xdg;
wlr_xdg_surface* xdg;
wlr_xwayland_surface* xwayland;
} m_uSurface;
// this is the position and size of the "bounding box"
Vector2D m_vPosition = Vector2D(0,0);
Vector2D m_vSize = Vector2D(0,0);
Vector2D m_vPosition = Vector2D(0, 0);
Vector2D m_vSize = Vector2D(0, 0);
// this is the real position and size used to draw the thing
CAnimatedVariable m_vRealPosition;
CAnimatedVariable m_vRealSize;
// for not spamming the protocols
Vector2D m_vReportedPosition;
Vector2D m_vReportedSize;
Vector2D m_vReportedPosition;
Vector2D m_vReportedSize;
// for restoring floating statuses
Vector2D m_vLastFloatingSize;
Vector2D m_vLastFloatingSize;
Vector2D m_vLastFloatingPosition;
// this is used for pseudotiling
bool m_bIsPseudotiled = false;
Vector2D m_vPseudoSize = Vector2D(0,0);
bool m_bIsPseudotiled = false;
Vector2D m_vPseudoSize = Vector2D(0, 0);
uint64_t m_iTags = 0;
bool m_bIsFloating = false;
bool m_bDraggingTiled = false; // for dragging around tiled windows
bool m_bIsFullscreen = false;
uint64_t m_iMonitorID = -1;
std::string m_szTitle = "";
int m_iWorkspaceID = -1;
uint64_t m_iTags = 0;
bool m_bIsFloating = false;
bool m_bDraggingTiled = false; // for dragging around tiled windows
bool m_bIsFullscreen = false;
uint64_t m_iMonitorID = -1;
std::string m_szTitle = "";
int m_iWorkspaceID = -1;
bool m_bIsMapped = false;
bool m_bIsMapped = false;
bool m_bRequestsFloat = false;
bool m_bRequestsFloat = false;
// This is for fullscreen apps
bool m_bCreatedOverFullscreen = false;
bool m_bCreatedOverFullscreen = false;
// XWayland stuff
bool m_bIsX11 = false;
bool m_bMappedX11 = false;
CWindow* m_pX11Parent = nullptr;
uint64_t m_iX11Type = 0;
bool m_bIsModal = false;
bool m_bX11DoesntWantBorders = false;
bool m_bX11ShouldntFocus = false;
bool m_bIsX11 = false;
bool m_bMappedX11 = false;
CWindow* m_pX11Parent = nullptr;
uint64_t m_iX11Type = 0;
bool m_bIsModal = false;
bool m_bX11DoesntWantBorders = false;
bool m_bX11ShouldntFocus = false;
//
// For nofocus
bool m_bNoFocus = false;
bool m_bNoInitialFocus = false;
bool m_bNoFocus = false;
bool m_bNoInitialFocus = false;
// initial fullscreen
bool m_bWantsInitialFullscreen = false;
// initial fullscreen and fullscreen disabled
bool m_bWantsInitialFullscreen = false;
bool m_bNoFullscreenRequest = false;
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
// Animated border
CAnimatedVariable m_cRealBorderColor;
CGradientValueData m_cRealBorderColor = {0};
CGradientValueData m_cRealBorderColorPrevious = {0};
CAnimatedVariable m_fBorderAnimationProgress;
// Fade in-out
CAnimatedVariable m_fAlpha;
bool m_bFadingOut = false;
bool m_bReadyToDelete = false;
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
Vector2D m_vOriginalClosedSize; // drawing the closing animations
bool m_bFadingOut = false;
bool m_bReadyToDelete = false;
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
Vector2D m_vOriginalClosedSize; // drawing the closing animations
// For pinned (sticky) windows
bool m_bPinned = false;
bool m_bPinned = false;
// fakefullscreen
bool m_bFakeFullscreenState = false;
// for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window.
CWindow* m_pLastCycledWindow = nullptr;
CWindow* m_pLastCycledWindow = nullptr;
// Foreign Toplevel proto
wlr_foreign_toplevel_handle_v1* m_phForeignToplevel = nullptr;
// Window decorations
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
// Special render data, rules, etc
SWindowSpecialRenderData m_sSpecialRenderData;
SWindowSpecialRenderData m_sSpecialRenderData;
SWindowAdditionalConfigData m_sAdditionalConfigData;
// for alpha
@@ -171,42 +184,42 @@ public:
CAnimatedVariable m_fDimPercent;
// swallowing
CWindow* m_pSwallowed = nullptr;
CWindow* m_pSwallowed = nullptr;
// for toplevel monitor events
uint64_t m_iLastToplevelMonitorID = -1;
uint64_t m_iLastSurfaceMonitorID = -1;
uint64_t m_iLastToplevelMonitorID = -1;
uint64_t m_iLastSurfaceMonitorID = -1;
// for idle inhibiting windows
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
// For the list lookup
bool operator==(const CWindow& rhs) {
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && m_bFadingOut == rhs.m_bFadingOut;
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
m_bFadingOut == rhs.m_bFadingOut;
}
// methods
wlr_box getFullWindowBoundingBox();
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
void updateWindowDecos();
pid_t getPID();
wlr_box getFullWindowBoundingBox();
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
void updateWindowDecos();
pid_t getPID();
IHyprWindowDecoration* getDecorationByType(eDecorationType);
void removeDecorationByType(eDecorationType);
void createToplevelHandle();
void destroyToplevelHandle();
void updateToplevel();
void updateSurfaceOutputs();
void moveToWorkspace(int);
CWindow* X11TransientFor();
void onUnmap();
void onMap();
void setHidden(bool hidden);
bool isHidden();
void applyDynamicRule(const SWindowRule& r);
void updateDynamicRules();
void removeDecorationByType(eDecorationType);
void createToplevelHandle();
void destroyToplevelHandle();
void updateToplevel();
void updateSurfaceOutputs();
void moveToWorkspace(int);
CWindow* X11TransientFor();
void onUnmap();
void onMap();
void setHidden(bool hidden);
bool isHidden();
void applyDynamicRule(const SWindowRule& r);
void updateDynamicRules();
private:
private:
// For hidden windows and stuff
bool m_bHidden = false;
bool m_bHidden = false;
};

View File

@@ -0,0 +1,50 @@
#pragma once
#include "../defines.hpp"
#include <vector>
enum eConfigValueDataTypes {
CVD_TYPE_INVALID = -1,
CVD_TYPE_GRADIENT = 0
};
interface ICustomConfigValueData {
public:
virtual ~ICustomConfigValueData() = 0;
virtual eConfigValueDataTypes getDataType() = 0;
};
class CGradientValueData : public ICustomConfigValueData {
public:
CGradientValueData(CColor col) {
m_vColors.push_back(col);
};
virtual ~CGradientValueData(){};
virtual eConfigValueDataTypes getDataType() {
return CVD_TYPE_GRADIENT;
}
void reset(CColor col) {
m_vColors.clear();
m_vColors.emplace_back(col);
m_fAngle = 0;
}
/* Vector containing the colors */
std::vector<CColor> m_vColors;
/* Float corresponding to the angle (rad) */
float m_fAngle = 0;
bool operator==(const CGradientValueData& other) {
if (other.m_vColors.size() != m_vColors.size() || m_fAngle != other.m_fAngle)
return false;
for (size_t i = 0; i < m_vColors.size(); ++i)
if (m_vColors[i] != other.m_vColors[i])
return false;
return true;
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -13,73 +13,75 @@
#include "../Window.hpp"
#include "defaultConfig.hpp"
#include "ConfigDataValues.hpp"
#define STRVAL_EMPTY "[[EMPTY]]"
#define INITANIMCFG(name) animationConfig[name] = {}
#define INITANIMCFG(name) animationConfig[name] = {}
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
struct SConfigValue {
int64_t intValue = -INT64_MAX;
float floatValue = -__FLT_MAX__;
std::string strValue = "";
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
int64_t intValue = -INT64_MAX;
float floatValue = -__FLT_MAX__;
std::string strValue = "";
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
std::shared_ptr<ICustomConfigValueData> data;
bool set = false; // used for device configs
bool set = false; // used for device configs
};
struct SMonitorRule {
std::string name = "";
Vector2D resolution = Vector2D(1280,720);
Vector2D offset = Vector2D(0,0);
float scale = 1;
float refreshRate = 60;
std::string defaultWorkspace = "";
bool disabled = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
std::string mirrorOf = "";
bool enable10bit = false;
std::string name = "";
Vector2D resolution = Vector2D(1280, 720);
Vector2D offset = Vector2D(0, 0);
float scale = 1;
float refreshRate = 60;
std::string defaultWorkspace = "";
bool disabled = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
std::string mirrorOf = "";
bool enable10bit = false;
};
struct SMonitorAdditionalReservedArea {
int top = 0;
int bottom = 0;
int left = 0;
int right = 0;
int top = 0;
int bottom = 0;
int left = 0;
int right = 0;
};
struct SAnimationPropertyConfig {
bool overriden = true;
bool overriden = true;
std::string internalBezier = "";
std::string internalStyle = "";
float internalSpeed = 0.f;
int internalEnabled = -1;
std::string internalBezier = "";
std::string internalStyle = "";
float internalSpeed = 0.f;
int internalEnabled = -1;
SAnimationPropertyConfig* pValues = nullptr;
SAnimationPropertyConfig* pValues = nullptr;
SAnimationPropertyConfig* pParentAnimation = nullptr;
};
struct SExecRequestedRule {
std::string szRule = "";
uint64_t iPid = 0;
std::string szRule = "";
uint64_t iPid = 0;
};
class CVarList {
public:
public:
CVarList(const std::string& in, long unsigned int lastArgNo = 0, const char separator = ',') {
std::string curitem = "";
std::string argZ = in;
std::string argZ = in;
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = lastArgNo != 0 && m_vArgs.size() >= lastArgNo - 1 ? std::string::npos : argZ.find_first_of(separator);
if (idx != std::string::npos) {
curitem = argZ.substr(0, idx);
argZ = argZ.substr(idx + 1);
argZ = argZ.substr(idx + 1);
} else {
curitem = argZ;
argZ = STRVAL_EMPTY;
argZ = STRVAL_EMPTY;
}
};
@@ -93,7 +95,7 @@ public:
~CVarList() = default;
int size() const {
size_t size() const {
return m_vArgs.size();
}
@@ -104,121 +106,130 @@ public:
}
// for range-based loops
std::vector<std::string>::iterator begin() { return m_vArgs.begin(); }
std::vector<std::string>::const_iterator begin() const { return m_vArgs.begin(); }
std::vector<std::string>::iterator end() { return m_vArgs.end(); }
std::vector<std::string>::const_iterator end() const { return m_vArgs.end(); }
std::vector<std::string>::iterator begin() {
return m_vArgs.begin();
}
std::vector<std::string>::const_iterator begin() const {
return m_vArgs.begin();
}
std::vector<std::string>::iterator end() {
return m_vArgs.end();
}
std::vector<std::string>::const_iterator end() const {
return m_vArgs.end();
}
private:
std::vector<std::string> m_vArgs;
};
class CConfigManager {
public:
public:
CConfigManager();
void tick();
void init();
void tick();
void init();
int getInt(const std::string&);
float getFloat(const std::string&);
std::string getString(const std::string&);
void setFloat(std::string, float);
void setInt(std::string, int);
void setString(std::string, std::string);
int getInt(const std::string&);
float getFloat(const std::string&);
std::string getString(const std::string&);
void setFloat(const std::string&, float);
void setInt(const std::string&, int);
void setString(const std::string&, const std::string&);
int getDeviceInt(const std::string&, const std::string&);
float getDeviceFloat(const std::string&, const std::string&);
std::string getDeviceString(const std::string&, const std::string&);
bool deviceConfigExists(const std::string&);
bool shouldBlurLS(const std::string&);
int getDeviceInt(const std::string&, const std::string&);
float getDeviceFloat(const std::string&, const std::string&);
std::string getDeviceString(const std::string&, const std::string&);
bool deviceConfigExists(const std::string&);
bool shouldBlurLS(const std::string&);
SConfigValue* getConfigValuePtr(std::string);
SConfigValue* getConfigValuePtrSafe(std::string);
SConfigValue* getConfigValuePtr(const std::string&);
SConfigValue* getConfigValuePtrSafe(const std::string&);
SMonitorRule getMonitorRuleFor(std::string, std::string displayName = "");
SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = "");
CMonitor* getBoundMonitorForWS(std::string);
CMonitor* getBoundMonitorForWS(const std::string&);
std::string getBoundMonitorStringForWS(const std::string&);
std::vector<SWindowRule> getMatchingRules(CWindow*);
std::vector<SWindowRule> getMatchingRules(CWindow*);
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
// no-op when done.
void dispatchExecOnce();
void dispatchExecOnce();
void performMonitorReload();
bool m_bWantsMonitorReload = false;
bool m_bForceReload = false;
bool m_bNoMonitorReload = false;
void ensureDPMS();
void ensureVRR(CMonitor* pMonitor = nullptr);
void performMonitorReload();
bool m_bWantsMonitorReload = false;
bool m_bForceReload = false;
bool m_bNoMonitorReload = false;
void ensureDPMS();
void ensureVRR(CMonitor* pMonitor = nullptr);
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
void addParseError(const std::string&);
void addParseError(const std::string&);
SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&);
void addExecRule(SExecRequestedRule);
void addExecRule(const SExecRequestedRule&);
std::string configCurrentPath;
std::string configCurrentPath;
private:
std::deque<std::string> configPaths; // stores all the config paths
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
std::unordered_map<std::string, std::string> configDynamicVars; // stores dynamic vars declared by the user
std::unordered_map<std::string, SConfigValue> configValues;
private:
std::deque<std::string> configPaths; // stores all the config paths
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
std::unordered_map<std::string, std::string> configDynamicVars; // stores dynamic vars declared by the user
std::unordered_map<std::string, SConfigValue> configValues;
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
std::string currentCategory = ""; // For storing the category of the current item
std::string currentCategory = ""; // For storing the category of the current item
std::string parseError = ""; // For storing a parse error to display later
std::string parseError = ""; // For storing a parse error to display later
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
std::vector<std::pair<std::string, std::string>> boundWorkspaces;
std::vector<std::pair<std::string, std::string>> boundWorkspaces;
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
bool isFirstLaunch = true; // For exec-once
bool isFirstLaunch = true; // For exec-once
std::deque<SMonitorRule> m_dMonitorRules;
std::deque<SWindowRule> m_dWindowRules;
std::deque<std::string> m_dBlurLSNamespaces;
std::deque<SMonitorRule> m_dMonitorRules;
std::deque<SWindowRule> m_dWindowRules;
std::deque<std::string> m_dBlurLSNamespaces;
bool firstExecDispatched = false;
std::deque<std::string> firstExecRequests;
bool firstExecDispatched = false;
std::deque<std::string> firstExecRequests;
// internal methods
void setDefaultVars();
void setDefaultAnimationVars();
void setDeviceDefaultVars(const std::string&);
void setDefaultVars();
void setDefaultAnimationVars();
void setDeviceDefaultVars(const std::string&);
void setAnimForChildren(SAnimationPropertyConfig *const);
void setAnimForChildren(SAnimationPropertyConfig* const);
void applyUserDefinedVars(std::string&, const size_t);
void loadConfigLoadVars();
SConfigValue getConfigValueSafe(const std::string&);
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
void parseLine(std::string&);
void configSetValueSafe(const std::string&, const std::string&);
void handleDeviceConfig(const std::string&, const std::string&);
void handleRawExec(const std::string&, const std::string&);
void handleMonitor(const std::string&, const std::string&);
void handleBind(const std::string&, const std::string&);
void handleUnbind(const std::string&, const std::string&);
void handleWindowRule(const std::string&, const std::string&);
void handleWindowRuleV2(const std::string&, const std::string&);
void handleDefaultWorkspace(const std::string&, const std::string&);
void handleBezier(const std::string&, const std::string&);
void handleAnimation(const std::string&, const std::string&);
void handleSource(const std::string&, const std::string&);
void handleSubmap(const std::string&, const std::string&);
void handleBlurLS(const std::string&, const std::string&);
void handleBindWS(const std::string&, const std::string&);
void applyUserDefinedVars(std::string&, const size_t);
void loadConfigLoadVars();
SConfigValue getConfigValueSafe(const std::string&);
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
void parseLine(std::string&);
void configSetValueSafe(const std::string&, const std::string&);
void handleDeviceConfig(const std::string&, const std::string&);
void handleRawExec(const std::string&, const std::string&);
void handleMonitor(const std::string&, const std::string&);
void handleBind(const std::string&, const std::string&);
void handleUnbind(const std::string&, const std::string&);
void handleWindowRule(const std::string&, const std::string&);
void handleWindowRuleV2(const std::string&, const std::string&);
void handleDefaultWorkspace(const std::string&, const std::string&);
void handleBezier(const std::string&, const std::string&);
void handleAnimation(const std::string&, const std::string&);
void handleSource(const std::string&, const std::string&);
void handleSubmap(const std::string&, const std::string&);
void handleBlurLS(const std::string&, const std::string&);
void handleBindWS(const std::string&, const std::string&);
};
inline std::unique_ptr<CConfigManager> g_pConfigManager;

View File

@@ -17,7 +17,7 @@ OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
autogenerated = 1 # remove this line to remove the warning
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=,preferred,auto,1
monitor=,preferred,auto,auto
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
@@ -51,7 +51,7 @@ general {
gaps_in = 5
gaps_out = 20
border_size = 2
col.active_border = rgba(1affffee)
col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
col.inactive_border = rgba(595959aa)
layout = dwindle

View File

@@ -20,7 +20,7 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
for (auto& m : g_pCompositor->m_vMonitors) {
result += getFormat(
R"#({
R"#({
"id": %i,
"name": "%s",
"description": "%s",
@@ -39,19 +39,11 @@ R"#({
"focused": %s,
"dpmsStatus": %s
},)#",
m->ID,
escapeJSONStrings(m->szName).c_str(),
escapeJSONStrings(m->output->description ? m->output->description : "").c_str(),
(int)m->vecPixelSize.x, (int)m->vecPixelSize.y,
m->refreshRate,
(int)m->vecPosition.x, (int)m->vecPosition.y,
m->activeWorkspace, escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName).c_str(),
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y,
m->scale,
(int)m->transform,
(m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"),
(m->dpmsStatus ? "true" : "false")
);
m->ID, escapeJSONStrings(m->szName).c_str(), escapeJSONStrings(m->output->description ? m->output->description : "").c_str(), (int)m->vecPixelSize.x,
(int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace,
escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName).c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"),
(m->dpmsStatus ? "true" : "false"));
}
// remove trailing comma
@@ -60,18 +52,50 @@ R"#({
result += "]";
} else {
for (auto& m : g_pCompositor->m_vMonitors) {
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tdescription: %s\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tfocused: %s\n\tdpmsStatus: %i\n\n",
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, (m->output->description ? m->output->description : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus);
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tdescription: %s\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: "
"%i\n\tfocused: %s\n\tdpmsStatus: %i\n\n",
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
(m->output->description ? m->output->description : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(),
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale,
(int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus);
}
}
return result;
}
static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
const bool isJson = format == HyprCtl::FORMAT_JSON;
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle")
return isJson ? "" : "0";
SLayoutMessageHeader header;
header.pWindow = w;
const auto groupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
if (groupMembers.empty())
return isJson ? "" : "0";
const auto comma = isJson ? ", " : ",";
const auto fmt = isJson ? "\"0x%x\"" : "%x";
std::ostringstream result;
bool first = true;
for (auto& gw : groupMembers) {
if (first)
first = false;
else
result << comma;
result << getFormat(fmt, gw);
}
return result.str();
}
static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
if (format == HyprCtl::FORMAT_JSON) {
return getFormat(
R"#({
R"#({
"address": "0x%x",
"at": [%i, %i],
"size": [%i, %i],
@@ -87,25 +111,33 @@ R"#({
"xwayland": %s,
"pinned": %s,
"fullscreen": %s,
"fullscreenMode": %i
"fullscreenMode": %i,
"grouped": [%s],
"swallowing": %s
},)#",
w,
(int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y,
w->m_iWorkspaceID, escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))).c_str(),
((int)w->m_bIsFloating == 1 ? "true" : "false"),
w->m_iMonitorID,
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w)).c_str(),
escapeJSONStrings(g_pXWaylandManager->getTitle(w)).c_str(),
w->getPID(),
((int)w->m_bIsX11 == 1 ? "true" : "false"),
(w->m_bPinned ? "true" : "false"),
(w->m_bIsFullscreen ? "true" : "false"),
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0)
);
w, (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, (int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" :
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName :
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)))
.c_str(),
((int)w->m_bIsFloating == 1 ? "true" : "false"), w->m_iMonitorID, escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w)).c_str(),
escapeJSONStrings(g_pXWaylandManager->getTitle(w)).c_str(), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"),
(w->m_bIsFullscreen ? "true" : "false"),
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
getGroupedData(w, format).c_str(), (w->m_pSwallowed ? getFormat("\"0x%x\"", w->m_pSwallowed).c_str() : "null"));
} else {
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\tpinned: %i\n\tfullscreen: %i\n\tfullscreenmode: %i\n\n",
w, w->m_szTitle.c_str(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, (int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w).c_str(), g_pXWaylandManager->getTitle(w).c_str(), w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, (w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0));
return getFormat(
"Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\tpinned: "
"%i\n\tfullscreen: %i\n\tfullscreenmode: %i\n\tgrouped: %s\n\tswallowing: %x\n\n",
w, w->m_szTitle.c_str(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, (int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y,
w->m_iWorkspaceID,
(w->m_iWorkspaceID == -1 ? "" :
g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() :
std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()),
(int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w).c_str(), g_pXWaylandManager->getTitle(w).c_str(), w->getPID(), (int)w->m_bIsX11,
(int)w->m_bPinned, (int)w->m_bIsFullscreen,
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
getGroupedData(w, format).c_str(), w->m_pSwallowed);
}
}
@@ -122,7 +154,7 @@ std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
// remove trailing comma
if (result != "[")
result.pop_back();
result.pop_back();
result += "]";
} else {
@@ -144,7 +176,7 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
const auto PLASTW = w->getLastFocusedWindow();
result += getFormat(
R"#({
R"#({
"id": %i,
"name": "%s",
"monitor": "%s",
@@ -153,14 +185,9 @@ R"#({
"lastwindow": "0x%x",
"lastwindowtitle": "%s"
},)#",
w->m_iID,
escapeJSONStrings(w->m_szName).c_str(),
escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(),
g_pCompositor->getWindowsOnWorkspace(w->m_iID),
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"),
PLASTW,
PLASTW ? escapeJSONStrings(PLASTW->m_szTitle).c_str() : ""
);
w->m_iID, escapeJSONStrings(w->m_szName).c_str(), escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(),
g_pCompositor->getWindowsOnWorkspace(w->m_iID), ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), PLASTW,
PLASTW ? escapeJSONStrings(PLASTW->m_szTitle).c_str() : "");
}
// remove trailing comma
@@ -170,8 +197,9 @@ R"#({
} else {
for (auto& w : g_pCompositor->m_vWorkspaces) {
const auto PLASTW = w->getLastFocusedWindow();
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\tlastwindow: 0x%x\n\tlastwindowtitle: %s\n\n",
w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow, PLASTW, PLASTW ? PLASTW->m_szTitle.c_str() : "");
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\tlastwindow: 0x%x\n\tlastwindowtitle: %s\n\n", w->m_iID,
w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID),
(int)w->m_bHasFullscreenWindow, PLASTW, PLASTW ? PLASTW->m_szTitle.c_str() : "");
}
}
return result;
@@ -199,23 +227,21 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
for (auto& mon : g_pCompositor->m_vMonitors) {
result += getFormat(
R"#("%s": {
R"#("%s": {
"levels": {
)#",
escapeJSONStrings(mon->szName).c_str()
);
escapeJSONStrings(mon->szName).c_str());
int layerLevel = 0;
for (auto& level : mon->m_aLayerSurfaceLists) {
result += getFormat(
R"#(
R"#(
"%i": [
)#",
layerLevel
);
layerLevel);
for (auto& layer : level) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"x": %i,
"y": %i,
@@ -223,13 +249,7 @@ R"#( {
"h": %i,
"namespace": "%s"
},)#",
layer.get(),
layer->geometry.x,
layer->geometry.y,
layer->geometry.width,
layer->geometry.height,
escapeJSONStrings(layer->szNamespace).c_str()
);
layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, escapeJSONStrings(layer->szNamespace).c_str());
}
// remove trailing comma
@@ -262,7 +282,8 @@ R"#( {
result += getFormat("\tLayer level %i:\n", layerLevel);
for (auto& layer : level) {
result += getFormat("\t\tLayer %x: xywh: %i %i %i %i, namespace: %s\n", layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, layer->szNamespace.c_str());
result += getFormat("\t\tLayer %x: xywh: %i %i %i %i, namespace: %s\n", layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width,
layer->geometry.height, layer->szNamespace.c_str());
}
layerLevel++;
@@ -283,15 +304,13 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s",
"defaultSpeed": %f
},)#",
&m,
escapeJSONStrings(m.mouse->name).c_str(),
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f
);
&m, escapeJSONStrings(m.name).c_str(),
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f);
}
// remove trailing comma
@@ -302,7 +321,7 @@ R"#( {
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s",
"rules": "%s",
@@ -313,16 +332,9 @@ R"#( {
"active_keymap": "%s",
"main": %s
},)#",
&k,
escapeJSONStrings(k.keyboard->name).c_str(),
escapeJSONStrings(k.currentRules.rules).c_str(),
escapeJSONStrings(k.currentRules.model).c_str(),
escapeJSONStrings(k.currentRules.layout).c_str(),
escapeJSONStrings(k.currentRules.variant).c_str(),
escapeJSONStrings(k.currentRules.options).c_str(),
escapeJSONStrings(KM).c_str(),
(k.active ? "true" : "false")
);
&k, escapeJSONStrings(k.name).c_str(), escapeJSONStrings(k.currentRules.rules).c_str(), escapeJSONStrings(k.currentRules.model).c_str(),
escapeJSONStrings(k.currentRules.layout).c_str(), escapeJSONStrings(k.currentRules.variant).c_str(), escapeJSONStrings(k.currentRules.options).c_str(),
escapeJSONStrings(KM).c_str(), (k.active ? "true" : "false"));
}
// remove trailing comma
@@ -333,7 +345,7 @@ R"#( {
for (auto& d : g_pInputManager->m_lTabletPads) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"type": "tabletPad",
"belongsTo": {
@@ -341,33 +353,26 @@ R"#( {
"name": "%s"
}
},)#",
&d,
d.pTabletParent,
escapeJSONStrings(d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "").c_str()
);
&d, d.pTabletParent, escapeJSONStrings(d.pTabletParent ? d.pTabletParent->name : "").c_str());
}
for (auto& d : g_pInputManager->m_lTablets) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
escapeJSONStrings(d.wlrDevice ? d.wlrDevice->name : "").c_str()
);
&d, escapeJSONStrings(d.name).c_str());
}
for (auto& d : g_pInputManager->m_lTabletTools) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"type": "tabletTool",
"belongsTo": "0x%x"
},)#",
&d,
d.wlrTabletTool ? d.wlrTabletTool->data : 0
);
&d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
}
// remove trailing comma
@@ -378,13 +383,11 @@ R"#( {
for (auto& d : g_pInputManager->m_lTouchDevices) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
d.pWlrDevice ? d.pWlrDevice->name : ""
);
&d, d.name.c_str());
}
// remove trailing comma
@@ -396,13 +399,11 @@ R"#( {
for (auto& d : g_pInputManager->m_lSwitches) {
result += getFormat(
R"#( {
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
d.pWlrDevice ? d.pWlrDevice->name : ""
);
&d, d.pWlrDevice ? d.pWlrDevice->name : "");
}
// remove trailing comma
@@ -416,24 +417,28 @@ R"#( {
result += "mice:\n";
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat("\tMouse at %x:\n\t\t%s\n\t\t\tdefault speed: %f\n", &m, m.mouse->name, (wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f));
result += getFormat(
"\tMouse at %x:\n\t\t%s\n\t\t\tdefault speed: %f\n", &m, m.name.c_str(),
(wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f));
}
result += "\n\nKeyboards:\n";
for (auto& k : g_pInputManager->m_lKeyboards) {
const auto KM = g_pInputManager->getActiveLayoutForKeyboard(&k);
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n\t\t\tmain: %s\n", &k, k.keyboard->name, k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(), k.currentRules.options.c_str(), KM.c_str(), (k.active ? "yes" : "no"));
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n\t\t\tmain: %s\n", &k,
k.name.c_str(), k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(),
k.currentRules.options.c_str(), KM.c_str(), (k.active ? "yes" : "no"));
}
result += "\n\nTablets:\n";
for (auto& d : g_pInputManager->m_lTabletPads) {
result += getFormat("\tTablet Pad at %x (belongs to %x -> %s)\n", &d, d.pTabletParent, d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "");
result += getFormat("\tTablet Pad at %x (belongs to %x -> %s)\n", &d, d.pTabletParent, d.pTabletParent ? d.pTabletParent->name.c_str() : "");
}
for (auto& d : g_pInputManager->m_lTablets) {
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.name.c_str());
}
for (auto& d : g_pInputManager->m_lTabletTools) {
@@ -443,7 +448,7 @@ R"#( {
result += "\n\nTouch:\n";
for (auto& d : g_pInputManager->m_lTouchDevices) {
result += getFormat("\tTouch Device at %x:\n\t\t%s\n", &d, d.pWlrDevice ? d.pWlrDevice->name : "");
result += getFormat("\tTouch Device at %x:\n\t\t%s\n", &d, d.name.c_str());
}
result += "\n\nSwitches:\n";
@@ -456,10 +461,56 @@ R"#( {
return result;
}
std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string ret = "";
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
ret += "bind";
if (kb.locked)
ret += "l";
if (kb.mouse)
ret += "m";
if (kb.release)
ret += "r";
if (kb.repeat)
ret += "e";
ret += getFormat("\n\tmodmask: %u\n\tsubmap: %s\n\tkey: %s\n\tkeycode: %d\n\tdispatcher: %s\n\targ: %s\n\n", kb.modmask, kb.submap.c_str(), kb.key.c_str(), kb.keycode,
kb.handler.c_str(), kb.arg.c_str());
}
} else {
// json
ret += "[";
for (auto& kb : g_pKeybindManager->m_lKeybinds) {
ret += getFormat(
R"#(
{
"locked": %s,
"mouse": %s,
"release": %s,
"repeat": %s,
"modmask": %u,
"submap": "%s",
"key": "%s",
"keycode": %i,
"dispatcher": "%s",
"arg": "%s"
},)#",
kb.locked ? "true" : "false", kb.mouse ? "true" : "false", kb.release ? "true" : "false", kb.repeat ? "true" : "false", kb.modmask, kb.submap.c_str(),
kb.key.c_str(), kb.keycode, kb.handler.c_str(), kb.arg.c_str());
}
ret.pop_back();
ret += "]";
}
return ret;
}
std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str() + ").\nflags: (if any)\n";
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" +
removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str() + ").\nflags: (if any)\n";
#ifdef LEGACY_RENDERER
result += "legacyrenderer\n";
@@ -468,7 +519,7 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
result += "debug\n";
#endif
#ifdef HYPRLAND_DEBUG
result += "debug\n";
result += "debug\n";
#endif
#ifdef NO_XWAYLAND
result += "no xwayland\n";
@@ -477,12 +528,13 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
return result;
} else {
std::string result = getFormat(
R"#({
R"#({
"branch": "%s",
"commit": "%s",
"dirty": %s,
"commit_message": "%s",
"flags": [)#", GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str());
"flags": [)#",
GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str());
#ifdef LEGACY_RENDERER
result += "\"legacyrenderer\",";
@@ -491,7 +543,7 @@ R"#({
result += "\"debug\",";
#endif
#ifdef HYPRLAND_DEBUG
result += "\"debug\",";
result += "\"debug\",";
#endif
#ifdef NO_XWAYLAND
result += "\"no xwayland\",";
@@ -531,9 +583,9 @@ std::string dispatchKeyword(std::string in) {
// get rid of the keyword keyword
in = in.substr(in.find_first_of(' ') + 1);
const auto COMMAND = in.substr(0, in.find_first_of(' '));
const auto COMMAND = in.substr(0, in.find_first_of(' '));
const auto VALUE = in.substr(in.find_first_of(' ') + 1);
const auto VALUE = in.substr(in.find_first_of(' ') + 1);
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE, true);
@@ -541,13 +593,23 @@ std::string dispatchKeyword(std::string in) {
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
if (COMMAND.contains("input") || COMMAND.contains("device:")) {
g_pInputManager->setKeyboardLayout(); // update kb layout
g_pInputManager->setPointerConfigs(); // update mouse cfgs
g_pInputManager->setKeyboardLayout(); // update kb layout
g_pInputManager->setPointerConfigs(); // update mouse cfgs
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
g_pInputManager->setTabletConfigs(); // update tablets
}
if (COMMAND.contains("general:layout"))
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
if (COMMAND.contains("decoration:screen_shader"))
g_pHyprOpenGL->m_bReloadScreenShader = true;
if (COMMAND.contains("blur")) {
for (auto& [m, rd] : g_pHyprOpenGL->m_mMonitorRenderResources) {
rd.blurFBDirty = true;
}
}
Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str());
@@ -557,7 +619,7 @@ std::string dispatchKeyword(std::string in) {
return retval;
}
std::string reloadRequest(std::string request) {
std::string reloadRequest(const std::string& request) {
const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
@@ -593,7 +655,8 @@ std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
"x": %i,
"y": %i
}
)#", (int)CURSORPOS.x, (int)CURSORPOS.y);
)#",
(int)CURSORPOS.x, (int)CURSORPOS.y);
}
return "error";
@@ -604,11 +667,11 @@ std::string getReply(std::string);
std::string dispatchBatch(std::string request) {
// split by ;
request = request.substr(9);
request = request.substr(9);
std::string curitem = "";
std::string reply = "";
std::string reply = "";
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = request.find_first_of(';');
if (idx != std::string::npos) {
@@ -636,7 +699,7 @@ std::string dispatchBatch(std::string request) {
std::string dispatchSetCursor(std::string request) {
std::string curitem = "";
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = request.find_first_of(' ');
if (idx != std::string::npos) {
@@ -683,10 +746,56 @@ std::string dispatchSetCursor(std::string request) {
return "ok";
}
std::string switchXKBLayoutRequest(const std::string& request) {
CVarList vars(request, 0, ' ');
const auto KB = vars[1];
const auto CMD = vars[2];
// get kb
const auto PKEYBOARD = std::find_if(g_pInputManager->m_lKeyboards.begin(), g_pInputManager->m_lKeyboards.end(),
[&](const SKeyboard& other) { return other.name == g_pInputManager->deviceNameToInternalString(KB); });
if (PKEYBOARD == g_pInputManager->m_lKeyboards.end())
return "device not found";
const auto PWLRKEYBOARD = wlr_keyboard_from_input_device(PKEYBOARD->keyboard);
const auto LAYOUTS = xkb_keymap_num_layouts(PWLRKEYBOARD->keymap);
xkb_layout_index_t activeLayout = 0;
while (activeLayout < LAYOUTS) {
if (xkb_state_layout_index_is_active(PWLRKEYBOARD->xkb_state, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE))
break;
activeLayout++;
}
if (CMD == "next") {
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked,
activeLayout > LAYOUTS ? 0 : activeLayout + 1);
} else if (CMD == "prev") {
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked,
activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1);
} else {
int requestedLayout = 0;
try {
requestedLayout = std::stoi(CMD);
} catch (std::exception& e) { return "invalid arg 2"; }
if (requestedLayout < 0 || (uint64_t)requestedLayout > LAYOUTS - 1) {
return "layout idx out of range of " + std::to_string(LAYOUTS);
}
wlr_keyboard_notify_modifiers(PWLRKEYBOARD, PWLRKEYBOARD->modifiers.depressed, PWLRKEYBOARD->modifiers.latched, PWLRKEYBOARD->modifiers.locked, requestedLayout);
}
return "ok";
}
std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
std::string curitem = "";
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = request.find_first_of(' ');
if (idx != std::string::npos) {
@@ -709,18 +818,20 @@ std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat
return "no such option";
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL)
return getFormat("option %s\n\tint: %lld\n\tfloat: %f\n\tstr: \"%s\"", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str());
return getFormat("option %s\n\tint: %lld\n\tfloat: %f\n\tstr: \"%s\"\n\tdata: %x", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str(),
PCFGOPT->data.get());
else {
return getFormat(
R"#(
R"#(
{
"option": "%s",
"int": %lld,
"float": %f,
"str": "%s"
"str": "%s",
"data": "0x%x"
}
)#", curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str()
);
)#",
curitem.c_str(), PCFGOPT->intValue, PCFGOPT->floatValue, PCFGOPT->strValue.c_str(), PCFGOPT->data.get());
}
}
@@ -758,7 +869,7 @@ void createOutputIter(wlr_backend* backend, void* data) {
std::string dispatchOutput(std::string request) {
std::string curitem = "";
auto nextItem = [&]() {
auto nextItem = [&]() {
auto idx = request.find_first_of(' ');
if (idx != std::string::npos) {
@@ -782,7 +893,7 @@ std::string dispatchOutput(std::string request) {
const auto NAME = curitem;
if (MODE == "create" || MODE == "add") {
std::pair<std::string, bool> result = { NAME, false };
std::pair<std::string, bool> result = {NAME, false};
wlr_multi_for_each_backend(g_pCompositor->m_sWLRBackend, createOutputIter, &result);
@@ -847,6 +958,10 @@ std::string getReply(std::string request) {
return splashRequest();
else if (request == "cursorpos")
return cursorPosRequest(format);
else if (request == "binds")
return bindsRequest(format);
else if (request.find("switchxkblayout") == 0)
return switchXKBLayoutRequest(request);
else if (request.find("output") == 0)
return dispatchOutput(request);
else if (request.find("dispatch") == 0)
@@ -868,13 +983,13 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
return 0;
sockaddr_in clientAddress;
socklen_t clientSize = sizeof(clientAddress);
socklen_t clientSize = sizeof(clientAddress);
const auto ACCEPTEDCONNECTION = accept(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize);
const auto ACCEPTEDCONNECTION = accept(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize);
char readBuffer[1024];
char readBuffer[1024];
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
std::string request(readBuffer);
@@ -914,7 +1029,10 @@ void HyprCtl::startHyprCtlSocket() {
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
if (bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS)) < 0) {
Debug::log(ERR, "Couldn't start the Hyprland Socket. (2) IPC will not work.");
return;
}
// 10 max queued.
listen(iSocketFD, 10);

View File

@@ -5,20 +5,21 @@
#include "../helpers/MiscFunctions.hpp"
namespace HyprCtl {
void startHyprCtlSocket();
void startHyprCtlSocket();
// very simple thread-safe request method
inline bool requestMade = false;
inline bool requestReady = false;
inline std::string request = "";
inline bool requestMade = false;
inline bool requestReady = false;
inline std::string request = "";
inline std::ifstream requestStream;
inline std::ifstream requestStream;
inline wl_event_source* hyprCtlTickSource = nullptr;
inline int iSocketFD = -1;
inline int iSocketFD = -1;
enum eHyprCtlOutputFormat {
enum eHyprCtlOutputFormat
{
FORMAT_NORMAL = 0,
FORMAT_JSON
};

View File

@@ -38,10 +38,10 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
if (!m_pMonitor)
return 0;
int yOffset = offset;
int yOffset = offset;
cairo_text_extents_t cairoExtents;
float maxX = 0;
std::string text = "";
float maxX = 0;
std::string text = "";
// get avg fps
float avgFrametime = 0;
@@ -62,7 +62,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
}
avgRenderTimeNoOverlay /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
const float idealFPS = m_dLastFrametimes.size();
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
@@ -75,7 +75,8 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
text = m_pMonitor->szName;
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
@@ -91,7 +92,8 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
text = std::string(std::to_string((int)FPS) + " FPS");
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
@@ -101,26 +103,30 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
text = std::string("Avg Frametime: " + std::to_string((int)avgFrametime) + "." + std::to_string((int)(avgFrametime * 10.f) % 10) + "ms");
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string("Avg Rendertime: " + std::to_string((int)avgRenderTime) + "." + std::to_string((int)(avgRenderTime * 10.f) % 10) + "ms");
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::string("Avg Rendertime (no overlay): " + std::to_string((int)avgRenderTimeNoOverlay) + "." + std::to_string((int)(avgRenderTimeNoOverlay * 10.f) % 10) + "ms");
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX) maxX = cairoExtents.width;
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
yOffset += 11;
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2, yOffset - offset + 2};
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2,
yOffset - offset + 2};
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
return yOffset - offset;
@@ -144,7 +150,7 @@ void CHyprDebugOverlay::draw() {
if (!m_pCairoSurface || !m_pCairo) {
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
m_pCairo = cairo_create(m_pCairoSurface);
m_pCairo = cairo_create(m_pCairoSurface);
}
// clear the pixmap
@@ -176,6 +182,6 @@ void CHyprDebugOverlay::draw() {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecSize.x, PMONITOR->vecSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
wlr_box pMonBox = {0,0,PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 255.f);
wlr_box pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
}

View File

@@ -8,38 +8,36 @@
#include <unordered_map>
class CHyprMonitorDebugOverlay {
public:
int draw(int offset);
public:
int draw(int offset);
void renderData(CMonitor* pMonitor, float µs);
void renderDataNoOverlay(CMonitor* pMonitor, float µs);
void frameData(CMonitor* pMonitor);
private:
std::deque<float> m_dLastFrametimes;
std::deque<float> m_dLastRenderTimes;
std::deque<float> m_dLastRenderTimesNoOverlay;
private:
std::deque<float> m_dLastFrametimes;
std::deque<float> m_dLastRenderTimes;
std::deque<float> m_dLastRenderTimesNoOverlay;
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
CMonitor* m_pMonitor = nullptr;
wlr_box m_wbLastDrawnBox;
CMonitor* m_pMonitor = nullptr;
wlr_box m_wbLastDrawnBox;
};
class CHyprDebugOverlay {
public:
public:
void draw();
void renderData(CMonitor*, float µs);
void renderDataNoOverlay(CMonitor*, float µs);
void frameData(CMonitor*);
private:
private:
std::unordered_map<CMonitor*, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
cairo_surface_t* m_pCairoSurface = nullptr;
cairo_t* m_pCairo = nullptr;
cairo_surface_t* m_pCairoSurface = nullptr;
cairo_t* m_pCairo = nullptr;
CTexture m_tTexture;
CTexture m_tTexture;
friend class CHyprMonitorDebugOverlay;
};

View File

@@ -5,12 +5,12 @@
#include <fstream>
#include <iostream>
void Debug::init(std::string IS) {
void Debug::init(const std::string& IS) {
logFile = "/tmp/hypr/" + IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
}
void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
char* outputStr = nullptr;
char* outputStr = nullptr;
std::ofstream ofs;
ofs.open(logFile, std::ios::out | std::ios::app);
@@ -35,28 +35,17 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
ofs.open(logFile, std::ios::out | std::ios::app);
switch (level) {
case LOG:
ofs << "[LOG] ";
break;
case WARN:
ofs << "[WARN] ";
break;
case ERR:
ofs << "[ERR] ";
break;
case CRIT:
ofs << "[CRITICAL] ";
break;
case INFO:
ofs << "[INFO] ";
break;
default:
break;
case LOG: ofs << "[LOG] "; break;
case WARN: ofs << "[WARN] "; break;
case ERR: ofs << "[ERR] "; break;
case CRIT: ofs << "[CRITICAL] "; break;
case INFO: ofs << "[INFO] "; break;
default: break;
}
// print date and time to the ofs
if (disableTime && !*disableTime) {
auto timet = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
auto timet = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
const auto MILLIS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() % 1000;
ofs << std::put_time(std::localtime(&timet), "[%H:%M:%S:");
@@ -71,7 +60,7 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
ofs << "] ";
}
char* outputStr = nullptr;
char* outputStr = nullptr;
va_list args;
va_start(args, fmt);

View File

@@ -4,9 +4,10 @@
#define LOGMESSAGESIZE 1024
enum LogLevel {
enum LogLevel
{
NONE = -1,
LOG = 0,
LOG = 0,
WARN,
ERR,
CRIT,
@@ -14,11 +15,11 @@ enum LogLevel {
};
namespace Debug {
void init(std::string IS);
void log(LogLevel level, const char* fmt, ...);
void wlrLog(wlr_log_importance level, const char* fmt, va_list args);
void init(const std::string& IS);
void log(LogLevel level, const char* fmt, ...);
void wlrLog(wlr_log_importance level, const char* fmt, va_list args);
inline std::string logFile;
inline int64_t* disableLogs = nullptr;
inline int64_t* disableTime = nullptr;
inline int64_t* disableLogs = nullptr;
inline int64_t* disableTime = nullptr;
};

View File

@@ -18,37 +18,44 @@
#define ISDEBUG false
#endif
#define LISTENER(name) void listener_##name(wl_listener*, void*); inline wl_listener listen_##name = { .notify = listener_##name };
#define DYNLISTENFUNC(name) void listener_##name(void*, void*);
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name;
#define DYNMULTILISTENER(name) wl_listener listen_##name;
#define LISTENER(name) \
void listener_##name(wl_listener*, void*); \
inline wl_listener listen_##name = {.notify = listener_##name}
#define DYNLISTENFUNC(name) void listener_##name(void*, void*)
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name
#define DYNMULTILISTENER(name) wl_listener listen_##name
#define VECINRECT(vec, x1, y1, x2, y2) (vec.x >= (x1) && vec.x <= (x2) && vec.y >= (y1) && vec.y <= (y2))
#define VECINRECT(vec, x1, y1, x2, y2) ((vec).x >= (x1) && (vec).x <= (x2) && (vec).y >= (y1) && (vec).y <= (y2))
#define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < delta)
#define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < (delta))
#define PIXMAN_DAMAGE_FOREACH(region) int rectsNum = 0; \
const auto RECTSARR = pixman_region32_rectangles(region, &rectsNum); \
#define PIXMAN_DAMAGE_FOREACH(region) \
int rectsNum = 0; \
const auto RECTSARR = pixman_region32_rectangles(region, &rectsNum); \
for (int i = 0; i < rectsNum; ++i)
#define PIXMAN_REGION_FOREACH(region) PIXMAN_DAMAGE_FOREACH(region)
#define interface class
#define STICKS(a, b) abs((a) - (b)) < 2
#define ALPHA(c) ((double)(((c) >> 24) & 0xff) / 255.0)
#define RED(c) ((double)(((c) >> 16) & 0xff) / 255.0)
#define RED(c) ((double)(((c) >> 16) & 0xff) / 255.0)
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
#define HYPRATOM(name) {name, 0}
#define HYPRATOM(name) \
{ name, 0 }
#ifndef __INTELLISENSE__
#define RASSERT(expr, reason, ...) \
if (!(expr)) { \
Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", getFormat(reason, ##__VA_ARGS__).c_str(), __LINE__, ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \
printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
*((int*)nullptr) = 1; /* so that we crash and get a coredump */ \
#define RASSERT(expr, reason, ...) \
if (!(expr)) { \
Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", \
getFormat(reason, ##__VA_ARGS__).c_str(), __LINE__, \
([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \
printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
*((int*)nullptr) = 1; /* so that we crash and get a coredump */ \
}
#else
#define RASSERT(expr, reason, ...)
@@ -57,7 +64,11 @@
#define ASSERT(expr) RASSERT(expr, "?")
#if ISDEBUG
#define UNREACHABLE() { Debug::log(CRIT, "\n\nMEMORY CORRUPTED: Unreachable failed! (Reached an unreachable position, memory corruption!!!)"); *((int*)nullptr) = 1; }
#define UNREACHABLE() \
{ \
Debug::log(CRIT, "\n\nMEMORY CORRUPTED: Unreachable failed! (Reached an unreachable position, memory corruption!!!)"); \
*((int*)nullptr) = 1; \
}
#else
#define UNREACHABLE() std::unreachable();
#endif
@@ -76,4 +87,6 @@
#define GIT_DIRTY "?"
#endif
#define SPECIAL_WORKSPACE_ID -99
#define SPECIAL_WORKSPACE_START (-99)
#define PI 3.14159265358979

View File

@@ -61,7 +61,7 @@ void Events::listener_requestMouse(wl_listener* listener, void* data) {
void Events::listener_newInput(wl_listener* listener, void* data) {
const auto DEVICE = (wlr_input_device*)data;
switch(DEVICE->type) {
switch (DEVICE->type) {
case WLR_INPUT_DEVICE_KEYBOARD:
Debug::log(LOG, "Attached a keyboard with name %s", DEVICE->name);
g_pInputManager->newKeyboard(DEVICE);
@@ -86,12 +86,10 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
Debug::log(LOG, "Attached a switch device with name %s", DEVICE->name);
g_pInputManager->newSwitch(DEVICE);
break;
default:
Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name);
break;
default: Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name); break;
}
g_pInputManager->updateCapabilities(DEVICE);
g_pInputManager->updateCapabilities();
}
void Events::listener_newConstraint(wl_listener* listener, void* data) {
@@ -102,7 +100,7 @@ void Events::listener_newConstraint(wl_listener* listener, void* data) {
g_pInputManager->m_lConstraints.emplace_back();
const auto CONSTRAINT = &g_pInputManager->m_lConstraints.back();
CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
CONSTRAINT->pMouse = g_pCompositor->m_sSeat.mouse;
CONSTRAINT->constraint = PCONSTRAINT;
CONSTRAINT->hyprListener_destroyConstraint.initCallback(&PCONSTRAINT->events.destroy, &Events::listener_destroyConstraint, CONSTRAINT, "Constraint");
@@ -110,6 +108,11 @@ void Events::listener_newConstraint(wl_listener* listener, void* data) {
if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) {
g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT);
if (!CONSTRAINT->hintSet) {
const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
CONSTRAINT->positionHint = g_pInputManager->getMouseCoordsInternal() - PWINDOW->m_vRealPosition.goalv();
}
}
}
@@ -123,15 +126,15 @@ void Events::listener_destroyConstraint(void* owner, void* data) {
if (PWINDOW) {
if (PWINDOW->m_bIsX11) {
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
PCONSTRAINT->constraint->current.cursor_hint.x + PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y + PCONSTRAINT->constraint->current.cursor_hint.y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PCONSTRAINT->positionHint.x + PWINDOW->m_uSurface.xwayland->x,
PWINDOW->m_uSurface.xwayland->y + PCONSTRAINT->positionHint.y);
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->constraint->current.cursor_hint.x, PCONSTRAINT->constraint->current.cursor_hint.y);
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y);
} else {
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
PCONSTRAINT->constraint->current.cursor_hint.x + PWINDOW->m_vRealPosition.vec().x, PCONSTRAINT->constraint->current.cursor_hint.y + PWINDOW->m_vRealPosition.vec().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PCONSTRAINT->positionHint.x + PWINDOW->m_vRealPosition.vec().x,
PCONSTRAINT->positionHint.y + PWINDOW->m_vRealPosition.vec().y);
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->constraint->current.cursor_hint.x, PCONSTRAINT->constraint->current.cursor_hint.y);
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y);
}
}
@@ -148,9 +151,9 @@ void Events::listener_setConstraintRegion(void* owner, void* data) {
}
void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
const auto EV = (wlr_virtual_pointer_v1_new_pointer_event*)data;
const auto EV = (wlr_virtual_pointer_v1_new_pointer_event*)data;
const auto POINTER = EV->new_pointer;
const auto DEVICE = &POINTER->pointer.base;
const auto DEVICE = &POINTER->pointer.base;
g_pInputManager->newMouse(DEVICE, true);
}

View File

@@ -31,7 +31,7 @@ namespace Events {
DYNLISTENFUNC(commitSubsurface);
// Popups
DYNLISTENFUNC(newPopup); // LayerSurface
DYNLISTENFUNC(newPopup); // LayerSurface
DYNLISTENFUNC(newPopupXDG);
DYNLISTENFUNC(mapPopupXDG);
@@ -60,7 +60,7 @@ namespace Events {
DYNLISTENFUNC(requestMaximize);
// Window subsurfaces
// LISTENER(newSubsurfaceWindow);
// LISTENER(newSubsurfaceWindow);
// Input events
LISTENER(mouseMove);
@@ -96,6 +96,7 @@ namespace Events {
// Monitor part 2 the sequel
DYNLISTENFUNC(monitorFrame);
DYNLISTENFUNC(monitorDestroy);
DYNLISTENFUNC(monitorStateRequest);
// XWayland
LISTENER(readyXWayland);

View File

@@ -34,7 +34,7 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
auto PMONITOR = (CMonitor*)g_pCompositor->getMonitorFromOutput(WLRLAYERSURFACE->output);
if (!WLRLAYERSURFACE->output || !PMONITOR || PMONITOR->pMirrorOf) {
PMONITOR = g_pCompositor->m_vMonitors.front().get();
PMONITOR = g_pCompositor->m_vMonitors.front().get();
WLRLAYERSURFACE->output = PMONITOR->output; // TODO: current mon
}
@@ -49,13 +49,14 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
layerSurface->layerSurface = WLRLAYERSURFACE;
layerSurface->layer = WLRLAYERSURFACE->current.layer;
WLRLAYERSURFACE->data = layerSurface;
layerSurface->monitorID = PMONITOR->ID;
layerSurface->layer = WLRLAYERSURFACE->current.layer;
WLRLAYERSURFACE->data = layerSurface;
layerSurface->monitorID = PMONITOR->ID;
layerSurface->forceBlur = g_pConfigManager->shouldBlurLS(layerSurface->szNamespace);
Debug::log(LOG, "LayerSurface %x (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer, PMONITOR->szName.c_str());
Debug::log(LOG, "LayerSurface %x (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer,
PMONITOR->szName.c_str());
}
void Events::listener_destroyLayerSurface(void* owner, void* data) {
@@ -94,12 +95,13 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
PMONITOR->scheduledRecalc = true;
// and damage
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
}
layersurface->readyToDelete = true;
layersurface->layerSurface = nullptr;
layersurface->layerSurface = nullptr;
}
void Events::listener_mapLayerSurface(void* owner, void* data) {
@@ -108,7 +110,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
Debug::log(LOG, "LayerSurface %x mapped", layersurface->layerSurface);
layersurface->layerSurface->mapped = true;
layersurface->mapped = true;
layersurface->mapped = true;
// anim
layersurface->alpha.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
@@ -128,7 +130,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
break;
}
}
layersurface->monitorID = PMONITOR->ID;
layersurface->monitorID = PMONITOR->ID;
PMONITOR->scheduledRecalc = true;
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
}
@@ -137,23 +139,26 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
if (layersurface->layerSurface->current.keyboard_interactive &&
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
const auto LOCAL =
g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y);
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
}
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
layersurface->alpha.setValue(0);
layersurface->alpha = 255.f;
layersurface->alpha = 1.f;
layersurface->readyToDelete = false;
layersurface->fadingOut = false;
layersurface->fadingOut = false;
g_pEventManager->postEvent(SHyprIPCEvent{"openlayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
}
@@ -202,18 +207,19 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
// refocus if needed
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus) {
Vector2D surfaceCoords;
Vector2D surfaceCoords;
SLayerSurface* pFoundLayerSurface = nullptr;
wlr_surface* foundSurface = nullptr;
wlr_surface* foundSurface = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
// find LS-es to focus
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
&surfaceCoords, &pFoundLayerSurface);
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
&surfaceCoords, &pFoundLayerSurface);
if (!foundSurface) {
// if there isn't any, focus the last window
@@ -226,13 +232,16 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
}
}
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y,
(int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
g_pHyprRenderer->damageBox(&geomFixed);
geomFixed = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
geomFixed = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width,
(int)layersurface->layerSurface->surface->current.height};
layersurface->geometry = geomFixed; // because the surface can overflow... for some reason?
}
@@ -248,7 +257,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
return;
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);
@@ -265,7 +274,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
}
}
layersurface->monitorID = PMONITOR->ID;
layersurface->monitorID = PMONITOR->ID;
PMONITOR->scheduledRecalc = true;
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
}
@@ -284,7 +293,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
layersurface->layer = layersurface->layerSurface->current.layer;
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
}
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
@@ -295,7 +304,8 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
// update geom if it changed
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, layersurface->layerSurface->surface->current.width, layersurface->layerSurface->surface->current.height};
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, layersurface->layerSurface->surface->current.width,
layersurface->layerSurface->surface->current.height};
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
}

View File

@@ -26,8 +26,8 @@ void Events::listener_outputMgrTest(wl_listener* listener, void* data) {
}
void Events::listener_leaseRequest(wl_listener* listener, void* data) {
const auto REQUEST = (wlr_drm_lease_request_v1*)data;
struct wlr_drm_lease_v1* lease = wlr_drm_lease_request_v1_grant(REQUEST);
const auto REQUEST = (wlr_drm_lease_request_v1*)data;
struct wlr_drm_lease_v1* lease = wlr_drm_lease_request_v1_grant(REQUEST);
if (!lease) {
Debug::log(ERR, "Failed to grant lease request!");
wlr_drm_lease_request_v1_reject(REQUEST);
@@ -47,7 +47,7 @@ void Events::listener_requestSetSel(wl_listener* listener, void* data) {
void Events::listener_readyXWayland(wl_listener* listener, void* data) {
#ifndef NO_XWAYLAND
const auto XCBCONNECTION = xcb_connect(g_pXWaylandManager->m_sWLRXWayland->display_name, NULL);
const auto ERR = xcb_connection_has_error(XCBCONNECTION);
const auto ERR = xcb_connection_has_error(XCBCONNECTION);
if (ERR) {
Debug::log(LogLevel::ERR, "XWayland -> xcb_connection_has_error failed with %i", ERR);
return;
@@ -55,7 +55,7 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) {
for (auto& ATOM : HYPRATOMS) {
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(XCBCONNECTION, 0, ATOM.first.length(), ATOM.first.c_str());
xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(XCBCONNECTION, cookie, NULL);
xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(XCBCONNECTION, cookie, NULL);
if (!reply) {
Debug::log(LogLevel::ERR, "XWayland -> Atom failed: %s", ATOM.first.c_str());
@@ -69,7 +69,8 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) {
const auto XCURSOR = wlr_xcursor_manager_get_xcursor(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", 1);
if (XCURSOR) {
wlr_xwayland_set_cursor(g_pXWaylandManager->m_sWLRXWayland, XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, XCURSOR->images[0]->width, XCURSOR->images[0]->height, XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y);
wlr_xwayland_set_cursor(g_pXWaylandManager->m_sWLRXWayland, XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, XCURSOR->images[0]->width,
XCURSOR->images[0]->height, XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y);
}
xcb_disconnect(XCBCONNECTION);
@@ -107,15 +108,16 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
Debug::log(LOG, "Drag started with an icon %x", wlrDrag->icon);
g_pInputManager->m_sDrag.dragIcon = wlrDrag->icon;
wlrDrag->icon->data = g_pInputManager->m_sDrag.dragIcon;
wlrDrag->icon->data = g_pInputManager->m_sDrag.dragIcon;
g_pInputManager->m_sDrag.hyprListener_mapIcon.initCallback(&wlrDrag->icon->events.map, &Events::listener_mapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
g_pInputManager->m_sDrag.hyprListener_unmapIcon.initCallback(&wlrDrag->icon->events.unmap, &Events::listener_unmapDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
g_pInputManager->m_sDrag.hyprListener_destroyIcon.initCallback(&wlrDrag->icon->events.destroy, &Events::listener_destroyDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
g_pInputManager->m_sDrag.hyprListener_commitIcon.initCallback(&wlrDrag->icon->surface->events.commit, &Events::listener_commitDragIcon, &g_pInputManager->m_sDrag, "DragIcon");
g_pInputManager->m_sDrag.hyprListener_commitIcon.initCallback(&wlrDrag->icon->surface->events.commit, &Events::listener_commitDragIcon, &g_pInputManager->m_sDrag,
"DragIcon");
}
static auto *const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
static auto* const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
if (*PFOLLOWONDND)
g_pInputManager->m_pFollowOnDnDBegin = g_pCompositor->m_pLastWindow;
@@ -126,16 +128,19 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
void Events::listener_destroyDrag(void* owner, void* data) {
Debug::log(LOG, "Drag destroyed.");
if (g_pInputManager->m_sDrag.drag && g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.dragIcon->surface)
g_pHyprRenderer->damageBox(g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4);
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
g_pInputManager->m_sDrag.drag = nullptr;
if (g_pInputManager->m_sDrag.drag && g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.dragIcon->surface)
g_pHyprRenderer->damageBox(g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4,
g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4);
g_pInputManager->m_sDrag.drag = nullptr;
g_pInputManager->m_sDrag.dragIcon = nullptr;
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();
g_pInputManager->refocus();
if (g_pInputManager->m_pFollowOnDnDBegin)
if (g_pInputManager->m_pFollowOnDnDBegin && *PFOLLOWMOUSE != 1)
g_pCompositor->focusWindow(g_pInputManager->m_pFollowOnDnDBegin);
g_pInputManager->m_pFollowOnDnDBegin = nullptr;
@@ -189,6 +194,12 @@ void Events::listener_sessionActive(wl_listener* listener, void* data) {
Debug::log(LOG, "Session got activated!");
g_pCompositor->m_bSessionActive = true;
for (auto& m : g_pCompositor->m_vMonitors) {
g_pCompositor->scheduleFrameForMonitor(m.get());
}
g_pConfigManager->m_bWantsMonitorReload = true;
}
void Events::listener_powerMgrSetMode(wl_listener* listener, void* data) {

View File

@@ -15,8 +15,6 @@
// //
// --------------------------------------------------------- //
CMonitor* pMostHzMonitor = nullptr;
void Events::listener_change(wl_listener* listener, void* data) {
// layout got changed, let's update monitors.
const auto CONFIG = wlr_output_configuration_v1_create();
@@ -29,14 +27,14 @@ void Events::listener_change(wl_listener* listener, void* data) {
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
//m->vecSize.x = BOX.width;
// m->vecSize.y = BOX.height;
// m->vecSize.y = BOX.height;
m->vecPosition.x = BOX.x;
m->vecPosition.y = BOX.y;
CONFIGHEAD->state.enabled = m->output->enabled;
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
}
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
@@ -75,19 +73,22 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
PNEWMONITOR->output = OUTPUT;
PNEWMONITOR->output = OUTPUT;
PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP;
PNEWMONITOR->onConnect(false);
if ((!pMostHzMonitor || PNEWMONITOR->refreshRate > pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
pMostHzMonitor = PNEWMONITOR;
if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR;
// ready to process cuz we have a monitor
if (PNEWMONITOR->m_bEnabled) {
g_pCompositor->m_bReadyToProcess = true;
g_pCompositor->m_bUnsafeState = false;
g_pCompositor->m_bUnsafeState = false;
}
g_pConfigManager->m_bWantsMonitorReload = true;
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR);
}
void Events::listener_monitorFrame(void* owner, void* data) {
@@ -101,17 +102,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (!PMONITOR->m_bEnabled)
return;
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("debug:damage_tracking")->intValue;
static auto *const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
static auto *const PNODIRECTSCANOUT = &g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout")->intValue;
static auto* const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto* const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("debug:damage_tracking")->intValue;
static auto* const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
static auto* const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
static auto* const PNODIRECTSCANOUT = &g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout")->intValue;
static int damageBlinkCleanup = 0; // because double-buffered
static int damageBlinkCleanup = 0; // because double-buffered
if (!*PDAMAGEBLINK)
damageBlinkCleanup = 0;
@@ -137,16 +138,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
}
// checks //
if (PMONITOR->ID == pMostHzMonitor->ID || !*PNOVFR) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
if (PMONITOR->ID == g_pHyprRenderer->m_pMostHzMonitor->ID ||
!*PNOVFR) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
g_pCompositor->sanityCheckWorkspaces();
g_pAnimationManager->tick();
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
if (g_pConfigManager->m_bWantsMonitorReload)
g_pConfigManager->performMonitorReload();
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
}
// //
@@ -170,7 +172,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
// check the damage
pixman_region32_t damage;
bool hasChanged;
bool hasChanged;
pixman_region32_init(&damage);
if (*PDAMAGETRACKINGMODE == -1) {
@@ -180,7 +182,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
g_pHyprOpenGL->preRender(PMONITOR);
if (!wlr_output_damage_attach_render(PMONITOR->damage, &hasChanged, &damage)){
if (!wlr_output_damage_attach_render(PMONITOR->damage, &hasChanged, &damage)) {
Debug::log(ERR, "Couldn't attach render to display %s ???", PMONITOR->szName.c_str());
return;
}
@@ -199,24 +201,25 @@ void Events::listener_monitorFrame(void* owner, void* data) {
}
// if we have no tracking or full tracking, invalidate the entire monitor
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 || PMONITOR->isMirror() /* why??? */) {
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 ||
PMONITOR->isMirror() /* why??? */) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); // wot?
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
} else {
static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
// if we use blur we need to expand the damage for proper blurring
if (*PBLURENABLED == 1) {
// TODO: can this be optimized?
static auto *const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
static auto *const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
// now, prep the damage, get the extended damage region
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
} else {
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
}
@@ -228,7 +231,6 @@ void Events::listener_monitorFrame(void* owner, void* data) {
PMONITOR->forceFullFrames = 0;
}
// TODO: this is getting called with extents being 0,0,0,0 should it be?
// potentially can save on resources.
@@ -237,8 +239,8 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (PMONITOR->isMirror()) {
g_pHyprOpenGL->renderMirrored();
} else {
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0));
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
@@ -255,7 +257,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
g_pHyprOpenGL->renderRect(&monrect, CColor(255, 0, 255, 100), 0);
g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0);
damageBlinkCleanup = 1;
} else if (*PDAMAGEBLINK) {
damageBlinkCleanup++;
@@ -263,15 +265,16 @@ void Events::listener_monitorFrame(void* owner, void* data) {
damageBlinkCleanup = 0;
}
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
wlr_output_render_software_cursors(PMONITOR->output, NULL);
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
if (wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y)) {
wlr_output_render_software_cursors(PMONITOR->output, NULL);
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
}
}
g_pHyprOpenGL->end();
g_pProtocolManager->m_pToplevelExportProtocolManager->onMonitorRender(PMONITOR); // dispatch any toplevel sharing
// calc frame damage
pixman_region32_t frameDamage;
pixman_region32_init(&frameDamage);
@@ -314,10 +317,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
void Events::listener_monitorDestroy(void* owner, void* data) {
const auto OUTPUT = (wlr_output*)data;
CMonitor* pMonitor = nullptr;
CMonitor* pMonitor = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->szName == OUTPUT->name) {
for (auto& m : g_pCompositor->m_vRealMonitors) {
if (m->output == OUTPUT) {
pMonitor = m.get();
break;
}
@@ -326,25 +329,21 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
if (!pMonitor)
return;
Debug::log(LOG, "Destroy called for monitor %s", pMonitor->output->name);
pMonitor->onDisconnect();
// cleanup if not unsafe
if (!g_pCompositor->m_bUnsafeState) {
g_pCompositor->m_vRealMonitors.erase(std::remove_if(g_pCompositor->m_vRealMonitors.begin(), g_pCompositor->m_vRealMonitors.end(), [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; }));
Debug::log(LOG, "Removing monitor %s from realMonitors", pMonitor->output->name);
if (pMostHzMonitor == pMonitor) {
int mostHz = 0;
CMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz) {
pMonitorMostHz = m.get();
mostHz = m->refreshRate;
}
}
pMostHzMonitor = pMonitorMostHz;
}
std::erase_if(g_pCompositor->m_vRealMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; });
}
}
void Events::listener_monitorStateRequest(void* owner, void* data) {
const auto PMONITOR = (CMonitor*)owner;
const auto E = (wlr_output_event_request_state*)data;
wlr_output_commit_state(PMONITOR->output, E->state);
}

View File

@@ -16,12 +16,12 @@
// --------------------------------------------- //
void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
SXDGPopup *const PPOPUP = (SXDGPopup*)pPopup;
SXDGPopup* const PPOPUP = (SXDGPopup*)pPopup;
auto curPopup = PPOPUP;
auto curPopup = PPOPUP;
int px = 0;
int py = 0;
int px = 0;
int py = 0;
while (true) {
px += curPopup->popup->current.geometry.x;
@@ -63,13 +63,14 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
wlr_xdg_popup_unconstrain_from_box(popup, &box);
pHyprPopup->monitor = PMONITOR;
Debug::log(LOG, "Popup: Unconstrained from lx ly: %f %f, pHyprPopup lx ly: %f %f", (float)PMONITOR->vecPosition.x, (float)PMONITOR->vecPosition.y, (float)pHyprPopup->lx, (float)pHyprPopup->ly);
Debug::log(LOG, "Popup: Unconstrained from lx ly: %f %f, pHyprPopup lx ly: %f %f", (float)PMONITOR->vecPosition.x, (float)PMONITOR->vecPosition.y, (float)pHyprPopup->lx,
(float)pHyprPopup->ly);
}
void Events::listener_newPopup(void* owner, void* data) {
@@ -85,9 +86,9 @@ void Events::listener_newPopup(void* owner, void* data) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->lx = layersurface->position.x;
PNEWPOPUP->ly = layersurface->position.y;
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->lx = layersurface->position.x;
PNEWPOPUP->ly = layersurface->position.y;
PNEWPOPUP->monitor = PMONITOR;
createNewPopup(WLRPOPUP, PNEWPOPUP);
}
@@ -108,11 +109,11 @@ void Events::listener_newPopupXDG(void* owner, void* data) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->lx = PWINDOW->m_vRealPosition.goalv().x;
PNEWPOPUP->ly = PWINDOW->m_vRealPosition.goalv().y;
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->lx = PWINDOW->m_vRealPosition.goalv().x;
PNEWPOPUP->ly = PWINDOW->m_vRealPosition.goalv().y;
PNEWPOPUP->parentWindow = PWINDOW;
PNEWPOPUP->monitor = PMONITOR;
PNEWPOPUP->monitor = PMONITOR;
createNewPopup(WLRPOPUP, PNEWPOPUP);
}
@@ -130,12 +131,12 @@ void Events::listener_newPopupFromPopupXDG(void* owner, void* data) {
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->parentPopup = PPOPUP;
PNEWPOPUP->lx = PPOPUP->lx;
PNEWPOPUP->ly = PPOPUP->ly;
PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->parentPopup = PPOPUP;
PNEWPOPUP->lx = PPOPUP->lx;
PNEWPOPUP->ly = PPOPUP->ly;
PNEWPOPUP->parentWindow = PPOPUP->parentWindow;
PNEWPOPUP->monitor = PPOPUP->monitor;
PNEWPOPUP->monitor = PPOPUP->monitor;
createNewPopup(WLRPOPUP, PNEWPOPUP);
}
@@ -182,7 +183,7 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
void Events::listener_commitPopupXDG(void* owner, void* data) {
SXDGPopup* PPOPUP = (SXDGPopup*)owner;
int lx = 0, ly = 0;
int lx = 0, ly = 0;
addPopupGlobalCoords(PPOPUP, &lx, &ly);
g_pHyprRenderer->damageSurface(PPOPUP->popup->base->surface, lx, ly);
@@ -200,5 +201,5 @@ void Events::listener_destroyPopupXDG(void* owner, void* data) {
PPOPUP->pSurfaceTree = nullptr;
}
g_pCompositor->m_vXDGPopups.erase(std::remove_if(g_pCompositor->m_vXDGPopups.begin(), g_pCompositor->m_vXDGPopups.end(), [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; }));
std::erase_if(g_pCompositor->m_vXDGPopups, [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; });
}

View File

@@ -20,7 +20,7 @@ void addViewCoords(void* pWindow, int* x, int* y) {
*x += PWINDOW->m_vRealPosition.goalv().x;
*y += PWINDOW->m_vRealPosition.goalv().y;
if (!PWINDOW->m_bIsX11) {
if (!PWINDOW->m_bIsX11 && PWINDOW->m_bIsMapped) {
wlr_box geom;
wlr_xdg_surface_get_geometry(PWINDOW->m_uSurface.xdg, &geom);
@@ -29,38 +29,33 @@ void addViewCoords(void* pWindow, int* x, int* y) {
}
}
int setAnimToMove(void* data) {
const auto PWINDOW = (CWindow*)data;
void setAnimToMove(void* data) {
auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
auto *const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
CAnimatedVariable* animvar = (CAnimatedVariable*)data;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return 0;
PWINDOW->m_vRealPosition.setConfig(PANIMCFG);
PWINDOW->m_vRealSize.setConfig(PANIMCFG);
return 0;
animvar->setConfig(PANIMCFG);
}
void Events::listener_mapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
CWindow* PWINDOW = (CWindow*)owner;
static auto *const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
static auto *const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
static auto *const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
static auto *const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
static auto *const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
static auto* const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
static auto* const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
static auto* const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true;
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceOpen ? SPECIAL_WORKSPACE_ID : PMONITOR->activeWorkspace;
PWINDOW->m_bIsMapped = true;
auto PMONITOR = g_pCompositor->m_pLastMonitor;
const auto PWORKSPACE =
PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true;
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
PWINDOW->m_bIsMapped = true;
PWINDOW->m_bReadyToDelete = false;
PWINDOW->m_bFadingOut = false;
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
PWINDOW->m_bFadingOut = false;
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
if (PWINDOW->m_iX11Type == 2)
g_pCompositor->moveUnmanagedX11ToWindows(PWINDOW);
@@ -85,7 +80,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
if (g_pXWaylandManager->shouldBeFloated(PWINDOW)) {
PWINDOW->m_bIsFloating = true;
PWINDOW->m_bIsFloating = true;
PWINDOW->m_bRequestsFloat = true;
}
@@ -96,7 +91,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWORKSPACE->m_bDefaultPseudo) {
PWINDOW->m_bIsPseudotiled = true;
wlr_box desiredGeometry = {0};
wlr_box desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry);
PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
}
@@ -105,22 +100,25 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
pFullscreenWindow = PFULLWINDOW;
pFullscreenWindow = PFULLWINDOW;
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, PWORKSPACE->m_efFullscreenMode);
}
// window rules
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
std::string requestedWorkspace = "";
bool workspaceSilent = false;
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen || (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen) || (PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
bool shouldFocus = true;
bool workspaceSilent = false;
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen ||
(!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen) ||
(PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
bool requestsMaximize = false;
bool shouldFocus = true;
bool workspaceSpecial = false;
for (auto& r : WINDOWRULES) {
if (r.szRule.find("monitor") == 0) {
try {
const auto MONITORSTR = r.szRule.substr(r.szRule.find(" "));
const auto MONITORSTR = r.szRule.substr(r.szRule.find(' '));
if (MONITORSTR == "unset") {
PWINDOW->m_iMonitorID = PMONITOR->ID;
@@ -133,12 +131,13 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->m_iMonitorID));
if (PWINDOW->m_iMonitorID != PMONITOR->ID) {
g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->m_iMonitorID));
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
}
Debug::log(ERR, "Rule monitor, applying to window %x -> mon: %i, workspace: %i", PWINDOW, PWINDOW->m_iMonitorID, PWINDOW->m_iWorkspaceID);
} catch (std::exception& e) {
Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what());
}
} catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what()); }
} else if (r.szRule.find("workspace") == 0) {
// check if it isnt unset
const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
@@ -149,7 +148,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
requestedWorkspace = WORKSPACERQ;
}
if (requestedWorkspace == PWORKSPACE->m_szName || requestedWorkspace == "name:" + PWORKSPACE->m_szName)
const auto JUSTWORKSPACE = WORKSPACERQ.contains(' ') ? WORKSPACERQ.substr(0, WORKSPACERQ.find_first_of(' ')) : WORKSPACERQ;
if (JUSTWORKSPACE == PWORKSPACE->m_szName || JUSTWORKSPACE == "name:" + PWORKSPACE->m_szName)
requestedWorkspace = "";
Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str());
@@ -161,14 +162,20 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bIsPseudotiled = true;
} else if (r.szRule.find("nofocus") == 0) {
PWINDOW->m_bNoFocus = true;
} else if (r.szRule.find("nofullscreenrequest") == 0) {
PWINDOW->m_bNoFullscreenRequest = true;
} else if (r.szRule == "fullscreen") {
requestsFullscreen = true;
} else if (r.szRule == "windowdance") {
PWINDOW->m_sAdditionalConfigData.windowDanceCompat = true;
} else if (r.szRule == "nomaxsize") {
PWINDOW->m_sAdditionalConfigData.noMaxSize = true;
} else if (r.szRule == "forceinput") {
PWINDOW->m_sAdditionalConfigData.forceAllowsInput = true;
} else if (r.szRule == "pin") {
PWINDOW->m_bPinned = true;
} else if (r.szRule == "maximize") {
requestsMaximize = true;
} else if (r.szRule.find("idleinhibit") == 0) {
auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
@@ -197,7 +204,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
// check for silent
if (requestedWorkspace.contains("silent")) {
workspaceSilent = true;
shouldFocus = false;
shouldFocus = false;
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
}
@@ -206,16 +213,18 @@ void Events::listener_mapWindow(void* owner, void* data) {
shouldFocus = true;
}
if (requestedWorkspace == "special") {
if (requestedWorkspace.find("special") == 0) {
workspaceSpecial = true;
workspaceSilent = true;
workspaceSilent = true;
}
if (!workspaceSilent) {
g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspace);
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
PMONITOR = g_pCompositor->m_pLastMonitor;
}
}
@@ -226,14 +235,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (!PWORKSPACE) {
std::string workspaceName = "";
int workspaceID = 0;
int workspaceID = 0;
if (requestedWorkspace.find("name:") == 0) {
workspaceName = requestedWorkspace.substr(5);
workspaceID = g_pCompositor->getNextAvailableNamedWorkspace();
workspaceID = g_pCompositor->getNextAvailableNamedWorkspace();
} else if (workspaceSpecial) {
workspaceName = "";
workspaceID = SPECIAL_WORKSPACE_ID;
workspaceID = getWorkspaceIDFromString(requestedWorkspace, workspaceName);
} else {
try {
workspaceID = std::stoi(requestedWorkspace);
@@ -253,7 +262,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWORKSPACE) {
PWINDOW->m_iWorkspaceID = PWORKSPACE->m_iID;
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
}
}
@@ -265,14 +274,18 @@ void Events::listener_mapWindow(void* owner, void* data) {
for (auto& r : WINDOWRULES) {
if (r.szRule.find("size") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW);
const auto SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
const auto SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
const auto SIZEX = SIZEXSTR == "max" ?
std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) :
(!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stof(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
const auto SIZEY = SIZEYSTR == "max" ?
std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) :
(!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
Debug::log(LOG, "Rule size, applying to window %x", PWINDOW);
@@ -280,87 +293,87 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule size failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} catch (...) { Debug::log(LOG, "Rule size failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); }
} else if (r.szRule.find("minsize") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
const auto SIZE = Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
const auto SIZE =
Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
PWINDOW->m_vRealSize = SIZE;
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule minsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} catch (...) { Debug::log(LOG, "Rule minsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); }
} else if (r.szRule.find("maxsize") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
const auto SIZE = Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
const auto SIZE =
Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
PWINDOW->m_vRealSize = SIZE;
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule maxsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} catch (...) { Debug::log(LOG, "Rule maxsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); }
} else if (r.szRule.find("move") == 0) {
try {
auto value = r.szRule.substr(r.szRule.find(" ") + 1);
auto value = r.szRule.substr(r.szRule.find(' ') + 1);
const bool CURSOR = value.find("cursor") == 0;
if (CURSOR)
value = value.substr(value.find_first_of(' ') + 1);
const auto POSXSTR = value.substr(0, value.find(" "));
const auto POSYSTR = value.substr(value.find(" ") + 1);
const auto POSXSTR = value.substr(0, value.find(' '));
const auto POSYSTR = value.substr(value.find(' ') + 1);
int posX = 0;
int posY = 0;
int posX = 0;
int posY = 0;
if (POSXSTR.find("100%-") == 0) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto POSXRAW = POSXSTR.substr(5);
posX = PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stoi(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
const auto POSXRAW = POSXSTR.substr(5);
posX =
PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
if (CURSOR)
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
} else if (!CURSOR) {
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
} else {
// cursor
if (POSXSTR == "cursor") {
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x;
} else {
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x + (!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().x);
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x +
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().x);
}
}
if (POSYSTR.find("100%-") == 0) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto POSYRAW = POSYSTR.substr(5);
posY = PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stoi(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
const auto POSYRAW = POSYSTR.substr(5);
posY =
PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
if (CURSOR)
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
} else if (!CURSOR) {
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
} else {
// cursor
if (POSYSTR == "cursor") {
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y;
} else {
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y + (!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().y);
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y +
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goalv().y);
}
}
@@ -369,9 +382,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition;
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} catch (...) { Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str()); }
} else if (r.szRule == "center") {
PWINDOW->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.f - PWINDOW->m_vRealSize.goalv() / 2.f;
}
@@ -386,17 +397,22 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
// Set the pseudo size here too so that it doesnt end up being 0x0
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10, 10);
}
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow;
if (PWINDOW->m_sAdditionalConfigData.forceAllowsInput) {
PWINDOW->m_bNoFocus = false;
PWINDOW->m_bNoInitialFocus = false;
PWINDOW->m_bNoFocus = false;
PWINDOW->m_bNoInitialFocus = false;
PWINDOW->m_bX11ShouldntFocus = false;
}
// check LS focus grab
const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus);
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
PWINDOW->m_bNoInitialFocus = true;
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2 && !workspaceSilent) {
g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
@@ -412,32 +428,39 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->hyprListener_commitWindow.initCallback(&PWINDOW->m_uSurface.xdg->surface->events.commit, &Events::listener_commitWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
"XDG Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW,
"XDG Window Late");
PWINDOW->hyprListener_requestMove.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_move, &Events::listener_requestMove, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_requestResize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_resize, &Events::listener_requestResize, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XDG Window Late");
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW,
"XDG Window Late");
} else {
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW,
"XWayland Window Late");
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_configureX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_configure, &Events::listener_configureX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, "Xwayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "Xwayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_minimize, &Events::listener_requestMinimize, PWINDOW,
"Xwayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_maximize, &Events::listener_requestMaximize, PWINDOW,
"Xwayland Window Late");
if (PWINDOW->m_iX11Type == 2)
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW,
"XWayland Window Late");
}
// do the animation thing
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
PWINDOW->m_fAlpha.setValueAndWarp(0.f);
PWINDOW->m_fAlpha = 255.f;
PWINDOW->m_fAlpha = 1.f;
const auto TIMER = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, setAnimToMove, PWINDOW);
wl_event_source_timer_update(TIMER, PWINDOW->m_vRealPosition.getDurationLeftMs() + 5);
PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove);
PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove);
if (requestsFullscreen) {
if ((requestsFullscreen || requestsMaximize) && !PWINDOW->m_bNoFullscreenRequest) {
// fix fullscreen on requested (basically do a switcheroo)
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
@@ -447,7 +470,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize.warp();
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
g_pCompositor->setWindowFullscreen(PWINDOW, true, requestsFullscreen ? FULLSCREEN_FULL : FULLSCREEN_MAXIMIZED);
}
if (pFullscreenWindow && workspaceSilent) {
@@ -492,7 +515,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (ppid) {
// get window by pid
std::vector<CWindow*> found;
CWindow* finalFound = nullptr;
CWindow* finalFound = nullptr;
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->isHidden())
continue;
@@ -529,10 +552,12 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
}
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", getFormat("%x,%s,%s,%s", PWINDOW, workspaceID.c_str(), g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), PWINDOW->m_szTitle.c_str())});
g_pEventManager->postEvent(
SHyprIPCEvent{"openwindow", getFormat("%x,%s,%s,%s", PWINDOW, workspaceID.c_str(), g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), PWINDOW->m_szTitle.c_str())});
// recalc the values for this window
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
@@ -545,6 +570,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", getFormat("%x", PWINDOW)});
g_pProtocolManager->m_pToplevelExportProtocolManager->onWindowUnmap(PWINDOW);
if (!PWINDOW->m_bIsX11) {
Debug::log(LOG, "Unregistered late callbacks XDG");
PWINDOW->hyprListener_commitWindow.removeCallback();
@@ -583,9 +610,9 @@ void Events::listener_unmapWindow(void* owner, void* data) {
bool wasLastWindow = false;
if (PWINDOW == g_pCompositor->m_pLastWindow) {
wasLastWindow = true;
wasLastWindow = true;
g_pCompositor->m_pLastWindow = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
}
PWINDOW->m_bMappedX11 = false;
@@ -633,11 +660,11 @@ void Events::listener_unmapWindow(void* owner, void* data) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
// do the animation thing
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.vec() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
// anims
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
@@ -677,7 +704,7 @@ void Events::listener_destroyWindow(void* owner, void* data) {
if (PWINDOW == g_pCompositor->m_pLastWindow) {
g_pCompositor->m_pLastWindow = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
}
PWINDOW->hyprListener_mapWindow.removeCallback();
@@ -693,13 +720,18 @@ void Events::listener_destroyWindow(void* owner, void* data) {
}
PWINDOW->m_bReadyToDelete = true;
if (!PWINDOW->m_bFadingOut) {
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
Debug::log(LOG, "Unmapped window %x removed instantly", PWINDOW);
}
}
void Events::listener_setTitleWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!g_pCompositor->windowValidMapped(PWINDOW))
return;
return;
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
@@ -721,21 +753,33 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
return;
}
if (PWINDOW->isHidden())
if (PWINDOW->isHidden() || PWINDOW->m_bNoFullscreenRequest)
return;
bool requestedFullState = false;
if (!PWINDOW->m_bIsX11) {
const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen && !PWINDOW->m_bFakeFullscreenState)
g_pCompositor->setWindowFullscreen(PWINDOW, REQUESTED->fullscreen, FULLSCREEN_FULL);
requestedFullState = REQUESTED->fullscreen;
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
if (!PWINDOW->m_uSurface.xwayland->mapped)
return;
g_pCompositor->setWindowFullscreen(PWINDOW, PWINDOW->m_uSurface.xwayland->fullscreen, FULLSCREEN_FULL);
if (!PWINDOW->m_bFakeFullscreenState)
g_pCompositor->setWindowFullscreen(PWINDOW, PWINDOW->m_uSurface.xwayland->fullscreen, FULLSCREEN_FULL);
requestedFullState = PWINDOW->m_uSurface.xwayland->fullscreen;
}
if (!requestedFullState && PWINDOW->m_bFakeFullscreenState) {
g_pXWaylandManager->setWindowFullscreen(PWINDOW, false); // fixes for apps expecting a de-fullscreen (e.g. ff)
g_pXWaylandManager->setWindowFullscreen(PWINDOW, true);
}
PWINDOW->updateToplevel();
@@ -744,9 +788,9 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
}
void Events::listener_activateXDG(wl_listener* listener, void* data) {
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
static auto *const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
static auto* const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
Debug::log(LOG, "Activate request for surface at %x", E->surface);
@@ -764,9 +808,9 @@ void Events::listener_activateXDG(wl_listener* listener, void* data) {
}
void Events::listener_activateX11(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
const auto PWINDOW = (CWindow*)owner;
static auto *const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
static auto* const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
Debug::log(LOG, "X11 Activate request for window %x", PWINDOW);
@@ -807,7 +851,7 @@ void Events::listener_configureX11(void* owner, void* data) {
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(E->x, E->y));
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec();
PWINDOW->m_vSize = PWINDOW->m_vRealSize.vec();
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
@@ -845,8 +889,10 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
return;
}
if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
Debug::log(LOG, "Unmanaged window %x requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y, (int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height);
if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 ||
abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
Debug::log(LOG, "Unmanaged window %x requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y,
(int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height);
g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y));
@@ -869,11 +915,12 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
if (XWSURFACE->parent)
Debug::log(LOG, "Window parent data: %s at %x", XWSURFACE->parent->_class, XWSURFACE->parent);
const auto PNEWWINDOW = XWSURFACE->override_redirect ? g_pCompositor->m_dUnmanagedX11Windows.emplace_back(std::make_unique<CWindow>()).get() : g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
const auto PNEWWINDOW = XWSURFACE->override_redirect ? g_pCompositor->m_dUnmanagedX11Windows.emplace_back(std::make_unique<CWindow>()).get() :
g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
PNEWWINDOW->m_uSurface.xwayland = XWSURFACE;
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
PNEWWINDOW->m_bIsX11 = true;
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
PNEWWINDOW->m_bIsX11 = true;
PNEWWINDOW->m_pX11Parent = g_pCompositor->getX11Parent(PNEWWINDOW);
@@ -891,7 +938,7 @@ void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
Debug::log(LOG, "New XDG Surface created. (class: %s)", XDGSURFACE->toplevel->app_id);
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window");
@@ -907,12 +954,15 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
void Events::listener_requestMaximize(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
Debug::log(LOG, "Maximize request for %x", PWINDOW);
if (PWINDOW->m_bNoFullscreenRequest)
return;
Debug::log(LOG, "Maximize request for %x", PWINDOW);
if (!PWINDOW->m_bIsX11) {
const auto EV = (wlr_foreign_toplevel_handle_v1_maximized_event*)data;
g_pCompositor->setWindowFullscreen(PWINDOW, EV ? EV->maximized : !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
g_pCompositor->setWindowFullscreen(PWINDOW, EV ? EV->maximized : !PWINDOW->m_bIsFullscreen,
FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {

View File

@@ -7,10 +7,10 @@ CAnimatedVariable::CAnimatedVariable() {
}
void CAnimatedVariable::create(ANIMATEDVARTYPE type, SAnimationPropertyConfig* pAnimConfig, void* pWindow, AVARDAMAGEPOLICY policy) {
m_eVarType = type;
m_eVarType = type;
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_pWindow = pWindow;
m_pConfig = pAnimConfig;
m_pWindow = pWindow;
m_bDummy = false;
}
@@ -22,25 +22,23 @@ void CAnimatedVariable::create(ANIMATEDVARTYPE type, std::any val, SAnimationPro
switch (type) {
case AVARTYPE_FLOAT: {
const auto V = std::any_cast<float>(val);
m_fValue = V;
m_fGoal = V;
m_fValue = V;
m_fGoal = V;
break;
}
case AVARTYPE_VECTOR: {
const auto V = std::any_cast<Vector2D>(val);
m_vValue = V;
m_vGoal = V;
m_vValue = V;
m_vGoal = V;
break;
}
case AVARTYPE_COLOR: {
const auto V = std::any_cast<CColor>(val);
m_cValue = V;
m_cGoal = V;
m_cValue = V;
m_cGoal = V;
break;
}
default:
ASSERT(false);
break;
default: ASSERT(false); break;
}
} catch (std::exception& e) {
Debug::log(ERR, "CAnimatedVariable create error: %s", e.what());
@@ -64,10 +62,20 @@ void CAnimatedVariable::registerVar() {
}
int CAnimatedVariable::getDurationLeftMs() {
return std::max((int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0);
return std::max(
(int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0);
}
float CAnimatedVariable::getPercent() {
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count();
return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f);
}
float CAnimatedVariable::getCurveValue() {
const auto SPENT = getPercent();
if (SPENT >= 1.f)
return 1.f;
return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT);
}

View File

@@ -12,7 +12,7 @@ enum ANIMATEDVARTYPE {
enum AVARDAMAGEPOLICY {
AVARDAMAGE_INVALID = -1,
AVARDAMAGE_ENTIRE = 0,
AVARDAMAGE_ENTIRE = 0,
AVARDAMAGE_BORDER,
AVARDAMAGE_SHADOW
};
@@ -24,7 +24,7 @@ struct SAnimationPropertyConfig;
class CHyprRenderer;
class CAnimatedVariable {
public:
public:
CAnimatedVariable(); // dummy var
void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY);
@@ -65,53 +65,59 @@ public:
return m_cGoal;
}
void operator=(const Vector2D& v) {
m_vGoal = v;
CAnimatedVariable& operator=(const Vector2D& v) {
m_vGoal = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
m_vBegun = m_vValue;
onAnimationBegin();
return *this;
}
void operator=(const float& v) {
m_fGoal = v;
CAnimatedVariable& operator=(const float& v) {
m_fGoal = v;
animationBegin = std::chrono::system_clock::now();
m_fBegun = m_fValue;
m_fBegun = m_fValue;
onAnimationBegin();
return *this;
}
void operator=(const CColor& v) {
m_cGoal = v;
CAnimatedVariable& operator=(const CColor& v) {
m_cGoal = v;
animationBegin = std::chrono::system_clock::now();
m_cBegun = m_cValue;
m_cBegun = m_cValue;
onAnimationBegin();
return *this;
}
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const Vector2D& v) {
m_vValue = v;
m_vValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
m_vBegun = m_vValue;
onAnimationBegin();
}
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const float& v) {
m_fValue = v;
m_fValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
m_vBegun = m_vValue;
onAnimationBegin();
}
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const CColor& v) {
m_cValue = v;
m_cValue = v;
animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue;
m_vBegun = m_vValue;
onAnimationBegin();
}
@@ -137,14 +143,10 @@ public:
// checks if an animation is in progress
bool isBeingAnimated() {
switch (m_eVarType) {
case AVARTYPE_FLOAT:
return m_fValue != m_fGoal;
case AVARTYPE_VECTOR:
return m_vValue != m_vGoal;
case AVARTYPE_COLOR:
return m_cValue != m_cGoal;
default:
UNREACHABLE();
case AVARTYPE_FLOAT: return m_fValue != m_fGoal;
case AVARTYPE_VECTOR: return m_vValue != m_vGoal;
case AVARTYPE_COLOR: return m_cValue != m_cGoal;
default: UNREACHABLE();
}
UNREACHABLE();
@@ -166,8 +168,7 @@ public:
m_cValue = m_cGoal;
break;
}
default:
UNREACHABLE();
default: UNREACHABLE();
}
if (endCallback)
@@ -187,11 +188,14 @@ public:
/* returns the spent (completion) % */
float getPercent();
/* returns the current curve value */
float getCurveValue();
/* sets a function to be ran when the animation finishes.
if an animation is not running, runs instantly.
if "remove" is set to true, will remove the callback when ran. */
void setCallbackOnEnd(std::function<void(void* thisptr)> func, bool remove = true) {
m_fEndCallback = func;
m_fEndCallback = func;
m_bRemoveEndAfterRan = remove;
if (!isBeingAnimated())
@@ -201,50 +205,57 @@ public:
/* sets a function to be ran when an animation is started.
if "remove" is set to true, will remove the callback when ran. */
void setCallbackOnBegin(std::function<void(void* thisptr)> func, bool remove = true) {
m_fBeginCallback = func;
m_fBeginCallback = func;
m_bRemoveBeginAfterRan = remove;
}
private:
/* resets all callbacks. Does not call any. */
void resetAllCallbacks() {
m_fBeginCallback = nullptr;
m_fEndCallback = nullptr;
m_bRemoveBeginAfterRan = false;
m_bRemoveEndAfterRan = false;
}
Vector2D m_vValue = Vector2D(0,0);
float m_fValue = 0;
CColor m_cValue;
private:
Vector2D m_vValue = Vector2D(0, 0);
float m_fValue = 0;
CColor m_cValue;
Vector2D m_vGoal = Vector2D(0,0);
float m_fGoal = 0;
CColor m_cGoal;
Vector2D m_vGoal = Vector2D(0, 0);
float m_fGoal = 0;
CColor m_cGoal;
Vector2D m_vBegun = Vector2D(0,0);
float m_fBegun = 0;
CColor m_cBegun;
Vector2D m_vBegun = Vector2D(0, 0);
float m_fBegun = 0;
CColor m_cBegun;
// owners
void* m_pWindow = nullptr;
void* m_pWorkspace = nullptr;
void* m_pLayer = nullptr;
void* m_pWindow = nullptr;
void* m_pWorkspace = nullptr;
void* m_pLayer = nullptr;
SAnimationPropertyConfig* m_pConfig = nullptr;
SAnimationPropertyConfig* m_pConfig = nullptr;
bool m_bDummy = true;
bool m_bIsRegistered = false;
bool m_bDummy = true;
bool m_bIsRegistered = false;
std::chrono::system_clock::time_point animationBegin;
ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID;
AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_INVALID;
ANIMATEDVARTYPE m_eVarType = AVARTYPE_INVALID;
AVARDAMAGEPOLICY m_eDamagePolicy = AVARDAMAGE_INVALID;
bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true;
std::function<void(void* thisptr)> m_fEndCallback;
std::function<void(void* thisptr)> m_fBeginCallback;
bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true;
std::function<void(void* thisptr)> m_fEndCallback;
std::function<void(void* thisptr)> m_fBeginCallback;
// methods
void onAnimationEnd() {
if (m_fEndCallback) {
m_fEndCallback(this);
if (m_bRemoveEndAfterRan)
m_fEndCallback = nullptr; // reset
m_fEndCallback = nullptr; // reset
}
}
@@ -252,7 +263,7 @@ private:
if (m_fBeginCallback) {
m_fBeginCallback(this);
if (m_bRemoveBeginAfterRan)
m_fBeginCallback = nullptr; // reset
m_fBeginCallback = nullptr; // reset
}
}

View File

@@ -5,13 +5,13 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
const auto BEGIN = std::chrono::high_resolution_clock::now();
m_dPoints.emplace_back(Vector2D(0,0));
m_dPoints.emplace_back(Vector2D(0, 0));
for (auto& p : *pVec) {
m_dPoints.push_back(p);
}
m_dPoints.emplace_back(Vector2D(1,1));
m_dPoints.emplace_back(Vector2D(1, 1));
RASSERT(m_dPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: %i)", m_dPoints.size());
@@ -21,7 +21,7 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
m_aPointsBaked[i] = Vector2D(getXForT((i + 1) / (float)BAKEDPOINTS), getYForT((i + 1) / (float)BAKEDPOINTS));
}
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f;
const auto BEGINCALC = std::chrono::high_resolution_clock::now();
@@ -29,9 +29,8 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
getYForPoint(i);
const auto ELAPSEDCALCAVG = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f;
Debug::log(LOG, "Created a bezier curve, baked %i points, mem usage: %.2fkB, time to bake: %.2fµs. Estimated average calc time: %.2fµs.",
BAKEDPOINTS, POINTSSIZE, ELAPSEDUS, ELAPSEDCALCAVG);
Debug::log(LOG, "Created a bezier curve, baked %i points, mem usage: %.2fkB, time to bake: %.2fµs. Estimated average calc time: %.2fµs.", BAKEDPOINTS, POINTSSIZE, ELAPSEDUS,
ELAPSEDCALCAVG);
}
float CBezierCurve::getYForT(float t) {
@@ -47,9 +46,9 @@ float CBezierCurve::getYForPoint(float x) {
// binary search for the range UPDOWN X
float upperT = 1;
float lowerT = 0;
float mid = 0.5;
float mid = 0.5;
while(std::abs(upperT - lowerT) > INVBAKEDPOINTS) {
while (std::abs(upperT - lowerT) > INVBAKEDPOINTS) {
if (m_aPointsBaked[((int)(mid * (float)BAKEDPOINTS))].x > x) {
upperT = mid;
} else {
@@ -65,7 +64,7 @@ float CBezierCurve::getYForPoint(float x) {
const auto PERCINDELTA = (x - LOWERPOINT->x) / (UPPERPOINT->x - LOWERPOINT->x);
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
return 0.f;
return LOWERPOINT->y + (UPPERPOINT->y - UPPERPOINT->y) * PERCINDELTA;

View File

@@ -3,25 +3,25 @@
#include "../defines.hpp"
#include <deque>
constexpr int BAKEDPOINTS = 200;
constexpr int BAKEDPOINTS = 200;
constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS;
// an implementation of a cubic bezier curve
// might do better later
// TODO: n-point curves
class CBezierCurve {
public:
public:
// sets up the bezier curve.
// this EXCLUDES the 0,0 and 1,1 points,
void setup(std::vector<Vector2D>* points);
void setup(std::vector<Vector2D>* points);
float getYForT(float t);
float getXForT(float t);
float getYForPoint(float x);
float getYForT(float t);
float getXForT(float t);
float getYForPoint(float x);
private:
private:
// this INCLUDES the 0,0 and 1,1 points.
std::deque<Vector2D> m_dPoints;
std::deque<Vector2D> m_dPoints;
std::array<Vector2D, BAKEDPOINTS> m_aPointsBaked;
std::array<Vector2D, BAKEDPOINTS> m_aPointsBaked;
};

View File

@@ -1,7 +1,7 @@
#include "Color.hpp"
#include "../defines.hpp"
CColor::CColor() { }
CColor::CColor() {}
CColor::CColor(float r, float g, float b, float a) {
this->r = r;
@@ -11,10 +11,10 @@ CColor::CColor(float r, float g, float b, float a) {
}
CColor::CColor(uint64_t hex) {
this->r = RED(hex) * 255.f;
this->g = GREEN(hex) * 255.f;
this->b = BLUE(hex) * 255.f;
this->a = ALPHA(hex) * 255.f;
this->r = RED(hex);
this->g = GREEN(hex);
this->b = BLUE(hex);
this->a = ALPHA(hex);
}
uint64_t CColor::getAsHex() {

View File

@@ -3,24 +3,24 @@
#include "../includes.hpp"
class CColor {
public:
public:
CColor();
CColor(float, float, float, float);
CColor(uint64_t);
float r = 0, g = 0, b = 0, a = 255;
float r = 0, g = 0, b = 0, a = 1.f;
uint64_t getAsHex();
uint64_t getAsHex();
CColor operator- (const CColor& c2) const {
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
CColor operator-(const CColor& c2) const {
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);
}
CColor operator+ (const CColor& c2) const {
CColor operator+(const CColor& c2) const {
return CColor(r + c2.r, g + c2.g, b + c2.b, a + c2.a);
}
CColor operator* (const float& v) const {
CColor operator*(const float& v) const {
return CColor(r * v, g * v, b * v, a * v);
}

View File

@@ -5,64 +5,63 @@
#include <sys/utsname.h>
#include <iomanip>
#if defined(__DragonFly__) || defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <sys/sysctl.h>
# if defined(__DragonFly__)
# include <sys/kinfo.h> // struct kinfo_proc
# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
# include <sys/user.h> // struct kinfo_proc
# endif
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/sysctl.h>
#if defined(__DragonFly__)
#include <sys/kinfo.h> // struct kinfo_proc
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <sys/user.h> // struct kinfo_proc
#endif
# if defined(__NetBSD__)
# undef KERN_PROC
# define KERN_PROC KERN_PROC2
# define KINFO_PROC struct kinfo_proc2
# else
# define KINFO_PROC struct kinfo_proc
# endif
# if defined(__DragonFly__)
# define KP_PPID(kp) kp.kp_ppid
# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
# define KP_PPID(kp) kp.ki_ppid
# else
# define KP_PPID(kp) kp.p_ppid
# endif
#if defined(__NetBSD__)
#undef KERN_PROC
#define KERN_PROC KERN_PROC2
#define KINFO_PROC struct kinfo_proc2
#else
#define KINFO_PROC struct kinfo_proc
#endif
#if defined(__DragonFly__)
#define KP_PPID(kp) kp.kp_ppid
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#define KP_PPID(kp) kp.ki_ppid
#else
#define KP_PPID(kp) kp.p_ppid
#endif
#endif
static const float transforms[][9] = {{
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
-1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
-1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
-1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
-1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, 1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},{
0.0f, -1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
},
};
std::string absolutePath(const std::string& rawpath, const std::string& currentPath) {
@@ -87,7 +86,7 @@ std::string absolutePath(const std::string& rawpath, const std::string& currentP
return value;
}
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, const std::string& ownerString) {
ASSERT(pSignal);
ASSERT(pListener);
@@ -96,12 +95,12 @@ void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::
Debug::log(LOG, "Registered signal for owner %x: %x -> %x (owner: %s)", pOwner, pSignal, pListener, ownerString.c_str());
}
void handleNoop(struct wl_listener *listener, void *data) {
void handleNoop(struct wl_listener* listener, void* data) {
// Do nothing
}
std::string getFormat(const char *fmt, ...) {
char* outputStr = nullptr;
std::string getFormat(const char* fmt, ...) {
char* outputStr = nullptr;
va_list args;
va_start(args, fmt);
@@ -116,32 +115,31 @@ std::string getFormat(const char *fmt, ...) {
std::string escapeJSONStrings(const std::string& str) {
std::ostringstream oss;
for (auto &c : str) {
for (auto& c : str) {
switch (c) {
case '"': oss << "\\\""; break;
case '\\': oss << "\\\\"; break;
case '\b': oss << "\\b"; break;
case '\f': oss << "\\f"; break;
case '\n': oss << "\\n"; break;
case '\r': oss << "\\r"; break;
case '\t': oss << "\\t"; break;
default:
if ('\x00' <= c && c <= '\x1f') {
oss << "\\u"
<< std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
} else {
oss << c;
}
case '"': oss << "\\\""; break;
case '\\': oss << "\\\\"; break;
case '\b': oss << "\\b"; break;
case '\f': oss << "\\f"; break;
case '\n': oss << "\\n"; break;
case '\r': oss << "\\r"; break;
case '\t': oss << "\\t"; break;
default:
if ('\x00' <= c && c <= '\x1f') {
oss << "\\u" << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
} else {
oss << c;
}
}
}
return oss.str();
}
void scaleBox(wlr_box* box, float scale) {
box->width = std::round(box->width * scale);
box->width = std::round(box->width * scale);
box->height = std::round(box->height * scale);
box->x = std::round(box->x * scale);
box->y = std::round(box->y * scale);
box->x = std::round(box->x * scale);
box->y = std::round(box->y * scale);
}
std::string removeBeginEndSpacesTabs(std::string str) {
@@ -164,41 +162,12 @@ std::string removeBeginEndSpacesTabs(std::string str) {
}
float getPlusMinusKeywordResult(std::string source, float relative) {
float result = INT_MAX;
if (source.find_first_of("+") == 0) {
try {
if (source.contains("."))
result = relative + std::stof(source.substr(1));
else
result = relative + std::stoi(source.substr(1));
} catch (...) {
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
return INT_MAX;
}
} else if (source.find_first_of("-") == 0) {
try {
if (source.contains("."))
result = relative - std::stof(source.substr(1));
else
result = relative - std::stoi(source.substr(1));
} catch (...) {
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
return INT_MAX;
}
} else {
try {
if (source.contains("."))
result = stof(source);
else
result = stoi(source);
} catch (...) {
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
return INT_MAX;
}
try {
return relative + stof(source);
} catch (...) {
Debug::log(ERR, "Invalid arg \"%s\" in getPlusMinusKeywordResult!", source.c_str());
return INT_MAX;
}
return result;
}
bool isNumber(const std::string& str, bool allowfloat) {
@@ -234,16 +203,34 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
int result = INT_MAX;
if (in.find("special") == 0) {
outName = "special";
return SPECIAL_WORKSPACE_ID;
if (in.length() > 8) {
const auto NAME = in.substr(8);
const auto WS = g_pCompositor->getWorkspaceByName("special:" + NAME);
outName = "special:" + NAME;
return WS ? WS->m_iID : g_pCompositor->getNewSpecialID();
}
return SPECIAL_WORKSPACE_START;
} else if (in.find("name:") == 0) {
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
if (!WORKSPACE) {
result = g_pCompositor->getNextAvailableNamedWorkspace();
} else {
result = WORKSPACE->m_iID;
}
outName = WORKSPACENAME;
} else if (in.find("empty") == 0) {
int id = 0;
while (++id < INT_MAX) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
if (!PWORKSPACE || (g_pCompositor->getWindowsOnWorkspace(id) == 0))
return id;
}
} else {
if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
bool onAllMonitors = in[0] == 'e';
@@ -258,52 +245,42 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
// result now has +/- what we should move on mon
int remains = (int)result;
int currentID = g_pCompositor->m_pLastMonitor->activeWorkspace;
int searchID = currentID;
int remains = (int)result;
while (remains != 0) {
if (remains < 0)
searchID--;
else
searchID++;
std::vector<int> validWSes;
for (auto& ws : g_pCompositor->m_vWorkspaces) {
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors))
continue;
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
// means we need to wrap around
int lowestID = 99999;
int highestID = -99999;
validWSes.push_back(ws->m_iID);
}
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iID == SPECIAL_WORKSPACE_ID)
continue;
std::sort(validWSes.begin(), validWSes.end());
if (w->m_iID < lowestID)
lowestID = w->m_iID;
// get the offset
remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size();
if (w->m_iID > highestID)
highestID = w->m_iID;
}
if (remains < 0)
searchID = highestID;
else
searchID = lowestID;
}
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE && PWORKSPACE->m_iID != SPECIAL_WORKSPACE_ID) {
if (onAllMonitors || PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
currentID = PWORKSPACE->m_iID;
if (remains < 0)
remains++;
else
remains--;
}
// get the current item
int currentItem = -1;
for (size_t i = 0; i < validWSes.size(); i++) {
if (validWSes[i] == g_pCompositor->m_pLastMonitor->activeWorkspace) {
currentItem = i;
break;
}
}
result = currentID;
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
// apply
currentItem += remains;
// sanitize
if (currentItem >= (int)validWSes.size()) {
currentItem = currentItem % validWSes.size();
} else if (currentItem < 0) {
currentItem = validWSes.size() + currentItem;
}
result = validWSes[currentItem];
outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName;
} else {
if (in[0] == '+' || in[0] == '-') {
@@ -337,8 +314,8 @@ float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Ve
// Execute a shell command and get the output
std::string execAndGet(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
std::array<char, 128> buffer;
std::string result;
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
if (!pipe) {
Debug::log(ERR, "execAndGet: failed in pipe");
@@ -379,8 +356,8 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
memset(mat, 0, sizeof(*mat) * 9);
const float* t = transforms[tr];
float x = 2.0f / w;
float y = 2.0f / h;
float x = 2.0f / w;
float y = 2.0f / h;
// Rotation + reflection
mat[0] = x * t[0];
@@ -403,35 +380,35 @@ int64_t getPPIDof(int64_t pid) {
KERN_PROC,
KERN_PROC_PID,
(int)pid,
# if defined(__NetBSD__) || defined(__OpenBSD__)
#if defined(__NetBSD__) || defined(__OpenBSD__)
sizeof(KINFO_PROC),
1,
# endif
#endif
};
u_int miblen = sizeof(mib) / sizeof(mib[0]);
u_int miblen = sizeof(mib) / sizeof(mib[0]);
KINFO_PROC kp;
size_t sz = sizeof(KINFO_PROC);
size_t sz = sizeof(KINFO_PROC);
if (sysctl(mib, miblen, &kp, &sz, NULL, 0) != -1)
return KP_PPID(kp);
return 0;
#else
std::string dir = "/proc/" + std::to_string(pid) + "/status";
FILE* infile;
FILE* infile;
infile = fopen(dir.c_str(), "r");
if (!infile)
return 0;
char* line = nullptr;
size_t len = 0;
ssize_t len2 = 0;
char* line = nullptr;
size_t len = 0;
ssize_t len2 = 0;
std::string pidstr;
while ((len2 = getline(&line, &len, infile)) != -1) {
if (strstr(line, "PPid:")) {
pidstr = std::string(line, len2);
pidstr = std::string(line, len2);
const auto tabpos = pidstr.find_last_of('\t');
if (tabpos != std::string::npos)
pidstr = pidstr.substr(tabpos);
@@ -445,9 +422,7 @@ int64_t getPPIDof(int64_t pid) {
try {
return std::stoll(pidstr);
} catch (std::exception& e) {
return 0;
}
} catch (std::exception& e) { return 0; }
#endif
}
@@ -456,7 +431,7 @@ int64_t configStringToInt(const std::string& VALUE) {
// Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE.substr(2);
return stol(VALUEWITHOUTHEX, nullptr, 16);
} else if (VALUE.find("rgba(") == 0 && VALUE.find(")") == VALUE.length() - 1) {
} else if (VALUE.find("rgba(") == 0 && VALUE.find(')') == VALUE.length() - 1) {
const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6);
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 8) {
@@ -468,7 +443,7 @@ int64_t configStringToInt(const std::string& VALUE) {
// now we need to RGBA -> ARGB. The config holds ARGB only.
return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF);
} else if (VALUE.find("rgb(") == 0 && VALUE.find(")") == VALUE.length() - 1) {
} else if (VALUE.find("rgb(") == 0 && VALUE.find(')') == VALUE.length() - 1) {
const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5);
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 6) {

View File

@@ -3,20 +3,20 @@
#include "../includes.hpp"
std::string absolutePath(const std::string&, const std::string&);
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString);
std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
std::string getFormat(const char* fmt, ...); // Basically Debug::log to a string
std::string escapeJSONStrings(const std::string& str);
void scaleBox(wlr_box*, float);
void scaleBox(wlr_box*, float);
std::string removeBeginEndSpacesTabs(std::string);
bool isNumber(const std::string&, bool allowfloat = false);
bool isDirection(const std::string&);
int getWorkspaceIDFromString(const std::string&, std::string&);
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
void logSystemInfo();
bool isNumber(const std::string&, bool allowfloat = false);
bool isDirection(const std::string&);
int getWorkspaceIDFromString(const std::string&, std::string&);
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
void logSystemInfo();
std::string execAndGet(const char*);
int64_t getPPIDof(int64_t pid);
int64_t configStringToInt(const std::string&);
int64_t getPPIDof(int64_t pid);
int64_t configStringToInt(const std::string&);
float getPlusMinusKeywordResult(std::string in, float relative);
float getPlusMinusKeywordResult(std::string in, float relative);
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);

View File

@@ -3,8 +3,18 @@
#include "../Compositor.hpp"
void CMonitor::onConnect(bool noRule) {
if (m_bEnabled)
hyprListener_monitorDestroy.removeCallback();
hyprListener_monitorFrame.removeCallback();
hyprListener_monitorStateRequest.removeCallback();
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
hyprListener_monitorStateRequest.initCallback(&output->events.request_state, &Events::listener_monitorStateRequest, this);
if (m_bEnabled) {
wlr_output_enable(output, 1);
wlr_output_commit(output);
return;
}
szName = output->name;
@@ -14,13 +24,9 @@ void CMonitor::onConnect(bool noRule) {
// get monitor rule that matches
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name, output->description ? output->description : "");
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
// if it's disabled, disable and ignore
if (monitorRule.disabled) {
wlr_output_enable_adaptive_sync(output, 1);
wlr_output_set_scale(output, 1);
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
@@ -61,15 +67,15 @@ void CMonitor::onConnect(bool noRule) {
if (output->non_desktop) {
Debug::log(LOG, "Not configuring non-desktop output");
if (g_pCompositor->m_sWRLDRMLeaseMgr) {
wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output);
}
return;
}
if (g_pCompositor->m_sWRLDRMLeaseMgr) {
wlr_drm_lease_v1_manager_offer_output(g_pCompositor->m_sWRLDRMLeaseMgr, output);
}
return;
}
if (!m_bRenderingInitPassed) {
output->allocator = nullptr;
output->renderer = nullptr;
output->renderer = nullptr;
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
m_bRenderingInitPassed = true;
}
@@ -85,19 +91,15 @@ void CMonitor::onConnect(bool noRule) {
}
}
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()){
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
}
m_bEnabled = true;
wlr_output_set_scale(output, monitorRule.scale);
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale);
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: support other transforms
// create it in the arr
vecPosition = monitorRule.offset;
vecSize = monitorRule.resolution;
vecSize = monitorRule.resolution;
refreshRate = monitorRule.refreshRate;
wlr_output_enable(output, 1);
@@ -106,7 +108,10 @@ void CMonitor::onConnect(bool noRule) {
if (!noRule)
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %x", output->name, (int)vecPosition.x, (int)vecPosition.y, (int)vecPixelSize.x, (int)vecPixelSize.y, output);
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
Debug::log(LOG, "Added new monitor with name %s at %i,%i with size %ix%i, pointer %x", output->name, (int)vecPosition.x, (int)vecPosition.y, (int)vecPixelSize.x,
(int)vecPixelSize.y, output);
damage = wlr_output_damage_create(output);
@@ -123,21 +128,33 @@ void CMonitor::onConnect(bool noRule) {
m_pThisWrap = nullptr;
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
//
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->m_pLastMonitor = this;
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->setActiveMonitor(this);
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
g_pHyprRenderer->arrangeLayersForMonitor(ID);
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
// ensure VRR (will enable if necessary)
g_pConfigManager->ensureVRR(this);
// verify last mon valid
bool found = false;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m.get() == g_pCompositor->m_pLastMonitor) {
found = true;
break;
}
}
if (!found)
g_pCompositor->setActiveMonitor(this);
}
void CMonitor::onDisconnect() {
@@ -145,6 +162,8 @@ void CMonitor::onDisconnect() {
if (!m_bEnabled || g_pCompositor->m_bIsShuttingDown)
return;
Debug::log(LOG, "onDisconnect called for %s", output->name);
// Cleanup everything. Move windows back, snap cursor, shit.
CMonitor* BACKUPMON = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) {
@@ -154,9 +173,6 @@ void CMonitor::onDisconnect() {
}
}
if (g_pCompositor->m_pLastMonitor == this)
g_pCompositor->m_pLastMonitor = BACKUPMON;
// remove mirror
if (pMirrorOf) {
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
@@ -171,15 +187,22 @@ void CMonitor::onDisconnect() {
g_pConfigManager->m_bWantsMonitorReload = true;
}
m_bEnabled = false;
m_bEnabled = false;
m_bRenderingInitPassed = false;
hyprListener_monitorFrame.removeCallback();
for (size_t i = 0; i < 4; ++i) {
for (auto& ls : m_aLayerSurfaceLists[i]) {
wlr_layer_surface_v1_destroy(ls->layerSurface);
}
m_aLayerSurfaceLists[i].clear();
}
if (!BACKUPMON) {
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
hyprListener_monitorMode.removeCallback();
hyprListener_monitorStateRequest.removeCallback();
hyprListener_monitorDestroy.removeCallback();
g_pCompositor->m_bUnsafeState = true;
@@ -187,10 +210,9 @@ void CMonitor::onDisconnect() {
return;
}
const auto BACKUPWORKSPACE = BACKUPMON->activeWorkspace > 0 ? std::to_string(BACKUPMON->activeWorkspace) : "name:" + g_pCompositor->getWorkspaceByID(BACKUPMON->activeWorkspace)->m_szName;
// snap cursor
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f,
BACKUPMON->vecPosition.y + BACKUPMON->vecTransformedSize.y / 2.f);
// move workspaces
std::deque<CWorkspace*> wspToMove;
@@ -215,13 +237,30 @@ void CMonitor::onDisconnect() {
wlr_output_commit(output);
g_pCompositor->m_vWorkspaces.erase(std::remove_if(g_pCompositor->m_vWorkspaces.begin(), g_pCompositor->m_vWorkspaces.end(), [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == ID; }));
std::erase_if(g_pCompositor->m_vWorkspaces, [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == ID; });
Debug::log(LOG, "Removed monitor %s!", szName.c_str());
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](std::shared_ptr<CMonitor>& el) { return el.get() == this; }));
if (g_pCompositor->m_pLastMonitor == this)
g_pCompositor->setActiveMonitor(BACKUPMON);
if (g_pHyprRenderer->m_pMostHzMonitor == this) {
int mostHz = 0;
CMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz && m.get() != this) {
pMonitorMostHz = m.get();
mostHz = m->refreshRate;
}
}
g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz;
}
std::erase_if(g_pCompositor->m_vMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == this; });
}
void CMonitor::addDamage(pixman_region32_t* rg) {
@@ -236,13 +275,27 @@ bool CMonitor::isMirror() {
return pMirrorOf != nullptr;
}
int CMonitor::findAvailableDefaultWS() {
for (size_t i = 1; i < INT32_MAX; ++i) {
if (g_pCompositor->getWorkspaceByID(i))
continue;
if (const auto BOUND = g_pConfigManager->getBoundMonitorStringForWS(std::to_string(i)); !BOUND.empty() && BOUND != szName)
continue;
return i;
}
return INT32_MAX; // shouldn't be reachable
}
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
// Workspace
std::string newDefaultWorkspaceName = "";
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
int64_t WORKSPACEID = monitorRule.defaultWorkspace == "" ? findAvailableDefaultWS() : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
if (WORKSPACEID == INT_MAX || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) {
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
@@ -317,13 +370,14 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
}
}
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) ==
g_pCompositor->m_vMonitors.end()) {
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
}
setupDefaultWS(RULE);
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, (int)vecPosition.x, (int)vecPosition.y);
g_pHyprRenderer->applyMonitorRule(this, (SMonitorRule*)&RULE, true); // will apply the offset and stuff
} else {
CMonitor* BACKUPMON = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) {
@@ -357,10 +411,28 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
pMirrorOf->mirrors.push_back(this);
// remove from mvmonitors
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) != g_pCompositor->m_vMonitors.end()) {
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return other.get() == this; }));
}
std::erase_if(g_pCompositor->m_vMonitors, [&](const auto& other) { return other.get() == this; });
g_pCompositor->m_pLastMonitor = g_pCompositor->m_vMonitors.front().get();
g_pCompositor->setActiveMonitor(g_pCompositor->m_vMonitors.front().get());
g_pCompositor->sanityCheckWorkspaces();
}
}
float CMonitor::getDefaultScale() {
if (!m_bEnabled)
return 1;
static constexpr double MMPERINCH = 25.4;
const auto DIAGONALPX = sqrt(pow(vecPixelSize.x, 2) + pow(vecPixelSize.y, 2));
const auto DIAGONALIN = sqrt(pow(output->phys_width / MMPERINCH, 2) + pow(output->phys_height / MMPERINCH, 2));
const auto PPI = DIAGONALPX / DIAGONALIN;
if (PPI > 200 /* High PPI, 2x*/)
return 2;
else if (PPI > 140 /* Medium PPI, 1.5x*/)
return 1.5;
return 1;
}

View File

@@ -10,70 +10,70 @@
struct SMonitorRule;
class CMonitor {
public:
Vector2D vecPosition = Vector2D(-1,-1); // means unset
Vector2D vecSize = Vector2D(0,0);
Vector2D vecPixelSize = Vector2D(0,0);
Vector2D vecTransformedSize = Vector2D(0,0);
public:
Vector2D vecPosition = Vector2D(-1, -1); // means unset
Vector2D vecSize = Vector2D(0, 0);
Vector2D vecPixelSize = Vector2D(0, 0);
Vector2D vecTransformedSize = Vector2D(0, 0);
bool primary = false;
bool primary = false;
uint64_t ID = -1;
int activeWorkspace = -1;
float scale = 1;
float scale = 1;
std::string szName = "";
std::string szName = "";
Vector2D vecReservedTopLeft = Vector2D(0,0);
Vector2D vecReservedBottomRight = Vector2D(0,0);
Vector2D vecReservedTopLeft = Vector2D(0, 0);
Vector2D vecReservedBottomRight = Vector2D(0, 0);
// WLR stuff
wlr_output* output = nullptr;
float refreshRate = 60;
wlr_output_damage* damage = nullptr;
int framesToSkip = 0;
int forceFullFrames = 0;
bool noFrameSchedule = false;
bool scheduledRecalc = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
wlr_output* output = nullptr;
float refreshRate = 60;
wlr_output_damage* damage = nullptr;
int framesToSkip = 0;
int forceFullFrames = 0;
bool noFrameSchedule = false;
bool scheduledRecalc = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
bool dpmsStatus = true;
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
bool createdByUser = false;
bool dpmsStatus = true;
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
bool createdByUser = false;
// mirroring
CMonitor* pMirrorOf = nullptr;
CMonitor* pMirrorOf = nullptr;
std::vector<CMonitor*> mirrors;
// for the special workspace
bool specialWorkspaceOpen = false;
// for the special workspace. 0 means not open.
int specialWorkspaceID = 0;
// Double-linked list because we need to have constant mem addresses for signals
// We have to store pointers and use raw new/delete because they might be moved between them
// and I am lazy
std::array<std::vector<std::unique_ptr<SLayerSurface>>, 4> m_aLayerSurfaceLists;
std::array<std::vector<std::unique_ptr<SLayerSurface>>, 4> m_aLayerSurfaceLists;
DYNLISTENER(monitorFrame);
DYNLISTENER(monitorDestroy);
DYNLISTENER(monitorMode);
DYNLISTENER(monitorStateRequest);
// hack: a group = workspaces on a monitor.
// I don't really care lol :P
wlr_ext_workspace_group_handle_v1* pWLRWorkspaceGroupHandle = nullptr;
// methods
void onConnect(bool noRule);
void onDisconnect();
void addDamage(pixman_region32_t* rg);
void addDamage(wlr_box* box);
void setMirror(const std::string&);
bool isMirror();
void onConnect(bool noRule);
void onDisconnect();
void addDamage(pixman_region32_t* rg);
void addDamage(wlr_box* box);
void setMirror(const std::string&);
bool isMirror();
float getDefaultScale();
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
bool m_bEnabled = false;
bool m_bRenderingInitPassed = false;
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
bool m_bEnabled = false;
bool m_bRenderingInitPassed = false;
// For the list lookup
@@ -81,6 +81,7 @@ public:
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
}
private:
void setupDefaultWS(const SMonitorRule&);
private:
void setupDefaultWS(const SMonitorRule&);
int findAvailableDefaultWS();
};

View File

@@ -48,6 +48,13 @@ inline const std::vector<std::string> SPLASHES = {
"Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm",
"Súbeme la radio que esta es mi canción",
"I'm beggin', beggin' you",
"Never gonna let you down (I am trying!)",
"\"I use Arch, btw\" - John Cena",
"\"Hyper\".replace(\"e\", \"\")",
"\"my win11 install runs hyprland that is true\" - raf",
"\"stop playing league loser\" - hyprBot",
"\"If it ain't broke, don't fix it\" - Lucascito_03",
"\"@vaxry how do i learn c++\" - flicko",
//
"Join the discord server!",
"Thanks ThatOneCalculator!",

View File

@@ -3,8 +3,8 @@
#include "../Compositor.hpp"
void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
*lx += node->pSurface->sx;
*ly += node->pSurface->sy;
*lx += node->pSurface->current.dx;
*ly += node->pSurface->current.dy;
if (node->offsetfn) {
// This is the root node
@@ -23,7 +23,7 @@ void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.emplace_back();
PNODE->pSurface = pSurface;
PNODE->pSurface = pSurface;
PNODE->pWindowOwner = pWindow;
PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode");
@@ -42,8 +42,8 @@ SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
}
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) {
const auto PNODE = createTree(surface, pWindow);
PNODE->pParent = pParent;
const auto PNODE = createTree(surface, pWindow);
PNODE->pParent = pParent;
PNODE->pSubsurface = pSubsurface;
Debug::log(LOG, "Creating a subsurface Node! (pWindow: %x)", pWindow);
@@ -56,7 +56,7 @@ SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlo
Debug::log(LOG, "Creating a surfaceTree Root! (pWindow: %x)", pWindow);
PNODE->offsetfn = fn;
PNODE->offsetfn = fn;
PNODE->globalOffsetData = data;
return PNODE;
@@ -74,8 +74,8 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
}
if (!exists) {
Debug::log(ERR, "Tried to remove a SurfaceTreeNode that doesn't exist?? (Node %x)", pNode);
return;
Debug::log(ERR, "Tried to remove a SurfaceTreeNode that doesn't exist?? (Node %x)", pNode);
return;
}
for (auto& c : pNode->childSubsurfaces)
@@ -132,14 +132,14 @@ void destroySubsurface(SSubsurface* pSubsurface) {
void Events::listener_newSubsurfaceNode(void* owner, void* data) {
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
const auto PSUBSURFACE = (wlr_subsurface*)data;
const auto PSUBSURFACE = (wlr_subsurface*)data;
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.emplace_back();
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.emplace_back();
Debug::log(LOG, "Added a new subsurface %x", PSUBSURFACE);
PNEWSUBSURFACE->pSubsurface = PSUBSURFACE;
PNEWSUBSURFACE->pParent = pNode;
PNEWSUBSURFACE->pParent = pNode;
PNEWSUBSURFACE->hyprListener_map.initCallback(&PSUBSURFACE->events.map, &Events::listener_mapSubsurface, PNEWSUBSURFACE, "Subsurface");
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
@@ -178,7 +178,8 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
if (subsurface->pChild) {
const auto PNODE = subsurface->pChild;
const auto IT = std::find_if(SubsurfaceTree::surfaceTreeNodes.begin(), SubsurfaceTree::surfaceTreeNodes.end(), [&](const SSurfaceTreeNode& other) { return &other == PNODE; });
const auto IT =
std::find_if(SubsurfaceTree::surfaceTreeNodes.begin(), SubsurfaceTree::surfaceTreeNodes.end(), [&](const SSurfaceTreeNode& other) { return &other == PNODE; });
if (IT != SubsurfaceTree::surfaceTreeNodes.end()) {
int lx = 0, ly = 0;
@@ -186,7 +187,7 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
wlr_box extents = {lx, ly, 0, 0};
if (PNODE->pSurface) {
extents.width = PNODE->pSurface->current.width;
extents.width = PNODE->pSurface->current.width;
extents.height = PNODE->pSurface->current.height;
g_pHyprRenderer->damageBox(&extents);
@@ -203,7 +204,7 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
// no damaging if it's not visible
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Refusing to commit damage from %x because it's invisible.", pNode->pWindowOwner);
return;
@@ -216,13 +217,14 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
// I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox)
// What this does is that basically, if the pNode is a child of some other node, on commit,
// it will also damage (check & damage if needed) all its siblings.
if (pNode->pParent) for (auto& cs : pNode->pParent->childSubsurfaces) {
const auto NODECOORDS = pNode->pSubsurface ? Vector2D(pNode->pSubsurface->pSubsurface->current.x, pNode->pSubsurface->pSubsurface->current.y) : Vector2D();
if (pNode->pParent)
for (auto& cs : pNode->pParent->childSubsurfaces) {
const auto NODECOORDS = pNode->pSubsurface ? Vector2D(pNode->pSubsurface->pSubsurface->current.x, pNode->pSubsurface->pSubsurface->current.y) : Vector2D();
if (&cs != pNode->pSubsurface && cs.pSubsurface) {
g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y);
if (&cs != pNode->pSubsurface && cs.pSubsurface) {
g_pHyprRenderer->damageSurface(cs.pSubsurface->surface, lx - NODECOORDS.x + cs.pSubsurface->current.x, ly - NODECOORDS.y + cs.pSubsurface->current.y);
}
}
}
g_pHyprRenderer->damageSurface(pNode->pSurface, lx, ly);
}

View File

@@ -6,49 +6,49 @@
struct SSubsurface;
class CWindow;
typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
typedef void (*applyGlobalOffsetFn)(void*, int*, int*);
struct SSurfaceTreeNode {
wlr_surface* pSurface = nullptr;
wlr_surface* pSurface = nullptr;
DYNLISTENER(newSubsurface);
DYNLISTENER(commit);
DYNLISTENER(destroy);
SSurfaceTreeNode* pParent = nullptr;
SSubsurface* pSubsurface = nullptr;
SSurfaceTreeNode* pParent = nullptr;
SSubsurface* pSubsurface = nullptr;
std::list<SSubsurface> childSubsurfaces;
applyGlobalOffsetFn offsetfn;
void *globalOffsetData;
CWindow* pWindowOwner = nullptr;
applyGlobalOffsetFn offsetfn;
void* globalOffsetData;
CWindow* pWindowOwner = nullptr;
bool operator==(const SSurfaceTreeNode& rhs) {
bool operator==(const SSurfaceTreeNode& rhs) {
return pSurface == rhs.pSurface;
}
};
struct SSubsurface {
wlr_subsurface* pSubsurface = nullptr;
wlr_subsurface* pSubsurface = nullptr;
SSurfaceTreeNode* pParent = nullptr;
SSurfaceTreeNode* pChild = nullptr;
SSurfaceTreeNode* pParent = nullptr;
SSurfaceTreeNode* pChild = nullptr;
DYNLISTENER(map);
DYNLISTENER(unmap);
DYNLISTENER(destroy);
CWindow* pWindowOwner = nullptr;
CWindow* pWindowOwner = nullptr;
bool operator==(const SSubsurface& rhs) {
bool operator==(const SSubsurface& rhs) {
return pSubsurface == rhs.pSubsurface;
}
};
namespace SubsurfaceTree {
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr);
void destroySurfaceTree(SSurfaceTreeNode*);
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr);
void destroySurfaceTree(SSurfaceTreeNode*);
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
};

View File

@@ -3,13 +3,13 @@
#include "../defines.hpp"
class CTimer {
public:
void reset();
float getSeconds();
int getMillis();
public:
void reset();
float getSeconds();
int getMillis();
private:
private:
std::chrono::system_clock::time_point m_tpLastReset;
std::chrono::system_clock::duration getDuration();
std::chrono::system_clock::duration getDuration();
};

View File

@@ -6,7 +6,11 @@ Vector2D::Vector2D(double xx, double yy) {
y = yy;
}
Vector2D::Vector2D() { x = 0; y = 0; }
Vector2D::Vector2D() {
x = 0;
y = 0;
}
Vector2D::~Vector2D() {}
double Vector2D::normalize() {
@@ -24,8 +28,5 @@ Vector2D Vector2D::floor() {
}
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) {
return Vector2D(
std::clamp(this->x, min.x, max.x == 0 ? INFINITY : max.x),
std::clamp(this->y, min.y, max.y == 0 ? INFINITY : max.y)
);
return Vector2D(std::clamp(this->x, min.x, max.x == 0 ? INFINITY : max.x), std::clamp(this->y, min.y, max.y == 0 ? INFINITY : max.y));
}

View File

@@ -3,7 +3,7 @@
#include <math.h>
class Vector2D {
public:
public:
Vector2D(double, double);
Vector2D();
~Vector2D();
@@ -12,18 +12,18 @@ class Vector2D {
double y = 0;
// returns the scale
double normalize();
double normalize();
Vector2D operator+(const Vector2D a) const {
Vector2D operator+(const Vector2D& a) const {
return Vector2D(this->x + a.x, this->y + a.y);
}
Vector2D operator-(const Vector2D a) const {
Vector2D operator-(const Vector2D& a) const {
return Vector2D(this->x - a.x, this->y - a.y);
}
Vector2D operator*(const float a) const {
Vector2D operator*(const float& a) const {
return Vector2D(this->x * a, this->y * a);
}
Vector2D operator/(const float a) const {
Vector2D operator/(const float& a) const {
return Vector2D(this->x / a, this->y / a);
}

View File

@@ -10,8 +10,8 @@
struct SLayerSurface {
SLayerSurface();
wlr_layer_surface_v1* layerSurface;
wl_list link;
wlr_layer_surface_v1* layerSurface;
wl_list link;
DYNLISTENER(destroyLayerSurface);
DYNLISTENER(mapLayerSurface);
@@ -19,22 +19,22 @@ struct SLayerSurface {
DYNLISTENER(commitLayerSurface);
DYNLISTENER(newPopup);
wlr_box geometry = {0,0,0,0};
Vector2D position;
wlr_box geometry = {0, 0, 0, 0};
Vector2D position;
zwlr_layer_shell_v1_layer layer;
bool mapped = false;
bool mapped = false;
int monitorID = -1;
int monitorID = -1;
std::string szNamespace = "";
std::string szNamespace = "";
CAnimatedVariable alpha;
bool fadingOut = false;
bool readyToDelete = false;
bool noProcess = false;
CAnimatedVariable alpha;
bool fadingOut = false;
bool readyToDelete = false;
bool noProcess = false;
bool forceBlur = false;
bool forceBlur = false;
// For the list lookup
bool operator==(const SLayerSurface& rhs) {
@@ -44,20 +44,20 @@ struct SLayerSurface {
struct SRenderData {
wlr_output* output;
timespec* when;
int x, y;
timespec* when;
int x, y;
// for iters
void* data = nullptr;
void* data = nullptr;
wlr_surface* surface = nullptr;
int w, h;
void* pMonitor = nullptr;
int w, h;
void* pMonitor = nullptr;
// for rounding
bool dontRound = true;
// for fade
float fadeAlpha = 255.f;
float fadeAlpha = 1.f;
// for alpha settings
float alpha = 1.f;
@@ -69,7 +69,8 @@ struct SRenderData {
int rounding = -1; // -1 means not set
// for blurring
bool blur = false;
bool blur = false;
bool blockBlurOptimization = false;
// only for windows, not popups
bool squishOversized = true;
@@ -79,17 +80,17 @@ struct SRenderData {
};
struct SExtensionFindingData {
Vector2D origin;
Vector2D vec;
Vector2D origin;
Vector2D vec;
wlr_surface** found;
};
struct SStringRuleNames {
std::string layout = "";
std::string model = "";
std::string layout = "";
std::string model = "";
std::string variant = "";
std::string options = "";
std::string rules = "";
std::string rules = "";
};
struct SKeyboard {
@@ -100,18 +101,19 @@ struct SKeyboard {
DYNLISTENER(keyboardKeymap);
DYNLISTENER(keyboardDestroy);
bool isVirtual = false;
bool active = false;
bool isVirtual = false;
bool active = false;
bool enabled = true;
xkb_layout_index_t activeLayout = 0;
std::string name = "";
std::string xkbFilePath = "";
std::string name = "";
std::string xkbFilePath = "";
SStringRuleNames currentRules;
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
SStringRuleNames currentRules;
int repeatRate = 0;
int repeatDelay = 0;
int numlockOn = -1;
// For the list lookup
bool operator==(const SKeyboard& rhs) {
@@ -120,18 +122,18 @@ struct SKeyboard {
};
struct SMouse {
wlr_input_device* mouse = nullptr;
wlr_input_device* mouse = nullptr;
wlr_pointer_constraint_v1* currentConstraint = nullptr;
bool constraintActive = false;
bool constraintActive = false;
pixman_region32_t confinedTo;
pixman_region32_t confinedTo;
std::string name = "";
std::string name = "";
bool virt = false;
bool virt = false;
bool connected = false; // means connected to the cursor
bool connected = false; // means connected to the cursor
DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse);
@@ -142,9 +144,12 @@ struct SMouse {
};
struct SConstraint {
SMouse* pMouse = nullptr;
SMouse* pMouse = nullptr;
wlr_pointer_constraint_v1* constraint = nullptr;
bool hintSet = false;
Vector2D positionHint; // the position hint, but will be set to the current cursor pos if not set.
DYNLISTENER(setConstraintRegion);
DYNLISTENER(destroyConstraint);
@@ -156,10 +161,10 @@ struct SConstraint {
class CMonitor;
struct SXDGPopup {
CWindow* parentWindow = nullptr;
SXDGPopup* parentPopup = nullptr;
wlr_xdg_popup* popup = nullptr;
CMonitor* monitor = nullptr;
CWindow* parentWindow = nullptr;
SXDGPopup* parentPopup = nullptr;
wlr_xdg_popup* popup = nullptr;
CMonitor* monitor = nullptr;
DYNLISTENER(newPopupFromPopupXDG);
DYNLISTENER(destroyPopupXDG);
@@ -167,8 +172,8 @@ struct SXDGPopup {
DYNLISTENER(unmapPopupXDG);
DYNLISTENER(commitPopupXDG);
double lx;
double ly;
double lx;
double ly;
SSurfaceTreeNode* pSurfaceTree = nullptr;
@@ -179,24 +184,24 @@ struct SXDGPopup {
};
struct SSeat {
wlr_seat* seat = nullptr;
wl_client* exclusiveClient = nullptr;
wlr_seat* seat = nullptr;
wl_client* exclusiveClient = nullptr;
SMouse* mouse = nullptr;
SMouse* mouse = nullptr;
};
struct SDrag {
wlr_drag* drag = nullptr;
wlr_drag* drag = nullptr;
DYNLISTENER(destroy);
// Icon
bool iconMapped = false;
bool iconMapped = false;
wlr_drag_icon* dragIcon = nullptr;
wlr_drag_icon* dragIcon = nullptr;
Vector2D pos;
Vector2D pos;
DYNLISTENER(destroyIcon);
DYNLISTENER(mapIcon);
@@ -211,31 +216,31 @@ struct STablet {
DYNLISTENER(Proximity);
DYNLISTENER(Destroy);
wlr_tablet* wlrTablet = nullptr;
wlr_tablet* wlrTablet = nullptr;
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
wlr_input_device* wlrDevice = nullptr;
wlr_input_device* wlrDevice = nullptr;
std::string name = "";
std::string name = "";
bool operator==(const STablet& b) {
bool operator==(const STablet& b) {
return wlrDevice == b.wlrDevice;
}
};
struct STabletTool {
wlr_tablet_tool* wlrTabletTool = nullptr;
wlr_tablet_tool* wlrTabletTool = nullptr;
wlr_tablet_v2_tablet_tool* wlrTabletToolV2 = nullptr;
wlr_tablet_v2_tablet* wlrTabletOwnerV2 = nullptr;
wlr_tablet_v2_tablet* wlrTabletOwnerV2 = nullptr;
wlr_surface* pSurface = nullptr;
wlr_surface* pSurface = nullptr;
double tiltX = 0;
double tiltY = 0;
double tiltX = 0;
double tiltY = 0;
bool active = true;
bool active = true;
std::string name = "";
std::string name = "";
DYNLISTENER(TabletToolDestroy);
DYNLISTENER(TabletToolSetCursor);
@@ -247,9 +252,10 @@ struct STabletTool {
struct STabletPad {
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
STablet* pTabletParent = nullptr;
STablet* pTabletParent = nullptr;
wlr_input_device* pWlrDevice = nullptr;
std::string name = "";
std::string name = "";
DYNLISTENER(Attach);
DYNLISTENER(Button);
@@ -264,7 +270,7 @@ struct STabletPad {
struct SIdleInhibitor {
wlr_idle_inhibitor_v1* pWlrInhibitor = nullptr;
CWindow* pWindow = nullptr;
CWindow* pWindow = nullptr;
DYNLISTENER(Destroy);
@@ -274,20 +280,20 @@ struct SIdleInhibitor {
};
struct SSwipeGesture {
CWorkspace* pWorkspaceBegin = nullptr;
CWorkspace* pWorkspaceBegin = nullptr;
double delta = 0;
double delta = 0;
float avgSpeed = 0;
int speedPoints = 0;
float avgSpeed = 0;
int speedPoints = 0;
CMonitor* pMonitor = nullptr;
CMonitor* pMonitor = nullptr;
};
struct STextInput {
wlr_text_input_v3* pWlrInput = nullptr;
wlr_surface* pPendingSurface = nullptr;
wlr_surface* pPendingSurface = nullptr;
DYNLISTENER(textInputEnable);
DYNLISTENER(textInputDisable);
@@ -300,7 +306,7 @@ struct STextInput {
struct SIMEKbGrab {
wlr_input_method_keyboard_grab_v2* pWlrKbGrab = nullptr;
wlr_keyboard* pKeyboard = nullptr;
wlr_keyboard* pKeyboard = nullptr;
DYNLISTENER(grabDestroy);
};
@@ -308,10 +314,10 @@ struct SIMEKbGrab {
struct SIMEPopup {
wlr_input_popup_surface_v2* pSurface = nullptr;
int x, y;
int realX, realY;
bool visible;
Vector2D lastSize;
int x, y;
int realX, realY;
bool visible;
Vector2D lastSize;
DYNLISTENER(mapPopup);
DYNLISTENER(unmapPopup);
@@ -328,9 +334,9 @@ struct SIMEPopup {
struct STouchDevice {
wlr_input_device* pWlrDevice = nullptr;
std::string name = "";
std::string name = "";
std::string boundOutput = "";
std::string boundOutput = "";
DYNLISTENER(destroy);

View File

@@ -14,7 +14,7 @@ CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, v
}
CHyprWLListener::CHyprWLListener() {
m_swWrapper.m_pSelf = this;
m_swWrapper.m_pSelf = this;
m_swWrapper.m_sListener.notify = &handleWrapped;
wl_list_init(&m_swWrapper.m_sListener.link);
}
@@ -41,9 +41,9 @@ void CHyprWLListener::initCallback(wl_signal* pSignal, std::function<void(void*,
return;
}
m_pOwner = pOwner;
m_pOwner = pOwner;
m_pCallback = callback;
m_szAuthor = author;
m_szAuthor = author;
addWLSignal(pSignal, &m_swWrapper.m_sListener, pOwner, m_szAuthor);
}

View File

@@ -4,35 +4,35 @@
#include <functional>
class CHyprWLListener {
public:
public:
CHyprWLListener(wl_signal*, std::function<void(void*, void*)>, void* owner);
CHyprWLListener();
~CHyprWLListener();
CHyprWLListener(const CHyprWLListener&) = delete;
CHyprWLListener(CHyprWLListener&&) = delete;
CHyprWLListener(CHyprWLListener&&) = delete;
CHyprWLListener& operator=(const CHyprWLListener&) = delete;
CHyprWLListener& operator=(CHyprWLListener&&) = delete;
void initCallback(wl_signal*, std::function<void(void*, void*)>, void* owner, std::string author = "");
void initCallback(wl_signal*, std::function<void(void*, void*)>, void* owner, std::string author = "");
void removeCallback();
void removeCallback();
bool isConnected();
bool isConnected();
struct SWrapper {
wl_listener m_sListener;
wl_listener m_sListener;
CHyprWLListener* m_pSelf;
};
void emit(void*);
private:
SWrapper m_swWrapper;
private:
SWrapper m_swWrapper;
void* m_pOwner = nullptr;
void* m_pOwner = nullptr;
std::function<void(void*, void*)> m_pCallback = nullptr;
std::string m_szAuthor = "";
std::string m_szAuthor = "";
};

View File

@@ -9,8 +9,8 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
return;
}
m_iMonitorID = monitorID;
m_szName = name;
m_iMonitorID = monitorID;
m_szName = name;
m_bIsSpecialWorkspace = special;
if (!special) {
@@ -26,10 +26,12 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
}
m_vRenderOffset.m_pWorkspace = this;
m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), nullptr, AVARDAMAGE_ENTIRE);
m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
nullptr, AVARDAMAGE_ENTIRE);
m_fAlpha.m_pWorkspace = this;
m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), nullptr, AVARDAMAGE_ENTIRE);
m_fAlpha.setValueAndWarp(255.f);
m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"),
nullptr, AVARDAMAGE_ENTIRE);
m_fAlpha.setValueAndWarp(1.f);
m_vRenderOffset.registerVar();
m_fAlpha.registerVar();
@@ -59,16 +61,16 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
if (in) {
m_fAlpha.setValueAndWarp(0.f);
m_fAlpha = 255.f;
m_fAlpha = 1.f;
} else {
m_fAlpha.setValueAndWarp(255.f);
m_fAlpha.setValueAndWarp(1.f);
m_fAlpha = 0.f;
}
} else if (ANIMSTYLE == "slidevert") {
// fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
m_fAlpha.setValueAndWarp(255.f); // fix a bug, if switching from fade -> slide.
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y));
@@ -80,7 +82,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
// fallback is slide
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
m_fAlpha.setValueAndWarp(255.f); // fix a bug, if switching from fade -> slide.
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x, 0));
@@ -96,11 +98,11 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
}
// check LS-es
if (in) {
if (in && !m_bIsSpecialWorkspace) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (!ls->fadingOut)
ls->alpha = m_bHasFullscreenWindow && m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 255.f;
ls->alpha = m_bHasFullscreenWindow && m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 1.f;
}
}
}

View File

@@ -3,7 +3,8 @@
#include "../defines.hpp"
#include "AnimatedVariable.hpp"
enum eFullscreenMode : uint8_t {
enum eFullscreenMode : uint8_t
{
FULLSCREEN_FULL = 0,
FULLSCREEN_MAXIMIZED
};
@@ -11,24 +12,24 @@ enum eFullscreenMode : uint8_t {
class CWindow;
class CWorkspace {
public:
public:
CWorkspace(int monitorID, std::string name, bool special = false);
~CWorkspace();
// Workspaces ID-based have IDs > 0
// and workspaces name-based have IDs starting with -1337
int m_iID = -1;
std::string m_szName = "";
uint64_t m_iMonitorID = -1;
int m_iID = -1;
std::string m_szName = "";
uint64_t m_iMonitorID = -1;
// Previous workspace ID is stored during a workspace change, allowing travel
// to the previous workspace.
int m_iPrevWorkspaceID = -1;
bool m_bHasFullscreenWindow = false;
eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL;
int m_iPrevWorkspaceID = -1;
bool m_bHasFullscreenWindow = false;
eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL;
wlr_ext_workspace_handle_v1* m_pWlrHandle = nullptr;
wl_array m_wlrCoordinateArr;
wl_array m_wlrCoordinateArr;
// for animations
CAnimatedVariable m_vRenderOffset;
@@ -36,19 +37,19 @@ public:
bool m_bForceRendering = false;
// "scratchpad"
bool m_bIsSpecialWorkspace = false;
bool m_bIsSpecialWorkspace = false;
// last window
CWindow* m_pLastFocusedWindow = nullptr;
CWindow* m_pLastFocusedWindow = nullptr;
// user-set
bool m_bDefaultFloating = false;
bool m_bDefaultPseudo = false;
bool m_bDefaultFloating = false;
bool m_bDefaultPseudo = false;
void startAnim(bool in, bool left, bool instant = false);
void setActive(bool on);
void startAnim(bool in, bool left, bool instant = false);
void setActive(bool on);
void moveToMonitor(const int&);
void moveToMonitor(const int&);
CWindow* getLastFocusedWindow();
CWindow* getLastFocusedWindow();
};

View File

@@ -28,68 +28,69 @@ typedef struct {
} xcb_size_hints_t;
typedef unsigned int xcb_window_t;
typedef enum xcb_stack_mode_t {
XCB_STACK_MODE_ABOVE = 0,
XCB_STACK_MODE_BELOW = 1,
XCB_STACK_MODE_TOP_IF = 2,
typedef enum xcb_stack_mode_t
{
XCB_STACK_MODE_ABOVE = 0,
XCB_STACK_MODE_BELOW = 1,
XCB_STACK_MODE_TOP_IF = 2,
XCB_STACK_MODE_BOTTOM_IF = 3,
XCB_STACK_MODE_OPPOSITE = 4
XCB_STACK_MODE_OPPOSITE = 4
} xcb_stack_mode_t;
struct wlr_xwayland {
struct wlr_xwayland_server *server;
struct wlr_xwm *xwm;
struct wlr_xwayland_cursor *cursor;
struct wlr_xwayland_server* server;
struct wlr_xwm* xwm;
struct wlr_xwayland_cursor* cursor;
const char *display_name;
const char* display_name;
struct wl_display *wl_display;
struct wlr_compositor *compositor;
struct wlr_seat *seat;
struct wl_display* wl_display;
struct wlr_compositor* compositor;
struct wlr_seat* seat;
void *data;
void* data;
};
struct wlr_xwayland_surface {
xcb_window_t window_id;
struct wlr_xwm *xwm;
uint32_t surface_id;
xcb_window_t window_id;
struct wlr_xwm* xwm;
uint32_t surface_id;
struct wl_list link;
struct wl_list stack_link;
struct wl_list unpaired_link;
struct wl_list link;
struct wl_list stack_link;
struct wl_list unpaired_link;
struct wlr_surface *surface;
int16_t x, y;
uint16_t width, height;
uint16_t saved_width, saved_height;
bool override_redirect;
bool mapped;
struct wlr_surface* surface;
int16_t x, y;
uint16_t width, height;
uint16_t saved_width, saved_height;
bool override_redirect;
bool mapped;
char *title;
char *_class;
char *instance;
char *role;
char *startup_id;
pid_t pid;
bool has_utf8_title;
char* title;
char* _class;
char* instance;
char* role;
char* startup_id;
pid_t pid;
bool has_utf8_title;
struct wl_list children; // wlr_xwayland_surface::parent_link
struct wlr_xwayland_surface *parent;
struct wl_list parent_link; // wlr_xwayland_surface::children
struct wl_list children; // wlr_xwayland_surface::parent_link
struct wlr_xwayland_surface* parent;
struct wl_list parent_link; // wlr_xwayland_surface::children
xcb_atom_t *window_type;
size_t window_type_len;
xcb_atom_t* window_type;
size_t window_type_len;
xcb_atom_t *protocols;
size_t protocols_len;
xcb_atom_t* protocols;
size_t protocols_len;
uint32_t decorations;
xcb_icccm_wm_hints_t *hints;
xcb_size_hints_t *size_hints;
uint32_t decorations;
xcb_icccm_wm_hints_t* hints;
xcb_size_hints_t* size_hints;
bool pinging;
struct wl_event_source *ping_timer;
bool pinging;
struct wl_event_source* ping_timer;
// _NET_WM_STATE
bool modal;
@@ -127,35 +128,41 @@ struct wlr_xwayland_surface {
};
struct wlr_xwayland_surface_configure_event {
struct wlr_xwayland_surface *surface;
int16_t x, y;
uint16_t width, height;
uint16_t mask; // xcb_config_window_t
struct wlr_xwayland_surface* surface;
int16_t x, y;
uint16_t width, height;
uint16_t mask; // xcb_config_window_t
};
struct wlr_xwayland_minimize_event {
struct wlr_xwayland_surface *surface;
bool minimize;
struct wlr_xwayland_surface* surface;
bool minimize;
};
inline void wlr_xwayland_destroy(wlr_xwayland*) { }
inline void wlr_xwayland_destroy(wlr_xwayland*) {}
inline void wlr_xwayland_surface_configure(wlr_xwayland_surface*, int, int, int, int) { }
inline void wlr_xwayland_surface_configure(wlr_xwayland_surface*, int, int, int, int) {}
inline bool wlr_surface_is_xwayland_surface(void*) { return false; }
inline bool wlr_surface_is_xwayland_surface(void*) {
return false;
}
inline void wlr_xwayland_surface_activate(wlr_xwayland_surface*, bool) { }
inline void wlr_xwayland_surface_activate(wlr_xwayland_surface*, bool) {}
inline void wlr_xwayland_surface_restack(wlr_xwayland_surface*, int, xcb_stack_mode_t) { }
inline void wlr_xwayland_surface_restack(wlr_xwayland_surface*, void*, xcb_stack_mode_t) {}
inline wlr_xwayland_surface* wlr_xwayland_surface_from_wlr_surface(void*) { return nullptr; }
inline wlr_xwayland_surface* wlr_xwayland_surface_from_wlr_surface(void*) {
return nullptr;
}
inline void wlr_xwayland_surface_close(wlr_xwayland_surface*) { }
inline void wlr_xwayland_surface_close(wlr_xwayland_surface*) {}
inline void wlr_xwayland_surface_set_fullscreen(wlr_xwayland_surface*, bool) { }
inline void wlr_xwayland_surface_set_fullscreen(wlr_xwayland_surface*, bool) {}
inline void wlr_xwayland_surface_set_minimized(wlr_xwayland_surface *, bool) { }
inline void wlr_xwayland_surface_set_minimized(wlr_xwayland_surface*, bool) {}
inline bool wlr_backend_is_x11(void*) { return false; }
inline bool wlr_backend_is_x11(void*) {
return false;
}
inline void wlr_x11_output_create(void*) { }
inline void wlr_x11_output_create(void*) {}

View File

@@ -3,7 +3,7 @@
void CHyprError::queueCreate(std::string message, const CColor& color) {
m_szQueued = message;
m_cQueued = color;
m_cQueued = color;
}
void CHyprError::createQueued() {
@@ -28,25 +28,25 @@ void CHyprError::createQueued() {
const auto LINECOUNT = 1 + std::count(m_szQueued.begin(), m_szQueued.end(), '\n');
cairo_set_source_rgba(CAIRO, m_cQueued.r / 255.f, m_cQueued.g / 255.f, m_cQueued.b / 255.f, m_cQueued.a / 255.f);
cairo_set_source_rgba(CAIRO, m_cQueued.r, m_cQueued.g, m_cQueued.b, m_cQueued.a);
cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecPixelSize.x, (FONTSIZE + 2 * (FONTSIZE / 10.f)) * LINECOUNT);
// outline
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
cairo_rectangle(CAIRO, PMONITOR->vecPixelSize.x - 1, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // right
cairo_rectangle(CAIRO, 0, PMONITOR->vecPixelSize.y - 1, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // bottom
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
cairo_rectangle(CAIRO, PMONITOR->vecPixelSize.x - 1, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // right
cairo_rectangle(CAIRO, 0, PMONITOR->vecPixelSize.y - 1, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // bottom
cairo_fill(CAIRO);
// draw the text with a common font
const CColor textColor = m_cQueued.r * m_cQueued.g * m_cQueued.b < 0.5f ? CColor(255, 255, 255, 255) : CColor(0, 0, 0, 255);
const CColor textColor = m_cQueued.r * m_cQueued.g * m_cQueued.b < 0.5f ? CColor(1.0, 1.0, 1.0, 1.0) : CColor(0, 0, 0, 1.0);
cairo_select_font_face(CAIRO, "Noto Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(CAIRO, FONTSIZE);
cairo_set_source_rgba(CAIRO, textColor.r / 255.f, textColor.g / 255.f, textColor.b / 255.f, textColor.a / 255.f);
cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a);
float yoffset = FONTSIZE;
while(m_szQueued != "") {
while (m_szQueued != "") {
std::string current = m_szQueued.substr(0, m_szQueued.find('\n'));
if (const auto NEWLPOS = m_szQueued.find('\n'); NEWLPOS != std::string::npos)
m_szQueued = m_szQueued.substr(NEWLPOS + 1);
@@ -57,7 +57,6 @@ void CHyprError::createQueued() {
yoffset += FONTSIZE + (FONTSIZE / 10.f);
}
cairo_surface_flush(CAIROSURFACE);
// copy the data to an OpenGL texture we have
@@ -79,8 +78,8 @@ void CHyprError::createQueued() {
cairo_surface_destroy(CAIROSURFACE);
m_bIsCreated = true;
m_szQueued = "";
m_cQueued = CColor();
m_szQueued = "";
m_cQueued = CColor();
g_pHyprRenderer->damageMonitor(PMONITOR);
}
@@ -96,7 +95,7 @@ void CHyprError::draw() {
m_bQueuedDestroy = false;
m_tTexture.destroyTexture();
m_bIsCreated = false;
m_szQueued = "";
m_szQueued = "";
g_pHyprRenderer->damageMonitor(g_pCompositor->m_vMonitors.front().get());
return;
}
@@ -108,7 +107,7 @@ void CHyprError::draw() {
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &windowBox, 255.f, 0);
g_pHyprOpenGL->renderTexture(m_tTexture, &windowBox, 1.f, 0);
}
void CHyprError::destroy() {

View File

@@ -6,18 +6,18 @@
#include <cairo/cairo.h>
class CHyprError {
public:
void queueCreate(std::string message, const CColor& color);
void draw();
void destroy();
public:
void queueCreate(std::string message, const CColor& color);
void draw();
void destroy();
private:
void createQueued();
std::string m_szQueued = "";
CColor m_cQueued;
bool m_bQueuedDestroy = false;
bool m_bIsCreated = false;
CTexture m_tTexture;
private:
void createQueued();
std::string m_szQueued = "";
CColor m_cQueued;
bool m_bQueuedDestroy = false;
bool m_bIsCreated = false;
CTexture m_tTexture;
};
inline std::unique_ptr<CHyprError> g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time.

View File

@@ -6,7 +6,6 @@
#pragma diag_suppress 1696
#endif
#include <X11/Xlib.h>
#include <getopt.h>
#include <libinput.h>
#include <linux/input-event-codes.h>
@@ -109,7 +108,6 @@ extern "C" {
#ifndef NO_XWAYLAND
#include <wlr/backend/x11.h>
#include <wlr/xwayland.h>
#include <X11/Xproto.h>
#endif
}

View File

@@ -4,10 +4,10 @@
void SDwindleNodeData::recalcSizePosRecursive(bool force) {
if (children[0]) {
const auto REVERSESPLITRATIO = 2.f - splitRatio;
const auto REVERSESPLITRATIO = 2.f - splitRatio;
static auto *const PPRESERVESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:preserve_split")->intValue;
static auto *const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
static auto* const PPRESERVESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:preserve_split")->intValue;
static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
if (*PPRESERVESPLIT == 0) {
splitTop = size.y * *PFLMULT > size.x;
@@ -18,15 +18,15 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force) {
if (SPLITSIDE) {
// split left/right
children[0]->position = position;
children[0]->size = Vector2D(size.x / 2.f * splitRatio, size.y);
children[0]->size = Vector2D(size.x / 2.f * splitRatio, size.y);
children[1]->position = Vector2D(position.x + size.x / 2.f * splitRatio, position.y);
children[1]->size = Vector2D(size.x / 2.f * REVERSESPLITRATIO, size.y);
children[1]->size = Vector2D(size.x / 2.f * REVERSESPLITRATIO, size.y);
} else {
// split top/bottom
children[0]->position = position;
children[0]->size = Vector2D(size.x, size.y / 2.f * splitRatio);
children[0]->size = Vector2D(size.x, size.y / 2.f * splitRatio);
children[1]->position = Vector2D(position.x, position.y + size.y / 2.f * splitRatio);
children[1]->size = Vector2D(size.x, size.y / 2.f * REVERSESPLITRATIO);
children[1]->size = Vector2D(size.x, size.y / 2.f * REVERSESPLITRATIO);
}
children[0]->recalcSizePosRecursive(force);
@@ -93,7 +93,7 @@ void SDwindleNodeData::setGroupFocusedNode(SDwindleNodeData* pMember) {
int SDwindleNodeData::getGroupMemberCount() {
SDwindleNodeData* current = this->pNextGroupMember;
int no = 1;
int no = 1;
while (current != this) {
current = current->pNextGroupMember;
@@ -144,9 +144,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
CMonitor* PMONITOR = nullptr;
if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) {
if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen) {
if (m->specialWorkspaceID == pNode->workspaceID) {
PMONITOR = m.get();
break;
}
@@ -161,14 +161,14 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
}
// for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
const auto PWINDOW = pNode->pWindow;
@@ -178,40 +178,40 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
return;
}
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position;
static auto *const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue;
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue;
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && (NODESONWORKSPACE == 1 || (pNode->isGroupMember() && pNode->getGroupMemberCount() == NODESONWORKSPACE))) {
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
(NODESONWORKSPACE == 1 || (pNode->isGroupMember() && pNode->getGroupMemberCount() == NODESONWORKSPACE) ||
(PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.decorate = false;
return;
}
PWINDOW->m_sSpecialRenderData.rounding = true;
PWINDOW->m_sSpecialRenderData.border = true;
PWINDOW->m_sSpecialRenderData.border = true;
PWINDOW->m_sSpecialRenderData.decorate = true;
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN,
DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN, DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN,
DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN, DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
calcPos = calcPos + OFFSETTOPLEFT;
calcPos = calcPos + OFFSETTOPLEFT;
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
if (PWINDOW->m_bIsPseudotiled) {
@@ -229,25 +229,25 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
}
auto DELTA = calcSize - PWINDOW->m_vPseudoSize * scale;
calcSize = PWINDOW->m_vPseudoSize * scale;
calcPos = calcPos + DELTA / 2.f; // center
calcSize = PWINDOW->m_vPseudoSize * scale;
calcPos = calcPos + DELTA / 2.f; // center
} else {
auto DELTA = calcSize - PWINDOW->m_vPseudoSize;
calcPos = calcPos + DELTA / 2.f; // center
calcSize = PWINDOW->m_vPseudoSize;
calcPos = calcPos + DELTA / 2.f; // center
calcSize = PWINDOW->m_vPseudoSize;
}
}
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
// if special, we adjust the coords a bit
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
} else {
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealPosition = calcPos;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
@@ -266,7 +266,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
// update visible node
const auto PVISNODE = pNode->getGroupVisible();
PVISNODE->pWindow->m_vRealSize = PWINDOW->m_vRealSize.goalv();
PVISNODE->pWindow->m_vRealSize = PWINDOW->m_vRealSize.goalv();
PVISNODE->pWindow->m_vRealPosition = PWINDOW->m_vRealPosition.goalv();
}
@@ -278,22 +278,23 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
return;
m_lDwindleNodesData.push_back(SDwindleNodeData());
const auto PNODE = &m_lDwindleNodesData.back();
const auto PNODE = &m_lDwindleNodesData.back();
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
static auto *const PUSEACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits")->intValue;
static auto* const PUSEACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:use_active_for_splits")->intValue;
// Populate the node with our window's data
PNODE->workspaceID = pWindow->m_iWorkspaceID;
PNODE->pWindow = pWindow;
PNODE->isNode = false;
PNODE->layout = this;
PNODE->pWindow = pWindow;
PNODE->isNode = false;
PNODE->layout = this;
SDwindleNodeData* OPENINGON;
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && !*PUSEACTIVE) {
if (PMONITOR->ID == MONFROMCURSOR->ID &&
(PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
// happens on reserved area
@@ -301,7 +302,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
} else if (*PUSEACTIVE) {
if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow &&
g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
} else {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
@@ -336,10 +338,20 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
}
// last fail-safe to avoid duplicate fullscreens
if ((!OPENINGON || OPENINGON->pWindow == pWindow) && getNodesOnWorkspace(PNODE->workspaceID) > 1) {
for (auto& node : m_lDwindleNodesData) {
if (node.workspaceID == PNODE->workspaceID && node.pWindow != pWindow) {
OPENINGON = &node;
break;
}
}
}
// if it's the first, it's easy. Make it fullscreen.
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
PNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
PNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
applyNodeDataToWindow(PNODE);
@@ -353,15 +365,15 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
const auto PTAIL = PHEAD->pPreviousGroupMember;
PHEAD->pPreviousGroupMember = PNODE;
PTAIL->pNextGroupMember = PNODE;
PTAIL->pNextGroupMember = PNODE;
PNODE->pNextGroupMember = PHEAD;
PNODE->pNextGroupMember = PHEAD;
PNODE->pPreviousGroupMember = PTAIL;
PHEAD->setGroupFocusedNode(PNODE);
PNODE->position = PHEAD->position;
PNODE->size = PHEAD->size;
PNODE->size = PHEAD->size;
applyNodeDataToWindow(PNODE);
@@ -376,25 +388,29 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
const auto NEWPARENT = &m_lDwindleNodesData.back();
// make the parent have the OPENINGON's stats
NEWPARENT->position = OPENINGON->position;
NEWPARENT->size = OPENINGON->size;
NEWPARENT->position = OPENINGON->position;
NEWPARENT->size = OPENINGON->size;
NEWPARENT->workspaceID = OPENINGON->workspaceID;
NEWPARENT->pParent = OPENINGON->pParent;
NEWPARENT->isNode = true; // it is a node
NEWPARENT->pParent = OPENINGON->pParent;
NEWPARENT->isNode = true; // it is a node
const auto PWIDTHMULTIPLIER = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
// if cursor over first child, make it first, etc
const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * *PWIDTHMULTIPLIER;
NEWPARENT->splitTop = !SIDEBYSIDE;
NEWPARENT->splitTop = !SIDEBYSIDE;
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
const auto PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
if (*PFORCESPLIT == 0) {
if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
if ((SIDEBYSIDE &&
VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f,
NEWPARENT->position.y + NEWPARENT->size.y)) ||
(!SIDEBYSIDE &&
VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x,
NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
// we are hovering over the first node, make PNODE first.
NEWPARENT->children[1] = OPENINGON;
NEWPARENT->children[0] = PNODE;
@@ -424,23 +440,22 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
// Update the children
if (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y) {
// split left/right
OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
PNODE->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y);
PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
PNODE->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y);
PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
} else {
// split top/bottom
OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
PNODE->position = Vector2D(NEWPARENT->position.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f);
PNODE->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
PNODE->position = Vector2D(NEWPARENT->position.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f);
PNODE->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
}
OPENINGON->pParent = NEWPARENT;
PNODE->pParent = NEWPARENT;
PNODE->pParent = NEWPARENT;
NEWPARENT->recalcSizePosRecursive();
@@ -457,6 +472,10 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
return;
}
pWindow->m_sSpecialRenderData.rounding = true;
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
@@ -466,12 +485,12 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
const auto PPREV = PNODE->pPreviousGroupMember;
const auto PNEXT = PNODE->pNextGroupMember;
PPREV->pNextGroupMember = PNEXT;
PPREV->pNextGroupMember = PNEXT;
PNEXT->pPreviousGroupMember = PPREV;
if (PNODE->groupHead) {
PNEXT->groupHead = true;
PNEXT->pParent = PNODE->pParent;
PNEXT->pParent = PNODE->pParent;
if (PNODE->pParent) {
if (PNODE->pParent->children[0] == PNODE) {
@@ -482,12 +501,12 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
}
PNEXT->position = PNODE->position;
PNEXT->size = PNODE->size;
PNEXT->size = PNODE->size;
} else {
const auto PHEAD = PNODE->getGroupHead();
PNEXT->position = PHEAD->position;
PNEXT->size = PHEAD->size;
PNEXT->size = PHEAD->size;
}
PNEXT->setGroupFocusedNode(PNEXT);
@@ -516,8 +535,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
const auto PSIBLING = PPARENT->children[0] == PNODE ? PPARENT->children[1] : PPARENT->children[0];
PSIBLING->position = PPARENT->position;
PSIBLING->size = PPARENT->size;
PSIBLING->pParent = PPARENT->pParent;
PSIBLING->size = PPARENT->size;
PSIBLING->pParent = PPARENT->pParent;
if (PSIBLING->isGroupMember()) {
// apply to all group members
@@ -525,8 +544,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
while (current != PSIBLING) {
current->position = PPARENT->position;
current->size = PPARENT->size;
current = current->pNextGroupMember;
current->size = PPARENT->size;
current = current->pNextGroupMember;
}
}
@@ -539,7 +558,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
}
PPARENT->valid = false;
PNODE->valid = false;
PNODE->valid = false;
if (PSIBLING->pParent)
PSIBLING->pParent->recalcSizePosRecursive();
@@ -563,12 +582,12 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
g_pHyprRenderer->damageMonitor(PMONITOR);
if (PMONITOR->specialWorkspaceOpen) {
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID);
if (PMONITOR->specialWorkspaceID) {
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->specialWorkspaceID);
if (TOPNODE && PMONITOR) {
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
TOPNODE->recalcSizePosRecursive();
}
}
@@ -585,12 +604,12 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
PWORKSPACE->m_bHasFullscreenWindow = false;
} else {
SDwindleNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
PFULLWINDOW->m_vPosition = fakeNode.position;
PFULLWINDOW->m_vSize = fakeNode.size;
PFULLWINDOW->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
@@ -602,7 +621,7 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
if (TOPNODE && PMONITOR) {
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
TOPNODE->recalcSizePosRecursive();
}
}
@@ -621,7 +640,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) {
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
PWINDOW->updateWindowDecos();
return;
}
@@ -629,10 +648,10 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
// get some data about our window
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
// construct allowed movement
@@ -647,7 +666,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
const auto PPARENT = PNODE->pParent;
if (!PPARENT)
return; // the only window on a workspace, ignore
return; // the only window on a workspace, ignore
const bool PARENTSIDEBYSIDE = !PPARENT->splitTop;
@@ -690,13 +709,13 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
// 2 axes of freedom
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
}
@@ -705,10 +724,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
if (!g_pCompositor->windowValidMapped(pWindow))
return;
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
if (on == pWindow->m_bIsFullscreen || g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID))
return; // ignore
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
@@ -718,7 +737,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
}
// otherwise, accept it.
pWindow->m_bIsFullscreen = on;
pWindow->m_bIsFullscreen = on;
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
@@ -730,8 +749,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
applyNodeDataToWindow(PNODE);
else {
// get back its' dimensions from position and size
pWindow->m_vRealPosition = pWindow->m_vPosition;
pWindow->m_vRealSize = pWindow->m_vSize;
pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
}
} else {
// if it now got fullscreen, make it fullscreen
@@ -740,26 +759,28 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
// save position and size if floating
if (pWindow->m_bIsFloating) {
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
pWindow->m_vSize = pWindow->m_vRealSize.vec();
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goalv();
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goalv();
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
}
// apply new pos and size being monitors' box
if (fullscreenMode == FULLSCREEN_FULL) {
pWindow->m_vRealPosition = PMONITOR->vecPosition;
pWindow->m_vRealSize = PMONITOR->vecSize;
pWindow->m_vRealSize = PMONITOR->vecSize;
} else {
// This is a massive hack.
// We make a fake "only" node and apply
// To keep consistent with the settings without C+P code
SDwindleNodeData fakeNode;
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
pWindow->m_vPosition = fakeNode.position;
pWindow->m_vSize = fakeNode.size;
pWindow->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
}
@@ -800,19 +821,21 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
// get the node
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
return; // reject
if (!PNODE) {
Debug::log(LOG, "Rejecting to group a floating window");
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && !PNODE->isGroupMember()) {
Debug::log(ERR, "Cannot enable group on fullscreen window");
Debug::log(ERR, "Cannot enable group on a fullscreen window");
return;
}
if (PNODE->isGroupMember()) {
// dissolve group
const auto PHEAD = PNODE->getGroupHead();
const auto PHEAD = PNODE->getGroupHead();
SDwindleNodeData* current = PNODE->pNextGroupMember;
@@ -820,26 +843,26 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
std::deque<CWindow*> toAddWindows;
const auto PWINDOWNODE = PNODE->pWindow;
const auto PWINDOWNODE = PNODE->pWindow;
toAddWindows.push_back(PWINDOWNODE);
while (current != PNODE) {
const auto PWINDOW = current->pWindow;
current = current->pNextGroupMember;
current = current->pNextGroupMember;
toAddWindows.push_back(PWINDOW);
PWINDOW->setHidden(false);
}
if (PHEAD->pPreviousGroupMember)
PHEAD->pPreviousGroupMember->pNextGroupMember = PHEAD->pNextGroupMember;
if (PHEAD->pPreviousGroupMember)
PHEAD->pPreviousGroupMember->pNextGroupMember = PHEAD->pNextGroupMember;
if (PHEAD->pNextGroupMember)
PHEAD->pNextGroupMember->pPreviousGroupMember = PHEAD->pPreviousGroupMember;
if (PHEAD->pNextGroupMember)
PHEAD->pNextGroupMember->pPreviousGroupMember = PHEAD->pPreviousGroupMember;
PHEAD->pPreviousGroupMember = nullptr;
PHEAD->pNextGroupMember = nullptr;
PHEAD->pPreviousGroupMember = nullptr;
PHEAD->pNextGroupMember = nullptr;
onWindowRemoved(PHEAD->pWindow);
@@ -860,8 +883,10 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
} else {
// create group
if (!PNODE->pParent)
if (!PNODE->pParent) {
Debug::log(LOG, "Rejecting to group a solitary window");
return;
}
PNODE->groupHead = true;
@@ -873,8 +898,10 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
addToDequeRecursive(&newGroupMembers, &nodesToRemove, PNODE->pParent->children[0] == PNODE ? PNODE->pParent->children[1] : PNODE->pParent->children[0]);
for (auto& n : newGroupMembers) {
if (n->isGroupMember())
return; // reject nested groups
if (n->isGroupMember()) {
Debug::log(LOG, "Rejecting to nest groups");
return;
}
}
for (auto& nd : nodesToRemove) {
@@ -882,7 +909,7 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
}
PNODE->position = PNODE->pParent->position;
PNODE->size = PNODE->pParent->size;
PNODE->size = PNODE->pParent->size;
applyNodeDataToWindow(PNODE);
@@ -905,14 +932,14 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
for (int i = 0; i < (int)newGroupMembers.size(); ++i) {
if (i != 0) {
newGroupMembers[i]->groupHead = false;
newGroupMembers[i]->pParent = PNODE->pParent;
newGroupMembers[i]->pParent = PNODE->pParent;
}
const auto PREVMEMBER = i == 0 ? newGroupMembers[newGroupMembers.size() - 1] : newGroupMembers[i - 1];
const auto NEXTMEMBER = i == (int)newGroupMembers.size() - 1 ? newGroupMembers[0] : newGroupMembers[i + 1];
newGroupMembers[i]->pPreviousGroupMember = PREVMEMBER;
newGroupMembers[i]->pNextGroupMember = NEXTMEMBER;
newGroupMembers[i]->pNextGroupMember = NEXTMEMBER;
// add the deco
newGroupMembers[i]->pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(newGroupMembers[i]->pWindow));
@@ -941,9 +968,9 @@ std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE || !PNODE->isGroupMember())
return result; // reject with empty
return result; // reject with empty
const auto HEAD = PNODE->getGroupHead();
const auto HEAD = PNODE->getGroupHead();
SDwindleNodeData* current = HEAD->pNextGroupMember;
result.push_back(HEAD->pWindow);
@@ -965,7 +992,7 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward, CWind
if (!PNODE || !PNODE->isGroupMember())
return; // reject
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
SDwindleNodeData* pNewNode;
@@ -983,8 +1010,8 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward, CWind
PNODE->setGroupFocusedNode(pNewNode);
pNewNode->position = PNODE->position;
pNewNode->size = PNODE->size;
pNewNode->position = PNODE->position;
pNewNode->size = PNODE->size;
pNewNode->workspaceID = PNODE->workspaceID;
applyNodeDataToWindow(pNewNode);
@@ -1008,6 +1035,8 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward, CWind
pNewNode->pWindow->updateWindowDecos();
PNODE->pWindow->updateWindowDecos();
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID));
}
SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow) {
@@ -1015,20 +1044,20 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
SWindowRenderLayoutHints hints;
static auto *const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->intValue;
static auto *const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->intValue;
static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->data;
static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->data;
const auto PNODE = getNodeFromWindow(pWindow);
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
return hints; // left for the future, maybe floating funkiness
if (PNODE->isGroupMember()) {
hints.isBorderColor = true;
hints.isBorderGradient = true;
if (pWindow == g_pCompositor->m_pLastWindow)
hints.borderColor = CColor(*PGROUPCOLACTIVE);
hints.borderGradient = (CGradientValueData*)PGROUPCOLACTIVE->get();
else
hints.borderColor = CColor(*PGROUPCOLINACTIVE);
hints.borderGradient = (CGradientValueData*)PGROUPCOLINACTIVE->get();
}
return hints;
@@ -1037,17 +1066,17 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
// windows should be valid, insallah
auto PNODE = getNodeFromWindow(pWindow);
auto PNODE = getNodeFromWindow(pWindow);
auto PNODE2 = getNodeFromWindow(pWindow2);
if (!PNODE2 || !PNODE) {
return;
}
return;
}
SDwindleNodeData* ACTIVE1 = nullptr;
SDwindleNodeData* ACTIVE2 = nullptr;
SDwindleNodeData* ACTIVE2 = nullptr;
if (PNODE2->isGroupMember() || PNODE->isGroupMember()) {
if (PNODE2->isGroupMember() || PNODE->isGroupMember()) {
if (PNODE->workspaceID != PNODE2->workspaceID) {
Debug::log(ERR, "Groups are confined to a monitor");
@@ -1056,85 +1085,88 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
if (PNODE->isGroupMember()) {
ACTIVE1 = PNODE;
PNODE = PNODE->getGroupHead();
}
PNODE = PNODE->getGroupHead();
}
if (PNODE2->isGroupMember()) {
if (PNODE2->isGroupMember()) {
ACTIVE2 = PNODE2;
PNODE2 = PNODE2->getGroupHead();
}
PNODE2 = PNODE2->getGroupHead();
}
if (PNODE2->pParent == PNODE->pParent) {
const auto PPARENT = PNODE->pParent;
if (PNODE2->pParent == PNODE->pParent) {
const auto PPARENT = PNODE->pParent;
if (PPARENT->children[0] == PNODE) {
PPARENT->children[0] = PNODE2;
PPARENT->children[1] = PNODE;
} else {
PPARENT->children[0] = PNODE;
PPARENT->children[1] = PNODE2;
}
} else {
if (PNODE->pParent) {
const auto PPARENT = PNODE->pParent;
if (PPARENT->children[0] == PNODE) {
PPARENT->children[0] = PNODE2;
PPARENT->children[1] = PNODE;
} else {
PPARENT->children[0] = PNODE;
PPARENT->children[1] = PNODE2;
}
} else {
if (PNODE->pParent) {
const auto PPARENT = PNODE->pParent;
if (PPARENT->children[0] == PNODE) {
PPARENT->children[0] = PNODE2;
} else {
PPARENT->children[1] = PNODE2;
}
}
if (PPARENT->children[0] == PNODE) {
PPARENT->children[0] = PNODE2;
} else {
PPARENT->children[1] = PNODE2;
}
}
if (PNODE2->pParent) {
const auto PPARENT = PNODE2->pParent;
if (PNODE2->pParent) {
const auto PPARENT = PNODE2->pParent;
if (PPARENT->children[0] == PNODE2) {
PPARENT->children[0] = PNODE;
} else {
PPARENT->children[1] = PNODE;
}
}
}
if (PPARENT->children[0] == PNODE2) {
PPARENT->children[0] = PNODE;
} else {
PPARENT->children[1] = PNODE;
}
}
}
const auto PPARENTNODE2 = PNODE2->pParent;
PNODE2->pParent = PNODE->pParent;
PNODE->pParent = PPARENTNODE2;
const auto PPARENTNODE2 = PNODE2->pParent;
PNODE2->pParent = PNODE->pParent;
PNODE->pParent = PPARENTNODE2;
std::swap(PNODE2->workspaceID, PNODE->workspaceID);
} else {
// swap the windows and recalc
PNODE2->pWindow = pWindow;
PNODE->pWindow = pWindow2;
}
std::swap(PNODE2->workspaceID, PNODE->workspaceID);
} else {
// swap the windows and recalc
PNODE2->pWindow = pWindow;
PNODE->pWindow = pWindow2;
}
if (PNODE->workspaceID != PNODE2->workspaceID) {
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
}
if (PNODE->workspaceID != PNODE2->workspaceID) {
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
}
// recalc the workspace
// recalc the workspace
getMasterNodeOnWorkspace(PNODE->workspaceID)->recalcSizePosRecursive();
if (PNODE2->workspaceID != PNODE->workspaceID) {
getMasterNodeOnWorkspace(PNODE2->workspaceID)->recalcSizePosRecursive();
}
if (ACTIVE1) {
ACTIVE1->position = PNODE->position;
ACTIVE1->size = PNODE->size;
ACTIVE1->pWindow->m_vPosition = ACTIVE1->position;
ACTIVE1->pWindow->m_vSize = ACTIVE1->size;
}
if (ACTIVE1) {
ACTIVE1->position = PNODE->position;
ACTIVE1->size = PNODE->size;
ACTIVE1->pWindow->m_vPosition = ACTIVE1->position;
ACTIVE1->pWindow->m_vSize = ACTIVE1->size;
}
if (ACTIVE2) {
ACTIVE2->position = PNODE2->position;
ACTIVE2->size = PNODE2->size;
ACTIVE2->pWindow->m_vPosition = ACTIVE2->position;
ACTIVE2->pWindow->m_vSize = ACTIVE2->size;
}
if (ACTIVE2) {
ACTIVE2->position = PNODE2->position;
ACTIVE2->size = PNODE2->size;
ACTIVE2->pWindow->m_vPosition = ACTIVE2->position;
ACTIVE2->pWindow->m_vSize = ACTIVE2->size;
}
g_pHyprRenderer->damageWindow(pWindow);
g_pHyprRenderer->damageWindow(pWindow2);
}
void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
void CHyprDwindleLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exact) {
// window should be valid, insallah
const auto PNODE = getNodeFromWindow(pWindow);
@@ -1142,7 +1174,8 @@ void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
if (!PNODE || !PNODE->pParent || (PNODE->isGroupMember() && PNODE->getGroupMemberCount() == g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID)))
return;
PNODE->pParent->splitRatio = std::clamp(PNODE->pParent->splitRatio + ratio, 0.1f, 1.9f);
float newRatio = exact ? ratio : PNODE->pParent->splitRatio + ratio;
PNODE->pParent->splitRatio = std::clamp(newRatio, 0.1f, 1.9f);
PNODE->pParent->recalcSizePosRecursive();
}

View File

@@ -4,80 +4,81 @@
#include <list>
#include <deque>
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
#include <array>
class CHyprDwindleLayout;
enum eFullscreenMode : uint8_t;
struct SDwindleNodeData {
SDwindleNodeData* pParent = nullptr;
bool isNode = false;
SDwindleNodeData* pParent = nullptr;
bool isNode = false;
CWindow* pWindow = nullptr;
CWindow* pWindow = nullptr;
std::array<SDwindleNodeData*, 2> children = { nullptr, nullptr };
std::array<SDwindleNodeData*, 2> children = {nullptr, nullptr};
bool splitTop = false; // for preserve_split
bool splitTop = false; // for preserve_split
bool groupHead = false;
SDwindleNodeData* pNextGroupMember = nullptr;
SDwindleNodeData* pPreviousGroupMember = nullptr;
bool groupHead = false;
SDwindleNodeData* pNextGroupMember = nullptr;
SDwindleNodeData* pPreviousGroupMember = nullptr;
Vector2D position;
Vector2D size;
Vector2D position;
Vector2D size;
int workspaceID = -1;
int workspaceID = -1;
float splitRatio = 1.f;
float splitRatio = 1.f;
bool valid = true;
bool valid = true;
// For list lookup
bool operator==(const SDwindleNodeData& rhs) {
return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && position == rhs.position && size == rhs.size && pParent == rhs.pParent && children[0] == rhs.children[0] && children[1] == rhs.children[1];
return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && position == rhs.position && size == rhs.size && pParent == rhs.pParent &&
children[0] == rhs.children[0] && children[1] == rhs.children[1];
}
void recalcSizePosRecursive(bool force = false);
void getAllChildrenRecursive(std::deque<SDwindleNodeData*>*);
bool isGroupMember();
SDwindleNodeData* getGroupHead();
SDwindleNodeData* getGroupVisible();
int getGroupMemberCount();
void setGroupFocusedNode(SDwindleNodeData*);
void recalcSizePosRecursive(bool force = false);
void getAllChildrenRecursive(std::deque<SDwindleNodeData*>*);
bool isGroupMember();
SDwindleNodeData* getGroupHead();
SDwindleNodeData* getGroupVisible();
int getGroupMemberCount();
void setGroupFocusedNode(SDwindleNodeData*);
CHyprDwindleLayout* layout = nullptr;
};
class CHyprDwindleLayout : public IHyprLayout {
public:
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*);
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
public:
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*);
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatioBy(CWindow*, float);
virtual std::string getLayoutName();
virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatio(CWindow*, float, bool);
virtual std::string getLayoutName();
virtual void onEnable();
virtual void onDisable();
virtual void onEnable();
virtual void onDisable();
private:
private:
std::list<SDwindleNodeData> m_lDwindleNodesData;
std::list<SDwindleNodeData> m_lDwindleNodesData;
int getNodesOnWorkspace(const int&);
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
SDwindleNodeData* getNodeFromWindow(CWindow*);
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
int getNodesOnWorkspace(const int&);
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
SDwindleNodeData* getNodeFromWindow(CWindow*);
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
void toggleWindowGroup(CWindow*);
void switchGroupWindow(CWindow*, bool forward, CWindow* to = nullptr);
void toggleSplit(CWindow*);
std::deque<CWindow*> getGroupMembers(CWindow*);
void toggleWindowGroup(CWindow*);
void switchGroupWindow(CWindow*, bool forward, CWindow* to = nullptr);
void toggleSplit(CWindow*);
std::deque<CWindow*> getGroupMembers(CWindow*);
friend struct SDwindleNodeData;
};

View File

@@ -10,7 +10,7 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow) {
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f;
} else {
pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
@@ -21,6 +21,9 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow) {
}
void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
if (pWindow->m_bIsFloating) {
onWindowRemovedFloating(pWindow);
} else {
@@ -47,9 +50,10 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) { // XDG windows should be fine. TODO: check for weird atoms?
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 &&
pWindow->m_iX11Type == 2) { // XDG windows should be fine. TODO: check for weird atoms?
pWindow->setHidden(true);
return;
}
@@ -59,7 +63,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
}
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f);
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f,
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f);
} else {
// we respect the size.
pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
@@ -72,10 +77,14 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
if (!pWindow->m_bIsX11) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)) {
if (VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x,
m->vecPosition.y + m->vecPosition.y) ||
VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x,
m->vecPosition.y + m->vecPosition.y) ||
VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x,
m->vecPosition.y + m->vecPosition.y) ||
VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y,
m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)) {
visible = true;
break;
@@ -129,32 +138,29 @@ void IHyprLayout::onBeginDragWindow() {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow) {
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
if (PWORKSPACE->m_bHasFullscreenWindow && (!DRAGGINGWINDOW->m_bCreatedOverFullscreen || !DRAGGINGWINDOW->m_bIsFloating)) {
Debug::log(LOG, "Rejecting drag on a fullscreen workspace. (window under fullscreen)");
return;
}
g_pInputManager->setCursorImageUntilUnset("hand1");
DRAGGINGWINDOW->m_vRealPosition.setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove"));
DRAGGINGWINDOW->m_vRealSize.setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove"));
DRAGGINGWINDOW->m_bDraggingTiled = false;
if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragMode == MBIND_MOVE) {
changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true;
DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goalv() / 2.f;
}
}
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goalv();
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
m_vLastDragXY = m_vBeginDragXY;
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
m_vLastDragXY = m_vBeginDragXY;
// get the grab corner
if (m_vBeginDragXY.x < m_vBeginDragPositionXY.x + m_vBeginDragSizeXY.x / 2.0) {
@@ -173,17 +179,18 @@ void IHyprLayout::onBeginDragWindow() {
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
// shadow to ignore any bound to MAIN_MOD
g_pKeybindManager->shadowKeybinds();
}
void IHyprLayout::onEndDragWindow() {
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
g_pInputManager->unsetCursorImage();
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
return;
g_pInputManager->unsetCursorImage();
g_pInputManager->currentlyDraggedWindow = nullptr;
if (DRAGGINGWINDOW->m_bDraggingTiled) {
DRAGGINGWINDOW->m_bIsFloating = false;
@@ -201,11 +208,14 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
// Window invalid or drag begin size 0,0 meaning we rejected it.
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
onEndDragWindow();
g_pInputManager->currentlyDraggedWindow = nullptr;
return;
}
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
const auto SPECIAL = g_pCompositor->isWorkspaceSpecial(DRAGGINGWINDOW->m_iWorkspaceID);
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
@@ -234,25 +244,25 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
// calc the new size and pos
Vector2D newSize = m_vBeginDragSizeXY;
Vector2D newPos = m_vBeginDragPositionXY;
Vector2D newPos = m_vBeginDragPositionXY;
if (m_iGrabbedCorner == 3) {
newSize = newSize + DELTA;
} else if (m_iGrabbedCorner == 0) {
newSize = newSize - DELTA;
newPos = newPos + DELTA;
newPos = newPos + DELTA;
} else if (m_iGrabbedCorner == 1) {
newSize = newSize + Vector2D(DELTA.x, -DELTA.y);
newPos = newPos + Vector2D(0, DELTA.y);
newPos = newPos + Vector2D(0, DELTA.y);
} else if (m_iGrabbedCorner == 4) {
newSize = newSize + Vector2D(-DELTA.x, DELTA.y);
newPos = newPos + Vector2D(DELTA.x, 0);
newPos = newPos + Vector2D(DELTA.x, 0);
}
newSize = newSize.clamp(Vector2D(20,20), MAXSIZE);
newSize = newSize.clamp(Vector2D(20, 20), MAXSIZE);
if (*PANIMATE) {
DRAGGINGWINDOW->m_vRealSize = newSize;
DRAGGINGWINDOW->m_vRealSize = newSize;
DRAGGINGWINDOW->m_vRealPosition = newPos;
} else {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(newSize);
@@ -271,7 +281,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
// and check its monitor
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
if (PMONITOR) {
if (PMONITOR && !SPECIAL) {
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
DRAGGINGWINDOW->moveToWorkspace(PMONITOR->activeWorkspace);
@@ -297,13 +307,16 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
const auto TILED = isWindowTiled(pWindow);
// event
g_pEventManager->postEvent(SHyprIPCEvent{"changefloatingmode", getFormat("%x,%d", pWindow, (int)TILED)});
if (!TILED) {
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
pWindow->m_iMonitorID = PNEWMON->ID;
pWindow->moveToWorkspace(PNEWMON->activeWorkspace);
// save real pos cuz the func applies the default 5,5 mid
const auto PSAVEDPOS = pWindow->m_vRealPosition.goalv();
const auto PSAVEDPOS = pWindow->m_vRealPosition.goalv();
const auto PSAVEDSIZE = pWindow->m_vRealSize.goalv();
// if the window is pseudo, update its size
@@ -330,9 +343,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
g_pCompositor->moveWindowToTop(pWindow);
pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
pWindow->m_vSize = pWindow->m_vRealSize.goalv();
pWindow->m_vPosition = pWindow->m_vRealPosition.goalv();
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
@@ -380,18 +393,31 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
return g_pCompositor->getFullscreenWindowOnWorkspace(pWindow->m_iWorkspaceID);
if (pWindow->m_bIsFloating) {
// the window was floating, let's try the last tiled window.
// find whether there is a floating window below this one
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
!w->m_bNoFocus && w.get() != pWindow) {
if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x,
w->m_vPosition.y + w->m_vSize.y)) {
return w.get();
}
}
}
// let's try the last tiled window.
if (m_pLastTiledWindow && m_pLastTiledWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID)
return m_pLastTiledWindow;
// if we don't, let's try to find any window that is in the middle
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f); PWINDOWCANDIDATE)
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f);
PWINDOWCANDIDATE && PWINDOWCANDIDATE != pWindow)
return PWINDOWCANDIDATE;
// if not, floating window
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus && !w->m_bNoFocus)
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus &&
!w->m_bNoFocus && w.get() != pWindow)
return w.get();
}
@@ -402,8 +428,11 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
// if it was a tiled window, we first try to find the window that will replace it.
const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f);
if (!PWINDOWCANDIDATE || pWindow == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
if (!PWINDOWCANDIDATE || pWindow == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus ||
PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
return nullptr;
return PWINDOWCANDIDATE;
}
IHyprLayout::~IHyprLayout() {}

View File

@@ -2,102 +2,104 @@
#include "../defines.hpp"
#include "../Window.hpp"
#include <any>
struct SWindowRenderLayoutHints {
bool isBorderColor = false;
CColor borderColor;
bool isBorderGradient = false;
CGradientValueData* borderGradient;
};
struct SLayoutMessageHeader {
CWindow* pWindow = nullptr;
CWindow* pWindow = nullptr;
};
enum eFullscreenMode : uint8_t;
interface IHyprLayout {
public:
virtual void onEnable() = 0;
virtual void onDisable() = 0;
public:
virtual ~IHyprLayout() = 0;
virtual void onEnable() = 0;
virtual void onDisable() = 0;
/*
Called when a window is created (mapped)
The layout HAS TO set the goal pos and size (anim mgr will use it)
If !animationinprogress, then the anim mgr will not apply an anim.
*/
virtual void onWindowCreated(CWindow*);
virtual void onWindowCreatedTiling(CWindow*) = 0;
virtual void onWindowCreatedFloating(CWindow*);
virtual void onWindowCreated(CWindow*);
virtual void onWindowCreatedTiling(CWindow*) = 0;
virtual void onWindowCreatedFloating(CWindow*);
/*
Return tiled status
*/
virtual bool isWindowTiled(CWindow*) = 0;
virtual bool isWindowTiled(CWindow*) = 0;
/*
Called when a window is removed (unmapped)
*/
virtual void onWindowRemoved(CWindow*);
virtual void onWindowRemovedTiling(CWindow*) = 0;
virtual void onWindowRemovedFloating(CWindow*);
virtual void onWindowRemoved(CWindow*);
virtual void onWindowRemovedTiling(CWindow*) = 0;
virtual void onWindowRemovedFloating(CWindow*);
/*
Called when the monitor requires a layout recalculation
this usually means reserved area changes
*/
virtual void recalculateMonitor(const int&) = 0;
virtual void recalculateMonitor(const int&) = 0;
/*
Called when the compositor requests a window
to be recalculated, e.g. when pseudo is toggled.
*/
virtual void recalculateWindow(CWindow*) = 0;
virtual void recalculateWindow(CWindow*) = 0;
/*
Called when a window is requested to be floated
*/
virtual void changeWindowFloatingMode(CWindow*);
virtual void changeWindowFloatingMode(CWindow*);
/*
Called when a window is clicked on, beginning a drag
this might be a resize, move, whatever the layout defines it
as.
*/
virtual void onBeginDragWindow();
virtual void onBeginDragWindow();
/*
Called when a user requests a resize of the current window by a vec
Vector2D holds pixel values
Optional pWindow for a specific window
*/
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
/*
Called when a user requests a move of the current window by a vec
Vector2D holds pixel values
Optional pWindow for a specific window
*/
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
/*
Called when a window is ended being dragged
(mouse up)
*/
virtual void onEndDragWindow();
virtual void onEndDragWindow();
/*
Called whenever the mouse moves, should the layout want to
do anything with it.
Useful for dragging.
*/
virtual void onMouseMove(const Vector2D&);
virtual void onMouseMove(const Vector2D&);
/*
Called when a window / the user requests to toggle the fullscreen state of a window
The layout sets all the fullscreen flags.
It can either accept or ignore.
*/
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool) = 0;
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool) = 0;
/*
Called when a dispatcher requests a custom message
The layout is free to ignore.
std::any is the reply. Can be empty.
*/
virtual std::any layoutMessage(SLayoutMessageHeader, std::string) = 0;
virtual std::any layoutMessage(SLayoutMessageHeader, std::string) = 0;
/*
Required to be handled, but may return just SWindowRenderLayoutHints()
@@ -110,35 +112,35 @@ public:
Called when the user requests two windows to be swapped places.
The layout is free to ignore.
*/
virtual void switchWindows(CWindow*, CWindow*) = 0;
virtual void switchWindows(CWindow*, CWindow*) = 0;
/*
Called when the user requests to change the splitratio by X
Called when the user requests to change the splitratio by or to X
on a window
*/
virtual void alterSplitRatioBy(CWindow*, float) = 0;
virtual void alterSplitRatio(CWindow*, float, bool exact = false) = 0;
/*
Called when something wants the current layout's name
*/
virtual std::string getLayoutName() = 0;
virtual std::string getLayoutName() = 0;
/*
Called for getting the next candidate for a focus
*/
virtual CWindow* getNextWindowCandidate(CWindow*);
virtual CWindow* getNextWindowCandidate(CWindow*);
/*
Internal: called when window focus changes
*/
virtual void onWindowFocusChange(CWindow*);
virtual void onWindowFocusChange(CWindow*);
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
int m_iGrabbedCorner = 0;
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
int m_iGrabbedCorner = 0;
CWindow* m_pLastTiledWindow = nullptr;
CWindow* m_pLastTiledWindow = nullptr;
};

View File

@@ -30,6 +30,28 @@ int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) {
return no;
}
SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) {
for (auto& n : m_lMasterWorkspacesData) {
if (n.workspaceID == ws)
return &n;
}
//create on the fly if it doesn't exist yet
const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back();
PWORKSPACEDATA->workspaceID = ws;
const auto orientation = &g_pConfigManager->getConfigValuePtr("master:orientation")->strValue;
if (*orientation == "top") {
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
} else if (*orientation == "right") {
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
} else if (*orientation == "bottom") {
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
} else {
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
}
return PWORKSPACEDATA;
}
std::string CHyprMasterLayout::getLayoutName() {
return "Master";
}
@@ -47,30 +69,30 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
if (pWindow->m_bIsFloating)
return;
static auto *const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
static auto* const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
PNODE->workspaceID = pWindow->m_iWorkspaceID;
PNODE->pWindow = pWindow;
PNODE->pWindow = pWindow;
static auto *const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue;
static auto* const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue;
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
float lastSplitPercent = 0.5f;
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
float lastSplitPercent = 0.5f;
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) {
for (auto& nd : m_lMasterNodesData) {
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
nd.isMaster = false;
nd.isMaster = false;
lastSplitPercent = nd.percMaster;
break;
}
}
PNODE->isMaster = true;
PNODE->isMaster = true;
PNODE->percMaster = lastSplitPercent;
// first, check if it isn't too big.
@@ -85,7 +107,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
PNODE->isMaster = false;
// first, check if it isn't too big.
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) {
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow);
MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) {
// we can't continue. make it floating.
pWindow->m_bIsFloating = true;
m_lMasterNodesData.remove(*PNODE);
@@ -111,6 +134,10 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
if (!PNODE)
return;
pWindow->m_sSpecialRenderData.rounding = true;
pWindow->m_sSpecialRenderData.border = true;
pWindow->m_sSpecialRenderData.decorate = true;
if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
@@ -120,17 +147,20 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
// find new one
for (auto& nd : m_lMasterNodesData) {
if (!nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
nd.isMaster = true;
nd.isMaster = true;
nd.percMaster = PNODE->percMaster;
break;
}
}
}
const auto WORKSPACEID = PNODE->workspaceID;
m_lMasterNodesData.remove(*PNODE);
if (getMastersOnWorkspace(PNODE->workspaceID) == getNodesOnWorkspace(PNODE->workspaceID) && MASTERSLEFT > 1) {
if (getMastersOnWorkspace(WORKSPACEID) == getNodesOnWorkspace(WORKSPACEID) && MASTERSLEFT > 1) {
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
if (it->workspaceID == PNODE->workspaceID) {
if (it->workspaceID == WORKSPACEID) {
it->isMaster = false;
break;
}
@@ -141,7 +171,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
}
void CHyprMasterLayout::recalculateMonitor(const int& monid) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (!PWORKSPACE)
@@ -149,8 +179,8 @@ void CHyprMasterLayout::recalculateMonitor(const int& monid) {
g_pHyprRenderer->damageMonitor(PMONITOR);
if (PMONITOR->specialWorkspaceOpen) {
calculateWorkspace(SPECIAL_WORKSPACE_ID);
if (PMONITOR->specialWorkspaceID) {
calculateWorkspace(PMONITOR->specialWorkspaceID);
}
if (PWORKSPACE->m_bHasFullscreenWindow) {
@@ -158,15 +188,15 @@ void CHyprMasterLayout::recalculateMonitor(const int& monid) {
return;
// massive hack from the fullscreen func
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
SMasterNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
fakeNode.pWindow = PFULLWINDOW;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = PWORKSPACE->m_iID;
PFULLWINDOW->m_vPosition = fakeNode.position;
PFULLWINDOW->m_vSize = fakeNode.size;
PFULLWINDOW->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
@@ -183,6 +213,8 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
if (!PWORKSPACE)
return;
const auto PWORKSPACEDATA = getMasterWorkspaceData(ws);
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID);
@@ -192,61 +224,129 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID);
//compute placement of master window(s)
if (getNodesOnWorkspace(PWORKSPACE->m_iID) < 2) {
PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition;
PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x,
PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
applyNodeDataToWindow(PMASTERNODE);
return;
} else {
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
int nodesLeft = MASTERS;
float nextY = 0;
} else if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT || PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
int nodesLeft = MASTERS;
float nextY = 0;
const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster;
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
if (PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition +
Vector2D(PMONITOR->vecSize.x - WIDTH - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x, nextY);
} else {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
}
float HEIGHT = nodesLeft > 1 ? heightLeft / nodesLeft * n.percSize : heightLeft;
if (HEIGHT > heightLeft * 0.9f && nodesLeft > 1)
HEIGHT = heightLeft * 0.9f;
n.size = Vector2D((PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster, HEIGHT);
n.size = Vector2D(WIDTH, HEIGHT);
nodesLeft--;
heightLeft -= HEIGHT;
nextY += HEIGHT;
applyNodeDataToWindow(&n);
}
}
} else if (PWORKSPACEDATA->orientation == ORIENTATION_TOP || PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x;
int nodesLeft = MASTERS;
float nextX = 0;
const float HEIGHT = (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y) * PMASTERNODE->percMaster;
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) {
if (PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition +
Vector2D(nextX, PMONITOR->vecSize.y - HEIGHT - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
} else {
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0);
}
float WIDTH = nodesLeft > 1 ? widthLeft / nodesLeft * n.percSize : widthLeft;
if (WIDTH > widthLeft * 0.9f && nodesLeft > 1)
WIDTH = widthLeft * 0.9f;
n.size = Vector2D(WIDTH, HEIGHT);
nodesLeft--;
widthLeft -= WIDTH;
nextX += WIDTH;
applyNodeDataToWindow(&n);
}
}
}
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
//compute placement of slave window(s)
int slavesLeft = getNodesOnWorkspace(PWORKSPACE->m_iID) - MASTERS;
float nextY = 0;
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT || PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
float nextY = 0;
const float WIDTH = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x;
for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
continue;
for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
continue;
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * PMONITOR->vecSize.x, nextY);
float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
HEIGHT = heightLeft * 0.9f;
nd.size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x, HEIGHT);
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT) {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition +
Vector2D(PMASTERNODE->percMaster * (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x), nextY);
} else {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
}
float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
HEIGHT = heightLeft * 0.9f;
nd.size = Vector2D(WIDTH, HEIGHT);
slavesLeft--;
heightLeft -= HEIGHT;
nextY += HEIGHT;
slavesLeft--;
heightLeft -= HEIGHT;
nextY += HEIGHT;
applyNodeDataToWindow(&nd);
applyNodeDataToWindow(&nd);
}
} else if (PWORKSPACEDATA->orientation == ORIENTATION_TOP || PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x;
float nextX = 0;
const float HEIGHT = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y - PMASTERNODE->size.y;
for (auto& nd : m_lMasterNodesData) {
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
continue;
if (PWORKSPACEDATA->orientation == ORIENTATION_TOP) {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition +
Vector2D(nextX, PMASTERNODE->percMaster * (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y));
} else {
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0);
}
float WIDTH = slavesLeft > 1 ? widthLeft / slavesLeft * nd.percSize : widthLeft;
if (WIDTH > widthLeft * 0.9f && slavesLeft > 1)
WIDTH = widthLeft * 0.9f;
nd.size = Vector2D(WIDTH, HEIGHT);
slavesLeft--;
widthLeft -= WIDTH;
nextX += WIDTH;
applyNodeDataToWindow(&nd);
}
}
}
void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
CMonitor* PMONITOR = nullptr;
if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) {
if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen) {
if (m->specialWorkspaceID == pNode->workspaceID) {
PMONITOR = m.get();
break;
}
@@ -261,14 +361,14 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
}
// for gaps outer
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
const auto PWINDOW = pNode->pWindow;
@@ -277,49 +377,49 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
return;
}
static auto *const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue;
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue;
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position;
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1) {
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
(getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 ||
(PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.decorate = false;
return;
}
PWINDOW->m_sSpecialRenderData.rounding = true;
PWINDOW->m_sSpecialRenderData.border = true;
PWINDOW->m_sSpecialRenderData.border = true;
PWINDOW->m_sSpecialRenderData.decorate = true;
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN,
DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN, DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN,
DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN, DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
calcPos = calcPos + OFFSETTOPLEFT;
calcPos = calcPos + OFFSETTOPLEFT;
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue;
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue;
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
} else {
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealSize = calcSize;
PWINDOW->m_vRealPosition = calcPos;
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
@@ -363,22 +463,38 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* p
m_bForceWarps = true;
double delta = pixResize.x / PMONITOR->vecSize.x;
const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace);
double delta = 0;
switch (PWORKSPACEDATA->orientation) {
case ORIENTATION_LEFT: delta = pixResize.x / PMONITOR->vecSize.x; break;
case ORIENTATION_RIGHT: delta = -pixResize.x / PMONITOR->vecSize.x; break;
case ORIENTATION_BOTTOM: delta = -pixResize.y / PMONITOR->vecSize.y; break;
case ORIENTATION_TOP: delta = pixResize.y / PMONITOR->vecSize.y; break;
default: UNREACHABLE();
}
for (auto& n : m_lMasterNodesData) {
if (n.isMaster)
if (n.isMaster && n.workspaceID == PMONITOR->activeWorkspace)
n.percMaster = std::clamp(n.percMaster + delta, 0.05, 0.95);
}
// check the up/down resize
if (pixResize.y != 0) {
const auto RESIZEDELTA = PWORKSPACEDATA->orientation % 2 == 1 ? pixResize.x : pixResize.y;
if (RESIZEDELTA != 0) {
if (PNODE->isMaster && getMastersOnWorkspace(PNODE->workspaceID) > 1) {
// check master size
const auto SIZEY = (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getMastersOnWorkspace(PNODE->workspaceID);
PNODE->percSize = std::clamp(PNODE->percSize + pixResize.y / SIZEY, 0.05, 1.95);
const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ?
(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / getMastersOnWorkspace(PNODE->workspaceID) :
(PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getMastersOnWorkspace(PNODE->workspaceID);
PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95);
} else if (!PNODE->isMaster && (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) > 1) {
const auto SIZEY = (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getNodesOnWorkspace(PNODE->workspaceID);
PNODE->percSize = std::clamp(PNODE->percSize + pixResize.y / SIZEY, 0.05, 1.95);
const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ?
(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / getNodesOnWorkspace(PNODE->workspaceID) :
(PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getNodesOnWorkspace(PNODE->workspaceID);
PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95);
}
}
@@ -391,10 +507,10 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
if (!g_pCompositor->windowValidMapped(pWindow))
return;
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return; // ignore
if (on == pWindow->m_bIsFullscreen || g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID))
return; // ignore
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
@@ -404,7 +520,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
}
// otherwise, accept it.
pWindow->m_bIsFullscreen = on;
pWindow->m_bIsFullscreen = on;
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
@@ -417,7 +533,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
else {
// get back its' dimensions from position and size
pWindow->m_vRealPosition = pWindow->m_vPosition;
pWindow->m_vRealSize = pWindow->m_vSize;
pWindow->m_vRealSize = pWindow->m_vSize;
}
} else {
// if it now got fullscreen, make it fullscreen
@@ -427,25 +543,25 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
// save position and size if floating
if (pWindow->m_bIsFloating) {
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
pWindow->m_vSize = pWindow->m_vRealSize.vec();
pWindow->m_vSize = pWindow->m_vRealSize.vec();
}
// apply new pos and size being monitors' box
if (fullscreenMode == FULLSCREEN_FULL) {
pWindow->m_vRealPosition = PMONITOR->vecPosition;
pWindow->m_vRealSize = PMONITOR->vecSize;
pWindow->m_vRealSize = PMONITOR->vecSize;
} else {
// This is a massive hack.
// We make a fake "only" node and apply
// To keep consistent with the settings without C+P code
SMasterNodeData fakeNode;
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.pWindow = pWindow;
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
pWindow->m_vPosition = fakeNode.position;
pWindow->m_vSize = fakeNode.size;
pWindow->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode);
}
@@ -480,27 +596,34 @@ SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(CWindow* pWindow)
void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
// windows should be valid, insallah
const auto PNODE = getNodeFromWindow(pWindow);
const auto PNODE = getNodeFromWindow(pWindow);
const auto PNODE2 = getNodeFromWindow(pWindow2);
if (!PNODE2 || !PNODE)
return;
const auto inheritFullscreen = prepareLoseFocus(pWindow);
if (PNODE->workspaceID != PNODE2->workspaceID) {
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
}
// massive hack: just swap window pointers, lol
PNODE->pWindow = pWindow2;
PNODE->pWindow = pWindow2;
PNODE2->pWindow = pWindow;
recalculateMonitor(pWindow->m_iMonitorID);
if (PNODE2->workspaceID != PNODE->workspaceID)
recalculateMonitor(pWindow2->m_iMonitorID);
g_pHyprRenderer->damageWindow(pWindow);
g_pHyprRenderer->damageWindow(pWindow2);
prepareNewFocus(pWindow2, inheritFullscreen);
}
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
void CHyprMasterLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exact) {
// window should be valid, insallah
const auto PNODE = getNodeFromWindow(pWindow);
@@ -510,7 +633,8 @@ void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
PMASTER->percMaster = std::clamp(PMASTER->percMaster + ratio, 0.05f, 0.95f);
float newRatio = exact ? ratio : PMASTER->percMaster + ratio;
PMASTER->percMaster = std::clamp(newRatio, 0.05f, 0.95f);
recalculateMonitor(pWindow->m_iMonitorID);
}
@@ -532,7 +656,7 @@ CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) {
} else {
// focus next
bool reached = false;
bool found = false;
bool found = false;
for (auto n : m_lMasterNodesData) {
if (n.pWindow == pWindow) {
reached = true;
@@ -552,16 +676,16 @@ CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) {
}
} else {
if (PNODE->isMaster) {
// focus the first non master
// focus the last non master
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
if (it->pWindow != pWindow && it->workspaceID == pWindow->m_iWorkspaceID) {
return it->pWindow;
}
}
} else {
// focus next
// focus previous
bool reached = false;
bool found = false;
bool found = false;
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
if (it->pWindow == pWindow) {
reached = true;
@@ -584,14 +708,35 @@ CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) {
return nullptr;
}
bool CHyprMasterLayout::prepareLoseFocus(CWindow* pWindow) {
if (!pWindow)
return false;
//if the current window is fullscreen, make it normal again if we are about to lose focus
if (pWindow->m_bIsFullscreen) {
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
static auto* const INHERIT = &g_pConfigManager->getConfigValuePtr("master:inherit_fullscreen")->intValue;
return *INHERIT == 1;
}
return false;
}
void CHyprMasterLayout::prepareNewFocus(CWindow* pWindow, bool inheritFullscreen) {
if (!pWindow)
return;
if (inheritFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, true, FULLSCREEN_MAXIMIZED);
}
std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
if (!g_pCompositor->windowValidMapped(PWINDOWTOCHANGETO))
return;
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, middle.x, middle.y);
g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f);
};
if (message == "swapwithmaster") {
@@ -605,12 +750,21 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID);
if (!PMASTER || PMASTER->pWindow == PWINDOW)
if (!PMASTER)
return 0;
switchWindows(PWINDOW, PMASTER->pWindow);
switchToWindow(PWINDOW);
if (PMASTER->pWindow != PWINDOW) {
switchWindows(PWINDOW, PMASTER->pWindow);
switchToWindow(PWINDOW);
} else {
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
switchWindows(n.pWindow, PMASTER->pWindow);
switchToWindow(n.pWindow);
break;
}
}
}
return 0;
} else if (message == "focusmaster") {
@@ -619,12 +773,25 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PWINDOW)
return 0;
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID);
if (!PMASTER || PMASTER->pWindow == PWINDOW)
if (!PMASTER)
return 0;
switchToWindow(PMASTER->pWindow);
if (PMASTER->pWindow != PWINDOW) {
switchToWindow(PMASTER->pWindow);
prepareNewFocus(PMASTER->pWindow, inheritFullscreen);
} else {
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
switchToWindow(n.pWindow);
prepareNewFocus(n.pWindow, inheritFullscreen);
break;
}
}
}
return 0;
} else if (message == "cyclenext") {
@@ -633,14 +800,22 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PWINDOW)
return 0;
switchToWindow(getNextWindow(PWINDOW, true));
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
const auto PNEXTWINDOW = getNextWindow(PWINDOW, true);
switchToWindow(PNEXTWINDOW);
prepareNewFocus(PNEXTWINDOW, inheritFullscreen);
} else if (message == "cycleprev") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
return 0;
switchToWindow(getNextWindow(PWINDOW, false));
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
const auto PPREVWINDOW = getNextWindow(PWINDOW, false);
switchToWindow(PPREVWINDOW);
prepareNewFocus(PPREVWINDOW, inheritFullscreen);
} else if (message == "swapnext") {
if (!g_pCompositor->windowValidMapped(header.pWindow))
return 0;
@@ -653,6 +828,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true);
if (PWINDOWTOSWAPWITH) {
prepareLoseFocus(header.pWindow);
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
g_pCompositor->focusWindow(header.pWindow);
}
@@ -668,6 +844,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false);
if (PWINDOWTOSWAPWITH) {
prepareLoseFocus(header.pWindow);
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
g_pCompositor->focusWindow(header.pWindow);
}
@@ -678,7 +855,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (header.pWindow->m_bIsFloating)
return 0;
const auto PNODE = getNodeFromWindow(header.pWindow);
const auto PNODE = getNodeFromWindow(header.pWindow);
const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID);
const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID);
@@ -686,6 +863,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (MASTERS + 2 > WINDOWS)
return 0;
prepareLoseFocus(header.pWindow);
if (!PNODE || PNODE->isMaster) {
// first non-master node
for (auto& n : m_lMasterNodesData) {
@@ -716,6 +895,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (WINDOWS < 2 || MASTERS < 2)
return 0;
prepareLoseFocus(header.pWindow);
if (!PNODE || !PNODE->isMaster) {
// first non-master node
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
@@ -728,6 +909,61 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
PNODE->isMaster = false;
}
recalculateMonitor(header.pWindow->m_iMonitorID);
} else if (message == "orientationleft" || message == "orientationright" || message == "orientationtop" || message == "orientationbottom") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
return 0;
prepareLoseFocus(PWINDOW);
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
if (message == "orientationleft")
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
else if (message == "orientationright")
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
else if (message == "orientationtop")
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
else if (message == "orientationbottom")
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
recalculateMonitor(header.pWindow->m_iMonitorID);
} else if (message == "orientationnext") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
return 0;
prepareLoseFocus(PWINDOW);
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
if (PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
} else {
PWORKSPACEDATA->orientation = (eOrientation)(PWORKSPACEDATA->orientation + 1);
}
recalculateMonitor(header.pWindow->m_iMonitorID);
} else if (message == "orientationprev") {
const auto PWINDOW = header.pWindow;
if (!PWINDOW)
return 0;
prepareLoseFocus(PWINDOW);
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT) {
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
} else {
PWORKSPACEDATA->orientation = (eOrientation)(PWORKSPACEDATA->orientation - 1);
}
recalculateMonitor(header.pWindow->m_iMonitorID);
}

View File

@@ -1,60 +1,84 @@
#pragma once
#include "IHyprLayout.hpp"
#include <vector>
#include <list>
#include <deque>
#include <any>
enum eFullscreenMode : uint8_t;
//orientation determines which side of the screen the master area resides
enum eOrientation : uint8_t
{
ORIENTATION_LEFT = 0,
ORIENTATION_TOP,
ORIENTATION_RIGHT,
ORIENTATION_BOTTOM
};
struct SMasterNodeData {
bool isMaster = false;
float percMaster = 0.5f;
bool isMaster = false;
float percMaster = 0.5f;
CWindow* pWindow = nullptr;
Vector2D position;
Vector2D size;
float percSize = 1.f; // size multiplier for resizing children
float percSize = 1.f; // size multiplier for resizing children
int workspaceID = -1;
int workspaceID = -1;
bool operator==(const SMasterNodeData& rhs) {
bool operator==(const SMasterNodeData& rhs) {
return pWindow == rhs.pWindow;
}
};
struct SMasterWorkspaceData {
int workspaceID = -1;
eOrientation orientation = ORIENTATION_LEFT;
bool operator==(const SMasterWorkspaceData& rhs) {
return workspaceID == rhs.workspaceID;
}
};
class CHyprMasterLayout : public IHyprLayout {
public:
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*);
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
public:
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*);
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatioBy(CWindow*, float);
virtual std::string getLayoutName();
virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatio(CWindow*, float, bool);
virtual std::string getLayoutName();
virtual void onEnable();
virtual void onDisable();
virtual void onEnable();
virtual void onDisable();
private:
private:
std::list<SMasterNodeData> m_lMasterNodesData;
std::vector<SMasterWorkspaceData> m_lMasterWorkspacesData;
std::list<SMasterNodeData> m_lMasterNodesData;
bool m_bForceWarps = false;
bool m_bForceWarps = false;
int getNodesOnWorkspace(const int&);
void applyNodeDataToWindow(SMasterNodeData*);
SMasterNodeData* getNodeFromWindow(CWindow*);
SMasterNodeData* getMasterNodeOnWorkspace(const int&);
void calculateWorkspace(const int&);
CWindow* getNextWindow(CWindow*, bool);
int getMastersOnWorkspace(const int&);
int getNodesOnWorkspace(const int&);
void applyNodeDataToWindow(SMasterNodeData*);
SMasterNodeData* getNodeFromWindow(CWindow*);
SMasterNodeData* getMasterNodeOnWorkspace(const int&);
SMasterWorkspaceData* getMasterWorkspaceData(const int&);
void calculateWorkspace(const int&);
CWindow* getNextWindow(CWindow*, bool);
int getMastersOnWorkspace(const int&);
bool prepareLoseFocus(CWindow*);
void prepareNewFocus(CWindow*, bool inherit_fullscreen);
friend struct SMasterNodeData;
friend struct SMasterWorkspaceData;
};

View File

@@ -4,10 +4,9 @@
#include "config/ConfigManager.hpp"
#include "init/initHelpers.hpp"
#include <iostream>
// I am a bad bad boy and have used some global vars here,
// just for this file
bool ignoreSudo = false;
#ifdef USES_SYSTEMD
#include <systemd/sd-daemon.h> // for sd_notify
#endif
int main(int argc, char** argv) {
@@ -19,9 +18,12 @@ int main(int argc, char** argv) {
for (auto i = 0; i < argc; ++i)
cmd += std::string(i == 0 ? "" : " ") + argv[i];
setenv("HYPRLAND_CMD", cmd.c_str(), 1);
setenv("XDG_BACKEND", "wayland", 1);
setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 0);
// parse some args
std::string configPath;
bool ignoreSudo = false;
for (int i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--i-am-really-stupid"))
ignoreSudo = true;
@@ -29,9 +31,9 @@ int main(int argc, char** argv) {
configPath = std::string(argv[++i]);
Debug::log(LOG, "Using config location %s.", configPath.c_str());
} else {
std::cout << "Hyprland usage: Hyprland [arg [...]].\n\nArguments:\n" <<
"--help -h | Show this help message\n" <<
"--config -c | Specify config file to use\n";
std::cout << "Hyprland usage: Hyprland [arg [...]].\n\nArguments:\n"
<< "--help -h | Show this help message\n"
<< "--config -c | Specify config file to use\n";
return 1;
}
}
@@ -42,7 +44,7 @@ int main(int argc, char** argv) {
if (Init::isSudo()) {
std::cout << "Hyprland shall not be run as the root user. If you really want to, use the --i-am-really-stupid flag.\n";
return 1;
}
}
} else {
std::cout << "Running with ignored root checks, I surely hope you know what you're doing.\n";
sleep(1);
@@ -56,7 +58,7 @@ int main(int argc, char** argv) {
// let's init the compositor.
// it initializes basic Wayland stuff in the constructor.
g_pCompositor = std::make_unique<CCompositor>();
g_pCompositor = std::make_unique<CCompositor>();
g_pCompositor->explicitConfigPath = configPath;
Debug::log(LOG, "Hyprland init finished.");
@@ -67,6 +69,12 @@ int main(int argc, char** argv) {
// If we are here it means we got yote.
Debug::log(LOG, "Hyprland reached the end.");
#ifdef USES_SYSTEMD
// tell systemd it destroy bound/related units
if (sd_booted() > 0)
sd_notify(0, "STOPPING=1");
#endif
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
// kill all clients

View File

@@ -21,17 +21,17 @@ void CAnimationManager::addBezierWithName(std::string name, const Vector2D& p1,
void CAnimationManager::tick() {
bool animGlobalDisabled = false;
bool animGlobalDisabled = false;
static auto *const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
if (!*PANIMENABLED)
animGlobalDisabled = true;
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto *const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto* const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
const auto DEFAULTBEZIER = m_mBezierCurves.find("default");
const auto DEFAULTBEZIER = m_mBezierCurves.find("default");
std::vector<CAnimatedVariable*> animationEndedVars;
@@ -50,23 +50,23 @@ void CAnimationManager::tick() {
const float SPENT = av->getPercent();
// window stuff
const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
CMonitor* PMONITOR = nullptr;
bool animationsDisabled = animGlobalDisabled;
const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
CMonitor* PMONITOR = nullptr;
bool animationsDisabled = animGlobalDisabled;
wlr_box WLRBOXPREV = {0,0,0,0};
wlr_box WLRBOXPREV = {0, 0, 0, 0};
if (PWINDOW) {
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
animationsDisabled = animationsDisabled || PWINDOW->m_sAdditionalConfigData.forceNoAnims;
} else if (PWORKSPACE) {
PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
} else if (PLAYER) {
WLRBOXPREV = PLAYER->geometry;
PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f);
PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f);
}
// beziers are with a switch unforto
@@ -85,7 +85,7 @@ void CAnimationManager::tick() {
break;
}
const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto DELTA = av->m_fGoal - av->m_fBegun;
const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier);
if (BEZIER != m_mBezierCurves.end())
@@ -106,7 +106,7 @@ void CAnimationManager::tick() {
break;
}
const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto DELTA = av->m_vGoal - av->m_vBegun;
const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier);
if (BEZIER != m_mBezierCurves.end())
@@ -127,7 +127,7 @@ void CAnimationManager::tick() {
break;
}
const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto DELTA = av->m_cGoal - av->m_cBegun;
const auto BEZIER = m_mBezierCurves.find(av->m_pConfig->pValues->internalBezier);
if (BEZIER != m_mBezierCurves.end())
@@ -164,40 +164,45 @@ void CAnimationManager::tick() {
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR);
}
break;
} case AVARDAMAGE_BORDER: {
}
case AVARDAMAGE_BORDER: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!");
// damage only the border.
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
const auto ROUNDINGSIZE = *PROUNDING + 1;
const auto BORDERSIZE = *PBORDERSIZE;
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
const auto ROUNDINGSIZE = *PROUNDING + 1;
const auto BORDERSIZE = *PBORDERSIZE;
// damage for old box
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXPREV.height + 2 * BORDERSIZE); // left
g_pHyprRenderer->damageBox(WLRBOXPREV.x + WLRBOXPREV.width - ROUNDINGSIZE, WLRBOXPREV.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXPREV.height + 2 * BORDERSIZE); // right
g_pHyprRenderer->damageBox(WLRBOXPREV.x, WLRBOXPREV.y + WLRBOXPREV.height - ROUNDINGSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
g_pHyprRenderer->damageBox(WLRBOXPREV.x - BORDERSIZE, WLRBOXPREV.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXPREV.height + 2 * BORDERSIZE); // left
g_pHyprRenderer->damageBox(WLRBOXPREV.x + WLRBOXPREV.width - ROUNDINGSIZE, WLRBOXPREV.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE,
WLRBOXPREV.height + 2 * BORDERSIZE); // right
g_pHyprRenderer->damageBox(WLRBOXPREV.x, WLRBOXPREV.y + WLRBOXPREV.height - ROUNDINGSIZE, WLRBOXPREV.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom
// damage for new box
const wlr_box WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y};
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // left
g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // right
g_pHyprRenderer->damageBox(WLRBOXNEW.x, WLRBOXNEW.y + WLRBOXNEW.height - ROUNDINGSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // left
g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE,
WLRBOXNEW.height + 2 * BORDERSIZE); // right
g_pHyprRenderer->damageBox(WLRBOXNEW.x, WLRBOXNEW.y + WLRBOXNEW.height - ROUNDINGSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom
break;
} case AVARDAMAGE_SHADOW: {
}
case AVARDAMAGE_SHADOW: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!");
static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
if (PDECO) {
const auto EXTENTS = PDECO->getWindowDecorationExtents();
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y,
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y,
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x,
PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
if (!*PSHADOWIGNOREWINDOW) {
// easy, damage the entire box
@@ -206,7 +211,8 @@ void CAnimationManager::tick() {
pixman_region32_t rg;
pixman_region32_init_rect(&rg, dmg.x, dmg.y, dmg.width, dmg.height);
pixman_region32_t wb;
pixman_region32_init_rect(&wb, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y);
pixman_region32_init_rect(&wb, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x,
PWINDOW->m_vRealSize.vec().y);
pixman_region32_subtract(&rg, &rg, &wb);
g_pHyprRenderer->damageRegion(&rg);
pixman_region32_fini(&rg);
@@ -265,7 +271,7 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
}
bool CAnimationManager::bezierExists(const std::string& bezier) {
for (auto&[bc, bz] : m_mBezierCurves) {
for (auto& [bc, bz] : m_mBezierCurves) {
if (bc == bezier)
return true;
}
@@ -279,33 +285,37 @@ bool CAnimationManager::bezierExists(const std::string& bezier) {
//
void CAnimationManager::animationPopin(CWindow* pWindow, bool close, float minPerc) {
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
if (!close) {
pWindow->m_vRealSize.setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}));
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_vValue / 2.f);
} else {
pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y});
pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y});
pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_vGoal / 2.f;
}
}
void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool close) {
pWindow->m_vRealSize.warp(false); // size we preserve in slide
pWindow->m_vRealSize.warp(false); // size we preserve in slide
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALPOS = pWindow->m_vRealPosition.goalv();
const auto GOALSIZE = pWindow->m_vRealSize.goalv();
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
Vector2D posOffset;
Vector2D posOffset;
if (force != "") {
if (force == "bottom") posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
else if (force == "left") posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
else if (force == "right") posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
else posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
if (force == "bottom")
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y + PMONITOR->vecSize.y);
else if (force == "left")
posOffset = GOALPOS - Vector2D(GOALSIZE.x, 0);
else if (force == "right")
posOffset = GOALPOS + Vector2D(GOALSIZE.x, 0);
else
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
if (!close)
pWindow->m_vRealPosition.setValue(posOffset);
@@ -318,9 +328,9 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool
const auto MIDPOINT = GOALPOS + GOALSIZE / 2.f;
// check sides it touches
const bool DISPLAYLEFT = STICKS(pWindow->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pWindow->m_vPosition.x + pWindow->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pWindow->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYLEFT = STICKS(pWindow->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
const bool DISPLAYRIGHT = STICKS(pWindow->m_vPosition.x + pWindow->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
const bool DISPLAYTOP = STICKS(pWindow->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
const bool DISPLAYBOTTOM = STICKS(pWindow->m_vPosition.y + pWindow->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
if (DISPLAYBOTTOM && DISPLAYTOP) {
@@ -351,12 +361,12 @@ void CAnimationManager::animationSlide(CWindow* pWindow, std::string force, bool
void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (!close) {
pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn");
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn");
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeIn");
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn");
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeIn");
} else {
pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut");
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut");
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeOut");
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut");
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeOut");
}
auto ANIMSTYLE = pWindow->m_vRealPosition.m_pConfig->pValues->internalStyle;
@@ -386,7 +396,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (pWindow->m_sAdditionalConfigData.animationStyle.find("%") != std::string::npos) {
try {
auto percstr = pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) {
; // oops
}
@@ -404,7 +414,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (ANIMSTYLE.find("%") != 0) {
try {
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) {
; // oops
}
@@ -425,10 +435,8 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
if (style.find("%") != std::string::npos) {
try {
auto percstr = style.substr(style.find_last_of(' '));
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) {
return "invalid minperc";
}
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
} catch (std::exception& e) { return "invalid minperc"; }
return "";
}
@@ -450,3 +458,9 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
return "";
}
CBezierCurve* CAnimationManager::getBezier(const std::string& name) {
const auto BEZIER = std::find_if(m_mBezierCurves.begin(), m_mBezierCurves.end(), [&](const auto& other) { return other.first == name; });
return BEZIER == m_mBezierCurves.end() ? &m_mBezierCurves["default"] : &BEZIER->second;
}

View File

@@ -8,35 +8,35 @@
#include "../Window.hpp"
class CAnimationManager {
public:
public:
CAnimationManager();
void tick();
void addBezierWithName(std::string, const Vector2D&, const Vector2D&);
void removeAllBeziers();
void tick();
void addBezierWithName(std::string, const Vector2D&, const Vector2D&);
void removeAllBeziers();
void onWindowPostCreateClose(CWindow*, bool close = false);
void onWindowPostCreateClose(CWindow*, bool close = false);
bool bezierExists(const std::string&);
bool bezierExists(const std::string&);
CBezierCurve* getBezier(const std::string&);
std::string styleValidInConfigVar(const std::string&, const std::string&);
std::string styleValidInConfigVar(const std::string&, const std::string&);
std::list<CAnimatedVariable*> m_lAnimatedVariables;
private:
bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b);
bool deltaSmallToFlip(const CColor& a, const CColor& b);
bool deltaSmallToFlip(const float& a, const float& b);
bool deltazero(const Vector2D& a, const Vector2D& b);
bool deltazero(const CColor& a, const CColor& b);
bool deltazero(const float& a, const float& b);
private:
bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b);
bool deltaSmallToFlip(const CColor& a, const CColor& b);
bool deltaSmallToFlip(const float& a, const float& b);
bool deltazero(const Vector2D& a, const Vector2D& b);
bool deltazero(const CColor& a, const CColor& b);
bool deltazero(const float& a, const float& b);
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
// Anim stuff
void animationPopin(CWindow*, bool close = false, float minPerc = 0.f);
void animationSlide(CWindow*, std::string force = "", bool close = false);
void animationPopin(CWindow*, bool close = false, float minPerc = 0.f);
void animationSlide(CWindow*, std::string force = "", bool close = false);
};
inline std::unique_ptr<CAnimationManager> g_pAnimationManager;

View File

@@ -15,14 +15,13 @@
#include <string>
CEventManager::CEventManager() {
}
CEventManager::CEventManager() {}
int fdHandleWrite(int fd, uint32_t mask, void* data) {
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) {
// remove, hanged up
const auto ACCEPTEDFDS = (std::deque<std::pair<int, wl_event_source*>>*)data;
for (auto it = ACCEPTEDFDS->begin(); it != ACCEPTEDFDS->end(); ) {
for (auto it = ACCEPTEDFDS->begin(); it != ACCEPTEDFDS->end();) {
if (it->first == fd) {
wl_event_source_remove(it->second); // remove this fd listener
it = ACCEPTEDFDS->erase(it);
@@ -45,7 +44,7 @@ void CEventManager::startThread() {
}
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket2.sock";
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket2.sock";
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
@@ -54,7 +53,7 @@ void CEventManager::startThread() {
listen(SOCKET, 10);
sockaddr_in clientAddress;
socklen_t clientSize = sizeof(clientAddress);
socklen_t clientSize = sizeof(clientAddress);
Debug::log(LOG, "Hypr socket 2 started at %s", socketPath.c_str());
@@ -70,7 +69,8 @@ void CEventManager::startThread() {
Debug::log(LOG, "Socket 2 accepted a new client at FD %d", ACCEPTEDCONNECTION);
// add to event loop so we can close it when we need to
m_dAcceptedSocketFDs.push_back({ACCEPTEDCONNECTION, wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, WL_EVENT_READABLE, fdHandleWrite, &m_dAcceptedSocketFDs)});
m_dAcceptedSocketFDs.push_back(
{ACCEPTEDCONNECTION, wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, WL_EVENT_READABLE, fdHandleWrite, &m_dAcceptedSocketFDs)});
}
}
@@ -98,15 +98,18 @@ void CEventManager::flushEvents() {
void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
if ((m_bIgnoreEvents && !force) || g_pCompositor->m_bIsShuttingDown) {
Debug::log(WARN, "Suppressed (ignoreevents true / shutting down) event of type %s, content: %s",event.event.c_str(), event.data.c_str());
Debug::log(WARN, "Suppressed (ignoreevents true / shutting down) event of type %s, content: %s", event.event.c_str(), event.data.c_str());
return;
}
std::thread([&](const SHyprIPCEvent ev) {
eventQueueMutex.lock();
m_dQueuedEvents.push_back(ev);
eventQueueMutex.unlock();
std::thread(
[&](const SHyprIPCEvent ev) {
eventQueueMutex.lock();
m_dQueuedEvents.push_back(ev);
eventQueueMutex.unlock();
flushEvents();
}, event).detach();
flushEvents();
},
event)
.detach();
}

View File

@@ -12,23 +12,22 @@ struct SHyprIPCEvent {
};
class CEventManager {
public:
public:
CEventManager();
void postEvent(const SHyprIPCEvent event, bool force = false);
void postEvent(const SHyprIPCEvent event, bool force = false);
void startThread();
void startThread();
bool m_bIgnoreEvents = false;
bool m_bIgnoreEvents = false;
std::thread m_tThread;
private:
private:
void flushEvents();
void flushEvents();
std::mutex eventQueueMutex;
std::deque<SHyprIPCEvent> m_dQueuedEvents;
std::mutex eventQueueMutex;
std::deque<SHyprIPCEvent> m_dQueuedEvents;
std::deque<std::pair<int, wl_event_source*>> m_dAcceptedSocketFDs;
};

View File

@@ -5,47 +5,48 @@
CKeybindManager::CKeybindManager() {
// initialize all dispatchers
m_mDispatchers["exec"] = spawn;
m_mDispatchers["killactive"] = killActive;
m_mDispatchers["closewindow"] = kill;
m_mDispatchers["togglefloating"] = toggleActiveFloating;
m_mDispatchers["workspace"] = changeworkspace;
m_mDispatchers["fullscreen"] = fullscreenActive;
m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace;
m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent;
m_mDispatchers["pseudo"] = toggleActivePseudo;
m_mDispatchers["movefocus"] = moveFocusTo;
m_mDispatchers["movewindow"] = moveActiveTo;
m_mDispatchers["centerwindow"] = centerWindow;
m_mDispatchers["togglegroup"] = toggleGroup;
m_mDispatchers["changegroupactive"] = changeGroupActive;
m_mDispatchers["togglesplit"] = toggleSplit;
m_mDispatchers["splitratio"] = alterSplitRatio;
m_mDispatchers["focusmonitor"] = focusMonitor;
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
m_mDispatchers["workspaceopt"] = workspaceOpt;
m_mDispatchers["exit"] = exitHyprland;
m_mDispatchers["exec"] = spawn;
m_mDispatchers["killactive"] = killActive;
m_mDispatchers["closewindow"] = kill;
m_mDispatchers["togglefloating"] = toggleActiveFloating;
m_mDispatchers["workspace"] = changeworkspace;
m_mDispatchers["fullscreen"] = fullscreenActive;
m_mDispatchers["fakefullscreen"] = fakeFullscreenActive;
m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace;
m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent;
m_mDispatchers["pseudo"] = toggleActivePseudo;
m_mDispatchers["movefocus"] = moveFocusTo;
m_mDispatchers["movewindow"] = moveActiveTo;
m_mDispatchers["centerwindow"] = centerWindow;
m_mDispatchers["togglegroup"] = toggleGroup;
m_mDispatchers["changegroupactive"] = changeGroupActive;
m_mDispatchers["togglesplit"] = toggleSplit;
m_mDispatchers["splitratio"] = alterSplitRatio;
m_mDispatchers["focusmonitor"] = focusMonitor;
m_mDispatchers["movecursortocorner"] = moveCursorToCorner;
m_mDispatchers["workspaceopt"] = workspaceOpt;
m_mDispatchers["exit"] = exitHyprland;
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
m_mDispatchers["forcerendererreload"] = forceRendererReload;
m_mDispatchers["resizeactive"] = resizeActive;
m_mDispatchers["moveactive"] = moveActive;
m_mDispatchers["cyclenext"] = circleNext;
m_mDispatchers["focuswindowbyclass"] = focusWindow;
m_mDispatchers["focuswindow"] = focusWindow;
m_mDispatchers["submap"] = setSubmap;
m_mDispatchers["pass"] = pass;
m_mDispatchers["layoutmsg"] = layoutmsg;
m_mDispatchers["toggleopaque"] = toggleOpaque;
m_mDispatchers["dpms"] = dpms;
m_mDispatchers["movewindowpixel"] = moveWindow;
m_mDispatchers["resizewindowpixel"] = resizeWindow;
m_mDispatchers["swapnext"] = swapnext;
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
m_mDispatchers["pin"] = pinActive;
m_mDispatchers["mouse"] = mouse;
m_mDispatchers["bringactivetotop"] = bringActiveToTop;
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
m_mDispatchers["forcerendererreload"] = forceRendererReload;
m_mDispatchers["resizeactive"] = resizeActive;
m_mDispatchers["moveactive"] = moveActive;
m_mDispatchers["cyclenext"] = circleNext;
m_mDispatchers["focuswindowbyclass"] = focusWindow;
m_mDispatchers["focuswindow"] = focusWindow;
m_mDispatchers["submap"] = setSubmap;
m_mDispatchers["pass"] = pass;
m_mDispatchers["layoutmsg"] = layoutmsg;
m_mDispatchers["toggleopaque"] = toggleOpaque;
m_mDispatchers["dpms"] = dpms;
m_mDispatchers["movewindowpixel"] = moveWindow;
m_mDispatchers["resizewindowpixel"] = resizeWindow;
m_mDispatchers["swapnext"] = swapnext;
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
m_mDispatchers["pin"] = pinActive;
m_mDispatchers["mouse"] = mouse;
m_mDispatchers["bringactivetotop"] = bringActiveToTop;
m_tScrollTimer.reset();
}
@@ -67,8 +68,7 @@ void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) {
if (it == m_lKeybinds.end())
break;
}
}
else if (it->modmask == mod && it->key == key) {
} else if (it->modmask == mod && it->key == key) {
it = m_lKeybinds.erase(it);
if (it == m_lKeybinds.end())
@@ -109,28 +109,27 @@ void CKeybindManager::updateXKBTranslationState() {
m_pXKBTranslationState = nullptr;
}
const auto FILEPATH = g_pConfigManager->getString("input:kb_file");
const auto RULES = g_pConfigManager->getString("input:kb_rules");
const auto MODEL = g_pConfigManager->getString("input:kb_model");
const auto LAYOUT = g_pConfigManager->getString("input:kb_layout");
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
const auto FILEPATH = g_pConfigManager->getString("input:kb_file");
const auto RULES = g_pConfigManager->getString("input:kb_rules");
const auto MODEL = g_pConfigManager->getString("input:kb_model");
const auto LAYOUT = g_pConfigManager->getString("input:kb_layout");
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
xkb_rule_names rules = {
.rules = RULES.c_str(),
.model = MODEL.c_str(),
.layout = LAYOUT.c_str(),
.variant = VARIANT.c_str(),
.options = OPTIONS.c_str()};
xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()};
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
auto PKEYMAP = FILEPATH == "" ? xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS) : xkb_keymap_new_from_file(PCONTEXT, fopen(FILEPATH.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
auto PKEYMAP = FILEPATH == "" ? xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS) :
xkb_keymap_new_from_file(PCONTEXT, fopen(FILEPATH.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!PKEYMAP) {
g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + ", layout: " + LAYOUT + " )", CColor(255, 50, 50, 255));
g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS +
", layout: " + LAYOUT + " )",
CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
Debug::log(ERR, "[XKBTranslationState] Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
Debug::log(ERR, "[XKBTranslationState] Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant,
rules.rules, rules.model, rules.options);
memset(&rules, 0, sizeof(rules));
PKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
@@ -148,7 +147,7 @@ bool CKeybindManager::ensureMouseBindState() {
m_bIsMouseBindActive = false;
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
g_pInputManager->currentlyDraggedWindow = nullptr;
g_pInputManager->dragMode = MBIND_INVALID;
g_pInputManager->dragMode = MBIND_INVALID;
return true;
}
@@ -176,9 +175,9 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
return true;
}
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(m_pXKBTranslationState, KEYCODE);
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(m_pXKBTranslationState, KEYCODE);
const xkb_keysym_t internalKeysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE);
if (handleInternalKeybinds(internalKeysym))
@@ -186,8 +185,8 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
m_uTimeLastMs = e->time_msec;
m_uLastCode = KEYCODE;
m_uTimeLastMs = e->time_msec;
m_uLastCode = KEYCODE;
m_uLastMouseCode = 0;
bool mouseBindWasActive = ensureMouseBindState();
@@ -198,7 +197,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
if (m_pActiveKeybindEventSource) {
wl_event_source_remove(m_pActiveKeybindEventSource);
m_pActiveKeybindEventSource = nullptr;
m_pActiveKeybind = nullptr;
m_pActiveKeybind = nullptr;
}
m_dPressedKeycodes.push_back(KEYCODE);
@@ -215,7 +214,7 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
if (m_pActiveKeybindEventSource) {
wl_event_source_remove(m_pActiveKeybindEventSource);
m_pActiveKeybindEventSource = nullptr;
m_pActiveKeybind = nullptr;
m_pActiveKeybind = nullptr;
}
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE), m_dPressedKeycodes.end());
@@ -232,9 +231,9 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
}
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
static auto *const PDELAY = &g_pConfigManager->getConfigValuePtr("binds:scroll_event_delay")->intValue;
static auto* const PDELAY = &g_pConfigManager->getConfigValuePtr("binds:scroll_event_delay")->intValue;
if (m_tScrollTimer.getMillis() < *PDELAY) {
m_tScrollTimer.reset();
@@ -261,11 +260,11 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
bool found = false;
bool found = false;
m_uLastMouseCode = e->button;
m_uLastCode = 0;
m_uTimeLastMs = e->time_msec;
m_uLastCode = 0;
m_uTimeLastMs = e->time_msec;
bool mouseBindWasActive = ensureMouseBindState();
@@ -316,7 +315,8 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
}
for (auto& k : m_lKeybinds) {
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release && k.handler != "pass" && k.handler != "mouse") || k.shadowed)
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap ||
(!pressed && !k.release && k.handler != "pass" && k.handler != "mouse") || k.shadowed)
continue;
if (!key.empty()) {
@@ -327,11 +327,11 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
continue;
} else {
if (keysym == 0)
continue; // this is a keycode check run
continue; // this is a keycode check run
// oMg such performance hit!!11!
// this little maneouver is gonna cost us 4µs
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
// small TODO: fix 0-9 keys and other modified ones with shift
@@ -370,7 +370,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
}
if (k.repeat) {
m_pActiveKeybind = &k;
m_pActiveKeybind = &k;
m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind);
const auto PACTIVEKEEB = g_pInputManager->m_pActiveKeyboard;
@@ -389,9 +389,9 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const int&
for (auto& k : m_lKeybinds) {
bool shadow = false;
bool shadow = false;
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
for (auto& pk : m_dPressedKeysyms) {
@@ -433,10 +433,10 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
// vtnr is bugged for some reason.
const std::string TTYSTR = execAndGet("head -n 1 /sys/devices/virtual/tty/tty0/active").substr(3);
unsigned int ttynum = 0;
unsigned int ttynum = 0;
try {
ttynum = std::stoll(TTYSTR);
} catch (std::exception &e) {
} catch (std::exception& e) {
; // oops?
}
@@ -452,7 +452,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
for (auto& m : g_pCompositor->m_vMonitors) {
m->noFrameSchedule = true;
m->framesToSkip = 1;
m->framesToSkip = 1;
}
Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY);
@@ -491,7 +491,7 @@ void CKeybindManager::spawn(std::string args) {
if (args[0] == '[') {
// we have exec rules
RULES = args.substr(1, args.substr(1).find_first_of(']'));
args = args.substr(args.find_first_of(']') + 1);
args = args.substr(args.find_first_of(']') + 1);
}
if (g_pXWaylandManager->m_sWLRXWayland)
@@ -594,7 +594,7 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
// remove drag status
g_pInputManager->currentlyDraggedWindow = nullptr;
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID))
return;
PWINDOW->m_bIsFloating = !PWINDOW->m_bIsFloating;
@@ -613,7 +613,7 @@ void CKeybindManager::centerWindow(std::string args) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
PWINDOW->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.f - PWINDOW->m_vRealSize.goalv() / 2.f;
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv();
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv();
}
void CKeybindManager::toggleActivePseudo(std::string args) {
@@ -629,8 +629,8 @@ void CKeybindManager::toggleActivePseudo(std::string args) {
}
void CKeybindManager::changeworkspace(std::string args) {
int workspaceToChangeTo = 0;
std::string workspaceName = "";
int workspaceToChangeTo = 0;
std::string workspaceName = "";
// Flag needed so that the previous workspace is not recorded when switching
// to a previous workspace.
@@ -639,7 +639,7 @@ void CKeybindManager::changeworkspace(std::string args) {
bool internal = false;
if (args.find("[internal]") == 0) {
workspaceToChangeTo = std::stoi(args.substr(10));
workspaceToChangeTo = std::stoi(args.substr(10));
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
if (PWORKSPACE)
workspaceName = PWORKSPACE->m_szName;
@@ -664,7 +664,7 @@ void CKeybindManager::changeworkspace(std::string args) {
// If the previous workspace ID isn't reset, cycles can form when continually going
// to the previous workspace again and again.
static auto *const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
static auto* const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
if (!*PALLOWWORKSPACECYCLES)
PCURRENTWORKSPACE->m_iPrevWorkspaceID = -1;
}
@@ -679,8 +679,8 @@ void CKeybindManager::changeworkspace(std::string args) {
// Workspace_back_and_forth being enabled means that an attempt to switch to
// the current workspace will instead switch to the previous.
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
static auto *const PBACKANDFORTH = &g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth")->intValue;
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
static auto* const PBACKANDFORTH = &g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth")->intValue;
if (*PBACKANDFORTH && PCURRENTWORKSPACE && PCURRENTWORKSPACE->m_iID == workspaceToChangeTo && PCURRENTWORKSPACE->m_iPrevWorkspaceID != -1 && !internal) {
@@ -707,6 +707,8 @@ void CKeybindManager::changeworkspace(std::string args) {
// remove constraints
g_pInputManager->unconstrainMouse();
g_pInputManager->m_bEmptyFocusCursorSet = false;
// if it's not internal, we will unfocus to prevent stuck focus
if (!internal)
g_pCompositor->focusWindow(nullptr);
@@ -721,7 +723,7 @@ void CKeybindManager::changeworkspace(std::string args) {
// Remember previous workspace.
PWORKSPACETOCHANGETO->m_iPrevWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
if (workspaceToChangeTo == SPECIAL_WORKSPACE_ID)
if (g_pCompositor->isWorkspaceSpecial(workspaceToChangeTo))
PWORKSPACETOCHANGETO->m_iMonitorID = PMONITOR->ID;
// if it's not visible, make it visible.
@@ -736,10 +738,10 @@ void CKeybindManager::changeworkspace(std::string args) {
}
// change it
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
if (!g_pCompositor->isWorkspaceSpecial(workspaceToChangeTo))
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
PMONITOR->specialWorkspaceOpen = true;
PMONITOR->specialWorkspaceID = workspaceToChangeTo;
// here and only here begin anim. we don't want to anim visible workspaces on other monitors.
// check if anim left or right
@@ -755,15 +757,9 @@ void CKeybindManager::changeworkspace(std::string args) {
}
// If the monitor is not the one our cursor's at, warp to it.
const bool anotherMonitor = PMONITOR != g_pCompositor->getMonitorFromCursor();
if (anotherMonitor) {
Vector2D middle = PMONITOR->vecPosition + PMONITOR->vecSize / 2.f;
g_pCompositor->warpCursorTo(middle);
// event for focusedmon, as we changed.
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", PMONITOR->szName + "," + PWORKSPACETOCHANGETO->m_szName});
g_pCompositor->m_pLastMonitor = PMONITOR;
}
const bool anotherMonitor = PMONITOR != g_pCompositor->m_pLastMonitor;
if (anotherMonitor)
g_pCompositor->warpCursorTo(PMONITOR->vecPosition + PMONITOR->vecSize / 2.f);
// set active and deactivate all other in wlr
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACETOCHANGETO->m_pWlrHandle);
@@ -786,9 +782,13 @@ void CKeybindManager::changeworkspace(std::string args) {
g_pInputManager->refocus();
} else if (g_pCompositor->getWindowsOnWorkspace(PWORKSPACETOCHANGETO->m_iID) > 0)
g_pInputManager->refocus();
else {
// if there are no windows on the workspace, just unfocus the window on the previous workspace
g_pCompositor->focusWindow(nullptr);
}
// set the new monitor as the last (no warps would bug otherwise)
g_pCompositor->m_pLastMonitor = g_pCompositor->getMonitorFromID(PWORKSPACETOCHANGETO->m_iMonitorID);
g_pCompositor->setActiveMonitor(g_pCompositor->getMonitorFromID(PWORKSPACETOCHANGETO->m_iMonitorID));
// mark the monitor dirty
g_pHyprRenderer->damageMonitor(PMONITOR);
@@ -812,6 +812,8 @@ void CKeybindManager::changeworkspace(std::string args) {
const auto PWORKSPACE = g_pCompositor->createNewWorkspace(workspaceToChangeTo, PMONITOR->ID, workspaceName);
const bool ANOTHERMONITOR = PMONITOR != g_pCompositor->m_pLastMonitor;
if (!isSwitchingToPrevious)
// Remember previous workspace.
PWORKSPACE->m_iPrevWorkspaceID = OLDWORKSPACE;
@@ -819,7 +821,7 @@ void CKeybindManager::changeworkspace(std::string args) {
// start anim on new workspace
PWORKSPACE->startAnim(true, ANIMTOLEFT);
PMONITOR->specialWorkspaceOpen = false;
PMONITOR->specialWorkspaceID = 0;
// fix pinned windows
for (auto& w : g_pCompositor->m_vWindows) {
@@ -828,10 +830,10 @@ void CKeybindManager::changeworkspace(std::string args) {
}
}
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
if (!g_pCompositor->isWorkspaceSpecial(workspaceToChangeTo))
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
PMONITOR->specialWorkspaceOpen = true;
PMONITOR->specialWorkspaceID = workspaceToChangeTo;
// set active and deactivate all other
g_pCompositor->deactivateAllWLRWorkspaces(PWORKSPACE->m_pWlrHandle);
@@ -844,13 +846,16 @@ void CKeybindManager::changeworkspace(std::string args) {
if (g_pCompositor->m_pLastMonitor != PMONITOR)
g_pCompositor->warpCursorTo(PMONITOR->vecPosition + PMONITOR->vecSize / 2.f);
g_pCompositor->m_pLastMonitor = PMONITOR;
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PWORKSPACE->m_szName});
g_pCompositor->setActiveMonitor(PMONITOR);
// focus (clears the last)
g_pInputManager->refocus();
// Event
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PWORKSPACE->m_szName});
// Events
if (ANOTHERMONITOR)
g_pCompositor->warpCursorTo(PMONITOR->vecPosition + PMONITOR->vecSize / 2.f);
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
}
@@ -861,7 +866,7 @@ void CKeybindManager::fullscreenActive(std::string args) {
if (!PWINDOW)
return;
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID))
return;
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, args == "1" ? FULLSCREEN_MAXIMIZED : FULLSCREEN_FULL);
@@ -873,7 +878,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
if (args.contains(',')) {
PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
args = args.substr(0, args.find_last_of(','));
args = args.substr(0, args.find_last_of(','));
} else {
PWINDOW = g_pCompositor->m_pLastWindow;
}
@@ -884,22 +889,26 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
const auto OLDWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
// hack
std::string unusedName;
const auto WORKSPACEID = getWorkspaceIDFromString(args, unusedName);
std::string workspaceName;
const auto WORKSPACEID = getWorkspaceIDFromString(args, workspaceName);
if (WORKSPACEID == INT_MAX) {
Debug::log(LOG, "Invalid workspace in moveActiveToWorkspace");
return;
}
if (WORKSPACEID == PWINDOW->m_iWorkspaceID) {
Debug::log(LOG, "Not moving to workspace because it didn't change.");
return;
}
auto PSAVEDSIZE = PWINDOW->m_vRealSize.goalv();
auto PSAVEDPOS = PWINDOW->m_vRealPosition.goalv();
auto PSAVEDSIZE = PWINDOW->m_bIsFloating && PWINDOW->m_bIsFullscreen ? PWINDOW->m_vLastFloatingSize : PWINDOW->m_vRealSize.goalv();
auto PSAVEDPOS = PWINDOW->m_bIsFloating && PWINDOW->m_bIsFullscreen ? PWINDOW->m_vLastFloatingPosition : PWINDOW->m_vRealPosition.goalv();
const bool WASFULLSCREEN = PWINDOW->m_bIsFullscreen;
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
g_pKeybindManager->changeworkspace(args);
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
if (PWORKSPACE == OLDWORKSPACE) {
Debug::log(LOG, "Not moving to workspace because it didn't change.");
@@ -907,19 +916,13 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
}
if (!PWORKSPACE) {
Debug::log(ERR, "Workspace null in moveActiveToWorkspace?");
return;
// create
PWORKSPACE = g_pCompositor->createNewWorkspace(WORKSPACEID, OLDWORKSPACE->m_iMonitorID, workspaceName);
}
OLDWORKSPACE->m_bHasFullscreenWindow = false;
PWINDOW->moveToWorkspace(PWORKSPACE->m_iID);
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
if (PWINDOW->m_bIsFullscreen) {
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
}
if (PWORKSPACE->m_bHasFullscreenWindow) {
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_FULL);
}
@@ -932,21 +935,20 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
// and restore it
if (PWINDOW->m_bIsFloating) {
PWINDOW->m_vRealSize.setValueAndWarp(PSAVEDSIZE);
PWINDOW->m_vRealPosition.setValueAndWarp(PSAVEDPOS - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
PWINDOW->m_vRealPosition.setValueAndWarp(PSAVEDPOS - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition +
g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
}
// undo the damage if we are moving to the special workspace
if (WORKSPACEID == SPECIAL_WORKSPACE_ID) {
changeworkspace("[internal]" + std::to_string(OLDWORKSPACE->m_iID));
OLDWORKSPACE->startAnim(true, true, true);
toggleSpecialWorkspace("");
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
if (WASFULLSCREEN)
g_pCompositor->setWindowFullscreen(PWINDOW, true, OLDWORKSPACE->m_efFullscreenMode);
for (auto& m : g_pCompositor->m_vMonitors)
m->specialWorkspaceOpen = false;
} else {
if (!g_pCompositor->isWorkspaceSpecial(WORKSPACEID)) {
g_pKeybindManager->changeworkspace(args);
g_pCompositor->focusWindow(PWINDOW);
} else {
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
g_pInputManager->refocus();
}
PWINDOW->updateToplevel();
@@ -954,14 +956,15 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
// hacky, but works lol
// TODO: this sucks
CWindow* PWINDOW = nullptr;
CWindow* PWINDOW = nullptr;
const auto ORIGINALARGS = args;
if (args.contains(',')) {
PWINDOW = g_pCompositor->getWindowByRegex(args.substr(args.find_last_of(',') + 1));
args = args.substr(0, args.find_last_of(','));
args = args.substr(0, args.find_last_of(','));
} else {
PWINDOW = g_pCompositor->m_pLastWindow;
}
@@ -969,8 +972,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
if (!PWINDOW)
return;
int workspaceToMoveTo = 0;
std::string workspaceName = "";
int workspaceToMoveTo = 0;
std::string workspaceName = "";
workspaceToMoveTo = getWorkspaceIDFromString(args, workspaceName);
@@ -995,9 +998,9 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
}
const auto OLDWORKSPACEIDONMONITOR = PMONITORNEW->activeWorkspace;
const auto OLDWORKSPACEIDRETURN = PMONITOR->activeWorkspace;
const auto OLDWORKSPACEIDRETURN = PMONITOR->activeWorkspace;
const auto POLDWORKSPACEONMON = g_pCompositor->getWorkspaceByID(OLDWORKSPACEIDONMONITOR);
const auto POLDWORKSPACEONMON = g_pCompositor->getWorkspaceByID(OLDWORKSPACEIDONMONITOR);
const auto POLDWORKSPACEIDRETURN = g_pCompositor->getWorkspaceByID(OLDWORKSPACEIDRETURN);
g_pEventManager->m_bIgnoreEvents = true;
@@ -1010,21 +1013,25 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDRETURN));
// revert animations
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
PWORKSPACE->m_fAlpha.setValueAndWarp(0.f);
POLDWORKSPACEIDRETURN->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
POLDWORKSPACEIDRETURN->m_fAlpha.setValueAndWarp(255.f);
POLDWORKSPACEIDRETURN->m_fAlpha.setValueAndWarp(1.f);
POLDWORKSPACEONMON->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
POLDWORKSPACEONMON->m_fAlpha.setValueAndWarp(255.f);
POLDWORKSPACEONMON->m_fAlpha.setValueAndWarp(1.f);
g_pEventManager->m_bIgnoreEvents = false;
// manually post event cuz it got ignored above
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", PWINDOW, PWORKSPACE->m_szName.c_str())});
g_pInputManager->refocus();
PWINDOW->m_iWorkspaceID = OLDWORKSPACEIDRETURN;
const auto PNEXTCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW);
PWINDOW->m_iWorkspaceID = workspaceToMoveTo;
g_pCompositor->focusWindow(PNEXTCANDIDATE);
}
void CKeybindManager::moveFocusTo(std::string args) {
@@ -1044,10 +1051,9 @@ void CKeybindManager::moveFocusTo(std::string args) {
g_pInputManager->unconstrainMouse();
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
if (PLASTWINDOW->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && PLASTWINDOW->m_bIsFullscreen) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PLASTWINDOW->m_iWorkspaceID);
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
if (!PWINDOWTOCHANGETO->m_bPinned)
g_pCompositor->setWindowFullscreen(PLASTWINDOW, false, FULLSCREEN_FULL);
@@ -1064,10 +1070,8 @@ void CKeybindManager::moveFocusTo(std::string args) {
if (PLASTWINDOW->m_iMonitorID != PWINDOWTOCHANGETO->m_iMonitorID) {
// event
const auto PNEWMON = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID);
const auto PNEWWS = g_pCompositor->getWorkspaceByID(PNEWMON->activeWorkspace);
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", PNEWMON->szName + "," + PNEWWS->m_szName});
g_pCompositor->m_pLastMonitor = PNEWMON;
g_pCompositor->setActiveMonitor(PNEWMON);
}
}
};
@@ -1085,7 +1089,7 @@ void CKeybindManager::moveFocusTo(std::string args) {
}
void CKeybindManager::moveActiveTo(std::string args) {
char arg = args[0];
char arg = args[0];
const auto LASTMONITOR = g_pCompositor->m_pLastMonitor;
@@ -1150,6 +1154,7 @@ void CKeybindManager::toggleSplit(std::string args) {
void CKeybindManager::alterSplitRatio(std::string args) {
float splitratio = 0;
bool exact = false;
if (args == "+" || args == "-") {
Debug::log(LOG, "alterSplitRatio: using LEGACY +/-, consider switching to the Hyprland syntax.");
@@ -1157,7 +1162,12 @@ void CKeybindManager::alterSplitRatio(std::string args) {
}
if (splitratio == 0) {
splitratio = getPlusMinusKeywordResult(args, 0);
if (args.find("exact") == 0) {
exact = true;
splitratio = getPlusMinusKeywordResult(args.substr(5), 0);
} else {
splitratio = getPlusMinusKeywordResult(args, 0);
}
}
if (splitratio == INT_MAX) {
@@ -1170,7 +1180,7 @@ void CKeybindManager::alterSplitRatio(std::string args) {
if (!PLASTWINDOW)
return;
g_pLayoutManager->getCurrentLayout()->alterSplitRatioBy(PLASTWINDOW, splitratio);
g_pLayoutManager->getCurrentLayout()->alterSplitRatio(PLASTWINDOW, splitratio, exact);
}
void CKeybindManager::focusMonitor(std::string arg) {
@@ -1203,15 +1213,18 @@ void CKeybindManager::moveCursorToCorner(std::string arg) {
switch (CORNER) {
case 0:
// bottom left
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y + PWINDOW->m_vRealSize.vec().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x,
PWINDOW->m_vRealPosition.vec().y + PWINDOW->m_vRealSize.vec().y);
break;
case 1:
// bottom right
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x + PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealPosition.vec().y + PWINDOW->m_vRealSize.vec().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x + PWINDOW->m_vRealSize.vec().x,
PWINDOW->m_vRealPosition.vec().y + PWINDOW->m_vRealSize.vec().y);
break;
case 2:
// top right
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x + PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealPosition.vec().y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PWINDOW->m_vRealPosition.vec().x + PWINDOW->m_vRealSize.vec().x,
PWINDOW->m_vRealPosition.vec().y);
break;
case 3:
// top left
@@ -1252,7 +1265,7 @@ void CKeybindManager::workspaceOpt(std::string args) {
continue;
if (!w->m_bRequestsFloat && w->m_bIsFloating != PWORKSPACE->m_bDefaultFloating) {
const auto SAVEDPOS = w->m_vRealPosition.vec();
const auto SAVEDPOS = w->m_vRealPosition.vec();
const auto SAVEDSIZE = w->m_vRealSize.vec();
w->m_bIsFloating = PWORKSPACE->m_bDefaultFloating;
@@ -1262,8 +1275,8 @@ void CKeybindManager::workspaceOpt(std::string args) {
w->m_vRealPosition.setValueAndWarp(SAVEDPOS);
w->m_vRealSize.setValueAndWarp(SAVEDSIZE);
g_pXWaylandManager->setWindowSize(w, SAVEDSIZE);
w->m_vRealSize = w->m_vRealSize.vec() + Vector2D(4,4);
w->m_vRealPosition = w->m_vRealPosition.vec() - Vector2D(2,2);
w->m_vRealSize = w->m_vRealSize.vec() + Vector2D(4, 4);
w->m_vRealPosition = w->m_vRealPosition.vec() - Vector2D(2, 2);
}
}
}
@@ -1300,17 +1313,17 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
return;
std::string workspace = args.substr(0, args.find_first_of(' '));
std::string monitor = args.substr(args.find_first_of(' ') + 1);
std::string monitor = args.substr(args.find_first_of(' ') + 1);
const auto PMONITOR = g_pCompositor->getMonitorFromString(monitor);
const auto PMONITOR = g_pCompositor->getMonitorFromString(monitor);
if (!PMONITOR){
if (!PMONITOR) {
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
return;
}
std::string workspaceName;
const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName);
const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName);
if (WORKSPACEID == INT_MAX) {
Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!");
@@ -1329,52 +1342,93 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
if (g_pCompositor->getWindowsOnWorkspace(SPECIAL_WORKSPACE_ID) == 0) {
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
std::string workspaceName = "";
int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName);
if (workspaceID == INT_MAX || !g_pCompositor->isWorkspaceSpecial(workspaceID)) {
Debug::log(ERR, "Invalid workspace passed to special");
return;
}
if (g_pCompositor->getWindowsOnWorkspace(workspaceID) == 0) {
Debug::log(LOG, "Can't open empty special workspace!");
return;
}
bool open = false;
bool requestedWorkspaceIsAlreadyOpen = false;
const auto PMONITOR = *PFOLLOWMOUSE == 1 ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->m_pLastMonitor;
int specialOpenOnMonitor = PMONITOR->specialWorkspaceID;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen) {
open = true;
if (m->specialWorkspaceID == workspaceID) {
requestedWorkspaceIsAlreadyOpen = true;
break;
}
}
if (open)
Debug::log(LOG, "Toggling special workspace to closed");
if (requestedWorkspaceIsAlreadyOpen && specialOpenOnMonitor == workspaceID)
Debug::log(LOG, "Toggling special workspace %d to closed");
else
Debug::log(LOG, "Toggling special workspace to open");
Debug::log(LOG, "Toggling special workspace %d to open");
if (open) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (m->specialWorkspaceOpen != !open) {
m->specialWorkspaceOpen = !open;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
if (requestedWorkspaceIsAlreadyOpen && specialOpenOnMonitor == workspaceID) {
// already open on this monitor
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
}
PMONITOR->specialWorkspaceID = 0;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
g_pCompositor->getWorkspaceByID(workspaceID)->startAnim(false, false);
if (const auto PWINDOW = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace)->getLastFocusedWindow(); PWINDOW)
g_pCompositor->focusWindow(PWINDOW);
else
g_pInputManager->refocus();
} else if (requestedWorkspaceIsAlreadyOpen) {
// already open on another monitor
if (specialOpenOnMonitor) {
g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID)->startAnim(false, false);
PMONITOR->specialWorkspaceID = 0;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
}
if (const auto PWINDOW = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace)->getLastFocusedWindow(); PWINDOW)
// move to current
const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceID);
const auto POLDMON = g_pCompositor->getMonitorFromID(PSPECIALWORKSPACE->m_iMonitorID);
POLDMON->specialWorkspaceID = 0;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
PMONITOR->specialWorkspaceID = workspaceID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
PSPECIALWORKSPACE->m_iMonitorID = PMONITOR->ID;
if (const auto PWINDOW = PSPECIALWORKSPACE->getLastFocusedWindow(); PWINDOW)
g_pCompositor->focusWindow(PWINDOW);
else
g_pInputManager->refocus();
} else {
auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
// not open anywhere
if (specialOpenOnMonitor) {
g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID)->startAnim(false, false);
PMONITOR->specialWorkspaceID = 0;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
}
auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceID);
if (!PSPECIALWORKSPACE) {
// ??? happens sometimes...?
PSPECIALWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(g_pCompositor->m_pLastMonitor->ID, "special", true)).get();
PSPECIALWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, PMONITOR->ID, workspaceName);
}
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
PMONITOR->specialWorkspaceID = workspaceID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
PSPECIALWORKSPACE->m_iMonitorID = PMONITOR->ID;
PSPECIALWORKSPACE->startAnim(true, true);
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
if (const auto PWINDOW = PSPECIALWORKSPACE->getLastFocusedWindow(); PWINDOW)
g_pCompositor->focusWindow(PWINDOW);
@@ -1411,8 +1465,8 @@ void CKeybindManager::resizeActive(std::string args) {
}
void CKeybindManager::moveActive(std::string args) {
if (!g_pCompositor->m_pLastWindow || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
return;
if (!g_pCompositor->m_pLastWindow || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
return;
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealPosition.goalv());
@@ -1422,7 +1476,7 @@ void CKeybindManager::moveActive(std::string args) {
void CKeybindManager::moveWindow(std::string args) {
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
const auto MOVECMD = args.substr(0, args.find_first_of(','));
const auto MOVECMD = args.substr(0, args.find_first_of(','));
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
@@ -1442,7 +1496,7 @@ void CKeybindManager::moveWindow(std::string args) {
void CKeybindManager::resizeWindow(std::string args) {
const auto WINDOWREGEX = args.substr(args.find_first_of(',') + 1);
const auto MOVECMD = args.substr(0, args.find_first_of(','));
const auto MOVECMD = args.substr(0, args.find_first_of(','));
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
@@ -1451,10 +1505,10 @@ void CKeybindManager::resizeWindow(std::string args) {
return;
}
if (PWINDOW->m_bIsFullscreen)
return;
if (PWINDOW->m_bIsFullscreen)
return;
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), PWINDOW);
@@ -1469,7 +1523,7 @@ void CKeybindManager::circleNext(std::string arg) {
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsFullscreen) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
if (!PWINDOWTOCHANGETO->m_bPinned)
g_pCompositor->setWindowFullscreen(g_pCompositor->m_pLastWindow, false, FULLSCREEN_FULL);
@@ -1551,13 +1605,13 @@ void CKeybindManager::pass(std::string regexp) {
const auto KEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
if (!KEYBOARD){
if (!KEYBOARD) {
Debug::log(ERR, "No kb in pass?");
return;
}
const auto XWTOXW = PWINDOW->m_bIsX11 && g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsX11;
const auto SL = Vector2D(g_pCompositor->m_sSeat.seat->pointer_state.sx, g_pCompositor->m_sSeat.seat->pointer_state.sy);
const auto SL = Vector2D(g_pCompositor->m_sSeat.seat->pointer_state.sx, g_pCompositor->m_sSeat.seat->pointer_state.sy);
// pass all mf shit
if (!XWTOXW) {
@@ -1567,7 +1621,6 @@ void CKeybindManager::pass(std::string regexp) {
wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, g_pXWaylandManager->getWindowSurface(PWINDOW), 1, 1);
}
wlr_keyboard_modifiers kbmods = {g_pInputManager->accumulateModsFromAllKBs(), 0, 0, 0};
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &kbmods);
@@ -1600,10 +1653,10 @@ void CKeybindManager::pass(std::string regexp) {
// please kill me
if (PWINDOW->m_bIsX11) {
if (g_pKeybindManager->m_uLastCode != 0) {
g_pCompositor->m_sSeat.seat->keyboard_state.focused_client = nullptr;
g_pCompositor->m_sSeat.seat->keyboard_state.focused_client = nullptr;
g_pCompositor->m_sSeat.seat->keyboard_state.focused_surface = nullptr;
} else {
g_pCompositor->m_sSeat.seat->pointer_state.focused_client = nullptr;
g_pCompositor->m_sSeat.seat->pointer_state.focused_client = nullptr;
g_pCompositor->m_sSeat.seat->pointer_state.focused_surface = nullptr;
}
}
@@ -1625,14 +1678,15 @@ void CKeybindManager::toggleOpaque(std::string unused) {
if (!PWINDOW)
return;
PWINDOW->m_sAdditionalConfigData.forceOpaque = !PWINDOW->m_sAdditionalConfigData.forceOpaque;
PWINDOW->m_sAdditionalConfigData.forceOpaque = !PWINDOW->m_sAdditionalConfigData.forceOpaque;
PWINDOW->m_sAdditionalConfigData.forceOpaqueOverriden = true;
g_pHyprRenderer->damageWindow(PWINDOW);
}
void CKeybindManager::dpms(std::string arg) {
bool enable = arg.find("on") == 0;
std::string port = "";
bool enable = arg.find("on") == 0;
std::string port = "";
if (arg.find_first_of(' ') != std::string::npos) {
port = arg.substr(arg.find_first_of(' ') + 1);
@@ -1667,7 +1721,10 @@ void CKeybindManager::swapnext(std::string arg) {
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
const auto PLASTCYCLED = g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow->m_pLastCycledWindow) && g_pCompositor->m_pLastWindow->m_pLastCycledWindow->m_iWorkspaceID == PLASTWINDOW->m_iWorkspaceID ? g_pCompositor->m_pLastWindow->m_pLastCycledWindow : nullptr;
const auto PLASTCYCLED = g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow->m_pLastCycledWindow) &&
g_pCompositor->m_pLastWindow->m_pLastCycledWindow->m_iWorkspaceID == PLASTWINDOW->m_iWorkspaceID ?
g_pCompositor->m_pLastWindow->m_pLastCycledWindow :
nullptr;
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
@@ -1706,7 +1763,7 @@ void CKeybindManager::pinActive(std::string args) {
if (!g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow->m_bIsFloating || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
return;
g_pCompositor->m_pLastWindow->m_bPinned = !g_pCompositor->m_pLastWindow->m_bPinned;
g_pCompositor->m_pLastWindow->m_bPinned = !g_pCompositor->m_pLastWindow->m_bPinned;
g_pCompositor->m_pLastWindow->m_iWorkspaceID = g_pCompositor->getMonitorFromID(g_pCompositor->m_pLastWindow->m_iMonitorID)->activeWorkspace;
g_pCompositor->m_pLastWindow->updateDynamicRules();
@@ -1726,7 +1783,7 @@ void CKeybindManager::mouse(std::string args) {
g_pKeybindManager->m_bIsMouseBindActive = true;
g_pInputManager->currentlyDraggedWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal());
g_pInputManager->dragMode = MBIND_MOVE;
g_pInputManager->dragMode = MBIND_MOVE;
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
} else {
@@ -1735,7 +1792,7 @@ void CKeybindManager::mouse(std::string args) {
if (g_pInputManager->currentlyDraggedWindow) {
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
g_pInputManager->currentlyDraggedWindow = nullptr;
g_pInputManager->dragMode = MBIND_INVALID;
g_pInputManager->dragMode = MBIND_INVALID;
}
}
} else if (TRUEARG == "resizewindow") {
@@ -1743,7 +1800,7 @@ void CKeybindManager::mouse(std::string args) {
g_pKeybindManager->m_bIsMouseBindActive = true;
g_pInputManager->currentlyDraggedWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal());
g_pInputManager->dragMode = MBIND_RESIZE;
g_pInputManager->dragMode = MBIND_RESIZE;
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
} else {
@@ -1752,7 +1809,7 @@ void CKeybindManager::mouse(std::string args) {
if (g_pInputManager->currentlyDraggedWindow) {
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
g_pInputManager->currentlyDraggedWindow = nullptr;
g_pInputManager->dragMode = MBIND_INVALID;
g_pInputManager->dragMode = MBIND_INVALID;
}
}
}
@@ -1762,3 +1819,12 @@ void CKeybindManager::bringActiveToTop(std::string args) {
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsFloating)
g_pCompositor->moveWindowToTop(g_pCompositor->m_pLastWindow);
}
void CKeybindManager::fakeFullscreenActive(std::string args) {
if (g_pCompositor->m_pLastWindow) {
// will also set the flag
g_pCompositor->m_pLastWindow->m_bFakeFullscreenState = !g_pCompositor->m_pLastWindow->m_bFakeFullscreenState;
g_pXWaylandManager->setWindowFullscreen(g_pCompositor->m_pLastWindow,
g_pCompositor->m_pLastWindow->m_bFakeFullscreenState || g_pCompositor->m_pLastWindow->m_bIsFullscreen);
}
}

View File

@@ -10,19 +10,19 @@ class CInputManager;
class CConfigManager;
struct SKeybind {
std::string key = "";
int keycode = -1;
uint32_t modmask = 0;
std::string handler = "";
std::string arg = "";
bool locked = false;
std::string submap = "";
bool release = false;
bool repeat = false;
bool mouse = false;
std::string key = "";
int keycode = -1;
uint32_t modmask = 0;
std::string handler = "";
std::string arg = "";
bool locked = false;
std::string submap = "";
bool release = false;
bool repeat = false;
bool mouse = false;
// DO NOT INITIALIZE
bool shadowed = false;
bool shadowed = false;
};
enum eFocusWindowMode {
@@ -33,96 +33,98 @@ enum eFocusWindowMode {
};
class CKeybindManager {
public:
public:
CKeybindManager();
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
bool onAxisEvent(wlr_pointer_axis_event*);
bool onMouseEvent(wlr_pointer_button_event*);
void onSwitchEvent(const std::string&);
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
bool onAxisEvent(wlr_pointer_axis_event*);
bool onMouseEvent(wlr_pointer_button_event*);
void onSwitchEvent(const std::string&);
void addKeybind(SKeybind);
void removeKeybind(uint32_t, const std::string&);
uint32_t stringToModMask(std::string);
void clearKeybinds();
void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const int& doesntHaveCode = 0);
void addKeybind(SKeybind);
void removeKeybind(uint32_t, const std::string&);
uint32_t stringToModMask(std::string);
void clearKeybinds();
void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const int& doesntHaveCode = 0);
std::unordered_map<std::string, std::function<void(std::string)>> m_mDispatchers;
wl_event_source* m_pActiveKeybindEventSource = nullptr;
wl_event_source* m_pActiveKeybindEventSource = nullptr;
private:
std::list<SKeybind> m_lKeybinds;
std::deque<xkb_keysym_t> m_dPressedKeysyms;
std::deque<int> m_dPressedKeycodes;
std::list<SKeybind> m_lKeybinds;
private:
std::deque<xkb_keysym_t> m_dPressedKeysyms;
std::deque<int> m_dPressedKeycodes;
inline static std::string m_szCurrentSelectedSubmap = "";
xkb_keysym_t m_kHeldBack = 0;
xkb_keysym_t m_kHeldBack = 0;
SKeybind* m_pActiveKeybind = nullptr;
SKeybind* m_pActiveKeybind = nullptr;
uint32_t m_uTimeLastMs = 0;
uint32_t m_uLastCode = 0;
uint32_t m_uLastMouseCode = 0;
uint32_t m_uTimeLastMs = 0;
uint32_t m_uLastCode = 0;
uint32_t m_uLastMouseCode = 0;
bool m_bIsMouseBindActive = false;
bool m_bIsMouseBindActive = false;
int m_iPassPressed = -1; // used for pass
int m_iPassPressed = -1; // used for pass
CTimer m_tScrollTimer;
CTimer m_tScrollTimer;
bool handleKeybinds(const uint32_t&, const std::string&, const xkb_keysym_t&, const int&, bool, uint32_t);
bool handleKeybinds(const uint32_t&, const std::string&, const xkb_keysym_t&, const int&, bool, uint32_t);
bool handleInternalKeybinds(xkb_keysym_t);
bool handleVT(xkb_keysym_t);
bool handleInternalKeybinds(xkb_keysym_t);
bool handleVT(xkb_keysym_t);
xkb_state* m_pXKBTranslationState = nullptr;
xkb_state* m_pXKBTranslationState = nullptr;
void updateXKBTranslationState();
bool ensureMouseBindState();
void updateXKBTranslationState();
bool ensureMouseBindState();
// -------------- Dispatchers -------------- //
static void killActive(std::string);
static void kill(std::string);
static void spawn(std::string);
static void toggleActiveFloating(std::string);
static void toggleActivePseudo(std::string);
static void changeworkspace(std::string);
static void fullscreenActive(std::string);
static void moveActiveToWorkspace(std::string);
static void moveActiveToWorkspaceSilent(std::string);
static void moveFocusTo(std::string);
static void centerWindow(std::string);
static void moveActiveTo(std::string);
static void toggleGroup(std::string);
static void changeGroupActive(std::string);
static void alterSplitRatio(std::string);
static void focusMonitor(std::string);
static void toggleSplit(std::string);
static void moveCursorToCorner(std::string);
static void workspaceOpt(std::string);
static void exitHyprland(std::string);
static void moveCurrentWorkspaceToMonitor(std::string);
static void moveWorkspaceToMonitor(std::string);
static void toggleSpecialWorkspace(std::string);
static void forceRendererReload(std::string);
static void resizeActive(std::string);
static void moveActive(std::string);
static void moveWindow(std::string);
static void resizeWindow(std::string);
static void circleNext(std::string);
static void focusWindow(std::string);
static void setSubmap(std::string);
static void pass(std::string);
static void layoutmsg(std::string);
static void toggleOpaque(std::string);
static void dpms(std::string);
static void swapnext(std::string);
static void swapActiveWorkspaces(std::string);
static void pinActive(std::string);
static void mouse(std::string);
static void bringActiveToTop(std::string);
static void killActive(std::string);
static void kill(std::string);
static void spawn(std::string);
static void toggleActiveFloating(std::string);
static void toggleActivePseudo(std::string);
static void changeworkspace(std::string);
static void fullscreenActive(std::string);
static void fakeFullscreenActive(std::string);
static void moveActiveToWorkspace(std::string);
static void moveActiveToWorkspaceSilent(std::string);
static void moveFocusTo(std::string);
static void centerWindow(std::string);
static void moveActiveTo(std::string);
static void toggleGroup(std::string);
static void changeGroupActive(std::string);
static void alterSplitRatio(std::string);
static void focusMonitor(std::string);
static void toggleSplit(std::string);
static void moveCursorToCorner(std::string);
static void workspaceOpt(std::string);
static void exitHyprland(std::string);
static void moveCurrentWorkspaceToMonitor(std::string);
static void moveWorkspaceToMonitor(std::string);
static void toggleSpecialWorkspace(std::string);
static void forceRendererReload(std::string);
static void resizeActive(std::string);
static void moveActive(std::string);
static void moveWindow(std::string);
static void resizeWindow(std::string);
static void circleNext(std::string);
static void focusWindow(std::string);
static void setSubmap(std::string);
static void pass(std::string);
static void layoutmsg(std::string);
static void toggleOpaque(std::string);
static void dpms(std::string);
static void swapnext(std::string);
static void swapActiveWorkspaces(std::string);
static void pinActive(std::string);
static void mouse(std::string);
static void bringActiveToTop(std::string);
friend class CCompositor;
friend class CInputManager;

View File

@@ -2,10 +2,8 @@
IHyprLayout* CLayoutManager::getCurrentLayout() {
switch (m_iCurrentLayoutID) {
case DWINDLE:
return &m_cDwindleLayout;
case MASTER:
return &m_cMasterLayout;
case LAYOUT_DWINDLE: return &m_cDwindleLayout;
case LAYOUT_MASTER: return &m_cMasterLayout;
}
// fallback
@@ -14,15 +12,15 @@ IHyprLayout* CLayoutManager::getCurrentLayout() {
void CLayoutManager::switchToLayout(std::string layout) {
if (layout == "dwindle") {
if (m_iCurrentLayoutID != DWINDLE) {
if (m_iCurrentLayoutID != LAYOUT_DWINDLE) {
getCurrentLayout()->onDisable();
m_iCurrentLayoutID = DWINDLE;
m_iCurrentLayoutID = LAYOUT_DWINDLE;
getCurrentLayout()->onEnable();
}
} else if (layout == "master") {
if (m_iCurrentLayoutID != MASTER) {
if (m_iCurrentLayoutID != LAYOUT_MASTER) {
getCurrentLayout()->onDisable();
m_iCurrentLayoutID = MASTER;
m_iCurrentLayoutID = LAYOUT_MASTER;
getCurrentLayout()->onEnable();
}
} else {

View File

@@ -4,19 +4,18 @@
#include "../layout/MasterLayout.hpp"
class CLayoutManager {
public:
public:
IHyprLayout* getCurrentLayout();
IHyprLayout* getCurrentLayout();
void switchToLayout(std::string);
void switchToLayout(std::string);
private:
private:
enum HYPRLAYOUTS {
DWINDLE = 0,
MASTER
LAYOUT_DWINDLE = 0,
LAYOUT_MASTER
};
HYPRLAYOUTS m_iCurrentLayoutID = DWINDLE;
HYPRLAYOUTS m_iCurrentLayoutID = LAYOUT_DWINDLE;
CHyprDwindleLayout m_cDwindleLayout;
CHyprMasterLayout m_cMasterLayout;

View File

@@ -0,0 +1,5 @@
#include "ProtocolManager.hpp"
CProtocolManager::CProtocolManager() {
m_pToplevelExportProtocolManager = std::make_unique<CToplevelExportProtocolManager>();
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "../defines.hpp"
#include "../protocols/ToplevelExport.hpp"
class CProtocolManager {
public:
CProtocolManager();
std::unique_ptr<CToplevelExportProtocolManager> m_pToplevelExportProtocolManager;
};
inline std::unique_ptr<CProtocolManager> g_pProtocolManager;

View File

@@ -5,9 +5,9 @@
int slowUpdate = 0;
int handleTimer(void* data) {
const auto PTM = (CThreadManager*)data;
const auto PTM = (CThreadManager*)data;
static auto *const PDISABLECFGRELOAD = &g_pConfigManager->getConfigValuePtr("misc:disable_autoreload")->intValue;
static auto* const PDISABLECFGRELOAD = &g_pConfigManager->getConfigValuePtr("misc:disable_autoreload")->intValue;
if (*PDISABLECFGRELOAD != 1)
g_pConfigManager->tick();

View File

@@ -5,13 +5,13 @@
#include "../Compositor.hpp"
class CThreadManager {
public:
public:
CThreadManager();
~CThreadManager();
wl_event_source* m_esConfigTimer;
private:
private:
};
inline std::unique_ptr<CThreadManager> g_pThreadManager;

View File

@@ -18,13 +18,11 @@ CHyprXWaylandManager::CHyprXWaylandManager() {
Debug::log(LOG, "CHyprXWaylandManager started on display %s", m_sWLRXWayland->display_name);
#else
unsetenv("DISPLAY"); // unset DISPLAY so that X11 apps do not try to start on a different/invalid DISPLAY
unsetenv("DISPLAY"); // unset DISPLAY so that X11 apps do not try to start on a different/invalid DISPLAY
#endif
}
CHyprXWaylandManager::~CHyprXWaylandManager() {
}
CHyprXWaylandManager::~CHyprXWaylandManager() {}
wlr_surface* CHyprXWaylandManager::getWindowSurface(CWindow* pWindow) {
if (pWindow->m_bIsX11)
@@ -46,9 +44,8 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
wlr_xwayland_surface_activate(wlr_xwayland_surface_from_wlr_surface(pSurface), activate);
if (activate)
wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), NULL, XCB_STACK_MODE_ABOVE);
wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), nullptr, XCB_STACK_MODE_ABOVE);
}
}
void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
@@ -56,16 +53,15 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
if (activate) {
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false);
wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, NULL, XCB_STACK_MODE_ABOVE);
wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, nullptr, XCB_STACK_MODE_ABOVE);
}
wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate);
}
else
} else
wlr_xdg_toplevel_set_activated(pWindow->m_uSurface.xdg->toplevel, activate);
if (activate) {
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
g_pCompositor->m_pLastWindow = pWindow;
}
@@ -78,14 +74,14 @@ void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox)
const auto SIZEHINTS = pWindow->m_uSurface.xwayland->size_hints;
if (SIZEHINTS && pWindow->m_iX11Type != 2) {
pbox->x = SIZEHINTS->x;
pbox->y = SIZEHINTS->y;
pbox->width = SIZEHINTS->width;
pbox->x = SIZEHINTS->x;
pbox->y = SIZEHINTS->y;
pbox->width = SIZEHINTS->width;
pbox->height = SIZEHINTS->height;
} else {
pbox->x = pWindow->m_uSurface.xwayland->x;
pbox->y = pWindow->m_uSurface.xwayland->y;
pbox->width = pWindow->m_uSurface.xwayland->width;
pbox->x = pWindow->m_uSurface.xwayland->x;
pbox->y = pWindow->m_uSurface.xwayland->y;
pbox->width = pWindow->m_uSurface.xwayland->width;
pbox->height = pWindow->m_uSurface.xwayland->height;
}
} else {
@@ -106,9 +102,7 @@ std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) {
} else {
return "";
}
} catch (...) {
Debug::log(ERR, "Error in getTitle (probably null title)");
}
} catch (...) { Debug::log(ERR, "Error in getTitle (probably null title)"); }
return "";
}
@@ -129,9 +123,7 @@ std::string CHyprXWaylandManager::getAppIDClass(CWindow* pWindow) {
} else {
return "";
}
} catch (std::logic_error& e) {
Debug::log(ERR, "Error in getAppIDClass: %s", e.what());
}
} catch (std::logic_error& e) { Debug::log(ERR, "Error in getAppIDClass: %s", e.what()); }
return "";
}
@@ -146,11 +138,12 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size, bool force) {
if (!force && ((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
if (!force &&
((pWindow->m_vReportedSize == size && pWindow->m_vRealPosition.vec() == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
return;
pWindow->m_vReportedPosition = pWindow->m_vRealPosition.vec();
pWindow->m_vReportedSize = size;
pWindow->m_vReportedSize = size;
if (pWindow->m_bIsX11)
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y);
@@ -173,18 +166,23 @@ wlr_surface* CHyprXWaylandManager::surfaceAt(CWindow* pWindow, const Vector2D& c
bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
if (pWindow->m_bIsX11) {
for (size_t i = 0; i < pWindow->m_uSurface.xwayland->window_type_len; i++)
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
{
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
pWindow->m_bX11ShouldntFocus = true;
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DIALOG"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLBAR"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"]) {
pWindow->m_bNoInitialFocus = true;
return true;
}
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"])
pWindow->m_bX11ShouldntFocus = true;
pWindow->m_bNoInitialFocus = true;
return true;
}
if (pWindow->m_uSurface.xwayland->role) {
try {
@@ -192,9 +190,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
if (winrole.contains("pop-up") || winrole.contains("task_dialog")) {
return true;
}
} catch (std::exception& e) {
Debug::log(ERR, "Error in shouldBeFloated, winrole threw %s", e.what());
}
} catch (std::exception& e) { Debug::log(ERR, "Error in shouldBeFloated, winrole threw %s", e.what()); }
}
if (pWindow->m_uSurface.xwayland->modal) {
@@ -212,7 +208,8 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
} else {
const auto PSTATE = &pWindow->m_uSurface.xdg->toplevel->current;
if ((PSTATE->min_width != 0 && PSTATE->min_height != 0 && (PSTATE->min_width == PSTATE->max_width || PSTATE->min_height == PSTATE->max_height)) || pWindow->m_uSurface.xdg->toplevel->parent)
if ((PSTATE->min_width != 0 && PSTATE->min_height != 0 && (PSTATE->min_width == PSTATE->max_width || PSTATE->min_height == PSTATE->max_height)) ||
pWindow->m_uSurface.xdg->toplevel->parent)
return true;
}
@@ -233,9 +230,12 @@ void CHyprXWaylandManager::checkBorders(CWindow* pWindow) {
return;
for (size_t i = 0; i < pWindow->m_uSurface.xwayland->window_type_len; i++) {
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_NOTIFICATION"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_COMBO"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"] || pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
if (pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_NOTIFICATION"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_COMBO"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"] ||
pWindow->m_uSurface.xwayland->window_type[i] == HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"]) {
pWindow->m_bX11DoesntWantBorders = true;
@@ -243,7 +243,7 @@ void CHyprXWaylandManager::checkBorders(CWindow* pWindow) {
}
}
if (pWindow->m_uSurface.xwayland->parent || pWindow->m_iX11Type == 2) {
if (pWindow->m_iX11Type == 2) {
pWindow->m_bX11DoesntWantBorders = true;
}
}
@@ -263,11 +263,12 @@ Vector2D CHyprXWaylandManager::getMaxSizeForWindow(CWindow* pWindow) {
if (!g_pCompositor->windowValidMapped(pWindow))
return Vector2D(99999, 99999);
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_uSurface.xdg->toplevel))
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_uSurface.xdg->toplevel) ||
pWindow->m_sAdditionalConfigData.noMaxSize)
return Vector2D(99999, 99999);
auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->max_width, pWindow->m_uSurface.xwayland->size_hints->max_height)
: Vector2D(pWindow->m_uSurface.xdg->toplevel->current.max_width, pWindow->m_uSurface.xdg->toplevel->current.max_height);
auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->max_width, pWindow->m_uSurface.xwayland->size_hints->max_height) :
Vector2D(pWindow->m_uSurface.xdg->toplevel->current.max_width, pWindow->m_uSurface.xdg->toplevel->current.max_height);
if (MAXSIZE.x < 5)
MAXSIZE.x = 99999;

View File

@@ -4,27 +4,27 @@
#include "../Window.hpp"
class CHyprXWaylandManager {
public:
public:
CHyprXWaylandManager();
~CHyprXWaylandManager();
wlr_xwayland* m_sWLRXWayland = nullptr;
wlr_xwayland* m_sWLRXWayland = nullptr;
wlr_surface* getWindowSurface(CWindow*);
void activateSurface(wlr_surface*, bool);
void activateWindow(CWindow*, bool);
void getGeometryForWindow(CWindow*, wlr_box*);
std::string getTitle(CWindow*);
std::string getAppIDClass(CWindow*);
void sendCloseWindow(CWindow*);
void setWindowSize(CWindow*, const Vector2D&, bool force = false);
void setWindowStyleTiled(CWindow*, uint32_t);
void setWindowFullscreen(CWindow*, bool);
wlr_surface* surfaceAt(CWindow*, const Vector2D&, Vector2D&);
bool shouldBeFloated(CWindow*);
void moveXWaylandWindow(CWindow*, const Vector2D&);
void checkBorders(CWindow*);
Vector2D getMaxSizeForWindow(CWindow*);
wlr_surface* getWindowSurface(CWindow*);
void activateSurface(wlr_surface*, bool);
void activateWindow(CWindow*, bool);
void getGeometryForWindow(CWindow*, wlr_box*);
std::string getTitle(CWindow*);
std::string getAppIDClass(CWindow*);
void sendCloseWindow(CWindow*);
void setWindowSize(CWindow*, const Vector2D&, bool force = false);
void setWindowStyleTiled(CWindow*, uint32_t);
void setWindowFullscreen(CWindow*, bool);
wlr_surface* surfaceAt(CWindow*, const Vector2D&, Vector2D&);
bool shouldBeFloated(CWindow*);
void moveXWaylandWindow(CWindow*, const Vector2D&);
void checkBorders(CWindow*);
Vector2D getMaxSizeForWindow(CWindow*);
};
inline std::unique_ptr<CHyprXWaylandManager> g_pXWaylandManager;

View File

@@ -17,17 +17,18 @@ void CInputManager::newIdleInhibitor(wlr_idle_inhibitor_v1* pInhibitor) {
PINHIBIT->pWlrInhibitor = pInhibitor;
PINHIBIT->hyprListener_Destroy.initCallback(&pInhibitor->events.destroy, [](void* owner, void* data){
PINHIBIT->hyprListener_Destroy.initCallback(
&pInhibitor->events.destroy,
[](void* owner, void* data) {
const auto PINH = (SIdleInhibitor*)owner;
const auto PINH = (SIdleInhibitor*)owner;
g_pInputManager->m_lIdleInhibitors.remove(*PINH);
g_pInputManager->m_lIdleInhibitors.remove(*PINH);
Debug::log(LOG, "Destroyed an idleinhibitor");
Debug::log(LOG, "Destroyed an idleinhibitor");
g_pInputManager->recheckIdleInhibitorStatus();
}, PINHIBIT, "IdleInhibitor");
g_pInputManager->recheckIdleInhibitorStatus();
},
PINHIBIT, "IdleInhibitor");
PINHIBIT->pWindow = g_pCompositor->getWindowFromSurface(pInhibitor->surface);

File diff suppressed because it is too large Load Diff

View File

@@ -7,86 +7,91 @@
#include "../../helpers/Timer.hpp"
#include "InputMethodRelay.hpp"
enum eClickBehaviorMode {
enum eClickBehaviorMode
{
CLICKMODE_DEFAULT = 0,
CLICKMODE_KILL
};
enum eMouseBindMode {
enum eMouseBindMode
{
MBIND_INVALID = -1,
MBIND_MOVE = 0,
MBIND_MOVE = 0,
MBIND_RESIZE
};
struct STouchData {
CWindow* touchFocusWindow = nullptr;
SLayerSurface* touchFocusLS = nullptr;
wlr_surface* touchFocusSurface = nullptr;
Vector2D touchSurfaceOrigin;
CWindow* touchFocusWindow = nullptr;
SLayerSurface* touchFocusLS = nullptr;
wlr_surface* touchFocusSurface = nullptr;
Vector2D touchSurfaceOrigin;
};
class CKeybindManager;
class CInputManager {
public:
public:
void onMouseMoved(wlr_pointer_motion_event*);
void onMouseWarp(wlr_pointer_motion_absolute_event*);
void onMouseButton(wlr_pointer_button_event*);
void onMouseWheel(wlr_pointer_axis_event*);
void onKeyboardKey(wlr_keyboard_key_event*, SKeyboard*);
void onKeyboardMod(void*, SKeyboard*);
void onMouseMoved(wlr_pointer_motion_event*);
void onMouseWarp(wlr_pointer_motion_absolute_event*);
void onMouseButton(wlr_pointer_button_event*);
void onMouseWheel(wlr_pointer_axis_event*);
void onKeyboardKey(wlr_keyboard_key_event*, SKeyboard*);
void onKeyboardMod(void*, SKeyboard*);
void newKeyboard(wlr_input_device*);
void newVirtualKeyboard(wlr_input_device*);
void newMouse(wlr_input_device*, bool virt = false);
void newTouchDevice(wlr_input_device*);
void newSwitch(wlr_input_device*);
void destroyTouchDevice(STouchDevice*);
void destroyKeyboard(SKeyboard*);
void destroyMouse(wlr_input_device*);
void destroySwitch(SSwitchDevice*);
void newKeyboard(wlr_input_device*);
void newVirtualKeyboard(wlr_input_device*);
void newMouse(wlr_input_device*, bool virt = false);
void newTouchDevice(wlr_input_device*);
void newSwitch(wlr_input_device*);
void destroyTouchDevice(STouchDevice*);
void destroyKeyboard(SKeyboard*);
void destroyMouse(wlr_input_device*);
void destroySwitch(SSwitchDevice*);
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
void recheckConstraint(SMouse*);
void unconstrainMouse();
SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*);
std::string getActiveLayoutForKeyboard(SKeyboard*);
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
void recheckConstraint(SMouse*);
void unconstrainMouse();
std::string getActiveLayoutForKeyboard(SKeyboard*);
Vector2D getMouseCoordsInternal();
void refocus();
Vector2D getMouseCoordsInternal();
void refocus();
void setKeyboardLayout();
void setPointerConfigs();
void setTouchDeviceConfigs();
void setTabletConfigs();
void setKeyboardLayout();
void setPointerConfigs();
void setTouchDeviceConfigs();
void updateDragIcon();
void updateCapabilities();
void updateDragIcon();
void updateCapabilities(wlr_input_device*);
void setClickMode(eClickBehaviorMode);
void setClickMode(eClickBehaviorMode);
eClickBehaviorMode getClickMode();
void processMouseRequest(wlr_seat_pointer_request_set_cursor_event*);
void processMouseRequest(wlr_seat_pointer_request_set_cursor_event*);
void onTouchDown(wlr_touch_down_event*);
void onTouchUp(wlr_touch_up_event*);
void onTouchMove(wlr_touch_motion_event*);
void onTouchDown(wlr_touch_down_event*);
void onTouchUp(wlr_touch_up_event*);
void onTouchMove(wlr_touch_motion_event*);
void onPointerHoldBegin(wlr_pointer_hold_begin_event*);
void onPointerHoldEnd(wlr_pointer_hold_end_event*);
void onPointerHoldBegin(wlr_pointer_hold_begin_event*);
void onPointerHoldEnd(wlr_pointer_hold_end_event*);
STouchData m_sTouchData;
STouchData m_sTouchData;
// for dragging floating windows
CWindow* currentlyDraggedWindow = nullptr;
eMouseBindMode dragMode = MBIND_INVALID;
CWindow* currentlyDraggedWindow = nullptr;
eMouseBindMode dragMode = MBIND_INVALID;
SDrag m_sDrag;
SDrag m_sDrag;
std::list<SConstraint> m_lConstraints;
std::list<SKeyboard> m_lKeyboards;
std::list<SMouse> m_lMice;
std::list<SConstraint> m_lConstraints;
std::list<SKeyboard> m_lKeyboards;
std::list<SMouse> m_lMice;
// tablets
std::list<STablet> m_lTablets;
std::list<STabletTool> m_lTabletTools;
std::list<STabletPad> m_lTabletPads;
std::list<STablet> m_lTablets;
std::list<STabletTool> m_lTabletTools;
std::list<STabletPad> m_lTabletPads;
// idle inhibitors
std::list<SIdleInhibitor> m_lIdleInhibitors;
@@ -97,70 +102,74 @@ public:
// Switches
std::list<SSwitchDevice> m_lSwitches;
void newTabletTool(wlr_input_device*);
void newTabletPad(wlr_input_device*);
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
void newIdleInhibitor(wlr_idle_inhibitor_v1*);
void recheckIdleInhibitorStatus();
void newTabletTool(wlr_input_device*);
void newTabletPad(wlr_input_device*);
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
void newIdleInhibitor(wlr_idle_inhibitor_v1*);
void recheckIdleInhibitorStatus();
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
void onSwipeEnd(wlr_pointer_swipe_end_event*);
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
void onSwipeEnd(wlr_pointer_swipe_end_event*);
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
SSwipeGesture m_sActiveSwipe;
SSwipeGesture m_sActiveSwipe;
SKeyboard* m_pActiveKeyboard = nullptr;
SKeyboard* m_pActiveKeyboard = nullptr;
CTimer m_tmrLastCursorMovement;
CTimer m_tmrLastCursorMovement;
CInputMethodRelay m_sIMERelay;
CInputMethodRelay m_sIMERelay;
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
void updateKeyboardsLeds(wlr_input_device* pKeyboard);
// for shared mods
uint32_t accumulateModsFromAllKBs();
uint32_t accumulateModsFromAllKBs();
CWindow* m_pFollowOnDnDBegin = nullptr;
CWindow* m_pFollowOnDnDBegin = nullptr;
// for virtual keyboards: whether we should respect them as normal ones
bool shouldIgnoreVirtualKeyboard(SKeyboard*);
bool shouldIgnoreVirtualKeyboard(SKeyboard*);
// for special cursors that we choose
void setCursorImageUntilUnset(std::string);
void unsetCursorImage();
void setCursorImageUntilUnset(std::string);
void unsetCursorImage();
private:
std::string deviceNameToInternalString(std::string);
std::string getNameForNewDevice(std::string);
bool m_bCursorImageOverriden = false;
private:
bool m_bCursorImageOverriden = false;
// for click behavior override
eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT;
bool m_bEmptyFocusCursorSet = false;
Vector2D m_vLastCursorPosFloored = Vector2D();
eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT;
bool m_bEmptyFocusCursorSet = false;
Vector2D m_vLastCursorPosFloored = Vector2D();
// for some bugs in follow mouse 0
bool m_bLastFocusOnLS = false;
bool m_bLastFocusOnLS = false;
void processMouseDownNormal(wlr_pointer_button_event* e);
void processMouseDownKill(wlr_pointer_button_event* e);
void processMouseDownNormal(wlr_pointer_button_event* e);
void processMouseDownKill(wlr_pointer_button_event* e);
void disableAllKeyboards(bool virt = false);
void disableAllKeyboards(bool virt = false);
uint32_t m_uiCapabilities = 0;
uint32_t m_uiCapabilities = 0;
void mouseMoveUnified(uint32_t, bool refocus = false);
void mouseMoveUnified(uint32_t, bool refocus = false);
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
void applyConfigToKeyboard(SKeyboard*);
void applyConfigToKeyboard(SKeyboard*);
// this will be set after a refocus()
wlr_surface* m_pFoundSurfaceToFocus = nullptr;
SLayerSurface* m_pFoundLSToFocus = nullptr;
CWindow* m_pFoundWindowToFocus = nullptr;
wlr_surface* m_pFoundSurfaceToFocus = nullptr;
SLayerSurface* m_pFoundLSToFocus = nullptr;
CWindow* m_pFoundWindowToFocus = nullptr;
// swipe
void beginWorkspaceSwipe();
void beginWorkspaceSwipe();
friend class CKeybindManager;
};
inline std::unique_ptr<CInputManager> g_pInputManager;

Some files were not shown because too many files have changed in this diff Show More